Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!a pkgxml/alt-php80-vld.xmlnu[ vld pecl.php.net Provides functionality to dump the internal representation of PHP scripts The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. Derick Rethans derick derick@xdebug.org yes 2022-09-16 0.18.0 0.18.0 beta beta BSD style - Add support for new PHP 8.1 opcodes with examples - Add support for PHP 8.2 (by removing JMPZNZ opcode) 7.0.0 1.4.0b1 vld PK!a pkgxml/alt-php83-vld.xmlnu[ vld pecl.php.net Provides functionality to dump the internal representation of PHP scripts The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. Derick Rethans derick derick@xdebug.org yes 2022-09-16 0.18.0 0.18.0 beta beta BSD style - Add support for new PHP 8.1 opcodes with examples - Add support for PHP 8.2 (by removing JMPZNZ opcode) 7.0.0 1.4.0b1 vld PK!J?jf f pkgxml/alt-php73-vld.xmlnu[ vld pecl.php.net Provides functionality to dump the internal representation of PHP scripts The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. Derick Rethans derick derick@xdebug.org yes 2021-01-11 0.17.1 0.17.1 beta beta BSD style - Added support for PHP 8.0. 7.0.0 1.4.0b1 vld PK!J?jf f pkgxml/alt-php74-vld.xmlnu[ vld pecl.php.net Provides functionality to dump the internal representation of PHP scripts The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. Derick Rethans derick derick@xdebug.org yes 2021-01-11 0.17.1 0.17.1 beta beta BSD style - Added support for PHP 8.0. 7.0.0 1.4.0b1 vld PK!J?jf f pkgxml/alt-php71-vld.xmlnu[ vld pecl.php.net Provides functionality to dump the internal representation of PHP scripts The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. Derick Rethans derick derick@xdebug.org yes 2021-01-11 0.17.1 0.17.1 beta beta BSD style - Added support for PHP 8.0. 7.0.0 1.4.0b1 vld PK!.depdbnu[a:3:{s:8:"_version";s:3:"1.0";s:12:"dependencies";a:1:{s:12:"pear.php.net";a:6:{s:4:"pear";a:9:{i:0;a:3:{s:3:"dep";a:3:{s:4:"name";s:11:"Archive_Tar";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:6:"1.3.11";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:4:{s:4:"name";s:16:"Structures_Graph";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.2";s:11:"recommended";s:5:"1.0.4";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:2;a:3:{s:3:"dep";a:4:{s:4:"name";s:14:"Console_Getopt";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.2";s:11:"recommended";s:5:"1.2.3";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:3;a:3:{s:3:"dep";a:4:{s:4:"name";s:8:"XML_Util";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.2.0";s:11:"recommended";s:5:"1.2.3";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:4;a:3:{s:3:"dep";a:4:{s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:3:"max";s:3:"0.4";s:9:"conflicts";s:0:"";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:5;a:3:{s:3:"dep";a:5:{s:4:"name";s:17:"PEAR_Frontend_Gtk";s:7:"channel";s:12:"pear.php.net";s:3:"max";s:5:"0.4.0";s:7:"exclude";s:5:"0.4.0";s:9:"conflicts";s:0:"";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:6;a:3:{s:3:"dep";a:3:{s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.5.1";}s:4:"type";s:8:"optional";s:5:"group";s:12:"webinstaller";}i:7;a:3:{s:3:"dep";a:3:{s:4:"name";s:17:"PEAR_Frontend_Gtk";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.4.0";}s:4:"type";s:8:"optional";s:5:"group";s:12:"gtkinstaller";}i:8;a:3:{s:3:"dep";a:2:{s:4:"name";s:18:"PEAR_Frontend_Gtk2";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"optional";s:5:"group";s:13:"gtk2installer";}}s:4:"mail";a:1:{i:0;a:3:{s:3:"dep";a:3:{s:4:"name";s:8:"Net_SMTP";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.1";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}s:9:"file_marc";a:2:{i:0;a:3:{s:3:"dep";a:2:{s:4:"name";s:21:"Structures_LinkedList";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:2:{s:4:"name";s:13:"Validate_ISPN";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}s:15:"mail_mimedecode";a:1:{i:0;a:3:{s:3:"dep";a:4:{s:4:"name";s:9:"Mail_Mime";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";s:7:"exclude";s:5:"1.4.0";}s:4:"type";s:8:"required";s:5:"group";b:0;}}s:9:"net_sieve";a:2:{i:0;a:3:{s:3:"dep";a:3:{s:4:"name";s:10:"Net_Socket";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.0";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:3:{s:4:"name";s:9:"Auth_SASL";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.0";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}s:8:"net_smtp";a:2:{i:0;a:3:{s:3:"dep";a:3:{s:4:"name";s:10:"Net_Socket";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.7";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:3:{s:4:"name";s:9:"Auth_SASL";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.5";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}}}s:8:"packages";a:1:{s:12:"pear.php.net";a:13:{s:11:"archive_tar";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:16:"structures_graph";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:14:"console_getopt";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:8:"xml_util";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:17:"pear_frontend_web";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:17:"pear_frontend_gtk";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:18:"pear_frontend_gtk2";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:8:"net_smtp";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"mail";}}s:21:"structures_linkedlist";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:9:"file_marc";}}s:13:"validate_ispn";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:9:"file_marc";}}s:9:"mail_mime";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:15:"mail_mimedecode";}}s:10:"net_socket";a:2:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:9:"net_sieve";}i:1;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:8:"net_smtp";}}s:9:"auth_sasl";a:2:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:9:"net_sieve";}i:1;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:8:"net_smtp";}}}}}PK!.locknu[PK! .depdblocknu[PK!Zaa.filemapnu[a:5:{s:3:"php";a:104:{s:15:"Archive/Tar.php";s:11:"archive_tar";s:18:"Console/Getopt.php";s:14:"console_getopt";s:12:"OS/Guess.php";s:4:"pear";s:27:"PEAR/ChannelFile/Parser.php";s:4:"pear";s:21:"PEAR/Command/Auth.xml";s:4:"pear";s:21:"PEAR/Command/Auth.php";s:4:"pear";s:22:"PEAR/Command/Build.xml";s:4:"pear";s:22:"PEAR/Command/Build.php";s:4:"pear";s:25:"PEAR/Command/Channels.xml";s:4:"pear";s:25:"PEAR/Command/Channels.php";s:4:"pear";s:23:"PEAR/Command/Common.php";s:4:"pear";s:23:"PEAR/Command/Config.xml";s:4:"pear";s:23:"PEAR/Command/Config.php";s:4:"pear";s:24:"PEAR/Command/Install.xml";s:4:"pear";s:24:"PEAR/Command/Install.php";s:4:"pear";s:23:"PEAR/Command/Mirror.xml";s:4:"pear";s:23:"PEAR/Command/Mirror.php";s:4:"pear";s:24:"PEAR/Command/Package.xml";s:4:"pear";s:24:"PEAR/Command/Package.php";s:4:"pear";s:23:"PEAR/Command/Pickle.xml";s:4:"pear";s:23:"PEAR/Command/Pickle.php";s:4:"pear";s:25:"PEAR/Command/Registry.xml";s:4:"pear";s:25:"PEAR/Command/Registry.php";s:4:"pear";s:23:"PEAR/Command/Remote.xml";s:4:"pear";s:23:"PEAR/Command/Remote.php";s:4:"pear";s:21:"PEAR/Command/Test.xml";s:4:"pear";s:21:"PEAR/Command/Test.php";s:4:"pear";s:27:"PEAR/Downloader/Package.php";s:4:"pear";s:21:"PEAR/Frontend/CLI.php";s:4:"pear";s:30:"PEAR/Installer/Role/Common.php";s:4:"pear";s:27:"PEAR/Installer/Role/Cfg.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Cfg.php";s:4:"pear";s:28:"PEAR/Installer/Role/Data.xml";s:4:"pear";s:28:"PEAR/Installer/Role/Data.php";s:4:"pear";s:27:"PEAR/Installer/Role/Doc.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Doc.php";s:4:"pear";s:27:"PEAR/Installer/Role/Ext.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Ext.php";s:4:"pear";s:27:"PEAR/Installer/Role/Man.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Man.php";s:4:"pear";s:27:"PEAR/Installer/Role/Php.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Php.php";s:4:"pear";s:30:"PEAR/Installer/Role/Script.xml";s:4:"pear";s:30:"PEAR/Installer/Role/Script.php";s:4:"pear";s:27:"PEAR/Installer/Role/Src.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Src.php";s:4:"pear";s:28:"PEAR/Installer/Role/Test.xml";s:4:"pear";s:28:"PEAR/Installer/Role/Test.php";s:4:"pear";s:27:"PEAR/Installer/Role/Www.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Www.php";s:4:"pear";s:23:"PEAR/Installer/Role.php";s:4:"pear";s:33:"PEAR/PackageFile/Generator/v1.php";s:4:"pear";s:33:"PEAR/PackageFile/Generator/v2.php";s:4:"pear";s:30:"PEAR/PackageFile/Parser/v1.php";s:4:"pear";s:30:"PEAR/PackageFile/Parser/v2.php";s:4:"pear";s:26:"PEAR/PackageFile/v2/rw.php";s:4:"pear";s:33:"PEAR/PackageFile/v2/Validator.php";s:4:"pear";s:23:"PEAR/PackageFile/v1.php";s:4:"pear";s:23:"PEAR/PackageFile/v2.php";s:4:"pear";s:16:"PEAR/REST/10.php";s:4:"pear";s:16:"PEAR/REST/11.php";s:4:"pear";s:16:"PEAR/REST/13.php";s:4:"pear";s:34:"PEAR/Task/Postinstallscript/rw.php";s:4:"pear";s:24:"PEAR/Task/Replace/rw.php";s:4:"pear";s:24:"PEAR/Task/Unixeol/rw.php";s:4:"pear";s:27:"PEAR/Task/Windowseol/rw.php";s:4:"pear";s:20:"PEAR/Task/Common.php";s:4:"pear";s:31:"PEAR/Task/Postinstallscript.php";s:4:"pear";s:21:"PEAR/Task/Replace.php";s:4:"pear";s:21:"PEAR/Task/Unixeol.php";s:4:"pear";s:24:"PEAR/Task/Windowseol.php";s:4:"pear";s:23:"PEAR/Validator/PECL.php";s:4:"pear";s:16:"PEAR/Builder.php";s:4:"pear";s:20:"PEAR/ChannelFile.php";s:4:"pear";s:16:"PEAR/Command.php";s:4:"pear";s:15:"PEAR/Common.php";s:4:"pear";s:15:"PEAR/Config.php";s:4:"pear";s:21:"PEAR/DependencyDB.php";s:4:"pear";s:20:"PEAR/Dependency2.php";s:4:"pear";s:19:"PEAR/Downloader.php";s:4:"pear";s:19:"PEAR/ErrorStack.php";s:4:"pear";s:18:"PEAR/Exception.php";s:4:"pear";s:17:"PEAR/Frontend.php";s:4:"pear";s:18:"PEAR/Installer.php";s:4:"pear";s:20:"PEAR/PackageFile.php";s:4:"pear";s:17:"PEAR/Packager.php";s:4:"pear";s:14:"PEAR/Proxy.php";s:4:"pear";s:17:"PEAR/Registry.php";s:4:"pear";s:13:"PEAR/REST.php";s:4:"pear";s:16:"PEAR/RunTest.php";s:4:"pear";s:17:"PEAR/Validate.php";s:4:"pear";s:18:"PEAR/XMLParser.php";s:4:"pear";s:19:"scripts/pearcmd.php";s:4:"pear";s:19:"scripts/peclcmd.php";s:4:"pear";s:8:"PEAR.php";s:4:"pear";s:10:"System.php";s:4:"pear";s:44:"Structures/Graph/Manipulator/AcyclicTest.php";s:16:"structures_graph";s:50:"Structures/Graph/Manipulator/TopologicalSorter.php";s:16:"structures_graph";s:25:"Structures/Graph/Node.php";s:16:"structures_graph";s:20:"Structures/Graph.php";s:16:"structures_graph";s:11:"XML/RPC.php";s:7:"xml_rpc";s:16:"XML/RPC/Dump.php";s:7:"xml_rpc";s:18:"XML/RPC/Server.php";s:7:"xml_rpc";s:12:"XML/Util.php";s:8:"xml_util";}s:3:"doc";a:8:{s:32:"archive_tar/docs/Archive_Tar.txt";s:11:"archive_tar";s:12:"pear/LICENSE";s:4:"pear";s:12:"pear/INSTALL";s:4:"pear";s:15:"pear/README.rst";s:4:"pear";s:69:"structures_graph/docs/tutorials/Structures_Graph/Structures_Graph.pkg";s:16:"structures_graph";s:24:"structures_graph/LICENSE";s:16:"structures_graph";s:29:"xml_util/examples/example.php";s:8:"xml_util";s:30:"xml_util/examples/example2.php";s:8:"xml_util";}s:4:"test";a:40:{s:36:"console_getopt/tests/001-getopt.phpt";s:14:"console_getopt";s:34:"console_getopt/tests/bug10557.phpt";s:14:"console_getopt";s:34:"console_getopt/tests/bug11068.phpt";s:14:"console_getopt";s:34:"console_getopt/tests/bug13140.phpt";s:14:"console_getopt";s:35:"structures_graph/tests/AllTests.php";s:16:"structures_graph";s:41:"structures_graph/tests/BasicGraphTest.php";s:16:"structures_graph";s:48:"structures_graph/tests/TopologicalSorterTest.php";s:16:"structures_graph";s:42:"structures_graph/tests/AcyclicTestTest.php";s:16:"structures_graph";s:33:"structures_graph/tests/helper.inc";s:16:"structures_graph";s:32:"xml_rpc/tests/actual-request.php";s:7:"xml_rpc";s:24:"xml_rpc/tests/allgot.inc";s:7:"xml_rpc";s:36:"xml_rpc/tests/empty-value-struct.php";s:7:"xml_rpc";s:29:"xml_rpc/tests/empty-value.php";s:7:"xml_rpc";s:24:"xml_rpc/tests/encode.php";s:7:"xml_rpc";s:29:"xml_rpc/tests/extra-lines.php";s:7:"xml_rpc";s:27:"xml_rpc/tests/protoport.php";s:7:"xml_rpc";s:27:"xml_rpc/tests/test_Dump.php";s:7:"xml_rpc";s:23:"xml_rpc/tests/types.php";s:7:"xml_rpc";s:36:"xml_util/tests/AbstractUnitTests.php";s:8:"xml_util";s:34:"xml_util/tests/ApiVersionTests.php";s:8:"xml_util";s:42:"xml_util/tests/AttributesToStringTests.php";s:8:"xml_util";s:41:"xml_util/tests/CollapseEmptyTagsTests.php";s:8:"xml_util";s:42:"xml_util/tests/CreateCDataSectionTests.php";s:8:"xml_util";s:37:"xml_util/tests/CreateCommentTests.php";s:8:"xml_util";s:40:"xml_util/tests/CreateEndElementTests.php";s:8:"xml_util";s:42:"xml_util/tests/CreateStartElementTests.php";s:8:"xml_util";s:33:"xml_util/tests/CreateTagTests.php";s:8:"xml_util";s:42:"xml_util/tests/CreateTagFromArrayTests.php";s:8:"xml_util";s:45:"xml_util/tests/GetDocTypeDeclarationTests.php";s:8:"xml_util";s:41:"xml_util/tests/GetXmlDeclarationTests.php";s:8:"xml_util";s:35:"xml_util/tests/IsValidNameTests.php";s:8:"xml_util";s:34:"xml_util/tests/RaiseErrorTests.php";s:8:"xml_util";s:39:"xml_util/tests/ReplaceEntitiesTests.php";s:8:"xml_util";s:39:"xml_util/tests/ReverseEntitiesTests.php";s:8:"xml_util";s:42:"xml_util/tests/SplitQualifiedNameTests.php";s:8:"xml_util";s:31:"xml_util/tests/Bug4950Tests.php";s:8:"xml_util";s:31:"xml_util/tests/Bug5392Tests.php";s:8:"xml_util";s:32:"xml_util/tests/Bug18343Tests.php";s:8:"xml_util";s:32:"xml_util/tests/Bug21177Tests.php";s:8:"xml_util";s:32:"xml_util/tests/Bug21184Tests.php";s:8:"xml_util";}s:6:"script";a:3:{s:15:"scripts/pear.sh";s:4:"pear";s:18:"scripts/peardev.sh";s:4:"pear";s:15:"scripts/pecl.sh";s:4:"pear";}s:4:"data";a:2:{s:16:"pear/package.dtd";s:4:"pear";s:18:"pear/template.spec";s:4:"pear";}}PK!`  .channels/__uri.regnu[a:4:{s:4:"name";s:5:"__uri";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:4:"****";}}}}s:7:"summary";s:34:"Pseudo-channel for static packages";s:13:"_lastmodified";i:1747073454;}PK!v++.channels/pecl.php.net.regnu[a:6:{s:14:"suggestedalias";s:4:"pecl";s:4:"name";s:12:"pecl.php.net";s:7:"summary";s:31:"PHP Extension Community Library";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:2:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:25:"http://pecl.php.net/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:25:"http://pecl.php.net/rest/";}}}}}s:15:"validatepackage";a:2:{s:8:"_content";s:19:"PEAR_Validator_PECL";s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}}s:13:"_lastmodified";i:1747073454;}PK!o/ .channels/.alias/phpdocs.txtnu[doc.php.netPK! .channels/.alias/pear.txtnu[pear.php.netPK!ui< .channels/.alias/pecl.txtnu[pecl.php.netPK!V.channels/doc.php.net.regnu[a:5:{s:14:"suggestedalias";s:7:"phpdocs";s:4:"name";s:11:"doc.php.net";s:7:"summary";s:22:"PHP Documentation Team";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:3:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:24:"http://doc.php.net/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:24:"http://doc.php.net/rest/";}i:2;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.3";}s:8:"_content";s:24:"http://doc.php.net/rest/";}}}}}s:13:"_lastmodified";i:1747073454;}PK!4M((.channels/pear.php.net.regnu[a:5:{s:14:"suggestedalias";s:4:"pear";s:4:"name";s:12:"pear.php.net";s:7:"summary";s:40:"PHP Extension and Application Repository";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:3:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:25:"http://pear.php.net/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:25:"http://pear.php.net/rest/";}i:2;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.3";}s:8:"_content";s:25:"http://pear.php.net/rest/";}}}}}s:13:"_lastmodified";i:1747073454;}PK!uvuv.registry/xml_util.regnu[a:23:{s:7:"attribs";a:6:{s:15:"packagerversion";s:6:"1.10.5";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:8:"XML_Util";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:17:"XML utility class";s:11:"description";s:192:"Selection of methods that are often needed when working with XML documents. Functionality includes creating of attribute lists from arrays, creation of tags, validation of XML names and more.";s:4:"lead";a:2:{i:0;a:4:{s:4:"name";s:13:"Chuck Burgess";s:4:"user";s:7:"ashnazg";s:5:"email";s:15:"ashnazg@php.net";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:15:"Stephan Schmidt";s:4:"user";s:5:"schst";s:5:"email";s:19:"schst@php-tools.net";s:6:"active";s:2:"no";}}s:6:"helper";a:4:{s:4:"name";s:12:"Davey Shafik";s:4:"user";s:5:"davey";s:5:"email";s:13:"davey@php.net";s:6:"active";s:2:"no";}s:4:"date";s:10:"2020-04-19";s:4:"time";s:8:"14:54:10";s:7:"version";a:2:{s:7:"release";s:5:"1.4.5";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:64:"* PR #12: fix Trying to access array offset on value of type int";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:25:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"af2746028ae4395f549855a5e444ada7";s:4:"name";s:20:"examples/example.php";s:4:"role";s:3:"doc";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b9e52f4aa372c4067c609f49c2285b8f";s:4:"name";s:21:"examples/example2.php";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d0af9354df0962e70e9e2215b5611b9c";s:4:"name";s:27:"tests/AbstractUnitTests.php";s:4:"role";s:4:"test";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"57ce547d64d6e1f2986c313407deffef";s:4:"name";s:25:"tests/ApiVersionTests.php";s:4:"role";s:4:"test";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2d0427db94790df7ada24a744547edf5";s:4:"name";s:33:"tests/AttributesToStringTests.php";s:4:"role";s:4:"test";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"673d1438c4718a70c5da3fe019027db4";s:4:"name";s:32:"tests/CollapseEmptyTagsTests.php";s:4:"role";s:4:"test";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"46b981f91edd163f1cd021cfef5d1bb1";s:4:"name";s:33:"tests/CreateCDataSectionTests.php";s:4:"role";s:4:"test";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6aa925b879572e9b3f1885b7cdbb223b";s:4:"name";s:28:"tests/CreateCommentTests.php";s:4:"role";s:4:"test";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dbc083b62a020fa245fde5a7828a4806";s:4:"name";s:31:"tests/CreateEndElementTests.php";s:4:"role";s:4:"test";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f58e38343ecf60811c842d4cfc8194ae";s:4:"name";s:33:"tests/CreateStartElementTests.php";s:4:"role";s:4:"test";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9385fba272f4ebccf4c95d43d16dcff4";s:4:"name";s:24:"tests/CreateTagTests.php";s:4:"role";s:4:"test";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"51e7ba1390e6dadc3c0be0c960bf171d";s:4:"name";s:33:"tests/CreateTagFromArrayTests.php";s:4:"role";s:4:"test";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6bbb54ef4cf56dc2c0b558b295de5668";s:4:"name";s:36:"tests/GetDocTypeDeclarationTests.php";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"825b440b0ee8abd10b4df017c08bf15f";s:4:"name";s:32:"tests/GetXmlDeclarationTests.php";s:4:"role";s:4:"test";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e6783bb330f8f2ae7225f02d56f194e4";s:4:"name";s:26:"tests/IsValidNameTests.php";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b273525b905ae6d5fc53adcb3ce0b8d9";s:4:"name";s:25:"tests/RaiseErrorTests.php";s:4:"role";s:4:"test";}}i:16;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"20befbef5e55639539336761a17c64f3";s:4:"name";s:30:"tests/ReplaceEntitiesTests.php";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a3ceff3302e31f90130be01c312b33b3";s:4:"name";s:30:"tests/ReverseEntitiesTests.php";s:4:"role";s:4:"test";}}i:18;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"aeb95108896180ef77a7dce3c310a3b8";s:4:"name";s:33:"tests/SplitQualifiedNameTests.php";s:4:"role";s:4:"test";}}i:19;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e93010b1eff68f889fefcb006bf20b63";s:4:"name";s:22:"tests/Bug4950Tests.php";s:4:"role";s:4:"test";}}i:20;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"748ffb640e13e7b960385c7e12413782";s:4:"name";s:22:"tests/Bug5392Tests.php";s:4:"role";s:4:"test";}}i:21;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"01e68b66e27a6fdb197d572c67ae6bc5";s:4:"name";s:23:"tests/Bug18343Tests.php";s:4:"role";s:4:"test";}}i:22;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d945220c38344bc773b18244439bb0cc";s:4:"name";s:23:"tests/Bug21177Tests.php";s:4:"role";s:4:"test";}}i:23;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"af2672bb90875c2e00f93f563bfafe70";s:4:"name";s:23:"tests/Bug21184Tests.php";s:4:"role";s:4:"test";}}i:24;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0db6fa9c169bf6904aa7e588c2325a13";s:4:"name";s:12:"XML/Util.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}}}}s:12:"dependencies";a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.4.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.9.0";}s:9:"extension";a:1:{s:4:"name";s:4:"pcre";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:31:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.1";s:3:"api";s:3:"0.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-08-01";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:14:"inital release";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.1.1";s:3:"api";s:5:"0.1.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-08-02";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:41:"bugfix: removed bug in createTagFromArray";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.2";s:3:"api";s:3:"0.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-08-12";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:39:"added XML_Util::getDocTypeDeclaration()";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.2.1";s:3:"api";s:5:"0.2.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-09-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:70:"fixed bug with zero as tag content in createTagFromArray and createTag";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.3";s:3:"api";s:3:"0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-09-12";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:49:"added createStartElement() and createEndElement()";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.4";s:3:"api";s:3:"0.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-09-21";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:132:"added createCDataSection(), added support for CData sections in createTag* methods, fixed bug #23, fixed bug in splitQualifiedName()";}i:6;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.5";s:3:"api";s:3:"0.5";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-09-23";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:170:"added support for multiline attributes in attributesToString(), createTag*() and createStartElement (requested by Yavor Shahpasov for XML_Serializer), added createComment";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.5.1";s:3:"api";s:5:"0.5.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-09-26";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:102:"added default namespace parameter (optional) in splitQualifiedName() (requested by Sebastian Bergmann)";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.5.2";s:3:"api";s:5:"0.5.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-11-22";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:78:"now creates XHTML compliant empty tags (Davey), minor whitespace fixes (Davey)";}i:9;a:5:{s:7:"version";a:2:{s:7:"release";s:10:"0.6.0beta1";s:3:"api";s:10:"0.6.0beta1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2004-05-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:567:"- Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey) - added optional parameter to replaceEntities() to define the set of entities to replace - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann) - allowed second parameter to XML_Util::attributesToString() to be an array containing options (easier to use, if you only need to set the last parameter) - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error";}i:10;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.6.0";s:3:"api";s:5:"0.6.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-06-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:567:"- Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey) - added optional parameter to replaceEntities() to define the set of entities to replace - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann) - allowed second parameter to XML_Util::attributesToString() to be an array containing options (easier to use, if you only need to set the last parameter) - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error";}i:11;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.6.1";s:3:"api";s:5:"0.6.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-10-28";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:103:"- Added check for tag name (either as local part or qualified name) in createTagFromArray() (bug #1083)";}i:12;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.0";s:3:"api";s:5:"1.0.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-10-28";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:41:"- Added reverseEntities() (request #2639)";}i:13;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.0";s:3:"api";s:5:"1.1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-11-19";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:73:"- Added collapseEmptyTags (patch by Sebastian Bergmann and Thomas Duffey)";}i:14;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.1";s:3:"api";s:5:"1.1.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-12-23";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:306:"- fixed bug in replaceEntities() and reverseEntities() in conjunction with XML_UTIL_ENTITIES_HTML - createTag() and createTagFromArray() now accept XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML, XML_UTIL_ENTITIES_NONE and XML_UTIL_CDATA_SECTION as $replaceEntities parameter";}i:15;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.2";s:3:"api";s:5:"1.1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-12-01";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:207:"- fixed bug #5419: isValidName() now checks for character classes - implemented request #8196: added optional parameter to influence array sorting to createTag() createTagFromArray() and createStartElement()";}i:16;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.4";s:3:"api";s:5:"1.1.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-12-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:61:"- Fixed bug #9561: Not allowing underscores in middle of tags";}i:17;a:5:{s:7:"version";a:2:{s:7:"release";s:7:"1.2.0a1";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:5:"alpha";}s:4:"date";s:10:"2008-05-04";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:208:"Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|ja.doma]";}i:18;a:5:{s:7:"version";a:2:{s:7:"release";s:7:"1.2.0a2";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:5:"alpha";}s:4:"date";s:10:"2008-05-22";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:403:"Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry] Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry] -- (this fix differs from the one in v1.2.0a1)";}i:19;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC1";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2008-07-12";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:403:"Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry] Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry] -- (this fix differs from the one in v1.2.0a1)";}i:20;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.0";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2008-07-26";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:403:"Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry] Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry] -- (this fix differs from the one in v1.2.0a1)";}i:21;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.1";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2011-12-31";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:68:"Fixed Bug #14760: Bug in getDocTypeDeclaration() [ashnazg|fpospisil]";}i:22;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.2";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2014-06-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:194:"QA release Bug #18343 Entities in file names decoded during packaging Bug #19174 upgrade PHPUnit require statements & other fixes (for PEAR QA Team) Request #19750 examples/example.php encoding";}i:23;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.3";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2014-06-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:40:"Bug #20293 Broken installation for 1.2.2";}i:24;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.0";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2015-02-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:76:"* Set minimum PHP version to 5.3.0 * Mark static methods with static keyword";}i:25;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.0";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2017-02-03";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:203:"* Set minimum PHP version to 5.4.0 * Set minimum PEAR version to 1.10.1 * Adds a new XML_UTIL_COLLAPSE_NONE option for preventing empty tag collapsing. * Request #15467 CDATA sections and blank nodes";}i:26;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.1";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2017-02-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:58:"* Bug #21177 XML_Util::collapseEmptyTags() can return NULL";}i:27;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.2";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2017-02-22";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:27:"* Bug #21184 Collapse issue";}i:28;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.3";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2017-06-28";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:63:"* Decrease minimum PEAR version to 1.9.0 to allow PEAR upgrades";}i:29;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.4";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2019-12-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:29:"* PR #11: fix phplint warning";}i:30;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.5";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2020-04-19";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:42:"http://opensource.org/licenses/bsd-license";}s:8:"_content";s:11:"BSD License";}s:5:"notes";s:64:"* PR #12: fix Trying to access array offset on value of type int";}}}s:8:"filelist";a:25:{s:20:"examples/example.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"af2746028ae4395f549855a5e444ada7";s:4:"name";s:20:"examples/example.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:63:"/opt/alt/php84/usr/share/doc/pear/XML_Util/examples/example.php";}s:21:"examples/example2.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b9e52f4aa372c4067c609f49c2285b8f";s:4:"name";s:21:"examples/example2.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:64:"/opt/alt/php84/usr/share/doc/pear/XML_Util/examples/example2.php";}s:27:"tests/AbstractUnitTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d0af9354df0962e70e9e2215b5611b9c";s:4:"name";s:27:"tests/AbstractUnitTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/AbstractUnitTests.php";}s:25:"tests/ApiVersionTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"57ce547d64d6e1f2986c313407deffef";s:4:"name";s:25:"tests/ApiVersionTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/ApiVersionTests.php";}s:33:"tests/AttributesToStringTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2d0427db94790df7ada24a744547edf5";s:4:"name";s:33:"tests/AttributesToStringTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/AttributesToStringTests.php";}s:32:"tests/CollapseEmptyTagsTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"673d1438c4718a70c5da3fe019027db4";s:4:"name";s:32:"tests/CollapseEmptyTagsTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/CollapseEmptyTagsTests.php";}s:33:"tests/CreateCDataSectionTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"46b981f91edd163f1cd021cfef5d1bb1";s:4:"name";s:33:"tests/CreateCDataSectionTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/CreateCDataSectionTests.php";}s:28:"tests/CreateCommentTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6aa925b879572e9b3f1885b7cdbb223b";s:4:"name";s:28:"tests/CreateCommentTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:72:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/CreateCommentTests.php";}s:31:"tests/CreateEndElementTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dbc083b62a020fa245fde5a7828a4806";s:4:"name";s:31:"tests/CreateEndElementTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:75:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/CreateEndElementTests.php";}s:33:"tests/CreateStartElementTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f58e38343ecf60811c842d4cfc8194ae";s:4:"name";s:33:"tests/CreateStartElementTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/CreateStartElementTests.php";}s:24:"tests/CreateTagTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9385fba272f4ebccf4c95d43d16dcff4";s:4:"name";s:24:"tests/CreateTagTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/CreateTagTests.php";}s:33:"tests/CreateTagFromArrayTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"51e7ba1390e6dadc3c0be0c960bf171d";s:4:"name";s:33:"tests/CreateTagFromArrayTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/CreateTagFromArrayTests.php";}s:36:"tests/GetDocTypeDeclarationTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6bbb54ef4cf56dc2c0b558b295de5668";s:4:"name";s:36:"tests/GetDocTypeDeclarationTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:80:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/GetDocTypeDeclarationTests.php";}s:32:"tests/GetXmlDeclarationTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"825b440b0ee8abd10b4df017c08bf15f";s:4:"name";s:32:"tests/GetXmlDeclarationTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/GetXmlDeclarationTests.php";}s:26:"tests/IsValidNameTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e6783bb330f8f2ae7225f02d56f194e4";s:4:"name";s:26:"tests/IsValidNameTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/IsValidNameTests.php";}s:25:"tests/RaiseErrorTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b273525b905ae6d5fc53adcb3ce0b8d9";s:4:"name";s:25:"tests/RaiseErrorTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/RaiseErrorTests.php";}s:30:"tests/ReplaceEntitiesTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"20befbef5e55639539336761a17c64f3";s:4:"name";s:30:"tests/ReplaceEntitiesTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:74:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/ReplaceEntitiesTests.php";}s:30:"tests/ReverseEntitiesTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a3ceff3302e31f90130be01c312b33b3";s:4:"name";s:30:"tests/ReverseEntitiesTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:74:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/ReverseEntitiesTests.php";}s:33:"tests/SplitQualifiedNameTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"aeb95108896180ef77a7dce3c310a3b8";s:4:"name";s:33:"tests/SplitQualifiedNameTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/SplitQualifiedNameTests.php";}s:22:"tests/Bug4950Tests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e93010b1eff68f889fefcb006bf20b63";s:4:"name";s:22:"tests/Bug4950Tests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/Bug4950Tests.php";}s:22:"tests/Bug5392Tests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"748ffb640e13e7b960385c7e12413782";s:4:"name";s:22:"tests/Bug5392Tests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/Bug5392Tests.php";}s:23:"tests/Bug18343Tests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"01e68b66e27a6fdb197d572c67ae6bc5";s:4:"name";s:23:"tests/Bug18343Tests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:67:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/Bug18343Tests.php";}s:23:"tests/Bug21177Tests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d945220c38344bc773b18244439bb0cc";s:4:"name";s:23:"tests/Bug21177Tests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:67:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/Bug21177Tests.php";}s:23:"tests/Bug21184Tests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"af2672bb90875c2e00f93f563bfafe70";s:4:"name";s:23:"tests/Bug21184Tests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:67:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests/Bug21184Tests.php";}s:12:"XML/Util.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0db6fa9c169bf6904aa7e588c2325a13";s:4:"name";s:12:"XML/Util.php";s:4:"role";s:3:"php";s:12:"installed_as";s:42:"/opt/alt/php84/usr/share/pear/XML/Util.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:5:{s:51:"/opt/alt/php84/usr/share/doc/pear/XML_Util/examples";b:1;s:42:"/opt/alt/php84/usr/share/doc/pear/XML_Util";b:1;s:49:"/opt/alt/php84/usr/share/pear/test/XML_Util/tests";b:1;s:43:"/opt/alt/php84/usr/share/pear/test/XML_Util";b:1;s:33:"/opt/alt/php84/usr/share/pear/XML";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.4.5";s:12:"release_date";s:10:"2020-04-19";s:13:"release_state";s:6:"stable";s:15:"release_license";s:11:"BSD License";s:13:"release_notes";s:64:"* PR #12: fix Trying to access array offset on value of type int";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.4.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.9.0";s:8:"optional";s:2:"no";}i:2;a:4:{s:4:"type";s:3:"ext";s:4:"name";s:4:"pcre";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:3:{i:0;a:5:{s:4:"name";s:13:"Chuck Burgess";s:5:"email";s:15:"ashnazg@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:7:"ashnazg";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:15:"Stephan Schmidt";s:5:"email";s:19:"schst@php-tools.net";s:6:"active";s:2:"no";s:6:"handle";s:5:"schst";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:12:"Davey Shafik";s:5:"email";s:13:"davey@php.net";s:6:"active";s:2:"no";s:6:"handle";s:5:"davey";s:4:"role";s:6:"helper";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1747073454;}PK!sРWW.registry/archive_tar.regnu[a:24:{s:7:"attribs";a:6:{s:15:"packagerversion";s:7:"1.10.12";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:11:"Archive_Tar";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:25:"Tar file management class";s:11:"description";s:321:"This class provides handling of tar files in PHP. It supports creating, listing, extracting and adding to tar files. Gzip support is available if PHP has the zlib extension built-in or loaded. Bz2 compression is also supported with the bz2 extension loaded. Also Lzma2 compressed archives are supported with xz extension.";s:4:"lead";a:3:{i:0;a:4:{s:4:"name";s:14:"Vincent Blavet";s:4:"user";s:7:"vblavet";s:5:"email";s:22:"vincent@phpconcept.net";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:11:"Greg Beaver";s:4:"user";s:6:"cellog";s:5:"email";s:22:"greg@chiaraquartet.net";s:6:"active";s:2:"no";}i:2;a:4:{s:4:"name";s:12:"Michiel Rook";s:4:"user";s:5:"mrook";s:5:"email";s:13:"mrook@php.net";s:6:"active";s:3:"yes";}}s:6:"helper";a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}s:4:"date";s:10:"2021-07-20";s:4:"time";s:8:"19:35:29";s:7:"version";a:2:{s:7:"release";s:6:"1.4.14";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:60:"* Properly fix symbolic link path traversal (CVE-2021-32610)";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:2:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"95f04c226245ad192b52c9164c1287ad";s:4:"name";s:15:"Archive/Tar.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2fb90f0be7089a45c09a0d1182792419";s:4:"name";s:20:"docs/Archive_Tar.txt";s:4:"role";s:3:"doc";}}}}}s:10:"compatible";a:4:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.8.0";s:3:"max";s:7:"1.10.10";}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.2.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.9.0";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:39:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.4.13";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2021-02-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:81:"* Fix Bug #27010: Relative symlinks failing (out-of path file extraction) [mrook]";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.4.12";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2021-01-18";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:82:"* Fix Bug #27008: Symlink out-of-path write vulnerability (CVE-2020-36193) [mrook]";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.4.11";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2020-11-19";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:97:"* Fix Bug #27002: Filename manipulation vulnerabilities (CVE-2020-28948 / CVE-2020-28949) [mrook]";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.4.10";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2020-09-15";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:165:"* Fix block padding when the file buffer length is a multiple of 512 and smaller than Archive_Tar buffer length * Don't try to copy username/groupname in chroot jail";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.9";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2019-12-04";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:67:"* Implement Feature #23861: Add option to disallow symlinks [mrook]";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.8";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2019-10-21";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:79:"* Fix Bug #23852: PHP 7.4 - Archive_Tar->_readHeader throws deprecation [mrook]";}i:6;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.7";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2019-04-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:53:"* Improved performance by increasing read buffer size";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.6";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2019-02-01";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:67:"* Improve path traversal detection for forward and backward slashes";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.5";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2019-01-02";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:54:"* Fix Bug #23788: Relative symlinks are broken [mrook]";}i:9;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.4";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2018-12-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:127:"* Fix Bug #21058: Long symlinks are not supported [mrook] * Fix Bug #23782: Prevent phar:// files from being extracted [mrook]";}i:10;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.3";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2017-06-11";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:103:"* Fix Bug #21218: Cannot use result of built-in function in write context in PHP 7.2.0alpha1 [mrook]";}i:11;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.2";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2016-02-25";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:164:"* Fix reading of archives with files > 8GB * Performance optimizations * Do not try to call require_once on PEAR.php if it has already been loaded by the autoloader";}i:12;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.1";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2015-08-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:60:"* Update composer.json to use pear-core-minimal 1.10.0alpha2";}i:13;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.0";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2015-07-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:104:"* Add support for PHP 7 * Drop support for PHP 4 * Add visibility declarations to methods and properties";}i:14;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.3.16";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2015-04-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:73:"* Fix Bug #20514: invalid package.xml; not installable with pyrus [mrook]";}i:15;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.3.15";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2015-03-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:33:"* Fixes composer.json parse error";}i:16;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.3.14";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2015-02-26";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:74:"* Fix Bug #18505: Possible incorrect handling of file names in TAR [mrook]";}i:17;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.3.13";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2014-09-02";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:16:"New BSD License";}s:5:"notes";s:36:"* Fix Bug #20382: gzopen fix [mrook]";}i:18;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.3.12";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2014-08-04";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:16:"New BSD License";}s:5:"notes";s:350:"* Fix Bug #19964: Memory leaking in Archive_Tar [mrook] * Fix Bug #20246: Broken with php 5.5.9 [mrook] * Fix Bug #20275: "pax_global_header" looks like a regular file * [mrook] * Implement Feature #19827: pass filename to _addFile function - downstream * patch [mrook] * Implement Feature #20132: Add custom mode/uid/gid to addString() [mrook]";}i:19;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.3.11";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2013-02-09";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:18:"New BSD License";}s:5:"notes";s:128:"* Fix Bug #19746: Broken with PHP 5.5 [mrook] * Implement Feature #11258: Custom date/time in files added on-the-fly * [mrook]";}i:20;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.3.10";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2012-04-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:18:"New BSD License";}s:5:"notes";s:143:"* Fix Bug #13361: Unable to add() some files (ex. mp3) [mrook] * Fix Bug #19330: Class creates incorrect (non-readable) tar.gz file * [mrook]";}i:21;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.9";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2012-02-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:17:"New BSD License";}s:5:"notes";s:259:"* Fix Bug #16759: No error thrown from missing PHP zlib functions [mrook] * Fix Bug #18877: Incorrect handling of backslashes in filenames on Linux [mrook] * Fix Bug #19085: Error while packaging [mrook] * Fix Bug #19289: Invalid tar file generated [mrook]";}i:22;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.8";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2011-10-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:449:"* Fix Bug #17853: Test failure: dirtraversal.phpt [mrook] * Fix Bug #18512: dead links are not saved in tar file [mrook] * Fix Bug #18702: Unpacks incorrectly on long file names using header prefix [mrook] * Implement Feature #10145: Patch to return a Pear Error Object on failure [mrook] * Implement Feature #17491: Option to preserve permissions [mrook] * Implement Feature #17813: Prevent PHP notice when extracting corrupted archive [mrook]";}i:23;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.7";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-04-26";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:25:"PEAR compatibility update";}i:24;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.6";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-03-09";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:168:"* Fix Bug #16963: extractList can't extract zipped files from big tar [mrook] * Implement Feature #4013: Ignoring files and directories on creating an archive. [mrook]";}i:25;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.5";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-12-31";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:64:"* Fix Bug #16958: Update 'compatible' tag in package.xml [mrook]";}i:26;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.4";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-12-30";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:338:"* Fix Bug #11871: wrong result of ::listContent() if filename begins or ends with space [mrook] * Fix Bug #12462: invalid tar magic [mrook] * Fix Bug #13918: Long filenames may get up to 511 0x00 bytes appended on read [mrook] * Fix Bug #16202: Bogus modification times [mrook] * Implement Feature #16212: Die is not exception [mrook]";}i:27;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.3";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-03-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:249:"Change the license to New BSD license minor bugfix release * fix Bug #9921 compression with bzip2 fails [cellog] * fix Bug #11594 _readLongHeader leaves 0 bytes in filename [jamessas] * fix Bug #11769 Incorrect symlink handing [fajar99]";}i:28;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.2";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-01-03";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:484:"Correct Bug #4016 Remove duplicate remove error display with '@' Correct Bug #3909 : Check existence of OS_WINDOWS constant Correct Bug #5452 fix for "lone zero block" when untarring packages Change filemode (from pear-core/Archive/Tar.php v.1.21) Correct Bug #6486 Can not extract symlinks Correct Bug #6933 Archive_Tar (Tar file management class) Directory traversal Correct Bug #8114 Files added on-the-fly not storing date Correct Bug #9352 Bug on _dirCheck function over nfs path";}i:29;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-03-17";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:17:"Correct Bug #3855";}i:30;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.0";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-03-06";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:40:"Bugs correction (2475, 2488, 2135, 2176)";}i:31;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.2";s:3:"api";s:3:"1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-05-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:71:"Add support for other separator than the space char and bug correction";}i:32;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.1";s:3:"api";s:3:"1.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-05-28";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:141:"* Add support for BZ2 compression * Add support for add and extract without using temporary files : methods addString() and extractInString()";}i:33;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.0";s:3:"api";s:3:"1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-01-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:23:"Change status to stable";}i:34;a:5:{s:7:"version";a:2:{s:7:"release";s:7:"0.10-b1";s:3:"api";s:7:"0.10-b1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2003-01-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:59:"Add support for long filenames (greater than 99 characters)";}i:35;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.9";s:3:"api";s:3:"0.9";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-05-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:25:"Auto-detect gzip'ed files";}i:36;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.4";s:3:"api";s:3:"0.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-05-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:51:"Windows bugfix: use forward slashes inside archives";}i:37;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.2";s:3:"api";s:3:"0.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-02-18";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:29:"From initial commit to stable";}i:38;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.3";s:3:"api";s:3:"0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-04-13";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:47:"Windows bugfix: used wrong directory separators";}}}s:8:"filelist";a:2:{s:15:"Archive/Tar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"95f04c226245ad192b52c9164c1287ad";s:4:"name";s:15:"Archive/Tar.php";s:4:"role";s:3:"php";s:12:"installed_as";s:45:"/opt/alt/php84/usr/share/pear/Archive/Tar.php";}s:20:"docs/Archive_Tar.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2fb90f0be7089a45c09a0d1182792419";s:4:"name";s:20:"docs/Archive_Tar.txt";s:4:"role";s:3:"doc";s:12:"installed_as";s:66:"/opt/alt/php84/usr/share/doc/pear/Archive_Tar/docs/Archive_Tar.txt";}}s:12:"_lastversion";N;s:7:"dirtree";a:3:{s:37:"/opt/alt/php84/usr/share/pear/Archive";b:1;s:50:"/opt/alt/php84/usr/share/doc/pear/Archive_Tar/docs";b:1;s:45:"/opt/alt/php84/usr/share/doc/pear/Archive_Tar";b:1;}s:3:"old";a:7:{s:7:"version";s:6:"1.4.14";s:12:"release_date";s:10:"2021-07-20";s:13:"release_state";s:6:"stable";s:15:"release_license";s:15:"New BSD License";s:13:"release_notes";s:60:"* Properly fix symbolic link path traversal (CVE-2021-32610)";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.2.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.9.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:4:{i:0;a:5:{s:4:"name";s:14:"Vincent Blavet";s:5:"email";s:22:"vincent@phpconcept.net";s:6:"active";s:2:"no";s:6:"handle";s:7:"vblavet";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:11:"Greg Beaver";s:5:"email";s:22:"greg@chiaraquartet.net";s:6:"active";s:2:"no";s:6:"handle";s:6:"cellog";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:12:"Michiel Rook";s:5:"email";s:13:"mrook@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:5:"mrook";s:4:"role";s:4:"lead";}i:3;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:6:"helper";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1747073454;}PK!)).registry/console_getopt.regnu[a:25:{s:7:"attribs";a:6:{s:15:"packagerversion";s:7:"1.10.10";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:14:"Console_Getopt";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:26:"Command-line option parser";s:11:"description";s:80:"This is a PHP implementation of "getopt" supporting both short and long options.";s:4:"lead";a:4:{s:4:"name";s:15:"Andrei Zmievski";s:4:"user";s:6:"andrei";s:5:"email";s:14:"andrei@php.net";s:6:"active";s:2:"no";}s:9:"developer";a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}s:6:"helper";a:4:{s:4:"name";s:11:"Greg Beaver";s:4:"user";s:6:"cellog";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:2:"no";}s:4:"date";s:10:"2019-11-20";s:4:"time";s:8:"18:27:07";s:7:"version";a:2:{s:7:"release";s:5:"1.4.3";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:12:"BSD-2-Clause";}s:5:"notes";s:98:"* PR #4: Fix PHP 7.4 deprecation: array/string curly braces access * PR #5: fix phplint warnings";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:5:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63da5909aa85a0eb76e0ad0b5e00811a";s:4:"name";s:18:"Console/Getopt.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5a6fa63ce6f2370cdad11dc24a5addd0";s:4:"name";s:21:"tests/001-getopt.phpt";s:4:"role";s:4:"test";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7540b630cb8e7bfd8bb06fb65a010ae9";s:4:"name";s:19:"tests/bug10557.phpt";s:4:"role";s:4:"test";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e469de3628de85779118103b3248a44f";s:4:"name";s:19:"tests/bug11068.phpt";s:4:"role";s:4:"test";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cdc108b084ad8e82eeb2417f04b49ec8";s:4:"name";s:19:"tests/bug13140.phpt";s:4:"role";s:4:"test";}}}}}s:10:"compatible";a:4:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";s:3:"max";s:9:"1.999.999";}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.4.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.8.0";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:14:{i:0;a:5:{s:4:"date";s:10:"2019-11-20";s:7:"version";a:2:{s:7:"release";s:5:"1.4.3";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:12:"BSD-2-Clause";}s:5:"notes";s:98:"* PR #4: Fix PHP 7.4 deprecation: array/string curly braces access * PR #5: fix phplint warnings";}i:1;a:5:{s:4:"date";s:10:"2019-02-06";s:7:"version";a:2:{s:7:"release";s:5:"1.4.2";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:12:"BSD-2-Clause";}s:5:"notes";s:49:"* Remove use of each(), which is removed in PHP 8";}i:2;a:5:{s:4:"date";s:10:"2015-07-20";s:7:"version";a:2:{s:7:"release";s:5:"1.4.1";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:12:"BSD-2-Clause";}s:5:"notes";s:34:"* Fix unit test on PHP 7 [cweiske]";}i:3;a:5:{s:4:"date";s:10:"2015-02-22";s:7:"version";a:2:{s:7:"release";s:5:"1.4.0";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:12:"BSD-2-Clause";}s:5:"notes";s:111:"* Change license to BSD-2-Clause * Set minimum PHP version to 5.4.0 * Mark static methods with "static" keyword";}i:4;a:5:{s:4:"date";s:10:"2011-03-07";s:7:"version";a:2:{s:7:"release";s:5:"1.3.1";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:51:"* Change the minimum PEAR installer dep to be lower";}i:5;a:6:{s:4:"date";s:10:"2010-12-11";s:4:"time";s:8:"20:20:13";s:7:"version";a:2:{s:7:"release";s:5:"1.3.0";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:106:"* Implement Request #13140: [PATCH] to skip unknown parameters. [patch by rquadling, improved on by dufuz]";}i:6;a:5:{s:4:"date";s:10:"2007-06-12";s:7:"version";a:2:{s:7:"release";s:5:"1.2.3";s:3:"api";s:5:"1.2.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:58:"* fix Bug #11068: No way to read plain "-" option [cardoe]";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.2";s:3:"api";s:5:"1.2.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-02-17";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:165:"* fix Bug #4475: An ambiguous error occurred when specifying similar longoption name. * fix Bug #10055: Not failing properly on short options missing required values";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.1";s:3:"api";s:5:"1.2.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-12-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:126:"Fixed bugs #4448 (Long parameter values truncated with longoption parameter) and #7444 (Trailing spaces after php closing tag)";}i:9;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.2";s:3:"api";s:3:"1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-12-11";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:69:"Fix to preserve BC with 1.0 and allow correct behaviour for new users";}i:10;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.0";s:3:"api";s:3:"1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-09-13";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:14:"Stable release";}i:11;a:5:{s:7:"version";a:2:{s:7:"release";s:4:"0.11";s:3:"api";s:4:"0.11";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2002-05-26";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:89:"POSIX getopt compatibility fix: treat first element of args array as command name";}i:12;a:5:{s:7:"version";a:2:{s:7:"release";s:4:"0.10";s:3:"api";s:4:"0.10";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2002-05-12";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:13:"Packaging fix";}i:13;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.9";s:3:"api";s:3:"0.9";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2002-05-12";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:15:"Initial release";}}}s:8:"filelist";a:5:{s:18:"Console/Getopt.php";a:4:{s:6:"md5sum";s:32:"63da5909aa85a0eb76e0ad0b5e00811a";s:4:"name";s:18:"Console/Getopt.php";s:4:"role";s:3:"php";s:12:"installed_as";s:48:"/opt/alt/php84/usr/share/pear/Console/Getopt.php";}s:21:"tests/001-getopt.phpt";a:4:{s:6:"md5sum";s:32:"5a6fa63ce6f2370cdad11dc24a5addd0";s:4:"name";s:21:"tests/001-getopt.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php84/usr/share/pear/test/Console_Getopt/tests/001-getopt.phpt";}s:19:"tests/bug10557.phpt";a:4:{s:6:"md5sum";s:32:"7540b630cb8e7bfd8bb06fb65a010ae9";s:4:"name";s:19:"tests/bug10557.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php84/usr/share/pear/test/Console_Getopt/tests/bug10557.phpt";}s:19:"tests/bug11068.phpt";a:4:{s:6:"md5sum";s:32:"e469de3628de85779118103b3248a44f";s:4:"name";s:19:"tests/bug11068.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php84/usr/share/pear/test/Console_Getopt/tests/bug11068.phpt";}s:19:"tests/bug13140.phpt";a:4:{s:6:"md5sum";s:32:"cdc108b084ad8e82eeb2417f04b49ec8";s:4:"name";s:19:"tests/bug13140.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php84/usr/share/pear/test/Console_Getopt/tests/bug13140.phpt";}}s:12:"_lastversion";N;s:7:"dirtree";a:3:{s:37:"/opt/alt/php84/usr/share/pear/Console";b:1;s:55:"/opt/alt/php84/usr/share/pear/test/Console_Getopt/tests";b:1;s:49:"/opt/alt/php84/usr/share/pear/test/Console_Getopt";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.4.3";s:12:"release_date";s:10:"2019-11-20";s:13:"release_state";s:6:"stable";s:15:"release_license";s:12:"BSD-2-Clause";s:13:"release_notes";s:98:"* PR #4: Fix PHP 7.4 deprecation: array/string curly braces access * PR #5: fix phplint warnings";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.4.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.8.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:3:{i:0;a:5:{s:4:"name";s:15:"Andrei Zmievski";s:5:"email";s:14:"andrei@php.net";s:6:"active";s:2:"no";s:6:"handle";s:6:"andrei";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:9:"developer";}i:2;a:5:{s:4:"name";s:11:"Greg Beaver";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:2:"no";s:6:"handle";s:6:"cellog";s:4:"role";s:6:"helper";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1747073454;}PK!՘DD.registry/pear.regnu[a:24:{s:7:"attribs";a:6:{s:15:"packagerversion";s:7:"1.10.13";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:16:"PEAR Base System";s:11:"description";s:1100:"The PEAR package contains: * the PEAR installer, for creating, distributing and installing packages * the PEAR_Exception PHP5 error handling mechanism * the PEAR_ErrorStack advanced error handling mechanism * the PEAR_Error error handling mechanism * the OS_Guess class for retrieving info about the OS where PHP is running on * the System class for quick handling of common operations with files and directories * the PEAR base class Features in a nutshell: * full support for channels * pre-download dependency validation * new package.xml 2.0 format allows tremendous flexibility while maintaining BC * support for optional dependency groups and limited support for sub-packaging * robust dependency support * full dependency validation on uninstall * remote install for hosts with only ftp access - no more problems with restricted host installation * full support for mirroring * support for bundling several packages into a single tarball * support for static dependencies on a url-based package * support for custom file roles and installation tasks";s:4:"lead";a:7:{i:0;a:4:{s:4:"name";s:11:"Greg Beaver";s:4:"user";s:6:"cellog";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:17:"Pierre-Alain Joye";s:4:"user";s:6:"pajoye";s:5:"email";s:14:"pierre@php.net";s:6:"active";s:2:"no";}i:2;a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}i:3;a:4:{s:4:"name";s:13:"Tomas V.V.Cox";s:4:"user";s:3:"cox";s:5:"email";s:15:"cox@idecnet.com";s:6:"active";s:2:"no";}i:4;a:4:{s:4:"name";s:13:"Helgi Thormar";s:4:"user";s:5:"dufuz";s:5:"email";s:13:"dufuz@php.net";s:6:"active";s:2:"no";}i:5;a:4:{s:4:"name";s:16:"Christian Weiske";s:4:"user";s:7:"cweiske";s:5:"email";s:15:"cweiske@php.net";s:6:"active";s:2:"no";}i:6;a:4:{s:4:"name";s:13:"Chuck Burgess";s:4:"user";s:7:"ashnazg";s:5:"email";s:15:"ashnazg@php.net";s:6:"active";s:3:"yes";}}s:9:"developer";a:4:{s:4:"name";s:9:"Tias Guns";s:4:"user";s:4:"tias";s:5:"email";s:12:"tias@php.net";s:6:"active";s:2:"no";}s:6:"helper";a:3:{i:0;a:4:{s:4:"name";s:11:"Tim Jackson";s:4:"user";s:4:"timj";s:5:"email";s:12:"timj@php.net";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:15:"Bertrand Gugger";s:4:"user";s:5:"toggg";s:5:"email";s:13:"toggg@php.net";s:6:"active";s:2:"no";}i:2;a:4:{s:4:"name";s:13:"Martin Jansen";s:4:"user";s:2:"mj";s:5:"email";s:10:"mj@php.net";s:6:"active";s:2:"no";}}s:4:"date";s:10:"2024-11-24";s:4:"time";s:8:"22:09:42";s:7:"version";a:2:{s:7:"release";s:7:"1.10.16";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:164:"* PR #141: Fix bug #27796: "Array to string" conversion warnings on installs/other actions * PR #145: Never reference E_STRICT on PHP 8.4+ * PR #147: Fix tests 8.1+";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:105:{i:0;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c0482b234f269360953c87472b5cf746";s:4:"name";s:12:"OS/Guess.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:1;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b371e9c6b4d667abb8be01f2788dcf9";s:4:"name";s:27:"PEAR/ChannelFile/Parser.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8fd87e64002e11fd86eb2f3fbfee6599";s:4:"name";s:21:"PEAR/Command/Auth.xml";s:4:"role";s:3:"php";}}i:3;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"65b6b36c4cc53f2836ad09b070829877";s:4:"name";s:21:"PEAR/Command/Auth.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ce6bb5b6fdc02e0f50e7676403fd84a4";s:4:"name";s:22:"PEAR/Command/Build.xml";s:4:"role";s:3:"php";}}i:5;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e19325f59c4013694a4a06b61e7ac3be";s:4:"name";s:22:"PEAR/Command/Build.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6d5aab4d4308c3005b5f584c7783a031";s:4:"name";s:25:"PEAR/Command/Channels.xml";s:4:"role";s:3:"php";}}i:7;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"56b3b36834a751f6e7b86dcba6cefe2f";s:4:"name";s:25:"PEAR/Command/Channels.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:8;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aae7cc03e9b7fe7c4f504b970dca5411";s:4:"name";s:23:"PEAR/Command/Common.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"91f189cb9423b5e87ee0abc5ea1a2be3";s:4:"name";s:23:"PEAR/Command/Config.xml";s:4:"role";s:3:"php";}}i:10;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3c5d633b0e8d4e39e9bfb286f51130a5";s:4:"name";s:23:"PEAR/Command/Config.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"24d05213cae7faa3880bbb5e40998867";s:4:"name";s:24:"PEAR/Command/Install.xml";s:4:"role";s:3:"php";}}i:12;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3dab53d092878709aa16f73143600107";s:4:"name";s:24:"PEAR/Command/Install.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5cb62a04c0a268f4edd64a49a3895c92";s:4:"name";s:23:"PEAR/Command/Mirror.xml";s:4:"role";s:3:"php";}}i:14;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2f5798bb62453d8d1bffa3d050584232";s:4:"name";s:23:"PEAR/Command/Mirror.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9367dcd7e4dbdde423f9c4c7d3f3a919";s:4:"name";s:24:"PEAR/Command/Package.xml";s:4:"role";s:3:"php";}}i:16;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"57521ff1e89bcd23a853134f30836990";s:4:"name";s:24:"PEAR/Command/Package.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:2:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@DATA-DIR@";s:2:"to";s:8:"data_dir";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"28dc842ea725d8787b9f9c3dbca5aa22";s:4:"name";s:23:"PEAR/Command/Pickle.xml";s:4:"role";s:3:"php";}}i:18;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4025dd6411a73b19a5c19b3300060625";s:4:"name";s:23:"PEAR/Command/Pickle.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"49b046cfc14747f0365e02e9c3f0e6dc";s:4:"name";s:25:"PEAR/Command/Registry.xml";s:4:"role";s:3:"php";}}i:20;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9f2ea65794243f0b7287e8883f2ab60e";s:4:"name";s:25:"PEAR/Command/Registry.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"29c02e823879b4e3e291f6b36fb339f1";s:4:"name";s:23:"PEAR/Command/Remote.xml";s:4:"role";s:3:"php";}}i:22;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"42c51cbb21c103fe0288e5c16871f401";s:4:"name";s:23:"PEAR/Command/Remote.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a50c32015005e0761cc3b04679b29ed0";s:4:"name";s:21:"PEAR/Command/Test.xml";s:4:"role";s:3:"php";}}i:24;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fbb0098fcda7fa29adaa0714a325caea";s:4:"name";s:21:"PEAR/Command/Test.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:25;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9229a9711a893a18298e473212689ab4";s:4:"name";s:27:"PEAR/Downloader/Package.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:26;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5379be9492842c3af98241c6e226d285";s:4:"name";s:21:"PEAR/Frontend/CLI.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:27;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"adae220f10a82e5f78b8689a57387753";s:4:"name";s:30:"PEAR/Installer/Role/Common.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d8c62e6275e3aaa7784290912406092c";s:4:"name";s:27:"PEAR/Installer/Role/Cfg.xml";s:4:"role";s:3:"php";}}i:29;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d89d39dcc1c55fb4464f447ce4f84eed";s:4:"name";s:27:"PEAR/Installer/Role/Cfg.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"89a4a2a286e842d45a98974f40a0565c";s:4:"name";s:28:"PEAR/Installer/Role/Data.xml";s:4:"role";s:3:"php";}}i:31;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"89754e8d153937f3dd3266fd8897d965";s:4:"name";s:28:"PEAR/Installer/Role/Data.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b1ce0fe105251c3b75209d6518ee69ac";s:4:"name";s:27:"PEAR/Installer/Role/Doc.xml";s:4:"role";s:3:"php";}}i:33;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"849c557b355f78890ef47fcfd12073ab";s:4:"name";s:27:"PEAR/Installer/Role/Doc.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"af71c0ad42d16a323afe24a4f884ef15";s:4:"name";s:27:"PEAR/Installer/Role/Ext.xml";s:4:"role";s:3:"php";}}i:35;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d3dc799576b3e3d74d187de118cc3e4";s:4:"name";s:27:"PEAR/Installer/Role/Ext.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"da6743f1e45cce72ea13aef5cdb14867";s:4:"name";s:27:"PEAR/Installer/Role/Man.xml";s:4:"role";s:3:"php";}}i:37;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2509a027ae42c4b96aa49557325a0ec4";s:4:"name";s:27:"PEAR/Installer/Role/Man.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ef88f0321d3e481c2130c95122cf76d8";s:4:"name";s:27:"PEAR/Installer/Role/Php.xml";s:4:"role";s:3:"php";}}i:39;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d7547896ec403dba2eed9825ed86ea64";s:4:"name";s:27:"PEAR/Installer/Role/Php.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"746461dc3b48af6d24094cb0211608f2";s:4:"name";s:30:"PEAR/Installer/Role/Script.xml";s:4:"role";s:3:"php";}}i:41;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"325c60df7f78be127741621561758f46";s:4:"name";s:30:"PEAR/Installer/Role/Script.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e147d63f168ea156fc2be38caaa63804";s:4:"name";s:27:"PEAR/Installer/Role/Src.xml";s:4:"role";s:3:"php";}}i:43;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"464722cee0665ebc75757f76532f0ab2";s:4:"name";s:27:"PEAR/Installer/Role/Src.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a24b596ec987aa5688fc19e8ed4e97ea";s:4:"name";s:28:"PEAR/Installer/Role/Test.xml";s:4:"role";s:3:"php";}}i:45;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a04eb2f4881ec6e6a13ae78f6a43e3cd";s:4:"name";s:28:"PEAR/Installer/Role/Test.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7641e71c5785bb33a4261ebe25ed0fd7";s:4:"name";s:27:"PEAR/Installer/Role/Www.xml";s:4:"role";s:3:"php";}}i:47;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"62699034e3186c2d68a6bb56a6cc23eb";s:4:"name";s:27:"PEAR/Installer/Role/Www.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:48;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e95f2d850fce183e221912b2c2056d04";s:4:"name";s:23:"PEAR/Installer/Role.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:49;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cfa08685115d5e2d7635225d73a91f39";s:4:"name";s:33:"PEAR/PackageFile/Generator/v1.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:50;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d264031153993866828e82129e389ab";s:4:"name";s:33:"PEAR/PackageFile/Generator/v2.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:51;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a2206e0e32ad2ba2f4e2a0c1797f295c";s:4:"name";s:30:"PEAR/PackageFile/Parser/v1.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:52;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3857f4b60878d64551a7cdae783437f7";s:4:"name";s:30:"PEAR/PackageFile/Parser/v2.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:53;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a253999b2109460badc3c71ad2c069e7";s:4:"name";s:26:"PEAR/PackageFile/v2/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:54;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"44dafa313204f68b5fb54b9f61a86d0c";s:4:"name";s:33:"PEAR/PackageFile/v2/Validator.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:55;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cc1ea307bb79c0cbcff4a90a4656e96e";s:4:"name";s:23:"PEAR/PackageFile/v1.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:56;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9e6012d4ef9cb8e12e2ccadcbdcf3d24";s:4:"name";s:23:"PEAR/PackageFile/v2.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:57;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ce77cc6593d8d4eda5ff8620ff09d6ec";s:4:"name";s:16:"PEAR/REST/10.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:58;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bdbd1f2e8afa2cddddecf2687579d316";s:4:"name";s:16:"PEAR/REST/11.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:59;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"11179085b6efb577d37f45cc25e42a35";s:4:"name";s:16:"PEAR/REST/13.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:60;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0eb57da4993a3cfed69fe8135f10b05a";s:4:"name";s:34:"PEAR/Task/Postinstallscript/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:61;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"46c1bdb9a7af8628643e639ec1c3bc58";s:4:"name";s:24:"PEAR/Task/Replace/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:62;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"50e20dbde7e51bb5e11545c56482b68a";s:4:"name";s:24:"PEAR/Task/Unixeol/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:63;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"340be01552844adb50f6e0fa37aa3ffe";s:4:"name";s:27:"PEAR/Task/Windowseol/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:64;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ec7f8db335ad3b5a25d78682745185d1";s:4:"name";s:20:"PEAR/Task/Common.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:65;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86f240c600447fdb86bd38bd32c66c02";s:4:"name";s:31:"PEAR/Task/Postinstallscript.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:66;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c993cdedc64084a1c4b735baec048d50";s:4:"name";s:21:"PEAR/Task/Replace.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:67;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"76c4ca15858c005cda208a9da1f5eb2d";s:4:"name";s:21:"PEAR/Task/Unixeol.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:68;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d790eb3aa5ba22a33e42cb7c5f99fb25";s:4:"name";s:24:"PEAR/Task/Windowseol.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:69;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b3c83ca826a4825ca2db726ed7d4b245";s:4:"name";s:23:"PEAR/Validator/PECL.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:70;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d89f25a54d100c2afd562fb3bd7c308";s:4:"name";s:16:"PEAR/Builder.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:71;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"edcd484ecfd400875df90ee480c5384d";s:4:"name";s:20:"PEAR/ChannelFile.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:72;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a5d56f9d15ff6d22c12f7db851f281e8";s:4:"name";s:16:"PEAR/Command.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:73;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0af44a13df74291ac2f46949d2035e0e";s:4:"name";s:15:"PEAR/Common.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:74;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"64d0f7b2737e5f182d0ab98bc77930d2";s:4:"name";s:15:"PEAR/Config.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:75;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7e8dfae09802be7f2e6170062bb80cbd";s:4:"name";s:21:"PEAR/DependencyDB.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:76;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"76fdabdee883fd16b986332552b9e3dc";s:4:"name";s:20:"PEAR/Dependency2.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:77;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2ccb7bb2d00eae201ee7ae1eef49ad8a";s:4:"name";s:19:"PEAR/Downloader.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:78;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea807632b63d2e0acd6924db23aaa0eb";s:4:"name";s:19:"PEAR/ErrorStack.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:79;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"544ed48cab9407a936d058d09e773e22";s:4:"name";s:18:"PEAR/Exception.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:80;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"31c0b91767550adf77f1c9bea92a0559";s:4:"name";s:17:"PEAR/Frontend.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:81;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8b85e42b840676ad3ae1c15e55b005b";s:4:"name";s:18:"PEAR/Installer.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:82;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2929765413405abf63574c8a544e4a04";s:4:"name";s:20:"PEAR/PackageFile.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:83;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ad25a29d464b62cbaaa3ca96e622526c";s:4:"name";s:17:"PEAR/Packager.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:84;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ef9d00adaeccff7516f08170096026d3";s:4:"name";s:14:"PEAR/Proxy.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:85;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae8c1dcfddb6a2717e09239bb1430dc7";s:4:"name";s:17:"PEAR/Registry.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:86;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"389d1bad72267d3ed770abf0662d8086";s:4:"name";s:13:"PEAR/REST.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:87;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df0d7022e22fd78ecd82080ff4f108d5";s:4:"name";s:16:"PEAR/RunTest.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:88;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3711c281e0234203ec7879f53bc766ab";s:4:"name";s:17:"PEAR/Validate.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:89;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"da9510087eddd489945dde07260256ee";s:4:"name";s:18:"PEAR/XMLParser.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:90;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d888d06143e3cac0dae78bbb2e761366";s:4:"name";s:16:"scripts/pear.bat";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:3:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@bin_dir@";s:2:"to";s:7:"bin_dir";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:16:"tasks:windowseol";s:0:"";}i:91;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"17d7d08ce2c6c476eeaae4763f69efcc";s:4:"name";s:19:"scripts/peardev.bat";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:3:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@bin_dir@";s:2:"to";s:7:"bin_dir";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:16:"tasks:windowseol";s:0:"";}i:92;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1c5819d67da59739e6298d6094c58f7b";s:4:"name";s:16:"scripts/pecl.bat";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:3:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@bin_dir@";s:2:"to";s:7:"bin_dir";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:16:"tasks:windowseol";s:0:"";}i:93;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8ac139504e80bede470aef6d405100b6";s:4:"name";s:15:"scripts/pear.sh";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:13:"tasks:unixeol";s:0:"";}i:94;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"08ea03525b4ba914dfd9ec69c4238cf4";s:4:"name";s:18:"scripts/peardev.sh";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:13:"tasks:unixeol";s:0:"";}i:95;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bde09b17fa816d58bb136375a13119c3";s:4:"name";s:15:"scripts/pecl.sh";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:13:"tasks:unixeol";s:0:"";}i:96;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9b5d5e5bd017c50df00c6b34ef32652e";s:4:"name";s:19:"scripts/pearcmd.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}}i:97;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"48867dfbb41f2532d034f56a79565893";s:4:"name";s:19:"scripts/peclcmd.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"45b44486d8090de17b2a8b4211fab247";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eaac3d33068c6e67573ed44155b149ae";s:4:"name";s:7:"INSTALL";s:4:"role";s:3:"doc";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"69341ea97af9c88956568f8e7e41d4c6";s:4:"name";s:11:"package.dtd";s:4:"role";s:4:"data";}}i:101;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47aeb7eaff6438beb60bc42bc0e6c658";s:4:"name";s:8:"PEAR.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cd10521cc4054923a3d2b6e15b4df493";s:4:"name";s:10:"README.rst";s:4:"role";s:3:"doc";}}i:103;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba9e5c5a567e51b440808a8ed53cd76d";s:4:"name";s:10:"System.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"acd010e3bc43c0f72df584acde7b9158";s:4:"name";s:13:"template.spec";s:4:"role";s:4:"data";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:4:{s:3:"php";a:1:{s:3:"min";s:5:"5.4.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:6:"1.10.1";}s:7:"package";a:4:{i:0;a:4:{s:4:"name";s:11:"Archive_Tar";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.9";s:11:"recommended";s:5:"1.4.4";}i:1;a:4:{s:4:"name";s:16:"Structures_Graph";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.1.0";s:11:"recommended";s:5:"1.1.1";}i:2;a:4:{s:4:"name";s:14:"Console_Getopt";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.1";s:11:"recommended";s:5:"1.4.3";}i:3;a:4:{s:4:"name";s:8:"XML_Util";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";s:11:"recommended";s:5:"1.4.5";}}s:9:"extension";a:2:{i:0;a:1:{s:4:"name";s:3:"xml";}i:1;a:1:{s:4:"name";s:4:"pcre";}}}s:5:"group";a:3:{i:0;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:26:"PEAR's web-based installer";s:4:"name";s:12:"webinstaller";}s:7:"package";a:3:{s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.5.1";}}i:1;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:30:"PEAR's PHP-GTK-based installer";s:4:"name";s:12:"gtkinstaller";}s:7:"package";a:3:{s:4:"name";s:17:"PEAR_Frontend_Gtk";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.4.0";}}i:2;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:31:"PEAR's PHP-GTK2-based installer";s:4:"name";s:13:"gtk2installer";}s:7:"package";a:2:{s:4:"name";s:18:"PEAR_Frontend_Gtk2";s:7:"channel";s:12:"pear.php.net";}}}}s:10:"phprelease";a:2:{i:0;a:2:{s:17:"installconditions";a:1:{s:2:"os";a:1:{s:4:"name";s:7:"windows";}}s:8:"filelist";a:2:{s:7:"install";a:5:{i:0;a:1:{s:7:"attribs";a:2:{s:2:"as";s:8:"pear.bat";s:4:"name";s:16:"scripts/pear.bat";}}i:1;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"peardev.bat";s:4:"name";s:19:"scripts/peardev.bat";}}i:2;a:1:{s:7:"attribs";a:2:{s:2:"as";s:8:"pecl.bat";s:4:"name";s:16:"scripts/pecl.bat";}}i:3;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"pearcmd.php";s:4:"name";s:19:"scripts/pearcmd.php";}}i:4;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"peclcmd.php";s:4:"name";s:19:"scripts/peclcmd.php";}}}s:6:"ignore";a:3:{i:0;a:1:{s:7:"attribs";a:1:{s:4:"name";s:18:"scripts/peardev.sh";}}i:1;a:1:{s:7:"attribs";a:1:{s:4:"name";s:15:"scripts/pear.sh";}}i:2;a:1:{s:7:"attribs";a:1:{s:4:"name";s:15:"scripts/pecl.sh";}}}}}i:1;a:1:{s:8:"filelist";a:2:{s:7:"install";a:5:{i:0;a:1:{s:7:"attribs";a:2:{s:2:"as";s:4:"pear";s:4:"name";s:15:"scripts/pear.sh";}}i:1;a:1:{s:7:"attribs";a:2:{s:2:"as";s:7:"peardev";s:4:"name";s:18:"scripts/peardev.sh";}}i:2;a:1:{s:7:"attribs";a:2:{s:2:"as";s:4:"pecl";s:4:"name";s:15:"scripts/pecl.sh";}}i:3;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"pearcmd.php";s:4:"name";s:19:"scripts/pearcmd.php";}}i:4;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"peclcmd.php";s:4:"name";s:19:"scripts/peclcmd.php";}}}s:6:"ignore";a:3:{i:0;a:1:{s:7:"attribs";a:1:{s:4:"name";s:16:"scripts/pear.bat";}}i:1;a:1:{s:7:"attribs";a:1:{s:4:"name";s:19:"scripts/peardev.bat";}}i:2;a:1:{s:7:"attribs";a:1:{s:4:"name";s:16:"scripts/pecl.bat";}}}}}}s:9:"changelog";a:1:{s:7:"release";a:35:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:11:"1.8.0alpha1";s:3:"api";s:5:"1.8.0";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-03-09";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:4876:"* Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz] * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz] * Implement Request #10825: Only display the "invalid or missing package file"-error if it makes sense [dufuz] * Implement Request #11170: script to generate Command/[command].xml [dufuz] * Implement Request #11176: improve channel ... has updated its protocols message [dufuz] * Implement Request #12706: pear list -a hard to read [dufuz] * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz] * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos] * Implement Request #13927: install-pear.php should have option to set www_dir [timj] * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz] * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz] - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate better what other package managers are doing. upgrade-all will still work as intended. * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz] - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for channel specific upgrades * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske] * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle] * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog] * Fix PHP Bug #47323: strotime warnings in make install [dufuz] * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz] * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj] * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit] * Fix Bug #13953: config-set/config-show with channel alias fail [cellog] * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz] * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz] * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz] * Fix Bug #14210: pear list -ia brings warnings [dufuz] * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz] * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz] * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos] * Fix Bug #14437: openbasedir warning when loading config [dufuz] * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske] * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali] * Fix Bug #14977: PEAR/Frontend.php doesn't require_once PEAR.php [dufuz] * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz] * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz] * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz] NOTE! Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment to migrate over to one of the alternatives that have ben provided: * PEAR_Common->downloadHttp (use PEAR_Downloader->downloadHttp instead) * PEAR_Common->infoFromTgzFile (use PEAR_PackageFile->fromTgzFile instead) * PEAR_Common->infoFromDescriptionFile (use PEAR_PackageFile->fromPackageFile instead) * PEAR_Common->infoFromString (use PEAR_PackageFile->fromXmlstring instead) * PEAR_Common->infoFromArray (use PEAR_PackageFile->fromAnyFile instead) * PEAR_Common->xmlFromInfo (use a PEAR_PackageFile_v* object's generator instead) * PEAR_Common->validatePackageInfo (use the validation of PEAR_PackageFile objects) * PEAR_Common->analyzeSourceCode (use a PEAR_PackageFile_v* object instead) * PEAR_Common->detectDependencies (use PEAR_Downloader_Package->detectDependencies instead) * PEAR_Common->buildProvidesArray (use PEAR_PackageFile_v1->_buildProvidesArray or PEAR_PackageFile_v2_Validator->_buildProvidesArray) PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls pear upgrade -f PEAR will allow people with lower versions to upgrade to this release but no guarantees will be made that it will work properly. Support for XML RPC channels has been dropped - The only ones that used it (pear.php.net and pecl.php.net) have used the REST interface for years now. SOAP support also removed as it was only proof of concept. Move codebase from the PHP License to New BSD 2 clause license";}i:1;a:5:{s:4:"date";s:10:"2009-03-27";s:7:"version";a:2:{s:7:"release";s:8:"1.8.0RC1";s:3:"api";s:5:"1.8.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:347:"* Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz] * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz] * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz] * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz]";}i:2;a:5:{s:4:"date";s:10:"2009-04-10";s:7:"version";a:2:{s:7:"release";s:5:"1.8.0";s:3:"api";s:5:"1.8.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:5737:"Changes since RC1: * Fix Bug #14792: Bad md5sum for files with replaced content [dufuz] * Fix Bug #16057:-r is limited to 4 directories in depth [dufuz] * Fix Bug #16077: PEAR5::getStaticProperty does not return a reference to the property [dufuz] Remove custom XML_Util class in favor of using upstream XML_Util package as dependency RC1 Release Notes: * Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz] * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz] * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz] * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz] Alpha1 Release Notes: * Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz] * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz] * Implement Request #10825: Only display the "invalid or missing package file"-error if it makes sense [dufuz] * Implement Request #11170: script to generate Command/[command].xml [dufuz] * Implement Request #11176: improve channel ... has updated its protocols message [dufuz] * Implement Request #12706: pear list -a hard to read [dufuz] * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz] * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos] * Implement Request #13927: install-pear.php should have option to set www_dir [timj] * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz] * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz] - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate better what other package managers are doing. upgrade-all will still work as intended. * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz] - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for channel specific upgrades * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske] * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle] * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog] * Fix PHP Bug #47323: strotime warnings in make install [dufuz] * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz] * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj] * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit] * Fix Bug #13953: config-set/config-show with channel alias fail [cellog] * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz] * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz] * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz] * Fix Bug #14210: pear list -ia brings warnings [dufuz] * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz] * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz] * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos] * Fix Bug #14437: openbasedir warning when loading config [dufuz] * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske] * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali] * Fix Bug #14977: PEAR/Frontend.php doesn't require_once PEAR.php [dufuz] * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz] * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz] * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz] NOTE! Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment to migrate over to one of the alternatives that have ben provided: * PEAR_Common->downloadHttp (use PEAR_Downloader->downloadHttp instead) * PEAR_Common->infoFromTgzFile (use PEAR_PackageFile->fromTgzFile instead) * PEAR_Common->infoFromDescriptionFile (use PEAR_PackageFile->fromPackageFile instead) * PEAR_Common->infoFromString (use PEAR_PackageFile->fromXmlstring instead) * PEAR_Common->infoFromArray (use PEAR_PackageFile->fromAnyFile instead) * PEAR_Common->xmlFromInfo (use a PEAR_PackageFile_v* object's generator instead) * PEAR_Common->validatePackageInfo (use the validation of PEAR_PackageFile objects) * PEAR_Common->analyzeSourceCode (use a PEAR_PackageFile_v* object instead) * PEAR_Common->detectDependencies (use PEAR_Downloader_Package->detectDependencies instead) * PEAR_Common->buildProvidesArray (use PEAR_PackageFile_v1->_buildProvidesArray or PEAR_PackageFile_v2_Validator->_buildProvidesArray) PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls pear upgrade -f PEAR will allow people with lower versions to upgrade to this release but no guarantees will be made that it will work properly. Support for XML RPC channels has been dropped - The only ones that used it (pear.php.net and pecl.php.net) have used the REST interface for years now. SOAP support also removed as it was only proof of concept. Move codebase from the PHP License to New BSD 2 clause license";}i:3;a:5:{s:4:"date";s:10:"2009-04-15";s:7:"version";a:2:{s:7:"release";s:5:"1.8.1";s:3:"api";s:5:"1.8.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:58:"* Fix Bug #16099 PEAR crash on PHP4 (parse error) [dufuz]";}i:4;a:5:{s:4:"date";s:10:"2009-08-18";s:7:"version";a:2:{s:7:"release";s:8:"1.9.0RC1";s:3:"api";s:8:"1.9.0RC1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:1106:"* Implement Request #16213: add alias to list-channels output [dufuz] * Implement Request #16378: pear svntag [dufuz] * Implement Request #16386: PEAR_Config::remove() does not support specifying a channel [timj] * Implement Request #16396: package-dependencies should allow package names [dufuz] * Fix Bug #11181: pear requests channel.xml from main server instead from mirror [dufuz] * Fix Bug #14493: pear install --offline doesn't print out errors [dufuz] * Fix Bug #11348: pear package-dependencies isn't well explained [dufuz] * Fix Bug #16108: PEAR_PackageFile_Generator_v2 PHP4 parse error when running upgrade-all [dufuz] * Fix Bug #16113: Installing certain packages fails due incorrect encoding handling [dufuz] * Fix Bug #16122: PEAR RunTest failed to run as expected [dufuz] * Fix Bug #16366: compiling 5.2.10 leads to non-functioning pear [dufuz] * Fix Bug #16387: channel-logout does not support logging out from a non-default channel [timj] * Fix Bug #16444: Setting preferred mirror fails [dufuz] * Fix the shutdown functions where a index might not exist and thus raise a notice [derick]";}i:5;a:5:{s:4:"date";s:10:"2009-08-20";s:7:"version";a:2:{s:7:"release";s:8:"1.9.0RC2";s:3:"api";s:8:"1.9.0RC2";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:107:"* REST 1.4 file was occasionally being included but REST 1.4 is not intended for this release cycle [dufuz]";}i:6;a:5:{s:4:"date";s:10:"2009-08-21";s:7:"version";a:2:{s:7:"release";s:8:"1.9.0RC3";s:3:"api";s:8:"1.9.0RC3";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:70:"* Improved svntag support to handle packages like PEAR it self [dufuz]";}i:7;a:5:{s:4:"date";s:10:"2009-08-23";s:7:"version";a:2:{s:7:"release";s:8:"1.9.0RC4";s:3:"api";s:8:"1.9.0RC4";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:244:"* Fixed a problem where the original channel could not be set as a preferred_mirror again [dufuz] * Make sure channel aliases can't be made to start with - [dufuz] * Output issues with pear search [dufuz] * Fixed couple of stray notices [dufuz]";}i:8;a:5:{s:4:"date";s:10:"2009-09-03";s:7:"version";a:2:{s:7:"release";s:5:"1.9.0";s:3:"api";s:5:"1.9.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:86:"* Fix Bug #16547: The phar for PEAR installer uses ereg() which is deprecated [dufuz]";}i:9;a:5:{s:4:"date";s:10:"2010-05-26";s:7:"version";a:2:{s:7:"release";s:5:"1.9.1";s:3:"api";s:5:"1.9.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:1111:"* svntag improvements, tag package files passed into the command and better directory checks [dufuz] * rely on Structures_Graph minimum version instead of recommended version [saltybeagle] * Fix Bug #12613: running go-pear.phar from C:\ fails [dufuz] * Fix Bug #14841: Installing pear into directory with space fails [dufuz] * Fix Bug #16644: pear.bat returns syntax error when parenthesis are in install path. [dufuz] [patch by bwaters (Bryan Waters)] * Fix Bug #16767: Use of Depreciated HTML Attributes in the Exception class [dufuz] [patch by fuhrysteve (Stephen J. Fuhry)] * Fix Bug #16864: "pear list-upgrades -i" issues E_WARNINGS [dufuz] [patch by rquadling (Richard Quadling)] * Fix Bug #17220: command `pear help` outputs to stderr instead of stdout [dufuz] * Fix Bug #17234: channel-discover adds port to HTTP Host header [dufuz] * Fix Bug #17292: Code Coverage in PEAR_RunTest does not work with namespaces [sebastian] * Fix Bug #17359: loadExtension() fails over missing dl() when used in multithread env [dufuz] * Fix Bug #17378: pear info $package fails if directory with that name exists [dufuz]";}i:10;a:6:{s:4:"date";s:10:"2011-02-28";s:4:"time";s:8:"18:30:00";s:7:"version";a:2:{s:7:"release";s:5:"1.9.2";s:3:"api";s:5:"1.9.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:1258:"Important! This is a security fix release. The advisory can be found at http://pear.php.net/advisory-20110228.txt Bugs: * Fixed Bug #17463: Regression: On Windows, svntag [patch by doconnor] * Fixed Bug #17641: pecl-list doesn't sort packages by name [dufuz] * Fixed Bug #17781: invalid argument warning on foreach due to an empty optional dependencie [dufuz] * Fixed Bug #17801: PEAR run-tests wrongly detects php-cgi [patch by David Jean Louis (izi)] * Fixed Bug #17839: pear svntag does not tag package.xml file [dufuz] * Fixed Bug #17986: PEAR Installer cannot handle files moved between packages [dufuz] * Fixed Bug #17997: Strange output if directories are not writeable [dufuz] * Fixed Bug #18001: PEAR/RunTest coverage fails [dufuz] * Fixed Bug #18056 [SECURITY]: Symlink attack in PEAR install [dufuz] * Fixed Bug #18218: "pear package" does not allow the use of late static binding [dufuz and Christer Edvartsen] * Fixed Bug #18238: Wrong return code from "pear help" [till] * Fixed Bug #18308: Broken error message about missing channel validator [yunosh] This feature is implemented as a result of #18056 * Implemented Request #16648: Use TMPDIR for builds instead of /var/tmp [dufuz]";}i:11;a:6:{s:4:"date";s:10:"2011-06-04";s:4:"time";s:8:"15:30:00";s:7:"version";a:2:{s:7:"release";s:5:"1.9.3";s:3:"api";s:5:"1.9.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:820:"* Fixed Bug #17744: Empty changelog causes fatal error in setChangelogentry [dufuz] * Fixed Bug #18340: raiseErro typo [doconnor] * Fixed Bug #18349: package.xml version not recognized when single quoted [dufuz] * Fixed Bug #18364: date.timezone errors for sh/bat files when TZ is not set in php.ini [dufuz] * Fixed Bug #18388: Parentheses error in REST.php line 232 [dufuz] * Fixed Bug #18428: invalid preg_match patterns [glen] * Fixed Bug #18486: REST/10.php does not check error condition [dufuz] * Fixed a problem in RunTest and code coverage. Correctly register the code coverage shutdown function in case we are inside a namespace. [sebastian] * Fixed a bug with extensions not providing their config.m4 and co in the root directory of their pecl package but rather in a sub directory, such as xhprof. [dufuz]";}i:12;a:6:{s:4:"date";s:10:"2011-07-06";s:4:"time";s:8:"15:30:00";s:7:"version";a:2:{s:7:"release";s:5:"1.9.4";s:3:"api";s:5:"1.9.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:705:"Bug Fixes: * Bug #17350: "pear install --force" doesn't uninstall files from previous pkg versions [dufuz] * Bug #18362: A whitespace TEMP_DIR path breaks install/upgrade functionality [dufuz] * Bug #18440: bad tmp folder path on install : Unable to create path for C:/Program/tmp [dufuz] * Bug #18581: "config-get -c" not returning channel's configuration when using alias [dufuz] * Bug #18639: regression: installing xdebug fails most likely due to another fix [dufuz] Features * All System (the class) functions can now take in spaced paths as long as they are surrounded in quotes. Prior to this it was possible to do that by passing all values in as an array (by product of #18362, #18440) [dufuz]";}i:13;a:6:{s:4:"date";s:10:"2014-06-27";s:4:"time";s:8:"18:17:00";s:7:"version";a:2:{s:7:"release";s:9:"1.9.5dev1";s:3:"api";s:5:"1.9.5";}s:9:"stability";a:2:{s:7:"release";s:5:"devel";s:3:"api";s:5:"devel";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:1093:"Bug fixes: * Fix bug #18343: Entities in file names decoded during packaging [cweiske] * Fix bug #18665: pecl extensions not enabled in empty php.ini files [Louis Opter] * Fix bug #18834: Do not truncate cache file if it is a symlink [avb] * Fix bug #18892: Parse error in Installer.php [ashnazg] * Fix bug #19482: fix pearcmd for include paths with trailing backslash [cweiske] * Fix bug #19793: PHP Notice about ob_end_clean() [cweiske] * Fix bug #20086: Invalid regexp in PEAR_Builder::build() [avb] * Fix bug #20203: split content-type and get real mime type [Samu Voutilainen] * Fix bug #20283: use full path for "zend_extension=..." [cweiske] * Fix bug #20284: Reset interpreter before running --CLEAN-- section php-cgi run [Mats Lindh] * Fix bug #20285: fix spelling mistakes [Veres Lajos] * Fix bug #20286: Support access of static variables on objects in validator [cweiske] * Fix bug #20321: Correctly detect name of current user during installation [cweiske] * Fix bug: let pear run-tests fail when there are failed tests [cweiske] * Prepare a test for bug #18056 / bug #18834 [avb]";}i:14;a:6:{s:4:"date";s:10:"2014-07-12";s:4:"time";s:8:"14:22:23";s:7:"version";a:2:{s:7:"release";s:5:"1.9.5";s:3:"api";s:5:"1.9.5";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:1137:"No changes since 1.9.5.dev1. Bug fixes in 1.9.5.dev1: * Fix bug #18343: Entities in file names decoded during packaging [cweiske] * Fix bug #18665: pecl extensions not enabled in empty php.ini files [Louis Opter] * Fix bug #18834: Do not truncate cache file if it is a symlink [avb] * Fix bug #18892: Parse error in Installer.php [ashnazg] * Fix bug #19482: fix pearcmd for include paths with trailing backslash [cweiske] * Fix bug #19793: PHP Notice about ob_end_clean() [cweiske] * Fix bug #20086: Invalid regexp in PEAR_Builder::build() [avb] * Fix bug #20203: split content-type and get real mime type [Samu Voutilainen] * Fix bug #20283: use full path for "zend_extension=..." [cweiske] * Fix bug #20284: Reset interpreter before running --CLEAN-- section php-cgi run [Mats Lindh] * Fix bug #20285: fix spelling mistakes [Veres Lajos] * Fix bug #20286: Support access of static variables on objects in validator [cweiske] * Fix bug #20321: Correctly detect name of current user during installation [cweiske] * Fix bug: let pear run-tests fail when there are failed tests [cweiske] * Prepare a test for bug #18056 / bug #18834 [avb]";}i:15;a:6:{s:4:"date";s:10:"2015-07-25";s:4:"time";s:8:"13:42:42";s:7:"version";a:2:{s:7:"release";s:10:"1.10.0dev1";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:5:"devel";s:3:"api";s:5:"devel";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:444:"* Implement #20488: Add support for PHP 7 [cweiske] * Drop support for PHP 4 and 5.0 - 5.3 [cweiske] * Remove deprecated methods [cweiske] * Fix static warnings [cweiske] * Fix #17045: avoid overwriting include path [glen] * Fix #17399: "pear help" doesn't mention the "version" command [kguest] * Add --showdiff to "pear run-tests" to print diff for failed tests [tyrael] * Fix channel.xml downloading from https if it did not change [cweiske]";}i:16;a:6:{s:4:"date";s:10:"2015-07-31";s:4:"time";s:8:"09:42:42";s:7:"version";a:2:{s:7:"release";s:10:"1.10.0dev2";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:5:"devel";s:3:"api";s:5:"devel";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:328:"* Fix #18638 and #18405: Make PEAR::loadExtension static [cweiske] * Fix #20319: allow pear to work when cache_dir is not writable [remicollet] * Implement #20333: New role=man for man pages [bjori] * Implement #20334: add "metadata_dir" configuration option [remicollet] * Add long option names to install-pear.php [remicollet]";}i:17;a:6:{s:4:"date";s:10:"2015-09-28";s:4:"time";s:8:"09:42:42";s:7:"version";a:2:{s:7:"release";s:10:"1.10.0dev3";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:5:"devel";s:3:"api";s:5:"devel";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:227:"* Fix #20507: pear list-upgrades does not take PHP version into account [cweiske] * Fix #20927: Use correct php-config [cweiske] * Fix #20946: PEAR_Builder::log() declaration [remicollet] * Remove PEAR/ErrorStack5.php [cweiske]";}i:18;a:6:{s:4:"date";s:10:"2015-10-07";s:4:"time";s:8:"11:22:42";s:7:"version";a:2:{s:7:"release";s:6:"1.10.0";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:1068:"No changes since version 1.10.0dev3. Changes since version 1.9.5: * Implement #20488: Add support for PHP 7 [cweiske] * Drop support for PHP 4 and 5.0 - 5.3 [cweiske] * Remove deprecated methods [cweiske] * Add --showdiff to "pear run-tests" to print diff for failed tests [tyrael] * Implement #20333: New role=man for man pages [bjori] * Implement #20334: add "metadata_dir" configuration option [remicollet] * Add long option names to install-pear.php [remicollet] * Remove PEAR/ErrorStack5.php [cweiske] * Fix #17045: avoid overwriting include path [glen] * Fix #17399: "pear help" doesn't mention the "version" command [kguest] * Fix #18638 and #18405: Make PEAR::loadExtension static [cweiske] * Fix #20319: allow pear to work when cache_dir is not writable [remicollet] * Fix #20507: pear list-upgrades does not take PHP version into account [cweiske] * Fix #20927: Use correct php-config [cweiske] * Fix #20946: PEAR_Builder::log() declaration [remicollet] * Fix channel.xml downloading from https if it did not change [cweiske] * Fix static warnings [cweiske]";}i:19;a:6:{s:4:"date";s:10:"2015-10-17";s:4:"time";s:8:"13:22:42";s:7:"version";a:2:{s:7:"release";s:6:"1.10.1";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:229:"* Fix bug #20959: Crash on channel discovery with channel.xml redirect [cweiske] * Fix bug #20968: Incorrect call to __construct() from PEAR() [edlman] * Add legacy constructor for PEAR_Error for backwards compatibility [cweiske]";}i:20;a:6:{s:4:"date";s:10:"2017-02-28";s:4:"time";s:8:"07:40:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.2";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:544:"* Fix Bug #4426: PEAR_Autoloader __call() must take only 2 arguments [kna] * Fix Bug #20989: fatal error/bug in the postinstallscript task [kguest] * Fix Bug #20991: Strict Standards: startSession and run methods in PEAR_Task_Postinstallscript [kguest] * Fix Bug #21001: PEAR_ERROR_DIE exit code is 0 [danielc] * Pull Request #52: Channel's _lastmodified is an int and not a string [sathieu] * Pull Request #53: Add proper HTTPS proxy support through the CONNECT verb [youknow0] * Pull Request #58: Make method signatures compatible. [yunosh]";}i:21;a:6:{s:4:"date";s:10:"2017-02-28";s:4:"time";s:8:"10:15:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.3";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:42:"* Bug #21188: Class 'PEAR_Proxy' not found";}i:22;a:5:{s:4:"date";s:10:"2017-04-25";s:7:"version";a:2:{s:7:"release";s:6:"1.10.4";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:50:"* Bug #18102: pear install does not fail on error";}i:23;a:5:{s:4:"date";s:10:"2017-06-27";s:7:"version";a:2:{s:7:"release";s:6:"1.10.5";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:73:"* Bug #21222: PHP 7.2 compatibility: Upgrade to Archive_Tar 1.4.3 needed";}i:24;a:5:{s:4:"date";s:10:"2018-08-22";s:7:"version";a:2:{s:7:"release";s:6:"1.10.6";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:544:"* PR #70: Fix notice undefined variable metadata_dir * PR #71: fix Warning: count(): Parameter must be an array or an object * PR #74: Bug #23744 Remove is_executable check * Bug #23744: The is_executable check in the Which method when run on Windows is unnecessary * PR #75: Migrate old while(list() = each()) constructs to foreach * PR #76: Fix PHP Warning: "continue" targeting switch is equivalent to "break" * PR #77: proxy server auth * PR #72: Correctly authenticate at proxy server * PR #78: array or Countable error in 7.2";}i:25;a:5:{s:4:"date";s:10:"2018-12-05";s:7:"version";a:2:{s:7:"release";s:6:"1.10.7";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:238:"* PR #79: Prevent Unable to find the wrapper "channel" Warning * PR #80: fix Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2" * PR #81: Add flags to PECL shell script for shared extensions";}i:26;a:5:{s:4:"date";s:10:"2019-02-07";s:7:"version";a:2:{s:7:"release";s:6:"1.10.8";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:83:"* PR #83: Drop track_errors from options * PR #84: Fix PHP 8 compatibility issues";}i:27;a:5:{s:4:"date";s:10:"2019-03-13";s:7:"version";a:2:{s:7:"release";s:6:"1.10.9";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:191:"* PR #85: Fixes static calls for PHP 8 * PR #86: Adjust silencing check for PHP 8 * PR #87: Comparison fixes * PR #88: Only add bin_dir to PATH if not already there (fixes PHP Bug #75852)";}i:28;a:5:{s:4:"date";s:10:"2019-11-19";s:7:"version";a:2:{s:7:"release";s:7:"1.10.10";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:672:"* PR #89: Fix scripts/* include paths * PR #90: Non-interactive configureoption answers * PR #91: Added missing preg quote * PR #92: handle "lib64" case for glibc detection * PR #93: Fix PHP Notice: Trying to access array offset on value of type bool with 7.4 * PR #94: Updated logic in useLocalCache to reuse getCacheId * PR #95: Fix manpage warning * PR #96: Implement the SOURCE_DATE_EPOCH specification * PR #97: Fix PHP 7.4 deprecation: array/string curly braces access * PR #98: Fix use of null/false as array * PR #99: Fix Travis builds on PHP 5.4 and 5.5 * PR #100: Honor PHP temp directory config * PR #101: Fix documentation: the `--force` is required";}i:29;a:5:{s:4:"date";s:10:"2020-04-10";s:7:"version";a:2:{s:7:"release";s:7:"1.10.11";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:230:"* PR #102: Fix logging error for urls not in cache * PR #103: Fix undefined constant name * PR #105: Sort list of packages * PR #106: Update REST.php * PR #107: Update .travis.yml to include PHP 7.4 * PR #108: Remove unneeded code";}i:30;a:5:{s:4:"date";s:10:"2020-04-19";s:7:"version";a:2:{s:7:"release";s:7:"1.10.12";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:43:"* adjust dependencies based on new releases";}i:31;a:5:{s:4:"date";s:10:"2021-08-10";s:7:"version";a:2:{s:7:"release";s:7:"1.10.13";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:116:"* PR #114: unsupported protocol - use --force to continue * PR #117: Add $this operator to _determineIfPowerpc calls";}i:32;a:5:{s:4:"date";s:10:"2023-11-26";s:7:"version";a:2:{s:7:"release";s:7:"1.10.14";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:583:"* PR #112: Put glue and pieces parameters to implode in correct order for PHP 7.4+ * PR #121: Fix PHP bug 81653: Typo in install-pear-nozlib.phar * PR #122: add %S EXPECTF capability * PR #124: Fix: Creation of dynamic property PEAR_Error::$callback is deprecated * PR #125: Fixed extension loaded check for pecl binaries * PR #126: Remove -n option from pecl.bat for shared extensions * PR #127: fix Using ${var} in strings is deprecated * PR #128: fix lingering license references to PHP license * PR #129: Exclude tests from composer classmap * PR #131: fix private lastError name";}i:33;a:5:{s:4:"date";s:10:"2024-03-09";s:7:"version";a:2:{s:7:"release";s:7:"1.10.15";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:100:"* PR #132: cleanup uneeded test * PR #135: Fix PHP Deprecated: Calling get_class() without arguments";}i:34;a:5:{s:4:"date";s:10:"2024-11-24";s:7:"version";a:2:{s:7:"release";s:7:"1.10.16";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:46:"http://opensource.org/licenses/bsd-license.php";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:164:"* PR #141: Fix bug #27796: "Array to string" conversion warnings on installs/other actions * PR #145: Never reference E_STRICT on PHP 8.4+ * PR #147: Fix tests 8.1+";}}}s:8:"filelist";a:102:{s:12:"OS/Guess.php";a:4:{s:6:"md5sum";s:32:"c0482b234f269360953c87472b5cf746";s:4:"name";s:12:"OS/Guess.php";s:4:"role";s:3:"php";s:12:"installed_as";s:42:"/opt/alt/php84/usr/share/pear/OS/Guess.php";}s:27:"PEAR/ChannelFile/Parser.php";a:4:{s:6:"md5sum";s:32:"3b371e9c6b4d667abb8be01f2788dcf9";s:4:"name";s:27:"PEAR/ChannelFile/Parser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/ChannelFile/Parser.php";}s:21:"PEAR/Command/Auth.xml";a:4:{s:6:"md5sum";s:32:"8fd87e64002e11fd86eb2f3fbfee6599";s:4:"name";s:21:"PEAR/Command/Auth.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php84/usr/share/pear/PEAR/Command/Auth.xml";}s:21:"PEAR/Command/Auth.php";a:4:{s:6:"md5sum";s:32:"65b6b36c4cc53f2836ad09b070829877";s:4:"name";s:21:"PEAR/Command/Auth.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php84/usr/share/pear/PEAR/Command/Auth.php";}s:22:"PEAR/Command/Build.xml";a:4:{s:6:"md5sum";s:32:"ce6bb5b6fdc02e0f50e7676403fd84a4";s:4:"name";s:22:"PEAR/Command/Build.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:52:"/opt/alt/php84/usr/share/pear/PEAR/Command/Build.xml";}s:22:"PEAR/Command/Build.php";a:4:{s:6:"md5sum";s:32:"e19325f59c4013694a4a06b61e7ac3be";s:4:"name";s:22:"PEAR/Command/Build.php";s:4:"role";s:3:"php";s:12:"installed_as";s:52:"/opt/alt/php84/usr/share/pear/PEAR/Command/Build.php";}s:25:"PEAR/Command/Channels.xml";a:4:{s:6:"md5sum";s:32:"6d5aab4d4308c3005b5f584c7783a031";s:4:"name";s:25:"PEAR/Command/Channels.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/opt/alt/php84/usr/share/pear/PEAR/Command/Channels.xml";}s:25:"PEAR/Command/Channels.php";a:4:{s:6:"md5sum";s:32:"56b3b36834a751f6e7b86dcba6cefe2f";s:4:"name";s:25:"PEAR/Command/Channels.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/opt/alt/php84/usr/share/pear/PEAR/Command/Channels.php";}s:23:"PEAR/Command/Common.php";a:4:{s:6:"md5sum";s:32:"aae7cc03e9b7fe7c4f504b970dca5411";s:4:"name";s:23:"PEAR/Command/Common.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Command/Common.php";}s:23:"PEAR/Command/Config.xml";a:4:{s:6:"md5sum";s:32:"91f189cb9423b5e87ee0abc5ea1a2be3";s:4:"name";s:23:"PEAR/Command/Config.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Command/Config.xml";}s:23:"PEAR/Command/Config.php";a:4:{s:6:"md5sum";s:32:"3c5d633b0e8d4e39e9bfb286f51130a5";s:4:"name";s:23:"PEAR/Command/Config.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Command/Config.php";}s:24:"PEAR/Command/Install.xml";a:4:{s:6:"md5sum";s:32:"24d05213cae7faa3880bbb5e40998867";s:4:"name";s:24:"PEAR/Command/Install.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/opt/alt/php84/usr/share/pear/PEAR/Command/Install.xml";}s:24:"PEAR/Command/Install.php";a:4:{s:6:"md5sum";s:32:"3dab53d092878709aa16f73143600107";s:4:"name";s:24:"PEAR/Command/Install.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/opt/alt/php84/usr/share/pear/PEAR/Command/Install.php";}s:23:"PEAR/Command/Mirror.xml";a:4:{s:6:"md5sum";s:32:"5cb62a04c0a268f4edd64a49a3895c92";s:4:"name";s:23:"PEAR/Command/Mirror.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Command/Mirror.xml";}s:23:"PEAR/Command/Mirror.php";a:4:{s:6:"md5sum";s:32:"2f5798bb62453d8d1bffa3d050584232";s:4:"name";s:23:"PEAR/Command/Mirror.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Command/Mirror.php";}s:24:"PEAR/Command/Package.xml";a:4:{s:6:"md5sum";s:32:"9367dcd7e4dbdde423f9c4c7d3f3a919";s:4:"name";s:24:"PEAR/Command/Package.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/opt/alt/php84/usr/share/pear/PEAR/Command/Package.xml";}s:24:"PEAR/Command/Package.php";a:4:{s:6:"md5sum";s:32:"a0a6b2ba1e67351359cf105b6f863806";s:4:"name";s:24:"PEAR/Command/Package.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/opt/alt/php84/usr/share/pear/PEAR/Command/Package.php";}s:23:"PEAR/Command/Pickle.xml";a:4:{s:6:"md5sum";s:32:"28dc842ea725d8787b9f9c3dbca5aa22";s:4:"name";s:23:"PEAR/Command/Pickle.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Command/Pickle.xml";}s:23:"PEAR/Command/Pickle.php";a:4:{s:6:"md5sum";s:32:"4025dd6411a73b19a5c19b3300060625";s:4:"name";s:23:"PEAR/Command/Pickle.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Command/Pickle.php";}s:25:"PEAR/Command/Registry.xml";a:4:{s:6:"md5sum";s:32:"49b046cfc14747f0365e02e9c3f0e6dc";s:4:"name";s:25:"PEAR/Command/Registry.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/opt/alt/php84/usr/share/pear/PEAR/Command/Registry.xml";}s:25:"PEAR/Command/Registry.php";a:4:{s:6:"md5sum";s:32:"9f2ea65794243f0b7287e8883f2ab60e";s:4:"name";s:25:"PEAR/Command/Registry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/opt/alt/php84/usr/share/pear/PEAR/Command/Registry.php";}s:23:"PEAR/Command/Remote.xml";a:4:{s:6:"md5sum";s:32:"29c02e823879b4e3e291f6b36fb339f1";s:4:"name";s:23:"PEAR/Command/Remote.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Command/Remote.xml";}s:23:"PEAR/Command/Remote.php";a:4:{s:6:"md5sum";s:32:"42c51cbb21c103fe0288e5c16871f401";s:4:"name";s:23:"PEAR/Command/Remote.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Command/Remote.php";}s:21:"PEAR/Command/Test.xml";a:4:{s:6:"md5sum";s:32:"a50c32015005e0761cc3b04679b29ed0";s:4:"name";s:21:"PEAR/Command/Test.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php84/usr/share/pear/PEAR/Command/Test.xml";}s:21:"PEAR/Command/Test.php";a:4:{s:6:"md5sum";s:32:"fbb0098fcda7fa29adaa0714a325caea";s:4:"name";s:21:"PEAR/Command/Test.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php84/usr/share/pear/PEAR/Command/Test.php";}s:27:"PEAR/Downloader/Package.php";a:4:{s:6:"md5sum";s:32:"9229a9711a893a18298e473212689ab4";s:4:"name";s:27:"PEAR/Downloader/Package.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Downloader/Package.php";}s:21:"PEAR/Frontend/CLI.php";a:4:{s:6:"md5sum";s:32:"5379be9492842c3af98241c6e226d285";s:4:"name";s:21:"PEAR/Frontend/CLI.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php84/usr/share/pear/PEAR/Frontend/CLI.php";}s:30:"PEAR/Installer/Role/Common.php";a:4:{s:6:"md5sum";s:32:"adae220f10a82e5f78b8689a57387753";s:4:"name";s:30:"PEAR/Installer/Role/Common.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Common.php";}s:27:"PEAR/Installer/Role/Cfg.xml";a:4:{s:6:"md5sum";s:32:"d8c62e6275e3aaa7784290912406092c";s:4:"name";s:27:"PEAR/Installer/Role/Cfg.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Cfg.xml";}s:27:"PEAR/Installer/Role/Cfg.php";a:4:{s:6:"md5sum";s:32:"d89d39dcc1c55fb4464f447ce4f84eed";s:4:"name";s:27:"PEAR/Installer/Role/Cfg.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Cfg.php";}s:28:"PEAR/Installer/Role/Data.xml";a:4:{s:6:"md5sum";s:32:"89a4a2a286e842d45a98974f40a0565c";s:4:"name";s:28:"PEAR/Installer/Role/Data.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Data.xml";}s:28:"PEAR/Installer/Role/Data.php";a:4:{s:6:"md5sum";s:32:"89754e8d153937f3dd3266fd8897d965";s:4:"name";s:28:"PEAR/Installer/Role/Data.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Data.php";}s:27:"PEAR/Installer/Role/Doc.xml";a:4:{s:6:"md5sum";s:32:"b1ce0fe105251c3b75209d6518ee69ac";s:4:"name";s:27:"PEAR/Installer/Role/Doc.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Doc.xml";}s:27:"PEAR/Installer/Role/Doc.php";a:4:{s:6:"md5sum";s:32:"849c557b355f78890ef47fcfd12073ab";s:4:"name";s:27:"PEAR/Installer/Role/Doc.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Doc.php";}s:27:"PEAR/Installer/Role/Ext.xml";a:4:{s:6:"md5sum";s:32:"af71c0ad42d16a323afe24a4f884ef15";s:4:"name";s:27:"PEAR/Installer/Role/Ext.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Ext.xml";}s:27:"PEAR/Installer/Role/Ext.php";a:4:{s:6:"md5sum";s:32:"7d3dc799576b3e3d74d187de118cc3e4";s:4:"name";s:27:"PEAR/Installer/Role/Ext.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Ext.php";}s:27:"PEAR/Installer/Role/Man.xml";a:4:{s:6:"md5sum";s:32:"da6743f1e45cce72ea13aef5cdb14867";s:4:"name";s:27:"PEAR/Installer/Role/Man.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Man.xml";}s:27:"PEAR/Installer/Role/Man.php";a:4:{s:6:"md5sum";s:32:"2509a027ae42c4b96aa49557325a0ec4";s:4:"name";s:27:"PEAR/Installer/Role/Man.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Man.php";}s:27:"PEAR/Installer/Role/Php.xml";a:4:{s:6:"md5sum";s:32:"ef88f0321d3e481c2130c95122cf76d8";s:4:"name";s:27:"PEAR/Installer/Role/Php.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Php.xml";}s:27:"PEAR/Installer/Role/Php.php";a:4:{s:6:"md5sum";s:32:"d7547896ec403dba2eed9825ed86ea64";s:4:"name";s:27:"PEAR/Installer/Role/Php.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Php.php";}s:30:"PEAR/Installer/Role/Script.xml";a:4:{s:6:"md5sum";s:32:"746461dc3b48af6d24094cb0211608f2";s:4:"name";s:30:"PEAR/Installer/Role/Script.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Script.xml";}s:30:"PEAR/Installer/Role/Script.php";a:4:{s:6:"md5sum";s:32:"325c60df7f78be127741621561758f46";s:4:"name";s:30:"PEAR/Installer/Role/Script.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Script.php";}s:27:"PEAR/Installer/Role/Src.xml";a:4:{s:6:"md5sum";s:32:"e147d63f168ea156fc2be38caaa63804";s:4:"name";s:27:"PEAR/Installer/Role/Src.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Src.xml";}s:27:"PEAR/Installer/Role/Src.php";a:4:{s:6:"md5sum";s:32:"464722cee0665ebc75757f76532f0ab2";s:4:"name";s:27:"PEAR/Installer/Role/Src.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Src.php";}s:28:"PEAR/Installer/Role/Test.xml";a:4:{s:6:"md5sum";s:32:"a24b596ec987aa5688fc19e8ed4e97ea";s:4:"name";s:28:"PEAR/Installer/Role/Test.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Test.xml";}s:28:"PEAR/Installer/Role/Test.php";a:4:{s:6:"md5sum";s:32:"a04eb2f4881ec6e6a13ae78f6a43e3cd";s:4:"name";s:28:"PEAR/Installer/Role/Test.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Test.php";}s:27:"PEAR/Installer/Role/Www.xml";a:4:{s:6:"md5sum";s:32:"7641e71c5785bb33a4261ebe25ed0fd7";s:4:"name";s:27:"PEAR/Installer/Role/Www.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Www.xml";}s:27:"PEAR/Installer/Role/Www.php";a:4:{s:6:"md5sum";s:32:"62699034e3186c2d68a6bb56a6cc23eb";s:4:"name";s:27:"PEAR/Installer/Role/Www.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role/Www.php";}s:23:"PEAR/Installer/Role.php";a:4:{s:6:"md5sum";s:32:"e95f2d850fce183e221912b2c2056d04";s:4:"name";s:23:"PEAR/Installer/Role.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role.php";}s:33:"PEAR/PackageFile/Generator/v1.php";a:4:{s:6:"md5sum";s:32:"cfa08685115d5e2d7635225d73a91f39";s:4:"name";s:33:"PEAR/PackageFile/Generator/v1.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/Generator/v1.php";}s:33:"PEAR/PackageFile/Generator/v2.php";a:4:{s:6:"md5sum";s:32:"8d264031153993866828e82129e389ab";s:4:"name";s:33:"PEAR/PackageFile/Generator/v2.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/Generator/v2.php";}s:30:"PEAR/PackageFile/Parser/v1.php";a:4:{s:6:"md5sum";s:32:"a2206e0e32ad2ba2f4e2a0c1797f295c";s:4:"name";s:30:"PEAR/PackageFile/Parser/v1.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/Parser/v1.php";}s:30:"PEAR/PackageFile/Parser/v2.php";a:4:{s:6:"md5sum";s:32:"3857f4b60878d64551a7cdae783437f7";s:4:"name";s:30:"PEAR/PackageFile/Parser/v2.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/Parser/v2.php";}s:26:"PEAR/PackageFile/v2/rw.php";a:4:{s:6:"md5sum";s:32:"a253999b2109460badc3c71ad2c069e7";s:4:"name";s:26:"PEAR/PackageFile/v2/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/v2/rw.php";}s:33:"PEAR/PackageFile/v2/Validator.php";a:4:{s:6:"md5sum";s:32:"44dafa313204f68b5fb54b9f61a86d0c";s:4:"name";s:33:"PEAR/PackageFile/v2/Validator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/v2/Validator.php";}s:23:"PEAR/PackageFile/v1.php";a:4:{s:6:"md5sum";s:32:"cc1ea307bb79c0cbcff4a90a4656e96e";s:4:"name";s:23:"PEAR/PackageFile/v1.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/v1.php";}s:23:"PEAR/PackageFile/v2.php";a:4:{s:6:"md5sum";s:32:"9e6012d4ef9cb8e12e2ccadcbdcf3d24";s:4:"name";s:23:"PEAR/PackageFile/v2.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/v2.php";}s:16:"PEAR/REST/10.php";a:4:{s:6:"md5sum";s:32:"ce77cc6593d8d4eda5ff8620ff09d6ec";s:4:"name";s:16:"PEAR/REST/10.php";s:4:"role";s:3:"php";s:12:"installed_as";s:46:"/opt/alt/php84/usr/share/pear/PEAR/REST/10.php";}s:16:"PEAR/REST/11.php";a:4:{s:6:"md5sum";s:32:"bdbd1f2e8afa2cddddecf2687579d316";s:4:"name";s:16:"PEAR/REST/11.php";s:4:"role";s:3:"php";s:12:"installed_as";s:46:"/opt/alt/php84/usr/share/pear/PEAR/REST/11.php";}s:16:"PEAR/REST/13.php";a:4:{s:6:"md5sum";s:32:"11179085b6efb577d37f45cc25e42a35";s:4:"name";s:16:"PEAR/REST/13.php";s:4:"role";s:3:"php";s:12:"installed_as";s:46:"/opt/alt/php84/usr/share/pear/PEAR/REST/13.php";}s:34:"PEAR/Task/Postinstallscript/rw.php";a:4:{s:6:"md5sum";s:32:"0eb57da4993a3cfed69fe8135f10b05a";s:4:"name";s:34:"PEAR/Task/Postinstallscript/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:64:"/opt/alt/php84/usr/share/pear/PEAR/Task/Postinstallscript/rw.php";}s:24:"PEAR/Task/Replace/rw.php";a:4:{s:6:"md5sum";s:32:"46c1bdb9a7af8628643e639ec1c3bc58";s:4:"name";s:24:"PEAR/Task/Replace/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/opt/alt/php84/usr/share/pear/PEAR/Task/Replace/rw.php";}s:24:"PEAR/Task/Unixeol/rw.php";a:4:{s:6:"md5sum";s:32:"50e20dbde7e51bb5e11545c56482b68a";s:4:"name";s:24:"PEAR/Task/Unixeol/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/opt/alt/php84/usr/share/pear/PEAR/Task/Unixeol/rw.php";}s:27:"PEAR/Task/Windowseol/rw.php";a:4:{s:6:"md5sum";s:32:"340be01552844adb50f6e0fa37aa3ffe";s:4:"name";s:27:"PEAR/Task/Windowseol/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php84/usr/share/pear/PEAR/Task/Windowseol/rw.php";}s:20:"PEAR/Task/Common.php";a:4:{s:6:"md5sum";s:32:"ec7f8db335ad3b5a25d78682745185d1";s:4:"name";s:20:"PEAR/Task/Common.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/opt/alt/php84/usr/share/pear/PEAR/Task/Common.php";}s:31:"PEAR/Task/Postinstallscript.php";a:4:{s:6:"md5sum";s:32:"86f240c600447fdb86bd38bd32c66c02";s:4:"name";s:31:"PEAR/Task/Postinstallscript.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php84/usr/share/pear/PEAR/Task/Postinstallscript.php";}s:21:"PEAR/Task/Replace.php";a:4:{s:6:"md5sum";s:32:"c993cdedc64084a1c4b735baec048d50";s:4:"name";s:21:"PEAR/Task/Replace.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php84/usr/share/pear/PEAR/Task/Replace.php";}s:21:"PEAR/Task/Unixeol.php";a:4:{s:6:"md5sum";s:32:"76c4ca15858c005cda208a9da1f5eb2d";s:4:"name";s:21:"PEAR/Task/Unixeol.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php84/usr/share/pear/PEAR/Task/Unixeol.php";}s:24:"PEAR/Task/Windowseol.php";a:4:{s:6:"md5sum";s:32:"d790eb3aa5ba22a33e42cb7c5f99fb25";s:4:"name";s:24:"PEAR/Task/Windowseol.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/opt/alt/php84/usr/share/pear/PEAR/Task/Windowseol.php";}s:23:"PEAR/Validator/PECL.php";a:4:{s:6:"md5sum";s:32:"b3c83ca826a4825ca2db726ed7d4b245";s:4:"name";s:23:"PEAR/Validator/PECL.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/PEAR/Validator/PECL.php";}s:16:"PEAR/Builder.php";a:4:{s:6:"md5sum";s:32:"7d89f25a54d100c2afd562fb3bd7c308";s:4:"name";s:16:"PEAR/Builder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:46:"/opt/alt/php84/usr/share/pear/PEAR/Builder.php";}s:20:"PEAR/ChannelFile.php";a:4:{s:6:"md5sum";s:32:"edcd484ecfd400875df90ee480c5384d";s:4:"name";s:20:"PEAR/ChannelFile.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/opt/alt/php84/usr/share/pear/PEAR/ChannelFile.php";}s:16:"PEAR/Command.php";a:4:{s:6:"md5sum";s:32:"a5d56f9d15ff6d22c12f7db851f281e8";s:4:"name";s:16:"PEAR/Command.php";s:4:"role";s:3:"php";s:12:"installed_as";s:46:"/opt/alt/php84/usr/share/pear/PEAR/Command.php";}s:15:"PEAR/Common.php";a:4:{s:6:"md5sum";s:32:"0af44a13df74291ac2f46949d2035e0e";s:4:"name";s:15:"PEAR/Common.php";s:4:"role";s:3:"php";s:12:"installed_as";s:45:"/opt/alt/php84/usr/share/pear/PEAR/Common.php";}s:15:"PEAR/Config.php";a:4:{s:6:"md5sum";s:32:"64d0f7b2737e5f182d0ab98bc77930d2";s:4:"name";s:15:"PEAR/Config.php";s:4:"role";s:3:"php";s:12:"installed_as";s:45:"/opt/alt/php84/usr/share/pear/PEAR/Config.php";}s:21:"PEAR/DependencyDB.php";a:4:{s:6:"md5sum";s:32:"7e8dfae09802be7f2e6170062bb80cbd";s:4:"name";s:21:"PEAR/DependencyDB.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php84/usr/share/pear/PEAR/DependencyDB.php";}s:20:"PEAR/Dependency2.php";a:4:{s:6:"md5sum";s:32:"76fdabdee883fd16b986332552b9e3dc";s:4:"name";s:20:"PEAR/Dependency2.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/opt/alt/php84/usr/share/pear/PEAR/Dependency2.php";}s:19:"PEAR/Downloader.php";a:4:{s:6:"md5sum";s:32:"2ccb7bb2d00eae201ee7ae1eef49ad8a";s:4:"name";s:19:"PEAR/Downloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:49:"/opt/alt/php84/usr/share/pear/PEAR/Downloader.php";}s:19:"PEAR/ErrorStack.php";a:4:{s:6:"md5sum";s:32:"ea807632b63d2e0acd6924db23aaa0eb";s:4:"name";s:19:"PEAR/ErrorStack.php";s:4:"role";s:3:"php";s:12:"installed_as";s:49:"/opt/alt/php84/usr/share/pear/PEAR/ErrorStack.php";}s:18:"PEAR/Exception.php";a:4:{s:6:"md5sum";s:32:"544ed48cab9407a936d058d09e773e22";s:4:"name";s:18:"PEAR/Exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:48:"/opt/alt/php84/usr/share/pear/PEAR/Exception.php";}s:17:"PEAR/Frontend.php";a:4:{s:6:"md5sum";s:32:"31c0b91767550adf77f1c9bea92a0559";s:4:"name";s:17:"PEAR/Frontend.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php84/usr/share/pear/PEAR/Frontend.php";}s:18:"PEAR/Installer.php";a:4:{s:6:"md5sum";s:32:"b8b85e42b840676ad3ae1c15e55b005b";s:4:"name";s:18:"PEAR/Installer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:48:"/opt/alt/php84/usr/share/pear/PEAR/Installer.php";}s:20:"PEAR/PackageFile.php";a:4:{s:6:"md5sum";s:32:"2929765413405abf63574c8a544e4a04";s:4:"name";s:20:"PEAR/PackageFile.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile.php";}s:17:"PEAR/Packager.php";a:4:{s:6:"md5sum";s:32:"ad25a29d464b62cbaaa3ca96e622526c";s:4:"name";s:17:"PEAR/Packager.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php84/usr/share/pear/PEAR/Packager.php";}s:14:"PEAR/Proxy.php";a:4:{s:6:"md5sum";s:32:"ef9d00adaeccff7516f08170096026d3";s:4:"name";s:14:"PEAR/Proxy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:44:"/opt/alt/php84/usr/share/pear/PEAR/Proxy.php";}s:17:"PEAR/Registry.php";a:4:{s:6:"md5sum";s:32:"ae8c1dcfddb6a2717e09239bb1430dc7";s:4:"name";s:17:"PEAR/Registry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php84/usr/share/pear/PEAR/Registry.php";}s:13:"PEAR/REST.php";a:4:{s:6:"md5sum";s:32:"389d1bad72267d3ed770abf0662d8086";s:4:"name";s:13:"PEAR/REST.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php84/usr/share/pear/PEAR/REST.php";}s:16:"PEAR/RunTest.php";a:4:{s:6:"md5sum";s:32:"df0d7022e22fd78ecd82080ff4f108d5";s:4:"name";s:16:"PEAR/RunTest.php";s:4:"role";s:3:"php";s:12:"installed_as";s:46:"/opt/alt/php84/usr/share/pear/PEAR/RunTest.php";}s:17:"PEAR/Validate.php";a:4:{s:6:"md5sum";s:32:"3711c281e0234203ec7879f53bc766ab";s:4:"name";s:17:"PEAR/Validate.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php84/usr/share/pear/PEAR/Validate.php";}s:18:"PEAR/XMLParser.php";a:4:{s:6:"md5sum";s:32:"da9510087eddd489945dde07260256ee";s:4:"name";s:18:"PEAR/XMLParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:48:"/opt/alt/php84/usr/share/pear/PEAR/XMLParser.php";}s:15:"scripts/pear.sh";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"10fee903f92b4c181e49ce3d80385317";s:4:"name";s:15:"scripts/pear.sh";s:4:"role";s:6:"script";s:10:"install-as";s:4:"pear";s:12:"installed_as";s:27:"/opt/alt/php84/usr/bin/pear";}s:18:"scripts/peardev.sh";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"be389867ea6ebdc170dcc56c2f38afa6";s:4:"name";s:18:"scripts/peardev.sh";s:4:"role";s:6:"script";s:10:"install-as";s:7:"peardev";s:12:"installed_as";s:30:"/opt/alt/php84/usr/bin/peardev";}s:15:"scripts/pecl.sh";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9fa87a30260fc9d4ebfa26a1ad678e97";s:4:"name";s:15:"scripts/pecl.sh";s:4:"role";s:6:"script";s:10:"install-as";s:4:"pecl";s:12:"installed_as";s:27:"/opt/alt/php84/usr/bin/pecl";}s:19:"scripts/pearcmd.php";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a3d846742480f7c61f0ebf7d77d86214";s:4:"name";s:19:"scripts/pearcmd.php";s:4:"role";s:3:"php";s:10:"install-as";s:11:"pearcmd.php";s:12:"installed_as";s:41:"/opt/alt/php84/usr/share/pear/pearcmd.php";}s:19:"scripts/peclcmd.php";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6a188506ab4d81bcdac6a64404f94894";s:4:"name";s:19:"scripts/peclcmd.php";s:4:"role";s:3:"php";s:10:"install-as";s:11:"peclcmd.php";s:12:"installed_as";s:41:"/opt/alt/php84/usr/share/pear/peclcmd.php";}s:7:"LICENSE";a:4:{s:6:"md5sum";s:32:"45b44486d8090de17b2a8b4211fab247";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:46:"/opt/alt/php84/usr/share/doc/pear/PEAR/LICENSE";}s:7:"INSTALL";a:4:{s:6:"md5sum";s:32:"eaac3d33068c6e67573ed44155b149ae";s:4:"name";s:7:"INSTALL";s:4:"role";s:3:"doc";s:12:"installed_as";s:46:"/opt/alt/php84/usr/share/doc/pear/PEAR/INSTALL";}s:11:"package.dtd";a:4:{s:6:"md5sum";s:32:"69341ea97af9c88956568f8e7e41d4c6";s:4:"name";s:11:"package.dtd";s:4:"role";s:4:"data";s:12:"installed_as";s:51:"/opt/alt/php84/usr/share/pear/data/PEAR/package.dtd";}s:8:"PEAR.php";a:4:{s:6:"md5sum";s:32:"47aeb7eaff6438beb60bc42bc0e6c658";s:4:"name";s:8:"PEAR.php";s:4:"role";s:3:"php";s:12:"installed_as";s:38:"/opt/alt/php84/usr/share/pear/PEAR.php";}s:10:"README.rst";a:4:{s:6:"md5sum";s:32:"cd10521cc4054923a3d2b6e15b4df493";s:4:"name";s:10:"README.rst";s:4:"role";s:3:"doc";s:12:"installed_as";s:49:"/opt/alt/php84/usr/share/doc/pear/PEAR/README.rst";}s:10:"System.php";a:4:{s:6:"md5sum";s:32:"ba9e5c5a567e51b440808a8ed53cd76d";s:4:"name";s:10:"System.php";s:4:"role";s:3:"php";s:12:"installed_as";s:40:"/opt/alt/php84/usr/share/pear/System.php";}s:13:"template.spec";a:4:{s:6:"md5sum";s:32:"acd010e3bc43c0f72df584acde7b9158";s:4:"name";s:13:"template.spec";s:4:"role";s:4:"data";s:12:"installed_as";s:53:"/opt/alt/php84/usr/share/pear/data/PEAR/template.spec";}}s:12:"_lastversion";N;s:7:"dirtree";a:23:{s:32:"/opt/alt/php84/usr/share/pear/OS";b:1;s:46:"/opt/alt/php84/usr/share/pear/PEAR/ChannelFile";b:1;s:34:"/opt/alt/php84/usr/share/pear/PEAR";b:1;s:42:"/opt/alt/php84/usr/share/pear/PEAR/Command";b:1;s:45:"/opt/alt/php84/usr/share/pear/PEAR/Downloader";b:1;s:43:"/opt/alt/php84/usr/share/pear/PEAR/Frontend";b:1;s:49:"/opt/alt/php84/usr/share/pear/PEAR/Installer/Role";b:1;s:44:"/opt/alt/php84/usr/share/pear/PEAR/Installer";b:1;s:56:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/Generator";b:1;s:46:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile";b:1;s:53:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/Parser";b:1;s:49:"/opt/alt/php84/usr/share/pear/PEAR/PackageFile/v2";b:1;s:39:"/opt/alt/php84/usr/share/pear/PEAR/REST";b:1;s:57:"/opt/alt/php84/usr/share/pear/PEAR/Task/Postinstallscript";b:1;s:39:"/opt/alt/php84/usr/share/pear/PEAR/Task";b:1;s:47:"/opt/alt/php84/usr/share/pear/PEAR/Task/Replace";b:1;s:47:"/opt/alt/php84/usr/share/pear/PEAR/Task/Unixeol";b:1;s:50:"/opt/alt/php84/usr/share/pear/PEAR/Task/Windowseol";b:1;s:44:"/opt/alt/php84/usr/share/pear/PEAR/Validator";b:1;s:22:"/opt/alt/php84/usr/bin";b:1;s:29:"/opt/alt/php84/usr/share/pear";b:1;s:38:"/opt/alt/php84/usr/share/doc/pear/PEAR";b:1;s:39:"/opt/alt/php84/usr/share/pear/data/PEAR";b:1;}s:3:"old";a:7:{s:7:"version";s:7:"1.10.16";s:12:"release_date";s:10:"2024-11-24";s:13:"release_state";s:6:"stable";s:15:"release_license";s:15:"New BSD License";s:13:"release_notes";s:164:"* PR #141: Fix bug #27796: "Array to string" conversion warnings on installs/other actions * PR #145: Never reference E_STRICT on PHP 8.4+ * PR #147: Fix tests 8.1+";s:12:"release_deps";a:8:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.4.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:6:"1.10.1";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:11:"Archive_Tar";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.9";s:8:"optional";s:2:"no";}i:3;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:16:"Structures_Graph";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.1.0";s:8:"optional";s:2:"no";}i:4;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:14:"Console_Getopt";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.1";s:8:"optional";s:2:"no";}i:5;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:8:"XML_Util";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:6;a:4:{s:4:"type";s:3:"ext";s:4:"name";s:3:"xml";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:7;a:4:{s:4:"type";s:3:"ext";s:4:"name";s:4:"pcre";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:11:{i:0;a:5:{s:4:"name";s:11:"Greg Beaver";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:2:"no";s:6:"handle";s:6:"cellog";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:17:"Pierre-Alain Joye";s:5:"email";s:14:"pierre@php.net";s:6:"active";s:2:"no";s:6:"handle";s:6:"pajoye";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:4:"lead";}i:3;a:5:{s:4:"name";s:13:"Tomas V.V.Cox";s:5:"email";s:15:"cox@idecnet.com";s:6:"active";s:2:"no";s:6:"handle";s:3:"cox";s:4:"role";s:4:"lead";}i:4;a:5:{s:4:"name";s:13:"Helgi Thormar";s:5:"email";s:13:"dufuz@php.net";s:6:"active";s:2:"no";s:6:"handle";s:5:"dufuz";s:4:"role";s:4:"lead";}i:5;a:5:{s:4:"name";s:16:"Christian Weiske";s:5:"email";s:15:"cweiske@php.net";s:6:"active";s:2:"no";s:6:"handle";s:7:"cweiske";s:4:"role";s:4:"lead";}i:6;a:5:{s:4:"name";s:13:"Chuck Burgess";s:5:"email";s:15:"ashnazg@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:7:"ashnazg";s:4:"role";s:4:"lead";}i:7;a:5:{s:4:"name";s:9:"Tias Guns";s:5:"email";s:12:"tias@php.net";s:6:"active";s:2:"no";s:6:"handle";s:4:"tias";s:4:"role";s:9:"developer";}i:8;a:5:{s:4:"name";s:11:"Tim Jackson";s:5:"email";s:12:"timj@php.net";s:6:"active";s:2:"no";s:6:"handle";s:4:"timj";s:4:"role";s:6:"helper";}i:9;a:5:{s:4:"name";s:15:"Bertrand Gugger";s:5:"email";s:13:"toggg@php.net";s:6:"active";s:2:"no";s:6:"handle";s:5:"toggg";s:4:"role";s:6:"helper";}i:10;a:5:{s:4:"name";s:13:"Martin Jansen";s:5:"email";s:10:"mj@php.net";s:6:"active";s:2:"no";s:6:"handle";s:2:"mj";s:4:"role";s:6:"helper";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1747073454;}PK! C}++.registry/structures_graph.regnu[a:24:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:16:"Structures_Graph";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:40:"Graph datastructure manipulation library";s:11:"description";s:293:"Structures_Graph is a package for creating and manipulating graph datastructures. It allows building of directed and undirected graphs, with data and metadata stored in nodes. The library provides functions for graph traversing as well as for characteristic extraction from the graph topology.";s:4:"lead";a:4:{s:4:"name";s:16:"Sérgio Carvalho";s:4:"user";s:9:"sergiosgc";s:5:"email";s:32:"sergio.carvalho@portugalmail.com";s:6:"active";s:3:"yes";}s:6:"helper";a:4:{s:4:"name";s:12:"Brett Bieber";s:4:"user";s:11:"saltybeagle";s:5:"email";s:22:"brett.bieber@gmail.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2015-07-20";s:4:"time";s:8:"20:04:01";s:7:"version";a:2:{s:7:"release";s:5:"1.1.1";s:3:"api";s:5:"1.1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";s:9:"LGPL-3.0+";s:5:"notes";s:55:"* Fix deprecated constructor warning on PHP 7 [cweiske]";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:12:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"628eb6532a8047bf5962fe24c1c245df";s:4:"name";s:52:"docs/tutorials/Structures_Graph/Structures_Graph.pkg";s:4:"role";s:3:"doc";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4b26eecd30f8695fc3739b1a5b59518e";s:4:"name";s:44:"Structures/Graph/Manipulator/AcyclicTest.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1f857de1fbbaace54b857ed9712f399f";s:4:"name";s:50:"Structures/Graph/Manipulator/TopologicalSorter.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f8e969f0b45d3859408901c8350bb701";s:4:"name";s:25:"Structures/Graph/Node.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"88ae1ad8bcd74d4b74ad845f55611cdd";s:4:"name";s:20:"Structures/Graph.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"65e4e85e573833516f5cc1d7a81db9c5";s:4:"name";s:18:"tests/AllTests.php";s:4:"role";s:4:"test";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"68ba309e2ac6713527f0fd31456457a1";s:4:"name";s:24:"tests/BasicGraphTest.php";s:4:"role";s:4:"test";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"190fc4634be55cd98608b72bc9d0a27f";s:4:"name";s:31:"tests/TopologicalSorterTest.php";s:4:"role";s:4:"test";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4dc0c43f054732ec0f2fc78458ebadde";s:4:"name";s:25:"tests/AcyclicTestTest.php";s:4:"role";s:4:"test";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"68ba309e2ac6713527f0fd31456457a1";s:4:"name";s:24:"tests/BasicGraphTest.php";s:4:"role";s:4:"test";}}i:10;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c891580ee21a7aa863ac32566c979fc5";s:4:"name";s:16:"tests/helper.inc";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b52f2d57d10c4f7ee67a7eb9615d5d24";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";}}}}}s:10:"compatible";a:4:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:8:"1.5.0RC3";s:3:"max";s:5:"1.9.1";}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.3";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:5:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.2";s:3:"api";s:5:"1.0.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-01-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:47:"http://opensource.org/licenses/lgpl-license.php";}s:8:"_content";s:4:"LGPL";}s:5:"notes";s:130:"- Bug #9682 only variables can be returned by reference - fix Bug #9661 notice in Structures_Graph_Manipulator_Topological::sort()";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.3";s:3:"api";s:5:"1.0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-10-11";s:7:"license";s:12:"LGPL License";s:5:"notes";s:258:"Bugfix Release: Version 1.0.3 is functionally equivalent to 1.0.2 but with an updated package.xml file. * Correct invalid md5 sum preventing installation with pyrus [saltybeagle] * Add compatible tag for PEAR 1.5.0RC3-1.9.0 [saltybeagle] * Update package.xml";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.4";s:3:"api";s:5:"1.0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-10-25";s:7:"license";s:12:"LGPL License";s:5:"notes";s:88:"Bugfix Release: * Bug #17108 BasicGraph::test_directed_degree fails on PHP 5 [clockwerx]";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.0";s:3:"api";s:5:"1.1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2015-02-26";s:7:"license";s:9:"LGPL-3.0+";s:5:"notes";s:128:"* Set minimum PHP version to 5.3 * Fix bug #19367: Incorrect FSF address in LICENSE * Change license from LGPL-2.1+ to LGPL-3.0+";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.1";s:3:"api";s:5:"1.1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2015-07-20";s:7:"license";s:9:"LGPL-3.0+";s:5:"notes";s:55:"* Fix deprecated constructor warning on PHP 7 [cweiske]";}}}s:8:"filelist";a:11:{s:52:"docs/tutorials/Structures_Graph/Structures_Graph.pkg";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"628eb6532a8047bf5962fe24c1c245df";s:4:"name";s:52:"docs/tutorials/Structures_Graph/Structures_Graph.pkg";s:4:"role";s:3:"doc";s:12:"installed_as";s:103:"/opt/alt/php84/usr/share/doc/pear/Structures_Graph/docs/tutorials/Structures_Graph/Structures_Graph.pkg";}s:44:"Structures/Graph/Manipulator/AcyclicTest.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4b26eecd30f8695fc3739b1a5b59518e";s:4:"name";s:44:"Structures/Graph/Manipulator/AcyclicTest.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php84/usr/share/pear/Structures/Graph/Manipulator/AcyclicTest.php";}s:50:"Structures/Graph/Manipulator/TopologicalSorter.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1f857de1fbbaace54b857ed9712f399f";s:4:"name";s:50:"Structures/Graph/Manipulator/TopologicalSorter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php84/usr/share/pear/Structures/Graph/Manipulator/TopologicalSorter.php";}s:25:"Structures/Graph/Node.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f8e969f0b45d3859408901c8350bb701";s:4:"name";s:25:"Structures/Graph/Node.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/opt/alt/php84/usr/share/pear/Structures/Graph/Node.php";}s:20:"Structures/Graph.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"88ae1ad8bcd74d4b74ad845f55611cdd";s:4:"name";s:20:"Structures/Graph.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/opt/alt/php84/usr/share/pear/Structures/Graph.php";}s:18:"tests/AllTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"65e4e85e573833516f5cc1d7a81db9c5";s:4:"name";s:18:"tests/AllTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php84/usr/share/pear/test/Structures_Graph/tests/AllTests.php";}s:24:"tests/BasicGraphTest.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"68ba309e2ac6713527f0fd31456457a1";s:4:"name";s:24:"tests/BasicGraphTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php84/usr/share/pear/test/Structures_Graph/tests/BasicGraphTest.php";}s:31:"tests/TopologicalSorterTest.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"190fc4634be55cd98608b72bc9d0a27f";s:4:"name";s:31:"tests/TopologicalSorterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php84/usr/share/pear/test/Structures_Graph/tests/TopologicalSorterTest.php";}s:25:"tests/AcyclicTestTest.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4dc0c43f054732ec0f2fc78458ebadde";s:4:"name";s:25:"tests/AcyclicTestTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/opt/alt/php84/usr/share/pear/test/Structures_Graph/tests/AcyclicTestTest.php";}s:16:"tests/helper.inc";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"559be007c7fb5cd0d8acbbfd7549dff6";s:4:"name";s:16:"tests/helper.inc";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php84/usr/share/pear/test/Structures_Graph/tests/helper.inc";}s:7:"LICENSE";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b52f2d57d10c4f7ee67a7eb9615d5d24";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:58:"/opt/alt/php84/usr/share/doc/pear/Structures_Graph/LICENSE";}}s:12:"_lastversion";N;s:7:"dirtree";a:9:{s:82:"/opt/alt/php84/usr/share/doc/pear/Structures_Graph/docs/tutorials/Structures_Graph";b:1;s:65:"/opt/alt/php84/usr/share/doc/pear/Structures_Graph/docs/tutorials";b:1;s:55:"/opt/alt/php84/usr/share/doc/pear/Structures_Graph/docs";b:1;s:50:"/opt/alt/php84/usr/share/doc/pear/Structures_Graph";b:1;s:58:"/opt/alt/php84/usr/share/pear/Structures/Graph/Manipulator";b:1;s:46:"/opt/alt/php84/usr/share/pear/Structures/Graph";b:1;s:40:"/opt/alt/php84/usr/share/pear/Structures";b:1;s:57:"/opt/alt/php84/usr/share/pear/test/Structures_Graph/tests";b:1;s:51:"/opt/alt/php84/usr/share/pear/test/Structures_Graph";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.1.1";s:12:"release_date";s:10:"2015-07-20";s:13:"release_state";s:6:"stable";s:15:"release_license";s:9:"LGPL-3.0+";s:13:"release_notes";s:55:"* Fix deprecated constructor warning on PHP 7 [cweiske]";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.3";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:2:{i:0;a:5:{s:4:"name";s:16:"Sérgio Carvalho";s:5:"email";s:32:"sergio.carvalho@portugalmail.com";s:6:"active";s:3:"yes";s:6:"handle";s:9:"sergiosgc";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:12:"Brett Bieber";s:5:"email";s:22:"brett.bieber@gmail.com";s:6:"active";s:3:"yes";s:6:"handle";s:11:"saltybeagle";s:4:"role";s:6:"helper";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1747073454;}PK!RRRpkgxml/Archive_Tar.xmlnu[ Archive_Tar pear.php.net Tar file management class This class provides handling of tar files in PHP. It supports creating, listing, extracting and adding to tar files. Gzip support is available if PHP has the zlib extension built-in or loaded. Bz2 compression is also supported with the bz2 extension loaded. Also Lzma2 compressed archives are supported with xz extension. Vincent Blavet vblavet vincent@phpconcept.net no Greg Beaver cellog greg@chiaraquartet.net no Michiel Rook mrook mrook@php.net no Drew Webber mcdruid drew@mcdruid.co.uk yes Stig Bakken ssb stig@php.net no 2025-07-19 1.6.0 1.6.0 stable stable New BSD License This release drops support for PHP 5.4 and 5.5. * PR #51: big file support * PR #53: Fix return value of _writeBlock * PR #58: Remove gzopen/gztell/gzseek shim PEAR pear.php.net 1.8.0 1.10.10 5.6.0 1.10.0 1.6.0 1.6.0 stable stable 2025-07-19 New BSD License This release drops support for PHP 5.4 and 5.5. * PR #51: big file support * PR #53: Fix return value of _writeBlock * PR #58: Remove gzopen/gztell/gzseek shim 1.5.0 1.5.0 stable stable 2024-03-16 New BSD License * PR #42: fix @return true... to @return bool true... on some functions * PR #46: use 775 default for mkdirs, to avoid world-write 1.4.14 1.4.0 stable stable 2021-02-16 New BSD License * Properly fix symbolic link path traversal (CVE-2021-32610) 1.4.13 1.4.0 stable stable 2021-02-16 New BSD License * Fix Bug #27010: Relative symlinks failing (out-of path file extraction) [mrook] 1.4.12 1.4.0 stable stable 2021-01-18 New BSD License * Fix Bug #27008: Symlink out-of-path write vulnerability (CVE-2020-36193) [mrook] 1.4.11 1.4.0 stable stable 2020-11-19 New BSD License * Fix Bug #27002: Filename manipulation vulnerabilities (CVE-2020-28948 / CVE-2020-28949) [mrook] 1.4.10 1.4.0 stable stable 2020-09-15 New BSD License * Fix block padding when the file buffer length is a multiple of 512 and smaller than Archive_Tar buffer length * Don't try to copy username/groupname in chroot jail 1.4.9 1.4.0 stable stable 2019-12-04 New BSD License * Implement Feature #23861: Add option to disallow symlinks [mrook] 1.4.8 1.4.0 stable stable 2019-10-21 New BSD License * Fix Bug #23852: PHP 7.4 - Archive_Tar->_readHeader throws deprecation [mrook] 1.4.7 1.4.0 stable stable 2019-04-08 New BSD License * Improved performance by increasing read buffer size 1.4.6 1.4.0 stable stable 2019-02-01 New BSD License * Improve path traversal detection for forward and backward slashes 1.4.5 1.4.0 stable stable 2019-01-02 New BSD License * Fix Bug #23788: Relative symlinks are broken [mrook] 1.4.4 1.4.0 stable stable 2018-12-20 New BSD License * Fix Bug #21058: Long symlinks are not supported [mrook] * Fix Bug #23782: Prevent phar:// files from being extracted [mrook] 1.4.3 1.4.0 stable stable 2017-06-11 New BSD License * Fix Bug #21218: Cannot use result of built-in function in write context in PHP 7.2.0alpha1 [mrook] 1.4.2 1.4.0 stable stable 2016-02-25 New BSD License * Fix reading of archives with files > 8GB * Performance optimizations * Do not try to call require_once on PEAR.php if it has already been loaded by the autoloader 1.4.1 1.4.0 stable stable 2015-08-05 New BSD License * Update composer.json to use pear-core-minimal 1.10.0alpha2 1.4.0 1.4.0 stable stable 2015-07-20 New BSD License * Add support for PHP 7 * Drop support for PHP 4 * Add visibility declarations to methods and properties 1.3.16 1.3.1 stable stable 2015-04-14 New BSD License * Fix Bug #20514: invalid package.xml; not installable with pyrus [mrook] 1.3.15 1.3.1 stable stable 2015-03-05 New BSD License * Fixes composer.json parse error 1.3.14 1.3.1 stable stable 2015-02-26 New BSD License * Fix Bug #18505: Possible incorrect handling of file names in TAR [mrook] 1.3.13 1.3.1 stable stable 2014-09-02 New BSD License * Fix Bug #20382: gzopen fix [mrook] 1.3.12 1.3.1 stable stable 2014-08-04 New BSD License * Fix Bug #19964: Memory leaking in Archive_Tar [mrook] * Fix Bug #20246: Broken with php 5.5.9 [mrook] * Fix Bug #20275: "pax_global_header" looks like a regular file * [mrook] * Implement Feature #19827: pass filename to _addFile function - downstream * patch [mrook] * Implement Feature #20132: Add custom mode/uid/gid to addString() [mrook] 1.3.11 1.3.1 stable stable 2013-02-09 New BSD License * Fix Bug #19746: Broken with PHP 5.5 [mrook] * Implement Feature #11258: Custom date/time in files added on-the-fly * [mrook] 1.3.10 1.3.1 stable stable 2012-04-10 New BSD License * Fix Bug #13361: Unable to add() some files (ex. mp3) [mrook] * Fix Bug #19330: Class creates incorrect (non-readable) tar.gz file * [mrook] 1.3.9 1.3.1 stable stable 2012-02-27 New BSD License * Fix Bug #16759: No error thrown from missing PHP zlib functions [mrook] * Fix Bug #18877: Incorrect handling of backslashes in filenames on Linux [mrook] * Fix Bug #19085: Error while packaging [mrook] * Fix Bug #19289: Invalid tar file generated [mrook] 1.3.8 1.3.1 stable stable 2011-10-14 New BSD License * Fix Bug #17853: Test failure: dirtraversal.phpt [mrook] * Fix Bug #18512: dead links are not saved in tar file [mrook] * Fix Bug #18702: Unpacks incorrectly on long file names using header prefix [mrook] * Implement Feature #10145: Patch to return a Pear Error Object on failure [mrook] * Implement Feature #17491: Option to preserve permissions [mrook] * Implement Feature #17813: Prevent PHP notice when extracting corrupted archive [mrook] 1.3.7 1.3.1 stable stable 2010-04-26 New BSD License PEAR compatibility update 1.3.6 1.3.1 stable stable 2010-03-09 New BSD License * Fix Bug #16963: extractList can't extract zipped files from big tar [mrook] * Implement Feature #4013: Ignoring files and directories on creating an archive. [mrook] 1.3.5 1.3.1 stable stable 2009-12-31 New BSD License * Fix Bug #16958: Update 'compatible' tag in package.xml [mrook] 1.3.4 1.3.1 stable stable 2009-12-30 New BSD License * Fix Bug #11871: wrong result of ::listContent() if filename begins or ends with space [mrook] * Fix Bug #12462: invalid tar magic [mrook] * Fix Bug #13918: Long filenames may get up to 511 0x00 bytes appended on read [mrook] * Fix Bug #16202: Bogus modification times [mrook] * Implement Feature #16212: Die is not exception [mrook] 1.3.3 1.3.1 stable stable 2009-03-27 New BSD License Change the license to New BSD license minor bugfix release * fix Bug #9921 compression with bzip2 fails [cellog] * fix Bug #11594 _readLongHeader leaves 0 bytes in filename [jamessas] * fix Bug #11769 Incorrect symlink handing [fajar99] 1.3.2 1.3.1 stable stable 2007-01-03 PHP License Correct Bug #4016 Remove duplicate remove error display with '@' Correct Bug #3909 : Check existence of OS_WINDOWS constant Correct Bug #5452 fix for "lone zero block" when untarring packages Change filemode (from pear-core/Archive/Tar.php v.1.21) Correct Bug #6486 Can not extract symlinks Correct Bug #6933 Archive_Tar (Tar file management class) Directory traversal Correct Bug #8114 Files added on-the-fly not storing date Correct Bug #9352 Bug on _dirCheck function over nfs path 1.3.1 1.3.1 stable stable 2005-03-17 PHP License Correct Bug #3855 1.3.0 1.3.0 stable stable 2005-03-06 PHP License Bugs correction (2475, 2488, 2135, 2176) 1.2 1.2 stable stable 2004-05-08 PHP License Add support for other separator than the space char and bug correction 1.1 1.1 stable stable 2003-05-28 PHP License * Add support for BZ2 compression * Add support for add and extract without using temporary files : methods addString() and extractInString() 1.0 1.0 stable stable 2003-01-24 PHP License Change status to stable 0.10-b1 0.10-b1 beta beta 2003-01-08 PHP License Add support for long filenames (greater than 99 characters) 0.9 0.9 stable stable 2002-05-27 PHP License Auto-detect gzip'ed files 0.4 0.4 stable stable 2002-05-20 PHP License Windows bugfix: use forward slashes inside archives 0.2 0.2 stable stable 2002-02-18 PHP License From initial commit to stable 0.3 0.3 stable stable 2002-04-13 PHP License Windows bugfix: used wrong directory separators PK!+8pkgxml/PEAR.xmlnu[ PEAR pear.php.net PEAR Base System The PEAR package contains: * the PEAR installer, for creating, distributing and installing packages * the PEAR_Exception PHP5 error handling mechanism * the PEAR_ErrorStack advanced error handling mechanism * the PEAR_Error error handling mechanism * the OS_Guess class for retrieving info about the OS where PHP is running on * the System class for quick handling of common operations with files and directories * the PEAR base class Features in a nutshell: * full support for channels * pre-download dependency validation * new package.xml 2.0 format allows tremendous flexibility while maintaining BC * support for optional dependency groups and limited support for sub-packaging * robust dependency support * full dependency validation on uninstall * remote install for hosts with only ftp access - no more problems with restricted host installation * full support for mirroring * support for bundling several packages into a single tarball * support for static dependencies on a url-based package * support for custom file roles and installation tasks Greg Beaver cellog cellog@php.net no Pierre-Alain Joye pajoye pierre@php.net no Stig Bakken ssb stig@php.net no Tomas V.V.Cox cox cox@idecnet.com no Helgi Thormar dufuz dufuz@php.net no Christian Weiske cweiske cweiske@php.net no Chuck Burgess ashnazg ashnazg@php.net yes Tias Guns tias tias@php.net no Tim Jackson timj timj@php.net no Bertrand Gugger toggg toggg@php.net no Martin Jansen mj mj@php.net no 2026-01-25 1.10.18 1.10.1 stable stable New BSD License * PR #164: don't use report_memleaks with 8.5+ 5.4.0 1.10.1 Archive_Tar pear.php.net 1.4.9 1.4.4 Structures_Graph pear.php.net 1.1.0 1.1.1 Console_Getopt pear.php.net 1.4.1 1.4.3 XML_Util pear.php.net 1.4.0 1.4.5 xml pcre PEAR_Frontend_Web pear.php.net 0.5.1 PEAR_Frontend_Gtk pear.php.net 0.4.0 PEAR_Frontend_Gtk2 pear.php.net windows 1.8.0alpha1 1.8.0 alpha stable 2009-03-09 New BSD License * Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz] * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz] * Implement Request #10825: Only display the "invalid or missing package file"-error if it makes sense [dufuz] * Implement Request #11170: script to generate Command/[command].xml [dufuz] * Implement Request #11176: improve channel ... has updated its protocols message [dufuz] * Implement Request #12706: pear list -a hard to read [dufuz] * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz] * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos] * Implement Request #13927: install-pear.php should have option to set www_dir [timj] * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz] * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz] - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate better what other package managers are doing. upgrade-all will still work as intended. * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz] - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for channel specific upgrades * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske] * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle] * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog] * Fix PHP Bug #47323: strotime warnings in make install [dufuz] * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz] * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj] * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit] * Fix Bug #13953: config-set/config-show with channel alias fail [cellog] * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz] * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz] * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz] * Fix Bug #14210: pear list -ia brings warnings [dufuz] * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz] * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz] * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos] * Fix Bug #14437: openbasedir warning when loading config [dufuz] * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske] * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali] * Fix Bug #14977: PEAR/Frontend.php doesn't require_once PEAR.php [dufuz] * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz] * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz] * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz] NOTE! Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment to migrate over to one of the alternatives that have ben provided: * PEAR_Common->downloadHttp (use PEAR_Downloader->downloadHttp instead) * PEAR_Common->infoFromTgzFile (use PEAR_PackageFile->fromTgzFile instead) * PEAR_Common->infoFromDescriptionFile (use PEAR_PackageFile->fromPackageFile instead) * PEAR_Common->infoFromString (use PEAR_PackageFile->fromXmlstring instead) * PEAR_Common->infoFromArray (use PEAR_PackageFile->fromAnyFile instead) * PEAR_Common->xmlFromInfo (use a PEAR_PackageFile_v* object's generator instead) * PEAR_Common->validatePackageInfo (use the validation of PEAR_PackageFile objects) * PEAR_Common->analyzeSourceCode (use a PEAR_PackageFile_v* object instead) * PEAR_Common->detectDependencies (use PEAR_Downloader_Package->detectDependencies instead) * PEAR_Common->buildProvidesArray (use PEAR_PackageFile_v1->_buildProvidesArray or PEAR_PackageFile_v2_Validator->_buildProvidesArray) PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls pear upgrade -f PEAR will allow people with lower versions to upgrade to this release but no guarantees will be made that it will work properly. Support for XML RPC channels has been dropped - The only ones that used it (pear.php.net and pecl.php.net) have used the REST interface for years now. SOAP support also removed as it was only proof of concept. Move codebase from the PHP License to New BSD 2 clause license 2009-03-27 1.8.0RC1 1.8.0 beta stable New BSD License * Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz] * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz] * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz] * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz] 2009-04-10 1.8.0 1.8.0 stable stable New BSD License Changes since RC1: * Fix Bug #14792: Bad md5sum for files with replaced content [dufuz] * Fix Bug #16057:-r is limited to 4 directories in depth [dufuz] * Fix Bug #16077: PEAR5::getStaticProperty does not return a reference to the property [dufuz] Remove custom XML_Util class in favor of using upstream XML_Util package as dependency RC1 Release Notes: * Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz] * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz] * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz] * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz] Alpha1 Release Notes: * Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz] * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz] * Implement Request #10825: Only display the "invalid or missing package file"-error if it makes sense [dufuz] * Implement Request #11170: script to generate Command/[command].xml [dufuz] * Implement Request #11176: improve channel ... has updated its protocols message [dufuz] * Implement Request #12706: pear list -a hard to read [dufuz] * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz] * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos] * Implement Request #13927: install-pear.php should have option to set www_dir [timj] * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz] * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz] - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate better what other package managers are doing. upgrade-all will still work as intended. * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz] - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for channel specific upgrades * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske] * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle] * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog] * Fix PHP Bug #47323: strotime warnings in make install [dufuz] * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz] * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj] * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit] * Fix Bug #13953: config-set/config-show with channel alias fail [cellog] * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz] * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz] * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz] * Fix Bug #14210: pear list -ia brings warnings [dufuz] * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz] * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz] * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos] * Fix Bug #14437: openbasedir warning when loading config [dufuz] * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske] * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali] * Fix Bug #14977: PEAR/Frontend.php doesn't require_once PEAR.php [dufuz] * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz] * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz] * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz] NOTE! Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment to migrate over to one of the alternatives that have ben provided: * PEAR_Common->downloadHttp (use PEAR_Downloader->downloadHttp instead) * PEAR_Common->infoFromTgzFile (use PEAR_PackageFile->fromTgzFile instead) * PEAR_Common->infoFromDescriptionFile (use PEAR_PackageFile->fromPackageFile instead) * PEAR_Common->infoFromString (use PEAR_PackageFile->fromXmlstring instead) * PEAR_Common->infoFromArray (use PEAR_PackageFile->fromAnyFile instead) * PEAR_Common->xmlFromInfo (use a PEAR_PackageFile_v* object's generator instead) * PEAR_Common->validatePackageInfo (use the validation of PEAR_PackageFile objects) * PEAR_Common->analyzeSourceCode (use a PEAR_PackageFile_v* object instead) * PEAR_Common->detectDependencies (use PEAR_Downloader_Package->detectDependencies instead) * PEAR_Common->buildProvidesArray (use PEAR_PackageFile_v1->_buildProvidesArray or PEAR_PackageFile_v2_Validator->_buildProvidesArray) PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls pear upgrade -f PEAR will allow people with lower versions to upgrade to this release but no guarantees will be made that it will work properly. Support for XML RPC channels has been dropped - The only ones that used it (pear.php.net and pecl.php.net) have used the REST interface for years now. SOAP support also removed as it was only proof of concept. Move codebase from the PHP License to New BSD 2 clause license 2009-04-15 1.8.1 1.8.1 stable stable New BSD License * Fix Bug #16099 PEAR crash on PHP4 (parse error) [dufuz] 2009-08-18 1.9.0RC1 1.9.0RC1 beta stable New BSD License * Implement Request #16213: add alias to list-channels output [dufuz] * Implement Request #16378: pear svntag [dufuz] * Implement Request #16386: PEAR_Config::remove() does not support specifying a channel [timj] * Implement Request #16396: package-dependencies should allow package names [dufuz] * Fix Bug #11181: pear requests channel.xml from main server instead from mirror [dufuz] * Fix Bug #14493: pear install --offline doesn't print out errors [dufuz] * Fix Bug #11348: pear package-dependencies isn't well explained [dufuz] * Fix Bug #16108: PEAR_PackageFile_Generator_v2 PHP4 parse error when running upgrade-all [dufuz] * Fix Bug #16113: Installing certain packages fails due incorrect encoding handling [dufuz] * Fix Bug #16122: PEAR RunTest failed to run as expected [dufuz] * Fix Bug #16366: compiling 5.2.10 leads to non-functioning pear [dufuz] * Fix Bug #16387: channel-logout does not support logging out from a non-default channel [timj] * Fix Bug #16444: Setting preferred mirror fails [dufuz] * Fix the shutdown functions where a index might not exist and thus raise a notice [derick] 2009-08-20 1.9.0RC2 1.9.0RC2 beta stable New BSD License * REST 1.4 file was occasionally being included but REST 1.4 is not intended for this release cycle [dufuz] 2009-08-21 1.9.0RC3 1.9.0RC3 beta stable New BSD License * Improved svntag support to handle packages like PEAR it self [dufuz] 2009-08-23 1.9.0RC4 1.9.0RC4 beta stable New BSD License * Fixed a problem where the original channel could not be set as a preferred_mirror again [dufuz] * Make sure channel aliases can't be made to start with - [dufuz] * Output issues with pear search [dufuz] * Fixed couple of stray notices [dufuz] 2009-09-03 1.9.0 1.9.0 stable stable New BSD License * Fix Bug #16547: The phar for PEAR installer uses ereg() which is deprecated [dufuz] 2010-05-26 1.9.1 1.9.1 stable stable New BSD License * svntag improvements, tag package files passed into the command and better directory checks [dufuz] * rely on Structures_Graph minimum version instead of recommended version [saltybeagle] * Fix Bug #12613: running go-pear.phar from C:\ fails [dufuz] * Fix Bug #14841: Installing pear into directory with space fails [dufuz] * Fix Bug #16644: pear.bat returns syntax error when parenthesis are in install path. [dufuz] [patch by bwaters (Bryan Waters)] * Fix Bug #16767: Use of Depreciated HTML Attributes in the Exception class [dufuz] [patch by fuhrysteve (Stephen J. Fuhry)] * Fix Bug #16864: "pear list-upgrades -i" issues E_WARNINGS [dufuz] [patch by rquadling (Richard Quadling)] * Fix Bug #17220: command `pear help` outputs to stderr instead of stdout [dufuz] * Fix Bug #17234: channel-discover adds port to HTTP Host header [dufuz] * Fix Bug #17292: Code Coverage in PEAR_RunTest does not work with namespaces [sebastian] * Fix Bug #17359: loadExtension() fails over missing dl() when used in multithread env [dufuz] * Fix Bug #17378: pear info $package fails if directory with that name exists [dufuz] 2011-02-28 1.9.2 1.9.2 stable stable New BSD License Important! This is a security fix release. The advisory can be found at http://pear.php.net/advisory-20110228.txt Bugs: * Fixed Bug #17463: Regression: On Windows, svntag [patch by doconnor] * Fixed Bug #17641: pecl-list doesn't sort packages by name [dufuz] * Fixed Bug #17781: invalid argument warning on foreach due to an empty optional dependencie [dufuz] * Fixed Bug #17801: PEAR run-tests wrongly detects php-cgi [patch by David Jean Louis (izi)] * Fixed Bug #17839: pear svntag does not tag package.xml file [dufuz] * Fixed Bug #17986: PEAR Installer cannot handle files moved between packages [dufuz] * Fixed Bug #17997: Strange output if directories are not writeable [dufuz] * Fixed Bug #18001: PEAR/RunTest coverage fails [dufuz] * Fixed Bug #18056 [SECURITY]: Symlink attack in PEAR install [dufuz] * Fixed Bug #18218: "pear package" does not allow the use of late static binding [dufuz and Christer Edvartsen] * Fixed Bug #18238: Wrong return code from "pear help" [till] * Fixed Bug #18308: Broken error message about missing channel validator [yunosh] This feature is implemented as a result of #18056 * Implemented Request #16648: Use TMPDIR for builds instead of /var/tmp [dufuz] 2011-06-04 1.9.3 1.9.2 stable stable New BSD License * Fixed Bug #17744: Empty changelog causes fatal error in setChangelogentry [dufuz] * Fixed Bug #18340: raiseErro typo [doconnor] * Fixed Bug #18349: package.xml version not recognized when single quoted [dufuz] * Fixed Bug #18364: date.timezone errors for sh/bat files when TZ is not set in php.ini [dufuz] * Fixed Bug #18388: Parentheses error in REST.php line 232 [dufuz] * Fixed Bug #18428: invalid preg_match patterns [glen] * Fixed Bug #18486: REST/10.php does not check error condition [dufuz] * Fixed a problem in RunTest and code coverage. Correctly register the code coverage shutdown function in case we are inside a namespace. [sebastian] * Fixed a bug with extensions not providing their config.m4 and co in the root directory of their pecl package but rather in a sub directory, such as xhprof. [dufuz] 2011-07-06 1.9.4 1.9.4 stable stable New BSD License Bug Fixes: * Bug #17350: "pear install --force" doesn't uninstall files from previous pkg versions [dufuz] * Bug #18362: A whitespace TEMP_DIR path breaks install/upgrade functionality [dufuz] * Bug #18440: bad tmp folder path on install : Unable to create path for C:/Program/tmp [dufuz] * Bug #18581: "config-get -c" not returning channel's configuration when using alias [dufuz] * Bug #18639: regression: installing xdebug fails most likely due to another fix [dufuz] Features * All System (the class) functions can now take in spaced paths as long as they are surrounded in quotes. Prior to this it was possible to do that by passing all values in as an array (by product of #18362, #18440) [dufuz] 2014-06-27 1.9.5dev1 1.9.5 devel devel New BSD License Bug fixes: * Fix bug #18343: Entities in file names decoded during packaging [cweiske] * Fix bug #18665: pecl extensions not enabled in empty php.ini files [Louis Opter] * Fix bug #18834: Do not truncate cache file if it is a symlink [avb] * Fix bug #18892: Parse error in Installer.php [ashnazg] * Fix bug #19482: fix pearcmd for include paths with trailing backslash [cweiske] * Fix bug #19793: PHP Notice about ob_end_clean() [cweiske] * Fix bug #20086: Invalid regexp in PEAR_Builder::build() [avb] * Fix bug #20203: split content-type and get real mime type [Samu Voutilainen] * Fix bug #20283: use full path for "zend_extension=..." [cweiske] * Fix bug #20284: Reset interpreter before running --CLEAN-- section php-cgi run [Mats Lindh] * Fix bug #20285: fix spelling mistakes [Veres Lajos] * Fix bug #20286: Support access of static variables on objects in validator [cweiske] * Fix bug #20321: Correctly detect name of current user during installation [cweiske] * Fix bug: let pear run-tests fail when there are failed tests [cweiske] * Prepare a test for bug #18056 / bug #18834 [avb] 2014-07-12 1.9.5 1.9.5 stable stable New BSD License No changes since 1.9.5.dev1. Bug fixes in 1.9.5.dev1: * Fix bug #18343: Entities in file names decoded during packaging [cweiske] * Fix bug #18665: pecl extensions not enabled in empty php.ini files [Louis Opter] * Fix bug #18834: Do not truncate cache file if it is a symlink [avb] * Fix bug #18892: Parse error in Installer.php [ashnazg] * Fix bug #19482: fix pearcmd for include paths with trailing backslash [cweiske] * Fix bug #19793: PHP Notice about ob_end_clean() [cweiske] * Fix bug #20086: Invalid regexp in PEAR_Builder::build() [avb] * Fix bug #20203: split content-type and get real mime type [Samu Voutilainen] * Fix bug #20283: use full path for "zend_extension=..." [cweiske] * Fix bug #20284: Reset interpreter before running --CLEAN-- section php-cgi run [Mats Lindh] * Fix bug #20285: fix spelling mistakes [Veres Lajos] * Fix bug #20286: Support access of static variables on objects in validator [cweiske] * Fix bug #20321: Correctly detect name of current user during installation [cweiske] * Fix bug: let pear run-tests fail when there are failed tests [cweiske] * Prepare a test for bug #18056 / bug #18834 [avb] 2015-07-25 1.10.0dev1 1.10.0 devel devel New BSD License * Implement #20488: Add support for PHP 7 [cweiske] * Drop support for PHP 4 and 5.0 - 5.3 [cweiske] * Remove deprecated methods [cweiske] * Fix static warnings [cweiske] * Fix #17045: avoid overwriting include path [glen] * Fix #17399: "pear help" doesn't mention the "version" command [kguest] * Add --showdiff to "pear run-tests" to print diff for failed tests [tyrael] * Fix channel.xml downloading from https if it did not change [cweiske] 2015-07-31 1.10.0dev2 1.10.0 devel devel New BSD License * Fix #18638 and #18405: Make PEAR::loadExtension static [cweiske] * Fix #20319: allow pear to work when cache_dir is not writable [remicollet] * Implement #20333: New role=man for man pages [bjori] * Implement #20334: add "metadata_dir" configuration option [remicollet] * Add long option names to install-pear.php [remicollet] 2015-09-28 1.10.0dev3 1.10.0 devel devel New BSD License * Fix #20507: pear list-upgrades does not take PHP version into account [cweiske] * Fix #20927: Use correct php-config [cweiske] * Fix #20946: PEAR_Builder::log() declaration [remicollet] * Remove PEAR/ErrorStack5.php [cweiske] 2015-10-07 1.10.0 1.10.0 stable stable New BSD License No changes since version 1.10.0dev3. Changes since version 1.9.5: * Implement #20488: Add support for PHP 7 [cweiske] * Drop support for PHP 4 and 5.0 - 5.3 [cweiske] * Remove deprecated methods [cweiske] * Add --showdiff to "pear run-tests" to print diff for failed tests [tyrael] * Implement #20333: New role=man for man pages [bjori] * Implement #20334: add "metadata_dir" configuration option [remicollet] * Add long option names to install-pear.php [remicollet] * Remove PEAR/ErrorStack5.php [cweiske] * Fix #17045: avoid overwriting include path [glen] * Fix #17399: "pear help" doesn't mention the "version" command [kguest] * Fix #18638 and #18405: Make PEAR::loadExtension static [cweiske] * Fix #20319: allow pear to work when cache_dir is not writable [remicollet] * Fix #20507: pear list-upgrades does not take PHP version into account [cweiske] * Fix #20927: Use correct php-config [cweiske] * Fix #20946: PEAR_Builder::log() declaration [remicollet] * Fix channel.xml downloading from https if it did not change [cweiske] * Fix static warnings [cweiske] 2015-10-17 1.10.1 1.10.1 stable stable New BSD License * Fix bug #20959: Crash on channel discovery with channel.xml redirect [cweiske] * Fix bug #20968: Incorrect call to __construct() from PEAR() [edlman] * Add legacy constructor for PEAR_Error for backwards compatibility [cweiske] 2017-02-28 1.10.2 1.10.1 stable stable New BSD License * Fix Bug #4426: PEAR_Autoloader __call() must take only 2 arguments [kna] * Fix Bug #20989: fatal error/bug in the postinstallscript task [kguest] * Fix Bug #20991: Strict Standards: startSession and run methods in PEAR_Task_Postinstallscript [kguest] * Fix Bug #21001: PEAR_ERROR_DIE exit code is 0 [danielc] * Pull Request #52: Channel's _lastmodified is an int and not a string [sathieu] * Pull Request #53: Add proper HTTPS proxy support through the CONNECT verb [youknow0] * Pull Request #58: Make method signatures compatible. [yunosh] 2017-02-28 1.10.3 1.10.1 stable stable New BSD License * Bug #21188: Class 'PEAR_Proxy' not found 2017-04-25 1.10.4 1.10.1 stable stable New BSD License * Bug #18102: pear install does not fail on error 2017-06-27 1.10.5 1.10.1 stable stable New BSD License * Bug #21222: PHP 7.2 compatibility: Upgrade to Archive_Tar 1.4.3 needed 2018-08-22 1.10.6 1.10.1 stable stable New BSD License * PR #70: Fix notice undefined variable metadata_dir * PR #71: fix Warning: count(): Parameter must be an array or an object * PR #74: Bug #23744 Remove is_executable check * Bug #23744: The is_executable check in the Which method when run on Windows is unnecessary * PR #75: Migrate old while(list() = each()) constructs to foreach * PR #76: Fix PHP Warning: "continue" targeting switch is equivalent to "break" * PR #77: proxy server auth * PR #72: Correctly authenticate at proxy server * PR #78: array or Countable error in 7.2 2018-12-05 1.10.7 1.10.1 stable stable New BSD License * PR #79: Prevent Unable to find the wrapper "channel" Warning * PR #80: fix Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2" * PR #81: Add flags to PECL shell script for shared extensions 2019-02-07 1.10.8 1.10.1 stable stable New BSD License * PR #83: Drop track_errors from options * PR #84: Fix PHP 8 compatibility issues 2019-03-13 1.10.9 1.10.1 stable stable New BSD License * PR #85: Fixes static calls for PHP 8 * PR #86: Adjust silencing check for PHP 8 * PR #87: Comparison fixes * PR #88: Only add bin_dir to PATH if not already there (fixes PHP Bug #75852) 2019-11-19 1.10.10 1.10.1 stable stable New BSD License * PR #89: Fix scripts/* include paths * PR #90: Non-interactive configureoption answers * PR #91: Added missing preg quote * PR #92: handle "lib64" case for glibc detection * PR #93: Fix PHP Notice: Trying to access array offset on value of type bool with 7.4 * PR #94: Updated logic in useLocalCache to reuse getCacheId * PR #95: Fix manpage warning * PR #96: Implement the SOURCE_DATE_EPOCH specification * PR #97: Fix PHP 7.4 deprecation: array/string curly braces access * PR #98: Fix use of null/false as array * PR #99: Fix Travis builds on PHP 5.4 and 5.5 * PR #100: Honor PHP temp directory config * PR #101: Fix documentation: the `--force` is required 2020-04-10 1.10.11 1.10.1 stable stable New BSD License * PR #102: Fix logging error for urls not in cache * PR #103: Fix undefined constant name * PR #105: Sort list of packages * PR #106: Update REST.php * PR #107: Update .travis.yml to include PHP 7.4 * PR #108: Remove unneeded code 2020-04-19 1.10.12 1.10.1 stable stable New BSD License * adjust dependencies based on new releases 2021-08-10 1.10.13 1.10.1 stable stable New BSD License * PR #114: unsupported protocol - use --force to continue * PR #117: Add $this operator to _determineIfPowerpc calls 2023-11-26 1.10.14 1.10.1 stable stable New BSD License * PR #112: Put glue and pieces parameters to implode in correct order for PHP 7.4+ * PR #121: Fix PHP bug 81653: Typo in install-pear-nozlib.phar * PR #122: add %S EXPECTF capability * PR #124: Fix: Creation of dynamic property PEAR_Error::$callback is deprecated * PR #125: Fixed extension loaded check for pecl binaries * PR #126: Remove -n option from pecl.bat for shared extensions * PR #127: fix Using ${var} in strings is deprecated * PR #128: fix lingering license references to PHP license * PR #129: Exclude tests from composer classmap * PR #131: fix private lastError name 2024-03-09 1.10.15 1.10.1 stable stable New BSD License * PR #132: cleanup uneeded test * PR #135: Fix PHP Deprecated: Calling get_class() without arguments 2024-11-24 1.10.16 1.10.1 stable stable New BSD License * PR #141: Fix bug #27796: "Array to string" conversion warnings on installs/other actions * PR #145: Never reference E_STRICT on PHP 8.4+ * PR #147: Fix tests 8.1+ 2025-12-14 1.10.17 1.10.1 stable stable New BSD License * PR #152: Fix HTTP chunked encoding handling * PR #153: fix composer.json: typo in replace for pear_exception package * PR #154: switch to https by default * PR #156: Throw new Error instead of E_USER_ERROR on PHP 7.0+ * PR #159: update tests for https-first behavior 2026-01-25 1.10.18 1.10.1 stable stable New BSD License * PR #164: don't use report_memleaks with 8.5+ PK!#ybbpkgxml/Structures_Graph.xmlnu[ Structures_Graph pear.php.net Graph datastructure manipulation library Structures_Graph is a package for creating and manipulating graph datastructures. It allows building of directed and undirected graphs, with data and metadata stored in nodes. The library provides functions for graph traversing as well as for characteristic extraction from the graph topology. Sérgio Carvalho sergiosgc sergio.carvalho@portugalmail.com yes Brett Bieber saltybeagle brett.bieber@gmail.com yes 2024-06-02 1.2.0 1.2.0 stable stable LGPL-3.0+ * update composer info (adds PHP/PEAR deps) * update phpunit tests * composer shows wrong license PEAR pear.php.net 1.5.0RC3 1.9.1 5.3.0 1.4.3 1.0.2 1.0.0 stable stable 2007-01-07 LGPL - Bug #9682 only variables can be returned by reference - fix Bug #9661 notice in Structures_Graph_Manipulator_Topological::sort() 1.0.3 1.0.3 stable stable 2009-10-11 LGPL License Bugfix Release: Version 1.0.3 is functionally equivalent to 1.0.2 but with an updated package.xml file. * Correct invalid md5 sum preventing installation with pyrus [saltybeagle] * Add compatible tag for PEAR 1.5.0RC3-1.9.0 [saltybeagle] * Update package.xml 1.0.4 1.0.3 stable stable 2010-10-25 LGPL License Bugfix Release: * Bug #17108 BasicGraph::test_directed_degree fails on PHP 5 [clockwerx] 1.1.0 1.1.0 stable stable 2015-02-26 LGPL-3.0+ * Set minimum PHP version to 5.3 * Fix bug #19367: Incorrect FSF address in LICENSE * Change license from LGPL-2.1+ to LGPL-3.0+ 1.1.1 1.1.0 stable stable 2015-07-20 LGPL-3.0+ * Fix deprecated constructor warning on PHP 7 [cweiske] 1.2.0 1.2.0 stable stable 2024-06-02 LGPL-3.0+ * update composer info (adds PHP/PEAR deps) * update phpunit tests * composer shows wrong license PK!7pKKpkgxml/XML_Util.xmlnu[ XML_Util pear.php.net XML utility class Selection of methods that are often needed when working with XML documents. Functionality includes creating of attribute lists from arrays, creation of tags, validation of XML names and more. Chuck Burgess ashnazg ashnazg@php.net yes Stephan Schmidt schst schst@php-tools.net no Davey Shafik davey davey@php.net no 2020-04-19 1.4.5 1.4.0 stable stable BSD License * PR #12: fix Trying to access array offset on value of type int 5.4.0 1.9.0 pcre 0.1 0.1 stable stable 2003-08-01 PHP License inital release 0.1.1 0.1.1 stable stable 2003-08-02 PHP License bugfix: removed bug in createTagFromArray 0.2 0.2 stable stable 2003-08-12 PHP License added XML_Util::getDocTypeDeclaration() 0.2.1 0.2.1 stable stable 2003-09-05 PHP License fixed bug with zero as tag content in createTagFromArray and createTag 0.3 0.3 stable stable 2003-09-12 PHP License added createStartElement() and createEndElement() 0.4 0.4 stable stable 2003-09-21 PHP License added createCDataSection(), added support for CData sections in createTag* methods, fixed bug #23, fixed bug in splitQualifiedName() 0.5 0.5 stable stable 2003-09-23 PHP License added support for multiline attributes in attributesToString(), createTag*() and createStartElement (requested by Yavor Shahpasov for XML_Serializer), added createComment 0.5.1 0.5.1 stable stable 2003-09-26 PHP License added default namespace parameter (optional) in splitQualifiedName() (requested by Sebastian Bergmann) 0.5.2 0.5.2 stable stable 2003-11-22 PHP License now creates XHTML compliant empty tags (Davey), minor whitespace fixes (Davey) 0.6.0beta1 0.6.0beta1 beta beta 2004-05-24 PHP License - Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey) - added optional parameter to replaceEntities() to define the set of entities to replace - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann) - allowed second parameter to XML_Util::attributesToString() to be an array containing options (easier to use, if you only need to set the last parameter) - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error 0.6.0 0.6.0 stable stable 2004-06-07 PHP License - Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey) - added optional parameter to replaceEntities() to define the set of entities to replace - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann) - allowed second parameter to XML_Util::attributesToString() to be an array containing options (easier to use, if you only need to set the last parameter) - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error 0.6.1 0.6.1 stable stable 2004-10-28 PHP License - Added check for tag name (either as local part or qualified name) in createTagFromArray() (bug #1083) 1.0.0 1.0.0 stable stable 2004-10-28 PHP License - Added reverseEntities() (request #2639) 1.1.0 1.1.0 stable stable 2004-11-19 PHP License - Added collapseEmptyTags (patch by Sebastian Bergmann and Thomas Duffey) 1.1.1 1.1.1 stable stable 2004-12-23 PHP License - fixed bug in replaceEntities() and reverseEntities() in conjunction with XML_UTIL_ENTITIES_HTML - createTag() and createTagFromArray() now accept XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML, XML_UTIL_ENTITIES_NONE and XML_UTIL_CDATA_SECTION as $replaceEntities parameter 1.1.2 1.1.2 stable stable 2006-12-01 PHP License - fixed bug #5419: isValidName() now checks for character classes - implemented request #8196: added optional parameter to influence array sorting to createTag() createTagFromArray() and createStartElement() 1.1.4 1.1.4 stable stable 2006-12-16 PHP License - Fixed bug #9561: Not allowing underscores in middle of tags 1.2.0a1 1.2.0 alpha alpha 2008-05-04 BSD License Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|ja.doma] 1.2.0a2 1.2.0 alpha alpha 2008-05-22 BSD License Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry] Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry] -- (this fix differs from the one in v1.2.0a1) 1.2.0RC1 1.2.0 beta beta 2008-07-12 BSD License Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry] Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry] -- (this fix differs from the one in v1.2.0a1) 1.2.0 1.2.0 stable stable 2008-07-26 BSD License Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry] Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry] -- (this fix differs from the one in v1.2.0a1) 1.2.1 1.2.0 stable stable 2011-12-31 BSD License Fixed Bug #14760: Bug in getDocTypeDeclaration() [ashnazg|fpospisil] 1.2.2 1.2.0 stable stable 2014-06-07 BSD License QA release Bug #18343 Entities in file names decoded during packaging Bug #19174 upgrade PHPUnit require statements & other fixes (for PEAR QA Team) Request #19750 examples/example.php encoding 1.2.3 1.2.0 stable stable 2014-06-07 BSD License Bug #20293 Broken installation for 1.2.2 1.3.0 1.3.0 stable stable 2015-02-27 BSD License * Set minimum PHP version to 5.3.0 * Mark static methods with static keyword 1.4.0 1.4.0 stable stable 2017-02-03 BSD License * Set minimum PHP version to 5.4.0 * Set minimum PEAR version to 1.10.1 * Adds a new XML_UTIL_COLLAPSE_NONE option for preventing empty tag collapsing. * Request #15467 CDATA sections and blank nodes 1.4.1 1.4.0 stable stable 2017-02-07 BSD License * Bug #21177 XML_Util::collapseEmptyTags() can return NULL 1.4.2 1.4.0 stable stable 2017-02-22 BSD License * Bug #21184 Collapse issue 1.4.3 1.4.0 stable stable 2017-06-28 BSD License * Decrease minimum PEAR version to 1.9.0 to allow PEAR upgrades 1.4.4 1.4.0 stable stable 2019-12-05 BSD License * PR #11: fix phplint warning 1.4.5 1.4.0 stable stable 2020-04-19 BSD License * PR #12: fix Trying to access array offset on value of type int PK!W^pkgxml/Console_Getopt.xmlnu[ Console_Getopt pear.php.net Command-line option parser This is a PHP implementation of "getopt" supporting both short and long options. Andrei Zmievski andrei andrei@php.net no Stig Bakken ssb stig@php.net no Greg Beaver cellog cellog@php.net no 2019-11-20 1.4.3 1.4.0 stable stable BSD-2-Clause * PR #4: Fix PHP 7.4 deprecation: array/string curly braces access * PR #5: fix phplint warnings PEAR pear.php.net 1.4.0 1.999.999 5.4.0 1.8.0 2019-11-20 1.4.3 1.4.0 stable stable BSD-2-Clause * PR #4: Fix PHP 7.4 deprecation: array/string curly braces access * PR #5: fix phplint warnings 2019-02-06 1.4.2 1.4.0 stable stable BSD-2-Clause * Remove use of each(), which is removed in PHP 8 2015-07-20 1.4.1 1.4.0 stable stable BSD-2-Clause * Fix unit test on PHP 7 [cweiske] 2015-02-22 1.4.0 1.4.0 stable stable BSD-2-Clause * Change license to BSD-2-Clause * Set minimum PHP version to 5.4.0 * Mark static methods with "static" keyword 2011-03-07 1.3.1 1.3.0 stable stable PHP License * Change the minimum PEAR installer dep to be lower 2010-12-11 1.3.0 1.3.0 stable stable PHP License * Implement Request #13140: [PATCH] to skip unknown parameters. [patch by rquadling, improved on by dufuz] 2007-06-12 1.2.3 1.2.1 stable stable PHP License * fix Bug #11068: No way to read plain "-" option [cardoe] 1.2.2 1.2.1 stable stable 2007-02-17 PHP License * fix Bug #4475: An ambiguous error occurred when specifying similar longoption name. * fix Bug #10055: Not failing properly on short options missing required values 1.2.1 1.2.1 stable stable 2006-12-08 PHP License Fixed bugs #4448 (Long parameter values truncated with longoption parameter) and #7444 (Trailing spaces after php closing tag) 1.2 1.2 stable stable 2003-12-11 PHP License Fix to preserve BC with 1.0 and allow correct behaviour for new users 1.0 1.0 stable stable 2002-09-13 PHP License Stable release 0.11 0.11 beta beta 2002-05-26 PHP License POSIX getopt compatibility fix: treat first element of args array as command name 0.10 0.10 beta beta 2002-05-12 PHP License Packaging fix 0.9 0.9 beta beta 2002-05-12 PHP License Initial release PK!a pkgxml/alt-php85-vld.xmlnu[ vld pecl.php.net Provides functionality to dump the internal representation of PHP scripts The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. Derick Rethans derick derick@xdebug.org yes 2022-09-16 0.18.0 0.18.0 beta beta BSD style - Add support for new PHP 8.1 opcodes with examples - Add support for PHP 8.2 (by removing JMPZNZ opcode) 7.0.0 1.4.0b1 vld PK!a pkgxml/alt-php84-vld.xmlnu[ vld pecl.php.net Provides functionality to dump the internal representation of PHP scripts The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. Derick Rethans derick derick@xdebug.org yes 2022-09-16 0.18.0 0.18.0 beta beta BSD style - Add support for new PHP 8.1 opcodes with examples - Add support for PHP 8.2 (by removing JMPZNZ opcode) 7.0.0 1.4.0b1 vld PK!a pkgxml/alt-php81-vld.xmlnu[ vld pecl.php.net Provides functionality to dump the internal representation of PHP scripts The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. Derick Rethans derick derick@xdebug.org yes 2022-09-16 0.18.0 0.18.0 beta beta BSD style - Add support for new PHP 8.1 opcodes with examples - Add support for PHP 8.2 (by removing JMPZNZ opcode) 7.0.0 1.4.0b1 vld PK!{ Mail/null.phpnu[ * @copyright 2010-2017 Phil Kernick * @license http://opensource.org/licenses/BSD-3-Clause New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/Mail/ */ /** * Null implementation of the PEAR Mail:: interface. * @access public * @package Mail * @version $Revision$ */ class Mail_null extends Mail { /** * Implements Mail_null::send() function. Silently discards all * mail. * * @param mixed $recipients Either a comma-seperated list of recipients * (RFC822 compliant), or an array of recipients, * each RFC822 valid. This may contain recipients not * specified in the headers, for Bcc:, resending * messages, etc. * * @param array $headers The array of headers to send with the mail, in an * associative array, where the array key is the * header name (ie, 'Subject'), and the array value * is the header value (ie, 'test'). The header * produced from those values would be 'Subject: * test'. * * @param string $body The full text of the message body, including any * Mime parts, etc. * * @return mixed Returns true on success, or a PEAR_Error * containing a descriptive error message on * failure. */ public function send($recipients, $headers, $body) { return true; } } PK!E@%>>Mail/sendmail.phpnu[ * @author Chuck Hagenbuch * @copyright 2010-2017 Chuck Hagenbuch * @license http://opensource.org/licenses/BSD-3-Clause New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/Mail/ */ /** * Sendmail implementation of the PEAR Mail:: interface. * @access public * @package Mail * @version $Revision$ */ class Mail_sendmail extends Mail { /** * The location of the sendmail or sendmail wrapper binary on the * filesystem. * @var string */ var $sendmail_path = '/usr/sbin/sendmail'; /** * Any extra command-line parameters to pass to the sendmail or * sendmail wrapper binary. * @var string */ var $sendmail_args = '-i'; /** * Constructor. * * Instantiates a new Mail_sendmail:: object based on the parameters * passed in. It looks for the following parameters: * sendmail_path The location of the sendmail binary on the * filesystem. Defaults to '/usr/sbin/sendmail'. * * sendmail_args Any extra parameters to pass to the sendmail * or sendmail wrapper binary. * * If a parameter is present in the $params array, it replaces the * default. * * @param array $params Hash containing any parameters different from the * defaults. */ public function __construct($params) { if (isset($params['sendmail_path'])) { $this->sendmail_path = $params['sendmail_path']; } if (isset($params['sendmail_args'])) { $this->sendmail_args = $params['sendmail_args']; } /* * Because we need to pass message headers to the sendmail program on * the commandline, we can't guarantee the use of the standard "\r\n" * separator. Instead, we use the system's native line separator. */ if (defined('PHP_EOL')) { $this->sep = PHP_EOL; } else { $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n"; } } /** * Implements Mail::send() function using the sendmail * command-line binary. * * @param mixed $recipients Either a comma-seperated list of recipients * (RFC822 compliant), or an array of recipients, * each RFC822 valid. This may contain recipients not * specified in the headers, for Bcc:, resending * messages, etc. * * @param array $headers The array of headers to send with the mail, in an * associative array, where the array key is the * header name (ie, 'Subject'), and the array value * is the header value (ie, 'test'). The header * produced from those values would be 'Subject: * test'. * * @param string $body The full text of the message body, including any * Mime parts, etc. * * @return mixed Returns true on success, or a PEAR_Error * containing a descriptive error message on * failure. */ public function send($recipients, $headers, $body) { if (!is_array($headers)) { return PEAR::raiseError('$headers must be an array'); } $result = $this->_sanitizeHeaders($headers); if (is_a($result, 'PEAR_Error')) { return $result; } $recipients = $this->parseRecipients($recipients); if (is_a($recipients, 'PEAR_Error')) { return $recipients; } $recipients = implode(' ', array_map('escapeshellarg', $recipients)); $headerElements = $this->prepareHeaders($headers); if (is_a($headerElements, 'PEAR_Error')) { return $headerElements; } list($from, $text_headers) = $headerElements; /* Since few MTAs are going to allow this header to be forged * unless it's in the MAIL FROM: exchange, we'll use * Return-Path instead of From: if it's set. */ if (!empty($headers['Return-Path'])) { $from = $headers['Return-Path']; } if (!isset($from)) { return PEAR::raiseError('No from address given.'); } elseif (strpos($from, ' ') !== false || strpos($from, ';') !== false || strpos($from, '&') !== false || strpos($from, '`') !== false) { return PEAR::raiseError('From address specified with dangerous characters.'); } $from = escapeshellarg($from); // Security bug #16200 $mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w'); if (!$mail) { return PEAR::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.'); } // Write the headers following by two newlines: one to end the headers // section and a second to separate the headers block from the body. fputs($mail, $text_headers . $this->sep . $this->sep); fputs($mail, $body); $result = pclose($mail); if (version_compare(phpversion(), '4.2.3') == -1) { // With older php versions, we need to shift the pclose // result to get the exit code. $result = $result >> 8 & 0xFF; } if ($result != 0) { return PEAR::raiseError('sendmail returned error code ' . $result, $result); } return true; } } PK!A~{{Mail/RFC822.phpnu[ * @author Chuck Hagenbuch * @author Chuck Hagenbuch * @version $Revision$ * @license BSD * @package Mail */ class Mail_RFC822 { /** * The address being parsed by the RFC822 object. * @var string $address */ var $address = ''; /** * The default domain to use for unqualified addresses. * @var string $default_domain */ var $default_domain = 'localhost'; /** * Should we return a nested array showing groups, or flatten everything? * @var boolean $nestGroups */ var $nestGroups = true; /** * Whether or not to validate atoms for non-ascii characters. * @var boolean $validate */ var $validate = true; /** * The array of raw addresses built up as we parse. * @var array $addresses */ var $addresses = array(); /** * The final array of parsed address information that we build up. * @var array $structure */ var $structure = array(); /** * The current error message, if any. * @var string $error */ var $error = null; /** * An internal counter/pointer. * @var integer $index */ var $index = null; /** * The number of groups that have been found in the address list. * @var integer $num_groups * @access public */ var $num_groups = 0; /** * A variable so that we can tell whether or not we're inside a * Mail_RFC822 object. * @var boolean $mailRFC822 */ var $mailRFC822 = true; /** * A limit after which processing stops * @var int $limit */ var $limit = null; /** * Sets up the object. The address must either be set here or when * calling parseAddressList(). One or the other. * * @param string $address The address(es) to validate. * @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost. * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. * * @return object Mail_RFC822 A new Mail_RFC822 object. */ public function __construct($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) { if (isset($address)) $this->address = $address; if (isset($default_domain)) $this->default_domain = $default_domain; if (isset($nest_groups)) $this->nestGroups = $nest_groups; if (isset($validate)) $this->validate = $validate; if (isset($limit)) $this->limit = $limit; } /** * Starts the whole process. The address must either be set here * or when creating the object. One or the other. * * @param string $address The address(es) to validate. * @param string $default_domain Default domain/host etc. * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. * * @return array A structured array of addresses. */ public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) { if (!isset($this) || !isset($this->mailRFC822)) { $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit); return $obj->parseAddressList(); } if (isset($address)) $this->address = $address; if (isset($default_domain)) $this->default_domain = $default_domain; if (isset($nest_groups)) $this->nestGroups = $nest_groups; if (isset($validate)) $this->validate = $validate; if (isset($limit)) $this->limit = $limit; $this->structure = array(); $this->addresses = array(); $this->error = null; $this->index = null; // Unfold any long lines in $this->address. $this->address = preg_replace('/\r?\n/', "\r\n", $this->address); $this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address); while ($this->address = $this->_splitAddresses($this->address)); if ($this->address === false || isset($this->error)) { require_once 'PEAR.php'; return PEAR::raiseError($this->error); } // Validate each address individually. If we encounter an invalid // address, stop iterating and return an error immediately. foreach ($this->addresses as $address) { $valid = $this->_validateAddress($address); if ($valid === false || isset($this->error)) { require_once 'PEAR.php'; return PEAR::raiseError($this->error); } if (!$this->nestGroups) { $this->structure = array_merge($this->structure, $valid); } else { $this->structure[] = $valid; } } return $this->structure; } /** * Splits an address into separate addresses. * * @param string $address The addresses to split. * @return boolean Success or failure. */ protected function _splitAddresses($address) { if (!empty($this->limit) && count($this->addresses) == $this->limit) { return ''; } if ($this->_isGroup($address) && !isset($this->error)) { $split_char = ';'; $is_group = true; } elseif (!isset($this->error)) { $split_char = ','; $is_group = false; } elseif (isset($this->error)) { return false; } // Split the string based on the above ten or so lines. $parts = explode($split_char, $address); $string = $this->_splitCheck($parts, $split_char); // If a group... if ($is_group) { // If $string does not contain a colon outside of // brackets/quotes etc then something's fubar. // First check there's a colon at all: if (strpos($string, ':') === false) { $this->error = 'Invalid address: ' . $string; return false; } // Now check it's outside of brackets/quotes: if (!$this->_splitCheck(explode(':', $string), ':')) { return false; } // We must have a group at this point, so increase the counter: $this->num_groups++; } // $string now contains the first full address/group. // Add to the addresses array. $this->addresses[] = array( 'address' => trim($string), 'group' => $is_group ); // Remove the now stored address from the initial line, the +1 // is to account for the explode character. $address = trim(substr($address, strlen($string) + 1)); // If the next char is a comma and this was a group, then // there are more addresses, otherwise, if there are any more // chars, then there is another address. if ($is_group && substr($address, 0, 1) == ','){ $address = trim(substr($address, 1)); return $address; } elseif (strlen($address) > 0) { return $address; } else { return ''; } // If you got here then something's off return false; } /** * Checks for a group at the start of the string. * * @param string $address The address to check. * @return boolean Whether or not there is a group at the start of the string. */ protected function _isGroup($address) { // First comma not in quotes, angles or escaped: $parts = explode(',', $address); $string = $this->_splitCheck($parts, ','); // Now we have the first address, we can reliably check for a // group by searching for a colon that's not escaped or in // quotes or angle brackets. if (count($parts = explode(':', $string)) > 1) { $string2 = $this->_splitCheck($parts, ':'); return ($string2 !== $string); } else { return false; } } /** * A common function that will check an exploded string. * * @param array $parts The exloded string. * @param string $char The char that was exploded on. * @return mixed False if the string contains unclosed quotes/brackets, or the string on success. */ protected function _splitCheck($parts, $char) { $string = $parts[0]; for ($i = 0; $i < count($parts); $i++) { if ($this->_hasUnclosedQuotes($string) || $this->_hasUnclosedBrackets($string, '<>') || $this->_hasUnclosedBrackets($string, '[]') || $this->_hasUnclosedBrackets($string, '()') || substr($string, -1) == '\\') { if (isset($parts[$i + 1])) { $string = $string . $char . $parts[$i + 1]; } else { $this->error = 'Invalid address spec. Unclosed bracket or quotes'; return false; } } else { $this->index = $i; break; } } return $string; } /** * Checks if a string has unclosed quotes or not. * * @param string $string The string to check. * @return boolean True if there are unclosed quotes inside the string, * false otherwise. */ protected function _hasUnclosedQuotes($string) { $string = trim($string); $iMax = strlen($string); $in_quote = false; $i = $slashes = 0; for (; $i < $iMax; ++$i) { switch ($string[$i]) { case '\\': ++$slashes; break; case '"': if ($slashes % 2 == 0) { $in_quote = !$in_quote; } // Fall through to default action below. default: $slashes = 0; break; } } return $in_quote; } /** * Checks if a string has an unclosed brackets or not. IMPORTANT: * This function handles both angle brackets and square brackets; * * @param string $string The string to check. * @param string $chars The characters to check for. * @return boolean True if there are unclosed brackets inside the string, false otherwise. */ protected function _hasUnclosedBrackets($string, $chars) { $num_angle_start = substr_count($string, $chars[0]); $num_angle_end = substr_count($string, $chars[1]); $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]); $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]); if ($num_angle_start < $num_angle_end) { $this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')'; return false; } else { return ($num_angle_start > $num_angle_end); } } /** * Sub function that is used only by hasUnclosedBrackets(). * * @param string $string The string to check. * @param integer &$num The number of occurences. * @param string $char The character to count. * @return integer The number of occurences of $char in $string, adjusted for backslashes. */ protected function _hasUnclosedBracketsSub($string, &$num, $char) { $parts = explode($char, $string); for ($i = 0; $i < count($parts); $i++){ if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i])) $num--; if (isset($parts[$i + 1])) $parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1]; } return $num; } /** * Function to begin checking the address. * * @param string $address The address to validate. * @return mixed False on failure, or a structured array of address information on success. */ protected function _validateAddress($address) { $is_group = false; $addresses = array(); if ($address['group']) { $is_group = true; // Get the group part of the name $parts = explode(':', $address['address']); $groupname = $this->_splitCheck($parts, ':'); $structure = array(); // And validate the group part of the name. if (!$this->_validatePhrase($groupname)){ $this->error = 'Group name did not validate.'; return false; } else { // Don't include groups if we are not nesting // them. This avoids returning invalid addresses. if ($this->nestGroups) { $structure = new stdClass; $structure->groupname = $groupname; } } $address['address'] = ltrim(substr($address['address'], strlen($groupname . ':'))); } // If a group then split on comma and put into an array. // Otherwise, Just put the whole address in an array. if ($is_group) { while (strlen($address['address']) > 0) { $parts = explode(',', $address['address']); $addresses[] = $this->_splitCheck($parts, ','); $address['address'] = trim(substr($address['address'], strlen(end($addresses) . ','))); } } else { $addresses[] = $address['address']; } // Trim the whitespace from all of the address strings. array_map('trim', $addresses); // Validate each mailbox. // Format could be one of: name // geezer@domain.com // geezer // ... or any other format valid by RFC 822. for ($i = 0; $i < count($addresses); $i++) { if (!$this->validateMailbox($addresses[$i])) { if (empty($this->error)) { $this->error = 'Validation failed for: ' . $addresses[$i]; } return false; } } // Nested format if ($this->nestGroups) { if ($is_group) { $structure->addresses = $addresses; } else { $structure = $addresses[0]; } // Flat format } else { if ($is_group) { $structure = array_merge($structure, $addresses); } else { $structure = $addresses; } } return $structure; } /** * Function to validate a phrase. * * @param string $phrase The phrase to check. * @return boolean Success or failure. */ protected function _validatePhrase($phrase) { // Splits on one or more Tab or space. $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY); $phrase_parts = array(); while (count($parts) > 0){ $phrase_parts[] = $this->_splitCheck($parts, ' '); for ($i = 0; $i < $this->index + 1; $i++) array_shift($parts); } foreach ($phrase_parts as $part) { // If quoted string: if (substr($part, 0, 1) == '"') { if (!$this->_validateQuotedString($part)) { return false; } continue; } // Otherwise it's an atom: if (!$this->_validateAtom($part)) return false; } return true; } /** * Function to validate an atom which from rfc822 is: * atom = 1* * * If validation ($this->validate) has been turned off, then * validateAtom() doesn't actually check anything. This is so that you * can split a list of addresses up before encoding personal names * (umlauts, etc.), for example. * * @param string $atom The string to check. * @return boolean Success or failure. */ protected function _validateAtom($atom) { if (!$this->validate) { // Validation has been turned off; assume the atom is okay. return true; } // Check for any char from ASCII 0 - ASCII 127 if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) { return false; } // Check for specials: if (preg_match('/[][()<>@,;\\:". ]/', $atom)) { return false; } // Check for control characters (ASCII 0-31): if (preg_match('/[\\x00-\\x1F]+/', $atom)) { return false; } return true; } /** * Function to validate quoted string, which is: * quoted-string = <"> *(qtext/quoted-pair) <"> * * @param string $qstring The string to check * @return boolean Success or failure. */ protected function _validateQuotedString($qstring) { // Leading and trailing " $qstring = substr($qstring, 1, -1); // Perform check, removing quoted characters first. return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring)); } /** * Function to validate a mailbox, which is: * mailbox = addr-spec ; simple address * / phrase route-addr ; name and route-addr * * @param string &$mailbox The string to check. * @return boolean Success or failure. */ public function validateMailbox(&$mailbox) { // A couple of defaults. $phrase = ''; $comment = ''; $comments = array(); // Catch any RFC822 comments and store them separately. $_mailbox = $mailbox; while (strlen(trim($_mailbox)) > 0) { $parts = explode('(', $_mailbox); $before_comment = $this->_splitCheck($parts, '('); if ($before_comment != $_mailbox) { // First char should be a (. $comment = substr(str_replace($before_comment, '', $_mailbox), 1); $parts = explode(')', $comment); $comment = $this->_splitCheck($parts, ')'); $comments[] = $comment; // +2 is for the brackets $_mailbox = substr($_mailbox, strpos($_mailbox, '('.$comment)+strlen($comment)+2); } else { break; } } foreach ($comments as $comment) { $mailbox = str_replace("($comment)", '', $mailbox); } $mailbox = trim($mailbox); // Check for name + route-addr if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') { $parts = explode('<', $mailbox); $name = $this->_splitCheck($parts, '<'); $phrase = trim($name); $route_addr = trim(substr($mailbox, strlen($name.'<'), -1)); if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) { return false; } // Only got addr-spec } else { // First snip angle brackets if present. if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') { $addr_spec = substr($mailbox, 1, -1); } else { $addr_spec = $mailbox; } if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { return false; } } // Construct the object that will be returned. $mbox = new stdClass(); // Add the phrase (even if empty) and comments $mbox->personal = $phrase; $mbox->comment = isset($comments) ? $comments : array(); if (isset($route_addr)) { $mbox->mailbox = $route_addr['local_part']; $mbox->host = $route_addr['domain']; $route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : ''; } else { $mbox->mailbox = $addr_spec['local_part']; $mbox->host = $addr_spec['domain']; } $mailbox = $mbox; return true; } /** * This function validates a route-addr which is: * route-addr = "<" [route] addr-spec ">" * * Angle brackets have already been removed at the point of * getting to this function. * * @param string $route_addr The string to check. * @return mixed False on failure, or an array containing validated address/route information on success. */ protected function _validateRouteAddr($route_addr) { // Check for colon. if (strpos($route_addr, ':') !== false) { $parts = explode(':', $route_addr); $route = $this->_splitCheck($parts, ':'); } else { $route = $route_addr; } // If $route is same as $route_addr then the colon was in // quotes or brackets or, of course, non existent. if ($route === $route_addr){ unset($route); $addr_spec = $route_addr; if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { return false; } } else { // Validate route part. if (($route = $this->_validateRoute($route)) === false) { return false; } $addr_spec = substr($route_addr, strlen($route . ':')); // Validate addr-spec part. if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { return false; } } if (isset($route)) { $return['adl'] = $route; } else { $return['adl'] = ''; } $return = array_merge($return, $addr_spec); return $return; } /** * Function to validate a route, which is: * route = 1#("@" domain) ":" * * @param string $route The string to check. * @return mixed False on failure, or the validated $route on success. */ protected function _validateRoute($route) { // Split on comma. $domains = explode(',', trim($route)); foreach ($domains as $domain) { $domain = str_replace('@', '', trim($domain)); if (!$this->_validateDomain($domain)) return false; } return $route; } /** * Function to validate a domain, though this is not quite what * you expect of a strict internet domain. * * domain = sub-domain *("." sub-domain) * * @param string $domain The string to check. * @return mixed False on failure, or the validated domain on success. */ protected function _validateDomain($domain) { // Note the different use of $subdomains and $sub_domains $subdomains = explode('.', $domain); while (count($subdomains) > 0) { $sub_domains[] = $this->_splitCheck($subdomains, '.'); for ($i = 0; $i < $this->index + 1; $i++) array_shift($subdomains); } foreach ($sub_domains as $sub_domain) { if (!$this->_validateSubdomain(trim($sub_domain))) return false; } // Managed to get here, so return input. return $domain; } /** * Function to validate a subdomain: * subdomain = domain-ref / domain-literal * * @param string $subdomain The string to check. * @return boolean Success or failure. */ protected function _validateSubdomain($subdomain) { if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){ if (!$this->_validateDliteral($arr[1])) return false; } else { if (!$this->_validateAtom($subdomain)) return false; } // Got here, so return successful. return true; } /** * Function to validate a domain literal: * domain-literal = "[" *(dtext / quoted-pair) "]" * * @param string $dliteral The string to check. * @return boolean Success or failure. */ protected function _validateDliteral($dliteral) { return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && ((! isset($matches[1])) || $matches[1] != '\\'); } /** * Function to validate an addr-spec. * * addr-spec = local-part "@" domain * * @param string $addr_spec The string to check. * @return mixed False on failure, or the validated addr-spec on success. */ protected function _validateAddrSpec($addr_spec) { $addr_spec = trim($addr_spec); // Split on @ sign if there is one. if (strpos($addr_spec, '@') !== false) { $parts = explode('@', $addr_spec); $local_part = $this->_splitCheck($parts, '@'); $domain = substr($addr_spec, strlen($local_part . '@')); // No @ sign so assume the default domain. } else { $local_part = $addr_spec; $domain = $this->default_domain; } if (($local_part = $this->_validateLocalPart($local_part)) === false) return false; if (($domain = $this->_validateDomain($domain)) === false) return false; // Got here so return successful. return array('local_part' => $local_part, 'domain' => $domain); } /** * Function to validate the local part of an address: * local-part = word *("." word) * * @param string $local_part * @return mixed False on failure, or the validated local part on success. */ protected function _validateLocalPart($local_part) { $parts = explode('.', $local_part); $words = array(); // Split the local_part into words. while (count($parts) > 0) { $words[] = $this->_splitCheck($parts, '.'); for ($i = 0; $i < $this->index + 1; $i++) { array_shift($parts); } } // Validate each word. foreach ($words as $word) { // word cannot be empty (#17317) if ($word === '') { return false; } // If this word contains an unquoted space, it is invalid. (6.2.4) if (strpos($word, ' ') && $word[0] !== '"') { return false; } if ($this->_validatePhrase(trim($word)) === false) return false; } // Managed to get here, so return the input. return $local_part; } /** * Returns an approximate count of how many addresses are in the * given string. This is APPROXIMATE as it only splits based on a * comma which has no preceding backslash. Could be useful as * large amounts of addresses will end up producing *large* * structures when used with parseAddressList(). * * @param string $data Addresses to count * @return int Approximate count */ public function approximateCount($data) { return count(preg_split('/(?@. This can be sufficient for most * people. Optional stricter mode can be utilised which restricts * mailbox characters allowed to alphanumeric, full stop, hyphen * and underscore. * * @param string $data Address to check * @param boolean $strict Optional stricter mode * @return mixed False if it fails, an indexed array * username/domain if it matches */ public function isValidInetAddress($data, $strict = false) { $regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i'; if (preg_match($regex, trim($data), $matches)) { return array($matches[1], $matches[2]); } else { return false; } } } PK!+V Mail/mime.phpnu[ * Copyright (c) 2003-2006, PEAR * 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 authors, 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. * * @category Mail * @package Mail_Mime * @author Richard Heyes * @author Tomas V.V. Cox * @author Cipriano Groenendal * @author Sean Coates * @author Aleksander Machniak * @copyright 2003-2006 PEAR * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime * * This class is based on HTML Mime Mail class from * Richard Heyes which was based also * in the mime_mail.class by Tobias Ratschiller * and Sascha Schumann */ require_once 'PEAR.php'; require_once 'Mail/mimePart.php'; /** * The Mail_Mime class provides an OO interface to create MIME * enabled email messages. This way you can create emails that * contain plain-text bodies, HTML bodies, attachments, inline * images and specific headers. * * @category Mail * @package Mail_Mime * @author Richard Heyes * @author Tomas V.V. Cox * @author Cipriano Groenendal * @author Sean Coates * @copyright 2003-2006 PEAR * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime */ class Mail_mime { /** * Contains the plain text part of the email * * @var string */ protected $txtbody = ''; /** * Contains the html part of the email * * @var string */ protected $htmlbody = ''; /** * Contains the text/calendar part of the email * * @var string */ protected $calbody = ''; /** * List of the attached images * * @var array */ protected $html_images = array(); /** * List of the attachements * * @var array */ protected $parts = array(); /** * Headers for the mail * * @var array */ protected $headers = array(); /** * Build parameters * * @var array */ protected $build_params = array( // What encoding to use for the headers // Options: quoted-printable or base64 'head_encoding' => 'quoted-printable', // What encoding to use for plain text // Options: 7bit, 8bit, base64, or quoted-printable 'text_encoding' => 'quoted-printable', // What encoding to use for html // Options: 7bit, 8bit, base64, or quoted-printable 'html_encoding' => 'quoted-printable', // What encoding to use for calendar part // Options: 7bit, 8bit, base64, or quoted-printable 'calendar_encoding' => 'quoted-printable', // The character set to use for html 'html_charset' => 'ISO-8859-1', // The character set to use for text 'text_charset' => 'ISO-8859-1', // The character set to use for calendar part 'calendar_charset' => 'UTF-8', // The character set to use for headers 'head_charset' => 'ISO-8859-1', // End-of-line sequence 'eol' => "\r\n", // Delay attachment files IO until building the message 'delay_file_io' => false, // Default calendar method 'calendar_method' => 'request', // multipart part preamble (RFC2046 5.1.1) 'preamble' => '', ); /** * Constructor function * * @param mixed $params Build parameters that change the way the email * is built. Should be an associative array. * See $_build_params. * * @return void */ public function __construct($params = array()) { // Backward-compatible EOL setting if (is_string($params)) { $this->build_params['eol'] = $params; } else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) { $this->build_params['eol'] = MAIL_MIME_CRLF; } // Update build parameters if (!empty($params) && is_array($params)) { $this->build_params = array_merge($this->build_params, $params); } } /** * Set build parameter value * * @param string $name Parameter name * @param string $value Parameter value * * @return void * @since 1.6.0 */ public function setParam($name, $value) { $this->build_params[$name] = $value; } /** * Get build parameter value * * @param string $name Parameter name * * @return mixed Parameter value * @since 1.6.0 */ public function getParam($name) { return isset($this->build_params[$name]) ? $this->build_params[$name] : null; } /** * Accessor function to set the body text. Body text is used if * it's not an html mail being sent or else is used to fill the * text/plain part that emails clients who don't support * html should show. * * @param string $data Either a string or the file name with the contents * @param bool $isfile If true the first param should be treated * as a file name, else as a string (default) * @param bool $append If true the text or file is appended to * the existing body, else the old body is * overwritten * * @return mixed True on success or PEAR_Error object */ public function setTXTBody($data, $isfile = false, $append = false) { return $this->setBody('txtbody', $data, $isfile, $append); } /** * Get message text body * * @return string Text body * @since 1.6.0 */ public function getTXTBody() { return $this->txtbody; } /** * Adds a html part to the mail. * * @param string $data Either a string or the file name with the contents * @param bool $isfile A flag that determines whether $data is a * filename, or a string(false, default) * * @return bool True on success or PEAR_Error object */ public function setHTMLBody($data, $isfile = false) { return $this->setBody('htmlbody', $data, $isfile); } /** * Get message HTML body * * @return string HTML body * @since 1.6.0 */ public function getHTMLBody() { return $this->htmlbody; } /** * Function to set a body of text/calendar part (not attachment) * * @param string $data Either a string or the file name with the contents * @param bool $isfile If true the first param should be treated * as a file name, else as a string (default) * @param bool $append If true the text or file is appended to * the existing body, else the old body is * overwritten * @param string $method iCalendar object method * @param string $charset iCalendar character set * @param string $encoding Transfer encoding * * @return mixed True on success or PEAR_Error object * @since 1.9.0 */ public function setCalendarBody($data, $isfile = false, $append = false, $method = 'request', $charset = 'UTF-8', $encoding = 'quoted-printable' ) { $result = $this->setBody('calbody', $data, $isfile, $append); if ($result === true) { $this->build_params['calendar_method'] = $method; $this->build_params['calendar_charset'] = $charset; $this->build_params['calendar_encoding'] = $encoding; } } /** * Get body of calendar part * * @return string Calendar part body * @since 1.9.0 */ public function getCalendarBody() { return $this->calbody; } /** * Adds an image to the list of embedded images. * Images added this way will be added as related parts of the HTML message. * * To correctly match the HTML image with the related attachment * HTML should refer to it by a filename (specified in $file or $name * arguments) or by cid: (specified in $content_id arg). * * @param string $file The image file name OR image data itself * @param string $c_type The content type * @param string $name The filename of the image. Used to find * the image in HTML content. * @param bool $isfile Whether $file is a filename or not. * Defaults to true * @param string $content_id Desired Content-ID of MIME part * Defaults to generated unique ID * * @return bool True on success */ public function addHTMLImage($file, $c_type = 'application/octet-stream', $name = '', $isfile = true, $content_id = null ) { $bodyfile = null; if ($isfile) { // Don't load file into memory if ($this->build_params['delay_file_io']) { $filedata = null; $bodyfile = $file; } else { if (self::isError($filedata = $this->file2str($file))) { return $filedata; } } $filename = $name ? $name : $file; } else { $filedata = $file; $filename = $name; } if (!$content_id) { $content_id = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true)); } $this->html_images[] = array( 'body' => $filedata, 'body_file' => $bodyfile, 'name' => $filename, 'c_type' => $c_type, 'cid' => $content_id ); return true; } /** * Adds a file to the list of attachments. * * @param mixed $file The file name or the file contents itself, * it can be also Mail_mimePart object * @param string $c_type The content type * @param string $name The filename of the attachment * Only use if $file is the contents * @param bool $isfile Whether $file is a filename or not. Defaults to true * @param string $encoding The type of encoding to use. Defaults to base64. * Possible values: 7bit, 8bit, base64 or quoted-printable. * @param string $disposition The content-disposition of this file * Defaults to attachment. * Possible values: attachment, inline. * @param string $charset The character set of attachment's content. * @param string $language The language of the attachment * @param string $location The RFC 2557.4 location of the attachment * @param string $n_encoding Encoding of the attachment's name in Content-Type * By default filenames are encoded using RFC2231 method * Here you can set RFC2047 encoding (quoted-printable * or base64) instead * @param string $f_encoding Encoding of the attachment's filename * in Content-Disposition header. * @param string $description Content-Description header * @param string $h_charset The character set of the headers e.g. filename * If not specified, $charset will be used * @param array $add_headers Additional part headers. Array keys can be in form * of : * * @return mixed True on success or PEAR_Error object */ public function addAttachment($file, $c_type = 'application/octet-stream', $name = '', $isfile = true, $encoding = 'base64', $disposition = 'attachment', $charset = '', $language = '', $location = '', $n_encoding = null, $f_encoding = null, $description = '', $h_charset = null, $add_headers = array() ) { if ($file instanceof Mail_mimePart) { $this->parts[] = $file; return true; } $bodyfile = null; if ($isfile) { // Don't load file into memory if ($this->build_params['delay_file_io']) { $filedata = null; $bodyfile = $file; } else { if (self::isError($filedata = $this->file2str($file))) { return $filedata; } } // Force the name the user supplied, otherwise use $file $filename = ($name ? $name : $this->basename($file)); } else { $filedata = $file; $filename = $name; } if (!strlen($filename)) { $msg = "The supplied filename for the attachment can't be empty"; return self::raiseError($msg); } $this->parts[] = array( 'body' => $filedata, 'body_file' => $bodyfile, 'name' => $filename, 'c_type' => $c_type, 'charset' => $charset, 'encoding' => $encoding, 'language' => $language, 'location' => $location, 'disposition' => $disposition, 'description' => $description, 'add_headers' => $add_headers, 'name_encoding' => $n_encoding, 'filename_encoding' => $f_encoding, 'headers_charset' => $h_charset, ); return true; } /** * Checks if the current message has many parts * * @return bool True if the message has many parts, False otherwise. * @since 1.9.0 */ public function isMultipart() { return count($this->parts) > 0 || count($this->html_images) > 0 || (strlen($this->htmlbody) > 0 && strlen($this->txtbody) > 0); } /** * Get the contents of the given file name as string * * @param string $file_name Path of file to process * * @return string Contents of $file_name */ protected function file2str($file_name) { // Check state of file and raise an error properly if (!file_exists($file_name)) { return self::raiseError('File not found: ' . $file_name); } if (!is_file($file_name)) { return self::raiseError('Not a regular file: ' . $file_name); } if (!is_readable($file_name)) { return self::raiseError('File is not readable: ' . $file_name); } // Temporarily reset magic_quotes_runtime and read file contents if (version_compare(PHP_VERSION, '5.4.0', '<')) { $magic_quotes = @ini_set('magic_quotes_runtime', 0); } $cont = file_get_contents($file_name); if (isset($magic_quotes)) { @ini_set('magic_quotes_runtime', $magic_quotes); } return $cont; } /** * Adds a text subpart to the mimePart object and * returns it during the build process. * * @param mixed $obj The object to add the part to, or * anything else if a new object is to be created. * * @return object The text mimePart object */ protected function addTextPart($obj = null) { return $this->addBodyPart($obj, $this->txtbody, 'text/plain', 'text'); } /** * Adds a html subpart to the mimePart object and * returns it during the build process. * * @param mixed $obj The object to add the part to, or * anything else if a new object is to be created. * * @return object The html mimePart object */ protected function addHtmlPart($obj = null) { return $this->addBodyPart($obj, $this->htmlbody, 'text/html', 'html'); } /** * Adds a calendar subpart to the mimePart object and * returns it during the build process. * * @param mixed $obj The object to add the part to, or * anything else if a new object is to be created. * * @return object The text mimePart object */ protected function addCalendarPart($obj = null) { $ctype = 'text/calendar; method='. $this->build_params['calendar_method']; return $this->addBodyPart($obj, $this->calbody, $ctype, 'calendar'); } /** * Creates a new mimePart object, using multipart/mixed as * the initial content-type and returns it during the * build process. * * @param array $params Additional part parameters * * @return object The multipart/mixed mimePart object */ protected function addMixedPart($params = array()) { $params['content_type'] = 'multipart/mixed'; $params['eol'] = $this->build_params['eol']; // Create empty multipart/mixed Mail_mimePart object to return return new Mail_mimePart('', $params); } /** * Adds a multipart/alternative part to a mimePart * object (or creates one), and returns it during * the build process. * * @param mixed $obj The object to add the part to, or * anything else if a new object is to be created. * * @return object The multipart/mixed mimePart object */ protected function addAlternativePart($obj = null) { $params['content_type'] = 'multipart/alternative'; $params['eol'] = $this->build_params['eol']; if (is_object($obj)) { $ret = $obj->addSubpart('', $params); } else { $ret = new Mail_mimePart('', $params); } return $ret; } /** * Adds a multipart/related part to a mimePart * object (or creates one), and returns it during * the build process. * * @param mixed $obj The object to add the part to, or * anything else if a new object is to be created * * @return object The multipart/mixed mimePart object */ protected function addRelatedPart($obj = null) { $params['content_type'] = 'multipart/related'; $params['eol'] = $this->build_params['eol']; if (is_object($obj)) { $ret = $obj->addSubpart('', $params); } else { $ret = new Mail_mimePart('', $params); } return $ret; } /** * Adds an html image subpart to a mimePart object * and returns it during the build process. * * @param object $obj The mimePart to add the image to * @param array $value The image information * * @return object The image mimePart object */ protected function addHtmlImagePart($obj, $value) { $params['content_type'] = $value['c_type']; $params['encoding'] = 'base64'; $params['disposition'] = 'inline'; $params['filename'] = $value['name']; $params['cid'] = $value['cid']; $params['body_file'] = $value['body_file']; $params['eol'] = $this->build_params['eol']; if (!empty($value['name_encoding'])) { $params['name_encoding'] = $value['name_encoding']; } if (!empty($value['filename_encoding'])) { $params['filename_encoding'] = $value['filename_encoding']; } return $obj->addSubpart($value['body'], $params); } /** * Adds an attachment subpart to a mimePart object * and returns it during the build process. * * @param object $obj The mimePart to add the image to * @param mixed $value The attachment information array or Mail_mimePart object * * @return object The image mimePart object */ protected function addAttachmentPart($obj, $value) { if ($value instanceof Mail_mimePart) { return $obj->addSubpart($value); } $params['eol'] = $this->build_params['eol']; $params['filename'] = $value['name']; $params['encoding'] = $value['encoding']; $params['content_type'] = $value['c_type']; $params['body_file'] = $value['body_file']; $params['disposition'] = isset($value['disposition']) ? $value['disposition'] : 'attachment'; // content charset if (!empty($value['charset'])) { $params['charset'] = $value['charset']; } // headers charset (filename, description) if (!empty($value['headers_charset'])) { $params['headers_charset'] = $value['headers_charset']; } if (!empty($value['language'])) { $params['language'] = $value['language']; } if (!empty($value['location'])) { $params['location'] = $value['location']; } if (!empty($value['name_encoding'])) { $params['name_encoding'] = $value['name_encoding']; } if (!empty($value['filename_encoding'])) { $params['filename_encoding'] = $value['filename_encoding']; } if (!empty($value['description'])) { $params['description'] = $value['description']; } if (is_array($value['add_headers'])) { $params['headers'] = $value['add_headers']; } return $obj->addSubpart($value['body'], $params); } /** * Returns the complete e-mail, ready to send using an alternative * mail delivery method. Note that only the mailpart that is made * with Mail_Mime is created. This means that, * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF * using the $headers parameter! * * @param string $separation The separation between these two parts. * @param array $params The Build parameters passed to the * get() function. See get() for more info. * @param array $headers The extra headers that should be passed * to the headers() method. * See that function for more info. * @param bool $overwrite Overwrite the existing headers with new. * * @return mixed The complete e-mail or PEAR error object */ public function getMessage($separation = null, $params = null, $headers = null, $overwrite = false ) { if ($separation === null) { $separation = $this->build_params['eol']; } $body = $this->get($params); if (self::isError($body)) { return $body; } return $this->txtHeaders($headers, $overwrite) . $separation . $body; } /** * Returns the complete e-mail body, ready to send using an alternative * mail delivery method. * * @param array $params The Build parameters passed to the * get() method. See get() for more info. * * @return mixed The e-mail body or PEAR error object * @since 1.6.0 */ public function getMessageBody($params = null) { return $this->get($params, null, true); } /** * Writes (appends) the complete e-mail into file. * * @param string $filename Output file location * @param array $params The Build parameters passed to the * get() method. See get() for more info. * @param array $headers The extra headers that should be passed * to the headers() function. * See that function for more info. * @param bool $overwrite Overwrite the existing headers with new. * * @return mixed True or PEAR error object * @since 1.6.0 */ public function saveMessage($filename, $params = null, $headers = null, $overwrite = false) { // Check state of file and raise an error properly if (file_exists($filename) && !is_writable($filename)) { return self::raiseError('File is not writable: ' . $filename); } // Temporarily reset magic_quotes_runtime and read file contents if (version_compare(PHP_VERSION, '5.4.0', '<')) { $magic_quotes = @ini_set('magic_quotes_runtime', 0); } if (!($fh = fopen($filename, 'ab'))) { return self::raiseError('Unable to open file: ' . $filename); } // Write message headers into file (skipping Content-* headers) $head = $this->txtHeaders($headers, $overwrite, true); if (fwrite($fh, $head) === false) { return self::raiseError('Error writing to file: ' . $filename); } fclose($fh); if (isset($magic_quotes)) { @ini_set('magic_quotes_runtime', $magic_quotes); } // Write the rest of the message into file $res = $this->get($params, $filename); return $res ? $res : true; } /** * Writes (appends) the complete e-mail body into file or stream. * * @param mixed $filename Output filename or file pointer where to save * the message instead of returning it * @param array $params The Build parameters passed to the * get() method. See get() for more info. * * @return mixed True or PEAR error object * @since 1.6.0 */ public function saveMessageBody($filename, $params = null) { if (!is_resource($filename)) { // Check state of file and raise an error properly if (!file_exists($filename) || !is_writable($filename)) { return self::raiseError('File is not writable: ' . $filename); } if (!($fh = fopen($filename, 'ab'))) { return self::raiseError('Unable to open file: ' . $filename); } } else { $fh = $filename; } // Temporarily reset magic_quotes_runtime and read file contents if (version_compare(PHP_VERSION, '5.4.0', '<')) { $magic_quotes = @ini_set('magic_quotes_runtime', 0); } // Write the rest of the message into file $res = $this->get($params, $fh, true); if (!is_resource($filename)) { fclose($fh); } if (isset($magic_quotes)) { @ini_set('magic_quotes_runtime', $magic_quotes); } return $res ? $res : true; } /** * Builds the multipart message from the list ($this->parts) and * returns the mime content. * * @param array $params Build parameters that change the way the email * is built. Should be associative. See $_build_params. * @param mixed $filename Output filename or file pointer where to save * the message instead of returning it * @param boolean $skip_head True if you want to return/save only the message * without headers * * @return mixed The MIME message content string, null or PEAR error object */ public function get($params = null, $filename = null, $skip_head = false) { if (!empty($params) && is_array($params)) { $this->build_params = array_merge($this->build_params, $params); } if (isset($this->headers['From'])) { // Bug #11381: Illegal characters in domain ID if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->headers['From'], $matches)) { $domainID = $matches[1]; } else { $domainID = '@localhost'; } foreach ($this->html_images as $i => $img) { $cid = $this->html_images[$i]['cid']; if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) { $this->html_images[$i]['cid'] = $cid . $domainID; } } } if (count($this->html_images) && strlen($this->htmlbody) > 0) { foreach ($this->html_images as $key => $value) { $rval = preg_quote($value['name'], '#'); $regex = array( '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' . $rval . '\3#', '#(?i)url(?-i)\(\s*(["\']?)' . $rval . '\1\s*\)#', ); $rep = array( '\1\2=\3cid:' . $value['cid'] .'\3', 'url(\1cid:' . $value['cid'] . '\1)', ); $this->htmlbody = preg_replace($regex, $rep, $this->htmlbody); $this->html_images[$key]['name'] = $this->basename($this->html_images[$key]['name']); } } $this->checkParams(); $message = $this->buildBodyPart(); if (!isset($message)) { return null; } // Use saved boundary if (!empty($this->build_params['boundary'])) { $boundary = $this->build_params['boundary']; } else { $boundary = null; } // Write output to file if ($filename) { // Append mimePart message headers and body into file $headers = $message->encodeToFile($filename, $boundary, $skip_head); if (self::isError($headers)) { return $headers; } $this->headers = array_merge($this->headers, $headers); } else { $output = $message->encode($boundary, $skip_head); if (self::isError($output)) { return $output; } $this->headers = array_merge($this->headers, $output['headers']); } // remember the boundary used, in case we'd handle headers() call later if (empty($boundary) && !empty($this->headers['Content-Type'])) { if (preg_match('/boundary="([^"]+)/', $this->headers['Content-Type'], $m)) { $this->build_params['boundary'] = $m[1]; } } return $filename ? null : $output['body']; } /** * Builds the main body MIME part for the email body. It will add a mixed part * if attachments are found. If no attachments are found it will return an * alternative part if several body texts are found (text, html, calendar), * or a single part if only one body text is found. * * @return Mail_mimePart|null The corresponding part for the body or null. * * @see buildAlternativeParts * @see buildHtmlParts */ protected function buildBodyPart() { $parts_count = count($this->parts); $mixed_params = array('preamble' => $this->build_params['preamble']); $message = null; if ($parts_count > 0) { $message = $this->addMixedPart($mixed_params); $this->buildAlternativeParts($message, null); for ($i = 0; $i < $parts_count; $i++) { $this->addAttachmentPart($message, $this->parts[$i]); } } else { $message = $this->buildAlternativeParts(null, $mixed_params); } return $message; } /** * Builds a single text, html, or calendar part only if one of them is found. * If two or more parts are found, then an alternative part containing them is built. * * @param Mail_mimePart|null $parent_part The parent mime part to add * the part or null * @param array $mixed_params The needed params to create the * part when no parent_part is * received. * * @return null|object The main part built inside the method. It will be an * alternative part or text, html, or calendar part. * Null if no body texts are found. */ protected function buildAlternativeParts($parent_part, $mixed_params = null) { $html = strlen($this->htmlbody) > 0; $calendar = strlen($this->calbody) > 0; $has_text = strlen($this->txtbody) > 0; $alternatives_count = $html + $calendar + $has_text; if ($alternatives_count > 1) { $alt_part = $this->addAlternativePart($parent_part ? $parent_part : $mixed_params); } else { $alt_part = null; } $dest_part = $alt_part ? $alt_part : $parent_part; $part = null; if ($has_text) { $part = $this->addTextPart($dest_part); } if ($html) { $part = $this->buildHtmlParts($dest_part); } if ($calendar) { $part = $this->addCalendarPart($dest_part); } return $dest_part ? $dest_part : $part; } /** * Builds html part as a single part or inside a related part with the html * images thar were found. * * @param Mail_mimePart|null $parent_part The object to add the part to, * or anything else if a new object * is to be created. * * @return Mail_mimePart|null The created part or null if no htmlbody found. */ protected function buildHtmlParts($parent_part) { if (!strlen($this->htmlbody)) { return null; } $count_html_images = count($this->html_images); if ($count_html_images > 0) { $part = $this->addRelatedPart($parent_part); $this->addHtmlPart($part); } else { $part = $this->addHtmlPart($parent_part); } for ($i = 0; $i < $count_html_images; $i++) { $this->addHtmlImagePart($part, $this->html_images[$i]); } return $part; } /** * Returns an array with the headers needed to prepend to the email * (MIME-Version and Content-Type). Format of argument is: * $array['header-name'] = 'header-value'; * * @param array $xtra_headers Assoc array with any extra headers (optional) * (Don't set Content-Type for multipart messages here!) * @param bool $overwrite Overwrite already existing headers. * @param bool $skip_content Don't return content headers: Content-Type, * Content-Disposition and Content-Transfer-Encoding * * @return array Assoc array with the mime headers */ public function headers($xtra_headers = null, $overwrite = false, $skip_content = false) { // Add mime version header $headers['MIME-Version'] = '1.0'; if (!empty($xtra_headers)) { $headers = array_merge($headers, $xtra_headers); } if ($overwrite) { $this->headers = array_merge($this->headers, $headers); } else { $this->headers = array_merge($headers, $this->headers); } // Always reset Content-Type/Content-Transfer-Encoding headers // In case the message structure changed in meantime unset($this->headers['Content-Type']); unset($this->headers['Content-Transfer-Encoding']); unset($this->headers['Content-Disposition']); $this->headers = array_merge($this->headers, $this->contentHeaders()); $headers = $this->headers; if ($skip_content) { unset($headers['Content-Type']); unset($headers['Content-Transfer-Encoding']); unset($headers['Content-Disposition']); } else if (!empty($this->build_params['ctype'])) { $headers['Content-Type'] = $this->build_params['ctype']; } return $this->encodeHeaders($headers); } /** * Get the text version of the headers * (usefull if you want to use the PHP mail() function) * * @param array $xtra_headers Assoc array with any extra headers (optional) * (Don't set Content-Type for multipart messages here!) * @param bool $overwrite Overwrite the existing headers with new. * @param bool $skip_content Don't return content headers: Content-Type, * Content-Disposition and Content-Transfer-Encoding * * @return string Plain text headers */ public function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false) { $headers = $this->headers($xtra_headers, $overwrite, $skip_content); // Place Received: headers at the beginning of the message // Spam detectors often flag messages with it after the Subject: as spam if (isset($headers['Received'])) { $received = $headers['Received']; unset($headers['Received']); $headers = array('Received' => $received) + $headers; } $ret = ''; $eol = $this->build_params['eol']; foreach ($headers as $key => $val) { if (is_array($val)) { foreach ($val as $value) { $ret .= "$key: $value" . $eol; } } else { $ret .= "$key: $val" . $eol; } } return $ret; } /** * Sets message Content-Type header. * Use it to build messages with various content-types e.g. miltipart/raport * not supported by contentHeaders() function. * * @param string $type Type name * @param array $params Hash array of header parameters * * @return void * @since 1.7.0 */ public function setContentType($type, $params = array()) { $header = $type; $eol = !empty($this->build_params['eol']) ? $this->build_params['eol'] : "\r\n"; // add parameters $token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#'; if (is_array($params)) { foreach ($params as $name => $value) { if ($name == 'boundary') { $this->build_params['boundary'] = $value; } else if (!preg_match($token_regexp, $value)) { $header .= ";$eol $name=$value"; } else { $value = addcslashes($value, '\\"'); $header .= ";$eol $name=\"$value\""; } } } // add required boundary parameter if not defined if (stripos($type, 'multipart/') === 0) { if (empty($this->build_params['boundary'])) { $this->build_params['boundary'] = '=_' . md5(rand() . microtime()); } $header .= ";$eol boundary=\"".$this->build_params['boundary']."\""; } $this->build_params['ctype'] = $header; } /** * Sets the Subject header * * @param string $subject String to set the subject to. * * @return void */ public function setSubject($subject) { $this->headers['Subject'] = $subject; } /** * Set an email to the From (the sender) header * * @param string $email The email address to use * * @return void */ public function setFrom($email) { $this->headers['From'] = $email; } /** * Add an email to the To header * (multiple calls to this method are allowed) * * @param string $email The email direction to add * * @return void */ public function addTo($email) { if (isset($this->headers['To'])) { $this->headers['To'] .= ", $email"; } else { $this->headers['To'] = $email; } } /** * Add an email to the Cc (carbon copy) header * (multiple calls to this method are allowed) * * @param string $email The email direction to add * * @return void */ public function addCc($email) { if (isset($this->headers['Cc'])) { $this->headers['Cc'] .= ", $email"; } else { $this->headers['Cc'] = $email; } } /** * Add an email to the Bcc (blank carbon copy) header * (multiple calls to this method are allowed) * * @param string $email The email direction to add * * @return void */ public function addBcc($email) { if (isset($this->headers['Bcc'])) { $this->headers['Bcc'] .= ", $email"; } else { $this->headers['Bcc'] = $email; } } /** * Since the PHP send function requires you to specify * recipients (To: header) separately from the other * headers, the To: header is not properly encoded. * To fix this, you can use this public method to encode * your recipients before sending to the send function. * * @param string $recipients A comma-delimited list of recipients * * @return string Encoded data */ public function encodeRecipients($recipients) { $input = array('To' => $recipients); $retval = $this->encodeHeaders($input); return $retval['To'] ; } /** * Encodes headers as per RFC2047 * * @param array $input The header data to encode * @param array $params Extra build parameters * * @return array Encoded data */ protected function encodeHeaders($input, $params = array()) { $build_params = $this->build_params; if (!empty($params)) { $build_params = array_merge($build_params, $params); } foreach ($input as $hdr_name => $hdr_value) { if (is_array($hdr_value)) { foreach ($hdr_value as $idx => $value) { $input[$hdr_name][$idx] = $this->encodeHeader( $hdr_name, $value, $build_params['head_charset'], $build_params['head_encoding'] ); } } else if ($hdr_value !== null) { $input[$hdr_name] = $this->encodeHeader( $hdr_name, $hdr_value, $build_params['head_charset'], $build_params['head_encoding'] ); } else { unset($input[$hdr_name]); } } return $input; } /** * Encodes a header as per RFC2047 * * @param string $name The header name * @param string $value The header data to encode * @param string $charset Character set name * @param string $encoding Encoding name (base64 or quoted-printable) * * @return string Encoded header data (without a name) * @since 1.5.3 */ public function encodeHeader($name, $value, $charset, $encoding) { return Mail_mimePart::encodeHeader( $name, $value, $charset, $encoding, $this->build_params['eol'] ); } /** * Get file's basename (locale independent) * * @param string $filename Filename * * @return string Basename */ protected function basename($filename) { // basename() is not unicode safe and locale dependent if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) { return preg_replace('/^.*[\\\\\\/]/', '', $filename); } else { return preg_replace('/^.*[\/]/', '', $filename); } } /** * Get Content-Type and Content-Transfer-Encoding headers of the message * * @return array Headers array */ protected function contentHeaders() { $attachments = count($this->parts) > 0; $html_images = count($this->html_images) > 0; $html = strlen($this->htmlbody) > 0; $calendar = strlen($this->calbody) > 0; $has_text = strlen($this->txtbody) > 0; $has_alternatives = ($html + $calendar + $has_text) > 1; $headers = array(); // See get() switch (true) { case $has_text && !$attachments && !$has_alternatives: $headers['Content-Type'] = 'text/plain'; break; case $html && !$html_images && !$attachments && !$has_alternatives: $headers['Content-Type'] = 'text/html'; break; case $html && $html_images && !$attachments && !$has_alternatives: $headers['Content-Type'] = 'multipart/related'; break; case $calendar && !$attachments && !$has_alternatives: $headers['Content-Type'] = 'text/calendar'; break; case $has_alternatives && !$attachments: $headers['Content-Type'] = 'multipart/alternative'; break; case $attachments: $headers['Content-Type'] = 'multipart/mixed'; break; } // Note: This is outside of the above switch construct to workaround // opcache bug: https://bugzilla.opensuse.org/show_bug.cgi?id=1166235 if (empty($headers)) { return $headers; } $this->checkParams(); $eol = !empty($this->build_params['eol']) ? $this->build_params['eol'] : "\r\n"; if ($headers['Content-Type'] == 'text/plain') { // single-part message: add charset and encoding if ($this->build_params['text_charset']) { $charset = 'charset=' . $this->build_params['text_charset']; // place charset parameter in the same line, if possible // 26 = strlen("Content-Type: text/plain; ") $headers['Content-Type'] .= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset"; } $headers['Content-Transfer-Encoding'] = $this->build_params['text_encoding']; } else if ($headers['Content-Type'] == 'text/html') { // single-part message: add charset and encoding if ($this->build_params['html_charset']) { $charset = 'charset=' . $this->build_params['html_charset']; // place charset parameter in the same line, if possible $headers['Content-Type'] .= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset"; } $headers['Content-Transfer-Encoding'] = $this->build_params['html_encoding']; } else if ($headers['Content-Type'] == 'text/calendar') { // single-part message: add charset and encoding if ($this->build_params['calendar_charset']) { $charset = 'charset=' . $this->build_params['calendar_charset']; $headers['Content-Type'] .= "; $charset"; } if ($this->build_params['calendar_method']) { $method = 'method=' . $this->build_params['calendar_method']; $headers['Content-Type'] .= "; $method"; } $headers['Content-Transfer-Encoding'] = $this->build_params['calendar_encoding']; } else { // multipart message: and boundary if (!empty($this->build_params['boundary'])) { $boundary = $this->build_params['boundary']; } else if (!empty($this->headers['Content-Type']) && preg_match('/boundary="([^"]+)"/', $this->headers['Content-Type'], $m) ) { $boundary = $m[1]; } else { $boundary = '=_' . md5(rand() . microtime()); } $this->build_params['boundary'] = $boundary; $headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; } return $headers; } /** * Validate and set build parameters * * @return void */ protected function checkParams() { $encodings = array('7bit', '8bit', 'base64', 'quoted-printable'); $this->build_params['text_encoding'] = strtolower($this->build_params['text_encoding']); $this->build_params['html_encoding'] = strtolower($this->build_params['html_encoding']); $this->build_params['calendar_encoding'] = strtolower($this->build_params['calendar_encoding']); if (!in_array($this->build_params['text_encoding'], $encodings)) { $this->build_params['text_encoding'] = '7bit'; } if (!in_array($this->build_params['html_encoding'], $encodings)) { $this->build_params['html_encoding'] = '7bit'; } if (!in_array($this->build_params['calendar_encoding'], $encodings)) { $this->build_params['calendar_encoding'] = '7bit'; } // text body if ($this->build_params['text_encoding'] == '7bit' && !preg_match('/ascii/i', $this->build_params['text_charset']) && preg_match('/[^\x00-\x7F]/', $this->txtbody) ) { $this->build_params['text_encoding'] = 'quoted-printable'; } // html body if ($this->build_params['html_encoding'] == '7bit' && !preg_match('/ascii/i', $this->build_params['html_charset']) && preg_match('/[^\x00-\x7F]/', $this->htmlbody) ) { $this->build_params['html_encoding'] = 'quoted-printable'; } // calendar body if ($this->build_params['calendar_encoding'] == '7bit' && !preg_match('/ascii/i', $this->build_params['calendar_charset']) && preg_match('/[^\x00-\x7F]/', $this->calbody) ) { $this->build_params['calendar_encoding'] = 'quoted-printable'; } } /** * Set body of specified message part * * @param string $type One of: txtbody, calbody, htmlbody * @param string $data Either a string or the file name with the contents * @param bool $isfile If true the first param should be treated * as a file name, else as a string (default) * @param bool $append If true the text or file is appended to * the existing body, else the old body is * overwritten * * @return mixed True on success or PEAR_Error object */ protected function setBody($type, $data, $isfile = false, $append = false) { if ($isfile) { $data = $this->file2str($data); if (self::isError($data)) { return $data; } } if (!$append) { $this->{$type} = $data; } else { $this->{$type} .= $data; } return true; } /** * Adds a subpart to the mimePart object and * returns it during the build process. * * @param mixed $obj The object to add the part to, or * anything else if a new object is to be created. * @param string $body Part body * @param string $ctype Part content type * @param string $type Internal part type * * @return object The mimePart object */ protected function addBodyPart($obj, $body, $ctype, $type) { $params['content_type'] = $ctype; $params['encoding'] = $this->build_params[$type . '_encoding']; $params['charset'] = $this->build_params[$type . '_charset']; $params['eol'] = $this->build_params['eol']; if (is_object($obj)) { $ret = $obj->addSubpart($body, $params); } else { $ret = new Mail_mimePart($body, $params); } return $ret; } /** * PEAR::isError implementation * * @param mixed $data Object * * @return bool True if object is an instance of PEAR_Error */ public static function isError($data) { // PEAR::isError() is not PHP 5.4 compatible (see Bug #19473) if (is_a($data, 'PEAR_Error')) { return true; } return false; } /** * PEAR::raiseError implementation * * @param string $message A text error message * * @return PEAR_Error Instance of PEAR_Error */ public static function raiseError($message) { // PEAR::raiseError() is not PHP 5.4 compatible return new PEAR_Error($message); } } PK!x عMail/mimeDecode.phpnu[ * Copyright (c) 2003-2006, PEAR * 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 authors, 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. * * @category Mail * @package Mail_Mime * @author Richard Heyes * @author George Schlossnagle * @author Cipriano Groenendal * @author Sean Coates * @copyright 2003-2006 PEAR * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @version CVS: $Id: mimeDecode.php 337165 2015-07-15 09:42:08Z alan_k $ * @link http://pear.php.net/package/Mail_mime */ /** * require PEAR * * This package depends on PEAR to raise errors. */ require_once 'PEAR.php'; /** * The Mail_mimeDecode class is used to decode mail/mime messages * * This class will parse a raw mime email and return the structure. * Returned structure is similar to that returned by imap_fetchstructure(). * * +----------------------------- IMPORTANT ------------------------------+ * | Usage of this class compared to native php extensions such as | * | mailparse or imap, is slow and may be feature deficient. If available| * | you are STRONGLY recommended to use the php extensions. | * +----------------------------------------------------------------------+ * * @category Mail * @package Mail_Mime * @author Richard Heyes * @author George Schlossnagle * @author Cipriano Groenendal * @author Sean Coates * @copyright 2003-2006 PEAR * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime */ class Mail_mimeDecode extends PEAR { /** * The raw email to decode * * @var string * @access private */ var $_input; /** * The header part of the input * * @var string * @access private */ var $_header; /** * The body part of the input * * @var string * @access private */ var $_body; /** * If an error occurs, this is used to store the message * * @var string * @access private */ var $_error; /** * Flag to determine whether to include bodies in the * returned object. * * @var boolean * @access private */ var $_include_bodies; /** * Flag to determine whether to decode bodies * * @var boolean * @access private */ var $_decode_bodies; /** * Flag to determine whether to decode headers * (set to UTF8 to iconv convert headers) * @var mixed * @access private */ var $_decode_headers; /** * Flag to determine whether to include attached messages * as body in the returned object. Depends on $_include_bodies * * @var boolean * @access private */ var $_rfc822_bodies; /** * Constructor. * * Sets up the object, initialise the variables, and splits and * stores the header and body of the input. * * @param string The input to decode * @access public */ function __construct($input) { list($header, $body) = $this->_splitBodyHeader($input); $this->_input = $input; $this->_header = $header; $this->_body = $body; $this->_decode_bodies = false; $this->_include_bodies = true; $this->_rfc822_bodies = false; } // BC function Mail_mimeDecode($input) { $this->__construct($input); } /** * Begins the decoding process. If called statically * it will create an object and call the decode() method * of it. * * @param array An array of various parameters that determine * various things: * include_bodies - Whether to include the body in the returned * object. * decode_bodies - Whether to decode the bodies * of the parts. (Transfer encoding) * decode_headers - Whether to decode headers, * - use "UTF8//IGNORE" to convert charset. * * input - If called statically, this will be treated * as the input * @return object Decoded results * @access public */ function decode($params = null) { // determine if this method has been called statically $isStatic = empty($this) || !is_a($this, __CLASS__); // Have we been called statically? // If so, create an object and pass details to that. if ($isStatic AND isset($params['input'])) { $obj = new Mail_mimeDecode($params['input']); $structure = $obj->decode($params); // Called statically but no input } elseif ($isStatic) { return PEAR::raiseError('Called statically and no input given'); // Called via an object } else { $this->_include_bodies = isset($params['include_bodies']) ? $params['include_bodies'] : false; $this->_decode_bodies = isset($params['decode_bodies']) ? $params['decode_bodies'] : false; $this->_decode_headers = isset($params['decode_headers']) ? $params['decode_headers'] : false; $this->_rfc822_bodies = isset($params['rfc_822bodies']) ? $params['rfc_822bodies'] : false; if (is_string($this->_decode_headers) && !function_exists('iconv')) { PEAR::raiseError('header decode conversion requested, however iconv is missing'); } $structure = $this->_decode($this->_header, $this->_body); if ($structure === false) { $structure = $this->raiseError($this->_error); } } return $structure; } /** * Performs the decoding. Decodes the body string passed to it * If it finds certain content-types it will call itself in a * recursive fashion * * @param string Header section * @param string Body section * @return object Results of decoding process * @access private */ function _decode($headers, $body, $default_ctype = 'text/plain') { $return = new stdClass; $return->headers = array(); $headers = $this->_parseHeaders($headers); foreach ($headers as $value) { $value['value'] = $this->_decodeHeader($value['value']); if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) { $return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]); $return->headers[strtolower($value['name'])][] = $value['value']; } elseif (isset($return->headers[strtolower($value['name'])])) { $return->headers[strtolower($value['name'])][] = $value['value']; } else { $return->headers[strtolower($value['name'])] = $value['value']; } } foreach ($headers as $key => $value) { $headers[$key]['name'] = strtolower($headers[$key]['name']); switch ($headers[$key]['name']) { case 'content-type': $content_type = $this->_parseHeaderValue($headers[$key]['value']); if (preg_match('/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) { $return->ctype_primary = $regs[1]; $return->ctype_secondary = $regs[2]; } if (isset($content_type['other'])) { foreach($content_type['other'] as $p_name => $p_value) { $return->ctype_parameters[$p_name] = $p_value; } } break; case 'content-disposition': $content_disposition = $this->_parseHeaderValue($headers[$key]['value']); $return->disposition = $content_disposition['value']; if (isset($content_disposition['other'])) { foreach($content_disposition['other'] as $p_name => $p_value) { $return->d_parameters[$p_name] = $p_value; } } break; case 'content-transfer-encoding': $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']); break; } } if (isset($content_type)) { switch (strtolower($content_type['value'])) { case 'text/plain': $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null; break; case 'text/html': $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null; break; case 'multipart/signed': // PGP $parts = $this->_boundarySplit($body, $content_type['other']['boundary'], true); $return->parts['msg_body'] = $parts[0]; list($part_header, $part_body) = $this->_splitBodyHeader($parts[1]); $return->parts['sig_hdr'] = $part_header; $return->parts['sig_body'] = $part_body; break; case 'multipart/parallel': case 'multipart/appledouble': // Appledouble mail case 'multipart/report': // RFC1892 case 'multipart/signed': // PGP case 'multipart/digest': case 'multipart/alternative': case 'multipart/related': case 'multipart/relative': //#20431 - android case 'multipart/mixed': case 'application/vnd.wap.multipart.related': if(!isset($content_type['other']['boundary'])){ $this->_error = 'No boundary found for ' . $content_type['value'] . ' part'; return false; } $default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain'; $parts = $this->_boundarySplit($body, $content_type['other']['boundary']); for ($i = 0; $i < count($parts); $i++) { list($part_header, $part_body) = $this->_splitBodyHeader($parts[$i]); $part = $this->_decode($part_header, $part_body, $default_ctype); if($part === false) $part = $this->raiseError($this->_error); $return->parts[] = $part; } break; case 'message/rfc822': case 'message/delivery-status': // #bug #18693 if ($this->_rfc822_bodies) { $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body); } $obj = new Mail_mimeDecode($body); $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies, 'decode_bodies' => $this->_decode_bodies, 'decode_headers' => $this->_decode_headers)); unset($obj); break; default: if(!isset($content_transfer_encoding['value'])) $content_transfer_encoding['value'] = '7bit'; $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body) : null; break; } } else { $ctype = explode('/', $default_ctype); $return->ctype_primary = $ctype[0]; $return->ctype_secondary = $ctype[1]; $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body) : $body) : null; } return $return; } /** * Given the output of the above function, this will return an * array of references to the parts, indexed by mime number. * * @param object $structure The structure to go through * @param string $mime_number Internal use only. * @return array Mime numbers */ function &getMimeNumbers(&$structure, $no_refs = false, $mime_number = '', $prepend = '') { $return = array(); if (!empty($structure->parts)) { if ($mime_number != '') { $structure->mime_id = $prepend . $mime_number; $return[$prepend . $mime_number] = &$structure; } for ($i = 0; $i < count($structure->parts); $i++) { if (!empty($structure->headers['content-type']) AND substr(strtolower($structure->headers['content-type']), 0, 8) == 'message/') { $prepend = $prepend . $mime_number . '.'; $_mime_number = ''; } else { $_mime_number = ($mime_number == '' ? $i + 1 : sprintf('%s.%s', $mime_number, $i + 1)); } $arr = &Mail_mimeDecode::getMimeNumbers($structure->parts[$i], $no_refs, $_mime_number, $prepend); foreach ($arr as $key => $val) { $no_refs ? $return[$key] = '' : $return[$key] = &$arr[$key]; } } } else { if ($mime_number == '') { $mime_number = '1'; } $structure->mime_id = $prepend . $mime_number; $no_refs ? $return[$prepend . $mime_number] = '' : $return[$prepend . $mime_number] = &$structure; } return $return; } /** * Given a string containing a header and body * section, this function will split them (at the first * blank line) and return them. * * @param string Input to split apart * @return array Contains header and body section * @access private */ function _splitBodyHeader($input) { if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) { return array($match[1], $match[2]); } // bug #17325 - empty bodies are allowed. - we just check that at least one line // of headers exist.. if (count(explode("\n",$input))) { return array($input, ''); } $this->_error = 'Could not split header and body'; return false; } /** * Parse headers given in $input and return * as assoc array. * * @param string Headers to parse * @return array Contains parsed headers * @access private */ function _parseHeaders($input) { if ($input !== '') { // Unfold the input $input = preg_replace("/\r?\n/", "\r\n", $input); //#7065 - wrapping.. with encoded stuff.. - probably not needed, // wrapping space should only get removed if the trailing item on previous line is a // encoded character $input = preg_replace("/=\r\n(\t| )+/", '=', $input); $input = preg_replace("/\r\n(\t| )+/", ' ', $input); $headers = explode("\r\n", trim($input)); $got_start = false; foreach ($headers as $value) { if (!$got_start) { // munge headers for mbox style from if ($value[0] == '>') { $value = substring($value, 1); // remove mbox > } if (substr($value,0,5) == 'From ') { $value = 'Return-Path: ' . substr($value, 5); } else { $got_start = true; } } $hdr_name = substr($value, 0, $pos = strpos($value, ':')); $hdr_value = substr($value, $pos+1); if($hdr_value[0] == ' ') { $hdr_value = substr($hdr_value, 1); } $return[] = array( 'name' => $hdr_name, 'value' => $hdr_value ); } } else { $return = array(); } return $return; } /** * Function to parse a header value, * extract first part, and any secondary * parts (after ;) This function is not as * robust as it could be. Eg. header comments * in the wrong place will probably break it. * * Extra things this can handle * filename*0=...... * filename*1=...... * * This is where lines are broken in, and need merging. * * filename*0*=ENC'lang'urlencoded data. * filename*1*=ENC'lang'urlencoded data. * * * * @param string Header value to parse * @return array Contains parsed result * @access private */ function _parseHeaderValue($input) { if (($pos = strpos($input, ';')) === false) { $input = $this->_decodeHeader($input); $return['value'] = trim($input); return $return; } $value = substr($input, 0, $pos); $value = $this->_decodeHeader($value); $return['value'] = trim($value); $input = trim(substr($input, $pos+1)); if (!strlen($input) > 0) { return $return; } // at this point input contains xxxx=".....";zzzz="...." // since we are dealing with quoted strings, we need to handle this properly.. $i = 0; $l = strlen($input); $key = ''; $val = false; // our string - including quotes.. $q = false; // in quote.. $lq = ''; // last quote.. while ($i < $l) { $c = $input[$i]; //var_dump(array('i'=>$i,'c'=>$c,'q'=>$q, 'lq'=>$lq, 'key'=>$key, 'val' =>$val)); $escaped = false; if ($c == '\\') { $i++; if ($i == $l-1) { // end of string. break; } $escaped = true; $c = $input[$i]; } // state - in key.. if ($val === false) { if (!$escaped && $c == '=') { $val = ''; $key = trim($key); $i++; continue; } if (!$escaped && $c == ';') { if ($key) { // a key without a value.. $key= trim($key); $return['other'][$key] = ''; } $key = ''; } $key .= $c; $i++; continue; } // state - in value.. (as $val is set..) if ($q === false) { // not in quote yet. if ((!strlen($val) || $lq !== false) && $c == ' ' || $c == "\t") { $i++; continue; // skip leading spaces after '=' or after '"' } // do not de-quote 'xxx*= itesm.. $key_is_trans = $key[strlen($key)-1] == '*'; if (!$key_is_trans && !$escaped && ($c == '"' || $c == "'")) { // start quoted area.. $q = $c; // in theory should not happen raw text in value part.. // but we will handle it as a merged part of the string.. $val = !strlen(trim($val)) ? '' : trim($val); $i++; continue; } // got end.... if (!$escaped && $c == ';') { $return['other'][$key] = trim($val); $val = false; $key = ''; $lq = false; $i++; continue; } $val .= $c; $i++; continue; } // state - in quote.. if (!$escaped && $c == $q) { // potential exit state.. // end of quoted string.. $lq = $q; $q = false; $i++; continue; } // normal char inside of quoted string.. $val.= $c; $i++; } // do we have anything left.. if (strlen(trim($key)) || $val !== false) { $val = trim($val); $return['other'][$key] = $val; } $clean_others = array(); // merge added values. eg. *1[*] foreach($return['other'] as $key =>$val) { if (preg_match('/\*[0-9]+\**$/', $key)) { $key = preg_replace('/(.*)\*[0-9]+(\**)$/', '\1\2', $key); if (isset($clean_others[$key])) { $clean_others[$key] .= $val; continue; } } $clean_others[$key] = $val; } // handle language translation of '*' ending others. foreach( $clean_others as $key =>$val) { if ( $key[strlen($key)-1] != '*') { $clean_others[strtolower($key)] = $val; continue; } unset($clean_others[$key]); $key = substr($key,0,-1); //extended-initial-value := [charset] "'" [language] "'" // extended-other-values $match = array(); $info = preg_match("/^([^']+)'([^']*)'(.*)$/", $val, $match); $clean_others[$key] = urldecode($match[3]); $clean_others[strtolower($key)] = $clean_others[$key]; $clean_others[strtolower($key).'-charset'] = $match[1]; $clean_others[strtolower($key).'-language'] = $match[2]; } $return['other'] = $clean_others; // decode values. foreach($return['other'] as $key =>$val) { $charset = isset($return['other'][$key . '-charset']) ? $return['other'][$key . '-charset'] : false; $return['other'][$key] = $this->_decodeHeader($val, $charset); } return $return; } /** * This function splits the input based * on the given boundary * * @param string Input to parse * @return array Contains array of resulting mime parts * @access private */ function _boundarySplit($input, $boundary, $eatline = false) { $parts = array(); $bs_possible = substr($boundary, 2, -2); $bs_check = '\"' . $bs_possible . '\"'; if ($boundary == $bs_check) { $boundary = $bs_possible; } // eatline is used by multipart/signed. $tmp = $eatline ? preg_split("/\r?\n--".preg_quote($boundary, '/')."(|--)\n/", $input) : preg_split("/--".preg_quote($boundary, '/')."((?=\s)|--)/", $input); $len = count($tmp) -1; for ($i = 1; $i < $len; $i++) { if (strlen(trim($tmp[$i]))) { $parts[] = $tmp[$i]; } } // add the last part on if it does not end with the 'closing indicator' if (!empty($tmp[$len]) && strlen(trim($tmp[$len])) && $tmp[$len][0] != '-') { $parts[] = $tmp[$len]; } return $parts; } /** * Given a header, this function will decode it * according to RFC2047. Probably not *exactly* * conformant, but it does pass all the given * examples (in RFC2047). * * @param string Input header value to decode * @return string Decoded header value * @access private */ function _decodeHeader($input, $default_charset=false) { if (!$this->_decode_headers) { return $input; } // Remove white space between encoded-words $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input); // For each encoded-word... while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) { $encoded = $matches[1]; $charset = $matches[2]; $encoding = $matches[3]; $text = $matches[4]; switch (strtolower($encoding)) { case 'b': $text = base64_decode($text); break; case 'q': $text = str_replace('_', ' ', $text); preg_match_all('/=([a-f0-9]{2})/i', $text, $matches); foreach($matches[1] as $value) $text = str_replace('='.$value, chr(hexdec($value)), $text); break; } if (is_string($this->_decode_headers)) { $conv = @iconv($charset, $this->_decode_headers, $text); $text = ($conv === false) ? $text : $conv; } $input = str_replace($encoded, $text, $input); } if ($default_charset && is_string($this->_decode_headers)) { $conv = @iconv($charset, $this->_decode_headers, $input); $input = ($conv === false) ? $input : $conv; } return $input; } /** * Given a body string and an encoding type, * this function will decode and return it. * * @param string Input body to decode * @param string Encoding type to use. * @return string Decoded body * @access private */ function _decodeBody($input, $encoding = '7bit') { switch (strtolower($encoding)) { case '7bit': return $input; break; case 'quoted-printable': return $this->_quotedPrintableDecode($input); break; case 'base64': return base64_decode($input); break; default: return $input; } } /** * Given a quoted-printable string, this * function will decode and return it. * * @param string Input body to decode * @return string Decoded body * @access private */ function _quotedPrintableDecode($input) { // Remove soft line breaks $input = preg_replace("/=\r?\n/", '', $input); // Replace encoded characters $cb = create_function('$matches', ' return chr(hexdec($matches[0]));'); $input = preg_replace_callback( '/=([a-f0-9]{2})/i', $cb, $input); return $input; } /** * Checks the input for uuencoded files and returns * an array of them. Can be called statically, eg: * * $files =& Mail_mimeDecode::uudecode($some_text); * * It will check for the begin 666 ... end syntax * however and won't just blindly decode whatever you * pass it. * * @param string Input body to look for attahcments in * @return array Decoded bodies, filenames and permissions * @access public * @author Unknown */ function &uudecode($input) { // Find all uuencoded sections preg_match_all("/begin ([0-7]{3}) (.+)\r?\n(.+)\r?\nend/Us", $input, $matches); for ($j = 0; $j < count($matches[3]); $j++) { $str = $matches[3][$j]; $filename = $matches[2][$j]; $fileperm = $matches[1][$j]; $file = ''; $str = preg_split("/\r?\n/", trim($str)); $strlen = count($str); for ($i = 0; $i < $strlen; $i++) { $pos = 1; $d = 0; $len=(int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077); while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) { $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20); $c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20); $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2)); $file .= chr(((($c2 - ' ') & 077) << 6) | (($c3 - ' ') & 077)); $pos += 4; $d += 3; } if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) { $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20); $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2)); $pos += 3; $d += 2; } if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) { $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); } } $files[] = array('filename' => $filename, 'fileperm' => $fileperm, 'filedata' => $file); } return $files; } /** * getSendArray() returns the arguments required for Mail::send() * used to build the arguments for a mail::send() call * * Usage: * $mailtext = Full email (for example generated by a template) * $decoder = new Mail_mimeDecode($mailtext); * $parts = $decoder->getSendArray(); * if (!PEAR::isError($parts) { * list($recipents,$headers,$body) = $parts; * $mail = Mail::factory('smtp'); * $mail->send($recipents,$headers,$body); * } else { * echo $parts->message; * } * @return mixed array of recipeint, headers,body or Pear_Error * @access public * @author Alan Knowles */ function getSendArray() { // prevent warning if this is not set $this->_decode_headers = FALSE; $headerlist =$this->_parseHeaders($this->_header); $to = ""; if (!$headerlist) { return $this->raiseError("Message did not contain headers"); } foreach($headerlist as $item) { $header[$item['name']] = $item['value']; switch (strtolower($item['name'])) { case "to": case "cc": case "bcc": $to .= ",".$item['value']; default: break; } } if ($to == "") { return $this->raiseError("Message did not contain any recipents"); } $to = substr($to,1); return array($to,$header,$this->_body); } /** * Returns a xml copy of the output of * Mail_mimeDecode::decode. Pass the output in as the * argument. This function can be called statically. Eg: * * $output = $obj->decode(); * $xml = Mail_mimeDecode::getXML($output); * * The DTD used for this should have been in the package. Or * alternatively you can get it from cvs, or here: * http://www.phpguru.org/xmail/xmail.dtd. * * @param object Input to convert to xml. This should be the * output of the Mail_mimeDecode::decode function * @return string XML version of input * @access public */ function getXML($input) { $crlf = "\r\n"; $output = '' . $crlf . '' . $crlf . '' . $crlf . Mail_mimeDecode::_getXML($input) . ''; return $output; } /** * Function that does the actual conversion to xml. Does a single * mimepart at a time. * * @param object Input to convert to xml. This is a mimepart object. * It may or may not contain subparts. * @param integer Number of tabs to indent * @return string XML version of input * @access private */ function _getXML($input, $indent = 1) { $htab = "\t"; $crlf = "\r\n"; $output = ''; $headers = @(array)$input->headers; foreach ($headers as $hdr_name => $hdr_value) { // Multiple headers with this name if (is_array($headers[$hdr_name])) { for ($i = 0; $i < count($hdr_value); $i++) { $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value[$i], $indent); } // Only one header of this sort } else { $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value, $indent); } } if (!empty($input->parts)) { for ($i = 0; $i < count($input->parts); $i++) { $output .= $crlf . str_repeat($htab, $indent) . '' . $crlf . Mail_mimeDecode::_getXML($input->parts[$i], $indent+1) . str_repeat($htab, $indent) . '' . $crlf; } } elseif (isset($input->body)) { $output .= $crlf . str_repeat($htab, $indent) . 'body . ']]>' . $crlf; } return $output; } /** * Helper function to _getXML(). Returns xml of a header. * * @param string Name of header * @param string Value of header * @param integer Number of tabs to indent * @return string XML version of input * @access private */ function _getXML_helper($hdr_name, $hdr_value, $indent) { $htab = "\t"; $crlf = "\r\n"; $return = ''; $new_hdr_value = ($hdr_name != 'received') ? Mail_mimeDecode::_parseHeaderValue($hdr_value) : array('value' => $hdr_value); $new_hdr_name = str_replace(' ', '-', ucwords(str_replace('-', ' ', $hdr_name))); // Sort out any parameters if (!empty($new_hdr_value['other'])) { foreach ($new_hdr_value['other'] as $paramname => $paramvalue) { $params[] = str_repeat($htab, $indent) . $htab . '' . $crlf . str_repeat($htab, $indent) . $htab . $htab . '' . htmlspecialchars($paramname) . '' . $crlf . str_repeat($htab, $indent) . $htab . $htab . '' . htmlspecialchars($paramvalue) . '' . $crlf . str_repeat($htab, $indent) . $htab . '' . $crlf; } $params = implode('', $params); } else { $params = ''; } $return = str_repeat($htab, $indent) . '
' . $crlf . str_repeat($htab, $indent) . $htab . '' . htmlspecialchars($new_hdr_name) . '' . $crlf . str_repeat($htab, $indent) . $htab . '' . htmlspecialchars($new_hdr_value['value']) . '' . $crlf . $params . str_repeat($htab, $indent) . '
' . $crlf; return $return; } } // End of class PK!B_Ǭ== Mail/smtp.phpnu[ * @author Chuck Hagenbuch * @copyright 2010-2017 Chuck Hagenbuch * @license http://opensource.org/licenses/BSD-3-Clause New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/Mail/ */ /** Error: Failed to create a Net_SMTP object */ define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000); /** Error: Failed to connect to SMTP server */ define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001); /** Error: SMTP authentication failure */ define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002); /** Error: No From: address has been provided */ define('PEAR_MAIL_SMTP_ERROR_FROM', 10003); /** Error: Failed to set sender */ define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004); /** Error: Failed to add recipient */ define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005); /** Error: Failed to send data */ define('PEAR_MAIL_SMTP_ERROR_DATA', 10006); /** * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class. * @access public * @package Mail * @version $Revision$ */ class Mail_smtp extends Mail { /** * SMTP connection object. * * @var object * @access private */ var $_smtp = null; /** * The list of service extension parameters to pass to the Net_SMTP * mailFrom() command. * * @var array */ var $_extparams = array(); /** * The SMTP host to connect to. * * @var string */ var $host = 'localhost'; /** * The port the SMTP server is on. * * @var integer */ var $port = 25; /** * Should SMTP authentication be used? * * This value may be set to true, false or the name of a specific * authentication method. * * If the value is set to true, the Net_SMTP package will attempt to use * the best authentication method advertised by the remote SMTP server. * * @var mixed */ var $auth = false; /** * The username to use if the SMTP server requires authentication. * * @var string */ var $username = ''; /** * The password to use if the SMTP server requires authentication. * * @var string */ var $password = ''; /** * Hostname or domain that will be sent to the remote SMTP server in the * HELO / EHLO message. * * @var string */ var $localhost = 'localhost'; /** * SMTP connection timeout value. NULL indicates no timeout. * * @var integer */ var $timeout = null; /** * Turn on Net_SMTP debugging? * * @var boolean $debug */ var $debug = false; /** * Indicates whether or not the SMTP connection should persist over * multiple calls to the send() method. * * @var boolean */ var $persist = false; /** * Use SMTP command pipelining (specified in RFC 2920) if the SMTP server * supports it. This speeds up delivery over high-latency connections. By * default, use the default value supplied by Net_SMTP. * * @var boolean */ var $pipelining; /** * The list of socket options * * @var array */ var $socket_options = array(); /** * Constructor. * * Instantiates a new Mail_smtp:: object based on the parameters * passed in. It looks for the following parameters: * host The server to connect to. Defaults to localhost. * port The port to connect to. Defaults to 25. * auth SMTP authentication. Defaults to none. * username The username to use for SMTP auth. No default. * password The password to use for SMTP auth. No default. * localhost The local hostname / domain. Defaults to localhost. * timeout The SMTP connection timeout. Defaults to none. * verp Whether to use VERP or not. Defaults to false. * DEPRECATED as of 1.2.0 (use setMailParams()). * debug Activate SMTP debug mode? Defaults to false. * persist Should the SMTP connection persist? * pipelining Use SMTP command pipelining * * If a parameter is present in the $params array, it replaces the * default. * * @param array Hash containing any parameters different from the * defaults. */ public function __construct($params) { if (isset($params['host'])) $this->host = $params['host']; if (isset($params['port'])) $this->port = $params['port']; if (isset($params['auth'])) $this->auth = $params['auth']; if (isset($params['username'])) $this->username = $params['username']; if (isset($params['password'])) $this->password = $params['password']; if (isset($params['localhost'])) $this->localhost = $params['localhost']; if (isset($params['timeout'])) $this->timeout = $params['timeout']; if (isset($params['debug'])) $this->debug = (bool)$params['debug']; if (isset($params['persist'])) $this->persist = (bool)$params['persist']; if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining']; if (isset($params['socket_options'])) $this->socket_options = $params['socket_options']; // Deprecated options if (isset($params['verp'])) { $this->addServiceExtensionParameter('XVERP', is_bool($params['verp']) ? null : $params['verp']); } } /** * Destructor implementation to ensure that we disconnect from any * potentially-alive persistent SMTP connections. */ public function __destruct() { $this->disconnect(); } /** * Implements Mail::send() function using SMTP. * * @param mixed $recipients Either a comma-seperated list of recipients * (RFC822 compliant), or an array of recipients, * each RFC822 valid. This may contain recipients not * specified in the headers, for Bcc:, resending * messages, etc. * * @param array $headers The array of headers to send with the mail, in an * associative array, where the array key is the * header name (e.g., 'Subject'), and the array value * is the header value (e.g., 'test'). The header * produced from those values would be 'Subject: * test'. * * @param string $body The full text of the message body, including any * MIME parts, etc. * * @return mixed Returns true on success, or a PEAR_Error * containing a descriptive error message on * failure. */ public function send($recipients, $headers, $body) { $result = $this->send_or_fail($recipients, $headers, $body); /* If persistent connections are disabled, destroy our SMTP object. */ if ($this->persist === false) { $this->disconnect(); } return $result; } protected function send_or_fail($recipients, $headers, $body) { /* If we don't already have an SMTP object, create one. */ $result = $this->getSMTPObject(); if (PEAR::isError($result)) { return $result; } if (!is_array($headers)) { return PEAR::raiseError('$headers must be an array'); } $this->_sanitizeHeaders($headers); $headerElements = $this->prepareHeaders($headers); if (is_a($headerElements, 'PEAR_Error')) { $this->_smtp->rset(); return $headerElements; } list($from, $textHeaders) = $headerElements; /* Since few MTAs are going to allow this header to be forged * unless it's in the MAIL FROM: exchange, we'll use * Return-Path instead of From: if it's set. */ if (!empty($headers['Return-Path'])) { $from = $headers['Return-Path']; } if (!isset($from)) { $this->_smtp->rset(); return PEAR::raiseError('No From: address has been provided', PEAR_MAIL_SMTP_ERROR_FROM); } $params = null; if (!empty($this->_extparams)) { foreach ($this->_extparams as $key => $val) { $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val); } } if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) { $error = $this->_error("Failed to set sender: $from", $res); $this->_smtp->rset(); return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER); } $recipients = $this->parseRecipients($recipients); if (is_a($recipients, 'PEAR_Error')) { $this->_smtp->rset(); return $recipients; } foreach ($recipients as $recipient) { $res = $this->_smtp->rcptTo($recipient); if (is_a($res, 'PEAR_Error')) { $error = $this->_error("Failed to add recipient: $recipient", $res); $this->_smtp->rset(); return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT); } } /* Send the message's headers and the body as SMTP data. */ $res = $this->_smtp->data($body, $textHeaders); list(,$args) = $this->_smtp->getResponse(); if (preg_match("/ queued as (.*)/", $args, $queued)) { $this->queued_as = $queued[1]; } /* we need the greeting; from it we can extract the authorative name of the mail server we've really connected to. * ideal if we're connecting to a round-robin of relay servers and need to track which exact one took the email */ $this->greeting = $this->_smtp->getGreeting(); if (is_a($res, 'PEAR_Error')) { $error = $this->_error('Failed to send data', $res); $this->_smtp->rset(); return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA); } return true; } /** * Connect to the SMTP server by instantiating a Net_SMTP object. * * @return mixed Returns a reference to the Net_SMTP object on success, or * a PEAR_Error containing a descriptive error message on * failure. * * @since 1.2.0 */ public function getSMTPObject() { if (is_object($this->_smtp) !== false) { return $this->_smtp; } include_once 'Net/SMTP.php'; $this->_smtp = new Net_SMTP($this->host, $this->port, $this->localhost, $this->pipelining, 0, $this->socket_options); /* If we still don't have an SMTP object at this point, fail. */ if (is_object($this->_smtp) === false) { return PEAR::raiseError('Failed to create a Net_SMTP object', PEAR_MAIL_SMTP_ERROR_CREATE); } /* Configure the SMTP connection. */ if ($this->debug) { $this->_smtp->setDebug(true); } /* Attempt to connect to the configured SMTP server. */ if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) { $error = $this->_error('Failed to connect to ' . $this->host . ':' . $this->port, $res); return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT); } /* Attempt to authenticate if authentication has been enabled. */ if ($this->auth) { $method = is_string($this->auth) ? $this->auth : ''; if (PEAR::isError($res = $this->_smtp->auth($this->username, $this->password, $method))) { $error = $this->_error("$method authentication failure", $res); $this->_smtp->rset(); return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH); } } return $this->_smtp; } /** * Add parameter associated with a SMTP service extension. * * @param string Extension keyword. * @param string Any value the keyword needs. * * @since 1.2.0 */ public function addServiceExtensionParameter($keyword, $value = null) { $this->_extparams[$keyword] = $value; } /** * Disconnect and destroy the current SMTP connection. * * @return boolean True if the SMTP connection no longer exists. * * @since 1.1.9 */ public function disconnect() { /* If we have an SMTP object, disconnect and destroy it. */ if (is_object($this->_smtp) && $this->_smtp->disconnect()) { $this->_smtp = null; } /* We are disconnected if we no longer have an SMTP object. */ return ($this->_smtp === null); } /** * Build a standardized string describing the current SMTP error. * * @param string $text Custom string describing the error context. * @param object $error Reference to the current PEAR_Error object. * * @return string A string describing the current SMTP error. * * @since 1.1.7 */ protected function _error($text, $error) { /* Split the SMTP response into a code and a response string. */ list($code, $response) = $this->_smtp->getResponse(); /* Build our standardized error string. */ return $text . ' [SMTP: ' . $error->getMessage() . " (code: $code, response: $response)]"; } } PK!wԐE;E;Mail/smtpmx.phpnu[ * @copyright 2010-2017 gERD Schaufelberger * @license http://opensource.org/licenses/BSD-3-Clause New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/Mail/ */ require_once 'Net/SMTP.php'; /** * SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class. * * * @access public * @author gERD Schaufelberger * @package Mail * @version $Revision$ */ class Mail_smtpmx extends Mail { /** * SMTP connection object. * * @var object * @access private */ var $_smtp = null; /** * The port the SMTP server is on. * @var integer * @see getservicebyname() */ var $port = 25; /** * Hostname or domain that will be sent to the remote SMTP server in the * HELO / EHLO message. * * @var string * @see posix_uname() */ var $mailname = 'localhost'; /** * SMTP connection timeout value. NULL indicates no timeout. * * @var integer */ var $timeout = 10; /** * use either PEAR:Net_DNS or getmxrr * * @var boolean */ var $withNetDns = true; /** * PEAR:Net_DNS_Resolver * * @var object */ var $resolver; /** * Whether to use VERP or not. If not a boolean, the string value * will be used as the VERP separators. * * @var mixed boolean or string */ var $verp = false; /** * Whether to use VRFY or not. * * @var boolean $vrfy */ var $vrfy = false; /** * Switch to test mode - don't send emails for real * * @var boolean $debug */ var $test = false; /** * Turn on Net_SMTP debugging? * * @var boolean $peardebug */ var $debug = false; /** * internal error codes * * translate internal error identifier to PEAR-Error codes and human * readable messages. * * @var boolean $debug * @todo as I need unique error-codes to identify what exactly went wrond * I did not use intergers as it should be. Instead I added a "namespace" * for each code. This avoids conflicts with error codes from different * classes. How can I use unique error codes and stay conform with PEAR? */ var $errorCode = array( 'not_connected' => array( 'code' => 1, 'msg' => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.' ), 'failed_vrfy_rcpt' => array( 'code' => 2, 'msg' => 'Recipient "{RCPT}" could not be veryfied.' ), 'failed_set_from' => array( 'code' => 3, 'msg' => 'Failed to set sender: {FROM}.' ), 'failed_set_rcpt' => array( 'code' => 4, 'msg' => 'Failed to set recipient: {RCPT}.' ), 'failed_send_data' => array( 'code' => 5, 'msg' => 'Failed to send mail to: {RCPT}.' ), 'no_from' => array( 'code' => 5, 'msg' => 'No from address has be provided.' ), 'send_data' => array( 'code' => 7, 'msg' => 'Failed to create Net_SMTP object.' ), 'no_mx' => array( 'code' => 8, 'msg' => 'No MX-record for {RCPT} found.' ), 'no_resolver' => array( 'code' => 9, 'msg' => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"' ), 'failed_rset' => array( 'code' => 10, 'msg' => 'RSET command failed, SMTP-connection corrupt.' ), ); /** * Constructor. * * Instantiates a new Mail_smtp:: object based on the parameters * passed in. It looks for the following parameters: * mailname The name of the local mail system (a valid hostname which matches the reverse lookup) * port smtp-port - the default comes from getservicebyname() and should work fine * timeout The SMTP connection timeout. Defaults to 30 seconds. * vrfy Whether to use VRFY or not. Defaults to false. * verp Whether to use VERP or not. Defaults to false. * test Activate test mode? Defaults to false. * debug Activate SMTP and Net_DNS debug mode? Defaults to false. * netdns whether to use PEAR:Net_DNS or the PHP build in function getmxrr, default is true * * If a parameter is present in the $params array, it replaces the * default. * * @access public * @param array Hash containing any parameters different from the * defaults. * @see _Mail_smtpmx() */ function __construct($params) { if (isset($params['mailname'])) { $this->mailname = $params['mailname']; } else { // try to find a valid mailname if (function_exists('posix_uname')) { $uname = posix_uname(); $this->mailname = $uname['nodename']; } } // port number if (isset($params['port'])) { $this->_port = $params['port']; } else { $this->_port = getservbyname('smtp', 'tcp'); } if (isset($params['timeout'])) $this->timeout = $params['timeout']; if (isset($params['verp'])) $this->verp = $params['verp']; if (isset($params['test'])) $this->test = $params['test']; if (isset($params['peardebug'])) $this->test = $params['peardebug']; if (isset($params['netdns'])) $this->withNetDns = $params['netdns']; } /** * Constructor wrapper for PHP4 * * @access public * @param array Hash containing any parameters different from the defaults * @see __construct() */ function Mail_smtpmx($params) { $this->__construct($params); register_shutdown_function(array(&$this, '__destruct')); } /** * Destructor implementation to ensure that we disconnect from any * potentially-alive persistent SMTP connections. */ function __destruct() { if (is_object($this->_smtp)) { $this->_smtp->disconnect(); $this->_smtp = null; } } /** * Implements Mail::send() function using SMTP direct delivery * * @access public * @param mixed $recipients in RFC822 style or array * @param array $headers The array of headers to send with the mail. * @param string $body The full text of the message body, * @return mixed Returns true on success, or a PEAR_Error */ function send($recipients, $headers, $body) { if (!is_array($headers)) { return PEAR::raiseError('$headers must be an array'); } $result = $this->_sanitizeHeaders($headers); if (is_a($result, 'PEAR_Error')) { return $result; } // Prepare headers $headerElements = $this->prepareHeaders($headers); if (is_a($headerElements, 'PEAR_Error')) { return $headerElements; } list($from, $textHeaders) = $headerElements; // use 'Return-Path' if possible if (!empty($headers['Return-Path'])) { $from = $headers['Return-Path']; } if (!isset($from)) { return $this->_raiseError('no_from'); } // Prepare recipients $recipients = $this->parseRecipients($recipients); if (is_a($recipients, 'PEAR_Error')) { return $recipients; } foreach ($recipients as $rcpt) { list($user, $host) = explode('@', $rcpt); $mx = $this->_getMx($host); if (is_a($mx, 'PEAR_Error')) { return $mx; } if (empty($mx)) { $info = array('rcpt' => $rcpt); return $this->_raiseError('no_mx', $info); } $connected = false; foreach ($mx as $mserver => $mpriority) { $this->_smtp = new Net_SMTP($mserver, $this->port, $this->mailname); // configure the SMTP connection. if ($this->debug) { $this->_smtp->setDebug(true); } // attempt to connect to the configured SMTP server. $res = $this->_smtp->connect($this->timeout); if (is_a($res, 'PEAR_Error')) { $this->_smtp = null; continue; } // connection established if ($res) { $connected = true; break; } } if (!$connected) { $info = array( 'host' => implode(', ', array_keys($mx)), 'port' => $this->port, 'rcpt' => $rcpt, ); return $this->_raiseError('not_connected', $info); } // Verify recipient if ($this->vrfy) { $res = $this->_smtp->vrfy($rcpt); if (is_a($res, 'PEAR_Error')) { $info = array('rcpt' => $rcpt); return $this->_raiseError('failed_vrfy_rcpt', $info); } } // mail from: $args['verp'] = $this->verp; $res = $this->_smtp->mailFrom($from, $args); if (is_a($res, 'PEAR_Error')) { $info = array('from' => $from); return $this->_raiseError('failed_set_from', $info); } // rcpt to: $res = $this->_smtp->rcptTo($rcpt); if (is_a($res, 'PEAR_Error')) { $info = array('rcpt' => $rcpt); return $this->_raiseError('failed_set_rcpt', $info); } // Don't send anything in test mode if ($this->test) { $result = $this->_smtp->rset(); $res = $this->_smtp->rset(); if (is_a($res, 'PEAR_Error')) { return $this->_raiseError('failed_rset'); } $this->_smtp->disconnect(); $this->_smtp = null; return true; } // Send data $res = $this->_smtp->data($body, $textHeaders); if (is_a($res, 'PEAR_Error')) { $info = array('rcpt' => $rcpt); return $this->_raiseError('failed_send_data', $info); } $this->_smtp->disconnect(); $this->_smtp = null; } return true; } /** * Recieve mx rexords for a spciefied host * * The MX records * * @access private * @param string $host mail host * @return mixed sorted */ function _getMx($host) { $mx = array(); if ($this->withNetDns) { $res = $this->_loadNetDns(); if (is_a($res, 'PEAR_Error')) { return $res; } $response = $this->resolver->query($host, 'MX'); if (!$response) { return false; } foreach ($response->answer as $rr) { if ($rr->type == 'MX') { $mx[$rr->exchange] = $rr->preference; } } } else { $mxHost = array(); $mxWeight = array(); if (!getmxrr($host, $mxHost, $mxWeight)) { return false; } for ($i = 0; $i < count($mxHost); ++$i) { $mx[$mxHost[$i]] = $mxWeight[$i]; } } asort($mx); return $mx; } /** * initialize PEAR:Net_DNS_Resolver * * @access private * @return boolean true on success */ function _loadNetDns() { if (is_object($this->resolver)) { return true; } if (!include_once 'Net/DNS.php') { return $this->_raiseError('no_resolver'); } $this->resolver = new Net_DNS_Resolver(); if ($this->debug) { $this->resolver->test = 1; } return true; } /** * raise standardized error * * include additional information in error message * * @access private * @param string $id maps error ids to codes and message * @param array $info optional information in associative array * @see _errorCode */ function _raiseError($id, $info = array()) { $code = $this->errorCode[$id]['code']; $msg = $this->errorCode[$id]['msg']; // include info to messages if (!empty($info)) { $search = array(); $replace = array(); foreach ($info as $key => $value) { array_push($search, '{' . strtoupper($key) . '}'); array_push($replace, $value); } $msg = str_replace($search, $replace, $msg); } return PEAR::raiseError($msg, $code); } } PK!؛JJMail/mimePart.phpnu[ * Copyright (c) 2003-2006, PEAR * 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 authors, 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. * * @category Mail * @package Mail_Mime * @author Richard Heyes * @author Cipriano Groenendal * @author Sean Coates * @author Aleksander Machniak * @copyright 2003-2006 PEAR * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime */ /** * Require PEAR * * This package depends on PEAR to raise errors. */ require_once 'PEAR.php'; /** * The Mail_mimePart class is used to create MIME E-mail messages * * This class enables you to manipulate and build a mime email * from the ground up. The Mail_Mime class is a userfriendly api * to this class for people who aren't interested in the internals * of mime mail. * This class however allows full control over the email. * * @category Mail * @package Mail_Mime * @author Richard Heyes * @author Cipriano Groenendal * @author Sean Coates * @author Aleksander Machniak * @copyright 2003-2006 PEAR * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime */ class Mail_mimePart { /** * The encoding type of this part * * @var string */ protected $encoding; /** * An array of subparts * * @var array */ protected $subparts = array(); /** * The output of this part after being built * * @var string */ protected $encoded; /** * Headers for this part * * @var array */ protected $headers = array(); /** * The body of this part (not encoded) * * @var string */ protected $body; /** * The location of file with body of this part (not encoded) * * @var string */ protected $body_file; /** * The short text of multipart part preamble (RFC2046 5.1.1) * * @var string */ protected $preamble; /** * The end-of-line sequence * * @var string */ protected $eol = "\r\n"; /** * Constructor. * * Sets up the object. * * @param string $body The body of the mime part if any. * @param array $params An associative array of optional parameters: * - content_type: The content type for this part eg multipart/mixed * - encoding: The encoding to use, 7bit, 8bit, base64, or quoted-printable * - charset: Content character set * - cid: Content ID to apply * - disposition: Content disposition, inline or attachment * - filename: Filename parameter for content disposition * - description: Content description * - name_encoding: Encoding of the attachment name (Content-Type) * By default filenames are encoded using RFC2231 * Here you can set RFC2047 encoding (quoted-printable * or base64) instead * - filename_encoding: Encoding of the attachment filename (Content-Disposition) * See 'name_encoding' * - headers_charset: Charset of the headers e.g. filename, description. * If not set, 'charset' will be used * - eol: End of line sequence. Default: "\r\n" * - headers: Hash array with additional part headers. Array keys * can be in form of : * - body_file: Location of file with part's body (instead of $body) * - preamble: short text of multipart part preamble (RFC2046 5.1.1) */ public function __construct($body = '', $params = array()) { if (!empty($params['eol'])) { $this->eol = $params['eol']; } else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat. $this->eol = MAIL_MIMEPART_CRLF; } // Additional part headers if (!empty($params['headers']) && is_array($params['headers'])) { $headers = $params['headers']; } foreach ($params as $key => $value) { switch ($key) { case 'encoding': $this->encoding = $value; $headers['Content-Transfer-Encoding'] = $value; break; case 'cid': $headers['Content-ID'] = '<' . $value . '>'; break; case 'location': $headers['Content-Location'] = $value; break; case 'body_file': $this->body_file = $value; break; case 'preamble': $this->preamble = $value; break; // for backward compatibility case 'dfilename': $params['filename'] = $value; break; } } // Default content-type if (empty($params['content_type'])) { $params['content_type'] = 'text/plain'; } // Content-Type $headers['Content-Type'] = $params['content_type']; if (!empty($params['charset'])) { $charset = "charset={$params['charset']}"; // place charset parameter in the same line, if possible if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) { $headers['Content-Type'] .= '; '; } else { $headers['Content-Type'] .= ';' . $this->eol . ' '; } $headers['Content-Type'] .= $charset; // Default headers charset if (!isset($params['headers_charset'])) { $params['headers_charset'] = $params['charset']; } } // header values encoding parameters $h_charset = !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII'; $h_language = !empty($params['language']) ? $params['language'] : null; $h_encoding = !empty($params['name_encoding']) ? $params['name_encoding'] : null; if (!empty($params['filename'])) { $headers['Content-Type'] .= ';' . $this->eol; $headers['Content-Type'] .= $this->buildHeaderParam( 'name', $params['filename'], $h_charset, $h_language, $h_encoding ); } // Content-Disposition if (!empty($params['disposition'])) { $headers['Content-Disposition'] = $params['disposition']; if (!empty($params['filename'])) { $headers['Content-Disposition'] .= ';' . $this->eol; $headers['Content-Disposition'] .= $this->buildHeaderParam( 'filename', $params['filename'], $h_charset, $h_language, !empty($params['filename_encoding']) ? $params['filename_encoding'] : null ); } // add attachment size $size = $this->body_file ? filesize($this->body_file) : strlen($body); if ($size) { $headers['Content-Disposition'] .= ';' . $this->eol . ' size=' . $size; } } if (!empty($params['description'])) { $headers['Content-Description'] = $this->encodeHeader( 'Content-Description', $params['description'], $h_charset, $h_encoding, $this->eol ); } // Search and add existing headers' parameters foreach ($headers as $key => $value) { $items = explode(':', $key); if (count($items) == 2) { $header = $items[0]; $param = $items[1]; if (isset($headers[$header])) { $headers[$header] .= ';' . $this->eol; } $headers[$header] .= $this->buildHeaderParam( $param, $value, $h_charset, $h_language, $h_encoding ); unset($headers[$key]); } } // Default encoding if (!isset($this->encoding)) { $this->encoding = '7bit'; } // Assign stuff to member variables $this->encoded = array(); $this->headers = $headers; $this->body = $body; } /** * Encodes and returns the email. Also stores * it in the encoded member variable * * @param string $boundary Pre-defined boundary string * * @return An associative array containing two elements, * body and headers. The headers element is itself * an indexed array. On error returns PEAR error object. */ public function encode($boundary=null) { $encoded =& $this->encoded; if (count($this->subparts)) { $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime()); $eol = $this->eol; $this->headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; $encoded['body'] = ''; if ($this->preamble) { $encoded['body'] .= $this->preamble . $eol . $eol; } for ($i = 0; $i < count($this->subparts); $i++) { $encoded['body'] .= '--' . $boundary . $eol; $tmp = $this->subparts[$i]->encode(); if (is_a($tmp, 'PEAR_Error')) { return $tmp; } foreach ($tmp['headers'] as $key => $value) { $encoded['body'] .= $key . ': ' . $value . $eol; } $encoded['body'] .= $eol . $tmp['body'] . $eol; } $encoded['body'] .= '--' . $boundary . '--' . $eol; } else if ($this->body) { $encoded['body'] = $this->getEncodedData($this->body, $this->encoding); } else if ($this->body_file) { // Temporarily reset magic_quotes_runtime for file reads and writes if (version_compare(PHP_VERSION, '5.4.0', '<')) { $magic_quotes = @ini_set('magic_quotes_runtime', 0); } $body = $this->getEncodedDataFromFile($this->body_file, $this->encoding); if (isset($magic_quotes)) { @ini_set('magic_quotes_runtime', $magic_quotes); } if (is_a($body, 'PEAR_Error')) { return $body; } $encoded['body'] = $body; } else { $encoded['body'] = ''; } // Add headers to $encoded $encoded['headers'] =& $this->headers; return $encoded; } /** * Encodes and saves the email into file or stream. * Data will be appended to the file/stream. * * @param mixed $filename Existing file location * or file pointer resource * @param string $boundary Pre-defined boundary string * @param boolean $skip_head True if you don't want to save headers * * @return array An associative array containing message headers * or PEAR error object * @since 1.6.0 */ public function encodeToFile($filename, $boundary = null, $skip_head = false) { if (!is_resource($filename)) { if (file_exists($filename) && !is_writable($filename)) { $err = self::raiseError('File is not writeable: ' . $filename); return $err; } if (!($fh = fopen($filename, 'ab'))) { $err = self::raiseError('Unable to open file: ' . $filename); return $err; } } else { $fh = $filename; } // Temporarily reset magic_quotes_runtime for file reads and writes if (version_compare(PHP_VERSION, '5.4.0', '<')) { $magic_quotes = @ini_set('magic_quotes_runtime', 0); } $res = $this->encodePartToFile($fh, $boundary, $skip_head); if (!is_resource($filename)) { fclose($fh); } if (isset($magic_quotes)) { @ini_set('magic_quotes_runtime', $magic_quotes); } return is_a($res, 'PEAR_Error') ? $res : $this->headers; } /** * Encodes given email part into file * * @param string $fh Output file handle * @param string $boundary Pre-defined boundary string * @param boolean $skip_head True if you don't want to save headers * * @return array True on sucess or PEAR error object */ protected function encodePartToFile($fh, $boundary = null, $skip_head = false) { $eol = $this->eol; if (count($this->subparts)) { $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime()); $this->headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; } if (!$skip_head) { foreach ($this->headers as $key => $value) { fwrite($fh, $key . ': ' . $value . $eol); } $f_eol = $eol; } else { $f_eol = ''; } if (count($this->subparts)) { if ($this->preamble) { fwrite($fh, $f_eol . $this->preamble . $eol); $f_eol = $eol; } for ($i = 0; $i < count($this->subparts); $i++) { fwrite($fh, $f_eol . '--' . $boundary . $eol); $res = $this->subparts[$i]->encodePartToFile($fh); if (is_a($res, 'PEAR_Error')) { return $res; } $f_eol = $eol; } fwrite($fh, $eol . '--' . $boundary . '--' . $eol); } else if ($this->body) { fwrite($fh, $f_eol); fwrite($fh, $this->getEncodedData($this->body, $this->encoding)); } else if ($this->body_file) { fwrite($fh, $f_eol); $res = $this->getEncodedDataFromFile( $this->body_file, $this->encoding, $fh ); if (is_a($res, 'PEAR_Error')) { return $res; } } return true; } /** * Adds a subpart to current mime part and returns * a reference to it * * @param mixed $body The body of the subpart or Mail_mimePart object * @param array $params The parameters for the subpart, same * as the $params argument for constructor * * @return Mail_mimePart A reference to the part you just added. */ public function addSubpart($body, $params = null) { if ($body instanceof Mail_mimePart) { $part = $body; } else { $part = new Mail_mimePart($body, $params); } $this->subparts[] = $part; return $part; } /** * Returns encoded data based upon encoding passed to it * * @param string $data The data to encode. * @param string $encoding The encoding type to use, 7bit, base64, * or quoted-printable. * * @return string Encoded data string */ protected function getEncodedData($data, $encoding) { switch ($encoding) { case 'quoted-printable': return self::quotedPrintableEncode($data, 76, $this->eol); break; case 'base64': return rtrim(chunk_split(base64_encode($data), 76, $this->eol)); break; case '8bit': case '7bit': default: return $data; } } /** * Returns encoded data based upon encoding passed to it * * @param string $filename Data file location * @param string $encoding The encoding type to use, 7bit, base64, * or quoted-printable. * @param resource $fh Output file handle. If set, data will be * stored into it instead of returning it * * @return string Encoded data or PEAR error object */ protected function getEncodedDataFromFile($filename, $encoding, $fh = null) { if (!is_readable($filename)) { $err = self::raiseError('Unable to read file: ' . $filename); return $err; } if (!($fd = fopen($filename, 'rb'))) { $err = self::raiseError('Could not open file: ' . $filename); return $err; } $data = ''; switch ($encoding) { case 'quoted-printable': while (!feof($fd)) { $buffer = self::quotedPrintableEncode(fgets($fd), 76, $this->eol); if ($fh) { fwrite($fh, $buffer); } else { $data .= $buffer; } } break; case 'base64': while (!feof($fd)) { // Should read in a multiple of 57 bytes so that // the output is 76 bytes per line. Don't use big chunks // because base64 encoding is memory expensive $buffer = fread($fd, 57 * 9198); // ca. 0.5 MB $buffer = base64_encode($buffer); $buffer = chunk_split($buffer, 76, $this->eol); if (feof($fd)) { $buffer = rtrim($buffer); } if ($fh) { fwrite($fh, $buffer); } else { $data .= $buffer; } } break; case '8bit': case '7bit': default: while (!feof($fd)) { $buffer = fread($fd, 1048576); // 1 MB if ($fh) { fwrite($fh, $buffer); } else { $data .= $buffer; } } } fclose($fd); if (!$fh) { return $data; } } /** * Encodes data to quoted-printable standard. * * @param string $input The data to encode * @param int $line_max Optional max line length. Should * not be more than 76 chars * @param string $eol End-of-line sequence. Default: "\r\n" * * @return string Encoded data */ public static function quotedPrintableEncode($input , $line_max = 76, $eol = "\r\n") { /* // imap_8bit() is extremely fast, but doesn't handle properly some characters if (function_exists('imap_8bit') && $line_max == 76) { $input = preg_replace('/\r?\n/', "\r\n", $input); $input = imap_8bit($input); if ($eol != "\r\n") { $input = str_replace("\r\n", $eol, $input); } return $input; } */ $lines = preg_split("/\r?\n/", $input); $escape = '='; $output = ''; foreach ($lines as $idx => $line) { $newline = ''; $i = 0; while (isset($line[$i])) { $char = $line[$i]; $dec = ord($char); $i++; if (($dec == 32) && (!isset($line[$i]))) { // convert space at eol only $char = '=20'; } elseif ($dec == 9 && isset($line[$i])) { ; // Do nothing if a TAB is not on eol } elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) { // Escape unprintable chars $char = $escape . sprintf('%02X', $dec); } elseif (($dec == 46) && (($newline == '') || ((strlen($newline) + strlen(".=")) > $line_max && isset($line[$i]))) ) { // Bug #9722: convert full-stop at bol, // some Windows servers need this, won't break anything (cipri) // Bug #11731: full-stop at bol also needs to be encoded // if this line would push us over the line_max limit. $char = '=2E'; } // EOL is not counted if ((strlen($newline) + strlen($char) == $line_max) && !isset($line[$i]) ) { ; // no soft break is needed if we're the last char } elseif ((strlen($newline) + strlen($char)) >= $line_max) { // soft line break; " =\r\n" is okay $output .= $newline . $escape . $eol; $newline = ''; } $newline .= $char; } // end of for $output .= $newline . $eol; unset($lines[$idx]); } // Don't want last crlf $output = substr($output, 0, -1 * strlen($eol)); return $output; } /** * Encodes the parameter of a header. * * @param string $name The name of the header-parameter * @param string $value The value of the paramter * @param string $charset The characterset of $value * @param string $language The language used in $value * @param string $encoding Parameter encoding. If not set, parameter value * is encoded according to RFC2231 * @param int $maxLength The maximum length of a line. Defauls to 75 * * @return string */ protected function buildHeaderParam($name, $value, $charset = null, $language = null, $encoding = null, $maxLength = 75 ) { // RFC 2045: // value needs encoding if contains non-ASCII chars or is longer than 78 chars if (!preg_match('#[^\x20-\x7E]#', $value)) { $token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D' . '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#'; if (!preg_match($token_regexp, $value)) { // token if (strlen($name) + strlen($value) + 3 <= $maxLength) { return " {$name}={$value}"; } } else { // quoted-string $quoted = addcslashes($value, '\\"'); if (strlen($name) + strlen($quoted) + 5 <= $maxLength) { return " {$name}=\"{$quoted}\""; } } } // RFC2047: use quoted-printable/base64 encoding if ($encoding == 'quoted-printable' || $encoding == 'base64') { return $this->buildRFC2047Param($name, $value, $charset, $encoding); } // RFC2231: $encValue = preg_replace_callback( '/([^\x21\x23\x24\x26\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])/', array($this, 'encodeReplaceCallback'), $value ); $value = "$charset'$language'$encValue"; $header = " {$name}*={$value}"; if (strlen($header) <= $maxLength) { return $header; } $preLength = strlen(" {$name}*0*="); $maxLength = max(16, $maxLength - $preLength - 3); $maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|"; $headers = array(); $headCount = 0; while ($value) { $matches = array(); $found = preg_match($maxLengthReg, $value, $matches); if ($found) { $headers[] = " {$name}*{$headCount}*={$matches[0]}"; $value = substr($value, strlen($matches[0])); } else { $headers[] = " {$name}*{$headCount}*={$value}"; $value = ''; } $headCount++; } $headers = implode(';' . $this->eol, $headers); return $headers; } /** * Encodes header parameter as per RFC2047 if needed * * @param string $name The parameter name * @param string $value The parameter value * @param string $charset The parameter charset * @param string $encoding Encoding type (quoted-printable or base64) * @param int $maxLength Encoded parameter max length. Default: 76 * * @return string Parameter line */ protected function buildRFC2047Param($name, $value, $charset, $encoding = 'quoted-printable', $maxLength = 76 ) { // WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in // parameter of a MIME Content-Type or Content-Disposition field", // but... it's supported by many clients/servers $quoted = ''; if ($encoding == 'base64') { $value = base64_encode($value); $prefix = '=?' . $charset . '?B?'; $suffix = '?='; // 2 x SPACE, 2 x '"', '=', ';' $add_len = strlen($prefix . $suffix) + strlen($name) + 6; $len = $add_len + strlen($value); while ($len > $maxLength) { // We can cut base64-encoded string every 4 characters $real_len = floor(($maxLength - $add_len) / 4) * 4; $_quote = substr($value, 0, $real_len); $value = substr($value, $real_len); $quoted .= $prefix . $_quote . $suffix . $this->eol . ' '; $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';' $len = strlen($value) + $add_len; } $quoted .= $prefix . $value . $suffix; } else { // quoted-printable $value = $this->encodeQP($value); $prefix = '=?' . $charset . '?Q?'; $suffix = '?='; // 2 x SPACE, 2 x '"', '=', ';' $add_len = strlen($prefix . $suffix) + strlen($name) + 6; $len = $add_len + strlen($value); while ($len > $maxLength) { $length = $maxLength - $add_len; // don't break any encoded letters if (preg_match("/^(.{0,$length}[^\=][^\=])/", $value, $matches)) { $_quote = $matches[1]; } $quoted .= $prefix . $_quote . $suffix . $this->eol . ' '; $value = substr($value, strlen($_quote)); $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';' $len = strlen($value) + $add_len; } $quoted .= $prefix . $value . $suffix; } return " {$name}=\"{$quoted}\""; } /** * Return charset for mbstring functions. * Replace ISO-2022-JP with ISO-2022-JP-MS to convert Windows dependent * characters. * * @param string $charset A original charset * * @return string A charset for mbstring * @since 1.10.8 */ protected static function mbstringCharset($charset) { $mb_charset = $charset; if ($charset == 'ISO-2022-JP') { $mb_charset = 'ISO-2022-JP-MS'; } return $mb_charset; } /** * Encodes a header as per RFC2047 * * @param string $name The header name * @param string $value The header data to encode * @param string $charset Character set name * @param string $encoding Encoding name (base64 or quoted-printable) * @param string $eol End-of-line sequence. Default: "\r\n" * * @return string Encoded header data (without a name) * @since 1.6.1 */ public static function encodeHeader($name, $value, $charset = 'ISO-8859-1', $encoding = 'quoted-printable', $eol = "\r\n" ) { // Structured headers $comma_headers = array( 'from', 'to', 'cc', 'bcc', 'sender', 'reply-to', 'resent-from', 'resent-to', 'resent-cc', 'resent-bcc', 'resent-sender', 'resent-reply-to', 'mail-reply-to', 'mail-followup-to', 'return-receipt-to', 'disposition-notification-to', ); $other_headers = array( 'references', 'in-reply-to', 'message-id', 'resent-message-id', ); $name = strtolower($name); if (in_array($name, $comma_headers)) { $separator = ','; } else if (in_array($name, $other_headers)) { $separator = ' '; } if (!$charset) { $charset = 'ISO-8859-1'; } // exploding quoted strings as well as some regexes below do not // work properly with some charset e.g. ISO-2022-JP, we'll use UTF-8 $mb = $charset != 'UTF-8' && function_exists('mb_convert_encoding'); $mb_charset = Mail_mimePart::mbstringCharset($charset); // Structured header (make sure addr-spec inside is not encoded) if (!empty($separator)) { // Simple e-mail address regexp $email_regexp = '([^\s<]+|("[^\r\n"]+"))@[^\s"]+'; if ($mb) { $value = mb_convert_encoding($value, 'UTF-8', $mb_charset); } $parts = Mail_mimePart::explodeQuotedString("[\t$separator]", $value); $value = ''; foreach ($parts as $part) { $part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part); $part = trim($part); if (!$part) { continue; } if ($value) { $value .= $separator == ',' ? $separator . ' ' : ' '; } else { $value = $name . ': '; } // let's find phrase (name) and/or addr-spec if (preg_match('/^<' . $email_regexp . '>$/', $part)) { $value .= $part; } else if (preg_match('/^' . $email_regexp . '$/', $part)) { // address without brackets and without name $value .= $part; } else if (preg_match('/<*' . $email_regexp . '>*$/', $part, $matches)) { // address with name (handle name) $address = $matches[0]; $word = str_replace($address, '', $part); $word = trim($word); // check if phrase requires quoting if ($word) { // non-ASCII: require encoding if (preg_match('#([^\s\x21-\x7E]){1}#', $word)) { if ($word[0] == '"' && $word[strlen($word)-1] == '"') { // de-quote quoted-string, encoding changes // string to atom $word = substr($word, 1, -1); $word = preg_replace('/\\\\([\\\\"])/', '$1', $word); } if ($mb) { $word = mb_convert_encoding($word, $mb_charset, 'UTF-8'); } // find length of last line if (($pos = strrpos($value, $eol)) !== false) { $last_len = strlen($value) - $pos; } else { $last_len = strlen($value); } $word = Mail_mimePart::encodeHeaderValue( $word, $charset, $encoding, $last_len, $eol ); } else if (($word[0] != '"' || $word[strlen($word)-1] != '"') && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word) ) { // ASCII: quote string if needed $word = '"'.addcslashes($word, '\\"').'"'; } } $value .= $word.' '.$address; } else { if ($mb) { $part = mb_convert_encoding($part, $mb_charset, 'UTF-8'); } // addr-spec not found, don't encode (?) $value .= $part; } // RFC2822 recommends 78 characters limit, use 76 from RFC2047 $value = wordwrap($value, 76, $eol . ' '); } // remove header name prefix (there could be EOL too) $value = preg_replace( '/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value ); } else { // Unstructured header // non-ASCII: require encoding if (preg_match('#([^\s\x21-\x7E]){1}#', $value)) { if ($value[0] == '"' && $value[strlen($value)-1] == '"') { if ($mb) { $value = mb_convert_encoding($value, 'UTF-8', $mb_charset); } // de-quote quoted-string, encoding changes // string to atom $value = substr($value, 1, -1); $value = preg_replace('/\\\\([\\\\"])/', '$1', $value); if ($mb) { $value = mb_convert_encoding($value, $mb_charset, 'UTF-8'); } } $value = Mail_mimePart::encodeHeaderValue( $value, $charset, $encoding, strlen($name) + 2, $eol ); } else if (strlen($name.': '.$value) > 78) { // ASCII: check if header line isn't too long and use folding $value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value); $tmp = wordwrap($name . ': ' . $value, 78, $eol . ' '); $value = preg_replace('/^' . $name . ':\s*/', '', $tmp); // hard limit 998 (RFC2822) $value = wordwrap($value, 998, $eol . ' ', true); } } return $value; } /** * Explode quoted string * * @param string $delimiter Delimiter expression string for preg_match() * @param string $string Input string * * @return array String tokens array */ protected static function explodeQuotedString($delimiter, $string) { $result = array(); $strlen = strlen($string); $quoted_string = '"(?:[^"\\\\]|\\\\.)*"'; for ($p=$i=0; $i < $strlen; $i++) { if ($string[$i] === '"') { $r = preg_match("/$quoted_string/", $string, $matches, 0, $i); if (!$r || empty($matches[0])) { break; } $i += strlen($matches[0]) - 1; } else if (preg_match("/$delimiter/", $string[$i])) { $result[] = substr($string, $p, $i - $p); $p = $i + 1; } } $result[] = substr($string, $p); return $result; } /** * Encodes a header value as per RFC2047 * * @param string $value The header data to encode * @param string $charset Character set name * @param string $encoding Encoding name (base64 or quoted-printable) * @param int $prefix_len Prefix length. Default: 0 * @param string $eol End-of-line sequence. Default: "\r\n" * * @return string Encoded header data * @since 1.6.1 */ public static function encodeHeaderValue($value, $charset, $encoding, $prefix_len = 0, $eol = "\r\n") { // #17311: Use multibyte aware method (requires mbstring extension) if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) { return $result; } // Generate the header using the specified params and dynamicly // determine the maximum length of such strings. // 75 is the value specified in the RFC. $encoding = $encoding == 'base64' ? 'B' : 'Q'; $prefix = '=?' . $charset . '?' . $encoding .'?'; $suffix = '?='; $maxLength = 75 - strlen($prefix . $suffix); $maxLength1stLine = $maxLength - $prefix_len; if ($encoding == 'B') { // Base64 encode the entire string $value = base64_encode($value); // We can cut base64 every 4 characters, so the real max // we can get must be rounded down. $maxLength = $maxLength - ($maxLength % 4); $maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4); $cutpoint = $maxLength1stLine; $output = ''; while ($value) { // Split translated string at every $maxLength $part = substr($value, 0, $cutpoint); $value = substr($value, $cutpoint); $cutpoint = $maxLength; // RFC 2047 specifies that any split header should // be separated by a CRLF SPACE. if ($output) { $output .= $eol . ' '; } $output .= $prefix . $part . $suffix; } $value = $output; } else { // quoted-printable encoding has been selected $value = Mail_mimePart::encodeQP($value); // This regexp will break QP-encoded text at every $maxLength // but will not break any encoded letters. $reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|"; $reg2nd = "|(.{0,$maxLength}[^\=][^\=])|"; if (strlen($value) > $maxLength1stLine) { // Begin with the regexp for the first line. $reg = $reg1st; $output = ''; while ($value) { // Split translated string at every $maxLength // But make sure not to break any translated chars. $found = preg_match($reg, $value, $matches); // After this first line, we need to use a different // regexp for the first line. $reg = $reg2nd; // Save the found part and encapsulate it in the // prefix & suffix. Then remove the part from the // $value_out variable. if ($found) { $part = $matches[0]; $len = strlen($matches[0]); $value = substr($value, $len); } else { $part = $value; $value = ''; } // RFC 2047 specifies that any split header should // be separated by a CRLF SPACE if ($output) { $output .= $eol . ' '; } $output .= $prefix . $part . $suffix; } $value = $output; } else { $value = $prefix . $value . $suffix; } } return $value; } /** * Encodes the given string using quoted-printable * * @param string $str String to encode * * @return string Encoded string * @since 1.6.0 */ public static function encodeQP($str) { // Bug #17226 RFC 2047 restricts some characters // if the word is inside a phrase, permitted chars are only: // ASCII letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_" // "=", "_", "?" must be encoded $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/'; $str = preg_replace_callback( $regexp, array('Mail_mimePart', 'qpReplaceCallback'), $str ); return str_replace(' ', '_', $str); } /** * Encodes the given string using base64 or quoted-printable. * This method makes sure that encoded-word represents an integral * number of characters as per RFC2047. * * @param string $str String to encode * @param string $charset Character set name * @param string $encoding Encoding name (base64 or quoted-printable) * @param int $prefix_len Prefix length. Default: 0 * @param string $eol End-of-line sequence. Default: "\r\n" * * @return string Encoded string * @since 1.8.0 */ public static function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n") { if (!function_exists('mb_substr') || !function_exists('mb_strlen')) { return; } $encoding = $encoding == 'base64' ? 'B' : 'Q'; // 75 is the value specified in the RFC $prefix = '=?' . $charset . '?'.$encoding.'?'; $suffix = '?='; $maxLength = 75 - strlen($prefix . $suffix); $mb_charset = Mail_mimePart::mbstringCharset($charset); // A multi-octet character may not be split across adjacent encoded-words // So, we'll loop over each character // mb_stlen() with wrong charset will generate a warning here and return null $length = mb_strlen($str, $mb_charset); $result = ''; $line_length = $prefix_len; if ($encoding == 'B') { // base64 $start = 0; $prev = ''; for ($i=1; $i<=$length; $i++) { // See #17311 $chunk = mb_substr($str, $start, $i-$start, $mb_charset); $chunk = base64_encode($chunk); $chunk_len = strlen($chunk); if ($line_length + $chunk_len == $maxLength || $i == $length) { if ($result) { $result .= "\n"; } $result .= $chunk; $line_length = 0; $start = $i; } else if ($line_length + $chunk_len > $maxLength) { if ($result) { $result .= "\n"; } if ($prev) { $result .= $prev; } $line_length = 0; $start = $i - 1; } else { $prev = $chunk; } } } else { // quoted-printable // see encodeQP() $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/'; for ($i=0; $i<=$length; $i++) { $char = mb_substr($str, $i, 1, $mb_charset); // RFC recommends underline (instead of =20) in place of the space // that's one of the reasons why we're not using iconv_mime_encode() if ($char == ' ') { $char = '_'; $char_len = 1; } else { $char = preg_replace_callback( $regexp, array('Mail_mimePart', 'qpReplaceCallback'), $char ); $char_len = strlen($char); } if ($line_length + $char_len > $maxLength) { if ($result) { $result .= "\n"; } $line_length = 0; } $result .= $char; $line_length += $char_len; } } if ($result) { $result = $prefix .str_replace("\n", $suffix.$eol.' '.$prefix, $result).$suffix; } return $result; } /** * Callback function to replace extended characters (\x80-xFF) with their * ASCII values (RFC2047: quoted-printable) * * @param array $matches Preg_replace's matches array * * @return string Encoded character string */ protected static function qpReplaceCallback($matches) { return sprintf('=%02X', ord($matches[1])); } /** * Callback function to replace extended characters (\x80-xFF) with their * ASCII values (RFC2231) * * @param array $matches Preg_replace's matches array * * @return string Encoded character string */ protected static function encodeReplaceCallback($matches) { return sprintf('%%%02X', ord($matches[1])); } /** * PEAR::raiseError implementation * * @param string $message A text error message * * @return PEAR_Error Instance of PEAR_Error */ public static function raiseError($message) { // PEAR::raiseError() is not PHP 5.4 compatible return new PEAR_Error($message); } } PK!Bshh Mail/mock.phpnu[ * @copyright 2010-2017 Chuck Hagenbuch * @license http://opensource.org/licenses/BSD-3-Clause New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/Mail/ */ /** * Mock implementation of the PEAR Mail:: interface for testing. * @access public * @package Mail * @version $Revision$ */ class Mail_mock extends Mail { /** * Array of messages that have been sent with the mock. * * @var array */ public $sentMessages = array(); /** * Callback before sending mail. * * @var callback */ protected $_preSendCallback; /** * Callback after sending mai. * * @var callback */ protected $_postSendCallback; /** * Constructor. * * Instantiates a new Mail_mock:: object based on the parameters * passed in. It looks for the following parameters, both optional: * preSendCallback Called before an email would be sent. * postSendCallback Called after an email would have been sent. * * @param array Hash containing any parameters. */ public function __construct($params) { if (isset($params['preSendCallback']) && is_callable($params['preSendCallback'])) { $this->_preSendCallback = $params['preSendCallback']; } if (isset($params['postSendCallback']) && is_callable($params['postSendCallback'])) { $this->_postSendCallback = $params['postSendCallback']; } } /** * Implements Mail_mock::send() function. Silently discards all * mail. * * @param mixed $recipients Either a comma-seperated list of recipients * (RFC822 compliant), or an array of recipients, * each RFC822 valid. This may contain recipients not * specified in the headers, for Bcc:, resending * messages, etc. * * @param array $headers The array of headers to send with the mail, in an * associative array, where the array key is the * header name (ie, 'Subject'), and the array value * is the header value (ie, 'test'). The header * produced from those values would be 'Subject: * test'. * * @param string $body The full text of the message body, including any * Mime parts, etc. * * @return mixed Returns true on success, or a PEAR_Error * containing a descriptive error message on * failure. */ public function send($recipients, $headers, $body) { if ($this->_preSendCallback) { call_user_func_array($this->_preSendCallback, array(&$this, $recipients, $headers, $body)); } $entry = array('recipients' => $recipients, 'headers' => $headers, 'body' => $body); $this->sentMessages[] = $entry; if ($this->_postSendCallback) { call_user_func_array($this->_postSendCallback, array(&$this, $recipients, $headers, $body)); } return true; } } PK!@iE\\ Mail/mail.phpnu[ * @copyright 2010-2017 Chuck Hagenbuch * @license http://opensource.org/licenses/BSD-3-Clause New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/Mail/ */ /** * internal PHP-mail() implementation of the PEAR Mail:: interface. * @package Mail * @version $Revision$ */ class Mail_mail extends Mail { /** * Any arguments to pass to the mail() function. * @var string */ var $_params = ''; /** * Constructor. * * Instantiates a new Mail_mail:: object based on the parameters * passed in. * * @param array $params Extra arguments for the mail() function. */ public function __construct($params = null) { // The other mail implementations accept parameters as arrays. // In the interest of being consistent, explode an array into // a string of parameter arguments. if (is_array($params)) { $this->_params = join(' ', $params); } else { $this->_params = $params; } /* Because the mail() function may pass headers as command * line arguments, we can't guarantee the use of the standard * "\r\n" separator. Instead, we use the system's native line * separator. */ if (defined('PHP_EOL')) { $this->sep = PHP_EOL; } else { $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n"; } } /** * Implements Mail_mail::send() function using php's built-in mail() * command. * * @param mixed $recipients Either a comma-seperated list of recipients * (RFC822 compliant), or an array of recipients, * each RFC822 valid. This may contain recipients not * specified in the headers, for Bcc:, resending * messages, etc. * * @param array $headers The array of headers to send with the mail, in an * associative array, where the array key is the * header name (ie, 'Subject'), and the array value * is the header value (ie, 'test'). The header * produced from those values would be 'Subject: * test'. * * @param string $body The full text of the message body, including any * Mime parts, etc. * * @return mixed Returns true on success, or a PEAR_Error * containing a descriptive error message on * failure. */ public function send($recipients, $headers, $body) { if (!is_array($headers)) { return PEAR::raiseError('$headers must be an array'); } $result = $this->_sanitizeHeaders($headers); if (is_a($result, 'PEAR_Error')) { return $result; } // If we're passed an array of recipients, implode it. if (is_array($recipients)) { $recipients = implode(', ', $recipients); } // Get the Subject out of the headers array so that we can // pass it as a seperate argument to mail(). $subject = ''; if (isset($headers['Subject'])) { $subject = $headers['Subject']; unset($headers['Subject']); } // Also remove the To: header. The mail() function will add its own // To: header based on the contents of $recipients. unset($headers['To']); // Flatten the headers out. $headerElements = $this->prepareHeaders($headers); if (is_a($headerElements, 'PEAR_Error')) { return $headerElements; } list(, $text_headers) = $headerElements; // We only use mail()'s optional fifth parameter if the additional // parameters have been provided and we're not running in safe mode. if (empty($this->_params) || ini_get('safe_mode')) { $result = mail($recipients, $subject, $body, $text_headers); } else { $result = mail($recipients, $subject, $body, $text_headers, $this->_params); } // If the mail() function returned failure, we need to create a // PEAR_Error object and return it instead of the boolean result. if ($result === false) { $result = PEAR::raiseError('mail() returned failure'); } return $result; } } PK!*z%-%- Structures/LinkedList/Double.phpnu[next()) work * as expected. * * To use this package, derive a child class from * Structures_LinkedList_DoubleNode and add data to the object. Then use the * Structures_LinkedList_Double class to access the nodes. * * PHP version 5 * * LICENSE: Copyright 2006 Dan Scott * * 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. * * @category Structures * @package Structures_LinkedList_Double * @author Dan Scott * @copyright 2006 Dan Scott * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @version CVS: $Id: Double.php -1 $ * @link http://pear.php.net/package/Structures_LinkedList * @example double_link_example.php * * @todo Add some actual error conditions **/ require_once 'PEAR/Exception.php'; require_once 'Single.php'; // {{{ class Structures_LinkedList_Double /** * The Structures_LinkedList_Double class represents a linked list structure * composed of {@link Structures_LinkedList_DoubleNode} objects. * * @category Structures * @package Structures_LinkedList_Double * @author Dan Scott * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @link http://pear.php.net/package/Structures_LinkedList */ class Structures_LinkedList_Double extends Structures_LinkedList_Single implements Iterator { // {{{ properties /** * Tail node of the linked list * @var Structures_LinkedList_DoubleNode */ protected $tail_node; // }}} // {{{ Constructor: function __construct() /** * Structures_LinkedList_Double constructor * * @param Structures_LinkedList_DoubleNode $root root node for the * linked list */ function __construct(Structures_LinkedList_DoubleNode $root = null) { if ($root) { $this->tail_node = $root; } else { $this->tail_node = null; } parent::__construct($root); } // }}} // {{{ Destructor: function __destruct() /** * Structures_LinkedList_Double destructor * * If we do not destroy all of the references in the linked list, * we will quickly run out of memory for large / complex structures. * */ function __destruct() { /* * Starting with root node, set last node = root_node * get next node * if next node exists: * delete last node's references to next node and previous node * make the old next node the new last node */ if (!$last_node = $this->root_node) { return; } while (($next_node = $last_node->next()) !== false) { $last_node->setNext(null); $last_node->setPrevious(null); $last_node = $next_node; } $this->current = null; $this->root_node = null; $this->tail_node = null; $last_node = null; $next_node = null; } // }}} // {{{ function end() /** * Sets the pointer for the linked list to its last node * * @return Structures_LinkedList_DoubleNode last node in the linked list */ public function end() { if ($this->tail_node) { $this->current = $this->tail_node; } else { $this->current = null; } return $this->current; } // }}} // {{{ function previous() /** * Sets the pointer for the linked list to the previous node and * returns that node * * @return Structures_LinkedList_DoubleNode previous node in the linked list */ public function previous() { if (!$this->current()->previous()) { return false; } $this->current = $this->current()->previous(); return $this->current(); } // }}} // {{{ function insertNode() /** * Inserts a {@link Structures_LinkedList_DoubleNode} object into the linked * list, based on a reference node that already exists in the list. * * @param Structures_LinkedList_DoubleNode $new_node New node to add to the list * @param Structures_LinkedList_DoubleNode $existing_node Reference position node * @param bool $before Insert new node before or after the existing node * * @return bool Success or failure **/ public function insertNode($new_node, $existing_node, $before = false) { if (!$this->root_node) { $this->__construct($new_node); } // Now add the node according to the requested mode switch ($before) { case true: $previous_node = $existing_node->previous(); if ($previous_node) { $previous_node->setNext($new_node); $new_node->setPrevious($previous_node); } else { // The existing node must be root node; make new node root $this->root_node = $new_node; $new_node->setPrevious(); } $new_node->setNext($existing_node); $existing_node->setPrevious($new_node); break; case false: $new_node->setPrevious($existing_node); $next_node = $existing_node->next(); if ($next_node) { $new_node->setNext($next_node); $next_node->setPrevious($new_node); } else { // The existing node must have been the tail node $this->tail_node = $new_node; } $existing_node->setNext($new_node); break; } return true; } // }}} // {{{ protected function getTailNode() /** * Returns the tail node of the linked list. * * This is a cheap operation for a doubly-linked list. * * @return bool Success or failure **/ protected function getTailNode() { return $this->tail_node; } // }}} // {{{ function deleteNode() /** * Deletes a {@link Structures_LinkedList_DoubleNode} from the list. * * @param Structures_LinkedList_DoubleNode $node Node to delete. * * @return null */ public function deleteNode($node) { /* If this is the root node, and there are more nodes in the list, * make the next node the new root node before deleting this node. */ if ($node === $this->root_node) { $this->root_node = $node->next(); } /* If this is the tail node, and there are more nodes in the list, * make the previous node the tail node before deleting this node */ if ($node === $this->tail_node) { $this->tail_node = $node->previous(); } /* If this is the current node, and there are other nodes in the list, * try making the previous node the current node so that next() works * as expected. * * If that fails, make the next node the current node. * * If that fails, null isn't such a bad place to be. */ if ($node === $this->current) { if ($node->previous()) { $this->current = $node->previous(); } elseif ($node->next()) { $this->current = $node->next(); } else { $this->current = null; } } $node->__destruct(); } // }}} } // }}} // {{{ class Structures_LinkedList_DoubleNode /** * The Structures_LinkedList_DoubleNode class represents a node in a * {@link Structures_LinkedList_Double} linked list structure. * * @category Structures * @package Structures_LinkedList_Double * @author Dan Scott * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @link http://pear.php.net/package/Structures_LinkedList */ class Structures_LinkedList_DoubleNode extends Structures_LinkedList_SingleNode { // {{{ properties /** * Previous node in the linked list * @var Structures_LinkedList_DoubleNode */ protected $previous; // }}} // {{{ Constructor: function __construct() /** * Structures_LinkedList_DoubleNode constructor */ public function __construct() { $this->next = null; $this->previous = null; } // }}} // {{{ Destructor: function __destruct() /** * Removes node from the list, adjusting the related nodes accordingly. * * This is a problem if the node is the root node for the list. * At this point, however, we do not have access to the list itself. Hmm. */ public function __destruct() { $next = $this->next(); $previous = $this->previous(); if ($previous && $next) { $previous->setNext($next); $next->setPrevious($previous); } elseif ($previous) { $previous->setNext(); } elseif ($next) { $next->setPrevious(); } } // }}} // {{{ function previous() /** * Return the previous node in the linked list * * @return Structures_LinkedList_DoubleNode previous node in the linked list */ public function previous() { if ($this->previous) { return $this->previous; } else { return false; } } // }}} // {{{ function setPrevious() /** * Sets the pointer for the previous node in the linked list * to the specified node * * @param Structures_LinkedList_DoubleNode $node new previous node * in the linked list * * @return Structures_LinkedList_DoubleNode new previous node in * the linked list */ public function setPrevious($node = null) { $this->previous = $node; return $this->previous; } // }}} } // }}} ?> PK!p:p: Structures/LinkedList/Single.phpnu[next()) work * as expected. * * To use this package, derive a child class from * Structures_LinkedList_SingleNode and add data to the object. Then use the * Structures_LinkedList_Single class to access the nodes. * * PHP version 5 * * LICENSE: Copyright 2006 Dan Scott * * 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. * * @category Structures * @package Structures_LinkedList_Single * @author Dan Scott * @copyright 2006 Dan Scott * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @version CVS: $Id: Single.php -1 $ * @link http://pear.php.net/package/Structures_LinkedList_Single * @example single_link_example.php * * @todo Add some actual error conditions **/ require_once 'PEAR/Exception.php'; // {{{ class Structures_LinkedList_Single /** * The Structures_LinkedList_Single class represents a linked list structure * composed of {@link Structures_LinkedList_SingleNode} objects. * * @category Structures * @package Structures_LinkedList_Single * @author Dan Scott * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @link http://pear.php.net/package/Structures_LinkedList_Single */ class Structures_LinkedList_Single implements Iterator { // {{{ properties /** * Current node in the linked list * @var Structures_LinkedList_SingleNode */ protected $current; /** * Root node of the linked list * @var Structures_LinkedList_SingleNode */ protected $root_node; /** * The linked list contains no nodes */ const ERROR_EMPTY = -1; public static $messages = array( self::ERROR_EMPTY => 'No nodes in this linked list' ); // }}} // {{{ Constructor: function __construct() /** * Structures_LinkedList_Single constructor * * @param Structures_LinkedList_SingleNode $root root node for the * linked list */ function __construct(Structures_LinkedList_SingleNode $root = null) { if ($root) { $this->root_node = $root; $this->current = $root; } else { $this->root_node = null; $this->current = null; } } // }}} // {{{ Destructor: function __destruct() /** * Structures_LinkedList_Single destructor * * If we do not destroy all of the references in the linked list, * we will quickly run out of memory for large / complex structures. * */ function __destruct() { /* * Starting with root node, set last node = root_node * get next node * if next node exists, delete last node reference to next node */ if (!$last_node = $this->root_node) { return; } while (($next_node = $last_node->next()) !== false) { $last_node->setNext(null); $temp_node = $last_node; $last_node = $next_node; unset($temp_node); } $this->current = null; $this->root_node = null; $last_node = null; $next_node = null; } // }}} // {{{ function current() /** * Returns the current node in the linked list * * @return Structures_LinkedList_SingleNode current node in the linked list */ public function current() { return $this->current; } // }}} // {{{ function rewind() /** * Sets the pointer for the linked list to the root node * * @return Structures_LinkedList_SingleNode root node in the linked list */ public function rewind() { if ($this->root_node) { $this->current = $this->root_node; } else { $this->current = null; } return $this->current; } // }}} // {{{ function end() /** * Sets the pointer for the linked list to the root node * * @return Structures_LinkedList_SingleNode root node in the linked list */ public function end() { $this->current = $this->getTailNode(); return $this->current; } // }}} // {{{ function key() /** * Stub for Iterator interface that simply returns the current node * * @return Structures_LinkedList_SingleNode current node in the linked list */ public function key() { return $this->current; } // }}} // {{{ function valid() /** * Stub for Iterator interface that simply returns the current node * * @return Structures_LinkedList_SingleNode current node in the linked list */ public function valid() { return $this->current(); } // }}} // {{{ function next() /** * Sets the pointer for the linked list to the next node and * returns that node * * @return Structures_LinkedList_SingleNode next node in the linked list */ public function next() { if (!$this->current) { return false; } $this->current = $this->current()->next(); return $this->current; } // }}} // {{{ function previous() /** * Sets the pointer for the linked list to the previous node and * returns that node * * @return Structures_LinkedList_SingleNode previous node in the linked list */ public function previous() { if (!$this->current) { return false; } $this->current = $this->_getPreviousNode(); return $this->current; } // }}} // {{{ protected function getTailNode() /** * Returns the tail node of the linked list. * * This is an expensive operation! * * @return bool Success or failure **/ protected function getTailNode() { $tail_node = $this->root_node; while (($y = $tail_node->next()) !== false) { $tail_node = $y; } return $tail_node; } // }}} // {{{ private function _getPreviousNode() /** * Returns the node prior to the current node in the linked list. * * This is an expensive operation for a singly linked list! * * @param Structures_LinkedList_SingleNode $node (Optional) Specific node * for which we want to find the previous node * * @return Structures_LinkedList_SingleNode Previous node **/ private function _getPreviousNode($node = null) { if (!$node) { $node = $this->current; } $prior_node = $this->root_node; while (($y = $prior_node->next()) !== false) { if ($y == $node) { return $prior_node; } $prior_node = $y; } return null; } // }}} // {{{ function appendNode() /** * Adds a {@link Structures_LinkedList_SingleNode} object to the end of * the linked list. * * @param Structures_LinkedList_SingleNode $new_node New node to append * * @return bool Success or failure **/ public function appendNode(Structures_LinkedList_SingleNode $new_node) { if (!$this->root_node) { $this->__construct($new_node); return true; } // This is just a special case of insertNode() $this->insertNode($new_node, $this->getTailNode()); return true; } // }}} // {{{ function insertNode() /** * Inserts a {@link Structures_LinkedList_SingleNode} object into the linked * list, based on a reference node that already exists in the list. * * @param Structures_LinkedList_SingleNode $new_node New node to add to * the list * @param Structures_LinkedList_SingleNode $existing_node Reference * position node * @param bool $before Insert new node * before or after the existing node * * @return bool Success or failure **/ public function insertNode($new_node, $existing_node, $before = false) { if (!$this->root_node) { $this->__construct($new_node); return true; } // Now add the node according to the requested mode switch ($before) { case true: if ($existing_node === $this->root_node) { $this->root_node = $new_node; } $previous_node = $this->_getPreviousNode($existing_node); if ($previous_node) { $previous_node->setNext($new_node); } $new_node->setNext($existing_node); break; case false: $next_node = $existing_node->next(); if ($next_node) { $new_node->setNext($next_node); } $existing_node->setNext($new_node); break; } return true; } // }}} // {{{ function prependNode() /** * Adds a {@link Structures_LinkedList_SingleNode} object to the start * of the linked list. * * @param Structures_LinkedList_SingleNode $new_node Node to prepend * to the list * * @return bool Success or failure **/ public function prependNode(Structures_LinkedList_SingleNode $new_node) { if (!$this->root_node) { $this->__construct($new_node); return true; } // This is just a special case of insertNode() $this->insertNode($new_node, $this->root_node, true); return true; } // }}} // {{{ function deleteNode() /** * Deletes a {@link Structures_LinkedList_SingleNode} from the list. * * @param Structures_LinkedList_SingleNode $node Node to delete. * * @return null */ public function deleteNode($node) { /* If this is the root node, and there are more nodes in the list, * make the next node the new root node before deleting this node. */ if ($node === $this->root_node) { $this->root_node = $node->next(); } /* If this is the current node, make the next node the current node. * * If that fails, null isn't such a bad place to be. */ if ($node === $this->current) { if ($node->next()) { $this->current = $node->next(); } else { $this->current = null; } } $node->__destruct(); } // }}} } // }}} // {{{ class Structures_LinkedList_SingleNode /** * The Structures_LinkedList_SingleNode class represents a node in a * {@link Structures_LinkedList_Single} linked list structure. * * @category Structures * @package Structures_LinkedList_Single * @author Dan Scott * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 * @link http://pear.php.net/package/Structures_LinkedList_Single */ class Structures_LinkedList_SingleNode { // {{{ properties /** * Next node in the linked list * @var Structures_LinkedList_SingleNode */ protected $next; // }}} // {{{ Constructor: function __construct() /** * Structures_LinkedList_SingleNode constructor */ public function __construct() { $this->next = null; } // }}} // {{{ Destructor: function __destruct() /** * Removes node from the list, adjusting the related nodes accordingly. * * This is a problem if the node is the root node for the list. * At this point, however, we do not have access to the list itself. Hmm. */ public function __destruct() { } // }}} // {{{ function next() /** * Return the next node in the linked list * * @return Structures_LinkedList_SingleNode next node in the linked list */ public function next() { if ($this->next) { return $this->next; } else { return false; } } // }}} // {{{ function previous() /** * Return the previous node in the linked list * * Stub method for Structures_LinkedList_DoubleNode to override. * * @return Structures_LinkedList_SingleNode previous node in the linked list */ public function previous() { return false; } // }}} // {{{ function setNext() /** * Sets the pointer for the next node in the linked list to the * specified node * * @param Structures_LinkedList_SingleNode $node new next node in * the linked list * * @return Structures_LinkedList_SingleNode new next node in the linked list */ public function setNext($node = null) { $this->next = $node; return $this->next; } // }}} // {{{ function setPrevious() /** * Sets the pointer for the next node in the linked list to the * specified node * * Stub method for Structures_LinkedList_DoubleNode to override. * * @param Structures_LinkedList_SingleNode $node new next node in * the linked list * * @return Structures_LinkedList_SingleNode new next node in the linked list */ public function setPrevious($node = null) { return false; } // }}} } // }}} ?> PK!UyvStructures/Graph.phpnu[ | // +-----------------------------------------------------------------------------+ // /** * The Graph.php file contains the definition of the Structures_Graph class * * @package Structures_Graph */ /* dependencies {{{ */ require_once 'PEAR.php'; require_once 'Structures/Graph/Node.php'; /* }}} */ define('STRUCTURES_GRAPH_ERROR_GENERIC', 100); /* class Structures_Graph {{{ */ /** * The Structures_Graph class represents a graph data structure. * * A Graph is a data structure composed by a set of nodes, connected by arcs. * Graphs may either be directed or undirected. In a directed graph, arcs are * directional, and can be traveled only one way. In an undirected graph, arcs * are bidirectional, and can be traveled both ways. * * @author Srgio Carvalho * @copyright (c) 2004 by Srgio Carvalho * @package Structures_Graph */ /* }}} */ class Structures_Graph { /** * List of node objects in this graph * @access private */ var $_nodes = array(); /** * If the graph is directed or not * @access private */ var $_directed = false; /** * Constructor * * @param boolean $directed Set to true if the graph is directed. * Set to false if it is not directed. */ public function __construct($directed = true) { $this->_directed = $directed; } /** * Old constructor (PHP4-style; kept for BC with extending classes) * * @param boolean $directed Set to true if the graph is directed. * Set to false if it is not directed. * * @return void */ public function Structures_Graph($directed = true) { $this->__construct($directed); } /** * Return true if a graph is directed * * @return boolean true if the graph is directed */ public function isDirected() { return (boolean) $this->_directed; } /** * Add a Node to the Graph * * @param Structures_Graph_Node $newNode The node to be added. * * @return void */ public function addNode(&$newNode) { // We only add nodes if (!is_a($newNode, 'Structures_Graph_Node')) { return Pear::raiseError( 'Structures_Graph::addNode received an object that is not' . ' a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC ); } //Graphs are node *sets*, so duplicates are forbidden. // We allow nodes that are exactly equal, but disallow equal references. foreach ($this->_nodes as $key => $node) { /* ZE1 equality operators choke on the recursive cycle introduced by the _graph field in the Node object. So, we'll check references the hard way (change $this->_nodes[$key] and check if the change reflects in $node) */ $savedData = $this->_nodes[$key]; $referenceIsEqualFlag = false; $this->_nodes[$key] = true; if ($node === true) { $this->_nodes[$key] = false; if ($node === false) { $referenceIsEqualFlag = true; } } $this->_nodes[$key] = $savedData; if ($referenceIsEqualFlag) { return Pear::raiseError( 'Structures_Graph::addNode received an object that is' . ' a duplicate for this dataset', STRUCTURES_GRAPH_ERROR_GENERIC ); } } $this->_nodes[] =& $newNode; $newNode->setGraph($this); } /** * Remove a Node from the Graph * * @param Structures_Graph_Node $node The node to be removed from the graph * * @return void * @todo This is unimplemented */ public function removeNode(&$node) { } /** * Return the node set, in no particular order. * For ordered node sets, use a Graph Manipulator insted. * * @return array The set of nodes in this graph * @see Structures_Graph_Manipulator_TopologicalSorter */ public function &getNodes() { return $this->_nodes; } } ?> PK!C + +Structures/Graph/Node.phpnu[ | // +-----------------------------------------------------------------------------+ // /** * This file contains the definition of the Structures_Graph_Node class * * @see Structures_Graph_Node * @package Structures_Graph */ /* dependencies {{{ */ /** */ require_once 'PEAR.php'; /** */ require_once 'Structures/Graph.php'; /* }}} */ /* class Structures_Graph_Node {{{ */ /** * The Structures_Graph_Node class represents a Node that can be member of a * graph node set. * * A graph node can contain data. Under this API, the node contains default data, * and key index data. It behaves, thus, both as a regular data node, and as a * dictionary (or associative array) node. * * Regular data is accessed via getData and setData. Key indexed data is accessed * via getMetadata and setMetadata. * * @author Srgio Carvalho * @copyright (c) 2004 by Srgio Carvalho * @package Structures_Graph */ /* }}} */ class Structures_Graph_Node { /* fields {{{ */ /** * @access private */ var $_data = null; /** @access private */ var $_metadata = array(); /** @access private */ var $_arcs = array(); /** @access private */ var $_graph = null; /* }}} */ /* Constructor {{{ */ /** * * Constructor * * @access public */ function __construct() { } /* }}} */ /* getGraph {{{ */ /** * * Node graph getter * * @return Structures_Graph Graph where node is stored * @access public */ function &getGraph() { return $this->_graph; } /* }}} */ /* setGraph {{{ */ /** * * Node graph setter. This method should not be called directly. Use Graph::addNode instead. * * @param Structures_Graph Set the graph for this node. * @see Structures_Graph::addNode() * @access public */ function setGraph(&$graph) { $this->_graph =& $graph; } /* }}} */ /* getData {{{ */ /** * * Node data getter. * * Each graph node can contain a reference to one variable. This is the getter for that reference. * * @return mixed Data stored in node * @access public */ function &getData() { return $this->_data; } /* }}} */ /* setData {{{ */ /** * * Node data setter * * Each graph node can contain a reference to one variable. This is the setter for that reference. * * @return mixed Data to store in node * @access public */ function setData(&$data) { $this->_data =& $data; } /* }}} */ /* metadataKeyExists {{{ */ /** * * Test for existence of metadata under a given key. * * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an * associative array or in a dictionary. This method tests whether a given metadata key exists for this node. * * @param string Key to test * @return boolean * @access public */ function metadataKeyExists($key) { return array_key_exists($key, $this->_metadata); } /* }}} */ /* getMetadata {{{ */ /** * * Node metadata getter * * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an * associative array or in a dictionary. This method gets the data under the given key. If the key does * not exist, an error will be thrown, so testing using metadataKeyExists might be needed. * * @param string Key * @param boolean nullIfNonexistent (defaults to false). * @return mixed Metadata Data stored in node under given key * @see metadataKeyExists * @access public */ function &getMetadata($key, $nullIfNonexistent = false) { if (array_key_exists($key, $this->_metadata)) { return $this->_metadata[$key]; } else { if ($nullIfNonexistent) { $a = null; return $a; } else { $a = Pear::raiseError('Structures_Graph_Node::getMetadata: Requested key does not exist', STRUCTURES_GRAPH_ERROR_GENERIC); return $a; } } } /* }}} */ /* unsetMetadata {{{ */ /** * * Delete metadata by key * * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an * associative array or in a dictionary. This method removes any data that might be stored under the provided key. * If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence. * * @param string Key * @access public */ function unsetMetadata($key) { if (array_key_exists($key, $this->_metadata)) unset($this->_metadata[$key]); } /* }}} */ /* setMetadata {{{ */ /** * * Node metadata setter * * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an * associative array or in a dictionary. This method stores data under the given key. If the key already exists, * previously stored data is discarded. * * @param string Key * @param mixed Data * @access public */ function setMetadata($key, &$data) { $this->_metadata[$key] =& $data; } /* }}} */ /* _connectTo {{{ */ /** @access private */ function _connectTo(&$destinationNode) { $this->_arcs[] =& $destinationNode; } /* }}} */ /* connectTo {{{ */ /** * * Connect this node to another one. * * If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created. * * @param Structures_Graph_Node Node to connect to * @access public */ function connectTo(&$destinationNode) { // We only connect to nodes if (!is_a($destinationNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph_Node::connectTo received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC); // Nodes must already be in graphs to be connected if ($this->_graph == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC); if ($destinationNode->getGraph() == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect to a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC); // Connect here $this->_connectTo($destinationNode); // If graph is undirected, connect back if (!$this->_graph->isDirected()) { $destinationNode->_connectTo($this); } } /* }}} */ /* getNeighbours {{{ */ /** * * Return nodes connected to this one. * * @return array Array of nodes * @access public */ function getNeighbours() { return $this->_arcs; } /* }}} */ /* connectsTo {{{ */ /** * * Test wether this node has an arc to the target node * * @return boolean True if the two nodes are connected * @access public */ function connectsTo(&$target) { if (version_compare(PHP_VERSION, '5.0.0') >= 0) { return in_array($target, $this->getNeighbours(), true); } $copy = $target; $arcKeys = array_keys($this->_arcs); foreach($arcKeys as $key) { /* ZE1 chokes on this expression: if ($target === $arc) return true; so, we'll use more convoluted stuff */ $arc =& $this->_arcs[$key]; $target = true; if ($arc === true) { $target = false; if ($arc === false) { $target = $copy; return true; } } } $target = $copy; return false; } /* }}} */ /* inDegree {{{ */ /** * * Calculate the in degree of the node. * * The indegree for a node is the number of arcs entering the node. For non directed graphs, * the indegree is equal to the outdegree. * * @return integer In degree of the node * @access public */ function inDegree() { if ($this->_graph == null) return 0; if (!$this->_graph->isDirected()) return $this->outDegree(); $result = 0; $graphNodes =& $this->_graph->getNodes(); foreach (array_keys($graphNodes) as $key) { if ($graphNodes[$key]->connectsTo($this)) $result++; } return $result; } /* }}} */ /* outDegree {{{ */ /** * * Calculate the out degree of the node. * * The outdegree for a node is the number of arcs exiting the node. For non directed graphs, * the outdegree is always equal to the indegree. * * @return integer Out degree of the node * @access public */ function outDegree() { if ($this->_graph == null) return 0; return sizeof($this->_arcs); } /* }}} */ } ?> PK!9,Structures/Graph/Manipulator/AcyclicTest.phpnu[ | // +-----------------------------------------------------------------------------+ // /** * This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator. * * @see Structures_Graph_Manipulator_AcyclicTest * @package Structures_Graph */ /* dependencies {{{ */ /** */ require_once 'PEAR.php'; /** */ require_once 'Structures/Graph.php'; /** */ require_once 'Structures/Graph/Node.php'; /* }}} */ /* class Structures_Graph_Manipulator_AcyclicTest {{{ */ /** * The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator * which tests whether a graph contains a cycle. * * The definition of an acyclic graph used in this manipulator is that of a * DAG. The graph must be directed, or else it is considered cyclic, even when * there are no arcs. * * @author Srgio Carvalho * @copyright (c) 2004 by Srgio Carvalho * @package Structures_Graph */ class Structures_Graph_Manipulator_AcyclicTest { /* _nonVisitedInDegree {{{ */ /** * * This is a variant of Structures_Graph::inDegree which does * not count nodes marked as visited. * * @return integer Number of non-visited nodes that link to this one */ protected static function _nonVisitedInDegree(&$node) { $result = 0; $graphNodes =& $node->_graph->getNodes(); foreach (array_keys($graphNodes) as $key) { if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++; } return $result; } /* }}} */ /* _isAcyclic {{{ */ /** * Check if the graph is acyclic */ protected static function _isAcyclic(&$graph) { // Mark every node as not visited $nodes =& $graph->getNodes(); $nodeKeys = array_keys($nodes); $refGenerator = array(); foreach($nodeKeys as $key) { $refGenerator[] = false; $nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]); } // Iteratively peel off leaf nodes do { // Find out which nodes are leafs (excluding visited nodes) $leafNodes = array(); foreach($nodeKeys as $key) { if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) { $leafNodes[] =& $nodes[$key]; } } // Mark leafs as visited for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) { $visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited'); $visited = true; $leafNodes[$i]->setMetadata('acyclic-test-visited', $visited); } } while (sizeof($leafNodes) > 0); // If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise $result = true; foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false; // Cleanup visited marks foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited'); return $result; } /* }}} */ /* isAcyclic {{{ */ /** * * isAcyclic returns true if a graph contains no cycles, false otherwise. * * @return boolean true iff graph is acyclic */ public static function isAcyclic(&$graph) { // We only test graphs if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_AcyclicTest::isAcyclic received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC); if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph); } /* }}} */ } /* }}} */ ?> PK!~(htt2Structures/Graph/Manipulator/TopologicalSorter.phpnu[ | // +-----------------------------------------------------------------------------+ // /** * This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class. * * @package Structures_Graph */ require_once 'PEAR.php'; require_once 'Structures/Graph.php'; require_once 'Structures/Graph/Node.php'; require_once 'Structures/Graph/Manipulator/AcyclicTest.php'; /** * The Structures_Graph_Manipulator_TopologicalSorter is a manipulator * which is able to return the set of nodes in a graph, sorted by topological * order. * * A graph may only be sorted topologically iff it's a DAG. You can test it * with the Structures_Graph_Manipulator_AcyclicTest. * * @author Srgio Carvalho * @copyright (c) 2004 by Srgio Carvalho * @see Structures_Graph_Manipulator_AcyclicTest * @package Structures_Graph */ class Structures_Graph_Manipulator_TopologicalSorter { /** * This is a variant of Structures_Graph::inDegree which does * not count nodes marked as visited. * * @param object $node Node to check * * @return integer Number of non-visited nodes that link to this one */ protected static function _nonVisitedInDegree(&$node) { $result = 0; $graphNodes =& $node->_graph->getNodes(); foreach (array_keys($graphNodes) as $key) { if ((!$graphNodes[$key]->getMetadata('topological-sort-visited')) && $graphNodes[$key]->connectsTo($node) ) { $result++; } } return $result; } /** * Sort implementation * * @param object $graph Graph to sort * * @return void */ protected static function _sort(&$graph) { // Mark every node as not visited $nodes =& $graph->getNodes(); $nodeKeys = array_keys($nodes); $refGenerator = array(); foreach ($nodeKeys as $key) { $refGenerator[] = false; $nodes[$key]->setMetadata( 'topological-sort-visited', $refGenerator[sizeof($refGenerator) - 1] ); } // Iteratively peel off leaf nodes $topologicalLevel = 0; do { // Find out which nodes are leafs (excluding visited nodes) $leafNodes = array(); foreach ($nodeKeys as $key) { if ((!$nodes[$key]->getMetadata('topological-sort-visited')) && static::_nonVisitedInDegree($nodes[$key]) == 0 ) { $leafNodes[] =& $nodes[$key]; } } // Mark leafs as visited $refGenerator[] = $topologicalLevel; for ($i = sizeof($leafNodes) - 1; $i>=0; $i--) { $visited =& $leafNodes[$i]->getMetadata('topological-sort-visited'); $visited = true; $leafNodes[$i]->setMetadata('topological-sort-visited', $visited); $leafNodes[$i]->setMetadata( 'topological-sort-level', $refGenerator[sizeof($refGenerator) - 1] ); } $topologicalLevel++; } while (sizeof($leafNodes) > 0); // Cleanup visited marks foreach ($nodeKeys as $key) { $nodes[$key]->unsetMetadata('topological-sort-visited'); } } /** * Sort returns the graph's nodes, sorted by topological order. * * The result is an array with as many entries as topological levels. * Each entry in this array is an array of nodes within * the given topological level. * * @param object $graph Graph to sort * * @return array The graph's nodes, sorted by topological order. */ public static function sort(&$graph) { // We only sort graphs if (!is_a($graph, 'Structures_Graph')) { return Pear::raiseError( 'Structures_Graph_Manipulator_TopologicalSorter::sort received' . ' an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC ); } if (!Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph)) { return Pear::raiseError( 'Structures_Graph_Manipulator_TopologicalSorter::sort' . ' received an graph that has cycles', STRUCTURES_GRAPH_ERROR_GENERIC ); } Structures_Graph_Manipulator_TopologicalSorter::_sort($graph); $result = array(); // Fill out result array $nodes =& $graph->getNodes(); $nodeKeys = array_keys($nodes); foreach ($nodeKeys as $key) { if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) { $result[$nodes[$key]->getMetadata('topological-sort-level')] = array(); } $result[$nodes[$key]->getMetadata('topological-sort-level')][] =& $nodes[$key]; $nodes[$key]->unsetMetadata('topological-sort-level'); } return $result; } } ?> PK!J} } Auth/SASL/Anonymous.phpnu[ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of ANONYMOUS SASL mechanism * * @author Richard Heyes * @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_Anonymous extends Auth_SASL_Common { /** * Not much to do here except return the token supplied. * No encoding, hashing or encryption takes place for this * mechanism, simply one of: * o An email address * o An opaque string not containing "@" that can be interpreted * by the sysadmin * o Nothing * * We could have some logic here for the second option, but this * would by no means create something interpretable. * * @param string $token Optional email address or string to provide * as trace information. * @return string The unaltered input token */ function getResponse($token = '') { return $token; } } ?>PK!P(~T T Auth/SASL/CramMD5.phpnu[ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of CRAM-MD5 SASL mechanism * * @author Richard Heyes * @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_CramMD5 extends Auth_SASL_Common { /** * Implements the CRAM-MD5 SASL mechanism * This DOES NOT base64 encode the return value, * you will need to do that yourself. * * @param string $user Username * @param string $pass Password * @param string $challenge The challenge supplied by the server. * this should be already base64_decoded. * * @return string The string to pass back to the server, of the form * " ". This is NOT base64_encoded. */ function getResponse($user, $pass, $challenge) { return $user . ' ' . $this->_HMAC_MD5($pass, $challenge); } } ?>PK!= = Auth/SASL/Plain.phpnu[ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of PLAIN SASL mechanism * * @author Richard Heyes * @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_Plain extends Auth_SASL_Common { /** * Returns PLAIN response * * @param string $authcid Authentication id (username) * @param string $pass Password * @param string $authzid Autorization id * @return string PLAIN Response */ function getResponse($authcid, $pass, $authzid = '') { return $authzid . chr(0) . $authcid . chr(0) . $pass; } } ?> PK!< O O Auth/SASL/Login.phpnu[ | // +-----------------------------------------------------------------------+ // // $Id$ /** * This is technically not a SASL mechanism, however * it's used by Net_Sieve, Net_Cyrus and potentially * other protocols , so here is a good place to abstract * it. * * @author Richard Heyes * @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_Login extends Auth_SASL_Common { /** * Pseudo SASL LOGIN mechanism * * @param string $user Username * @param string $pass Password * @return string LOGIN string */ function getResponse($user, $pass) { return sprintf('LOGIN %s %s', $user, $pass); } } ?>PK!%ׅtg!g!Auth/SASL/DigestMD5.phpnu[ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of DIGEST-MD5 SASL mechanism * * @author Richard Heyes * @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_DigestMD5 extends Auth_SASL_Common { /** * Provides the (main) client response for DIGEST-MD5 * requires a few extra parameters than the other * mechanisms, which are unavoidable. * * @param string $authcid Authentication id (username) * @param string $pass Password * @param string $challenge The digest challenge sent by the server * @param string $hostname The hostname of the machine you're connecting to * @param string $service The servicename (eg. imap, pop, acap etc) * @param string $authzid Authorization id (username to proxy as) * @return string The digest response (NOT base64 encoded) * @access public */ function getResponse($authcid, $pass, $challenge, $hostname, $service, $authzid = '') { $challenge = $this->_parseChallenge($challenge); $authzid_string = ''; if ($authzid != '') { $authzid_string = ',authzid="' . $authzid . '"'; } if (!empty($challenge)) { $cnonce = $this->_getCnonce(); $digest_uri = sprintf('%s/%s', $service, $hostname); $response_value = $this->_getResponseValue($authcid, $pass, $challenge['realm'], $challenge['nonce'], $cnonce, $digest_uri, $authzid); if ($challenge['realm']) { return sprintf('username="%s",realm="%s"' . $authzid_string . ',nonce="%s",cnonce="%s",nc=00000001,qop=auth,digest-uri="%s",response=%s,maxbuf=%d', $authcid, $challenge['realm'], $challenge['nonce'], $cnonce, $digest_uri, $response_value, $challenge['maxbuf']); } else { return sprintf('username="%s"' . $authzid_string . ',nonce="%s",cnonce="%s",nc=00000001,qop=auth,digest-uri="%s",response=%s,maxbuf=%d', $authcid, $challenge['nonce'], $cnonce, $digest_uri, $response_value, $challenge['maxbuf']); } } else { return PEAR::raiseError('Invalid digest challenge'); } } /** * Parses and verifies the digest challenge* * * @param string $challenge The digest challenge * @return array The parsed challenge as an assoc * array in the form "directive => value". * @access private */ function _parseChallenge($challenge) { $tokens = array(); while (preg_match('/^([a-z-]+)=("[^"]+(? PK!TAuth/SASL/Common.phpnu[ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Common functionality to SASL mechanisms * * @author Richard Heyes * @access public * @version 1.0 * @package Auth_SASL */ class Auth_SASL_Common { /** * Function which implements HMAC MD5 digest * * @param string $key The secret key * @param string $data The data to hash * @param bool $raw_output Whether the digest is returned in binary or hexadecimal format. * * @return string The HMAC-MD5 digest */ function _HMAC_MD5($key, $data, $raw_output = FALSE) { if (strlen($key) > 64) { $key = pack('H32', md5($key)); } if (strlen($key) < 64) { $key = str_pad($key, 64, chr(0)); } $k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64); $k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64); $inner = pack('H32', md5($k_ipad . $data)); $digest = md5($k_opad . $inner, $raw_output); return $digest; } /** * Function which implements HMAC-SHA-1 digest * * @param string $key The secret key * @param string $data The data to hash * @param bool $raw_output Whether the digest is returned in binary or hexadecimal format. * @return string The HMAC-SHA-1 digest * @author Jehan * @access protected */ protected function _HMAC_SHA1($key, $data, $raw_output = FALSE) { if (strlen($key) > 64) { $key = sha1($key, TRUE); } if (strlen($key) < 64) { $key = str_pad($key, 64, chr(0)); } $k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64); $k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64); $inner = pack('H40', sha1($k_ipad . $data)); $digest = sha1($k_opad . $inner, $raw_output); return $digest; } } ?> PK!vRr, , Auth/SASL/External.phpnu[ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of EXTERNAL SASL mechanism * * @author Christoph Schulz * @access public * @version 1.0.3 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_External extends Auth_SASL_Common { /** * Returns EXTERNAL response * * @param string $authcid Authentication id (username) * @param string $pass Password * @param string $authzid Autorization id * @return string EXTERNAL Response */ function getResponse($authcid, $pass, $authzid = '') { return $authzid; } } ?> PK!ќ00Auth/SASL/SCRAM.phpnu[ * @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_SCRAM extends Auth_SASL_Common { /** * Construct a SCRAM-H client where 'H' is a cryptographic hash function. * * @param string $hash The name cryptographic hash function 'H' as registered by IANA in the "Hash Function Textual * Names" registry. * @link http://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml "Hash Function Textual * Names" * format of core PHP hash function. * @access public */ function __construct($hash) { // Though I could be strict, I will actually also accept the naming used in the PHP core hash framework. // For instance "sha1" is accepted, while the registered hash name should be "SHA-1". $hash = strtolower($hash); $hashes = array('md2' => 'md2', 'md5' => 'md5', 'sha-1' => 'sha1', 'sha1' => 'sha1', 'sha-224' > 'sha224', 'sha224' > 'sha224', 'sha-256' => 'sha256', 'sha256' => 'sha256', 'sha-384' => 'sha384', 'sha384' => 'sha384', 'sha-512' => 'sha512', 'sha512' => 'sha512'); if (function_exists('hash_hmac') && isset($hashes[$hash])) { $this->hash = create_function('$data', 'return hash("' . $hashes[$hash] . '", $data, TRUE);'); $this->hmac = create_function('$key,$str,$raw', 'return hash_hmac("' . $hashes[$hash] . '", $str, $key, $raw);'); } elseif ($hash == 'md5') { $this->hash = create_function('$data', 'return md5($data, true);'); $this->hmac = array($this, '_HMAC_MD5'); } elseif (in_array($hash, array('sha1', 'sha-1'))) { $this->hash = create_function('$data', 'return sha1($data, true);'); $this->hmac = array($this, '_HMAC_SHA1'); } else return PEAR::raiseError('Invalid SASL mechanism type'); } /** * Provides the (main) client response for SCRAM-H. * * @param string $authcid Authentication id (username) * @param string $pass Password * @param string $challenge The challenge sent by the server. * If the challenge is NULL or an empty string, the result will be the "initial response". * @param string $authzid Authorization id (username to proxy as) * @return string|false The response (binary, NOT base64 encoded) * @access public */ public function getResponse($authcid, $pass, $challenge = NULL, $authzid = NULL) { $authcid = $this->_formatName($authcid); if (empty($authcid)) { return false; } if (!empty($authzid)) { $authzid = $this->_formatName($authzid); if (empty($authzid)) { return false; } } if (empty($challenge)) { return $this->_generateInitialResponse($authcid, $authzid); } else { return $this->_generateResponse($challenge, $pass); } } /** * Prepare a name for inclusion in a SCRAM response. * * @param string $username a name to be prepared. * @return string the reformated name. * @access private */ private function _formatName($username) { // TODO: prepare through the SASLprep profile of the stringprep algorithm. // See RFC-4013. $username = str_replace('=', '=3D', $username); $username = str_replace(',', '=2C', $username); return $username; } /** * Generate the initial response which can be either sent directly in the first message or as a response to an empty * server challenge. * * @param string $authcid Prepared authentication identity. * @param string $authzid Prepared authorization identity. * @return string The SCRAM response to send. * @access private */ private function _generateInitialResponse($authcid, $authzid) { $init_rep = ''; $gs2_cbind_flag = 'n,'; // TODO: support channel binding. $this->gs2_header = $gs2_cbind_flag . (!empty($authzid)? 'a=' . $authzid : '') . ','; // I must generate a client nonce and "save" it for later comparison on second response. $this->cnonce = $this->_getCnonce(); // XXX: in the future, when mandatory and/or optional extensions are defined in any updated RFC, // this message can be updated. $this->first_message_bare = 'n=' . $authcid . ',r=' . $this->cnonce; return $this->gs2_header . $this->first_message_bare; } /** * Parses and verifies a non-empty SCRAM challenge. * * @param string $challenge The SCRAM challenge * @return string|false The response to send; false in case of wrong challenge or if an initial response has not * been generated first. * @access private */ private function _generateResponse($challenge, $password) { // XXX: as I don't support mandatory extension, I would fail on them. // And I simply ignore any optional extension. $server_message_regexp = "#^r=([\x21-\x2B\x2D-\x7E]+),s=((?:[A-Za-z0-9/+]{4})*(?:[A-Za-z0-9]{3}=|[A-Xa-z0-9]{2}==)?),i=([0-9]*)(,[A-Za-z]=[^,])*$#"; if (!isset($this->cnonce, $this->gs2_header) || !preg_match($server_message_regexp, $challenge, $matches)) { return false; } $nonce = $matches[1]; $salt = base64_decode($matches[2]); if (!$salt) { // Invalid Base64. return false; } $i = intval($matches[3]); $cnonce = substr($nonce, 0, strlen($this->cnonce)); if ($cnonce <> $this->cnonce) { // Invalid challenge! Are we under attack? return false; } $channel_binding = 'c=' . base64_encode($this->gs2_header); // TODO: support channel binding. $final_message = $channel_binding . ',r=' . $nonce; // XXX: no extension. // TODO: $password = $this->normalize($password); // SASLprep profile of stringprep. $saltedPassword = $this->hi($password, $salt, $i); $this->saltedPassword = $saltedPassword; $clientKey = call_user_func($this->hmac, $saltedPassword, "Client Key", TRUE); $storedKey = call_user_func($this->hash, $clientKey, TRUE); $authMessage = $this->first_message_bare . ',' . $challenge . ',' . $final_message; $this->authMessage = $authMessage; $clientSignature = call_user_func($this->hmac, $storedKey, $authMessage, TRUE); $clientProof = $clientKey ^ $clientSignature; $proof = ',p=' . base64_encode($clientProof); return $final_message . $proof; } /** * SCRAM has also a server verification step. On a successful outcome, it will send additional data which must * absolutely be checked against this function. If this fails, the entity which we are communicating with is probably * not the server as it has not access to your ServerKey. * * @param string $data The additional data sent along a successful outcome. * @return bool Whether the server has been authenticated. * If false, the client must close the connection and consider to be under a MITM attack. * @access public */ public function processOutcome($data) { $verifier_regexp = '#^v=((?:[A-Za-z0-9/+]{4})*(?:[A-Za-z0-9]{3}=|[A-Xa-z0-9]{2}==)?)$#'; if (!isset($this->saltedPassword, $this->authMessage) || !preg_match($verifier_regexp, $data, $matches)) { // This cannot be an outcome, you never sent the challenge's response. return false; } $verifier = $matches[1]; $proposed_serverSignature = base64_decode($verifier); $serverKey = call_user_func($this->hmac, $this->saltedPassword, "Server Key", true); $serverSignature = call_user_func($this->hmac, $serverKey, $this->authMessage, TRUE); return ($proposed_serverSignature === $serverSignature); } /** * Hi() call, which is essentially PBKDF2 (RFC-2898) with HMAC-H() as the pseudorandom function. * * @param string $str The string to hash. * @param string $hash The hash value. * @param int $i The iteration count. * @access private */ private function hi($str, $salt, $i) { $int1 = "\0\0\0\1"; $ui = call_user_func($this->hmac, $str, $salt . $int1, true); $result = $ui; for ($k = 1; $k < $i; $k++) { $ui = call_user_func($this->hmac, $str, $ui, true); $result = $result ^ $ui; } return $result; } /** * Creates the client nonce for the response * * @return string The cnonce value * @access private * @author Richard Heyes */ private function _getCnonce() { // TODO: I reused the nonce function from the DigestMD5 class. // I should probably make this a protected function in Common. if (@file_exists('/dev/urandom') && $fd = @fopen('/dev/urandom', 'r')) { return base64_encode(fread($fd, 32)); } elseif (@file_exists('/dev/random') && $fd = @fopen('/dev/random', 'r')) { return base64_encode(fread($fd, 32)); } else { $str = ''; for ($i=0; $i<32; $i++) { $str .= chr(mt_rand(0, 255)); } return base64_encode($str); } } } ?> PK!K  Auth/SASL.phpnu[ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Client implementation of various SASL mechanisms * * @author Richard Heyes * @access public * @version 1.0 * @package Auth_SASL */ require_once('PEAR.php'); class Auth_SASL { /** * Factory class. Returns an object of the request * type. * * @param string $type One of: Anonymous * Plain * CramMD5 * DigestMD5 * SCRAM-* (any mechanism of the SCRAM family) * Types are not case sensitive */ function &factory($type) { switch (strtolower($type)) { case 'anonymous': $filename = 'Auth/SASL/Anonymous.php'; $classname = 'Auth_SASL_Anonymous'; break; case 'login': $filename = 'Auth/SASL/Login.php'; $classname = 'Auth_SASL_Login'; break; case 'plain': $filename = 'Auth/SASL/Plain.php'; $classname = 'Auth_SASL_Plain'; break; case 'external': $filename = 'Auth/SASL/External.php'; $classname = 'Auth_SASL_External'; break; case 'crammd5': // $msg = 'Deprecated mechanism name. Use IANA-registered name: CRAM-MD5.'; // trigger_error($msg, E_USER_DEPRECATED); case 'cram-md5': $filename = 'Auth/SASL/CramMD5.php'; $classname = 'Auth_SASL_CramMD5'; break; case 'digestmd5': // $msg = 'Deprecated mechanism name. Use IANA-registered name: DIGEST-MD5.'; // trigger_error($msg, E_USER_DEPRECATED); case 'digest-md5': // $msg = 'DIGEST-MD5 is a deprecated SASL mechanism as per RFC-6331. Using it could be a security risk.'; // trigger_error($msg, E_USER_NOTICE); $filename = 'Auth/SASL/DigestMD5.php'; $classname = 'Auth_SASL_DigestMD5'; break; default: $scram = '/^SCRAM-(.{1,9})$/i'; if (preg_match($scram, $type, $matches)) { $hash = $matches[1]; $filename = dirname(__FILE__) .'/SASL/SCRAM.php'; $classname = 'Auth_SASL_SCRAM'; $parameter = $hash; break; } return PEAR::raiseError('Invalid SASL mechanism type'); break; } require_once($filename); if (isset($parameter)) $obj = new $classname($parameter); else $obj = new $classname(); return $obj; } } ?> PK!T,, OS/Guess.phpnu[ * @author Gregory Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since PEAR 0.1 */ // {{{ uname examples // php_uname() without args returns the same as 'uname -a', or a PHP-custom // string for Windows. // PHP versions prior to 4.3 return the uname of the host where PHP was built, // as of 4.3 it returns the uname of the host running the PHP code. // // PC RedHat Linux 7.1: // Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown // // PC Debian Potato: // Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown // // PC FreeBSD 3.3: // FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386 // // PC FreeBSD 4.3: // FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386 // // PC FreeBSD 4.5: // FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386 // // PC FreeBSD 4.5 w/uname from GNU shellutils: // FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown // // HP 9000/712 HP-UX 10: // HP-UX iq B.10.10 A 9000/712 2008429113 two-user license // // HP 9000/712 HP-UX 10 w/uname from GNU shellutils: // HP-UX host B.10.10 A 9000/712 unknown // // IBM RS6000/550 AIX 4.3: // AIX host 3 4 000003531C00 // // AIX 4.3 w/uname from GNU shellutils: // AIX host 3 4 000003531C00 unknown // // SGI Onyx IRIX 6.5 w/uname from GNU shellutils: // IRIX64 host 6.5 01091820 IP19 mips // // SGI Onyx IRIX 6.5: // IRIX64 host 6.5 01091820 IP19 // // SparcStation 20 Solaris 8 w/uname from GNU shellutils: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc // // SparcStation 20 Solaris 8: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20 // // Mac OS X (Darwin) // Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh // // Mac OS X early versions // // }}} /* TODO: * - define endianness, to allow matchSignature("bigend") etc. */ /** * Retrieves information about the current operating system * * This class uses php_uname() to grok information about the current OS * * @category pear * @package PEAR * @author Stig Bakken * @author Gregory Beaver * @copyright 1997-2020 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class OS_Guess { var $sysname; var $nodename; var $cpu; var $release; var $extra; function __construct($uname = null) { list($this->sysname, $this->release, $this->cpu, $this->extra, $this->nodename) = $this->parseSignature($uname); } function parseSignature($uname = null) { static $sysmap = array( 'HP-UX' => 'hpux', 'IRIX64' => 'irix', ); static $cpumap = array( 'i586' => 'i386', 'i686' => 'i386', 'ppc' => 'powerpc', ); if ($uname === null) { $uname = php_uname(); } $parts = preg_split('/\s+/', trim($uname)); $n = count($parts); $release = $machine = $cpu = ''; $sysname = $parts[0]; $nodename = $parts[1]; $cpu = $parts[$n-1]; $extra = ''; if ($cpu == 'unknown') { $cpu = $parts[$n - 2]; } switch ($sysname) { case 'AIX' : $release = "$parts[3].$parts[2]"; break; case 'Windows' : $release = $parts[1]; if ($release == '95/98') { $release = '9x'; } $cpu = 'i386'; break; case 'Linux' : $extra = $this->_detectGlibcVersion(); // use only the first two digits from the kernel version $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]); break; case 'Mac' : $sysname = 'darwin'; $nodename = $parts[2]; $release = $parts[3]; $cpu = $this->_determineIfPowerpc($cpu, $parts); break; case 'Darwin' : $cpu = $this->_determineIfPowerpc($cpu, $parts); $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]); break; default: $release = preg_replace('/-.*/', '', $parts[2]); break; } if (isset($sysmap[$sysname])) { $sysname = $sysmap[$sysname]; } else { $sysname = strtolower($sysname); } if (isset($cpumap[$cpu])) { $cpu = $cpumap[$cpu]; } return array($sysname, $release, $cpu, $extra, $nodename); } function _determineIfPowerpc($cpu, $parts) { $n = count($parts); if ($cpu == 'Macintosh' && $parts[$n - 2] == 'Power') { $cpu = 'powerpc'; } return $cpu; } function _detectGlibcVersion() { static $glibc = false; if ($glibc !== false) { return $glibc; // no need to run this multiple times } $major = $minor = 0; include_once "System.php"; // Let's try reading possible libc.so.6 symlinks $libcs = array( '/lib64/libc.so.6', '/lib/libc.so.6', '/lib/i386-linux-gnu/libc.so.6' ); $versions = array(); foreach ($libcs as $file) { $versions = $this->_readGlibCVersionFromSymlink($file); if ($versions != []) { list($major, $minor) = $versions; break; } } // Use glibc's header file to // get major and minor version number: if (!($major && $minor)) { $versions = $this->_readGlibCVersionFromFeaturesHeaderFile(); } if (is_array($versions) && $versions != []) { list($major, $minor) = $versions; } if (!($major && $minor)) { return $glibc = ''; } return $glibc = "glibc{$major}.{$minor}"; } function _readGlibCVersionFromSymlink($file) { $versions = array(); if (@is_link($file) && (preg_match('/^libc-(.*)\.so$/', basename(readlink($file)), $matches)) ) { $versions = explode('.', $matches[1]); } return $versions; } function _readGlibCVersionFromFeaturesHeaderFile() { $features_header_file = '/usr/include/features.h'; if (!(@file_exists($features_header_file) && @is_readable($features_header_file)) ) { return array(); } if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) { return $this->_parseFeaturesHeaderFile($features_header_file); } // no cpp return $this->_fromGlibCTest(); } function _parseFeaturesHeaderFile($features_header_file) { $features_file = fopen($features_header_file, 'rb'); while (!feof($features_file)) { $line = fgets($features_file, 8192); if (!$this->_IsADefinition($line)) { continue; } if (strpos($line, '__GLIBC__')) { // major version number #define __GLIBC__ version $line = preg_split('/\s+/', $line); $glibc_major = trim($line[2]); if (isset($glibc_minor)) { break; } continue; } if (strpos($line, '__GLIBC_MINOR__')) { // got the minor version number // #define __GLIBC_MINOR__ version $line = preg_split('/\s+/', $line); $glibc_minor = trim($line[2]); if (isset($glibc_major)) { break; } } } fclose($features_file); if (!isset($glibc_major) || !isset($glibc_minor)) { return array(); } return array(trim($glibc_major), trim($glibc_minor)); } function _IsADefinition($line) { if ($line === false) { return false; } return strpos(trim($line), '#define') !== false; } function _fromGlibCTest() { $major = null; $minor = null; $tmpfile = System::mktemp("glibctest"); $fp = fopen($tmpfile, "w"); fwrite($fp, "#include \n__GLIBC__ __GLIBC_MINOR__\n"); fclose($fp); $cpp = popen("/usr/bin/cpp $tmpfile", "r"); while ($line = fgets($cpp, 1024)) { if ($line[0] == '#' || trim($line) == '') { continue; } if (list($major, $minor) = explode(' ', trim($line))) { break; } } pclose($cpp); unlink($tmpfile); if ($major !== null && $minor !== null) { return [$major, $minor]; } } function getSignature() { if (empty($this->extra)) { return "{$this->sysname}-{$this->release}-{$this->cpu}"; } return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}"; } function getSysname() { return $this->sysname; } function getNodename() { return $this->nodename; } function getCpu() { return $this->cpu; } function getRelease() { return $this->release; } function getExtra() { return $this->extra; } function matchSignature($match) { $fragments = is_array($match) ? $match : explode('-', $match); $n = count($fragments); $matches = 0; if ($n > 0) { $matches += $this->_matchFragment($fragments[0], $this->sysname); } if ($n > 1) { $matches += $this->_matchFragment($fragments[1], $this->release); } if ($n > 2) { $matches += $this->_matchFragment($fragments[2], $this->cpu); } if ($n > 3) { $matches += $this->_matchFragment($fragments[3], $this->extra); } return ($matches == $n); } function _matchFragment($fragment, $value) { if (strcspn($fragment, '*?') < strlen($fragment)) { $expression = str_replace( array('*', '?', '/'), array('.*', '.', '\\/'), $fragment ); $reg = '/^' . $expression . '\\z/'; return preg_match($reg, $value); } return ($fragment == '*' || !strcasecmp($fragment, $value)); } } /* * Local Variables: * indent-tabs-mode: nil * c-basic-offset: 4 * End: */ PK!PEAR/Config.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * Required for error handling */ require_once 'PEAR.php'; require_once 'PEAR/Registry.php'; require_once 'PEAR/Installer/Role.php'; require_once 'System.php'; /** * Last created PEAR_Config instance. * @var object */ $GLOBALS['_PEAR_Config_instance'] = null; if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) { $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear'; } else { $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR; } // Below we define constants with default values for all configuration // parameters except username/password. All of them can have their // defaults set through environment variables. The reason we use the // PHP_ prefix is for some security, PHP protects environment // variables starting with PHP_*. // default channel and preferred mirror is based on whether we are invoked through // the "pear" or the "pecl" command if (!defined('PEAR_RUNTYPE')) { define('PEAR_RUNTYPE', 'pear'); } if (PEAR_RUNTYPE == 'pear') { define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net'); } else { define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net'); } if (getenv('PHP_PEAR_SYSCONF_DIR')) { define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR')); } elseif (getenv('SystemRoot')) { define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot')); } else { define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR); } // Default for master_server if (getenv('PHP_PEAR_MASTER_SERVER')) { define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER')); } else { define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net'); } // Default for http_proxy if (getenv('PHP_PEAR_HTTP_PROXY')) { define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY')); } elseif (getenv('http_proxy')) { define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy')); } else { define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', ''); } // Default for php_dir if (getenv('PHP_PEAR_INSTALL_DIR')) { define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR')); } else { define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); } // Default for metadata_dir if (getenv('PHP_PEAR_METADATA_DIR')) { define('PEAR_CONFIG_DEFAULT_METADATA_DIR', getenv('PHP_PEAR_METADATA_DIR')); } else { define('PEAR_CONFIG_DEFAULT_METADATA_DIR', ''); } // Default for ext_dir if (getenv('PHP_PEAR_EXTENSION_DIR')) { define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR')); } else { if (ini_get('extension_dir')) { define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir')); } elseif (defined('PEAR_EXTENSION_DIR') && file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) { define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR); } elseif (defined('PHP_EXTENSION_DIR')) { define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR); } else { define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.'); } } // Default for doc_dir if (getenv('PHP_PEAR_DOC_DIR')) { define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR')); } else { define('PEAR_CONFIG_DEFAULT_DOC_DIR', $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs'); } // Default for bin_dir if (getenv('PHP_PEAR_BIN_DIR')) { define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR')); } else { define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR); } // Default for data_dir if (getenv('PHP_PEAR_DATA_DIR')) { define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR')); } else { define('PEAR_CONFIG_DEFAULT_DATA_DIR', $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data'); } // Default for cfg_dir if (getenv('PHP_PEAR_CFG_DIR')) { define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR')); } else { define('PEAR_CONFIG_DEFAULT_CFG_DIR', $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg'); } // Default for www_dir if (getenv('PHP_PEAR_WWW_DIR')) { define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR')); } else { define('PEAR_CONFIG_DEFAULT_WWW_DIR', $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www'); } // Default for man_dir if (getenv('PHP_PEAR_MAN_DIR')) { define('PEAR_CONFIG_DEFAULT_MAN_DIR', getenv('PHP_PEAR_MAN_DIR')); } else { if (defined('PHP_MANDIR')) { // Added in PHP5.3.7 define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_MANDIR); } else { define('PEAR_CONFIG_DEFAULT_MAN_DIR', PHP_PREFIX . DIRECTORY_SEPARATOR . 'local' . DIRECTORY_SEPARATOR .'man'); } } // Default for test_dir if (getenv('PHP_PEAR_TEST_DIR')) { define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR')); } else { define('PEAR_CONFIG_DEFAULT_TEST_DIR', $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests'); } // Default for temp_dir if (getenv('PHP_PEAR_TEMP_DIR')) { define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR')); } else { define('PEAR_CONFIG_DEFAULT_TEMP_DIR', System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . DIRECTORY_SEPARATOR . 'temp'); } // Default for cache_dir if (getenv('PHP_PEAR_CACHE_DIR')) { define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR')); } else { define('PEAR_CONFIG_DEFAULT_CACHE_DIR', System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . DIRECTORY_SEPARATOR . 'cache'); } // Default for download_dir if (getenv('PHP_PEAR_DOWNLOAD_DIR')) { define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR')); } else { define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . DIRECTORY_SEPARATOR . 'download'); } // Default for php_bin if (getenv('PHP_PEAR_PHP_BIN')) { define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN')); } else { define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR. DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : '')); } // Default for verbose if (getenv('PHP_PEAR_VERBOSE')) { define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE')); } else { define('PEAR_CONFIG_DEFAULT_VERBOSE', 1); } // Default for preferred_state if (getenv('PHP_PEAR_PREFERRED_STATE')) { define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE')); } else { define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable'); } // Default for umask if (getenv('PHP_PEAR_UMASK')) { define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK')); } else { define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask())); } // Default for cache_ttl if (getenv('PHP_PEAR_CACHE_TTL')) { define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL')); } else { define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600); } // Default for sig_type if (getenv('PHP_PEAR_SIG_TYPE')) { define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE')); } else { define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg'); } // Default for sig_bin if (getenv('PHP_PEAR_SIG_BIN')) { define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN')); } else { define('PEAR_CONFIG_DEFAULT_SIG_BIN', System::which( 'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg')); } // Default for sig_keydir if (getenv('PHP_PEAR_SIG_KEYDIR')) { define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR')); } else { define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys'); } /** * This is a class for storing configuration data, keeping track of * which are system-defined, user-defined or defaulted. * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Config extends PEAR { /** * Array of config files used. * * @var array layer => config file */ var $files = array( 'system' => '', 'user' => '', ); var $layers = array(); /** * Configuration data, two-dimensional array where the first * dimension is the config layer ('user', 'system' and 'default'), * and the second dimension is keyname => value. * * The order in the first dimension is important! Earlier * layers will shadow later ones when a config value is * requested (if a 'user' value exists, it will be returned first, * then 'system' and finally 'default'). * * @var array layer => array(keyname => value, ...) */ var $configuration = array( 'user' => array(), 'system' => array(), 'default' => array(), ); /** * Configuration values that can be set for a channel * * All other configuration values can only have a global value * @var array * @access private */ var $_channelConfigInfo = array( 'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir', 'test_dir', 'www_dir', 'php_bin', 'php_prefix', 'php_suffix', 'username', 'password', 'verbose', 'preferred_state', 'umask', 'preferred_mirror', 'php_ini' ); /** * Channels that can be accessed * @see setChannels() * @var array * @access private */ var $_channels = array('pear.php.net', 'pecl.php.net', '__uri'); /** * This variable is used to control the directory values returned * @see setInstallRoot(); * @var string|false * @access private */ var $_installRoot = false; /** * If requested, this will always refer to the registry * contained in php_dir * @var PEAR_Registry */ var $_registry = array(); /** * @var array * @access private */ var $_regInitialized = array(); /** * @var bool * @access private */ var $_noRegistry = false; /** * amount of errors found while parsing config * @var integer * @access private */ var $_errorsFound = 0; var $_lastError = null; /** * Information about the configuration data. Stores the type, * default value and a documentation string for each configuration * value. * * @var array layer => array(infotype => value, ...) */ var $configuration_info = array( // Channels/Internet Access 'default_channel' => array( 'type' => 'string', 'default' => PEAR_CONFIG_DEFAULT_CHANNEL, 'doc' => 'the default channel to use for all non explicit commands', 'prompt' => 'Default Channel', 'group' => 'Internet Access', ), 'preferred_mirror' => array( 'type' => 'string', 'default' => PEAR_CONFIG_DEFAULT_CHANNEL, 'doc' => 'the default server or mirror to use for channel actions', 'prompt' => 'Default Channel Mirror', 'group' => 'Internet Access', ), 'remote_config' => array( 'type' => 'password', 'default' => '', 'doc' => 'ftp url of remote configuration file to use for synchronized install', 'prompt' => 'Remote Configuration File', 'group' => 'Internet Access', ), 'auto_discover' => array( 'type' => 'integer', 'default' => 0, 'doc' => 'whether to automatically discover new channels', 'prompt' => 'Auto-discover new Channels', 'group' => 'Internet Access', ), // Internet Access 'master_server' => array( 'type' => 'string', 'default' => 'pear.php.net', 'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]', 'prompt' => 'PEAR server [DEPRECATED]', 'group' => 'Internet Access', ), 'http_proxy' => array( 'type' => 'string', 'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY, 'doc' => 'HTTP proxy (host:port) to use when downloading packages', 'prompt' => 'HTTP Proxy Server Address', 'group' => 'Internet Access', ), // File Locations 'php_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_PHP_DIR, 'doc' => 'directory where .php files are installed', 'prompt' => 'PEAR directory', 'group' => 'File Locations', ), 'ext_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_EXT_DIR, 'doc' => 'directory where loadable extensions are installed', 'prompt' => 'PHP extension directory', 'group' => 'File Locations', ), 'doc_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_DOC_DIR, 'doc' => 'directory where documentation is installed', 'prompt' => 'PEAR documentation directory', 'group' => 'File Locations', ), 'bin_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_BIN_DIR, 'doc' => 'directory where executables are installed', 'prompt' => 'PEAR executables directory', 'group' => 'File Locations', ), 'data_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_DATA_DIR, 'doc' => 'directory where data files are installed', 'prompt' => 'PEAR data directory', 'group' => 'File Locations (Advanced)', ), 'cfg_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_CFG_DIR, 'doc' => 'directory where modifiable configuration files are installed', 'prompt' => 'PEAR configuration file directory', 'group' => 'File Locations (Advanced)', ), 'www_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_WWW_DIR, 'doc' => 'directory where www frontend files (html/js) are installed', 'prompt' => 'PEAR www files directory', 'group' => 'File Locations (Advanced)', ), 'man_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_MAN_DIR, 'doc' => 'directory where unix manual pages are installed', 'prompt' => 'Systems manpage files directory', 'group' => 'File Locations (Advanced)', ), 'test_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_TEST_DIR, 'doc' => 'directory where regression tests are installed', 'prompt' => 'PEAR test directory', 'group' => 'File Locations (Advanced)', ), 'cache_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR, 'doc' => 'directory which is used for web service cache', 'prompt' => 'PEAR Installer cache directory', 'group' => 'File Locations (Advanced)', ), 'temp_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR, 'doc' => 'directory which is used for all temp files', 'prompt' => 'PEAR Installer temp directory', 'group' => 'File Locations (Advanced)', ), 'download_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR, 'doc' => 'directory which is used for all downloaded files', 'prompt' => 'PEAR Installer download directory', 'group' => 'File Locations (Advanced)', ), 'php_bin' => array( 'type' => 'file', 'default' => PEAR_CONFIG_DEFAULT_PHP_BIN, 'doc' => 'PHP CLI/CGI binary for executing scripts', 'prompt' => 'PHP CLI/CGI binary', 'group' => 'File Locations (Advanced)', ), 'php_prefix' => array( 'type' => 'string', 'default' => '', 'doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs', 'prompt' => '--program-prefix passed to PHP\'s ./configure', 'group' => 'File Locations (Advanced)', ), 'php_suffix' => array( 'type' => 'string', 'default' => '', 'doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs', 'prompt' => '--program-suffix passed to PHP\'s ./configure', 'group' => 'File Locations (Advanced)', ), 'php_ini' => array( 'type' => 'file', 'default' => '', 'doc' => 'location of php.ini in which to enable PECL extensions on install', 'prompt' => 'php.ini location', 'group' => 'File Locations (Advanced)', ), 'metadata_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_METADATA_DIR, 'doc' => 'directory where metadata files are installed (registry, filemap, channels, ...)', 'prompt' => 'PEAR metadata directory', 'group' => 'File Locations (Advanced)', ), // Maintainers 'username' => array( 'type' => 'string', 'default' => '', 'doc' => '(maintainers) your PEAR account name', 'prompt' => 'PEAR username (for maintainers)', 'group' => 'Maintainers', ), 'password' => array( 'type' => 'password', 'default' => '', 'doc' => '(maintainers) your PEAR account password', 'prompt' => 'PEAR password (for maintainers)', 'group' => 'Maintainers', ), // Advanced 'verbose' => array( 'type' => 'integer', 'default' => PEAR_CONFIG_DEFAULT_VERBOSE, 'doc' => 'verbosity level 0: really quiet 1: somewhat quiet 2: verbose 3: debug', 'prompt' => 'Debug Log Level', 'group' => 'Advanced', ), 'preferred_state' => array( 'type' => 'set', 'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE, 'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified', 'valid_set' => array( 'stable', 'beta', 'alpha', 'devel', 'snapshot'), 'prompt' => 'Preferred Package State', 'group' => 'Advanced', ), 'umask' => array( 'type' => 'mask', 'default' => PEAR_CONFIG_DEFAULT_UMASK, 'doc' => 'umask used when creating files (Unix-like systems only)', 'prompt' => 'Unix file mask', 'group' => 'Advanced', ), 'cache_ttl' => array( 'type' => 'integer', 'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL, 'doc' => 'amount of secs where the local cache is used and not updated', 'prompt' => 'Cache TimeToLive', 'group' => 'Advanced', ), 'sig_type' => array( 'type' => 'set', 'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE, 'doc' => 'which package signature mechanism to use', 'valid_set' => array('gpg'), 'prompt' => 'Package Signature Type', 'group' => 'Maintainers', ), 'sig_bin' => array( 'type' => 'string', 'default' => PEAR_CONFIG_DEFAULT_SIG_BIN, 'doc' => 'which package signature mechanism to use', 'prompt' => 'Signature Handling Program', 'group' => 'Maintainers', ), 'sig_keyid' => array( 'type' => 'string', 'default' => '', 'doc' => 'which key to use for signing with', 'prompt' => 'Signature Key Id', 'group' => 'Maintainers', ), 'sig_keydir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR, 'doc' => 'directory where signature keys are located', 'prompt' => 'Signature Key Directory', 'group' => 'Maintainers', ), // __channels is reserved - used for channel-specific configuration ); /** * Constructor. * * @param string file to read user-defined options from * @param string file to read system-wide defaults from * @param bool determines whether a registry object "follows" * the value of php_dir (is automatically created * and moved when php_dir is changed) * @param bool if true, fails if configuration files cannot be loaded * * @access public * * @see PEAR_Config::singleton */ function __construct($user_file = '', $system_file = '', $ftp_file = false, $strict = true) { parent::__construct(); PEAR_Installer_Role::initializeConfig($this); $sl = DIRECTORY_SEPARATOR; if (empty($user_file)) { if (OS_WINDOWS) { $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini'; } else { $user_file = getenv('HOME') . $sl . '.pearrc'; } } if (empty($system_file)) { $system_file = PEAR_CONFIG_SYSCONFDIR . $sl; if (OS_WINDOWS) { $system_file .= 'pearsys.ini'; } else { $system_file .= 'pear.conf'; } } $this->layers = array_keys($this->configuration); $this->files['user'] = $user_file; $this->files['system'] = $system_file; if ($user_file && file_exists($user_file)) { $this->pushErrorHandling(PEAR_ERROR_RETURN); $this->readConfigFile($user_file, 'user', $strict); $this->popErrorHandling(); if ($this->_errorsFound > 0) { return; } } if ($system_file && @file_exists($system_file)) { $this->mergeConfigFile($system_file, false, 'system', $strict); if ($this->_errorsFound > 0) { return; } } if (!$ftp_file) { $ftp_file = $this->get('remote_config'); } if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) { $this->readFTPConfigFile($ftp_file); } foreach ($this->configuration_info as $key => $info) { $this->configuration['default'][$key] = $info['default']; } $this->_registry['default'] = new PEAR_Registry( $this->configuration['default']['php_dir'], false, false, $this->configuration['default']['metadata_dir']); $this->_registry['default']->setConfig($this, false); $this->_regInitialized['default'] = false; //$GLOBALS['_PEAR_Config_instance'] = &$this; } /** * Return the default locations of user and system configuration files */ public static function getDefaultConfigFiles() { $sl = DIRECTORY_SEPARATOR; if (OS_WINDOWS) { return array( 'user' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini', 'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini' ); } return array( 'user' => getenv('HOME') . $sl . '.pearrc', 'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf' ); } /** * Static singleton method. If you want to keep only one instance * of this class in use, this method will give you a reference to * the last created PEAR_Config object if one exists, or create a * new object. * * @param string (optional) file to read user-defined options from * @param string (optional) file to read system-wide defaults from * * @return object an existing or new PEAR_Config instance * * @see PEAR_Config::PEAR_Config */ public static function &singleton($user_file = '', $system_file = '', $strict = true) { if (is_object($GLOBALS['_PEAR_Config_instance'])) { return $GLOBALS['_PEAR_Config_instance']; } $t_conf = new PEAR_Config($user_file, $system_file, false, $strict); if ($t_conf->_errorsFound > 0) { return $t_conf->_lastError; } $GLOBALS['_PEAR_Config_instance'] = &$t_conf; return $GLOBALS['_PEAR_Config_instance']; } /** * Determine whether any configuration files have been detected, and whether a * registry object can be retrieved from this configuration. * @return bool * @since PEAR 1.4.0a1 */ function validConfiguration() { if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) { return true; } return false; } /** * Reads configuration data from a file. All existing values in * the config layer are discarded and replaced with data from the * file. * @param string file to read from, if NULL or not specified, the * last-used file for the same layer (second param) is used * @param string config layer to insert data into ('user' or 'system') * @return bool TRUE on success or a PEAR error on failure */ function readConfigFile($file = null, $layer = 'user', $strict = true) { if (empty($this->files[$layer])) { return $this->raiseError("unknown config layer `$layer'"); } if ($file === null) { $file = $this->files[$layer]; } $data = $this->_readConfigDataFrom($file); if (PEAR::isError($data)) { if (!$strict) { return true; } $this->_errorsFound++; $this->_lastError = $data; return $data; } $this->files[$layer] = $file; $this->_decodeInput($data); $this->configuration[$layer] = $data; $this->_setupChannels(); if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) { $this->_registry[$layer] = new PEAR_Registry( $phpdir, false, false, $this->get('metadata_dir', $layer, 'pear.php.net')); $this->_registry[$layer]->setConfig($this, false); $this->_regInitialized[$layer] = false; } else { unset($this->_registry[$layer]); } return true; } /** * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini * @return true|PEAR_Error */ function readFTPConfigFile($path) { do { // poor man's try if (!class_exists('PEAR_FTP')) { if (!class_exists('PEAR_Common')) { require_once 'PEAR/Common.php'; } if (PEAR_Common::isIncludeable('PEAR/FTP.php')) { require_once 'PEAR/FTP.php'; } } if (!class_exists('PEAR_FTP')) { return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config'); } $this->_ftp = new PEAR_FTP; $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN); $e = $this->_ftp->init($path); if (PEAR::isError($e)) { $this->_ftp->popErrorHandling(); return $e; } $tmp = System::mktemp('-d'); PEAR_Common::addTempFile($tmp); $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR . 'pear.ini', false, FTP_BINARY); if (PEAR::isError($e)) { $this->_ftp->popErrorHandling(); return $e; } PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini'); $this->_ftp->disconnect(); $this->_ftp->popErrorHandling(); $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini'; $e = $this->readConfigFile(null, 'ftp'); if (PEAR::isError($e)) { return $e; } $fail = array(); foreach ($this->configuration_info as $key => $val) { if (in_array($this->getGroup($key), array('File Locations', 'File Locations (Advanced)')) && $this->getType($key) == 'directory') { // any directory configs must be set for this to work if (!isset($this->configuration['ftp'][$key])) { $fail[] = $key; } } } if (!count($fail)) { return true; } $fail = '"' . implode('", "', $fail) . '"'; unset($this->files['ftp']); unset($this->configuration['ftp']); return PEAR::raiseError('ERROR: Ftp configuration file must set all ' . 'directory configuration variables. These variables were not set: ' . $fail); } while (false); // poor man's catch unset($this->files['ftp']); return PEAR::raiseError('no remote host specified'); } /** * Reads the existing configurations and creates the _channels array from it */ function _setupChannels() { $set = array_flip(array_values($this->_channels)); foreach ($this->configuration as $layer => $data) { $i = 1000; if (isset($data['__channels']) && is_array($data['__channels'])) { foreach ($data['__channels'] as $channel => $info) { $set[$channel] = $i++; } } } $this->_channels = array_values(array_flip($set)); $this->setChannels($this->_channels); } function deleteChannel($channel) { $ch = strtolower($channel); foreach ($this->configuration as $layer => $data) { if (isset($data['__channels']) && isset($data['__channels'][$ch])) { unset($this->configuration[$layer]['__channels'][$ch]); } } $this->_channels = array_flip($this->_channels); unset($this->_channels[$ch]); $this->_channels = array_flip($this->_channels); } /** * Merges data into a config layer from a file. Does the same * thing as readConfigFile, except it does not replace all * existing values in the config layer. * @param string file to read from * @param bool whether to overwrite existing data (default TRUE) * @param string config layer to insert data into ('user' or 'system') * @param string if true, errors are returned if file opening fails * @return bool TRUE on success or a PEAR error on failure */ function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true) { if (empty($this->files[$layer])) { return $this->raiseError("unknown config layer `$layer'"); } if ($file === null) { $file = $this->files[$layer]; } $data = $this->_readConfigDataFrom($file); if (PEAR::isError($data)) { if (!$strict) { return true; } $this->_errorsFound++; $this->_lastError = $data; return $data; } $this->_decodeInput($data); if ($override) { $this->configuration[$layer] = PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data); } else { $this->configuration[$layer] = PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]); } $this->_setupChannels(); if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) { $this->_registry[$layer] = new PEAR_Registry( $phpdir, false, false, $this->get('metadata_dir', $layer, 'pear.php.net')); $this->_registry[$layer]->setConfig($this, false); $this->_regInitialized[$layer] = false; } else { unset($this->_registry[$layer]); } return true; } /** * @param array * @param array * @return array */ public static function arrayMergeRecursive($arr2, $arr1) { $ret = array(); foreach ($arr2 as $key => $data) { if (!isset($arr1[$key])) { $ret[$key] = $data; unset($arr1[$key]); continue; } if (is_array($data)) { if (!is_array($arr1[$key])) { $ret[$key] = $arr1[$key]; unset($arr1[$key]); continue; } $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]); unset($arr1[$key]); } } return array_merge($ret, $arr1); } /** * Writes data into a config layer from a file. * * @param string|null file to read from, or null for default * @param string config layer to insert data into ('user' or * 'system') * @param string|null data to write to config file or null for internal data [DEPRECATED] * @return bool TRUE on success or a PEAR error on failure */ function writeConfigFile($file = null, $layer = 'user', $data = null) { $this->_lazyChannelSetup($layer); if ($layer == 'both' || $layer == 'all') { foreach ($this->files as $type => $file) { $err = $this->writeConfigFile($file, $type, $data); if (PEAR::isError($err)) { return $err; } } return true; } if (empty($this->files[$layer])) { return $this->raiseError("unknown config file type `$layer'"); } if ($file === null) { $file = $this->files[$layer]; } $data = ($data === null) ? $this->configuration[$layer] : $data; $this->_encodeOutput($data); $opt = array('-p', dirname($file)); if (!@System::mkDir($opt)) { return $this->raiseError("could not create directory: " . dirname($file)); } if (file_exists($file) && is_file($file) && !is_writeable($file)) { return $this->raiseError("no write access to $file!"); } $fp = @fopen($file, "w"); if (!$fp) { return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)"); } $contents = "#PEAR_Config 0.9\n" . serialize($data); if (!@fwrite($fp, $contents)) { return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)"); } return true; } /** * Reads configuration data from a file and returns the parsed data * in an array. * * @param string file to read from * @return array configuration data or a PEAR error on failure * @access private */ function _readConfigDataFrom($file) { $fp = false; if (file_exists($file)) { $fp = @fopen($file, "r"); } if (!$fp) { return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed"); } $size = filesize($file); fclose($fp); $contents = file_get_contents($file); if (empty($contents)) { return $this->raiseError('Configuration file "' . $file . '" is empty'); } $version = false; if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) { $version = $matches[1]; $contents = substr($contents, strlen($matches[0])); } else { // Museum config file if (substr($contents,0,2) == 'a:') { $version = '0.1'; } } if ($version && version_compare("$version", '1', '<')) { $data = @unserialize($contents); if (!is_array($data) && !$data) { if ($contents == serialize(false)) { $data = array(); } else { $err = $this->raiseError("PEAR_Config: bad data in $file"); return $err; } } if (!is_array($data)) { if (strlen(trim($contents)) > 0) { $error = "PEAR_Config: bad data in $file"; $err = $this->raiseError($error); return $err; } $data = array(); } // add parsing of newer formats here... } else { $err = $this->raiseError("$file: unknown version `$version'"); return $err; } return $data; } /** * Gets the file used for storing the config for a layer * * @param string $layer 'user' or 'system' */ function getConfFile($layer) { return $this->files[$layer]; } /** * @param string Configuration class name, used for detecting duplicate calls * @param array information on a role as parsed from its xml file * @return true|PEAR_Error * @access private */ function _addConfigVars($class, $vars) { static $called = array(); if (isset($called[$class])) { return; } $called[$class] = 1; if (count($vars) > 3) { return $this->raiseError('Roles can only define 3 new config variables or less'); } foreach ($vars as $name => $var) { if (!is_array($var)) { return $this->raiseError('Configuration information must be an array'); } if (!isset($var['type'])) { return $this->raiseError('Configuration information must contain a type'); } elseif (!in_array($var['type'], array('string', 'mask', 'password', 'directory', 'file', 'set'))) { return $this->raiseError( 'Configuration type must be one of directory, file, string, ' . 'mask, set, or password'); } if (!isset($var['default'])) { return $this->raiseError( 'Configuration information must contain a default value ("default" index)'); } if (is_array($var['default'])) { $real_default = ''; foreach ($var['default'] as $config_var => $val) { if (strpos($config_var, 'text') === 0) { $real_default .= $val; } elseif (strpos($config_var, 'constant') === 0) { if (!defined($val)) { return $this->raiseError( 'Unknown constant "' . $val . '" requested in ' . 'default value for configuration variable "' . $name . '"'); } $real_default .= constant($val); } elseif (isset($this->configuration_info[$config_var])) { $real_default .= $this->configuration_info[$config_var]['default']; } else { return $this->raiseError( 'Unknown request for "' . $config_var . '" value in ' . 'default value for configuration variable "' . $name . '"'); } } $var['default'] = $real_default; } if ($var['type'] == 'integer') { $var['default'] = (integer) $var['default']; } if (!isset($var['doc'])) { return $this->raiseError( 'Configuration information must contain a summary ("doc" index)'); } if (!isset($var['prompt'])) { return $this->raiseError( 'Configuration information must contain a simple prompt ("prompt" index)'); } if (!isset($var['group'])) { return $this->raiseError( 'Configuration information must contain a simple group ("group" index)'); } if (isset($this->configuration_info[$name])) { return $this->raiseError('Configuration variable "' . $name . '" already exists'); } $this->configuration_info[$name] = $var; // fix bug #7351: setting custom config variable in a channel fails $this->_channelConfigInfo[] = $name; } return true; } /** * Encodes/scrambles configuration data before writing to files. * Currently, 'password' values will be base64-encoded as to avoid * that people spot cleartext passwords by accident. * * @param array (reference) array to encode values in * @return bool TRUE on success * @access private */ function _encodeOutput(&$data) { foreach ($data as $key => $value) { if ($key == '__channels') { foreach ($data['__channels'] as $channel => $blah) { $this->_encodeOutput($data['__channels'][$channel]); } } if (!isset($this->configuration_info[$key])) { continue; } $type = $this->configuration_info[$key]['type']; switch ($type) { // we base64-encode passwords so they are at least // not shown in plain by accident case 'password': { $data[$key] = base64_encode($data[$key]); break; } case 'mask': { $data[$key] = octdec($data[$key]); break; } } } return true; } /** * Decodes/unscrambles configuration data after reading from files. * * @param array (reference) array to encode values in * @return bool TRUE on success * @access private * * @see PEAR_Config::_encodeOutput */ function _decodeInput(&$data) { if (!is_array($data)) { return true; } foreach ($data as $key => $value) { if ($key == '__channels') { foreach ($data['__channels'] as $channel => $blah) { $this->_decodeInput($data['__channels'][$channel]); } } if (!isset($this->configuration_info[$key])) { continue; } $type = $this->configuration_info[$key]['type']; switch ($type) { case 'password': { $data[$key] = base64_decode($data[$key]); break; } case 'mask': { $data[$key] = decoct($data[$key]); break; } } } return true; } /** * Retrieve the default channel. * * On startup, channels are not initialized, so if the default channel is not * pear.php.net, then initialize the config. * @param string registry layer * @return string|false */ function getDefaultChannel($layer = null) { $ret = false; if ($layer === null) { foreach ($this->layers as $layer) { if (isset($this->configuration[$layer]['default_channel'])) { $ret = $this->configuration[$layer]['default_channel']; break; } } } elseif (isset($this->configuration[$layer]['default_channel'])) { $ret = $this->configuration[$layer]['default_channel']; } if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') { $ret = 'pecl.php.net'; } if ($ret) { if ($ret != 'pear.php.net') { $this->_lazyChannelSetup(); } return $ret; } return PEAR_CONFIG_DEFAULT_CHANNEL; } /** * Returns a configuration value, prioritizing layers as per the * layers property. * * @param string config key * @return mixed the config value, or NULL if not found * @access public */ function get($key, $layer = null, $channel = false) { if (!isset($this->configuration_info[$key])) { return null; } if ($key == '__channels') { return null; } if ($key == 'default_channel') { return $this->getDefaultChannel($layer); } if (!$channel) { $channel = $this->getDefaultChannel(); } elseif ($channel != 'pear.php.net') { $this->_lazyChannelSetup(); } $channel = strtolower($channel); $test = (in_array($key, $this->_channelConfigInfo)) ? $this->_getChannelValue($key, $layer, $channel) : null; if ($test !== null) { if ($this->_installRoot) { if (in_array($this->getGroup($key), array('File Locations', 'File Locations (Advanced)')) && $this->getType($key) == 'directory') { return $this->_prependPath($test, $this->_installRoot); } } return $test; } if ($layer === null) { foreach ($this->layers as $layer) { if (isset($this->configuration[$layer][$key])) { $test = $this->configuration[$layer][$key]; if ($this->_installRoot) { if (in_array($this->getGroup($key), array('File Locations', 'File Locations (Advanced)')) && $this->getType($key) == 'directory') { return $this->_prependPath($test, $this->_installRoot); } } if ($key == 'preferred_mirror') { $reg = &$this->getRegistry(); if (is_object($reg)) { $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $channel; } if (!$chan->getMirror($test) && $chan->getName() != $test) { return $channel; // mirror does not exist } } } return $test; } } } elseif (isset($this->configuration[$layer][$key])) { $test = $this->configuration[$layer][$key]; if ($this->_installRoot) { if (in_array($this->getGroup($key), array('File Locations', 'File Locations (Advanced)')) && $this->getType($key) == 'directory') { return $this->_prependPath($test, $this->_installRoot); } } if ($key == 'preferred_mirror') { $reg = &$this->getRegistry(); if (is_object($reg)) { $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $channel; } if (!$chan->getMirror($test) && $chan->getName() != $test) { return $channel; // mirror does not exist } } } return $test; } return null; } /** * Returns a channel-specific configuration value, prioritizing layers as per the * layers property. * * @param string config key * @return mixed the config value, or NULL if not found * @access private */ function _getChannelValue($key, $layer, $channel) { if ($key == '__channels' || $channel == 'pear.php.net') { return null; } $ret = null; if ($layer === null) { foreach ($this->layers as $ilayer) { if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) { $ret = $this->configuration[$ilayer]['__channels'][$channel][$key]; break; } } } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) { $ret = $this->configuration[$layer]['__channels'][$channel][$key]; } if ($key != 'preferred_mirror') { return $ret; } if ($ret !== null) { $reg = &$this->getRegistry($layer); if (is_object($reg)) { $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $channel; } if (!$chan->getMirror($ret) && $chan->getName() != $ret) { return $channel; // mirror does not exist } } return $ret; } if ($channel != $this->getDefaultChannel($layer)) { return $channel; // we must use the channel name as the preferred mirror // if the user has not chosen an alternate } return $this->getDefaultChannel($layer); } /** * Set a config value in a specific layer (defaults to 'user'). * Enforces the types defined in the configuration_info array. An * integer config variable will be cast to int, and a set config * variable will be validated against its legal values. * * @param string config key * @param string config value * @param string (optional) config layer * @param string channel to set this value for, or null for global value * @return bool TRUE on success, FALSE on failure */ function set($key, $value, $layer = 'user', $channel = false) { if ($key == '__channels') { return false; } if (!isset($this->configuration[$layer])) { return false; } if ($key == 'default_channel') { // can only set this value globally $channel = 'pear.php.net'; if ($value != 'pear.php.net') { $this->_lazyChannelSetup($layer); } } if ($key == 'preferred_mirror') { if ($channel == '__uri') { return false; // can't set the __uri pseudo-channel's mirror } $reg = &$this->getRegistry($layer); if (is_object($reg)) { $chan = $reg->getChannel($channel ? $channel : 'pear.php.net'); if (PEAR::isError($chan)) { return false; } if (!$chan->getMirror($value) && $chan->getName() != $value) { return false; // mirror does not exist } } } if (!isset($this->configuration_info[$key])) { return false; } extract($this->configuration_info[$key]); switch ($type) { case 'integer': $value = (int)$value; break; case 'set': { // If a valid_set is specified, require the value to // be in the set. If there is no valid_set, accept // any value. if ($valid_set) { reset($valid_set); if ((key($valid_set) === 0 && !in_array($value, $valid_set)) || (key($valid_set) !== 0 && empty($valid_set[$value]))) { return false; } } break; } } if (!$channel) { $channel = $this->get('default_channel', null, 'pear.php.net'); } if (!in_array($channel, $this->_channels)) { $this->_lazyChannelSetup($layer); $reg = &$this->getRegistry($layer); if ($reg) { $channel = $reg->channelName($channel); } if (!in_array($channel, $this->_channels)) { return false; } } if ($channel != 'pear.php.net') { if (in_array($key, $this->_channelConfigInfo)) { $this->configuration[$layer]['__channels'][$channel][$key] = $value; return true; } return false; } if ($key == 'default_channel') { if (!isset($reg)) { $reg = &$this->getRegistry($layer); if (!$reg) { $reg = &$this->getRegistry(); } } if ($reg) { $value = $reg->channelName($value); } if (!$value) { return false; } } $this->configuration[$layer][$key] = $value; if ($key == 'php_dir' && !$this->_noRegistry) { if (!isset($this->_registry[$layer]) || $value != $this->_registry[$layer]->install_dir) { $this->_registry[$layer] = new PEAR_Registry($value); $this->_regInitialized[$layer] = false; $this->_registry[$layer]->setConfig($this, false); } } return true; } function _lazyChannelSetup($uselayer = false) { if ($this->_noRegistry) { return; } $merge = false; foreach ($this->_registry as $layer => $p) { if ($uselayer && $uselayer != $layer) { continue; } if (!$this->_regInitialized[$layer]) { if ($layer == 'default' && isset($this->_registry['user']) || isset($this->_registry['system'])) { // only use the default registry if there are no alternatives continue; } if (!is_object($this->_registry[$layer])) { if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) { $this->_registry[$layer] = new PEAR_Registry( $phpdir, false, false, $this->get('metadata_dir', $layer, 'pear.php.net')); $this->_registry[$layer]->setConfig($this, false); $this->_regInitialized[$layer] = false; } else { unset($this->_registry[$layer]); return; } } $this->setChannels($this->_registry[$layer]->listChannels(), $merge); $this->_regInitialized[$layer] = true; $merge = true; } } } /** * Set the list of channels. * * This should be set via a call to {@link PEAR_Registry::listChannels()} * @param array * @param bool * @return bool success of operation */ function setChannels($channels, $merge = false) { if (!is_array($channels)) { return false; } if ($merge) { $this->_channels = array_merge($this->_channels, $channels); } else { $this->_channels = $channels; } foreach ($channels as $channel) { $channel = strtolower($channel); if ($channel == 'pear.php.net') { continue; } foreach ($this->layers as $layer) { if (!isset($this->configuration[$layer]['__channels'])) { $this->configuration[$layer]['__channels'] = array(); } if (!isset($this->configuration[$layer]['__channels'][$channel]) || !is_array($this->configuration[$layer]['__channels'][$channel])) { $this->configuration[$layer]['__channels'][$channel] = array(); } } } return true; } /** * Get the type of a config value. * * @param string config key * * @return string type, one of "string", "integer", "file", * "directory", "set" or "password". * * @access public * */ function getType($key) { if (isset($this->configuration_info[$key])) { return $this->configuration_info[$key]['type']; } return false; } /** * Get the documentation for a config value. * * @param string config key * @return string documentation string * * @access public * */ function getDocs($key) { if (isset($this->configuration_info[$key])) { return $this->configuration_info[$key]['doc']; } return false; } /** * Get the short documentation for a config value. * * @param string config key * @return string short documentation string * * @access public * */ function getPrompt($key) { if (isset($this->configuration_info[$key])) { return $this->configuration_info[$key]['prompt']; } return false; } /** * Get the parameter group for a config key. * * @param string config key * @return string parameter group * * @access public * */ function getGroup($key) { if (isset($this->configuration_info[$key])) { return $this->configuration_info[$key]['group']; } return false; } /** * Get the list of parameter groups. * * @return array list of parameter groups * * @access public * */ function getGroups() { $tmp = array(); foreach ($this->configuration_info as $key => $info) { $tmp[$info['group']] = 1; } return array_keys($tmp); } /** * Get the list of the parameters in a group. * * @param string $group parameter group * @return array list of parameters in $group * * @access public * */ function getGroupKeys($group) { $keys = array(); foreach ($this->configuration_info as $key => $info) { if ($info['group'] == $group) { $keys[] = $key; } } return $keys; } /** * Get the list of allowed set values for a config value. Returns * NULL for config values that are not sets. * * @param string config key * @return array enumerated array of set values, or NULL if the * config key is unknown or not a set * * @access public * */ function getSetValues($key) { if (isset($this->configuration_info[$key]) && isset($this->configuration_info[$key]['type']) && $this->configuration_info[$key]['type'] == 'set') { $valid_set = $this->configuration_info[$key]['valid_set']; reset($valid_set); if (key($valid_set) === 0) { return $valid_set; } return array_keys($valid_set); } return null; } /** * Get all the current config keys. * * @return array simple array of config keys * * @access public */ function getKeys() { $keys = array(); foreach ($this->layers as $layer) { $test = $this->configuration[$layer]; if (isset($test['__channels'])) { foreach ($test['__channels'] as $channel => $configs) { $keys = array_merge($keys, $configs); } } unset($test['__channels']); $keys = array_merge($keys, $test); } return array_keys($keys); } /** * Remove the a config key from a specific config layer. * * @param string config key * @param string (optional) config layer * @param string (optional) channel (defaults to default channel) * @return bool TRUE on success, FALSE on failure * * @access public */ function remove($key, $layer = 'user', $channel = null) { if ($channel === null) { $channel = $this->getDefaultChannel(); } if ($channel !== 'pear.php.net') { if (isset($this->configuration[$layer]['__channels'][$channel][$key])) { unset($this->configuration[$layer]['__channels'][$channel][$key]); return true; } } if (isset($this->configuration[$layer][$key])) { unset($this->configuration[$layer][$key]); return true; } return false; } /** * Temporarily remove an entire config layer. USE WITH CARE! * * @param string config key * @param string (optional) config layer * @return bool TRUE on success, FALSE on failure * * @access public */ function removeLayer($layer) { if (isset($this->configuration[$layer])) { $this->configuration[$layer] = array(); return true; } return false; } /** * Stores configuration data in a layer. * * @param string config layer to store * @return bool TRUE on success, or PEAR error on failure * * @access public */ function store($layer = 'user', $data = null) { return $this->writeConfigFile(null, $layer, $data); } /** * Tells what config layer that gets to define a key. * * @param string config key * @param boolean return the defining channel * * @return string|array the config layer, or an empty string if not found. * * if $returnchannel, the return is an array array('layer' => layername, * 'channel' => channelname), or an empty string if not found * * @access public */ function definedBy($key, $returnchannel = false) { foreach ($this->layers as $layer) { $channel = $this->getDefaultChannel(); if ($channel !== 'pear.php.net') { if (isset($this->configuration[$layer]['__channels'][$channel][$key])) { if ($returnchannel) { return array('layer' => $layer, 'channel' => $channel); } return $layer; } } if (isset($this->configuration[$layer][$key])) { if ($returnchannel) { return array('layer' => $layer, 'channel' => 'pear.php.net'); } return $layer; } } return ''; } /** * Tells whether a given key exists as a config value. * * @param string config key * @return bool whether exists in this object * * @access public */ function isDefined($key) { foreach ($this->layers as $layer) { if (isset($this->configuration[$layer][$key])) { return true; } } return false; } /** * Tells whether a given config layer exists. * * @param string config layer * @return bool whether exists in this object * * @access public */ function isDefinedLayer($layer) { return isset($this->configuration[$layer]); } /** * Returns the layers defined (except the 'default' one) * * @return array of the defined layers */ function getLayers() { $cf = $this->configuration; unset($cf['default']); return array_keys($cf); } function apiVersion() { return '1.1'; } /** * @return PEAR_Registry */ function &getRegistry($use = null) { $layer = $use === null ? 'user' : $use; if (isset($this->_registry[$layer])) { return $this->_registry[$layer]; } elseif ($use === null && isset($this->_registry['system'])) { return $this->_registry['system']; } elseif ($use === null && isset($this->_registry['default'])) { return $this->_registry['default']; } elseif ($use) { $a = false; return $a; } // only go here if null was passed in echo "CRITICAL ERROR: Registry could not be initialized from any value"; exit(1); } /** * This is to allow customization like the use of installroot * @param PEAR_Registry * @return bool */ function setRegistry(&$reg, $layer = 'user') { if ($this->_noRegistry) { return false; } if (!in_array($layer, array('user', 'system'))) { return false; } $this->_registry[$layer] = &$reg; if (is_object($reg)) { $this->_registry[$layer]->setConfig($this, false); } return true; } function noRegistry() { $this->_noRegistry = true; } /** * @return PEAR_REST */ function &getREST($version, $options = array()) { $version = str_replace('.', '', $version); if (!class_exists($class = 'PEAR_REST_' . $version)) { require_once 'PEAR/REST/' . $version . '.php'; } $remote = new $class($this, $options); return $remote; } /** * The ftp server is set in {@link readFTPConfigFile()}. It exists only if a * remote configuration file has been specified * @return PEAR_FTP|false */ function &getFTP() { if (isset($this->_ftp)) { return $this->_ftp; } $a = false; return $a; } static function _prependPath($path, $prepend) { if (strlen($prepend) > 0) { if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { if (preg_match('/^[a-z]:/i', $prepend)) { $prepend = substr($prepend, 2); } elseif ($prepend[0] != '\\') { $prepend = "\\$prepend"; } $path = substr($path, 0, 2) . $prepend . substr($path, 2); } else { $path = $prepend . $path; } } return $path; } /** * @param string|false installation directory to prepend to all _dir variables, or false to * disable */ function setInstallRoot($root) { if (substr($root, -1) == DIRECTORY_SEPARATOR) { $root = substr($root, 0, -1); } $old = $this->_installRoot; $this->_installRoot = $root; if (($old != $root) && !$this->_noRegistry) { foreach (array_keys($this->_registry) as $layer) { if ($layer == 'ftp' || !isset($this->_registry[$layer])) { continue; } $this->_registry[$layer] = new PEAR_Registry( $this->get('php_dir', $layer, 'pear.php.net'), false, false, $this->get('metadata_dir', $layer, 'pear.php.net')); $this->_registry[$layer]->setConfig($this, false); $this->_regInitialized[$layer] = false; } } } } PK!`eEAEA PEAR/REST.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * For downloading xml files */ require_once 'PEAR.php'; require_once 'PEAR/XMLParser.php'; require_once 'PEAR/Proxy.php'; /** * Intelligently retrieve data, following hyperlinks if necessary, and re-directing * as well * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_REST { var $config; var $_options; function __construct(&$config, $options = array()) { $this->config = &$config; $this->_options = $options; } /** * Retrieve REST data, but always retrieve the local cache if it is available. * * This is useful for elements that should never change, such as information on a particular * release * @param string full URL to this resource * @param array|false contents of the accept-encoding header * @param boolean if true, xml will be returned as a string, otherwise, xml will be * parsed using PEAR_XMLParser * @return string|array */ function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false) { $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . md5($url) . 'rest.cachefile'; if (file_exists($cachefile)) { return unserialize(implode('', file($cachefile))); } return $this->retrieveData($url, $accept, $forcestring, $channel); } /** * Retrieve a remote REST resource * @param string full URL to this resource * @param array|false contents of the accept-encoding header * @param boolean if true, xml will be returned as a string, otherwise, xml will be * parsed using PEAR_XMLParser * @return string|array */ function retrieveData($url, $accept = false, $forcestring = false, $channel = false) { $cacheId = $this->getCacheId($url); if ($ret = $this->useLocalCache($url, $cacheId)) { return $ret; } $file = $trieddownload = false; if (!isset($this->_options['offline'])) { $trieddownload = true; $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel); } if (PEAR::isError($file)) { if ($file->getCode() !== -9276) { return $file; } $trieddownload = false; $file = false; // use local copy if available on socket connect error } if (!$file) { $ret = $this->getCache($url); if (!PEAR::isError($ret) && $trieddownload) { // reset the age of the cache if the server says it was unmodified $result = $this->saveCache($url, $ret, null, true, $cacheId); if (PEAR::isError($result)) { return PEAR::raiseError($result->getMessage()); } } return $ret; } if (is_array($file)) { $headers = $file[2]; $lastmodified = $file[1]; $content = $file[0]; } else { $headers = array(); $lastmodified = false; $content = $file; } if ($forcestring) { $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId); if (PEAR::isError($result)) { return PEAR::raiseError($result->getMessage()); } return $content; } if (isset($headers['content-type'])) { $content_type = explode(";", $headers['content-type']); $content_type = $content_type[0]; switch ($content_type) { case 'text/xml' : case 'application/xml' : case 'text/plain' : if ($content_type === 'text/plain') { $check = substr($content, 0, 5); if ($check !== 'parse($content); PEAR::popErrorHandling(); if (PEAR::isError($err)) { return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' . $err->getMessage()); } $content = $parser->getData(); case 'text/html' : default : // use it as a string } } else { // assume XML $parser = new PEAR_XMLParser; $parser->parse($content); $content = $parser->getData(); } $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId); if (PEAR::isError($result)) { return PEAR::raiseError($result->getMessage()); } return $content; } function useLocalCache($url, $cacheid = null) { if (!is_array($cacheid)) { $cacheid = $this->getCacheId($url); } $cachettl = $this->config->get('cache_ttl'); // If cache is newer than $cachettl seconds, we use the cache! if (is_array($cacheid) && time() - $cacheid['age'] < $cachettl) { return $this->getCache($url); } return false; } /** * @param string $url * * @return bool|mixed */ function getCacheId($url) { $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . md5($url) . 'rest.cacheid'; if (!file_exists($cacheidfile)) { return false; } $ret = unserialize(implode('', file($cacheidfile))); return $ret; } function getCache($url) { $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . md5($url) . 'rest.cachefile'; if (!file_exists($cachefile)) { return PEAR::raiseError('No cached content available for "' . $url . '"'); } return unserialize(implode('', file($cachefile))); } /** * @param string full URL to REST resource * @param string original contents of the REST resource * @param array HTTP Last-Modified and ETag headers * @param bool if true, then the cache id file should be regenerated to * trigger a new time-to-live value */ function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null) { $cache_dir = $this->config->get('cache_dir'); $d = $cache_dir . DIRECTORY_SEPARATOR . md5($url); $cacheidfile = $d . 'rest.cacheid'; $cachefile = $d . 'rest.cachefile'; if (!is_dir($cache_dir)) { if (System::mkdir(array('-p', $cache_dir)) === false) { return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed."); } } if (!is_writeable($cache_dir)) { // If writing to the cache dir is not going to work, silently do nothing. // An ugly hack, but retains compat with PEAR 1.9.1 where many commands // work fine as non-root user (w/out write access to default cache dir). return true; } if ($cacheid === null && $nochange) { $cacheid = unserialize(implode('', file($cacheidfile))); } $idData = serialize(array( 'age' => time(), 'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified), )); $result = $this->saveCacheFile($cacheidfile, $idData); if (PEAR::isError($result)) { return $result; } elseif ($nochange) { return true; } $result = $this->saveCacheFile($cachefile, serialize($contents)); if (PEAR::isError($result)) { if (file_exists($cacheidfile)) { @unlink($cacheidfile); } return $result; } return true; } function saveCacheFile($file, $contents) { $len = strlen($contents); $cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode if ($cachefile_fp !== false) { // create file if (fwrite($cachefile_fp, $contents, $len) < $len) { fclose($cachefile_fp); return PEAR::raiseError("Could not write $file."); } } else { // update file $cachefile_fp = @fopen($file, 'r+b'); // do not truncate file if (!$cachefile_fp) { return PEAR::raiseError("Could not open $file for writing."); } if (OS_WINDOWS) { $not_symlink = !is_link($file); // see bug #18834 } else { $cachefile_lstat = lstat($file); $cachefile_fstat = fstat($cachefile_fp); $not_symlink = $cachefile_lstat['mode'] == $cachefile_fstat['mode'] && $cachefile_lstat['ino'] == $cachefile_fstat['ino'] && $cachefile_lstat['dev'] == $cachefile_fstat['dev'] && $cachefile_fstat['nlink'] === 1; } if ($not_symlink) { ftruncate($cachefile_fp, 0); // NOW truncate if (fwrite($cachefile_fp, $contents, $len) < $len) { fclose($cachefile_fp); return PEAR::raiseError("Could not write $file."); } } else { fclose($cachefile_fp); $link = function_exists('readlink') ? readlink($file) : $file; return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack'); } } fclose($cachefile_fp); return true; } /** * Efficiently Download a file through HTTP. Returns downloaded file as a string in-memory * This is best used for small files * * If an HTTP proxy has been configured (http_proxy PEAR_Config * setting), the proxy will be used. * * @param string $url the URL to download * @param string $save_dir directory to save file in * @param false|string|array $lastmodified header values to check against for caching * use false to return the header values from this download * @param false|array $accept Accept headers to send * @return string|array Returns the contents of the downloaded file or a PEAR * error on failure. If the error is caused by * socket-related errors, the error object will * have the fsockopen error code available through * getCode(). If caching is requested, then return the header * values. * * @access public */ function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) { static $redirect = 0; // always reset , so we are clean case of error $wasredirect = $redirect; $redirect = 0; $info = parse_url($url); if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) { return PEAR::raiseError('Cannot download non-http URL "' . $url . '"'); } if (!isset($info['host'])) { return PEAR::raiseError('Cannot download from non-URL "' . $url . '"'); } $host = isset($info['host']) ? $info['host'] : null; $port = isset($info['port']) ? $info['port'] : null; $path = isset($info['path']) ? $info['path'] : null; $schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http'; $proxy = new PEAR_Proxy($this->config); if (empty($port)) { $port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80; } if ($proxy->isProxyConfigured() && $schema === 'http') { $request = "GET $url HTTP/1.1\r\n"; } else { $request = "GET $path HTTP/1.1\r\n"; } $request .= "Host: $host\r\n"; $ifmodifiedsince = ''; if (is_array($lastmodified)) { if (isset($lastmodified['Last-Modified'])) { $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n"; } if (isset($lastmodified['ETag'])) { $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n"; } } else { $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : ''); } $request .= $ifmodifiedsince . "User-Agent: PEAR/1.10.16/PHP/" . PHP_VERSION . "\r\n"; $username = $this->config->get('username', null, $channel); $password = $this->config->get('password', null, $channel); if ($username && $password) { $tmp = base64_encode("$username:$password"); $request .= "Authorization: Basic $tmp\r\n"; } $proxyAuth = $proxy->getProxyAuth(); if ($proxyAuth) { $request .= 'Proxy-Authorization: Basic ' . $proxyAuth . "\r\n"; } if ($accept) { $request .= 'Accept: ' . implode(', ', $accept) . "\r\n"; } $request .= "Accept-Encoding:\r\n"; $request .= "Connection: close\r\n"; $request .= "\r\n"; $secure = ($schema == 'https'); $fp = $proxy->openSocket($host, $port, $secure); if (PEAR::isError($fp)) { return $fp; } fwrite($fp, $request); $headers = array(); $reply = 0; while ($line = trim(fgets($fp, 1024))) { if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) { $headers[strtolower($matches[1])] = trim($matches[2]); } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { $reply = (int)$matches[1]; if ($reply == 304 && ($lastmodified || ($lastmodified === false))) { return false; } if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) { return PEAR::raiseError("File $schema://$host:$port$path not valid (received: $line)"); } } } if ($reply != 200) { if (!isset($headers['location'])) { return PEAR::raiseError("File $schema://$host:$port$path not valid (redirected but no location)"); } if ($wasredirect > 4) { return PEAR::raiseError("File $schema://$host:$port$path not valid (redirection looped more than 5 times)"); } $redirect = $wasredirect + 1; return $this->downloadHttp($headers['location'], $lastmodified, $accept, $channel); } $length = isset($headers['content-length']) ? $headers['content-length'] : -1; $data = ''; while ($chunk = @fread($fp, 8192)) { $data .= $chunk; } fclose($fp); if ($lastmodified === false || $lastmodified) { if (isset($headers['etag'])) { $lastmodified = array('ETag' => $headers['etag']); } if (isset($headers['last-modified'])) { if (is_array($lastmodified)) { $lastmodified['Last-Modified'] = $headers['last-modified']; } else { $lastmodified = $headers['last-modified']; } } return array($data, $lastmodified, $headers); } return $data; } } PK!ym6m6PEAR/Exception.phpnu[ * @author Hans Lellelid * @author Bertrand Mansion * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.3.3 */ /** * Base PEAR_Exception Class * * 1) Features: * * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) * - Definable triggers, shot when exceptions occur * - Pretty and informative error messages * - Added more context info available (like class, method or cause) * - cause can be a PEAR_Exception or an array of mixed * PEAR_Exceptions/PEAR_ErrorStack warnings * - callbacks for specific exception classes and their children * * 2) Ideas: * * - Maybe a way to define a 'template' for the output * * 3) Inherited properties from PHP Exception Class: * * protected $message * protected $code * protected $line * protected $file * private $trace * * 4) Inherited methods from PHP Exception Class: * * __clone * __construct * getMessage * getCode * getFile * getLine * getTraceSafe * getTraceSafeAsString * __toString * * 5) Usage example * * * require_once 'PEAR/Exception.php'; * * class Test { * function foo() { * throw new PEAR_Exception('Error Message', ERROR_CODE); * } * } * * function myLogger($pear_exception) { * echo $pear_exception->getMessage(); * } * // each time a exception is thrown the 'myLogger' will be called * // (its use is completely optional) * PEAR_Exception::addObserver('myLogger'); * $test = new Test; * try { * $test->foo(); * } catch (PEAR_Exception $e) { * print $e; * } * * * @category pear * @package PEAR * @author Tomas V.V.Cox * @author Hans Lellelid * @author Bertrand Mansion * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.3.3 * */ class PEAR_Exception extends Exception { const OBSERVER_PRINT = -2; const OBSERVER_TRIGGER = -4; const OBSERVER_DIE = -8; protected $cause; private static $_observers = array(); private static $_uniqueid = 0; private $_trace; /** * Supported signatures: * - PEAR_Exception(string $message); * - PEAR_Exception(string $message, int $code); * - PEAR_Exception(string $message, Exception $cause); * - PEAR_Exception(string $message, Exception $cause, int $code); * - PEAR_Exception(string $message, PEAR_Error $cause); * - PEAR_Exception(string $message, PEAR_Error $cause, int $code); * - PEAR_Exception(string $message, array $causes); * - PEAR_Exception(string $message, array $causes, int $code); * @param string exception message * @param int|Exception|PEAR_Error|array|null exception cause * @param int|null exception code or null */ public function __construct($message, $p2 = null, $p3 = null) { if (is_int($p2)) { $code = $p2; $this->cause = null; } elseif (is_object($p2) || is_array($p2)) { // using is_object allows both Exception and PEAR_Error if (is_object($p2) && !($p2 instanceof Exception)) { if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) { throw new PEAR_Exception('exception cause must be Exception, ' . 'array, or PEAR_Error'); } } $code = $p3; if (is_array($p2) && isset($p2['message'])) { // fix potential problem of passing in a single warning $p2 = array($p2); } $this->cause = $p2; } else { $code = null; $this->cause = null; } parent::__construct($message, $code); $this->signal(); } /** * @param mixed $callback - A valid php callback, see php func is_callable() * - A PEAR_Exception::OBSERVER_* constant * - An array(const PEAR_Exception::OBSERVER_*, * mixed $options) * @param string $label The name of the observer. Use this if you want * to remove it later with removeObserver() */ public static function addObserver($callback, $label = 'default') { self::$_observers[$label] = $callback; } public static function removeObserver($label = 'default') { unset(self::$_observers[$label]); } /** * @return int unique identifier for an observer */ public static function getUniqueId() { return self::$_uniqueid++; } private function signal() { foreach (self::$_observers as $func) { if (is_callable($func)) { call_user_func($func, $this); continue; } settype($func, 'array'); switch ($func[0]) { case self::OBSERVER_PRINT : $f = (isset($func[1])) ? $func[1] : '%s'; printf($f, $this->getMessage()); break; case self::OBSERVER_TRIGGER : $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; trigger_error($this->getMessage(), $f); break; case self::OBSERVER_DIE : $f = (isset($func[1])) ? $func[1] : '%s'; die(printf($f, $this->getMessage())); break; default: trigger_error('invalid observer type', E_USER_WARNING); } } } /** * Return specific error information that can be used for more detailed * error messages or translation. * * This method may be overridden in child exception classes in order * to add functionality not present in PEAR_Exception and is a placeholder * to define API * * The returned array must be an associative array of parameter => value like so: *
     * array('name' => $name, 'context' => array(...))
     * 
* @return array */ public function getErrorData() { return array(); } /** * Returns the exception that caused this exception to be thrown * @access public * @return Exception|array The context of the exception */ public function getCause() { return $this->cause; } /** * Function must be public to call on caused exceptions * @param array */ public function getCauseMessage(&$causes) { $trace = $this->getTraceSafe(); $cause = array('class' => get_class($this), 'message' => $this->message, 'file' => 'unknown', 'line' => 'unknown'); if (isset($trace[0])) { if (isset($trace[0]['file'])) { $cause['file'] = $trace[0]['file']; $cause['line'] = $trace[0]['line']; } } $causes[] = $cause; if ($this->cause instanceof PEAR_Exception) { $this->cause->getCauseMessage($causes); } elseif ($this->cause instanceof Exception) { $causes[] = array('class' => get_class($this->cause), 'message' => $this->cause->getMessage(), 'file' => $this->cause->getFile(), 'line' => $this->cause->getLine()); } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) { $causes[] = array('class' => get_class($this->cause), 'message' => $this->cause->getMessage(), 'file' => 'unknown', 'line' => 'unknown'); } elseif (is_array($this->cause)) { foreach ($this->cause as $cause) { if ($cause instanceof PEAR_Exception) { $cause->getCauseMessage($causes); } elseif ($cause instanceof Exception) { $causes[] = array('class' => get_class($cause), 'message' => $cause->getMessage(), 'file' => $cause->getFile(), 'line' => $cause->getLine()); } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) { $causes[] = array('class' => get_class($cause), 'message' => $cause->getMessage(), 'file' => 'unknown', 'line' => 'unknown'); } elseif (is_array($cause) && isset($cause['message'])) { // PEAR_ErrorStack warning $causes[] = array( 'class' => $cause['package'], 'message' => $cause['message'], 'file' => isset($cause['context']['file']) ? $cause['context']['file'] : 'unknown', 'line' => isset($cause['context']['line']) ? $cause['context']['line'] : 'unknown', ); } } } } public function getTraceSafe() { if (!isset($this->_trace)) { $this->_trace = $this->getTrace(); if (empty($this->_trace)) { $backtrace = debug_backtrace(); $this->_trace = array($backtrace[count($backtrace)-1]); } } return $this->_trace; } public function getErrorClass() { $trace = $this->getTraceSafe(); return $trace[0]['class']; } public function getErrorMethod() { $trace = $this->getTraceSafe(); return $trace[0]['function']; } public function __toString() { if (isset($_SERVER['REQUEST_URI'])) { return $this->toHtml(); } return $this->toText(); } public function toHtml() { $trace = $this->getTraceSafe(); $causes = array(); $this->getCauseMessage($causes); $html = '' . "\n"; foreach ($causes as $i => $cause) { $html .= '\n"; } $html .= '' . "\n" . '' . '' . '' . "\n"; foreach ($trace as $k => $v) { $html .= '' . '' . '' . "\n"; } $html .= '' . '' . '' . "\n" . '
' . str_repeat('-', $i) . ' ' . $cause['class'] . ': ' . htmlspecialchars($cause['message']) . ' in ' . $cause['file'] . ' ' . 'on line ' . $cause['line'] . '' . "
Exception trace
#FunctionLocation
' . $k . ''; if (!empty($v['class'])) { $html .= $v['class'] . $v['type']; } $html .= $v['function']; $args = array(); if (!empty($v['args'])) { foreach ($v['args'] as $arg) { if (is_null($arg)) $args[] = 'null'; elseif (is_array($arg)) $args[] = 'Array'; elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; elseif (is_int($arg) || is_double($arg)) $args[] = $arg; else { $arg = (string)$arg; $str = htmlspecialchars(substr($arg, 0, 16)); if (strlen($arg) > 16) $str .= '…'; $args[] = "'" . $str . "'"; } } } $html .= '(' . implode(', ',$args) . ')' . '' . (isset($v['file']) ? $v['file'] : 'unknown') . ':' . (isset($v['line']) ? $v['line'] : 'unknown') . '
' . ($k+1) . '{main} 
'; return $html; } public function toText() { $causes = array(); $this->getCauseMessage($causes); $causeMsg = ''; foreach ($causes as $i => $cause) { $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' . $cause['message'] . ' in ' . $cause['file'] . ' on line ' . $cause['line'] . "\n"; } return $causeMsg . $this->getTraceAsString(); } }PK!r"PEAR/ChannelFile.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Needed for error handling */ require_once 'PEAR/ErrorStack.php'; require_once 'PEAR/XMLParser.php'; require_once 'PEAR/Common.php'; /** * Error code if the channel.xml tag does not contain a valid version */ define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1); /** * Error code if the channel.xml tag version is not supported (version 1.0 is the only supported version, * currently */ define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2); /** * Error code if parsing is attempted with no xml extension */ define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3); /** * Error code if creating the xml parser resource fails */ define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4); /** * Error code used for all sax xml parsing errors */ define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5); /**#@+ * Validation errors */ /** * Error code when channel name is missing */ define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6); /** * Error code when channel name is invalid */ define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7); /** * Error code when channel summary is missing */ define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8); /** * Error code when channel summary is multi-line */ define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9); /** * Error code when channel server is missing for protocol */ define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10); /** * Error code when channel server is invalid for protocol */ define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11); /** * Error code when a mirror name is invalid */ define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21); /** * Error code when a mirror type is invalid */ define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22); /** * Error code when an attempt is made to generate xml, but the parsed content is invalid */ define('PEAR_CHANNELFILE_ERROR_INVALID', 23); /** * Error code when an empty package name validate regex is passed in */ define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24); /** * Error code when a tag has no version */ define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25); /** * Error code when a tag has no name */ define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26); /** * Error code when a tag has no name */ define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27); /** * Error code when a tag has no version attribute */ define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28); /** * Error code when a mirror does not exist but is called for in one of the set* * methods. */ define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32); /** * Error code when a server port is not numeric */ define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33); /** * Error code when contains no version attribute */ define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34); /** * Error code when contains no type attribute in a protocol definition */ define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35); /** * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel */ define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36); /** * Error code when ssl attribute is present and is not "yes" */ define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37); /**#@-*/ /** * Mirror types allowed. Currently only internet servers are recognized. */ $GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] = array('server'); /** * The Channel handling class * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_ChannelFile { /** * @access private * @var PEAR_ErrorStack * @access private */ var $_stack; /** * Supported channel.xml versions, for parsing * @var array * @access private */ var $_supportedVersions = array('1.0'); /** * Parsed channel information * @var array * @access private */ var $_channelInfo; /** * index into the subchannels array, used for parsing xml * @var int * @access private */ var $_subchannelIndex; /** * index into the mirrors array, used for parsing xml * @var int * @access private */ var $_mirrorIndex; /** * Flag used to determine the validity of parsed content * @var boolean * @access private */ var $_isValid = false; function __construct() { $this->_stack = new PEAR_ErrorStack('PEAR_ChannelFile'); $this->_stack->setErrorMessageTemplate($this->_getErrorMessage()); $this->_isValid = false; } /** * @return array * @access protected */ function _getErrorMessage() { return array( PEAR_CHANNELFILE_ERROR_INVALID_VERSION => 'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%', PEAR_CHANNELFILE_ERROR_NO_VERSION => 'No version number found in tag', PEAR_CHANNELFILE_ERROR_NO_XML_EXT => '%error%', PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER => 'Unable to create XML parser', PEAR_CHANNELFILE_ERROR_PARSER_ERROR => '%error%', PEAR_CHANNELFILE_ERROR_NO_NAME => 'Missing channel name', PEAR_CHANNELFILE_ERROR_INVALID_NAME => 'Invalid channel %tag% "%name%"', PEAR_CHANNELFILE_ERROR_NO_SUMMARY => 'Missing channel summary', PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY => 'Channel summary should be on one line, but is multi-line', PEAR_CHANNELFILE_ERROR_NO_HOST => 'Missing channel server for %type% server', PEAR_CHANNELFILE_ERROR_INVALID_HOST => 'Server name "%server%" is invalid for %type% server', PEAR_CHANNELFILE_ERROR_INVALID_MIRROR => 'Invalid mirror name "%name%", mirror type %type%', PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE => 'Invalid mirror type "%type%"', PEAR_CHANNELFILE_ERROR_INVALID => 'Cannot generate xml, contents are invalid', PEAR_CHANNELFILE_ERROR_EMPTY_REGEX => 'packagenameregex cannot be empty', PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION => '%parent% %protocol% function has no version', PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME => '%parent% %protocol% function has no name', PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE => '%parent% rest baseurl has no type', PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME => 'Validation package has no name in tag', PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION => 'Validation package "%package%" has no version', PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND => 'Mirror "%mirror%" does not exist', PEAR_CHANNELFILE_ERROR_INVALID_PORT => 'Port "%port%" must be numeric', PEAR_CHANNELFILE_ERROR_NO_STATICVERSION => ' tag must contain version attribute', PEAR_CHANNELFILE_URI_CANT_MIRROR => 'The __uri pseudo-channel cannot have mirrors', PEAR_CHANNELFILE_ERROR_INVALID_SSL => '%server% has invalid ssl attribute "%ssl%" can only be yes or not present', ); } /** * @param string contents of package.xml file * @return bool success of parsing */ function fromXmlString($data) { if (preg_match('/_supportedVersions)) { $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error', array('version' => $channelversion[1])); return false; } $parser = new PEAR_XMLParser; $result = $parser->parse($data); if ($result !== true) { if ($result->getCode() == 1) { $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error', array('error' => $result->getMessage())); } else { $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error'); } return false; } $this->_channelInfo = $parser->getData(); return true; } else { $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data)); return false; } } /** * @return array */ function toArray() { if (!$this->_isValid && !$this->validate()) { return false; } return $this->_channelInfo; } /** * @param array * * @return PEAR_ChannelFile|false false if invalid */ public static function &fromArray( $data, $compatibility = false, $stackClass = 'PEAR_ErrorStack' ) { $a = new PEAR_ChannelFile($compatibility, $stackClass); $a->_fromArray($data); if (!$a->validate()) { $a = false; return $a; } return $a; } /** * Unlike {@link fromArray()} this does not do any validation * * @param array * * @return PEAR_ChannelFile */ public static function &fromArrayWithErrors( $data, $compatibility = false, $stackClass = 'PEAR_ErrorStack' ) { $a = new PEAR_ChannelFile($compatibility, $stackClass); $a->_fromArray($data); return $a; } /** * @param array * @access private */ function _fromArray($data) { $this->_channelInfo = $data; } /** * Wrapper to {@link PEAR_ErrorStack::getErrors()} * @param boolean determines whether to purge the error stack after retrieving * @return array */ function getErrors($purge = false) { return $this->_stack->getErrors($purge); } /** * Unindent given string (?) * * @param string $str The string that has to be unindented. * @return string * @access private */ function _unIndent($str) { // remove leading newlines $str = preg_replace('/^[\r\n]+/', '', $str); // find whitespace at the beginning of the first line $indent_len = strspn($str, " \t"); $indent = substr($str, 0, $indent_len); $data = ''; // remove the same amount of whitespace from following lines foreach (explode("\n", $str) as $line) { if (substr($line, 0, $indent_len) == $indent) { $data .= substr($line, $indent_len) . "\n"; } } return $data; } /** * Parse a channel.xml file. Expects the name of * a channel xml file as input. * * @param string $descfile name of channel xml file * @return bool success of parsing */ function fromXmlFile($descfile) { if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) || (!$fp = fopen($descfile, 'r'))) { require_once 'PEAR.php'; return PEAR::raiseError("Unable to open $descfile"); } // read the whole thing so we only get one cdata callback // for each block of cdata fclose($fp); $data = file_get_contents($descfile); return $this->fromXmlString($data); } /** * Parse channel information from different sources * * This method is able to extract information about a channel * from an .xml file or a string * * @access public * @param string Filename of the source or the source itself * @return bool */ function fromAny($info) { if (is_string($info) && file_exists($info) && strlen($info) < 255) { $tmp = substr($info, -4); if ($tmp == '.xml') { $info = $this->fromXmlFile($info); } else { $fp = fopen($info, "r"); $test = fread($fp, 5); fclose($fp); if ($test == "fromXmlFile($info); } } if (PEAR::isError($info)) { require_once 'PEAR.php'; return PEAR::raiseError($info); } } if (is_string($info)) { $info = $this->fromXmlString($info); } return $info; } /** * Return an XML document based on previous parsing and modifications * * @return string XML data * * @access public */ function toXml() { if (!$this->_isValid && !$this->validate()) { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID); return false; } if (!isset($this->_channelInfo['attribs']['version'])) { $this->_channelInfo['attribs']['version'] = '1.0'; } $channelInfo = $this->_channelInfo; $ret = "\n"; $ret .= " $channelInfo[name] " . htmlspecialchars($channelInfo['summary'])." "; if (isset($channelInfo['suggestedalias'])) { $ret .= ' ' . $channelInfo['suggestedalias'] . "\n"; } if (isset($channelInfo['validatepackage'])) { $ret .= ' ' . htmlspecialchars($channelInfo['validatepackage']['_content']) . "\n"; } $ret .= " \n"; $ret .= ' _makeRestXml($channelInfo['servers']['primary']['rest'], ' '); } $ret .= " \n"; if (isset($channelInfo['servers']['mirror'])) { $ret .= $this->_makeMirrorsXml($channelInfo); } $ret .= " \n"; $ret .= ""; return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret)); } /** * Generate the tag * @access private */ function _makeRestXml($info, $indent) { $ret = $indent . "\n"; if (isset($info['baseurl']) && !isset($info['baseurl'][0])) { $info['baseurl'] = array($info['baseurl']); } if (isset($info['baseurl'])) { foreach ($info['baseurl'] as $url) { $ret .= "$indent \n"; } } $ret .= $indent . "\n"; return $ret; } /** * Generate the tag * @access private */ function _makeMirrorsXml($channelInfo) { $ret = ""; if (!isset($channelInfo['servers']['mirror'][0])) { $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']); } foreach ($channelInfo['servers']['mirror'] as $mirror) { $ret .= ' _makeRestXml($mirror['rest'], ' '); } $ret .= " \n"; } else { $ret .= "/>\n"; } } return $ret; } /** * Generate the tag * @access private */ function _makeFunctionsXml($functions, $indent, $rest = false) { $ret = ''; if (!isset($functions[0])) { $functions = array($functions); } foreach ($functions as $function) { $ret .= "$indent\n"; } return $ret; } /** * Validation error. Also marks the object contents as invalid * @param error code * @param array error information * @access private */ function _validateError($code, $params = array()) { $this->_stack->push($code, 'error', $params); $this->_isValid = false; } /** * Validation warning. Does not mark the object contents invalid. * @param error code * @param array error information * @access private */ function _validateWarning($code, $params = array()) { $this->_stack->push($code, 'warning', $params); } /** * Validate parsed file. * * @access public * @return boolean */ function validate() { $this->_isValid = true; $info = $this->_channelInfo; if (empty($info['name'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME); } elseif (!$this->validChannelServer($info['name'])) { if ($info['name'] != '__uri') { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name', 'name' => $info['name'])); } } if (empty($info['summary'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY); } elseif (strpos(trim($info['summary']), "\n") !== false) { $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY, array('summary' => $info['summary'])); } if (isset($info['suggestedalias'])) { if (!$this->validChannelServer($info['suggestedalias'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias'])); } } if (isset($info['localalias'])) { if (!$this->validChannelServer($info['localalias'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'localalias', 'name' =>$info['localalias'])); } } if (isset($info['validatepackage'])) { if (!isset($info['validatepackage']['_content'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME); } if (!isset($info['validatepackage']['attribs']['version'])) { $content = isset($info['validatepackage']['_content']) ? $info['validatepackage']['_content'] : null; $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION, array('package' => $content)); } } if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['port']) && !is_numeric($info['servers']['primary']['attribs']['port'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT, array('port' => $info['servers']['primary']['attribs']['port'])); } if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['ssl']) && $info['servers']['primary']['attribs']['ssl'] != 'yes') { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL, array('ssl' => $info['servers']['primary']['attribs']['ssl'], 'server' => $info['name'])); } if (isset($info['servers']['primary']['rest']) && isset($info['servers']['primary']['rest']['baseurl'])) { $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']); } if (isset($info['servers']['mirror'])) { if ($this->_channelInfo['name'] == '__uri') { $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR); } if (!isset($info['servers']['mirror'][0])) { $info['servers']['mirror'] = array($info['servers']['mirror']); } foreach ($info['servers']['mirror'] as $mirror) { if (!isset($mirror['attribs']['host'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST, array('type' => 'mirror')); } elseif (!$this->validChannelServer($mirror['attribs']['host'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST, array('server' => $mirror['attribs']['host'], 'type' => 'mirror')); } if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL, array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host'])); } if (isset($mirror['rest'])) { $this->_validateFunctions('rest', $mirror['rest']['baseurl'], $mirror['attribs']['host']); } } } return $this->_isValid; } /** * @param string rest - protocol name this function applies to * @param array the functions * @param string the name of the parent element (mirror name, for instance) */ function _validateFunctions($protocol, $functions, $parent = '') { if (!isset($functions[0])) { $functions = array($functions); } foreach ($functions as $function) { if (!isset($function['_content']) || empty($function['_content'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME, array('parent' => $parent, 'protocol' => $protocol)); } if ($protocol == 'rest') { if (!isset($function['attribs']['type']) || empty($function['attribs']['type'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE, array('parent' => $parent, 'protocol' => $protocol)); } } else { if (!isset($function['attribs']['version']) || empty($function['attribs']['version'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION, array('parent' => $parent, 'protocol' => $protocol)); } } } } /** * Test whether a string contains a valid channel server. * @param string $ver the package version to test * @return bool */ function validChannelServer($server) { if ($server == '__uri') { return true; } return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server); } /** * @return string|false */ function getName() { if (isset($this->_channelInfo['name'])) { return $this->_channelInfo['name']; } return false; } /** * @return string|false */ function getServer() { if (isset($this->_channelInfo['name'])) { return $this->_channelInfo['name']; } return false; } /** * @return int|80 port number to connect to */ function getPort($mirror = false) { if ($mirror) { if ($mir = $this->getMirror($mirror)) { if (isset($mir['attribs']['port'])) { return $mir['attribs']['port']; } if ($this->getSSL($mirror)) { return 443; } return 80; } return false; } if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) { return $this->_channelInfo['servers']['primary']['attribs']['port']; } if ($this->getSSL()) { return 443; } return 80; } /** * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel */ function getSSL($mirror = false) { if ($mirror) { if ($mir = $this->getMirror($mirror)) { if (isset($mir['attribs']['ssl'])) { return true; } return false; } return false; } if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) { return true; } return false; } /** * @return string|false */ function getSummary() { if (isset($this->_channelInfo['summary'])) { return $this->_channelInfo['summary']; } return false; } /** * @param string protocol type * @param string Mirror name * @return array|false */ function getFunctions($protocol, $mirror = false) { if ($this->getName() == '__uri') { return false; } $function = $protocol == 'rest' ? 'baseurl' : 'function'; if ($mirror) { if ($mir = $this->getMirror($mirror)) { if (isset($mir[$protocol][$function])) { return $mir[$protocol][$function]; } } return false; } if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) { return $this->_channelInfo['servers']['primary'][$protocol][$function]; } return false; } /** * @param string Protocol type * @param string Function name (null to return the * first protocol of the type requested) * @param string Mirror name, if any * @return array */ function getFunction($type, $name = null, $mirror = false) { $protocols = $this->getFunctions($type, $mirror); if (!$protocols) { return false; } foreach ($protocols as $protocol) { if ($name === null) { return $protocol; } if ($protocol['_content'] != $name) { continue; } return $protocol; } return false; } /** * @param string protocol type * @param string protocol name * @param string version * @param string mirror name * @return boolean */ function supports($type, $name = null, $mirror = false, $version = '1.0') { $protocols = $this->getFunctions($type, $mirror); if (!$protocols) { return false; } foreach ($protocols as $protocol) { if ($protocol['attribs']['version'] != $version) { continue; } if ($name === null) { return true; } if ($protocol['_content'] != $name) { continue; } return true; } return false; } /** * Determines whether a channel supports Representational State Transfer (REST) protocols * for retrieving channel information * @param string * @return bool */ function supportsREST($mirror = false) { if ($mirror == $this->_channelInfo['name']) { $mirror = false; } if ($mirror) { if ($mir = $this->getMirror($mirror)) { return isset($mir['rest']); } return false; } return isset($this->_channelInfo['servers']['primary']['rest']); } /** * Get the URL to access a base resource. * * Hyperlinks in the returned xml will be used to retrieve the proper information * needed. This allows extreme extensibility and flexibility in implementation * @param string Resource Type to retrieve */ function getBaseURL($resourceType, $mirror = false) { if ($mirror == $this->_channelInfo['name']) { $mirror = false; } if ($mirror) { $mir = $this->getMirror($mirror); if (!$mir) { return false; } $rest = $mir['rest']; } else { $rest = $this->_channelInfo['servers']['primary']['rest']; } if (!isset($rest['baseurl'][0])) { $rest['baseurl'] = array($rest['baseurl']); } foreach ($rest['baseurl'] as $baseurl) { if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) { return $baseurl['_content']; } } return false; } /** * Since REST does not implement RPC, provide this as a logical wrapper around * resetFunctions for REST * @param string|false mirror name, if any */ function resetREST($mirror = false) { return $this->resetFunctions('rest', $mirror); } /** * Empty all protocol definitions * @param string protocol type * @param string|false mirror name, if any */ function resetFunctions($type, $mirror = false) { if ($mirror) { if (isset($this->_channelInfo['servers']['mirror'])) { $mirrors = $this->_channelInfo['servers']['mirror']; if (!isset($mirrors[0])) { $mirrors = array($mirrors); } foreach ($mirrors as $i => $mir) { if ($mir['attribs']['host'] == $mirror) { if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) { unset($this->_channelInfo['servers']['mirror'][$i][$type]); } return true; } } return false; } return false; } if (isset($this->_channelInfo['servers']['primary'][$type])) { unset($this->_channelInfo['servers']['primary'][$type]); } return true; } /** * Set a channel's protocols to the protocols supported by pearweb */ function setDefaultPEARProtocols($version = '1.0', $mirror = false) { switch ($version) { case '1.0' : $this->resetREST($mirror); if (!isset($this->_channelInfo['servers'])) { $this->_channelInfo['servers'] = array('primary' => array('rest' => array())); } elseif (!isset($this->_channelInfo['servers']['primary'])) { $this->_channelInfo['servers']['primary'] = array('rest' => array()); } return true; break; default : return false; break; } } /** * @return array */ function getMirrors() { if (isset($this->_channelInfo['servers']['mirror'])) { $mirrors = $this->_channelInfo['servers']['mirror']; if (!isset($mirrors[0])) { $mirrors = array($mirrors); } return $mirrors; } return array(); } /** * Get the unserialized XML representing a mirror * @return array|false */ function getMirror($server) { foreach ($this->getMirrors() as $mirror) { if ($mirror['attribs']['host'] == $server) { return $mirror; } } return false; } /** * @param string * @return string|false * @error PEAR_CHANNELFILE_ERROR_NO_NAME * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME */ function setName($name) { return $this->setServer($name); } /** * Set the socket number (port) that is used to connect to this channel * @param integer * @param string|false name of the mirror server, or false for the primary */ function setPort($port, $mirror = false) { if ($mirror) { if (!isset($this->_channelInfo['servers']['mirror'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, array('mirror' => $mirror)); return false; } if (isset($this->_channelInfo['servers']['mirror'][0])) { foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { if ($mirror == $mir['attribs']['host']) { $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port; return true; } } return false; } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port; $this->_isValid = false; return true; } } $this->_channelInfo['servers']['primary']['attribs']['port'] = $port; $this->_isValid = false; return true; } /** * Set the socket number (port) that is used to connect to this channel * @param bool Determines whether to turn on SSL support or turn it off * @param string|false name of the mirror server, or false for the primary */ function setSSL($ssl = true, $mirror = false) { if ($mirror) { if (!isset($this->_channelInfo['servers']['mirror'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, array('mirror' => $mirror)); return false; } if (isset($this->_channelInfo['servers']['mirror'][0])) { foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { if ($mirror == $mir['attribs']['host']) { if (!$ssl) { if (isset($this->_channelInfo['servers']['mirror'][$i] ['attribs']['ssl'])) { unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']); } } else { $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes'; } return true; } } return false; } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { if (!$ssl) { if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) { unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']); } } else { $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes'; } $this->_isValid = false; return true; } } if ($ssl) { $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes'; } else { if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) { unset($this->_channelInfo['servers']['primary']['attribs']['ssl']); } } $this->_isValid = false; return true; } /** * @param string * @return string|false * @error PEAR_CHANNELFILE_ERROR_NO_SERVER * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER */ function setServer($server, $mirror = false) { if (empty($server)) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER); return false; } elseif (!$this->validChannelServer($server)) { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name', 'name' => $server)); return false; } if ($mirror) { $found = false; foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { if ($mirror == $mir['attribs']['host']) { $found = true; break; } } if (!$found) { $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, array('mirror' => $mirror)); return false; } $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server; return true; } $this->_channelInfo['name'] = $server; return true; } /** * @param string * @return boolean success * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY */ function setSummary($summary) { if (empty($summary)) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY); return false; } elseif (strpos(trim($summary), "\n") !== false) { $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY, array('summary' => $summary)); } $this->_channelInfo['summary'] = $summary; return true; } /** * @param string * @param boolean determines whether the alias is in channel.xml or local * @return boolean success */ function setAlias($alias, $local = false) { if (!$this->validChannelServer($alias)) { $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'suggestedalias', 'name' => $alias)); return false; } if ($local) { $this->_channelInfo['localalias'] = $alias; } else { $this->_channelInfo['suggestedalias'] = $alias; } return true; } /** * @return string */ function getAlias() { if (isset($this->_channelInfo['localalias'])) { return $this->_channelInfo['localalias']; } if (isset($this->_channelInfo['suggestedalias'])) { return $this->_channelInfo['suggestedalias']; } if (isset($this->_channelInfo['name'])) { return $this->_channelInfo['name']; } return ''; } /** * Set the package validation object if it differs from PEAR's default * The class must be includeable via changing _ in the classname to path separator, * but no checking of this is made. * @param string|false pass in false to reset to the default packagename regex * @return boolean success */ function setValidationPackage($validateclass, $version) { if (empty($validateclass)) { unset($this->_channelInfo['validatepackage']); } $this->_channelInfo['validatepackage'] = array('_content' => $validateclass); $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version); } /** * Add a protocol to the provides section * @param string protocol type * @param string protocol version * @param string protocol name, if any * @param string mirror name, if this is a mirror's protocol * @return bool */ function addFunction($type, $version, $name = '', $mirror = false) { if ($mirror) { return $this->addMirrorFunction($mirror, $type, $version, $name); } $set = array('attribs' => array('version' => $version), '_content' => $name); if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) { if (!isset($this->_channelInfo['servers'])) { $this->_channelInfo['servers'] = array('primary' => array($type => array())); } elseif (!isset($this->_channelInfo['servers']['primary'])) { $this->_channelInfo['servers']['primary'] = array($type => array()); } $this->_channelInfo['servers']['primary'][$type]['function'] = $set; $this->_isValid = false; return true; } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) { $this->_channelInfo['servers']['primary'][$type]['function'] = array( $this->_channelInfo['servers']['primary'][$type]['function']); } $this->_channelInfo['servers']['primary'][$type]['function'][] = $set; return true; } /** * Add a protocol to a mirror's provides section * @param string mirror name (server) * @param string protocol type * @param string protocol version * @param string protocol name, if any */ function addMirrorFunction($mirror, $type, $version, $name = '') { if (!isset($this->_channelInfo['servers']['mirror'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, array('mirror' => $mirror)); return false; } $setmirror = false; if (isset($this->_channelInfo['servers']['mirror'][0])) { foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { if ($mirror == $mir['attribs']['host']) { $setmirror = &$this->_channelInfo['servers']['mirror'][$i]; break; } } } else { if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { $setmirror = &$this->_channelInfo['servers']['mirror']; } } if (!$setmirror) { $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, array('mirror' => $mirror)); return false; } $set = array('attribs' => array('version' => $version), '_content' => $name); if (!isset($setmirror[$type]['function'])) { $setmirror[$type]['function'] = $set; $this->_isValid = false; return true; } elseif (!isset($setmirror[$type]['function'][0])) { $setmirror[$type]['function'] = array($setmirror[$type]['function']); } $setmirror[$type]['function'][] = $set; $this->_isValid = false; return true; } /** * @param string Resource Type this url links to * @param string URL * @param string|false mirror name, if this is not a primary server REST base URL */ function setBaseURL($resourceType, $url, $mirror = false) { if ($mirror) { if (!isset($this->_channelInfo['servers']['mirror'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, array('mirror' => $mirror)); return false; } $setmirror = false; if (isset($this->_channelInfo['servers']['mirror'][0])) { foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { if ($mirror == $mir['attribs']['host']) { $setmirror = &$this->_channelInfo['servers']['mirror'][$i]; break; } } } else { if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { $setmirror = &$this->_channelInfo['servers']['mirror']; } } } else { $setmirror = &$this->_channelInfo['servers']['primary']; } $set = array('attribs' => array('type' => $resourceType), '_content' => $url); if (!isset($setmirror['rest'])) { $setmirror['rest'] = array(); } if (!isset($setmirror['rest']['baseurl'])) { $setmirror['rest']['baseurl'] = $set; $this->_isValid = false; return true; } elseif (!isset($setmirror['rest']['baseurl'][0])) { $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']); } foreach ($setmirror['rest']['baseurl'] as $i => $url) { if ($url['attribs']['type'] == $resourceType) { $this->_isValid = false; $setmirror['rest']['baseurl'][$i] = $set; return true; } } $setmirror['rest']['baseurl'][] = $set; $this->_isValid = false; return true; } /** * @param string mirror server * @param int mirror http port * @return boolean */ function addMirror($server, $port = null) { if ($this->_channelInfo['name'] == '__uri') { return false; // the __uri channel cannot have mirrors by definition } $set = array('attribs' => array('host' => $server)); if (is_numeric($port)) { $set['attribs']['port'] = $port; } if (!isset($this->_channelInfo['servers']['mirror'])) { $this->_channelInfo['servers']['mirror'] = $set; return true; } if (!isset($this->_channelInfo['servers']['mirror'][0])) { $this->_channelInfo['servers']['mirror'] = array($this->_channelInfo['servers']['mirror']); } $this->_channelInfo['servers']['mirror'][] = $set; return true; } /** * Retrieve the name of the validation package for this channel * @return string|false */ function getValidationPackage() { if (!$this->_isValid && !$this->validate()) { return false; } if (!isset($this->_channelInfo['validatepackage'])) { return array('attribs' => array('version' => 'default'), '_content' => 'PEAR_Validate'); } return $this->_channelInfo['validatepackage']; } /** * Retrieve the object that can be used for custom validation * @param string|false the name of the package to validate. If the package is * the channel validation package, PEAR_Validate is returned * @return PEAR_Validate|false false is returned if the validation package * cannot be located */ function &getValidationObject($package = false) { if (!class_exists('PEAR_Validate')) { require_once 'PEAR/Validate.php'; } if (!$this->_isValid) { if (!$this->validate()) { $a = false; return $a; } } if (isset($this->_channelInfo['validatepackage'])) { if ($package == $this->_channelInfo['validatepackage']) { // channel validation packages are always validated by PEAR_Validate $val = new PEAR_Validate; return $val; } if (!class_exists(str_replace('.', '_', $this->_channelInfo['validatepackage']['_content']))) { if ($this->isIncludeable(str_replace('_', '/', $this->_channelInfo['validatepackage']['_content']) . '.php')) { include_once str_replace('_', '/', $this->_channelInfo['validatepackage']['_content']) . '.php'; $vclass = str_replace('.', '_', $this->_channelInfo['validatepackage']['_content']); $val = new $vclass; } else { $a = false; return $a; } } else { $vclass = str_replace('.', '_', $this->_channelInfo['validatepackage']['_content']); $val = new $vclass; } } else { $val = new PEAR_Validate; } return $val; } function isIncludeable($path) { $possibilities = explode(PATH_SEPARATOR, ini_get('include_path')); foreach ($possibilities as $dir) { if (file_exists($dir . DIRECTORY_SEPARATOR . $path) && is_readable($dir . DIRECTORY_SEPARATOR . $path)) { return true; } } return false; } /** * This function is used by the channel updater and retrieves a value set by * the registry, or the current time if it has not been set * @return string */ function lastModified() { if (isset($this->_channelInfo['_lastmodified'])) { return $this->_channelInfo['_lastmodified']; } return time(); } } PK!gkUUPEAR/Validate.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /**#@+ * Constants for install stage */ define('PEAR_VALIDATE_INSTALLING', 1); define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others define('PEAR_VALIDATE_NORMAL', 3); define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others define('PEAR_VALIDATE_PACKAGING', 7); /**#@-*/ require_once 'PEAR/Common.php'; require_once 'PEAR/Validator/PECL.php'; /** * Validation class for package.xml - channel-level advanced validation * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Validate { var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG; /** * @var PEAR_PackageFile_v1|PEAR_PackageFile_v2 */ var $_packagexml; /** * @var int one of the PEAR_VALIDATE_* constants */ var $_state = PEAR_VALIDATE_NORMAL; /** * Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same) * @var array * @access private */ var $_failures = array('error' => array(), 'warning' => array()); /** * Override this method to handle validation of normal package names * @param string * @return bool * @access protected */ function _validPackageName($name) { return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name); } /** * @param string package name to validate * @param string name of channel-specific validation package * @final */ function validPackageName($name, $validatepackagename = false) { if ($validatepackagename) { if (strtolower($name) == strtolower($validatepackagename)) { return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name); } } return $this->_validPackageName($name); } /** * This validates a bundle name, and bundle names must conform * to the PEAR naming convention, so the method is final and static. * @param string * @final */ public static function validGroupName($name) { return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name); } /** * Determine whether $state represents a valid stability level * @param string * @return bool * @final */ public static function validState($state) { return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable')); } /** * Get a list of valid stability levels * @return array * @final */ public static function getValidStates() { return array('snapshot', 'devel', 'alpha', 'beta', 'stable'); } /** * Determine whether a version is a properly formatted version number that can be used * by version_compare * @param string * @return bool * @final */ public static function validVersion($ver) { return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver); } /** * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 */ function setPackageFile(&$pf) { $this->_packagexml = &$pf; } /** * @access private */ function _addFailure($field, $reason) { $this->_failures['errors'][] = array('field' => $field, 'reason' => $reason); } /** * @access private */ function _addWarning($field, $reason) { $this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason); } function getFailures() { $failures = $this->_failures; $this->_failures = array('warnings' => array(), 'errors' => array()); return $failures; } /** * @param int one of the PEAR_VALIDATE_* constants */ function validate($state = null) { if (!isset($this->_packagexml)) { return false; } if ($state !== null) { $this->_state = $state; } $this->_failures = array('warnings' => array(), 'errors' => array()); $this->validatePackageName(); $this->validateVersion(); $this->validateMaintainers(); $this->validateDate(); $this->validateSummary(); $this->validateDescription(); $this->validateLicense(); $this->validateNotes(); if ($this->_packagexml->getPackagexmlVersion() == '1.0') { $this->validateState(); $this->validateFilelist(); } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' || $this->_packagexml->getPackagexmlVersion() == '2.1') { $this->validateTime(); $this->validateStability(); $this->validateDeps(); $this->validateMainFilelist(); $this->validateReleaseFilelist(); //$this->validateGlobalTasks(); $this->validateChangelog(); } return !((bool) count($this->_failures['errors'])); } /** * @access protected */ function validatePackageName() { if ($this->_state == PEAR_VALIDATE_PACKAGING || $this->_state == PEAR_VALIDATE_NORMAL) { if (($this->_packagexml->getPackagexmlVersion() == '2.0' || $this->_packagexml->getPackagexmlVersion() == '2.1') && $this->_packagexml->getExtends()) { $version = $this->_packagexml->getVersion() . ''; $name = $this->_packagexml->getPackage(); $a = explode('.', $version); $test = array_shift($a); if ($test == '0') { return true; } $vlen = strlen($test); $majver = substr($name, strlen($name) - $vlen); while ($majver && !is_numeric($majver[0])) { $majver = substr($majver, 1); } if ($majver != $test) { $this->_addWarning('package', "package $name extends package " . $this->_packagexml->getExtends() . ' and so the name should ' . 'have a postfix equal to the major version like "' . $this->_packagexml->getExtends() . $test . '"'); return true; } elseif (substr($name, 0, strlen($name) - $vlen) != $this->_packagexml->getExtends()) { $this->_addWarning('package', "package $name extends package " . $this->_packagexml->getExtends() . ' and so the name must ' . 'be an extension like "' . $this->_packagexml->getExtends() . $test . '"'); return true; } } } if (!$this->validPackageName($this->_packagexml->getPackage())) { $this->_addFailure('name', 'package name "' . $this->_packagexml->getPackage() . '" is invalid'); return false; } } /** * @access protected */ function validateVersion() { if ($this->_state != PEAR_VALIDATE_PACKAGING) { if (!$this->validVersion($this->_packagexml->getVersion())) { $this->_addFailure('version', 'Invalid version number "' . $this->_packagexml->getVersion() . '"'); } return false; } $version = $this->_packagexml->getVersion(); $versioncomponents = explode('.', $version); if (count($versioncomponents) != 3) { $this->_addWarning('version', 'A version number should have 3 decimals (x.y.z)'); return true; } $name = $this->_packagexml->getPackage(); // version must be based upon state switch ($this->_packagexml->getState()) { case 'snapshot' : return true; case 'devel' : if ($versioncomponents[0] . 'a' == '0a') { return true; } if ($versioncomponents[0] == 0) { $versioncomponents[0] = '0'; $this->_addWarning('version', 'version "' . $version . '" should be "' . implode('.' ,$versioncomponents) . '"'); } else { $this->_addWarning('version', 'packages with devel stability must be < version 1.0.0'); } return true; break; case 'alpha' : case 'beta' : // check for a package that extends a package, // like Foo and Foo2 if ($this->_state == PEAR_VALIDATE_PACKAGING) { if (substr($versioncomponents[2], 1, 2) == 'rc') { $this->_addFailure('version', 'Release Candidate versions ' . 'must have capital RC, not lower-case rc'); return false; } } if (!$this->_packagexml->getExtends()) { if ($versioncomponents[0] == '1') { if ($versioncomponents[2][0] == '0') { if ($versioncomponents[2] == '0') { // version 1.*.0000 $this->_addWarning('version', 'version 1.' . $versioncomponents[1] . '.0 probably should not be alpha or beta'); return true; } elseif (strlen($versioncomponents[2]) > 1) { // version 1.*.0RC1 or 1.*.0beta24 etc. return true; } else { // version 1.*.0 $this->_addWarning('version', 'version 1.' . $versioncomponents[1] . '.0 probably should not be alpha or beta'); return true; } } else { $this->_addWarning('version', 'bugfix versions (1.3.x where x > 0) probably should ' . 'not be alpha or beta'); return true; } } elseif ($versioncomponents[0] != '0') { $this->_addWarning('version', 'major versions greater than 1 are not allowed for packages ' . 'without an tag or an identical postfix (foo2 v2.0.0)'); return true; } if ($versioncomponents[0] . 'a' == '0a') { return true; } if ($versioncomponents[0] == 0) { $versioncomponents[0] = '0'; $this->_addWarning('version', 'version "' . $version . '" should be "' . implode('.' ,$versioncomponents) . '"'); } } else { $vlen = strlen($versioncomponents[0] . ''); $majver = substr($name, strlen($name) - $vlen); while ($majver && !is_numeric($majver[0])) { $majver = substr($majver, 1); } if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) { $this->_addWarning('version', 'first version number "' . $versioncomponents[0] . '" must match the postfix of ' . 'package name "' . $name . '" (' . $majver . ')'); return true; } if ($versioncomponents[0] == $majver) { if ($versioncomponents[2][0] == '0') { if ($versioncomponents[2] == '0') { // version 2.*.0000 $this->_addWarning('version', "version $majver." . $versioncomponents[1] . '.0 probably should not be alpha or beta'); return false; } elseif (strlen($versioncomponents[2]) > 1) { // version 2.*.0RC1 or 2.*.0beta24 etc. return true; } else { // version 2.*.0 $this->_addWarning('version', "version $majver." . $versioncomponents[1] . '.0 cannot be alpha or beta'); return true; } } else { $this->_addWarning('version', "bugfix versions ($majver.x.y where y > 0) should " . 'not be alpha or beta'); return true; } } elseif ($versioncomponents[0] != '0') { $this->_addWarning('version', "only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases"); return true; } if ($versioncomponents[0] . 'a' == '0a') { return true; } if ($versioncomponents[0] == 0) { $versioncomponents[0] = '0'; $this->_addWarning('version', 'version "' . $version . '" should be "' . implode('.' ,$versioncomponents) . '"'); } } return true; break; case 'stable' : if ($versioncomponents[0] == '0') { $this->_addWarning('version', 'versions less than 1.0.0 cannot ' . 'be stable'); return true; } if (!is_numeric($versioncomponents[2])) { if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i', $versioncomponents[2])) { $this->_addWarning('version', 'version "' . $version . '" or any ' . 'RC/beta/alpha version cannot be stable'); return true; } } // check for a package that extends a package, // like Foo and Foo2 if ($this->_packagexml->getExtends()) { $vlen = strlen($versioncomponents[0] . ''); $majver = substr($name, strlen($name) - $vlen); while ($majver && !is_numeric($majver[0])) { $majver = substr($majver, 1); } if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) { $this->_addWarning('version', 'first version number "' . $versioncomponents[0] . '" must match the postfix of ' . 'package name "' . $name . '" (' . $majver . ')'); return true; } } elseif ($versioncomponents[0] > 1) { $this->_addWarning('version', 'major version x in x.y.z may not be greater than ' . '1 for any package that does not have an tag'); } return true; break; default : return false; break; } } /** * @access protected */ function validateMaintainers() { // maintainers can only be truly validated server-side for most channels // but allow this customization for those who wish it return true; } /** * @access protected */ function validateDate() { if ($this->_state == PEAR_VALIDATE_NORMAL || $this->_state == PEAR_VALIDATE_PACKAGING) { if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/', $this->_packagexml->getDate(), $res) || count($res) < 4 || !checkdate($res[2], $res[3], $res[1]) ) { $this->_addFailure('date', 'invalid release date "' . $this->_packagexml->getDate() . '"'); return false; } if ($this->_state == PEAR_VALIDATE_PACKAGING && $this->_packagexml->getDate() != date('Y-m-d')) { $this->_addWarning('date', 'Release Date "' . $this->_packagexml->getDate() . '" is not today'); } } return true; } /** * @access protected */ function validateTime() { if (!$this->_packagexml->getTime()) { // default of no time value set return true; } // packager automatically sets time, so only validate if pear validate is called if ($this->_state = PEAR_VALIDATE_NORMAL) { if (!preg_match('/\d\d:\d\d:\d\d/', $this->_packagexml->getTime())) { $this->_addFailure('time', 'invalid release time "' . $this->_packagexml->getTime() . '"'); return false; } $result = preg_match('|\d{2}\:\d{2}\:\d{2}|', $this->_packagexml->getTime(), $matches); if ($result === false || empty($matches)) { $this->_addFailure('time', 'invalid release time "' . $this->_packagexml->getTime() . '"'); return false; } } return true; } /** * @access protected */ function validateState() { // this is the closest to "final" php4 can get if (!PEAR_Validate::validState($this->_packagexml->getState())) { if (strtolower($this->_packagexml->getState() == 'rc')) { $this->_addFailure('state', 'RC is not a state, it is a version ' . 'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta'); } $this->_addFailure('state', 'invalid release state "' . $this->_packagexml->getState() . '", must be one of: ' . implode(', ', PEAR_Validate::getValidStates())); return false; } return true; } /** * @access protected */ function validateStability() { $ret = true; $packagestability = $this->_packagexml->getState(); $apistability = $this->_packagexml->getState('api'); if (!PEAR_Validate::validState($packagestability)) { $this->_addFailure('state', 'invalid release stability "' . $this->_packagexml->getState() . '", must be one of: ' . implode(', ', PEAR_Validate::getValidStates())); $ret = false; } $apistates = PEAR_Validate::getValidStates(); array_shift($apistates); // snapshot is not allowed if (!in_array($apistability, $apistates)) { $this->_addFailure('state', 'invalid API stability "' . $this->_packagexml->getState('api') . '", must be one of: ' . implode(', ', $apistates)); $ret = false; } return $ret; } /** * @access protected */ function validateSummary() { return true; } /** * @access protected */ function validateDescription() { return true; } /** * @access protected */ function validateLicense() { return true; } /** * @access protected */ function validateNotes() { return true; } /** * for package.xml 2.0 only - channels can't use package.xml 1.0 * @access protected */ function validateDependencies() { return true; } /** * for package.xml 1.0 only * @access private */ function _validateFilelist() { return true; // placeholder for now } /** * for package.xml 2.0 only * @access protected */ function validateMainFilelist() { return true; // placeholder for now } /** * for package.xml 2.0 only * @access protected */ function validateReleaseFilelist() { return true; // placeholder for now } /** * @access protected */ function validateChangelog() { return true; } /** * @access protected */ function validateFilelist() { return true; } /** * @access protected */ function validateDeps() { return true; } }PK!d֣SPEAR/Command/Pickle.xmlnu[ Build PECL Package doPackage pi Z Do not gzip the package file n Print the name of the packaged file. [descfile] Creates a PECL package from its package2.xml file. An automatic conversion will be made to a package.xml 1.0 and written out to disk in the current directory as "package.xml". Note that only simple package.xml 2.0 will be converted. package.xml 2.0 with: - dependency types other than required/optional PECL package/ext/php/pearinstaller - more than one extsrcrelease or zendextsrcrelease - zendextbinrelease, extbinrelease, phprelease, or bundle release type - dependency groups - ignore tags in release filelist - tasks other than replace - custom roles will cause pickle to fail, and output an error message. If your package2.xml uses any of these features, you are best off using PEAR_PackageFileManager to generate both package.xml. PK!zk<k<PEAR/Command/Config.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; /** * PEAR commands for managing configuration data. * * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Command_Config extends PEAR_Command_Common { var $commands = array( 'config-show' => array( 'summary' => 'Show All Settings', 'function' => 'doConfigShow', 'shortcut' => 'csh', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'show configuration variables for another channel', 'arg' => 'CHAN', ), ), 'doc' => '[layer] Displays all configuration values. An optional argument may be used to tell which configuration layer to display. Valid configuration layers are "user", "system" and "default". To display configurations for different channels, set the default_channel configuration variable and run config-show again. ', ), 'config-get' => array( 'summary' => 'Show One Setting', 'function' => 'doConfigGet', 'shortcut' => 'cg', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'show configuration variables for another channel', 'arg' => 'CHAN', ), ), 'doc' => ' [layer] Displays the value of one configuration parameter. The first argument is the name of the parameter, an optional second argument may be used to tell which configuration layer to look in. Valid configuration layers are "user", "system" and "default". If no layer is specified, a value will be picked from the first layer that defines the parameter, in the order just specified. The configuration value will be retrieved for the channel specified by the default_channel configuration variable. ', ), 'config-set' => array( 'summary' => 'Change Setting', 'function' => 'doConfigSet', 'shortcut' => 'cs', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'show configuration variables for another channel', 'arg' => 'CHAN', ), ), 'doc' => ' [layer] Sets the value of one configuration parameter. The first argument is the name of the parameter, the second argument is the new value. Some parameters are subject to validation, and the command will fail with an error message if the new value does not make sense. An optional third argument may be used to specify in which layer to set the configuration parameter. The default layer is "user". The configuration value will be set for the current channel, which is controlled by the default_channel configuration variable. ', ), 'config-help' => array( 'summary' => 'Show Information About Setting', 'function' => 'doConfigHelp', 'shortcut' => 'ch', 'options' => array(), 'doc' => '[parameter] Displays help for a configuration parameter. Without arguments it displays help for all configuration parameters. ', ), 'config-create' => array( 'summary' => 'Create a Default configuration file', 'function' => 'doConfigCreate', 'shortcut' => 'coc', 'options' => array( 'windows' => array( 'shortopt' => 'w', 'doc' => 'create a config file for a windows install', ), ), 'doc' => ' Create a default configuration file with all directory configuration variables set to subdirectories of , and save it as . This is useful especially for creating a configuration file for a remote PEAR installation (using the --remoteconfig option of install, upgrade, and uninstall). ', ), ); /** * PEAR_Command_Config constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } function doConfigShow($command, $options, $params) { $layer = null; if (is_array($params)) { $layer = isset($params[0]) ? $params[0] : null; } // $params[0] -> the layer if ($error = $this->_checkLayer($layer)) { return $this->raiseError("config-show:$error"); } $keys = $this->config->getKeys(); sort($keys); $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); $reg = &$this->config->getRegistry(); if (!$reg->channelExists($channel)) { return $this->raiseError('Channel "' . $channel . '" does not exist'); } $channel = $reg->channelName($channel); $data = array('caption' => 'Configuration (channel ' . $channel . '):'); foreach ($keys as $key) { $type = $this->config->getType($key); $value = $this->config->get($key, $layer, $channel); if ($type == 'password' && $value) { $value = '********'; } if ($value === false) { $value = 'false'; } elseif ($value === true) { $value = 'true'; } $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value); } foreach ($this->config->getLayers() as $layer) { $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer)); } $this->ui->outputData($data, $command); return true; } function doConfigGet($command, $options, $params) { $args_cnt = is_array($params) ? count($params) : 0; switch ($args_cnt) { case 1: $config_key = $params[0]; $layer = null; break; case 2: $config_key = $params[0]; $layer = $params[1]; if ($error = $this->_checkLayer($layer)) { return $this->raiseError("config-get:$error"); } break; case 0: default: return $this->raiseError("config-get expects 1 or 2 parameters"); } $reg = &$this->config->getRegistry(); $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); if (!$reg->channelExists($channel)) { return $this->raiseError('Channel "' . $channel . '" does not exist'); } $channel = $reg->channelName($channel); $this->ui->outputData($this->config->get($config_key, $layer, $channel), $command); return true; } function doConfigSet($command, $options, $params) { // $param[0] -> a parameter to set // $param[1] -> the value for the parameter // $param[2] -> the layer $failmsg = ''; if (count($params) < 2 || count($params) > 3) { $failmsg .= "config-set expects 2 or 3 parameters"; return PEAR::raiseError($failmsg); } if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) { $failmsg .= $error; return PEAR::raiseError("config-set:$failmsg"); } $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); $reg = &$this->config->getRegistry(); if (!$reg->channelExists($channel)) { return $this->raiseError('Channel "' . $channel . '" does not exist'); } $channel = $reg->channelName($channel); if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) { return $this->raiseError('Channel "' . $params[1] . '" does not exist'); } if ($params[0] == 'preferred_mirror' && ( !$reg->mirrorExists($channel, $params[1]) && (!$reg->channelExists($params[1]) || $channel != $params[1]) ) ) { $msg = 'Channel Mirror "' . $params[1] . '" does not exist'; $msg .= ' in your registry for channel "' . $channel . '".'; $msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"'; $msg .= ' if you believe this mirror should exist as you may'; $msg .= ' have outdated channel information.'; return $this->raiseError($msg); } if (count($params) == 2) { array_push($params, 'user'); $layer = 'user'; } else { $layer = $params[2]; } array_push($params, $channel); if (!call_user_func_array(array(&$this->config, 'set'), $params)) { array_pop($params); $failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel"; } else { $this->config->store($layer); } if ($failmsg) { return $this->raiseError($failmsg); } $this->ui->outputData('config-set succeeded', $command); return true; } function doConfigHelp($command, $options, $params) { if (empty($params)) { $params = $this->config->getKeys(); } $data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : ''); $data['headline'] = array('Name', 'Type', 'Description'); $data['border'] = true; foreach ($params as $name) { $type = $this->config->getType($name); $docs = $this->config->getDocs($name); if ($type == 'set') { $docs = rtrim($docs) . "\nValid set: " . implode(' ', $this->config->getSetValues($name)); } $data['data'][] = array($name, $type, $docs); } $this->ui->outputData($data, $command); } function doConfigCreate($command, $options, $params) { if (count($params) != 2) { return PEAR::raiseError('config-create: must have 2 parameters, root path and ' . 'filename to save as'); } $root = $params[0]; // Clean up the DIRECTORY_SEPARATOR mess $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; $root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"), array('/', '/', '/'), $root); if ($root[0] != '/') { if (!isset($options['windows'])) { return PEAR::raiseError('Root directory must be an absolute path beginning ' . 'with "/", was: "' . $root . '"'); } if (!preg_match('/^[A-Za-z]:/', $root)) { return PEAR::raiseError('Root directory must be an absolute path beginning ' . 'with "\\" or "C:\\", was: "' . $root . '"'); } } $windows = isset($options['windows']); if ($windows) { $root = str_replace('/', '\\', $root); } if (!file_exists($params[1]) && !@touch($params[1])) { return PEAR::raiseError('Could not create "' . $params[1] . '"'); } $params[1] = realpath($params[1]); $config = new PEAR_Config($params[1], '#no#system#config#', false, false); if ($root[strlen($root) - 1] == '/') { $root = substr($root, 0, strlen($root) - 1); } $config->noRegistry(); $config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user'); $config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data"); $config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www"); $config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg"); $config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext"); $config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs"); $config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests"); $config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache"); $config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download"); $config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp"); $config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear"); $config->set('man_dir', $windows ? "$root\\pear\\man" : "$root/pear/man"); $config->writeConfigFile(); $this->_showConfig($config); $this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"', $command); } function _showConfig(&$config) { $params = array('user'); $keys = $config->getKeys(); sort($keys); $channel = 'pear.php.net'; $data = array('caption' => 'Configuration (channel ' . $channel . '):'); foreach ($keys as $key) { $type = $config->getType($key); $value = $config->get($key, 'user', $channel); if ($type == 'password' && $value) { $value = '********'; } if ($value === false) { $value = 'false'; } elseif ($value === true) { $value = 'true'; } $data['data'][$config->getGroup($key)][] = array($config->getPrompt($key) , $key, $value); } foreach ($config->getLayers() as $layer) { $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $config->getConfFile($layer)); } $this->ui->outputData($data, 'config-show'); return true; } /** * Checks if a layer is defined or not * * @param string $layer The layer to search for * @return mixed False on no error or the error message */ function _checkLayer($layer = null) { if (!empty($layer) && $layer != 'default') { $layers = $this->config->getLayers(); if (!in_array($layer, $layers)) { return " only the layers: \"" . implode('" or "', $layers) . "\" are supported"; } } return false; } } PK!݄ Downloads each available package from the default channel doDownloadAll da c specify a channel other than the default channel CHAN Requests a list of available packages from the default channel ({config default_channel}) and downloads them to current working directory. Note: only packages within preferred_state ({config preferred_state}) will be downloaded PK!,t"u"uPEAR/Command/Remote.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; require_once 'PEAR/REST.php'; /** * PEAR commands for remote server querying * * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Command_Remote extends PEAR_Command_Common { var $commands = array( 'remote-info' => array( 'summary' => 'Information About Remote Packages', 'function' => 'doRemoteInfo', 'shortcut' => 'ri', 'options' => array(), 'doc' => ' Get details on a package from the server.', ), 'list-upgrades' => array( 'summary' => 'List Available Upgrades', 'function' => 'doListUpgrades', 'shortcut' => 'lu', 'options' => array( 'channelinfo' => array( 'shortopt' => 'i', 'doc' => 'output fully channel-aware data, even on failure', ), ), 'doc' => '[preferred_state] List releases on the server of packages you have installed where a newer version is available with the same release state (stable etc.) or the state passed as the second parameter.' ), 'remote-list' => array( 'summary' => 'List Remote Packages', 'function' => 'doRemoteList', 'shortcut' => 'rl', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'specify a channel other than the default channel', 'arg' => 'CHAN', ) ), 'doc' => ' Lists the packages available on the configured server along with the latest stable release of each package.', ), 'search' => array( 'summary' => 'Search remote package database', 'function' => 'doSearch', 'shortcut' => 'sp', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'specify a channel other than the default channel', 'arg' => 'CHAN', ), 'allchannels' => array( 'shortopt' => 'a', 'doc' => 'search packages from all known channels', ), 'channelinfo' => array( 'shortopt' => 'i', 'doc' => 'output fully channel-aware data, even on failure', ), ), 'doc' => '[packagename] [packageinfo] Lists all packages which match the search parameters. The first parameter is a fragment of a packagename. The default channel will be used unless explicitly overridden. The second parameter will be used to match any portion of the summary/description', ), 'list-all' => array( 'summary' => 'List All Packages', 'function' => 'doListAll', 'shortcut' => 'la', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'specify a channel other than the default channel', 'arg' => 'CHAN', ), 'channelinfo' => array( 'shortopt' => 'i', 'doc' => 'output fully channel-aware data, even on failure', ), ), 'doc' => ' Lists the packages available on the configured server along with the latest stable release of each package.', ), 'download' => array( 'summary' => 'Download Package', 'function' => 'doDownload', 'shortcut' => 'd', 'options' => array( 'nocompress' => array( 'shortopt' => 'Z', 'doc' => 'download an uncompressed (.tar) file', ), ), 'doc' => '... Download package tarballs. The files will be named as suggested by the server, for example if you download the DB package and the latest stable version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.', ), 'clear-cache' => array( 'summary' => 'Clear Web Services Cache', 'function' => 'doClearCache', 'shortcut' => 'cc', 'options' => array(), 'doc' => ' Clear the REST cache. See also the cache_ttl configuration parameter. ', ), ); /** * PEAR_Command_Remote constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } function _checkChannelForStatus($channel, $chan) { if (PEAR::isError($chan)) { $this->raiseError($chan); } if (!is_a($chan, 'PEAR_ChannelFile')) { return $this->raiseError('Internal corruption error: invalid channel "' . $channel . '"'); } $rest = new PEAR_REST($this->config); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $mirror = $this->config->get('preferred_mirror', null, $channel); $a = $rest->downloadHttp('http://' . $channel . '/channel.xml', $chan->lastModified()); PEAR::staticPopErrorHandling(); if (!PEAR::isError($a) && $a) { $this->ui->outputData('WARNING: channel "' . $channel . '" has ' . 'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel . '" to update'); } } function doRemoteInfo($command, $options, $params) { if (sizeof($params) != 1) { return $this->raiseError("$command expects one param: the remote package name"); } $savechannel = $channel = $this->config->get('default_channel'); $reg = &$this->config->getRegistry(); $package = $params[0]; $parsed = $reg->parsePackageName($package, $channel); if (PEAR::isError($parsed)) { return $this->raiseError('Invalid package name "' . $package . '"'); } $channel = $parsed['channel']; $this->config->set('default_channel', $channel); $chan = $reg->getChannel($channel); if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { return $e; } $mirror = $this->config->get('preferred_mirror'); if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) { $rest = &$this->config->getREST('1.0', array()); $info = $rest->packageInfo($base, $parsed['package'], $channel); } if (!isset($info)) { return $this->raiseError('No supported protocol was found'); } if (PEAR::isError($info)) { $this->config->set('default_channel', $savechannel); return $this->raiseError($info); } if (!isset($info['name'])) { return $this->raiseError('No remote package "' . $package . '" was found'); } $installed = $reg->packageInfo($info['name'], null, $channel); $info['installed'] = $installed ? $installed['version'] : '- no -'; if (is_array($info['installed'])) { $info['installed'] = $info['installed']['release']; } $this->ui->outputData($info, $command); $this->config->set('default_channel', $savechannel); return true; } function doRemoteList($command, $options, $params) { $savechannel = $channel = $this->config->get('default_channel'); $reg = &$this->config->getRegistry(); if (isset($options['channel'])) { $channel = $options['channel']; if (!$reg->channelExists($channel)) { return $this->raiseError('Channel "' . $channel . '" does not exist'); } $this->config->set('default_channel', $channel); } $chan = $reg->getChannel($channel); if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { return $e; } $list_options = false; if ($this->config->get('preferred_state') == 'stable') { $list_options = true; } $available = array(); if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror')) ) { // use faster list-all if available $rest = &$this->config->getREST('1.1', array()); $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName()); } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName()); } if (PEAR::isError($available)) { $this->config->set('default_channel', $savechannel); return $this->raiseError($available); } $i = $j = 0; $data = array( 'caption' => 'Channel ' . $channel . ' Available packages:', 'border' => true, 'headline' => array('Package', 'Version'), 'channel' => $channel ); if (count($available) == 0) { $data = '(no packages available yet)'; } else { foreach ($available as $name => $info) { $version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-'; $data['data'][] = array($name, $version); } } $this->ui->outputData($data, $command); $this->config->set('default_channel', $savechannel); return true; } function doListAll($command, $options, $params) { $savechannel = $channel = $this->config->get('default_channel'); $reg = &$this->config->getRegistry(); if (isset($options['channel'])) { $channel = $options['channel']; if (!$reg->channelExists($channel)) { return $this->raiseError("Channel \"$channel\" does not exist"); } $this->config->set('default_channel', $channel); } $list_options = false; if ($this->config->get('preferred_state') == 'stable') { $list_options = true; } $chan = $reg->getChannel($channel); if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { return $e; } if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { // use faster list-all if available $rest = &$this->config->getREST('1.1', array()); $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName()); } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName()); } if (PEAR::isError($available)) { $this->config->set('default_channel', $savechannel); return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")'); } $data = array( 'caption' => 'All packages [Channel ' . $channel . ']:', 'border' => true, 'headline' => array('Package', 'Latest', 'Local'), 'channel' => $channel, ); if (isset($options['channelinfo'])) { // add full channelinfo $data['caption'] = 'Channel ' . $channel . ' All packages:'; $data['headline'] = array('Channel', 'Package', 'Latest', 'Local', 'Description', 'Dependencies'); } $local_pkgs = $reg->listPackages($channel); foreach ($available as $name => $info) { $installed = $reg->packageInfo($name, null, $channel); if ($installed && is_array($installed['version'])) { $installed['version'] = $installed['version']['release']; } $desc = $info['summary']; if (isset($params[$name])) { $desc .= "\n\n".$info['description']; } if (isset($options['mode'])) { if ($options['mode'] == 'installed' && !isset($installed['version'])) { continue; } if ($options['mode'] == 'notinstalled' && isset($installed['version'])) { continue; } if ($options['mode'] == 'upgrades' && (!isset($installed['version']) || version_compare($installed['version'], $info['stable'], '>='))) { continue; } } $pos = array_search(strtolower($name), $local_pkgs); if ($pos !== false) { unset($local_pkgs[$pos]); } if (isset($info['stable']) && !$info['stable']) { $info['stable'] = null; } if (isset($options['channelinfo'])) { // add full channelinfo if ($info['stable'] === $info['unstable']) { $state = $info['state']; } else { $state = 'stable'; } $latest = $info['stable'].' ('.$state.')'; $local = ''; if (isset($installed['version'])) { $inst_state = $reg->packageInfo($name, 'release_state', $channel); $local = $installed['version'].' ('.$inst_state.')'; } $packageinfo = array( $channel, $name, $latest, $local, isset($desc) ? $desc : null, isset($info['deps']) ? $info['deps'] : null, ); } else { $packageinfo = array( $reg->channelAlias($channel) . '/' . $name, isset($info['stable']) ? $info['stable'] : null, isset($installed['version']) ? $installed['version'] : null, isset($desc) ? $desc : null, isset($info['deps']) ? $info['deps'] : null, ); } $data['data'][$info['category']][] = $packageinfo; } if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) { $this->config->set('default_channel', $savechannel); $this->ui->outputData($data, $command); return true; } foreach ($local_pkgs as $name) { $info = &$reg->getPackage($name, $channel); $data['data']['Local'][] = array( $reg->channelAlias($channel) . '/' . $info->getPackage(), '', $info->getVersion(), $info->getSummary(), $info->getDeps() ); } $this->config->set('default_channel', $savechannel); $this->ui->outputData($data, $command); return true; } function doSearch($command, $options, $params) { if ((!isset($params[0]) || empty($params[0])) && (!isset($params[1]) || empty($params[1]))) { return $this->raiseError('no valid search string supplied'); } $channelinfo = isset($options['channelinfo']); $reg = &$this->config->getRegistry(); if (isset($options['allchannels'])) { // search all channels unset($options['allchannels']); $channels = $reg->getChannels(); $errors = array(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); foreach ($channels as $channel) { if ($channel->getName() != '__uri') { $options['channel'] = $channel->getName(); $ret = $this->doSearch($command, $options, $params); if (PEAR::isError($ret)) { $errors[] = $ret; } } } PEAR::staticPopErrorHandling(); if (count($errors) !== 0) { // for now, only give first error return PEAR::raiseError($errors[0]); } return true; } $savechannel = $channel = $this->config->get('default_channel'); $package = strtolower($params[0]); $summary = isset($params[1]) ? $params[1] : false; if (isset($options['channel'])) { $reg = &$this->config->getRegistry(); $channel = $options['channel']; if (!$reg->channelExists($channel)) { return $this->raiseError('Channel "' . $channel . '" does not exist'); } $this->config->set('default_channel', $channel); } $chan = $reg->getChannel($channel); if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { return $e; } if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName()); } if (PEAR::isError($available)) { $this->config->set('default_channel', $savechannel); return $this->raiseError($available); } if (!$available && !$channelinfo) { // clean exit when not found, no error ! $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.'; $this->ui->outputData($data); $this->config->set('default_channel', $channel); return true; } if ($channelinfo) { $data = array( 'caption' => 'Matched packages, channel ' . $channel . ':', 'border' => true, 'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'), 'channel' => $channel ); } else { $data = array( 'caption' => 'Matched packages, channel ' . $channel . ':', 'border' => true, 'headline' => array('Package', 'Stable/(Latest)', 'Local'), 'channel' => $channel ); } if (!$available && $channelinfo) { unset($data['headline']); $data['data'] = 'No packages found that match pattern "' . $package . '".'; $available = array(); } foreach ($available as $name => $info) { $installed = $reg->packageInfo($name, null, $channel); $desc = $info['summary']; if (isset($params[$name])) $desc .= "\n\n".$info['description']; if (!isset($info['stable']) || !$info['stable']) { $version_remote = 'none'; } else { if ($info['unstable']) { $version_remote = $info['unstable']; } else { $version_remote = $info['stable']; } $version_remote .= ' ('.$info['state'].')'; } $version = is_array($installed['version']) ? $installed['version']['release'] : $installed['version']; if ($channelinfo) { $packageinfo = array( $channel, $name, $version_remote, $version, $desc, ); } else { $packageinfo = array( $name, $version_remote, $version, $desc, ); } $data['data'][$info['category']][] = $packageinfo; } $this->ui->outputData($data, $command); $this->config->set('default_channel', $channel); return true; } function &getDownloader($options) { if (!class_exists('PEAR_Downloader')) { require_once 'PEAR/Downloader.php'; } $a = new PEAR_Downloader($this->ui, $options, $this->config); return $a; } function doDownload($command, $options, $params) { // make certain that dependencies are ignored $options['downloadonly'] = 1; // eliminate error messages for preferred_state-related errors /* TODO: Should be an option, but until now download does respect preferred state */ /* $options['ignorepreferred_state'] = 1; */ // eliminate error messages for preferred_state-related errors $downloader = &$this->getDownloader($options); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $e = $downloader->setDownloadDir(getcwd()); PEAR::staticPopErrorHandling(); if (PEAR::isError($e)) { return $this->raiseError('Current directory is not writeable, cannot download'); } $errors = array(); $downloaded = array(); $err = $downloader->download($params); if (PEAR::isError($err)) { return $err; } $errors = $downloader->getErrorMsgs(); if (count($errors)) { foreach ($errors as $error) { if ($error !== null) { $this->ui->outputData($error); } } return $this->raiseError("$command failed"); } $downloaded = $downloader->getDownloadedPackages(); foreach ($downloaded as $pkg) { $this->ui->outputData("File $pkg[file] downloaded", $command); } return true; } function downloadCallback($msg, $params = null) { if ($msg == 'done') { $this->bytes_downloaded = $params; } } function doListUpgrades($command, $options, $params) { require_once 'PEAR/Common.php'; if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) { return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"'); } $savechannel = $channel = $this->config->get('default_channel'); $reg = &$this->config->getRegistry(); foreach ($reg->listChannels() as $channel) { $inst = array_flip($reg->listPackages($channel)); if (!count($inst)) { continue; } if ($channel == '__uri') { continue; } $this->config->set('default_channel', $channel); $state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0]; $caption = $channel . ' Available Upgrades'; $chan = $reg->getChannel($channel); if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { return $e; } $latest = array(); $base2 = false; $preferred_mirror = $this->config->get('preferred_mirror'); if ($chan->supportsREST($preferred_mirror) && ( ($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror)) || ($base = $chan->getBaseURL('REST1.0', $preferred_mirror)) ) ) { if ($base2) { $rest = &$this->config->getREST('1.3', array()); $base = $base2; } else { $rest = &$this->config->getREST('1.0', array()); } if (empty($state) || $state == 'any') { $state = false; } else { $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')'; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg); PEAR::staticPopErrorHandling(); } if (PEAR::isError($latest)) { $this->ui->outputData($latest->getMessage()); continue; } $caption .= ':'; if (PEAR::isError($latest)) { $this->config->set('default_channel', $savechannel); return $latest; } $data = array( 'caption' => $caption, 'border' => 1, 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'), 'channel' => $channel ); foreach ((array)$latest as $pkg => $info) { $package = strtolower($pkg); if (!isset($inst[$package])) { // skip packages we don't have installed continue; } extract($info); $inst_version = $reg->packageInfo($package, 'version', $channel); $inst_state = $reg->packageInfo($package, 'release_state', $channel); if (version_compare("$version", "$inst_version", "le")) { // installed version is up-to-date continue; } if ($filesize >= 20480) { $filesize += 1024 - ($filesize % 1024); $fs = sprintf("%dkB", $filesize / 1024); } elseif ($filesize > 0) { $filesize += 103 - ($filesize % 103); $fs = sprintf("%.1fkB", $filesize / 1024.0); } else { $fs = " -"; // XXX center instead } $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs); } if (isset($options['channelinfo'])) { if (empty($data['data'])) { unset($data['headline']); if (count($inst) == 0) { $data['data'] = '(no packages installed)'; } else { $data['data'] = '(no upgrades available)'; } } $this->ui->outputData($data, $command); } else { if (empty($data['data'])) { $this->ui->outputData('Channel ' . $channel . ': No upgrades available'); } else { $this->ui->outputData($data, $command); } } } $this->config->set('default_channel', $savechannel); return true; } function doClearCache($command, $options, $params) { $cache_dir = $this->config->get('cache_dir'); $verbose = $this->config->get('verbose'); $output = ''; if (!file_exists($cache_dir) || !is_dir($cache_dir)) { return $this->raiseError("$cache_dir does not exist or is not a directory"); } if (!($dp = @opendir($cache_dir))) { return $this->raiseError("opendir($cache_dir) failed: $php_errormsg"); } if ($verbose >= 1) { $output .= "reading directory $cache_dir\n"; } $num = 0; while ($ent = readdir($dp)) { if (preg_match('/rest.cache(file|id)\\z/', $ent)) { $path = $cache_dir . DIRECTORY_SEPARATOR . $ent; if (file_exists($path)) { $ok = @unlink($path); } else { $ok = false; $php_errormsg = ''; } if ($ok) { if ($verbose >= 2) { $output .= "deleted $path\n"; } $num++; } elseif ($verbose >= 1) { $output .= "failed to delete $path $php_errormsg\n"; } } } closedir($dp); if ($verbose >= 1) { $output .= "$num cache entries cleared\n"; } $this->ui->outputData(rtrim($output), $command); return $num; } } PK! \ PEAR/Command/Remote.xmlnu[ Information About Remote Packages doRemoteInfo ri <package> Get details on a package from the server. List Available Upgrades doListUpgrades lu i output fully channel-aware data, even on failure [preferred_state] List releases on the server of packages you have installed where a newer version is available with the same release state (stable etc.) or the state passed as the second parameter. List Remote Packages doRemoteList rl c specify a channel other than the default channel CHAN Lists the packages available on the configured server along with the latest stable release of each package. Search remote package database doSearch sp c specify a channel other than the default channel CHAN a search packages from all known channels i output fully channel-aware data, even on failure [packagename] [packageinfo] Lists all packages which match the search parameters. The first parameter is a fragment of a packagename. The default channel will be used unless explicitly overridden. The second parameter will be used to match any portion of the summary/description List All Packages doListAll la c specify a channel other than the default channel CHAN i output fully channel-aware data, even on failure Lists the packages available on the configured server along with the latest stable release of each package. Download Package doDownload d Z download an uncompressed (.tar) file <package>... Download package tarballs. The files will be named as suggested by the server, for example if you download the DB package and the latest stable version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz. Clear Web Services Cache doClearCache cc Clear the XML-RPC/REST cache. See also the cache_ttl configuration parameter. PK!j!!PEAR/Command/Install.xmlnu[ Install Package doInstall i f will overwrite newer installed packages l do not check for recommended dependency version n ignore dependencies, install anyway r do not install files, only register the package as installed s soft install, fail silently, or upgrade if already installed B don't build C extensions D OPTION1=VALUE[ OPTION2=VALUE] Z request uncompressed files when downloading R root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM DIR P root directory used when packaging files, like RPM packaging DIR force install even if there were errors a install all required and optional dependencies o install all required dependencies O do not attempt to download any urls or contact channels p Only list the packages that would be downloaded [channel/]<package> ... Installs one or more PEAR packages. You can specify a package to install in four ways: "Package-1.0.tgz" : installs from a local file "http://example.com/Package-1.0.tgz" : installs from anywhere on the net. "package.xml" : installs the package described in package.xml. Useful for testing, or for wrapping a PEAR package in another package manager such as RPM. "Package[-version/state][.tar]" : queries your default channel's server ({config master_server}) and downloads the newest package with the preferred quality/state ({config preferred_state}). To retrieve Package version 1.1, use "Package-1.1," to retrieve Package state beta, use "Package-beta." To retrieve an uncompressed file, append .tar (make sure there is no file by the same name first) To download a package from another channel, prefix with the channel name like "channel/Package" More than one package may be specified at once. It is ok to mix these four ways of specifying packages. Upgrade Package doInstall up c upgrade packages from a specific channel CHAN f overwrite newer installed packages l do not check for recommended dependency version n ignore dependencies, upgrade anyway r do not install files, only register the package as upgraded B don't build C extensions Z request uncompressed files when downloading R root directory used when installing files (ala PHP's INSTALL_ROOT) DIR force install even if there were errors a install all required and optional dependencies o install all required dependencies O do not attempt to download any urls or contact channels p Only list the packages that would be downloaded <package> ... Upgrades one or more PEAR packages. See documentation for the "install" command for ways to specify a package. When upgrading, your package will be updated if the provided new package has a higher version number (use the -f option if you need to upgrade anyway). More than one package may be specified at once. Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters] doUpgradeAll ua c upgrade packages from a specific channel CHAN n ignore dependencies, upgrade anyway r do not install files, only register the package as upgraded B don't build C extensions Z request uncompressed files when downloading R root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM DIR force install even if there were errors do not check for recommended dependency version WARNING: This function is deprecated in favor of using the upgrade command with no params Upgrades all packages that have a newer release available. Upgrades are done only if there is a release available of the state specified in "preferred_state" (currently {config preferred_state}), or a state considered more stable. Un-install Package doUninstall un n ignore dependencies, uninstall anyway r do not remove files, only register the packages as not installed R root directory used when installing files (ala PHP's INSTALL_ROOT) DIR force install even if there were errors O do not attempt to uninstall remotely [channel/]<package> ... Uninstalls one or more PEAR packages. More than one package may be specified at once. Prefix with channel name to uninstall from a channel not in your default channel ({config default_channel}) Unpacks a Pecl Package doBundle bun d Optional destination directory for unpacking (defaults to current path or "ext" if exists) DIR f Force the unpacking even if there were errors in the package <package> Unpacks a Pecl Package into the selected location. It will download the package if needed. Run Post-Install Scripts bundled with a package doRunScripts rs <package> Run post-installation scripts in package <package>, if any exist. PK!%qPEAR/Command/Channels.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500); /** * PEAR commands for managing channels. * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Command_Channels extends PEAR_Command_Common { var $commands = array( 'list-channels' => array( 'summary' => 'List Available Channels', 'function' => 'doList', 'shortcut' => 'lc', 'options' => array(), 'doc' => ' List all available channels for installation. ', ), 'update-channels' => array( 'summary' => 'Update the Channel List', 'function' => 'doUpdateAll', 'shortcut' => 'uc', 'options' => array(), 'doc' => ' List all installed packages in all channels. ' ), 'channel-delete' => array( 'summary' => 'Remove a Channel From the List', 'function' => 'doDelete', 'shortcut' => 'cde', 'options' => array(), 'doc' => ' Delete a channel from the registry. You may not remove any channel that has installed packages. ' ), 'channel-add' => array( 'summary' => 'Add a Channel', 'function' => 'doAdd', 'shortcut' => 'ca', 'options' => array(), 'doc' => ' Add a private channel to the channel list. Note that all public channels should be synced using "update-channels". Parameter may be either a local file or remote URL to a channel.xml. ' ), 'channel-update' => array( 'summary' => 'Update an Existing Channel', 'function' => 'doUpdate', 'shortcut' => 'cu', 'options' => array( 'force' => array( 'shortopt' => 'f', 'doc' => 'will force download of new channel.xml if an existing channel name is used', ), 'channel' => array( 'shortopt' => 'c', 'arg' => 'CHANNEL', 'doc' => 'will force download of new channel.xml if an existing channel name is used', ), ), 'doc' => '[|] Update a channel in the channel list directly. Note that all public channels can be synced using "update-channels". Parameter may be a local or remote channel.xml, or the name of an existing channel. ' ), 'channel-info' => array( 'summary' => 'Retrieve Information on a Channel', 'function' => 'doInfo', 'shortcut' => 'ci', 'options' => array(), 'doc' => ' List the files in an installed package. ' ), 'channel-alias' => array( 'summary' => 'Specify an alias to a channel name', 'function' => 'doAlias', 'shortcut' => 'cha', 'options' => array(), 'doc' => ' Specify a specific alias to use for a channel name. The alias may not be an existing channel name or alias. ' ), 'channel-discover' => array( 'summary' => 'Initialize a Channel from its server', 'function' => 'doDiscover', 'shortcut' => 'di', 'options' => array(), 'doc' => '[|] Initialize a channel from its server and create a local channel.xml. If is in the format ":@" then and will be set as the login username/password for . Use caution when passing the username/password in this way, as it may allow other users on your computer to briefly view your username/ password via the system\'s process list. ' ), 'channel-login' => array( 'summary' => 'Connects and authenticates to remote channel server', 'shortcut' => 'cli', 'function' => 'doLogin', 'options' => array(), 'doc' => ' Log in to a remote channel server. If is not supplied, the default channel is used. To use remote functions in the installer that require any kind of privileges, you need to log in first. The username and password you enter here will be stored in your per-user PEAR configuration (~/.pearrc on Unix-like systems). After logging in, your username and password will be sent along in subsequent operations on the remote server.', ), 'channel-logout' => array( 'summary' => 'Logs out from the remote channel server', 'shortcut' => 'clo', 'function' => 'doLogout', 'options' => array(), 'doc' => ' Logs out from a remote channel server. If is not supplied, the default channel is used. This command does not actually connect to the remote server, it only deletes the stored username and password from your user configuration.', ), ); /** * PEAR_Command_Registry constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } function _sortChannels($a, $b) { return strnatcasecmp($a->getName(), $b->getName()); } function doList($command, $options, $params) { $reg = &$this->config->getRegistry(); $registered = $reg->getChannels(); usort($registered, array(&$this, '_sortchannels')); $i = $j = 0; $data = array( 'caption' => 'Registered Channels:', 'border' => true, 'headline' => array('Channel', 'Alias', 'Summary') ); foreach ($registered as $channel) { $data['data'][] = array($channel->getName(), $channel->getAlias(), $channel->getSummary()); } if (count($registered) === 0) { $data = '(no registered channels)'; } $this->ui->outputData($data, $command); return true; } function doUpdateAll($command, $options, $params) { $reg = &$this->config->getRegistry(); $channels = $reg->getChannels(); $success = true; foreach ($channels as $channel) { if ($channel->getName() != '__uri') { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = $this->doUpdate('channel-update', $options, array($channel->getName())); if (PEAR::isError($err)) { $this->ui->outputData($err->getMessage(), $command); $success = false; } else { $success &= $err; } } } return $success; } function doInfo($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError("No channel specified"); } $reg = &$this->config->getRegistry(); $channel = strtolower($params[0]); if ($reg->channelExists($channel)) { $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $this->raiseError($chan); } } else { if (strpos($channel, '://')) { $downloader = &$this->getDownloader(); $tmpdir = $this->config->get('temp_dir'); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir); PEAR::staticPopErrorHandling(); if (PEAR::isError($loc)) { return $this->raiseError('Cannot open "' . $channel . '" (' . $loc->getMessage() . ')'); } else { $contents = implode('', file($loc)); } } else { if (!file_exists($params[0])) { return $this->raiseError('Unknown channel "' . $channel . '"'); } $fp = fopen($params[0], 'r'); if (!$fp) { return $this->raiseError('Cannot open "' . $params[0] . '"'); } $contents = ''; while (!feof($fp)) { $contents .= fread($fp, 1024); } fclose($fp); } if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $chan = new PEAR_ChannelFile; $chan->fromXmlString($contents); $chan->validate(); if ($errs = $chan->getErrors(true)) { foreach ($errs as $err) { $this->ui->outputData($err['level'] . ': ' . $err['message']); } return $this->raiseError('Channel file "' . $params[0] . '" is not valid'); } } if (!$chan) { return $this->raiseError('Serious error: Channel "' . $params[0] . '" has a corrupted registry entry'); } $channel = $chan->getName(); $caption = 'Channel ' . $channel . ' Information:'; $data1 = array( 'caption' => $caption, 'border' => true); $data1['data']['server'] = array('Name and Server', $chan->getName()); if ($chan->getAlias() != $chan->getName()) { $data1['data']['alias'] = array('Alias', $chan->getAlias()); } $data1['data']['summary'] = array('Summary', $chan->getSummary()); $validate = $chan->getValidationPackage(); $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']); $data1['data']['vpackageversion'] = array('Validation Package Version', $validate['attribs']['version']); $d = array(); $d['main'] = $data1; $data['data'] = array(); $data['caption'] = 'Server Capabilities'; $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base'); if ($chan->supportsREST()) { if ($chan->supportsREST()) { $funcs = $chan->getFunctions('rest'); if (!isset($funcs[0])) { $funcs = array($funcs); } foreach ($funcs as $protocol) { $data['data'][] = array('rest', $protocol['attribs']['type'], $protocol['_content']); } } } else { $data['data'][] = array('No supported protocols'); } $d['protocols'] = $data; $data['data'] = array(); $mirrors = $chan->getMirrors(); if ($mirrors) { $data['caption'] = 'Channel ' . $channel . ' Mirrors:'; unset($data['headline']); foreach ($mirrors as $mirror) { $data['data'][] = array($mirror['attribs']['host']); $d['mirrors'] = $data; } foreach ($mirrors as $i => $mirror) { $data['data'] = array(); $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities'; $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base'); if ($chan->supportsREST($mirror['attribs']['host'])) { if ($chan->supportsREST($mirror['attribs']['host'])) { $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']); if (!isset($funcs[0])) { $funcs = array($funcs); } foreach ($funcs as $protocol) { $data['data'][] = array('rest', $protocol['attribs']['type'], $protocol['_content']); } } } else { $data['data'][] = array('No supported protocols'); } $d['mirrorprotocols' . $i] = $data; } } $this->ui->outputData($d, 'channel-info'); } // }}} function doDelete($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError('channel-delete: no channel specified'); } $reg = &$this->config->getRegistry(); if (!$reg->channelExists($params[0])) { return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist'); } $channel = $reg->channelName($params[0]); if ($channel == 'pear.php.net') { return $this->raiseError('Cannot delete the pear.php.net channel'); } if ($channel == 'pecl.php.net') { return $this->raiseError('Cannot delete the pecl.php.net channel'); } if ($channel == 'doc.php.net') { return $this->raiseError('Cannot delete the doc.php.net channel'); } if ($channel == '__uri') { return $this->raiseError('Cannot delete the __uri pseudo-channel'); } if (PEAR::isError($err = $reg->listPackages($channel))) { return $err; } if (count($err)) { return $this->raiseError('Channel "' . $channel . '" has installed packages, cannot delete'); } if (!$reg->deleteChannel($channel)) { return $this->raiseError('Channel "' . $channel . '" deletion failed'); } else { $this->config->deleteChannel($channel); $this->ui->outputData('Channel "' . $channel . '" deleted', $command); } } function doAdd($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError('channel-add: no channel file specified'); } if (strpos($params[0], '://')) { $downloader = &$this->getDownloader(); $tmpdir = $this->config->get('temp_dir'); if (!file_exists($tmpdir)) { require_once 'System.php'; PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = System::mkdir(array('-p', $tmpdir)); PEAR::staticPopErrorHandling(); if (PEAR::isError($err)) { return $this->raiseError('channel-add: temp_dir does not exist: "' . $tmpdir . '" - You can change this location with "pear config-set temp_dir"'); } } if (!is_writable($tmpdir)) { return $this->raiseError('channel-add: temp_dir is not writable: "' . $tmpdir . '" - You can change this location with "pear config-set temp_dir"'); } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false); PEAR::staticPopErrorHandling(); if (PEAR::isError($loc)) { return $this->raiseError('channel-add: Cannot open "' . $params[0] . '" (' . $loc->getMessage() . ')'); } list($loc, $lastmodified) = $loc; $contents = implode('', file($loc)); } else { $lastmodified = $fp = false; if (file_exists($params[0])) { $fp = fopen($params[0], 'r'); } if (!$fp) { return $this->raiseError('channel-add: cannot open "' . $params[0] . '"'); } $contents = ''; while (!feof($fp)) { $contents .= fread($fp, 1024); } fclose($fp); } if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $channel = new PEAR_ChannelFile; PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $result = $channel->fromXmlString($contents); PEAR::staticPopErrorHandling(); if (!$result) { $exit = false; if (count($errors = $channel->getErrors(true))) { foreach ($errors as $error) { $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message'])); if (!$exit) { $exit = $error['level'] == 'error' ? true : false; } } if ($exit) { return $this->raiseError('channel-add: invalid channel.xml file'); } } } $reg = &$this->config->getRegistry(); if ($reg->channelExists($channel->getName())) { return $this->raiseError('channel-add: Channel "' . $channel->getName() . '" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS); } $ret = $reg->addChannel($channel, $lastmodified); if (PEAR::isError($ret)) { return $ret; } if (!$ret) { return $this->raiseError('channel-add: adding Channel "' . $channel->getName() . '" to registry failed'); } $this->config->setChannels($reg->listChannels()); $this->config->writeConfigFile(); $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command); } function doUpdate($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError("No channel file specified"); } $tmpdir = $this->config->get('temp_dir'); if (!file_exists($tmpdir)) { require_once 'System.php'; PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = System::mkdir(array('-p', $tmpdir)); PEAR::staticPopErrorHandling(); if (PEAR::isError($err)) { return $this->raiseError('channel-add: temp_dir does not exist: "' . $tmpdir . '" - You can change this location with "pear config-set temp_dir"'); } } if (!is_writable($tmpdir)) { return $this->raiseError('channel-add: temp_dir is not writable: "' . $tmpdir . '" - You can change this location with "pear config-set temp_dir"'); } $reg = &$this->config->getRegistry(); $lastmodified = false; if ((!file_exists($params[0]) || is_dir($params[0])) && $reg->channelExists(strtolower($params[0]))) { $c = $reg->getChannel(strtolower($params[0])); if (PEAR::isError($c)) { return $this->raiseError($c); } $this->ui->outputData("Updating channel \"$params[0]\"", $command); $dl = &$this->getDownloader(array()); // if force is specified, use a timestamp of "1" to force retrieval $lastmodified = isset($options['force']) ? false : $c->lastModified(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml', $this->ui, $tmpdir, null, $lastmodified); PEAR::staticPopErrorHandling(); if (PEAR::isError($contents)) { // Attempt to fall back to https $this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage()); $this->ui->outputData("Trying channel \"$params[0]\" over https:// instead"); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml', $this->ui, $tmpdir, null, $lastmodified); PEAR::staticPopErrorHandling(); if (PEAR::isError($contents)) { return $this->raiseError('Cannot retrieve channel.xml for channel "' . $c->getName() . '" (' . $contents->getMessage() . ')'); } } list($contents, $lastmodified) = $contents; if (!$contents) { $this->ui->outputData("Channel \"$params[0]\" is up to date"); return; } $contents = implode('', file($contents)); if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $channel = new PEAR_ChannelFile; $channel->fromXmlString($contents); if (!$channel->getErrors()) { // security check: is the downloaded file for the channel we got it from? if (strtolower($channel->getName()) != strtolower($c->getName())) { if (!isset($options['force'])) { return $this->raiseError('ERROR: downloaded channel definition file' . ' for channel "' . $channel->getName() . '" from channel "' . strtolower($c->getName()) . '"'); } $this->ui->log(0, 'WARNING: downloaded channel definition file' . ' for channel "' . $channel->getName() . '" from channel "' . strtolower($c->getName()) . '"'); } } } else { if (strpos($params[0], '://')) { $dl = &$this->getDownloader(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $loc = $dl->downloadHttp($params[0], $this->ui, $tmpdir, null, $lastmodified); PEAR::staticPopErrorHandling(); if (PEAR::isError($loc)) { return $this->raiseError("Cannot open " . $params[0] . ' (' . $loc->getMessage() . ')'); } list($loc, $lastmodified) = $loc; $contents = implode('', file($loc)); } else { $fp = false; if (file_exists($params[0])) { $fp = fopen($params[0], 'r'); } if (!$fp) { return $this->raiseError("Cannot open " . $params[0]); } $contents = ''; while (!feof($fp)) { $contents .= fread($fp, 1024); } fclose($fp); } if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $channel = new PEAR_ChannelFile; $channel->fromXmlString($contents); } $exit = false; if (count($errors = $channel->getErrors(true))) { foreach ($errors as $error) { $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message'])); if (!$exit) { $exit = $error['level'] == 'error' ? true : false; } } if ($exit) { return $this->raiseError('Invalid channel.xml file'); } } if (!$reg->channelExists($channel->getName())) { return $this->raiseError('Error: Channel "' . $channel->getName() . '" does not exist, use channel-add to add an entry'); } $ret = $reg->updateChannel($channel, $lastmodified); if (PEAR::isError($ret)) { return $ret; } if (!$ret) { return $this->raiseError('Updating Channel "' . $channel->getName() . '" in registry failed'); } $this->config->setChannels($reg->listChannels()); $this->config->writeConfigFile(); $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded'); } function &getDownloader() { if (!class_exists('PEAR_Downloader')) { require_once 'PEAR/Downloader.php'; } $a = new PEAR_Downloader($this->ui, array(), $this->config); return $a; } function doAlias($command, $options, $params) { if (count($params) === 1) { return $this->raiseError('No channel alias specified'); } if (count($params) !== 2 || (!empty($params[1]) && $params[1][0] == '-')) { return $this->raiseError( 'Invalid format, correct is: channel-alias channel alias'); } $reg = &$this->config->getRegistry(); if (!$reg->channelExists($params[0], true)) { $extra = ''; if ($reg->isAlias($params[0])) { $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' . strtolower($params[1]) . '")'; } return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra); } if ($reg->isAlias($params[1])) { return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' . 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias'); } $chan = $reg->getChannel($params[0]); if (PEAR::isError($chan)) { return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] . '" information (' . $chan->getMessage() . ')'); } // make it a local alias if (!$chan->setAlias(strtolower($params[1]), true)) { return $this->raiseError('Alias "' . strtolower($params[1]) . '" is not a valid channel alias'); } $reg->updateChannel($chan); $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' . strtolower($params[1]) . '"'); } /** * The channel-discover command * * @param string $command command name * @param array $options option_name => value * @param array $params list of additional parameters. * $params[0] should contain a string with either: * - or * - :@ * @return null|PEAR_Error */ function doDiscover($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError("No channel server specified"); } // Look for the possible input format ":@" if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) { $username = $matches[1]; $password = $matches[2]; $channel = $matches[3]; } else { $channel = $params[0]; } $reg = &$this->config->getRegistry(); if ($reg->channelExists($channel)) { if (!$reg->isAlias($channel)) { return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS); } return $this->raiseError("A channel alias named \"$channel\" " . 'already exists, aliasing channel "' . $reg->channelName($channel) . '"'); } $this->pushErrorHandling(PEAR_ERROR_RETURN); $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml')); $this->popErrorHandling(); if (PEAR::isError($err)) { if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) { return $this->raiseError("Discovery of channel \"$channel\" failed (" . $err->getMessage() . ')'); } // Attempt fetch via https $this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage()); $this->ui->outputData("Trying to discover channel $channel over https:// instead"); $this->pushErrorHandling(PEAR_ERROR_RETURN); $err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml')); $this->popErrorHandling(); if (PEAR::isError($err)) { return $this->raiseError("Discovery of channel \"$channel\" failed (" . $err->getMessage() . ')'); } } // Store username/password if they were given // Arguably we should do a logintest on the channel here, but since // that's awkward on a REST-based channel (even "pear login" doesn't // do it for those), and XML-RPC is deprecated, it's fairly pointless. if (isset($username)) { $this->config->set('username', $username, 'user', $channel); $this->config->set('password', $password, 'user', $channel); $this->config->store(); $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command); } $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command); } /** * Execute the 'login' command. * * @param string $command command name * @param array $options option_name => value * @param array $params list of additional parameters * * @return bool TRUE on success or * a PEAR error on failure * * @access public */ function doLogin($command, $options, $params) { $reg = &$this->config->getRegistry(); // If a parameter is supplied, use that as the channel to log in to $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel'); $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $this->raiseError($chan); } $server = $this->config->get('preferred_mirror', null, $channel); $username = $this->config->get('username', null, $channel); if (empty($username)) { $username = isset($_ENV['USER']) ? $_ENV['USER'] : null; } $this->ui->outputData("Logging in to $server.", $command); list($username, $password) = $this->ui->userDialog( $command, array('Username', 'Password'), array('text', 'password'), array($username, '') ); $username = trim($username); $password = trim($password); $ourfile = $this->config->getConfFile('user'); if (!$ourfile) { $ourfile = $this->config->getConfFile('system'); } $this->config->set('username', $username, 'user', $channel); $this->config->set('password', $password, 'user', $channel); if ($chan->supportsREST()) { $ok = true; } if ($ok !== true) { return $this->raiseError('Login failed!'); } $this->ui->outputData("Logged in.", $command); // avoid changing any temporary settings changed with -d $ourconfig = new PEAR_Config($ourfile, $ourfile); $ourconfig->set('username', $username, 'user', $channel); $ourconfig->set('password', $password, 'user', $channel); $ourconfig->store(); return true; } /** * Execute the 'logout' command. * * @param string $command command name * @param array $options option_name => value * @param array $params list of additional parameters * * @return bool TRUE on success or * a PEAR error on failure * * @access public */ function doLogout($command, $options, $params) { $reg = &$this->config->getRegistry(); // If a parameter is supplied, use that as the channel to log in to $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel'); $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $this->raiseError($chan); } $server = $this->config->get('preferred_mirror', null, $channel); $this->ui->outputData("Logging out from $server.", $command); $this->config->remove('username', 'user', $channel); $this->config->remove('password', 'user', $channel); $this->config->store(); return true; } } PK!nmi?;;PEAR/Command/Install.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; /** * PEAR commands for installation or deinstallation/upgrading of * packages. * * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Command_Install extends PEAR_Command_Common { // {{{ properties var $commands = array( 'install' => array( 'summary' => 'Install Package', 'function' => 'doInstall', 'shortcut' => 'i', 'options' => array( 'force' => array( 'shortopt' => 'f', 'doc' => 'will overwrite newer installed packages', ), 'loose' => array( 'shortopt' => 'l', 'doc' => 'do not check for recommended dependency version', ), 'nodeps' => array( 'shortopt' => 'n', 'doc' => 'ignore dependencies, install anyway', ), 'register-only' => array( 'shortopt' => 'r', 'doc' => 'do not install files, only register the package as installed', ), 'soft' => array( 'shortopt' => 's', 'doc' => 'soft install, fail silently, or upgrade if already installed', ), 'nobuild' => array( 'shortopt' => 'B', 'doc' => 'don\'t build C extensions', ), 'configureoptions' => array( 'shortopt' => 'D', 'arg' => 'OPTION1=VALUE[ OPTION2=VALUE]', 'doc' => 'space-delimited list of configure options', ), 'nocompress' => array( 'shortopt' => 'Z', 'doc' => 'request uncompressed files when downloading', ), 'installroot' => array( 'shortopt' => 'R', 'arg' => 'DIR', 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM', ), 'packagingroot' => array( 'shortopt' => 'P', 'arg' => 'DIR', 'doc' => 'root directory used when packaging files, like RPM packaging', ), 'ignore-errors' => array( 'doc' => 'force install even if there were errors', ), 'alldeps' => array( 'shortopt' => 'a', 'doc' => 'install all required and optional dependencies', ), 'onlyreqdeps' => array( 'shortopt' => 'o', 'doc' => 'install all required dependencies', ), 'offline' => array( 'shortopt' => 'O', 'doc' => 'do not attempt to download any urls or contact channels', ), 'pretend' => array( 'shortopt' => 'p', 'doc' => 'Only list the packages that would be downloaded', ), ), 'doc' => '[channel/] ... Installs one or more PEAR packages. You can specify a package to install in four ways: "Package-1.0.tgz" : installs from a local file "http://example.com/Package-1.0.tgz" : installs from anywhere on the net. "package.xml" : installs the package described in package.xml. Useful for testing, or for wrapping a PEAR package in another package manager such as RPM. "Package[-version/state][.tar]" : queries your default channel\'s server ({config master_server}) and downloads the newest package with the preferred quality/state ({config preferred_state}). To retrieve Package version 1.1, use "Package-1.1," to retrieve Package state beta, use "Package-beta." To retrieve an uncompressed file, append .tar (make sure there is no file by the same name first) To download a package from another channel, prefix with the channel name like "channel/Package" More than one package may be specified at once. It is ok to mix these four ways of specifying packages. '), 'upgrade' => array( 'summary' => 'Upgrade Package', 'function' => 'doInstall', 'shortcut' => 'up', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'upgrade packages from a specific channel', 'arg' => 'CHAN', ), 'force' => array( 'shortopt' => 'f', 'doc' => 'overwrite newer installed packages', ), 'loose' => array( 'shortopt' => 'l', 'doc' => 'do not check for recommended dependency version', ), 'nodeps' => array( 'shortopt' => 'n', 'doc' => 'ignore dependencies, upgrade anyway', ), 'register-only' => array( 'shortopt' => 'r', 'doc' => 'do not install files, only register the package as upgraded', ), 'nobuild' => array( 'shortopt' => 'B', 'doc' => 'don\'t build C extensions', ), 'nocompress' => array( 'shortopt' => 'Z', 'doc' => 'request uncompressed files when downloading', ), 'installroot' => array( 'shortopt' => 'R', 'arg' => 'DIR', 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', ), 'ignore-errors' => array( 'doc' => 'force install even if there were errors', ), 'alldeps' => array( 'shortopt' => 'a', 'doc' => 'install all required and optional dependencies', ), 'onlyreqdeps' => array( 'shortopt' => 'o', 'doc' => 'install all required dependencies', ), 'offline' => array( 'shortopt' => 'O', 'doc' => 'do not attempt to download any urls or contact channels', ), 'pretend' => array( 'shortopt' => 'p', 'doc' => 'Only list the packages that would be downloaded', ), ), 'doc' => ' ... Upgrades one or more PEAR packages. See documentation for the "install" command for ways to specify a package. When upgrading, your package will be updated if the provided new package has a higher version number (use the -f option if you need to upgrade anyway). More than one package may be specified at once. '), 'upgrade-all' => array( 'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]', 'function' => 'doUpgradeAll', 'shortcut' => 'ua', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'upgrade packages from a specific channel', 'arg' => 'CHAN', ), 'nodeps' => array( 'shortopt' => 'n', 'doc' => 'ignore dependencies, upgrade anyway', ), 'register-only' => array( 'shortopt' => 'r', 'doc' => 'do not install files, only register the package as upgraded', ), 'nobuild' => array( 'shortopt' => 'B', 'doc' => 'don\'t build C extensions', ), 'nocompress' => array( 'shortopt' => 'Z', 'doc' => 'request uncompressed files when downloading', ), 'installroot' => array( 'shortopt' => 'R', 'arg' => 'DIR', 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM', ), 'ignore-errors' => array( 'doc' => 'force install even if there were errors', ), 'loose' => array( 'doc' => 'do not check for recommended dependency version', ), ), 'doc' => ' WARNING: This function is deprecated in favor of using the upgrade command with no params Upgrades all packages that have a newer release available. Upgrades are done only if there is a release available of the state specified in "preferred_state" (currently {config preferred_state}), or a state considered more stable. '), 'uninstall' => array( 'summary' => 'Un-install Package', 'function' => 'doUninstall', 'shortcut' => 'un', 'options' => array( 'nodeps' => array( 'shortopt' => 'n', 'doc' => 'ignore dependencies, uninstall anyway', ), 'register-only' => array( 'shortopt' => 'r', 'doc' => 'do not remove files, only register the packages as not installed', ), 'installroot' => array( 'shortopt' => 'R', 'arg' => 'DIR', 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', ), 'ignore-errors' => array( 'doc' => 'force install even if there were errors', ), 'offline' => array( 'shortopt' => 'O', 'doc' => 'do not attempt to uninstall remotely', ), ), 'doc' => '[channel/] ... Uninstalls one or more PEAR packages. More than one package may be specified at once. Prefix with channel name to uninstall from a channel not in your default channel ({config default_channel}) '), 'bundle' => array( 'summary' => 'Unpacks a Pecl Package', 'function' => 'doBundle', 'shortcut' => 'bun', 'options' => array( 'destination' => array( 'shortopt' => 'd', 'arg' => 'DIR', 'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)', ), 'force' => array( 'shortopt' => 'f', 'doc' => 'Force the unpacking even if there were errors in the package', ), ), 'doc' => ' Unpacks a Pecl Package into the selected location. It will download the package if needed. '), 'run-scripts' => array( 'summary' => 'Run Post-Install Scripts bundled with a package', 'function' => 'doRunScripts', 'shortcut' => 'rs', 'options' => array( ), 'doc' => ' Run post-installation scripts in package , if any exist. '), ); // }}} // {{{ constructor /** * PEAR_Command_Install constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } // }}} /** * For unit testing purposes */ function &getDownloader(&$ui, $options, &$config) { if (!class_exists('PEAR_Downloader')) { require_once 'PEAR/Downloader.php'; } $a = new PEAR_Downloader($ui, $options, $config); return $a; } /** * For unit testing purposes */ function &getInstaller(&$ui) { if (!class_exists('PEAR_Installer')) { require_once 'PEAR/Installer.php'; } $a = new PEAR_Installer($ui); return $a; } function enableExtension($binaries, $type) { if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) { return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location'); } $ini = $this->_parseIni($phpini); if (PEAR::isError($ini)) { return $ini; } $line = 0; if ($type == 'extsrc' || $type == 'extbin') { $search = 'extensions'; $enable = 'extension'; } else { $search = 'zend_extensions'; ob_start(); phpinfo(INFO_GENERAL); $info = ob_get_contents(); ob_end_clean(); $debug = function_exists('leak') ? '_debug' : ''; $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; $enable = 'zend_extension' . $debug . $ts; } foreach ($ini[$search] as $line => $extension) { if (in_array($extension, $binaries, true) || in_array( $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) { // already enabled - assume if one is, all are return true; } } if ($line) { $newini = array_slice($ini['all'], 0, $line); } else { $newini = array(); } foreach ($binaries as $binary) { if ($ini['extension_dir']) { $binary = basename($binary); } $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n"); } $newini = array_merge($newini, array_slice($ini['all'], $line)); $fp = @fopen($phpini, 'wb'); if (!$fp) { return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing'); } foreach ($newini as $line) { fwrite($fp, $line); } fclose($fp); return true; } function disableExtension($binaries, $type) { if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) { return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location'); } $ini = $this->_parseIni($phpini); if (PEAR::isError($ini)) { return $ini; } $line = 0; if ($type == 'extsrc' || $type == 'extbin') { $search = 'extensions'; $enable = 'extension'; } else { $search = 'zend_extensions'; ob_start(); phpinfo(INFO_GENERAL); $info = ob_get_contents(); ob_end_clean(); $debug = function_exists('leak') ? '_debug' : ''; $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; $enable = 'zend_extension' . $debug . $ts; } $found = false; foreach ($ini[$search] as $line => $extension) { if (in_array($extension, $binaries, true) || in_array( $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) { $found = true; break; } } if (!$found) { // not enabled return true; } $fp = @fopen($phpini, 'wb'); if (!$fp) { return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing'); } if ($line) { $newini = array_slice($ini['all'], 0, $line); // delete the enable line $newini = array_merge($newini, array_slice($ini['all'], $line + 1)); } else { $newini = array_slice($ini['all'], 1); } foreach ($newini as $line) { fwrite($fp, $line); } fclose($fp); return true; } function _parseIni($filename) { if (!file_exists($filename)) { return PEAR::raiseError('php.ini "' . $filename . '" does not exist'); } if (filesize($filename) > 300000) { return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting'); } ob_start(); phpinfo(INFO_GENERAL); $info = ob_get_contents(); ob_end_clean(); $debug = function_exists('leak') ? '_debug' : ''; $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; $zend_extension_line = 'zend_extension' . $debug . $ts; $all = @file($filename); if ($all === false) { return PEAR::raiseError('php.ini "' . $filename .'" could not be read'); } $zend_extensions = $extensions = array(); // assume this is right, but pull from the php.ini if it is found $extension_dir = ini_get('extension_dir'); foreach ($all as $linenum => $line) { $line = trim($line); if (!$line) { continue; } if ($line[0] == ';') { continue; } if (strtolower(substr($line, 0, 13)) == 'extension_dir') { $line = trim(substr($line, 13)); if ($line[0] == '=') { $x = trim(substr($line, 1)); $x = explode(';', $x); $extension_dir = str_replace('"', '', array_shift($x)); continue; } } if (strtolower(substr($line, 0, 9)) == 'extension') { $line = trim(substr($line, 9)); if ($line[0] == '=') { $x = trim(substr($line, 1)); $x = explode(';', $x); $extensions[$linenum] = str_replace('"', '', array_shift($x)); continue; } } if (strtolower(substr($line, 0, strlen($zend_extension_line))) == $zend_extension_line) { $line = trim(substr($line, strlen($zend_extension_line))); if ($line[0] == '=') { $x = trim(substr($line, 1)); $x = explode(';', $x); $zend_extensions[$linenum] = str_replace('"', '', array_shift($x)); continue; } } } return array( 'extensions' => $extensions, 'zend_extensions' => $zend_extensions, 'extension_dir' => $extension_dir, 'all' => $all, ); } // {{{ doInstall() function doInstall($command, $options, $params) { if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } if (isset($options['installroot']) && isset($options['packagingroot'])) { return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot'); } $reg = &$this->config->getRegistry(); $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); if (!$reg->channelExists($channel)) { return $this->raiseError('Channel "' . $channel . '" does not exist'); } if (empty($this->installer)) { $this->installer = &$this->getInstaller($this->ui); } if ($command == 'upgrade' || $command == 'upgrade-all') { // If people run the upgrade command but pass nothing, emulate a upgrade-all if ($command == 'upgrade' && empty($params)) { return $this->doUpgradeAll($command, $options, $params); } $options['upgrade'] = true; } else { $packages = $params; } $instreg = &$reg; // instreg used to check if package is installed if (isset($options['packagingroot']) && !isset($options['upgrade'])) { $packrootphp_dir = $this->installer->_prependPath( $this->config->get('php_dir', null, 'pear.php.net'), $options['packagingroot']); $metadata_dir = $this->config->get('metadata_dir', null, 'pear.php.net'); if ($metadata_dir) { $metadata_dir = $this->installer->_prependPath( $metadata_dir, $options['packagingroot']); } $instreg = new PEAR_Registry($packrootphp_dir, false, false, $metadata_dir); // other instreg! if ($this->config->get('verbose') > 2) { $this->ui->outputData('using package root: ' . $options['packagingroot']); } } $abstractpackages = $otherpackages = array(); // parse params PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); foreach ($params as $param) { if (strpos($param, 'http://') === 0) { $otherpackages[] = $param; continue; } if (strpos($param, 'channel://') === false && @file_exists($param)) { if (isset($options['force'])) { $otherpackages[] = $param; continue; } $pkg = new PEAR_PackageFile($this->config); $pf = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING); if (PEAR::isError($pf)) { $otherpackages[] = $param; continue; } $exists = $reg->packageExists($pf->getPackage(), $pf->getChannel()); $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel()); $version_compare = version_compare($pf->getVersion(), $pversion, '<='); if ($exists && $version_compare) { if ($this->config->get('verbose')) { $this->ui->outputData('Ignoring installed package ' . $reg->parsedPackageNameToString( array('package' => $pf->getPackage(), 'channel' => $pf->getChannel()), true)); } continue; } $otherpackages[] = $param; continue; } $e = $reg->parsePackageName($param, $channel); if (PEAR::isError($e)) { $otherpackages[] = $param; } else { $abstractpackages[] = $e; } } PEAR::staticPopErrorHandling(); // if there are any local package .tgz or remote static url, we can't // filter. The filter only works for abstract packages if (count($abstractpackages) && !isset($options['force'])) { // when not being forced, only do necessary upgrades/installs if (isset($options['upgrade'])) { $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command); } else { $count = count($abstractpackages); foreach ($abstractpackages as $i => $package) { if (isset($package['group'])) { // do not filter out install groups continue; } if ($instreg->packageExists($package['package'], $package['channel'])) { if ($count > 1) { if ($this->config->get('verbose')) { $this->ui->outputData('Ignoring installed package ' . $reg->parsedPackageNameToString($package, true)); } unset($abstractpackages[$i]); } elseif ($count === 1) { // Lets try to upgrade it since it's already installed $options['upgrade'] = true; } } } } $abstractpackages = array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); } elseif (count($abstractpackages)) { $abstractpackages = array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); } $packages = array_merge($abstractpackages, $otherpackages); if (!count($packages)) { $c = ''; if (isset($options['channel'])){ $c .= ' in channel "' . $options['channel'] . '"'; } $this->ui->outputData('Nothing to ' . $command . $c); return true; } $this->downloader = &$this->getDownloader($this->ui, $options, $this->config); $errors = $downloaded = $binaries = array(); $downloaded = &$this->downloader->download($packages); if (PEAR::isError($downloaded)) { return $this->raiseError($downloaded); } $errors = $this->downloader->getErrorMsgs(); if (count($errors)) { $err = array(); $err['data'] = array(); foreach ($errors as $error) { if ($error !== null) { $err['data'][] = array($error); } } if (!empty($err['data'])) { $err['headline'] = 'Install Errors'; $this->ui->outputData($err); } if (!count($downloaded)) { return $this->raiseError("$command failed"); } } $data = array( 'headline' => 'Packages that would be Installed' ); if (isset($options['pretend'])) { foreach ($downloaded as $package) { $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage())); } $this->ui->outputData($data, 'pretend'); return true; } $this->installer->setOptions($options); $this->installer->sortPackagesForInstall($downloaded); if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) { $this->raiseError($err->getMessage()); return true; } $binaries = $extrainfo = array(); foreach ($downloaded as $param) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $info = $this->installer->install($param, $options); PEAR::staticPopErrorHandling(); if (PEAR::isError($info)) { $oldinfo = $info; $pkg = &$param->getPackageFile(); if ($info->getCode() != PEAR_INSTALLER_NOBINARY) { if (!($info = $pkg->installBinary($this->installer))) { return $this->raiseError('ERROR: ' .$oldinfo->getMessage()); } // we just installed a different package than requested, // let's change the param and info so that the rest of this works $param = $info[0]; $info = $info[1]; } } if (!is_array($info)) { return $this->raiseError("$command failed"); } if ($param->getPackageType() == 'extsrc' || $param->getPackageType() == 'extbin' || $param->getPackageType() == 'zendextsrc' || $param->getPackageType() == 'zendextbin' ) { $pkg = &$param->getPackageFile(); if ($instbin = $pkg->getInstalledBinary()) { $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel()); } else { $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel()); } foreach ($instpkg->getFilelist() as $name => $atts) { $pinfo = pathinfo($atts['installed_as']); if (!isset($pinfo['extension']) || in_array($pinfo['extension'], array('c', 'h')) ) { continue; // make sure we don't match php_blah.h } if ((strpos($pinfo['basename'], 'php_') === 0 && $pinfo['extension'] == 'dll') || // most unices $pinfo['extension'] == 'so' || // hp-ux $pinfo['extension'] == 'sl') { $binaries[] = array($atts['installed_as'], $pinfo); break; } } if (count($binaries)) { foreach ($binaries as $pinfo) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType()); PEAR::staticPopErrorHandling(); if (PEAR::isError($ret)) { $extrainfo[] = $ret->getMessage(); if ($param->getPackageType() == 'extsrc' || $param->getPackageType() == 'extbin') { $exttype = 'extension'; $extpath = $pinfo[1]['basename']; } else { $exttype = 'zend_extension'; $extpath = $atts['installed_as']; } $extrainfo[] = 'You should add "' . $exttype . '=' . $extpath . '" to php.ini'; } else { $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() . ' enabled in php.ini'; } } } } if ($this->config->get('verbose') > 0) { $chan = $param->getChannel(); $label = $reg->parsedPackageNameToString( array( 'channel' => $chan, 'package' => $param->getPackage(), 'version' => $param->getVersion(), )); $out = array('data' => "$command ok: $label"); if (isset($info['release_warnings'])) { $out['release_warnings'] = $info['release_warnings']; } $this->ui->outputData($out, $command); if (!isset($options['register-only']) && !isset($options['offline'])) { if ($this->config->isDefinedLayer('ftp')) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $info = $this->installer->ftpInstall($param); PEAR::staticPopErrorHandling(); if (PEAR::isError($info)) { $this->ui->outputData($info->getMessage()); $this->ui->outputData("remote install failed: $label"); } else { $this->ui->outputData("remote install ok: $label"); } } } } $deps = $param->getDeps(); if ($deps) { if (isset($deps['group'])) { $groups = $deps['group']; if (!isset($groups[0])) { $groups = array($groups); } foreach ($groups as $group) { if ($group['attribs']['name'] == 'default') { // default group is always installed, unless the user // explicitly chooses to install another group continue; } $extrainfo[] = $param->getPackage() . ': Optional feature ' . $group['attribs']['name'] . ' available (' . $group['attribs']['hint'] . ')'; } $extrainfo[] = $param->getPackage() . ': To install optional features use "pear install ' . $reg->parsedPackageNameToString( array('package' => $param->getPackage(), 'channel' => $param->getChannel()), true) . '#featurename"'; } } $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel()); // $pkg may be NULL if install is a 'fake' install via --packagingroot if (is_object($pkg)) { $pkg->setConfig($this->config); if ($list = $pkg->listPostinstallScripts()) { $pn = $reg->parsedPackageNameToString(array('channel' => $param->getChannel(), 'package' => $param->getPackage()), true); $extrainfo[] = $pn . ' has post-install scripts:'; foreach ($list as $file) { $extrainfo[] = $file; } $extrainfo[] = $param->getPackage() . ': Use "pear run-scripts ' . $pn . '" to finish setup.'; $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES'; } } } if (count($extrainfo)) { foreach ($extrainfo as $info) { $this->ui->outputData($info); } } return true; } // }}} // {{{ doUpgradeAll() function doUpgradeAll($command, $options, $params) { $reg = &$this->config->getRegistry(); $upgrade = array(); if (isset($options['channel'])) { $channels = array($options['channel']); } else { $channels = $reg->listChannels(); } foreach ($channels as $channel) { if ($channel == '__uri') { continue; } // parse name with channel foreach ($reg->listPackages($channel) as $name) { $upgrade[] = $reg->parsedPackageNameToString(array( 'channel' => $channel, 'package' => $name )); } } $err = $this->doInstall($command, $options, $upgrade); if (PEAR::isError($err)) { $this->ui->outputData($err->getMessage(), $command); } } // }}} // {{{ doUninstall() function doUninstall($command, $options, $params) { if (count($params) < 1) { return $this->raiseError("Please supply the package(s) you want to uninstall"); } if (empty($this->installer)) { $this->installer = &$this->getInstaller($this->ui); } if (isset($options['remoteconfig'])) { $e = $this->config->readFTPConfigFile($options['remoteconfig']); if (!PEAR::isError($e)) { $this->installer->setConfig($this->config); } } $reg = &$this->config->getRegistry(); $newparams = array(); $binaries = array(); $badparams = array(); foreach ($params as $pkg) { $channel = $this->config->get('default_channel'); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $parsed = $reg->parsePackageName($pkg, $channel); PEAR::staticPopErrorHandling(); if (!$parsed || PEAR::isError($parsed)) { $badparams[] = $pkg; continue; } $package = $parsed['package']; $channel = $parsed['channel']; $info = &$reg->getPackage($package, $channel); if ($info === null && ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) { // make sure this isn't a package that has flipped from pear to pecl but // used a package.xml 1.0 $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net'; $info = &$reg->getPackage($package, $testc); if ($info !== null) { $channel = $testc; } } if ($info === null) { $badparams[] = $pkg; } else { $newparams[] = &$info; // check for binary packages (this is an alias for those packages if so) if ($installedbinary = $info->getInstalledBinary()) { $this->ui->log('adding binary package ' . $reg->parsedPackageNameToString(array('channel' => $channel, 'package' => $installedbinary), true)); $newparams[] = &$reg->getPackage($installedbinary, $channel); } // add the contents of a dependency group to the list of installed packages if (isset($parsed['group'])) { $group = $info->getDependencyGroup($parsed['group']); if ($group) { $installed = $reg->getInstalledGroup($group); if ($installed) { foreach ($installed as $i => $p) { $newparams[] = &$installed[$i]; } } } } } } $err = $this->installer->sortPackagesForUninstall($newparams); if (PEAR::isError($err)) { $this->ui->outputData($err->getMessage(), $command); return true; } $params = $newparams; // twist this to use it to check on whether dependent packages are also being uninstalled // for circular dependencies like subpackages $this->installer->setUninstallPackages($newparams); $params = array_merge($params, $badparams); $binaries = array(); foreach ($params as $pkg) { $this->installer->pushErrorHandling(PEAR_ERROR_RETURN); if ($err = $this->installer->uninstall($pkg, $options)) { $this->installer->popErrorHandling(); if (PEAR::isError($err)) { $this->ui->outputData($err->getMessage(), $command); continue; } if ($pkg->getPackageType() == 'extsrc' || $pkg->getPackageType() == 'extbin' || $pkg->getPackageType() == 'zendextsrc' || $pkg->getPackageType() == 'zendextbin') { if ($instbin = $pkg->getInstalledBinary()) { continue; // this will be uninstalled later } foreach ($pkg->getFilelist() as $name => $atts) { $pinfo = pathinfo($atts['installed_as']); if (!isset($pinfo['extension']) || in_array($pinfo['extension'], array('c', 'h'))) { continue; // make sure we don't match php_blah.h } if ((strpos($pinfo['basename'], 'php_') === 0 && $pinfo['extension'] == 'dll') || // most unices $pinfo['extension'] == 'so' || // hp-ux $pinfo['extension'] == 'sl') { $binaries[] = array($atts['installed_as'], $pinfo); break; } } if (count($binaries)) { foreach ($binaries as $pinfo) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType()); PEAR::staticPopErrorHandling(); if (PEAR::isError($ret)) { $extrainfo[] = $ret->getMessage(); if ($pkg->getPackageType() == 'extsrc' || $pkg->getPackageType() == 'extbin') { $exttype = 'extension'; } else { ob_start(); phpinfo(INFO_GENERAL); $info = ob_get_contents(); ob_end_clean(); $debug = function_exists('leak') ? '_debug' : ''; $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; $exttype = 'zend_extension' . $debug . $ts; } $this->ui->outputData('Unable to remove "' . $exttype . '=' . $pinfo[1]['basename'] . '" from php.ini', $command); } else { $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() . ' disabled in php.ini', $command); } } } } $savepkg = $pkg; if ($this->config->get('verbose') > 0) { if (is_object($pkg)) { $pkg = $reg->parsedPackageNameToString($pkg); } $this->ui->outputData("uninstall ok: $pkg", $command); } if (!isset($options['offline']) && is_object($savepkg) && defined('PEAR_REMOTEINSTALL_OK')) { if ($this->config->isDefinedLayer('ftp')) { $this->installer->pushErrorHandling(PEAR_ERROR_RETURN); $info = $this->installer->ftpUninstall($savepkg); $this->installer->popErrorHandling(); if (PEAR::isError($info)) { $this->ui->outputData($info->getMessage()); $this->ui->outputData("remote uninstall failed: $pkg"); } else { $this->ui->outputData("remote uninstall ok: $pkg"); } } } } else { $this->installer->popErrorHandling(); if (!is_object($pkg)) { return $this->raiseError("uninstall failed: $pkg"); } $pkg = $reg->parsedPackageNameToString($pkg); } } return true; } // }}} // }}} // {{{ doBundle() /* (cox) It just downloads and untars the package, does not do any check that the PEAR_Installer::_installFile() does. */ function doBundle($command, $options, $params) { $opts = array( 'force' => true, 'nodeps' => true, 'soft' => true, 'downloadonly' => true ); $downloader = &$this->getDownloader($this->ui, $opts, $this->config); $reg = &$this->config->getRegistry(); if (count($params) < 1) { return $this->raiseError("Please supply the package you want to bundle"); } if (isset($options['destination'])) { if (!is_dir($options['destination'])) { System::mkdir('-p ' . $options['destination']); } $dest = realpath($options['destination']); } else { $pwd = getcwd(); $dir = $pwd . DIRECTORY_SEPARATOR . 'ext'; $dest = is_dir($dir) ? $dir : $pwd; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = $downloader->setDownloadDir($dest); PEAR::staticPopErrorHandling(); if (PEAR::isError($err)) { return PEAR::raiseError('download directory "' . $dest . '" is not writeable.'); } $result = &$downloader->download(array($params[0])); if (PEAR::isError($result)) { return $result; } if (!isset($result[0])) { return $this->raiseError('unable to unpack ' . $params[0]); } $pkgfile = &$result[0]->getPackageFile(); $pkgname = $pkgfile->getName(); $pkgversion = $pkgfile->getVersion(); // Unpacking ------------------------------------------------- $dest .= DIRECTORY_SEPARATOR . $pkgname; $orig = $pkgname . '-' . $pkgversion; $tar = new Archive_Tar($pkgfile->getArchiveFile()); if (!$tar->extractModify($dest, $orig)) { return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile()); } $this->ui->outputData("Package ready at '$dest'"); // }}} } // }}} function doRunScripts($command, $options, $params) { if (!isset($params[0])) { return $this->raiseError('run-scripts expects 1 parameter: a package name'); } $reg = &$this->config->getRegistry(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel')); PEAR::staticPopErrorHandling(); if (PEAR::isError($parsed)) { return $this->raiseError($parsed); } $package = &$reg->getPackage($parsed['package'], $parsed['channel']); if (!is_object($package)) { return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry'); } $package->setConfig($this->config); $package->runPostinstallScripts(); $this->ui->outputData('Install scripts complete', $command); return true; } /** * Given a list of packages, filter out those ones that are already up to date * * @param $packages: packages, in parsed array format ! * @return list of packages that can be upgraded */ function _filterUptodatePackages($packages, $command) { $reg = &$this->config->getRegistry(); $latestReleases = array(); $ret = array(); foreach ($packages as $package) { if (isset($package['group'])) { $ret[] = $package; continue; } $channel = $package['channel']; $name = $package['package']; if (!$reg->packageExists($name, $channel)) { $ret[] = $package; continue; } if (!isset($latestReleases[$channel])) { // fill in cache for this channel $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $this->raiseError($chan); } $base2 = false; $preferred_mirror = $this->config->get('preferred_mirror', null, $channel); if ($chan->supportsREST($preferred_mirror) && ( //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) || ($base = $chan->getBaseURL('REST1.0', $preferred_mirror)) ) ) { $dorest = true; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); if (!isset($package['state'])) { $state = $this->config->get('preferred_state', null, $channel); } else { $state = $package['state']; } if ($dorest) { if ($base2) { $rest = &$this->config->getREST('1.4', array()); $base = $base2; } else { $rest = &$this->config->getREST('1.0', array()); } $installed = array_flip($reg->listPackages($channel)); $latest = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg); } PEAR::staticPopErrorHandling(); if (PEAR::isError($latest)) { $this->ui->outputData('Error getting channel info from ' . $channel . ': ' . $latest->getMessage()); continue; } $latestReleases[$channel] = array_change_key_case($latest); } // check package for latest release $name_lower = strtolower($name); if (isset($latestReleases[$channel][$name_lower])) { // if not set, up to date $inst_version = $reg->packageInfo($name, 'version', $channel); $channel_version = $latestReleases[$channel][$name_lower]['version']; if (version_compare($channel_version, $inst_version, 'le')) { // installed version is up-to-date continue; } // maintain BC if ($command == 'upgrade-all') { $this->ui->outputData(array('data' => 'Will upgrade ' . $reg->parsedPackageNameToString($package)), $command); } $ret[] = $package; } } return $ret; } } PK!X PEAR/Command/Auth.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 * @deprecated since 1.8.0alpha1 */ /** * base class */ require_once 'PEAR/Command/Channels.php'; /** * PEAR commands for login/logout * * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 * @deprecated since 1.8.0alpha1 */ class PEAR_Command_Auth extends PEAR_Command_Channels { var $commands = array( 'login' => array( 'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]', 'shortcut' => 'li', 'function' => 'doLogin', 'options' => array(), 'doc' => ' WARNING: This function is deprecated in favor of using channel-login Log in to a remote channel server. If is not supplied, the default channel is used. To use remote functions in the installer that require any kind of privileges, you need to log in first. The username and password you enter here will be stored in your per-user PEAR configuration (~/.pearrc on Unix-like systems). After logging in, your username and password will be sent along in subsequent operations on the remote server.', ), 'logout' => array( 'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]', 'shortcut' => 'lo', 'function' => 'doLogout', 'options' => array(), 'doc' => ' WARNING: This function is deprecated in favor of using channel-logout Logs out from the remote server. This command does not actually connect to the remote server, it only deletes the stored username and password from your user configuration.', ) ); /** * PEAR_Command_Auth constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } } PK!s6 6 PEAR/Command/Config.xmlnu[ Show All Settings doConfigShow csh c show configuration variables for another channel CHAN [layer] Displays all configuration values. An optional argument may be used to tell which configuration layer to display. Valid configuration layers are "user", "system" and "default". To display configurations for different channels, set the default_channel configuration variable and run config-show again. Show One Setting doConfigGet cg c show configuration variables for another channel CHAN <parameter> [layer] Displays the value of one configuration parameter. The first argument is the name of the parameter, an optional second argument may be used to tell which configuration layer to look in. Valid configuration layers are "user", "system" and "default". If no layer is specified, a value will be picked from the first layer that defines the parameter, in the order just specified. The configuration value will be retrieved for the channel specified by the default_channel configuration variable. Change Setting doConfigSet cs c show configuration variables for another channel CHAN <parameter> <value> [layer] Sets the value of one configuration parameter. The first argument is the name of the parameter, the second argument is the new value. Some parameters are subject to validation, and the command will fail with an error message if the new value does not make sense. An optional third argument may be used to specify in which layer to set the configuration parameter. The default layer is "user". The configuration value will be set for the current channel, which is controlled by the default_channel configuration variable. Show Information About Setting doConfigHelp ch [parameter] Displays help for a configuration parameter. Without arguments it displays help for all configuration parameters. Create a Default configuration file doConfigCreate coc w create a config file for a windows install <root path> <filename> Create a default configuration file with all directory configuration variables set to subdirectories of <root path>, and save it as <filename>. This is useful especially for creating a configuration file for a remote PEAR installation (using the --remoteconfig option of install, upgrade, and uninstall). PK!%FiiPEAR/Command/Test.xmlnu[ Run Regression Tests doRunTests rt r Run tests in child directories, recursively. 4 dirs deep maximum i actual string of settings to pass to php in format " -d setting=blah" SETTINGS l Log test runs/results as they are run q Only display detail for failed tests s Display simple output for all tests p Treat parameters as installed packages from which to run tests u Search parameters for AllTests.php, and use that to run phpunit-based tests If none is found, all .phpt tests will be tried instead. t Output run-tests.log in TAP-compliant format c CGI php executable (needed for tests with POST/GET section) PHPCGI x Generate a code coverage report (requires Xdebug 2.0.0+) [testfile|dir ...] Run regression tests with PHP's regression testing script (run-tests.php). PK!Z h66PEAR/Command/Package.xmlnu[ Build Package doPackage p Z Do not gzip the package file n Print the name of the packaged file. [descfile] [descfile2] Creates a PEAR package from its description file (usually called package.xml). If a second packagefile is passed in, then the packager will check to make sure that one is a package.xml version 1.0, and the other is a package.xml version 2.0. The package.xml version 1.0 will be saved as "package.xml" in the archive, and the other as "package2.xml" in the archive" Validate Package Consistency doPackageValidate pv Run a "cvs diff" for all files in a package doCvsDiff cd q Be quiet Q Be really quiet D Diff against revision of DATE DATE R Diff against tag for package release REL REL r Diff against revision REV REV c Generate context diff u Generate unified diff i Ignore case, consider upper- and lower-case letters equivalent b Ignore changes in amount of white space B Ignore changes that insert or delete blank lines Report only whether the files differ, no details n Don't do anything, just pretend <package.xml> Compares all the files in a package. Without any options, this command will compare the current code with the last checked-in code. Using the -r or -R option you may compare the current code with that of a specific release. Set SVN Release Tag doSvnTag sv q Be quiet F Move (slide) tag if it exists d Remove tag n Don't do anything, just pretend <package.xml> [files...] Sets a SVN tag on all files in a package. Use this command after you have packaged a distribution tarball with the "package" command to tag what revisions of what files were in that release. If need to fix something after running svntag once, but before the tarball is released to the public, use the "slide" option to move the release tag. to include files (such as a second package.xml, or tests not included in the release), pass them as additional parameters. Set CVS Release Tag doCvsTag ct q Be quiet Q Be really quiet F Move (slide) tag if it exists d Remove tag n Don't do anything, just pretend <package.xml> [files...] Sets a CVS tag on all files in a package. Use this command after you have packaged a distribution tarball with the "package" command to tag what revisions of what files were in that release. If need to fix something after running cvstag once, but before the tarball is released to the public, use the "slide" option to move the release tag. to include files (such as a second package.xml, or tests not included in the release), pass them as additional parameters. Show package dependencies doPackageDependencies pd <package-file> or <package.xml> or <install-package-name> List all dependencies the package has. Can take a tgz / tar file, package.xml or a package name of an installed package. Sign a package distribution file doSign si v Display GnuPG output <package-file> Signs a package distribution (.tar or .tgz) file with GnuPG. Builds an RPM spec file from a PEAR package doMakeRPM rpm t Use FILE as RPM spec file template FILE p Use FORMAT as format string for RPM package name, %s is replaced by the PEAR package name, defaults to "PEAR::%s". FORMAT <package-file> Creates an RPM .spec file for wrapping a PEAR package inside an RPM package. Intended to be used from the SPECS directory, with the PEAR package tarball in the SOURCES directory: $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz Wrote RPM spec file PEAR::Net_Geo-1.0.spec $ rpm -bb PEAR::Net_Socket-1.0.spec ... Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm Convert a package.xml 1.0 to package.xml 2.0 format doConvert c2 f do not beautify the filelist. [descfile] [descfile2] Converts a package.xml in 1.0 format into a package.xml in 2.0 format. The new file will be named package2.xml by default, and package.xml will be used as the old file by default. This is not the most intelligent conversion, and should only be used for automated conversion or learning the format. PK!wzzPEAR/Command/Channels.xmlnu[ List Available Channels doList lc List all available channels for installation. Update the Channel List doUpdateAll uc List all installed packages in all channels. Remove a Channel From the List doDelete cde <channel name> Delete a channel from the registry. You may not remove any channel that has installed packages. Add a Channel doAdd ca <channel.xml> Add a private channel to the channel list. Note that all public channels should be synced using "update-channels". Parameter may be either a local file or remote URL to a channel.xml. Update an Existing Channel doUpdate cu f will force download of new channel.xml if an existing channel name is used c will force download of new channel.xml if an existing channel name is used CHANNEL [<channel.xml>|<channel name>] Update a channel in the channel list directly. Note that all public channels can be synced using "update-channels". Parameter may be a local or remote channel.xml, or the name of an existing channel. Retrieve Information on a Channel doInfo ci <package> List the files in an installed package. Specify an alias to a channel name doAlias cha <channel> <alias> Specify a specific alias to use for a channel name. The alias may not be an existing channel name or alias. Initialize a Channel from its server doDiscover di [<channel.xml>|<channel name>] Initialize a channel from its server and create a local channel.xml. If <channel name> is in the format "<username>:<password>@<channel>" then <username> and <password> will be set as the login username/password for <channel>. Use caution when passing the username/password in this way, as it may allow other users on your computer to briefly view your username/ password via the system's process list. Connects and authenticates to remote channel server doLogin cli <channel name> Log in to a remote channel server. If <channel name> is not supplied, the default channel is used. To use remote functions in the installer that require any kind of privileges, you need to log in first. The username and password you enter here will be stored in your per-user PEAR configuration (~/.pearrc on Unix-like systems). After logging in, your username and password will be sent along in subsequent operations on the remote server. Logs out from the remote channel server doLogout clo <channel name> Logs out from a remote channel server. If <channel name> is not supplied, the default channel is used. This command does not actually connect to the remote server, it only deletes the stored username and password from your user configuration. PK!+9 ҜҜPEAR/Command/Package.phpnu[ * @author Martin Jansen * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; /** * PEAR commands for login/logout * * @category pear * @package PEAR * @author Stig Bakken * @author Martin Jansen * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Command_Package extends PEAR_Command_Common { var $commands = array( 'package' => array( 'summary' => 'Build Package', 'function' => 'doPackage', 'shortcut' => 'p', 'options' => array( 'nocompress' => array( 'shortopt' => 'Z', 'doc' => 'Do not gzip the package file' ), 'showname' => array( 'shortopt' => 'n', 'doc' => 'Print the name of the packaged file.', ), ), 'doc' => '[descfile] [descfile2] Creates a PEAR package from its description file (usually called package.xml). If a second packagefile is passed in, then the packager will check to make sure that one is a package.xml version 1.0, and the other is a package.xml version 2.0. The package.xml version 1.0 will be saved as "package.xml" in the archive, and the other as "package2.xml" in the archive" ' ), 'package-validate' => array( 'summary' => 'Validate Package Consistency', 'function' => 'doPackageValidate', 'shortcut' => 'pv', 'options' => array(), 'doc' => ' ', ), 'cvsdiff' => array( 'summary' => 'Run a "cvs diff" for all files in a package', 'function' => 'doCvsDiff', 'shortcut' => 'cd', 'options' => array( 'quiet' => array( 'shortopt' => 'q', 'doc' => 'Be quiet', ), 'reallyquiet' => array( 'shortopt' => 'Q', 'doc' => 'Be really quiet', ), 'date' => array( 'shortopt' => 'D', 'doc' => 'Diff against revision of DATE', 'arg' => 'DATE', ), 'release' => array( 'shortopt' => 'R', 'doc' => 'Diff against tag for package release REL', 'arg' => 'REL', ), 'revision' => array( 'shortopt' => 'r', 'doc' => 'Diff against revision REV', 'arg' => 'REV', ), 'context' => array( 'shortopt' => 'c', 'doc' => 'Generate context diff', ), 'unified' => array( 'shortopt' => 'u', 'doc' => 'Generate unified diff', ), 'ignore-case' => array( 'shortopt' => 'i', 'doc' => 'Ignore case, consider upper- and lower-case letters equivalent', ), 'ignore-whitespace' => array( 'shortopt' => 'b', 'doc' => 'Ignore changes in amount of white space', ), 'ignore-blank-lines' => array( 'shortopt' => 'B', 'doc' => 'Ignore changes that insert or delete blank lines', ), 'brief' => array( 'doc' => 'Report only whether the files differ, no details', ), 'dry-run' => array( 'shortopt' => 'n', 'doc' => 'Don\'t do anything, just pretend', ), ), 'doc' => ' Compares all the files in a package. Without any options, this command will compare the current code with the last checked-in code. Using the -r or -R option you may compare the current code with that of a specific release. ', ), 'svntag' => array( 'summary' => 'Set SVN Release Tag', 'function' => 'doSvnTag', 'shortcut' => 'sv', 'options' => array( 'quiet' => array( 'shortopt' => 'q', 'doc' => 'Be quiet', ), 'slide' => array( 'shortopt' => 'F', 'doc' => 'Move (slide) tag if it exists', ), 'delete' => array( 'shortopt' => 'd', 'doc' => 'Remove tag', ), 'dry-run' => array( 'shortopt' => 'n', 'doc' => 'Don\'t do anything, just pretend', ), ), 'doc' => ' [files...] Sets a SVN tag on all files in a package. Use this command after you have packaged a distribution tarball with the "package" command to tag what revisions of what files were in that release. If need to fix something after running svntag once, but before the tarball is released to the public, use the "slide" option to move the release tag. to include files (such as a second package.xml, or tests not included in the release), pass them as additional parameters. ', ), 'cvstag' => array( 'summary' => 'Set CVS Release Tag', 'function' => 'doCvsTag', 'shortcut' => 'ct', 'options' => array( 'quiet' => array( 'shortopt' => 'q', 'doc' => 'Be quiet', ), 'reallyquiet' => array( 'shortopt' => 'Q', 'doc' => 'Be really quiet', ), 'slide' => array( 'shortopt' => 'F', 'doc' => 'Move (slide) tag if it exists', ), 'delete' => array( 'shortopt' => 'd', 'doc' => 'Remove tag', ), 'dry-run' => array( 'shortopt' => 'n', 'doc' => 'Don\'t do anything, just pretend', ), ), 'doc' => ' [files...] Sets a CVS tag on all files in a package. Use this command after you have packaged a distribution tarball with the "package" command to tag what revisions of what files were in that release. If need to fix something after running cvstag once, but before the tarball is released to the public, use the "slide" option to move the release tag. to include files (such as a second package.xml, or tests not included in the release), pass them as additional parameters. ', ), 'package-dependencies' => array( 'summary' => 'Show package dependencies', 'function' => 'doPackageDependencies', 'shortcut' => 'pd', 'options' => array(), 'doc' => ' or or List all dependencies the package has. Can take a tgz / tar file, package.xml or a package name of an installed package.' ), 'sign' => array( 'summary' => 'Sign a package distribution file', 'function' => 'doSign', 'shortcut' => 'si', 'options' => array( 'verbose' => array( 'shortopt' => 'v', 'doc' => 'Display GnuPG output', ), ), 'doc' => ' Signs a package distribution (.tar or .tgz) file with GnuPG.', ), 'makerpm' => array( 'summary' => 'Builds an RPM spec file from a PEAR package', 'function' => 'doMakeRPM', 'shortcut' => 'rpm', 'options' => array( 'spec-template' => array( 'shortopt' => 't', 'arg' => 'FILE', 'doc' => 'Use FILE as RPM spec file template' ), 'rpm-pkgname' => array( 'shortopt' => 'p', 'arg' => 'FORMAT', 'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced by the PEAR package name, defaults to "PEAR::%s".', ), ), 'doc' => ' Creates an RPM .spec file for wrapping a PEAR package inside an RPM package. Intended to be used from the SPECS directory, with the PEAR package tarball in the SOURCES directory: $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz Wrote RPM spec file PEAR::Net_Geo-1.0.spec $ rpm -bb PEAR::Net_Socket-1.0.spec ... Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm ', ), 'convert' => array( 'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format', 'function' => 'doConvert', 'shortcut' => 'c2', 'options' => array( 'flat' => array( 'shortopt' => 'f', 'doc' => 'do not beautify the filelist.', ), ), 'doc' => '[descfile] [descfile2] Converts a package.xml in 1.0 format into a package.xml in 2.0 format. The new file will be named package2.xml by default, and package.xml will be used as the old file by default. This is not the most intelligent conversion, and should only be used for automated conversion or learning the format. ' ), ); var $output; /** * PEAR_Command_Package constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } function _displayValidationResults($err, $warn, $strict = false) { foreach ($err as $e) { $this->output .= "Error: $e\n"; } foreach ($warn as $w) { $this->output .= "Warning: $w\n"; } $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n", sizeof($err), sizeof($warn)); if ($strict && count($err) > 0) { $this->output .= "Fix these errors and try again."; return false; } return true; } function &getPackager() { if (!class_exists('PEAR_Packager')) { require_once 'PEAR/Packager.php'; } $a = new PEAR_Packager; return $a; } function &getPackageFile($config, $debug = false) { if (!class_exists('PEAR_Common')) { require_once 'PEAR/Common.php'; } if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } $a = new PEAR_PackageFile($config, $debug); $common = new PEAR_Common; $common->ui = $this->ui; $a->setLogger($common); return $a; } function doPackage($command, $options, $params) { $this->output = ''; $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml'; $pkg2 = isset($params[1]) ? $params[1] : null; if (!$pkg2 && !isset($params[0]) && file_exists('package2.xml')) { $pkg2 = 'package2.xml'; } $packager = &$this->getPackager(); $compress = empty($options['nocompress']) ? true : false; $result = $packager->package($pkginfofile, $compress, $pkg2); if (PEAR::isError($result)) { return $this->raiseError($result); } // Don't want output, only the package file name just created if (isset($options['showname'])) { $this->output = $result; } if ($this->output) { $this->ui->outputData($this->output, $command); } return true; } function doPackageValidate($command, $options, $params) { $this->output = ''; if (count($params) < 1) { $params[0] = 'package.xml'; } $obj = &$this->getPackageFile($this->config, $this->_debug); $obj->rawReturn(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL); if (PEAR::isError($info)) { $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL); } else { $archive = $info->getArchiveFile(); $tar = new Archive_Tar($archive); $tar->extract(dirname($info->getPackageFile())); $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR . $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR . basename($info->getPackageFile())); } PEAR::staticPopErrorHandling(); if (PEAR::isError($info)) { return $this->raiseError($info); } $valid = false; if ($info->getPackagexmlVersion() == '2.0') { if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) { $info->flattenFileList(); $valid = $info->validate(PEAR_VALIDATE_PACKAGING); } } else { $valid = $info->validate(PEAR_VALIDATE_PACKAGING); } $err = $warn = array(); if ($errors = $info->getValidationWarnings()) { foreach ($errors as $error) { if ($error['level'] == 'warning') { $warn[] = $error['message']; } else { $err[] = $error['message']; } } } $this->_displayValidationResults($err, $warn); $this->ui->outputData($this->output, $command); return true; } function doSvnTag($command, $options, $params) { $this->output = ''; $_cmd = $command; if (count($params) < 1) { $help = $this->getHelp($command); return $this->raiseError("$command: missing parameter: $help[0]"); } $packageFile = realpath($params[0]); $dir = dirname($packageFile); $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1); $obj = &$this->getPackageFile($this->config, $this->_debug); $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL); if (PEAR::isError($info)) { return $this->raiseError($info); } $err = $warn = array(); if (!$info->validate()) { foreach ($info->getValidationWarnings() as $error) { if ($error['level'] == 'warning') { $warn[] = $error['message']; } else { $err[] = $error['message']; } } } if (!$this->_displayValidationResults($err, $warn, true)) { $this->ui->outputData($this->output, $command); return $this->raiseError('SVN tag failed'); } $version = $info->getVersion(); $package = $info->getName(); $svntag = "$package-$version"; if (isset($options['delete'])) { return $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options); } $path = $this->_svnFindPath($packageFile); // Check if there are any modified files $fp = popen('svn st --xml ' . dirname($packageFile), "r"); $out = ''; while ($line = fgets($fp, 1024)) { $out .= rtrim($line)."\n"; } pclose($fp); if (!isset($options['quiet']) && strpos($out, 'item="modified"')) { $params = array(array( 'name' => 'modified', 'type' => 'yesno', 'default' => 'no', 'prompt' => 'You have files in your SVN checkout (' . $path['from'] . ') that have been modified but not committed, do you still want to tag ' . $version . '?', )); $answers = $this->ui->confirmDialog($params); if (!in_array($answers['modified'], array('y', 'yes', 'on', '1'))) { return true; } } if (isset($options['slide'])) { $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options); } // Check if tag already exists $releaseTag = $path['local']['base'] . 'tags' . DIRECTORY_SEPARATOR . $svntag; $existsCommand = 'svn ls ' . $path['base'] . 'tags/'; $fp = popen($existsCommand, "r"); $out = ''; while ($line = fgets($fp, 1024)) { $out .= rtrim($line)."\n"; } pclose($fp); if (in_array($svntag . DIRECTORY_SEPARATOR, explode("\n", $out))) { $this->ui->outputData($this->output, $command); return $this->raiseError('SVN tag ' . $svntag . ' for ' . $package . ' already exists.'); } elseif (file_exists($path['local']['base'] . 'tags') === false) { return $this->raiseError('Can not locate the tags directory at ' . $path['local']['base'] . 'tags'); } elseif (is_writeable($path['local']['base'] . 'tags') === false) { return $this->raiseError('Can not write to the tag directory at ' . $path['local']['base'] . 'tags'); } else { $makeCommand = 'svn mkdir ' . $releaseTag; $this->output .= "+ $makeCommand\n"; if (empty($options['dry-run'])) { // We need to create the tag dir. $fp = popen($makeCommand, "r"); $out = ''; while ($line = fgets($fp, 1024)) { $out .= rtrim($line)."\n"; } pclose($fp); $this->output .= "$out\n"; } } $command = 'svn'; if (isset($options['quiet'])) { $command .= ' -q'; } $command .= ' copy --parents '; $dir = dirname($packageFile); $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1); $files = array_keys($info->getFilelist()); if (!in_array(basename($packageFile), $files)) { $files[] = basename($packageFile); } array_shift($params); if (count($params)) { // add in additional files to be tagged (package files and such) $files = array_merge($files, $params); } $commands = array(); foreach ($files as $file) { if (!file_exists($file)) { $file = $dir . DIRECTORY_SEPARATOR . $file; } $commands[] = $command . ' ' . escapeshellarg($file) . ' ' . escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file); } $this->output .= implode("\n", $commands) . "\n"; if (empty($options['dry-run'])) { foreach ($commands as $command) { $fp = popen($command, "r"); while ($line = fgets($fp, 1024)) { $this->output .= rtrim($line)."\n"; } pclose($fp); } } $command = 'svn ci -m "Tagging the ' . $version . ' release" ' . $releaseTag . "\n"; $this->output .= "+ $command\n"; if (empty($options['dry-run'])) { $fp = popen($command, "r"); while ($line = fgets($fp, 1024)) { $this->output .= rtrim($line)."\n"; } pclose($fp); } $this->ui->outputData($this->output, $_cmd); return true; } function _svnFindPath($file) { $xml = ''; $command = "svn info --xml $file"; $fp = popen($command, "r"); while ($line = fgets($fp, 1024)) { $xml .= rtrim($line)."\n"; } pclose($fp); $url_tag = strpos($xml, ''); $url = substr($xml, $url_tag + 5, strpos($xml, '', $url_tag + 5) - ($url_tag + 5)); $path = array(); $path['from'] = substr($url, 0, strrpos($url, '/')); $path['base'] = substr($path['from'], 0, strrpos($path['from'], '/') + 1); // Figure out the local paths - see http://pear.php.net/bugs/17463 $pos = strpos($file, DIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR); if ($pos === false) { $pos = strpos($file, DIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR); } $path['local']['base'] = substr($file, 0, $pos + 1); return $path; } function _svnRemoveTag($version, $package, $tag, $packageFile, $options) { $command = 'svn'; if (isset($options['quiet'])) { $command .= ' -q'; } $command .= ' remove'; $command .= ' -m "Removing tag for the ' . $version . ' release."'; $path = $this->_svnFindPath($packageFile); $command .= ' ' . $path['base'] . 'tags/' . $tag; if ($this->config->get('verbose') > 1) { $this->output .= "+ $command\n"; } $this->output .= "+ $command\n"; if (empty($options['dry-run'])) { $fp = popen($command, "r"); while ($line = fgets($fp, 1024)) { $this->output .= rtrim($line)."\n"; } pclose($fp); } $this->ui->outputData($this->output, $command); return true; } function doCvsTag($command, $options, $params) { $this->output = ''; $_cmd = $command; if (count($params) < 1) { $help = $this->getHelp($command); return $this->raiseError("$command: missing parameter: $help[0]"); } $packageFile = realpath($params[0]); $obj = &$this->getPackageFile($this->config, $this->_debug); $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL); if (PEAR::isError($info)) { return $this->raiseError($info); } $err = $warn = array(); if (!$info->validate()) { foreach ($info->getValidationWarnings() as $error) { if ($error['level'] == 'warning') { $warn[] = $error['message']; } else { $err[] = $error['message']; } } } if (!$this->_displayValidationResults($err, $warn, true)) { $this->ui->outputData($this->output, $command); return $this->raiseError('CVS tag failed'); } $version = $info->getVersion(); $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version); $cvstag = "RELEASE_$cvsversion"; $files = array_keys($info->getFilelist()); $command = 'cvs'; if (isset($options['quiet'])) { $command .= ' -q'; } if (isset($options['reallyquiet'])) { $command .= ' -Q'; } $command .= ' tag'; if (isset($options['slide'])) { $command .= ' -F'; } if (isset($options['delete'])) { $command .= ' -d'; } $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]); array_shift($params); if (count($params)) { // add in additional files to be tagged $files = array_merge($files, $params); } $dir = dirname($packageFile); $dir = substr($dir, strrpos($dir, '/') + 1); foreach ($files as $file) { if (!file_exists($file)) { $file = $dir . DIRECTORY_SEPARATOR . $file; } $command .= ' ' . escapeshellarg($file); } if ($this->config->get('verbose') > 1) { $this->output .= "+ $command\n"; } $this->output .= "+ $command\n"; if (empty($options['dry-run'])) { $fp = popen($command, "r"); while ($line = fgets($fp, 1024)) { $this->output .= rtrim($line)."\n"; } pclose($fp); } $this->ui->outputData($this->output, $_cmd); return true; } function doCvsDiff($command, $options, $params) { $this->output = ''; if (sizeof($params) < 1) { $help = $this->getHelp($command); return $this->raiseError("$command: missing parameter: $help[0]"); } $file = realpath($params[0]); $obj = &$this->getPackageFile($this->config, $this->_debug); $info = $obj->fromAnyFile($file, PEAR_VALIDATE_NORMAL); if (PEAR::isError($info)) { return $this->raiseError($info); } $err = $warn = array(); if (!$info->validate()) { foreach ($info->getValidationWarnings() as $error) { if ($error['level'] == 'warning') { $warn[] = $error['message']; } else { $err[] = $error['message']; } } } if (!$this->_displayValidationResults($err, $warn, true)) { $this->ui->outputData($this->output, $command); return $this->raiseError('CVS diff failed'); } $info1 = $info->getFilelist(); $files = $info1; $cmd = "cvs"; if (isset($options['quiet'])) { $cmd .= ' -q'; unset($options['quiet']); } if (isset($options['reallyquiet'])) { $cmd .= ' -Q'; unset($options['reallyquiet']); } if (isset($options['release'])) { $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']); $cvstag = "RELEASE_$cvsversion"; $options['revision'] = $cvstag; unset($options['release']); } $execute = true; if (isset($options['dry-run'])) { $execute = false; unset($options['dry-run']); } $cmd .= ' diff'; // the rest of the options are passed right on to "cvs diff" foreach ($options as $option => $optarg) { $arg = $short = false; if (isset($this->commands[$command]['options'][$option])) { $arg = $this->commands[$command]['options'][$option]['arg']; $short = $this->commands[$command]['options'][$option]['shortopt']; } $cmd .= $short ? " -$short" : " --$option"; if ($arg && $optarg) { $cmd .= ($short ? '' : '=') . escapeshellarg($optarg); } } foreach ($files as $file) { $cmd .= ' ' . escapeshellarg($file['name']); } if ($this->config->get('verbose') > 1) { $this->output .= "+ $cmd\n"; } if ($execute) { $fp = popen($cmd, "r"); while ($line = fgets($fp, 1024)) { $this->output .= rtrim($line)."\n"; } pclose($fp); } $this->ui->outputData($this->output, $command); return true; } function doPackageDependencies($command, $options, $params) { // $params[0] -> the PEAR package to list its information if (count($params) !== 1) { return $this->raiseError("bad parameter(s), try \"help $command\""); } $obj = &$this->getPackageFile($this->config, $this->_debug); if (is_file($params[0]) || strpos($params[0], '.xml') > 0) { $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); } else { $reg = $this->config->getRegistry(); $info = $obj->fromArray($reg->packageInfo($params[0])); } if (PEAR::isError($info)) { return $this->raiseError($info); } $deps = $info->getDeps(); if (is_array($deps)) { if ($info->getPackagexmlVersion() == '1.0') { $data = array( 'caption' => 'Dependencies for pear/' . $info->getPackage(), 'border' => true, 'headline' => array("Required?", "Type", "Name", "Relation", "Version"), ); foreach ($deps as $d) { if (isset($d['optional'])) { if ($d['optional'] == 'yes') { $req = 'No'; } else { $req = 'Yes'; } } else { $req = 'Yes'; } if (isset($this->_deps_rel_trans[$d['rel']])) { $rel = $this->_deps_rel_trans[$d['rel']]; } else { $rel = $d['rel']; } if (isset($this->_deps_type_trans[$d['type']])) { $type = ucfirst($this->_deps_type_trans[$d['type']]); } else { $type = $d['type']; } if (isset($d['name'])) { $name = $d['name']; } else { $name = ''; } if (isset($d['version'])) { $version = $d['version']; } else { $version = ''; } $data['data'][] = array($req, $type, $name, $rel, $version); } } else { // package.xml 2.0 dependencies display require_once 'PEAR/Dependency2.php'; $deps = $info->getDependencies(); $reg = &$this->config->getRegistry(); if (is_array($deps)) { $data = array( 'caption' => 'Dependencies for ' . $info->getPackage(), 'border' => true, 'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'), ); foreach ($deps as $type => $subd) { $req = ($type == 'required') ? 'Yes' : 'No'; if ($type == 'group' && isset($subd['attribs']['name'])) { $group = $subd['attribs']['name']; } else { $group = ''; } if (!isset($subd[0])) { $subd = array($subd); } foreach ($subd as $groupa) { foreach ($groupa as $deptype => $depinfo) { if ($deptype == 'attribs') { continue; } if ($deptype == 'pearinstaller') { $deptype = 'pear Installer'; } if (!isset($depinfo[0])) { $depinfo = array($depinfo); } foreach ($depinfo as $inf) { $name = ''; if (isset($inf['channel'])) { $alias = $reg->channelAlias($inf['channel']); if (!$alias) { $alias = '(channel?) ' .$inf['channel']; } $name = $alias . '/'; } if (isset($inf['name'])) { $name .= $inf['name']; } elseif (isset($inf['pattern'])) { $name .= $inf['pattern']; } else { $name .= ''; } if (isset($inf['uri'])) { $name .= ' [' . $inf['uri'] . ']'; } if (isset($inf['conflicts'])) { $ver = 'conflicts'; } else { $ver = PEAR_Dependency2::_getExtraString($inf); } $data['data'][] = array($req, ucfirst($deptype), $name, $ver, $group); } } } } } } $this->ui->outputData($data, $command); return true; } // Fallback $this->ui->outputData("This package does not have any dependencies.", $command); } function doSign($command, $options, $params) { // should move most of this code into PEAR_Packager // so it'll be easy to implement "pear package --sign" if (count($params) !== 1) { return $this->raiseError("bad parameter(s), try \"help $command\""); } require_once 'System.php'; require_once 'Archive/Tar.php'; if (!file_exists($params[0])) { return $this->raiseError("file does not exist: $params[0]"); } $obj = $this->getPackageFile($this->config, $this->_debug); $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL); if (PEAR::isError($info)) { return $this->raiseError($info); } $tar = new Archive_Tar($params[0]); $tmpdir = $this->config->get('temp_dir'); $tmpdir = System::mktemp(' -t "' . $tmpdir . '" -d pearsign'); if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) { return $this->raiseError("failed to extract tar file"); } if (file_exists("$tmpdir/package.sig")) { return $this->raiseError("package already signed"); } $packagexml = 'package.xml'; if (file_exists("$tmpdir/package2.xml")) { $packagexml = 'package2.xml'; } if (file_exists("$tmpdir/package.sig")) { unlink("$tmpdir/package.sig"); } if (!file_exists("$tmpdir/$packagexml")) { return $this->raiseError("Extracted file $tmpdir/$packagexml not found."); } $input = $this->ui->userDialog($command, array('GnuPG Passphrase'), array('password')); if (!isset($input[0])) { //use empty passphrase $input[0] = ''; } $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null'; $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w"); if (!$gpg) { return $this->raiseError("gpg command failed"); } fwrite($gpg, "$input[0]\n"); if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) { return $this->raiseError("gpg sign failed"); } if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) { return $this->raiseError('failed adding signature to file'); } $this->ui->outputData("Package signed.", $command); return true; } /** * For unit testing purposes */ function &getInstaller(&$ui) { if (!class_exists('PEAR_Installer')) { require_once 'PEAR/Installer.php'; } $a = new PEAR_Installer($ui); return $a; } /** * For unit testing purposes */ function &getCommandPackaging(&$ui, &$config) { if (!class_exists('PEAR_Command_Packaging')) { if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) { fclose($fp); include_once 'PEAR/Command/Packaging.php'; } } if (class_exists('PEAR_Command_Packaging')) { $a = new PEAR_Command_Packaging($ui, $config); } else { $a = null; } return $a; } function doMakeRPM($command, $options, $params) { // Check to see if PEAR_Command_Packaging is installed, and // transparently switch to use the "make-rpm-spec" command from it // instead, if it does. Otherwise, continue to use the old version // of "makerpm" supplied with this package (PEAR). $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config); if ($packaging_cmd !== null) { $this->ui->outputData('PEAR_Command_Packaging is installed; using '. 'newer "make-rpm-spec" command instead'); return $packaging_cmd->run('make-rpm-spec', $options, $params); } $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '. 'improved version is available via "pear make-rpm-spec", which '. 'is available by installing PEAR_Command_Packaging'); return true; } function doConvert($command, $options, $params) { $packagexml = isset($params[0]) ? $params[0] : 'package.xml'; $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) . DIRECTORY_SEPARATOR . 'package2.xml'; $pkg = &$this->getPackageFile($this->config, $this->_debug); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL); PEAR::staticPopErrorHandling(); if (PEAR::isError($pf)) { if (is_array($pf->getUserInfo())) { foreach ($pf->getUserInfo() as $warning) { $this->ui->outputData($warning['message']); } } return $this->raiseError($pf); } if (is_a($pf, 'PEAR_PackageFile_v2')) { $this->ui->outputData($packagexml . ' is already a package.xml version 2.0'); return true; } $gen = &$pf->getDefaultGenerator(); $newpf = &$gen->toV2(); $newpf->setPackagefile($newpackagexml); $gen = &$newpf->getDefaultGenerator(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL); $saved = $gen->toPackageFile(dirname($newpackagexml), $state, basename($newpackagexml)); PEAR::staticPopErrorHandling(); if (PEAR::isError($saved)) { if (is_array($saved->getUserInfo())) { foreach ($saved->getUserInfo() as $warning) { $this->ui->outputData($warning['message']); } } $this->ui->outputData($saved->getMessage()); return true; } $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"'); return true; } } PK! uPEAR/Command/Build.xmlnu[ Build an Extension From C Source doBuild b D OPTION1=VALUE[ OPTION2=VALUE] [package.xml] Builds one or more extensions contained in a package. PK!PEAR/Command/Mirror.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.2.0 */ /** * base class */ require_once 'PEAR/Command/Common.php'; /** * PEAR commands for providing file mirrors * * @category pear * @package PEAR * @author Alexander Merz * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.2.0 */ class PEAR_Command_Mirror extends PEAR_Command_Common { var $commands = array( 'download-all' => array( 'summary' => 'Downloads each available package from the default channel', 'function' => 'doDownloadAll', 'shortcut' => 'da', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'specify a channel other than the default channel', 'arg' => 'CHAN', ), ), 'doc' => ' Requests a list of available packages from the default channel ({config default_channel}) and downloads them to current working directory. Note: only packages within preferred_state ({config preferred_state}) will be downloaded' ), ); /** * PEAR_Command_Mirror constructor. * * @access public * @param object PEAR_Frontend a reference to an frontend * @param object PEAR_Config a reference to the configuration data */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } /** * For unit-testing */ function &factory($a) { $a = &PEAR_Command::factory($a, $this->config); return $a; } /** * retrieves a list of avaible Packages from master server * and downloads them * * @access public * @param string $command the command * @param array $options the command options before the command * @param array $params the stuff after the command name * @return bool true if successful * @throw PEAR_Error */ function doDownloadAll($command, $options, $params) { $savechannel = $this->config->get('default_channel'); $reg = &$this->config->getRegistry(); $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); if (!$reg->channelExists($channel)) { $this->config->set('default_channel', $savechannel); return $this->raiseError('Channel "' . $channel . '" does not exist'); } $this->config->set('default_channel', $channel); $this->ui->outputData('Using Channel ' . $this->config->get('default_channel')); $chan = $reg->getChannel($channel); if (PEAR::isError($chan)) { return $this->raiseError($chan); } if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); $remoteInfo = array_flip($rest->listPackages($base, $channel)); } if (PEAR::isError($remoteInfo)) { return $remoteInfo; } $cmd = &$this->factory("download"); if (PEAR::isError($cmd)) { return $cmd; } $this->ui->outputData('Using Preferred State of ' . $this->config->get('preferred_state')); $this->ui->outputData('Gathering release information, please wait...'); /** * Error handling not necessary, because already done by * the download command */ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo)); PEAR::staticPopErrorHandling(); $this->config->set('default_channel', $savechannel); if (PEAR::isError($err)) { $this->ui->outputData($err->getMessage()); } return true; } } PK!,_h/h/PEAR/Command/Test.phpnu[ * @author Martin Jansen * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; /** * PEAR commands for login/logout * * @category pear * @package PEAR * @author Stig Bakken * @author Martin Jansen * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Command_Test extends PEAR_Command_Common { var $commands = array( 'run-tests' => array( 'summary' => 'Run Regression Tests', 'function' => 'doRunTests', 'shortcut' => 'rt', 'options' => array( 'recur' => array( 'shortopt' => 'r', 'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum', ), 'ini' => array( 'shortopt' => 'i', 'doc' => 'actual string of settings to pass to php in format " -d setting=blah"', 'arg' => 'SETTINGS' ), 'realtimelog' => array( 'shortopt' => 'l', 'doc' => 'Log test runs/results as they are run', ), 'quiet' => array( 'shortopt' => 'q', 'doc' => 'Only display detail for failed tests', ), 'simple' => array( 'shortopt' => 's', 'doc' => 'Display simple output for all tests', ), 'package' => array( 'shortopt' => 'p', 'doc' => 'Treat parameters as installed packages from which to run tests', ), 'phpunit' => array( 'shortopt' => 'u', 'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests If none is found, all .phpt tests will be tried instead.', ), 'tapoutput' => array( 'shortopt' => 't', 'doc' => 'Output run-tests.log in TAP-compliant format', ), 'cgi' => array( 'shortopt' => 'c', 'doc' => 'CGI php executable (needed for tests with POST/GET section)', 'arg' => 'PHPCGI', ), 'coverage' => array( 'shortopt' => 'x', 'doc' => 'Generate a code coverage report (requires Xdebug 2.0.0+)', ), 'showdiff' => array( 'shortopt' => 'd', 'doc' => 'Output diff on test failure', ), ), 'doc' => '[testfile|dir ...] Run regression tests with PHP\'s regression testing script (run-tests.php).', ), ); var $output; /** * PEAR_Command_Test constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } function doRunTests($command, $options, $params) { if (isset($options['phpunit']) && isset($options['tapoutput'])) { return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time'); } require_once 'PEAR/Common.php'; require_once 'System.php'; $log = new PEAR_Common; $log->ui = &$this->ui; // slightly hacky, but it will work $tests = array(); $depth = isset($options['recur']) ? 14 : 1; if (!count($params)) { $params[] = '.'; } if (isset($options['package'])) { $oldparams = $params; $params = array(); $reg = &$this->config->getRegistry(); foreach ($oldparams as $param) { $pname = $reg->parsePackageName($param, $this->config->get('default_channel')); if (PEAR::isError($pname)) { return $this->raiseError($pname); } $package = &$reg->getPackage($pname['package'], $pname['channel']); if (!$package) { return PEAR::raiseError('Unknown package "' . $reg->parsedPackageNameToString($pname) . '"'); } $filelist = $package->getFilelist(); foreach ($filelist as $name => $atts) { if (isset($atts['role']) && $atts['role'] != 'test') { continue; } if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) { $params[] = $atts['installed_as']; continue; } elseif (!preg_match('/\.phpt\\z/', $name)) { continue; } $params[] = $atts['installed_as']; } } } foreach ($params as $p) { if (is_dir($p)) { if (isset($options['phpunit'])) { $dir = System::find(array($p, '-type', 'f', '-maxdepth', $depth, '-name', 'AllTests.php')); if (count($dir)) { foreach ($dir as $p) { $p = realpath($p); if (!count($tests) || (count($tests) && strlen($p) < strlen($tests[0]))) { // this is in a higher-level directory, use this one instead. $tests = array($p); } } } continue; } $args = array($p, '-type', 'f', '-name', '*.phpt'); } else { if (isset($options['phpunit'])) { if (preg_match('/AllTests\.php\\z/i', $p)) { $p = realpath($p); if (!count($tests) || (count($tests) && strlen($p) < strlen($tests[0]))) { // this is in a higher-level directory, use this one instead. $tests = array($p); } } continue; } if (file_exists($p) && preg_match('/\.phpt$/', $p)) { $tests[] = $p; continue; } if (!preg_match('/\.phpt\\z/', $p)) { $p .= '.phpt'; } $args = array(dirname($p), '-type', 'f', '-name', $p); } if (!isset($options['recur'])) { $args[] = '-maxdepth'; $args[] = 1; } $dir = System::find($args); $tests = array_merge($tests, $dir); } $ini_settings = ''; if (isset($options['ini'])) { $ini_settings .= $options['ini']; } if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) { $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}"; } if ($ini_settings) { $this->ui->outputData('Using INI settings: "' . $ini_settings . '"'); } $skipped = $passed = $failed = array(); $tests_count = count($tests); $this->ui->outputData('Running ' . $tests_count . ' tests', $command); $start = time(); if (isset($options['realtimelog']) && file_exists('run-tests.log')) { unlink('run-tests.log'); } if (isset($options['tapoutput'])) { $tap = '1..' . $tests_count . "\n"; } require_once 'PEAR/RunTest.php'; $run = new PEAR_RunTest($log, $options); $run->tests_count = $tests_count; if (isset($options['coverage']) && extension_loaded('xdebug')){ $run->xdebug_loaded = true; } else { $run->xdebug_loaded = false; } $j = $i = 1; foreach ($tests as $t) { if (isset($options['realtimelog'])) { $fp = @fopen('run-tests.log', 'a'); if ($fp) { fwrite($fp, "Running test [$i / $tests_count] $t..."); fclose($fp); } } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); if (isset($options['phpunit'])) { $result = $run->runPHPUnit($t, $ini_settings); } else { $result = $run->run($t, $ini_settings, $j); } PEAR::staticPopErrorHandling(); if (PEAR::isError($result)) { $this->ui->log($result->getMessage()); continue; } if (isset($options['tapoutput'])) { $tap .= $result[0] . ' ' . $i . $result[1] . "\n"; continue; } if (isset($options['realtimelog'])) { $fp = @fopen('run-tests.log', 'a'); if ($fp) { fwrite($fp, "$result\n"); fclose($fp); } } if ($result == 'FAILED') { $failed[] = $t; } if ($result == 'PASSED') { $passed[] = $t; } if ($result == 'SKIPPED') { $skipped[] = $t; } $j++; } $total = date('i:s', time() - $start); if (isset($options['tapoutput'])) { $fp = @fopen('run-tests.log', 'w'); if ($fp) { fwrite($fp, $tap, strlen($tap)); fclose($fp); $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') . '"', $command); } } else { if (count($failed)) { $output = "TOTAL TIME: $total\n"; $output .= count($passed) . " PASSED TESTS\n"; $output .= count($skipped) . " SKIPPED TESTS\n"; $output .= count($failed) . " FAILED TESTS:\n"; foreach ($failed as $failure) { $output .= $failure . "\n"; } $mode = isset($options['realtimelog']) ? 'a' : 'w'; $fp = @fopen('run-tests.log', $mode); if ($fp) { fwrite($fp, $output, strlen($output)); fclose($fp); $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command); } } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) { @unlink('run-tests.log'); } } $this->ui->outputData('TOTAL TIME: ' . $total); $this->ui->outputData(count($passed) . ' PASSED TESTS', $command); $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command); if (count($failed)) { $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command); foreach ($failed as $failure) { $this->ui->outputData($failure, $command); } } if (count($failed) == 0) { return true; } return $this->raiseError('Some tests failed'); } } PK!%sp  PEAR/Command/Common.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR.php'; /** * PEAR commands base class * * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Command_Common extends PEAR { /** * PEAR_Config object used to pass user system and configuration * on when executing commands * * @var PEAR_Config */ var $config; /** * @var PEAR_Registry * @access protected */ var $_registry; /** * User Interface object, for all interaction with the user. * @var object */ var $ui; var $_deps_rel_trans = array( 'lt' => '<', 'le' => '<=', 'eq' => '=', 'ne' => '!=', 'gt' => '>', 'ge' => '>=', 'has' => '==' ); var $_deps_type_trans = array( 'pkg' => 'package', 'ext' => 'extension', 'php' => 'PHP', 'prog' => 'external program', 'ldlib' => 'external library for linking', 'rtlib' => 'external runtime library', 'os' => 'operating system', 'websrv' => 'web server', 'sapi' => 'SAPI backend' ); /** * PEAR_Command_Common constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct(); $this->config = &$config; $this->ui = &$ui; } /** * Return a list of all the commands defined by this class. * @return array list of commands * @access public */ function getCommands() { $ret = array(); foreach (array_keys($this->commands) as $command) { $ret[$command] = $this->commands[$command]['summary']; } return $ret; } /** * Return a list of all the command shortcuts defined by this class. * @return array shortcut => command * @access public */ function getShortcuts() { $ret = array(); foreach (array_keys($this->commands) as $command) { if (isset($this->commands[$command]['shortcut'])) { $ret[$this->commands[$command]['shortcut']] = $command; } } return $ret; } function getOptions($command) { $shortcuts = $this->getShortcuts(); if (isset($shortcuts[$command])) { $command = $shortcuts[$command]; } if (isset($this->commands[$command]) && isset($this->commands[$command]['options'])) { return $this->commands[$command]['options']; } return null; } function getGetoptArgs($command, &$short_args, &$long_args) { $short_args = ''; $long_args = array(); if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) { return; } reset($this->commands[$command]['options']); foreach ($this->commands[$command]['options'] as $option => $info) { $larg = $sarg = ''; if (isset($info['arg'])) { if ($info['arg'][0] == '(') { $larg = '=='; $sarg = '::'; $arg = substr($info['arg'], 1, -1); } else { $larg = '='; $sarg = ':'; $arg = $info['arg']; } } if (isset($info['shortopt'])) { $short_args .= $info['shortopt'] . $sarg; } $long_args[] = $option . $larg; } } /** * Returns the help message for the given command * * @param string $command The command * @return mixed A fail string if the command does not have help or * a two elements array containing [0]=>help string, * [1]=> help string for the accepted cmd args */ function getHelp($command) { $config = &PEAR_Config::singleton(); if (!isset($this->commands[$command])) { return "No such command \"$command\""; } $help = null; if (isset($this->commands[$command]['doc'])) { $help = $this->commands[$command]['doc']; } if (empty($help)) { // XXX (cox) Fallback to summary if there is no doc (show both?) if (!isset($this->commands[$command]['summary'])) { return "No help for command \"$command\""; } $help = $this->commands[$command]['summary']; } if (preg_match_all('/{config\s+([^\}]+)}/', $help, $matches)) { foreach($matches[0] as $k => $v) { $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help); } } return array($help, $this->getHelpArgs($command)); } /** * Returns the help for the accepted arguments of a command * * @param string $command * @return string The help string */ function getHelpArgs($command) { if (isset($this->commands[$command]['options']) && count($this->commands[$command]['options'])) { $help = "Options:\n"; foreach ($this->commands[$command]['options'] as $k => $v) { if (isset($v['arg'])) { if ($v['arg'][0] == '(') { $arg = substr($v['arg'], 1, -1); $sapp = " [$arg]"; $lapp = "[=$arg]"; } else { $sapp = " $v[arg]"; $lapp = "=$v[arg]"; } } else { $sapp = $lapp = ""; } if (isset($v['shortopt'])) { $s = $v['shortopt']; $help .= " -$s$sapp, --$k$lapp\n"; } else { $help .= " --$k$lapp\n"; } $p = " "; $doc = rtrim(str_replace("\n", "\n$p", $v['doc'])); $help .= " $doc\n"; } return $help; } return null; } function run($command, $options, $params) { if (empty($this->commands[$command]['function'])) { // look for shortcuts foreach (array_keys($this->commands) as $cmd) { if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) { if (empty($this->commands[$cmd]['function'])) { return $this->raiseError("unknown command `$command'"); } else { $func = $this->commands[$cmd]['function']; } $command = $cmd; //$command = $this->commands[$cmd]['function']; break; } } } else { $func = $this->commands[$command]['function']; } return $this->$func($command, $options, $params); } } PK!0(;rʹʹPEAR/Command/Registry.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; /** * PEAR commands for registry manipulation * * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Command_Registry extends PEAR_Command_Common { var $commands = array( 'list' => array( 'summary' => 'List Installed Packages In The Default Channel', 'function' => 'doList', 'shortcut' => 'l', 'options' => array( 'channel' => array( 'shortopt' => 'c', 'doc' => 'list installed packages from this channel', 'arg' => 'CHAN', ), 'allchannels' => array( 'shortopt' => 'a', 'doc' => 'list installed packages from all channels', ), 'channelinfo' => array( 'shortopt' => 'i', 'doc' => 'output fully channel-aware data, even on failure', ), ), 'doc' => ' If invoked without parameters, this command lists the PEAR packages installed in your php_dir ({config php_dir}). With a parameter, it lists the files in a package. ', ), 'list-files' => array( 'summary' => 'List Files In Installed Package', 'function' => 'doFileList', 'shortcut' => 'fl', 'options' => array(), 'doc' => ' List the files in an installed package. ' ), 'shell-test' => array( 'summary' => 'Shell Script Test', 'function' => 'doShellTest', 'shortcut' => 'st', 'options' => array(), 'doc' => ' [[relation] version] Tests if a package is installed in the system. Will exit(1) if it is not. The version comparison operator. One of: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne The version to compare with '), 'info' => array( 'summary' => 'Display information about a package', 'function' => 'doInfo', 'shortcut' => 'in', 'options' => array(), 'doc' => ' Displays information about a package. The package argument may be a local package file, an URL to a package file, or the name of an installed package.' ) ); /** * PEAR_Command_Registry constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } function _sortinfo($a, $b) { $apackage = isset($a['package']) ? $a['package'] : $a['name']; $bpackage = isset($b['package']) ? $b['package'] : $b['name']; return strcmp($apackage, $bpackage); } function doList($command, $options, $params) { $reg = &$this->config->getRegistry(); $channelinfo = isset($options['channelinfo']); if (isset($options['allchannels']) && !$channelinfo) { return $this->doListAll($command, array(), $params); } if (isset($options['allchannels']) && $channelinfo) { // allchannels with $channelinfo unset($options['allchannels']); $channels = $reg->getChannels(); $errors = array(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); foreach ($channels as $channel) { $options['channel'] = $channel->getName(); $ret = $this->doList($command, $options, $params); if (PEAR::isError($ret)) { $errors[] = $ret; } } PEAR::staticPopErrorHandling(); if (count($errors)) { // for now, only give first error return PEAR::raiseError($errors[0]); } return true; } if (count($params) === 1) { return $this->doFileList($command, $options, $params); } if (isset($options['channel'])) { if (!$reg->channelExists($options['channel'])) { return $this->raiseError('Channel "' . $options['channel'] .'" does not exist'); } $channel = $reg->channelName($options['channel']); } else { $channel = $this->config->get('default_channel'); } $installed = $reg->packageInfo(null, null, $channel); usort($installed, array(&$this, '_sortinfo')); $data = array( 'caption' => 'Installed packages, channel ' . $channel . ':', 'border' => true, 'headline' => array('Package', 'Version', 'State'), 'channel' => $channel, ); if ($channelinfo) { $data['headline'] = array('Channel', 'Package', 'Version', 'State'); } if (count($installed) && !isset($data['data'])) { $data['data'] = array(); } foreach ($installed as $package) { $pobj = $reg->getPackage(isset($package['package']) ? $package['package'] : $package['name'], $channel); if ($channelinfo) { $packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(), $pobj->getState() ? $pobj->getState() : null); } else { $packageinfo = array($pobj->getPackage(), $pobj->getVersion(), $pobj->getState() ? $pobj->getState() : null); } $data['data'][] = $packageinfo; } if (count($installed) === 0) { if (!$channelinfo) { $data = '(no packages installed from channel ' . $channel . ')'; } else { $data = array( 'caption' => 'Installed packages, channel ' . $channel . ':', 'border' => true, 'channel' => $channel, 'data' => array(array('(no packages installed)')), ); } } $this->ui->outputData($data, $command); return true; } function doListAll($command, $options, $params) { // This duplicate code is deprecated over // list --channelinfo, which gives identical // output for list and list --allchannels. $reg = &$this->config->getRegistry(); $installed = $reg->packageInfo(null, null, null); foreach ($installed as $channel => $packages) { usort($packages, array($this, '_sortinfo')); $data = array( 'caption' => 'Installed packages, channel ' . $channel . ':', 'border' => true, 'headline' => array('Package', 'Version', 'State'), 'channel' => $channel ); foreach ($packages as $package) { $p = isset($package['package']) ? $package['package'] : $package['name']; $pobj = $reg->getPackage($p, $channel); $data['data'][] = array($pobj->getPackage(), $pobj->getVersion(), $pobj->getState() ? $pobj->getState() : null); } // Adds a blank line after each section $data['data'][] = array(); if (count($packages) === 0) { $data = array( 'caption' => 'Installed packages, channel ' . $channel . ':', 'border' => true, 'data' => array(array('(no packages installed)'), array()), 'channel' => $channel ); } $this->ui->outputData($data, $command); } return true; } function doFileList($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError('list-files expects 1 parameter'); } $reg = &$this->config->getRegistry(); $fp = false; if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))) { if ($fp) { fclose($fp); } if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } $pkg = new PEAR_PackageFile($this->config, $this->_debug); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $info = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); PEAR::staticPopErrorHandling(); $headings = array('Package File', 'Install Path'); $installed = false; } else { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel')); PEAR::staticPopErrorHandling(); if (PEAR::isError($parsed)) { return $this->raiseError($parsed); } $info = &$reg->getPackage($parsed['package'], $parsed['channel']); $headings = array('Type', 'Install Path'); $installed = true; } if (PEAR::isError($info)) { return $this->raiseError($info); } if ($info === null) { return $this->raiseError("`$params[0]' not installed"); } $list = ($info->getPackagexmlVersion() == '1.0' || $installed) ? $info->getFilelist() : $info->getContents(); if ($installed) { $caption = 'Installed Files For ' . $params[0]; } else { $caption = 'Contents of ' . basename($params[0]); } $data = array( 'caption' => $caption, 'border' => true, 'headline' => $headings); if ($info->getPackagexmlVersion() == '1.0' || $installed) { foreach ($list as $file => $att) { if ($installed) { if (empty($att['installed_as'])) { continue; } $data['data'][] = array($att['role'], $att['installed_as']); } else { if (isset($att['baseinstalldir']) && !in_array($att['role'], array('test', 'data', 'doc'))) { $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR . $file; } else { $dest = $file; } switch ($att['role']) { case 'test': case 'data': case 'doc': $role = $att['role']; if ($role == 'test') { $role .= 's'; } $dest = $this->config->get($role . '_dir') . DIRECTORY_SEPARATOR . $info->getPackage() . DIRECTORY_SEPARATOR . $dest; break; case 'php': default: $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR . $dest; } $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; $dest = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $dest); $file = preg_replace('!/+!', '/', $file); $data['data'][] = array($file, $dest); } } } else { // package.xml 2.0, not installed if (!isset($list['dir']['file'][0])) { $list['dir']['file'] = array($list['dir']['file']); } foreach ($list['dir']['file'] as $att) { $att = $att['attribs']; $file = $att['name']; $role = &PEAR_Installer_Role::factory($info, $att['role'], $this->config); $role->setup($this, $info, $att, $file); if (!$role->isInstallable()) { $dest = '(not installable)'; } else { $dest = $role->processInstallation($info, $att, $file, ''); if (PEAR::isError($dest)) { $dest = '(Unknown role "' . $att['role'] . ')'; } else { list(,, $dest) = $dest; } } $data['data'][] = array($file, $dest); } } $this->ui->outputData($data, $command); return true; } function doShellTest($command, $options, $params) { if (count($params) < 1) { return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]'); } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $reg = &$this->config->getRegistry(); $info = $reg->parsePackageName($params[0], $this->config->get('default_channel')); if (PEAR::isError($info)) { exit(1); // invalid package name } $package = $info['package']; $channel = $info['channel']; // "pear shell-test Foo" if (!$reg->packageExists($package, $channel)) { if ($channel == 'pecl.php.net') { if ($reg->packageExists($package, 'pear.php.net')) { $channel = 'pear.php.net'; // magically change channels for extensions } } } if (count($params) === 1) { if (!$reg->packageExists($package, $channel)) { exit(1); } // "pear shell-test Foo 1.0" } elseif (count($params) === 2) { $v = $reg->packageInfo($package, 'version', $channel); if (!$v || !version_compare("$v", "{$params[1]}", "ge")) { exit(1); } // "pear shell-test Foo ge 1.0" } elseif (count($params) === 3) { $v = $reg->packageInfo($package, 'version', $channel); if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) { exit(1); } } else { PEAR::staticPopErrorHandling(); $this->raiseError("$command: expects 1 to 3 parameters"); exit(1); } } function doInfo($command, $options, $params) { if (count($params) !== 1) { return $this->raiseError('pear info expects 1 parameter'); } $info = $fp = false; $reg = &$this->config->getRegistry(); if (is_file($params[0]) && !is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r')) ) { if ($fp) { fclose($fp); } if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } $pkg = new PEAR_PackageFile($this->config, $this->_debug); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $obj = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); PEAR::staticPopErrorHandling(); if (PEAR::isError($obj)) { $uinfo = $obj->getUserInfo(); if (is_array($uinfo)) { foreach ($uinfo as $message) { if (is_array($message)) { $message = $message['message']; } $this->ui->outputData($message); } } return $this->raiseError($obj); } if ($obj->getPackagexmlVersion() != '1.0') { return $this->_doInfo2($command, $options, $params, $obj, false); } $info = $obj->toArray(); } else { $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel')); if (PEAR::isError($parsed)) { return $this->raiseError($parsed); } $package = $parsed['package']; $channel = $parsed['channel']; $info = $reg->packageInfo($package, null, $channel); if (isset($info['old'])) { $obj = $reg->getPackage($package, $channel); return $this->_doInfo2($command, $options, $params, $obj, true); } } if (PEAR::isError($info)) { return $info; } if (empty($info)) { $this->raiseError("No information found for `$params[0]'"); return; } unset($info['filelist']); unset($info['dirtree']); unset($info['changelog']); if (isset($info['xsdversion'])) { $info['package.xml version'] = $info['xsdversion']; unset($info['xsdversion']); } if (isset($info['packagerversion'])) { $info['packaged with PEAR version'] = $info['packagerversion']; unset($info['packagerversion']); } $keys = array_keys($info); $longtext = array('description', 'summary'); foreach ($keys as $key) { if (is_array($info[$key])) { switch ($key) { case 'maintainers': { $i = 0; $mstr = ''; foreach ($info[$key] as $m) { if ($i++ > 0) { $mstr .= "\n"; } $mstr .= $m['name'] . " <"; if (isset($m['email'])) { $mstr .= $m['email']; } else { $mstr .= $m['handle'] . '@php.net'; } $mstr .= "> ($m[role])"; } $info[$key] = $mstr; break; } case 'release_deps': { $i = 0; $dstr = ''; foreach ($info[$key] as $d) { if (isset($this->_deps_rel_trans[$d['rel']])) { $rel = $this->_deps_rel_trans[$d['rel']]; } else { $rel = $d['rel']; } if (isset($this->_deps_type_trans[$d['type']])) { $type = ucfirst($this->_deps_type_trans[$d['type']]); } else { $type = $d['type']; } if (isset($d['name'])) { $name = $d['name'] . ' '; } else { $name = ''; } if (isset($d['version'])) { $version = $d['version'] . ' '; } else { $version = ''; } if (isset($d['optional']) && $d['optional'] == 'yes') { $optional = ' (optional)'; } else { $optional = ''; } $dstr .= "$type $name$rel $version$optional\n"; } $info[$key] = $dstr; break; } case 'provides' : { $debug = $this->config->get('verbose'); if ($debug < 2) { $pstr = 'Classes: '; } else { $pstr = ''; } $i = 0; foreach ($info[$key] as $p) { if ($debug < 2 && $p['type'] != "class") { continue; } // Only print classes when verbosity mode is < 2 if ($debug < 2) { if ($i++ > 0) { $pstr .= ", "; } $pstr .= $p['name']; } else { if ($i++ > 0) { $pstr .= "\n"; } $pstr .= ucfirst($p['type']) . " " . $p['name']; if (isset($p['explicit']) && $p['explicit'] == 1) { $pstr .= " (explicit)"; } } } $info[$key] = $pstr; break; } case 'configure_options' : { foreach ($info[$key] as $i => $p) { $info[$key][$i] = array_map(null, array_keys($p), array_values($p)); $info[$key][$i] = array_map( function($a) { return join(" = ", $a); }, $info[$key][$i]); $info[$key][$i] = implode(', ', $info[$key][$i]); } $info[$key] = implode("\n", $info[$key]); break; } default: { $info[$key] = implode(", ", $info[$key]); break; } } } if ($key == '_lastmodified') { $hdate = date('Y-m-d', $info[$key]); unset($info[$key]); $info['Last Modified'] = $hdate; } elseif ($key == '_lastversion') { $info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -'; unset($info[$key]); } else { $info[$key] = trim($info[$key]); if (in_array($key, $longtext)) { $info[$key] = preg_replace('/ +/', ' ', $info[$key]); } } } $caption = 'About ' . $info['package'] . '-' . $info['version']; $data = array( 'caption' => $caption, 'border' => true); foreach ($info as $key => $value) { $key = ucwords(trim(str_replace('_', ' ', $key))); $data['data'][] = array($key, $value); } $data['raw'] = $info; $this->ui->outputData($data, 'package-info'); } /** * @access private */ function _doInfo2($command, $options, $params, &$obj, $installed) { $reg = &$this->config->getRegistry(); $caption = 'About ' . $obj->getChannel() . '/' .$obj->getPackage() . '-' . $obj->getVersion(); $data = array( 'caption' => $caption, 'border' => true); switch ($obj->getPackageType()) { case 'php' : $release = 'PEAR-style PHP-based Package'; break; case 'extsrc' : $release = 'PECL-style PHP extension (source code)'; break; case 'zendextsrc' : $release = 'PECL-style Zend extension (source code)'; break; case 'extbin' : $release = 'PECL-style PHP extension (binary)'; break; case 'zendextbin' : $release = 'PECL-style Zend extension (binary)'; break; case 'bundle' : $release = 'Package bundle (collection of packages)'; break; } $extends = $obj->getExtends(); $extends = $extends ? $obj->getPackage() . ' (extends ' . $extends . ')' : $obj->getPackage(); if ($src = $obj->getSourcePackage()) { $extends .= ' (source package ' . $src['channel'] . '/' . $src['package'] . ')'; } $info = array( 'Release Type' => $release, 'Name' => $extends, 'Channel' => $obj->getChannel(), 'Summary' => preg_replace('/ +/', ' ', $obj->getSummary()), 'Description' => preg_replace('/ +/', ' ', $obj->getDescription()), ); $info['Maintainers'] = ''; foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { $leads = $obj->{"get{$role}s"}(); if (!$leads) { continue; } if (isset($leads['active'])) { $leads = array($leads); } foreach ($leads as $lead) { if (!empty($info['Maintainers'])) { $info['Maintainers'] .= "\n"; } $active = $lead['active'] == 'no' ? ', inactive' : ''; $info['Maintainers'] .= $lead['name'] . ' <'; $info['Maintainers'] .= $lead['email'] . "> ($role$active)"; } } $info['Release Date'] = $obj->getDate(); if ($time = $obj->getTime()) { $info['Release Date'] .= ' ' . $time; } $info['Release Version'] = $obj->getVersion() . ' (' . $obj->getState() . ')'; $info['API Version'] = $obj->getVersion('api') . ' (' . $obj->getState('api') . ')'; $info['License'] = $obj->getLicense(); $uri = $obj->getLicenseLocation(); if ($uri) { if (isset($uri['uri'])) { $info['License'] .= ' (' . $uri['uri'] . ')'; } else { $extra = $obj->getInstalledLocation($info['filesource']); if ($extra) { $info['License'] .= ' (' . $uri['filesource'] . ')'; } } } $info['Release Notes'] = $obj->getNotes(); if ($compat = $obj->getCompatible()) { if (!isset($compat[0])) { $compat = array($compat); } $info['Compatible with'] = ''; foreach ($compat as $package) { $info['Compatible with'] .= $package['channel'] . '/' . $package['name'] . "\nVersions >= " . $package['min'] . ', <= ' . $package['max']; if (isset($package['exclude'])) { if (is_array($package['exclude'])) { $package['exclude'] = implode(', ', $package['exclude']); } if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info['Not Compatible with'] .= "\n"; } $info['Not Compatible with'] .= $package['channel'] . '/' . $package['name'] . "\nVersions " . $package['exclude']; } } } $usesrole = $obj->getUsesrole(); if ($usesrole) { if (!isset($usesrole[0])) { $usesrole = array($usesrole); } foreach ($usesrole as $roledata) { if (isset($info['Uses Custom Roles'])) { $info['Uses Custom Roles'] .= "\n"; } else { $info['Uses Custom Roles'] = ''; } if (isset($roledata['package'])) { $rolepackage = $reg->parsedPackageNameToString($roledata, true); } else { $rolepackage = $roledata['uri']; } $info['Uses Custom Roles'] .= $roledata['role'] . ' (' . $rolepackage . ')'; } } $usestask = $obj->getUsestask(); if ($usestask) { if (!isset($usestask[0])) { $usestask = array($usestask); } foreach ($usestask as $taskdata) { if (isset($info['Uses Custom Tasks'])) { $info['Uses Custom Tasks'] .= "\n"; } else { $info['Uses Custom Tasks'] = ''; } if (isset($taskdata['package'])) { $taskpackage = $reg->parsedPackageNameToString($taskdata, true); } else { $taskpackage = $taskdata['uri']; } $info['Uses Custom Tasks'] .= $taskdata['task'] . ' (' . $taskpackage . ')'; } } $deps = $obj->getDependencies(); $info['Required Dependencies'] = 'PHP version ' . $deps['required']['php']['min']; if (isset($deps['required']['php']['max'])) { $info['Required Dependencies'] .= '-' . $deps['required']['php']['max'] . "\n"; } else { $info['Required Dependencies'] .= "\n"; } if (isset($deps['required']['php']['exclude'])) { if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info['Not Compatible with'] .= "\n"; } if (is_array($deps['required']['php']['exclude'])) { $deps['required']['php']['exclude'] = implode(', ', $deps['required']['php']['exclude']); } $info['Not Compatible with'] .= "PHP versions\n " . $deps['required']['php']['exclude']; } $info['Required Dependencies'] .= 'PEAR installer version'; if (isset($deps['required']['pearinstaller']['max'])) { $info['Required Dependencies'] .= 's ' . $deps['required']['pearinstaller']['min'] . '-' . $deps['required']['pearinstaller']['max']; } else { $info['Required Dependencies'] .= ' ' . $deps['required']['pearinstaller']['min'] . ' or newer'; } if (isset($deps['required']['pearinstaller']['exclude'])) { if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info['Not Compatible with'] .= "\n"; } if (is_array($deps['required']['pearinstaller']['exclude'])) { $deps['required']['pearinstaller']['exclude'] = implode(', ', $deps['required']['pearinstaller']['exclude']); } $info['Not Compatible with'] .= "PEAR installer\n Versions " . $deps['required']['pearinstaller']['exclude']; } foreach (array('Package', 'Extension') as $type) { $index = strtolower($type); if (isset($deps['required'][$index])) { if (isset($deps['required'][$index]['name'])) { $deps['required'][$index] = array($deps['required'][$index]); } foreach ($deps['required'][$index] as $package) { if (isset($package['conflicts'])) { $infoindex = 'Not Compatible with'; if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info['Not Compatible with'] .= "\n"; } } else { $infoindex = 'Required Dependencies'; $info[$infoindex] .= "\n"; } if ($index == 'extension') { $name = $package['name']; } else { if (isset($package['channel'])) { $name = $package['channel'] . '/' . $package['name']; } else { $name = '__uri/' . $package['name'] . ' (static URI)'; } } $info[$infoindex] .= "$type $name"; if (isset($package['uri'])) { $info[$infoindex] .= "\n Download URI: $package[uri]"; continue; } if (isset($package['max']) && isset($package['min'])) { $info[$infoindex] .= " \n Versions " . $package['min'] . '-' . $package['max']; } elseif (isset($package['min'])) { $info[$infoindex] .= " \n Version " . $package['min'] . ' or newer'; } elseif (isset($package['max'])) { $info[$infoindex] .= " \n Version " . $package['max'] . ' or older'; } if (isset($package['recommended'])) { $info[$infoindex] .= "\n Recommended version: $package[recommended]"; } if (isset($package['exclude'])) { if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info['Not Compatible with'] .= "\n"; } if (is_array($package['exclude'])) { $package['exclude'] = implode(', ', $package['exclude']); } $package['package'] = $package['name']; // for parsedPackageNameToString if (isset($package['conflicts'])) { $info['Not Compatible with'] .= '=> except '; } $info['Not Compatible with'] .= 'Package ' . $reg->parsedPackageNameToString($package, true); $info['Not Compatible with'] .= "\n Versions " . $package['exclude']; } } } } if (isset($deps['required']['os'])) { if (isset($deps['required']['os']['name'])) { $dep['required']['os']['name'] = array($dep['required']['os']['name']); } foreach ($dep['required']['os'] as $os) { if (isset($os['conflicts']) && $os['conflicts'] == 'yes') { if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info['Not Compatible with'] .= "\n"; } $info['Not Compatible with'] .= "$os[name] Operating System"; } else { $info['Required Dependencies'] .= "\n"; $info['Required Dependencies'] .= "$os[name] Operating System"; } } } if (isset($deps['required']['arch'])) { if (isset($deps['required']['arch']['pattern'])) { $dep['required']['arch']['pattern'] = array($dep['required']['os']['pattern']); } foreach ($dep['required']['arch'] as $os) { if (isset($os['conflicts']) && $os['conflicts'] == 'yes') { if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info['Not Compatible with'] .= "\n"; } $info['Not Compatible with'] .= "OS/Arch matching pattern '/$os[pattern]/'"; } else { $info['Required Dependencies'] .= "\n"; $info['Required Dependencies'] .= "OS/Arch matching pattern '/$os[pattern]/'"; } } } if (isset($deps['optional'])) { foreach (array('Package', 'Extension') as $type) { $index = strtolower($type); if (isset($deps['optional'][$index])) { if (isset($deps['optional'][$index]['name'])) { $deps['optional'][$index] = array($deps['optional'][$index]); } foreach ($deps['optional'][$index] as $package) { if (isset($package['conflicts']) && $package['conflicts'] == 'yes') { $infoindex = 'Not Compatible with'; if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info['Not Compatible with'] .= "\n"; } } else { $infoindex = 'Optional Dependencies'; if (!isset($info['Optional Dependencies'])) { $info['Optional Dependencies'] = ''; } else { $info['Optional Dependencies'] .= "\n"; } } if ($index == 'extension') { $name = $package['name']; } else { if (isset($package['channel'])) { $name = $package['channel'] . '/' . $package['name']; } else { $name = '__uri/' . $package['name'] . ' (static URI)'; } } $info[$infoindex] .= "$type $name"; if (isset($package['uri'])) { $info[$infoindex] .= "\n Download URI: $package[uri]"; continue; } if ($infoindex == 'Not Compatible with') { // conflicts is only used to say that all versions conflict continue; } if (isset($package['max']) && isset($package['min'])) { $info[$infoindex] .= " \n Versions " . $package['min'] . '-' . $package['max']; } elseif (isset($package['min'])) { $info[$infoindex] .= " \n Version " . $package['min'] . ' or newer'; } elseif (isset($package['max'])) { $info[$infoindex] .= " \n Version " . $package['min'] . ' or older'; } if (isset($package['recommended'])) { $info[$infoindex] .= "\n Recommended version: $package[recommended]"; } if (isset($package['exclude'])) { if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info['Not Compatible with'] .= "\n"; } if (is_array($package['exclude'])) { $package['exclude'] = implode(', ', $package['exclude']); } $info['Not Compatible with'] .= "Package $package\n Versions " . $package['exclude']; } } } } } if (isset($deps['group'])) { if (!isset($deps['group'][0])) { $deps['group'] = array($deps['group']); } foreach ($deps['group'] as $group) { $info['Dependency Group ' . $group['attribs']['name']] = $group['attribs']['hint']; $groupindex = $group['attribs']['name'] . ' Contents'; $info[$groupindex] = ''; foreach (array('Package', 'Extension') as $type) { $index = strtolower($type); if (isset($group[$index])) { if (isset($group[$index]['name'])) { $group[$index] = array($group[$index]); } foreach ($group[$index] as $package) { if (!empty($info[$groupindex])) { $info[$groupindex] .= "\n"; } if ($index == 'extension') { $name = $package['name']; } else { if (isset($package['channel'])) { $name = $package['channel'] . '/' . $package['name']; } else { $name = '__uri/' . $package['name'] . ' (static URI)'; } } if (isset($package['uri'])) { if (isset($package['conflicts']) && $package['conflicts'] == 'yes') { $info[$groupindex] .= "Not Compatible with $type $name"; } else { $info[$groupindex] .= "$type $name"; } $info[$groupindex] .= "\n Download URI: $package[uri]"; continue; } if (isset($package['conflicts']) && $package['conflicts'] == 'yes') { $info[$groupindex] .= "Not Compatible with $type $name"; continue; } $info[$groupindex] .= "$type $name"; if (isset($package['max']) && isset($package['min'])) { $info[$groupindex] .= " \n Versions " . $package['min'] . '-' . $package['max']; } elseif (isset($package['min'])) { $info[$groupindex] .= " \n Version " . $package['min'] . ' or newer'; } elseif (isset($package['max'])) { $info[$groupindex] .= " \n Version " . $package['min'] . ' or older'; } if (isset($package['recommended'])) { $info[$groupindex] .= "\n Recommended version: $package[recommended]"; } if (isset($package['exclude'])) { if (!isset($info['Not Compatible with'])) { $info['Not Compatible with'] = ''; } else { $info[$groupindex] .= "Not Compatible with\n"; } if (is_array($package['exclude'])) { $package['exclude'] = implode(', ', $package['exclude']); } $info[$groupindex] .= " Package $package\n Versions " . $package['exclude']; } } } } } } if ($obj->getPackageType() == 'bundle') { $info['Bundled Packages'] = ''; foreach ($obj->getBundledPackages() as $package) { if (!empty($info['Bundled Packages'])) { $info['Bundled Packages'] .= "\n"; } if (isset($package['uri'])) { $info['Bundled Packages'] .= '__uri/' . $package['name']; $info['Bundled Packages'] .= "\n (URI: $package[uri]"; } else { $info['Bundled Packages'] .= $package['channel'] . '/' . $package['name']; } } } $info['package.xml version'] = '2.0'; if ($installed) { if ($obj->getLastModified()) { $info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified()); } $v = $obj->getLastInstalledVersion(); $info['Previous Installed Version'] = $v ? $v : '- None -'; } foreach ($info as $key => $value) { $data['data'][] = array($key, $value); } $data['raw'] = $obj->getArray(); // no validation needed $this->ui->outputData($data, 'package-info'); } } PK!4{PEAR/Command/Auth.xmlnu[ Connects and authenticates to remote server [Deprecated in favor of channel-login] doLogin li <channel name> WARNING: This function is deprecated in favor of using channel-login Log in to a remote channel server. If <channel name> is not supplied, the default channel is used. To use remote functions in the installer that require any kind of privileges, you need to log in first. The username and password you enter here will be stored in your per-user PEAR configuration (~/.pearrc on Unix-like systems). After logging in, your username and password will be sent along in subsequent operations on the remote server. Logs out from the remote server [Deprecated in favor of channel-logout] doLogout lo WARNING: This function is deprecated in favor of using channel-logout Logs out from the remote server. This command does not actually connect to the remote server, it only deletes the stored username and password from your user configuration. PK! #S S PEAR/Command/Build.phpnu[ * @author Tomas V.V.Cox * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; /** * PEAR commands for building extensions. * * @category pear * @package PEAR * @author Stig Bakken * @author Tomas V.V.Cox * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Command_Build extends PEAR_Command_Common { var $commands = array( 'build' => array( 'summary' => 'Build an Extension From C Source', 'function' => 'doBuild', 'shortcut' => 'b', 'options' => array( 'configureoptions' => array( 'shortopt' => 'D', 'arg' => 'OPTION1=VALUE[ OPTION2=VALUE]', 'doc' => 'space-delimited list of configure options', ), ), 'doc' => '[package.xml] Builds one or more extensions contained in a package.' ), ); /** * PEAR_Command_Build constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } function doBuild($command, $options, $params) { require_once 'PEAR/Builder.php'; if (sizeof($params) < 1) { $params[0] = 'package.xml'; } $configureoptions = empty($options['configureoptions']) ? '' : $options['configureoptions']; $builder = new PEAR_Builder($configureoptions, $this->ui); $this->debug = $this->config->get('verbose'); $err = $builder->build($params[0], array(&$this, 'buildCallback')); if (PEAR::isError($err)) { return $err; } return true; } function buildCallback($what, $data) { if (($what == 'cmdoutput' && $this->debug > 1) || ($what == 'output' && $this->debug > 0)) { $this->ui->outputData(rtrim($data), 'build'); } } } PK!uPEAR/Command/Registry.xmlnu[ List Installed Packages In The Default Channel doList l c list installed packages from this channel CHAN a list installed packages from all channels i output fully channel-aware data, even on failure <package> If invoked without parameters, this command lists the PEAR packages installed in your php_dir ({config php_dir}). With a parameter, it lists the files in a package. List Files In Installed Package doFileList fl <package> List the files in an installed package. Shell Script Test doShellTest st <package> [[relation] version] Tests if a package is installed in the system. Will exit(1) if it is not. <relation> The version comparison operator. One of: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne <version> The version to compare with Display information about a package doInfo in <package> Displays information about a package. The package argument may be a local package file, an URL to a package file, or the name of an installed package. PK!P>>PEAR/Command/Pickle.phpnu[ * @copyright 2005-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.1 */ /** * base class */ require_once 'PEAR/Command/Common.php'; /** * PEAR commands for login/logout * * @category pear * @package PEAR * @author Greg Beaver * @copyright 2005-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.1 */ class PEAR_Command_Pickle extends PEAR_Command_Common { var $commands = array( 'pickle' => array( 'summary' => 'Build PECL Package', 'function' => 'doPackage', 'shortcut' => 'pi', 'options' => array( 'nocompress' => array( 'shortopt' => 'Z', 'doc' => 'Do not gzip the package file' ), 'showname' => array( 'shortopt' => 'n', 'doc' => 'Print the name of the packaged file.', ), ), 'doc' => '[descfile] Creates a PECL package from its package2.xml file. An automatic conversion will be made to a package.xml 1.0 and written out to disk in the current directory as "package.xml". Note that only simple package.xml 2.0 will be converted. package.xml 2.0 with: - dependency types other than required/optional PECL package/ext/php/pearinstaller - more than one extsrcrelease or zendextsrcrelease - zendextbinrelease, extbinrelease, phprelease, or bundle release type - dependency groups - ignore tags in release filelist - tasks other than replace - custom roles will cause pickle to fail, and output an error message. If your package2.xml uses any of these features, you are best off using PEAR_PackageFileManager to generate both package.xml. ' ), ); /** * PEAR_Command_Package constructor. * * @access public */ function __construct(&$ui, &$config) { parent::__construct($ui, $config); } /** * For unit-testing ease * * @return PEAR_Packager */ function &getPackager() { if (!class_exists('PEAR_Packager')) { require_once 'PEAR/Packager.php'; } $a = new PEAR_Packager; return $a; } /** * For unit-testing ease * * @param PEAR_Config $config * @param bool $debug * @param string|null $tmpdir * @return PEAR_PackageFile */ function &getPackageFile($config, $debug = false) { if (!class_exists('PEAR_Common')) { require_once 'PEAR/Common.php'; } if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } $a = new PEAR_PackageFile($config, $debug); $common = new PEAR_Common; $common->ui = $this->ui; $a->setLogger($common); return $a; } function doPackage($command, $options, $params) { $this->output = ''; $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml'; $packager = &$this->getPackager(); if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) { return $err; } $compress = empty($options['nocompress']) ? true : false; $result = $packager->package($pkginfofile, $compress, 'package.xml'); if (PEAR::isError($result)) { return $this->raiseError($result); } // Don't want output, only the package file name just created if (isset($options['showname'])) { $this->ui->outputData($result, $command); } return true; } function _convertPackage($packagexml) { $pkg = &$this->getPackageFile($this->config); $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL); if (!is_a($pf2, 'PEAR_PackageFile_v2')) { return $this->raiseError('Cannot process "' . $packagexml . '", is not a package.xml 2.0'); } require_once 'PEAR/PackageFile/v1.php'; $pf = new PEAR_PackageFile_v1; $pf->setConfig($this->config); if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') { return $this->raiseError('Cannot safely convert "' . $packagexml . '", is not an extension source package. Using a PEAR_PackageFileManager-based ' . 'script is an option'); } if (is_array($pf2->getUsesRole())) { return $this->raiseError('Cannot safely convert "' . $packagexml . '", contains custom roles. Using a PEAR_PackageFileManager-based script or ' . 'the convert command is an option'); } if (is_array($pf2->getUsesTask())) { return $this->raiseError('Cannot safely convert "' . $packagexml . '", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' . 'the convert command is an option'); } $deps = $pf2->getDependencies(); if (isset($deps['group'])) { return $this->raiseError('Cannot safely convert "' . $packagexml . '", contains dependency groups. Using a PEAR_PackageFileManager-based script ' . 'or the convert command is an option'); } if (isset($deps['required']['subpackage']) || isset($deps['optional']['subpackage'])) { return $this->raiseError('Cannot safely convert "' . $packagexml . '", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '. 'script is an option'); } if (isset($deps['required']['os'])) { return $this->raiseError('Cannot safely convert "' . $packagexml . '", contains os dependencies. Using a PEAR_PackageFileManager-based '. 'script is an option'); } if (isset($deps['required']['arch'])) { return $this->raiseError('Cannot safely convert "' . $packagexml . '", contains arch dependencies. Using a PEAR_PackageFileManager-based '. 'script is an option'); } $pf->setPackage($pf2->getPackage()); $pf->setSummary($pf2->getSummary()); $pf->setDescription($pf2->getDescription()); foreach ($pf2->getMaintainers() as $maintainer) { $pf->addMaintainer($maintainer['role'], $maintainer['handle'], $maintainer['name'], $maintainer['email']); } $pf->setVersion($pf2->getVersion()); $pf->setDate($pf2->getDate()); $pf->setLicense($pf2->getLicense()); $pf->setState($pf2->getState()); $pf->setNotes($pf2->getNotes()); $pf->addPhpDep($deps['required']['php']['min'], 'ge'); if (isset($deps['required']['php']['max'])) { $pf->addPhpDep($deps['required']['php']['max'], 'le'); } if (isset($deps['required']['package'])) { if (!isset($deps['required']['package'][0])) { $deps['required']['package'] = array($deps['required']['package']); } foreach ($deps['required']['package'] as $dep) { if (!isset($dep['channel'])) { return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . ' contains uri-based dependency on a package. Using a ' . 'PEAR_PackageFileManager-based script is an option'); } if ($dep['channel'] != 'pear.php.net' && $dep['channel'] != 'pecl.php.net' && $dep['channel'] != 'doc.php.net') { return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . ' contains dependency on a non-standard channel package. Using a ' . 'PEAR_PackageFileManager-based script is an option'); } if (isset($dep['conflicts'])) { return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . ' contains conflicts dependency. Using a ' . 'PEAR_PackageFileManager-based script is an option'); } if (isset($dep['exclude'])) { $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); } if (isset($dep['min'])) { $pf->addPackageDep($dep['name'], $dep['min'], 'ge'); } if (isset($dep['max'])) { $pf->addPackageDep($dep['name'], $dep['max'], 'le'); } } } if (isset($deps['required']['extension'])) { if (!isset($deps['required']['extension'][0])) { $deps['required']['extension'] = array($deps['required']['extension']); } foreach ($deps['required']['extension'] as $dep) { if (isset($dep['conflicts'])) { return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . ' contains conflicts dependency. Using a ' . 'PEAR_PackageFileManager-based script is an option'); } if (isset($dep['exclude'])) { $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); } if (isset($dep['min'])) { $pf->addExtensionDep($dep['name'], $dep['min'], 'ge'); } if (isset($dep['max'])) { $pf->addExtensionDep($dep['name'], $dep['max'], 'le'); } } } if (isset($deps['optional']['package'])) { if (!isset($deps['optional']['package'][0])) { $deps['optional']['package'] = array($deps['optional']['package']); } foreach ($deps['optional']['package'] as $dep) { if (!isset($dep['channel'])) { return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . ' contains uri-based dependency on a package. Using a ' . 'PEAR_PackageFileManager-based script is an option'); } if ($dep['channel'] != 'pear.php.net' && $dep['channel'] != 'pecl.php.net' && $dep['channel'] != 'doc.php.net') { return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . ' contains dependency on a non-standard channel package. Using a ' . 'PEAR_PackageFileManager-based script is an option'); } if (isset($dep['exclude'])) { $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); } if (isset($dep['min'])) { $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes'); } if (isset($dep['max'])) { $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes'); } } } if (isset($deps['optional']['extension'])) { if (!isset($deps['optional']['extension'][0])) { $deps['optional']['extension'] = array($deps['optional']['extension']); } foreach ($deps['optional']['extension'] as $dep) { if (isset($dep['exclude'])) { $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); } if (isset($dep['min'])) { $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes'); } if (isset($dep['max'])) { $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes'); } } } $contents = $pf2->getContents(); $release = $pf2->getReleases(); if (isset($releases[0])) { return $this->raiseError('Cannot safely process "' . $packagexml . '" contains ' . 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' . 'or the convert command is an option'); } if ($configoptions = $pf2->getConfigureOptions()) { foreach ($configoptions as $option) { $default = isset($option['default']) ? $option['default'] : false; $pf->addConfigureOption($option['name'], $option['prompt'], $default); } } if (isset($release['filelist']['ignore'])) { return $this->raiseError('Cannot safely process "' . $packagexml . '" contains ' . 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' . ' command is an option'); } if (isset($release['filelist']['install']) && !isset($release['filelist']['install'][0])) { $release['filelist']['install'] = array($release['filelist']['install']); } if (isset($contents['dir']['attribs']['baseinstalldir'])) { $baseinstalldir = $contents['dir']['attribs']['baseinstalldir']; } else { $baseinstalldir = false; } if (!isset($contents['dir']['file'][0])) { $contents['dir']['file'] = array($contents['dir']['file']); } foreach ($contents['dir']['file'] as $file) { if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) { $file['attribs']['baseinstalldir'] = $baseinstalldir; } $processFile = $file; unset($processFile['attribs']); if (count($processFile)) { foreach ($processFile as $name => $task) { if ($name != $pf2->getTasksNs() . ':replace') { return $this->raiseError('Cannot safely process "' . $packagexml . '" contains tasks other than replace. Using a ' . 'PEAR_PackageFileManager-based script is an option.'); } $file['attribs']['replace'][] = $task; } } if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) { return $this->raiseError('Cannot safely convert "' . $packagexml . '", contains custom roles. Using a PEAR_PackageFileManager-based script ' . 'or the convert command is an option'); } if (isset($release['filelist']['install'])) { foreach ($release['filelist']['install'] as $installas) { if ($installas['attribs']['name'] == $file['attribs']['name']) { $file['attribs']['install-as'] = $installas['attribs']['as']; } } } $pf->addFile('/', $file['attribs']['name'], $file['attribs']); } if ($pf2->getChangeLog()) { $this->ui->outputData('WARNING: changelog is not translated to package.xml ' . '1.0, use PEAR_PackageFileManager-based script if you need changelog-' . 'translation for package.xml 1.0'); } $gen = &$pf->getDefaultGenerator(); $gen->toPackageFile('.'); } } PK!TIIPEAR/Builder.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 * * TODO: log output parameters in PECL command line * TODO: msdev path in configuration */ /** * Needed for extending PEAR_Builder */ require_once 'PEAR/Common.php'; require_once 'PEAR/PackageFile.php'; require_once 'System.php'; /** * Class to handle building (compiling) extensions. * * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since PHP 4.0.2 * @see http://pear.php.net/manual/en/core.ppm.pear-builder.php */ class PEAR_Builder extends PEAR_Common { var $php_api_version = 0; var $zend_module_api_no = 0; var $zend_extension_api_no = 0; var $extensions_built = array(); /** * @var string Used for reporting when it is not possible to pass function * via extra parameter, e.g. log, msdevCallback */ var $current_callback = null; // used for msdev builds var $_lastline = null; var $_firstline = null; /** * Parsed --configureoptions. * * @var mixed[] */ var $_parsed_configure_options; /** * PEAR_Builder constructor. * * @param mixed[] $configureoptions * @param object $ui user interface object (instance of PEAR_Frontend_*) * * @access public */ function __construct($configureoptions, &$ui) { parent::__construct(); $this->setFrontendObject($ui); $this->_parseConfigureOptions($configureoptions); } /** * Parse --configureoptions string. * * @param string Options, in the form "X=1 Y=2 Z='there\'s always one'" */ function _parseConfigureOptions($options) { $data = ''; $parser = xml_parser_create('ISO-8859-1'); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); xml_set_element_handler( $parser, array($this, '_parseConfigureOptionsStartElement'), array($this, '_parseConfigureOptionsEndElement')); xml_parse($parser, $data, true); xml_parser_free($parser); } /** * Handle element start. * * @see PEAR_Builder::_parseConfigureOptions() * * @param resource $parser * @param string $tagName * @param mixed[] $attribs */ function _parseConfigureOptionsStartElement($parser, $tagName, $attribs) { if ($tagName !== 'PROPERTIES') { return; } $this->_parsed_configure_options = $attribs; } /** * Handle element end. * * @see PEAR_Builder::_parseConfigureOptions() * * @param resource * @param string $element */ function _parseConfigureOptionsEndElement($parser, $element) { } /** * Build an extension from source on windows. * requires msdev */ function _build_win32($descfile, $callback = null) { if (is_object($descfile)) { $pkg = $descfile; $descfile = $pkg->getPackageFile(); } else { $pf = new PEAR_PackageFile($this->config, $this->debug); $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); if (PEAR::isError($pkg)) { return $pkg; } } $dir = dirname($descfile); $old_cwd = getcwd(); if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { return $this->raiseError("could not chdir to $dir"); } // packages that were in a .tar have the packagefile in this directory $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); if (file_exists($dir) && is_dir($vdir)) { if (!chdir($vdir)) { return $this->raiseError("could not chdir to " . realpath($vdir)); } $dir = getcwd(); } $this->log(2, "building in $dir"); $dsp = $pkg->getPackage().'.dsp'; if (!file_exists("$dir/$dsp")) { return $this->raiseError("The DSP $dsp does not exist."); } // XXX TODO: make release build type configurable $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"'; $err = $this->_runCommand($command, array(&$this, 'msdevCallback')); if (PEAR::isError($err)) { return $err; } // figure out the build platform and type $platform = 'Win32'; $buildtype = 'Release'; if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) { $platform = $matches[1]; $buildtype = $matches[2]; } if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) { if ($matches[2]) { // there were errors in the build return $this->raiseError("There were errors during compilation."); } $out = $matches[1]; } else { return $this->raiseError("Did not understand the completion status returned from msdev.exe."); } // msdev doesn't tell us the output directory :/ // open the dsp, find /out and use that directory $dsptext = join('', file($dsp)); // this regex depends on the build platform and type having been // correctly identified above. $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'. $pkg->getPackage().'\s-\s'. $platform.'\s'. $buildtype.'").*?'. '\/out:"(.*?)"/is'; if ($dsptext && preg_match($regex, $dsptext, $matches)) { // what we get back is a relative path to the output file itself. $outfile = realpath($matches[2]); } else { return $this->raiseError("Could not retrieve output information from $dsp."); } // realpath returns false if the file doesn't exist if ($outfile && copy($outfile, "$dir/$out")) { $outfile = "$dir/$out"; } $built_files[] = array( 'file' => "$outfile", 'php_api' => $this->php_api_version, 'zend_mod_api' => $this->zend_module_api_no, 'zend_ext_api' => $this->zend_extension_api_no, ); return $built_files; } // }}} // {{{ msdevCallback() function msdevCallback($what, $data) { if (!$this->_firstline) $this->_firstline = $data; $this->_lastline = $data; call_user_func($this->current_callback, $what, $data); } /** * @param string * @param string * @param array * @access private */ function _harvestInstDir($dest_prefix, $dirname, &$built_files) { $d = opendir($dirname); if (!$d) return false; $ret = true; while (($ent = readdir($d)) !== false) { if ($ent[0] == '.') continue; $full = $dirname . DIRECTORY_SEPARATOR . $ent; if (is_dir($full)) { if (!$this->_harvestInstDir( $dest_prefix . DIRECTORY_SEPARATOR . $ent, $full, $built_files)) { $ret = false; break; } } else { $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent; $built_files[] = array( 'file' => $full, 'dest' => $dest, 'php_api' => $this->php_api_version, 'zend_mod_api' => $this->zend_module_api_no, 'zend_ext_api' => $this->zend_extension_api_no, ); } } closedir($d); return $ret; } /** * Build an extension from source. Runs "phpize" in the source * directory, but compiles in a temporary directory * (TMPDIR/pear-build-USER/PACKAGE-VERSION). * * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or * a PEAR_PackageFile object * * @param mixed $callback callback function used to report output, * see PEAR_Builder::_runCommand for details * * @return array an array of associative arrays with built files, * format: * array( array( 'file' => '/path/to/ext.so', * 'php_api' => YYYYMMDD, * 'zend_mod_api' => YYYYMMDD, * 'zend_ext_api' => YYYYMMDD ), * ... ) * * @access public * * @see PEAR_Builder::_runCommand */ function build($descfile, $callback = null) { if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php([^\\/\\\\]+)?$/', $this->config->get('php_bin'), $matches)) { if (isset($matches[2]) && strlen($matches[2]) && trim($matches[2]) != trim($this->config->get('php_prefix'))) { $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') . ' appears to have a prefix ' . $matches[2] . ', but' . ' config variable php_prefix does not match'); } if (isset($matches[3]) && strlen($matches[3]) && trim($matches[3]) != trim($this->config->get('php_suffix'))) { $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') . ' appears to have a suffix ' . $matches[3] . ', but' . ' config variable php_suffix does not match'); } } $this->current_callback = $callback; if (PEAR_OS == "Windows") { return $this->_build_win32($descfile, $callback); } if (PEAR_OS != 'Unix') { return $this->raiseError("building extensions not supported on this platform"); } if (is_object($descfile)) { $pkg = $descfile; $descfile = $pkg->getPackageFile(); if (is_a($pkg, 'PEAR_PackageFile_v1')) { $dir = dirname($descfile); } else { $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName(); // automatically delete at session end self::addTempFile($dir); } } else { $pf = new PEAR_PackageFile($this->config); $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); if (PEAR::isError($pkg)) { return $pkg; } $dir = dirname($descfile); } // Find config. outside of normal path - e.g. config.m4 foreach (array_keys($pkg->getInstallationFileList()) as $item) { if (stristr(basename($item), 'config.m4') && dirname($item) != '.') { $dir .= DIRECTORY_SEPARATOR . dirname($item); break; } } $old_cwd = getcwd(); if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { return $this->raiseError("could not chdir to $dir"); } $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); if (is_dir($vdir)) { chdir($vdir); } $dir = getcwd(); $this->log(2, "building in $dir"); $binDir = $this->config->get('bin_dir'); if (!preg_match('@(^|:)' . preg_quote($binDir, '@') . '(:|$)@', getenv('PATH'))) { putenv('PATH=' . $binDir . ':' . getenv('PATH')); } $err = $this->_runCommand($this->config->get('php_prefix') . "phpize" . $this->config->get('php_suffix'), array(&$this, 'phpizeCallback')); if (PEAR::isError($err)) { return $err; } if (!$err) { return $this->raiseError("`phpize' failed"); } // {{{ start of interactive part $configure_command = "$dir/configure"; $phpConfigName = $this->config->get('php_prefix') . 'php-config' . $this->config->get('php_suffix'); $phpConfigPath = System::which($phpConfigName); if ($phpConfigPath !== false) { $configure_command .= ' --with-php-config=' . $phpConfigPath; } $configure_options = $pkg->getConfigureOptions(); if ($configure_options) { foreach ($configure_options as $option) { $default = array_key_exists('default', $option) ? $option['default'] : null; if (array_key_exists($option['name'], $this->_parsed_configure_options)) { $response = $this->_parsed_configure_options[$option['name']]; } else { list($response) = $this->ui->userDialog( 'build', [$option['prompt']], ['text'], [$default]); } if (substr($option['name'], 0, 5) === 'with-' && ($response === 'yes' || $response === 'autodetect')) { $configure_command .= " --{$option['name']}"; } else { $configure_command .= " --{$option['name']}=".trim($response); } } } // }}} end of interactive part // FIXME make configurable if (!$user=getenv('USER')) { $user='defaultuser'; } $tmpdir = $this->config->get('temp_dir'); $build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"'); $build_dir = "$build_basedir/$vdir"; $inst_dir = "$build_basedir/install-$vdir"; $this->log(1, "building in $build_dir"); if (is_dir($build_dir)) { System::rm(array('-rf', $build_dir)); } if (!System::mkDir(array('-p', $build_dir))) { return $this->raiseError("could not create build dir: $build_dir"); } self::addTempFile($build_dir); if (!System::mkDir(array('-p', $inst_dir))) { return $this->raiseError("could not create temporary install dir: $inst_dir"); } self::addTempFile($inst_dir); $make_command = getenv('MAKE') ? getenv('MAKE') : 'make'; $to_run = array( $configure_command, $make_command, "$make_command INSTALL_ROOT=\"$inst_dir\" install", "find \"$inst_dir\" | xargs ls -dils" ); if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) { return $this->raiseError("could not chdir to $build_dir"); } putenv('PHP_PEAR_VERSION=1.10.16'); foreach ($to_run as $cmd) { $err = $this->_runCommand($cmd, $callback); if (PEAR::isError($err)) { chdir($old_cwd); return $err; } if (!$err) { chdir($old_cwd); return $this->raiseError("`$cmd' failed"); } } if (!($dp = opendir("modules"))) { chdir($old_cwd); return $this->raiseError("no `modules' directory found"); } $built_files = array(); $prefix = exec($this->config->get('php_prefix') . "php-config" . $this->config->get('php_suffix') . " --prefix"); $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files); chdir($old_cwd); return $built_files; } /** * Message callback function used when running the "phpize" * program. Extracts the API numbers used. Ignores other message * types than "cmdoutput". * * @param string $what the type of message * @param mixed $data the message * * @return void * * @access public */ function phpizeCallback($what, $data) { if ($what != 'cmdoutput') { return; } $this->log(1, rtrim($data)); if (preg_match('/You should update your .aclocal.m4/', $data)) { return; } $matches = array(); if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) { $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1])); $apino = (int)$matches[2]; if (isset($this->$member)) { $this->$member = $apino; //$msg = sprintf("%-22s : %d", $matches[1], $apino); //$this->log(1, $msg); } } } /** * Run an external command, using a message callback to report * output. The command will be run through popen and output is * reported for every line with a "cmdoutput" message with the * line string, including newlines, as payload. * * @param string $command the command to run * * @param mixed $callback (optional) function to use as message * callback * * @return bool whether the command was successful (exit code 0 * means success, any other means failure) * * @access private */ function _runCommand($command, $callback = null) { $this->log(1, "running: $command"); $pp = popen("$command 2>&1", "r"); if (!$pp) { return $this->raiseError("failed to run `$command'"); } if ($callback && $callback[0]->debug == 1) { $olddbg = $callback[0]->debug; $callback[0]->debug = 2; } while ($line = fgets($pp, 1024)) { if ($callback) { call_user_func($callback, 'cmdoutput', $line); } else { $this->log(2, rtrim($line)); } } if ($callback && isset($olddbg)) { $callback[0]->debug = $olddbg; } $exitcode = is_resource($pp) ? pclose($pp) : -1; return ($exitcode == 0); } function log($level, $msg, $append_crlf = true) { if ($this->current_callback) { if ($this->debug >= $level) { call_user_func($this->current_callback, 'output', $msg); } return; } return parent::log($level, $msg, $append_crlf); } } PK![ WPEAR/XMLParser.phpnu[ * @author Stephan Schmidt (original XML_Unserializer code) * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Parser for any xml file * @category pear * @package PEAR * @author Greg Beaver * @author Stephan Schmidt (original XML_Unserializer code) * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_XMLParser { /** * unserilialized data * @var string $_serializedData */ var $_unserializedData = null; /** * name of the root tag * @var string $_root */ var $_root = null; /** * stack for all data that is found * @var array $_dataStack */ var $_dataStack = array(); /** * stack for all values that are generated * @var array $_valStack */ var $_valStack = array(); /** * current tag depth * @var int $_depth */ var $_depth = 0; /** * The XML encoding to use * @var string $encoding */ var $encoding = 'ISO-8859-1'; /** * @return array */ function getData() { return $this->_unserializedData; } /** * @param string xml content * @return true|PEAR_Error */ function parse($data) { if (!extension_loaded('xml')) { include_once 'PEAR.php'; return PEAR::raiseError("XML Extension not found", 1); } $this->_dataStack = $this->_valStack = array(); $this->_depth = 0; if ( strpos($data, 'encoding="UTF-8"') || strpos($data, 'encoding="utf-8"') || strpos($data, "encoding='UTF-8'") || strpos($data, "encoding='utf-8'") ) { $this->encoding = 'UTF-8'; } $xp = xml_parser_create($this->encoding); xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0); xml_set_object($xp, $this); xml_set_element_handler($xp, 'startHandler', 'endHandler'); xml_set_character_data_handler($xp, 'cdataHandler'); if (!xml_parse($xp, $data)) { $msg = xml_error_string(xml_get_error_code($xp)); $line = xml_get_current_line_number($xp); xml_parser_free($xp); include_once 'PEAR.php'; return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2); } xml_parser_free($xp); return true; } /** * Start element handler for XML parser * * @access private * @param object $parser XML parser object * @param string $element XML element * @param array $attribs attributes of XML tag * @return void */ function startHandler($parser, $element, $attribs) { $this->_depth++; $this->_dataStack[$this->_depth] = null; $val = array( 'name' => $element, 'value' => null, 'type' => 'string', 'childrenKeys' => array(), 'aggregKeys' => array() ); if (count($attribs) > 0) { $val['children'] = array(); $val['type'] = 'array'; $val['children']['attribs'] = $attribs; } array_push($this->_valStack, $val); } /** * post-process data * * @param string $data * @param string $element element name */ function postProcess($data, $element) { return trim($data); } /** * End element handler for XML parser * * @access private * @param object XML parser object * @param string * @return void */ function endHandler($parser, $element) { $value = array_pop($this->_valStack); $data = $this->postProcess($this->_dataStack[$this->_depth], $element); // adjust type of the value switch (strtolower($value['type'])) { // unserialize an array case 'array': if ($data !== '') { $value['children']['_content'] = $data; } $value['value'] = isset($value['children']) ? $value['children'] : array(); break; /* * unserialize a null value */ case 'null': $data = null; break; /* * unserialize any scalar value */ default: settype($data, $value['type']); $value['value'] = $data; break; } $parent = array_pop($this->_valStack); if ($parent === null) { $this->_unserializedData = &$value['value']; $this->_root = &$value['name']; return true; } // parent has to be an array if (!isset($parent['children']) || !is_array($parent['children'])) { $parent['children'] = array(); if ($parent['type'] != 'array') { $parent['type'] = 'array'; } } if (!empty($value['name'])) { // there already has been a tag with this name if (in_array($value['name'], $parent['childrenKeys'])) { // no aggregate has been created for this tag if (!in_array($value['name'], $parent['aggregKeys'])) { if (isset($parent['children'][$value['name']])) { $parent['children'][$value['name']] = array($parent['children'][$value['name']]); } else { $parent['children'][$value['name']] = array(); } array_push($parent['aggregKeys'], $value['name']); } array_push($parent['children'][$value['name']], $value['value']); } else { $parent['children'][$value['name']] = &$value['value']; array_push($parent['childrenKeys'], $value['name']); } } else { array_push($parent['children'],$value['value']); } array_push($this->_valStack, $parent); $this->_depth--; } /** * Handler for character data * * @access private * @param object XML parser object * @param string CDATA * @return void */ function cdataHandler($parser, $cdata) { $this->_dataStack[$this->_depth] .= $cdata; } }PK!l(ePEAR/Downloader.phpnu[ * @author Stig Bakken * @author Tomas V. V. Cox * @author Martin Jansen * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.3.0 */ /** * Needed for constants, extending */ require_once 'PEAR/Common.php'; require_once 'PEAR/Proxy.php'; define('PEAR_INSTALLER_OK', 1); define('PEAR_INSTALLER_FAILED', 0); define('PEAR_INSTALLER_SKIPPED', -1); define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2); /** * Administration class used to download anything from the internet (PEAR Packages, * static URLs, xml files) * * @category pear * @package PEAR * @author Greg Beaver * @author Stig Bakken * @author Tomas V. V. Cox * @author Martin Jansen * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.3.0 */ class PEAR_Downloader extends PEAR_Common { /** * @var PEAR_Registry * @access private */ var $_registry; /** * Preferred Installation State (snapshot, devel, alpha, beta, stable) * @var string|null * @access private */ var $_preferredState; /** * Options from command-line passed to Install. * * Recognized options:
* - onlyreqdeps : install all required dependencies as well * - alldeps : install all dependencies, including optional * - installroot : base relative path to install files in * - force : force a download even if warnings would prevent it * - nocompress : download uncompressed tarballs * - configureoptions : additional configure options * @see PEAR_Command_Install * @access private * @var array */ var $_options; /** * Downloaded Packages after a call to download(). * * Format of each entry: * * * array('pkg' => 'package_name', 'file' => '/path/to/local/file', * 'info' => array() // parsed package.xml * ); * * @access private * @var array */ var $_downloadedPackages = array(); /** * Packages slated for download. * * This is used to prevent downloading a package more than once should it be a dependency * for two packages to be installed. * Format of each entry: * *
     * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,
     * );
     * 
* @access private * @var array */ var $_toDownload = array(); /** * Array of every package installed, with names lower-cased. * * Format: * * array('package1' => 0, 'package2' => 1, ); * * @var array */ var $_installed = array(); /** * @var array * @access private */ var $_errorStack = array(); /** * @var boolean * @access private */ var $_internalDownload = false; /** * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()} * @var array * @access private */ var $_packageSortTree; /** * Temporary directory, or configuration value where downloads will occur * @var string */ var $_downloadDir; /** * List of methods that can be called both statically and non-statically. * @var array */ protected static $bivalentMethods = array( 'setErrorHandling' => true, 'raiseError' => true, 'throwError' => true, 'pushErrorHandling' => true, 'popErrorHandling' => true, 'downloadHttp' => true, ); /** * @param PEAR_Frontend_* * @param array * @param PEAR_Config */ function __construct($ui = null, $options = array(), $config = null) { parent::__construct(); $this->_options = $options; if ($config !== null) { $this->config = &$config; $this->_preferredState = $this->config->get('preferred_state'); } $this->ui = &$ui; if (!$this->_preferredState) { // don't inadvertently use a non-set preferred_state $this->_preferredState = null; } if ($config !== null) { if (isset($this->_options['installroot'])) { $this->config->setInstallRoot($this->_options['installroot']); } $this->_registry = &$config->getRegistry(); } if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) { $this->_installed = $this->_registry->listAllPackages(); foreach ($this->_installed as $key => $unused) { if (!count($unused)) { continue; } $strtolower = function($a) { return strtolower($a); }; array_walk($this->_installed[$key], $strtolower); } } } /** * Attempt to discover a channel's remote capabilities from * its server name * @param string * @return boolean */ function discover($channel) { $this->log(1, 'Attempting to discover channel "' . $channel . '"...'); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $callback = $this->ui ? array(&$this, '_downloadCallback') : null; if (!class_exists('System')) { require_once 'System.php'; } $tmpdir = $this->config->get('temp_dir'); $tmp = System::mktemp('-d -t "' . $tmpdir . '"'); $a = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false); PEAR::popErrorHandling(); if (PEAR::isError($a)) { // Attempt to fallback to https automatically. PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $this->log(1, 'Attempting fallback to https instead of http on channel "' . $channel . '"...'); $a = $this->downloadHttp('https://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false); PEAR::popErrorHandling(); if (PEAR::isError($a)) { return false; } } list($a, $lastmodified) = $a; if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $b = new PEAR_ChannelFile; if ($b->fromXmlFile($a)) { unlink($a); if ($this->config->get('auto_discover')) { $this->_registry->addChannel($b, $lastmodified); $alias = $b->getName(); if ($b->getName() == $this->_registry->channelName($b->getAlias())) { $alias = $b->getAlias(); } $this->log(1, 'Auto-discovered channel "' . $channel . '", alias "' . $alias . '", adding to registry'); } return true; } unlink($a); return false; } /** * For simpler unit-testing * @param PEAR_Downloader * @return PEAR_Downloader_Package */ function newDownloaderPackage(&$t) { if (!class_exists('PEAR_Downloader_Package')) { require_once 'PEAR/Downloader/Package.php'; } $a = new PEAR_Downloader_Package($t); return $a; } /** * For simpler unit-testing * @param PEAR_Config * @param array * @param array * @param int */ function &getDependency2Object(&$c, $i, $p, $s) { if (!class_exists('PEAR_Dependency2')) { require_once 'PEAR/Dependency2.php'; } $z = new PEAR_Dependency2($c, $i, $p, $s); return $z; } function &download($params) { if (!count($params)) { $a = array(); return $a; } if (!isset($this->_registry)) { $this->_registry = &$this->config->getRegistry(); } $channelschecked = array(); // convert all parameters into PEAR_Downloader_Package objects foreach ($params as $i => $param) { $params[$i] = $this->newDownloaderPackage($this); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = $params[$i]->initialize($param); PEAR::staticPopErrorHandling(); if (!$err) { // skip parameters that were missed by preferred_state continue; } if (PEAR::isError($err)) { if (!isset($this->_options['soft']) && $err->getMessage() !== '') { $this->log(0, $err->getMessage()); } $params[$i] = false; if (is_object($param)) { $param = $param->getChannel() . '/' . $param->getPackage(); } if (!isset($this->_options['soft'])) { $this->log(2, 'Package "' . $param . '" is not valid'); } // Message logged above in a specific verbose mode, passing null to not show up on CLI $this->pushError(null, PEAR_INSTALLER_SKIPPED); } else { do { if ($params[$i] && $params[$i]->getType() == 'local') { // bug #7090 skip channel.xml check for local packages break; } if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) && !isset($this->_options['offline']) ) { $channelschecked[$params[$i]->getChannel()] = true; PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); if (!class_exists('System')) { require_once 'System.php'; } $curchannel = $this->_registry->getChannel($params[$i]->getChannel()); if (PEAR::isError($curchannel)) { PEAR::staticPopErrorHandling(); return $this->raiseError($curchannel); } if (PEAR::isError($dir = $this->getDownloadDir())) { PEAR::staticPopErrorHandling(); break; } $mirror = $this->config->get('preferred_mirror', null, $params[$i]->getChannel()); $url = 'http://' . $mirror . '/channel.xml'; $a = $this->downloadHttp($url, $this->ui, $dir, null, $curchannel->lastModified()); PEAR::staticPopErrorHandling(); if ($a === false) { //channel.xml not modified break; } else if (PEAR::isError($a)) { // Attempt fallback to https automatically PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $a = $this->downloadHttp('https://' . $mirror . '/channel.xml', $this->ui, $dir, null, $curchannel->lastModified()); PEAR::staticPopErrorHandling(); if (PEAR::isError($a) || !$a) { break; } } $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' . 'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $params[$i]->getChannel() . '" to update'); } } while (false); if ($params[$i] && !isset($this->_options['downloadonly'])) { if (isset($this->_options['packagingroot'])) { $checkdir = $this->_prependPath( $this->config->get('php_dir', null, $params[$i]->getChannel()), $this->_options['packagingroot']); } else { $checkdir = $this->config->get('php_dir', null, $params[$i]->getChannel()); } while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) { $checkdir = dirname($checkdir); } if ($checkdir == '.') { $checkdir = '/'; } if (!is_writeable($checkdir)) { return PEAR::raiseError('Cannot install, php_dir for channel "' . $params[$i]->getChannel() . '" is not writeable by the current user'); } } } } unset($channelschecked); PEAR_Downloader_Package::removeDuplicates($params); if (!count($params)) { $a = array(); return $a; } if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) { $reverify = true; while ($reverify) { $reverify = false; foreach ($params as $i => $param) { //PHP Bug 40768 / PEAR Bug #10944 //Nested foreaches fail in PHP 5.2.1 key($params); $ret = $params[$i]->detectDependencies($params); if (PEAR::isError($ret)) { $reverify = true; $params[$i] = false; PEAR_Downloader_Package::removeDuplicates($params); if (!isset($this->_options['soft'])) { $this->log(0, $ret->getMessage()); } continue 2; } } } } if (isset($this->_options['offline'])) { $this->log(3, 'Skipping dependency download check, --offline specified'); } if (!count($params)) { $a = array(); return $a; } while (PEAR_Downloader_Package::mergeDependencies($params)); PEAR_Downloader_Package::removeDuplicates($params, true); $errorparams = array(); if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) { if (count($errorparams)) { foreach ($errorparams as $param) { $name = $this->_registry->parsedPackageNameToString($param->getParsedPackage()); $this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED); } $a = array(); return $a; } } PEAR_Downloader_Package::removeInstalled($params); if (!count($params)) { $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED); $a = array(); return $a; } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $err = $this->analyzeDependencies($params); PEAR::popErrorHandling(); if (!count($params)) { $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED); $a = array(); return $a; } $ret = array(); $newparams = array(); if (isset($this->_options['pretend'])) { return $params; } $somefailed = false; foreach ($params as $i => $package) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $pf = &$params[$i]->download(); PEAR::staticPopErrorHandling(); if (PEAR::isError($pf)) { if (!isset($this->_options['soft'])) { $this->log(1, $pf->getMessage()); $this->log(0, 'Error: cannot download "' . $this->_registry->parsedPackageNameToString($package->getParsedPackage(), true) . '"'); } $somefailed = true; continue; } $newparams[] = &$params[$i]; $ret[] = array( 'file' => $pf->getArchiveFile(), 'info' => &$pf, 'pkg' => $pf->getPackage() ); } if ($somefailed) { // remove params that did not download successfully PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $err = $this->analyzeDependencies($newparams, true); PEAR::popErrorHandling(); if (!count($newparams)) { $this->pushError('Download failed', PEAR_INSTALLER_FAILED); $a = array(); return $a; } } $this->_downloadedPackages = $ret; return $newparams; } /** * @param array all packages to be installed */ function analyzeDependencies(&$params, $force = false) { if (isset($this->_options['downloadonly'])) { return; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $redo = true; $reset = $hasfailed = $failed = false; while ($redo) { $redo = false; foreach ($params as $i => $param) { $deps = $param->getDeps(); if (!$deps) { $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(), $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING); $send = $param->getPackageFile(); $installcheck = $depchecker->validatePackage($send, $this, $params); if (PEAR::isError($installcheck)) { if (!isset($this->_options['soft'])) { $this->log(0, $installcheck->getMessage()); } $hasfailed = true; $params[$i] = false; $reset = true; $redo = true; $failed = false; PEAR_Downloader_Package::removeDuplicates($params); continue 2; } continue; } if (!$reset && $param->alreadyValidated() && !$force) { continue; } if (count($deps)) { $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(), $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING); $send = $param->getPackageFile(); if ($send === null) { $send = $param->getDownloadURL(); } $installcheck = $depchecker->validatePackage($send, $this, $params); if (PEAR::isError($installcheck)) { if (!isset($this->_options['soft'])) { $this->log(0, $installcheck->getMessage()); } $hasfailed = true; $params[$i] = false; $reset = true; $redo = true; $failed = false; PEAR_Downloader_Package::removeDuplicates($params); continue 2; } $failed = false; if (isset($deps['required']) && is_array($deps['required'])) { foreach ($deps['required'] as $type => $dep) { // note: Dependency2 will never return a PEAR_Error if ignore-errors // is specified, so soft is needed to turn off logging if (!isset($dep[0])) { if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep, true, $params))) { $failed = true; if (!isset($this->_options['soft'])) { $this->log(0, $e->getMessage()); } } elseif (is_array($e) && !$param->alreadyValidated()) { if (!isset($this->_options['soft'])) { $this->log(0, $e[0]); } } } else { foreach ($dep as $d) { if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($d, true, $params))) { $failed = true; if (!isset($this->_options['soft'])) { $this->log(0, $e->getMessage()); } } elseif (is_array($e) && !$param->alreadyValidated()) { if (!isset($this->_options['soft'])) { $this->log(0, $e[0]); } } } } } if (isset($deps['optional']) && is_array($deps['optional'])) { foreach ($deps['optional'] as $type => $dep) { if (!isset($dep[0])) { if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep, false, $params))) { $failed = true; if (!isset($this->_options['soft'])) { $this->log(0, $e->getMessage()); } } elseif (is_array($e) && !$param->alreadyValidated()) { if (!isset($this->_options['soft'])) { $this->log(0, $e[0]); } } } else { foreach ($dep as $d) { if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($d, false, $params))) { $failed = true; if (!isset($this->_options['soft'])) { $this->log(0, $e->getMessage()); } } elseif (is_array($e) && !$param->alreadyValidated()) { if (!isset($this->_options['soft'])) { $this->log(0, $e[0]); } } } } } } $groupname = $param->getGroup(); if (isset($deps['group']) && $groupname) { if (!isset($deps['group'][0])) { $deps['group'] = array($deps['group']); } $found = false; foreach ($deps['group'] as $group) { if ($group['attribs']['name'] == $groupname) { $found = true; break; } } if ($found) { unset($group['attribs']); foreach ($group as $type => $dep) { if (!isset($dep[0])) { if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep, false, $params))) { $failed = true; if (!isset($this->_options['soft'])) { $this->log(0, $e->getMessage()); } } elseif (is_array($e) && !$param->alreadyValidated()) { if (!isset($this->_options['soft'])) { $this->log(0, $e[0]); } } } else { foreach ($dep as $d) { if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($d, false, $params))) { $failed = true; if (!isset($this->_options['soft'])) { $this->log(0, $e->getMessage()); } } elseif (is_array($e) && !$param->alreadyValidated()) { if (!isset($this->_options['soft'])) { $this->log(0, $e[0]); } } } } } } } } else { foreach ($deps as $dep) { if (PEAR::isError($e = $depchecker->validateDependency1($dep, $params))) { $failed = true; if (!isset($this->_options['soft'])) { $this->log(0, $e->getMessage()); } } elseif (is_array($e) && !$param->alreadyValidated()) { if (!isset($this->_options['soft'])) { $this->log(0, $e[0]); } } } } $params[$i]->setValidated(); } if ($failed) { $hasfailed = true; $params[$i] = false; $reset = true; $redo = true; $failed = false; PEAR_Downloader_Package::removeDuplicates($params); continue 2; } } } PEAR::staticPopErrorHandling(); if ($hasfailed && (isset($this->_options['ignore-errors']) || isset($this->_options['nodeps']))) { // this is probably not needed, but just in case if (!isset($this->_options['soft'])) { $this->log(0, 'WARNING: dependencies failed'); } } } /** * Retrieve the directory that downloads will happen in * @access private * @return string */ function getDownloadDir() { if (isset($this->_downloadDir)) { return $this->_downloadDir; } $downloaddir = $this->config->get('download_dir'); if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) { if (is_dir($downloaddir) && !is_writable($downloaddir)) { $this->log(0, 'WARNING: configuration download directory "' . $downloaddir . '" is not writeable. Change download_dir config variable to ' . 'a writeable dir to avoid this warning'); } if (!class_exists('System')) { require_once 'System.php'; } if (PEAR::isError($downloaddir = System::mktemp('-d'))) { return $downloaddir; } $this->log(3, '+ tmp dir created at ' . $downloaddir); } if (!is_writable($downloaddir)) { if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) || !is_writable($downloaddir)) { return PEAR::raiseError('download directory "' . $downloaddir . '" is not writeable. Change download_dir config variable to ' . 'a writeable dir'); } } return $this->_downloadDir = $downloaddir; } function setDownloadDir($dir) { if (!@is_writable($dir)) { if (PEAR::isError(System::mkdir(array('-p', $dir)))) { return PEAR::raiseError('download directory "' . $dir . '" is not writeable. Change download_dir config variable to ' . 'a writeable dir'); } } $this->_downloadDir = $dir; } function configSet($key, $value, $layer = 'user', $channel = false) { $this->config->set($key, $value, $layer, $channel); $this->_preferredState = $this->config->get('preferred_state', null, $channel); if (!$this->_preferredState) { // don't inadvertently use a non-set preferred_state $this->_preferredState = null; } } function setOptions($options) { $this->_options = $options; } function getOptions() { return $this->_options; } /** * @param array output of {@link parsePackageName()} * @access private */ function _getPackageDownloadUrl($parr) { $curchannel = $this->config->get('default_channel'); $this->configSet('default_channel', $parr['channel']); // getDownloadURL returns an array. On error, it only contains information // on the latest release as array(version, info). On success it contains // array(version, info, download url string) $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state'); if (!$this->_registry->channelExists($parr['channel'])) { do { if ($this->config->get('auto_discover') && $this->discover($parr['channel'])) { break; } $this->configSet('default_channel', $curchannel); return PEAR::raiseError('Unknown remote channel: ' . $parr['channel']); } while (false); } $chan = $this->_registry->getChannel($parr['channel']); if (PEAR::isError($chan)) { return $chan; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $version = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']); $stability = $this->_registry->packageInfo($parr['package'], 'stability', $parr['channel']); // package is installed - use the installed release stability level if (!isset($parr['state']) && $stability !== null) { $state = $stability['release']; } PEAR::staticPopErrorHandling(); $base2 = false; $preferred_mirror = $this->config->get('preferred_mirror'); if (!$chan->supportsREST($preferred_mirror) || ( !($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror)) && !($base = $chan->getBaseURL('REST1.0', $preferred_mirror)) ) ) { return $this->raiseError($parr['channel'] . ' is using an unsupported protocol - This should never happen. Use --force to continue'); } if ($base2) { $rest = &$this->config->getREST('1.3', $this->_options); $base = $base2; } else { $rest = &$this->config->getREST('1.0', $this->_options); } $downloadVersion = false; if (!isset($parr['version']) && !isset($parr['state']) && $version && !PEAR::isError($version) && !isset($this->_options['downloadonly']) ) { $downloadVersion = $version; } $url = $rest->getDownloadURL($base, $parr, $state, $downloadVersion, $chan->getName()); if (PEAR::isError($url)) { $this->configSet('default_channel', $curchannel); return $url; } if ($parr['channel'] != $curchannel) { $this->configSet('default_channel', $curchannel); } if (!is_array($url)) { return $url; } $url['raw'] = false; // no checking is necessary for REST if (!is_array($url['info'])) { return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' . 'this should never happen'); } if (!isset($this->_options['force']) && !isset($this->_options['downloadonly']) && $version && !PEAR::isError($version) && !isset($parr['group']) ) { if (version_compare($version, $url['version'], '=')) { return PEAR::raiseError($this->_registry->parsedPackageNameToString( $parr, true) . ' is already installed and is the same as the ' . 'released version ' . $url['version'], -976); } if (version_compare($version, $url['version'], '>')) { return PEAR::raiseError($this->_registry->parsedPackageNameToString( $parr, true) . ' is already installed and is newer than detected ' . 'released version ' . $url['version'], -976); } } if (isset($url['info']['required']) || $url['compatible']) { require_once 'PEAR/PackageFile/v2.php'; $pf = new PEAR_PackageFile_v2; $pf->setRawChannel($parr['channel']); if ($url['compatible']) { $pf->setRawCompatible($url['compatible']); } } else { require_once 'PEAR/PackageFile/v1.php'; $pf = new PEAR_PackageFile_v1; } $pf->setRawPackage($url['package']); $pf->setDeps($url['info']); if ($url['compatible']) { $pf->setCompatible($url['compatible']); } $pf->setRawState($url['stability']); $url['info'] = &$pf; if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { $ext = '.tar'; } else { $ext = '.tgz'; } if (is_array($url) && isset($url['url'])) { $url['url'] .= $ext; } return $url; } /** * @param array dependency array * @access private */ function _getDepPackageDownloadUrl($dep, $parr) { $xsdversion = isset($dep['rel']) ? '1.0' : '2.0'; $curchannel = $this->config->get('default_channel'); if (isset($dep['uri'])) { $xsdversion = '2.0'; $chan = $this->_registry->getChannel('__uri'); if (PEAR::isError($chan)) { return $chan; } $version = $this->_registry->packageInfo($dep['name'], 'version', '__uri'); $this->configSet('default_channel', '__uri'); } else { if (isset($dep['channel'])) { $remotechannel = $dep['channel']; } else { $remotechannel = 'pear.php.net'; } if (!$this->_registry->channelExists($remotechannel)) { do { if ($this->config->get('auto_discover')) { if ($this->discover($remotechannel)) { break; } } return PEAR::raiseError('Unknown remote channel: ' . $remotechannel); } while (false); } $chan = $this->_registry->getChannel($remotechannel); if (PEAR::isError($chan)) { return $chan; } $version = $this->_registry->packageInfo($dep['name'], 'version', $remotechannel); $this->configSet('default_channel', $remotechannel); } $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state'); if (isset($parr['state']) && isset($parr['version'])) { unset($parr['state']); } if (isset($dep['uri'])) { $info = $this->newDownloaderPackage($this); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = $info->initialize($dep); PEAR::staticPopErrorHandling(); if (!$err) { // skip parameters that were missed by preferred_state return PEAR::raiseError('Cannot initialize dependency'); } if (PEAR::isError($err)) { if (!isset($this->_options['soft'])) { $this->log(0, $err->getMessage()); } if (is_object($info)) { $param = $info->getChannel() . '/' . $info->getPackage(); } return PEAR::raiseError('Package "' . $param . '" is not valid'); } return $info; } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && ( ($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror'))) || ($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) ) ) { if ($base2) { $base = $base2; $rest = &$this->config->getREST('1.3', $this->_options); } else { $rest = &$this->config->getREST('1.0', $this->_options); } $url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr, $state, $version, $chan->getName()); if (PEAR::isError($url)) { return $url; } if ($parr['channel'] != $curchannel) { $this->configSet('default_channel', $curchannel); } if (!is_array($url)) { return $url; } $url['raw'] = false; // no checking is necessary for REST if (!is_array($url['info'])) { return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' . 'this should never happen'); } if (isset($url['info']['required'])) { if (!class_exists('PEAR_PackageFile_v2')) { require_once 'PEAR/PackageFile/v2.php'; } $pf = new PEAR_PackageFile_v2; $pf->setRawChannel($remotechannel); } else { if (!class_exists('PEAR_PackageFile_v1')) { require_once 'PEAR/PackageFile/v1.php'; } $pf = new PEAR_PackageFile_v1; } $pf->setRawPackage($url['package']); $pf->setDeps($url['info']); if ($url['compatible']) { $pf->setCompatible($url['compatible']); } $pf->setRawState($url['stability']); $url['info'] = &$pf; if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { $ext = '.tar'; } else { $ext = '.tgz'; } if (is_array($url) && isset($url['url'])) { $url['url'] .= $ext; } return $url; } return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.'); } /** * @deprecated in favor of _getPackageDownloadUrl */ function getPackageDownloadUrl($package, $version = null, $channel = false) { if ($version) { $package .= "-$version"; } if ($this === null || $this->_registry === null) { $package = "http://pear.php.net/get/$package"; } else { $chan = $this->_registry->getChannel($channel); if (PEAR::isError($chan)) { return ''; } $package = "http://" . $chan->getServer() . "/get/$package"; } if (!extension_loaded("zlib")) { $package .= '?uncompress=yes'; } return $package; } /** * Retrieve a list of downloaded packages after a call to {@link download()}. * * Also resets the list of downloaded packages. * @return array */ function getDownloadedPackages() { $ret = $this->_downloadedPackages; $this->_downloadedPackages = array(); $this->_toDownload = array(); return $ret; } function _downloadCallback($msg, $params = null) { switch ($msg) { case 'saveas': $this->log(1, "downloading $params ..."); break; case 'done': $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes'); break; case 'bytesread': static $bytes; if (empty($bytes)) { $bytes = 0; } if (!($bytes % 10240)) { $this->log(1, '.', false); } $bytes += $params; break; case 'start': if($params[1] == -1) { $length = "Unknown size"; } else { $length = number_format($params[1], 0, '', ',')." bytes"; } $this->log(1, "Starting to download {$params[0]} ($length)"); break; } if (method_exists($this->ui, '_downloadCallback')) $this->ui->_downloadCallback($msg, $params); } function _prependPath($path, $prepend) { if (strlen($prepend) > 0) { if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { if (preg_match('/^[a-z]:/i', $prepend)) { $prepend = substr($prepend, 2); } elseif ($prepend[0] != '\\') { $prepend = "\\$prepend"; } $path = substr($path, 0, 2) . $prepend . substr($path, 2); } else { $path = $prepend . $path; } } return $path; } /** * @param string * @param integer */ function pushError($errmsg, $code = -1) { array_push($this->_errorStack, array($errmsg, $code)); } function getErrorMsgs() { $msgs = array(); $errs = $this->_errorStack; foreach ($errs as $err) { $msgs[] = $err[0]; } $this->_errorStack = array(); return $msgs; } /** * for BC * * @deprecated */ function sortPkgDeps(&$packages, $uninstall = false) { $uninstall ? $this->sortPackagesForUninstall($packages) : $this->sortPackagesForInstall($packages); } /** * Sort a list of arrays of array(downloaded packagefilename) by dependency. * * This uses the topological sort method from graph theory, and the * Structures_Graph package to properly sort dependencies for installation. * @param array an array of downloaded PEAR_Downloader_Packages * @return array array of array(packagefilename, package.xml contents) */ function sortPackagesForInstall(&$packages) { require_once 'Structures/Graph.php'; require_once 'Structures/Graph/Node.php'; require_once 'Structures/Graph/Manipulator/TopologicalSorter.php'; $depgraph = new Structures_Graph(true); $nodes = array(); $reg = &$this->config->getRegistry(); foreach ($packages as $i => $package) { $pname = $reg->parsedPackageNameToString( array( 'channel' => $package->getChannel(), 'package' => strtolower($package->getPackage()), )); $nodes[$pname] = new Structures_Graph_Node; $nodes[$pname]->setData($packages[$i]); $depgraph->addNode($nodes[$pname]); } $deplinks = array(); foreach ($nodes as $package => $node) { $pf = &$node->getData(); $pdeps = $pf->getDeps(true); if (!$pdeps) { continue; } if ($pf->getPackagexmlVersion() == '1.0') { foreach ($pdeps as $dep) { if ($dep['type'] != 'pkg' || (isset($dep['optional']) && $dep['optional'] == 'yes')) { continue; } $dname = $reg->parsedPackageNameToString( array( 'channel' => 'pear.php.net', 'package' => strtolower($dep['name']), )); if (isset($nodes[$dname])) { if (!isset($deplinks[$dname])) { $deplinks[$dname] = array(); } $deplinks[$dname][$package] = 1; // dependency is in installed packages continue; } $dname = $reg->parsedPackageNameToString( array( 'channel' => 'pecl.php.net', 'package' => strtolower($dep['name']), )); if (isset($nodes[$dname])) { if (!isset($deplinks[$dname])) { $deplinks[$dname] = array(); } $deplinks[$dname][$package] = 1; // dependency is in installed packages continue; } } } else { // the only ordering we care about is: // 1) subpackages must be installed before packages that depend on them // 2) required deps must be installed before packages that depend on them if (isset($pdeps['required']['subpackage'])) { $t = $pdeps['required']['subpackage']; if (!isset($t[0])) { $t = array($t); } $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); } if (isset($pdeps['group'])) { if (!isset($pdeps['group'][0])) { $pdeps['group'] = array($pdeps['group']); } foreach ($pdeps['group'] as $group) { if (isset($group['subpackage'])) { $t = $group['subpackage']; if (!isset($t[0])) { $t = array($t); } $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); } } } if (isset($pdeps['optional']['subpackage'])) { $t = $pdeps['optional']['subpackage']; if (!isset($t[0])) { $t = array($t); } $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); } if (isset($pdeps['required']['package'])) { $t = $pdeps['required']['package']; if (!isset($t[0])) { $t = array($t); } $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); } if (isset($pdeps['group'])) { if (!isset($pdeps['group'][0])) { $pdeps['group'] = array($pdeps['group']); } foreach ($pdeps['group'] as $group) { if (isset($group['package'])) { $t = $group['package']; if (!isset($t[0])) { $t = array($t); } $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); } } } } } $this->_detectDepCycle($deplinks); foreach ($deplinks as $dependent => $parents) { foreach ($parents as $parent => $unused) { $nodes[$dependent]->connectTo($nodes[$parent]); } } $installOrder = Structures_Graph_Manipulator_TopologicalSorter::sort($depgraph); $ret = array(); for ($i = 0, $count = count($installOrder); $i < $count; $i++) { foreach ($installOrder[$i] as $index => $sortedpackage) { $data = &$installOrder[$i][$index]->getData(); $ret[] = &$nodes[$reg->parsedPackageNameToString( array( 'channel' => $data->getChannel(), 'package' => strtolower($data->getPackage()), ))]->getData(); } } $packages = $ret; return; } /** * Detect recursive links between dependencies and break the cycles * * @param array * @access private */ function _detectDepCycle(&$deplinks) { do { $keepgoing = false; foreach ($deplinks as $dep => $parents) { foreach ($parents as $parent => $unused) { // reset the parent cycle detector $this->_testCycle(null, null, null); if ($this->_testCycle($dep, $deplinks, $parent)) { $keepgoing = true; unset($deplinks[$dep][$parent]); if (count($deplinks[$dep]) == 0) { unset($deplinks[$dep]); } continue 3; } } } } while ($keepgoing); } function _testCycle($test, $deplinks, $dep) { static $visited = array(); if ($test === null) { $visited = array(); return; } // this happens when a parent has a dep cycle on another dependency // but the child is not part of the cycle if (isset($visited[$dep])) { return false; } $visited[$dep] = 1; if ($test == $dep) { return true; } if (isset($deplinks[$dep])) { if (in_array($test, array_keys($deplinks[$dep]), true)) { return true; } foreach ($deplinks[$dep] as $parent => $unused) { if ($this->_testCycle($test, $deplinks, $parent)) { return true; } } } return false; } /** * Set up the dependency for installation parsing * * @param array $t dependency information * @param PEAR_Registry $reg * @param array $deplinks list of dependency links already established * @param array $nodes all existing package nodes * @param string $package parent package name * @access private */ function _setupGraph($t, $reg, &$deplinks, &$nodes, $package) { foreach ($t as $dep) { $depchannel = !isset($dep['channel']) ? '__uri': $dep['channel']; $dname = $reg->parsedPackageNameToString( array( 'channel' => $depchannel, 'package' => strtolower($dep['name']), )); if (isset($nodes[$dname])) { if (!isset($deplinks[$dname])) { $deplinks[$dname] = array(); } $deplinks[$dname][$package] = 1; } } } function _dependsOn($a, $b) { return $this->_checkDepTree(strtolower($a->getChannel()), strtolower($a->getPackage()), $b); } function _checkDepTree($channel, $package, $b, $checked = array()) { $checked[$channel][$package] = true; if (!isset($this->_depTree[$channel][$package])) { return false; } if (isset($this->_depTree[$channel][$package][strtolower($b->getChannel())] [strtolower($b->getPackage())])) { return true; } foreach ($this->_depTree[$channel][$package] as $ch => $packages) { foreach ($packages as $pa => $true) { if ($this->_checkDepTree($ch, $pa, $b, $checked)) { return true; } } } return false; } function _sortInstall($a, $b) { if (!$a->getDeps() && !$b->getDeps()) { return 0; // neither package has dependencies, order is insignificant } if ($a->getDeps() && !$b->getDeps()) { return 1; // $a must be installed after $b because $a has dependencies } if (!$a->getDeps() && $b->getDeps()) { return -1; // $b must be installed after $a because $b has dependencies } // both packages have dependencies if ($this->_dependsOn($a, $b)) { return 1; } if ($this->_dependsOn($b, $a)) { return -1; } return 0; } /** * Download a file through HTTP. Considers suggested file name in * Content-disposition: header and can run a callback function for * different events. The callback will be called with two * parameters: the callback type, and parameters. The implemented * callback types are: * * 'setup' called at the very beginning, parameter is a UI object * that should be used for all output * 'message' the parameter is a string with an informational message * 'saveas' may be used to save with a different file name, the * parameter is the filename that is about to be used. * If a 'saveas' callback returns a non-empty string, * that file name will be used as the filename instead. * Note that $save_dir will not be affected by this, only * the basename of the file. * 'start' download is starting, parameter is number of bytes * that are expected, or -1 if unknown * 'bytesread' parameter is the number of bytes read so far * 'done' download is complete, parameter is the total number * of bytes read * 'connfailed' if the TCP/SSL connection fails, this callback is called * with array(host,port,errno,errmsg) * 'writefailed' if writing to disk fails, this callback is called * with array(destfile,errmsg) * * If an HTTP proxy has been configured (http_proxy PEAR_Config * setting), the proxy will be used. * * @param string $url the URL to download * @param object $ui PEAR_Frontend_* instance * @param object $config PEAR_Config instance * @param string $save_dir directory to save file in * @param mixed $callback function/method to call for status * updates * @param false|string|array $lastmodified header values to check against for caching * use false to return the header values from this download * @param false|array $accept Accept headers to send * @param false|string $channel Channel to use for retrieving authentication * @return mixed Returns the full path of the downloaded file or a PEAR * error on failure. If the error is caused by * socket-related errors, the error object will * have the fsockopen error code available through * getCode(). If caching is requested, then return the header * values. * If $lastmodified was given and the there are no changes, * boolean false is returned. * * @access public */ public static function _downloadHttp( $object, $url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null, $accept = false, $channel = false ) { static $redirect = 0; // always reset , so we are clean case of error $wasredirect = $redirect; $redirect = 0; if ($callback) { call_user_func($callback, 'setup', array(&$ui)); } $info = parse_url($url); if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) { return PEAR::raiseError('Cannot download non-http URL "' . $url . '"'); } if (!isset($info['host'])) { return PEAR::raiseError('Cannot download from non-URL "' . $url . '"'); } $host = isset($info['host']) ? $info['host'] : null; $port = isset($info['port']) ? $info['port'] : null; $path = isset($info['path']) ? $info['path'] : null; if ($object !== null) { $config = $object->config; } else { $config = &PEAR_Config::singleton(); } $proxy = new PEAR_Proxy($config); if ($proxy->isProxyConfigured() && $callback) { call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); } if (empty($port)) { $port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80; } $scheme = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http'; $secure = ($scheme == 'https'); $fp = $proxy->openSocket($host, $port, $secure); if (PEAR::isError($fp)) { if ($callback) { $errno = $fp->getCode(); $errstr = $fp->getMessage(); call_user_func($callback, 'connfailed', array($host, $port, $errno, $errstr)); } return $fp; } $requestPath = $path; if ($proxy->isProxyConfigured()) { $requestPath = $url; } if ($lastmodified === false || $lastmodified) { $request = "GET $requestPath HTTP/1.1\r\n"; } else { $request = "GET $requestPath HTTP/1.0\r\n"; } $request .= "Host: $host\r\n"; $ifmodifiedsince = ''; if (is_array($lastmodified)) { if (isset($lastmodified['Last-Modified'])) { $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n"; } if (isset($lastmodified['ETag'])) { $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n"; } } else { $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : ''); } $request .= $ifmodifiedsince . "User-Agent: PEAR/1.10.16/PHP/" . PHP_VERSION . "\r\n"; if ($object !== null) { // only pass in authentication for non-static calls $username = $config->get('username', null, $channel); $password = $config->get('password', null, $channel); if ($username && $password) { $tmp = base64_encode("$username:$password"); $request .= "Authorization: Basic $tmp\r\n"; } } $proxyAuth = $proxy->getProxyAuth(); if ($proxyAuth) { $request .= 'Proxy-Authorization: Basic ' . $proxyAuth . "\r\n"; } if ($accept) { $request .= 'Accept: ' . implode(', ', $accept) . "\r\n"; } $request .= "Connection: close\r\n"; $request .= "\r\n"; fwrite($fp, $request); $headers = array(); $reply = 0; while (trim($line = fgets($fp, 1024))) { if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) { $headers[strtolower($matches[1])] = trim($matches[2]); } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { $reply = (int)$matches[1]; if ($reply == 304 && ($lastmodified || ($lastmodified === false))) { return false; } if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) { return PEAR::raiseError("File $scheme://$host:$port$path not valid (received: $line)"); } } } if ($reply != 200) { if (!isset($headers['location'])) { return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirected but no location)"); } if ($wasredirect > 4) { return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirection looped more than 5 times)"); } $redirect = $wasredirect + 1; return static::_downloadHttp($object, $headers['location'], $ui, $save_dir, $callback, $lastmodified, $accept); } if (isset($headers['content-disposition']) && preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) { $save_as = basename($matches[1]); } else { $save_as = basename($url); } if ($callback) { $tmp = call_user_func($callback, 'saveas', $save_as); if ($tmp) { $save_as = $tmp; } } $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as; if (is_link($dest_file)) { return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $dest_file . ' as it is symlinked to ' . readlink($dest_file) . ' - Possible symlink attack'); } if (!$wp = @fopen($dest_file, 'wb')) { fclose($fp); if ($callback) { call_user_func($callback, 'writefailed', array($dest_file, error_get_last()["message"])); } return PEAR::raiseError("could not open $dest_file for writing"); } $length = isset($headers['content-length']) ? $headers['content-length'] : -1; $bytes = 0; if ($callback) { call_user_func($callback, 'start', array(basename($dest_file), $length)); } while ($data = fread($fp, 1024)) { $bytes += strlen($data); if ($callback) { call_user_func($callback, 'bytesread', $bytes); } if (!@fwrite($wp, $data)) { fclose($fp); if ($callback) { call_user_func($callback, 'writefailed', array($dest_file, error_get_last()["message"])); } return PEAR::raiseError( "$dest_file: write failed (" . error_get_last()["message"] . ")"); } } fclose($fp); fclose($wp); if ($callback) { call_user_func($callback, 'done', $bytes); } if ($lastmodified === false || $lastmodified) { if (isset($headers['etag'])) { $lastmodified = array('ETag' => $headers['etag']); } if (isset($headers['last-modified'])) { if (is_array($lastmodified)) { $lastmodified['Last-Modified'] = $headers['last-modified']; } else { $lastmodified = $headers['last-modified']; } } return array($dest_file, $lastmodified, $headers); } return $dest_file; } } PK!b PEAR/ErrorStack.phpnu[ * @copyright 2004-2008 Greg Beaver * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR_ErrorStack */ /** * Singleton storage * * Format: *
 * array(
 *  'package1' => PEAR_ErrorStack object,
 *  'package2' => PEAR_ErrorStack object,
 *  ...
 * )
 * 
* @access private * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] */ $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array(); /** * Global error callback (default) * * This is only used if set to non-false. * is the default callback for * all packages, whereas specific packages may set a default callback * for all instances, regardless of whether they are a singleton or not. * * To exclude non-singletons, only set the local callback for the singleton * @see PEAR_ErrorStack::setDefaultCallback() * @access private * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] */ $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array( '*' => false, ); /** * Global Log object (default) * * This is only used if set to non-false. Use to set a default log object for * all stacks, regardless of instantiation order or location * @see PEAR_ErrorStack::setDefaultLogger() * @access private * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] */ $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false; /** * Global Overriding Callback * * This callback will override any error callbacks that specific loggers have set. * Use with EXTREME caution * @see PEAR_ErrorStack::staticPushCallback() * @access private * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] */ $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); /**#@+ * One of four possible return values from the error Callback * @see PEAR_ErrorStack::_errorCallback() */ /** * If this is returned, then the error will be both pushed onto the stack * and logged. */ define('PEAR_ERRORSTACK_PUSHANDLOG', 1); /** * If this is returned, then the error will only be pushed onto the stack, * and not logged. */ define('PEAR_ERRORSTACK_PUSH', 2); /** * If this is returned, then the error will only be logged, but not pushed * onto the error stack. */ define('PEAR_ERRORSTACK_LOG', 3); /** * If this is returned, then the error is completely ignored. */ define('PEAR_ERRORSTACK_IGNORE', 4); /** * If this is returned, then the error is logged and die() is called. */ define('PEAR_ERRORSTACK_DIE', 5); /**#@-*/ /** * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in * the singleton method. */ define('PEAR_ERRORSTACK_ERR_NONCLASS', 1); /** * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()} * that has no __toString() method */ define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2); /** * Error Stack Implementation * * Usage: * * // global error stack * $global_stack = &PEAR_ErrorStack::singleton('MyPackage'); * // local error stack * $local_stack = new PEAR_ErrorStack('MyPackage'); * * @author Greg Beaver * @version 1.10.16 * @package PEAR_ErrorStack * @category Debugging * @copyright 2004-2008 Greg Beaver * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR_ErrorStack */ class PEAR_ErrorStack { /** * Errors are stored in the order that they are pushed on the stack. * @since 0.4alpha Errors are no longer organized by error level. * This renders pop() nearly unusable, and levels could be more easily * handled in a callback anyway * @var array * @access private */ var $_errors = array(); /** * Storage of errors by level. * * Allows easy retrieval and deletion of only errors from a particular level * @since PEAR 1.4.0dev * @var array * @access private */ var $_errorsByLevel = array(); /** * Package name this error stack represents * @var string * @access protected */ var $_package; /** * Determines whether a PEAR_Error is thrown upon every error addition * @var boolean * @access private */ var $_compat = false; /** * If set to a valid callback, this will be used to generate the error * message from the error code, otherwise the message passed in will be * used * @var false|string|array * @access private */ var $_msgCallback = false; /** * If set to a valid callback, this will be used to generate the error * context for an error. For PHP-related errors, this will be a file * and line number as retrieved from debug_backtrace(), but can be * customized for other purposes. The error might actually be in a separate * configuration file, or in a database query. * @var false|string|array * @access protected */ var $_contextCallback = false; /** * If set to a valid callback, this will be called every time an error * is pushed onto the stack. The return value will be used to determine * whether to allow an error to be pushed or logged. * * The return value must be one an PEAR_ERRORSTACK_* constant * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG * @var false|string|array * @access protected */ var $_errorCallback = array(); /** * PEAR::Log object for logging errors * @var false|Log * @access protected */ var $_logger = false; /** * Error messages - designed to be overridden * @var array * @abstract */ var $_errorMsgs = array(); /** * Set up a new error stack * * @param string $package name of the package this error stack represents * @param callback $msgCallback callback used for error message generation * @param callback $contextCallback callback used for context generation, * defaults to {@link getFileLine()} * @param boolean $throwPEAR_Error */ function __construct($package, $msgCallback = false, $contextCallback = false, $throwPEAR_Error = false) { $this->_package = $package; $this->setMessageCallback($msgCallback); $this->setContextCallback($contextCallback); $this->_compat = $throwPEAR_Error; } /** * Return a single error stack for this package. * * Note that all parameters are ignored if the stack for package $package * has already been instantiated * @param string $package name of the package this error stack represents * @param callback $msgCallback callback used for error message generation * @param callback $contextCallback callback used for context generation, * defaults to {@link getFileLine()} * @param boolean $throwPEAR_Error * @param string $stackClass class to instantiate * * @return PEAR_ErrorStack */ public static function &singleton( $package, $msgCallback = false, $contextCallback = false, $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack' ) { if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; } if (!class_exists($stackClass)) { if (function_exists('debug_backtrace')) { $trace = debug_backtrace(); } PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, 'exception', array('stackclass' => $stackClass), 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', false, $trace); } $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error); return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; } /** * Internal error handler for PEAR_ErrorStack class * * Dies if the error is an exception (and would have died anyway) * @access private */ function _handleError($err) { if ($err['level'] == 'exception') { $message = $err['message']; if (isset($_SERVER['REQUEST_URI'])) { echo '
'; } else { echo "\n"; } var_dump($err['context']); die($message); } } /** * Set up a PEAR::Log object for all error stacks that don't have one * @param Log $log */ public static function setDefaultLogger(&$log) { if (is_object($log) && method_exists($log, 'log') ) { $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; } elseif (is_callable($log)) { $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; } } /** * Set up a PEAR::Log object for this error stack * @param Log $log */ function setLogger(&$log) { if (is_object($log) && method_exists($log, 'log') ) { $this->_logger = &$log; } elseif (is_callable($log)) { $this->_logger = &$log; } } /** * Set an error code => error message mapping callback * * This method sets the callback that can be used to generate error * messages for any instance * @param array|string Callback function/method */ function setMessageCallback($msgCallback) { if (!$msgCallback) { $this->_msgCallback = array(&$this, 'getErrorMessage'); } else { if (is_callable($msgCallback)) { $this->_msgCallback = $msgCallback; } } } /** * Get an error code => error message mapping callback * * This method returns the current callback that can be used to generate error * messages * @return array|string|false Callback function/method or false if none */ function getMessageCallback() { return $this->_msgCallback; } /** * Sets a default callback to be used by all error stacks * * This method sets the callback that can be used to generate error * messages for a singleton * @param array|string Callback function/method * @param string Package name, or false for all packages */ public static function setDefaultCallback($callback = false, $package = false) { if (!is_callable($callback)) { $callback = false; } $package = $package ? $package : '*'; $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback; } /** * Set a callback that generates context information (location of error) for an error stack * * This method sets the callback that can be used to generate context * information for an error. Passing in NULL will disable context generation * and remove the expensive call to debug_backtrace() * @param array|string|null Callback function/method */ function setContextCallback($contextCallback) { if ($contextCallback === null) { return $this->_contextCallback = false; } if (!$contextCallback) { $this->_contextCallback = array(&$this, 'getFileLine'); } else { if (is_callable($contextCallback)) { $this->_contextCallback = $contextCallback; } } } /** * Set an error Callback * If set to a valid callback, this will be called every time an error * is pushed onto the stack. The return value will be used to determine * whether to allow an error to be pushed or logged. * * The return value must be one of the ERRORSTACK_* constants. * * This functionality can be used to emulate PEAR's pushErrorHandling, and * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of * the error stack or logging * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG * @see popCallback() * @param string|array $cb */ function pushCallback($cb) { array_push($this->_errorCallback, $cb); } /** * Remove a callback from the error callback stack * @see pushCallback() * @return array|string|false */ function popCallback() { if (!count($this->_errorCallback)) { return false; } return array_pop($this->_errorCallback); } /** * Set a temporary overriding error callback for every package error stack * * Use this to temporarily disable all existing callbacks (can be used * to emulate the @ operator, for instance) * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG * @see staticPopCallback(), pushCallback() * @param string|array $cb */ public static function staticPushCallback($cb) { array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb); } /** * Remove a temporary overriding error callback * @see staticPushCallback() * @return array|string|false */ public static function staticPopCallback() { $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) { $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); } return $ret; } /** * Add an error to the stack * * If the message generator exists, it is called with 2 parameters. * - the current Error Stack object * - an array that is in the same format as an error. Available indices * are 'code', 'package', 'time', 'params', 'level', and 'context' * * Next, if the error should contain context information, this is * handled by the context grabbing method. * Finally, the error is pushed onto the proper error stack * @param int $code Package-specific error code * @param string $level Error level. This is NOT spell-checked * @param array $params associative array of error parameters * @param string $msg Error message, or a portion of it if the message * is to be generated * @param array $repackage If this error re-packages an error pushed by * another package, place the array returned from * {@link pop()} in this parameter * @param array $backtrace Protected parameter: use this to pass in the * {@link debug_backtrace()} that should be used * to find error context * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also * thrown. If a PEAR_Error is returned, the userinfo * property is set to the following array: * * * array( * 'code' => $code, * 'params' => $params, * 'package' => $this->_package, * 'level' => $level, * 'time' => time(), * 'context' => $context, * 'message' => $msg, * //['repackage' => $err] repackaged error array/Exception class * ); * * * Normally, the previous array is returned. */ function push($code, $level = 'error', $params = array(), $msg = false, $repackage = false, $backtrace = false) { $context = false; // grab error context if ($this->_contextCallback) { if (!$backtrace) { $backtrace = debug_backtrace(); } $context = call_user_func($this->_contextCallback, $code, $params, $backtrace); } // save error $time = explode(' ', microtime()); $time = $time[1] + $time[0]; $err = array( 'code' => $code, 'params' => $params, 'package' => $this->_package, 'level' => $level, 'time' => $time, 'context' => $context, 'message' => $msg, ); if ($repackage) { $err['repackage'] = $repackage; } // set up the error message, if necessary if ($this->_msgCallback) { $msg = call_user_func_array($this->_msgCallback, array(&$this, $err)); $err['message'] = $msg; } $push = $log = true; $die = false; // try the overriding callback first $callback = $this->staticPopCallback(); if ($callback) { $this->staticPushCallback($callback); } if (!is_callable($callback)) { // try the local callback next $callback = $this->popCallback(); if (is_callable($callback)) { $this->pushCallback($callback); } else { // try the default callback $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ? $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] : $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*']; } } if (is_callable($callback)) { switch(call_user_func($callback, $err)){ case PEAR_ERRORSTACK_IGNORE: return $err; break; case PEAR_ERRORSTACK_PUSH: $log = false; break; case PEAR_ERRORSTACK_LOG: $push = false; break; case PEAR_ERRORSTACK_DIE: $die = true; break; // anything else returned has the same effect as pushandlog } } if ($push) { array_unshift($this->_errors, $err); if (!isset($this->_errorsByLevel[$err['level']])) { $this->_errorsByLevel[$err['level']] = array(); } $this->_errorsByLevel[$err['level']][] = &$this->_errors[0]; } if ($log) { if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) { $this->_log($err); } } if ($die) { die(); } if ($this->_compat && $push) { return $this->raiseError($msg, $code, null, null, $err); } return $err; } /** * Static version of {@link push()} * * @param string $package Package name this error belongs to * @param int $code Package-specific error code * @param string $level Error level. This is NOT spell-checked * @param array $params associative array of error parameters * @param string $msg Error message, or a portion of it if the message * is to be generated * @param array $repackage If this error re-packages an error pushed by * another package, place the array returned from * {@link pop()} in this parameter * @param array $backtrace Protected parameter: use this to pass in the * {@link debug_backtrace()} that should be used * to find error context * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also * thrown. see docs for {@link push()} */ public static function staticPush( $package, $code, $level = 'error', $params = array(), $msg = false, $repackage = false, $backtrace = false ) { $s = &PEAR_ErrorStack::singleton($package); if ($s->_contextCallback) { if (!$backtrace) { if (function_exists('debug_backtrace')) { $backtrace = debug_backtrace(); } } } return $s->push($code, $level, $params, $msg, $repackage, $backtrace); } /** * Log an error using PEAR::Log * @param array $err Error array * @param array $levels Error level => Log constant map * @access protected */ function _log($err) { if ($this->_logger) { $logger = &$this->_logger; } else { $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']; } if (is_a($logger, 'Log')) { $levels = array( 'exception' => PEAR_LOG_CRIT, 'alert' => PEAR_LOG_ALERT, 'critical' => PEAR_LOG_CRIT, 'error' => PEAR_LOG_ERR, 'warning' => PEAR_LOG_WARNING, 'notice' => PEAR_LOG_NOTICE, 'info' => PEAR_LOG_INFO, 'debug' => PEAR_LOG_DEBUG); if (isset($levels[$err['level']])) { $level = $levels[$err['level']]; } else { $level = PEAR_LOG_INFO; } $logger->log($err['message'], $level, $err); } else { // support non-standard logs call_user_func($logger, $err); } } /** * Pop an error off of the error stack * * @return false|array * @since 0.4alpha it is no longer possible to specify a specific error * level to return - the last error pushed will be returned, instead */ function pop() { $err = @array_shift($this->_errors); if (!is_null($err)) { @array_pop($this->_errorsByLevel[$err['level']]); if (!count($this->_errorsByLevel[$err['level']])) { unset($this->_errorsByLevel[$err['level']]); } } return $err; } /** * Pop an error off of the error stack, static method * * @param string package name * @return boolean * @since PEAR1.5.0a1 */ static function staticPop($package) { if ($package) { if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { return false; } return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop(); } } /** * Determine whether there are any errors on the stack * @param string|array Level name. Use to determine if any errors * of level (string), or levels (array) have been pushed * @return boolean */ function hasErrors($level = false) { if ($level) { return isset($this->_errorsByLevel[$level]); } return count($this->_errors); } /** * Retrieve all errors since last purge * * @param boolean set in order to empty the error stack * @param string level name, to return only errors of a particular severity * @return array */ function getErrors($purge = false, $level = false) { if (!$purge) { if ($level) { if (!isset($this->_errorsByLevel[$level])) { return array(); } else { return $this->_errorsByLevel[$level]; } } else { return $this->_errors; } } if ($level) { $ret = $this->_errorsByLevel[$level]; foreach ($this->_errorsByLevel[$level] as $i => $unused) { // entries are references to the $_errors array $this->_errorsByLevel[$level][$i] = false; } // array_filter removes all entries === false $this->_errors = array_filter($this->_errors); unset($this->_errorsByLevel[$level]); return $ret; } $ret = $this->_errors; $this->_errors = array(); $this->_errorsByLevel = array(); return $ret; } /** * Determine whether there are any errors on a single error stack, or on any error stack * * The optional parameter can be used to test the existence of any errors without the need of * singleton instantiation * @param string|false Package name to check for errors * @param string Level name to check for a particular severity * @return boolean */ public static function staticHasErrors($package = false, $level = false) { if ($package) { if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { return false; } return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level); } foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { if ($obj->hasErrors($level)) { return true; } } return false; } /** * Get a list of all errors since last purge, organized by package * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be * @param boolean $purge Set to purge the error stack of existing errors * @param string $level Set to a level name in order to retrieve only errors of a particular level * @param boolean $merge Set to return a flat array, not organized by package * @param array $sortfunc Function used to sort a merged array - default * sorts by time, and should be good for most cases * * @return array */ public static function staticGetErrors( $purge = false, $level = false, $merge = false, $sortfunc = array('PEAR_ErrorStack', '_sortErrors') ) { $ret = array(); if (!is_callable($sortfunc)) { $sortfunc = array('PEAR_ErrorStack', '_sortErrors'); } foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level); if ($test) { if ($merge) { $ret = array_merge($ret, $test); } else { $ret[$package] = $test; } } } if ($merge) { usort($ret, $sortfunc); } return $ret; } /** * Error sorting function, sorts by time * @access private */ public static function _sortErrors($a, $b) { if ($a['time'] == $b['time']) { return 0; } if ($a['time'] < $b['time']) { return 1; } return -1; } /** * Standard file/line number/function/class context callback * * This function uses a backtrace generated from {@link debug_backtrace()} * and so will not work at all in PHP < 4.3.0. The frame should * reference the frame that contains the source of the error. * @return array|false either array('file' => file, 'line' => line, * 'function' => function name, 'class' => class name) or * if this doesn't work, then false * @param unused * @param integer backtrace frame. * @param array Results of debug_backtrace() */ public static function getFileLine($code, $params, $backtrace = null) { if ($backtrace === null) { return false; } $frame = 0; $functionframe = 1; if (!isset($backtrace[1])) { $functionframe = 0; } else { while (isset($backtrace[$functionframe]['function']) && $backtrace[$functionframe]['function'] == 'eval' && isset($backtrace[$functionframe + 1])) { $functionframe++; } } if (isset($backtrace[$frame])) { if (!isset($backtrace[$frame]['file'])) { $frame++; } $funcbacktrace = $backtrace[$functionframe]; $filebacktrace = $backtrace[$frame]; $ret = array('file' => $filebacktrace['file'], 'line' => $filebacktrace['line']); // rearrange for eval'd code or create function errors if (strpos($filebacktrace['file'], '(') && preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'], $matches)) { $ret['file'] = $matches[1]; $ret['line'] = $matches[2] + 0; } if (isset($funcbacktrace['function']) && isset($backtrace[1])) { if ($funcbacktrace['function'] != 'eval') { if ($funcbacktrace['function'] == '__lambda_func') { $ret['function'] = 'create_function() code'; } else { $ret['function'] = $funcbacktrace['function']; } } } if (isset($funcbacktrace['class']) && isset($backtrace[1])) { $ret['class'] = $funcbacktrace['class']; } return $ret; } return false; } /** * Standard error message generation callback * * This method may also be called by a custom error message generator * to fill in template values from the params array, simply * set the third parameter to the error message template string to use * * The special variable %__msg% is reserved: use it only to specify * where a message passed in by the user should be placed in the template, * like so: * * Error message: %msg% - internal error * * If the message passed like so: * * * $stack->push(ERROR_CODE, 'error', array(), 'server error 500'); * * * The returned error message will be "Error message: server error 500 - * internal error" * @param PEAR_ErrorStack * @param array * @param string|false Pre-generated error message template * * @return string */ public static function getErrorMessage(&$stack, $err, $template = false) { if ($template) { $mainmsg = $template; } else { $mainmsg = $stack->getErrorMessageTemplate($err['code']); } $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg); if (is_array($err['params']) && count($err['params'])) { foreach ($err['params'] as $name => $val) { if (is_array($val)) { // @ is needed in case $val is a multi-dimensional array $val = @implode(', ', $val); } if (is_object($val)) { if (method_exists($val, '__toString')) { $val = $val->__toString(); } else { PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING, 'warning', array('obj' => get_class($val)), 'object %obj% passed into getErrorMessage, but has no __toString() method'); $val = 'Object'; } } $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg); } } return $mainmsg; } /** * Standard Error Message Template generator from code * @return string */ function getErrorMessageTemplate($code) { if (!isset($this->_errorMsgs[$code])) { return '%__msg%'; } return $this->_errorMsgs[$code]; } /** * Set the Error Message Template array * * The array format must be: *
     * array(error code => 'message template',...)
     * 
* * Error message parameters passed into {@link push()} will be used as input * for the error message. If the template is 'message %foo% was %bar%', and the * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will * be 'message one was six' * @return string */ function setErrorMessageTemplate($template) { $this->_errorMsgs = $template; } /** * emulate PEAR::raiseError() * * @return PEAR_Error */ function raiseError() { require_once 'PEAR.php'; $args = func_get_args(); return call_user_func_array(array('PEAR', 'raiseError'), $args); } } $stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); $stack->pushCallback(array('PEAR_ErrorStack', '_handleError')); ?> PK!(PzPEAR/Proxy.phpnu[config = $config; $this->_parseProxyInfo(); } /** * @access private */ function _parseProxyInfo() { $this->proxy_host = $this->proxy_port = $this->proxy_user = $this->proxy_pass = ''; if ($this->config->get('http_proxy')&& $proxy = parse_url($this->config->get('http_proxy')) ) { $this->proxy_host = isset($proxy['host']) ? $proxy['host'] : null; $this->proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; $this->proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; $this->proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; $this->proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http'; } } /** * @access private */ function _httpConnect($fp, $host, $port) { fwrite($fp, "CONNECT $host:$port HTTP/1.1\r\n"); fwrite($fp, "Host: $host:$port\r\n"); if ($this->getProxyAuth()) { fwrite($fp, 'Proxy-Authorization: Basic ' . $this->getProxyAuth() . "\r\n"); } fwrite($fp, "\r\n"); while ($line = trim(fgets($fp, 1024))) { if (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { $code = (int)$matches[1]; /* as per RFC 2817 */ if ($code < 200 || $code >= 300) { return PEAR::raiseError("Establishing a CONNECT tunnel through proxy failed with response code $code"); } } } // connection was successful -- establish SSL through // the tunnel $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT; if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; } // set the correct hostname for working hostname // verification stream_context_set_option($fp, 'ssl', 'peer_name', $host); // blocking socket needed for // stream_socket_enable_crypto() // see // stream_set_blocking ($fp, true); $crypto_res = stream_socket_enable_crypto($fp, true, $crypto_method); if (!$crypto_res) { return PEAR::raiseError("Could not establish SSL connection through proxy: $crypto_res"); } return true; } /** * get the authorization information for the proxy, encoded to be * passed in the Proxy-Authentication HTTP header. * @return null|string the encoded authentication information if a * proxy and authentication is configured, null * otherwise. */ function getProxyAuth() { if ($this->isProxyConfigured() && $this->proxy_user != '') { return base64_encode($this->proxy_user . ':' . $this->proxy_pass); } return null; } function getProxyUser() { return $this->proxy_user; } /** * Check if we are configured to use a proxy. * * @return boolean true if we are configured to use a proxy, false * otherwise. * @access public */ function isProxyConfigured() { return $this->proxy_host != ''; } /** * Open a socket to a remote server, possibly involving a HTTP * proxy. * * If an HTTP proxy has been configured (http_proxy PEAR_Config * setting), the proxy will be used. * * @param string $host the host to connect to * @param string $port the port to connect to * @param boolean $secure if true, establish a secure connection * using TLS. * @access public */ function openSocket($host, $port, $secure = false) { if ($this->isProxyConfigured()) { $fp = @fsockopen( $this->proxy_host, $this->proxy_port, $errno, $errstr, 15 ); if (!$fp) { return PEAR::raiseError("Connection to the proxy failed: $errstr", -9276); } /* HTTPS is to be used and we have a proxy, use CONNECT verb */ if ($secure) { $res = $this->_httpConnect($fp, $host, $port); if (PEAR::isError($res)) { return $res; } } } else { if ($secure) { $host = 'ssl://' . $host; } $fp = @fsockopen($host, $port, $errno, $errstr); if (!$fp) { return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); } } return $fp; } } PK!'PEAR/RunTest.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.3.3 */ /** * for error handling */ require_once 'PEAR.php'; require_once 'PEAR/Config.php'; define('DETAILED', 1); putenv("PHP_PEAR_RUNTESTS=1"); /** * Simplified version of PHP's test suite * * Try it with: * * $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);' * * * @category pear * @package PEAR * @author Tomas V.V.Cox * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.3.3 */ class PEAR_RunTest { var $_headers = array(); var $_logger; var $_options; var $_php; var $tests_count; var $xdebug_loaded; /** * Saved value of php executable, used to reset $_php when we * have a test that uses cgi * * @var unknown_type */ var $_savephp; var $ini_overwrites = array( 'output_handler=', 'open_basedir=', 'disable_functions=', 'output_buffering=Off', 'display_errors=1', 'log_errors=0', 'html_errors=0', 'report_memleaks=0', 'report_zend_debug=0', 'docref_root=', 'docref_ext=.html', 'error_prepend_string=', 'error_append_string=', 'auto_prepend_file=', 'auto_append_file=', 'xdebug.default_enable=0', 'allow_url_fopen=1', ); /** * An object that supports the PEAR_Common->log() signature, or null * @param PEAR_Common|null */ function __construct($logger = null, $options = array()) { if (!defined('E_DEPRECATED')) { define('E_DEPRECATED', 0); } if (!defined('E_STRICT')) { define('E_STRICT', 0); } $excluded_error_reporting = E_DEPRECATED; if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) { $excluded_error_reporting |= E_STRICT; } $this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~$excluded_error_reporting); if (is_null($logger)) { require_once 'PEAR/Common.php'; $logger = new PEAR_Common; } $this->_logger = $logger; $this->_options = $options; $conf = &PEAR_Config::singleton(); $this->_php = $conf->get('php_bin'); } /** * Taken from php-src/run-tests.php * * @param string $commandline command name * @param array $env * @param string $stdin standard input to pass to the command * @return unknown */ function system_with_timeout($commandline, $env = null, $stdin = null) { $data = ''; $proc = proc_open($commandline, array( 0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w') ), $pipes, null, $env, array('suppress_errors' => true)); if (!$proc) { return false; } if (is_string($stdin)) { fwrite($pipes[0], $stdin); } fclose($pipes[0]); while (true) { /* hide errors from interrupted syscalls */ $r = $pipes; unset($r[0]); $e = $w = []; $n = @stream_select($r, $w, $e, 60); if ($n === 0) { /* timed out */ $data .= "\n ** ERROR: process timed out **\n"; proc_terminate($proc); return array(1234567890, $data); } else if ($n > 0) { $line = fread($pipes[1], 8192); if (strlen($line) == 0) { /* EOF */ break; } $data .= $line; } } if (function_exists('proc_get_status')) { $stat = proc_get_status($proc); if ($stat['signaled']) { $data .= "\nTermsig=".$stat['stopsig']; } } $code = proc_close($proc); if (function_exists('proc_get_status')) { $code = $stat['exitcode']; } return array($code, $data); } /** * Turns a PHP INI string into an array * * Turns -d "include_path=/foo/bar" into this: * array( * 'include_path' => array( * 'operator' => '-d', * 'value' => '/foo/bar', * ) * ) * Works both with quotes and without * * @param string an PHP INI string, -d "include_path=/foo/bar" * @return array */ function iniString2array($ini_string) { if (!$ini_string) { return array(); } $split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY); $key = $split[1][0] == '"' ? substr($split[1], 1) : $split[1]; $value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2]; // FIXME review if this is really the struct to go with $array = array($key => array('operator' => $split[0], 'value' => $value)); return $array; } function settings2array($settings, $ini_settings) { foreach ($settings as $setting) { if (strpos($setting, '=') !== false) { $setting = explode('=', $setting, 2); $name = trim(strtolower($setting[0])); $value = trim($setting[1]); $ini_settings[$name] = $value; } } return $ini_settings; } function settings2params($ini_settings) { $settings = ''; foreach ($ini_settings as $name => $value) { if (is_array($value)) { $operator = $value['operator']; $value = $value['value']; } else { $operator = '-d'; } $value = addslashes($value); $settings .= " $operator \"$name=$value\""; } return $settings; } function _preparePhpBin($php, $file, $ini_settings) { $file = escapeshellarg($file); $cmd = $php . $ini_settings . ' -f ' . $file; return $cmd; } function runPHPUnit($file, $ini_settings = '') { if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) { $file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file); } elseif (file_exists($file)) { $file = realpath($file); } $cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings); if (isset($this->_logger)) { $this->_logger->log(2, 'Running command "' . $cmd . '"'); } $savedir = getcwd(); // in case the test moves us around chdir(dirname($file)); echo `$cmd`; chdir($savedir); return 'PASSED'; // we have no way of knowing this information so assume passing } /** * Runs an individual test case. * * @param string The filename of the test * @param array|string INI settings to be applied to the test run * @param integer Number what the current running test is of the * whole test suite being runned. * * @return string|object Returns PASSED, WARNED, FAILED depending on how the * test came out. * PEAR Error when the tester it self fails */ function run($file, $ini_settings = array(), $test_number = 1) { $this->_restorePHPBinary(); if (empty($this->_options['cgi'])) { // try to see if php-cgi is in the path $res = $this->system_with_timeout('php-cgi -v'); if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) { $this->_options['cgi'] = 'php-cgi'; } } if (1 < $len = strlen($this->tests_count)) { $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT); $test_nr = "[$test_number/$this->tests_count] "; } else { $test_nr = ''; } $file = realpath($file); $section_text = $this->_readFile($file); if (PEAR::isError($section_text)) { return $section_text; } if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) { return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file"); } $cwd = getcwd(); $pass_options = ''; if (!empty($this->_options['ini'])) { $pass_options = $this->_options['ini']; } if (is_string($ini_settings)) { $ini_settings = $this->iniString2array($ini_settings); } $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings); if ($section_text['INI']) { if (strpos($section_text['INI'], '{PWD}') !== false) { $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']); } $ini = preg_split( "/[\n\r]+/", $section_text['INI']); $ini_settings = $this->settings2array($ini, $ini_settings); } $ini_settings = $this->settings2params($ini_settings); $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file); $tested = trim($section_text['TEST']); $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' '; if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) || !empty($section_text['UPLOAD']) || !empty($section_text['GET']) || !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) { if (empty($this->_options['cgi'])) { if (!isset($this->_options['quiet'])) { $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')"); } if (isset($this->_options['tapoutput'])) { return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info'); } return 'SKIPPED'; } $this->_savePHPBinary(); $this->_php = $this->_options['cgi']; } $temp_dir = realpath(dirname($file)); $main_file_name = basename($file, 'phpt'); $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff'; $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log'; $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp'; $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out'; $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem'; $temp_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php'; $temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php'; $temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php'; $tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.'); // unlink old test results $this->_cleanupOldFiles($file); // Check if test should be skipped. $res = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings); if ($res == 'SKIPPED' || count($res) != 2) { return $res; } $info = $res['info']; $warn = $res['warn']; // We've satisfied the preconditions - run the test! if (isset($this->_options['coverage']) && $this->xdebug_loaded) { $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug'; $text = "\n" . 'function coverage_shutdown() {' . "\n" . ' $xdebug = var_export(xdebug_get_code_coverage(), true);'; if (!function_exists('file_put_contents')) { $text .= "\n" . ' $fh = fopen(\'' . $xdebug_file . '\', "wb");' . "\n" . ' if ($fh !== false) {' . "\n" . ' fwrite($fh, $xdebug);' . "\n" . ' fclose($fh);' . "\n" . ' }'; } else { $text .= "\n" . ' file_put_contents(\'' . $xdebug_file . '\', $xdebug);'; } // Workaround for http://pear.php.net/bugs/bug.php?id=17292 $lines = explode("\n", $section_text['FILE']); $numLines = count($lines); $namespace = ''; $coverage_shutdown = 'coverage_shutdown'; if ( substr($lines[0], 0, 2) == 'save_text($temp_file, "save_text($temp_file, $section_text['FILE']); } $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : ''; $cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings); $cmd.= "$args 2>&1"; if (isset($this->_logger)) { $this->_logger->log(2, 'Running command "' . $cmd . '"'); } // Reset environment from any previous test. $env = $this->_resetEnv($section_text, $temp_file); $section_text = $this->_processUpload($section_text, $file); if (PEAR::isError($section_text)) { return $section_text; } if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) { $post = trim($section_text['POST_RAW']); $raw_lines = explode("\n", $post); $request = ''; $started = false; foreach ($raw_lines as $i => $line) { if (empty($env['CONTENT_TYPE']) && preg_match('/^Content-Type:(.*)/i', $line, $res)) { $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1])); continue; } if ($started) { $request .= "\n"; } $started = true; $request .= $line; } $env['CONTENT_LENGTH'] = strlen($request); $env['REQUEST_METHOD'] = 'POST'; $this->save_text($tmp_post, $request); $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post"; } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) { $post = trim($section_text['POST']); $this->save_text($tmp_post, $post); $content_length = strlen($post); $env['REQUEST_METHOD'] = 'POST'; $env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; $env['CONTENT_LENGTH'] = $content_length; $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post"; } else { $env['REQUEST_METHOD'] = 'GET'; $env['CONTENT_TYPE'] = ''; $env['CONTENT_LENGTH'] = ''; } if (OS_WINDOWS && isset($section_text['RETURNS'])) { ob_start(); system($cmd, $return_value); $out = ob_get_contents(); ob_end_clean(); $section_text['RETURNS'] = (int) trim($section_text['RETURNS']); $returnfail = ($return_value != $section_text['RETURNS']); } else { $returnfail = false; $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null; $out = $this->system_with_timeout($cmd, $env, $stdin); $return_value = $out[0]; $out = $out[1]; } $output = preg_replace('/\r\n/', "\n", trim($out)); if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) { @unlink(realpath($tmp_post)); } chdir($cwd); // in case the test moves us around /* when using CGI, strip the headers from the output */ $output = $this->_stripHeadersCGI($output); if (isset($section_text['EXPECTHEADERS'])) { $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']); $missing = array_diff_assoc($testheaders, $this->_headers); $changed = ''; foreach ($missing as $header => $value) { if (isset($this->_headers[$header])) { $changed .= "-$header: $value\n+$header: "; $changed .= $this->_headers[$header]; } else { $changed .= "-$header: $value\n"; } } if ($missing) { // tack on failed headers to output: $output .= "\n====EXPECTHEADERS FAILURE====:\n$changed"; } } $this->_testCleanup($section_text, $temp_clean); // Does the output match what is expected? do { if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { if (isset($section_text['EXPECTF'])) { $wanted = trim($section_text['EXPECTF']); } else { $wanted = trim($section_text['EXPECTREGEX']); } $wanted_re = preg_replace('/\r\n/', "\n", $wanted); if (isset($section_text['EXPECTF'])) { $wanted_re = preg_quote($wanted_re, '/'); // Stick to basics $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy $wanted_re = str_replace("%S", ".*?", $wanted_re); //not greedy $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re); $wanted_re = str_replace("%d", "[0-9]+", $wanted_re); $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re); $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re); $wanted_re = str_replace("%c", ".", $wanted_re); // %f allows two points "-.0.0" but that is the best *simple* expression } /* DEBUG YOUR REGEX HERE var_dump($wanted_re); print(str_repeat('=', 80) . "\n"); var_dump($output); */ if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) { if (file_exists($temp_file)) { unlink($temp_file); } if (array_key_exists('FAIL', $section_text)) { break; } if (!isset($this->_options['quiet'])) { $this->_logger->log(0, "PASS $test_nr$tested$info"); } if (isset($this->_options['tapoutput'])) { return array('ok', ' - ' . $tested); } return 'PASSED'; } } else { if (isset($section_text['EXPECTFILE'])) { $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']); if (!($fp = @fopen($f, 'rb'))) { return PEAR::raiseError('--EXPECTFILE-- section file ' . $f . ' not found'); } fclose($fp); $section_text['EXPECT'] = file_get_contents($f); } if (isset($section_text['EXPECT'])) { $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT'])); } else { $wanted = ''; } // compare and leave on success if (!$returnfail && 0 == strcmp($output, $wanted)) { if (file_exists($temp_file)) { unlink($temp_file); } if (array_key_exists('FAIL', $section_text)) { break; } if (!isset($this->_options['quiet'])) { $this->_logger->log(0, "PASS $test_nr$tested$info"); } if (isset($this->_options['tapoutput'])) { return array('ok', ' - ' . $tested); } return 'PASSED'; } } } while (false); if (array_key_exists('FAIL', $section_text)) { // we expect a particular failure // this is only used for testing PEAR_RunTest $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null; $faildiff = $this->generate_diff($wanted, $output, null, $expectf); $faildiff = preg_replace('/\r/', '', $faildiff); $wanted = preg_replace('/\r/', '', trim($section_text['FAIL'])); if ($faildiff == $wanted) { if (!isset($this->_options['quiet'])) { $this->_logger->log(0, "PASS $test_nr$tested$info"); } if (isset($this->_options['tapoutput'])) { return array('ok', ' - ' . $tested); } return 'PASSED'; } unset($section_text['EXPECTF']); $output = $faildiff; if (isset($section_text['RETURNS'])) { return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' . $file); } } // Test failed so we need to report details. $txt = $warn ? 'WARN ' : 'FAIL '; $this->_logger->log(0, $txt . $test_nr . $tested . $info); // write .exp $res = $this->_writeLog($exp_filename, $wanted); if (PEAR::isError($res)) { return $res; } // write .out $res = $this->_writeLog($output_filename, $output); if (PEAR::isError($res)) { return $res; } // write .diff $returns = isset($section_text['RETURNS']) ? array(trim($section_text['RETURNS']), $return_value) : null; $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null; $data = $this->generate_diff($wanted, $output, $returns, $expectf); $res = $this->_writeLog($diff_filename, $data); if (isset($this->_options['showdiff'])) { $this->_logger->log(0, "========DIFF========"); $this->_logger->log(0, $data); $this->_logger->log(0, "========DONE========"); } if (PEAR::isError($res)) { return $res; } // write .log $data = " ---- EXPECTED OUTPUT $wanted ---- ACTUAL OUTPUT $output ---- FAILED "; if ($returnfail) { $data .= " ---- EXPECTED RETURN $section_text[RETURNS] ---- ACTUAL RETURN $return_value "; } $res = $this->_writeLog($log_filename, $data); if (PEAR::isError($res)) { return $res; } if (isset($this->_options['tapoutput'])) { $wanted = explode("\n", $wanted); $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted); $output = explode("\n", $output); $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output); return array($wanted . $output . 'not ok', ' - ' . $tested); } return $warn ? 'WARNED' : 'FAILED'; } function generate_diff($wanted, $output, $rvalue, $wanted_re) { $w = explode("\n", $wanted); $o = explode("\n", $output); $wr = explode("\n", $wanted_re); $w1 = array_diff_assoc($w, $o); $o1 = array_diff_assoc($o, $w); $o2 = $w2 = array(); foreach ($w1 as $idx => $val) { if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) || !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) { $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val; } } foreach ($o1 as $idx => $val) { if (!$wanted_re || !isset($wr[$idx]) || !preg_match('/^' . $wr[$idx] . '\\z/', $val)) { $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val; } } $diff = array_merge($w2, $o2); ksort($diff); $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : ''; return implode("\r\n", $diff) . $extra; } // Write the given text to a temporary file, and return the filename. function save_text($filename, $text) { if (!$fp = fopen($filename, 'w')) { return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)"); } fwrite($fp, $text); fclose($fp); if (1 < DETAILED) echo " FILE $filename {{{ $text }}} "; } function _cleanupOldFiles($file) { $temp_dir = realpath(dirname($file)); $mainFileName = basename($file, 'phpt'); $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff'; $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log'; $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp'; $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out'; $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem'; $temp_file = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php'; $temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php'; $temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php'; $tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.'); // unlink old test results @unlink($diff_filename); @unlink($log_filename); @unlink($exp_filename); @unlink($output_filename); @unlink($memcheck_filename); @unlink($temp_file); @unlink($temp_skipif); @unlink($tmp_post); @unlink($temp_clean); } function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings) { $info = ''; $warn = false; if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) { $this->save_text($temp_skipif, $section_text['SKIPIF']); $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\""); $output = $output[1]; $loutput = ltrim($output); unlink($temp_skipif); if (!strncasecmp('skip', $loutput, 4)) { $skipreason = "SKIP $tested"; if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) { $skipreason .= '(reason: ' . $m[1] . ')'; } if (!isset($this->_options['quiet'])) { $this->_logger->log(0, $skipreason); } if (isset($this->_options['tapoutput'])) { return array('ok', ' # skip ' . $reason); } return 'SKIPPED'; } if (!strncasecmp('info', $loutput, 4) && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) { $info = " (info: $m[1])"; } if (!strncasecmp('warn', $loutput, 4) && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) { $warn = true; /* only if there is a reason */ $info = " (warn: $m[1])"; } } return array('warn' => $warn, 'info' => $info); } function _stripHeadersCGI($output) { $this->headers = array(); if (!empty($this->_options['cgi']) && $this->_php == $this->_options['cgi'] && preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) { $output = isset($match[2]) ? trim($match[2]) : ''; $this->_headers = $this->_processHeaders($match[1]); } return $output; } /** * Return an array that can be used with array_diff() to compare headers * * @param string $text */ function _processHeaders($text) { $headers = array(); $rh = preg_split("/[\n\r]+/", $text); foreach ($rh as $line) { if (strpos($line, ':')!== false) { $line = explode(':', $line, 2); $headers[trim($line[0])] = trim($line[1]); } } return $headers; } function _readFile($file) { // Load the sections of the test file. $section_text = array( 'TEST' => '(unnamed test)', 'SKIPIF' => '', 'GET' => '', 'COOKIE' => '', 'POST' => '', 'ARGS' => '', 'INI' => '', 'CLEAN' => '', ); if (!is_file($file) || !$fp = fopen($file, "r")) { return PEAR::raiseError("Cannot open test file: $file"); } $section = ''; while (!feof($fp)) { $line = fgets($fp); // Match the beginning of a section. if (preg_match('/^--([_A-Z]+)--/', $line, $r)) { $section = $r[1]; $section_text[$section] = ''; continue; } elseif (empty($section)) { fclose($fp); return PEAR::raiseError("Invalid sections formats in test file: $file"); } // Add to the section text. $section_text[$section] .= $line; } fclose($fp); return $section_text; } function _writeLog($logname, $data) { if (!$log = fopen($logname, 'w')) { return PEAR::raiseError("Cannot create test log - $logname"); } fwrite($log, $data); fclose($log); } function _resetEnv($section_text, $temp_file) { $env = $_ENV; $env['REDIRECT_STATUS'] = ''; $env['QUERY_STRING'] = ''; $env['PATH_TRANSLATED'] = ''; $env['SCRIPT_FILENAME'] = ''; $env['REQUEST_METHOD'] = ''; $env['CONTENT_TYPE'] = ''; $env['CONTENT_LENGTH'] = ''; if (!empty($section_text['ENV'])) { if (strpos($section_text['ENV'], '{PWD}') !== false) { $section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']); } foreach (explode("\n", trim($section_text['ENV'])) as $e) { $e = explode('=', trim($e), 2); if (!empty($e[0]) && isset($e[1])) { $env[$e[0]] = $e[1]; } } } if (array_key_exists('GET', $section_text)) { $env['QUERY_STRING'] = trim($section_text['GET']); } else { $env['QUERY_STRING'] = ''; } if (array_key_exists('COOKIE', $section_text)) { $env['HTTP_COOKIE'] = trim($section_text['COOKIE']); } else { $env['HTTP_COOKIE'] = ''; } $env['REDIRECT_STATUS'] = '1'; $env['PATH_TRANSLATED'] = $temp_file; $env['SCRIPT_FILENAME'] = $temp_file; return $env; } function _processUpload($section_text, $file) { if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) { $upload_files = trim($section_text['UPLOAD']); $upload_files = explode("\n", $upload_files); $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" . "-----------------------------20896060251896012921717172737\n"; foreach ($upload_files as $fileinfo) { $fileinfo = explode('=', $fileinfo); if (count($fileinfo) != 2) { return PEAR::raiseError("Invalid UPLOAD section in test file: $file"); } if (!realpath(dirname($file) . '/' . $fileinfo[1])) { return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " . "in test file: $file"); } $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]); $fileinfo[1] = basename($fileinfo[1]); $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n"; $request .= "Content-Type: text/plain\n\n"; $request .= $file_contents . "\n" . "-----------------------------20896060251896012921717172737\n"; } if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) { // encode POST raw $post = trim($section_text['POST']); $post = explode('&', $post); foreach ($post as $i => $post_info) { $post_info = explode('=', $post_info); if (count($post_info) != 2) { return PEAR::raiseError("Invalid POST data in test file: $file"); } $post_info[0] = rawurldecode($post_info[0]); $post_info[1] = rawurldecode($post_info[1]); $post[$i] = $post_info; } foreach ($post as $post_info) { $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n"; $request .= $post_info[1] . "\n" . "-----------------------------20896060251896012921717172737\n"; } unset($section_text['POST']); } $section_text['POST_RAW'] = $request; } return $section_text; } function _testCleanup($section_text, $temp_clean) { if ($section_text['CLEAN']) { $this->_restorePHPBinary(); // perform test cleanup $this->save_text($temp_clean, $section_text['CLEAN']); $output = $this->system_with_timeout("$this->_php $temp_clean 2>&1"); if (strlen($output[1])) { echo "BORKED --CLEAN-- section! output:\n", $output[1]; } if (file_exists($temp_clean)) { unlink($temp_clean); } } } function _savePHPBinary() { $this->_savephp = $this->_php; } function _restorePHPBinary() { if (isset($this->_savephp)) { $this->_php = $this->_savephp; unset($this->_savephp); } } } PK!jy99PEAR/Validator/PECL.phpnu[ * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a5 */ /** * This is the parent class for all validators */ require_once 'PEAR/Validate.php'; /** * Channel Validator for the pecl.php.net channel * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a5 */ class PEAR_Validator_PECL extends PEAR_Validate { function validateVersion() { if ($this->_state == PEAR_VALIDATE_PACKAGING) { $version = $this->_packagexml->getVersion(); $versioncomponents = explode('.', $version); $last = array_pop($versioncomponents); if (substr($last, 1, 2) == 'rc') { $this->_addFailure('version', 'Release Candidate versions must have ' . 'upper-case RC, not lower-case rc'); return false; } } return true; } function validatePackageName() { $ret = parent::validatePackageName(); if ($this->_packagexml->getPackageType() == 'extsrc' || $this->_packagexml->getPackageType() == 'zendextsrc') { if (strtolower($this->_packagexml->getPackage()) != strtolower($this->_packagexml->getProvidesExtension())) { $this->_addWarning('providesextension', 'package name "' . $this->_packagexml->getPackage() . '" is different from extension name "' . $this->_packagexml->getProvidesExtension() . '"'); } } return $ret; } } ?>PK!pPEAR/Dependency2.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Required for the PEAR_VALIDATE_* constants */ require_once 'PEAR/Validate.php'; /** * Dependency check for PEAR packages * * This class handles both version 1.0 and 2.0 dependencies * WARNING: *any* changes to this class must be duplicated in the * test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc, * or unit tests will not actually validate the changes * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Dependency2 { /** * One of the PEAR_VALIDATE_* states * @see PEAR_VALIDATE_NORMAL * @var integer */ var $_state; /** * Command-line options to install/upgrade/uninstall commands * @param array */ var $_options; /** * @var OS_Guess */ var $_os; /** * @var PEAR_Registry */ var $_registry; /** * @var PEAR_Config */ var $_config; /** * @var PEAR_DependencyDB */ var $_dependencydb; /** * Output of PEAR_Registry::parsedPackageName() * @var array */ var $_currentPackage; /** * @param PEAR_Config * @param array installation options * @param array format of PEAR_Registry::parsedPackageName() * @param int installation state (one of PEAR_VALIDATE_*) */ function __construct(&$config, $installoptions, $package, $state = PEAR_VALIDATE_INSTALLING) { $this->_config = &$config; if (!class_exists('PEAR_DependencyDB')) { require_once 'PEAR/DependencyDB.php'; } if (isset($installoptions['packagingroot'])) { // make sure depdb is in the right location $config->setInstallRoot($installoptions['packagingroot']); } $this->_registry = &$config->getRegistry(); $this->_dependencydb = &PEAR_DependencyDB::singleton($config); if (isset($installoptions['packagingroot'])) { $config->setInstallRoot(false); } $this->_options = $installoptions; $this->_state = $state; if (!class_exists('OS_Guess')) { require_once 'OS/Guess.php'; } $this->_os = new OS_Guess; $this->_currentPackage = $package; } static function _getExtraString($dep) { $extra = ' ('; if (isset($dep['uri'])) { return ''; } if (isset($dep['recommended'])) { $extra .= 'recommended version ' . $dep['recommended']; } else { if (isset($dep['min'])) { $extra .= 'version >= ' . $dep['min']; } if (isset($dep['max'])) { if ($extra != ' (') { $extra .= ', '; } $extra .= 'version <= ' . $dep['max']; } if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } if ($extra != ' (') { $extra .= ', '; } $extra .= 'excluded versions: '; foreach ($dep['exclude'] as $i => $exclude) { if ($i) { $extra .= ', '; } $extra .= $exclude; } } } $extra .= ')'; if ($extra == ' ()') { $extra = ''; } return $extra; } /** * This makes unit-testing a heck of a lot easier */ function getPHP_OS() { return PHP_OS; } /** * This makes unit-testing a heck of a lot easier */ function getsysname() { return $this->_os->getSysname(); } /** * Specify a dependency on an OS. Use arch for detailed os/processor information * * There are two generic OS dependencies that will be the most common, unix and windows. * Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix */ function validateOsDependency($dep) { if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) { return true; } if ($dep['name'] == '*') { return true; } $not = isset($dep['conflicts']) ? true : false; switch (strtolower($dep['name'])) { case 'windows' : if ($not) { if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError("Cannot install %s on Windows"); } return $this->warning("warning: Cannot install %s on Windows"); } } else { if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError("Can only install %s on Windows"); } return $this->warning("warning: Can only install %s on Windows"); } } break; case 'unix' : $unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix'); if ($not) { if (in_array($this->getSysname(), $unices)) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError("Cannot install %s on any Unix system"); } return $this->warning( "warning: Cannot install %s on any Unix system"); } } else { if (!in_array($this->getSysname(), $unices)) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError("Can only install %s on a Unix system"); } return $this->warning("warning: Can only install %s on a Unix system"); } } break; default : if ($not) { if (strtolower($dep['name']) == strtolower($this->getSysname())) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('Cannot install %s on ' . $dep['name'] . ' operating system'); } return $this->warning('warning: Cannot install %s on ' . $dep['name'] . ' operating system'); } } else { if (strtolower($dep['name']) != strtolower($this->getSysname())) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('Cannot install %s on ' . $this->getSysname() . ' operating system, can only install on ' . $dep['name']); } return $this->warning('warning: Cannot install %s on ' . $this->getSysname() . ' operating system, can only install on ' . $dep['name']); } } } return true; } /** * This makes unit-testing a heck of a lot easier */ function matchSignature($pattern) { return $this->_os->matchSignature($pattern); } /** * Specify a complex dependency on an OS/processor/kernel version, * Use OS for simple operating system dependency. * * This is the only dependency that accepts an eregable pattern. The pattern * will be matched against the php_uname() output parsed by OS_Guess */ function validateArchDependency($dep) { if ($this->_state != PEAR_VALIDATE_INSTALLING) { return true; } $not = isset($dep['conflicts']) ? true : false; if (!$this->matchSignature($dep['pattern'])) { if (!$not) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s Architecture dependency failed, does not ' . 'match "' . $dep['pattern'] . '"'); } return $this->warning('warning: %s Architecture dependency failed, does ' . 'not match "' . $dep['pattern'] . '"'); } return true; } if ($not) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s Architecture dependency failed, required "' . $dep['pattern'] . '"'); } return $this->warning('warning: %s Architecture dependency failed, ' . 'required "' . $dep['pattern'] . '"'); } return true; } /** * This makes unit-testing a heck of a lot easier */ function extension_loaded($name) { return extension_loaded($name); } /** * This makes unit-testing a heck of a lot easier */ function phpversion($name = null) { if ($name !== null) { return phpversion($name); } return phpversion(); } function validateExtensionDependency($dep, $required = true) { if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) { return true; } $loaded = $this->extension_loaded($dep['name']); $extra = self::_getExtraString($dep); if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } } if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended']) && !isset($dep['exclude']) ) { if ($loaded) { if (isset($dep['conflicts'])) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s conflicts with PHP extension "' . $dep['name'] . '"' . $extra); } return $this->warning('warning: %s conflicts with PHP extension "' . $dep['name'] . '"' . $extra); } return true; } if (isset($dep['conflicts'])) { return true; } if ($required) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires PHP extension "' . $dep['name'] . '"' . $extra); } return $this->warning('warning: %s requires PHP extension "' . $dep['name'] . '"' . $extra); } return $this->warning('%s can optionally use PHP extension "' . $dep['name'] . '"' . $extra); } if (!$loaded) { if (isset($dep['conflicts'])) { return true; } if (!$required) { return $this->warning('%s can optionally use PHP extension "' . $dep['name'] . '"' . $extra); } if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires PHP extension "' . $dep['name'] . '"' . $extra); } return $this->warning('warning: %s requires PHP extension "' . $dep['name'] . '"' . $extra); } $version = (string) $this->phpversion($dep['name']); if (empty($version)) { $version = '0'; } $fail = false; if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) { $fail = true; } if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) { $fail = true; } if ($fail && !isset($dep['conflicts'])) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires PHP extension "' . $dep['name'] . '"' . $extra . ', installed version is ' . $version); } return $this->warning('warning: %s requires PHP extension "' . $dep['name'] . '"' . $extra . ', installed version is ' . $version); } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s conflicts with PHP extension "' . $dep['name'] . '"' . $extra . ', installed version is ' . $version); } return $this->warning('warning: %s conflicts with PHP extension "' . $dep['name'] . '"' . $extra . ', installed version is ' . $version); } if (isset($dep['exclude'])) { foreach ($dep['exclude'] as $exclude) { if (version_compare($version, $exclude, '==')) { if (isset($dep['conflicts'])) { continue; } if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s is not compatible with PHP extension "' . $dep['name'] . '" version ' . $exclude); } return $this->warning('warning: %s is not compatible with PHP extension "' . $dep['name'] . '" version ' . $exclude); } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s conflicts with PHP extension "' . $dep['name'] . '"' . $extra . ', installed version is ' . $version); } return $this->warning('warning: %s conflicts with PHP extension "' . $dep['name'] . '"' . $extra . ', installed version is ' . $version); } } } if (isset($dep['recommended'])) { if (version_compare($version, $dep['recommended'], '==')) { return true; } if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] . ' version "' . $version . '"' . ' is not the recommended version "' . $dep['recommended'] . '", but may be compatible, use --force to install'); } return $this->warning('warning: %s dependency: PHP extension ' . $dep['name'] . ' version "' . $version . '"' . ' is not the recommended version "' . $dep['recommended'].'"'); } return true; } function validatePhpDependency($dep) { if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) { return true; } $version = $this->phpversion(); $extra = self::_getExtraString($dep); if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } } if (isset($dep['min'])) { if (!version_compare($version, $dep['min'], '>=')) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires PHP' . $extra . ', installed version is ' . $version); } return $this->warning('warning: %s requires PHP' . $extra . ', installed version is ' . $version); } } if (isset($dep['max'])) { if (!version_compare($version, $dep['max'], '<=')) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires PHP' . $extra . ', installed version is ' . $version); } return $this->warning('warning: %s requires PHP' . $extra . ', installed version is ' . $version); } } if (isset($dep['exclude'])) { foreach ($dep['exclude'] as $exclude) { if (version_compare($version, $exclude, '==')) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s is not compatible with PHP version ' . $exclude); } return $this->warning( 'warning: %s is not compatible with PHP version ' . $exclude); } } } return true; } /** * This makes unit-testing a heck of a lot easier */ function getPEARVersion() { return '1.10.16'; } function validatePearinstallerDependency($dep) { $pearversion = $this->getPEARVersion(); $extra = self::_getExtraString($dep); if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } } if (version_compare($pearversion, $dep['min'], '<')) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires PEAR Installer' . $extra . ', installed version is ' . $pearversion); } return $this->warning('warning: %s requires PEAR Installer' . $extra . ', installed version is ' . $pearversion); } if (isset($dep['max'])) { if (version_compare($pearversion, $dep['max'], '>')) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires PEAR Installer' . $extra . ', installed version is ' . $pearversion); } return $this->warning('warning: %s requires PEAR Installer' . $extra . ', installed version is ' . $pearversion); } } if (isset($dep['exclude'])) { if (!isset($dep['exclude'][0])) { $dep['exclude'] = array($dep['exclude']); } foreach ($dep['exclude'] as $exclude) { if (version_compare($exclude, $pearversion, '==')) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s is not compatible with PEAR Installer ' . 'version ' . $exclude); } return $this->warning('warning: %s is not compatible with PEAR ' . 'Installer version ' . $exclude); } } } return true; } function validateSubpackageDependency($dep, $required, $params) { return $this->validatePackageDependency($dep, $required, $params); } /** * @param array dependency information (2.0 format) * @param boolean whether this is a required dependency * @param array a list of downloaded packages to be installed, if any * @param boolean if true, then deps on pear.php.net that fail will also check * against pecl.php.net packages to accommodate extensions that have * moved to pecl.php.net from pear.php.net */ function validatePackageDependency($dep, $required, $params, $depv1 = false) { if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) { return true; } if (isset($dep['providesextension'])) { if ($this->extension_loaded($dep['providesextension'])) { $save = $dep; $subdep = $dep; $subdep['name'] = $subdep['providesextension']; PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $ret = $this->validateExtensionDependency($subdep, $required); PEAR::popErrorHandling(); if (!PEAR::isError($ret)) { return true; } } } if ($this->_state == PEAR_VALIDATE_INSTALLING) { return $this->_validatePackageInstall($dep, $required, $depv1); } if ($this->_state == PEAR_VALIDATE_DOWNLOADING) { return $this->_validatePackageDownload($dep, $required, $params, $depv1); } } function _validatePackageDownload($dep, $required, $params, $depv1 = false) { $dep['package'] = $dep['name']; if (isset($dep['uri'])) { $dep['channel'] = '__uri'; } $depname = $this->_registry->parsedPackageNameToString($dep, true); $found = false; foreach ($params as $param) { if ($param->isEqual( array('package' => $dep['name'], 'channel' => $dep['channel']))) { $found = true; break; } if ($depv1 && $dep['channel'] == 'pear.php.net') { if ($param->isEqual( array('package' => $dep['name'], 'channel' => 'pecl.php.net'))) { $found = true; break; } } } if (!$found && isset($dep['providesextension'])) { foreach ($params as $param) { if ($param->isExtension($dep['providesextension'])) { $found = true; break; } } } if ($found) { $version = $param->getVersion(); $installed = false; $downloaded = true; } else { if ($this->_registry->packageExists($dep['name'], $dep['channel'])) { $installed = true; $downloaded = false; $version = $this->_registry->packageinfo($dep['name'], 'version', $dep['channel']); } else { if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'], 'pear.php.net')) { $installed = true; $downloaded = false; $version = $this->_registry->packageinfo($dep['name'], 'version', 'pear.php.net'); } else { $version = 'not installed or downloaded'; $installed = false; $downloaded = false; } } } $extra = self::_getExtraString($dep); if (isset($dep['exclude']) && !is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended']) && !isset($dep['exclude']) ) { if ($installed || $downloaded) { $installed = $installed ? 'installed' : 'downloaded'; if (isset($dep['conflicts'])) { $rest = ''; if ($version) { $rest = ", $installed version is " . $version; } if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest); } return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest); } return true; } if (isset($dep['conflicts'])) { return true; } if ($required) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires package "' . $depname . '"' . $extra); } return $this->warning('warning: %s requires package "' . $depname . '"' . $extra); } return $this->warning('%s can optionally use package "' . $depname . '"' . $extra); } if (!$installed && !$downloaded) { if (isset($dep['conflicts'])) { return true; } if ($required) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires package "' . $depname . '"' . $extra); } return $this->warning('warning: %s requires package "' . $depname . '"' . $extra); } return $this->warning('%s can optionally use package "' . $depname . '"' . $extra); } $fail = false; if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) { $fail = true; } if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) { $fail = true; } if ($fail && !isset($dep['conflicts'])) { $installed = $installed ? 'installed' : 'downloaded'; $dep['package'] = $dep['name']; $dep = $this->_registry->parsedPackageNameToString($dep, true); if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires package "' . $depname . '"' . $extra . ", $installed version is " . $version); } return $this->warning('warning: %s requires package "' . $depname . '"' . $extra . ", $installed version is " . $version); } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts']) && !isset($dep['exclude'])) { $installed = $installed ? 'installed' : 'downloaded'; if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . ", $installed version is " . $version); } return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . ", $installed version is " . $version); } if (isset($dep['exclude'])) { $installed = $installed ? 'installed' : 'downloaded'; foreach ($dep['exclude'] as $exclude) { if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) ) { return $this->raiseError('%s is not compatible with ' . $installed . ' package "' . $depname . '" version ' . $exclude); } return $this->warning('warning: %s is not compatible with ' . $installed . ' package "' . $depname . '" version ' . $exclude); } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) { $installed = $installed ? 'installed' : 'downloaded'; if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . ", $installed version is " . $version); } return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . ", $installed version is " . $version); } } } if (isset($dep['recommended'])) { $installed = $installed ? 'installed' : 'downloaded'; if (version_compare($version, $dep['recommended'], '==')) { return true; } if (!$found && $installed) { $param = $this->_registry->getPackage($dep['name'], $dep['channel']); } if ($param) { $found = false; foreach ($params as $parent) { if ($parent->isEqual($this->_currentPackage)) { $found = true; break; } } if ($found) { if ($param->isCompatible($parent)) { return true; } } else { // this is for validPackage() calls $parent = $this->_registry->getPackage($this->_currentPackage['package'], $this->_currentPackage['channel']); if ($parent !== null && $param->isCompatible($parent)) { return true; } } } if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) && !isset($this->_options['loose']) ) { return $this->raiseError('%s dependency package "' . $depname . '" ' . $installed . ' version ' . $version . ' is not the recommended version ' . $dep['recommended'] . ', but may be compatible, use --force to install'); } return $this->warning('warning: %s dependency package "' . $depname . '" ' . $installed . ' version ' . $version . ' is not the recommended version ' . $dep['recommended']); } return true; } function _validatePackageInstall($dep, $required, $depv1 = false) { return $this->_validatePackageDownload($dep, $required, array(), $depv1); } /** * Verify that uninstalling packages passed in to command line is OK. * * @param PEAR_Installer $dl * @return PEAR_Error|true */ function validatePackageUninstall(&$dl) { if (PEAR::isError($this->_dependencydb)) { return $this->_dependencydb; } $params = array(); // construct an array of "downloaded" packages to fool the package dependency checker // into using these to validate uninstalls of circular dependencies $downloaded = &$dl->getUninstallPackages(); foreach ($downloaded as $i => $pf) { if (!class_exists('PEAR_Downloader_Package')) { require_once 'PEAR/Downloader/Package.php'; } $dp = new PEAR_Downloader_Package($dl); $dp->setPackageFile($downloaded[$i]); $params[$i] = $dp; } // check cache $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' . strtolower($this->_currentPackage['package']); if (isset($dl->___uninstall_package_cache)) { $badpackages = $dl->___uninstall_package_cache; if (isset($badpackages[$memyselfandI]['warnings'])) { foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { $dl->log(0, $warning[0]); } } if (isset($badpackages[$memyselfandI]['errors'])) { foreach ($badpackages[$memyselfandI]['errors'] as $error) { if (is_array($error)) { $dl->log(0, $error[0]); } else { $dl->log(0, $error->getMessage()); } } if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { return $this->warning( 'warning: %s should not be uninstalled, other installed packages depend ' . 'on this package'); } return $this->raiseError( '%s cannot be uninstalled, other installed packages depend on this package'); } return true; } // first, list the immediate parents of each package to be uninstalled $perpackagelist = array(); $allparents = array(); foreach ($params as $i => $param) { $a = array( 'channel' => strtolower($param->getChannel()), 'package' => strtolower($param->getPackage()) ); $deps = $this->_dependencydb->getDependentPackages($a); if ($deps) { foreach ($deps as $d) { $pardeps = $this->_dependencydb->getDependencies($d); foreach ($pardeps as $dep) { if (strtolower($dep['dep']['channel']) == $a['channel'] && strtolower($dep['dep']['name']) == $a['package']) { if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) { $perpackagelist[$a['channel'] . '/' . $a['package']] = array(); } $perpackagelist[$a['channel'] . '/' . $a['package']][] = array($d['channel'] . '/' . $d['package'], $dep); if (!isset($allparents[$d['channel'] . '/' . $d['package']])) { $allparents[$d['channel'] . '/' . $d['package']] = array(); } if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) { $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array(); } $allparents[$d['channel'] . '/' . $d['package']] [$a['channel'] . '/' . $a['package']][] = array($d, $dep); } } } } } // next, remove any packages from the parents list that are not installed $remove = array(); foreach ($allparents as $parent => $d1) { foreach ($d1 as $d) { if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) { continue; } $remove[$parent] = true; } } // next remove any packages from the parents list that are not passed in for // uninstallation foreach ($allparents as $parent => $d1) { foreach ($d1 as $d) { foreach ($params as $param) { if (strtolower($param->getChannel()) == $d[0][0]['channel'] && strtolower($param->getPackage()) == $d[0][0]['package']) { // found it continue 3; } } $remove[$parent] = true; } } // remove all packages whose dependencies fail // save which ones failed for error reporting $badchildren = array(); do { $fail = false; foreach ($remove as $package => $unused) { if (!isset($allparents[$package])) { continue; } foreach ($allparents[$package] as $kid => $d1) { foreach ($d1 as $depinfo) { if ($depinfo[1]['type'] != 'optional') { if (isset($badchildren[$kid])) { continue; } $badchildren[$kid] = true; $remove[$kid] = true; $fail = true; continue 2; } } } if ($fail) { // start over, we removed some children continue 2; } } } while ($fail); // next, construct the list of packages that can't be uninstalled $badpackages = array(); $save = $this->_currentPackage; foreach ($perpackagelist as $package => $packagedeps) { foreach ($packagedeps as $parent) { if (!isset($remove[$parent[0]])) { continue; } $packagename = $this->_registry->parsePackageName($parent[0]); $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']); $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']); $packagename['package'] = $pa->getPackage(); $this->_currentPackage = $packagename; // parent is not present in uninstall list, make sure we can actually // uninstall it (parent dep is optional) $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']); $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']); $parentname['package'] = $pa->getPackage(); $parent[1]['dep']['package'] = $parentname['package']; $parent[1]['dep']['channel'] = $parentname['channel']; if ($parent[1]['type'] == 'optional') { $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl); if ($test !== true) { $badpackages[$package]['warnings'][] = $test; } } else { $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl); if ($test !== true) { $badpackages[$package]['errors'][] = $test; } } } } $this->_currentPackage = $save; $dl->___uninstall_package_cache = $badpackages; if (isset($badpackages[$memyselfandI])) { if (isset($badpackages[$memyselfandI]['warnings'])) { foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { $dl->log(0, $warning[0]); } } if (isset($badpackages[$memyselfandI]['errors'])) { foreach ($badpackages[$memyselfandI]['errors'] as $error) { if (is_array($error)) { $dl->log(0, $error[0]); } else { $dl->log(0, $error->getMessage()); } } if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { return $this->warning( 'warning: %s should not be uninstalled, other installed packages depend ' . 'on this package'); } return $this->raiseError( '%s cannot be uninstalled, other installed packages depend on this package'); } } return true; } function _validatePackageUninstall($dep, $required, $dl) { $depname = $this->_registry->parsedPackageNameToString($dep, true); $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']); if (!$version) { return true; } $extra = self::_getExtraString($dep); if (isset($dep['exclude']) && !is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } if (isset($dep['conflicts'])) { return true; // uninstall OK - these packages conflict (probably installed with --force) } if (!isset($dep['min']) && !isset($dep['max'])) { if (!$required) { return $this->warning('"' . $depname . '" can be optionally used by ' . 'installed package %s' . $extra); } if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('"' . $depname . '" is required by ' . 'installed package %s' . $extra); } return $this->warning('warning: "' . $depname . '" is required by ' . 'installed package %s' . $extra); } $fail = false; if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) { $fail = true; } if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) { $fail = true; } // we re-use this variable, preserve the original value $saverequired = $required; if (!$required) { return $this->warning($depname . $extra . ' can be optionally used by installed package' . ' "%s"'); } if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError($depname . $extra . ' is required by installed package' . ' "%s"'); } return $this->raiseError('warning: ' . $depname . $extra . ' is required by installed package "%s"'); } /** * validate a downloaded package against installed packages * * As of PEAR 1.4.3, this will only validate * * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2 * $pkg package identifier (either * array('package' => blah, 'channel' => blah) or an array with * index 'info' referencing an object) * @param PEAR_Downloader $dl * @param array $params full list of packages to install * @return true|PEAR_Error */ function validatePackage($pkg, &$dl, $params = array()) { if (is_array($pkg) && isset($pkg['info'])) { $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']); } else { $deps = $this->_dependencydb->getDependentPackageDependencies($pkg); } $fail = false; if ($deps) { if (!class_exists('PEAR_Downloader_Package')) { require_once 'PEAR/Downloader/Package.php'; } $dp = new PEAR_Downloader_Package($dl); if (is_object($pkg)) { $dp->setPackageFile($pkg); } else { $dp->setDownloadURL($pkg); } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); foreach ($deps as $channel => $info) { foreach ($info as $package => $ds) { foreach ($params as $packd) { if (strtolower($packd->getPackage()) == strtolower($package) && $packd->getChannel() == $channel) { $dl->log(3, 'skipping installed package check of "' . $this->_registry->parsedPackageNameToString( array('channel' => $channel, 'package' => $package), true) . '", version "' . $packd->getVersion() . '" will be ' . 'downloaded and installed'); continue 2; // jump to next package } } foreach ($ds as $d) { $checker = new PEAR_Dependency2($this->_config, $this->_options, array('channel' => $channel, 'package' => $package), $this->_state); $dep = $d['dep']; $required = $d['type'] == 'required'; $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp)); if (is_array($ret)) { $dl->log(0, $ret[0]); } elseif (PEAR::isError($ret)) { $dl->log(0, $ret->getMessage()); $fail = true; } } } } PEAR::popErrorHandling(); } if ($fail) { return $this->raiseError( '%s cannot be installed, conflicts with installed packages'); } return true; } /** * validate a package.xml 1.0 dependency */ function validateDependency1($dep, $params = array()) { if (!isset($dep['optional'])) { $dep['optional'] = 'no'; } list($newdep, $type) = self::normalizeDep($dep); if (!$newdep) { return $this->raiseError("Invalid Dependency"); } if (method_exists($this, "validate{$type}Dependency")) { return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no', $params, true); } } /** * Convert a 1.0 dep into a 2.0 dep */ static function normalizeDep($dep) { $types = array( 'pkg' => 'Package', 'ext' => 'Extension', 'os' => 'Os', 'php' => 'Php' ); if (!isset($types[$dep['type']])) { return array(false, false); } $type = $types[$dep['type']]; $newdep = array(); switch ($type) { case 'Package' : $newdep['channel'] = 'pear.php.net'; case 'Extension' : case 'Os' : $newdep['name'] = $dep['name']; break; } $dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']); switch ($dep['rel']) { case 'has' : return array($newdep, $type); break; case 'not' : $newdep['conflicts'] = true; break; case '>=' : case '>' : $newdep['min'] = $dep['version']; if ($dep['rel'] == '>') { $newdep['exclude'] = $dep['version']; } break; case '<=' : case '<' : $newdep['max'] = $dep['version']; if ($dep['rel'] == '<') { $newdep['exclude'] = $dep['version']; } break; case 'ne' : case '!=' : $newdep['min'] = '0'; $newdep['max'] = '100000'; $newdep['exclude'] = $dep['version']; break; case '==' : $newdep['min'] = $dep['version']; $newdep['max'] = $dep['version']; break; } if ($type == 'Php') { if (!isset($newdep['min'])) { $newdep['min'] = '4.4.0'; } if (!isset($newdep['max'])) { $newdep['max'] = '6.0.0'; } } return array($newdep, $type); } /** * Converts text comparing operators to them sign equivalents * * Example: 'ge' to '>=' * * @access public * @param string Operator * @return string Sign equivalent */ static function signOperator($operator) { switch($operator) { case 'lt': return '<'; case 'le': return '<='; case 'gt': return '>'; case 'ge': return '>='; case 'eq': return '=='; case 'ne': return '!='; default: return $operator; } } function raiseError($msg) { if (isset($this->_options['ignore-errors'])) { return $this->warning($msg); } return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString( $this->_currentPackage, true))); } function warning($msg) { return array(sprintf($msg, $this->_registry->parsedPackageNameToString( $this->_currentPackage, true))); } } PK!wv@@PEAR/PackageFile/v2.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * For error handling */ require_once 'PEAR/ErrorStack.php'; /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_PackageFile_v2 { /** * Parsed package information * @var array * @access private */ var $_packageInfo = array(); /** * path to package .tgz or false if this is a local/extracted package.xml * @var string|false * @access private */ var $_archiveFile; /** * path to package .xml or false if this is an abstract parsed-from-string xml * @var string|false * @access private */ var $_packageFile; /** * This is used by file analysis routines to log progress information * @var PEAR_Common * @access protected */ var $_logger; /** * This is set to the highest validation level that has been validated * * If the package.xml is invalid or unknown, this is set to 0. If * normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL. If * downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING * or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING. This allows validation * "caching" to occur, which is particularly important for package validation, so * that PHP files are not validated twice * @var int * @access private */ var $_isValid = 0; /** * True if the filelist has been validated * @param bool */ var $_filesValid = false; /** * @var PEAR_Registry * @access protected */ var $_registry; /** * @var PEAR_Config * @access protected */ var $_config; /** * Optional Dependency group requested for installation * @var string * @access private */ var $_requestedGroup = false; /** * @var PEAR_ErrorStack * @access protected */ var $_stack; /** * Namespace prefix used for tasks in this package.xml - use tasks: whenever possible */ var $_tasksNs; /** * Determines whether this packagefile was initialized only with partial package info * * If this package file was constructed via parsing REST, it will only contain * * - package name * - channel name * - dependencies * @var boolean * @access private */ var $_incomplete = true; /** * @var PEAR_PackageFile_v2_Validator */ var $_v2Validator; /** * The constructor merely sets up the private error stack */ function __construct() { $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null); $this->_isValid = false; } /** * PHP 4 style constructor for backwards compatibility. * Used by PEAR_PackageFileManager2 */ public function PEAR_PackageFile_v2() { $this->__construct(); } /** * To make unit-testing easier * @param PEAR_Frontend_* * @param array options * @param PEAR_Config * @return PEAR_Downloader * @access protected */ function &getPEARDownloader(&$i, $o, &$c) { $z = new PEAR_Downloader($i, $o, $c); return $z; } /** * To make unit-testing easier * @param PEAR_Config * @param array options * @param array package name as returned from {@link PEAR_Registry::parsePackageName()} * @param int PEAR_VALIDATE_* constant * @return PEAR_Dependency2 * @access protected */ function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING) { if (!class_exists('PEAR_Dependency2')) { require_once 'PEAR/Dependency2.php'; } $z = new PEAR_Dependency2($c, $o, $p, $s); return $z; } function getInstalledBinary() { return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] : false; } /** * Installation of source package has failed, attempt to download and install the * binary version of this package. * @param PEAR_Installer * @return array|false */ function installBinary(&$installer) { if (!OS_WINDOWS) { $a = false; return $a; } if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { $releasetype = $this->getPackageType() . 'release'; if (!is_array($installer->getInstallPackages())) { $a = false; return $a; } foreach ($installer->getInstallPackages() as $p) { if ($p->isExtension($this->_packageInfo['providesextension'])) { if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') { $a = false; return $a; // the user probably downloaded it separately } } } if (isset($this->_packageInfo[$releasetype]['binarypackage'])) { $installer->log(0, 'Attempting to download binary version of extension "' . $this->_packageInfo['providesextension'] . '"'); $params = $this->_packageInfo[$releasetype]['binarypackage']; if (!is_array($params) || !isset($params[0])) { $params = array($params); } if (isset($this->_packageInfo['channel'])) { foreach ($params as $i => $param) { $params[$i] = array('channel' => $this->_packageInfo['channel'], 'package' => $param, 'version' => $this->getVersion()); } } $dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(), $installer->config); $verbose = $dl->config->get('verbose'); $dl->config->set('verbose', -1); foreach ($params as $param) { PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $ret = $dl->download(array($param)); PEAR::popErrorHandling(); if (is_array($ret) && count($ret)) { break; } } $dl->config->set('verbose', $verbose); if (is_array($ret)) { if (count($ret) == 1) { $pf = $ret[0]->getPackageFile(); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $err = $installer->install($ret[0]); PEAR::popErrorHandling(); if (is_array($err)) { $this->_packageInfo['#binarypackage'] = $ret[0]->getPackage(); // "install" self, so all dependencies will work transparently $this->_registry->addPackage2($this); $installer->log(0, 'Download and install of binary extension "' . $this->_registry->parsedPackageNameToString( array('channel' => $pf->getChannel(), 'package' => $pf->getPackage()), true) . '" successful'); $a = array($ret[0], $err); return $a; } $installer->log(0, 'Download and install of binary extension "' . $this->_registry->parsedPackageNameToString( array('channel' => $pf->getChannel(), 'package' => $pf->getPackage()), true) . '" failed'); } } } } $a = false; return $a; } /** * @return string|false Extension name */ function getProvidesExtension() { if (in_array($this->getPackageType(), array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { if (isset($this->_packageInfo['providesextension'])) { return $this->_packageInfo['providesextension']; } } return false; } /** * @param string Extension name * @return bool */ function isExtension($extension) { if (in_array($this->getPackageType(), array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { return $this->_packageInfo['providesextension'] == $extension; } return false; } /** * Tests whether every part of the package.xml 1.0 is represented in * this package.xml 2.0 * @param PEAR_PackageFile_v1 * @return bool */ function isEquivalent($pf1) { if (!$pf1) { return true; } if ($this->getPackageType() == 'bundle') { return false; } $this->_stack->getErrors(true); if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) { return false; } $pass = true; if ($pf1->getPackage() != $this->getPackage()) { $this->_differentPackage($pf1->getPackage()); $pass = false; } if ($pf1->getVersion() != $this->getVersion()) { $this->_differentVersion($pf1->getVersion()); $pass = false; } if (trim($pf1->getSummary()) != $this->getSummary()) { $this->_differentSummary($pf1->getSummary()); $pass = false; } if (preg_replace('/\s+/', '', $pf1->getDescription()) != preg_replace('/\s+/', '', $this->getDescription())) { $this->_differentDescription($pf1->getDescription()); $pass = false; } if ($pf1->getState() != $this->getState()) { $this->_differentState($pf1->getState()); $pass = false; } if (!strstr(preg_replace('/\s+/', '', $this->getNotes()), preg_replace('/\s+/', '', $pf1->getNotes()))) { $this->_differentNotes($pf1->getNotes()); $pass = false; } $mymaintainers = $this->getMaintainers(); $yourmaintainers = $pf1->getMaintainers(); for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) { $reset = false; for ($i2 = 0; $i2 < count($mymaintainers); $i2++) { if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) { if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) { $this->_differentRole($mymaintainers[$i2]['handle'], $yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']); $pass = false; } if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) { $this->_differentEmail($mymaintainers[$i2]['handle'], $yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']); $pass = false; } if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) { $this->_differentName($mymaintainers[$i2]['handle'], $yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']); $pass = false; } unset($mymaintainers[$i2]); $mymaintainers = array_values($mymaintainers); unset($yourmaintainers[$i1]); $yourmaintainers = array_values($yourmaintainers); $reset = true; break; } } if ($reset) { $i1 = -1; } } $this->_unmatchedMaintainers($mymaintainers, $yourmaintainers); $filelist = $this->getFilelist(); foreach ($pf1->getFilelist() as $file => $atts) { if (!isset($filelist[$file])) { $this->_missingFile($file); $pass = false; } } return $pass; } function _differentPackage($package) { $this->_stack->push(__FUNCTION__, 'error', array('package' => $package, 'self' => $this->getPackage()), 'package.xml 1.0 package "%package%" does not match "%self%"'); } function _differentVersion($version) { $this->_stack->push(__FUNCTION__, 'error', array('version' => $version, 'self' => $this->getVersion()), 'package.xml 1.0 version "%version%" does not match "%self%"'); } function _differentState($state) { $this->_stack->push(__FUNCTION__, 'error', array('state' => $state, 'self' => $this->getState()), 'package.xml 1.0 state "%state%" does not match "%self%"'); } function _differentRole($handle, $role, $selfrole) { $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle, 'role' => $role, 'self' => $selfrole), 'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"'); } function _differentEmail($handle, $email, $selfemail) { $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle, 'email' => $email, 'self' => $selfemail), 'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"'); } function _differentName($handle, $name, $selfname) { $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle, 'name' => $name, 'self' => $selfname), 'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"'); } function _unmatchedMaintainers($my, $yours) { if ($my) { array_walk($my, function(&$i, $k) { $i = $i["handle"]; }); $this->_stack->push(__FUNCTION__, 'error', array('handles' => $my), 'package.xml 2.0 has unmatched extra maintainers "%handles%"'); } if ($yours) { array_walk($yours, function(&$i, $k) { $i = $i["handle"]; }); $this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours), 'package.xml 1.0 has unmatched extra maintainers "%handles%"'); } } function _differentNotes($notes) { $truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...'; $truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() : substr($this->getNotes(), 0, 24) . '...'; $this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes, 'self' => $truncmynotes), 'package.xml 1.0 release notes "%notes%" do not match "%self%"'); } function _differentSummary($summary) { $truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...'; $truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() : substr($this->getsummary(), 0, 24) . '...'; $this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary, 'self' => $truncmysummary), 'package.xml 1.0 summary "%summary%" does not match "%self%"'); } function _differentDescription($description) { $truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...'); $truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() : substr($this->getdescription(), 0, 24) . '...'); $this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription, 'self' => $truncmydescription), 'package.xml 1.0 description "%description%" does not match "%self%"'); } function _missingFile($file) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'package.xml 1.0 file "%file%" is not present in '); } /** * WARNING - do not use this function unless you know what you're doing */ function setRawState($state) { if (!isset($this->_packageInfo['stability'])) { $this->_packageInfo['stability'] = array(); } $this->_packageInfo['stability']['release'] = $state; } /** * WARNING - do not use this function unless you know what you're doing */ function setRawCompatible($compatible) { $this->_packageInfo['compatible'] = $compatible; } /** * WARNING - do not use this function unless you know what you're doing */ function setRawPackage($package) { $this->_packageInfo['name'] = $package; } /** * WARNING - do not use this function unless you know what you're doing */ function setRawChannel($channel) { $this->_packageInfo['channel'] = $channel; } function setRequestedGroup($group) { $this->_requestedGroup = $group; } function getRequestedGroup() { if (isset($this->_requestedGroup)) { return $this->_requestedGroup; } return false; } /** * For saving in the registry. * * Set the last version that was installed * @param string */ function setLastInstalledVersion($version) { $this->_packageInfo['_lastversion'] = $version; } /** * @return string|false */ function getLastInstalledVersion() { if (isset($this->_packageInfo['_lastversion'])) { return $this->_packageInfo['_lastversion']; } return false; } /** * Determines whether this package.xml has post-install scripts or not * @return array|false */ function listPostinstallScripts() { $filelist = $this->getFilelist(); $contents = $this->getContents(); $contents = $contents['dir']['file']; if (!is_array($contents) || !isset($contents[0])) { $contents = array($contents); } $taskfiles = array(); foreach ($contents as $file) { $atts = $file['attribs']; unset($file['attribs']); if (count($file)) { $taskfiles[$atts['name']] = $file; } } $common = new PEAR_Common; $common->debug = $this->_config->get('verbose'); $this->_scripts = array(); $ret = array(); foreach ($taskfiles as $name => $tasks) { if (!isset($filelist[$name])) { // ignored files will not be in the filelist continue; } $atts = $filelist[$name]; foreach ($tasks as $tag => $raw) { $task = $this->getTask($tag); $task = new $task($this->_config, $common, PEAR_TASK_INSTALL); if ($task->isScript()) { $ret[] = $filelist[$name]['installed_as']; } } } if (count($ret)) { return $ret; } return false; } /** * Initialize post-install scripts for running * * This method can be used to detect post-install scripts, as the return value * indicates whether any exist * @return bool */ function initPostinstallScripts() { $filelist = $this->getFilelist(); $contents = $this->getContents(); $contents = $contents['dir']['file']; if (!is_array($contents) || !isset($contents[0])) { $contents = array($contents); } $taskfiles = array(); foreach ($contents as $file) { $atts = $file['attribs']; unset($file['attribs']); if (count($file)) { $taskfiles[$atts['name']] = $file; } } $common = new PEAR_Common; $common->debug = $this->_config->get('verbose'); $this->_scripts = array(); foreach ($taskfiles as $name => $tasks) { if (!isset($filelist[$name])) { // file was not installed due to installconditions continue; } $atts = $filelist[$name]; foreach ($tasks as $tag => $raw) { $taskname = $this->getTask($tag); $task = new $taskname($this->_config, $common, PEAR_TASK_INSTALL); if (!$task->isScript()) { continue; // scripts are only handled after installation } $lastversion = isset($this->_packageInfo['_lastversion']) ? $this->_packageInfo['_lastversion'] : null; $task->init($raw, $atts, $lastversion); $res = $task->startSession($this, $atts['installed_as'], null); if (!$res) { continue; // skip this file } if (PEAR::isError($res)) { return $res; } $this->_scripts[] = $task; } } if (count($this->_scripts)) { return true; } return false; } function runPostinstallScripts() { if ($this->initPostinstallScripts()) { $ui = &PEAR_Frontend::singleton(); if ($ui) { $ui->runPostinstallScripts($this->_scripts, $this); } } } /** * Convert a recursive set of and tags into a single tag with * tags. */ function flattenFilelist() { if (isset($this->_packageInfo['bundle'])) { return; } $filelist = array(); if (isset($this->_packageInfo['contents']['dir']['dir'])) { $this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']); if (!isset($filelist[1])) { $filelist = $filelist[0]; } $this->_packageInfo['contents']['dir']['file'] = $filelist; unset($this->_packageInfo['contents']['dir']['dir']); } else { // else already flattened but check for baseinstalldir propagation if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) { if (isset($this->_packageInfo['contents']['dir']['file'][0])) { foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) { if (isset($file['attribs']['baseinstalldir'])) { continue; } $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir'] = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir']; } } else { if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) { $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'] = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir']; } } } } } /** * @param array the final flattened file list * @param array the current directory being processed * @param string|false any recursively inherited baeinstalldir attribute * @param string private recursion variable * @return array * @access protected */ function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '') { if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) { $baseinstall = $dir['attribs']['baseinstalldir']; } if (isset($dir['dir'])) { if (!isset($dir['dir'][0])) { $dir['dir'] = array($dir['dir']); } foreach ($dir['dir'] as $subdir) { if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) { $name = '*unknown*'; } else { $name = $subdir['attribs']['name']; } $newpath = empty($path) ? $name : $path . '/' . $name; $this->_getFlattenedFilelist($files, $subdir, $baseinstall, $newpath); } } if (isset($dir['file'])) { if (!isset($dir['file'][0])) { $dir['file'] = array($dir['file']); } foreach ($dir['file'] as $file) { $attrs = $file['attribs']; $name = $attrs['name']; if ($baseinstall && !isset($attrs['baseinstalldir'])) { $attrs['baseinstalldir'] = $baseinstall; } $attrs['name'] = empty($path) ? $name : $path . '/' . $name; $attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $attrs['name']); $file['attribs'] = $attrs; $files[] = $file; } } } function setConfig(&$config) { $this->_config = &$config; $this->_registry = &$config->getRegistry(); } function setLogger(&$logger) { if (!is_object($logger) || !method_exists($logger, 'log')) { return PEAR::raiseError('Logger must be compatible with PEAR_Common::log'); } $this->_logger = &$logger; } /** * WARNING - do not use this function directly unless you know what you're doing */ function setDeps($deps) { $this->_packageInfo['dependencies'] = $deps; } /** * WARNING - do not use this function directly unless you know what you're doing */ function setCompatible($compat) { $this->_packageInfo['compatible'] = $compat; } function setPackagefile($file, $archive = false) { $this->_packageFile = $file; $this->_archiveFile = $archive ? $archive : $file; } /** * Wrapper to {@link PEAR_ErrorStack::getErrors()} * @param boolean determines whether to purge the error stack after retrieving * @return array */ function getValidationWarnings($purge = true) { return $this->_stack->getErrors($purge); } function getPackageFile() { return $this->_packageFile; } function getArchiveFile() { return $this->_archiveFile; } /** * Directly set the array that defines this packagefile * * WARNING: no validation. This should only be performed by internal methods * inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2 * @param array */ function fromArray($pinfo) { unset($pinfo['old']); unset($pinfo['xsdversion']); // If the changelog isn't an array then it was passed in as an empty tag if (isset($pinfo['changelog']) && !is_array($pinfo['changelog'])) { unset($pinfo['changelog']); } $this->_incomplete = false; $this->_packageInfo = $pinfo; } function isIncomplete() { return $this->_incomplete; } /** * @return array */ function toArray($forreg = false) { if (!$this->validate(PEAR_VALIDATE_NORMAL)) { return false; } return $this->getArray($forreg); } function getArray($forReg = false) { if ($forReg) { $arr = $this->_packageInfo; $arr['old'] = array(); $arr['old']['version'] = $this->getVersion(); $arr['old']['release_date'] = $this->getDate(); $arr['old']['release_state'] = $this->getState(); $arr['old']['release_license'] = $this->getLicense(); $arr['old']['release_notes'] = $this->getNotes(); $arr['old']['release_deps'] = $this->getDeps(); $arr['old']['maintainers'] = $this->getMaintainers(); $arr['xsdversion'] = '2.0'; return $arr; } else { $info = $this->_packageInfo; unset($info['dirtree']); if (isset($info['_lastversion'])) { unset($info['_lastversion']); } if (isset($info['#binarypackage'])) { unset($info['#binarypackage']); } return $info; } } function packageInfo($field) { $arr = $this->getArray(true); if ($field == 'state') { return $arr['stability']['release']; } if ($field == 'api-version') { return $arr['version']['api']; } if ($field == 'api-state') { return $arr['stability']['api']; } if (isset($arr['old'][$field])) { if (!is_string($arr['old'][$field])) { return null; } return $arr['old'][$field]; } if (isset($arr[$field])) { if (!is_string($arr[$field])) { return null; } return $arr[$field]; } return null; } function getName() { return $this->getPackage(); } function getPackage() { if (isset($this->_packageInfo['name'])) { return $this->_packageInfo['name']; } return false; } function getChannel() { if (isset($this->_packageInfo['uri'])) { return '__uri'; } if (isset($this->_packageInfo['channel'])) { return strtolower($this->_packageInfo['channel']); } return false; } function getUri() { if (isset($this->_packageInfo['uri'])) { return $this->_packageInfo['uri']; } return false; } function getExtends() { if (isset($this->_packageInfo['extends'])) { return $this->_packageInfo['extends']; } return false; } function getSummary() { if (isset($this->_packageInfo['summary'])) { return $this->_packageInfo['summary']; } return false; } function getDescription() { if (isset($this->_packageInfo['description'])) { return $this->_packageInfo['description']; } return false; } function getMaintainers($raw = false) { if (!isset($this->_packageInfo['lead'])) { return false; } if ($raw) { $ret = array('lead' => $this->_packageInfo['lead']); (isset($this->_packageInfo['developer'])) ? $ret['developer'] = $this->_packageInfo['developer'] :null; (isset($this->_packageInfo['contributor'])) ? $ret['contributor'] = $this->_packageInfo['contributor'] :null; (isset($this->_packageInfo['helper'])) ? $ret['helper'] = $this->_packageInfo['helper'] :null; return $ret; } else { $ret = array(); $leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] : array($this->_packageInfo['lead']); foreach ($leads as $lead) { $s = $lead; $s['handle'] = $s['user']; unset($s['user']); $s['role'] = 'lead'; $ret[] = $s; } if (isset($this->_packageInfo['developer'])) { $leads = isset($this->_packageInfo['developer'][0]) ? $this->_packageInfo['developer'] : array($this->_packageInfo['developer']); foreach ($leads as $maintainer) { $s = $maintainer; $s['handle'] = $s['user']; unset($s['user']); $s['role'] = 'developer'; $ret[] = $s; } } if (isset($this->_packageInfo['contributor'])) { $leads = isset($this->_packageInfo['contributor'][0]) ? $this->_packageInfo['contributor'] : array($this->_packageInfo['contributor']); foreach ($leads as $maintainer) { $s = $maintainer; $s['handle'] = $s['user']; unset($s['user']); $s['role'] = 'contributor'; $ret[] = $s; } } if (isset($this->_packageInfo['helper'])) { $leads = isset($this->_packageInfo['helper'][0]) ? $this->_packageInfo['helper'] : array($this->_packageInfo['helper']); foreach ($leads as $maintainer) { $s = $maintainer; $s['handle'] = $s['user']; unset($s['user']); $s['role'] = 'helper'; $ret[] = $s; } } return $ret; } return false; } function getLeads() { if (isset($this->_packageInfo['lead'])) { return $this->_packageInfo['lead']; } return false; } function getDevelopers() { if (isset($this->_packageInfo['developer'])) { return $this->_packageInfo['developer']; } return false; } function getContributors() { if (isset($this->_packageInfo['contributor'])) { return $this->_packageInfo['contributor']; } return false; } function getHelpers() { if (isset($this->_packageInfo['helper'])) { return $this->_packageInfo['helper']; } return false; } function setDate($date) { if (!isset($this->_packageInfo['date'])) { // ensure that the extends tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), array(), 'date'); } $this->_packageInfo['date'] = $date; $this->_isValid = 0; } function setTime($time) { $this->_isValid = 0; if (!isset($this->_packageInfo['time'])) { // ensure that the time tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $time, 'time'); } $this->_packageInfo['time'] = $time; } function getDate() { if (isset($this->_packageInfo['date'])) { return $this->_packageInfo['date']; } return false; } function getTime() { if (isset($this->_packageInfo['time'])) { return $this->_packageInfo['time']; } return false; } /** * @param package|api version category to return */ function getVersion($key = 'release') { if (isset($this->_packageInfo['version'][$key])) { return $this->_packageInfo['version'][$key]; } return false; } function getStability() { if (isset($this->_packageInfo['stability'])) { return $this->_packageInfo['stability']; } return false; } function getState($key = 'release') { if (isset($this->_packageInfo['stability'][$key])) { return $this->_packageInfo['stability'][$key]; } return false; } function getLicense($raw = false) { if (isset($this->_packageInfo['license'])) { if ($raw) { return $this->_packageInfo['license']; } if (is_array($this->_packageInfo['license'])) { return $this->_packageInfo['license']['_content']; } else { return $this->_packageInfo['license']; } } return false; } function getLicenseLocation() { if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) { return false; } return $this->_packageInfo['license']['attribs']; } function getNotes() { if (isset($this->_packageInfo['notes'])) { return $this->_packageInfo['notes']; } return false; } /** * Return the tag contents, if any * @return array|false */ function getUsesrole() { if (isset($this->_packageInfo['usesrole'])) { return $this->_packageInfo['usesrole']; } return false; } /** * Return the tag contents, if any * @return array|false */ function getUsestask() { if (isset($this->_packageInfo['usestask'])) { return $this->_packageInfo['usestask']; } return false; } /** * This should only be used to retrieve filenames and install attributes */ function getFilelist($preserve = false) { if (isset($this->_packageInfo['filelist']) && !$preserve) { return $this->_packageInfo['filelist']; } $this->flattenFilelist(); if ($contents = $this->getContents()) { $ret = array(); if (!isset($contents['dir'])) { return false; } if (!isset($contents['dir']['file'][0])) { $contents['dir']['file'] = array($contents['dir']['file']); } foreach ($contents['dir']['file'] as $file) { if (!isset($file['attribs']['name'])) { continue; } $name = $file['attribs']['name']; if (!$preserve) { $file = $file['attribs']; } $ret[$name] = $file; } if (!$preserve) { $this->_packageInfo['filelist'] = $ret; } return $ret; } return false; } /** * Return configure options array, if any * * @return array|false */ function getConfigureOptions() { if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { return false; } $releases = $this->getReleases(); if (isset($releases[0])) { $releases = $releases[0]; } if (isset($releases['configureoption'])) { if (!isset($releases['configureoption'][0])) { $releases['configureoption'] = array($releases['configureoption']); } for ($i = 0; $i < count($releases['configureoption']); $i++) { $releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs']; } return $releases['configureoption']; } return false; } /** * This is only used at install-time, after all serialization * is over. */ function resetFilelist() { $this->_packageInfo['filelist'] = array(); } /** * Retrieve a list of files that should be installed on this computer * @return array */ function getInstallationFilelist($forfilecheck = false) { $contents = $this->getFilelist(true); if (isset($contents['dir']['attribs']['baseinstalldir'])) { $base = $contents['dir']['attribs']['baseinstalldir']; } if (isset($this->_packageInfo['bundle'])) { return PEAR::raiseError( 'Exception: bundles should be handled in download code only'); } $release = $this->getReleases(); if ($release) { if (!isset($release[0])) { if (!isset($release['installconditions']) && !isset($release['filelist'])) { if ($forfilecheck) { return $this->getFilelist(); } return $contents; } $release = array($release); } $depchecker = &$this->getPEARDependency2($this->_config, array(), array('channel' => $this->getChannel(), 'package' => $this->getPackage()), PEAR_VALIDATE_INSTALLING); foreach ($release as $instance) { if (isset($instance['installconditions'])) { $installconditions = $instance['installconditions']; if (is_array($installconditions)) { PEAR::pushErrorHandling(PEAR_ERROR_RETURN); foreach ($installconditions as $type => $conditions) { if (!isset($conditions[0])) { $conditions = array($conditions); } foreach ($conditions as $condition) { $ret = $depchecker->{"validate{$type}Dependency"}($condition); if (PEAR::isError($ret)) { PEAR::popErrorHandling(); continue 3; // skip this release } } } PEAR::popErrorHandling(); } } // this is the release to use if (isset($instance['filelist'])) { // ignore files if (isset($instance['filelist']['ignore'])) { $ignore = isset($instance['filelist']['ignore'][0]) ? $instance['filelist']['ignore'] : array($instance['filelist']['ignore']); foreach ($ignore as $ig) { unset ($contents[$ig['attribs']['name']]); } } // install files as this name if (isset($instance['filelist']['install'])) { $installas = isset($instance['filelist']['install'][0]) ? $instance['filelist']['install'] : array($instance['filelist']['install']); foreach ($installas as $as) { $contents[$as['attribs']['name']]['attribs']['install-as'] = $as['attribs']['as']; } } } if ($forfilecheck) { foreach ($contents as $file => $attrs) { $contents[$file] = $attrs['attribs']; } } return $contents; } } else { // simple release - no installconditions or install-as if ($forfilecheck) { return $this->getFilelist(); } return $contents; } // no releases matched return PEAR::raiseError('No releases in package.xml matched the existing operating ' . 'system, extensions installed, or architecture, cannot install'); } /** * This is only used at install-time, after all serialization * is over. * @param string file name * @param string installed path */ function setInstalledAs($file, $path) { if ($path) { return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; } unset($this->_packageInfo['filelist'][$file]['installed_as']); } function getInstalledLocation($file) { if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) { return $this->_packageInfo['filelist'][$file]['installed_as']; } return false; } /** * This is only used at install-time, after all serialization * is over. */ function installedFile($file, $atts) { if (isset($this->_packageInfo['filelist'][$file])) { $this->_packageInfo['filelist'][$file] = array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']); } else { $this->_packageInfo['filelist'][$file] = $atts['attribs']; } } /** * Retrieve the contents tag */ function getContents() { if (isset($this->_packageInfo['contents'])) { return $this->_packageInfo['contents']; } return false; } /** * @param string full path to file * @param string attribute name * @param string attribute value * @param int risky but fast - use this to choose a file based on its position in the list * of files. Index is zero-based like PHP arrays. * @return bool success of operation */ function setFileAttribute($filename, $attr, $value, $index = false) { $this->_isValid = 0; if (in_array($attr, array('role', 'name', 'baseinstalldir'))) { $this->_filesValid = false; } if ($index !== false && isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) { $this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value; return true; } if (!isset($this->_packageInfo['contents']['dir']['file'])) { return false; } $files = $this->_packageInfo['contents']['dir']['file']; if (!isset($files[0])) { $files = array($files); $ind = false; } else { $ind = true; } foreach ($files as $i => $file) { if (isset($file['attribs'])) { if ($file['attribs']['name'] == $filename) { if ($ind) { $this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value; } else { $this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value; } return true; } } } return false; } function setDirtree($path) { if (!isset($this->_packageInfo['dirtree'])) { $this->_packageInfo['dirtree'] = array(); } $this->_packageInfo['dirtree'][$path] = true; } function getDirtree() { if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) { return $this->_packageInfo['dirtree']; } return false; } function resetDirtree() { unset($this->_packageInfo['dirtree']); } /** * Determines whether this package claims it is compatible with the version of * the package that has a recommended version dependency * @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package * @return boolean */ function isCompatible($pf) { if (!isset($this->_packageInfo['compatible'])) { return false; } if (!isset($this->_packageInfo['channel'])) { return false; } $me = $pf->getVersion(); $compatible = $this->_packageInfo['compatible']; if (!isset($compatible[0])) { $compatible = array($compatible); } $found = false; foreach ($compatible as $info) { if (strtolower($info['name']) == strtolower($pf->getPackage())) { if (strtolower($info['channel']) == strtolower($pf->getChannel())) { $found = true; break; } } } if (!$found) { return false; } if (isset($info['exclude'])) { if (!isset($info['exclude'][0])) { $info['exclude'] = array($info['exclude']); } foreach ($info['exclude'] as $exclude) { if (version_compare($me, $exclude, '==')) { return false; } } } if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) { return true; } return false; } /** * @return array|false */ function getCompatible() { if (isset($this->_packageInfo['compatible'])) { return $this->_packageInfo['compatible']; } return false; } function getDependencies() { if (isset($this->_packageInfo['dependencies'])) { return $this->_packageInfo['dependencies']; } return false; } function isSubpackageOf($p) { return $p->isSubpackage($this); } /** * Determines whether the passed in package is a subpackage of this package. * * No version checking is done, only name verification. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @return bool */ function isSubpackage($p) { $sub = array(); if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) { $sub = $this->_packageInfo['dependencies']['required']['subpackage']; if (!isset($sub[0])) { $sub = array($sub); } } if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) { $sub1 = $this->_packageInfo['dependencies']['optional']['subpackage']; if (!isset($sub1[0])) { $sub1 = array($sub1); } $sub = array_merge($sub, $sub1); } if (isset($this->_packageInfo['dependencies']['group'])) { $group = $this->_packageInfo['dependencies']['group']; if (!isset($group[0])) { $group = array($group); } foreach ($group as $deps) { if (isset($deps['subpackage'])) { $sub2 = $deps['subpackage']; if (!isset($sub2[0])) { $sub2 = array($sub2); } $sub = array_merge($sub, $sub2); } } } foreach ($sub as $dep) { if (strtolower($dep['name']) == strtolower($p->getPackage())) { if (isset($dep['channel'])) { if (strtolower($dep['channel']) == strtolower($p->getChannel())) { return true; } } else { if ($dep['uri'] == $p->getURI()) { return true; } } } } return false; } function dependsOn($package, $channel) { if (!($deps = $this->getDependencies())) { return false; } foreach (array('package', 'subpackage') as $type) { foreach (array('required', 'optional') as $needed) { if (isset($deps[$needed][$type])) { if (!isset($deps[$needed][$type][0])) { $deps[$needed][$type] = array($deps[$needed][$type]); } foreach ($deps[$needed][$type] as $dep) { $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri'; if (strtolower($dep['name']) == strtolower($package) && $depchannel == $channel) { return true; } } } } if (isset($deps['group'])) { if (!isset($deps['group'][0])) { $dep['group'] = array($deps['group']); } foreach ($deps['group'] as $group) { if (isset($group[$type])) { if (!is_array($group[$type])) { $group[$type] = array($group[$type]); } foreach ($group[$type] as $dep) { $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri'; if (strtolower($dep['name']) == strtolower($package) && $depchannel == $channel) { return true; } } } } } } return false; } /** * Get the contents of a dependency group * @param string * @return array|false */ function getDependencyGroup($name) { $name = strtolower($name); if (!isset($this->_packageInfo['dependencies']['group'])) { return false; } $groups = $this->_packageInfo['dependencies']['group']; if (!isset($groups[0])) { $groups = array($groups); } foreach ($groups as $group) { if (strtolower($group['attribs']['name']) == $name) { return $group; } } return false; } /** * Retrieve a partial package.xml 1.0 representation of dependencies * * a very limited representation of dependencies is returned by this method. * The tag for excluding certain versions of a dependency is * completely ignored. In addition, dependency groups are ignored, with the * assumption that all dependencies in dependency groups are also listed in * the optional group that work with all dependency groups * @param boolean return package.xml 2.0 tag * @return array|false */ function getDeps($raw = false, $nopearinstaller = false) { if (isset($this->_packageInfo['dependencies'])) { if ($raw) { return $this->_packageInfo['dependencies']; } $ret = array(); $map = array( 'php' => 'php', 'package' => 'pkg', 'subpackage' => 'pkg', 'extension' => 'ext', 'os' => 'os', 'pearinstaller' => 'pkg', ); foreach (array('required', 'optional') as $type) { $optional = ($type == 'optional') ? 'yes' : 'no'; if (!isset($this->_packageInfo['dependencies'][$type]) || empty($this->_packageInfo['dependencies'][$type])) { continue; } foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) { if ($dtype == 'pearinstaller' && $nopearinstaller) { continue; } if ((is_array($deps) && !isset($deps[0])) || !is_array($deps)) { $deps = array($deps); } foreach ($deps as $dep) { if (!isset($map[$dtype])) { // no support for arch type continue; } if ($dtype == 'pearinstaller') { $dep['name'] = 'PEAR'; $dep['channel'] = 'pear.php.net'; } $s = array('type' => $map[$dtype]); if (isset($dep['channel'])) { $s['channel'] = $dep['channel']; } if (isset($dep['uri'])) { $s['uri'] = $dep['uri']; } if (isset($dep['name'])) { $s['name'] = $dep['name']; } if (isset($dep['conflicts'])) { $s['rel'] = 'not'; } else { if (!isset($dep['min']) && !isset($dep['max'])) { $s['rel'] = 'has'; $s['optional'] = $optional; } elseif (isset($dep['min']) && isset($dep['max'])) { $s['rel'] = 'ge'; $s1 = $s; $s1['rel'] = 'le'; $s['version'] = $dep['min']; $s1['version'] = $dep['max']; if (isset($dep['channel'])) { $s1['channel'] = $dep['channel']; } if ($dtype != 'php') { $s['name'] = $dep['name']; $s1['name'] = $dep['name']; } $s['optional'] = $optional; $s1['optional'] = $optional; $ret[] = $s1; } elseif (isset($dep['min'])) { if (isset($dep['exclude']) && $dep['exclude'] == $dep['min']) { $s['rel'] = 'gt'; } else { $s['rel'] = 'ge'; } $s['version'] = $dep['min']; $s['optional'] = $optional; if ($dtype != 'php') { $s['name'] = $dep['name']; } } elseif (isset($dep['max'])) { if (isset($dep['exclude']) && $dep['exclude'] == $dep['max']) { $s['rel'] = 'lt'; } else { $s['rel'] = 'le'; } $s['version'] = $dep['max']; $s['optional'] = $optional; if ($dtype != 'php') { $s['name'] = $dep['name']; } } } $ret[] = $s; } } } if (count($ret)) { return $ret; } } return false; } /** * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false */ function getPackageType() { if (isset($this->_packageInfo['phprelease'])) { return 'php'; } if (isset($this->_packageInfo['extsrcrelease'])) { return 'extsrc'; } if (isset($this->_packageInfo['extbinrelease'])) { return 'extbin'; } if (isset($this->_packageInfo['zendextsrcrelease'])) { return 'zendextsrc'; } if (isset($this->_packageInfo['zendextbinrelease'])) { return 'zendextbin'; } if (isset($this->_packageInfo['bundle'])) { return 'bundle'; } return false; } /** * @return array|false */ function getReleases() { $type = $this->getPackageType(); if ($type != 'bundle') { $type .= 'release'; } if ($this->getPackageType() && isset($this->_packageInfo[$type])) { return $this->_packageInfo[$type]; } return false; } /** * @return array */ function getChangelog() { if (isset($this->_packageInfo['changelog'])) { return $this->_packageInfo['changelog']; } return false; } function hasDeps() { return isset($this->_packageInfo['dependencies']); } function getPackagexmlVersion() { if (isset($this->_packageInfo['zendextsrcrelease'])) { return '2.1'; } if (isset($this->_packageInfo['zendextbinrelease'])) { return '2.1'; } return '2.0'; } /** * @return array|false */ function getSourcePackage() { if (isset($this->_packageInfo['extbinrelease']) || isset($this->_packageInfo['zendextbinrelease'])) { return array('channel' => $this->_packageInfo['srcchannel'], 'package' => $this->_packageInfo['srcpackage']); } return false; } function getBundledPackages() { if (isset($this->_packageInfo['bundle'])) { return $this->_packageInfo['contents']['bundledpackage']; } return false; } function getLastModified() { if (isset($this->_packageInfo['_lastmodified'])) { return $this->_packageInfo['_lastmodified']; } return false; } /** * Get the contents of a file listed within the package.xml * @param string * @return string */ function getFileContents($file) { if ($this->_archiveFile == $this->_packageFile) { // unpacked $dir = dirname($this->_packageFile); $file = $dir . DIRECTORY_SEPARATOR . $file; $file = str_replace(array('/', '\\'), array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file); if (file_exists($file) && is_readable($file)) { return implode('', file($file)); } } else { // tgz $tar = new Archive_Tar($this->_archiveFile); $tar->pushErrorHandling(PEAR_ERROR_RETURN); if ($file != 'package.xml' && $file != 'package2.xml') { $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file; } $file = $tar->extractInString($file); $tar->popErrorHandling(); if (PEAR::isError($file)) { return PEAR::raiseError("Cannot locate file '$file' in archive"); } return $file; } } function &getRW() { if (!class_exists('PEAR_PackageFile_v2_rw')) { require_once 'PEAR/PackageFile/v2/rw.php'; } $a = new PEAR_PackageFile_v2_rw; foreach (get_object_vars($this) as $name => $unused) { if (!isset($this->$name)) { continue; } if ($name == '_config' || $name == '_logger'|| $name == '_registry' || $name == '_stack') { $a->$name = &$this->$name; } else { $a->$name = $this->$name; } } return $a; } function &getDefaultGenerator() { if (!class_exists('PEAR_PackageFile_Generator_v2')) { require_once 'PEAR/PackageFile/Generator/v2.php'; } $a = new PEAR_PackageFile_Generator_v2($this); return $a; } function analyzeSourceCode($file, $string = false) { if (!isset($this->_v2Validator) || !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) { if (!class_exists('PEAR_PackageFile_v2_Validator')) { require_once 'PEAR/PackageFile/v2/Validator.php'; } $this->_v2Validator = new PEAR_PackageFile_v2_Validator; } return $this->_v2Validator->analyzeSourceCode($file, $string); } function validate($state = PEAR_VALIDATE_NORMAL) { if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { return false; } if (!isset($this->_v2Validator) || !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) { if (!class_exists('PEAR_PackageFile_v2_Validator')) { require_once 'PEAR/PackageFile/v2/Validator.php'; } $this->_v2Validator = new PEAR_PackageFile_v2_Validator; } if (isset($this->_packageInfo['xsdversion'])) { unset($this->_packageInfo['xsdversion']); } return $this->_v2Validator->validate($this, $state); } function getTasksNs() { if (!isset($this->_tasksNs)) { if (isset($this->_packageInfo['attribs'])) { foreach ($this->_packageInfo['attribs'] as $name => $value) { if ($value == 'http://pear.php.net/dtd/tasks-1.0') { $this->_tasksNs = str_replace('xmlns:', '', $name); break; } } } } return $this->_tasksNs; } /** * Determine whether a task name is a valid task. Custom tasks may be defined * using subdirectories by putting a "-" in the name, as in * * Note that this method will auto-load the task class file and test for the existence * of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class * PEAR_Task_mycustom_task * @param string * @return boolean */ function getTask($task) { $this->getTasksNs(); // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace $task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task); $taskfile = str_replace(' ', '/', ucwords($task)); $task = str_replace(array(' ', '/'), '_', ucwords($task)); if (class_exists("PEAR_Task_$task")) { return "PEAR_Task_$task"; } $fp = @fopen("PEAR/Task/$taskfile.php", 'r', true); if ($fp) { fclose($fp); require_once "PEAR/Task/$taskfile.php"; return "PEAR_Task_$task"; } return false; } /** * Key-friendly array_splice * @param tagname to splice a value in before * @param mixed the value to splice in * @param string the new tag name */ function _ksplice($array, $key, $value, $newkey) { $offset = array_search($key, array_keys($array)); $after = array_slice($array, $offset); $before = array_slice($array, 0, $offset); $before[$newkey] = $value; return array_merge($before, $after); } /** * @param array a list of possible keys, in the order they may occur * @param mixed contents of the new package.xml tag * @param string tag name * @access private */ function _insertBefore($array, $keys, $contents, $newkey) { foreach ($keys as $key) { if (isset($array[$key])) { return $array = $this->_ksplice($array, $key, $contents, $newkey); } } $array[$newkey] = $contents; return $array; } /** * @param subsection of {@link $_packageInfo} * @param array|string tag contents * @param array format: *
     * array(
     *   tagname => array(list of tag names that follow this one),
     *   childtagname => array(list of child tag names that follow this one),
     * )
     * 
* * This allows construction of nested tags * @access private */ function _mergeTag($manip, $contents, $order) { if (count($order)) { foreach ($order as $tag => $curorder) { if (!isset($manip[$tag])) { // ensure that the tag is set up $manip = $this->_insertBefore($manip, $curorder, array(), $tag); } if (count($order) > 1) { $manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1)); return $manip; } } } else { return $manip; } if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) { $manip[$tag][] = $contents; } else { if (is_array($manip[$tag]) && !count($manip[$tag])) { $manip[$tag] = $contents; } else { $manip[$tag] = array($manip[$tag]); $manip[$tag][] = $contents; } } return $manip; } } ?> PK!C8LL!PEAR/PackageFile/v2/Validator.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a8 */ /** * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a8 * @access private */ class PEAR_PackageFile_v2_Validator { /** * @var array */ var $_packageInfo; /** * @var PEAR_PackageFile_v2 */ var $_pf; /** * @var PEAR_ErrorStack */ var $_stack; /** * @var int */ var $_isValid = 0; /** * @var int */ var $_filesValid = 0; /** * @var int */ var $_curState = 0; /** * @param PEAR_PackageFile_v2 * @param int */ function validate(&$pf, $state = PEAR_VALIDATE_NORMAL) { $this->_pf = &$pf; $this->_curState = $state; $this->_packageInfo = $this->_pf->getArray(); $this->_isValid = $this->_pf->_isValid; $this->_filesValid = $this->_pf->_filesValid; $this->_stack = &$pf->_stack; $this->_stack->getErrors(true); if (($this->_isValid & $state) == $state) { return true; } if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { return false; } if (!isset($this->_packageInfo['attribs']['version']) || ($this->_packageInfo['attribs']['version'] != '2.0' && $this->_packageInfo['attribs']['version'] != '2.1') ) { $this->_noPackageVersion(); } $structure = array( 'name', 'channel|uri', '*extends', // can't be multiple, but this works fine 'summary', 'description', '+lead', // these all need content checks '*developer', '*contributor', '*helper', 'date', '*time', 'version', 'stability', 'license->?uri->?filesource', 'notes', 'contents', //special validation needed '*compatible', 'dependencies', //special validation needed '*usesrole', '*usestask', // reserve these for 1.4.0a1 to implement // this will allow a package.xml to gracefully say it // needs a certain package installed in order to implement a role or task '*providesextension', '*srcpackage|*srcuri', '+phprelease|+extsrcrelease|+extbinrelease|' . '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed '*changelog', ); $test = $this->_packageInfo; if (isset($test['dependencies']) && isset($test['dependencies']['required']) && isset($test['dependencies']['required']['pearinstaller']) && isset($test['dependencies']['required']['pearinstaller']['min']) && '1.10.16' != '@package' . '_version@' && version_compare('1.10.16', $test['dependencies']['required']['pearinstaller']['min'], '<') ) { $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']); return false; } // ignore post-installation array fields if (array_key_exists('filelist', $test)) { unset($test['filelist']); } if (array_key_exists('_lastmodified', $test)) { unset($test['_lastmodified']); } if (array_key_exists('#binarypackage', $test)) { unset($test['#binarypackage']); } if (array_key_exists('old', $test)) { unset($test['old']); } if (array_key_exists('_lastversion', $test)) { unset($test['_lastversion']); } if (!$this->_stupidSchemaValidate($structure, $test, '')) { return false; } if (empty($this->_packageInfo['name'])) { $this->_tagCannotBeEmpty('name'); } $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel'; if (empty($this->_packageInfo[$test])) { $this->_tagCannotBeEmpty($test); } if (is_array($this->_packageInfo['license']) && (!isset($this->_packageInfo['license']['_content']) || empty($this->_packageInfo['license']['_content']))) { $this->_tagCannotBeEmpty('license'); } elseif (empty($this->_packageInfo['license'])) { $this->_tagCannotBeEmpty('license'); } if (empty($this->_packageInfo['summary'])) { $this->_tagCannotBeEmpty('summary'); } if (empty($this->_packageInfo['description'])) { $this->_tagCannotBeEmpty('description'); } if (empty($this->_packageInfo['date'])) { $this->_tagCannotBeEmpty('date'); } if (empty($this->_packageInfo['notes'])) { $this->_tagCannotBeEmpty('notes'); } if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) { $this->_tagCannotBeEmpty('time'); } if (isset($this->_packageInfo['dependencies'])) { $this->_validateDependencies(); } if (isset($this->_packageInfo['compatible'])) { $this->_validateCompatible(); } if (!isset($this->_packageInfo['bundle'])) { if (empty($this->_packageInfo['contents'])) { $this->_tagCannotBeEmpty('contents'); } if (!isset($this->_packageInfo['contents']['dir'])) { $this->_filelistMustContainDir('contents'); return false; } if (isset($this->_packageInfo['contents']['file'])) { $this->_filelistCannotContainFile('contents'); return false; } } $this->_validateMaintainers(); $this->_validateStabilityVersion(); $fail = false; if (array_key_exists('usesrole', $this->_packageInfo)) { $roles = $this->_packageInfo['usesrole']; if (!is_array($roles) || !isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if (!isset($role['role'])) { $this->_usesroletaskMustHaveRoleTask('usesrole', 'role'); $fail = true; } else { if (!isset($role['channel'])) { if (!isset($role['uri'])) { $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole'); $fail = true; } } elseif (!isset($role['package'])) { $this->_usesroletaskMustHavePackage($role['role'], 'usesrole'); $fail = true; } } } } if (array_key_exists('usestask', $this->_packageInfo)) { $roles = $this->_packageInfo['usestask']; if (!is_array($roles) || !isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if (!isset($role['task'])) { $this->_usesroletaskMustHaveRoleTask('usestask', 'task'); $fail = true; } else { if (!isset($role['channel'])) { if (!isset($role['uri'])) { $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask'); $fail = true; } } elseif (!isset($role['package'])) { $this->_usesroletaskMustHavePackage($role['task'], 'usestask'); $fail = true; } } } } if ($fail) { return false; } $list = $this->_packageInfo['contents']; if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) { $this->_multipleToplevelDirNotAllowed(); return $this->_isValid = 0; } $this->_validateFilelist(); $this->_validateRelease(); if (!$this->_stack->hasErrors()) { $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true); if (PEAR::isError($chan)) { $this->_unknownChannel($this->_pf->getChannel()); } else { $valpack = $chan->getValidationPackage(); // for channel validator packages, always use the default PEAR validator. // otherwise, they can't be installed or packaged $validator = $chan->getValidationObject($this->_pf->getPackage()); if (!$validator) { $this->_stack->push(__FUNCTION__, 'error', array('channel' => $chan->getName(), 'package' => $this->_pf->getPackage(), 'name' => $valpack['_content'], 'version' => $valpack['attribs']['version']), 'package "%channel%/%package%" cannot be properly validated without ' . 'validation package "%channel%/%name%-%version%"'); return $this->_isValid = 0; } $validator->setPackageFile($this->_pf); $validator->validate($state); $failures = $validator->getFailures(); foreach ($failures['errors'] as $error) { $this->_stack->push(__FUNCTION__, 'error', $error, 'Channel validator error: field "%field%" - %reason%'); } foreach ($failures['warnings'] as $warning) { $this->_stack->push(__FUNCTION__, 'warning', $warning, 'Channel validator warning: field "%field%" - %reason%'); } } } $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error'); if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) { if ($this->_pf->getPackageType() == 'bundle') { if ($this->_analyzeBundledPackages()) { $this->_filesValid = $this->_pf->_filesValid = true; } else { $this->_pf->_isValid = $this->_isValid = 0; } } else { if (!$this->_analyzePhpFiles()) { $this->_pf->_isValid = $this->_isValid = 0; } else { $this->_filesValid = $this->_pf->_filesValid = true; } } } if ($this->_isValid) { return $this->_pf->_isValid = $this->_isValid = $state; } return $this->_pf->_isValid = $this->_isValid = 0; } function _stupidSchemaValidate($structure, $xml, $root) { if (!is_array($xml)) { $xml = array(); } $keys = array_keys($xml); reset($keys); $key = current($keys); while ($key == 'attribs' || $key == '_contents') { $key = next($keys); } $unfoundtags = $optionaltags = array(); $ret = true; $mismatch = false; foreach ($structure as $struc) { if ($key) { $tag = $xml[$key]; } $test = $this->_processStructure($struc); if (isset($test['choices'])) { $loose = true; foreach ($test['choices'] as $choice) { if ($key == $choice['tag']) { $key = next($keys); while ($key == 'attribs' || $key == '_contents') { $key = next($keys); } $unfoundtags = $optionaltags = array(); $mismatch = false; if ($key && $key != $choice['tag'] && isset($choice['multiple'])) { $unfoundtags[] = $choice['tag']; $optionaltags[] = $choice['tag']; if ($key) { $mismatch = true; } } $ret &= $this->_processAttribs($choice, $tag, $root); continue 2; } else { $unfoundtags[] = $choice['tag']; $mismatch = true; } if (!isset($choice['multiple']) || $choice['multiple'] != '*') { $loose = false; } else { $optionaltags[] = $choice['tag']; } } if (!$loose) { $this->_invalidTagOrder($unfoundtags, $key, $root); return false; } } else { if ($key != $test['tag']) { if (isset($test['multiple']) && $test['multiple'] != '*') { $unfoundtags[] = $test['tag']; $this->_invalidTagOrder($unfoundtags, $key, $root); return false; } else { if ($key) { $mismatch = true; } $unfoundtags[] = $test['tag']; $optionaltags[] = $test['tag']; } if (!isset($test['multiple'])) { $this->_invalidTagOrder($unfoundtags, $key, $root); return false; } continue; } else { $unfoundtags = $optionaltags = array(); $mismatch = false; } $key = next($keys); while ($key == 'attribs' || $key == '_contents') { $key = next($keys); } if ($key && $key != $test['tag'] && isset($test['multiple'])) { $unfoundtags[] = $test['tag']; $optionaltags[] = $test['tag']; $mismatch = true; } $ret &= $this->_processAttribs($test, $tag, $root); continue; } } if (!$mismatch && count($optionaltags)) { // don't error out on any optional tags $unfoundtags = array_diff($unfoundtags, $optionaltags); } if (count($unfoundtags)) { $this->_invalidTagOrder($unfoundtags, $key, $root); } elseif ($key) { // unknown tags $this->_invalidTagOrder('*no tags allowed here*', $key, $root); while ($key = next($keys)) { $this->_invalidTagOrder('*no tags allowed here*', $key, $root); } } return $ret; } function _processAttribs($choice, $tag, $context) { if (isset($choice['attribs'])) { if (!is_array($tag)) { $tag = array($tag); } $tags = $tag; if (!isset($tags[0])) { $tags = array($tags); } $ret = true; foreach ($tags as $i => $tag) { if (!is_array($tag) || !isset($tag['attribs'])) { foreach ($choice['attribs'] as $attrib) { if ($attrib[0] != '?') { $ret &= $this->_tagHasNoAttribs($choice['tag'], $context); continue 2; } } } foreach ($choice['attribs'] as $attrib) { if ($attrib[0] != '?') { if (!isset($tag['attribs'][$attrib])) { $ret &= $this->_tagMissingAttribute($choice['tag'], $attrib, $context); } } } } return $ret; } return true; } function _processStructure($key) { $ret = array(); if (count($pieces = explode('|', $key)) > 1) { $ret['choices'] = array(); foreach ($pieces as $piece) { $ret['choices'][] = $this->_processStructure($piece); } return $ret; } $multi = $key[0]; if ($multi == '+' || $multi == '*') { $ret['multiple'] = $key[0]; $key = substr($key, 1); } if (count($attrs = explode('->', $key)) > 1) { $ret['tag'] = array_shift($attrs); $ret['attribs'] = $attrs; } else { $ret['tag'] = $key; } return $ret; } function _validateStabilityVersion() { $structure = array('release', 'api'); $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], ''); $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], ''); if ($a) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $this->_packageInfo['version']['release'])) { $this->_invalidVersion('release', $this->_packageInfo['version']['release']); } if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $this->_packageInfo['version']['api'])) { $this->_invalidVersion('api', $this->_packageInfo['version']['api']); } if (!in_array($this->_packageInfo['stability']['release'], array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) { $this->_invalidState('release', $this->_packageInfo['stability']['release']); } if (!in_array($this->_packageInfo['stability']['api'], array('devel', 'alpha', 'beta', 'stable'))) { $this->_invalidState('api', $this->_packageInfo['stability']['api']); } } } function _validateMaintainers() { $structure = array( 'name', 'user', 'email', 'active', ); foreach (array('lead', 'developer', 'contributor', 'helper') as $type) { if (!isset($this->_packageInfo[$type])) { continue; } if (isset($this->_packageInfo[$type][0])) { foreach ($this->_packageInfo[$type] as $lead) { $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>'); } } else { $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type], '<' . $type . '>'); } } } function _validatePhpDep($dep, $installcondition = false) { $structure = array( 'min', '*max', '*exclude', ); $type = $installcondition ? '' : ''; $this->_stupidSchemaValidate($structure, $dep, $type); if (isset($dep['min'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', $dep['min'])) { $this->_invalidVersion($type . '', $dep['min']); } } if (isset($dep['max'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', $dep['max'])) { $this->_invalidVersion($type . '', $dep['max']); } } if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } foreach ($dep['exclude'] as $exclude) { if (!preg_match( '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', $exclude)) { $this->_invalidVersion($type . '', $exclude); } } } } function _validatePearinstallerDep($dep) { $structure = array( 'min', '*max', '*recommended', '*exclude', ); $this->_stupidSchemaValidate($structure, $dep, ''); if (isset($dep['min'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['min'])) { $this->_invalidVersion('', $dep['min']); } } if (isset($dep['max'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['max'])) { $this->_invalidVersion('', $dep['max']); } } if (isset($dep['recommended'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['recommended'])) { $this->_invalidVersion('', $dep['recommended']); } } if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } foreach ($dep['exclude'] as $exclude) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $exclude)) { $this->_invalidVersion('', $exclude); } } } } function _validatePackageDep($dep, $group, $type = '') { if (isset($dep['uri'])) { if (isset($dep['conflicts'])) { $structure = array( 'name', 'uri', 'conflicts', '*providesextension', ); } else { $structure = array( 'name', 'uri', '*providesextension', ); } } else { if (isset($dep['conflicts'])) { $structure = array( 'name', 'channel', '*min', '*max', '*exclude', 'conflicts', '*providesextension', ); } else { $structure = array( 'name', 'channel', '*min', '*max', '*recommended', '*exclude', '*nodefault', '*providesextension', ); } } if (isset($dep['name'])) { $type .= '' . $dep['name'] . ''; } $this->_stupidSchemaValidate($structure, $dep, '' . $group . $type); if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) || isset($dep['recommended']) || isset($dep['exclude']))) { $this->_uriDepsCannotHaveVersioning('' . $group . $type); } if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') { $this->_DepchannelCannotBeUri('' . $group . $type); } if (isset($dep['min'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['min'])) { $this->_invalidVersion('' . $group . $type . '', $dep['min']); } } if (isset($dep['max'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['max'])) { $this->_invalidVersion('' . $group . $type . '', $dep['max']); } } if (isset($dep['recommended'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['recommended'])) { $this->_invalidVersion('' . $group . $type . '', $dep['recommended']); } } if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } foreach ($dep['exclude'] as $exclude) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $exclude)) { $this->_invalidVersion('' . $group . $type . '', $exclude); } } } } function _validateSubpackageDep($dep, $group) { $this->_validatePackageDep($dep, $group, ''); if (isset($dep['providesextension'])) { $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : ''); } if (isset($dep['conflicts'])) { $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : ''); } } function _validateExtensionDep($dep, $group = false, $installcondition = false) { if (isset($dep['conflicts'])) { $structure = array( 'name', '*min', '*max', '*exclude', 'conflicts', ); } else { $structure = array( 'name', '*min', '*max', '*recommended', '*exclude', ); } if ($installcondition) { $type = ''; } else { $type = '' . $group . ''; } if (isset($dep['name'])) { $type .= '' . $dep['name'] . ''; } $this->_stupidSchemaValidate($structure, $dep, $type); if (isset($dep['min'])) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $dep['min'])) { $this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '' : ''; if ($this->_stupidSchemaValidate($structure, $dep, $type)) { if ($dep['name'] == '*') { if (array_key_exists('conflicts', $dep)) { $this->_cannotConflictWithAllOs($type); } } } } function _validateArchDep($dep, $installcondition = false) { $structure = array( 'pattern', '*conflicts', ); $type = $installcondition ? '' : ''; $this->_stupidSchemaValidate($structure, $dep, $type); } function _validateInstallConditions($cond, $release) { $structure = array( '*php', '*extension', '*os', '*arch', ); if (!$this->_stupidSchemaValidate($structure, $cond, $release)) { return false; } foreach (array('php', 'extension', 'os', 'arch') as $type) { if (isset($cond[$type])) { $iter = $cond[$type]; if (!is_array($iter) || !isset($iter[0])) { $iter = array($iter); } foreach ($iter as $package) { if ($type == 'extension') { $this->{"_validate{$type}Dep"}($package, false, true); } else { $this->{"_validate{$type}Dep"}($package, true); } } } } } function _validateDependencies() { $structure = array( 'required', '*optional', '*group->name->hint' ); if (!$this->_stupidSchemaValidate($structure, $this->_packageInfo['dependencies'], '')) { return false; } foreach (array('required', 'optional') as $simpledep) { if (isset($this->_packageInfo['dependencies'][$simpledep])) { if ($simpledep == 'optional') { $structure = array( '*package', '*subpackage', '*extension', ); } else { $structure = array( 'php', 'pearinstaller', '*package', '*subpackage', '*extension', '*os', '*arch', ); } if ($this->_stupidSchemaValidate($structure, $this->_packageInfo['dependencies'][$simpledep], "<$simpledep>")) { foreach (array('package', 'subpackage', 'extension') as $type) { if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { $iter = $this->_packageInfo['dependencies'][$simpledep][$type]; if (!isset($iter[0])) { $iter = array($iter); } foreach ($iter as $package) { if ($type != 'extension') { if (isset($package['uri'])) { if (isset($package['channel'])) { $this->_UrlOrChannel($type, $package['name']); } } else { if (!isset($package['channel'])) { $this->_NoChannel($type, $package['name']); } } } $this->{"_validate{$type}Dep"}($package, "<$simpledep>"); } } } if ($simpledep == 'optional') { continue; } foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) { if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { $iter = $this->_packageInfo['dependencies'][$simpledep][$type]; if (!isset($iter[0])) { $iter = array($iter); } foreach ($iter as $package) { $this->{"_validate{$type}Dep"}($package); } } } } } } if (isset($this->_packageInfo['dependencies']['group'])) { $groups = $this->_packageInfo['dependencies']['group']; if (!isset($groups[0])) { $groups = array($groups); } $structure = array( '*package', '*subpackage', '*extension', ); foreach ($groups as $group) { if ($this->_stupidSchemaValidate($structure, $group, '')) { if (!PEAR_Validate::validGroupName($group['attribs']['name'])) { $this->_invalidDepGroupName($group['attribs']['name']); } foreach (array('package', 'subpackage', 'extension') as $type) { if (isset($group[$type])) { $iter = $group[$type]; if (!isset($iter[0])) { $iter = array($iter); } foreach ($iter as $package) { if ($type != 'extension') { if (isset($package['uri'])) { if (isset($package['channel'])) { $this->_UrlOrChannelGroup($type, $package['name'], $group['name']); } } else { if (!isset($package['channel'])) { $this->_NoChannelGroup($type, $package['name'], $group['name']); } } } $this->{"_validate{$type}Dep"}($package, ''); } } } } } } } function _validateCompatible() { $compat = $this->_packageInfo['compatible']; if (!isset($compat[0])) { $compat = array($compat); } $required = array('name', 'channel', 'min', 'max', '*exclude'); foreach ($compat as $package) { $type = ''; if (is_array($package) && array_key_exists('name', $package)) { $type .= '' . $package['name'] . ''; } $this->_stupidSchemaValidate($required, $package, $type); if (is_array($package) && array_key_exists('min', $package)) { if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', $package['min'])) { $this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_NoBundledPackages(); } if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) { return $this->_AtLeast2BundledPackages(); } foreach ($list['bundledpackage'] as $package) { if (!is_string($package)) { $this->_bundledPackagesMustBeFilename(); } } } function _validateFilelist($list = false, $allowignore = false, $dirs = '') { $iscontents = false; if (!$list) { $iscontents = true; $list = $this->_packageInfo['contents']; if (isset($this->_packageInfo['bundle'])) { return $this->_validateBundle($list); } } if ($allowignore) { $struc = array( '*install->name->as', '*ignore->name' ); } else { $struc = array( '*dir->name->?baseinstalldir', '*file->name->role->?baseinstalldir->?md5sum' ); if (isset($list['dir']) && isset($list['file'])) { // stave off validation errors without requiring a set order. $_old = $list; if (isset($list['attribs'])) { $list = array('attribs' => $_old['attribs']); } $list['dir'] = $_old['dir']; $list['file'] = $_old['file']; } } if (!isset($list['attribs']) || !isset($list['attribs']['name'])) { $unknown = $allowignore ? '' : ''; $dirname = $iscontents ? '' : $unknown; } else { $dirname = ''; if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $list['attribs']['name']))) { // file contains .. parent directory or . cur directory $this->_invalidDirName($list['attribs']['name']); } } $res = $this->_stupidSchemaValidate($struc, $list, $dirname); if ($allowignore && $res) { $ignored_or_installed = array(); $this->_pf->getFilelist(); $fcontents = $this->_pf->getContents(); $filelist = array(); if (!isset($fcontents['dir']['file'][0])) { $fcontents['dir']['file'] = array($fcontents['dir']['file']); } foreach ($fcontents['dir']['file'] as $file) { $filelist[$file['attribs']['name']] = true; } if (isset($list['install'])) { if (!isset($list['install'][0])) { $list['install'] = array($list['install']); } foreach ($list['install'] as $file) { if (!isset($filelist[$file['attribs']['name']])) { $this->_notInContents($file['attribs']['name'], 'install'); continue; } if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { $this->_multipleInstallAs($file['attribs']['name']); } if (!isset($ignored_or_installed[$file['attribs']['name']])) { $ignored_or_installed[$file['attribs']['name']] = array(); } $ignored_or_installed[$file['attribs']['name']][] = 1; if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file['attribs']['as']))) { // file contains .. parent directory or . cur directory references $this->_invalidFileInstallAs($file['attribs']['name'], $file['attribs']['as']); } } } if (isset($list['ignore'])) { if (!isset($list['ignore'][0])) { $list['ignore'] = array($list['ignore']); } foreach ($list['ignore'] as $file) { if (!isset($filelist[$file['attribs']['name']])) { $this->_notInContents($file['attribs']['name'], 'ignore'); continue; } if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { $this->_ignoreAndInstallAs($file['attribs']['name']); } } } } if (!$allowignore && isset($list['file'])) { if (is_string($list['file'])) { $this->_oldStyleFileNotAllowed(); return false; } if (!isset($list['file'][0])) { // single file $list['file'] = array($list['file']); } foreach ($list['file'] as $i => $file) { if (isset($file['attribs']) && isset($file['attribs']['name'])) { if ($file['attribs']['name'][0] == '.' && $file['attribs']['name'][1] == '/') { // name is something like "./doc/whatever.txt" $this->_invalidFileName($file['attribs']['name'], $dirname); } if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file['attribs']['name']))) { // file contains .. parent directory or . cur directory $this->_invalidFileName($file['attribs']['name'], $dirname); } } if (isset($file['attribs']) && isset($file['attribs']['role'])) { if (!$this->_validateRole($file['attribs']['role'])) { if (isset($this->_packageInfo['usesrole'])) { $roles = $this->_packageInfo['usesrole']; if (!isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if ($role['role'] = $file['attribs']['role']) { $msg = 'This package contains role "%role%" and requires ' . 'package "%package%" to be used'; if (isset($role['uri'])) { $params = array('role' => $role['role'], 'package' => $role['uri']); } else { $params = array('role' => $role['role'], 'package' => $this->_pf->_registry-> parsedPackageNameToString(array('package' => $role['package'], 'channel' => $role['channel']), true)); } $this->_stack->push('_mustInstallRole', 'error', $params, $msg); } } } $this->_invalidFileRole($file['attribs']['name'], $dirname, $file['attribs']['role']); } } if (!isset($file['attribs'])) { continue; } $save = $file['attribs']; if ($dirs) { $save['name'] = $dirs . '/' . $save['name']; } unset($file['attribs']); if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks foreach ($file as $task => $value) { if ($tagClass = $this->_pf->getTask($task)) { if (!is_array($value) || !isset($value[0])) { $value = array($value); } foreach ($value as $v) { $ret = call_user_func(array($tagClass, 'validateXml'), $this->_pf, $v, $this->_pf->_config, $save); if (is_array($ret)) { $this->_invalidTask($task, $ret, isset($save['name']) ? $save['name'] : ''); } } } else { if (isset($this->_packageInfo['usestask'])) { $roles = $this->_packageInfo['usestask']; if (!isset($roles[0])) { $roles = array($roles); } foreach ($roles as $role) { if ($role['task'] = $task) { $msg = 'This package contains task "%task%" and requires ' . 'package "%package%" to be used'; if (isset($role['uri'])) { $params = array('task' => $role['task'], 'package' => $role['uri']); } else { $params = array('task' => $role['task'], 'package' => $this->_pf->_registry-> parsedPackageNameToString(array('package' => $role['package'], 'channel' => $role['channel']), true)); } $this->_stack->push('_mustInstallTask', 'error', $params, $msg); } } } $this->_unknownTask($task, $save['name']); } } } } } if (isset($list['ignore'])) { if (!$allowignore) { $this->_ignoreNotAllowed('ignore'); } } if (isset($list['install'])) { if (!$allowignore) { $this->_ignoreNotAllowed('install'); } } if (isset($list['file'])) { if ($allowignore) { $this->_fileNotAllowed('file'); } } if (isset($list['dir'])) { if ($allowignore) { $this->_fileNotAllowed('dir'); } else { if (!isset($list['dir'][0])) { $list['dir'] = array($list['dir']); } foreach ($list['dir'] as $dir) { if (isset($dir['attribs']) && isset($dir['attribs']['name'])) { if ($dir['attribs']['name'] == '/' || !isset($this->_packageInfo['contents']['dir']['dir'])) { // always use nothing if the filelist has already been flattened $newdirs = ''; } elseif ($dirs == '') { $newdirs = $dir['attribs']['name']; } else { $newdirs = $dirs . '/' . $dir['attribs']['name']; } } else { $newdirs = $dirs; } $this->_validateFilelist($dir, $allowignore, $newdirs); } } } } function _validateRelease() { if (isset($this->_packageInfo['phprelease'])) { $release = 'phprelease'; if (isset($this->_packageInfo['providesextension'])) { $this->_cannotProvideExtension($release); } if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { $this->_cannotHaveSrcpackage($release); } $releases = $this->_packageInfo['phprelease']; if (!is_array($releases)) { return true; } if (!isset($releases[0])) { $releases = array($releases); } foreach ($releases as $rel) { $this->_stupidSchemaValidate(array( '*installconditions', '*filelist', ), $rel, ''); } } foreach (array('', 'zend') as $prefix) { $releasetype = $prefix . 'extsrcrelease'; if (isset($this->_packageInfo[$releasetype])) { $release = $releasetype; if (!isset($this->_packageInfo['providesextension'])) { $this->_mustProvideExtension($release); } if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { $this->_cannotHaveSrcpackage($release); } $releases = $this->_packageInfo[$releasetype]; if (!is_array($releases)) { return true; } if (!isset($releases[0])) { $releases = array($releases); } foreach ($releases as $rel) { $this->_stupidSchemaValidate(array( '*installconditions', '*configureoption->name->prompt->?default', '*binarypackage', '*filelist', ), $rel, '<' . $releasetype . '>'); if (isset($rel['binarypackage'])) { if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) { $rel['binarypackage'] = array($rel['binarypackage']); } foreach ($rel['binarypackage'] as $bin) { if (!is_string($bin)) { $this->_binaryPackageMustBePackagename(); } } } } } $releasetype = 'extbinrelease'; if (isset($this->_packageInfo[$releasetype])) { $release = $releasetype; if (!isset($this->_packageInfo['providesextension'])) { $this->_mustProvideExtension($release); } if (isset($this->_packageInfo['channel']) && !isset($this->_packageInfo['srcpackage'])) { $this->_mustSrcPackage($release); } if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) { $this->_mustSrcuri($release); } $releases = $this->_packageInfo[$releasetype]; if (!is_array($releases)) { return true; } if (!isset($releases[0])) { $releases = array($releases); } foreach ($releases as $rel) { $this->_stupidSchemaValidate(array( '*installconditions', '*filelist', ), $rel, '<' . $releasetype . '>'); } } } if (isset($this->_packageInfo['bundle'])) { $release = 'bundle'; if (isset($this->_packageInfo['providesextension'])) { $this->_cannotProvideExtension($release); } if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { $this->_cannotHaveSrcpackage($release); } $releases = $this->_packageInfo['bundle']; if (!is_array($releases) || !isset($releases[0])) { $releases = array($releases); } foreach ($releases as $rel) { $this->_stupidSchemaValidate(array( '*installconditions', '*filelist', ), $rel, ''); } } foreach ($releases as $rel) { if (is_array($rel) && array_key_exists('installconditions', $rel)) { $this->_validateInstallConditions($rel['installconditions'], "<$release>"); } if (is_array($rel) && array_key_exists('filelist', $rel)) { if ($rel['filelist']) { $this->_validateFilelist($rel['filelist'], true); } } } } /** * This is here to allow role extension through plugins * @param string */ function _validateRole($role) { return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())); } function _pearVersionTooLow($version) { $this->_stack->push(__FUNCTION__, 'error', array('version' => $version), 'This package.xml requires PEAR version %version% to parse properly, we are ' . 'version 1.10.16'); } function _invalidTagOrder($oktags, $actual, $root) { $this->_stack->push(__FUNCTION__, 'error', array('oktags' => $oktags, 'actual' => $actual, 'root' => $root), 'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"'); } function _ignoreNotAllowed($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '<%type%> is not allowed inside global , only inside ' . '//, use and only'); } function _fileNotAllowed($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '<%type%> is not allowed inside release , only inside ' . ', use and only'); } function _oldStyleFileNotAllowed() { $this->_stack->push(__FUNCTION__, 'error', array(), 'Old-style name is not allowed. Use' . ''); } function _tagMissingAttribute($tag, $attr, $context) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'attribute' => $attr, 'context' => $context), 'tag <%tag%> in context "%context%" has no attribute "%attribute%"'); } function _tagHasNoAttribs($tag, $context) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'context' => $context), 'tag <%tag%> has no attributes in context "%context%"'); } function _invalidInternalStructure() { $this->_stack->push(__FUNCTION__, 'exception', array(), 'internal array was not generated by compatible parser, or extreme parser error, cannot continue'); } function _invalidFileRole($file, $dir, $role) { $this->_stack->push(__FUNCTION__, 'error', array( 'file' => $file, 'dir' => $dir, 'role' => $role, 'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())), 'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%'); } function _invalidFileName($file, $dir) { $this->_stack->push(__FUNCTION__, 'error', array( 'file' => $file), 'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."'); } function _invalidFileInstallAs($file, $as) { $this->_stack->push(__FUNCTION__, 'error', array( 'file' => $file, 'as' => $as), 'File "%file%" cannot contain "./" or contain ".."'); } function _invalidDirName($dir) { $this->_stack->push(__FUNCTION__, 'error', array( 'dir' => $file), 'Directory "%dir%" cannot begin with "./" or contain ".."'); } function _filelistCannotContainFile($filelist) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), '<%tag%> can only contain , contains . Use ' . ' as the first dir element'); } function _filelistMustContainDir($filelist) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), '<%tag%> must contain . Use as the ' . 'first dir element'); } function _tagCannotBeEmpty($tag) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), '<%tag%> cannot be empty (<%tag%/>)'); } function _UrlOrChannel($type, $name) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'name' => $name), 'Required dependency <%type%> "%name%" can have either url OR ' . 'channel attributes, and not both'); } function _NoChannel($type, $name) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'name' => $name), 'Required dependency <%type%> "%name%" must have either url OR ' . 'channel attributes'); } function _UrlOrChannelGroup($type, $name, $group) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'name' => $name, 'group' => $group), 'Group "%group%" dependency <%type%> "%name%" can have either url OR ' . 'channel attributes, and not both'); } function _NoChannelGroup($type, $name, $group) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'name' => $name, 'group' => $group), 'Group "%group%" dependency <%type%> "%name%" must have either url OR ' . 'channel attributes'); } function _unknownChannel($channel) { $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel), 'Unknown channel "%channel%"'); } function _noPackageVersion() { $this->_stack->push(__FUNCTION__, 'error', array(), 'package.xml tag has no version attribute, or version is not 2.0'); } function _NoBundledPackages() { $this->_stack->push(__FUNCTION__, 'error', array(), 'No tag was found in , required for bundle packages'); } function _AtLeast2BundledPackages() { $this->_stack->push(__FUNCTION__, 'error', array(), 'At least 2 packages must be bundled in a bundle package'); } function _ChannelOrUri($name) { $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), 'Bundled package "%name%" can have either a uri or a channel, not both'); } function _noChildTag($child, $tag) { $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag), 'Tag <%tag%> is missing child tag <%child%>'); } function _invalidVersion($type, $value) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value), 'Version type <%type%> is not a valid version (%value%)'); } function _invalidState($type, $value) { $states = array('stable', 'beta', 'alpha', 'devel'); if ($type != 'api') { $states[] = 'snapshot'; } if (strtolower($value) == 'rc') { $this->_stack->push(__FUNCTION__, 'error', array('version' => $this->_packageInfo['version']['release']), 'RC is not a state, it is a version postfix, try %version%RC1, stability beta'); } $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value, 'types' => $states), 'Stability type <%type%> is not a valid stability (%value%), must be one of ' . '%types%'); } function _invalidTask($task, $ret, $file) { switch ($ret[0]) { case PEAR_TASK_ERROR_MISSING_ATTRIB : $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file); $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%'; break; case PEAR_TASK_ERROR_NOATTRIBS : $info = array('task' => $task, 'file' => $file); $msg = 'task <%task%> has no attributes in file %file%'; break; case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE : $info = array('attrib' => $ret[1], 'values' => $ret[3], 'was' => $ret[2], 'task' => $task, 'file' => $file); $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '. 'in file %file%, expecting one of "%values%"'; break; case PEAR_TASK_ERROR_INVALID : $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file); $msg = 'task <%task%> in file %file% is invalid because of "%reason%"'; break; } $this->_stack->push(__FUNCTION__, 'error', $info, $msg); } function _unknownTask($task, $file) { $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file), 'Unknown task "%task%" passed in file '); } function _subpackageCannotProvideExtension($name) { $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), 'Subpackage dependency "%name%" cannot use , ' . 'only package dependencies can use this tag'); } function _subpackagesCannotConflict($name) { $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), 'Subpackage dependency "%name%" cannot use , ' . 'only package dependencies can use this tag'); } function _cannotProvideExtension($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '<%release%> packages cannot use , only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension'); } function _mustProvideExtension($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '<%release%> packages must use to indicate which PHP extension is provided'); } function _cannotHaveSrcpackage($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '<%release%> packages cannot specify a source code package, only extension binaries may use the tag'); } function _mustSrcPackage($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '/ packages must specify a source code package with '); } function _mustSrcuri($release) { $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), '/ packages must specify a source code package with '); } function _uriDepsCannotHaveVersioning($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '%type%: dependencies with a tag cannot have any versioning information'); } function _conflictingDepsCannotHaveVersioning($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '%type%: conflicting dependencies cannot have versioning info, use to ' . 'exclude specific versions of a dependency'); } function _DepchannelCannotBeUri($type) { $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' . 'dependencies only'); } function _bundledPackagesMustBeFilename() { $this->_stack->push(__FUNCTION__, 'error', array(), ' tags must contain only the filename of a package release ' . 'in the bundle'); } function _binaryPackageMustBePackagename() { $this->_stack->push(__FUNCTION__, 'error', array(), ' tags must contain the name of a package that is ' . 'a compiled version of this extsrc/zendextsrc package'); } function _fileNotFound($file) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'File "%file%" in package.xml does not exist'); } function _notInContents($file, $tag) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag), '<%tag% name="%file%"> is invalid, file is not in '); } function _cannotValidateNoPathSet() { $this->_stack->push(__FUNCTION__, 'error', array(), 'Cannot validate files, no path to package file is set (use setPackageFile())'); } function _usesroletaskMustHaveChannelOrUri($role, $tag) { $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), '<%tag%> for role "%role%" must contain either , or and '); } function _usesroletaskMustHavePackage($role, $tag) { $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), '<%tag%> for role "%role%" must contain '); } function _usesroletaskMustHaveRoleTask($tag, $type) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type), '<%tag%> must contain <%type%> defining the %type% to be used'); } function _cannotConflictWithAllOs($type) { $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), '%tag% cannot conflict with all OSes'); } function _invalidDepGroupName($name) { $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), 'Invalid dependency group name "%name%"'); } function _multipleToplevelDirNotAllowed() { $this->_stack->push(__FUNCTION__, 'error', array(), 'Multiple top-level tags are not allowed. Enclose them ' . 'in a '); } function _multipleInstallAs($file) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'Only one tag is allowed for file "%file%"'); } function _ignoreAndInstallAs($file) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'Cannot have both and tags for file "%file%"'); } function _analyzeBundledPackages() { if (!$this->_isValid) { return false; } if (!$this->_pf->getPackageType() == 'bundle') { return false; } if (!isset($this->_pf->_packageFile)) { return false; } $dir_prefix = dirname($this->_pf->_packageFile); $common = new PEAR_Common; $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : array($common, 'log'); $info = $this->_pf->getContents(); $info = $info['bundledpackage']; if (!is_array($info)) { $info = array($info); } $pkg = new PEAR_PackageFile($this->_pf->_config); foreach ($info as $package) { if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) { $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package); $this->_isValid = 0; continue; } call_user_func_array($log, array(1, "Analyzing bundled package $package")); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package, PEAR_VALIDATE_NORMAL); PEAR::popErrorHandling(); if (PEAR::isError($ret)) { call_user_func_array($log, array(0, "ERROR: package $package is not a valid " . 'package')); $inf = $ret->getUserInfo(); if (is_array($inf)) { foreach ($inf as $err) { call_user_func_array($log, array(1, $err['message'])); } } return false; } } return true; } function _analyzePhpFiles() { if (!$this->_isValid) { return false; } if (!isset($this->_pf->_packageFile)) { $this->_cannotValidateNoPathSet(); return false; } $dir_prefix = dirname($this->_pf->_packageFile); $common = new PEAR_Common; $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : array(&$common, 'log'); $info = $this->_pf->getContents(); if (!$info || !isset($info['dir']['file'])) { $this->_tagCannotBeEmpty('contents>_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file); $this->_isValid = 0; continue; } if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) { call_user_func_array($log, array(1, "Analyzing $file")); $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); if ($srcinfo) { $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo)); } } } $this->_packageName = $pn = $this->_pf->getPackage(); $pnl = strlen($pn); foreach ($provides as $key => $what) { if (isset($what['explicit']) || !$what) { // skip conformance checks if the provides entry is // specified in the package.xml file continue; } extract($what); if ($type == 'class') { if (!strncasecmp($name, $pn, $pnl)) { continue; } $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), 'in %file%: %type% "%name%" not prefixed with package name "%package%"'); } elseif ($type == 'function') { if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { continue; } $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), 'in %file%: %type% "%name%" not prefixed with package name "%package%"'); } } return $this->_isValid; } /** * Analyze the source code of the given PHP file * * @param string Filename of the PHP file * @param boolean whether to analyze $file as the file contents * @return mixed */ function analyzeSourceCode($file, $string = false) { if (!function_exists("token_get_all")) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer'); return false; } if (!defined('T_DOC_COMMENT')) { define('T_DOC_COMMENT', T_COMMENT); } if (!defined('T_INTERFACE')) { define('T_INTERFACE', -1); } if (!defined('T_IMPLEMENTS')) { define('T_IMPLEMENTS', -1); } if ($string) { $contents = $file; } else { if (!$fp = @fopen($file, "r")) { return false; } fclose($fp); $contents = file_get_contents($file); } // Silence this function so we can catch PHP Warnings and show our own custom message $tokens = @token_get_all($contents); if (isset($php_errormsg)) { if (isset($this->_stack)) { $pn = $this->_pf->getPackage(); $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file, 'package' => $pn), 'in %file%: Could not process file for unknown reasons,' . ' possibly a PHP parse error in %file% from %package%'); } } /* for ($i = 0; $i < sizeof($tokens); $i++) { @list($token, $data) = $tokens[$i]; if (is_string($token)) { var_dump($token); } else { print token_name($token) . ' '; var_dump(rtrim($data)); } } */ $look_for = 0; $paren_level = 0; $bracket_level = 0; $brace_level = 0; $lastphpdoc = ''; $current_class = ''; $current_interface = ''; $current_class_level = -1; $current_function = ''; $current_function_level = -1; $declared_classes = array(); $declared_interfaces = array(); $declared_functions = array(); $declared_methods = array(); $used_classes = array(); $used_functions = array(); $extends = array(); $implements = array(); $nodeps = array(); $inquote = false; $interface = false; for ($i = 0; $i < sizeof($tokens); $i++) { if (is_array($tokens[$i])) { list($token, $data) = $tokens[$i]; } else { $token = $tokens[$i]; $data = ''; } if ($inquote) { if ($token != '"' && $token != T_END_HEREDOC) { continue; } else { $inquote = false; continue; } } switch ($token) { case T_WHITESPACE : continue 2; case ';': if ($interface) { $current_function = ''; $current_function_level = -1; } break; case '"': case T_START_HEREDOC: $inquote = true; break; case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: case '{': $brace_level++; continue 2; case '}': $brace_level--; if ($current_class_level == $brace_level) { $current_class = ''; $current_class_level = -1; } if ($current_function_level == $brace_level) { $current_function = ''; $current_function_level = -1; } continue 2; case '[': $bracket_level++; continue 2; case ']': $bracket_level--; continue 2; case '(': $paren_level++; continue 2; case ')': $paren_level--; continue 2; case T_INTERFACE: $interface = true; case T_CLASS: if (($current_class_level != -1) || ($current_function_level != -1)) { if (isset($this->_stack)) { $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), 'Parser error: invalid PHP found in file "%file%"'); } else { PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"", PEAR_COMMON_ERROR_INVALIDPHP); } return false; } case T_FUNCTION: case T_NEW: case T_EXTENDS: case T_IMPLEMENTS: $look_for = $token; continue 2; case T_STRING: if ($look_for == T_CLASS) { $current_class = $data; $current_class_level = $brace_level; $declared_classes[] = $current_class; } elseif ($look_for == T_INTERFACE) { $current_interface = $data; $current_class_level = $brace_level; $declared_interfaces[] = $current_interface; } elseif ($look_for == T_IMPLEMENTS) { $implements[$current_class] = $data; } elseif ($look_for == T_EXTENDS) { $extends[$current_class] = $data; } elseif ($look_for == T_FUNCTION) { if ($current_class) { $current_function = "$current_class::$data"; $declared_methods[$current_class][] = $data; } elseif ($current_interface) { $current_function = "$current_interface::$data"; $declared_methods[$current_interface][] = $data; } else { $current_function = $data; $declared_functions[] = $current_function; } $current_function_level = $brace_level; $m = array(); } elseif ($look_for == T_NEW) { $used_classes[$data] = true; } $look_for = 0; continue 2; case T_VARIABLE: $look_for = 0; continue 2; case T_DOC_COMMENT: case T_COMMENT: if (preg_match('!^/\*\*\s!', $data)) { $lastphpdoc = $data; if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { $nodeps = array_merge($nodeps, $m[1]); } } continue 2; case T_DOUBLE_COLON: $token = $tokens[$i - 1][0]; if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC || $token == T_VARIABLE)) { if (isset($this->_stack)) { $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file), 'Parser error: invalid PHP found in file "%file%"'); } else { PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"", PEAR_COMMON_ERROR_INVALIDPHP); } return false; } $class = $tokens[$i - 1][1]; if (strtolower($class) != 'parent') { $used_classes[$class] = true; } continue 2; } } return array( "source_file" => $file, "declared_classes" => $declared_classes, "declared_interfaces" => $declared_interfaces, "declared_methods" => $declared_methods, "declared_functions" => $declared_functions, "used_classes" => array_diff(array_keys($used_classes), $nodeps), "inheritance" => $extends, "implements" => $implements, ); } /** * Build a "provides" array from data returned by * analyzeSourceCode(). The format of the built array is like * this: * * array( * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), * ... * ) * * * @param array $srcinfo array with information about a source file * as returned by the analyzeSourceCode() method. * * @return void * * @access private * */ function _buildProvidesArray($srcinfo) { if (!$this->_isValid) { return array(); } $providesret = array(); $file = basename($srcinfo['source_file']); $pn = isset($this->_pf) ? $this->_pf->getPackage() : ''; $pnl = strlen($pn); foreach ($srcinfo['declared_classes'] as $class) { $key = "class;$class"; if (isset($providesret[$key])) { continue; } $providesret[$key] = array('file'=> $file, 'type' => 'class', 'name' => $class); if (isset($srcinfo['inheritance'][$class])) { $providesret[$key]['extends'] = $srcinfo['inheritance'][$class]; } } foreach ($srcinfo['declared_methods'] as $class => $methods) { foreach ($methods as $method) { $function = "$class::$method"; $key = "function;$function"; if ($method[0] == '_' || !strcasecmp($method, $class) || isset($providesret[$key])) { continue; } $providesret[$key] = array('file'=> $file, 'type' => 'function', 'name' => $function); } } foreach ($srcinfo['declared_functions'] as $function) { $key = "function;$function"; if ($function[0] == '_' || isset($providesret[$key])) { continue; } if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; } $providesret[$key] = array('file'=> $file, 'type' => 'function', 'name' => $function); } return $providesret; } } PK!=__PEAR/PackageFile/v2/rw.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a8 */ /** * For base class */ require_once 'PEAR/PackageFile/v2.php'; /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a8 */ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2 { /** * @param string Extension name * @return bool success of operation */ function setProvidesExtension($extension) { if (in_array($this->getPackageType(), array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { if (!isset($this->_packageInfo['providesextension'])) { // ensure that the channel tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $extension, 'providesextension'); } $this->_packageInfo['providesextension'] = $extension; return true; } return false; } function setPackage($package) { $this->_isValid = 0; if (!isset($this->_packageInfo['attribs'])) { $this->_packageInfo = array_merge(array('attribs' => array( 'version' => '2.0', 'xmlns' => 'http://pear.php.net/dtd/package-2.0', 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd', )), $this->_packageInfo); } if (!isset($this->_packageInfo['name'])) { return $this->_packageInfo = array_merge(array('name' => $package), $this->_packageInfo); } $this->_packageInfo['name'] = $package; } /** * set this as a package.xml version 2.1 * @access private */ function _setPackageVersion2_1() { $info = array( 'version' => '2.1', 'xmlns' => 'http://pear.php.net/dtd/package-2.1', 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.1 http://pear.php.net/dtd/package-2.1.xsd', ); if (!isset($this->_packageInfo['attribs'])) { $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo); } else { $this->_packageInfo['attribs'] = $info; } } function setUri($uri) { unset($this->_packageInfo['channel']); $this->_isValid = 0; if (!isset($this->_packageInfo['uri'])) { // ensure that the uri tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('extends', 'summary', 'description', 'lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $uri, 'uri'); } $this->_packageInfo['uri'] = $uri; } function setChannel($channel) { unset($this->_packageInfo['uri']); $this->_isValid = 0; if (!isset($this->_packageInfo['channel'])) { // ensure that the channel tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('extends', 'summary', 'description', 'lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $channel, 'channel'); } $this->_packageInfo['channel'] = $channel; } function setExtends($extends) { $this->_isValid = 0; if (!isset($this->_packageInfo['extends'])) { // ensure that the extends tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('summary', 'description', 'lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $extends, 'extends'); } $this->_packageInfo['extends'] = $extends; } function setSummary($summary) { $this->_isValid = 0; if (!isset($this->_packageInfo['summary'])) { // ensure that the summary tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('description', 'lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $summary, 'summary'); } $this->_packageInfo['summary'] = $summary; } function setDescription($desc) { $this->_isValid = 0; if (!isset($this->_packageInfo['description'])) { // ensure that the description tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $desc, 'description'); } $this->_packageInfo['description'] = $desc; } /** * Adds a new maintainer - no checking of duplicates is performed, use * updatemaintainer for that purpose. */ function addMaintainer($role, $handle, $name, $email, $active = 'yes') { if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) { return false; } if (isset($this->_packageInfo[$role])) { if (!isset($this->_packageInfo[$role][0])) { $this->_packageInfo[$role] = array($this->_packageInfo[$role]); } $this->_packageInfo[$role][] = array( 'name' => $name, 'user' => $handle, 'email' => $email, 'active' => $active, ); } else { $testarr = array('lead', 'developer', 'contributor', 'helper', 'date', 'time', 'version', 'stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'); foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) { array_shift($testarr); if ($role == $testrole) { break; } } if (!isset($this->_packageInfo[$role])) { // ensure that the extends tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr, array(), $role); } $this->_packageInfo[$role] = array( 'name' => $name, 'user' => $handle, 'email' => $email, 'active' => $active, ); } $this->_isValid = 0; } function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes') { $found = false; foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { if (!isset($this->_packageInfo[$role])) { continue; } $info = $this->_packageInfo[$role]; if (!isset($info[0])) { if ($info['user'] == $handle) { $found = true; break; } } foreach ($info as $i => $maintainer) { if (is_array($maintainer) && $maintainer['user'] == $handle) { $found = $i; break 2; } } } if ($found === false) { return $this->addMaintainer($newrole, $handle, $name, $email, $active); } if ($found !== false) { if ($found === true) { unset($this->_packageInfo[$role]); } else { unset($this->_packageInfo[$role][$found]); $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]); } } $this->addMaintainer($newrole, $handle, $name, $email, $active); $this->_isValid = 0; } function deleteMaintainer($handle) { $found = false; foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { if (!isset($this->_packageInfo[$role])) { continue; } if (!isset($this->_packageInfo[$role][0])) { $this->_packageInfo[$role] = array($this->_packageInfo[$role]); } foreach ($this->_packageInfo[$role] as $i => $maintainer) { if ($maintainer['user'] == $handle) { $found = $i; break; } } if ($found !== false) { unset($this->_packageInfo[$role][$found]); if (!count($this->_packageInfo[$role]) && $role == 'lead') { $this->_isValid = 0; } if (!count($this->_packageInfo[$role])) { unset($this->_packageInfo[$role]); return true; } $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]); if (count($this->_packageInfo[$role]) == 1) { $this->_packageInfo[$role] = $this->_packageInfo[$role][0]; } return true; } if (count($this->_packageInfo[$role]) == 1) { $this->_packageInfo[$role] = $this->_packageInfo[$role][0]; } } return false; } function setReleaseVersion($version) { if (isset($this->_packageInfo['version']) && isset($this->_packageInfo['version']['release'])) { unset($this->_packageInfo['version']['release']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( 'version' => array('stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 'release' => array('api'))); $this->_isValid = 0; } function setAPIVersion($version) { if (isset($this->_packageInfo['version']) && isset($this->_packageInfo['version']['api'])) { unset($this->_packageInfo['version']['api']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( 'version' => array('stability', 'license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 'api' => array())); $this->_isValid = 0; } /** * snapshot|devel|alpha|beta|stable */ function setReleaseStability($state) { if (isset($this->_packageInfo['stability']) && isset($this->_packageInfo['stability']['release'])) { unset($this->_packageInfo['stability']['release']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( 'stability' => array('license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 'release' => array('api'))); $this->_isValid = 0; } /** * @param devel|alpha|beta|stable */ function setAPIStability($state) { if (isset($this->_packageInfo['stability']) && isset($this->_packageInfo['stability']['api'])) { unset($this->_packageInfo['stability']['api']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( 'stability' => array('license', 'notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 'api' => array())); $this->_isValid = 0; } function setLicense($license, $uri = false, $filesource = false) { if (!isset($this->_packageInfo['license'])) { // ensure that the license tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('notes', 'contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), 0, 'license'); } if ($uri || $filesource) { $attribs = array(); if ($uri) { $attribs['uri'] = $uri; } $uri = true; // for test below if ($filesource) { $attribs['filesource'] = $filesource; } } $license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license; $this->_packageInfo['license'] = $license; $this->_isValid = 0; } function setNotes($notes) { $this->_isValid = 0; if (!isset($this->_packageInfo['notes'])) { // ensure that the notes tag is set up in the right location $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('contents', 'compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'extbinrelease', 'bundle', 'changelog'), $notes, 'notes'); } $this->_packageInfo['notes'] = $notes; } /** * This is only used at install-time, after all serialization * is over. * @param string file name * @param string installed path */ function setInstalledAs($file, $path) { if ($path) { return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; } unset($this->_packageInfo['filelist'][$file]['installed_as']); } /** * This is only used at install-time, after all serialization * is over. */ function installedFile($file, $atts) { if (isset($this->_packageInfo['filelist'][$file])) { $this->_packageInfo['filelist'][$file] = array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']); } else { $this->_packageInfo['filelist'][$file] = $atts['attribs']; } } /** * Reset the listing of package contents * @param string base installation dir for the whole package, if any */ function clearContents($baseinstall = false) { $this->_filesValid = false; $this->_isValid = 0; if (!isset($this->_packageInfo['contents'])) { $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), array(), 'contents'); } if ($this->getPackageType() != 'bundle') { $this->_packageInfo['contents'] = array('dir' => array('attribs' => array('name' => '/'))); if ($baseinstall) { $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall; } } else { $this->_packageInfo['contents'] = array('bundledpackage' => array()); } } /** * @param string relative path of the bundled package. */ function addBundledPackage($path) { if ($this->getPackageType() != 'bundle') { return false; } $this->_filesValid = false; $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array( 'contents' => array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'bundledpackage' => array())); } /** * @param string file name * @param PEAR_Task_Common a read/write task */ function addTaskToFile($filename, $task) { if (!method_exists($task, 'getXml')) { return false; } if (!method_exists($task, 'getName')) { return false; } if (!method_exists($task, 'validate')) { return false; } if (!$task->validate()) { return false; } if (!isset($this->_packageInfo['contents']['dir']['file'])) { return false; } $this->getTasksNs(); // discover the tasks namespace if not done already $files = $this->_packageInfo['contents']['dir']['file']; if (!isset($files[0])) { $files = array($files); $ind = false; } else { $ind = true; } foreach ($files as $i => $file) { if (isset($file['attribs'])) { if ($file['attribs']['name'] == $filename) { if ($ind) { $t = isset($this->_packageInfo['contents']['dir']['file'][$i] ['attribs'][$this->_tasksNs . ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file'][$i] ['attribs'][$this->_tasksNs . ':' . $task->getName()] : false; if ($t && !isset($t[0])) { $this->_packageInfo['contents']['dir']['file'][$i] [$this->_tasksNs . ':' . $task->getName()] = array($t); } $this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs . ':' . $task->getName()][] = $task->getXml(); } else { $t = isset($this->_packageInfo['contents']['dir']['file'] ['attribs'][$this->_tasksNs . ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file'] ['attribs'][$this->_tasksNs . ':' . $task->getName()] : false; if ($t && !isset($t[0])) { $this->_packageInfo['contents']['dir']['file'] [$this->_tasksNs . ':' . $task->getName()] = array($t); } $this->_packageInfo['contents']['dir']['file'][$this->_tasksNs . ':' . $task->getName()][] = $task->getXml(); } return true; } } } return false; } /** * @param string path to the file * @param string filename * @param array extra attributes */ function addFile($dir, $file, $attrs) { if ($this->getPackageType() == 'bundle') { return false; } $this->_filesValid = false; $this->_isValid = 0; $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir); if ($dir == '/' || $dir == '') { $dir = ''; } else { $dir .= '/'; } $attrs['name'] = $dir . $file; if (!isset($this->_packageInfo['contents'])) { // ensure that the contents tag is set up $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), array(), 'contents'); } if (isset($this->_packageInfo['contents']['dir']['file'])) { if (!isset($this->_packageInfo['contents']['dir']['file'][0])) { $this->_packageInfo['contents']['dir']['file'] = array($this->_packageInfo['contents']['dir']['file']); } $this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs; } else { $this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs; } } /** * @param string Dependent package name * @param string Dependent package's channel name * @param string minimum version of specified package that this release is guaranteed to be * compatible with * @param string maximum version of specified package that this release is guaranteed to be * compatible with * @param string versions of specified package that this release is not compatible with */ function addCompatiblePackage($name, $channel, $min, $max, $exclude = false) { $this->_isValid = 0; $set = array( 'name' => $name, 'channel' => $channel, 'min' => $min, 'max' => $max, ); if ($exclude) { $set['exclude'] = $exclude; } $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( 'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') )); } /** * Removes the tag entirely */ function resetUsesrole() { if (isset($this->_packageInfo['usesrole'])) { unset($this->_packageInfo['usesrole']); } } /** * @param string * @param string package name or uri * @param string channel name if non-uri */ function addUsesrole($role, $packageOrUri, $channel = false) { $set = array('role' => $role); if ($channel) { $set['package'] = $packageOrUri; $set['channel'] = $channel; } else { $set['uri'] = $packageOrUri; } $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( 'usesrole' => array('usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') )); } /** * Removes the tag entirely */ function resetUsestask() { if (isset($this->_packageInfo['usestask'])) { unset($this->_packageInfo['usestask']); } } /** * @param string * @param string package name or uri * @param string channel name if non-uri */ function addUsestask($task, $packageOrUri, $channel = false) { $set = array('task' => $task); if ($channel) { $set['package'] = $packageOrUri; $set['channel'] = $channel; } else { $set['uri'] = $packageOrUri; } $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( 'usestask' => array('srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') )); } /** * Remove all compatible tags */ function clearCompatible() { unset($this->_packageInfo['compatible']); } /** * Reset dependencies prior to adding new ones */ function clearDeps() { if (!isset($this->_packageInfo['dependencies'])) { $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'))); } $this->_packageInfo['dependencies'] = array(); } /** * @param string minimum PHP version allowed * @param string maximum PHP version allowed * @param array $exclude incompatible PHP versions */ function setPhpDep($min, $max = false, $exclude = false) { $this->_isValid = 0; $dep = array( 'min' => $min, ); if ($max) { $dep['max'] = $max; } if ($exclude) { if (count($exclude) == 1) { $exclude = $exclude[0]; } $dep['exclude'] = $exclude; } if (isset($this->_packageInfo['dependencies']['required']['php'])) { $this->_stack->push(__FUNCTION__, 'warning', array('dep' => $this->_packageInfo['dependencies']['required']['php']), 'warning: PHP dependency already exists, overwriting'); unset($this->_packageInfo['dependencies']['required']['php']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch') )); return true; } /** * @param string minimum allowed PEAR installer version * @param string maximum allowed PEAR installer version * @param string recommended PEAR installer version * @param array incompatible version of the PEAR installer */ function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false) { $this->_isValid = 0; $dep = array( 'min' => $min, ); if ($max) { $dep['max'] = $max; } if ($recommended) { $dep['recommended'] = $recommended; } if ($exclude) { if (count($exclude) == 1) { $exclude = $exclude[0]; } $dep['exclude'] = $exclude; } if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) { $this->_stack->push(__FUNCTION__, 'warning', array('dep' => $this->_packageInfo['dependencies']['required']['pearinstaller']), 'warning: PEAR Installer dependency already exists, overwriting'); unset($this->_packageInfo['dependencies']['required']['pearinstaller']); } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch') )); } /** * Mark a package as conflicting with this package * @param string package name * @param string package channel * @param string extension this package provides, if any * @param string|false minimum version required * @param string|false maximum version allowed * @param array|false versions to exclude from installation */ function addConflictingPackageDepWithChannel($name, $channel, $providesextension = false, $min = false, $max = false, $exclude = false) { $this->_isValid = 0; $dep = $this->_constructDep($name, $channel, false, $min, $max, false, $exclude, $providesextension, false, true); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'package' => array('subpackage', 'extension', 'os', 'arch') )); } /** * Mark a package as conflicting with this package * @param string package name * @param string package channel * @param string extension this package provides, if any */ function addConflictingPackageDepWithUri($name, $uri, $providesextension = false) { $this->_isValid = 0; $dep = array( 'name' => $name, 'uri' => $uri, 'conflicts' => '', ); if ($providesextension) { $dep['providesextension'] = $providesextension; } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'package' => array('subpackage', 'extension', 'os', 'arch') )); } function addDependencyGroup($name, $hint) { $this->_isValid = 0; $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array('attribs' => array('name' => $name, 'hint' => $hint)), array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'group' => array(), )); } /** * @param string package name * @param string|false channel name, false if this is a uri * @param string|false uri name, false if this is a channel * @param string|false minimum version required * @param string|false maximum version allowed * @param string|false recommended installation version * @param array|false versions to exclude from installation * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package * @param bool if true, tells the installer to negate this dependency (conflicts) * @return array * @access private */ function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude, $providesextension = false, $nodefault = false, $conflicts = false) { $dep = array( 'name' => $name, ); if ($channel) { $dep['channel'] = $channel; } elseif ($uri) { $dep['uri'] = $uri; } if ($min) { $dep['min'] = $min; } if ($max) { $dep['max'] = $max; } if ($recommended) { $dep['recommended'] = $recommended; } if ($exclude) { if (is_array($exclude) && count($exclude) == 1) { $exclude = $exclude[0]; } $dep['exclude'] = $exclude; } if ($conflicts) { $dep['conflicts'] = ''; } if ($nodefault) { $dep['nodefault'] = ''; } if ($providesextension) { $dep['providesextension'] = $providesextension; } return $dep; } /** * @param package|subpackage * @param string group name * @param string package name * @param string package channel * @param string minimum version * @param string maximum version * @param string recommended version * @param array|false optional excluded versions * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package * @return bool false if the dependency group has not been initialized with * {@link addDependencyGroup()}, or a subpackage is added with * a providesextension */ function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false, $max = false, $recommended = false, $exclude = false, $providesextension = false, $nodefault = false) { if ($type == 'subpackage' && $providesextension) { return false; // subpackages must be php packages } $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, $providesextension, $nodefault); return $this->_addGroupDependency($type, $dep, $groupname); } /** * @param package|subpackage * @param string group name * @param string package name * @param string package uri * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package * @return bool false if the dependency group has not been initialized with * {@link addDependencyGroup()} */ function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false, $nodefault = false) { if ($type == 'subpackage' && $providesextension) { return false; // subpackages must be php packages } $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $providesextension, $nodefault); return $this->_addGroupDependency($type, $dep, $groupname); } /** * @param string group name (must be pre-existing) * @param string extension name * @param string minimum version allowed * @param string maximum version allowed * @param string recommended version * @param array incompatible versions */ function addGroupExtensionDep($groupname, $name, $min = false, $max = false, $recommended = false, $exclude = false) { $this->_isValid = 0; $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); return $this->_addGroupDependency('extension', $dep, $groupname); } /** * @param package|subpackage|extension * @param array dependency contents * @param string name of the dependency group to add this to * @return boolean * @access private */ function _addGroupDependency($type, $dep, $groupname) { $arr = array('subpackage', 'extension'); if ($type != 'package') { array_shift($arr); } if ($type == 'extension') { array_shift($arr); } if (!isset($this->_packageInfo['dependencies']['group'])) { return false; } else { if (!isset($this->_packageInfo['dependencies']['group'][0])) { if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) { $this->_packageInfo['dependencies']['group'] = $this->_mergeTag( $this->_packageInfo['dependencies']['group'], $dep, array( $type => $arr )); $this->_isValid = 0; return true; } else { return false; } } else { foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) { if ($group['attribs']['name'] == $groupname) { $this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag( $this->_packageInfo['dependencies']['group'][$i], $dep, array( $type => $arr )); $this->_isValid = 0; return true; } } return false; } } } /** * @param optional|required * @param string package name * @param string package channel * @param string minimum version * @param string maximum version * @param string recommended version * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package * @param array|false optional excluded versions */ function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false, $recommended = false, $exclude = false, $providesextension = false, $nodefault = false) { if (!in_array($type, array('optional', 'required'), true)) { $type = 'required'; } $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, $providesextension, $nodefault); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'package' => array('subpackage', 'extension', 'os', 'arch') )); } /** * @param optional|required * @param string name of the package * @param string uri of the package * @param string extension this package provides, if any * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package */ function addPackageDepWithUri($type, $name, $uri, $providesextension = false, $nodefault = false) { $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $providesextension, $nodefault); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'package' => array('subpackage', 'extension', 'os', 'arch') )); } /** * @param optional|required optional, required * @param string package name * @param string package channel * @param string minimum version * @param string maximum version * @param string recommended version * @param array incompatible versions * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package */ function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false, $recommended = false, $exclude = false, $nodefault = false) { $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, $nodefault); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'subpackage' => array('extension', 'os', 'arch') )); } /** * @param optional|required optional, required * @param string package name * @param string package uri for download * @param bool if true, tells the installer to ignore the default optional dependency group * when installing this package */ function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false) { $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'subpackage' => array('extension', 'os', 'arch') )); } /** * @param optional|required optional, required * @param string extension name * @param string minimum version * @param string maximum version * @param string recommended version * @param array incompatible versions */ function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false, $exclude = false) { $this->_isValid = 0; $arr = array('optional', 'group'); if ($type != 'required') { array_shift($arr); } $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $type => $arr, 'extension' => array('os', 'arch') )); } /** * @param string Operating system name * @param boolean true if this package cannot be installed on this OS */ function addOsDep($name, $conflicts = false) { $this->_isValid = 0; $dep = array('name' => $name); if ($conflicts) { $dep['conflicts'] = ''; } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'os' => array('arch') )); } /** * @param string Architecture matching pattern * @param boolean true if this package cannot be installed on this architecture */ function addArchDep($pattern, $conflicts = false) { $this->_isValid = 0; $dep = array('pattern' => $pattern); if ($conflicts) { $dep['conflicts'] = ''; } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, array( 'dependencies' => array('providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), 'required' => array('optional', 'group'), 'arch' => array() )); } /** * Set the kind of package, and erase all release tags * * - a php package is a PEAR-style package * - an extbin package is a PECL-style extension binary * - an extsrc package is a PECL-style source for a binary * - an zendextbin package is a PECL-style zend extension binary * - an zendextsrc package is a PECL-style source for a zend extension binary * - a bundle package is a collection of other pre-packaged packages * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle * @return bool success */ function setPackageType($type) { $this->_isValid = 0; if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc', 'zendextbin', 'bundle'))) { return false; } if (in_array($type, array('zendextsrc', 'zendextbin'))) { $this->_setPackageVersion2_1(); } if ($type != 'bundle') { $type .= 'release'; } foreach (array('phprelease', 'extbinrelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) { unset($this->_packageInfo[$test]); } if (!isset($this->_packageInfo[$type])) { // ensure that the release tag is set up $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'), array(), $type); } $this->_packageInfo[$type] = array(); return true; } /** * @return bool true if package type is set up */ function addRelease() { if ($type = $this->getPackageType()) { if ($type != 'bundle') { $type .= 'release'; } $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), array($type => array('changelog'))); return true; } return false; } /** * Get the current release tag in order to add to it * @param bool returns only releases that have installcondition if true * @return array|null */ function &_getCurrentRelease($strict = true) { if ($p = $this->getPackageType()) { if ($strict) { if ($p == 'extsrc' || $p == 'zendextsrc') { $a = null; return $a; } } if ($p != 'bundle') { $p .= 'release'; } if (isset($this->_packageInfo[$p][0])) { return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1]; } else { return $this->_packageInfo[$p]; } } else { $a = null; return $a; } } /** * Add a file to the current release that should be installed under a different name * @param string path to file * @param string name the file should be installed as */ function addInstallAs($path, $as) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; $r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)), array( 'filelist' => array(), 'install' => array('ignore') )); } /** * Add a file to the current release that should be ignored * @param string path to file * @return bool success of operation */ function addIgnore($path) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; $r = $this->_mergeTag($r, array('attribs' => array('name' => $path)), array( 'filelist' => array(), 'ignore' => array() )); } /** * Add an extension binary package for this extension source code release * * Note that the package must be from the same channel as the extension source package * @param string */ function addBinarypackage($package) { if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { return false; } $r = &$this->_getCurrentRelease(false); if ($r === null) { return false; } $this->_isValid = 0; $r = $this->_mergeTag($r, $package, array( 'binarypackage' => array('filelist'), )); } /** * Add a configureoption to an extension source package * @param string * @param string * @param string */ function addConfigureOption($name, $prompt, $default = null) { if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { return false; } $r = &$this->_getCurrentRelease(false); if ($r === null) { return false; } $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt)); if ($default !== null) { $opt['attribs']['default'] = $default; } $this->_isValid = 0; $r = $this->_mergeTag($r, $opt, array( 'configureoption' => array('binarypackage', 'filelist'), )); } /** * Set an installation condition based on php version for the current release set * @param string minimum version * @param string maximum version * @param false|array incompatible versions of PHP */ function setPhpInstallCondition($min, $max, $exclude = false) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; if (isset($r['installconditions']['php'])) { unset($r['installconditions']['php']); } $dep = array('min' => $min, 'max' => $max); if ($exclude) { if (is_array($exclude) && count($exclude) == 1) { $exclude = $exclude[0]; } $dep['exclude'] = $exclude; } if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('configureoption', 'binarypackage', 'filelist'), 'php' => array('extension', 'os', 'arch') )); } else { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('filelist'), 'php' => array('extension', 'os', 'arch') )); } } /** * @param optional|required optional, required * @param string extension name * @param string minimum version * @param string maximum version * @param string recommended version * @param array incompatible versions */ function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false, $exclude = false) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('configureoption', 'binarypackage', 'filelist'), 'extension' => array('os', 'arch') )); } else { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('filelist'), 'extension' => array('os', 'arch') )); } } /** * Set an installation condition based on operating system for the current release set * @param string OS name * @param bool whether this OS is incompatible with the current release */ function setOsInstallCondition($name, $conflicts = false) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; if (isset($r['installconditions']['os'])) { unset($r['installconditions']['os']); } $dep = array('name' => $name); if ($conflicts) { $dep['conflicts'] = ''; } if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('configureoption', 'binarypackage', 'filelist'), 'os' => array('arch') )); } else { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('filelist'), 'os' => array('arch') )); } } /** * Set an installation condition based on architecture for the current release set * @param string architecture pattern * @param bool whether this arch is incompatible with the current release */ function setArchInstallCondition($pattern, $conflicts = false) { $r = &$this->_getCurrentRelease(); if ($r === null) { return false; } $this->_isValid = 0; if (isset($r['installconditions']['arch'])) { unset($r['installconditions']['arch']); } $dep = array('pattern' => $pattern); if ($conflicts) { $dep['conflicts'] = ''; } if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('configureoption', 'binarypackage', 'filelist'), 'arch' => array() )); } else { $r = $this->_mergeTag($r, $dep, array( 'installconditions' => array('filelist'), 'arch' => array() )); } } /** * For extension binary releases, this is used to specify either the * static URI to a source package, or the package name and channel of the extsrc/zendextsrc * package it is based on. * @param string Package name, or full URI to source package (extsrc/zendextsrc type) */ function setSourcePackage($packageOrUri) { $this->_isValid = 0; if (isset($this->_packageInfo['channel'])) { $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $packageOrUri, 'srcpackage'); } else { $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), $packageOrUri, 'srcuri'); } } /** * Generate a valid change log entry from the current package.xml * @param string|false */ function generateChangeLogEntry($notes = false) { return array( 'version' => array( 'release' => $this->getVersion('release'), 'api' => $this->getVersion('api'), ), 'stability' => $this->getStability(), 'date' => $this->getDate(), 'license' => $this->getLicense(true), 'notes' => $notes ? $notes : $this->getNotes() ); } /** * @param string release version to set change log notes for * @param array output of {@link generateChangeLogEntry()} */ function setChangelogEntry($releaseversion, $contents) { if (!isset($this->_packageInfo['changelog'])) { $this->_packageInfo['changelog']['release'] = $contents; return; } if (!isset($this->_packageInfo['changelog']['release'][0])) { if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) { $this->_packageInfo['changelog']['release'] = array( $this->_packageInfo['changelog']['release']); } else { $this->_packageInfo['changelog']['release'] = array( $this->_packageInfo['changelog']['release']); return $this->_packageInfo['changelog']['release'][] = $contents; } } foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) { if (isset($changelog['version']) && strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) { $curlog = $index; } } if (isset($curlog)) { $this->_packageInfo['changelog']['release'][$curlog] = $contents; } else { $this->_packageInfo['changelog']['release'][] = $contents; } } /** * Remove the changelog entirely */ function clearChangeLog() { unset($this->_packageInfo['changelog']); } }PK!5PEAR/PackageFile/v1.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * For error handling */ require_once 'PEAR/ErrorStack.php'; /** * Error code if parsing is attempted with no xml extension */ define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3); /** * Error code if creating the xml parser resource fails */ define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4); /** * Error code used for all sax xml parsing errors */ define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5); /** * Error code used when there is no name */ define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6); /** * Error code when a package name is not valid */ define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7); /** * Error code used when no summary is parsed */ define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8); /** * Error code for summaries that are more than 1 line */ define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9); /** * Error code used when no description is present */ define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10); /** * Error code used when no license is present */ define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11); /** * Error code used when a version number is not present */ define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12); /** * Error code used when a version number is invalid */ define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13); /** * Error code when release state is missing */ define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14); /** * Error code when release state is invalid */ define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15); /** * Error code when release state is missing */ define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16); /** * Error code when release state is invalid */ define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17); /** * Error code when no release notes are found */ define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18); /** * Error code when no maintainers are found */ define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19); /** * Error code when a maintainer has no handle */ define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20); /** * Error code when a maintainer has no handle */ define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21); /** * Error code when a maintainer has no name */ define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22); /** * Error code when a maintainer has no email */ define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23); /** * Error code when a maintainer has no handle */ define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24); /** * Error code when a dependency is not a PHP dependency, but has no name */ define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25); /** * Error code when a dependency has no type (pkg, php, etc.) */ define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26); /** * Error code when a dependency has no relation (lt, ge, has, etc.) */ define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27); /** * Error code when a dependency is not a 'has' relation, but has no version */ define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28); /** * Error code when a dependency has an invalid relation */ define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29); /** * Error code when a dependency has an invalid type */ define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30); /** * Error code when a dependency has an invalid optional option */ define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31); /** * Error code when a dependency is a pkg dependency, and has an invalid package name */ define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32); /** * Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel */ define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33); /** * Error code when rel="has" and version attribute is present. */ define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34); /** * Error code when type="php" and dependency name is present */ define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35); /** * Error code when a configure option has no name */ define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36); /** * Error code when a configure option has no name */ define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37); /** * Error code when a file in the filelist has an invalid role */ define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38); /** * Error code when a file in the filelist has no role */ define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39); /** * Error code when analyzing a php source file that has parse errors */ define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40); /** * Error code when analyzing a php source file reveals a source element * without a package name prefix */ define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41); /** * Error code when an unknown channel is specified */ define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42); /** * Error code when no files are found in the filelist */ define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43); /** * Error code when a file is not valid php according to _analyzeSourceCode() */ define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44); /** * Error code when the channel validator returns an error or warning */ define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45); /** * Error code when a php5 package is packaged in php4 (analysis doesn't work) */ define('PEAR_PACKAGEFILE_ERROR_PHP5', 46); /** * Error code when a file is listed in package.xml but does not exist */ define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47); /** * Error code when a * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_PackageFile_v1 { /** * @access private * @var PEAR_ErrorStack * @access private */ var $_stack; /** * A registry object, used to access the package name validation regex for non-standard channels * @var PEAR_Registry * @access private */ var $_registry; /** * An object that contains a log method that matches PEAR_Common::log's signature * @var object * @access private */ var $_logger; /** * Parsed package information * @var array * @access private */ var $_packageInfo; /** * path to package.xml * @var string * @access private */ var $_packageFile; /** * path to package .tgz or false if this is a local/extracted package.xml * @var string * @access private */ var $_archiveFile; /** * @var int * @access private */ var $_isValid = 0; /** * Determines whether this packagefile was initialized only with partial package info * * If this package file was constructed via parsing REST, it will only contain * * - package name * - channel name * - dependencies * @var boolean * @access private */ var $_incomplete = true; /** * @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack * @param string Name of Error Stack class to use. */ function __construct() { $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v1'); $this->_stack->setErrorMessageTemplate($this->_getErrorMessage()); $this->_isValid = 0; } function installBinary($installer) { return false; } function isExtension($name) { return false; } function setConfig(&$config) { $this->_config = &$config; $this->_registry = &$config->getRegistry(); } function setRequestedGroup() { // placeholder } /** * For saving in the registry. * * Set the last version that was installed * @param string */ function setLastInstalledVersion($version) { $this->_packageInfo['_lastversion'] = $version; } /** * @return string|false */ function getLastInstalledVersion() { if (isset($this->_packageInfo['_lastversion'])) { return $this->_packageInfo['_lastversion']; } return false; } function getInstalledBinary() { return false; } function listPostinstallScripts() { return false; } function initPostinstallScripts() { return false; } function setLogger(&$logger) { if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) { return PEAR::raiseError('Logger must be compatible with PEAR_Common::log'); } $this->_logger = &$logger; } function setPackagefile($file, $archive = false) { $this->_packageFile = $file; $this->_archiveFile = $archive ? $archive : $file; } function getPackageFile() { return isset($this->_packageFile) ? $this->_packageFile : false; } function getPackageType() { return 'php'; } function getArchiveFile() { return $this->_archiveFile; } function packageInfo($field) { if (!is_string($field) || empty($field) || !isset($this->_packageInfo[$field])) { return false; } return $this->_packageInfo[$field]; } function setDirtree($path) { if (!isset($this->_packageInfo['dirtree'])) { $this->_packageInfo['dirtree'] = array(); } $this->_packageInfo['dirtree'][$path] = true; } function getDirtree() { if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) { return $this->_packageInfo['dirtree']; } return false; } function resetDirtree() { unset($this->_packageInfo['dirtree']); } function fromArray($pinfo) { $this->_incomplete = false; $this->_packageInfo = $pinfo; } function isIncomplete() { return $this->_incomplete; } function getChannel() { return 'pear.php.net'; } function getUri() { return false; } function getTime() { return false; } function getExtends() { if (isset($this->_packageInfo['extends'])) { return $this->_packageInfo['extends']; } return false; } /** * @return array */ function toArray() { if (!$this->validate(PEAR_VALIDATE_NORMAL)) { return false; } return $this->getArray(); } function getArray() { return $this->_packageInfo; } function getName() { return $this->getPackage(); } function getPackage() { if (isset($this->_packageInfo['package'])) { return $this->_packageInfo['package']; } return false; } /** * WARNING - don't use this unless you know what you are doing */ function setRawPackage($package) { $this->_packageInfo['package'] = $package; } function setPackage($package) { $this->_packageInfo['package'] = $package; $this->_isValid = false; } function getVersion() { if (isset($this->_packageInfo['version'])) { return $this->_packageInfo['version']; } return false; } function setVersion($version) { $this->_packageInfo['version'] = $version; $this->_isValid = false; } function clearMaintainers() { unset($this->_packageInfo['maintainers']); } function getMaintainers() { if (isset($this->_packageInfo['maintainers'])) { return $this->_packageInfo['maintainers']; } return false; } /** * Adds a new maintainer - no checking of duplicates is performed, use * updatemaintainer for that purpose. */ function addMaintainer($role, $handle, $name, $email) { $this->_packageInfo['maintainers'][] = array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name); $this->_isValid = false; } function updateMaintainer($role, $handle, $name, $email) { $found = false; if (!isset($this->_packageInfo['maintainers']) || !is_array($this->_packageInfo['maintainers'])) { return $this->addMaintainer($role, $handle, $name, $email); } foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) { if ($maintainer['handle'] == $handle) { $found = $i; break; } } if ($found !== false) { unset($this->_packageInfo['maintainers'][$found]); $this->_packageInfo['maintainers'] = array_values($this->_packageInfo['maintainers']); } $this->addMaintainer($role, $handle, $name, $email); } function deleteMaintainer($handle) { $found = false; foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) { if ($maintainer['handle'] == $handle) { $found = $i; break; } } if ($found !== false) { unset($this->_packageInfo['maintainers'][$found]); $this->_packageInfo['maintainers'] = array_values($this->_packageInfo['maintainers']); return true; } return false; } function getState() { if (isset($this->_packageInfo['release_state'])) { return $this->_packageInfo['release_state']; } return false; } function setRawState($state) { $this->_packageInfo['release_state'] = $state; } function setState($state) { $this->_packageInfo['release_state'] = $state; $this->_isValid = false; } function getDate() { if (isset($this->_packageInfo['release_date'])) { return $this->_packageInfo['release_date']; } return false; } function setDate($date) { $this->_packageInfo['release_date'] = $date; $this->_isValid = false; } function getLicense() { if (isset($this->_packageInfo['release_license'])) { return $this->_packageInfo['release_license']; } return false; } function setLicense($date) { $this->_packageInfo['release_license'] = $date; $this->_isValid = false; } function getSummary() { if (isset($this->_packageInfo['summary'])) { return $this->_packageInfo['summary']; } return false; } function setSummary($summary) { $this->_packageInfo['summary'] = $summary; $this->_isValid = false; } function getDescription() { if (isset($this->_packageInfo['description'])) { return $this->_packageInfo['description']; } return false; } function setDescription($desc) { $this->_packageInfo['description'] = $desc; $this->_isValid = false; } function getNotes() { if (isset($this->_packageInfo['release_notes'])) { return $this->_packageInfo['release_notes']; } return false; } function setNotes($notes) { $this->_packageInfo['release_notes'] = $notes; $this->_isValid = false; } function getDeps() { if (isset($this->_packageInfo['release_deps'])) { return $this->_packageInfo['release_deps']; } return false; } /** * Reset dependencies prior to adding new ones */ function clearDeps() { unset($this->_packageInfo['release_deps']); } function addPhpDep($version, $rel) { $this->_isValid = false; $this->_packageInfo['release_deps'][] = array('type' => 'php', 'rel' => $rel, 'version' => $version); } function addPackageDep($name, $version, $rel, $optional = 'no') { $this->_isValid = false; $dep = array('type' => 'pkg', 'name' => $name, 'rel' => $rel, 'optional' => $optional); if ($rel != 'has' && $rel != 'not') { $dep['version'] = $version; } $this->_packageInfo['release_deps'][] = $dep; } function addExtensionDep($name, $version, $rel, $optional = 'no') { $this->_isValid = false; $this->_packageInfo['release_deps'][] = array('type' => 'ext', 'name' => $name, 'rel' => $rel, 'version' => $version, 'optional' => $optional); } /** * WARNING - do not use this function directly unless you know what you're doing */ function setDeps($deps) { $this->_packageInfo['release_deps'] = $deps; } function hasDeps() { return isset($this->_packageInfo['release_deps']) && count($this->_packageInfo['release_deps']); } function getDependencyGroup($group) { return false; } function isCompatible($pf) { return false; } function isSubpackageOf($p) { return $p->isSubpackage($this); } function isSubpackage($p) { return false; } function dependsOn($package, $channel) { if (strtolower($channel) != 'pear.php.net') { return false; } if (!($deps = $this->getDeps())) { return false; } foreach ($deps as $dep) { if ($dep['type'] != 'pkg') { continue; } if (strtolower($dep['name']) == strtolower($package)) { return true; } } return false; } function getConfigureOptions() { if (isset($this->_packageInfo['configure_options'])) { return $this->_packageInfo['configure_options']; } return false; } function hasConfigureOptions() { return isset($this->_packageInfo['configure_options']) && count($this->_packageInfo['configure_options']); } function addConfigureOption($name, $prompt, $default = false) { $o = array('name' => $name, 'prompt' => $prompt); if ($default !== false) { $o['default'] = $default; } if (!isset($this->_packageInfo['configure_options'])) { $this->_packageInfo['configure_options'] = array(); } $this->_packageInfo['configure_options'][] = $o; } function clearConfigureOptions() { unset($this->_packageInfo['configure_options']); } function getProvides() { if (isset($this->_packageInfo['provides'])) { return $this->_packageInfo['provides']; } return false; } function getProvidesExtension() { return false; } function addFile($dir, $file, $attrs) { $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir); if ($dir == '/' || $dir == '') { $dir = ''; } else { $dir .= '/'; } $file = $dir . $file; $file = preg_replace('![\\/]+!', '/', $file); $this->_packageInfo['filelist'][$file] = $attrs; } function getInstallationFilelist() { return $this->getFilelist(); } function getFilelist() { if (isset($this->_packageInfo['filelist'])) { return $this->_packageInfo['filelist']; } return false; } function setFileAttribute($file, $attr, $value) { $this->_packageInfo['filelist'][$file][$attr] = $value; } function resetFilelist() { $this->_packageInfo['filelist'] = array(); } function setInstalledAs($file, $path) { if ($path) { return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; } unset($this->_packageInfo['filelist'][$file]['installed_as']); } function installedFile($file, $atts) { if (isset($this->_packageInfo['filelist'][$file])) { $this->_packageInfo['filelist'][$file] = array_merge($this->_packageInfo['filelist'][$file], $atts); } else { $this->_packageInfo['filelist'][$file] = $atts; } } function getChangelog() { if (isset($this->_packageInfo['changelog'])) { return $this->_packageInfo['changelog']; } return false; } function getPackagexmlVersion() { return '1.0'; } /** * Wrapper to {@link PEAR_ErrorStack::getErrors()} * @param boolean determines whether to purge the error stack after retrieving * @return array */ function getValidationWarnings($purge = true) { return $this->_stack->getErrors($purge); } // }}} /** * Validation error. Also marks the object contents as invalid * @param error code * @param array error information * @access private */ function _validateError($code, $params = array()) { $this->_stack->push($code, 'error', $params, false, false, debug_backtrace()); $this->_isValid = false; } /** * Validation warning. Does not mark the object contents invalid. * @param error code * @param array error information * @access private */ function _validateWarning($code, $params = array()) { $this->_stack->push($code, 'warning', $params, false, false, debug_backtrace()); } /** * @param integer error code * @access protected */ function _getErrorMessage() { return array( PEAR_PACKAGEFILE_ERROR_NO_NAME => 'Missing Package Name', PEAR_PACKAGEFILE_ERROR_NO_SUMMARY => 'No summary found', PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY => 'Summary should be on one line', PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION => 'Missing description', PEAR_PACKAGEFILE_ERROR_NO_LICENSE => 'Missing license', PEAR_PACKAGEFILE_ERROR_NO_VERSION => 'No release version found', PEAR_PACKAGEFILE_ERROR_NO_STATE => 'No release state found', PEAR_PACKAGEFILE_ERROR_NO_DATE => 'No release date found', PEAR_PACKAGEFILE_ERROR_NO_NOTES => 'No release notes found', PEAR_PACKAGEFILE_ERROR_NO_LEAD => 'Package must have at least one lead maintainer', PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS => 'No maintainers found, at least one must be defined', PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE => 'Maintainer %index% has no handle (user ID at channel server)', PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE => 'Maintainer %index% has no role', PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME => 'Maintainer %index% has no name', PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL => 'Maintainer %index% has no email', PEAR_PACKAGEFILE_ERROR_NO_DEPNAME => 'Dependency %index% is not a php dependency, and has no name', PEAR_PACKAGEFILE_ERROR_NO_DEPREL => 'Dependency %index% has no relation (rel)', PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE => 'Dependency %index% has no type', PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED => 'PHP Dependency %index% has a name attribute of "%name%" which will be' . ' ignored!', PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION => 'Dependency %index% is not a rel="has" or rel="not" dependency, ' . 'and has no version', PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION => 'Dependency %index% is a type="php" dependency, ' . 'and has no version', PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED => 'Dependency %index% is a rel="%rel%" dependency, versioning is ignored', PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL => 'Dependency %index% has invalid optional value "%opt%", should be yes or no', PEAR_PACKAGEFILE_PHP_NO_NOT => 'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' . ' to exclude specific versions', PEAR_PACKAGEFILE_ERROR_NO_CONFNAME => 'Configure Option %index% has no name', PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT => 'Configure Option %index% has no prompt', PEAR_PACKAGEFILE_ERROR_NO_FILES => 'No files in section of package.xml', PEAR_PACKAGEFILE_ERROR_NO_FILEROLE => 'File "%file%" has no role, expecting one of "%roles%"', PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE => 'File "%file%" has invalid role "%role%", expecting one of "%roles%"', PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME => 'File "%file%" cannot start with ".", cannot package or install', PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE => 'Parser error: invalid PHP found in file "%file%"', PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX => 'in %file%: %type% "%name%" not prefixed with package name "%package%"', PEAR_PACKAGEFILE_ERROR_INVALID_FILE => 'Parser error: invalid PHP file "%file%"', PEAR_PACKAGEFILE_ERROR_CHANNELVAL => 'Channel validator error: field "%field%" - %reason%', PEAR_PACKAGEFILE_ERROR_PHP5 => 'Error, PHP5 token encountered in %file%, analysis should be in PHP5', PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND => 'File "%file%" in package.xml does not exist', PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS => 'Package.xml contains non-ISO-8859-1 characters, and may not validate', ); } /** * Validate XML package definition file. * * @access public * @return boolean */ function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false) { if (($this->_isValid & $state) == $state) { return true; } $this->_isValid = true; $info = $this->_packageInfo; if (empty($info['package'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME); $this->_packageName = $pn = 'unknown'; } else { $this->_packageName = $pn = $info['package']; } if (empty($info['summary'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY); } elseif (strpos(trim($info['summary']), "\n") !== false) { $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY, array('summary' => $info['summary'])); } if (empty($info['description'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION); } if (empty($info['release_license'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE); } if (empty($info['version'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION); } if (empty($info['release_state'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE); } if (empty($info['release_date'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE); } if (empty($info['release_notes'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES); } if (empty($info['maintainers'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS); } else { $haslead = false; $i = 1; foreach ($info['maintainers'] as $m) { if (empty($m['handle'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE, array('index' => $i)); } if (empty($m['role'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE, array('index' => $i, 'roles' => PEAR_Common::getUserRoles())); } elseif ($m['role'] == 'lead') { $haslead = true; } if (empty($m['name'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME, array('index' => $i)); } if (empty($m['email'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL, array('index' => $i)); } $i++; } if (!$haslead) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD); } } if (!empty($info['release_deps'])) { $i = 1; foreach ($info['release_deps'] as $d) { if (!isset($d['type']) || empty($d['type'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE, array('index' => $i, 'types' => PEAR_Common::getDependencyTypes())); continue; } if (!isset($d['rel']) || empty($d['rel'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL, array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations())); continue; } if (!empty($d['optional'])) { if (!in_array($d['optional'], array('yes', 'no'))) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL, array('index' => $i, 'opt' => $d['optional'])); } } if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION, array('index' => $i)); } elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) { $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED, array('index' => $i, 'rel' => $d['rel'])); } if ($d['type'] == 'php' && !empty($d['name'])) { $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED, array('index' => $i, 'name' => $d['name'])); } elseif ($d['type'] != 'php' && empty($d['name'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME, array('index' => $i)); } if ($d['type'] == 'php' && empty($d['version'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION, array('index' => $i)); } if (($d['rel'] == 'not') && ($d['type'] == 'php')) { $this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT, array('index' => $i)); } $i++; } } if (!empty($info['configure_options'])) { $i = 1; foreach ($info['configure_options'] as $c) { if (empty($c['name'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME, array('index' => $i)); } if (empty($c['prompt'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT, array('index' => $i)); } $i++; } } if (empty($info['filelist'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES); $errors[] = 'no files'; } else { foreach ($info['filelist'] as $file => $fa) { if (empty($fa['role'])) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE, array('file' => $file, 'roles' => PEAR_Common::getFileRoles())); continue; } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE, array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles())); } if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) { // file contains .. parent directory or . cur directory references $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, array('file' => $file)); } if (isset($fa['install-as']) && preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $fa['install-as']))) { // install-as contains .. parent directory or . cur directory references $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, array('file' => $file . ' [installed as ' . $fa['install-as'] . ']')); } if (isset($fa['baseinstalldir']) && preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $fa['baseinstalldir']))) { // install-as contains .. parent directory or . cur directory references $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']')); } } } if (isset($this->_registry) && $this->_isValid) { $chan = $this->_registry->getChannel('pear.php.net'); if (PEAR::isError($chan)) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage()); return $this->_isValid = 0; } $validator = $chan->getValidationObject(); $validator->setPackageFile($this); $validator->validate($state); $failures = $validator->getFailures(); foreach ($failures['errors'] as $error) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error); } foreach ($failures['warnings'] as $warning) { $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning); } } if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) { if ($this->_analyzePhpFiles()) { $this->_isValid = true; } } if ($this->_isValid) { return $this->_isValid = $state; } return $this->_isValid = 0; } function _analyzePhpFiles() { if (!$this->_isValid) { return false; } if (!isset($this->_packageFile)) { return false; } $dir_prefix = dirname($this->_packageFile); $common = new PEAR_Common; $log = isset($this->_logger) ? array(&$this->_logger, 'log') : array($common, 'log'); $info = $this->getFilelist(); foreach ($info as $file => $fa) { if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND, array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file)); continue; } if ($fa['role'] == 'php' && $dir_prefix) { call_user_func_array($log, array(1, "Analyzing $file")); $srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); if ($srcinfo) { $this->_buildProvidesArray($srcinfo); } } } $this->_packageName = $pn = $this->getPackage(); $pnl = strlen($pn); if (isset($this->_packageInfo['provides'])) { foreach ((array) $this->_packageInfo['provides'] as $key => $what) { if (isset($what['explicit'])) { // skip conformance checks if the provides entry is // specified in the package.xml file continue; } extract($what); if ($type == 'class') { if (!strncasecmp($name, $pn, $pnl)) { continue; } $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX, array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn)); } elseif ($type == 'function') { if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { continue; } $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX, array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn)); } } } return $this->_isValid; } /** * Get the default xml generator object * * @return PEAR_PackageFile_Generator_v1 */ function &getDefaultGenerator() { if (!class_exists('PEAR_PackageFile_Generator_v1')) { require_once 'PEAR/PackageFile/Generator/v1.php'; } $a = new PEAR_PackageFile_Generator_v1($this); return $a; } /** * Get the contents of a file listed within the package.xml * @param string * @return string */ function getFileContents($file) { if ($this->_archiveFile == $this->_packageFile) { // unpacked $dir = dirname($this->_packageFile); $file = $dir . DIRECTORY_SEPARATOR . $file; $file = str_replace(array('/', '\\'), array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file); if (file_exists($file) && is_readable($file)) { return implode('', file($file)); } } else { // tgz if (!class_exists('Archive_Tar')) { require_once 'Archive/Tar.php'; } $tar = new Archive_Tar($this->_archiveFile); $tar->pushErrorHandling(PEAR_ERROR_RETURN); if ($file != 'package.xml' && $file != 'package2.xml') { $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file; } $file = $tar->extractInString($file); $tar->popErrorHandling(); if (PEAR::isError($file)) { return PEAR::raiseError("Cannot locate file '$file' in archive"); } return $file; } } // {{{ analyzeSourceCode() /** * Analyze the source code of the given PHP file * * @param string Filename of the PHP file * @return mixed * @access private */ function _analyzeSourceCode($file) { if (!function_exists("token_get_all")) { return false; } if (!defined('T_DOC_COMMENT')) { define('T_DOC_COMMENT', T_COMMENT); } if (!defined('T_INTERFACE')) { define('T_INTERFACE', -1); } if (!defined('T_IMPLEMENTS')) { define('T_IMPLEMENTS', -1); } if (!$fp = @fopen($file, "r")) { return false; } fclose($fp); $contents = file_get_contents($file); $tokens = token_get_all($contents); /* for ($i = 0; $i < sizeof($tokens); $i++) { @list($token, $data) = $tokens[$i]; if (is_string($token)) { var_dump($token); } else { print token_name($token) . ' '; var_dump(rtrim($data)); } } */ $look_for = 0; $paren_level = 0; $bracket_level = 0; $brace_level = 0; $lastphpdoc = ''; $current_class = ''; $current_interface = ''; $current_class_level = -1; $current_function = ''; $current_function_level = -1; $declared_classes = array(); $declared_interfaces = array(); $declared_functions = array(); $declared_methods = array(); $used_classes = array(); $used_functions = array(); $extends = array(); $implements = array(); $nodeps = array(); $inquote = false; $interface = false; for ($i = 0; $i < sizeof($tokens); $i++) { if (is_array($tokens[$i])) { list($token, $data) = $tokens[$i]; } else { $token = $tokens[$i]; $data = ''; } if ($inquote) { if ($token != '"' && $token != T_END_HEREDOC) { continue; } else { $inquote = false; continue; } } switch ($token) { case T_WHITESPACE: break; case ';': if ($interface) { $current_function = ''; $current_function_level = -1; } break; case '"': case T_START_HEREDOC: $inquote = true; break; case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: case '{': $brace_level++; continue 2; case '}': $brace_level--; if ($current_class_level == $brace_level) { $current_class = ''; $current_class_level = -1; } if ($current_function_level == $brace_level) { $current_function = ''; $current_function_level = -1; } continue 2; case '[': $bracket_level++; continue 2; case ']': $bracket_level--; continue 2; case '(': $paren_level++; continue 2; case ')': $paren_level--; continue 2; case T_INTERFACE: $interface = true; case T_CLASS: if (($current_class_level != -1) || ($current_function_level != -1)) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE, array('file' => $file)); return false; } case T_FUNCTION: case T_NEW: case T_EXTENDS: case T_IMPLEMENTS: $look_for = $token; continue 2; case T_STRING: if ($look_for == T_CLASS) { $current_class = $data; $current_class_level = $brace_level; $declared_classes[] = $current_class; } elseif ($look_for == T_INTERFACE) { $current_interface = $data; $current_class_level = $brace_level; $declared_interfaces[] = $current_interface; } elseif ($look_for == T_IMPLEMENTS) { $implements[$current_class] = $data; } elseif ($look_for == T_EXTENDS) { $extends[$current_class] = $data; } elseif ($look_for == T_FUNCTION) { if ($current_class) { $current_function = "$current_class::$data"; $declared_methods[$current_class][] = $data; } elseif ($current_interface) { $current_function = "$current_interface::$data"; $declared_methods[$current_interface][] = $data; } else { $current_function = $data; $declared_functions[] = $current_function; } $current_function_level = $brace_level; $m = array(); } elseif ($look_for == T_NEW) { $used_classes[$data] = true; } $look_for = 0; continue 2; case T_VARIABLE: $look_for = 0; continue 2; case T_DOC_COMMENT: case T_COMMENT: if (preg_match('!^/\*\*\s!', $data)) { $lastphpdoc = $data; if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { $nodeps = array_merge($nodeps, $m[1]); } } continue 2; case T_DOUBLE_COLON: if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) { $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE, array('file' => $file)); return false; } $class = $tokens[$i - 1][1]; if (strtolower($class) != 'parent') { $used_classes[$class] = true; } continue 2; } } return array( "source_file" => $file, "declared_classes" => $declared_classes, "declared_interfaces" => $declared_interfaces, "declared_methods" => $declared_methods, "declared_functions" => $declared_functions, "used_classes" => array_diff(array_keys($used_classes), $nodeps), "inheritance" => $extends, "implements" => $implements, ); } /** * Build a "provides" array from data returned by * analyzeSourceCode(). The format of the built array is like * this: * * array( * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), * ... * ) * * * @param array $srcinfo array with information about a source file * as returned by the analyzeSourceCode() method. * * @return void * * @access private * */ function _buildProvidesArray($srcinfo) { if (!$this->_isValid) { return false; } $file = basename($srcinfo['source_file']); $pn = $this->getPackage(); $pnl = strlen($pn); foreach ($srcinfo['declared_classes'] as $class) { $key = "class;$class"; if (isset($this->_packageInfo['provides'][$key])) { continue; } $this->_packageInfo['provides'][$key] = array('file'=> $file, 'type' => 'class', 'name' => $class); if (isset($srcinfo['inheritance'][$class])) { $this->_packageInfo['provides'][$key]['extends'] = $srcinfo['inheritance'][$class]; } } foreach ($srcinfo['declared_methods'] as $class => $methods) { foreach ($methods as $method) { $function = "$class::$method"; $key = "function;$function"; if ($method[0] == '_' || !strcasecmp($method, $class) || isset($this->_packageInfo['provides'][$key])) { continue; } $this->_packageInfo['provides'][$key] = array('file'=> $file, 'type' => 'function', 'name' => $function); } } foreach ($srcinfo['declared_functions'] as $function) { $key = "function;$function"; if ($function[0] == '_' || isset($this->_packageInfo['provides'][$key])) { continue; } if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; } $this->_packageInfo['provides'][$key] = array('file'=> $file, 'type' => 'function', 'name' => $function); } } // }}} } ?> PK!ɁɁ!PEAR/PackageFile/Generator/v2.phpnu[ * @author Stephan Schmidt (original XML_Serializer code) * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * file/dir manipulation routines */ require_once 'System.php'; require_once 'XML/Util.php'; /** * This class converts a PEAR_PackageFile_v2 object into any output format. * * Supported output formats include array, XML string (using S. Schmidt's * XML_Serializer, slightly customized) * @category pear * @package PEAR * @author Greg Beaver * @author Stephan Schmidt (original XML_Serializer code) * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_PackageFile_Generator_v2 { /** * default options for the serialization * @access private * @var array $_defaultOptions */ var $_defaultOptions = array( 'indent' => ' ', // string used for indentation 'linebreak' => "\n", // string used for newlines 'typeHints' => false, // automatically add type hin attributes 'addDecl' => true, // add an XML declaration 'defaultTagName' => 'XML_Serializer_Tag', // tag used for indexed arrays or invalid names 'classAsTagName' => false, // use classname for objects in indexed arrays 'keyAttribute' => '_originalKey', // attribute where original key is stored 'typeAttribute' => '_type', // attribute for type (only if typeHints => true) 'classAttribute' => '_class', // attribute for class of objects (only if typeHints => true) 'scalarAsAttributes' => false, // scalar values (strings, ints,..) will be serialized as attribute 'prependAttributes' => '', // prepend string for attributes 'indentAttributes' => false, // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column 'mode' => 'simplexml', // use 'simplexml' to use parent name as tagname if transforming an indexed array 'addDoctype' => false, // add a doctype declaration 'doctype' => null, // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()} 'rootName' => 'package', // name of the root tag 'rootAttributes' => array( 'version' => '2.0', 'xmlns' => 'http://pear.php.net/dtd/package-2.0', 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd', ), // attributes of the root tag 'attributesArray' => 'attribs', // all values in this key will be treated as attributes 'contentName' => '_content', // this value will be used directly as content, instead of creating a new tag, may only be used in conjunction with attributesArray 'beautifyFilelist' => false, 'encoding' => 'UTF-8', ); /** * options for the serialization * @access private * @var array $options */ var $options = array(); /** * current tag depth * @var integer $_tagDepth */ var $_tagDepth = 0; /** * serilialized representation of the data * @var string $_serializedData */ var $_serializedData = null; /** * @var PEAR_PackageFile_v2 */ var $_packagefile; /** * @param PEAR_PackageFile_v2 */ function __construct(&$packagefile) { $this->_packagefile = &$packagefile; if (isset($this->_packagefile->encoding)) { $this->_defaultOptions['encoding'] = $this->_packagefile->encoding; } } /** * @return string */ function getPackagerVersion() { return '1.10.16'; } /** * @param PEAR_Packager * @param bool generate a .tgz or a .tar * @param string|null temporary directory to package in */ function toTgz(&$packager, $compress = true, $where = null) { $a = null; return $this->toTgz2($packager, $a, $compress, $where); } /** * Package up both a package.xml and package2.xml for the same release * @param PEAR_Packager * @param PEAR_PackageFile_v1 * @param bool generate a .tgz or a .tar * @param string|null temporary directory to package in */ function toTgz2(&$packager, &$pf1, $compress = true, $where = null) { require_once 'Archive/Tar.php'; if (!$this->_packagefile->isEquivalent($pf1)) { return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . basename($pf1->getPackageFile()) . '" is not equivalent to "' . basename($this->_packagefile->getPackageFile()) . '"'); } if ($where === null) { if (!($where = System::mktemp(array('-d')))) { return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed'); } } elseif (!@System::mkDir(array('-p', $where))) { return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' . ' not be created'); } $file = $where . DIRECTORY_SEPARATOR . 'package.xml'; if (file_exists($file) && !is_file($file)) { return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' . ' "' . $file .'"'); } if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) { return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml'); } $ext = $compress ? '.tgz' : '.tar'; $pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion(); $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; if (file_exists($dest_package) && !is_file($dest_package)) { return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' . $dest_package . '"'); } $pkgfile = $this->_packagefile->getPackageFile(); if (!$pkgfile) { return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' . 'be created from a real file'); } $pkgdir = dirname(realpath($pkgfile)); $pkgfile = basename($pkgfile); // {{{ Create the package file list $filelist = array(); $i = 0; $this->_packagefile->flattenFilelist(); $contents = $this->_packagefile->getContents(); if (isset($contents['bundledpackage'])) { // bundles of packages $contents = $contents['bundledpackage']; if (!isset($contents[0])) { $contents = array($contents); } $packageDir = $where; foreach ($contents as $i => $package) { $fname = $package; $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; if (!file_exists($file)) { return $packager->raiseError("File does not exist: $fname"); } $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname; System::mkdir(array('-p', dirname($tfile))); copy($file, $tfile); $filelist[$i++] = $tfile; $packager->log(2, "Adding package $fname"); } } else { // normal packages $contents = $contents['dir']['file']; if (!isset($contents[0])) { $contents = array($contents); } $packageDir = $where; foreach ($contents as $i => $file) { $fname = $file['attribs']['name']; $atts = $file['attribs']; $orig = $file; $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; if (!file_exists($file)) { return $packager->raiseError("File does not exist: $fname"); } $origperms = fileperms($file); $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname; unset($orig['attribs']); if (count($orig)) { // file with tasks // run any package-time tasks $contents = file_get_contents($file); foreach ($orig as $tag => $raw) { $tag = str_replace( array($this->_packagefile->getTasksNs() . ':', '-'), array('', '_'), $tag); $task = "PEAR_Task_$tag"; $task = new $task($this->_packagefile->_config, $this->_packagefile->_logger, PEAR_TASK_PACKAGE); $task->init($raw, $atts, null); $res = $task->startSession($this->_packagefile, $contents, $tfile); if (!$res) { continue; // skip this task } if (PEAR::isError($res)) { return $res; } $contents = $res; // save changes System::mkdir(array('-p', dirname($tfile))); $wp = fopen($tfile, "wb"); fwrite($wp, $contents); fclose($wp); } } if (!file_exists($tfile)) { System::mkdir(array('-p', dirname($tfile))); copy($file, $tfile); } chmod($tfile, $origperms); $filelist[$i++] = $tfile; $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1); $packager->log(2, "Adding file $fname"); } } // }}} $name = $pf1 !== null ? 'package2.xml' : 'package.xml'; $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name); if ($packagexml) { $tar = new Archive_Tar($dest_package, $compress); $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors // ----- Creates with the package.xml file $ok = $tar->createModify(array($packagexml), '', $where); if (PEAR::isError($ok)) { return $packager->raiseError($ok); } elseif (!$ok) { return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name . ' failed'); } // ----- Add the content of the package if (!$tar->addModify($filelist, $pkgver, $where)) { return $packager->raiseError( 'PEAR_Packagefile_v2::toTgz(): tarball creation failed'); } // add the package.xml version 1.0 if ($pf1 !== null) { $pfgen = &$pf1->getDefaultGenerator(); $packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true); if (!$tar->addModify(array($packagexml1), '', $where)) { return $packager->raiseError( 'PEAR_Packagefile_v2::toTgz(): adding package.xml failed'); } } return $dest_package; } } function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml') { if (!$this->_packagefile->validate($state)) { return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml', null, null, null, $this->_packagefile->getValidationWarnings()); } if ($where === null) { if (!($where = System::mktemp(array('-d')))) { return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed'); } } elseif (!@System::mkDir(array('-p', $where))) { return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' . ' not be created'); } $newpkgfile = $where . DIRECTORY_SEPARATOR . $name; $np = @fopen($newpkgfile, 'wb'); if (!$np) { return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' . "$name as $newpkgfile"); } fwrite($np, $this->toXml($state)); fclose($np); return $newpkgfile; } function &toV2() { return $this->_packagefile; } /** * Return an XML document based on the package info (as returned * by the PEAR_Common::infoFrom* methods). * * @return string XML data */ function toXml($state = PEAR_VALIDATE_NORMAL, $options = array()) { $this->_packagefile->setDate(date('Y-m-d')); $this->_packagefile->setTime(date('H:i:s')); if (!$this->_packagefile->validate($state)) { return false; } if (is_array($options)) { $this->options = array_merge($this->_defaultOptions, $options); } else { $this->options = $this->_defaultOptions; } $arr = $this->_packagefile->getArray(); if (isset($arr['filelist'])) { unset($arr['filelist']); } if (isset($arr['_lastversion'])) { unset($arr['_lastversion']); } // Fix the notes a little bit if (isset($arr['notes'])) { // This trims out the indenting, needs fixing $arr['notes'] = "\n" . trim($arr['notes']) . "\n"; } if (isset($arr['changelog']) && !empty($arr['changelog'])) { // Fix for inconsistency how the array is filled depending on the changelog release amount if (!isset($arr['changelog']['release'][0])) { $release = $arr['changelog']['release']; unset($arr['changelog']['release']); $arr['changelog']['release'] = array(); $arr['changelog']['release'][0] = $release; } foreach (array_keys($arr['changelog']['release']) as $key) { $c =& $arr['changelog']['release'][$key]; if (isset($c['notes'])) { // This trims out the indenting, needs fixing $c['notes'] = "\n" . trim($c['notes']) . "\n"; } } } if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) { $use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']); unset($arr['contents']['dir']['file']); if (isset($use['dir'])) { $arr['contents']['dir']['dir'] = $use['dir']; } if (isset($use['file'])) { $arr['contents']['dir']['file'] = $use['file']; } $this->options['beautifyFilelist'] = true; } $arr['attribs']['packagerversion'] = '1.10.16'; if ($this->serialize($arr, $options)) { return $this->_serializedData . "\n"; } return false; } function _recursiveXmlFilelist($list) { $dirs = array(); if (isset($list['attribs'])) { $file = $list['attribs']['name']; unset($list['attribs']['name']); $attributes = $list['attribs']; $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes); } else { foreach ($list as $a) { $file = $a['attribs']['name']; $attributes = $a['attribs']; unset($a['attribs']); $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a); } } $this->_formatDir($dirs); $this->_deFormat($dirs); return $dirs; } function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null) { if (!$tasks) { $tasks = array(); } if ($dir == array() || $dir == array('.')) { $dirs['file'][basename($file)] = $tasks; $attributes['name'] = basename($file); $dirs['file'][basename($file)]['attribs'] = $attributes; return; } $curdir = array_shift($dir); if (!isset($dirs['dir'][$curdir])) { $dirs['dir'][$curdir] = array(); } $this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks); } function _formatDir(&$dirs) { if (!count($dirs)) { return array(); } $newdirs = array(); if (isset($dirs['dir'])) { $newdirs['dir'] = $dirs['dir']; } if (isset($dirs['file'])) { $newdirs['file'] = $dirs['file']; } $dirs = $newdirs; if (isset($dirs['dir'])) { uksort($dirs['dir'], 'strnatcasecmp'); foreach ($dirs['dir'] as $dir => $contents) { $this->_formatDir($dirs['dir'][$dir]); } } if (isset($dirs['file'])) { uksort($dirs['file'], 'strnatcasecmp'); }; } function _deFormat(&$dirs) { if (!count($dirs)) { return array(); } $newdirs = array(); if (isset($dirs['dir'])) { foreach ($dirs['dir'] as $dir => $contents) { $newdir = array(); $newdir['attribs']['name'] = $dir; $this->_deFormat($contents); foreach ($contents as $tag => $val) { $newdir[$tag] = $val; } $newdirs['dir'][] = $newdir; } if (count($newdirs['dir']) == 1) { $newdirs['dir'] = $newdirs['dir'][0]; } } if (isset($dirs['file'])) { foreach ($dirs['file'] as $name => $file) { $newdirs['file'][] = $file; } if (count($newdirs['file']) == 1) { $newdirs['file'] = $newdirs['file'][0]; } } $dirs = $newdirs; } /** * reset all options to default options * * @access public * @see setOption(), XML_Unserializer() */ function resetOptions() { $this->options = $this->_defaultOptions; } /** * set an option * * You can use this method if you do not want to set all options in the constructor * * @access public * @see resetOption(), XML_Serializer() */ function setOption($name, $value) { $this->options[$name] = $value; } /** * sets several options at once * * You can use this method if you do not want to set all options in the constructor * * @access public * @see resetOption(), XML_Unserializer(), setOption() */ function setOptions($options) { $this->options = array_merge($this->options, $options); } /** * serialize data * * @access public * @param mixed $data data to serialize * @return boolean true on success, pear error on failure */ function serialize($data, $options = null) { // if options have been specified, use them instead // of the previously defined ones if (is_array($options)) { $optionsBak = $this->options; if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) { $this->options = array_merge($this->_defaultOptions, $options); } else { $this->options = array_merge($this->options, $options); } } else { $optionsBak = null; } // start depth is zero $this->_tagDepth = 0; $this->_serializedData = ''; // serialize an array if (is_array($data)) { $tagName = isset($this->options['rootName']) ? $this->options['rootName'] : 'array'; $this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']); } // add doctype declaration if ($this->options['addDoctype'] === true) { $this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype']) . $this->options['linebreak'] . $this->_serializedData; } // build xml declaration if ($this->options['addDecl']) { $atts = array(); $encoding = isset($this->options['encoding']) ? $this->options['encoding'] : null; $this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding) . $this->options['linebreak'] . $this->_serializedData; } if ($optionsBak !== null) { $this->options = $optionsBak; } return true; } /** * get the result of the serialization * * @access public * @return string serialized XML */ function getSerializedData() { if ($this->_serializedData === null) { return $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION); } return $this->_serializedData; } /** * serialize any value * * This method checks for the type of the value and calls the appropriate method * * @access private * @param mixed $value * @param string $tagName * @param array $attributes * @return string */ function _serializeValue($value, $tagName = null, $attributes = array()) { if (is_array($value)) { $xml = $this->_serializeArray($value, $tagName, $attributes); } elseif (is_object($value)) { $xml = $this->_serializeObject($value, $tagName); } else { $tag = array( 'qname' => $tagName, 'attributes' => $attributes, 'content' => $value ); $xml = $this->_createXMLTag($tag); } return $xml; } /** * serialize an array * * @access private * @param array $array array to serialize * @param string $tagName name of the root tag * @param array $attributes attributes for the root tag * @return string $string serialized data * @uses XML_Util::isValidName() to check, whether key has to be substituted */ function _serializeArray(&$array, $tagName = null, $attributes = array()) { $_content = null; /** * check for special attributes */ if ($this->options['attributesArray'] !== null) { if (isset($array[$this->options['attributesArray']])) { $attributes = $array[$this->options['attributesArray']]; unset($array[$this->options['attributesArray']]); } /** * check for special content */ if ($this->options['contentName'] !== null) { if (isset($array[$this->options['contentName']])) { $_content = $array[$this->options['contentName']]; unset($array[$this->options['contentName']]); } } } /* * if mode is set to simpleXML, check whether * the array is associative or indexed */ if (is_array($array) && $this->options['mode'] == 'simplexml') { $indexed = true; if (!count($array)) { $indexed = false; } foreach ($array as $key => $val) { if (!is_int($key)) { $indexed = false; break; } } if ($indexed && $this->options['mode'] == 'simplexml') { $string = ''; foreach ($array as $key => $val) { if ($this->options['beautifyFilelist'] && $tagName == 'dir') { if (!isset($this->_curdir)) { $this->_curdir = ''; } $savedir = $this->_curdir; if (isset($val['attribs'])) { if ($val['attribs']['name'] == '/') { $this->_curdir = '/'; } else { if ($this->_curdir == '/') { $this->_curdir = ''; } $this->_curdir .= '/' . $val['attribs']['name']; } } } $string .= $this->_serializeValue( $val, $tagName, $attributes); if ($this->options['beautifyFilelist'] && $tagName == 'dir') { $string .= ' '; if (empty($savedir)) { unset($this->_curdir); } else { $this->_curdir = $savedir; } } $string .= $this->options['linebreak']; // do indentation if ($this->options['indent'] !== null && $this->_tagDepth > 0) { $string .= str_repeat($this->options['indent'], $this->_tagDepth); } } return rtrim($string); } } if ($this->options['scalarAsAttributes'] === true) { foreach ($array as $key => $value) { if (is_scalar($value) && (XML_Util::isValidName($key) === true)) { unset($array[$key]); $attributes[$this->options['prependAttributes'].$key] = $value; } } } // check for empty array => create empty tag if (empty($array)) { $tag = array( 'qname' => $tagName, 'content' => $_content, 'attributes' => $attributes ); } else { $this->_tagDepth++; $tmp = $this->options['linebreak']; foreach ($array as $key => $value) { // do indentation if ($this->options['indent'] !== null && $this->_tagDepth > 0) { $tmp .= str_repeat($this->options['indent'], $this->_tagDepth); } // copy key $origKey = $key; // key cannot be used as tagname => use default tag $valid = XML_Util::isValidName($key); if (PEAR::isError($valid)) { if ($this->options['classAsTagName'] && is_object($value)) { $key = get_class($value); } else { $key = $this->options['defaultTagName']; } } $atts = array(); if ($this->options['typeHints'] === true) { $atts[$this->options['typeAttribute']] = gettype($value); if ($key !== $origKey) { $atts[$this->options['keyAttribute']] = (string)$origKey; } } if ($this->options['beautifyFilelist'] && $key == 'dir') { if (!isset($this->_curdir)) { $this->_curdir = ''; } $savedir = $this->_curdir; if (isset($value['attribs'])) { if ($value['attribs']['name'] == '/') { $this->_curdir = '/'; } else { $this->_curdir .= '/' . $value['attribs']['name']; } } } if (is_string($value) && $value && ($value[strlen($value) - 1] == "\n")) { $value .= str_repeat($this->options['indent'], $this->_tagDepth); } $tmp .= $this->_createXMLTag(array( 'qname' => $key, 'attributes' => $atts, 'content' => $value ) ); if ($this->options['beautifyFilelist'] && $key == 'dir') { if (isset($value['attribs'])) { $tmp .= ' '; if (empty($savedir)) { unset($this->_curdir); } else { $this->_curdir = $savedir; } } } $tmp .= $this->options['linebreak']; } $this->_tagDepth--; if ($this->options['indent']!==null && $this->_tagDepth>0) { $tmp .= str_repeat($this->options['indent'], $this->_tagDepth); } if (trim($tmp) === '') { $tmp = null; } $tag = array( 'qname' => $tagName, 'content' => $tmp, 'attributes' => $attributes ); } if ($this->options['typeHints'] === true) { if (!isset($tag['attributes'][$this->options['typeAttribute']])) { $tag['attributes'][$this->options['typeAttribute']] = 'array'; } } $string = $this->_createXMLTag($tag, false); return $string; } /** * create a tag from an array * this method awaits an array in the following format * array( * 'qname' => $tagName, * 'attributes' => array(), * 'content' => $content, // optional * 'namespace' => $namespace // optional * 'namespaceUri' => $namespaceUri // optional * ) * * @access private * @param array $tag tag definition * @param boolean $replaceEntities whether to replace XML entities in content or not * @return string $string XML tag */ function _createXMLTag($tag, $replaceEntities = true) { if ($this->options['indentAttributes'] !== false) { $multiline = true; $indent = str_repeat($this->options['indent'], $this->_tagDepth); if ($this->options['indentAttributes'] == '_auto') { $indent .= str_repeat(' ', (strlen($tag['qname'])+2)); } else { $indent .= $this->options['indentAttributes']; } } else { $indent = $multiline = false; } if (is_array($tag['content'])) { if (empty($tag['content'])) { $tag['content'] = ''; } } elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') { $tag['content'] = ''; } if (is_scalar($tag['content']) || is_null($tag['content'])) { if ($replaceEntities === true) { $replaceEntities = XML_UTIL_ENTITIES_XML; } $tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']); } elseif (is_array($tag['content'])) { $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']); } elseif (is_object($tag['content'])) { $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']); } elseif (is_resource($tag['content'])) { settype($tag['content'], 'string'); $tag = XML_Util::createTagFromArray($tag, $replaceEntities); } return $tag; } } PK!`=!PEAR/PackageFile/Generator/v1.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * needed for PEAR_VALIDATE_* constants */ require_once 'PEAR/Validate.php'; require_once 'System.php'; require_once 'PEAR/PackageFile/v2.php'; /** * This class converts a PEAR_PackageFile_v1 object into any output format. * * Supported output formats include array, XML string, and a PEAR_PackageFile_v2 * object, for converting package.xml 1.0 into package.xml 2.0 with no sweat. * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_PackageFile_Generator_v1 { /** * @var PEAR_PackageFile_v1 */ var $_packagefile; function __construct(&$packagefile) { $this->_packagefile = &$packagefile; } function getPackagerVersion() { return '1.10.16'; } /** * @param PEAR_Packager * @param bool if true, a .tgz is written, otherwise a .tar is written * @param string|null directory in which to save the .tgz * @return string|PEAR_Error location of package or error object */ function toTgz(&$packager, $compress = true, $where = null) { require_once 'Archive/Tar.php'; if ($where === null) { if (!($where = System::mktemp(array('-d')))) { return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed'); } } elseif (!@System::mkDir(array('-p', $where))) { return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' . ' not be created'); } if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') && !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) { return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' . ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"'); } if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) { return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file'); } $pkginfo = $this->_packagefile->getArray(); $ext = $compress ? '.tgz' : '.tar'; $pkgver = $pkginfo['package'] . '-' . $pkginfo['version']; $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) && !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) { return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' . getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"'); } if ($pkgfile = $this->_packagefile->getPackageFile()) { $pkgdir = dirname(realpath($pkgfile)); $pkgfile = basename($pkgfile); } else { return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' . 'be created from a real file'); } // {{{ Create the package file list $filelist = array(); $i = 0; foreach ($this->_packagefile->getFilelist() as $fname => $atts) { $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; if (!file_exists($file)) { return PEAR::raiseError("File does not exist: $fname"); } else { $filelist[$i++] = $file; if (!isset($atts['md5sum'])) { $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file)); } $packager->log(2, "Adding file $fname"); } } // }}} $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true); if ($packagexml) { $tar = new Archive_Tar($dest_package, $compress); $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors // ----- Creates with the package.xml file $ok = $tar->createModify(array($packagexml), '', $where); if (PEAR::isError($ok)) { return $ok; } elseif (!$ok) { return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed'); } // ----- Add the content of the package if (!$tar->addModify($filelist, $pkgver, $pkgdir)) { return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed'); } return $dest_package; } } /** * @param string|null directory to place the package.xml in, or null for a temporary dir * @param int one of the PEAR_VALIDATE_* constants * @param string name of the generated file * @param bool if true, then no analysis will be performed on role="php" files * @return string|PEAR_Error path to the created file on success */ function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml', $nofilechecking = false) { if (!$this->_packagefile->validate($state, $nofilechecking)) { return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml', null, null, null, $this->_packagefile->getValidationWarnings()); } if ($where === null) { if (!($where = System::mktemp(array('-d')))) { return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed'); } } elseif (!@System::mkDir(array('-p', $where))) { return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' . ' not be created'); } $newpkgfile = $where . DIRECTORY_SEPARATOR . $name; $np = @fopen($newpkgfile, 'wb'); if (!$np) { return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' . "$name as $newpkgfile"); } fwrite($np, $this->toXml($state, true)); fclose($np); return $newpkgfile; } /** * fix both XML encoding to be UTF8, and replace standard XML entities < > " & ' * * @param string $string * @return string * @access private */ function _fixXmlEncoding($string) { return strtr($string, array( '&' => '&', '>' => '>', '<' => '<', '"' => '"', '\'' => ''' )); } /** * Return an XML document based on the package info (as returned * by the PEAR_Common::infoFrom* methods). * * @return string XML data */ function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false) { $this->_packagefile->setDate(date('Y-m-d')); if (!$this->_packagefile->validate($state, $nofilevalidation)) { return false; } $pkginfo = $this->_packagefile->getArray(); static $maint_map = array( "handle" => "user", "name" => "name", "email" => "email", "role" => "role", ); $ret = "\n"; $ret .= "\n"; $ret .= "\n" . " $pkginfo[package]"; if (isset($pkginfo['extends'])) { $ret .= "\n$pkginfo[extends]"; } $ret .= "\n ".$this->_fixXmlEncoding($pkginfo['summary'])."\n" . " ".trim($this->_fixXmlEncoding($pkginfo['description']))."\n \n" . " \n"; foreach ($pkginfo['maintainers'] as $maint) { $ret .= " \n"; foreach ($maint_map as $idx => $elm) { $ret .= " <$elm>"; $ret .= $this->_fixXmlEncoding($maint[$idx]); $ret .= "\n"; } $ret .= " \n"; } $ret .= " \n"; $ret .= $this->_makeReleaseXml($pkginfo, false, $state); if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) { $ret .= " \n"; foreach ($pkginfo['changelog'] as $oldrelease) { $ret .= $this->_makeReleaseXml($oldrelease, true); } $ret .= " \n"; } $ret .= "\n"; return $ret; } // }}} // {{{ _makeReleaseXml() /** * Generate part of an XML description with release information. * * @param array $pkginfo array with release information * @param bool $changelog whether the result will be in a changelog element * * @return string XML data * * @access private */ function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL) { // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!! $indent = $changelog ? " " : ""; $ret = "$indent \n"; if (!empty($pkginfo['version'])) { $ret .= "$indent $pkginfo[version]\n"; } if (!empty($pkginfo['release_date'])) { $ret .= "$indent $pkginfo[release_date]\n"; } if (!empty($pkginfo['release_license'])) { $ret .= "$indent $pkginfo[release_license]\n"; } if (!empty($pkginfo['release_state'])) { $ret .= "$indent $pkginfo[release_state]\n"; } if (!empty($pkginfo['release_notes'])) { $ret .= "$indent ".trim($this->_fixXmlEncoding($pkginfo['release_notes'])) ."\n$indent \n"; } if (!empty($pkginfo['release_warnings'])) { $ret .= "$indent ".$this->_fixXmlEncoding($pkginfo['release_warnings'])."\n"; } if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) { $ret .= "$indent \n"; foreach ($pkginfo['release_deps'] as $dep) { $ret .= "$indent _fixXmlEncoding($c['name']) . "\""; if (isset($c['default'])) { $ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\""; } $ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\""; $ret .= "/>\n"; } $ret .= "$indent \n"; } if (isset($pkginfo['provides'])) { foreach ($pkginfo['provides'] as $key => $what) { $ret .= "$indent recursiveXmlFilelist($pkginfo['filelist']); } else { foreach ($pkginfo['filelist'] as $file => $fa) { if (!isset($fa['role'])) { $fa['role'] = ''; } $ret .= "$indent _fixXmlEncoding($fa['baseinstalldir']) . '"'; } if (isset($fa['md5sum'])) { $ret .= " md5sum=\"$fa[md5sum]\""; } if (isset($fa['platform'])) { $ret .= " platform=\"$fa[platform]\""; } if (!empty($fa['install-as'])) { $ret .= ' install-as="' . $this->_fixXmlEncoding($fa['install-as']) . '"'; } $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"'; if (empty($fa['replacements'])) { $ret .= "/>\n"; } else { $ret .= ">\n"; foreach ($fa['replacements'] as $r) { $ret .= "$indent $v) { $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"'; } $ret .= "/>\n"; } $ret .= "$indent \n"; } } } $ret .= "$indent \n"; } $ret .= "$indent \n"; return $ret; } /** * @param array * @access protected */ function recursiveXmlFilelist($list) { $this->_dirs = array(); foreach ($list as $file => $attributes) { $this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes); } return $this->_formatDir($this->_dirs); } /** * @param array * @param array * @param string|null * @param array|null * @access private */ function _addDir(&$dirs, $dir, $file = null, $attributes = null) { if ($dir == array() || $dir == array('.')) { $dirs['files'][basename($file)] = $attributes; return; } $curdir = array_shift($dir); if (!isset($dirs['dirs'][$curdir])) { $dirs['dirs'][$curdir] = array(); } $this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes); } /** * @param array * @param string * @param string * @access private */ function _formatDir($dirs, $indent = '', $curdir = '') { $ret = ''; if (!count($dirs)) { return ''; } if (isset($dirs['dirs'])) { uksort($dirs['dirs'], 'strnatcasecmp'); foreach ($dirs['dirs'] as $dir => $contents) { $usedir = "$curdir/$dir"; $ret .= "$indent \n"; $ret .= $this->_formatDir($contents, "$indent ", $usedir); $ret .= "$indent \n"; } } if (isset($dirs['files'])) { uksort($dirs['files'], 'strnatcasecmp'); foreach ($dirs['files'] as $file => $attribs) { $ret .= $this->_formatFile($file, $attribs, $indent); } } return $ret; } /** * @param string * @param array * @param string * @access private */ function _formatFile($file, $attributes, $indent) { $ret = "$indent _fixXmlEncoding($attributes['baseinstalldir']) . '"'; } if (isset($attributes['md5sum'])) { $ret .= " md5sum=\"$attributes[md5sum]\""; } if (isset($attributes['platform'])) { $ret .= " platform=\"$attributes[platform]\""; } if (!empty($attributes['install-as'])) { $ret .= ' install-as="' . $this->_fixXmlEncoding($attributes['install-as']) . '"'; } $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"'; if (empty($attributes['replacements'])) { $ret .= "/>\n"; } else { $ret .= ">\n"; foreach ($attributes['replacements'] as $r) { $ret .= "$indent $v) { $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"'; } $ret .= "/>\n"; } $ret .= "$indent \n"; } return $ret; } // {{{ _unIndent() /** * Unindent given string (?) * * @param string $str The string that has to be unindented. * @return string * @access private */ function _unIndent($str) { // remove leading newlines $str = preg_replace('/^[\r\n]+/', '', $str); // find whitespace at the beginning of the first line $indent_len = strspn($str, " \t"); $indent = substr($str, 0, $indent_len); $data = ''; // remove the same amount of whitespace from following lines foreach (explode("\n", $str) as $line) { if (substr($line, 0, $indent_len) == $indent) { $data .= substr($line, $indent_len) . "\n"; } } return $data; } /** * @return array */ function dependenciesToV2() { $arr = array(); $this->_convertDependencies2_0($arr); return $arr['dependencies']; } /** * Convert a package.xml version 1.0 into version 2.0 * * Note that this does a basic conversion, to allow more advanced * features like bundles and multiple releases * @param string the classname to instantiate and return. This must be * PEAR_PackageFile_v2 or a descendant * @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the * strictest parameters will be converted * @return PEAR_PackageFile_v2|PEAR_Error */ function &toV2($class = 'PEAR_PackageFile_v2', $strict = false) { if ($strict) { if (!$this->_packagefile->validate()) { $a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' . ' to version 2.0', null, null, null, $this->_packagefile->getValidationWarnings(true)); return $a; } } $arr = array( 'attribs' => array( 'version' => '2.0', 'xmlns' => 'http://pear.php.net/dtd/package-2.0', 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" . "http://pear.php.net/dtd/tasks-1.0.xsd\n" . "http://pear.php.net/dtd/package-2.0\n" . 'http://pear.php.net/dtd/package-2.0.xsd', ), 'name' => $this->_packagefile->getPackage(), 'channel' => 'pear.php.net', ); $arr['summary'] = $this->_packagefile->getSummary(); $arr['description'] = $this->_packagefile->getDescription(); $maintainers = $this->_packagefile->getMaintainers(); foreach ($maintainers as $maintainer) { if ($maintainer['role'] != 'lead') { continue; } $new = array( 'name' => $maintainer['name'], 'user' => $maintainer['handle'], 'email' => $maintainer['email'], 'active' => 'yes', ); $arr['lead'][] = $new; } if (!isset($arr['lead'])) { // some people... you know? $arr['lead'] = array( 'name' => 'unknown', 'user' => 'unknown', 'email' => 'noleadmaintainer@example.com', 'active' => 'no', ); } if (count($arr['lead']) == 1) { $arr['lead'] = $arr['lead'][0]; } foreach ($maintainers as $maintainer) { if ($maintainer['role'] == 'lead') { continue; } $new = array( 'name' => $maintainer['name'], 'user' => $maintainer['handle'], 'email' => $maintainer['email'], 'active' => 'yes', ); $arr[$maintainer['role']][] = $new; } if (isset($arr['developer']) && count($arr['developer']) == 1) { $arr['developer'] = $arr['developer'][0]; } if (isset($arr['contributor']) && count($arr['contributor']) == 1) { $arr['contributor'] = $arr['contributor'][0]; } if (isset($arr['helper']) && count($arr['helper']) == 1) { $arr['helper'] = $arr['helper'][0]; } $arr['date'] = $this->_packagefile->getDate(); $arr['version'] = array( 'release' => $this->_packagefile->getVersion(), 'api' => $this->_packagefile->getVersion(), ); $arr['stability'] = array( 'release' => $this->_packagefile->getState(), 'api' => $this->_packagefile->getState(), ); $licensemap = array( 'php' => 'http://www.php.net/license', 'php license' => 'http://www.php.net/license', 'lgpl' => 'http://www.gnu.org/copyleft/lesser.html', 'bsd' => 'http://www.opensource.org/licenses/bsd-license.php', 'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php', 'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php', 'mit' => 'http://www.opensource.org/licenses/mit-license.php', 'gpl' => 'http://www.gnu.org/copyleft/gpl.html', 'apache' => 'http://www.opensource.org/licenses/apache2.0.php' ); if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) { $arr['license'] = array( 'attribs' => array('uri' => $licensemap[strtolower($this->_packagefile->getLicense())]), '_content' => $this->_packagefile->getLicense() ); } else { // don't use bogus uri $arr['license'] = $this->_packagefile->getLicense(); } $arr['notes'] = $this->_packagefile->getNotes(); $temp = array(); $arr['contents'] = $this->_convertFilelist2_0($temp); $this->_convertDependencies2_0($arr); $release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ? 'extsrcrelease' : 'phprelease'; if ($release == 'extsrcrelease') { $arr['channel'] = 'pecl.php.net'; $arr['providesextension'] = $arr['name']; // assumption } $arr[$release] = array(); if ($this->_packagefile->getConfigureOptions()) { $arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions(); foreach ($arr[$release]['configureoption'] as $i => $opt) { $arr[$release]['configureoption'][$i] = array('attribs' => $opt); } if (count($arr[$release]['configureoption']) == 1) { $arr[$release]['configureoption'] = $arr[$release]['configureoption'][0]; } } $this->_convertRelease2_0($arr[$release], $temp); if ($release == 'extsrcrelease' && count($arr[$release]) > 1) { // multiple extsrcrelease tags added in PEAR 1.4.1 $arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1'; } if ($cl = $this->_packagefile->getChangelog()) { foreach ($cl as $release) { $rel = array(); $rel['version'] = array( 'release' => $release['version'], 'api' => $release['version'], ); if (!isset($release['release_state'])) { $release['release_state'] = 'stable'; } $rel['stability'] = array( 'release' => $release['release_state'], 'api' => $release['release_state'], ); if (isset($release['release_date'])) { $rel['date'] = $release['release_date']; } else { $rel['date'] = date('Y-m-d'); } if (isset($release['release_license'])) { if (isset($licensemap[strtolower($release['release_license'])])) { $uri = $licensemap[strtolower($release['release_license'])]; } else { $uri = 'http://www.example.com'; } $rel['license'] = array( 'attribs' => array('uri' => $uri), '_content' => $release['release_license'] ); } else { $rel['license'] = $arr['license']; } if (!isset($release['release_notes'])) { $release['release_notes'] = 'no release notes'; } $rel['notes'] = $release['release_notes']; $arr['changelog']['release'][] = $rel; } } $ret = new $class; $ret->setConfig($this->_packagefile->_config); if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) { $ret->setLogger($this->_packagefile->_logger); } $ret->fromArray($arr); return $ret; } /** * @param array * @param bool * @access private */ function _convertDependencies2_0(&$release, $internal = false) { $peardep = array('pearinstaller' => array('min' => '1.4.0b1')); // this is a lot safer $required = $optional = array(); $release['dependencies'] = array('required' => array()); if ($this->_packagefile->hasDeps()) { foreach ($this->_packagefile->getDeps() as $dep) { if (!isset($dep['optional']) || $dep['optional'] == 'no') { $required[] = $dep; } else { $optional[] = $dep; } } foreach (array('required', 'optional') as $arr) { $deps = array(); foreach ($$arr as $dep) { // organize deps by dependency type and name if (!isset($deps[$dep['type']])) { $deps[$dep['type']] = array(); } if (isset($dep['name'])) { $deps[$dep['type']][$dep['name']][] = $dep; } else { $deps[$dep['type']][] = $dep; } } do { if (isset($deps['php'])) { $php = array(); if (count($deps['php']) > 1) { $php = $this->_processPhpDeps($deps['php']); } else { if (!isset($deps['php'][0])) { // Buggy versions $key = key($deps['php']); $info = current($deps['php']); $deps['php'] = array($info[0]); } $php = $this->_processDep($deps['php'][0]); if (!$php) { break; // poor mans throw } } $release['dependencies'][$arr]['php'] = $php; } } while (false); do { if (isset($deps['pkg'])) { $pkg = array(); $pkg = $this->_processMultipleDepsName($deps['pkg']); if (!$pkg) { break; // poor mans throw } $release['dependencies'][$arr]['package'] = $pkg; } } while (false); do { if (isset($deps['ext'])) { $pkg = array(); $pkg = $this->_processMultipleDepsName($deps['ext']); $release['dependencies'][$arr]['extension'] = $pkg; } } while (false); // skip sapi - it's not supported so nobody will have used it // skip os - it's not supported in 1.0 } } if (isset($release['dependencies']['required'])) { $release['dependencies']['required'] = array_merge($peardep, $release['dependencies']['required']); } else { $release['dependencies']['required'] = $peardep; } if (!isset($release['dependencies']['required']['php'])) { $release['dependencies']['required']['php'] = array('min' => '4.0.0'); } $order = array(); $bewm = $release['dependencies']['required']; $order['php'] = $bewm['php']; $order['pearinstaller'] = $bewm['pearinstaller']; isset($bewm['package']) ? $order['package'] = $bewm['package'] :0; isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0; $release['dependencies']['required'] = $order; } /** * @param array * @access private */ function _convertFilelist2_0(&$package) { $ret = array('dir' => array( 'attribs' => array('name' => '/'), 'file' => array() ) ); $package['platform'] = $package['install-as'] = array(); $this->_isExtension = false; foreach ($this->_packagefile->getFilelist() as $name => $file) { $file['name'] = $name; if (isset($file['role']) && $file['role'] == 'src') { $this->_isExtension = true; } if (isset($file['replacements'])) { $repl = $file['replacements']; unset($file['replacements']); } else { unset($repl); } if (isset($file['install-as'])) { $package['install-as'][$name] = $file['install-as']; unset($file['install-as']); } if (isset($file['platform'])) { $package['platform'][$name] = $file['platform']; unset($file['platform']); } $file = array('attribs' => $file); if (isset($repl)) { foreach ($repl as $replace ) { $file['tasks:replace'][] = array('attribs' => $replace); } if (count($repl) == 1) { $file['tasks:replace'] = $file['tasks:replace'][0]; } } $ret['dir']['file'][] = $file; } return $ret; } /** * Post-process special files with install-as/platform attributes and * make the release tag. * * This complex method follows this work-flow to create the release tags: * *
     * - if any install-as/platform exist, create a generic release and fill it with
     *   o  tags for 
     *   o  tags for 
     *   o  tags for 
     *   o  tags for 
     * - create a release for each platform encountered and fill with
     *   o  tags for 
     *   o  tags for 
     *   o  tags for 
     *   o  tags for 
     *   o  tags for 
     *   o  tags for 
     *   o  tags for 
     * 
* * It does this by accessing the $package parameter, which contains an array with * indices: * * - platform: mapping of file => OS the file should be installed on * - install-as: mapping of file => installed name * - osmap: mapping of OS => list of files that should be installed * on that OS * - notosmap: mapping of OS => list of files that should not be * installed on that OS * * @param array * @param array * @access private */ function _convertRelease2_0(&$release, $package) { //- if any install-as/platform exist, create a generic release and fill it with if (count($package['platform']) || count($package['install-as'])) { $generic = array(); $genericIgnore = array(); foreach ($package['install-as'] as $file => $as) { //o tags for if (!isset($package['platform'][$file])) { $generic[] = $file; continue; } //o tags for if (isset($package['platform'][$file]) && $package['platform'][$file][0] == '!') { $generic[] = $file; continue; } //o tags for if (isset($package['platform'][$file]) && $package['platform'][$file][0] != '!') { $genericIgnore[] = $file; continue; } } foreach ($package['platform'] as $file => $platform) { if (isset($package['install-as'][$file])) { continue; } if ($platform[0] != '!') { //o tags for $genericIgnore[] = $file; } } if (count($package['platform'])) { $oses = $notplatform = $platform = array(); foreach ($package['platform'] as $file => $os) { // get a list of oses if ($os[0] == '!') { if (isset($oses[substr($os, 1)])) { continue; } $oses[substr($os, 1)] = count($oses); } else { if (isset($oses[$os])) { continue; } $oses[$os] = count($oses); } } //- create a release for each platform encountered and fill with foreach ($oses as $os => $releaseNum) { $release[$releaseNum]['installconditions']['os']['name'] = $os; $release[$releaseNum]['filelist'] = array('install' => array(), 'ignore' => array()); foreach ($package['install-as'] as $file => $as) { //o tags for if (!isset($package['platform'][$file])) { $release[$releaseNum]['filelist']['install'][] = array( 'attribs' => array( 'name' => $file, 'as' => $as, ), ); continue; } //o tags for // if (isset($package['platform'][$file]) && $package['platform'][$file] == $os) { $release[$releaseNum]['filelist']['install'][] = array( 'attribs' => array( 'name' => $file, 'as' => $as, ), ); continue; } //o tags for // if (isset($package['platform'][$file]) && $package['platform'][$file] != "!$os" && $package['platform'][$file][0] == '!') { $release[$releaseNum]['filelist']['install'][] = array( 'attribs' => array( 'name' => $file, 'as' => $as, ), ); continue; } //o tags for // if (isset($package['platform'][$file]) && $package['platform'][$file] == "!$os") { $release[$releaseNum]['filelist']['ignore'][] = array( 'attribs' => array( 'name' => $file, ), ); continue; } //o tags for // if (isset($package['platform'][$file]) && $package['platform'][$file][0] != '!' && $package['platform'][$file] != $os) { $release[$releaseNum]['filelist']['ignore'][] = array( 'attribs' => array( 'name' => $file, ), ); continue; } } foreach ($package['platform'] as $file => $platform) { if (isset($package['install-as'][$file])) { continue; } //o tags for if ($platform == "!$os") { $release[$releaseNum]['filelist']['ignore'][] = array( 'attribs' => array( 'name' => $file, ), ); continue; } //o tags for if ($platform[0] != '!' && $platform != $os) { $release[$releaseNum]['filelist']['ignore'][] = array( 'attribs' => array( 'name' => $file, ), ); } } if (!count($release[$releaseNum]['filelist']['install'])) { unset($release[$releaseNum]['filelist']['install']); } if (!count($release[$releaseNum]['filelist']['ignore'])) { unset($release[$releaseNum]['filelist']['ignore']); } } if (count($generic) || count($genericIgnore)) { $release[count($oses)] = array(); if (count($generic)) { foreach ($generic as $file) { if (isset($package['install-as'][$file])) { $installas = $package['install-as'][$file]; } else { $installas = $file; } $release[count($oses)]['filelist']['install'][] = array( 'attribs' => array( 'name' => $file, 'as' => $installas, ) ); } } if (count($genericIgnore)) { foreach ($genericIgnore as $file) { $release[count($oses)]['filelist']['ignore'][] = array( 'attribs' => array( 'name' => $file, ) ); } } } // cleanup foreach ($release as $i => $rel) { if (isset($rel['filelist']['install']) && count($rel['filelist']['install']) == 1) { $release[$i]['filelist']['install'] = $release[$i]['filelist']['install'][0]; } if (isset($rel['filelist']['ignore']) && count($rel['filelist']['ignore']) == 1) { $release[$i]['filelist']['ignore'] = $release[$i]['filelist']['ignore'][0]; } } if (count($release) == 1) { $release = $release[0]; } } else { // no platform atts, but some install-as atts foreach ($package['install-as'] as $file => $value) { $release['filelist']['install'][] = array( 'attribs' => array( 'name' => $file, 'as' => $value ) ); } if (count($release['filelist']['install']) == 1) { $release['filelist']['install'] = $release['filelist']['install'][0]; } } } } /** * @param array * @return array * @access private */ function _processDep($dep) { if ($dep['type'] == 'php') { if ($dep['rel'] == 'has') { // come on - everyone has php! return false; } } $php = array(); if ($dep['type'] != 'php') { $php['name'] = $dep['name']; if ($dep['type'] == 'pkg') { $php['channel'] = 'pear.php.net'; } } switch ($dep['rel']) { case 'gt' : $php['min'] = $dep['version']; $php['exclude'] = $dep['version']; break; case 'ge' : if (!isset($dep['version'])) { if ($dep['type'] == 'php') { if (isset($dep['name'])) { $dep['version'] = $dep['name']; } } } $php['min'] = $dep['version']; break; case 'lt' : $php['max'] = $dep['version']; $php['exclude'] = $dep['version']; break; case 'le' : $php['max'] = $dep['version']; break; case 'eq' : $php['min'] = $dep['version']; $php['max'] = $dep['version']; break; case 'ne' : $php['exclude'] = $dep['version']; break; case 'not' : $php['conflicts'] = 'yes'; break; } return $php; } /** * @param array * @return array */ function _processPhpDeps($deps) { $test = array(); foreach ($deps as $dep) { $test[] = $this->_processDep($dep); } $min = array(); $max = array(); foreach ($test as $dep) { if (!$dep) { continue; } if (isset($dep['min'])) { $min[$dep['min']] = count($min); } if (isset($dep['max'])) { $max[$dep['max']] = count($max); } } if (count($min) > 0) { uksort($min, 'version_compare'); } if (count($max) > 0) { uksort($max, 'version_compare'); } if (count($min)) { // get the highest minimum $a = array_flip($min); $min = array_pop($a); } else { $min = false; } if (count($max)) { // get the lowest maximum $a = array_flip($max); $max = array_shift($a); } else { $max = false; } if ($min) { $php['min'] = $min; } if ($max) { $php['max'] = $max; } $exclude = array(); foreach ($test as $dep) { if (!isset($dep['exclude'])) { continue; } $exclude[] = $dep['exclude']; } if (count($exclude)) { $php['exclude'] = $exclude; } return $php; } /** * process multiple dependencies that have a name, like package deps * @param array * @return array * @access private */ function _processMultipleDepsName($deps) { $ret = $tests = array(); foreach ($deps as $name => $dep) { foreach ($dep as $d) { $tests[$name][] = $this->_processDep($d); } } foreach ($tests as $name => $test) { $max = $min = $php = array(); $php['name'] = $name; foreach ($test as $dep) { if (!$dep) { continue; } if (isset($dep['channel'])) { $php['channel'] = 'pear.php.net'; } if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') { $php['conflicts'] = 'yes'; } if (isset($dep['min'])) { $min[$dep['min']] = count($min); } if (isset($dep['max'])) { $max[$dep['max']] = count($max); } } if (count($min) > 0) { uksort($min, 'version_compare'); } if (count($max) > 0) { uksort($max, 'version_compare'); } if (count($min)) { // get the highest minimum $a = array_flip($min); $min = array_pop($a); } else { $min = false; } if (count($max)) { // get the lowest maximum $a = array_flip($max); $max = array_shift($a); } else { $max = false; } if ($min) { $php['min'] = $min; } if ($max) { $php['max'] = $max; } $exclude = array(); foreach ($test as $dep) { if (!isset($dep['exclude'])) { continue; } $exclude[] = $dep['exclude']; } if (count($exclude)) { $php['exclude'] = $exclude; } $ret[] = $php; } return $ret; } } ?> PK!OWH H PEAR/PackageFile/Parser/v2.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * base xml parser class */ require_once 'PEAR/XMLParser.php'; require_once 'PEAR/PackageFile/v2.php'; /** * Parser for package.xml version 2.0 * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: @PEAR-VER@ * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser { var $_config; var $_logger; var $_registry; function setConfig(&$c) { $this->_config = &$c; $this->_registry = &$c->getRegistry(); } function setLogger(&$l) { $this->_logger = &$l; } /** * Unindent given string * * @param string $str The string that has to be unindented. * @return string * @access private */ function _unIndent($str) { // remove leading newlines $str = preg_replace('/^[\r\n]+/', '', $str); // find whitespace at the beginning of the first line $indent_len = strspn($str, " \t"); $indent = substr($str, 0, $indent_len); $data = ''; // remove the same amount of whitespace from following lines foreach (explode("\n", $str) as $line) { if (substr($line, 0, $indent_len) == $indent) { $data .= substr($line, $indent_len) . "\n"; } else { $data .= $line . "\n"; } } return $data; } /** * post-process data * * @param string $data * @param string $element element name */ function postProcess($data, $element) { if ($element == 'notes') { return trim($this->_unIndent($data)); } return trim($data); } /** * @param string * @param string file name of the package.xml * @param string|false name of the archive this package.xml came from, if any * @param string class name to instantiate and return. This must be PEAR_PackageFile_v2 or * a subclass * @return PEAR_PackageFile_v2 */ function parse($data, $file = null, $archive = false, $class = 'PEAR_PackageFile_v2') { if (PEAR::isError($err = parent::parse($data))) { return $err; } $ret = new $class; $ret->encoding = $this->encoding; $ret->setConfig($this->_config); if (isset($this->_logger)) { $ret->setLogger($this->_logger); } $ret->fromArray($this->_unserializedData); $ret->setPackagefile($file, $archive); return $ret; } }PK!_=@@PEAR/PackageFile/Parser/v1.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * package.xml abstraction class */ require_once 'PEAR/PackageFile/v1.php'; /** * Parser for package.xml version 1.0 * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: @PEAR-VER@ * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_PackageFile_Parser_v1 { var $_registry; var $_config; var $_logger; /** * BC hack to allow PEAR_Common::infoFromString() to sort of * work with the version 2.0 format - there's no filelist though * @param PEAR_PackageFile_v2 */ function fromV2($packagefile) { $info = $packagefile->getArray(true); $ret = new PEAR_PackageFile_v1; $ret->fromArray($info['old']); } function setConfig(&$c) { $this->_config = &$c; $this->_registry = &$c->getRegistry(); } function setLogger(&$l) { $this->_logger = &$l; } /** * @param string contents of package.xml file, version 1.0 * @return bool success of parsing */ function &parse($data, $file, $archive = false) { if (!extension_loaded('xml')) { return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension'); } $xp = xml_parser_create(); if (!$xp) { $a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml'); return $a; } xml_set_object($xp, $this); xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0'); xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0'); xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false); $this->element_stack = array(); $this->_packageInfo = array('provides' => array()); $this->current_element = false; unset($this->dir_install); $this->_packageInfo['filelist'] = array(); $this->filelist =& $this->_packageInfo['filelist']; $this->dir_names = array(); $this->in_changelog = false; $this->d_i = 0; $this->cdata = ''; $this->_isValid = true; if (!xml_parse($xp, $data, 1)) { $code = xml_get_error_code($xp); $line = xml_get_current_line_number($xp); xml_parser_free($xp); $a = PEAR::raiseError(sprintf("XML error: %s at line %d", $str = xml_error_string($code), $line), 2); return $a; } xml_parser_free($xp); $pf = new PEAR_PackageFile_v1; $pf->setConfig($this->_config); if (isset($this->_logger)) { $pf->setLogger($this->_logger); } $pf->setPackagefile($file, $archive); $pf->fromArray($this->_packageInfo); return $pf; } // {{{ _unIndent() /** * Unindent given string * * @param string $str The string that has to be unindented. * @return string * @access private */ function _unIndent($str) { // remove leading newlines $str = preg_replace('/^[\r\n]+/', '', $str); // find whitespace at the beginning of the first line $indent_len = strspn($str, " \t"); $indent = substr($str, 0, $indent_len); $data = ''; // remove the same amount of whitespace from following lines foreach (explode("\n", $str) as $line) { if (substr($line, 0, $indent_len) == $indent) { $data .= substr($line, $indent_len) . "\n"; } elseif (trim(substr($line, 0, $indent_len))) { $data .= ltrim($line); } } return $data; } // Support for package DTD v1.0: // {{{ _element_start_1_0() /** * XML parser callback for ending elements. Used for version 1.0 * packages. * * @param resource $xp XML parser resource * @param string $name name of ending element * * @return void * * @access private */ function _element_start_1_0($xp, $name, $attribs) { array_push($this->element_stack, $name); $this->current_element = $name; $spos = sizeof($this->element_stack) - 2; $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : ''; $this->current_attributes = $attribs; $this->cdata = ''; switch ($name) { case 'dir': if ($this->in_changelog) { break; } if (array_key_exists('name', $attribs) && $attribs['name'] != '/') { $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $attribs['name']); if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) { $attribs['name'] = substr($attribs['name'], 0, strlen($attribs['name']) - 1); } if (strpos($attribs['name'], '/') === 0) { $attribs['name'] = substr($attribs['name'], 1); } $this->dir_names[] = $attribs['name']; } if (isset($attribs['baseinstalldir'])) { $this->dir_install = $attribs['baseinstalldir']; } if (isset($attribs['role'])) { $this->dir_role = $attribs['role']; } break; case 'file': if ($this->in_changelog) { break; } if (isset($attribs['name'])) { $path = ''; if (count($this->dir_names)) { foreach ($this->dir_names as $dir) { $path .= $dir . '/'; } } $path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $attribs['name']); unset($attribs['name']); $this->current_path = $path; $this->filelist[$path] = $attribs; // Set the baseinstalldir only if the file don't have this attrib if (!isset($this->filelist[$path]['baseinstalldir']) && isset($this->dir_install)) { $this->filelist[$path]['baseinstalldir'] = $this->dir_install; } // Set the Role if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) { $this->filelist[$path]['role'] = $this->dir_role; } } break; case 'replace': if (!$this->in_changelog) { $this->filelist[$this->current_path]['replacements'][] = $attribs; } break; case 'maintainers': $this->_packageInfo['maintainers'] = array(); $this->m_i = 0; // maintainers array index break; case 'maintainer': // compatibility check if (!isset($this->_packageInfo['maintainers'])) { $this->_packageInfo['maintainers'] = array(); $this->m_i = 0; } $this->_packageInfo['maintainers'][$this->m_i] = array(); $this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i]; break; case 'changelog': $this->_packageInfo['changelog'] = array(); $this->c_i = 0; // changelog array index $this->in_changelog = true; break; case 'release': if ($this->in_changelog) { $this->_packageInfo['changelog'][$this->c_i] = array(); $this->current_release = &$this->_packageInfo['changelog'][$this->c_i]; } else { $this->current_release = &$this->_packageInfo; } break; case 'deps': if (!$this->in_changelog) { $this->_packageInfo['release_deps'] = array(); } break; case 'dep': // dependencies array index if (!$this->in_changelog) { $this->d_i++; isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false; $this->_packageInfo['release_deps'][$this->d_i] = $attribs; } break; case 'configureoptions': if (!$this->in_changelog) { $this->_packageInfo['configure_options'] = array(); } break; case 'configureoption': if (!$this->in_changelog) { $this->_packageInfo['configure_options'][] = $attribs; } break; case 'provides': if (empty($attribs['type']) || empty($attribs['name'])) { break; } $attribs['explicit'] = true; $this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs; break; case 'package' : if (isset($attribs['version'])) { $this->_packageInfo['xsdversion'] = trim($attribs['version']); } else { $this->_packageInfo['xsdversion'] = '1.0'; } if (isset($attribs['packagerversion'])) { $this->_packageInfo['packagerversion'] = $attribs['packagerversion']; } break; } } // }}} // {{{ _element_end_1_0() /** * XML parser callback for ending elements. Used for version 1.0 * packages. * * @param resource $xp XML parser resource * @param string $name name of ending element * * @return void * * @access private */ function _element_end_1_0($xp, $name) { $data = trim($this->cdata); switch ($name) { case 'name': switch ($this->prev_element) { case 'package': $this->_packageInfo['package'] = $data; break; case 'maintainer': $this->current_maintainer['name'] = $data; break; } break; case 'extends' : $this->_packageInfo['extends'] = $data; break; case 'summary': $this->_packageInfo['summary'] = $data; break; case 'description': $data = $this->_unIndent($this->cdata); $this->_packageInfo['description'] = $data; break; case 'user': $this->current_maintainer['handle'] = $data; break; case 'email': $this->current_maintainer['email'] = $data; break; case 'role': $this->current_maintainer['role'] = $data; break; case 'version': if ($this->in_changelog) { $this->current_release['version'] = $data; } else { $this->_packageInfo['version'] = $data; } break; case 'date': if ($this->in_changelog) { $this->current_release['release_date'] = $data; } else { $this->_packageInfo['release_date'] = $data; } break; case 'notes': // try to "de-indent" release notes in case someone // has been over-indenting their xml ;-) // Trim only on the right side $data = rtrim($this->_unIndent($this->cdata)); if ($this->in_changelog) { $this->current_release['release_notes'] = $data; } else { $this->_packageInfo['release_notes'] = $data; } break; case 'warnings': if ($this->in_changelog) { $this->current_release['release_warnings'] = $data; } else { $this->_packageInfo['release_warnings'] = $data; } break; case 'state': if ($this->in_changelog) { $this->current_release['release_state'] = $data; } else { $this->_packageInfo['release_state'] = $data; } break; case 'license': if ($this->in_changelog) { $this->current_release['release_license'] = $data; } else { $this->_packageInfo['release_license'] = $data; } break; case 'dep': if ($data && !$this->in_changelog) { $this->_packageInfo['release_deps'][$this->d_i]['name'] = $data; } break; case 'dir': if ($this->in_changelog) { break; } array_pop($this->dir_names); break; case 'file': if ($this->in_changelog) { break; } if ($data) { $path = ''; if (count($this->dir_names)) { foreach ($this->dir_names as $dir) { $path .= $dir . '/'; } } $path .= $data; $this->filelist[$path] = $this->current_attributes; // Set the baseinstalldir only if the file don't have this attrib if (!isset($this->filelist[$path]['baseinstalldir']) && isset($this->dir_install)) { $this->filelist[$path]['baseinstalldir'] = $this->dir_install; } // Set the Role if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) { $this->filelist[$path]['role'] = $this->dir_role; } } break; case 'maintainer': if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) { $this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead'; } $this->m_i++; break; case 'release': if ($this->in_changelog) { $this->c_i++; } break; case 'changelog': $this->in_changelog = false; break; } array_pop($this->element_stack); $spos = sizeof($this->element_stack) - 1; $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : ''; $this->cdata = ''; } // }}} // {{{ _pkginfo_cdata_1_0() /** * XML parser callback for character data. Used for version 1.0 * packages. * * @param resource $xp XML parser resource * @param string $name character data * * @return void * * @access private */ function _pkginfo_cdata_1_0($xp, $data) { if (isset($this->cdata)) { $this->cdata .= $data; } } // }}} } ?>PK!c__PEAR/DependencyDB.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Needed for error handling */ require_once 'PEAR.php'; require_once 'PEAR/Config.php'; $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array(); /** * Track dependency relationships between installed packages * @category pear * @package PEAR * @author Greg Beaver * @author Tomas V.V.Cox * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_DependencyDB { // {{{ properties /** * This is initialized by {@link setConfig()} * @var PEAR_Config * @access private */ var $_config; /** * This is initialized by {@link setConfig()} * @var PEAR_Registry * @access private */ var $_registry; /** * Filename of the dependency DB (usually .depdb) * @var string * @access private */ var $_depdb = false; /** * File name of the lockfile (usually .depdblock) * @var string * @access private */ var $_lockfile = false; /** * Open file resource for locking the lockfile * @var resource|false * @access private */ var $_lockFp = false; /** * API version of this class, used to validate a file on-disk * @var string * @access private */ var $_version = '1.0'; /** * Cached dependency database file * @var array|null * @access private */ var $_cache; // }}} // {{{ & singleton() /** * Get a raw dependency database. Calls setConfig() and assertDepsDB() * @param PEAR_Config * @param string|false full path to the dependency database, or false to use default * @return PEAR_DependencyDB|PEAR_Error */ public static function &singleton(&$config, $depdb = false) { $phpdir = $config->get('php_dir', null, 'pear.php.net'); if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) { $a = new PEAR_DependencyDB; $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a; $a->setConfig($config, $depdb); $e = $a->assertDepsDB(); if (PEAR::isError($e)) { return $e; } } return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir]; } /** * Set up the registry/location of dependency DB * @param PEAR_Config|false * @param string|false full path to the dependency database, or false to use default */ function setConfig(&$config, $depdb = false) { if (!$config) { $this->_config = &PEAR_Config::singleton(); } else { $this->_config = &$config; } $this->_registry = &$this->_config->getRegistry(); if (!$depdb) { $dir = $this->_config->get('metadata_dir', null, 'pear.php.net'); if (!$dir) { $dir = $this->_config->get('php_dir', null, 'pear.php.net'); } $this->_depdb = $dir . DIRECTORY_SEPARATOR . '.depdb'; } else { $this->_depdb = $depdb; } $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock'; } // }}} function hasWriteAccess() { if (!file_exists($this->_depdb)) { $dir = $this->_depdb; while ($dir && $dir != '.') { $dir = dirname($dir); // cd .. if ($dir != '.' && file_exists($dir)) { if (is_writeable($dir)) { return true; } return false; } } return false; } return is_writeable($this->_depdb); } // {{{ assertDepsDB() /** * Create the dependency database, if it doesn't exist. Error if the database is * newer than the code reading it. * @return void|PEAR_Error */ function assertDepsDB() { if (!is_file($this->_depdb)) { $this->rebuildDB(); return; } $depdb = $this->_getDepDB(); // Datatype format has been changed, rebuild the Deps DB if ($depdb['_version'] < $this->_version) { $this->rebuildDB(); } if ($depdb['_version'][0] > $this->_version[0]) { return PEAR::raiseError('Dependency database is version ' . $depdb['_version'] . ', and we are version ' . $this->_version . ', cannot continue'); } } /** * Get a list of installed packages that depend on this package * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array * @return array|false */ function getDependentPackages(&$pkg) { $data = $this->_getDepDB(); if (is_object($pkg)) { $channel = strtolower($pkg->getChannel()); $package = strtolower($pkg->getPackage()); } else { $channel = strtolower($pkg['channel']); $package = strtolower($pkg['package']); } if (isset($data['packages'][$channel][$package])) { return $data['packages'][$channel][$package]; } return false; } /** * Get a list of the actual dependencies of installed packages that depend on * a package. * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array * @return array|false */ function getDependentPackageDependencies(&$pkg) { $data = $this->_getDepDB(); if (is_object($pkg)) { $channel = strtolower($pkg->getChannel()); $package = strtolower($pkg->getPackage()); } else if (is_array($pkg)) { $channel = strtolower($pkg['channel']); $package = strtolower($pkg['package']); } else { return false; } $depend = $this->getDependentPackages($pkg); if (!$depend) { return false; } $dependencies = array(); foreach ($depend as $info) { $temp = $this->getDependencies($info); foreach ($temp as $dep) { if ( isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) && strtolower($dep['dep']['channel']) == $channel && strtolower($dep['dep']['name']) == $package ) { if (!isset($dependencies[$info['channel']])) { $dependencies[$info['channel']] = array(); } if (!isset($dependencies[$info['channel']][$info['package']])) { $dependencies[$info['channel']][$info['package']] = array(); } $dependencies[$info['channel']][$info['package']][] = $dep; } } } return $dependencies; } /** * Get a list of dependencies of this installed package * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array * @return array|false */ function getDependencies(&$pkg) { if (is_object($pkg)) { $channel = strtolower($pkg->getChannel()); $package = strtolower($pkg->getPackage()); } else { $channel = strtolower($pkg['channel']); $package = strtolower($pkg['package']); } $data = $this->_getDepDB(); if (isset($data['dependencies'][$channel][$package])) { return $data['dependencies'][$channel][$package]; } return false; } /** * Determine whether $parent depends on $child, near or deep * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2 * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2 */ function dependsOn($parent, $child) { $c = array(); $this->_getDepDB(); return $this->_dependsOn($parent, $child, $c); } function _dependsOn($parent, $child, &$checked) { if (is_object($parent)) { $channel = strtolower($parent->getChannel()); $package = strtolower($parent->getPackage()); } else { $channel = strtolower($parent['channel']); $package = strtolower($parent['package']); } if (is_object($child)) { $depchannel = strtolower($child->getChannel()); $deppackage = strtolower($child->getPackage()); } else { $depchannel = strtolower($child['channel']); $deppackage = strtolower($child['package']); } if (isset($checked[$channel][$package][$depchannel][$deppackage])) { return false; // avoid endless recursion } $checked[$channel][$package][$depchannel][$deppackage] = true; if (!isset($this->_cache['dependencies'][$channel][$package])) { return false; } foreach ($this->_cache['dependencies'][$channel][$package] as $info) { if (isset($info['dep']['uri'])) { if (is_object($child)) { if ($info['dep']['uri'] == $child->getURI()) { return true; } } elseif (isset($child['uri'])) { if ($info['dep']['uri'] == $child['uri']) { return true; } } return false; } if (strtolower($info['dep']['channel']) == $depchannel && strtolower($info['dep']['name']) == $deppackage) { return true; } } foreach ($this->_cache['dependencies'][$channel][$package] as $info) { if (isset($info['dep']['uri'])) { if ($this->_dependsOn(array( 'uri' => $info['dep']['uri'], 'package' => $info['dep']['name']), $child, $checked)) { return true; } } else { if ($this->_dependsOn(array( 'channel' => $info['dep']['channel'], 'package' => $info['dep']['name']), $child, $checked)) { return true; } } } return false; } /** * Register dependencies of a package that is being installed or upgraded * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2 */ function installPackage(&$package) { $data = $this->_getDepDB(); unset($this->_cache); $this->_setPackageDeps($data, $package); $this->_writeDepDB($data); } /** * Remove dependencies of a package that is being uninstalled, or upgraded. * * Upgraded packages first uninstall, then install * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have * indices 'channel' and 'package' */ function uninstallPackage(&$pkg) { $data = $this->_getDepDB(); unset($this->_cache); if (is_object($pkg)) { $channel = strtolower($pkg->getChannel()); $package = strtolower($pkg->getPackage()); } else { $channel = strtolower($pkg['channel']); $package = strtolower($pkg['package']); } if (!isset($data['dependencies'][$channel][$package])) { return true; } foreach ($data['dependencies'][$channel][$package] as $dep) { $found = false; $depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']); $depname = strtolower($dep['dep']['name']); if (isset($data['packages'][$depchannel][$depname])) { foreach ($data['packages'][$depchannel][$depname] as $i => $info) { if ($info['channel'] == $channel && $info['package'] == $package) { $found = true; break; } } } if ($found) { unset($data['packages'][$depchannel][$depname][$i]); if (!count($data['packages'][$depchannel][$depname])) { unset($data['packages'][$depchannel][$depname]); if (!count($data['packages'][$depchannel])) { unset($data['packages'][$depchannel]); } } else { $data['packages'][$depchannel][$depname] = array_values($data['packages'][$depchannel][$depname]); } } } unset($data['dependencies'][$channel][$package]); if (!count($data['dependencies'][$channel])) { unset($data['dependencies'][$channel]); } if (!count($data['dependencies'])) { unset($data['dependencies']); } if (!count($data['packages'])) { unset($data['packages']); } $this->_writeDepDB($data); } /** * Rebuild the dependency DB by reading registry entries. * @return true|PEAR_Error */ function rebuildDB() { $depdb = array('_version' => $this->_version); if (!$this->hasWriteAccess()) { // allow startup for read-only with older Registry return $depdb; } $packages = $this->_registry->listAllPackages(); if (PEAR::isError($packages)) { return $packages; } foreach ($packages as $channel => $ps) { foreach ($ps as $package) { $package = $this->_registry->getPackage($package, $channel); if (PEAR::isError($package)) { return $package; } $this->_setPackageDeps($depdb, $package); } } $error = $this->_writeDepDB($depdb); if (PEAR::isError($error)) { return $error; } $this->_cache = $depdb; return true; } /** * Register usage of the dependency DB to prevent race conditions * @param int one of the LOCK_* constants * @return true|PEAR_Error * @access private */ function _lock($mode = LOCK_EX) { if (stristr(php_uname(), 'Windows 9')) { return true; } if ($mode != LOCK_UN && is_resource($this->_lockFp)) { // XXX does not check type of lock (LOCK_SH/LOCK_EX) return true; } $open_mode = 'w'; // XXX People reported problems with LOCK_SH and 'w' if ($mode === LOCK_SH) { if (!file_exists($this->_lockfile)) { touch($this->_lockfile); } elseif (!is_file($this->_lockfile)) { return PEAR::raiseError('could not create Dependency lock file, ' . 'it exists and is not a regular file'); } $open_mode = 'r'; } if (!is_resource($this->_lockFp)) { $this->_lockFp = @fopen($this->_lockfile, $open_mode); } if (!is_resource($this->_lockFp)) { $last_errormsg = ''; $last_error = error_get_last(); if (!empty($last_error['message'])) { $last_errormsg = $last_error['message']; } return PEAR::raiseError("could not create Dependency lock file" . (isset($last_errormsg) ? ": " . $last_errormsg : "")); } if (!(int)flock($this->_lockFp, $mode)) { switch ($mode) { case LOCK_SH: $str = 'shared'; break; case LOCK_EX: $str = 'exclusive'; break; case LOCK_UN: $str = 'unlock'; break; default: $str = 'unknown'; break; } return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)"); } return true; } /** * Release usage of dependency DB * @return true|PEAR_Error * @access private */ function _unlock() { $ret = $this->_lock(LOCK_UN); if (is_resource($this->_lockFp)) { fclose($this->_lockFp); } $this->_lockFp = null; return $ret; } /** * Load the dependency database from disk, or return the cache * @return array|PEAR_Error */ function _getDepDB() { if (!$this->hasWriteAccess()) { return array('_version' => $this->_version); } if (isset($this->_cache)) { return $this->_cache; } if (!$fp = fopen($this->_depdb, 'r')) { $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'"); return $err; } clearstatcache(); fclose($fp); $data = @unserialize(file_get_contents($this->_depdb)); $this->_cache = $data; return $data; } /** * Write out the dependency database to disk * @param array the database * @return true|PEAR_Error * @access private */ function _writeDepDB(&$deps) { if (PEAR::isError($e = $this->_lock(LOCK_EX))) { return $e; } if (!$fp = fopen($this->_depdb, 'wb')) { $this->_unlock(); return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing"); } fwrite($fp, serialize($deps)); fclose($fp); $this->_unlock(); $this->_cache = $deps; return true; } /** * Register all dependencies from a package in the dependencies database, in essence * "installing" the package's dependency information * @param array the database * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @access private */ function _setPackageDeps(&$data, &$pkg) { $pkg->setConfig($this->_config); if ($pkg->getPackagexmlVersion() == '1.0') { $gen = &$pkg->getDefaultGenerator(); $deps = $gen->dependenciesToV2(); } else { $deps = $pkg->getDeps(true); } if (!$deps) { return; } if (!is_array($data)) { $data = array(); } if (!isset($data['dependencies'])) { $data['dependencies'] = array(); } $channel = strtolower($pkg->getChannel()); $package = strtolower($pkg->getPackage()); if (!isset($data['dependencies'][$channel])) { $data['dependencies'][$channel] = array(); } $data['dependencies'][$channel][$package] = array(); if (isset($deps['required']['package'])) { if (!isset($deps['required']['package'][0])) { $deps['required']['package'] = array($deps['required']['package']); } foreach ($deps['required']['package'] as $dep) { $this->_registerDep($data, $pkg, $dep, 'required'); } } if (isset($deps['optional']['package'])) { if (!isset($deps['optional']['package'][0])) { $deps['optional']['package'] = array($deps['optional']['package']); } foreach ($deps['optional']['package'] as $dep) { $this->_registerDep($data, $pkg, $dep, 'optional'); } } if (isset($deps['required']['subpackage'])) { if (!isset($deps['required']['subpackage'][0])) { $deps['required']['subpackage'] = array($deps['required']['subpackage']); } foreach ($deps['required']['subpackage'] as $dep) { $this->_registerDep($data, $pkg, $dep, 'required'); } } if (isset($deps['optional']['subpackage'])) { if (!isset($deps['optional']['subpackage'][0])) { $deps['optional']['subpackage'] = array($deps['optional']['subpackage']); } foreach ($deps['optional']['subpackage'] as $dep) { $this->_registerDep($data, $pkg, $dep, 'optional'); } } if (isset($deps['group'])) { if (!isset($deps['group'][0])) { $deps['group'] = array($deps['group']); } foreach ($deps['group'] as $group) { if (isset($group['package'])) { if (!isset($group['package'][0])) { $group['package'] = array($group['package']); } foreach ($group['package'] as $dep) { $this->_registerDep($data, $pkg, $dep, 'optional', $group['attribs']['name']); } } if (isset($group['subpackage'])) { if (!isset($group['subpackage'][0])) { $group['subpackage'] = array($group['subpackage']); } foreach ($group['subpackage'] as $dep) { $this->_registerDep($data, $pkg, $dep, 'optional', $group['attribs']['name']); } } } } if ($data['dependencies'][$channel][$package] == array()) { unset($data['dependencies'][$channel][$package]); if (!count($data['dependencies'][$channel])) { unset($data['dependencies'][$channel]); } } } /** * @param array the database * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @param array the specific dependency * @param required|optional whether this is a required or an optional dep * @param string|false dependency group this dependency is from, or false for ordinary dep */ function _registerDep(&$data, &$pkg, $dep, $type, $group = false) { $info = array( 'dep' => $dep, 'type' => $type, 'group' => $group ); $dep = array_map('strtolower', $dep); $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri'; if (!isset($data['dependencies'])) { $data['dependencies'] = array(); } $channel = strtolower($pkg->getChannel()); $package = strtolower($pkg->getPackage()); if (!isset($data['dependencies'][$channel])) { $data['dependencies'][$channel] = array(); } if (!isset($data['dependencies'][$channel][$package])) { $data['dependencies'][$channel][$package] = array(); } $data['dependencies'][$channel][$package][] = $info; if (isset($data['packages'][$depchannel][$dep['name']])) { $found = false; foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) { if ($p['channel'] == $channel && $p['package'] == $package) { $found = true; break; } } } else { if (!isset($data['packages'])) { $data['packages'] = array(); } if (!isset($data['packages'][$depchannel])) { $data['packages'][$depchannel] = array(); } if (!isset($data['packages'][$depchannel][$dep['name']])) { $data['packages'][$depchannel][$dep['name']] = array(); } $found = false; } if (!$found) { $data['packages'][$depchannel][$dep['name']][] = array( 'channel' => $channel, 'package' => $package ); } } } PK!@PPEAR/ChannelFile/Parser.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * base xml parser class */ require_once 'PEAR/XMLParser.php'; require_once 'PEAR/ChannelFile.php'; /** * Parser for channel.xml * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_ChannelFile_Parser extends PEAR_XMLParser { var $_config; var $_logger; var $_registry; function setConfig(&$c) { $this->_config = &$c; $this->_registry = &$c->getRegistry(); } function setLogger(&$l) { $this->_logger = &$l; } function parse($data, $file) { if (PEAR::isError($err = parent::parse($data, $file))) { return $err; } $ret = new PEAR_ChannelFile; $ret->setConfig($this->_config); if (isset($this->_logger)) { $ret->setLogger($this->_logger); } $ret->fromArray($this->_unserializedData); // make sure the filelist is in the easy to read format needed $ret->flattenFilelist(); $ret->setPackagefile($file, $archive); return $ret; } }PK!_00PEAR/Command.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * Needed for error handling */ require_once 'PEAR.php'; require_once 'PEAR/Frontend.php'; require_once 'PEAR/XMLParser.php'; /** * List of commands and what classes they are implemented in. * @var array command => implementing class */ $GLOBALS['_PEAR_Command_commandlist'] = array(); /** * List of commands and their descriptions * @var array command => description */ $GLOBALS['_PEAR_Command_commanddesc'] = array(); /** * List of shortcuts to common commands. * @var array shortcut => command */ $GLOBALS['_PEAR_Command_shortcuts'] = array(); /** * Array of command objects * @var array class => object */ $GLOBALS['_PEAR_Command_objects'] = array(); /** * PEAR command class, a simple factory class for administrative * commands. * * How to implement command classes: * * - The class must be called PEAR_Command_Nnn, installed in the * "PEAR/Common" subdir, with a method called getCommands() that * returns an array of the commands implemented by the class (see * PEAR/Command/Install.php for an example). * * - The class must implement a run() function that is called with three * params: * * (string) command name * (array) assoc array with options, freely defined by each * command, for example: * array('force' => true) * (array) list of the other parameters * * The run() function returns a PEAR_CommandResponse object. Use * these methods to get information: * * int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL) * *_PARTIAL means that you need to issue at least * one more command to complete the operation * (used for example for validation steps). * * string getMessage() Returns a message for the user. Remember, * no HTML or other interface-specific markup. * * If something unexpected happens, run() returns a PEAR error. * * - DON'T OUTPUT ANYTHING! Return text for output instead. * * - DON'T USE HTML! The text you return will be used from both Gtk, * web and command-line interfaces, so for now, keep everything to * plain text. * * - DON'T USE EXIT OR DIE! Always use pear errors. From static * classes do PEAR::raiseError(), from other classes do * $this->raiseError(). * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Command { // {{{ factory() /** * Get the right object for executing a command. * * @param string $command The name of the command * @param object $config Instance of PEAR_Config object * * @return object the command object or a PEAR error */ public static function &factory($command, &$config) { if (empty($GLOBALS['_PEAR_Command_commandlist'])) { PEAR_Command::registerCommands(); } if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; } if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { $a = PEAR::raiseError("unknown command `$command'"); return $a; } $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; if (!class_exists($class)) { require_once $GLOBALS['_PEAR_Command_objects'][$class]; } if (!class_exists($class)) { $a = PEAR::raiseError("unknown command `$command'"); return $a; } $ui =& PEAR_Command::getFrontendObject(); $obj = new $class($ui, $config); return $obj; } // }}} // {{{ & getObject() public static function &getObject($command) { $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; if (!class_exists($class)) { require_once $GLOBALS['_PEAR_Command_objects'][$class]; } if (!class_exists($class)) { return PEAR::raiseError("unknown command `$command'"); } $ui =& PEAR_Command::getFrontendObject(); $config = &PEAR_Config::singleton(); $obj = new $class($ui, $config); return $obj; } // }}} // {{{ & getFrontendObject() /** * Get instance of frontend object. * * @return object|PEAR_Error */ public static function &getFrontendObject() { $a = &PEAR_Frontend::singleton(); return $a; } // }}} // {{{ & setFrontendClass() /** * Load current frontend class. * * @param string $uiclass Name of class implementing the frontend * * @return object the frontend object, or a PEAR error */ public static function &setFrontendClass($uiclass) { $a = &PEAR_Frontend::setFrontendClass($uiclass); return $a; } // }}} // {{{ setFrontendType() /** * Set current frontend. * * @param string $uitype Name of the frontend type (for example "CLI") * * @return object the frontend object, or a PEAR error */ public static function setFrontendType($uitype) { $uiclass = 'PEAR_Frontend_' . $uitype; return PEAR_Command::setFrontendClass($uiclass); } // }}} // {{{ registerCommands() /** * Scan through the Command directory looking for classes * and see what commands they implement. * * @param bool (optional) if FALSE (default), the new list of * commands should replace the current one. If TRUE, * new entries will be merged with old. * * @param string (optional) where (what directory) to look for * classes, defaults to the Command subdirectory of * the directory from where this file (__FILE__) is * included. * * @return bool TRUE on success, a PEAR error on failure */ public static function registerCommands($merge = false, $dir = null) { $parser = new PEAR_XMLParser; if ($dir === null) { $dir = dirname(__FILE__) . '/Command'; } if (!is_dir($dir)) { return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory"); } $dp = @opendir($dir); if (empty($dp)) { return PEAR::raiseError("registerCommands: opendir($dir) failed"); } if (!$merge) { $GLOBALS['_PEAR_Command_commandlist'] = array(); } while ($file = readdir($dp)) { if ($file[0] == '.' || substr($file, -4) != '.xml') { continue; } $f = substr($file, 0, -4); $class = "PEAR_Command_" . $f; // List of commands if (empty($GLOBALS['_PEAR_Command_objects'][$class])) { $GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php'; } $parser->parse(file_get_contents("$dir/$file")); $implements = $parser->getData(); foreach ($implements as $command => $desc) { if ($command == 'attribs') { continue; } if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { return PEAR::raiseError('Command "' . $command . '" already registered in ' . 'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); } $GLOBALS['_PEAR_Command_commandlist'][$command] = $class; $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary']; if (isset($desc['shortcut'])) { $shortcut = $desc['shortcut']; if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) { return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' . 'registered to command "' . $command . '" in class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); } $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command; } if (isset($desc['options']) && $desc['options']) { foreach ($desc['options'] as $oname => $option) { if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) { return PEAR::raiseError('Option "' . $oname . '" short option "' . $option['shortopt'] . '" must be ' . 'only 1 character in Command "' . $command . '" in class "' . $class . '"'); } } } } } ksort($GLOBALS['_PEAR_Command_shortcuts']); ksort($GLOBALS['_PEAR_Command_commandlist']); @closedir($dp); return true; } // }}} // {{{ getCommands() /** * Get the list of currently supported commands, and what * classes implement them. * * @return array command => implementing class */ public static function getCommands() { if (empty($GLOBALS['_PEAR_Command_commandlist'])) { PEAR_Command::registerCommands(); } return $GLOBALS['_PEAR_Command_commandlist']; } // }}} // {{{ getShortcuts() /** * Get the list of command shortcuts. * * @return array shortcut => command */ public static function getShortcuts() { if (empty($GLOBALS['_PEAR_Command_shortcuts'])) { PEAR_Command::registerCommands(); } return $GLOBALS['_PEAR_Command_shortcuts']; } // }}} // {{{ getGetoptArgs() /** * Compiles arguments for getopt. * * @param string $command command to get optstring for * @param string $short_args (reference) short getopt format * @param array $long_args (reference) long getopt format * * @return void */ public static function getGetoptArgs($command, &$short_args, &$long_args) { if (empty($GLOBALS['_PEAR_Command_commandlist'])) { PEAR_Command::registerCommands(); } if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; } if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { return null; } $obj = &PEAR_Command::getObject($command); return $obj->getGetoptArgs($command, $short_args, $long_args); } // }}} // {{{ getDescription() /** * Get description for a command. * * @param string $command Name of the command * * @return string command description */ public static function getDescription($command) { if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) { return null; } return $GLOBALS['_PEAR_Command_commanddesc'][$command]; } // }}} // {{{ getHelp() /** * Get help for command. * * @param string $command Name of the command to return help for */ public static function getHelp($command) { $cmds = PEAR_Command::getCommands(); if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; } if (isset($cmds[$command])) { $obj = &PEAR_Command::getObject($command); return $obj->getHelp($command); } return false; } // }}} }PK!ٲ==PEAR/PackageFile.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * needed for PEAR_VALIDATE_* constants */ require_once 'PEAR/Validate.php'; /** * Error code if the package.xml tag does not contain a valid version */ define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1); /** * Error code if the package.xml tag version is not supported (version 1.0 and 1.1 are the only supported versions, * currently */ define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2); /** * Abstraction for the package.xml package description file * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_PackageFile { /** * @var PEAR_Config */ var $_config; var $_debug; var $_logger = false; /** * @var boolean */ var $_rawReturn = false; /** * helper for extracting Archive_Tar errors * @var array * @access private */ var $_extractErrors = array(); /** * * @param PEAR_Config $config * @param ? $debug * @param string @tmpdir Optional temporary directory for uncompressing * files */ function __construct(&$config, $debug = false) { $this->_config = $config; $this->_debug = $debug; } /** * Turn off validation - return a parsed package.xml without checking it * * This is used by the package-validate command */ function rawReturn() { $this->_rawReturn = true; } function setLogger(&$l) { $this->_logger = &$l; } /** * Create a PEAR_PackageFile_Parser_v* of a given version. * @param int $version * @return PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1 */ function &parserFactory($version) { if (!in_array($version[0], array('1', '2'))) { $a = false; return $a; } include_once 'PEAR/PackageFile/Parser/v' . $version[0] . '.php'; $version = $version[0]; $class = "PEAR_PackageFile_Parser_v$version"; $a = new $class; return $a; } /** * For simpler unit-testing * @return string */ function getClassPrefix() { return 'PEAR_PackageFile_v'; } /** * Create a PEAR_PackageFile_v* of a given version. * @param int $version * @return PEAR_PackageFile_v1|PEAR_PackageFile_v1 */ function &factory($version) { if (!in_array($version[0], array('1', '2'))) { $a = false; return $a; } include_once 'PEAR/PackageFile/v' . $version[0] . '.php'; $version = $version[0]; $class = $this->getClassPrefix() . $version; $a = new $class; return $a; } /** * Create a PEAR_PackageFile_v* from its toArray() method * * WARNING: no validation is performed, the array is assumed to be valid, * always parse from xml if you want validation. * @param array $arr * @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2 * @uses factory() to construct the returned object. */ function &fromArray($arr) { if (isset($arr['xsdversion'])) { $obj = &$this->factory($arr['xsdversion']); if ($this->_logger) { $obj->setLogger($this->_logger); } $obj->setConfig($this->_config); $obj->fromArray($arr); return $obj; } if (isset($arr['package']['attribs']['version'])) { $obj = &$this->factory($arr['package']['attribs']['version']); } else { $obj = &$this->factory('1.0'); } if ($this->_logger) { $obj->setLogger($this->_logger); } $obj->setConfig($this->_config); $obj->fromArray($arr); return $obj; } /** * Create a PEAR_PackageFile_v* from an XML string. * @access public * @param string $data contents of package.xml file * @param int $state package state (one of PEAR_VALIDATE_* constants) * @param string $file full path to the package.xml file (and the files * it references) * @param string $archive optional name of the archive that the XML was * extracted from, if any * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @uses parserFactory() to construct a parser to load the package. */ function &fromXmlString($data, $state, $file, $archive = false) { if (preg_match('/]+version=[\'"]([0-9]+\.[0-9]+)[\'"]/', $data, $packageversion)) { if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) { return PEAR::raiseError('package.xml version "' . $packageversion[1] . '" is not supported, only 1.0, 2.0, and 2.1 are supported.'); } $object = &$this->parserFactory($packageversion[1]); if ($this->_logger) { $object->setLogger($this->_logger); } $object->setConfig($this->_config); $pf = $object->parse($data, $file, $archive); if (PEAR::isError($pf)) { return $pf; } if ($this->_rawReturn) { return $pf; } if (!$pf->validate($state)) {; if ($this->_config->get('verbose') > 0 && $this->_logger && $pf->getValidationWarnings(false) ) { foreach ($pf->getValidationWarnings(false) as $warning) { $this->_logger->log(0, 'ERROR: ' . $warning['message']); } } $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed', 2, null, null, $pf->getValidationWarnings()); return $a; } if ($this->_logger && $pf->getValidationWarnings(false)) { foreach ($pf->getValidationWarnings() as $warning) { $this->_logger->log(0, 'WARNING: ' . $warning['message']); } } if (method_exists($pf, 'flattenFilelist')) { $pf->flattenFilelist(); // for v2 } return $pf; } elseif (preg_match('/]+version=[\'"]([^"\']+)[\'"]/', $data, $packageversion)) { $a = PEAR::raiseError('package.xml file "' . $file . '" has unsupported package.xml version "' . $packageversion[1] . '"'); return $a; } else { if (!class_exists('PEAR_ErrorStack')) { require_once 'PEAR/ErrorStack.php'; } PEAR_ErrorStack::staticPush('PEAR_PackageFile', PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION, 'warning', array('xml' => $data), 'package.xml "' . $file . '" has no package.xml version'); $object = &$this->parserFactory('1.0'); $object->setConfig($this->_config); $pf = $object->parse($data, $file, $archive); if (PEAR::isError($pf)) { return $pf; } if ($this->_rawReturn) { return $pf; } if (!$pf->validate($state)) { $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed', 2, null, null, $pf->getValidationWarnings()); return $a; } if ($this->_logger && $pf->getValidationWarnings(false)) { foreach ($pf->getValidationWarnings() as $warning) { $this->_logger->log(0, 'WARNING: ' . $warning['message']); } } if (method_exists($pf, 'flattenFilelist')) { $pf->flattenFilelist(); // for v2 } return $pf; } } /** * Register a temporary file or directory. When the destructor is * executed, all registered temporary files and directories are * removed. * * @param string $file name of file or directory * @return void */ static function addTempFile($file) { $GLOBALS['_PEAR_Common_tempfiles'][] = $file; } /** * Create a PEAR_PackageFile_v* from a compressed Tar or Tgz file. * @access public * @param string contents of package.xml file * @param int package state (one of PEAR_VALIDATE_* constants) * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @using Archive_Tar to extract the files * @using fromPackageFile() to load the package after the package.xml * file is extracted. */ function &fromTgzFile($file, $state) { if (!class_exists('Archive_Tar')) { require_once 'Archive/Tar.php'; } $tar = new Archive_Tar($file); if ($this->_debug <= 1) { $tar->pushErrorHandling(PEAR_ERROR_RETURN); } $content = $tar->listContent(); if ($this->_debug <= 1) { $tar->popErrorHandling(); } if (!is_array($content)) { if (is_string($file) && strlen($file) < 255 && (!file_exists($file) || !@is_file($file))) { $ret = PEAR::raiseError("could not open file \"$file\""); return $ret; } $file = realpath($file); $ret = PEAR::raiseError("Could not get contents of package \"$file\"". '. Invalid tgz file.'); return $ret; } if (!count($content) && !@is_file($file)) { $ret = PEAR::raiseError("could not open file \"$file\""); return $ret; } $xml = null; $origfile = $file; foreach ($content as $file) { $name = $file['filename']; if ($name == 'package2.xml') { // allow a .tgz to distribute both versions $xml = $name; break; } if ($name == 'package.xml') { $xml = $name; break; } elseif (preg_match('/package.xml$/', $name, $match)) { $xml = $name; break; } } $tmpdir = System::mktemp('-t "' . $this->_config->get('temp_dir') . '" -d pear'); if ($tmpdir === false) { $ret = PEAR::raiseError("there was a problem with getting the configured temp directory"); return $ret; } PEAR_PackageFile::addTempFile($tmpdir); $this->_extractErrors(); PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors')); if (!$xml || !$tar->extractList(array($xml), $tmpdir)) { $extra = implode("\n", $this->_extractErrors()); if ($extra) { $extra = ' ' . $extra; } PEAR::staticPopErrorHandling(); $ret = PEAR::raiseError('could not extract the package.xml file from "' . $origfile . '"' . $extra); return $ret; } PEAR::staticPopErrorHandling(); $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile); return $ret; } /** * helper callback for extracting Archive_Tar errors * * @param PEAR_Error|null $err * @return array * @access private */ function _extractErrors($err = null) { static $errors = array(); if ($err === null) { $e = $errors; $errors = array(); return $e; } $errors[] = $err->getMessage(); } /** * Create a PEAR_PackageFile_v* from a package.xml file. * * @access public * @param string $descfile name of package xml file * @param int $state package state (one of PEAR_VALIDATE_* constants) * @param string|false $archive name of the archive this package.xml came * from, if any * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @uses PEAR_PackageFile::fromXmlString to create the oject after the * XML is loaded from the package.xml file. */ function &fromPackageFile($descfile, $state, $archive = false) { $fp = false; if (is_string($descfile) && strlen($descfile) < 255 && ( !file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) || (!$fp = @fopen($descfile, 'r')) ) ) { $a = PEAR::raiseError("Unable to open $descfile"); return $a; } // read the whole thing so we only get one cdata callback // for each block of cdata fclose($fp); $data = file_get_contents($descfile); $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive); return $ret; } /** * Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file. * * This method is able to extract information about a package from a .tgz * archive or from a XML package definition file. * * @access public * @param string $info file name * @param int $state package state (one of PEAR_VALIDATE_* constants) * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @uses fromPackageFile() if the file appears to be XML * @uses fromTgzFile() to load all non-XML files */ function &fromAnyFile($info, $state) { if (is_dir($info)) { $dir_name = realpath($info); if (file_exists($dir_name . '/package.xml')) { $info = PEAR_PackageFile::fromPackageFile($dir_name . '/package.xml', $state); } elseif (file_exists($dir_name . '/package2.xml')) { $info = PEAR_PackageFile::fromPackageFile($dir_name . '/package2.xml', $state); } else { $info = PEAR::raiseError("No package definition found in '$info' directory"); } return $info; } $fp = false; if (is_string($info) && strlen($info) < 255 && (file_exists($info) || ($fp = @fopen($info, 'r'))) ) { if ($fp) { fclose($fp); } $tmp = substr($info, -4); if ($tmp == '.xml') { $info = &PEAR_PackageFile::fromPackageFile($info, $state); } elseif ($tmp == '.tar' || $tmp == '.tgz') { $info = &PEAR_PackageFile::fromTgzFile($info, $state); } else { $fp = fopen($info, 'r'); $test = fread($fp, 5); fclose($fp); if ($test == ' * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Base class */ require_once 'PEAR/Task/Common.php'; /** * Implements the replace file task. * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Task_Replace extends PEAR_Task_Common { public $type = 'simple'; public $phase = PEAR_TASK_PACKAGEANDINSTALL; public $_replacements; /** * Validate the raw xml at parsing-time. * * @param PEAR_PackageFile_v2 * @param array raw, parsed xml * @param PEAR_Config */ public static function validateXml($pkg, $xml, $config, $fileXml) { if (!isset($xml['attribs'])) { return array(PEAR_TASK_ERROR_NOATTRIBS); } if (!isset($xml['attribs']['type'])) { return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type'); } if (!isset($xml['attribs']['to'])) { return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to'); } if (!isset($xml['attribs']['from'])) { return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from'); } if ($xml['attribs']['type'] == 'pear-config') { if (!in_array($xml['attribs']['to'], $config->getKeys())) { return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'], $config->getKeys(), ); } } elseif ($xml['attribs']['type'] == 'php-const') { if (defined($xml['attribs']['to'])) { return true; } else { return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'], array('valid PHP constant'), ); } } elseif ($xml['attribs']['type'] == 'package-info') { if (in_array( $xml['attribs']['to'], array('name', 'summary', 'channel', 'notes', 'extends', 'description', 'release_notes', 'license', 'release-license', 'license-uri', 'version', 'api-version', 'state', 'api-state', 'release_date', 'date', 'time', ) )) { return true; } else { return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'], array('name', 'summary', 'channel', 'notes', 'extends', 'description', 'release_notes', 'license', 'release-license', 'license-uri', 'version', 'api-version', 'state', 'api-state', 'release_date', 'date', 'time', ), ); } } else { return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'], array('pear-config', 'package-info', 'php-const'), ); } return true; } /** * Initialize a task instance with the parameters * @param array raw, parsed xml * @param unused * @param unused */ public function init($xml, $attribs, $lastVersion = null) { $this->_replacements = isset($xml['attribs']) ? array($xml) : $xml; } /** * Do a package.xml 1.0 replacement, with additional package-info fields available * * See validateXml() source for the complete list of allowed fields * * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @param string file contents * @param string the eventual final file location (informational only) * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail * (use $this->throwError), otherwise return the new contents */ public function startSession($pkg, $contents, $dest) { $subst_from = $subst_to = array(); foreach ($this->_replacements as $a) { $a = $a['attribs']; $to = ''; if ($a['type'] == 'pear-config') { if ($this->installphase == PEAR_TASK_PACKAGE) { return false; } if ($a['to'] == 'master_server') { $chan = $this->registry->getChannel($pkg->getChannel()); if (!PEAR::isError($chan)) { $to = $chan->getServer(); } else { $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]"); return false; } } else { if ($this->config->isDefinedLayer('ftp')) { // try the remote config file first $to = $this->config->get($a['to'], 'ftp', $pkg->getChannel()); if (is_null($to)) { // then default to local $to = $this->config->get($a['to'], null, $pkg->getChannel()); } } else { $to = $this->config->get($a['to'], null, $pkg->getChannel()); } } if (is_null($to)) { $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]"); return false; } } elseif ($a['type'] == 'php-const') { if ($this->installphase == PEAR_TASK_PACKAGE) { return false; } if (defined($a['to'])) { $to = constant($a['to']); } else { $this->logger->log(0, "$dest: invalid php-const replacement: $a[to]"); return false; } } else { if ($t = $pkg->packageInfo($a['to'])) { $to = $t; } else { $this->logger->log(0, "$dest: invalid package-info replacement: $a[to]"); return false; } } if (!is_null($to)) { $subst_from[] = $a['from']; $subst_to[] = $to; } } $this->logger->log( 3, "doing ".sizeof($subst_from). " substitution(s) for $dest" ); if (sizeof($subst_from)) { $contents = str_replace($subst_from, $subst_to, $contents); } return $contents; } } PK!&%75))PEAR/Task/Windowseol/rw.phpnu[ - read/write version * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a10 */ /** * Base class */ require_once 'PEAR/Task/Windowseol.php'; /** * Abstracts the windowseol task xml. * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol { function __construct(&$pkg, &$config, &$logger, $fileXml) { parent::__construct($config, $logger, PEAR_TASK_PACKAGE); $this->_contents = $fileXml; $this->_pkg = &$pkg; $this->_params = array(); } public function validate() { return true; } public function getName() { return 'windowseol'; } public function getXml() { return ''; } } ?> PK!3}PEAR/Task/Replace/rw.phpnu[ - read/write version * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a10 */ /** * Base class */ require_once 'PEAR/Task/Replace.php'; /** * Abstracts the replace task xml. * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ class PEAR_Task_Replace_rw extends PEAR_Task_Replace { public function __construct(&$pkg, &$config, &$logger, $fileXml) { parent::__construct($config, $logger, PEAR_TASK_PACKAGE); $this->_contents = $fileXml; $this->_pkg = &$pkg; $this->_params = array(); } public function validate() { return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents); } public function setInfo($from, $to, $type) { $this->_params = array('attribs' => array('from' => $from, 'to' => $to, 'type' => $type)); } public function getName() { return 'replace'; } public function getXml() { return $this->_params; } } PK!& i."PEAR/Task/Postinstallscript/rw.phpnu[ - read/write version * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a10 */ /** * Base class */ require_once 'PEAR/Task/Postinstallscript.php'; /** * Abstracts the postinstallscript file task xml. * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript { /** * parent package file object * * @var PEAR_PackageFile_v2_rw */ public $_pkg; /** * Enter description here... * * @param PEAR_PackageFile_v2_rw $pkg Package * @param PEAR_Config $config Config * @param PEAR_Frontend $logger Logger * @param array $fileXml XML * * @return PEAR_Task_Postinstallscript_rw */ function __construct(&$pkg, &$config, &$logger, $fileXml) { parent::__construct($config, $logger, PEAR_TASK_PACKAGE); $this->_contents = $fileXml; $this->_pkg = &$pkg; $this->_params = array(); } public function validate() { return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents); } public function getName() { return 'postinstallscript'; } /** * add a simple to the post-install script * * Order is significant, so call this method in the same * sequence the users should see the paramgroups. The $params * parameter should either be the result of a call to {@link getParam()} * or an array of calls to getParam(). * * Use {@link addConditionTypeGroup()} to add a containing * a tag * * @param string $id id as seen by the script * @param array|false $params array of getParam() calls, or false for no params * @param string|false $instructions */ public function addParamGroup($id, $params = false, $instructions = false) { if ($params && isset($params[0]) && !isset($params[1])) { $params = $params[0]; } $stuff = array( $this->_pkg->getTasksNs().':id' => $id, ); if ($instructions) { $stuff[$this->_pkg->getTasksNs().':instructions'] = $instructions; } if ($params) { $stuff[$this->_pkg->getTasksNs().':param'] = $params; } $this->_params[$this->_pkg->getTasksNs().':paramgroup'][] = $stuff; } /** * Add a complex to the post-install script with conditions * * This inserts a with * * Order is significant, so call this method in the same * sequence the users should see the paramgroups. The $params * parameter should either be the result of a call to {@link getParam()} * or an array of calls to getParam(). * * Use {@link addParamGroup()} to add a simple * * @param string $id id as seen by the script * @param string $oldgroup id of the section referenced by * * @param string $param name of the from the older section referenced * by * @param string $value value to match of the parameter * @param string $conditiontype one of '=', '!=', 'preg_match' * @param array|false $params array of getParam() calls, or false for no params * @param string|false $instructions */ public function addConditionTypeGroup($id, $oldgroup, $param, $value, $conditiontype = '=', $params = false, $instructions = false ) { if ($params && isset($params[0]) && !isset($params[1])) { $params = $params[0]; } $stuff = array( $this->_pkg->getTasksNs().':id' => $id, ); if ($instructions) { $stuff[$this->_pkg->getTasksNs().':instructions'] = $instructions; } $stuff[$this->_pkg->getTasksNs().':name'] = $oldgroup.'::'.$param; $stuff[$this->_pkg->getTasksNs().':conditiontype'] = $conditiontype; $stuff[$this->_pkg->getTasksNs().':value'] = $value; if ($params) { $stuff[$this->_pkg->getTasksNs().':param'] = $params; } $this->_params[$this->_pkg->getTasksNs().':paramgroup'][] = $stuff; } public function getXml() { return $this->_params; } /** * Use to set up a param tag for use in creating a paramgroup * * @param mixed $name Name of parameter * @param mixed $prompt Prompt * @param string $type Type, defaults to 'string' * @param mixed $default Default value * * @return array */ public function getParam( $name, $prompt, $type = 'string', $default = null ) { if ($default !== null) { return array( $this->_pkg->getTasksNs().':name' => $name, $this->_pkg->getTasksNs().':prompt' => $prompt, $this->_pkg->getTasksNs().':type' => $type, $this->_pkg->getTasksNs().':default' => $default, ); } return array( $this->_pkg->getTasksNs().':name' => $name, $this->_pkg->getTasksNs().':prompt' => $prompt, $this->_pkg->getTasksNs().':type' => $type, ); } } PK!-!PEAR/Task/Common.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /**#@+ * Error codes for task validation routines */ define('PEAR_TASK_ERROR_NOATTRIBS', 1); define('PEAR_TASK_ERROR_MISSING_ATTRIB', 2); define('PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE', 3); define('PEAR_TASK_ERROR_INVALID', 4); /**#@-*/ define('PEAR_TASK_PACKAGE', 1); define('PEAR_TASK_INSTALL', 2); define('PEAR_TASK_PACKAGEANDINSTALL', 3); /** * A task is an operation that manipulates the contents of a file. * * Simple tasks operate on 1 file. Multiple tasks are executed after all files have been * processed and installed, and are designed to operate on all files containing the task. * The Post-install script task simply takes advantage of the fact that it will be run * after installation, replace is a simple task. * * Combining tasks is possible, but ordering is significant. * * * * * * * This will first replace any instance of @data-dir@ in the test.php file * with the path to the current data directory. Then, it will include the * test.php file and run the script it contains to configure the package post-installation. * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 * @abstract */ class PEAR_Task_Common { /** * Valid types for this version are 'simple' and 'multiple' * * - simple tasks operate on the contents of a file and write out changes to disk * - multiple tasks operate on the contents of many files and write out the * changes directly to disk * * Child task classes must override this property. * * @access protected */ protected $type = 'simple'; /** * Determines which install phase this task is executed under */ public $phase = PEAR_TASK_INSTALL; /** * @access protected */ protected $config; /** * @access protected */ protected $registry; /** * @access protected */ public $logger; /** * @access protected */ protected $installphase; /** * @param PEAR_Config * @param PEAR_Common */ function __construct(&$config, &$logger, $phase) { $this->config = &$config; $this->registry = &$config->getRegistry(); $this->logger = &$logger; $this->installphase = $phase; if ($this->type == 'multiple') { $GLOBALS['_PEAR_TASK_POSTINSTANCES'][get_class($this)][] = &$this; } } /** * Validate the basic contents of a task tag. * * @param PEAR_PackageFile_v2 * @param array * @param PEAR_Config * @param array the entire parsed tag * * @return true|array On error, return an array in format: * array(PEAR_TASK_ERROR_???[, param1][, param2][, ...]) * * For PEAR_TASK_ERROR_MISSING_ATTRIB, pass the attribute name in * For PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, pass the attribute name and * an array of legal values in * * @abstract */ public static function validateXml($pkg, $xml, $config, $fileXml) { } /** * Initialize a task instance with the parameters * * @param array raw, parsed xml * @param array attributes from the tag containing this task * @param string|null last installed version of this package * @abstract */ public function init($xml, $fileAttributes, $lastVersion) { } /** * Begin a task processing session. All multiple tasks will be processed * after each file has been successfully installed, all simple tasks should * perform their task here and return any errors using the custom * throwError() method to allow forward compatibility * * This method MUST NOT write out any changes to disk * * @param PEAR_PackageFile_v2 * @param string file contents * @param string the eventual final file location (informational only) * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail * (use $this->throwError), otherwise return the new contents * @abstract */ public function startSession($pkg, $contents, $dest) { } /** * This method is used to process each of the tasks for a particular * multiple class type. Simple tasks need not implement this method. * * @param array an array of tasks * @access protected */ public static function run($tasks) { } /** * @final */ public static function hasPostinstallTasks() { return isset($GLOBALS['_PEAR_TASK_POSTINSTANCES']); } /** * @final */ public static function runPostinstallTasks() { foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) { $err = call_user_func( array($class, 'run'), $GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class] ); if ($err) { return PEAR_Task_Common::throwError($err); } } unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']); } /** * Determines whether a role is a script * @return bool */ public function isScript() { return $this->type == 'script'; } public function throwError($msg, $code = -1) { include_once 'PEAR.php'; return PEAR::raiseError($msg, $code); } } PK!D$PEAR/Task/Windowseol.phpnu[ * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Base class */ require_once 'PEAR/Task/Common.php'; /** * Implements the windows line endsings file task. * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Task_Windowseol extends PEAR_Task_Common { public $type = 'simple'; public $phase = PEAR_TASK_PACKAGE; public $_replacements; /** * Validate the raw xml at parsing-time. * * @param PEAR_PackageFile_v2 * @param array raw, parsed xml * @param PEAR_Config */ public static function validateXml($pkg, $xml, $config, $fileXml) { if ($xml != '') { return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed'); } return true; } /** * Initialize a task instance with the parameters * @param array raw, parsed xml * @param unused * @param unused */ public function init($xml, $attribs, $lastVersion = null) { } /** * Replace all line endings with windows line endings * * See validateXml() source for the complete list of allowed fields * * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @param string file contents * @param string the eventual final file location (informational only) * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail * (use $this->throwError), otherwise return the new contents */ public function startSession($pkg, $contents, $dest) { $this->logger->log(3, "replacing all line endings with \\r\\n in $dest"); return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents); } } PK!ZEx9x9PEAR/Task/Postinstallscript.phpnu[ * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Base class */ require_once 'PEAR/Task/Common.php'; /** * Implements the postinstallscript file task. * * Note that post-install scripts are handled separately from installation, by the * "pear run-scripts" command * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Task_Postinstallscript extends PEAR_Task_Common { public $type = 'script'; public $_class; public $_params; public $_obj; /** * * @var PEAR_PackageFile_v2 */ public $_pkg; public $_contents; public $phase = PEAR_TASK_INSTALL; /** * Validate the raw xml at parsing-time. * * This also attempts to validate the script to make sure it meets the criteria * for a post-install script * * @param PEAR_PackageFile_v2 * @param array The XML contents of the tag * @param PEAR_Config * @param array the entire parsed tag */ public static function validateXml($pkg, $xml, $config, $fileXml) { if ($fileXml['role'] != 'php') { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" must be role="php"', ); } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $file = $pkg->getFileContents($fileXml['name']); if (PEAR::isError($file)) { PEAR::popErrorHandling(); return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" is not valid: '. $file->getMessage(), ); } elseif ($file === null) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" could not be retrieved for processing!', ); } else { $analysis = $pkg->analyzeSourceCode($file, true); if (!$analysis) { PEAR::popErrorHandling(); $warnings = ''; foreach ($pkg->getValidationWarnings() as $warn) { $warnings .= $warn['message']."\n"; } return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "'. $fileXml['name'].'" failed: '.$warnings, ); } if (count($analysis['declared_classes']) != 1) { PEAR::popErrorHandling(); return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" must declare exactly 1 class', ); } $class = $analysis['declared_classes'][0]; if ($class != str_replace( array('/', '.php'), array('_', ''), $fileXml['name'] ).'_postinstall') { PEAR::popErrorHandling(); return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" class "'.$class.'" must be named "'. str_replace( array('/', '.php'), array('_', ''), $fileXml['name'] ).'_postinstall"', ); } if (!isset($analysis['declared_methods'][$class])) { PEAR::popErrorHandling(); return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" must declare methods init() and run()', ); } $methods = array('init' => 0, 'run' => 1); foreach ($analysis['declared_methods'][$class] as $method) { if (isset($methods[$method])) { unset($methods[$method]); } } if (count($methods)) { PEAR::popErrorHandling(); return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" must declare methods init() and run()', ); } } PEAR::popErrorHandling(); $definedparams = array(); $tasksNamespace = $pkg->getTasksNs().':'; if (!isset($xml[$tasksNamespace.'paramgroup']) && isset($xml['paramgroup'])) { // in order to support the older betas, which did not expect internal tags // to also use the namespace $tasksNamespace = ''; } if (isset($xml[$tasksNamespace.'paramgroup'])) { $params = $xml[$tasksNamespace.'paramgroup']; if (!is_array($params) || !isset($params[0])) { $params = array($params); } foreach ($params as $param) { if (!isset($param[$tasksNamespace.'id'])) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" must have '. 'an '.$tasksNamespace.'id> tag', ); } if (isset($param[$tasksNamespace.'name'])) { if (!in_array($param[$tasksNamespace.'name'], $definedparams)) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" '.$tasksNamespace. 'paramgroup> id "'.$param[$tasksNamespace.'id']. '" parameter "'.$param[$tasksNamespace.'name']. '" has not been previously defined', ); } if (!isset($param[$tasksNamespace.'conditiontype'])) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" '.$tasksNamespace. 'paramgroup> id "'.$param[$tasksNamespace.'id']. '" must have a '.$tasksNamespace. 'conditiontype> tag containing either "=", '. '"!=", or "preg_match"', ); } if (!in_array( $param[$tasksNamespace.'conditiontype'], array('=', '!=', 'preg_match') )) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" '.$tasksNamespace. 'paramgroup> id "'.$param[$tasksNamespace.'id']. '" must have a '.$tasksNamespace. 'conditiontype> tag containing either "=", '. '"!=", or "preg_match"', ); } if (!isset($param[$tasksNamespace.'value'])) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" '.$tasksNamespace. 'paramgroup> id "'.$param[$tasksNamespace.'id']. '" must have a '.$tasksNamespace. 'value> tag containing expected parameter value', ); } } if (isset($param[$tasksNamespace.'instructions'])) { if (!is_string($param[$tasksNamespace.'instructions'])) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" '.$tasksNamespace. 'paramgroup> id "'.$param[$tasksNamespace.'id']. '" '.$tasksNamespace.'instructions> must be simple text', ); } } if (!isset($param[$tasksNamespace.'param'])) { continue; // is no longer required } $subparams = $param[$tasksNamespace.'param']; if (!is_array($subparams) || !isset($subparams[0])) { $subparams = array($subparams); } foreach ($subparams as $subparam) { if (!isset($subparam[$tasksNamespace.'name'])) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" parameter for '. $tasksNamespace.'paramgroup> id "'. $param[$tasksNamespace.'id'].'" must have '. 'a '.$tasksNamespace.'name> tag', ); } if (!preg_match( '/[a-zA-Z0-9]+/', $subparam[$tasksNamespace.'name'] )) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" parameter "'. $subparam[$tasksNamespace.'name']. '" for '.$tasksNamespace.'paramgroup> id "'. $param[$tasksNamespace.'id']. '" is not a valid name. Must contain only alphanumeric characters', ); } if (!isset($subparam[$tasksNamespace.'prompt'])) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" parameter "'. $subparam[$tasksNamespace.'name']. '" for '.$tasksNamespace.'paramgroup> id "'. $param[$tasksNamespace.'id']. '" must have a '.$tasksNamespace.'prompt> tag', ); } if (!isset($subparam[$tasksNamespace.'type'])) { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "'. $fileXml['name'].'" parameter "'. $subparam[$tasksNamespace.'name']. '" for '.$tasksNamespace.'paramgroup> id "'. $param[$tasksNamespace.'id']. '" must have a '.$tasksNamespace.'type> tag', ); } $definedparams[] = $param[$tasksNamespace.'id'].'::'. $subparam[$tasksNamespace.'name']; } } } return true; } /** * Initialize a task instance with the parameters * @param array $xml raw, parsed xml * @param array $fileattribs attributes from the tag containing * this task * @param string|null $lastversion last installed version of this package, * if any (useful for upgrades) */ public function init($xml, $fileattribs, $lastversion) { $this->_class = str_replace('/', '_', $fileattribs['name']); $this->_filename = $fileattribs['name']; $this->_class = str_replace('.php', '', $this->_class).'_postinstall'; $this->_params = $xml; $this->_lastversion = $lastversion; } /** * Strip the tasks: namespace from internal params * * @access private */ public function _stripNamespace($params = null) { if ($params === null) { $params = array(); if (!is_array($this->_params)) { return; } foreach ($this->_params as $i => $param) { if (is_array($param)) { $param = $this->_stripNamespace($param); } $params[str_replace($this->_pkg->getTasksNs().':', '', $i)] = $param; } $this->_params = $params; } else { $newparams = array(); foreach ($params as $i => $param) { if (is_array($param)) { $param = $this->_stripNamespace($param); } $newparams[str_replace($this->_pkg->getTasksNs().':', '', $i)] = $param; } return $newparams; } } /** * Unlike other tasks, the installed file name is passed in instead of the * file contents, because this task is handled post-installation * * @param mixed $pkg PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @param string $contents file name * @param string $dest the eventual final file location (informational only) * * @return bool|PEAR_Error false to skip this file, PEAR_Error to fail * (use $this->throwError) */ public function startSession($pkg, $contents, $dest) { if ($this->installphase != PEAR_TASK_INSTALL) { return false; } // remove the tasks: namespace if present $this->_pkg = $pkg; $this->_stripNamespace(); $this->logger->log( 0, 'Including external post-installation script "'. $contents.'" - any errors are in this script' ); include_once $contents; if (class_exists($this->_class)) { $this->logger->log(0, 'Inclusion succeeded'); } else { return $this->throwError( 'init of post-install script class "'.$this->_class .'" failed' ); } $this->_obj = new $this->_class(); $this->logger->log(1, 'running post-install script "'.$this->_class.'->init()"'); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $res = $this->_obj->init($this->config, $pkg, $this->_lastversion); PEAR::popErrorHandling(); if ($res) { $this->logger->log(0, 'init succeeded'); } else { return $this->throwError( 'init of post-install script "'.$this->_class. '->init()" failed' ); } $this->_contents = $contents; return true; } /** * No longer used * * @see PEAR_PackageFile_v2::runPostinstallScripts() * @param array an array of tasks * @param string install or upgrade * @access protected */ public static function run($tasks) { } } PK!\kPEAR/Task/Unixeol/rw.phpnu[ - read/write version * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a10 */ /** * Base class */ require_once 'PEAR/Task/Unixeol.php'; /** * Abstracts the unixeol task xml. * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol { function __construct(&$pkg, &$config, &$logger, $fileXml) { parent::__construct($config, $logger, PEAR_TASK_PACKAGE); $this->_contents = $fileXml; $this->_pkg = &$pkg; $this->_params = array(); } public function validate() { return true; } public function getName() { return 'unixeol'; } public function getXml() { return ''; } } ?> PK! PEAR/Task/Unixeol.phpnu[ * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Base class */ require_once 'PEAR/Task/Common.php'; /** * Implements the unix line endings file task. * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Task_Unixeol extends PEAR_Task_Common { public $type = 'simple'; public $phase = PEAR_TASK_PACKAGE; public $_replacements; /** * Validate the raw xml at parsing-time. * * @param PEAR_PackageFile_v2 * @param array raw, parsed xml * @param PEAR_Config */ public static function validateXml($pkg, $xml, $config, $fileXml) { if ($xml != '') { return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed'); } return true; } /** * Initialize a task instance with the parameters * @param array raw, parsed xml * @param unused * @param unused */ public function init($xml, $attribs, $lastVersion = null) { } /** * Replace all line endings with line endings customized for the current OS * * See validateXml() source for the complete list of allowed fields * * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @param string file contents * @param string the eventual final file location (informational only) * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail * (use $this->throwError), otherwise return the new contents */ public function startSession($pkg, $contents, $dest) { $this->logger->log(3, "replacing all line endings with \\n in $dest"); return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents); } } PK!WfPEAR/REST/10.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a12 */ /** * For downloading REST xml/txt files */ require_once 'PEAR/REST.php'; /** * Implement REST 1.0 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a12 */ class PEAR_REST_10 { /** * @var PEAR_REST */ var $_rest; function __construct($config, $options = array()) { $this->_rest = new PEAR_REST($config, $options); } /** * Retrieve information about a remote package to be downloaded from a REST server * * @param string $base The uri to prepend to all REST calls * @param array $packageinfo an array of format: *
     *  array(
     *   'package' => 'packagename',
     *   'channel' => 'channelname',
     *  ['state' => 'alpha' (or valid state),]
     *  -or-
     *  ['version' => '1.whatever']
     * 
* @param string $prefstate Current preferred_state config variable value * @param bool $installed the installed version of this package to compare against * @return array|false|PEAR_Error see {@link _returnDownloadURL()} */ function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false) { $states = $this->betterStates($prefstate, true); if (!$states) { return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); } $channel = $packageinfo['channel']; $package = $packageinfo['package']; $state = isset($packageinfo['state']) ? $packageinfo['state'] : null; $version = isset($packageinfo['version']) ? $packageinfo['version'] : null; $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml'; $info = $this->_rest->retrieveData($restFile, false, false, $channel); if (PEAR::isError($info)) { return PEAR::raiseError('No releases available for package "' . $channel . '/' . $package . '"'); } if (!isset($info['r'])) { return false; } $release = $found = false; if (!is_array($info['r']) || !isset($info['r'][0])) { $info['r'] = array($info['r']); } foreach ($info['r'] as $release) { if (!isset($this->_rest->_options['force']) && ($installed && version_compare($release['v'], $installed, '<'))) { continue; } if (isset($state)) { // try our preferred state first if ($release['s'] == $state) { $found = true; break; } // see if there is something newer and more stable // bug #7221 if (in_array($release['s'], $this->betterStates($state), true)) { $found = true; break; } } elseif (isset($version)) { if ($release['v'] == $version) { $found = true; break; } } else { if (in_array($release['s'], $states)) { $found = true; break; } } } return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel); } function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage, $prefstate = 'stable', $installed = false, $channel = false) { $states = $this->betterStates($prefstate, true); if (!$states) { return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); } $channel = $dependency['channel']; $package = $dependency['name']; $state = isset($dependency['state']) ? $dependency['state'] : null; $version = isset($dependency['version']) ? $dependency['version'] : null; $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml'; $info = $this->_rest->retrieveData($restFile, false, false, $channel); if (PEAR::isError($info)) { return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package'] . '" dependency "' . $channel . '/' . $package . '" has no releases'); } if (!is_array($info) || !isset($info['r'])) { return false; } $exclude = array(); $min = $max = $recommended = false; if ($xsdversion == '1.0') { switch ($dependency['rel']) { case 'ge' : $min = $dependency['version']; break; case 'gt' : $min = $dependency['version']; $exclude = array($dependency['version']); break; case 'eq' : $recommended = $dependency['version']; break; case 'lt' : $max = $dependency['version']; $exclude = array($dependency['version']); break; case 'le' : $max = $dependency['version']; break; case 'ne' : $exclude = array($dependency['version']); break; } } else { $min = isset($dependency['min']) ? $dependency['min'] : false; $max = isset($dependency['max']) ? $dependency['max'] : false; $recommended = isset($dependency['recommended']) ? $dependency['recommended'] : false; if (isset($dependency['exclude'])) { if (!isset($dependency['exclude'][0])) { $exclude = array($dependency['exclude']); } } } $release = $found = false; if (!is_array($info['r']) || !isset($info['r'][0])) { $info['r'] = array($info['r']); } foreach ($info['r'] as $release) { if (!isset($this->_rest->_options['force']) && ($installed && version_compare($release['v'], $installed, '<'))) { continue; } if (in_array($release['v'], $exclude)) { // skip excluded versions continue; } // allow newer releases to say "I'm OK with the dependent package" if ($xsdversion == '2.0' && isset($release['co'])) { if (!is_array($release['co']) || !isset($release['co'][0])) { $release['co'] = array($release['co']); } foreach ($release['co'] as $entry) { if (isset($entry['x']) && !is_array($entry['x'])) { $entry['x'] = array($entry['x']); } elseif (!isset($entry['x'])) { $entry['x'] = array(); } if ($entry['c'] == $deppackage['channel'] && strtolower($entry['p']) == strtolower($deppackage['package']) && version_compare($deppackage['version'], $entry['min'], '>=') && version_compare($deppackage['version'], $entry['max'], '<=') && !in_array($release['v'], $entry['x'])) { $recommended = $release['v']; break; } } } if ($recommended) { if ($release['v'] != $recommended) { // if we want a specific // version, then skip all others continue; } else { if (!in_array($release['s'], $states)) { // the stability is too low, but we must return the // recommended version if possible return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel); } } } if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions continue; } if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions continue; } if ($installed && version_compare($release['v'], $installed, '<')) { continue; } if (in_array($release['s'], $states)) { // if in the preferred state... $found = true; // ... then use it break; } } return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel); } /** * Take raw data and return the array needed for processing a download URL * * @param string $base REST base uri * @param string $package Package name * @param array $release an array of format array('v' => version, 's' => state) * describing the release to download * @param array $info list of all releases as defined by allreleases.xml * @param bool|null $found determines whether the release was found or this is the next * best alternative. If null, then versions were skipped because * of PHP dependency * @return array|PEAR_Error * @access private */ function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false) { if (!$found) { $release = $info['r'][0]; } $packageLower = strtolower($package); $pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' . 'info.xml', false, false, $channel); if (PEAR::isError($pinfo)) { return PEAR::raiseError('Package "' . $package . '" does not have REST info xml available'); } $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' . $release['v'] . '.xml', false, false, $channel); if (PEAR::isError($releaseinfo)) { return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] . '" does not have REST xml available'); } $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' . 'deps.' . $release['v'] . '.txt', false, true, $channel); if (PEAR::isError($packagexml)) { return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] . '" does not have REST dependency information available'); } $packagexml = unserialize($packagexml); if (!$packagexml) { $packagexml = array(); } $allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower . '/allreleases.xml', false, false, $channel); if (PEAR::isError($allinfo)) { return $allinfo; } if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) { $allinfo['r'] = array($allinfo['r']); } $compatible = false; foreach ($allinfo['r'] as $release) { if ($release['v'] != $releaseinfo['v']) { continue; } if (!isset($release['co'])) { break; } $compatible = array(); if (!is_array($release['co']) || !isset($release['co'][0])) { $release['co'] = array($release['co']); } foreach ($release['co'] as $entry) { $comp = array(); $comp['name'] = $entry['p']; $comp['channel'] = $entry['c']; $comp['min'] = $entry['min']; $comp['max'] = $entry['max']; if (isset($entry['x']) && !is_array($entry['x'])) { $comp['exclude'] = $entry['x']; } $compatible[] = $comp; } if (count($compatible) == 1) { $compatible = $compatible[0]; } break; } $deprecated = false; if (isset($pinfo['dc']) && isset($pinfo['dp'])) { if (is_array($pinfo['dp'])) { $deprecated = array('channel' => (string) $pinfo['dc'], 'package' => trim($pinfo['dp']['_content'])); } else { $deprecated = array('channel' => (string) $pinfo['dc'], 'package' => trim($pinfo['dp'])); } } $return = array( 'version' => $releaseinfo['v'], 'info' => $packagexml, 'package' => $releaseinfo['p']['_content'], 'stability' => $releaseinfo['st'], 'compatible' => $compatible, 'deprecated' => $deprecated, ); if ($found) { $return['url'] = $releaseinfo['g']; return $return; } $return['php'] = $phpversion; return $return; } function listPackages($base, $channel = false) { $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); if (PEAR::isError($packagelist)) { return $packagelist; } if (!is_array($packagelist) || !isset($packagelist['p'])) { return array(); } if (!is_array($packagelist['p'])) { $packagelist['p'] = array($packagelist['p']); } return $packagelist['p']; } /** * List all categories of a REST server * * @param string $base base URL of the server * @return array of categorynames */ function listCategories($base, $channel = false) { $categories = array(); // c/categories.xml does not exist; // check for every package its category manually // This is SLOOOWWWW : /// $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); if (PEAR::isError($packagelist)) { return $packagelist; } if (!is_array($packagelist) || !isset($packagelist['p'])) { $ret = array(); return $ret; } if (!is_array($packagelist['p'])) { $packagelist['p'] = array($packagelist['p']); } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); foreach ($packagelist['p'] as $package) { $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); if (PEAR::isError($inf)) { PEAR::popErrorHandling(); return $inf; } $cat = $inf['ca']['_content']; if (!isset($categories[$cat])) { $categories[$cat] = $inf['ca']; } } return array_values($categories); } /** * List a category of a REST server * * @param string $base base URL of the server * @param string $category name of the category * @param boolean $info also download full package info * @return array of packagenames */ function listCategory($base, $category, $info = false, $channel = false) { // gives '404 Not Found' error when category doesn't exist $packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel); if (PEAR::isError($packagelist)) { return $packagelist; } if (!is_array($packagelist) || !isset($packagelist['p'])) { return array(); } if (!is_array($packagelist['p']) || !isset($packagelist['p'][0])) { // only 1 pkg $packagelist = array($packagelist['p']); } else { $packagelist = $packagelist['p']; } if ($info == true) { // get individual package info PEAR::pushErrorHandling(PEAR_ERROR_RETURN); foreach ($packagelist as $i => $packageitem) { $url = sprintf('%s'.'r/%s/latest.txt', $base, strtolower($packageitem['_content'])); $version = $this->_rest->retrieveData($url, false, false, $channel); if (PEAR::isError($version)) { break; // skipit } $url = sprintf('%s'.'r/%s/%s.xml', $base, strtolower($packageitem['_content']), $version); $info = $this->_rest->retrieveData($url, false, false, $channel); if (PEAR::isError($info)) { break; // skipit } $packagelist[$i]['info'] = $info; } PEAR::popErrorHandling(); } return $packagelist; } function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false) { $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); if (PEAR::isError($packagelist)) { return $packagelist; } if ($this->_rest->config->get('verbose') > 0) { $ui = &PEAR_Frontend::singleton(); $ui->log('Retrieving data...0%', true); } $ret = array(); if (!is_array($packagelist) || !isset($packagelist['p'])) { return $ret; } if (!is_array($packagelist['p'])) { $packagelist['p'] = array($packagelist['p']); } // only search-packagename = quicksearch ! if ($searchpackage && (!$searchsummary || empty($searchpackage))) { $newpackagelist = array(); foreach ($packagelist['p'] as $package) { if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) { $newpackagelist[] = $package; } } $packagelist['p'] = $newpackagelist; } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $next = .1; foreach ($packagelist['p'] as $progress => $package) { if ($this->_rest->config->get('verbose') > 0) { if ($progress / count($packagelist['p']) >= $next) { if ($next == .5) { $ui->log('50%', false); } else { $ui->log('.', false); } $next += .1; } } if ($basic) { // remote-list command if ($dostable) { $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/stable.txt', false, false, $channel); } else { $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/latest.txt', false, false, $channel); } if (PEAR::isError($latest)) { $latest = false; } $info = array('stable' => $latest); } else { // list-all command $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); if (PEAR::isError($inf)) { PEAR::popErrorHandling(); return $inf; } if ($searchpackage) { $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false); if (!$found && !(isset($searchsummary) && !empty($searchsummary) && (stristr($inf['s'], $searchsummary) !== false || stristr($inf['d'], $searchsummary) !== false))) { continue; }; } $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases.xml', false, false, $channel); if (PEAR::isError($releases)) { continue; } if (!isset($releases['r'][0])) { $releases['r'] = array($releases['r']); } unset($latest); unset($unstable); unset($stable); unset($state); foreach ($releases['r'] as $release) { if (!isset($latest)) { if ($dostable && $release['s'] == 'stable') { $latest = $release['v']; $state = 'stable'; } if (!$dostable) { $latest = $release['v']; $state = $release['s']; } } if (!isset($stable) && $release['s'] == 'stable') { $stable = $release['v']; if (!isset($unstable)) { $unstable = $stable; } } if (!isset($unstable) && $release['s'] != 'stable') { $latest = $unstable = $release['v']; $state = $release['s']; } if (isset($latest) && !isset($state)) { $state = $release['s']; } if (isset($latest) && isset($stable) && isset($unstable)) { break; } } $deps = array(); if (!isset($unstable)) { $unstable = false; $state = 'stable'; if (isset($stable)) { $latest = $unstable = $stable; } } else { $latest = $unstable; } if (!isset($latest)) { $latest = false; } if ($latest) { $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' . $latest . '.txt', false, false, $channel); if (!PEAR::isError($d)) { $d = unserialize($d); if ($d) { if (isset($d['required'])) { if (!class_exists('PEAR_PackageFile_v2')) { require_once 'PEAR/PackageFile/v2.php'; } if (!isset($pf)) { $pf = new PEAR_PackageFile_v2; } $pf->setDeps($d); $tdeps = $pf->getDeps(); } else { $tdeps = $d; } foreach ($tdeps as $dep) { if ($dep['type'] !== 'pkg') { continue; } $deps[] = $dep; } } } } if (!isset($stable)) { $stable = '-n/a-'; } if (!$searchpackage) { $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' => $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'], 'unstable' => $unstable, 'state' => $state); } else { $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' => $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'], 'unstable' => $unstable, 'state' => $state); } } $ret[$package] = $info; } PEAR::popErrorHandling(); return $ret; } function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg) { $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); if (PEAR::isError($packagelist)) { return $packagelist; } $ret = array(); if (!is_array($packagelist) || !isset($packagelist['p'])) { return $ret; } if (!is_array($packagelist['p'])) { $packagelist['p'] = array($packagelist['p']); } foreach ($packagelist['p'] as $package) { if (!isset($installed[strtolower($package)])) { continue; } $inst_version = $reg->packageInfo($package, 'version', $channel); $inst_state = $reg->packageInfo($package, 'release_state', $channel); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases.xml', false, false, $channel); PEAR::popErrorHandling(); if (PEAR::isError($info)) { continue; // no remote releases } if (!isset($info['r'])) { continue; } $release = $found = false; if (!is_array($info['r']) || !isset($info['r'][0])) { $info['r'] = array($info['r']); } // $info['r'] is sorted by version number usort($info['r'], array($this, '_sortReleasesByVersionNumber')); foreach ($info['r'] as $release) { if ($inst_version && version_compare($release['v'], $inst_version, '<=')) { // not newer than the one installed break; } // new version > installed version if (!$pref_state) { // every state is a good state $found = true; break; } else { $new_state = $release['s']; // if new state >= installed state: go if (in_array($new_state, $this->betterStates($inst_state, true))) { $found = true; break; } else { // only allow to lower the state of package, // if new state >= preferred state: go if (in_array($new_state, $this->betterStates($pref_state, true))) { $found = true; break; } } } } if (!$found) { continue; } $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . $release['v'] . '.xml', false, false, $channel); if (PEAR::isError($relinfo)) { return $relinfo; } $ret[$package] = array( 'version' => $release['v'], 'state' => $release['s'], 'filesize' => $relinfo['f'], ); } return $ret; } function packageInfo($base, $package, $channel = false) { PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); if (PEAR::isError($pinfo)) { PEAR::popErrorHandling(); return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' . $pinfo->getMessage()); } $releases = array(); $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases.xml', false, false, $channel); if (!PEAR::isError($allreleases)) { if (!class_exists('PEAR_PackageFile_v2')) { require_once 'PEAR/PackageFile/v2.php'; } if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) { $allreleases['r'] = array($allreleases['r']); } $pf = new PEAR_PackageFile_v2; foreach ($allreleases['r'] as $release) { $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' . $release['v'] . '.txt', false, false, $channel); if (PEAR::isError($ds)) { continue; } if (!isset($latest)) { $latest = $release['v']; } $pf->setDeps(unserialize($ds)); $ds = $pf->getDeps(); $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . $release['v'] . '.xml', false, false, $channel); if (PEAR::isError($info)) { continue; } $releases[$release['v']] = array( 'doneby' => $info['m'], 'license' => $info['l'], 'summary' => $info['s'], 'description' => $info['d'], 'releasedate' => $info['da'], 'releasenotes' => $info['n'], 'state' => $release['s'], 'deps' => $ds ? $ds : array(), ); } } else { $latest = ''; } PEAR::popErrorHandling(); if (isset($pinfo['dc']) && isset($pinfo['dp'])) { if (is_array($pinfo['dp'])) { $deprecated = array('channel' => (string) $pinfo['dc'], 'package' => trim($pinfo['dp']['_content'])); } else { $deprecated = array('channel' => (string) $pinfo['dc'], 'package' => trim($pinfo['dp'])); } } else { $deprecated = false; } if (!isset($latest)) { $latest = ''; } return array( 'name' => $pinfo['n'], 'channel' => $pinfo['c'], 'category' => $pinfo['ca']['_content'], 'stable' => $latest, 'license' => $pinfo['l'], 'summary' => $pinfo['s'], 'description' => $pinfo['d'], 'releases' => $releases, 'deprecated' => $deprecated, ); } /** * Return an array containing all of the states that are more stable than * or equal to the passed in state * * @param string Release state * @param boolean Determines whether to include $state in the list * @return false|array False if $state is not a valid release state */ function betterStates($state, $include = false) { static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); $i = array_search($state, $states); if ($i === false) { return false; } if ($include) { $i--; } return array_slice($states, $i + 1); } /** * Sort releases by version number * * @access private */ function _sortReleasesByVersionNumber($a, $b) { if (version_compare($a['v'], $b['v'], '=')) { return 0; } if (version_compare($a['v'], $b['v'], '>')) { return -1; } if (version_compare($a['v'], $b['v'], '<')) { return 1; } } } PK!Y;;PEAR/REST/13.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a12 */ /** * For downloading REST xml/txt files */ require_once 'PEAR/REST.php'; require_once 'PEAR/REST/10.php'; /** * Implement REST 1.3 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a12 */ class PEAR_REST_13 extends PEAR_REST_10 { /** * Retrieve information about a remote package to be downloaded from a REST server * * This is smart enough to resolve the minimum PHP version dependency prior to download * @param string $base The uri to prepend to all REST calls * @param array $packageinfo an array of format: *
     *  array(
     *   'package' => 'packagename',
     *   'channel' => 'channelname',
     *  ['state' => 'alpha' (or valid state),]
     *  -or-
     *  ['version' => '1.whatever']
     * 
* @param string $prefstate Current preferred_state config variable value * @param bool $installed the installed version of this package to compare against * @return array|false|PEAR_Error see {@link _returnDownloadURL()} */ function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false) { $states = $this->betterStates($prefstate, true); if (!$states) { return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); } $channel = $packageinfo['channel']; $package = $packageinfo['package']; $state = isset($packageinfo['state']) ? $packageinfo['state'] : null; $version = isset($packageinfo['version']) ? $packageinfo['version'] : null; $restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml'; $info = $this->_rest->retrieveData($restFile, false, false, $channel); if (PEAR::isError($info)) { return PEAR::raiseError('No releases available for package "' . $channel . '/' . $package . '"'); } if (!isset($info['r'])) { return false; } $release = $found = false; if (!is_array($info['r']) || !isset($info['r'][0])) { $info['r'] = array($info['r']); } $skippedphp = false; foreach ($info['r'] as $release) { if (!isset($this->_rest->_options['force']) && ($installed && version_compare($release['v'], $installed, '<'))) { continue; } if (isset($state)) { // try our preferred state first if ($release['s'] == $state) { if (!isset($version) && version_compare($release['m'], phpversion(), '>')) { // skip releases that require a PHP version newer than our PHP version $skippedphp = $release; continue; } $found = true; break; } // see if there is something newer and more stable // bug #7221 if (in_array($release['s'], $this->betterStates($state), true)) { if (!isset($version) && version_compare($release['m'], phpversion(), '>')) { // skip releases that require a PHP version newer than our PHP version $skippedphp = $release; continue; } $found = true; break; } } elseif (isset($version)) { if ($release['v'] == $version) { if (!isset($this->_rest->_options['force']) && !isset($version) && version_compare($release['m'], phpversion(), '>')) { // skip releases that require a PHP version newer than our PHP version $skippedphp = $release; continue; } $found = true; break; } } else { if (in_array($release['s'], $states)) { if (version_compare($release['m'], phpversion(), '>')) { // skip releases that require a PHP version newer than our PHP version $skippedphp = $release; continue; } $found = true; break; } } } if (!$found && $skippedphp) { $found = null; } return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel); } function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage, $prefstate = 'stable', $installed = false, $channel = false) { $states = $this->betterStates($prefstate, true); if (!$states) { return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); } $channel = $dependency['channel']; $package = $dependency['name']; $state = isset($dependency['state']) ? $dependency['state'] : null; $version = isset($dependency['version']) ? $dependency['version'] : null; $restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml'; $info = $this->_rest->retrieveData($restFile, false, false, $channel); if (PEAR::isError($info)) { return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package'] . '" dependency "' . $channel . '/' . $package . '" has no releases'); } if (!is_array($info) || !isset($info['r'])) { return false; } $exclude = array(); $min = $max = $recommended = false; if ($xsdversion == '1.0') { $pinfo['package'] = $dependency['name']; $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this switch ($dependency['rel']) { case 'ge' : $min = $dependency['version']; break; case 'gt' : $min = $dependency['version']; $exclude = array($dependency['version']); break; case 'eq' : $recommended = $dependency['version']; break; case 'lt' : $max = $dependency['version']; $exclude = array($dependency['version']); break; case 'le' : $max = $dependency['version']; break; case 'ne' : $exclude = array($dependency['version']); break; } } else { $pinfo['package'] = $dependency['name']; $min = isset($dependency['min']) ? $dependency['min'] : false; $max = isset($dependency['max']) ? $dependency['max'] : false; $recommended = isset($dependency['recommended']) ? $dependency['recommended'] : false; if (isset($dependency['exclude'])) { if (!isset($dependency['exclude'][0])) { $exclude = array($dependency['exclude']); } } } $skippedphp = $found = $release = false; if (!is_array($info['r']) || !isset($info['r'][0])) { $info['r'] = array($info['r']); } foreach ($info['r'] as $release) { if (!isset($this->_rest->_options['force']) && ($installed && version_compare($release['v'], $installed, '<'))) { continue; } if (in_array($release['v'], $exclude)) { // skip excluded versions continue; } // allow newer releases to say "I'm OK with the dependent package" if ($xsdversion == '2.0' && isset($release['co'])) { if (!is_array($release['co']) || !isset($release['co'][0])) { $release['co'] = array($release['co']); } foreach ($release['co'] as $entry) { if (isset($entry['x']) && !is_array($entry['x'])) { $entry['x'] = array($entry['x']); } elseif (!isset($entry['x'])) { $entry['x'] = array(); } if ($entry['c'] == $deppackage['channel'] && strtolower($entry['p']) == strtolower($deppackage['package']) && version_compare($deppackage['version'], $entry['min'], '>=') && version_compare($deppackage['version'], $entry['max'], '<=') && !in_array($release['v'], $entry['x'])) { if (version_compare($release['m'], phpversion(), '>')) { // skip dependency releases that require a PHP version // newer than our PHP version $skippedphp = $release; continue; } $recommended = $release['v']; break; } } } if ($recommended) { if ($release['v'] != $recommended) { // if we want a specific // version, then skip all others continue; } if (!in_array($release['s'], $states)) { // the stability is too low, but we must return the // recommended version if possible return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel); } } if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions continue; } if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions continue; } if ($installed && version_compare($release['v'], $installed, '<')) { continue; } if (in_array($release['s'], $states)) { // if in the preferred state... if (version_compare($release['m'], phpversion(), '>')) { // skip dependency releases that require a PHP version // newer than our PHP version $skippedphp = $release; continue; } $found = true; // ... then use it break; } } if (!$found && $skippedphp) { $found = null; } return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel); } /** * List package upgrades but take the PHP version into account. */ function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg) { $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); if (PEAR::isError($packagelist)) { return $packagelist; } $ret = array(); if (!is_array($packagelist) || !isset($packagelist['p'])) { return $ret; } if (!is_array($packagelist['p'])) { $packagelist['p'] = array($packagelist['p']); } foreach ($packagelist['p'] as $package) { if (!isset($installed[strtolower($package)])) { continue; } $inst_version = $reg->packageInfo($package, 'version', $channel); $inst_state = $reg->packageInfo($package, 'release_state', $channel); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases2.xml', false, false, $channel); PEAR::popErrorHandling(); if (PEAR::isError($info)) { continue; // no remote releases } if (!isset($info['r'])) { continue; } $release = $found = false; if (!is_array($info['r']) || !isset($info['r'][0])) { $info['r'] = array($info['r']); } // $info['r'] is sorted by version number usort($info['r'], array($this, '_sortReleasesByVersionNumber')); foreach ($info['r'] as $release) { if ($inst_version && version_compare($release['v'], $inst_version, '<=')) { // not newer than the one installed break; } if (version_compare($release['m'], phpversion(), '>')) { // skip dependency releases that require a PHP version // newer than our PHP version continue; } // new version > installed version if (!$pref_state) { // every state is a good state $found = true; break; } else { $new_state = $release['s']; // if new state >= installed state: go if (in_array($new_state, $this->betterStates($inst_state, true))) { $found = true; break; } else { // only allow to lower the state of package, // if new state >= preferred state: go if (in_array($new_state, $this->betterStates($pref_state, true))) { $found = true; break; } } } } if (!$found) { continue; } $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . $release['v'] . '.xml', false, false, $channel); if (PEAR::isError($relinfo)) { return $relinfo; } $ret[$package] = array( 'version' => $release['v'], 'state' => $release['s'], 'filesize' => $relinfo['f'], ); } return $ret; } }PK!,#y++PEAR/REST/11.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.3 */ /** * For downloading REST xml/txt files */ require_once 'PEAR/REST.php'; /** * Implement REST 1.1 * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.3 */ class PEAR_REST_11 { /** * @var PEAR_REST */ var $_rest; function __construct($config, $options = array()) { $this->_rest = new PEAR_REST($config, $options); } function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false) { $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel); if (PEAR::isError($categorylist)) { return $categorylist; } $ret = array(); if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) { $categorylist['c'] = array($categorylist['c']); } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); foreach ($categorylist['c'] as $progress => $category) { $category = $category['_content']; $packagesinfo = $this->_rest->retrieveData($base . 'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel); if (PEAR::isError($packagesinfo)) { continue; } if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) { continue; } if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) { $packagesinfo['pi'] = array($packagesinfo['pi']); } foreach ($packagesinfo['pi'] as $packageinfo) { if (empty($packageinfo)) { continue; } $info = $packageinfo['p']; $package = $info['n']; $releases = isset($packageinfo['a']) ? $packageinfo['a'] : false; unset($latest); unset($unstable); unset($stable); unset($state); if ($releases) { if (!isset($releases['r'][0])) { $releases['r'] = array($releases['r']); } foreach ($releases['r'] as $release) { if (!isset($latest)) { if ($dostable && $release['s'] == 'stable') { $latest = $release['v']; $state = 'stable'; } if (!$dostable) { $latest = $release['v']; $state = $release['s']; } } if (!isset($stable) && $release['s'] == 'stable') { $stable = $release['v']; if (!isset($unstable)) { $unstable = $stable; } } if (!isset($unstable) && $release['s'] != 'stable') { $unstable = $release['v']; $state = $release['s']; } if (isset($latest) && !isset($state)) { $state = $release['s']; } if (isset($latest) && isset($stable) && isset($unstable)) { break; } } } if ($basic) { // remote-list command if (!isset($latest)) { $latest = false; } if ($dostable) { // $state is not set if there are no releases if (isset($state) && $state == 'stable') { $ret[$package] = array('stable' => $latest); } else { $ret[$package] = array('stable' => '-n/a-'); } } else { $ret[$package] = array('stable' => $latest); } continue; } // list-all command if (!isset($unstable)) { $unstable = false; $state = 'stable'; if (isset($stable)) { $latest = $unstable = $stable; } } else { $latest = $unstable; } if (!isset($latest)) { $latest = false; } $deps = array(); if ($latest && isset($packageinfo['deps'])) { if (!is_array($packageinfo['deps']) || !isset($packageinfo['deps'][0]) ) { $packageinfo['deps'] = array($packageinfo['deps']); } $d = false; foreach ($packageinfo['deps'] as $dep) { if ($dep['v'] == $latest) { $d = unserialize($dep['d']); } } if ($d) { if (isset($d['required'])) { if (!class_exists('PEAR_PackageFile_v2')) { require_once 'PEAR/PackageFile/v2.php'; } if (!isset($pf)) { $pf = new PEAR_PackageFile_v2; } $pf->setDeps($d); $tdeps = $pf->getDeps(); } else { $tdeps = $d; } foreach ($tdeps as $dep) { if ($dep['type'] !== 'pkg') { continue; } $deps[] = $dep; } } } $info = array( 'stable' => $latest, 'summary' => $info['s'], 'description' => $info['d'], 'deps' => $deps, 'category' => $info['ca']['_content'], 'unstable' => $unstable, 'state' => $state ); $ret[$package] = $info; } } PEAR::popErrorHandling(); return $ret; } /** * List all categories of a REST server * * @param string $base base URL of the server * @return array of categorynames */ function listCategories($base, $channel = false) { $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel); if (PEAR::isError($categorylist)) { return $categorylist; } if (!is_array($categorylist) || !isset($categorylist['c'])) { return array(); } if (isset($categorylist['c']['_content'])) { // only 1 category $categorylist['c'] = array($categorylist['c']); } return $categorylist['c']; } /** * List packages in a category of a REST server * * @param string $base base URL of the server * @param string $category name of the category * @param boolean $info also download full package info * @return array of packagenames */ function listCategory($base, $category, $info = false, $channel = false) { if ($info == false) { $url = '%s'.'c/%s/packages.xml'; } else { $url = '%s'.'c/%s/packagesinfo.xml'; } $url = sprintf($url, $base, urlencode($category)); // gives '404 Not Found' error when category doesn't exist $packagelist = $this->_rest->retrieveData($url, false, false, $channel); if (PEAR::isError($packagelist)) { return $packagelist; } if (!is_array($packagelist)) { return array(); } if ($info == false) { if (!isset($packagelist['p'])) { return array(); } if (!is_array($packagelist['p']) || !isset($packagelist['p'][0])) { // only 1 pkg $packagelist = array($packagelist['p']); } else { $packagelist = $packagelist['p']; } return $packagelist; } // info == true if (!isset($packagelist['pi'])) { return array(); } if (!is_array($packagelist['pi']) || !isset($packagelist['pi'][0])) { // only 1 pkg $packagelist_pre = array($packagelist['pi']); } else { $packagelist_pre = $packagelist['pi']; } $packagelist = array(); foreach ($packagelist_pre as $i => $item) { // compatibility with r/.xml if (isset($item['a']['r'][0])) { // multiple releases $item['p']['v'] = $item['a']['r'][0]['v']; $item['p']['st'] = $item['a']['r'][0]['s']; } elseif (isset($item['a'])) { // first and only release $item['p']['v'] = $item['a']['r']['v']; $item['p']['st'] = $item['a']['r']['s']; } $packagelist[$i] = array('attribs' => $item['p']['r'], '_content' => $item['p']['n'], 'info' => $item['p']); } return $packagelist; } /** * Return an array containing all of the states that are more stable than * or equal to the passed in state * * @param string Release state * @param boolean Determines whether to include $state in the list * @return false|array False if $state is not a valid release state */ function betterStates($state, $include = false) { static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); $i = array_search($state, $states); if ($i === false) { return false; } if ($include) { $i--; } return array_slice($states, $i + 1); } } ?> PK!U  PEAR/Packager.phpnu[ * @author Tomas V. V. Cox * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR/Common.php'; require_once 'PEAR/PackageFile.php'; require_once 'System.php'; /** * Administration class used to make a PEAR release tarball. * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Packager extends PEAR_Common { /** * @var PEAR_Registry */ var $_registry; function package($pkgfile = null, $compress = true, $pkg2 = null) { // {{{ validate supplied package.xml file if (empty($pkgfile)) { $pkgfile = 'package.xml'; } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $pkg = new PEAR_PackageFile($this->config, $this->debug); $pf = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL); $main = &$pf; PEAR::staticPopErrorHandling(); if (PEAR::isError($pf)) { if (is_array($pf->getUserInfo())) { foreach ($pf->getUserInfo() as $error) { $this->log(0, 'Error: ' . $error['message']); } } $this->log(0, $pf->getMessage()); return $this->raiseError("Cannot package, errors in package file"); } foreach ($pf->getValidationWarnings() as $warning) { $this->log(1, 'Warning: ' . $warning['message']); } // }}} if ($pkg2) { $this->log(0, 'Attempting to process the second package file'); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL); PEAR::staticPopErrorHandling(); if (PEAR::isError($pf2)) { if (is_array($pf2->getUserInfo())) { foreach ($pf2->getUserInfo() as $error) { $this->log(0, 'Error: ' . $error['message']); } } $this->log(0, $pf2->getMessage()); return $this->raiseError("Cannot package, errors in second package file"); } foreach ($pf2->getValidationWarnings() as $warning) { $this->log(1, 'Warning: ' . $warning['message']); } if ($pf2->getPackagexmlVersion() == '2.0' || $pf2->getPackagexmlVersion() == '2.1' ) { $main = &$pf2; $other = &$pf; } else { $main = &$pf; $other = &$pf2; } if ($main->getPackagexmlVersion() != '2.0' && $main->getPackagexmlVersion() != '2.1') { return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' . 'only package together a package.xml 1.0 and package.xml 2.0'); } if ($other->getPackagexmlVersion() != '1.0') { return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' . 'only package together a package.xml 1.0 and package.xml 2.0'); } } $main->setLogger($this); if (!$main->validate(PEAR_VALIDATE_PACKAGING)) { foreach ($main->getValidationWarnings() as $warning) { $this->log(0, 'Error: ' . $warning['message']); } return $this->raiseError("Cannot package, errors in package"); } foreach ($main->getValidationWarnings() as $warning) { $this->log(1, 'Warning: ' . $warning['message']); } if ($pkg2) { $other->setLogger($this); $a = false; if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) { foreach ($other->getValidationWarnings() as $warning) { $this->log(0, 'Error: ' . $warning['message']); } foreach ($main->getValidationWarnings() as $warning) { $this->log(0, 'Error: ' . $warning['message']); } if ($a) { return $this->raiseError('The two package.xml files are not equivalent!'); } return $this->raiseError("Cannot package, errors in package"); } foreach ($other->getValidationWarnings() as $warning) { $this->log(1, 'Warning: ' . $warning['message']); } $gen = &$main->getDefaultGenerator(); $tgzfile = $gen->toTgz2($this, $other, $compress); if (PEAR::isError($tgzfile)) { return $tgzfile; } $dest_package = basename($tgzfile); $pkgdir = dirname($pkgfile); // TAR the Package ------------------------------------------- $this->log(1, "Package $dest_package done"); if (file_exists("$pkgdir/CVS/Root")) { $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion()); $cvstag = "RELEASE_$cvsversion"; $this->log(1, 'Tag the released code with "pear cvstag ' . $main->getPackageFile() . '"'); $this->log(1, "(or set the CVS tag $cvstag by hand)"); } elseif (file_exists("$pkgdir/.svn")) { $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion()); $svntag = $pf->getName() . "-$svnversion"; $this->log(1, 'Tag the released code with "pear svntag ' . $main->getPackageFile() . '"'); $this->log(1, "(or set the SVN tag $svntag by hand)"); } } else { // this branch is executed for single packagefile packaging $gen = &$pf->getDefaultGenerator(); $tgzfile = $gen->toTgz($this, $compress); if (PEAR::isError($tgzfile)) { $this->log(0, $tgzfile->getMessage()); return $this->raiseError("Cannot package, errors in package"); } $dest_package = basename($tgzfile); $pkgdir = dirname($pkgfile); // TAR the Package ------------------------------------------- $this->log(1, "Package $dest_package done"); if (file_exists("$pkgdir/CVS/Root")) { $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion()); $cvstag = "RELEASE_$cvsversion"; $this->log(1, "Tag the released code with `pear cvstag $pkgfile'"); $this->log(1, "(or set the CVS tag $cvstag by hand)"); } elseif (file_exists("$pkgdir/.svn")) { $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion()); $svntag = $pf->getName() . "-$svnversion"; $this->log(1, "Tag the released code with `pear svntag $pkgfile'"); $this->log(1, "(or set the SVN tag $svntag by hand)"); } } return $dest_package; } }PK!ZbgbgPEAR/Common.phpnu[ * @author Tomas V. V. Cox * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1.0 * @deprecated File deprecated since Release 1.4.0a1 */ /** * Include error handling */ require_once 'PEAR.php'; /** * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode() */ define('PEAR_COMMON_ERROR_INVALIDPHP', 1); define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+'); define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/'); // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1 define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?'); define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i'); // XXX far from perfect :-) define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?'); define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG . '\\z/'); define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+'); define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/'); // this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*'); define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i'); define('_PEAR_CHANNELS_PACKAGE_PREG', '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/(' . _PEAR_COMMON_PACKAGE_NAME_PREG . ')'); define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i'); define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::(' . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?'); define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/'); /** * List of temporary files and directories registered by * PEAR_Common::addTempFile(). * @var array */ $GLOBALS['_PEAR_Common_tempfiles'] = array(); /** * Valid maintainer roles * @var array */ $GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper'); /** * Valid release states * @var array */ $GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel'); /** * Valid dependency types * @var array */ $GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi'); /** * Valid dependency relations * @var array */ $GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne'); /** * Valid file roles * @var array */ $GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script'); /** * Valid replacement types * @var array */ $GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info'); /** * Valid "provide" types * @var array */ $GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api'); /** * Valid "provide" types * @var array */ $GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup'); /** * Class providing common functionality for PEAR administration classes. * @category pear * @package PEAR * @author Stig Bakken * @author Tomas V. V. Cox * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 * @deprecated This class will disappear, and its components will be spread * into smaller classes, like the AT&T breakup, as of Release 1.4.0a1 */ class PEAR_Common extends PEAR { /** * User Interface object (PEAR_Frontend_* class). If null, * the log() method uses print. * @var object */ var $ui = null; /** * Configuration object (PEAR_Config). * @var PEAR_Config */ var $config = null; /** stack of elements, gives some sort of XML context */ var $element_stack = array(); /** name of currently parsed XML element */ var $current_element; /** array of attributes of the currently parsed XML element */ var $current_attributes = array(); /** assoc with information about a package */ var $pkginfo = array(); var $current_path = null; /** * Flag variable used to mark a valid package file * @var boolean * @access private */ var $_validPackageFile; /** * PEAR_Common constructor * * @access public */ function __construct() { parent::__construct(); $this->config = &PEAR_Config::singleton(); $this->debug = $this->config->get('verbose'); } /** * PEAR_Common destructor * * @access private */ function _PEAR_Common() { // doesn't work due to bug #14744 //$tempfiles = $this->_tempfiles; $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles']; while ($file = array_shift($tempfiles)) { if (@is_dir($file)) { if (!class_exists('System')) { require_once 'System.php'; } System::rm(array('-rf', $file)); } elseif (file_exists($file)) { unlink($file); } } } /** * Register a temporary file or directory. When the destructor is * executed, all registered temporary files and directories are * removed. * * @param string $file name of file or directory * * @return void * * @access public */ static function addTempFile($file) { if (!class_exists('PEAR_Frontend')) { require_once 'PEAR/Frontend.php'; } PEAR_Frontend::addTempFile($file); } /** * Wrapper to System::mkDir(), creates a directory as well as * any necessary parent directories. * * @param string $dir directory name * * @return bool TRUE on success, or a PEAR error * * @access public */ function mkDirHier($dir) { // Only used in Installer - move it there ? $this->log(2, "+ create dir $dir"); if (!class_exists('System')) { require_once 'System.php'; } return System::mkDir(array('-p', $dir)); } /** * Logging method. * * @param int $level log level (0 is quiet, higher is noisier) * @param string $msg message to write to the log * * @return void */ public function log($level, $msg, $append_crlf = true) { if ($this->debug >= $level) { if (!class_exists('PEAR_Frontend')) { require_once 'PEAR/Frontend.php'; } $ui = &PEAR_Frontend::singleton(); if (is_a($ui, 'PEAR_Frontend')) { $ui->log($msg, $append_crlf); } else { print "$msg\n"; } } } /** * Create and register a temporary directory. * * @param string $tmpdir (optional) Directory to use as tmpdir. * Will use system defaults (for example * /tmp or c:\windows\temp) if not specified * * @return string name of created directory * * @access public */ function mkTempDir($tmpdir = '') { $topt = $tmpdir ? array('-t', $tmpdir) : array(); $topt = array_merge($topt, array('-d', 'pear')); if (!class_exists('System')) { require_once 'System.php'; } if (!$tmpdir = System::mktemp($topt)) { return false; } self::addTempFile($tmpdir); return $tmpdir; } /** * Set object that represents the frontend to be used. * * @param object Reference of the frontend object * @return void * @access public */ function setFrontendObject(&$ui) { $this->ui = &$ui; } /** * Return an array containing all of the states that are more stable than * or equal to the passed in state * * @param string Release state * @param boolean Determines whether to include $state in the list * @return false|array False if $state is not a valid release state */ static function betterStates($state, $include = false) { static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); $i = array_search($state, $states); if ($i === false) { return false; } if ($include) { $i--; } return array_slice($states, $i + 1); } /** * Get the valid roles for a PEAR package maintainer * * @return array */ public static function getUserRoles() { return $GLOBALS['_PEAR_Common_maintainer_roles']; } /** * Get the valid package release states of packages * * @return array */ public static function getReleaseStates() { return $GLOBALS['_PEAR_Common_release_states']; } /** * Get the implemented dependency types (php, ext, pkg etc.) * * @return array */ public static function getDependencyTypes() { return $GLOBALS['_PEAR_Common_dependency_types']; } /** * Get the implemented dependency relations (has, lt, ge etc.) * * @return array */ public static function getDependencyRelations() { return $GLOBALS['_PEAR_Common_dependency_relations']; } /** * Get the implemented file roles * * @return array */ public static function getFileRoles() { return $GLOBALS['_PEAR_Common_file_roles']; } /** * Get the implemented file replacement types in * * @return array */ public static function getReplacementTypes() { return $GLOBALS['_PEAR_Common_replacement_types']; } /** * Get the implemented file replacement types in * * @return array */ public static function getProvideTypes() { return $GLOBALS['_PEAR_Common_provide_types']; } /** * Get the implemented file replacement types in * * @return array */ public static function getScriptPhases() { return $GLOBALS['_PEAR_Common_script_phases']; } /** * Test whether a string contains a valid package name. * * @param string $name the package name to test * * @return bool * * @access public */ function validPackageName($name) { return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name); } /** * Test whether a string contains a valid package version. * * @param string $ver the package version to test * * @return bool * * @access public */ function validPackageVersion($ver) { return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver); } /** * @param string $path relative or absolute include path * @return boolean */ public static function isIncludeable($path) { if (file_exists($path) && is_readable($path)) { return true; } $ipath = explode(PATH_SEPARATOR, ini_get('include_path')); foreach ($ipath as $include) { $test = realpath($include . DIRECTORY_SEPARATOR . $path); if (file_exists($test) && is_readable($test)) { return true; } } return false; } function _postProcessChecks($pf) { if (!PEAR::isError($pf)) { return $this->_postProcessValidPackagexml($pf); } $errs = $pf->getUserinfo(); if (is_array($errs)) { foreach ($errs as $error) { $e = $this->raiseError($error['message'], $error['code'], null, null, $error); } } return $pf; } /** * Returns information about a package file. Expects the name of * a gzipped tar file as input. * * @param string $file name of .tgz file * * @return array array with package information * * @access public * @deprecated use PEAR_PackageFile->fromTgzFile() instead * */ function infoFromTgzFile($file) { $packagefile = new PEAR_PackageFile($this->config); $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL); return $this->_postProcessChecks($pf); } /** * Returns information about a package file. Expects the name of * a package xml file as input. * * @param string $descfile name of package xml file * * @return array array with package information * * @access public * @deprecated use PEAR_PackageFile->fromPackageFile() instead * */ function infoFromDescriptionFile($descfile) { $packagefile = new PEAR_PackageFile($this->config); $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); return $this->_postProcessChecks($pf); } /** * Returns information about a package file. Expects the contents * of a package xml file as input. * * @param string $data contents of package.xml file * * @return array array with package information * * @access public * @deprecated use PEAR_PackageFile->fromXmlstring() instead * */ function infoFromString($data) { $packagefile = new PEAR_PackageFile($this->config); $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false); return $this->_postProcessChecks($pf); } /** * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @return array */ function _postProcessValidPackagexml(&$pf) { if (!is_a($pf, 'PEAR_PackageFile_v2')) { $this->pkginfo = $pf->toArray(); return $this->pkginfo; } // sort of make this into a package.xml 1.0-style array // changelog is not converted to old format. $arr = $pf->toArray(true); $arr = array_merge($arr, $arr['old']); unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'], $arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'], $arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'], $arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'], $arr['helper'], $arr['contributor']); $arr['filelist'] = $pf->getFilelist(); $this->pkginfo = $arr; return $arr; } /** * Returns package information from different sources * * This method is able to extract information about a package * from a .tgz archive or from a XML package definition file. * * @access public * @param string Filename of the source ('package.xml', '.tgz') * @return string * @deprecated use PEAR_PackageFile->fromAnyFile() instead */ function infoFromAny($info) { if (is_string($info) && file_exists($info)) { $packagefile = new PEAR_PackageFile($this->config); $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL); if (PEAR::isError($pf)) { $errs = $pf->getUserinfo(); if (is_array($errs)) { foreach ($errs as $error) { $e = $this->raiseError($error['message'], $error['code'], null, null, $error); } } return $pf; } return $this->_postProcessValidPackagexml($pf); } return $info; } /** * Return an XML document based on the package info (as returned * by the PEAR_Common::infoFrom* methods). * * @param array $pkginfo package info * * @return string XML data * * @access public * @deprecated use a PEAR_PackageFile_v* object's generator instead */ function xmlFromInfo($pkginfo) { $config = &PEAR_Config::singleton(); $packagefile = new PEAR_PackageFile($config); $pf = &$packagefile->fromArray($pkginfo); $gen = &$pf->getDefaultGenerator(); return $gen->toXml(PEAR_VALIDATE_PACKAGING); } /** * Validate XML package definition file. * * @param string $info Filename of the package archive or of the * package definition file * @param array $errors Array that will contain the errors * @param array $warnings Array that will contain the warnings * @param string $dir_prefix (optional) directory where source files * may be found, or empty if they are not available * @access public * @return boolean * @deprecated use the validation of PEAR_PackageFile objects */ function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '') { $config = &PEAR_Config::singleton(); $packagefile = new PEAR_PackageFile($config); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); if (strpos($info, 'fromXmlString($info, PEAR_VALIDATE_NORMAL, ''); } else { $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL); } PEAR::staticPopErrorHandling(); if (PEAR::isError($pf)) { $errs = $pf->getUserinfo(); if (is_array($errs)) { foreach ($errs as $error) { if ($error['level'] == 'error') { $errors[] = $error['message']; } else { $warnings[] = $error['message']; } } } return false; } return true; } /** * Build a "provides" array from data returned by * analyzeSourceCode(). The format of the built array is like * this: * * array( * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), * ... * ) * * * @param array $srcinfo array with information about a source file * as returned by the analyzeSourceCode() method. * * @return void * * @access public * */ function buildProvidesArray($srcinfo) { $file = basename($srcinfo['source_file']); $pn = ''; if (isset($this->_packageName)) { $pn = $this->_packageName; } $pnl = strlen($pn); foreach ($srcinfo['declared_classes'] as $class) { $key = "class;$class"; if (isset($this->pkginfo['provides'][$key])) { continue; } $this->pkginfo['provides'][$key] = array('file'=> $file, 'type' => 'class', 'name' => $class); if (isset($srcinfo['inheritance'][$class])) { $this->pkginfo['provides'][$key]['extends'] = $srcinfo['inheritance'][$class]; } } foreach ($srcinfo['declared_methods'] as $class => $methods) { foreach ($methods as $method) { $function = "$class::$method"; $key = "function;$function"; if ($method[0] == '_' || !strcasecmp($method, $class) || isset($this->pkginfo['provides'][$key])) { continue; } $this->pkginfo['provides'][$key] = array('file'=> $file, 'type' => 'function', 'name' => $function); } } foreach ($srcinfo['declared_functions'] as $function) { $key = "function;$function"; if ($function[0] == '_' || isset($this->pkginfo['provides'][$key])) { continue; } if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; } $this->pkginfo['provides'][$key] = array('file'=> $file, 'type' => 'function', 'name' => $function); } } /** * Analyze the source code of the given PHP file * * @param string Filename of the PHP file * @return mixed * @access public */ static function analyzeSourceCode($file) { if (!class_exists('PEAR_PackageFile_v2_Validator')) { require_once 'PEAR/PackageFile/v2/Validator.php'; } $a = new PEAR_PackageFile_v2_Validator; return $a->analyzeSourceCode($file); } function detectDependencies($any, $status_callback = null) { if (!function_exists("token_get_all")) { return false; } if (PEAR::isError($info = $this->infoFromAny($any))) { return $this->raiseError($info); } if (!is_array($info)) { return false; } $deps = array(); $used_c = $decl_c = $decl_f = $decl_m = array(); foreach ($info['filelist'] as $file => $fa) { $tmp = $this->analyzeSourceCode($file); $used_c = @array_merge($used_c, $tmp['used_classes']); $decl_c = @array_merge($decl_c, $tmp['declared_classes']); $decl_f = @array_merge($decl_f, $tmp['declared_functions']); $decl_m = @array_merge($decl_m, $tmp['declared_methods']); $inheri = @array_merge($inheri, $tmp['inheritance']); } $used_c = array_unique($used_c); $decl_c = array_unique($decl_c); $undecl_c = array_diff($used_c, $decl_c); return array('used_classes' => $used_c, 'declared_classes' => $decl_c, 'declared_methods' => $decl_m, 'declared_functions' => $decl_f, 'undeclared_classes' => $undecl_c, 'inheritance' => $inheri, ); } /** * Download a file through HTTP. Considers suggested file name in * Content-disposition: header and can run a callback function for * different events. The callback will be called with two * parameters: the callback type, and parameters. The implemented * callback types are: * * 'setup' called at the very beginning, parameter is a UI object * that should be used for all output * 'message' the parameter is a string with an informational message * 'saveas' may be used to save with a different file name, the * parameter is the filename that is about to be used. * If a 'saveas' callback returns a non-empty string, * that file name will be used as the filename instead. * Note that $save_dir will not be affected by this, only * the basename of the file. * 'start' download is starting, parameter is number of bytes * that are expected, or -1 if unknown * 'bytesread' parameter is the number of bytes read so far * 'done' download is complete, parameter is the total number * of bytes read * 'connfailed' if the TCP connection fails, this callback is called * with array(host,port,errno,errmsg) * 'writefailed' if writing to disk fails, this callback is called * with array(destfile,errmsg) * * If an HTTP proxy has been configured (http_proxy PEAR_Config * setting), the proxy will be used. * * @param string $url the URL to download * @param object $ui PEAR_Frontend_* instance * @param object $config PEAR_Config instance * @param string $save_dir (optional) directory to save file in * @param mixed $callback (optional) function/method to call for status * updates * @param false|string|array $lastmodified header values to check against * for caching * use false to return the header * values from this download * @param false|array $accept Accept headers to send * @param false|string $channel Channel to use for retrieving * authentication * * @return mixed Returns the full path of the downloaded file or a PEAR * error on failure. If the error is caused by * socket-related errors, the error object will * have the fsockopen error code available through * getCode(). If caching is requested, then return the header * values. * If $lastmodified was given and the there are no changes, * boolean false is returned. * * @access public */ function downloadHttp( $url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null, $accept = false, $channel = false ) { if (!class_exists('PEAR_Downloader')) { require_once 'PEAR/Downloader.php'; } return PEAR_Downloader::_downloadHttp( $this, $url, $ui, $save_dir, $callback, $lastmodified, $accept, $channel ); } } require_once 'PEAR/Config.php'; require_once 'PEAR/PackageFile.php'; PK!$((PEAR/Registry.phpnu[ * @author Tomas V. V. Cox * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * for PEAR_Error */ require_once 'PEAR.php'; require_once 'PEAR/DependencyDB.php'; define('PEAR_REGISTRY_ERROR_LOCK', -2); define('PEAR_REGISTRY_ERROR_FORMAT', -3); define('PEAR_REGISTRY_ERROR_FILE', -4); define('PEAR_REGISTRY_ERROR_CONFLICT', -5); define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6); /** * Administration class used to maintain the installed package database. * @category pear * @package PEAR * @author Stig Bakken * @author Tomas V. V. Cox * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Registry extends PEAR { /** * File containing all channel information. * @var string */ var $channels = ''; /** Directory where registry files are stored. * @var string */ var $statedir = ''; /** File where the file map is stored * @var string */ var $filemap = ''; /** Directory where registry files for channels are stored. * @var string */ var $channelsdir = ''; /** Name of file used for locking the registry * @var string */ var $lockfile = ''; /** File descriptor used during locking * @var resource */ var $lock_fp = null; /** Mode used during locking * @var int */ var $lock_mode = 0; // XXX UNUSED /** Cache of package information. Structure: * array( * 'package' => array('id' => ... ), * ... ) * @var array */ var $pkginfo_cache = array(); /** Cache of file map. Structure: * array( '/path/to/file' => 'package', ... ) * @var array */ var $filemap_cache = array(); /** * @var false|PEAR_ChannelFile */ var $_pearChannel; /** * @var false|PEAR_ChannelFile */ var $_peclChannel; /** * @var false|PEAR_ChannelFile */ var $_docChannel; /** * @var PEAR_DependencyDB */ var $_dependencyDB; /** * @var PEAR_Config */ var $_config; /** * PEAR_Registry constructor. * * @param string (optional) PEAR install directory (for .php files) * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if * default values are not desired. Only used the very first time a PEAR * repository is initialized * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if * default values are not desired. Only used the very first time a PEAR * repository is initialized * * @access public */ function __construct($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false, $pecl_channel = false, $pear_metadata_dir = '') { parent::__construct(); $this->setInstallDir($pear_install_dir, $pear_metadata_dir); $this->_pearChannel = $pear_channel; $this->_peclChannel = $pecl_channel; $this->_config = false; } function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR, $pear_metadata_dir = '') { $ds = DIRECTORY_SEPARATOR; $this->install_dir = $pear_install_dir; if (!$pear_metadata_dir) { $pear_metadata_dir = $pear_install_dir; } $this->channelsdir = $pear_metadata_dir.$ds.'.channels'; $this->statedir = $pear_metadata_dir.$ds.'.registry'; $this->filemap = $pear_metadata_dir.$ds.'.filemap'; $this->lockfile = $pear_metadata_dir.$ds.'.lock'; } function hasWriteAccess() { if (!file_exists($this->install_dir)) { $dir = $this->install_dir; while ($dir && $dir != '.') { $olddir = $dir; $dir = dirname($dir); if ($dir != '.' && file_exists($dir)) { if (is_writeable($dir)) { return true; } return false; } if ($dir == $olddir) { // this can happen in safe mode return @is_writable($dir); } } return false; } return is_writeable($this->install_dir); } function setConfig(&$config, $resetInstallDir = true) { $this->_config = &$config; if ($resetInstallDir) { $this->setInstallDir($config->get('php_dir'), $config->get('metadata_dir')); } } function _initializeChannelDirs() { static $running = false; if (!$running) { $running = true; $ds = DIRECTORY_SEPARATOR; if (!is_dir($this->channelsdir) || !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') || !file_exists($this->channelsdir . $ds . '__uri.reg')) { if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { $pear_channel = $this->_pearChannel; if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) { if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $pear_channel = new PEAR_ChannelFile; $pear_channel->setAlias('pear'); $pear_channel->setServer('pear.php.net'); $pear_channel->setSummary('PHP Extension and Application Repository'); $pear_channel->setDefaultPEARProtocols(); $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/'); //$pear_channel->setBaseURL('REST1.4', 'http://pear.php.net/rest/'); } else { $pear_channel->setServer('pear.php.net'); $pear_channel->setAlias('pear'); } $pear_channel->validate(); $this->_addChannel($pear_channel); } if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) { $pecl_channel = $this->_peclChannel; if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) { if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $pecl_channel = new PEAR_ChannelFile; $pecl_channel->setAlias('pecl'); $pecl_channel->setServer('pecl.php.net'); $pecl_channel->setSummary('PHP Extension Community Library'); $pecl_channel->setDefaultPEARProtocols(); $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); } else { $pecl_channel->setServer('pecl.php.net'); $pecl_channel->setAlias('pecl'); } $pecl_channel->validate(); $this->_addChannel($pecl_channel); } if (!file_exists($this->channelsdir . $ds . 'doc.php.net.reg')) { $doc_channel = $this->_docChannel; if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate()) { if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $doc_channel = new PEAR_ChannelFile; $doc_channel->setAlias('phpdocs'); $doc_channel->setServer('doc.php.net'); $doc_channel->setSummary('PHP Documentation Team'); $doc_channel->setDefaultPEARProtocols(); $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/'); $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/'); $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/'); } else { $doc_channel->setServer('doc.php.net'); $doc_channel->setAlias('doc'); } $doc_channel->validate(); $this->_addChannel($doc_channel); } if (!file_exists($this->channelsdir . $ds . '__uri.reg')) { if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $private = new PEAR_ChannelFile; $private->setName('__uri'); $private->setDefaultPEARProtocols(); $private->setBaseURL('REST1.0', '****'); $private->setSummary('Pseudo-channel for static packages'); $this->_addChannel($private); } $this->_rebuildFileMap(); } $running = false; } } function _initializeDirs() { $ds = DIRECTORY_SEPARATOR; // XXX Compatibility code should be removed in the future // rename all registry files if any to lowercase if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) && $handle = opendir($this->statedir)) { $dest = $this->statedir . $ds; while (false !== ($file = readdir($handle))) { if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) { rename($dest . $file, $dest . strtolower($file)); } } closedir($handle); } $this->_initializeChannelDirs(); if (!file_exists($this->filemap)) { $this->_rebuildFileMap(); } $this->_initializeDepDB(); } function _initializeDepDB() { if (!isset($this->_dependencyDB)) { static $initializing = false; if (!$initializing) { $initializing = true; if (!$this->_config) { // never used? $file = OS_WINDOWS ? 'pear.ini' : '.pearrc'; $this->_config = new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR . $file); $this->_config->setRegistry($this); $this->_config->set('php_dir', $this->install_dir); } $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); if (PEAR::isError($this->_dependencyDB)) { // attempt to recover by removing the dep db if (file_exists($this->_config->get('metadata_dir', null, 'pear.php.net') . DIRECTORY_SEPARATOR . '.depdb')) { @unlink($this->_config->get('metadata_dir', null, 'pear.php.net') . DIRECTORY_SEPARATOR . '.depdb'); } $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); if (PEAR::isError($this->_dependencyDB)) { echo $this->_dependencyDB->getMessage(); echo 'Unrecoverable error'; exit(1); } } $initializing = false; } } } /** * PEAR_Registry destructor. Makes sure no locks are forgotten. * * @access private */ function _PEAR_Registry() { parent::_PEAR(); if (is_resource($this->lock_fp)) { $this->_unlock(); } } /** * Make sure the directory where we keep registry files exists. * * @return bool TRUE if directory exists, FALSE if it could not be * created * * @access private */ function _assertStateDir($channel = false) { if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { return $this->_assertChannelStateDir($channel); } static $init = false; if (!file_exists($this->statedir)) { if (!$this->hasWriteAccess()) { return false; } require_once 'System.php'; if (!System::mkdir(array('-p', $this->statedir))) { return $this->raiseError("could not create directory '{$this->statedir}'"); } $init = true; } elseif (!is_dir($this->statedir)) { return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' . 'it already exists and is not a directory'); } $ds = DIRECTORY_SEPARATOR; if (!file_exists($this->channelsdir)) { if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') || !file_exists($this->channelsdir . $ds . '__uri.reg')) { $init = true; } } elseif (!is_dir($this->channelsdir)) { return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' . 'it already exists and is not a directory'); } if ($init) { static $running = false; if (!$running) { $running = true; $this->_initializeDirs(); $running = false; $init = false; } } else { $this->_initializeDepDB(); } return true; } /** * Make sure the directory where we keep registry files exists for a non-standard channel. * * @param string channel name * @return bool TRUE if directory exists, FALSE if it could not be * created * * @access private */ function _assertChannelStateDir($channel) { $ds = DIRECTORY_SEPARATOR; if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { $this->_initializeChannelDirs(); } return $this->_assertStateDir($channel); } $channelDir = $this->_channelDirectoryName($channel); if (!is_dir($this->channelsdir) || !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { $this->_initializeChannelDirs(); } if (!file_exists($channelDir)) { if (!$this->hasWriteAccess()) { return false; } require_once 'System.php'; if (!System::mkdir(array('-p', $channelDir))) { return $this->raiseError("could not create directory '" . $channelDir . "'"); } } elseif (!is_dir($channelDir)) { return $this->raiseError("could not create directory '" . $channelDir . "', already exists and is not a directory"); } return true; } /** * Make sure the directory where we keep registry files for channels exists * * @return bool TRUE if directory exists, FALSE if it could not be * created * * @access private */ function _assertChannelDir() { if (!file_exists($this->channelsdir)) { if (!$this->hasWriteAccess()) { return false; } require_once 'System.php'; if (!System::mkdir(array('-p', $this->channelsdir))) { return $this->raiseError("could not create directory '{$this->channelsdir}'"); } } elseif (!is_dir($this->channelsdir)) { return $this->raiseError("could not create directory '{$this->channelsdir}" . "', it already exists and is not a directory"); } if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { if (!$this->hasWriteAccess()) { return false; } require_once 'System.php'; if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) { return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'"); } } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { return $this->raiseError("could not create directory '{$this->channelsdir}" . "/.alias', it already exists and is not a directory"); } return true; } /** * Get the name of the file where data for a given package is stored. * * @param string channel name, or false if this is a PEAR package * @param string package name * * @return string registry file name * * @access public */ function _packageFileName($package, $channel = false) { if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR . strtolower($package) . '.reg'; } return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg'; } /** * Get the name of the file where data for a given channel is stored. * @param string channel name * @return string registry file name */ function _channelFileName($channel, $noaliases = false) { if (!$noaliases) { if (file_exists($this->_getChannelAliasFileName($channel))) { $channel = implode('', file($this->_getChannelAliasFileName($channel))); } } return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($channel)) . '.reg'; } /** * @param string * @return string */ function _getChannelAliasFileName($alias) { return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' . DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt'; } /** * Get the name of a channel from its alias */ function _getChannelFromAlias($channel) { if (!$this->_channelExists($channel)) { if ($channel == 'pear.php.net') { return 'pear.php.net'; } if ($channel == 'pecl.php.net') { return 'pecl.php.net'; } if ($channel == 'doc.php.net') { return 'doc.php.net'; } if ($channel == '__uri') { return '__uri'; } return false; } $channel = strtolower($channel); if (file_exists($this->_getChannelAliasFileName($channel))) { // translate an alias to an actual channel return implode('', file($this->_getChannelAliasFileName($channel))); } return $channel; } /** * Get the alias of a channel from its alias or its name */ function _getAlias($channel) { if (!$this->_channelExists($channel)) { if ($channel == 'pear.php.net') { return 'pear'; } if ($channel == 'pecl.php.net') { return 'pecl'; } if ($channel == 'doc.php.net') { return 'phpdocs'; } return false; } $channel = $this->_getChannel($channel); if (PEAR::isError($channel)) { return $channel; } return $channel->getAlias(); } /** * Get the name of the file where data for a given package is stored. * * @param string channel name, or false if this is a PEAR package * @param string package name * * @return string registry file name * * @access public */ function _channelDirectoryName($channel) { if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { return $this->statedir; } $ch = $this->_getChannelFromAlias($channel); if (!$ch) { $ch = $channel; } return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' . str_replace('/', '_', $ch)); } function _openPackageFile($package, $mode, $channel = false) { if (!$this->_assertStateDir($channel)) { return null; } if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { return null; } $file = $this->_packageFileName($package, $channel); if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { return null; } $fp = @fopen($file, $mode); if (!$fp) { return null; } return $fp; } function _closePackageFile($fp) { fclose($fp); } function _openChannelFile($channel, $mode) { if (!$this->_assertChannelDir()) { return null; } if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { return null; } $file = $this->_channelFileName($channel); if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { return null; } $fp = @fopen($file, $mode); if (!$fp) { return null; } return $fp; } function _closeChannelFile($fp) { fclose($fp); } function _rebuildFileMap() { if (!class_exists('PEAR_Installer_Role')) { require_once 'PEAR/Installer/Role.php'; } $channels = $this->_listAllPackages(); $files = array(); foreach ($channels as $channel => $packages) { foreach ($packages as $package) { $version = $this->_packageInfo($package, 'version', $channel); $filelist = $this->_packageInfo($package, 'filelist', $channel); if (!is_array($filelist)) { continue; } foreach ($filelist as $name => $attrs) { if (isset($attrs['attribs'])) { $attrs = $attrs['attribs']; } // it is possible for conflicting packages in different channels to // conflict with data files/doc files if ($name == 'dirtree') { continue; } if (isset($attrs['role']) && !in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) { // these are not installed continue; } if (isset($attrs['role']) && !in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) { $attrs['baseinstalldir'] = $package; } if (isset($attrs['baseinstalldir'])) { $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; } else { $file = $name; } $file = preg_replace(',^/+,', '', $file); if ($channel != 'pear.php.net') { if (!isset($files[$attrs['role']])) { $files[$attrs['role']] = array(); } $files[$attrs['role']][$file] = array(strtolower($channel), strtolower($package)); } else { if (!isset($files[$attrs['role']])) { $files[$attrs['role']] = array(); } $files[$attrs['role']][$file] = strtolower($package); } } } } $this->_assertStateDir(); if (!$this->hasWriteAccess()) { return false; } $fp = @fopen($this->filemap, 'wb'); if (!$fp) { return false; } $this->filemap_cache = $files; fwrite($fp, serialize($files)); fclose($fp); return true; } function _readFileMap() { if (!file_exists($this->filemap)) { return array(); } $fp = @fopen($this->filemap, 'r'); if (!$fp) { $last_errormsg = ''; $last_error = error_get_last(); if (!empty($last_error['message'])) { $last_errormsg = $last_error['message']; } return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $last_errormsg); } clearstatcache(); $fsize = filesize($this->filemap); fclose($fp); $data = file_get_contents($this->filemap); $tmp = unserialize($data); if (!$tmp && $fsize > 7) { return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data); } $this->filemap_cache = $tmp; return true; } /** * Lock the registry. * * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN. * See flock manual for more information. * * @return bool TRUE on success, FALSE if locking failed, or a * PEAR error if some other error occurs (such as the * lock file not being writable). * * @access private */ function _lock($mode = LOCK_EX) { if (stristr(php_uname(), 'Windows 9')) { return true; } if ($mode != LOCK_UN && is_resource($this->lock_fp)) { // XXX does not check type of lock (LOCK_SH/LOCK_EX) return true; } if (!$this->_assertStateDir()) { if ($mode == LOCK_EX) { return $this->raiseError('Registry directory is not writeable by the current user'); } return true; } $open_mode = 'w'; // XXX People reported problems with LOCK_SH and 'w' if ($mode === LOCK_SH || $mode === LOCK_UN) { if (!file_exists($this->lockfile)) { touch($this->lockfile); } $open_mode = 'r'; } if (!is_resource($this->lock_fp)) { $this->lock_fp = @fopen($this->lockfile, $open_mode); } if (!is_resource($this->lock_fp)) { $this->lock_fp = null; return $this->raiseError("could not create lock file" . (isset($php_errormsg) ? ": " . $php_errormsg : "")); } if (!(int)flock($this->lock_fp, $mode)) { switch ($mode) { case LOCK_SH: $str = 'shared'; break; case LOCK_EX: $str = 'exclusive'; break; case LOCK_UN: $str = 'unlock'; break; default: $str = 'unknown'; break; } //is resource at this point, close it on error. fclose($this->lock_fp); $this->lock_fp = null; return $this->raiseError("could not acquire $str lock ($this->lockfile)", PEAR_REGISTRY_ERROR_LOCK); } return true; } function _unlock() { $ret = $this->_lock(LOCK_UN); if (is_resource($this->lock_fp)) { fclose($this->lock_fp); } $this->lock_fp = null; return $ret; } function _packageExists($package, $channel = false) { return file_exists($this->_packageFileName($package, $channel)); } /** * Determine whether a channel exists in the registry * * @param string Channel name * @param bool if true, then aliases will be ignored * @return boolean */ function _channelExists($channel, $noaliases = false) { $a = file_exists($this->_channelFileName($channel, $noaliases)); if (!$a && $channel == 'pear.php.net') { return true; } if (!$a && $channel == 'pecl.php.net') { return true; } if (!$a && $channel == 'doc.php.net') { return true; } return $a; } /** * Determine whether a mirror exists within the default channel in the registry * * @param string Channel name * @param string Mirror name * * @return boolean */ function _mirrorExists($channel, $mirror) { $data = $this->_channelInfo($channel); if (!isset($data['servers']['mirror'])) { return false; } foreach ($data['servers']['mirror'] as $m) { if ($m['attribs']['host'] == $mirror) { return true; } } return false; } /** * @param PEAR_ChannelFile Channel object * @param donotuse * @param string Last-Modified HTTP tag from remote request * @return boolean|PEAR_Error True on creation, false if it already exists */ function _addChannel($channel, $update = false, $lastmodified = false) { if (!is_a($channel, 'PEAR_ChannelFile')) { return false; } if (!$channel->validate()) { return false; } if (file_exists($this->_channelFileName($channel->getName()))) { if (!$update) { return false; } $checker = $this->_getChannel($channel->getName()); if (PEAR::isError($checker)) { return $checker; } if ($channel->getAlias() != $checker->getAlias()) { if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) { @unlink($this->_getChannelAliasFileName($checker->getAlias())); } } } else { if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net', 'doc.php.net'))) { return false; } } $ret = $this->_assertChannelDir(); if (PEAR::isError($ret)) { return $ret; } $ret = $this->_assertChannelStateDir($channel->getName()); if (PEAR::isError($ret)) { return $ret; } if ($channel->getAlias() != $channel->getName()) { if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) && $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) { $channel->setAlias($channel->getName()); } if (!$this->hasWriteAccess()) { return false; } $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w'); if (!$fp) { return false; } fwrite($fp, $channel->getName()); fclose($fp); } if (!$this->hasWriteAccess()) { return false; } $fp = @fopen($this->_channelFileName($channel->getName()), 'wb'); if (!$fp) { return false; } $info = $channel->toArray(); if ($lastmodified) { $info['_lastmodified'] = $lastmodified; } else { $info['_lastmodified'] = self::getSourceDateEpoch(); } fwrite($fp, serialize($info)); fclose($fp); return true; } /** * Deletion fails if there are any packages installed from the channel * @param string|PEAR_ChannelFile channel name * @return boolean|PEAR_Error True on deletion, false if it doesn't exist */ function _deleteChannel($channel) { if (!is_string($channel)) { if (!is_a($channel, 'PEAR_ChannelFile')) { return false; } if (!$channel->validate()) { return false; } $channel = $channel->getName(); } if ($this->_getChannelFromAlias($channel) == '__uri') { return false; } if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { return false; } if ($this->_getChannelFromAlias($channel) == 'doc.php.net') { return false; } if (!$this->_channelExists($channel)) { return false; } if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { return false; } $channel = $this->_getChannelFromAlias($channel); if ($channel == 'pear.php.net') { return false; } $test = $this->_listChannelPackages($channel); if (count($test)) { return false; } $test = @rmdir($this->_channelDirectoryName($channel)); if (!$test) { return false; } $file = $this->_getChannelAliasFileName($this->_getAlias($channel)); if (file_exists($file)) { $test = @unlink($file); if (!$test) { return false; } } $file = $this->_channelFileName($channel); $ret = true; if (file_exists($file)) { $ret = @unlink($file); } return $ret; } /** * Determine whether a channel exists in the registry * @param string Channel Alias * @return boolean */ function _isChannelAlias($alias) { return file_exists($this->_getChannelAliasFileName($alias)); } /** * @param string|null * @param string|null * @param string|null * @return array|null * @access private */ function _packageInfo($package = null, $key = null, $channel = 'pear.php.net') { if ($package === null) { if ($channel === null) { $channels = $this->_listChannels(); $ret = array(); foreach ($channels as $channel) { $channel = strtolower($channel); $ret[$channel] = array(); $packages = $this->_listPackages($channel); foreach ($packages as $package) { $ret[$channel][] = $this->_packageInfo($package, null, $channel); } } return $ret; } $ps = $this->_listPackages($channel); if (!count($ps)) { return array(); } return array_map(array(&$this, '_packageInfo'), $ps, array_fill(0, count($ps), null), array_fill(0, count($ps), $channel)); } $fp = $this->_openPackageFile($package, 'r', $channel); if ($fp === null) { return null; } clearstatcache(); $this->_closePackageFile($fp); $data = file_get_contents($this->_packageFileName($package, $channel)); $data = @unserialize($data); if ($key === null) { return $data; } // compatibility for package.xml version 2.0 if (isset($data['old'][$key])) { return $data['old'][$key]; } if (isset($data[$key])) { return $data[$key]; } return null; } /** * @param string Channel name * @param bool whether to strictly retrieve info of channels, not just aliases * @return array|null */ function _channelInfo($channel, $noaliases = false) { if (!$this->_channelExists($channel, $noaliases)) { return null; } $fp = $this->_openChannelFile($channel, 'r'); if ($fp === null) { return null; } clearstatcache(); $this->_closeChannelFile($fp); $data = file_get_contents($this->_channelFileName($channel)); $data = unserialize($data); return $data; } function _listChannels() { $channellist = array(); if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) { return array('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri'); } $dp = opendir($this->channelsdir); while ($ent = readdir($dp)) { if ($ent[0] == '.' || substr($ent, -4) != '.reg') { continue; } if ($ent == '__uri.reg') { $channellist[] = '__uri'; continue; } $channellist[] = str_replace('_', '/', substr($ent, 0, -4)); } closedir($dp); if (!in_array('pear.php.net', $channellist)) { $channellist[] = 'pear.php.net'; } if (!in_array('pecl.php.net', $channellist)) { $channellist[] = 'pecl.php.net'; } if (!in_array('doc.php.net', $channellist)) { $channellist[] = 'doc.php.net'; } if (!in_array('__uri', $channellist)) { $channellist[] = '__uri'; } natsort($channellist); return $channellist; } function _listPackages($channel = false) { if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { return $this->_listChannelPackages($channel); } if (!file_exists($this->statedir) || !is_dir($this->statedir)) { return array(); } $pkglist = array(); $dp = opendir($this->statedir); if (!$dp) { return $pkglist; } while ($ent = readdir($dp)) { if ($ent[0] == '.' || substr($ent, -4) != '.reg') { continue; } $pkglist[] = substr($ent, 0, -4); } closedir($dp); sort($pkglist); return $pkglist; } function _listChannelPackages($channel) { $pkglist = array(); if (!file_exists($this->_channelDirectoryName($channel)) || !is_dir($this->_channelDirectoryName($channel))) { return array(); } $dp = opendir($this->_channelDirectoryName($channel)); if (!$dp) { return $pkglist; } while ($ent = readdir($dp)) { if ($ent[0] == '.' || substr($ent, -4) != '.reg') { continue; } $pkglist[] = substr($ent, 0, -4); } closedir($dp); return $pkglist; } function _listAllPackages() { $ret = array(); foreach ($this->_listChannels() as $channel) { $ret[$channel] = $this->_listPackages($channel); } return $ret; } /** * Add an installed package to the registry * @param string package name * @param array package info (parsed by PEAR_Common::infoFrom*() methods) * @return bool success of saving * @access private */ function _addPackage($package, $info) { if ($this->_packageExists($package)) { return false; } $fp = $this->_openPackageFile($package, 'wb'); if ($fp === null) { return false; } $info['_lastmodified'] = self::getSourceDateEpoch(); fwrite($fp, serialize($info)); $this->_closePackageFile($fp); if (isset($info['filelist'])) { $this->_rebuildFileMap(); } return true; } /** * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @return bool * @access private */ function _addPackage2($info) { if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) { return false; } if (!$info->validate()) { if (class_exists('PEAR_Common')) { $ui = PEAR_Frontend::singleton(); if ($ui) { foreach ($info->getValidationWarnings() as $err) { $ui->log($err['message'], true); } } } return false; } $channel = $info->getChannel(); $package = $info->getPackage(); $save = $info; if ($this->_packageExists($package, $channel)) { return false; } if (!$this->_channelExists($channel, true)) { return false; } $info = $info->toArray(true); if (!$info) { return false; } $fp = $this->_openPackageFile($package, 'wb', $channel); if ($fp === null) { return false; } $info['_lastmodified'] = self::getSourceDateEpoch(); fwrite($fp, serialize($info)); $this->_closePackageFile($fp); $this->_rebuildFileMap(); return true; } /** * @param string Package name * @param array parsed package.xml 1.0 * @param bool this parameter is only here for BC. Don't use it. * @access private */ function _updatePackage($package, $info, $merge = true) { $oldinfo = $this->_packageInfo($package); if (empty($oldinfo)) { return false; } $fp = $this->_openPackageFile($package, 'w'); if ($fp === null) { return false; } if (is_object($info)) { $info = $info->toArray(); } $info['_lastmodified'] = self::getSourceDateEpoch(); $newinfo = $info; if ($merge) { $info = array_merge($oldinfo, $info); } else { $diff = $info; } fwrite($fp, serialize($info)); $this->_closePackageFile($fp); if (isset($newinfo['filelist'])) { $this->_rebuildFileMap(); } return true; } /** * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @return bool * @access private */ function _updatePackage2($info) { if (!$this->_packageExists($info->getPackage(), $info->getChannel())) { return false; } $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel()); if ($fp === null) { return false; } $save = $info; $info = $save->getArray(true); $info['_lastmodified'] = self::getSourceDateEpoch(); fwrite($fp, serialize($info)); $this->_closePackageFile($fp); $this->_rebuildFileMap(); return true; } /** * @param string Package name * @param string Channel name * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null * @access private */ function &_getPackage($package, $channel = 'pear.php.net') { $info = $this->_packageInfo($package, null, $channel); if ($info === null) { return $info; } $a = $this->_config; if (!$a) { $this->_config = new PEAR_Config; $this->_config->set('php_dir', $this->statedir); } if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } $pkg = new PEAR_PackageFile($this->_config); $pf = &$pkg->fromArray($info); return $pf; } /** * @param string channel name * @param bool whether to strictly retrieve channel names * @return PEAR_ChannelFile|PEAR_Error * @access private */ function &_getChannel($channel, $noaliases = false) { $ch = false; if ($this->_channelExists($channel, $noaliases)) { $chinfo = $this->_channelInfo($channel, $noaliases); if ($chinfo) { if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo); } } if ($ch) { if ($ch->validate()) { return $ch; } foreach ($ch->getErrors(true) as $err) { $message = $err['message'] . "\n"; } $ch = PEAR::raiseError($message); return $ch; } if ($this->_getChannelFromAlias($channel) == 'pear.php.net') { // the registry is not properly set up, so use defaults if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $pear_channel = new PEAR_ChannelFile; $pear_channel->setServer('pear.php.net'); $pear_channel->setAlias('pear'); $pear_channel->setSummary('PHP Extension and Application Repository'); $pear_channel->setDefaultPEARProtocols(); $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/'); return $pear_channel; } if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { // the registry is not properly set up, so use defaults if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $pear_channel = new PEAR_ChannelFile; $pear_channel->setServer('pecl.php.net'); $pear_channel->setAlias('pecl'); $pear_channel->setSummary('PHP Extension Community Library'); $pear_channel->setDefaultPEARProtocols(); $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); return $pear_channel; } if ($this->_getChannelFromAlias($channel) == 'doc.php.net') { // the registry is not properly set up, so use defaults if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $doc_channel = new PEAR_ChannelFile; $doc_channel->setServer('doc.php.net'); $doc_channel->setAlias('phpdocs'); $doc_channel->setSummary('PHP Documentation Team'); $doc_channel->setDefaultPEARProtocols(); $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/'); $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/'); $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/'); return $doc_channel; } if ($this->_getChannelFromAlias($channel) == '__uri') { // the registry is not properly set up, so use defaults if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $private = new PEAR_ChannelFile; $private->setName('__uri'); $private->setDefaultPEARProtocols(); $private->setBaseURL('REST1.0', '****'); $private->setSummary('Pseudo-channel for static packages'); return $private; } return $ch; } /** * @param string Package name * @param string Channel name * @return bool */ function packageExists($package, $channel = 'pear.php.net') { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_packageExists($package, $channel); $this->_unlock(); return $ret; } // }}} // {{{ channelExists() /** * @param string channel name * @param bool if true, then aliases will be ignored * @return bool */ function channelExists($channel, $noaliases = false) { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_channelExists($channel, $noaliases); $this->_unlock(); return $ret; } // }}} /** * @param string channel name mirror is in * @param string mirror name * * @return bool */ function mirrorExists($channel, $mirror) { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_mirrorExists($channel, $mirror); $this->_unlock(); return $ret; } // {{{ isAlias() /** * Determines whether the parameter is an alias of a channel * @param string * @return bool */ function isAlias($alias) { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_isChannelAlias($alias); $this->_unlock(); return $ret; } // }}} // {{{ packageInfo() /** * @param string|null * @param string|null * @param string * @return array|null */ function packageInfo($package = null, $key = null, $channel = 'pear.php.net') { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_packageInfo($package, $key, $channel); $this->_unlock(); return $ret; } // }}} // {{{ channelInfo() /** * Retrieve a raw array of channel data. * * Do not use this, instead use {@link getChannel()} for normal * operations. Array structure is undefined in this method * @param string channel name * @param bool whether to strictly retrieve information only on non-aliases * @return array|null|PEAR_Error */ function channelInfo($channel = null, $noaliases = false) { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_channelInfo($channel, $noaliases); $this->_unlock(); return $ret; } // }}} /** * @param string */ function channelName($channel) { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_getChannelFromAlias($channel); $this->_unlock(); return $ret; } /** * @param string */ function channelAlias($channel) { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_getAlias($channel); $this->_unlock(); return $ret; } // {{{ listPackages() function listPackages($channel = false) { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_listPackages($channel); $this->_unlock(); return $ret; } // }}} // {{{ listAllPackages() function listAllPackages() { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_listAllPackages(); $this->_unlock(); return $ret; } // }}} // {{{ listChannel() function listChannels() { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_listChannels(); $this->_unlock(); return $ret; } // }}} // {{{ addPackage() /** * Add an installed package to the registry * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object * that will be passed to {@link addPackage2()} * @param array package info (parsed by PEAR_Common::infoFrom*() methods) * @return bool success of saving */ function addPackage($package, $info) { if (is_object($info)) { return $this->addPackage2($info); } if (PEAR::isError($e = $this->_lock(LOCK_EX))) { return $e; } $ret = $this->_addPackage($package, $info); $this->_unlock(); if ($ret) { if (!class_exists('PEAR_PackageFile_v1')) { require_once 'PEAR/PackageFile/v1.php'; } $pf = new PEAR_PackageFile_v1; $pf->setConfig($this->_config); $pf->fromArray($info); $this->_dependencyDB->uninstallPackage($pf); $this->_dependencyDB->installPackage($pf); } return $ret; } // }}} // {{{ addPackage2() function addPackage2($info) { if (!is_object($info)) { return $this->addPackage($info['package'], $info); } if (PEAR::isError($e = $this->_lock(LOCK_EX))) { return $e; } $ret = $this->_addPackage2($info); $this->_unlock(); if ($ret) { $this->_dependencyDB->uninstallPackage($info); $this->_dependencyDB->installPackage($info); } return $ret; } // }}} // {{{ updateChannel() /** * For future expandibility purposes, separate this * @param PEAR_ChannelFile */ function updateChannel($channel, $lastmodified = null) { if ($channel->getName() == '__uri') { return false; } return $this->addChannel($channel, $lastmodified, true); } // }}} // {{{ deleteChannel() /** * Deletion fails if there are any packages installed from the channel * @param string|PEAR_ChannelFile channel name * @return boolean|PEAR_Error True on deletion, false if it doesn't exist */ function deleteChannel($channel) { if (PEAR::isError($e = $this->_lock(LOCK_EX))) { return $e; } $ret = $this->_deleteChannel($channel); $this->_unlock(); if ($ret && is_a($this->_config, 'PEAR_Config')) { $this->_config->setChannels($this->listChannels()); } return $ret; } // }}} // {{{ addChannel() /** * @param PEAR_ChannelFile Channel object * @param string Last-Modified header from HTTP for caching * @return boolean|PEAR_Error True on creation, false if it already exists */ function addChannel($channel, $lastmodified = false, $update = false) { if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate()) { return false; } if (PEAR::isError($e = $this->_lock(LOCK_EX))) { return $e; } $ret = $this->_addChannel($channel, $update, $lastmodified); $this->_unlock(); if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) { $this->_config->setChannels($this->listChannels()); } return $ret; } // }}} // {{{ deletePackage() function deletePackage($package, $channel = 'pear.php.net') { if (PEAR::isError($e = $this->_lock(LOCK_EX))) { return $e; } $file = $this->_packageFileName($package, $channel); $ret = file_exists($file) ? @unlink($file) : false; $this->_rebuildFileMap(); $this->_unlock(); $p = array('channel' => $channel, 'package' => $package); $this->_dependencyDB->uninstallPackage($p); return $ret; } // }}} // {{{ updatePackage() function updatePackage($package, $info, $merge = true) { if (is_object($info)) { return $this->updatePackage2($info, $merge); } if (PEAR::isError($e = $this->_lock(LOCK_EX))) { return $e; } $ret = $this->_updatePackage($package, $info, $merge); $this->_unlock(); if ($ret) { if (!class_exists('PEAR_PackageFile_v1')) { require_once 'PEAR/PackageFile/v1.php'; } $pf = new PEAR_PackageFile_v1; $pf->setConfig($this->_config); $pf->fromArray($this->packageInfo($package)); $this->_dependencyDB->uninstallPackage($pf); $this->_dependencyDB->installPackage($pf); } return $ret; } // }}} // {{{ updatePackage2() function updatePackage2($info) { if (!is_object($info)) { return $this->updatePackage($info['package'], $info, $merge); } if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) { return false; } if (PEAR::isError($e = $this->_lock(LOCK_EX))) { return $e; } $ret = $this->_updatePackage2($info); $this->_unlock(); if ($ret) { $this->_dependencyDB->uninstallPackage($info); $this->_dependencyDB->installPackage($info); } return $ret; } // }}} // {{{ getChannel() /** * @param string channel name * @param bool whether to strictly return raw channels (no aliases) * @return PEAR_ChannelFile|PEAR_Error */ function getChannel($channel, $noaliases = false) { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $ret = $this->_getChannel($channel, $noaliases); $this->_unlock(); if (!$ret) { return PEAR::raiseError('Unknown channel: ' . $channel); } return $ret; } // }}} // {{{ getPackage() /** * @param string package name * @param string channel name * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null */ function &getPackage($package, $channel = 'pear.php.net') { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $pf = &$this->_getPackage($package, $channel); $this->_unlock(); return $pf; } // }}} /** * Get PEAR_PackageFile_v[1/2] objects representing the contents of * a dependency group that are installed. * * This is used at uninstall-time * @param array * @return array|false */ function getInstalledGroup($group) { $ret = array(); if (isset($group['package'])) { if (!isset($group['package'][0])) { $group['package'] = array($group['package']); } foreach ($group['package'] as $package) { $depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; $p = &$this->getPackage($package['name'], $depchannel); if ($p) { $save = &$p; $ret[] = &$save; } } } if (isset($group['subpackage'])) { if (!isset($group['subpackage'][0])) { $group['subpackage'] = array($group['subpackage']); } foreach ($group['subpackage'] as $package) { $depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; $p = &$this->getPackage($package['name'], $depchannel); if ($p) { $save = &$p; $ret[] = &$save; } } } if (!count($ret)) { return false; } return $ret; } // {{{ getChannelValidator() /** * @param string channel name * @return PEAR_Validate|false */ function &getChannelValidator($channel) { $chan = $this->getChannel($channel); if (PEAR::isError($chan)) { return $chan; } $val = $chan->getValidationObject(); return $val; } // }}} // {{{ getChannels() /** * @param string channel name * @return array an array of PEAR_ChannelFile objects representing every installed channel */ function &getChannels() { $ret = array(); if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } foreach ($this->_listChannels() as $channel) { $e = &$this->_getChannel($channel); if (!$e || PEAR::isError($e)) { continue; } $ret[] = $e; } $this->_unlock(); return $ret; } // }}} // {{{ checkFileMap() /** * Test whether a file or set of files belongs to a package. * * If an array is passed in * @param string|array file path, absolute or relative to the pear * install dir * @param string|array name of PEAR package or array('package' => name, 'channel' => * channel) of a package that will be ignored * @param string API version - 1.1 will exclude any files belonging to a package * @param array private recursion variable * @return array|false which package and channel the file belongs to, or an empty * string if the file does not belong to an installed package, * or belongs to the second parameter's package */ function checkFileMap($path, $package = false, $api = '1.0', $attrs = false) { if (is_array($path)) { static $notempty; if (empty($notempty)) { if (!class_exists('PEAR_Installer_Role')) { require_once 'PEAR/Installer/Role.php'; } $notempty = function($a) { return !empty($a); }; } $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1])) : strtolower($package); $pkgs = array(); foreach ($path as $name => $attrs) { if (is_array($attrs)) { if (isset($attrs['install-as'])) { $name = $attrs['install-as']; } if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) { // these are not installed continue; } if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) { $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package; } if (isset($attrs['baseinstalldir'])) { $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name; } } $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs); if (PEAR::isError($pkgs[$name])) { return $pkgs[$name]; } } return array_filter($pkgs, $notempty); } if (empty($this->filemap_cache)) { if (PEAR::isError($e = $this->_lock(LOCK_SH))) { return $e; } $err = $this->_readFileMap(); $this->_unlock(); if (PEAR::isError($err)) { return $err; } } if (!$attrs) { $attrs = array('role' => 'php'); // any old call would be for PHP role only } if (isset($this->filemap_cache[$attrs['role']][$path])) { if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { return false; } return $this->filemap_cache[$attrs['role']][$path]; } $l = strlen($this->install_dir); if (substr($path, 0, $l) == $this->install_dir) { $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l)); } if (isset($this->filemap_cache[$attrs['role']][$path])) { if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { return false; } return $this->filemap_cache[$attrs['role']][$path]; } return false; } // }}} // {{{ flush() /** * Force a reload of the filemap * @since 1.5.0RC3 */ function flushFileMap() { $this->filemap_cache = null; clearstatcache(); // ensure that the next read gets the full, current filemap } // }}} // {{{ apiVersion() /** * Get the expected API version. Channels API is version 1.1, as it is backwards * compatible with 1.0 * @return string */ function apiVersion() { return '1.1'; } // }}} /** * Parse a package name, or validate a parsed package name array * @param string|array pass in an array of format * array( * 'package' => 'pname', * ['channel' => 'channame',] * ['version' => 'version',] * ['state' => 'state',] * ['group' => 'groupname']) * or a string of format * [channel://][channame/]pname[-version|-state][/group=groupname] * @return array|PEAR_Error */ function parsePackageName($param, $defaultchannel = 'pear.php.net') { $saveparam = $param; if (is_array($param)) { // convert to string for error messages $saveparam = $this->parsedPackageNameToString($param); // process the array if (!isset($param['package'])) { return PEAR::raiseError('parsePackageName(): array $param ' . 'must contain a valid package name in index "param"', 'package', null, null, $param); } if (!isset($param['uri'])) { if (!isset($param['channel'])) { $param['channel'] = $defaultchannel; } } else { $param['channel'] = '__uri'; } } else { $components = @parse_url((string) $param); if (isset($components['scheme'])) { if ($components['scheme'] == 'http') { // uri package $param = array('uri' => $param, 'channel' => '__uri'); } elseif($components['scheme'] != 'channel') { return PEAR::raiseError('parsePackageName(): only channel:// uris may ' . 'be downloaded, not "' . $param . '"', 'invalid', null, null, $param); } } if (!isset($components['path'])) { return PEAR::raiseError('parsePackageName(): array $param ' . 'must contain a valid package name in "' . $param . '"', 'package', null, null, $param); } if (isset($components['host'])) { // remove the leading "/" $components['path'] = substr($components['path'], 1); } if (!isset($components['scheme'])) { if (strpos($components['path'], '/') !== false) { if ($components['path'][0] == '/') { return PEAR::raiseError('parsePackageName(): this is not ' . 'a package name, it begins with "/" in "' . $param . '"', 'invalid', null, null, $param); } $parts = explode('/', $components['path']); $components['host'] = array_shift($parts); if (count($parts) > 1) { $components['path'] = array_pop($parts); $components['host'] .= '/' . implode('/', $parts); } else { $components['path'] = implode('/', $parts); } } else { $components['host'] = $defaultchannel; } } else { if (strpos($components['path'], '/')) { $parts = explode('/', $components['path']); $components['path'] = array_pop($parts); $components['host'] .= '/' . implode('/', $parts); } } if (is_array($param)) { $param['package'] = $components['path']; } else { $param = array( 'package' => $components['path'] ); if (isset($components['host'])) { $param['channel'] = $components['host']; } } if (isset($components['fragment'])) { $param['group'] = $components['fragment']; } if (isset($components['user'])) { $param['user'] = $components['user']; } if (isset($components['pass'])) { $param['pass'] = $components['pass']; } if (isset($components['query'])) { parse_str($components['query'], $param['opts']); } // check for extension $pathinfo = pathinfo($param['package']); if (isset($pathinfo['extension']) && in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) { $param['extension'] = $pathinfo['extension']; $param['package'] = substr($pathinfo['basename'], 0, strlen($pathinfo['basename']) - 4); } // check for version if (strpos($param['package'], '-')) { $test = explode('-', $param['package']); if (count($test) != 2) { return PEAR::raiseError('parsePackageName(): only one version/state ' . 'delimiter "-" is allowed in "' . $saveparam . '"', 'version', null, null, $param); } list($param['package'], $param['version']) = $test; } } // validation $info = $this->channelExists($param['channel']); if (PEAR::isError($info)) { return $info; } if (!$info) { return PEAR::raiseError('unknown channel "' . $param['channel'] . '" in "' . $saveparam . '"', 'channel', null, null, $param); } $chan = $this->getChannel($param['channel']); if (PEAR::isError($chan)) { return $chan; } if (!$chan) { return PEAR::raiseError("Exception: corrupt registry, could not " . "retrieve channel " . $param['channel'] . " information", 'registry', null, null, $param); } $param['channel'] = $chan->getName(); $validate = $chan->getValidationObject(); $vpackage = $chan->getValidationPackage(); // validate package name if (!$validate->validPackageName($param['package'], $vpackage['_content'])) { return PEAR::raiseError('parsePackageName(): invalid package name "' . $param['package'] . '" in "' . $saveparam . '"', 'package', null, null, $param); } if (isset($param['group'])) { if (!PEAR_Validate::validGroupName($param['group'])) { return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] . '" is not a valid group name in "' . $saveparam . '"', 'group', null, null, $param); } } if (isset($param['state'])) { if (!in_array(strtolower($param['state']), $validate->getValidStates())) { return PEAR::raiseError('parsePackageName(): state "' . $param['state'] . '" is not a valid state in "' . $saveparam . '"', 'state', null, null, $param); } } if (isset($param['version'])) { if (isset($param['state'])) { return PEAR::raiseError('parsePackageName(): cannot contain both ' . 'a version and a stability (state) in "' . $saveparam . '"', 'version/state', null, null, $param); } // check whether version is actually a state if (in_array(strtolower($param['version']), $validate->getValidStates())) { $param['state'] = strtolower($param['version']); unset($param['version']); } else { if (!$validate->validVersion($param['version'])) { return PEAR::raiseError('parsePackageName(): "' . $param['version'] . '" is neither a valid version nor a valid state in "' . $saveparam . '"', 'version/state', null, null, $param); } } } return $param; } /** * @param array * @return string */ function parsedPackageNameToString($parsed, $brief = false) { if (is_string($parsed)) { return $parsed; } if (is_object($parsed)) { $p = $parsed; $parsed = array( 'package' => $p->getPackage(), 'channel' => $p->getChannel(), 'version' => $p->getVersion(), ); } if (isset($parsed['uri'])) { return $parsed['uri']; } if ($brief) { if ($channel = $this->channelAlias($parsed['channel'])) { return $channel . '/' . $parsed['package']; } } $upass = ''; if (isset($parsed['user'])) { $upass = $parsed['user']; if (isset($parsed['pass'])) { $upass .= ':' . $parsed['pass']; } $upass = "$upass@"; } $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package']; if (isset($parsed['version']) || isset($parsed['state'])) { $ver = isset($parsed['version']) ? $parsed['version'] : ''; $ver .= isset($parsed['state']) ? $parsed['state'] : ''; $ret .= '-' . $ver; } if (isset($parsed['extension'])) { $ret .= '.' . $parsed['extension']; } if (isset($parsed['opts'])) { $ret .= '?'; foreach ($parsed['opts'] as $name => $value) { $parsed['opts'][$name] = "$name=$value"; } $ret .= implode('&', $parsed['opts']); } if (isset($parsed['group'])) { $ret .= '#' . $parsed['group']; } return $ret; } } PK! MdMdPEAR/Frontend/CLI.phpnu[ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR/Frontend.php'; /** * Command-line Frontend for the PEAR Installer * @category pear * @package PEAR * @author Stig Bakken * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Frontend_CLI extends PEAR_Frontend { /** * What type of user interface this frontend is for. * @var string * @access public */ var $type = 'CLI'; var $lp = ''; // line prefix var $params = array(); var $term = array( 'bold' => '', 'normal' => '', ); function __construct() { parent::__construct(); $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1 if (function_exists('posix_isatty') && !posix_isatty(1)) { // output is being redirected to a file or through a pipe } elseif ($term) { if (preg_match('/^(xterm|vt220|linux)/', $term)) { $this->term['bold'] = sprintf("%c%c%c%c", 27, 91, 49, 109); $this->term['normal'] = sprintf("%c%c%c", 27, 91, 109); } elseif (preg_match('/^vt100/', $term)) { $this->term['bold'] = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); $this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0); } } elseif (OS_WINDOWS) { // XXX add ANSI codes here } } /** * @param object PEAR_Error object */ function displayError($e) { return $this->_displayLine($e->getMessage()); } /** * @param object PEAR_Error object */ function displayFatalError($eobj) { $this->displayError($eobj); if (class_exists('PEAR_Config')) { $config = &PEAR_Config::singleton(); if ($config->get('verbose') > 5) { if (function_exists('debug_print_backtrace')) { debug_print_backtrace(); exit(1); } $raised = false; foreach (debug_backtrace() as $i => $frame) { if (!$raised) { if (isset($frame['class']) && strtolower($frame['class']) == 'pear' && strtolower($frame['function']) == 'raiseerror' ) { $raised = true; } else { continue; } } $frame['class'] = !isset($frame['class']) ? '' : $frame['class']; $frame['type'] = !isset($frame['type']) ? '' : $frame['type']; $frame['function'] = !isset($frame['function']) ? '' : $frame['function']; $frame['line'] = !isset($frame['line']) ? '' : $frame['line']; $this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]"); } } } exit(1); } /** * Instruct the runInstallScript method to skip a paramgroup that matches the * id value passed in. * * This method is useful for dynamically configuring which sections of a post-install script * will be run based on the user's setup, which is very useful for making flexible * post-install scripts without losing the cross-Frontend ability to retrieve user input * @param string */ function skipParamgroup($id) { $this->_skipSections[$id] = true; } function runPostinstallScripts(&$scripts) { foreach ($scripts as $i => $script) { $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj); } } /** * @param array $xml contents of postinstallscript tag * @param object $script post-installation script * @param string install|upgrade */ function runInstallScript($xml, &$script) { $this->_skipSections = array(); if (!is_array($xml) || !isset($xml['paramgroup'])) { $script->run(array(), '_default'); return; } $completedPhases = array(); if (!isset($xml['paramgroup'][0])) { $xml['paramgroup'] = array($xml['paramgroup']); } foreach ($xml['paramgroup'] as $group) { if (isset($this->_skipSections[$group['id']])) { // the post-install script chose to skip this section dynamically continue; } if (isset($group['name'])) { $paramname = explode('::', $group['name']); if ($lastgroup['id'] != $paramname[0]) { continue; } $group['name'] = $paramname[1]; if (!isset($answers)) { return; } if (isset($answers[$group['name']])) { switch ($group['conditiontype']) { case '=' : if ($answers[$group['name']] != $group['value']) { continue 2; } break; case '!=' : if ($answers[$group['name']] == $group['value']) { continue 2; } break; case 'preg_match' : if (!@preg_match('/' . $group['value'] . '/', $answers[$group['name']])) { continue 2; } break; default : return; } } } $lastgroup = $group; if (isset($group['instructions'])) { $this->_display($group['instructions']); } if (!isset($group['param'][0])) { $group['param'] = array($group['param']); } if (isset($group['param'])) { if (method_exists($script, 'postProcessPrompts')) { $prompts = $script->postProcessPrompts($group['param'], $group['id']); if (!is_array($prompts) || count($prompts) != count($group['param'])) { $this->outputData('postinstall', 'Error: post-install script did not ' . 'return proper post-processed prompts'); $prompts = $group['param']; } else { foreach ($prompts as $i => $var) { if (!is_array($var) || !isset($var['prompt']) || !isset($var['name']) || ($var['name'] != $group['param'][$i]['name']) || ($var['type'] != $group['param'][$i]['type']) ) { $this->outputData('postinstall', 'Error: post-install script ' . 'modified the variables or prompts, severe security risk. ' . 'Will instead use the defaults from the package.xml'); $prompts = $group['param']; } } } $answers = $this->confirmDialog($prompts); } else { $answers = $this->confirmDialog($group['param']); } } if ((isset($answers) && $answers) || !isset($group['param'])) { if (!isset($answers)) { $answers = array(); } array_unshift($completedPhases, $group['id']); if (!$script->run($answers, $group['id'])) { $script->run($completedPhases, '_undoOnError'); return; } } else { $script->run($completedPhases, '_undoOnError'); return; } } } /** * Ask for user input, confirm the answers and continue until the user is satisfied * @param array an array of arrays, format array('name' => 'paramname', 'prompt' => * 'text to display', 'type' => 'string'[, default => 'default value']) * @return array */ function confirmDialog($params) { $answers = $prompts = $types = array(); foreach ($params as $param) { $prompts[$param['name']] = $param['prompt']; $types[$param['name']] = $param['type']; $answers[$param['name']] = isset($param['default']) ? $param['default'] : ''; } $tried = false; do { if ($tried) { $i = 1; foreach ($answers as $var => $value) { if (!strlen($value)) { echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n"); } $i++; } } $answers = $this->userDialog('', $prompts, $types, $answers); $tried = true; } while (is_array($answers) && count(array_filter($answers)) != count($prompts)); return $answers; } function userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20) { if (!is_array($prompts)) { return array(); } $testprompts = array_keys($prompts); $result = $defaults; reset($prompts); if (count($prompts) === 1) { foreach ($prompts as $key => $prompt) { $type = $types[$key]; $default = @$defaults[$key]; print "$prompt "; if ($default) { print "[$default] "; } print ": "; $line = fgets(STDIN, 2048); $result[$key] = ($default && trim($line) == '') ? $default : trim($line); } return $result; } $first_run = true; while (true) { $descLength = max(array_map('strlen', $prompts)); $descFormat = "%-{$descLength}s"; $last = count($prompts); $i = 0; foreach ($prompts as $n => $var) { $res = isset($result[$n]) ? $result[$n] : null; printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res); } print "\n1-$last, 'all', 'abort', or Enter to continue: "; $tmp = trim(fgets(STDIN, 1024)); if (empty($tmp)) { break; } if ($tmp == 'abort') { return false; } if (isset($testprompts[(int)$tmp - 1])) { $var = $testprompts[(int)$tmp - 1]; $desc = $prompts[$var]; $current = @$result[$var]; print "$desc [$current] : "; $tmp = trim(fgets(STDIN, 1024)); if ($tmp !== '') { $result[$var] = $tmp; } } elseif ($tmp == 'all') { foreach ($prompts as $var => $desc) { $current = $result[$var]; print "$desc [$current] : "; $tmp = trim(fgets(STDIN, 1024)); if (trim($tmp) !== '') { $result[$var] = trim($tmp); } } } $first_run = false; } return $result; } function userConfirm($prompt, $default = 'yes') { trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR); static $positives = array('y', 'yes', 'on', '1'); static $negatives = array('n', 'no', 'off', '0'); print "$this->lp$prompt [$default] : "; $fp = fopen("php://stdin", "r"); $line = fgets($fp, 2048); fclose($fp); $answer = strtolower(trim($line)); if (empty($answer)) { $answer = $default; } if (in_array($answer, $positives)) { return true; } if (in_array($answer, $negatives)) { return false; } if (in_array($default, $positives)) { return true; } return false; } function outputData($data, $command = '_default') { switch ($command) { case 'channel-info': foreach ($data as $type => $section) { if ($type == 'main') { $section['data'] = array_values($section['data']); } $this->outputData($section); } break; case 'install': case 'upgrade': case 'upgrade-all': if (is_array($data) && isset($data['release_warnings'])) { $this->_displayLine(''); $this->_startTable(array( 'border' => false, 'caption' => 'Release Warnings' )); $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55))); $this->_endTable(); $this->_displayLine(''); } $this->_displayLine(is_array($data) ? $data['data'] : $data); break; case 'search': $this->_startTable($data); if (isset($data['headline']) && is_array($data['headline'])) { $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); } $packages = array(); foreach($data['data'] as $category) { foreach($category as $name => $pkg) { $packages[$pkg[0]] = $pkg; } } $p = array_keys($packages); natcasesort($p); foreach ($p as $name) { $this->_tableRow($packages[$name], null, array(1 => array('wrap' => 55))); } $this->_endTable(); break; case 'list-all': if (!isset($data['data'])) { $this->_displayLine('No packages in channel'); break; } $this->_startTable($data); if (isset($data['headline']) && is_array($data['headline'])) { $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); } $packages = array(); foreach($data['data'] as $category) { foreach($category as $name => $pkg) { $packages[$pkg[0]] = $pkg; } } $p = array_keys($packages); natcasesort($p); foreach ($p as $name) { $pkg = $packages[$name]; unset($pkg[4], $pkg[5]); $this->_tableRow($pkg, null, array(1 => array('wrap' => 55))); } $this->_endTable(); break; case 'config-show': $data['border'] = false; $opts = array( 0 => array('wrap' => 30), 1 => array('wrap' => 20), 2 => array('wrap' => 35) ); $this->_startTable($data); if (isset($data['headline']) && is_array($data['headline'])) { $this->_tableRow($data['headline'], array('bold' => true), $opts); } foreach ($data['data'] as $group) { foreach ($group as $value) { if ($value[2] == '') { $value[2] = ""; } $this->_tableRow($value, null, $opts); } } $this->_endTable(); break; case 'remote-info': $d = $data; $data = array( 'caption' => 'Package details:', 'border' => false, 'data' => array( array("Latest", $data['stable']), array("Installed", $data['installed']), array("Package", $data['name']), array("License", $data['license']), array("Category", $data['category']), array("Summary", $data['summary']), array("Description", $data['description']), ), ); if (isset($d['deprecated']) && $d['deprecated']) { $conf = &PEAR_Config::singleton(); $reg = $conf->getRegistry(); $name = $reg->parsedPackageNameToString($d['deprecated'], true); $data['data'][] = array('Deprecated! use', $name); } default: { if (is_array($data)) { $this->_startTable($data); $count = count($data['data'][0]); if ($count == 2) { $opts = array(0 => array('wrap' => 25), 1 => array('wrap' => 48) ); } elseif ($count == 3) { $opts = array(0 => array('wrap' => 30), 1 => array('wrap' => 20), 2 => array('wrap' => 35) ); } else { $opts = null; } if (isset($data['headline']) && is_array($data['headline'])) { $this->_tableRow($data['headline'], array('bold' => true), $opts); } if (is_array($data['data'])) { foreach($data['data'] as $row) { $this->_tableRow($row, null, $opts); } } else { $this->_tableRow(array($data['data']), null, $opts); } $this->_endTable(); } else { $this->_displayLine($data); } } } } function log($text, $append_crlf = true) { if ($append_crlf) { return $this->_displayLine($text); } return $this->_display($text); } function bold($text) { if (empty($this->term['bold'])) { return strtoupper($text); } return $this->term['bold'] . $text . $this->term['normal']; } function _displayHeading($title) { print $this->lp.$this->bold($title)."\n"; print $this->lp.str_repeat("=", strlen($title))."\n"; } function _startTable($params = array()) { $params['table_data'] = array(); $params['widest'] = array(); // indexed by column $params['highest'] = array(); // indexed by row $params['ncols'] = 0; $this->params = $params; } function _tableRow($columns, $rowparams = array(), $colparams = array()) { $highest = 1; for ($i = 0; $i < count($columns); $i++) { $col = &$columns[$i]; if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) { $col = wordwrap($col, $colparams[$i]['wrap']); } if (strpos($col, "\n") !== false) { $multiline = explode("\n", $col); $w = 0; foreach ($multiline as $n => $line) { $len = strlen($line); if ($len > $w) { $w = $len; } } $lines = count($multiline); } else { $w = strlen($col); } if (isset($this->params['widest'][$i])) { if ($w > $this->params['widest'][$i]) { $this->params['widest'][$i] = $w; } } else { $this->params['widest'][$i] = $w; } $tmp = count_chars($columns[$i], 1); // handle unix, mac and windows formats $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1; if ($lines > $highest) { $highest = $lines; } } if (count($columns) > $this->params['ncols']) { $this->params['ncols'] = count($columns); } $new_row = array( 'data' => $columns, 'height' => $highest, 'rowparams' => $rowparams, 'colparams' => $colparams, ); $this->params['table_data'][] = $new_row; } function _endTable() { extract($this->params); if (!empty($caption)) { $this->_displayHeading($caption); } if (count($table_data) === 0) { return; } if (!isset($width)) { $width = $widest; } else { for ($i = 0; $i < $ncols; $i++) { if (!isset($width[$i])) { $width[$i] = $widest[$i]; } } } $border = false; if (empty($border)) { $cellstart = ''; $cellend = ' '; $rowend = ''; $padrowend = false; $borderline = ''; } else { $cellstart = '| '; $cellend = ' '; $rowend = '|'; $padrowend = true; $borderline = '+'; foreach ($width as $w) { $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1); $borderline .= '+'; } } if ($borderline) { $this->_displayLine($borderline); } for ($i = 0; $i < count($table_data); $i++) { extract($table_data[$i]); if (!is_array($rowparams)) { $rowparams = array(); } if (!is_array($colparams)) { $colparams = array(); } $rowlines = array(); if ($height > 1) { for ($c = 0; $c < count($data); $c++) { $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]); if (count($rowlines[$c]) < $height) { $rowlines[$c] = array_pad($rowlines[$c], $height, ''); } } } else { for ($c = 0; $c < count($data); $c++) { $rowlines[$c] = array($data[$c]); } } for ($r = 0; $r < $height; $r++) { $rowtext = ''; for ($c = 0; $c < count($data); $c++) { if (isset($colparams[$c])) { $attribs = array_merge($rowparams, $colparams); } else { $attribs = $rowparams; } $w = isset($width[$c]) ? $width[$c] : 0; //$cell = $data[$c]; $cell = $rowlines[$c][$r]; $l = strlen($cell); if ($l > $w) { $cell = substr($cell, 0, $w); } if (isset($attribs['bold'])) { $cell = $this->bold($cell); } if ($l < $w) { // not using str_pad here because we may // add bold escape characters to $cell $cell .= str_repeat(' ', $w - $l); } $rowtext .= $cellstart . $cell . $cellend; } if (!$border) { $rowtext = rtrim($rowtext); } $rowtext .= $rowend; $this->_displayLine($rowtext); } } if ($borderline) { $this->_displayLine($borderline); } } function _displayLine($text) { print "$this->lp$text\n"; } function _display($text) { print $text; } } PK!  PEAR/Installer/Role/Doc.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {} ?>PK!/PEAR/Installer/Role/Cfg.xmlnu[ php extsrc extbin zendextsrc zendextbin 1 cfg_dir 1 PK!>1HPEAR/Installer/Role/Www.xmlnu[ php extsrc extbin zendextsrc zendextbin 1 www_dir 1 PK!?m  PEAR/Installer/Role/Php.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {} ?>PK!*Y| %%PEAR/Installer/Role/Man.phpnu[ * @copyright 2011 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version SVN: $Id: $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.10.0 */ /** * @category pear * @package PEAR * @author Hannes Magnusson * @copyright 2011 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.10.0 */ class PEAR_Installer_Role_Man extends PEAR_Installer_Role_Common {} ?> PK!BBPEAR/Installer/Role/Ext.xmlnu[ extbin zendextbin 1 ext_dir 1 1 PK!p""PEAR/Installer/Role/Src.xmlnu[ extsrc zendextsrc 1 temp_dir PK!h&P*PEAR/Installer/Role/Doc.xmlnu[ php extsrc extbin zendextsrc zendextbin 1 doc_dir PK!B] PEAR/Installer/Role/Test.xmlnu[ php extsrc extbin zendextsrc zendextbin 1 test_dir PK!zqPEAR/Installer/Role/Php.xmlnu[ php extsrc extbin zendextsrc zendextbin 1 php_dir 1 1 PK! PEAR/Installer/Role/Data.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {} ?>PK!0cPEAR/Installer/Role/Man.xmlnu[ php extsrc extbin zendextsrc zendextbin 1 man_dir 1 PK!K  PEAR/Installer/Role/Ext.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {} ?>PK!YPEAR/Installer/Role/Test.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {} ?>PK!@vаPEAR/Installer/Role/Script.xmlnu[ php extsrc extbin zendextsrc zendextbin 1 bin_dir 1 1 PK!fszPEAR/Installer/Role/Data.xmlnu[ php extsrc extbin zendextsrc zendextbin 1 data_dir PK!?GGPEAR/Installer/Role/Common.phpnu[ * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Base class for all installation roles. * * This class allows extensibility of file roles. Packages with complex * customization can now provide custom file roles along with the possibility of * adding configuration values to match. * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Installer_Role_Common { /** * @var PEAR_Config * @access protected */ var $config; /** * @param PEAR_Config */ function __construct(&$config) { $this->config = $config; } /** * Retrieve configuration information about a file role from its XML info * * @param string $role Role Classname, as in "PEAR_Installer_Role_Data" * @return array */ function getInfo($role) { if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) { return PEAR::raiseError('Unknown Role class: "' . $role . '"'); } return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role]; } /** * This is called for each file to set up the directories and files * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @param array attributes from the tag * @param string file name * @return array an array consisting of: * * 1 the original, pre-baseinstalldir installation directory * 2 the final installation directory * 3 the full path to the final location of the file * 4 the location of the pre-installation file */ function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null) { $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); if (PEAR::isError($roleInfo)) { return $roleInfo; } if (!$roleInfo['locationconfig']) { return false; } if ($roleInfo['honorsbaseinstall']) { $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer, $pkg->getChannel()); if (!empty($atts['baseinstalldir'])) { $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; } } elseif ($roleInfo['unusualbaseinstall']) { $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); if (!empty($atts['baseinstalldir'])) { $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; } } else { $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); } if (dirname($file) != '.' && empty($atts['install-as'])) { $dest_dir .= DIRECTORY_SEPARATOR . dirname($file); } if (empty($atts['install-as'])) { $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file); } else { $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as']; } $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file; // Clean up the DIRECTORY_SEPARATOR mess $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), array($dest_dir, $dest_file, $orig_file)); return array($save_destdir, $dest_dir, $dest_file, $orig_file); } /** * Get the name of the configuration variable that specifies the location of this file * @return string|false */ function getLocationConfig() { $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); if (PEAR::isError($roleInfo)) { return $roleInfo; } return $roleInfo['locationconfig']; } /** * Do any unusual setup here * @param PEAR_Installer * @param PEAR_PackageFile_v2 * @param array file attributes * @param string file name */ function setup(&$installer, $pkg, $atts, $file) { } function isExecutable() { $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); if (PEAR::isError($roleInfo)) { return $roleInfo; } return $roleInfo['executable']; } function isInstallable() { $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); if (PEAR::isError($roleInfo)) { return $roleInfo; } return $roleInfo['installable']; } function isExtension() { $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); if (PEAR::isError($roleInfo)) { return $roleInfo; } return $roleInfo['phpextension']; } } ?> PK!^D{  PEAR/Installer/Role/Www.phpnu[ * @copyright 2007-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.7.0 */ /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 2007-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.7.0 */ class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {} ?>PK!ƤPEAR/Installer/Role/Cfg.phpnu[ * @copyright 2007-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.7.0 */ /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 2007-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.7.0 */ class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common { /** * @var PEAR_Installer */ var $installer; /** * the md5 of the original file * * @var unknown_type */ var $md5 = null; /** * Do any unusual setup here * @param PEAR_Installer * @param PEAR_PackageFile_v2 * @param array file attributes * @param string file name */ function setup(&$installer, $pkg, $atts, $file) { $this->installer = &$installer; $reg = &$this->installer->config->getRegistry(); $package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel()); if ($package) { $filelist = $package->getFilelist(); if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) { $this->md5 = $filelist[$file]['md5sum']; } } } function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null) { $test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer); if (@file_exists($test[2]) && @file_exists($test[3])) { $md5 = md5_file($test[2]); // configuration has already been installed, check for mods if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) { // configuration has been modified, so save our version as // configfile-version $old = $test[2]; $test[2] .= '.new-' . $pkg->getVersion(); // backup original and re-install it PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $tmpcfg = $this->config->get('temp_dir'); $newloc = System::mkdir(array('-p', $tmpcfg)); if (!$newloc) { // try temp_dir $newloc = System::mktemp(array('-d')); if (!$newloc || PEAR::isError($newloc)) { PEAR::popErrorHandling(); return PEAR::raiseError('Could not save existing configuration file '. $old . ', unable to install. Please set temp_dir ' . 'configuration variable to a writeable location and try again'); } } else { $newloc = $tmpcfg; } $temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile'); if (!@copy($old, $temp_file)) { PEAR::popErrorHandling(); return PEAR::raiseError('Could not save existing configuration file '. $old . ', unable to install. Please set temp_dir ' . 'configuration variable to a writeable location and try again'); } PEAR::popErrorHandling(); $this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file"); $this->installer->addFileOperation('rename', array($temp_file, $old, false)); $this->installer->addFileOperation('delete', array($temp_file)); } } return $test; } }PK![PEAR/Installer/Role/Script.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {} ?>PK!srrPEAR/Installer/Role/Src.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common { function setup(&$installer, $pkg, $atts, $file) { $installer->source_files++; } } ?>PK!VZPEAR/Installer/Role.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * base class for installer roles */ require_once 'PEAR/Installer/Role/Common.php'; require_once 'PEAR/XMLParser.php'; /** * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Installer_Role { /** * Set up any additional configuration variables that file roles require * * Never call this directly, it is called by the PEAR_Config constructor * @param PEAR_Config */ public static function initializeConfig(&$config) { if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { PEAR_Installer_Role::registerRoles(); } foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) { if (!$info['config_vars']) { continue; } $config->_addConfigVars($class, $info['config_vars']); } } /** * @param PEAR_PackageFile_v2 * @param string role name * @param PEAR_Config * @return PEAR_Installer_Role_Common */ public static function &factory($pkg, $role, &$config) { if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { PEAR_Installer_Role::registerRoles(); } if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) { $a = false; return $a; } $a = 'PEAR_Installer_Role_' . ucfirst($role); if (!class_exists($a)) { require_once str_replace('_', '/', $a) . '.php'; } $b = new $a($config); return $b; } /** * Get a list of file roles that are valid for the particular release type. * * For instance, src files serve no purpose in regular php releases. * @param string * @param bool clear cache * @return array */ public static function getValidRoles($release, $clear = false) { if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { PEAR_Installer_Role::registerRoles(); } static $ret = array(); if ($clear) { $ret = array(); } if (isset($ret[$release])) { return $ret[$release]; } $ret[$release] = array(); foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { if (in_array($release, $okreleases['releasetypes'])) { $ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); } } return $ret[$release]; } /** * Get a list of roles that require their files to be installed * * Most roles must be installed, but src and package roles, for instance * are pseudo-roles. src files are compiled into a new extension. Package * roles are actually fully bundled releases of a package * @param bool clear cache * @return array */ public static function getInstallableRoles($clear = false) { if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { PEAR_Installer_Role::registerRoles(); } static $ret; if ($clear) { unset($ret); } if (isset($ret)) { return $ret; } $ret = array(); foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { if ($okreleases['installable']) { $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); } } return $ret; } /** * Return an array of roles that are affected by the baseinstalldir attribute * * Most roles ignore this attribute, and instead install directly into: * PackageName/filepath * so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php * @param bool clear cache * @return array */ public static function getBaseinstallRoles($clear = false) { if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { PEAR_Installer_Role::registerRoles(); } static $ret; if ($clear) { unset($ret); } if (isset($ret)) { return $ret; } $ret = array(); foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { if ($okreleases['honorsbaseinstall']) { $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); } } return $ret; } /** * Return an array of file roles that should be analyzed for PHP content at package time, * like the "php" role. * @param bool clear cache * @return array */ public static function getPhpRoles($clear = false) { if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { PEAR_Installer_Role::registerRoles(); } static $ret; if ($clear) { unset($ret); } if (isset($ret)) { return $ret; } $ret = array(); foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { if ($okreleases['phpfile']) { $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); } } return $ret; } /** * Scan through the Command directory looking for classes * and see what commands they implement. * @param string which directory to look for classes, defaults to * the Installer/Roles subdirectory of * the directory from where this file (__FILE__) is * included. * * @return bool TRUE on success, a PEAR error on failure */ public static function registerRoles($dir = null) { $GLOBALS['_PEAR_INSTALLER_ROLES'] = array(); $parser = new PEAR_XMLParser; if ($dir === null) { $dir = dirname(__FILE__) . '/Role'; } if (!file_exists($dir) || !is_dir($dir)) { return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory"); } $dp = @opendir($dir); if (empty($dp)) { return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg"); } while ($entry = readdir($dp)) { if ($entry[0] == '.' || substr($entry, -4) != '.xml') { continue; } $class = "PEAR_Installer_Role_".substr($entry, 0, -4); // List of roles if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) { $file = "$dir/$entry"; $parser->parse(file_get_contents($file)); $data = $parser->getData(); if (!is_array($data['releasetypes'])) { $data['releasetypes'] = array($data['releasetypes']); } $GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data; } } closedir($dp); ksort($GLOBALS['_PEAR_INSTALLER_ROLES']); PEAR_Installer_Role::getBaseinstallRoles(true); PEAR_Installer_Role::getInstallableRoles(true); PEAR_Installer_Role::getPhpRoles(true); PEAR_Installer_Role::getValidRoles('****', true); return true; } }PK!{ ))PEAR/Downloader/Package.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Error code when parameter initialization fails because no releases * exist within preferred_state, but releases do exist */ define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003); /** * Error code when parameter initialization fails because no releases * exist that will work with the existing PHP version */ define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004); /** * Coordinates download parameters and manages their dependencies * prior to downloading them. * * Input can come from three sources: * * - local files (archives or package.xml) * - remote files (downloadable urls) * - abstract package names * * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the * format returned of dependencies is slightly different from that used in package.xml. * * This class hides the differences between these elements, and makes automatic * dependency resolution a piece of cake. It also manages conflicts when * two classes depend on incompatible dependencies, or differing versions of the same * package dependency. In addition, download will not be attempted if the php version is * not supported, PEAR installer version is not supported, or non-PECL extensions are not * installed. * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Downloader_Package { /** * @var PEAR_Downloader */ var $_downloader; /** * @var PEAR_Config */ var $_config; /** * @var PEAR_Registry */ var $_registry; /** * Used to implement packagingroot properly * @var PEAR_Registry */ var $_installRegistry; /** * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2 */ var $_packagefile; /** * @var array */ var $_parsedname; /** * @var array */ var $_downloadURL; /** * @var array */ var $_downloadDeps = array(); /** * @var boolean */ var $_valid = false; /** * @var boolean */ var $_analyzed = false; /** * if this or a parent package was invoked with Package-state, this is set to the * state variable. * * This allows temporary reassignment of preferred_state for a parent package and all of * its dependencies. * @var string|false */ var $_explicitState = false; /** * If this package is invoked with Package#group, this variable will be true */ var $_explicitGroup = false; /** * Package type local|url * @var string */ var $_type; /** * Contents of package.xml, if downloaded from a remote channel * @var string|false * @access private */ var $_rawpackagefile; /** * @var boolean * @access private */ var $_validated = false; /** * @param PEAR_Downloader */ function __construct(&$downloader) { $this->_downloader = &$downloader; $this->_config = &$this->_downloader->config; $this->_registry = &$this->_config->getRegistry(); $options = $downloader->getOptions(); if (isset($options['packagingroot'])) { $this->_config->setInstallRoot($options['packagingroot']); $this->_installRegistry = &$this->_config->getRegistry(); $this->_config->setInstallRoot(false); } else { $this->_installRegistry = &$this->_registry; } $this->_valid = $this->_analyzed = false; } /** * Parse the input and determine whether this is a local file, a remote uri, or an * abstract package name. * * This is the heart of the PEAR_Downloader_Package(), and is used in * {@link PEAR_Downloader::download()} * @param string * @return bool|PEAR_Error */ function initialize($param) { $origErr = $this->_fromFile($param); if ($this->_valid) { return true; } $options = $this->_downloader->getOptions(); if (isset($options['offline'])) { if (PEAR::isError($origErr) && !isset($options['soft'])) { foreach ($origErr->getUserInfo() as $userInfo) { if (isset($userInfo['message'])) { $this->_downloader->log(0, $userInfo['message']); } } $this->_downloader->log(0, $origErr->getMessage()); } return PEAR::raiseError('Cannot download non-local package "' . $param . '"'); } $err = $this->_fromUrl($param); if (PEAR::isError($err) || !$this->_valid) { if ($this->_type == 'url') { if (PEAR::isError($err) && !isset($options['soft'])) { $this->_downloader->log(0, $err->getMessage()); } return PEAR::raiseError("Invalid or missing remote package file"); } $err = $this->_fromString($param); if (PEAR::isError($err) || !$this->_valid) { if (PEAR::isError($err) && $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) { return false; // instruct the downloader to silently skip } if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) { if (is_array($origErr->getUserInfo())) { foreach ($origErr->getUserInfo() as $err) { if (is_array($err)) { $err = $err['message']; } if (!isset($options['soft'])) { $this->_downloader->log(0, $err); } } } if (!isset($options['soft'])) { $this->_downloader->log(0, $origErr->getMessage()); } if (is_array($param)) { $param = $this->_registry->parsedPackageNameToString($param, true); } if (!isset($options['soft'])) { $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file"); } // Passing no message back - already logged above return PEAR::raiseError(); } if (PEAR::isError($err) && !isset($options['soft'])) { $this->_downloader->log(0, $err->getMessage()); } if (is_array($param)) { $param = $this->_registry->parsedPackageNameToString($param, true); } if (!isset($options['soft'])) { $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file"); } // Passing no message back - already logged above return PEAR::raiseError(); } } return true; } /** * Retrieve any non-local packages * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error */ function &download() { if (isset($this->_packagefile)) { return $this->_packagefile; } if (isset($this->_downloadURL['url'])) { $this->_isvalid = false; $info = $this->getParsedPackage(); foreach ($info as $i => $p) { $info[$i] = strtolower($p); } $err = $this->_fromUrl($this->_downloadURL['url'], $this->_registry->parsedPackageNameToString($this->_parsedname, true)); $newinfo = $this->getParsedPackage(); foreach ($newinfo as $i => $p) { $newinfo[$i] = strtolower($p); } if ($info != $newinfo) { do { if ($info['channel'] == 'pecl.php.net' && $newinfo['channel'] == 'pear.php.net') { $info['channel'] = 'pear.php.net'; if ($info == $newinfo) { // skip the channel check if a pecl package says it's a PEAR package break; } } if ($info['channel'] == 'pear.php.net' && $newinfo['channel'] == 'pecl.php.net') { $info['channel'] = 'pecl.php.net'; if ($info == $newinfo) { // skip the channel check if a pecl package says it's a PEAR package break; } } return PEAR::raiseError('CRITICAL ERROR: We are ' . $this->_registry->parsedPackageNameToString($info) . ', but the file ' . 'downloaded claims to be ' . $this->_registry->parsedPackageNameToString($this->getParsedPackage())); } while (false); } if (PEAR::isError($err) || !$this->_valid) { return $err; } } $this->_type = 'local'; return $this->_packagefile; } function &getPackageFile() { return $this->_packagefile; } function &getDownloader() { return $this->_downloader; } function getType() { return $this->_type; } /** * Like {@link initialize()}, but operates on a dependency */ function fromDepURL($dep) { $this->_downloadURL = $dep; if (isset($dep['uri'])) { $options = $this->_downloader->getOptions(); if (!extension_loaded("zlib") || isset($options['nocompress'])) { $ext = '.tar'; } else { $ext = '.tgz'; } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $err = $this->_fromUrl($dep['uri'] . $ext); PEAR::popErrorHandling(); if (PEAR::isError($err)) { if (!isset($options['soft'])) { $this->_downloader->log(0, $err->getMessage()); } return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' . 'cannot download'); } } else { $this->_parsedname = array( 'package' => $dep['info']->getPackage(), 'channel' => $dep['info']->getChannel(), 'version' => $dep['version'] ); if (!isset($dep['nodefault'])) { $this->_parsedname['group'] = 'default'; // download the default dependency group $this->_explicitGroup = false; } $this->_rawpackagefile = $dep['raw']; } } function detectDependencies($params) { $options = $this->_downloader->getOptions(); if (isset($options['downloadonly'])) { return; } if (isset($options['offline'])) { $this->_downloader->log(3, 'Skipping dependency download check, --offline specified'); return; } $pname = $this->getParsedPackage(); if (!$pname) { return; } $deps = $this->getDeps(); if (!$deps) { return; } if (isset($deps['required'])) { // package.xml 2.0 return $this->_detect2($deps, $pname, $options, $params); } return $this->_detect1($deps, $pname, $options, $params); } function setValidated() { $this->_validated = true; } function alreadyValidated() { return $this->_validated; } /** * Remove packages to be downloaded that are already installed * @param array of PEAR_Downloader_Package objects */ public static function removeInstalled(&$params) { if (!isset($params[0])) { return; } $options = $params[0]->_downloader->getOptions(); if (!isset($options['downloadonly'])) { foreach ($params as $i => $param) { $package = $param->getPackage(); $channel = $param->getChannel(); // remove self if already installed with this version // this does not need any pecl magic - we only remove exact matches if ($param->_installRegistry->packageExists($package, $channel)) { $packageVersion = $param->_installRegistry->packageInfo($package, 'version', $channel); if (version_compare($packageVersion, $param->getVersion(), '==')) { if (!isset($options['force']) && !isset($options['packagingroot'])) { $info = $param->getParsedPackage(); unset($info['version']); unset($info['state']); if (!isset($options['soft'])) { $param->_downloader->log(1, 'Skipping package "' . $param->getShortName() . '", already installed as version ' . $packageVersion); } $params[$i] = false; } } elseif (!isset($options['force']) && !isset($options['upgrade']) && !isset($options['soft']) && !isset($options['packagingroot'])) { $info = $param->getParsedPackage(); $param->_downloader->log(1, 'Skipping package "' . $param->getShortName() . '", already installed as version ' . $packageVersion); $params[$i] = false; } } } } PEAR_Downloader_Package::removeDuplicates($params); } function _detect2($deps, $pname, $options, $params) { $this->_downloadDeps = array(); $groupnotfound = false; foreach (array('package', 'subpackage') as $packagetype) { // get required dependency group if (isset($deps['required'][$packagetype])) { if (isset($deps['required'][$packagetype][0])) { foreach ($deps['required'][$packagetype] as $dep) { if (isset($dep['conflicts'])) { // skip any package that this package conflicts with continue; } $ret = $this->_detect2Dep($dep, $pname, 'required', $params); if (is_array($ret)) { $this->_downloadDeps[] = $ret; } elseif (PEAR::isError($ret) && !isset($options['soft'])) { $this->_downloader->log(0, $ret->getMessage()); } } } else { $dep = $deps['required'][$packagetype]; if (!isset($dep['conflicts'])) { // skip any package that this package conflicts with $ret = $this->_detect2Dep($dep, $pname, 'required', $params); if (is_array($ret)) { $this->_downloadDeps[] = $ret; } elseif (PEAR::isError($ret) && !isset($options['soft'])) { $this->_downloader->log(0, $ret->getMessage()); } } } } // get optional dependency group, if any if (isset($deps['optional'][$packagetype])) { $skipnames = array(); if (!isset($deps['optional'][$packagetype][0])) { $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]); } foreach ($deps['optional'][$packagetype] as $dep) { $skip = false; if (!isset($options['alldeps'])) { $dep['package'] = $dep['name']; if (!isset($options['soft'])) { $this->_downloader->log(3, 'Notice: package "' . $this->_registry->parsedPackageNameToString($this->getParsedPackage(), true) . '" optional dependency "' . $this->_registry->parsedPackageNameToString(array('package' => $dep['name'], 'channel' => 'pear.php.net'), true) . '" will not be automatically downloaded'); } $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true); $skip = true; unset($dep['package']); } $ret = $this->_detect2Dep($dep, $pname, 'optional', $params); if (PEAR::isError($ret) && !isset($options['soft'])) { $this->_downloader->log(0, $ret->getMessage()); } if (!$ret) { $dep['package'] = $dep['name']; $skip = count($skipnames) ? $skipnames[count($skipnames) - 1] : ''; if ($skip == $this->_registry->parsedPackageNameToString($dep, true)) { array_pop($skipnames); } } if (!$skip && is_array($ret)) { $this->_downloadDeps[] = $ret; } } if (count($skipnames)) { if (!isset($options['soft'])) { $this->_downloader->log(1, 'Did not download optional dependencies: ' . implode(', ', $skipnames) . ', use --alldeps to download automatically'); } } } // get requested dependency group, if any $groupname = $this->getGroup(); $explicit = $this->_explicitGroup; if (!$groupname) { if (!$this->canDefault()) { continue; } $groupname = 'default'; // try the default dependency group } if ($groupnotfound) { continue; } if (isset($deps['group'])) { if (isset($deps['group']['attribs'])) { if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) { $group = $deps['group']; } elseif ($explicit) { if (!isset($options['soft'])) { $this->_downloader->log(0, 'Warning: package "' . $this->_registry->parsedPackageNameToString($pname, true) . '" has no dependency ' . 'group named "' . $groupname . '"'); } $groupnotfound = true; continue; } } else { $found = false; foreach ($deps['group'] as $group) { if (strtolower($group['attribs']['name']) == strtolower($groupname)) { $found = true; break; } } if (!$found) { if ($explicit) { if (!isset($options['soft'])) { $this->_downloader->log(0, 'Warning: package "' . $this->_registry->parsedPackageNameToString($pname, true) . '" has no dependency ' . 'group named "' . $groupname . '"'); } } $groupnotfound = true; continue; } } } if (isset($group) && isset($group[$packagetype])) { if (isset($group[$packagetype][0])) { foreach ($group[$packagetype] as $dep) { $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' . $group['attribs']['name'] . '"', $params); if (is_array($ret)) { $this->_downloadDeps[] = $ret; } elseif (PEAR::isError($ret) && !isset($options['soft'])) { $this->_downloader->log(0, $ret->getMessage()); } } } else { $ret = $this->_detect2Dep($group[$packagetype], $pname, 'dependency group "' . $group['attribs']['name'] . '"', $params); if (is_array($ret)) { $this->_downloadDeps[] = $ret; } elseif (PEAR::isError($ret) && !isset($options['soft'])) { $this->_downloader->log(0, $ret->getMessage()); } } } } } function _detect2Dep($dep, $pname, $group, $params) { if (isset($dep['conflicts'])) { return true; } $options = $this->_downloader->getOptions(); if (isset($dep['uri'])) { return array('uri' => $dep['uri'], 'dep' => $dep);; } $testdep = $dep; $testdep['package'] = $dep['name']; if (PEAR_Downloader_Package::willDownload($testdep, $params)) { $dep['package'] = $dep['name']; if (!isset($options['soft'])) { $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group . ' dependency "' . $this->_registry->parsedPackageNameToString($dep, true) . '", will be installed'); } return false; } $options = $this->_downloader->getOptions(); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); if ($this->_explicitState) { $pname['state'] = $this->_explicitState; } $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); if (PEAR::isError($url)) { PEAR::popErrorHandling(); return $url; } $dep['package'] = $dep['name']; $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' && !isset($options['alldeps']), true); PEAR::popErrorHandling(); if (PEAR::isError($ret)) { if (!isset($options['soft'])) { $this->_downloader->log(0, $ret->getMessage()); } return false; } // check to see if a dep is already installed and is the same or newer if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) { $oper = 'has'; } else { $oper = 'gt'; } // do not try to move this before getDepPackageDownloadURL // we can't determine whether upgrade is necessary until we know what // version would be downloaded if (!isset($options['force']) && $this->isInstalled($ret, $oper)) { $version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']); $dep['package'] = $dep['name']; if (!isset($options['soft'])) { $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . ' dependency "' . $this->_registry->parsedPackageNameToString($dep, true) . '" version ' . $url['version'] . ', already installed as version ' . $version); } return false; } if (isset($dep['nodefault'])) { $ret['nodefault'] = true; } return $ret; } function _detect1($deps, $pname, $options, $params) { $this->_downloadDeps = array(); $skipnames = array(); foreach ($deps as $dep) { $nodownload = false; if (isset ($dep['type']) && $dep['type'] === 'pkg') { $dep['channel'] = 'pear.php.net'; $dep['package'] = $dep['name']; switch ($dep['rel']) { case 'not' : continue 2; case 'ge' : case 'eq' : case 'gt' : case 'has' : $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? 'required' : 'optional'; if (PEAR_Downloader_Package::willDownload($dep, $params)) { $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group . ' dependency "' . $this->_registry->parsedPackageNameToString($dep, true) . '", will be installed'); continue 2; } $fakedp = new PEAR_PackageFile_v1; $fakedp->setPackage($dep['name']); // skip internet check if we are not upgrading (bug #5810) if (!isset($options['upgrade']) && $this->isInstalled( $fakedp, $dep['rel'])) { $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group . ' dependency "' . $this->_registry->parsedPackageNameToString($dep, true) . '", is already installed'); continue 2; } } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); if ($this->_explicitState) { $pname['state'] = $this->_explicitState; } $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); $chan = 'pear.php.net'; if (PEAR::isError($url)) { // check to see if this is a pecl package that has jumped // from pear.php.net to pecl.php.net channel if (!class_exists('PEAR_Dependency2')) { require_once 'PEAR/Dependency2.php'; } $newdep = PEAR_Dependency2::normalizeDep($dep); $newdep = $newdep[0]; $newdep['channel'] = 'pecl.php.net'; $chan = 'pecl.php.net'; $url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname); $obj = &$this->_installRegistry->getPackage($dep['name']); if (PEAR::isError($url)) { PEAR::popErrorHandling(); if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) { $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? 'required' : 'optional'; $dep['package'] = $dep['name']; if (!isset($options['soft'])) { $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . ' dependency "' . $this->_registry->parsedPackageNameToString($dep, true) . '", already installed as version ' . $obj->getVersion()); } $skip = count($skipnames) ? $skipnames[count($skipnames) - 1] : ''; if ($skip == $this->_registry->parsedPackageNameToString($dep, true)) { array_pop($skipnames); } continue; } else { if (isset($dep['optional']) && $dep['optional'] == 'yes') { $this->_downloader->log(2, $this->getShortName() . ': Skipping optional dependency "' . $this->_registry->parsedPackageNameToString($dep, true) . '", no releases exist'); continue; } else { return $url; } } } } PEAR::popErrorHandling(); if (!isset($options['alldeps'])) { if (isset($dep['optional']) && $dep['optional'] == 'yes') { if (!isset($options['soft'])) { $this->_downloader->log(3, 'Notice: package "' . $this->getShortName() . '" optional dependency "' . $this->_registry->parsedPackageNameToString( array('channel' => $chan, 'package' => $dep['name']), true) . '" will not be automatically downloaded'); } $skipnames[] = $this->_registry->parsedPackageNameToString( array('channel' => $chan, 'package' => $dep['name']), true); $nodownload = true; } } if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) { if (!isset($dep['optional']) || $dep['optional'] == 'no') { if (!isset($options['soft'])) { $this->_downloader->log(3, 'Notice: package "' . $this->getShortName() . '" required dependency "' . $this->_registry->parsedPackageNameToString( array('channel' => $chan, 'package' => $dep['name']), true) . '" will not be automatically downloaded'); } $skipnames[] = $this->_registry->parsedPackageNameToString( array('channel' => $chan, 'package' => $dep['name']), true); $nodownload = true; } } // check to see if a dep is already installed // do not try to move this before getDepPackageDownloadURL // we can't determine whether upgrade is necessary until we know what // version would be downloaded if (!isset($options['force']) && $this->isInstalled( $url, $dep['rel'])) { $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? 'required' : 'optional'; $dep['package'] = $dep['name']; if (isset($newdep)) { $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']); } else { $version = $this->_installRegistry->packageInfo($dep['name'], 'version'); } $dep['version'] = $url['version']; if (!isset($options['soft'])) { $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . ' dependency "' . $this->_registry->parsedPackageNameToString($dep, true) . '", already installed as version ' . $version); } $skip = count($skipnames) ? $skipnames[count($skipnames) - 1] : ''; if ($skip == $this->_registry->parsedPackageNameToString($dep, true)) { array_pop($skipnames); } continue; } if ($nodownload) { continue; } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); if (isset($newdep)) { $dep = $newdep; } $dep['package'] = $dep['name']; $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, isset($dep['optional']) && $dep['optional'] == 'yes' && !isset($options['alldeps']), true); PEAR::popErrorHandling(); if (PEAR::isError($ret)) { if (!isset($options['soft'])) { $this->_downloader->log(0, $ret->getMessage()); } continue; } $this->_downloadDeps[] = $ret; } } if (count($skipnames)) { if (!isset($options['soft'])) { $this->_downloader->log(1, 'Did not download dependencies: ' . implode(', ', $skipnames) . ', use --alldeps or --onlyreqdeps to download automatically'); } } } function setDownloadURL($pkg) { $this->_downloadURL = $pkg; } /** * Set the package.xml object for this downloaded package * * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg */ function setPackageFile(&$pkg) { $this->_packagefile = &$pkg; } function getShortName() { return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(), 'package' => $this->getPackage()), true); } function getParsedPackage() { if (isset($this->_packagefile) || isset($this->_parsedname)) { return array('channel' => $this->getChannel(), 'package' => $this->getPackage(), 'version' => $this->getVersion()); } return false; } function getDownloadURL() { return $this->_downloadURL; } function canDefault() { if (isset($this->_downloadURL) && isset($this->_downloadURL['nodefault'])) { return false; } return true; } function getPackage() { if (isset($this->_packagefile)) { return $this->_packagefile->getPackage(); } elseif (isset($this->_downloadURL['info'])) { return $this->_downloadURL['info']->getPackage(); } return false; } /** * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 */ function isSubpackage(&$pf) { if (isset($this->_packagefile)) { return $this->_packagefile->isSubpackage($pf); } elseif (isset($this->_downloadURL['info'])) { return $this->_downloadURL['info']->isSubpackage($pf); } return false; } function getPackageType() { if (isset($this->_packagefile)) { return $this->_packagefile->getPackageType(); } elseif (isset($this->_downloadURL['info'])) { return $this->_downloadURL['info']->getPackageType(); } return false; } function isBundle() { if (isset($this->_packagefile)) { return $this->_packagefile->getPackageType() == 'bundle'; } return false; } function getPackageXmlVersion() { if (isset($this->_packagefile)) { return $this->_packagefile->getPackagexmlVersion(); } elseif (isset($this->_downloadURL['info'])) { return $this->_downloadURL['info']->getPackagexmlVersion(); } return '1.0'; } function getChannel() { if (isset($this->_packagefile)) { return $this->_packagefile->getChannel(); } elseif (isset($this->_downloadURL['info'])) { return $this->_downloadURL['info']->getChannel(); } return false; } function getURI() { if (isset($this->_packagefile)) { return $this->_packagefile->getURI(); } elseif (isset($this->_downloadURL['info'])) { return $this->_downloadURL['info']->getURI(); } return false; } function getVersion() { if (isset($this->_packagefile)) { return $this->_packagefile->getVersion(); } elseif (isset($this->_downloadURL['version'])) { return $this->_downloadURL['version']; } return false; } function isCompatible($pf) { if (isset($this->_packagefile)) { return $this->_packagefile->isCompatible($pf); } elseif (isset($this->_downloadURL['info'])) { return $this->_downloadURL['info']->isCompatible($pf); } return true; } function setGroup($group) { $this->_parsedname['group'] = $group; } function getGroup() { if (isset($this->_parsedname['group'])) { return $this->_parsedname['group']; } return ''; } function isExtension($name) { if (isset($this->_packagefile)) { return $this->_packagefile->isExtension($name); } elseif (isset($this->_downloadURL['info'])) { if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') { return $this->_downloadURL['info']->getProvidesExtension() == $name; } return false; } return false; } function getDeps() { if (isset($this->_packagefile)) { $ver = $this->_packagefile->getPackagexmlVersion(); if (version_compare($ver, '2.0', '>=')) { return $this->_packagefile->getDeps(true); } return $this->_packagefile->getDeps(); } elseif (isset($this->_downloadURL['info'])) { $ver = $this->_downloadURL['info']->getPackagexmlVersion(); if (version_compare($ver, '2.0', '>=')) { return $this->_downloadURL['info']->getDeps(true); } return $this->_downloadURL['info']->getDeps(); } return array(); } /** * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency * returned from getDepDownloadURL() */ function isEqual($param) { if (is_object($param)) { $channel = $param->getChannel(); $package = $param->getPackage(); if ($param->getURI()) { $param = array( 'channel' => $param->getChannel(), 'package' => $param->getPackage(), 'version' => $param->getVersion(), 'uri' => $param->getURI(), ); } else { $param = array( 'channel' => $param->getChannel(), 'package' => $param->getPackage(), 'version' => $param->getVersion(), ); } } else { if (isset($param['uri'])) { if ($this->getChannel() != '__uri') { return false; } return $param['uri'] == $this->getURI(); } $package = isset($param['package']) ? $param['package'] : $param['info']->getPackage(); $channel = isset($param['channel']) ? $param['channel'] : $param['info']->getChannel(); if (isset($param['rel'])) { if (!class_exists('PEAR_Dependency2')) { require_once 'PEAR/Dependency2.php'; } $newdep = PEAR_Dependency2::normalizeDep($param); $newdep = $newdep[0]; } elseif (isset($param['min'])) { $newdep = $param; } } if (isset($newdep)) { if (!isset($newdep['min'])) { $newdep['min'] = '0'; } if (!isset($newdep['max'])) { $newdep['max'] = '100000000000000000000'; } // use magic to support pecl packages suddenly jumping to the pecl channel // we need to support both dependency possibilities if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') { if ($package == $this->getPackage()) { $channel = 'pecl.php.net'; } } if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { if ($package == $this->getPackage()) { $channel = 'pear.php.net'; } } return (strtolower($package) == strtolower($this->getPackage()) && $channel == $this->getChannel() && version_compare($newdep['min'], $this->getVersion(), '<=') && version_compare($newdep['max'], $this->getVersion(), '>=')); } // use magic to support pecl packages suddenly jumping to the pecl channel if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { if (strtolower($package) == strtolower($this->getPackage())) { $channel = 'pear.php.net'; } } if (isset($param['version'])) { return (strtolower($package) == strtolower($this->getPackage()) && $channel == $this->getChannel() && $param['version'] == $this->getVersion()); } return strtolower($package) == strtolower($this->getPackage()) && $channel == $this->getChannel(); } function isInstalled($dep, $oper = '==') { if (!$dep) { return false; } if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') { return false; } if (is_object($dep)) { $package = $dep->getPackage(); $channel = $dep->getChannel(); if ($dep->getURI()) { $dep = array( 'uri' => $dep->getURI(), 'version' => $dep->getVersion(), ); } else { $dep = array( 'version' => $dep->getVersion(), ); } } else { if (isset($dep['uri'])) { $channel = '__uri'; $package = $dep['dep']['name']; } else { $channel = $dep['info']->getChannel(); $package = $dep['info']->getPackage(); } } $options = $this->_downloader->getOptions(); $test = $this->_installRegistry->packageExists($package, $channel); if (!$test && $channel == 'pecl.php.net') { // do magic to allow upgrading from old pecl packages to new ones $test = $this->_installRegistry->packageExists($package, 'pear.php.net'); $channel = 'pear.php.net'; } if ($test) { if (isset($dep['uri'])) { if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) { return true; } } if (isset($options['upgrade'])) { $packageVersion = $this->_installRegistry->packageInfo($package, 'version', $channel); if (version_compare($packageVersion, $dep['version'], '>=')) { return true; } return false; } return true; } return false; } /** * Detect duplicate package names with differing versions * * If a user requests to install Date 1.4.6 and Date 1.4.7, * for instance, this is a logic error. This method * detects this situation. * * @param array $params array of PEAR_Downloader_Package objects * @param array $errorparams empty array * @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts */ public static function detectStupidDuplicates($params, &$errorparams) { $existing = array(); foreach ($params as $i => $param) { $package = $param->getPackage(); $channel = $param->getChannel(); $group = $param->getGroup(); if (!isset($existing[$channel . '/' . $package])) { $existing[$channel . '/' . $package] = array(); } if (!isset($existing[$channel . '/' . $package][$group])) { $existing[$channel . '/' . $package][$group] = array(); } $existing[$channel . '/' . $package][$group][] = $i; } $indices = array(); foreach ($existing as $package => $groups) { foreach ($groups as $group => $dupes) { if (count($dupes) > 1) { $indices = $indices + $dupes; } } } $indices = array_unique($indices); foreach ($indices as $index) { $errorparams[] = $params[$index]; } return count($errorparams); } /** * @param array * @param bool ignore install groups - for final removal of dupe packages */ public static function removeDuplicates(&$params, $ignoreGroups = false) { $pnames = array(); foreach ($params as $i => $param) { if (!$param) { continue; } if ($param->getPackage()) { $group = $ignoreGroups ? '' : $param->getGroup(); $pnames[$i] = $param->getChannel() . '/' . $param->getPackage() . '-' . $param->getVersion() . '#' . $group; } } $pnames = array_unique($pnames); $unset = array_diff(array_keys($params), array_keys($pnames)); $testp = array_flip($pnames); foreach ($params as $i => $param) { if (!$param) { $unset[] = $i; continue; } if (!is_a($param, 'PEAR_Downloader_Package')) { $unset[] = $i; continue; } $group = $ignoreGroups ? '' : $param->getGroup(); if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' . $param->getVersion() . '#' . $group])) { $unset[] = $i; } } foreach ($unset as $i) { unset($params[$i]); } $ret = array(); foreach ($params as $i => $param) { $ret[] = &$params[$i]; } $params = array(); foreach ($ret as $i => $param) { $params[] = &$ret[$i]; } } function explicitState() { return $this->_explicitState; } function setExplicitState($s) { $this->_explicitState = $s; } /** */ public static function mergeDependencies(&$params) { $bundles = $newparams = array(); foreach ($params as $i => $param) { if (!$param->isBundle()) { continue; } $bundles[] = $i; $pf = &$param->getPackageFile(); $newdeps = array(); $contents = $pf->getBundledPackages(); if (!is_array($contents)) { $contents = array($contents); } foreach ($contents as $file) { $filecontents = $pf->getFileContents($file); $dl = &$param->getDownloader(); $options = $dl->getOptions(); if (PEAR::isError($dir = $dl->getDownloadDir())) { return $dir; } $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb'); if (!$fp) { continue; } // FIXME do symlink check fwrite($fp, $filecontents, strlen($filecontents)); fclose($fp); if ($s = $params[$i]->explicitState()) { $obj->setExplicitState($s); } $obj = new PEAR_Downloader_Package($params[$i]->getDownloader()); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); if (PEAR::isError($dir = $dl->getDownloadDir())) { PEAR::popErrorHandling(); return $dir; } $a = $dir . DIRECTORY_SEPARATOR . $file; $e = $obj->_fromFile($a); PEAR::popErrorHandling(); if (PEAR::isError($e)) { if (!isset($options['soft'])) { $dl->log(0, $e->getMessage()); } continue; } if (!PEAR_Downloader_Package::willDownload($obj, array_merge($params, $newparams)) && !$param->isInstalled($obj)) { $newparams[] = $obj; } } } foreach ($bundles as $i) { unset($params[$i]); // remove bundles - only their contents matter for installation } PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices if (count($newparams)) { // add in bundled packages for install foreach ($newparams as $i => $unused) { $params[] = &$newparams[$i]; } $newparams = array(); } foreach ($params as $i => $param) { $newdeps = array(); foreach ($param->_downloadDeps as $dep) { $merge = array_merge($params, $newparams); if (!PEAR_Downloader_Package::willDownload($dep, $merge) && !$param->isInstalled($dep) ) { $newdeps[] = $dep; } else { //var_dump($dep); // detect versioning conflicts here } } // convert the dependencies into PEAR_Downloader_Package objects for the next time around $params[$i]->_downloadDeps = array(); foreach ($newdeps as $dep) { $obj = new PEAR_Downloader_Package($params[$i]->getDownloader()); if ($s = $params[$i]->explicitState()) { $obj->setExplicitState($s); } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $e = $obj->fromDepURL($dep); PEAR::popErrorHandling(); if (PEAR::isError($e)) { if (!isset($options['soft'])) { $obj->_downloader->log(0, $e->getMessage()); } continue; } $e = $obj->detectDependencies($params); if (PEAR::isError($e)) { if (!isset($options['soft'])) { $obj->_downloader->log(0, $e->getMessage()); } } $newparams[] = $obj; } } if (count($newparams)) { foreach ($newparams as $i => $unused) { $params[] = &$newparams[$i]; } return true; } return false; } /** */ public static function willDownload($param, $params) { if (!is_array($params)) { return false; } foreach ($params as $obj) { if ($obj->isEqual($param)) { return true; } } return false; } /** * For simpler unit-testing * @param PEAR_Config * @param int * @param string */ function &getPackagefileObject(&$c, $d) { $a = new PEAR_PackageFile($c, $d); return $a; } /** * This will retrieve from a local file if possible, and parse out * a group name as well. The original parameter will be modified to reflect this. * @param string|array can be a parsed package name as well * @access private */ function _fromFile(&$param) { $saveparam = $param; if (is_string($param) && substr($param, 0, 10) !== 'channel://') { if (!@file_exists($param)) { $test = explode('#', $param); $group = array_pop($test); if (@file_exists(implode('#', $test))) { $this->setGroup($group); $param = implode('#', $test); $this->_explicitGroup = true; } } if (@is_file($param)) { $this->_type = 'local'; $options = $this->_downloader->getOptions(); $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->_debug); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING); PEAR::popErrorHandling(); if (PEAR::isError($pf)) { $this->_valid = false; $param = $saveparam; return $pf; } $this->_packagefile = &$pf; if (!$this->getGroup()) { $this->setGroup('default'); // install the default dependency group } return $this->_valid = true; } } $param = $saveparam; return $this->_valid = false; } function _fromUrl($param, $saveparam = '') { if (!is_array($param) && (preg_match('#^(http|https|ftp)://#', $param))) { $options = $this->_downloader->getOptions(); $this->_type = 'url'; $callback = $this->_downloader->ui ? array(&$this->_downloader, '_downloadCallback') : null; $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN); if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { $this->_downloader->popErrorHandling(); return $dir; } $this->_downloader->log(3, 'Downloading "' . $param . '"'); $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui, $dir, $callback, null, false, $this->getChannel()); $this->_downloader->popErrorHandling(); if (PEAR::isError($file)) { if (!empty($saveparam)) { $saveparam = ", cannot download \"$saveparam\""; } $err = PEAR::raiseError('Could not download from "' . $param . '"' . $saveparam . ' (' . $file->getMessage() . ')'); return $err; } if ($this->_rawpackagefile) { require_once 'Archive/Tar.php'; $tar = new Archive_Tar($file); $packagexml = $tar->extractInString('package2.xml'); if (!$packagexml) { $packagexml = $tar->extractInString('package.xml'); } if (str_replace(array("\n", "\r"), array('',''), $packagexml) != str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) { if ($this->getChannel() != 'pear.php.net') { return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' . 'not match value returned from xml-rpc'); } // be more lax for the existing PEAR packages that have not-ok // characters in their package.xml $this->_downloader->log(0, 'CRITICAL WARNING: The "' . $this->getPackage() . '" package has invalid characters in its ' . 'package.xml. The next version of PEAR may not be able to install ' . 'this package for security reasons. Please open a bug report at ' . 'http://pear.php.net/package/' . $this->getPackage() . '/bugs'); } } // whew, download worked! $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING); PEAR::popErrorHandling(); if (PEAR::isError($pf)) { if (is_array($pf->getUserInfo())) { foreach ($pf->getUserInfo() as $err) { if (is_array($err)) { $err = $err['message']; } if (!isset($options['soft'])) { $this->_downloader->log(0, "Validation Error: $err"); } } } if (!isset($options['soft'])) { $this->_downloader->log(0, $pf->getMessage()); } ///FIXME need to pass back some error code that we can use to match with to cancel all further operations /// At least stop all deps of this package from being installed $out = $saveparam ? $saveparam : $param; $err = PEAR::raiseError('Download of "' . $out . '" succeeded, but it is not a valid package archive'); $this->_valid = false; return $err; } $this->_packagefile = &$pf; $this->setGroup('default'); // install the default dependency group return $this->_valid = true; } return $this->_valid = false; } /** * * @param string|array pass in an array of format * array( * 'package' => 'pname', * ['channel' => 'channame',] * ['version' => 'version',] * ['state' => 'state',]) * or a string of format [channame/]pname[-version|-state] */ function _fromString($param) { $options = $this->_downloader->getOptions(); $channel = $this->_config->get('default_channel'); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $pname = $this->_registry->parsePackageName($param, $channel); PEAR::popErrorHandling(); if (PEAR::isError($pname)) { if ($pname->getCode() == 'invalid') { $this->_valid = false; return false; } if ($pname->getCode() == 'channel') { $parsed = $pname->getUserInfo(); if ($this->_downloader->discover($parsed['channel'])) { if ($this->_config->get('auto_discover')) { PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $pname = $this->_registry->parsePackageName($param, $channel); PEAR::popErrorHandling(); } else { if (!isset($options['soft'])) { $this->_downloader->log(0, 'Channel "' . $parsed['channel'] . '" is not initialized, use ' . '"pear channel-discover ' . $parsed['channel'] . '" to initialize' . 'or pear config-set auto_discover 1'); } } } if (PEAR::isError($pname)) { if (!isset($options['soft'])) { $this->_downloader->log(0, $pname->getMessage()); } if (is_array($param)) { $param = $this->_registry->parsedPackageNameToString($param); } $err = PEAR::raiseError('invalid package name/package file "' . $param . '"'); $this->_valid = false; return $err; } } else { if (!isset($options['soft'])) { $this->_downloader->log(0, $pname->getMessage()); } $err = PEAR::raiseError('invalid package name/package file "' . $param . '"'); $this->_valid = false; return $err; } } if (!isset($this->_type)) { $this->_type = 'rest'; } $this->_parsedname = $pname; $this->_explicitState = isset($pname['state']) ? $pname['state'] : false; $this->_explicitGroup = isset($pname['group']) ? true : false; $info = $this->_downloader->_getPackageDownloadUrl($pname); if (PEAR::isError($info)) { if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') { // try pecl $pname['channel'] = 'pecl.php.net'; if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) { if (!PEAR::isError($test)) { $info = PEAR::raiseError($info->getMessage() . ' - package ' . $this->_registry->parsedPackageNameToString($pname, true) . ' can be installed with "pecl install ' . $pname['package'] . '"'); } else { $pname['channel'] = 'pear.php.net'; } } else { $pname['channel'] = 'pear.php.net'; } } return $info; } $this->_rawpackagefile = $info['raw']; $ret = $this->_analyzeDownloadURL($info, $param, $pname); if (PEAR::isError($ret)) { return $ret; } if ($ret) { $this->_downloadURL = $ret; return $this->_valid = (bool) $ret; } } /** * @param array output of package.getDownloadURL * @param string|array|object information for detecting packages to be downloaded, and * for errors * @param array name information of the package * @param array|null packages to be downloaded * @param bool is this an optional dependency? * @param bool is this any kind of dependency? * @access private */ function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false, $isdependency = false) { if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) { return false; } if ($info === false) { $saveparam = !is_string($param) ? ", cannot download \"$param\"" : ''; // no releases exist return PEAR::raiseError('No releases for package "' . $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam); } if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) { $err = false; if ($pname['channel'] == 'pecl.php.net') { if ($info['info']->getChannel() != 'pear.php.net') { $err = true; } } elseif ($info['info']->getChannel() == 'pecl.php.net') { if ($pname['channel'] != 'pear.php.net') { $err = true; } } else { $err = true; } if ($err) { return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] . '" retrieved another channel\'s name for download! ("' . $info['info']->getChannel() . '")'); } } $preferred_state = $this->_config->get('preferred_state'); if (!isset($info['url'])) { $package_version = $this->_registry->packageInfo($info['info']->getPackage(), 'version', $info['info']->getChannel()); if ($this->isInstalled($info)) { if ($isdependency && version_compare($info['version'], $package_version, '<=')) { // ignore bogus errors of "failed to download dependency" // if it is already installed and the one that would be // downloaded is older or the same version (Bug #7219) return false; } } if ($info['version'] === $package_version) { if (!isset($options['soft'])) { $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] . '/' . $pname['package'] . '-' . $package_version. ', additionally the suggested version' . ' (' . $package_version . ') is the same as the locally installed one.'); } return false; } if (version_compare($info['version'], $package_version, '<=')) { if (!isset($options['soft'])) { $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] . '/' . $pname['package'] . '-' . $package_version . ', additionally the suggested version' . ' (' . $info['version'] . ') is a lower version than the locally installed one (' . $package_version . ').'); } return false; } $instead = ', will instead download version ' . $info['version'] . ', stability "' . $info['info']->getState() . '"'; // releases exist, but we failed to get any if (isset($this->_downloader->_options['force'])) { if (isset($pname['version'])) { $vs = ', version "' . $pname['version'] . '"'; } elseif (isset($pname['state'])) { $vs = ', stability "' . $pname['state'] . '"'; } elseif ($param == 'dependency') { if (!class_exists('PEAR_Common')) { require_once 'PEAR/Common.php'; } if (!in_array($info['info']->getState(), PEAR_Common::betterStates($preferred_state, true))) { if ($optional) { // don't spit out confusing error message return $this->_downloader->_getPackageDownloadUrl( array('package' => $pname['package'], 'channel' => $pname['channel'], 'version' => $info['version'])); } $vs = ' within preferred state "' . $preferred_state . '"'; } else { if (!class_exists('PEAR_Dependency2')) { require_once 'PEAR/Dependency2.php'; } if ($optional) { // don't spit out confusing error message return $this->_downloader->_getPackageDownloadUrl( array('package' => $pname['package'], 'channel' => $pname['channel'], 'version' => $info['version'])); } $vs = PEAR_Dependency2::_getExtraString($pname); $instead = ''; } } else { $vs = ' within preferred state "' . $preferred_state . '"'; } if (!isset($options['soft'])) { $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] . '/' . $pname['package'] . $vs . $instead); } // download the latest release return $this->_downloader->_getPackageDownloadUrl( array('package' => $pname['package'], 'channel' => $pname['channel'], 'version' => $info['version'])); } else { if (isset($info['php']) && $info['php']) { $err = PEAR::raiseError('Failed to download ' . $this->_registry->parsedPackageNameToString( array('channel' => $pname['channel'], 'package' => $pname['package']), true) . ', latest release is version ' . $info['php']['v'] . ', but it requires PHP version "' . $info['php']['m'] . '", use "' . $this->_registry->parsedPackageNameToString( array('channel' => $pname['channel'], 'package' => $pname['package'], 'version' => $info['php']['v'])) . '" to install', PEAR_DOWNLOADER_PACKAGE_PHPVERSION); return $err; } // construct helpful error message if (isset($pname['version'])) { $vs = ', version "' . $pname['version'] . '"'; } elseif (isset($pname['state'])) { $vs = ', stability "' . $pname['state'] . '"'; } elseif ($param == 'dependency') { if (!class_exists('PEAR_Common')) { require_once 'PEAR/Common.php'; } if (!in_array($info['info']->getState(), PEAR_Common::betterStates($preferred_state, true))) { if ($optional) { // don't spit out confusing error message, and don't die on // optional dep failure! return $this->_downloader->_getPackageDownloadUrl( array('package' => $pname['package'], 'channel' => $pname['channel'], 'version' => $info['version'])); } $vs = ' within preferred state "' . $preferred_state . '"'; } else { if (!class_exists('PEAR_Dependency2')) { require_once 'PEAR/Dependency2.php'; } if ($optional) { // don't spit out confusing error message, and don't die on // optional dep failure! return $this->_downloader->_getPackageDownloadUrl( array('package' => $pname['package'], 'channel' => $pname['channel'], 'version' => $info['version'])); } $vs = PEAR_Dependency2::_getExtraString($pname); } } else { $vs = ' within preferred state "' . $this->_downloader->config->get('preferred_state') . '"'; } $options = $this->_downloader->getOptions(); // this is only set by the "download-all" command if (isset($options['ignorepreferred_state'])) { $err = PEAR::raiseError( 'Failed to download ' . $this->_registry->parsedPackageNameToString( array('channel' => $pname['channel'], 'package' => $pname['package']), true) . $vs . ', latest release is version ' . $info['version'] . ', stability "' . $info['info']->getState() . '", use "' . $this->_registry->parsedPackageNameToString( array('channel' => $pname['channel'], 'package' => $pname['package'], 'version' => $info['version'])) . '" to install', PEAR_DOWNLOADER_PACKAGE_STATE); return $err; } // Checks if the user has a package installed already and checks the release against // the state against the installed package, this allows upgrades for packages // with lower stability than the preferred_state $stability = $this->_registry->packageInfo($pname['package'], 'stability', $pname['channel']); if (!$this->isInstalled($info) || !in_array($info['info']->getState(), PEAR_Common::betterStates($stability['release'], true)) ) { $err = PEAR::raiseError( 'Failed to download ' . $this->_registry->parsedPackageNameToString( array('channel' => $pname['channel'], 'package' => $pname['package']), true) . $vs . ', latest release is version ' . $info['version'] . ', stability "' . $info['info']->getState() . '", use "' . $this->_registry->parsedPackageNameToString( array('channel' => $pname['channel'], 'package' => $pname['package'], 'version' => $info['version'])) . '" to install'); return $err; } } } if (isset($info['deprecated']) && $info['deprecated']) { $this->_downloader->log(0, 'WARNING: "' . $this->_registry->parsedPackageNameToString( array('channel' => $info['info']->getChannel(), 'package' => $info['info']->getPackage()), true) . '" is deprecated in favor of "' . $this->_registry->parsedPackageNameToString($info['deprecated'], true) . '"'); } return $info; } } PK!.4PEAR/Frontend.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ /** * Include error handling */ //require_once 'PEAR.php'; /** * Which user interface class is being used. * @var string class name */ $GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI'; /** * Instance of $_PEAR_Command_uiclass. * @var object */ $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null; /** * Singleton-based frontend for PEAR user input/output * * @category pear * @package PEAR * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ class PEAR_Frontend extends PEAR { /** * Retrieve the frontend object * @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk */ public static function &singleton($type = null) { if ($type === null) { if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) { $a = false; return $a; } return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; } $a = PEAR_Frontend::setFrontendClass($type); return $a; } /** * Set the frontend class that will be used by calls to {@link singleton()} * * Frontends are expected to conform to the PEAR naming standard of * _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php) * @param string $uiclass full class name * @return PEAR_Frontend */ public static function &setFrontendClass($uiclass) { if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) { return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; } if (!class_exists($uiclass)) { $file = str_replace('_', '/', $uiclass) . '.php'; if (PEAR_Frontend::isIncludeable($file)) { include_once $file; } } if (class_exists($uiclass)) { $obj = new $uiclass; // quick test to see if this class implements a few of the most // important frontend methods if (is_a($obj, 'PEAR_Frontend')) { $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj; $GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass; return $obj; } $err = PEAR::raiseError("not a frontend class: $uiclass"); return $err; } $err = PEAR::raiseError("no such class: $uiclass"); return $err; } /** * Set the frontend class that will be used by calls to {@link singleton()} * * Frontends are expected to be a descendant of PEAR_Frontend * @param PEAR_Frontend * @return PEAR_Frontend */ public static function &setFrontendObject($uiobject) { if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) { return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; } if (!is_a($uiobject, 'PEAR_Frontend')) { $err = PEAR::raiseError('not a valid frontend class: (' . get_class($uiobject) . ')'); return $err; } $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject; $GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject); return $uiobject; } /** * @param string $path relative or absolute include path * @return boolean */ public static function isIncludeable($path) { if (file_exists($path) && is_readable($path)) { return true; } $fp = @fopen($path, 'r', true); if ($fp) { fclose($fp); return true; } return false; } /** * @param PEAR_Config */ function setConfig(&$config) { } /** * This can be overridden to allow session-based temporary file management * * By default, all files are deleted at the end of a session. The web installer * needs to be able to sustain a list over many sessions in order to support * user interaction with install scripts */ static function addTempFile($file) { $GLOBALS['_PEAR_Common_tempfiles'][] = $file; } /** * Log an action * * @param string $msg the message to log * @param boolean $append_crlf * @return boolean true * @abstract */ function log($msg, $append_crlf = true) { } /** * Run a post-installation script * * @param array $scripts array of post-install scripts * @abstract */ function runPostinstallScripts(&$scripts) { } /** * Display human-friendly output formatted depending on the * $command parameter. * * This should be able to handle basic output data with no command * @param mixed $data data structure containing the information to display * @param string $command command from which this method was called * @abstract */ function outputData($data, $command = '_default') { } /** * Display a modal form dialog and return the given input * * A frontend that requires multiple requests to retrieve and process * data must take these needs into account, and implement the request * handling code. * @param string $command command from which this method was called * @param array $prompts associative array. keys are the input field names * and values are the description * @param array $types array of input field types (text, password, * etc.) keys have to be the same like in $prompts * @param array $defaults array of default values. again keys have * to be the same like in $prompts. Do not depend * on a default value being set. * @return array input sent by the user * @abstract */ function userDialog($command, $prompts, $types = array(), $defaults = array()) { } } PK!،wPEAR/Installer.phpnu[ * @author Tomas V.V. Cox * @author Martin Jansen * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * Used for installation groups in package.xml 2.0 and platform exceptions */ require_once 'OS/Guess.php'; require_once 'PEAR/Downloader.php'; define('PEAR_INSTALLER_NOBINARY', -240); /** * Administration class used to install PEAR packages and maintain the * installed package database. * * @category pear * @package PEAR * @author Stig Bakken * @author Tomas V.V. Cox * @author Martin Jansen * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ class PEAR_Installer extends PEAR_Downloader { // {{{ properties /** name of the package directory, for example Foo-1.0 * @var string */ var $pkgdir; /** directory where PHP code files go * @var string */ var $phpdir; /** directory where PHP extension files go * @var string */ var $extdir; /** directory where documentation goes * @var string */ var $docdir; /** installation root directory (ala PHP's INSTALL_ROOT or * automake's DESTDIR * @var string */ var $installroot = ''; /** debug level * @var int */ var $debug = 1; /** temporary directory * @var string */ var $tmpdir; /** * PEAR_Registry object used by the installer * @var PEAR_Registry */ var $registry; /** * array of PEAR_Downloader_Packages * @var array */ var $_downloadedPackages; /** List of file transactions queued for an install/upgrade/uninstall. * * Format: * array( * 0 => array("rename => array("from-file", "to-file")), * 1 => array("delete" => array("file-to-delete")), * ... * ) * * @var array */ var $file_operations = array(); // }}} // {{{ constructor /** * PEAR_Installer constructor. * * @param object $ui user interface object (instance of PEAR_Frontend_*) * * @access public */ function __construct(&$ui) { parent::__construct($ui, array(), null); $this->setFrontendObject($ui); $this->debug = $this->config->get('verbose'); } function setOptions($options) { $this->_options = $options; } function setConfig(&$config) { $this->config = &$config; $this->_registry = &$config->getRegistry(); } // }}} function _removeBackups($files) { foreach ($files as $path) { $this->addFileOperation('removebackup', array($path)); } } // {{{ _deletePackageFiles() /** * Delete a package's installed files, does not remove empty directories. * * @param string package name * @param string channel name * @param bool if true, then files are backed up first * @return bool TRUE on success, or a PEAR error on failure * @access protected */ function _deletePackageFiles($package, $channel = false, $backup = false) { if (!$channel) { $channel = 'pear.php.net'; } if (!strlen($package)) { return $this->raiseError("No package to uninstall given"); } if (strtolower($package) == 'pear' && $channel == 'pear.php.net') { // to avoid race conditions, include all possible needed files require_once 'PEAR/Task/Common.php'; require_once 'PEAR/Task/Replace.php'; require_once 'PEAR/Task/Unixeol.php'; require_once 'PEAR/Task/Windowseol.php'; require_once 'PEAR/PackageFile/v1.php'; require_once 'PEAR/PackageFile/v2.php'; require_once 'PEAR/PackageFile/Generator/v1.php'; require_once 'PEAR/PackageFile/Generator/v2.php'; } $filelist = $this->_registry->packageInfo($package, 'filelist', $channel); if ($filelist == null) { return $this->raiseError("$channel/$package not installed"); } $ret = array(); foreach ($filelist as $file => $props) { if (empty($props['installed_as'])) { continue; } $path = $props['installed_as']; if ($backup) { $this->addFileOperation('backup', array($path)); $ret[] = $path; } $this->addFileOperation('delete', array($path)); } if ($backup) { return $ret; } return true; } // }}} // {{{ _installFile() /** * @param string filename * @param array attributes from tag in package.xml * @param string path to install the file in * @param array options from command-line * @access private */ function _installFile($file, $atts, $tmp_path, $options) { // {{{ return if this file is meant for another platform static $os; if (!isset($this->_registry)) { $this->_registry = &$this->config->getRegistry(); } if (isset($atts['platform'])) { if (empty($os)) { $os = new OS_Guess(); } if (strlen($atts['platform']) && $atts['platform'][0] == '!') { $negate = true; $platform = substr($atts['platform'], 1); } else { $negate = false; $platform = $atts['platform']; } if ((bool) $os->matchSignature($platform) === $negate) { $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")"); return PEAR_INSTALLER_SKIPPED; } } // }}} $channel = $this->pkginfo->getChannel(); // {{{ assemble the destination paths switch ($atts['role']) { case 'src': case 'extsrc': $this->source_files++; return; case 'doc': case 'data': case 'test': $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel) . DIRECTORY_SEPARATOR . $this->pkginfo->getPackage(); unset($atts['baseinstalldir']); break; case 'ext': case 'php': $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel); break; case 'script': $dest_dir = $this->config->get('bin_dir', null, $channel); break; default: return $this->raiseError("Invalid role `$atts[role]' for file $file"); } $save_destdir = $dest_dir; if (!empty($atts['baseinstalldir'])) { $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; } if (dirname($file) != '.' && empty($atts['install-as'])) { $dest_dir .= DIRECTORY_SEPARATOR . dirname($file); } if (empty($atts['install-as'])) { $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file); } else { $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as']; } $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file; // Clean up the DIRECTORY_SEPARATOR mess $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), array($dest_file, $orig_file)); $final_dest_file = $installed_as = $dest_file; if (isset($this->_options['packagingroot'])) { $installedas_dest_dir = dirname($final_dest_file); $installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']); } else { $installedas_dest_dir = dirname($final_dest_file); $installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); } $dest_dir = dirname($final_dest_file); $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) { return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED); } // }}} if (empty($this->_options['register-only']) && (!file_exists($dest_dir) || !is_dir($dest_dir))) { if (!$this->mkDirHier($dest_dir)) { return $this->raiseError("failed to mkdir $dest_dir", PEAR_INSTALLER_FAILED); } $this->log(3, "+ mkdir $dest_dir"); } // pretty much nothing happens if we are only registering the install if (empty($this->_options['register-only'])) { if (empty($atts['replacements'])) { if (!file_exists($orig_file)) { return $this->raiseError("file $orig_file does not exist", PEAR_INSTALLER_FAILED); } if (!@copy($orig_file, $dest_file)) { return $this->raiseError( "failed to write $dest_file: " . error_get_last()["message"], PEAR_INSTALLER_FAILED); } $this->log(3, "+ cp $orig_file $dest_file"); if (isset($atts['md5sum'])) { $md5sum = md5_file($dest_file); } } else { // {{{ file with replacements if (!file_exists($orig_file)) { return $this->raiseError("file does not exist", PEAR_INSTALLER_FAILED); } $contents = file_get_contents($orig_file); if ($contents === false) { $contents = ''; } if (isset($atts['md5sum'])) { $md5sum = md5($contents); } $subst_from = $subst_to = array(); foreach ($atts['replacements'] as $a) { $to = ''; if ($a['type'] == 'php-const') { if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) { eval("\$to = $a[to];"); } else { if (!isset($options['soft'])) { $this->log(0, "invalid php-const replacement: $a[to]"); } continue; } } elseif ($a['type'] == 'pear-config') { if ($a['to'] == 'master_server') { $chan = $this->_registry->getChannel($channel); if (!PEAR::isError($chan)) { $to = $chan->getServer(); } else { $to = $this->config->get($a['to'], null, $channel); } } else { $to = $this->config->get($a['to'], null, $channel); } if (is_null($to)) { if (!isset($options['soft'])) { $this->log(0, "invalid pear-config replacement: $a[to]"); } continue; } } elseif ($a['type'] == 'package-info') { if ($t = $this->pkginfo->packageInfo($a['to'])) { $to = $t; } else { if (!isset($options['soft'])) { $this->log(0, "invalid package-info replacement: $a[to]"); } continue; } } if (!is_null($to)) { $subst_from[] = $a['from']; $subst_to[] = $to; } } $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file"); if (sizeof($subst_from)) { $contents = str_replace($subst_from, $subst_to, $contents); } $wp = @fopen($dest_file, "wb"); if (!is_resource($wp)) { return $this->raiseError( "failed to create $dest_file: " . error_get_last()["message"], PEAR_INSTALLER_FAILED); } if (@fwrite($wp, $contents) === false) { return $this->raiseError( "failed writing to $dest_file: " . error_get_last()["message"], PEAR_INSTALLER_FAILED); } fclose($wp); // }}} } // {{{ check the md5 if (isset($md5sum)) { if (strtolower($md5sum) === strtolower($atts['md5sum'])) { $this->log(2, "md5sum ok: $final_dest_file"); } else { if (empty($options['force'])) { // delete the file if (file_exists($dest_file)) { unlink($dest_file); } if (!isset($options['ignore-errors'])) { return $this->raiseError("bad md5sum for file $final_dest_file", PEAR_INSTALLER_FAILED); } if (!isset($options['soft'])) { $this->log(0, "warning : bad md5sum for file $final_dest_file"); } } else { if (!isset($options['soft'])) { $this->log(0, "warning : bad md5sum for file $final_dest_file"); } } } } // }}} // {{{ set file permissions if (!OS_WINDOWS) { if ($atts['role'] == 'script') { $mode = 0777 & ~(int)octdec($this->config->get('umask')); $this->log(3, "+ chmod +x $dest_file"); } else { $mode = 0666 & ~(int)octdec($this->config->get('umask')); } if ($atts['role'] != 'src') { $this->addFileOperation("chmod", array($mode, $dest_file)); if (!@chmod($dest_file, $mode)) { if (!isset($options['soft'])) { $this->log(0, "failed to change mode of $dest_file: " . error_get_last()["message"]); } } } } // }}} if ($atts['role'] == 'src') { rename($dest_file, $final_dest_file); $this->log(2, "renamed source file $dest_file to $final_dest_file"); } else { $this->addFileOperation("rename", array($dest_file, $final_dest_file, $atts['role'] == 'ext')); } } // Store the full path where the file was installed for easy unistall if ($atts['role'] != 'script') { $loc = $this->config->get($atts['role'] . '_dir'); } else { $loc = $this->config->get('bin_dir'); } if ($atts['role'] != 'src') { $this->addFileOperation("installed_as", array($file, $installed_as, $loc, dirname(substr($installedas_dest_file, strlen($loc))))); } //$this->log(2, "installed: $dest_file"); return PEAR_INSTALLER_OK; } // }}} // {{{ _installFile2() /** * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @param string filename * @param array attributes from tag in package.xml * @param string path to install the file in * @param array options from command-line * @access private */ function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options) { $atts = $real_atts; if (!isset($this->_registry)) { $this->_registry = &$this->config->getRegistry(); } $channel = $pkg->getChannel(); // {{{ assemble the destination paths if (!in_array($atts['attribs']['role'], PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) { return $this->raiseError('Invalid role `' . $atts['attribs']['role'] . "' for file $file"); } $role = &PEAR_Installer_Role::factory($pkg, $atts['attribs']['role'], $this->config); $err = $role->setup($this, $pkg, $atts['attribs'], $file); if (PEAR::isError($err)) { return $err; } if (!$role->isInstallable()) { return; } $info = $role->processInstallation($pkg, $atts['attribs'], $file, $tmp_path); if (PEAR::isError($info)) { return $info; } list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info; if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) { return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED); } $final_dest_file = $installed_as = $dest_file; if (isset($this->_options['packagingroot'])) { $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']); } $dest_dir = dirname($final_dest_file); $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); // }}} if (empty($this->_options['register-only'])) { if (!file_exists($dest_dir) || !is_dir($dest_dir)) { if (!$this->mkDirHier($dest_dir)) { return $this->raiseError("failed to mkdir $dest_dir", PEAR_INSTALLER_FAILED); } $this->log(3, "+ mkdir $dest_dir"); } } $attribs = $atts['attribs']; unset($atts['attribs']); // pretty much nothing happens if we are only registering the install if (empty($this->_options['register-only'])) { if (!count($atts)) { // no tasks if (!file_exists($orig_file)) { return $this->raiseError("file $orig_file does not exist", PEAR_INSTALLER_FAILED); } if (!@copy($orig_file, $dest_file)) { return $this->raiseError( "failed to write $dest_file: " . error_get_last()["message"], PEAR_INSTALLER_FAILED); } $this->log(3, "+ cp $orig_file $dest_file"); if (isset($attribs['md5sum'])) { $md5sum = md5_file($dest_file); } } else { // file with tasks if (!file_exists($orig_file)) { return $this->raiseError("file $orig_file does not exist", PEAR_INSTALLER_FAILED); } $contents = file_get_contents($orig_file); if ($contents === false) { $contents = ''; } if (isset($attribs['md5sum'])) { $md5sum = md5($contents); } foreach ($atts as $tag => $raw) { $tag = str_replace(array($pkg->getTasksNs() . ':', '-'), array('', '_'), $tag); $task = "PEAR_Task_$tag"; $task = new $task($this->config, $this, PEAR_TASK_INSTALL); if (!$task->isScript()) { // scripts are only handled after installation $task->init($raw, $attribs, $pkg->getLastInstalledVersion()); $res = $task->startSession($pkg, $contents, $final_dest_file); if ($res === false) { continue; // skip this file } if (PEAR::isError($res)) { return $res; } $contents = $res; // save changes } $wp = @fopen($dest_file, "wb"); if (!is_resource($wp)) { return $this->raiseError( "failed to create $dest_file: " . error_get_last()["message"], PEAR_INSTALLER_FAILED); } if (fwrite($wp, $contents) === false) { return $this->raiseError( "failed writing to $dest_file: " . error_get_last()["message"], PEAR_INSTALLER_FAILED); } fclose($wp); } } // {{{ check the md5 if (isset($md5sum)) { // Make sure the original md5 sum matches with expected if (strtolower($md5sum) === strtolower($attribs['md5sum'])) { $this->log(2, "md5sum ok: $final_dest_file"); if (isset($contents)) { // set md5 sum based on $content in case any tasks were run. $real_atts['attribs']['md5sum'] = md5($contents); } } else { if (empty($options['force'])) { // delete the file if (file_exists($dest_file)) { unlink($dest_file); } if (!isset($options['ignore-errors'])) { return $this->raiseError("bad md5sum for file $final_dest_file", PEAR_INSTALLER_FAILED); } if (!isset($options['soft'])) { $this->log(0, "warning : bad md5sum for file $final_dest_file"); } } else { if (!isset($options['soft'])) { $this->log(0, "warning : bad md5sum for file $final_dest_file"); } } } } else { $real_atts['attribs']['md5sum'] = md5_file($dest_file); } // }}} // {{{ set file permissions if (!OS_WINDOWS) { if ($role->isExecutable()) { $mode = 0777 & ~(int)octdec($this->config->get('umask')); $this->log(3, "+ chmod +x $dest_file"); } else { $mode = 0666 & ~(int)octdec($this->config->get('umask')); } if ($attribs['role'] != 'src') { $this->addFileOperation("chmod", array($mode, $dest_file)); if (!@chmod($dest_file, $mode)) { if (!isset($options['soft'])) { $this->log(0, "failed to change mode of $dest_file: " . error_get_last()["message"]); } } } } // }}} if ($attribs['role'] == 'src') { rename($dest_file, $final_dest_file); $this->log(2, "renamed source file $dest_file to $final_dest_file"); } else { $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension())); } } // Store the full path where the file was installed for easy uninstall if ($attribs['role'] != 'src') { $loc = $this->config->get($role->getLocationConfig(), null, $channel); $this->addFileOperation('installed_as', array($file, $installed_as, $loc, dirname(substr($installed_as, strlen($loc))))); } //$this->log(2, "installed: $dest_file"); return PEAR_INSTALLER_OK; } // }}} // {{{ addFileOperation() /** * Add a file operation to the current file transaction. * * @see startFileTransaction() * @param string $type This can be one of: * - rename: rename a file ($data has 3 values) * - backup: backup an existing file ($data has 1 value) * - removebackup: clean up backups created during install ($data has 1 value) * - chmod: change permissions on a file ($data has 2 values) * - delete: delete a file ($data has 1 value) * - rmdir: delete a directory if empty ($data has 1 value) * - installed_as: mark a file as installed ($data has 4 values). * @param array $data For all file operations, this array must contain the * full path to the file or directory that is being operated on. For * the rename command, the first parameter must be the file to rename, * the second its new name, the third whether this is a PHP extension. * * The installed_as operation contains 4 elements in this order: * 1. Filename as listed in the filelist element from package.xml * 2. Full path to the installed file * 3. Full path from the php_dir configuration variable used in this * installation * 4. Relative path from the php_dir that this file is installed in */ function addFileOperation($type, $data) { if (!is_array($data)) { return $this->raiseError('Internal Error: $data in addFileOperation' . ' must be an array, was ' . gettype($data)); } if ($type == 'chmod') { $octmode = decoct($data[0]); $this->log(3, "adding to transaction: $type $octmode $data[1]"); } else { $this->log(3, "adding to transaction: $type " . implode(" ", $data)); } $this->file_operations[] = array($type, $data); } // }}} // {{{ startFileTransaction() function startFileTransaction($rollback_in_case = false) { if (count($this->file_operations) && $rollback_in_case) { $this->rollbackFileTransaction(); } $this->file_operations = array(); } // }}} // {{{ commitFileTransaction() function commitFileTransaction() { // {{{ first, check permissions and such manually $errors = array(); foreach ($this->file_operations as $key => $tr) { list($type, $data) = $tr; switch ($type) { case 'rename': if (!file_exists($data[0])) { $errors[] = "cannot rename file $data[0], doesn't exist"; } // check that dest dir. is writable if (!is_writable(dirname($data[1]))) { $errors[] = "permission denied ($type): $data[1]"; } break; case 'chmod': // check that file is writable if (!is_writable($data[1])) { $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]); } break; case 'delete': if (!file_exists($data[0])) { $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted"); } // check that directory is writable if (file_exists($data[0])) { if (!is_writable(dirname($data[0]))) { $errors[] = "permission denied ($type): $data[0]"; } else { // make sure the file to be deleted can be opened for writing $fp = false; if (!is_dir($data[0]) && (!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) { $errors[] = "permission denied ($type): $data[0]"; } elseif ($fp) { fclose($fp); } } /* Verify we are not deleting a file owned by another package * This can happen when a file moves from package A to B in * an upgrade ala http://pear.php.net/17986 */ $info = array( 'package' => strtolower($this->pkginfo->getName()), 'channel' => strtolower($this->pkginfo->getChannel()), ); $result = $this->_registry->checkFileMap($data[0], $info, '1.1'); if (is_array($result)) { $res = array_diff($result, $info); if (!empty($res)) { $new = $this->_registry->getPackage($result[1], $result[0]); $this->file_operations[$key] = false; $pkginfoName = $this->pkginfo->getName(); $newChannel = $new->getChannel(); $newPackage = $new->getName(); $this->log(3, "file $data[0] was scheduled for removal from $pkginfoName but is owned by $newChannel/$newPackage, removal has been cancelled."); } } } break; } } // }}} $n = count($this->file_operations); $this->log(2, "about to commit $n file operations for " . $this->pkginfo->getName()); $m = count($errors); if ($m > 0) { foreach ($errors as $error) { if (!isset($this->_options['soft'])) { $this->log(1, $error); } } if (!isset($this->_options['ignore-errors'])) { return false; } } $this->_dirtree = array(); // {{{ really commit the transaction foreach ($this->file_operations as $i => $tr) { if (!$tr) { // support removal of non-existing backups continue; } list($type, $data) = $tr; switch ($type) { case 'backup': if (!file_exists($data[0])) { $this->file_operations[$i] = false; break; } if (!@copy($data[0], $data[0] . '.bak')) { $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] . '.bak ' . error_get_last()["message"]); return false; } $this->log(3, "+ backup $data[0] to $data[0].bak"); break; case 'removebackup': if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) { unlink($data[0] . '.bak'); $this->log(3, "+ rm backup of $data[0] ($data[0].bak)"); } break; case 'rename': $test = file_exists($data[1]) ? @unlink($data[1]) : null; if (!$test && file_exists($data[1])) { if ($data[2]) { $extra = ', this extension must be installed manually. Rename to "' . basename($data[1]) . '"'; } else { $extra = ''; } if (!isset($this->_options['soft'])) { $this->log(1, 'Could not delete ' . $data[1] . ', cannot rename ' . $data[0] . $extra); } if (!isset($this->_options['ignore-errors'])) { return false; } } // permissions issues with rename - copy() is far superior $perms = @fileperms($data[0]); if (!@copy($data[0], $data[1])) { $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] . ' ' . error_get_last()["message"]); return false; } // copy over permissions, otherwise they are lost @chmod($data[1], $perms); @unlink($data[0]); $this->log(3, "+ mv $data[0] $data[1]"); break; case 'chmod': if (!@chmod($data[1], $data[0])) { $this->log(1, 'Could not chmod ' . $data[1] . ' to ' . decoct($data[0]) . ' ' . error_get_last()["message"]); return false; } $octmode = decoct($data[0]); $this->log(3, "+ chmod $octmode $data[1]"); break; case 'delete': if (file_exists($data[0])) { if (!@unlink($data[0])) { $this->log(1, 'Could not delete ' . $data[0] . ' ' . error_get_last()["message"]); return false; } $this->log(3, "+ rm $data[0]"); } break; case 'rmdir': if (file_exists($data[0])) { do { $testme = opendir($data[0]); while (false !== ($entry = readdir($testme))) { if ($entry == '.' || $entry == '..') { continue; } closedir($testme); break 2; // this directory is not empty and can't be // deleted } closedir($testme); if (!@rmdir($data[0])) { $this->log(1, 'Could not rmdir ' . $data[0] . ' ' . error_get_last()["message"]); return false; } $this->log(3, "+ rmdir $data[0]"); } while (false); } break; case 'installed_as': $this->pkginfo->setInstalledAs($data[0], $data[1]); if (!isset($this->_dirtree[dirname($data[1])])) { $this->_dirtree[dirname($data[1])] = true; $this->pkginfo->setDirtree(dirname($data[1])); while(!empty($data[3]) && dirname($data[3]) != $data[3] && $data[3] != '/' && $data[3] != '\\') { $this->pkginfo->setDirtree($pp = $this->_prependPath($data[3], $data[2])); $this->_dirtree[$pp] = true; $data[3] = dirname($data[3]); } } break; } } // }}} $this->log(2, "successfully committed $n file operations"); $this->file_operations = array(); return true; } // }}} // {{{ rollbackFileTransaction() function rollbackFileTransaction() { $n = count($this->file_operations); $this->log(2, "rolling back $n file operations"); foreach ($this->file_operations as $tr) { list($type, $data) = $tr; switch ($type) { case 'backup': if (file_exists($data[0] . '.bak')) { if (file_exists($data[0] && is_writable($data[0]))) { unlink($data[0]); } @copy($data[0] . '.bak', $data[0]); $this->log(3, "+ restore $data[0] from $data[0].bak"); } break; case 'removebackup': if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) { unlink($data[0] . '.bak'); $this->log(3, "+ rm backup of $data[0] ($data[0].bak)"); } break; case 'rename': @unlink($data[0]); $this->log(3, "+ rm $data[0]"); break; case 'mkdir': @rmdir($data[0]); $this->log(3, "+ rmdir $data[0]"); break; case 'chmod': break; case 'delete': break; case 'installed_as': $this->pkginfo->setInstalledAs($data[0], false); break; } } $this->pkginfo->resetDirtree(); $this->file_operations = array(); } // }}} // {{{ mkDirHier($dir) function mkDirHier($dir) { $this->addFileOperation('mkdir', array($dir)); return parent::mkDirHier($dir); } // }}} // {{{ _parsePackageXml() function _parsePackageXml(&$descfile) { // Parse xml file ----------------------------------------------- $pkg = new PEAR_PackageFile($this->config, $this->debug); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING); PEAR::staticPopErrorHandling(); if (PEAR::isError($p)) { if (is_array($p->getUserInfo())) { foreach ($p->getUserInfo() as $err) { $loglevel = $err['level'] == 'error' ? 0 : 1; if (!isset($this->_options['soft'])) { $this->log($loglevel, ucfirst($err['level']) . ': ' . $err['message']); } } } return $this->raiseError('Installation failed: invalid package file'); } $descfile = $p->getPackageFile(); return $p; } // }}} /** * Set the list of PEAR_Downloader_Package objects to allow more sane * dependency validation * @param array */ function setDownloadedPackages(&$pkgs) { PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $err = $this->analyzeDependencies($pkgs); PEAR::popErrorHandling(); if (PEAR::isError($err)) { return $err; } $this->_downloadedPackages = &$pkgs; } /** * Set the list of PEAR_Downloader_Package objects to allow more sane * dependency validation * @param array */ function setUninstallPackages(&$pkgs) { $this->_downloadedPackages = &$pkgs; } function getInstallPackages() { return $this->_downloadedPackages; } // {{{ install() /** * Installs the files within the package file specified. * * @param string|PEAR_Downloader_Package $pkgfile path to the package file, * or a pre-initialized packagefile object * @param array $options * recognized options: * - installroot : optional prefix directory for installation * - force : force installation * - register-only : update registry but don't install files * - upgrade : upgrade existing install * - soft : fail silently * - nodeps : ignore dependency conflicts/missing dependencies * - alldeps : install all dependencies * - onlyreqdeps : install only required dependencies * * @return array|PEAR_Error package info if successful */ function install($pkgfile, $options = array()) { $this->_options = $options; $this->_registry = &$this->config->getRegistry(); if (is_object($pkgfile)) { $dlpkg = &$pkgfile; $pkg = $pkgfile->getPackageFile(); $pkgfile = $pkg->getArchiveFile(); $descfile = $pkg->getPackageFile(); } else { $descfile = $pkgfile; $pkg = $this->_parsePackageXml($descfile); if (PEAR::isError($pkg)) { return $pkg; } } $tmpdir = dirname($descfile); if (realpath($descfile) != realpath($pkgfile)) { // Use the temp_dir since $descfile can contain the download dir path $tmpdir = $this->config->get('temp_dir', null, 'pear.php.net'); $tmpdir = System::mktemp('-d -t "' . $tmpdir . '"'); $tar = new Archive_Tar($pkgfile); if (!$tar->extract($tmpdir)) { return $this->raiseError("unable to unpack $pkgfile"); } } $pkgname = $pkg->getName(); $channel = $pkg->getChannel(); if (isset($options['installroot'])) { $this->config->setInstallRoot($options['installroot']); $this->_registry = &$this->config->getRegistry(); $installregistry = &$this->_registry; $this->installroot = ''; // all done automagically now $php_dir = $this->config->get('php_dir', null, $channel); } else { $this->config->setInstallRoot(false); $this->_registry = &$this->config->getRegistry(); if (isset($this->_options['packagingroot'])) { $regdir = $this->_prependPath( $this->config->get('php_dir', null, 'pear.php.net'), $this->_options['packagingroot']); $metadata_dir = $this->config->get('metadata_dir', null, 'pear.php.net'); if ($metadata_dir) { $metadata_dir = $this->_prependPath( $metadata_dir, $this->_options['packagingroot']); } $packrootphp_dir = $this->_prependPath( $this->config->get('php_dir', null, $channel), $this->_options['packagingroot']); $installregistry = new PEAR_Registry($regdir, false, false, $metadata_dir); if (!$installregistry->channelExists($channel, true)) { // we need to fake a channel-discover of this channel $chanobj = $this->_registry->getChannel($channel, true); $installregistry->addChannel($chanobj); } $php_dir = $packrootphp_dir; } else { $installregistry = &$this->_registry; $php_dir = $this->config->get('php_dir', null, $channel); } $this->installroot = ''; } // {{{ checks to do when not in "force" mode if (empty($options['force']) && (file_exists($this->config->get('php_dir')) && is_dir($this->config->get('php_dir')))) { $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname); $instfilelist = $pkg->getInstallationFileList(true); if (PEAR::isError($instfilelist)) { return $instfilelist; } // ensure we have the most accurate registry $installregistry->flushFileMap(); $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1'); if (PEAR::isError($test)) { return $test; } if (sizeof($test)) { $pkgs = $this->getInstallPackages(); $found = false; foreach ($pkgs as $param) { if ($pkg->isSubpackageOf($param)) { $found = true; break; } } if ($found) { // subpackages can conflict with earlier versions of parent packages $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel()); $tmp = $test; foreach ($tmp as $file => $info) { if (is_array($info)) { if (strtolower($info[1]) == strtolower($param->getPackage()) && strtolower($info[0]) == strtolower($param->getChannel()) ) { if (isset($parentreg['filelist'][$file])) { unset($parentreg['filelist'][$file]); } else{ $pos = strpos($file, '/'); $basedir = substr($file, 0, $pos); $file2 = substr($file, $pos + 1); if (isset($parentreg['filelist'][$file2]['baseinstalldir']) && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir ) { unset($parentreg['filelist'][$file2]); } } unset($test[$file]); } } else { if (strtolower($param->getChannel()) != 'pear.php.net') { continue; } if (strtolower($info) == strtolower($param->getPackage())) { if (isset($parentreg['filelist'][$file])) { unset($parentreg['filelist'][$file]); } else{ $pos = strpos($file, '/'); $basedir = substr($file, 0, $pos); $file2 = substr($file, $pos + 1); if (isset($parentreg['filelist'][$file2]['baseinstalldir']) && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir ) { unset($parentreg['filelist'][$file2]); } } unset($test[$file]); } } } $pfk = new PEAR_PackageFile($this->config); $parentpkg = &$pfk->fromArray($parentreg); $installregistry->updatePackage2($parentpkg); } if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) { $tmp = $test; foreach ($tmp as $file => $info) { if (is_string($info)) { // pear.php.net packages are always stored as strings if (strtolower($info) == strtolower($param->getPackage())) { // upgrading existing package unset($test[$file]); } } } } if (count($test)) { $msg = "$channel/$pkgname: conflicting files found:\n"; $longest = max(array_map("strlen", array_keys($test))); $fmt = "%{$longest}s (%s)\n"; foreach ($test as $file => $info) { if (!is_array($info)) { $info = array('pear.php.net', $info); } $info = $info[0] . '/' . $info[1]; $msg .= sprintf($fmt, $file, $info); } if (!isset($options['ignore-errors'])) { return $this->raiseError($msg); } if (!isset($options['soft'])) { $this->log(0, "WARNING: $msg"); } } } } // }}} $this->startFileTransaction(); $usechannel = $channel; if ($channel == 'pecl.php.net') { $test = $installregistry->packageExists($pkgname, $channel); if (!$test) { $test = $installregistry->packageExists($pkgname, 'pear.php.net'); $usechannel = 'pear.php.net'; } } else { $test = $installregistry->packageExists($pkgname, $channel); } if (empty($options['upgrade']) && empty($options['soft'])) { // checks to do only when installing new packages if (empty($options['force']) && $test) { return $this->raiseError("$channel/$pkgname is already installed"); } } else { // Upgrade if ($test) { $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel); $v2 = $pkg->getVersion(); $cmp = version_compare("$v1", "$v2", 'gt'); if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) { return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)"); } } } // Do cleanups for upgrade and install, remove old release's files first if ($test && empty($options['register-only'])) { // when upgrading, remove old release's files first: if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel, true))) { if (!isset($options['ignore-errors'])) { return $this->raiseError($err); } if (!isset($options['soft'])) { $this->log(0, 'WARNING: ' . $err->getMessage()); } } else { $backedup = $err; } } // {{{ Copy files to dest dir --------------------------------------- // info from the package it self we want to access from _installFile $this->pkginfo = &$pkg; // used to determine whether we should build any C code $this->source_files = 0; $savechannel = $this->config->get('default_channel'); if (empty($options['register-only']) && !is_dir($php_dir)) { if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) { return $this->raiseError("no installation destination directory '$php_dir'\n"); } } if (substr($pkgfile, -4) != '.xml') { $tmpdir .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion(); } $this->configSet('default_channel', $channel); // {{{ install files $ver = $pkg->getPackagexmlVersion(); if (version_compare($ver, '2.0', '>=')) { $filelist = $pkg->getInstallationFilelist(); } else { $filelist = $pkg->getFileList(); } if (PEAR::isError($filelist)) { return $filelist; } $p = &$installregistry->getPackage($pkgname, $channel); $dirtree = (empty($options['register-only']) && $p) ? $p->getDirTree() : false; $pkg->resetFilelist(); $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(), 'version', $pkg->getChannel())); foreach ($filelist as $file => $atts) { $this->expectError(PEAR_INSTALLER_FAILED); if ($pkg->getPackagexmlVersion() == '1.0') { $res = $this->_installFile($file, $atts, $tmpdir, $options); } else { $res = $this->_installFile2($pkg, $file, $atts, $tmpdir, $options); } $this->popExpect(); if (PEAR::isError($res)) { if (empty($options['ignore-errors'])) { $this->rollbackFileTransaction(); if ($res->getMessage() == "file does not exist") { $this->raiseError("file $file in package.xml does not exist"); } return $this->raiseError($res); } if (!isset($options['soft'])) { $this->log(0, "Warning: " . $res->getMessage()); } } $real = isset($atts['attribs']) ? $atts['attribs'] : $atts; if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') { // Register files that were installed $pkg->installedFile($file, $atts); } } // }}} // {{{ compile and install source files if ($this->source_files > 0 && empty($options['nobuild'])) { $configureoptions = empty($options['configureoptions']) ? '' : $options['configureoptions']; if (PEAR::isError($err = $this->_compileSourceFiles($savechannel, $pkg, $configureoptions))) { return $err; } } // }}} if (isset($backedup)) { $this->_removeBackups($backedup); } if (!$this->commitFileTransaction()) { $this->rollbackFileTransaction(); $this->configSet('default_channel', $savechannel); return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED); } // }}} $ret = false; $installphase = 'install'; $oldversion = false; // {{{ Register that the package is installed ----------------------- if (empty($options['upgrade'])) { // if 'force' is used, replace the info in registry $usechannel = $channel; if ($channel == 'pecl.php.net') { $test = $installregistry->packageExists($pkgname, $channel); if (!$test) { $test = $installregistry->packageExists($pkgname, 'pear.php.net'); $usechannel = 'pear.php.net'; } } else { $test = $installregistry->packageExists($pkgname, $channel); } if (!empty($options['force']) && $test) { $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel); $installregistry->deletePackage($pkgname, $usechannel); } $ret = $installregistry->addPackage2($pkg); } else { if ($dirtree) { $this->startFileTransaction(); // attempt to delete empty directories uksort($dirtree, array($this, '_sortDirs')); foreach($dirtree as $dir => $notused) { $this->addFileOperation('rmdir', array($dir)); } $this->commitFileTransaction(); } $usechannel = $channel; if ($channel == 'pecl.php.net') { $test = $installregistry->packageExists($pkgname, $channel); if (!$test) { $test = $installregistry->packageExists($pkgname, 'pear.php.net'); $usechannel = 'pear.php.net'; } } else { $test = $installregistry->packageExists($pkgname, $channel); } // new: upgrade installs a package if it isn't installed if (!$test) { $ret = $installregistry->addPackage2($pkg); } else { if ($usechannel != $channel) { $installregistry->deletePackage($pkgname, $usechannel); $ret = $installregistry->addPackage2($pkg); } else { $ret = $installregistry->updatePackage2($pkg); } $installphase = 'upgrade'; } } if (!$ret) { $this->configSet('default_channel', $savechannel); return $this->raiseError("Adding package $channel/$pkgname to registry failed"); } // }}} $this->configSet('default_channel', $savechannel); if (class_exists('PEAR_Task_Common')) { // this is auto-included if any tasks exist if (PEAR_Task_Common::hasPostinstallTasks()) { PEAR_Task_Common::runPostinstallTasks($installphase); } } return $pkg->toArray(true); } // }}} // {{{ _compileSourceFiles() /** * @param string * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @param mixed[] $configureoptions */ function _compileSourceFiles($savechannel, &$filelist, $configureoptions) { require_once 'PEAR/Builder.php'; $this->log(1, "$this->source_files source files, building"); $bob = new PEAR_Builder($configureoptions, $this->ui); $bob->debug = $this->debug; $built = $bob->build($filelist, array(&$this, '_buildCallback')); if (PEAR::isError($built)) { $this->rollbackFileTransaction(); $this->configSet('default_channel', $savechannel); return $built; } $this->log(1, "\nBuild process completed successfully"); foreach ($built as $ext) { $bn = basename($ext['file']); list($_ext_name, $_ext_suff) = explode('.', $bn); if ($_ext_suff == 'so' || $_ext_suff == 'dll') { if (extension_loaded($_ext_name)) { return $this->raiseError("Extension '$_ext_name' already loaded. " . 'Please unload it in your php.ini file ' . 'prior to install or upgrade'); } $role = 'ext'; } else { $role = 'src'; } $dest = $ext['dest']; $packagingroot = ''; if (isset($this->_options['packagingroot'])) { $packagingroot = $this->_options['packagingroot']; } $copyto = $this->_prependPath($dest, $packagingroot); $extra = $copyto != $dest ? " as '$copyto'" : ''; $this->log(1, "Installing '$dest'$extra"); $copydir = dirname($copyto); // pretty much nothing happens if we are only registering the install if (empty($this->_options['register-only'])) { if (!file_exists($copydir) || !is_dir($copydir)) { if (!$this->mkDirHier($copydir)) { return $this->raiseError("failed to mkdir $copydir", PEAR_INSTALLER_FAILED); } $this->log(3, "+ mkdir $copydir"); } if (!@copy($ext['file'], $copyto)) { return $this->raiseError( "failed to write $copyto (" . error_get_last()["message"] . ")", PEAR_INSTALLER_FAILED); } $this->log(3, "+ cp $ext[file] $copyto"); $this->addFileOperation('rename', array($ext['file'], $copyto)); if (!OS_WINDOWS) { $mode = 0666 & ~(int)octdec($this->config->get('umask')); $this->addFileOperation('chmod', array($mode, $copyto)); if (!@chmod($copyto, $mode)) { $this->log(0, "failed to change mode of $copyto (" . error_get_last()["message"] . ")"); } } } $data = array( 'role' => $role, 'name' => $bn, 'installed_as' => $dest, 'php_api' => $ext['php_api'], 'zend_mod_api' => $ext['zend_mod_api'], 'zend_ext_api' => $ext['zend_ext_api'], ); if ($filelist->getPackageXmlVersion() == '1.0') { $filelist->installedFile($bn, $data); } else { $filelist->installedFile($bn, array('attribs' => $data)); } } } // }}} function &getUninstallPackages() { return $this->_downloadedPackages; } // {{{ uninstall() /** * Uninstall a package * * This method removes all files installed by the application, and then * removes any empty directories. * @param string package name * @param array Command-line options. Possibilities include: * * - installroot: base installation dir, if not the default * - register-only : update registry but don't remove files * - nodeps: do not process dependencies of other packages to ensure * uninstallation does not break things */ function uninstall($package, $options = array()) { $installRoot = isset($options['installroot']) ? $options['installroot'] : ''; $this->config->setInstallRoot($installRoot); $this->installroot = ''; $this->_registry = &$this->config->getRegistry(); if (is_object($package)) { $channel = $package->getChannel(); $pkg = $package; $package = $pkg->getPackage(); } else { $pkg = false; $info = $this->_registry->parsePackageName($package, $this->config->get('default_channel')); $channel = $info['channel']; $package = $info['package']; } $savechannel = $this->config->get('default_channel'); $this->configSet('default_channel', $channel); if (!is_object($pkg)) { $pkg = $this->_registry->getPackage($package, $channel); } if (!$pkg) { $this->configSet('default_channel', $savechannel); return $this->raiseError($this->_registry->parsedPackageNameToString( array( 'channel' => $channel, 'package' => $package ), true) . ' not installed'); } if ($pkg->getInstalledBinary()) { // this is just an alias for a binary package return $this->_registry->deletePackage($package, $channel); } $filelist = $pkg->getFilelist(); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); if (!class_exists('PEAR_Dependency2')) { require_once 'PEAR/Dependency2.php'; } $depchecker = new PEAR_Dependency2($this->config, $options, array('channel' => $channel, 'package' => $package), PEAR_VALIDATE_UNINSTALLING); $e = $depchecker->validatePackageUninstall($this); PEAR::staticPopErrorHandling(); if (PEAR::isError($e)) { if (!isset($options['ignore-errors'])) { return $this->raiseError($e); } if (!isset($options['soft'])) { $this->log(0, 'WARNING: ' . $e->getMessage()); } } elseif (is_array($e)) { if (!isset($options['soft'])) { $this->log(0, $e[0]); } } $this->pkginfo = &$pkg; // pretty much nothing happens if we are only registering the uninstall if (empty($options['register-only'])) { // {{{ Delete the files $this->startFileTransaction(); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) { PEAR::popErrorHandling(); $this->rollbackFileTransaction(); $this->configSet('default_channel', $savechannel); if (!isset($options['ignore-errors'])) { return $this->raiseError($err); } if (!isset($options['soft'])) { $this->log(0, 'WARNING: ' . $err->getMessage()); } } else { PEAR::popErrorHandling(); } if (!$this->commitFileTransaction()) { $this->rollbackFileTransaction(); if (!isset($options['ignore-errors'])) { return $this->raiseError("uninstall failed"); } if (!isset($options['soft'])) { $this->log(0, 'WARNING: uninstall failed'); } } else { $this->startFileTransaction(); $dirtree = $pkg->getDirTree(); if ($dirtree === false) { $this->configSet('default_channel', $savechannel); return $this->_registry->deletePackage($package, $channel); } // attempt to delete empty directories uksort($dirtree, array($this, '_sortDirs')); foreach($dirtree as $dir => $notused) { $this->addFileOperation('rmdir', array($dir)); } if (!$this->commitFileTransaction()) { $this->rollbackFileTransaction(); if (!isset($options['ignore-errors'])) { return $this->raiseError("uninstall failed"); } if (!isset($options['soft'])) { $this->log(0, 'WARNING: uninstall failed'); } } } // }}} } $this->configSet('default_channel', $savechannel); // Register that the package is no longer installed return $this->_registry->deletePackage($package, $channel); } /** * Sort a list of arrays of array(downloaded packagefilename) by dependency. * * It also removes duplicate dependencies * @param array an array of PEAR_PackageFile_v[1/2] objects * @return array|PEAR_Error array of array(packagefilename, package.xml contents) */ function sortPackagesForUninstall(&$packages) { $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->config); if (PEAR::isError($this->_dependencyDB)) { return $this->_dependencyDB; } usort($packages, array(&$this, '_sortUninstall')); } function _sortUninstall($a, $b) { if (!$a->getDeps() && !$b->getDeps()) { return 0; // neither package has dependencies, order is insignificant } if ($a->getDeps() && !$b->getDeps()) { return -1; // $a must be installed after $b because $a has dependencies } if (!$a->getDeps() && $b->getDeps()) { return 1; // $b must be installed after $a because $b has dependencies } // both packages have dependencies if ($this->_dependencyDB->dependsOn($a, $b)) { return -1; } if ($this->_dependencyDB->dependsOn($b, $a)) { return 1; } return 0; } // }}} // {{{ _sortDirs() function _sortDirs($a, $b) { if (strnatcmp($a, $b) == -1) return 1; if (strnatcmp($a, $b) == 1) return -1; return 0; } // }}} // {{{ _buildCallback() function _buildCallback($what, $data) { if (($what == 'cmdoutput' && $this->debug > 1) || ($what == 'output' && $this->debug > 0)) { $this->ui->outputData(rtrim($data), 'build'); } } // }}} } PK!#K Net/IDNA2.phpnu[ * @author Matthias Sommerfeld * @author Stefan Neufeind * @version $Id: IDNA2.php 305344 2010-11-14 23:52:42Z neufeind $ */ class Net_IDNA2 { // {{{ npdata /** * These Unicode codepoints are * mapped to nothing, See RFC3454 for details * * @static * @var array * @access private */ private static $_np_map_nothing = array( 0xAD, 0x34F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF ); /** * Prohibited codepints * * @static * @var array * @access private */ private static $_general_prohibited = array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2F, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x3002 ); /** * Codepints prohibited by Nameprep * @static * @var array * @access private */ private static $_np_prohibit = array( 0xA0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x202F, 0x205F, 0x3000, 0x6DD, 0x70F, 0x180E, 0x200C, 0x200D, 0x2028, 0x2029, 0xFEFF, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0x340, 0x341, 0x200E, 0x200F, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E, 0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F, 0xE0001 ); /** * Codepoint ranges prohibited by nameprep * * @static * @var array * @access private */ private static $_np_prohibit_ranges = array( array(0x80, 0x9F ), array(0x2060, 0x206F ), array(0x1D173, 0x1D17A ), array(0xE000, 0xF8FF ), array(0xF0000, 0xFFFFD ), array(0x100000, 0x10FFFD), array(0xFDD0, 0xFDEF ), array(0xD800, 0xDFFF ), array(0x2FF0, 0x2FFB ), array(0xE0020, 0xE007F ) ); /** * Replacement mappings (casemapping, replacement sequences, ...) * * @static * @var array * @access private */ private static $_np_replacemaps = array( 0x41 => array(0x61), 0x42 => array(0x62), 0x43 => array(0x63), 0x44 => array(0x64), 0x45 => array(0x65), 0x46 => array(0x66), 0x47 => array(0x67), 0x48 => array(0x68), 0x49 => array(0x69), 0x4A => array(0x6A), 0x4B => array(0x6B), 0x4C => array(0x6C), 0x4D => array(0x6D), 0x4E => array(0x6E), 0x4F => array(0x6F), 0x50 => array(0x70), 0x51 => array(0x71), 0x52 => array(0x72), 0x53 => array(0x73), 0x54 => array(0x74), 0x55 => array(0x75), 0x56 => array(0x76), 0x57 => array(0x77), 0x58 => array(0x78), 0x59 => array(0x79), 0x5A => array(0x7A), 0xB5 => array(0x3BC), 0xC0 => array(0xE0), 0xC1 => array(0xE1), 0xC2 => array(0xE2), 0xC3 => array(0xE3), 0xC4 => array(0xE4), 0xC5 => array(0xE5), 0xC6 => array(0xE6), 0xC7 => array(0xE7), 0xC8 => array(0xE8), 0xC9 => array(0xE9), 0xCA => array(0xEA), 0xCB => array(0xEB), 0xCC => array(0xEC), 0xCD => array(0xED), 0xCE => array(0xEE), 0xCF => array(0xEF), 0xD0 => array(0xF0), 0xD1 => array(0xF1), 0xD2 => array(0xF2), 0xD3 => array(0xF3), 0xD4 => array(0xF4), 0xD5 => array(0xF5), 0xD6 => array(0xF6), 0xD8 => array(0xF8), 0xD9 => array(0xF9), 0xDA => array(0xFA), 0xDB => array(0xFB), 0xDC => array(0xFC), 0xDD => array(0xFD), 0xDE => array(0xFE), 0xDF => array(0x73, 0x73), 0x100 => array(0x101), 0x102 => array(0x103), 0x104 => array(0x105), 0x106 => array(0x107), 0x108 => array(0x109), 0x10A => array(0x10B), 0x10C => array(0x10D), 0x10E => array(0x10F), 0x110 => array(0x111), 0x112 => array(0x113), 0x114 => array(0x115), 0x116 => array(0x117), 0x118 => array(0x119), 0x11A => array(0x11B), 0x11C => array(0x11D), 0x11E => array(0x11F), 0x120 => array(0x121), 0x122 => array(0x123), 0x124 => array(0x125), 0x126 => array(0x127), 0x128 => array(0x129), 0x12A => array(0x12B), 0x12C => array(0x12D), 0x12E => array(0x12F), 0x130 => array(0x69, 0x307), 0x132 => array(0x133), 0x134 => array(0x135), 0x136 => array(0x137), 0x139 => array(0x13A), 0x13B => array(0x13C), 0x13D => array(0x13E), 0x13F => array(0x140), 0x141 => array(0x142), 0x143 => array(0x144), 0x145 => array(0x146), 0x147 => array(0x148), 0x149 => array(0x2BC, 0x6E), 0x14A => array(0x14B), 0x14C => array(0x14D), 0x14E => array(0x14F), 0x150 => array(0x151), 0x152 => array(0x153), 0x154 => array(0x155), 0x156 => array(0x157), 0x158 => array(0x159), 0x15A => array(0x15B), 0x15C => array(0x15D), 0x15E => array(0x15F), 0x160 => array(0x161), 0x162 => array(0x163), 0x164 => array(0x165), 0x166 => array(0x167), 0x168 => array(0x169), 0x16A => array(0x16B), 0x16C => array(0x16D), 0x16E => array(0x16F), 0x170 => array(0x171), 0x172 => array(0x173), 0x174 => array(0x175), 0x176 => array(0x177), 0x178 => array(0xFF), 0x179 => array(0x17A), 0x17B => array(0x17C), 0x17D => array(0x17E), 0x17F => array(0x73), 0x181 => array(0x253), 0x182 => array(0x183), 0x184 => array(0x185), 0x186 => array(0x254), 0x187 => array(0x188), 0x189 => array(0x256), 0x18A => array(0x257), 0x18B => array(0x18C), 0x18E => array(0x1DD), 0x18F => array(0x259), 0x190 => array(0x25B), 0x191 => array(0x192), 0x193 => array(0x260), 0x194 => array(0x263), 0x196 => array(0x269), 0x197 => array(0x268), 0x198 => array(0x199), 0x19C => array(0x26F), 0x19D => array(0x272), 0x19F => array(0x275), 0x1A0 => array(0x1A1), 0x1A2 => array(0x1A3), 0x1A4 => array(0x1A5), 0x1A6 => array(0x280), 0x1A7 => array(0x1A8), 0x1A9 => array(0x283), 0x1AC => array(0x1AD), 0x1AE => array(0x288), 0x1AF => array(0x1B0), 0x1B1 => array(0x28A), 0x1B2 => array(0x28B), 0x1B3 => array(0x1B4), 0x1B5 => array(0x1B6), 0x1B7 => array(0x292), 0x1B8 => array(0x1B9), 0x1BC => array(0x1BD), 0x1C4 => array(0x1C6), 0x1C5 => array(0x1C6), 0x1C7 => array(0x1C9), 0x1C8 => array(0x1C9), 0x1CA => array(0x1CC), 0x1CB => array(0x1CC), 0x1CD => array(0x1CE), 0x1CF => array(0x1D0), 0x1D1 => array(0x1D2), 0x1D3 => array(0x1D4), 0x1D5 => array(0x1D6), 0x1D7 => array(0x1D8), 0x1D9 => array(0x1DA), 0x1DB => array(0x1DC), 0x1DE => array(0x1DF), 0x1E0 => array(0x1E1), 0x1E2 => array(0x1E3), 0x1E4 => array(0x1E5), 0x1E6 => array(0x1E7), 0x1E8 => array(0x1E9), 0x1EA => array(0x1EB), 0x1EC => array(0x1ED), 0x1EE => array(0x1EF), 0x1F0 => array(0x6A, 0x30C), 0x1F1 => array(0x1F3), 0x1F2 => array(0x1F3), 0x1F4 => array(0x1F5), 0x1F6 => array(0x195), 0x1F7 => array(0x1BF), 0x1F8 => array(0x1F9), 0x1FA => array(0x1FB), 0x1FC => array(0x1FD), 0x1FE => array(0x1FF), 0x200 => array(0x201), 0x202 => array(0x203), 0x204 => array(0x205), 0x206 => array(0x207), 0x208 => array(0x209), 0x20A => array(0x20B), 0x20C => array(0x20D), 0x20E => array(0x20F), 0x210 => array(0x211), 0x212 => array(0x213), 0x214 => array(0x215), 0x216 => array(0x217), 0x218 => array(0x219), 0x21A => array(0x21B), 0x21C => array(0x21D), 0x21E => array(0x21F), 0x220 => array(0x19E), 0x222 => array(0x223), 0x224 => array(0x225), 0x226 => array(0x227), 0x228 => array(0x229), 0x22A => array(0x22B), 0x22C => array(0x22D), 0x22E => array(0x22F), 0x230 => array(0x231), 0x232 => array(0x233), 0x345 => array(0x3B9), 0x37A => array(0x20, 0x3B9), 0x386 => array(0x3AC), 0x388 => array(0x3AD), 0x389 => array(0x3AE), 0x38A => array(0x3AF), 0x38C => array(0x3CC), 0x38E => array(0x3CD), 0x38F => array(0x3CE), 0x390 => array(0x3B9, 0x308, 0x301), 0x391 => array(0x3B1), 0x392 => array(0x3B2), 0x393 => array(0x3B3), 0x394 => array(0x3B4), 0x395 => array(0x3B5), 0x396 => array(0x3B6), 0x397 => array(0x3B7), 0x398 => array(0x3B8), 0x399 => array(0x3B9), 0x39A => array(0x3BA), 0x39B => array(0x3BB), 0x39C => array(0x3BC), 0x39D => array(0x3BD), 0x39E => array(0x3BE), 0x39F => array(0x3BF), 0x3A0 => array(0x3C0), 0x3A1 => array(0x3C1), 0x3A3 => array(0x3C3), 0x3A4 => array(0x3C4), 0x3A5 => array(0x3C5), 0x3A6 => array(0x3C6), 0x3A7 => array(0x3C7), 0x3A8 => array(0x3C8), 0x3A9 => array(0x3C9), 0x3AA => array(0x3CA), 0x3AB => array(0x3CB), 0x3B0 => array(0x3C5, 0x308, 0x301), 0x3C2 => array(0x3C3), 0x3D0 => array(0x3B2), 0x3D1 => array(0x3B8), 0x3D2 => array(0x3C5), 0x3D3 => array(0x3CD), 0x3D4 => array(0x3CB), 0x3D5 => array(0x3C6), 0x3D6 => array(0x3C0), 0x3D8 => array(0x3D9), 0x3DA => array(0x3DB), 0x3DC => array(0x3DD), 0x3DE => array(0x3DF), 0x3E0 => array(0x3E1), 0x3E2 => array(0x3E3), 0x3E4 => array(0x3E5), 0x3E6 => array(0x3E7), 0x3E8 => array(0x3E9), 0x3EA => array(0x3EB), 0x3EC => array(0x3ED), 0x3EE => array(0x3EF), 0x3F0 => array(0x3BA), 0x3F1 => array(0x3C1), 0x3F2 => array(0x3C3), 0x3F4 => array(0x3B8), 0x3F5 => array(0x3B5), 0x400 => array(0x450), 0x401 => array(0x451), 0x402 => array(0x452), 0x403 => array(0x453), 0x404 => array(0x454), 0x405 => array(0x455), 0x406 => array(0x456), 0x407 => array(0x457), 0x408 => array(0x458), 0x409 => array(0x459), 0x40A => array(0x45A), 0x40B => array(0x45B), 0x40C => array(0x45C), 0x40D => array(0x45D), 0x40E => array(0x45E), 0x40F => array(0x45F), 0x410 => array(0x430), 0x411 => array(0x431), 0x412 => array(0x432), 0x413 => array(0x433), 0x414 => array(0x434), 0x415 => array(0x435), 0x416 => array(0x436), 0x417 => array(0x437), 0x418 => array(0x438), 0x419 => array(0x439), 0x41A => array(0x43A), 0x41B => array(0x43B), 0x41C => array(0x43C), 0x41D => array(0x43D), 0x41E => array(0x43E), 0x41F => array(0x43F), 0x420 => array(0x440), 0x421 => array(0x441), 0x422 => array(0x442), 0x423 => array(0x443), 0x424 => array(0x444), 0x425 => array(0x445), 0x426 => array(0x446), 0x427 => array(0x447), 0x428 => array(0x448), 0x429 => array(0x449), 0x42A => array(0x44A), 0x42B => array(0x44B), 0x42C => array(0x44C), 0x42D => array(0x44D), 0x42E => array(0x44E), 0x42F => array(0x44F), 0x460 => array(0x461), 0x462 => array(0x463), 0x464 => array(0x465), 0x466 => array(0x467), 0x468 => array(0x469), 0x46A => array(0x46B), 0x46C => array(0x46D), 0x46E => array(0x46F), 0x470 => array(0x471), 0x472 => array(0x473), 0x474 => array(0x475), 0x476 => array(0x477), 0x478 => array(0x479), 0x47A => array(0x47B), 0x47C => array(0x47D), 0x47E => array(0x47F), 0x480 => array(0x481), 0x48A => array(0x48B), 0x48C => array(0x48D), 0x48E => array(0x48F), 0x490 => array(0x491), 0x492 => array(0x493), 0x494 => array(0x495), 0x496 => array(0x497), 0x498 => array(0x499), 0x49A => array(0x49B), 0x49C => array(0x49D), 0x49E => array(0x49F), 0x4A0 => array(0x4A1), 0x4A2 => array(0x4A3), 0x4A4 => array(0x4A5), 0x4A6 => array(0x4A7), 0x4A8 => array(0x4A9), 0x4AA => array(0x4AB), 0x4AC => array(0x4AD), 0x4AE => array(0x4AF), 0x4B0 => array(0x4B1), 0x4B2 => array(0x4B3), 0x4B4 => array(0x4B5), 0x4B6 => array(0x4B7), 0x4B8 => array(0x4B9), 0x4BA => array(0x4BB), 0x4BC => array(0x4BD), 0x4BE => array(0x4BF), 0x4C1 => array(0x4C2), 0x4C3 => array(0x4C4), 0x4C5 => array(0x4C6), 0x4C7 => array(0x4C8), 0x4C9 => array(0x4CA), 0x4CB => array(0x4CC), 0x4CD => array(0x4CE), 0x4D0 => array(0x4D1), 0x4D2 => array(0x4D3), 0x4D4 => array(0x4D5), 0x4D6 => array(0x4D7), 0x4D8 => array(0x4D9), 0x4DA => array(0x4DB), 0x4DC => array(0x4DD), 0x4DE => array(0x4DF), 0x4E0 => array(0x4E1), 0x4E2 => array(0x4E3), 0x4E4 => array(0x4E5), 0x4E6 => array(0x4E7), 0x4E8 => array(0x4E9), 0x4EA => array(0x4EB), 0x4EC => array(0x4ED), 0x4EE => array(0x4EF), 0x4F0 => array(0x4F1), 0x4F2 => array(0x4F3), 0x4F4 => array(0x4F5), 0x4F8 => array(0x4F9), 0x500 => array(0x501), 0x502 => array(0x503), 0x504 => array(0x505), 0x506 => array(0x507), 0x508 => array(0x509), 0x50A => array(0x50B), 0x50C => array(0x50D), 0x50E => array(0x50F), 0x531 => array(0x561), 0x532 => array(0x562), 0x533 => array(0x563), 0x534 => array(0x564), 0x535 => array(0x565), 0x536 => array(0x566), 0x537 => array(0x567), 0x538 => array(0x568), 0x539 => array(0x569), 0x53A => array(0x56A), 0x53B => array(0x56B), 0x53C => array(0x56C), 0x53D => array(0x56D), 0x53E => array(0x56E), 0x53F => array(0x56F), 0x540 => array(0x570), 0x541 => array(0x571), 0x542 => array(0x572), 0x543 => array(0x573), 0x544 => array(0x574), 0x545 => array(0x575), 0x546 => array(0x576), 0x547 => array(0x577), 0x548 => array(0x578), 0x549 => array(0x579), 0x54A => array(0x57A), 0x54B => array(0x57B), 0x54C => array(0x57C), 0x54D => array(0x57D), 0x54E => array(0x57E), 0x54F => array(0x57F), 0x550 => array(0x580), 0x551 => array(0x581), 0x552 => array(0x582), 0x553 => array(0x583), 0x554 => array(0x584), 0x555 => array(0x585), 0x556 => array(0x586), 0x587 => array(0x565, 0x582), 0x1E00 => array(0x1E01), 0x1E02 => array(0x1E03), 0x1E04 => array(0x1E05), 0x1E06 => array(0x1E07), 0x1E08 => array(0x1E09), 0x1E0A => array(0x1E0B), 0x1E0C => array(0x1E0D), 0x1E0E => array(0x1E0F), 0x1E10 => array(0x1E11), 0x1E12 => array(0x1E13), 0x1E14 => array(0x1E15), 0x1E16 => array(0x1E17), 0x1E18 => array(0x1E19), 0x1E1A => array(0x1E1B), 0x1E1C => array(0x1E1D), 0x1E1E => array(0x1E1F), 0x1E20 => array(0x1E21), 0x1E22 => array(0x1E23), 0x1E24 => array(0x1E25), 0x1E26 => array(0x1E27), 0x1E28 => array(0x1E29), 0x1E2A => array(0x1E2B), 0x1E2C => array(0x1E2D), 0x1E2E => array(0x1E2F), 0x1E30 => array(0x1E31), 0x1E32 => array(0x1E33), 0x1E34 => array(0x1E35), 0x1E36 => array(0x1E37), 0x1E38 => array(0x1E39), 0x1E3A => array(0x1E3B), 0x1E3C => array(0x1E3D), 0x1E3E => array(0x1E3F), 0x1E40 => array(0x1E41), 0x1E42 => array(0x1E43), 0x1E44 => array(0x1E45), 0x1E46 => array(0x1E47), 0x1E48 => array(0x1E49), 0x1E4A => array(0x1E4B), 0x1E4C => array(0x1E4D), 0x1E4E => array(0x1E4F), 0x1E50 => array(0x1E51), 0x1E52 => array(0x1E53), 0x1E54 => array(0x1E55), 0x1E56 => array(0x1E57), 0x1E58 => array(0x1E59), 0x1E5A => array(0x1E5B), 0x1E5C => array(0x1E5D), 0x1E5E => array(0x1E5F), 0x1E60 => array(0x1E61), 0x1E62 => array(0x1E63), 0x1E64 => array(0x1E65), 0x1E66 => array(0x1E67), 0x1E68 => array(0x1E69), 0x1E6A => array(0x1E6B), 0x1E6C => array(0x1E6D), 0x1E6E => array(0x1E6F), 0x1E70 => array(0x1E71), 0x1E72 => array(0x1E73), 0x1E74 => array(0x1E75), 0x1E76 => array(0x1E77), 0x1E78 => array(0x1E79), 0x1E7A => array(0x1E7B), 0x1E7C => array(0x1E7D), 0x1E7E => array(0x1E7F), 0x1E80 => array(0x1E81), 0x1E82 => array(0x1E83), 0x1E84 => array(0x1E85), 0x1E86 => array(0x1E87), 0x1E88 => array(0x1E89), 0x1E8A => array(0x1E8B), 0x1E8C => array(0x1E8D), 0x1E8E => array(0x1E8F), 0x1E90 => array(0x1E91), 0x1E92 => array(0x1E93), 0x1E94 => array(0x1E95), 0x1E96 => array(0x68, 0x331), 0x1E97 => array(0x74, 0x308), 0x1E98 => array(0x77, 0x30A), 0x1E99 => array(0x79, 0x30A), 0x1E9A => array(0x61, 0x2BE), 0x1E9B => array(0x1E61), 0x1EA0 => array(0x1EA1), 0x1EA2 => array(0x1EA3), 0x1EA4 => array(0x1EA5), 0x1EA6 => array(0x1EA7), 0x1EA8 => array(0x1EA9), 0x1EAA => array(0x1EAB), 0x1EAC => array(0x1EAD), 0x1EAE => array(0x1EAF), 0x1EB0 => array(0x1EB1), 0x1EB2 => array(0x1EB3), 0x1EB4 => array(0x1EB5), 0x1EB6 => array(0x1EB7), 0x1EB8 => array(0x1EB9), 0x1EBA => array(0x1EBB), 0x1EBC => array(0x1EBD), 0x1EBE => array(0x1EBF), 0x1EC0 => array(0x1EC1), 0x1EC2 => array(0x1EC3), 0x1EC4 => array(0x1EC5), 0x1EC6 => array(0x1EC7), 0x1EC8 => array(0x1EC9), 0x1ECA => array(0x1ECB), 0x1ECC => array(0x1ECD), 0x1ECE => array(0x1ECF), 0x1ED0 => array(0x1ED1), 0x1ED2 => array(0x1ED3), 0x1ED4 => array(0x1ED5), 0x1ED6 => array(0x1ED7), 0x1ED8 => array(0x1ED9), 0x1EDA => array(0x1EDB), 0x1EDC => array(0x1EDD), 0x1EDE => array(0x1EDF), 0x1EE0 => array(0x1EE1), 0x1EE2 => array(0x1EE3), 0x1EE4 => array(0x1EE5), 0x1EE6 => array(0x1EE7), 0x1EE8 => array(0x1EE9), 0x1EEA => array(0x1EEB), 0x1EEC => array(0x1EED), 0x1EEE => array(0x1EEF), 0x1EF0 => array(0x1EF1), 0x1EF2 => array(0x1EF3), 0x1EF4 => array(0x1EF5), 0x1EF6 => array(0x1EF7), 0x1EF8 => array(0x1EF9), 0x1F08 => array(0x1F00), 0x1F09 => array(0x1F01), 0x1F0A => array(0x1F02), 0x1F0B => array(0x1F03), 0x1F0C => array(0x1F04), 0x1F0D => array(0x1F05), 0x1F0E => array(0x1F06), 0x1F0F => array(0x1F07), 0x1F18 => array(0x1F10), 0x1F19 => array(0x1F11), 0x1F1A => array(0x1F12), 0x1F1B => array(0x1F13), 0x1F1C => array(0x1F14), 0x1F1D => array(0x1F15), 0x1F28 => array(0x1F20), 0x1F29 => array(0x1F21), 0x1F2A => array(0x1F22), 0x1F2B => array(0x1F23), 0x1F2C => array(0x1F24), 0x1F2D => array(0x1F25), 0x1F2E => array(0x1F26), 0x1F2F => array(0x1F27), 0x1F38 => array(0x1F30), 0x1F39 => array(0x1F31), 0x1F3A => array(0x1F32), 0x1F3B => array(0x1F33), 0x1F3C => array(0x1F34), 0x1F3D => array(0x1F35), 0x1F3E => array(0x1F36), 0x1F3F => array(0x1F37), 0x1F48 => array(0x1F40), 0x1F49 => array(0x1F41), 0x1F4A => array(0x1F42), 0x1F4B => array(0x1F43), 0x1F4C => array(0x1F44), 0x1F4D => array(0x1F45), 0x1F50 => array(0x3C5, 0x313), 0x1F52 => array(0x3C5, 0x313, 0x300), 0x1F54 => array(0x3C5, 0x313, 0x301), 0x1F56 => array(0x3C5, 0x313, 0x342), 0x1F59 => array(0x1F51), 0x1F5B => array(0x1F53), 0x1F5D => array(0x1F55), 0x1F5F => array(0x1F57), 0x1F68 => array(0x1F60), 0x1F69 => array(0x1F61), 0x1F6A => array(0x1F62), 0x1F6B => array(0x1F63), 0x1F6C => array(0x1F64), 0x1F6D => array(0x1F65), 0x1F6E => array(0x1F66), 0x1F6F => array(0x1F67), 0x1F80 => array(0x1F00, 0x3B9), 0x1F81 => array(0x1F01, 0x3B9), 0x1F82 => array(0x1F02, 0x3B9), 0x1F83 => array(0x1F03, 0x3B9), 0x1F84 => array(0x1F04, 0x3B9), 0x1F85 => array(0x1F05, 0x3B9), 0x1F86 => array(0x1F06, 0x3B9), 0x1F87 => array(0x1F07, 0x3B9), 0x1F88 => array(0x1F00, 0x3B9), 0x1F89 => array(0x1F01, 0x3B9), 0x1F8A => array(0x1F02, 0x3B9), 0x1F8B => array(0x1F03, 0x3B9), 0x1F8C => array(0x1F04, 0x3B9), 0x1F8D => array(0x1F05, 0x3B9), 0x1F8E => array(0x1F06, 0x3B9), 0x1F8F => array(0x1F07, 0x3B9), 0x1F90 => array(0x1F20, 0x3B9), 0x1F91 => array(0x1F21, 0x3B9), 0x1F92 => array(0x1F22, 0x3B9), 0x1F93 => array(0x1F23, 0x3B9), 0x1F94 => array(0x1F24, 0x3B9), 0x1F95 => array(0x1F25, 0x3B9), 0x1F96 => array(0x1F26, 0x3B9), 0x1F97 => array(0x1F27, 0x3B9), 0x1F98 => array(0x1F20, 0x3B9), 0x1F99 => array(0x1F21, 0x3B9), 0x1F9A => array(0x1F22, 0x3B9), 0x1F9B => array(0x1F23, 0x3B9), 0x1F9C => array(0x1F24, 0x3B9), 0x1F9D => array(0x1F25, 0x3B9), 0x1F9E => array(0x1F26, 0x3B9), 0x1F9F => array(0x1F27, 0x3B9), 0x1FA0 => array(0x1F60, 0x3B9), 0x1FA1 => array(0x1F61, 0x3B9), 0x1FA2 => array(0x1F62, 0x3B9), 0x1FA3 => array(0x1F63, 0x3B9), 0x1FA4 => array(0x1F64, 0x3B9), 0x1FA5 => array(0x1F65, 0x3B9), 0x1FA6 => array(0x1F66, 0x3B9), 0x1FA7 => array(0x1F67, 0x3B9), 0x1FA8 => array(0x1F60, 0x3B9), 0x1FA9 => array(0x1F61, 0x3B9), 0x1FAA => array(0x1F62, 0x3B9), 0x1FAB => array(0x1F63, 0x3B9), 0x1FAC => array(0x1F64, 0x3B9), 0x1FAD => array(0x1F65, 0x3B9), 0x1FAE => array(0x1F66, 0x3B9), 0x1FAF => array(0x1F67, 0x3B9), 0x1FB2 => array(0x1F70, 0x3B9), 0x1FB3 => array(0x3B1, 0x3B9), 0x1FB4 => array(0x3AC, 0x3B9), 0x1FB6 => array(0x3B1, 0x342), 0x1FB7 => array(0x3B1, 0x342, 0x3B9), 0x1FB8 => array(0x1FB0), 0x1FB9 => array(0x1FB1), 0x1FBA => array(0x1F70), 0x1FBB => array(0x1F71), 0x1FBC => array(0x3B1, 0x3B9), 0x1FBE => array(0x3B9), 0x1FC2 => array(0x1F74, 0x3B9), 0x1FC3 => array(0x3B7, 0x3B9), 0x1FC4 => array(0x3AE, 0x3B9), 0x1FC6 => array(0x3B7, 0x342), 0x1FC7 => array(0x3B7, 0x342, 0x3B9), 0x1FC8 => array(0x1F72), 0x1FC9 => array(0x1F73), 0x1FCA => array(0x1F74), 0x1FCB => array(0x1F75), 0x1FCC => array(0x3B7, 0x3B9), 0x1FD2 => array(0x3B9, 0x308, 0x300), 0x1FD3 => array(0x3B9, 0x308, 0x301), 0x1FD6 => array(0x3B9, 0x342), 0x1FD7 => array(0x3B9, 0x308, 0x342), 0x1FD8 => array(0x1FD0), 0x1FD9 => array(0x1FD1), 0x1FDA => array(0x1F76), 0x1FDB => array(0x1F77), 0x1FE2 => array(0x3C5, 0x308, 0x300), 0x1FE3 => array(0x3C5, 0x308, 0x301), 0x1FE4 => array(0x3C1, 0x313), 0x1FE6 => array(0x3C5, 0x342), 0x1FE7 => array(0x3C5, 0x308, 0x342), 0x1FE8 => array(0x1FE0), 0x1FE9 => array(0x1FE1), 0x1FEA => array(0x1F7A), 0x1FEB => array(0x1F7B), 0x1FEC => array(0x1FE5), 0x1FF2 => array(0x1F7C, 0x3B9), 0x1FF3 => array(0x3C9, 0x3B9), 0x1FF4 => array(0x3CE, 0x3B9), 0x1FF6 => array(0x3C9, 0x342), 0x1FF7 => array(0x3C9, 0x342, 0x3B9), 0x1FF8 => array(0x1F78), 0x1FF9 => array(0x1F79), 0x1FFA => array(0x1F7C), 0x1FFB => array(0x1F7D), 0x1FFC => array(0x3C9, 0x3B9), 0x20A8 => array(0x72, 0x73), 0x2102 => array(0x63), 0x2103 => array(0xB0, 0x63), 0x2107 => array(0x25B), 0x2109 => array(0xB0, 0x66), 0x210B => array(0x68), 0x210C => array(0x68), 0x210D => array(0x68), 0x2110 => array(0x69), 0x2111 => array(0x69), 0x2112 => array(0x6C), 0x2115 => array(0x6E), 0x2116 => array(0x6E, 0x6F), 0x2119 => array(0x70), 0x211A => array(0x71), 0x211B => array(0x72), 0x211C => array(0x72), 0x211D => array(0x72), 0x2120 => array(0x73, 0x6D), 0x2121 => array(0x74, 0x65, 0x6C), 0x2122 => array(0x74, 0x6D), 0x2124 => array(0x7A), 0x2126 => array(0x3C9), 0x2128 => array(0x7A), 0x212A => array(0x6B), 0x212B => array(0xE5), 0x212C => array(0x62), 0x212D => array(0x63), 0x2130 => array(0x65), 0x2131 => array(0x66), 0x2133 => array(0x6D), 0x213E => array(0x3B3), 0x213F => array(0x3C0), 0x2145 => array(0x64), 0x2160 => array(0x2170), 0x2161 => array(0x2171), 0x2162 => array(0x2172), 0x2163 => array(0x2173), 0x2164 => array(0x2174), 0x2165 => array(0x2175), 0x2166 => array(0x2176), 0x2167 => array(0x2177), 0x2168 => array(0x2178), 0x2169 => array(0x2179), 0x216A => array(0x217A), 0x216B => array(0x217B), 0x216C => array(0x217C), 0x216D => array(0x217D), 0x216E => array(0x217E), 0x216F => array(0x217F), 0x24B6 => array(0x24D0), 0x24B7 => array(0x24D1), 0x24B8 => array(0x24D2), 0x24B9 => array(0x24D3), 0x24BA => array(0x24D4), 0x24BB => array(0x24D5), 0x24BC => array(0x24D6), 0x24BD => array(0x24D7), 0x24BE => array(0x24D8), 0x24BF => array(0x24D9), 0x24C0 => array(0x24DA), 0x24C1 => array(0x24DB), 0x24C2 => array(0x24DC), 0x24C3 => array(0x24DD), 0x24C4 => array(0x24DE), 0x24C5 => array(0x24DF), 0x24C6 => array(0x24E0), 0x24C7 => array(0x24E1), 0x24C8 => array(0x24E2), 0x24C9 => array(0x24E3), 0x24CA => array(0x24E4), 0x24CB => array(0x24E5), 0x24CC => array(0x24E6), 0x24CD => array(0x24E7), 0x24CE => array(0x24E8), 0x24CF => array(0x24E9), 0x3371 => array(0x68, 0x70, 0x61), 0x3373 => array(0x61, 0x75), 0x3375 => array(0x6F, 0x76), 0x3380 => array(0x70, 0x61), 0x3381 => array(0x6E, 0x61), 0x3382 => array(0x3BC, 0x61), 0x3383 => array(0x6D, 0x61), 0x3384 => array(0x6B, 0x61), 0x3385 => array(0x6B, 0x62), 0x3386 => array(0x6D, 0x62), 0x3387 => array(0x67, 0x62), 0x338A => array(0x70, 0x66), 0x338B => array(0x6E, 0x66), 0x338C => array(0x3BC, 0x66), 0x3390 => array(0x68, 0x7A), 0x3391 => array(0x6B, 0x68, 0x7A), 0x3392 => array(0x6D, 0x68, 0x7A), 0x3393 => array(0x67, 0x68, 0x7A), 0x3394 => array(0x74, 0x68, 0x7A), 0x33A9 => array(0x70, 0x61), 0x33AA => array(0x6B, 0x70, 0x61), 0x33AB => array(0x6D, 0x70, 0x61), 0x33AC => array(0x67, 0x70, 0x61), 0x33B4 => array(0x70, 0x76), 0x33B5 => array(0x6E, 0x76), 0x33B6 => array(0x3BC, 0x76), 0x33B7 => array(0x6D, 0x76), 0x33B8 => array(0x6B, 0x76), 0x33B9 => array(0x6D, 0x76), 0x33BA => array(0x70, 0x77), 0x33BB => array(0x6E, 0x77), 0x33BC => array(0x3BC, 0x77), 0x33BD => array(0x6D, 0x77), 0x33BE => array(0x6B, 0x77), 0x33BF => array(0x6D, 0x77), 0x33C0 => array(0x6B, 0x3C9), 0x33C1 => array(0x6D, 0x3C9), /* 0x33C2 => array(0x61, 0x2E, 0x6D, 0x2E), */ 0x33C3 => array(0x62, 0x71), 0x33C6 => array(0x63, 0x2215, 0x6B, 0x67), 0x33C7 => array(0x63, 0x6F, 0x2E), 0x33C8 => array(0x64, 0x62), 0x33C9 => array(0x67, 0x79), 0x33CB => array(0x68, 0x70), 0x33CD => array(0x6B, 0x6B), 0x33CE => array(0x6B, 0x6D), 0x33D7 => array(0x70, 0x68), 0x33D9 => array(0x70, 0x70, 0x6D), 0x33DA => array(0x70, 0x72), 0x33DC => array(0x73, 0x76), 0x33DD => array(0x77, 0x62), 0xFB00 => array(0x66, 0x66), 0xFB01 => array(0x66, 0x69), 0xFB02 => array(0x66, 0x6C), 0xFB03 => array(0x66, 0x66, 0x69), 0xFB04 => array(0x66, 0x66, 0x6C), 0xFB05 => array(0x73, 0x74), 0xFB06 => array(0x73, 0x74), 0xFB13 => array(0x574, 0x576), 0xFB14 => array(0x574, 0x565), 0xFB15 => array(0x574, 0x56B), 0xFB16 => array(0x57E, 0x576), 0xFB17 => array(0x574, 0x56D), 0xFF21 => array(0xFF41), 0xFF22 => array(0xFF42), 0xFF23 => array(0xFF43), 0xFF24 => array(0xFF44), 0xFF25 => array(0xFF45), 0xFF26 => array(0xFF46), 0xFF27 => array(0xFF47), 0xFF28 => array(0xFF48), 0xFF29 => array(0xFF49), 0xFF2A => array(0xFF4A), 0xFF2B => array(0xFF4B), 0xFF2C => array(0xFF4C), 0xFF2D => array(0xFF4D), 0xFF2E => array(0xFF4E), 0xFF2F => array(0xFF4F), 0xFF30 => array(0xFF50), 0xFF31 => array(0xFF51), 0xFF32 => array(0xFF52), 0xFF33 => array(0xFF53), 0xFF34 => array(0xFF54), 0xFF35 => array(0xFF55), 0xFF36 => array(0xFF56), 0xFF37 => array(0xFF57), 0xFF38 => array(0xFF58), 0xFF39 => array(0xFF59), 0xFF3A => array(0xFF5A), 0x10400 => array(0x10428), 0x10401 => array(0x10429), 0x10402 => array(0x1042A), 0x10403 => array(0x1042B), 0x10404 => array(0x1042C), 0x10405 => array(0x1042D), 0x10406 => array(0x1042E), 0x10407 => array(0x1042F), 0x10408 => array(0x10430), 0x10409 => array(0x10431), 0x1040A => array(0x10432), 0x1040B => array(0x10433), 0x1040C => array(0x10434), 0x1040D => array(0x10435), 0x1040E => array(0x10436), 0x1040F => array(0x10437), 0x10410 => array(0x10438), 0x10411 => array(0x10439), 0x10412 => array(0x1043A), 0x10413 => array(0x1043B), 0x10414 => array(0x1043C), 0x10415 => array(0x1043D), 0x10416 => array(0x1043E), 0x10417 => array(0x1043F), 0x10418 => array(0x10440), 0x10419 => array(0x10441), 0x1041A => array(0x10442), 0x1041B => array(0x10443), 0x1041C => array(0x10444), 0x1041D => array(0x10445), 0x1041E => array(0x10446), 0x1041F => array(0x10447), 0x10420 => array(0x10448), 0x10421 => array(0x10449), 0x10422 => array(0x1044A), 0x10423 => array(0x1044B), 0x10424 => array(0x1044C), 0x10425 => array(0x1044D), 0x1D400 => array(0x61), 0x1D401 => array(0x62), 0x1D402 => array(0x63), 0x1D403 => array(0x64), 0x1D404 => array(0x65), 0x1D405 => array(0x66), 0x1D406 => array(0x67), 0x1D407 => array(0x68), 0x1D408 => array(0x69), 0x1D409 => array(0x6A), 0x1D40A => array(0x6B), 0x1D40B => array(0x6C), 0x1D40C => array(0x6D), 0x1D40D => array(0x6E), 0x1D40E => array(0x6F), 0x1D40F => array(0x70), 0x1D410 => array(0x71), 0x1D411 => array(0x72), 0x1D412 => array(0x73), 0x1D413 => array(0x74), 0x1D414 => array(0x75), 0x1D415 => array(0x76), 0x1D416 => array(0x77), 0x1D417 => array(0x78), 0x1D418 => array(0x79), 0x1D419 => array(0x7A), 0x1D434 => array(0x61), 0x1D435 => array(0x62), 0x1D436 => array(0x63), 0x1D437 => array(0x64), 0x1D438 => array(0x65), 0x1D439 => array(0x66), 0x1D43A => array(0x67), 0x1D43B => array(0x68), 0x1D43C => array(0x69), 0x1D43D => array(0x6A), 0x1D43E => array(0x6B), 0x1D43F => array(0x6C), 0x1D440 => array(0x6D), 0x1D441 => array(0x6E), 0x1D442 => array(0x6F), 0x1D443 => array(0x70), 0x1D444 => array(0x71), 0x1D445 => array(0x72), 0x1D446 => array(0x73), 0x1D447 => array(0x74), 0x1D448 => array(0x75), 0x1D449 => array(0x76), 0x1D44A => array(0x77), 0x1D44B => array(0x78), 0x1D44C => array(0x79), 0x1D44D => array(0x7A), 0x1D468 => array(0x61), 0x1D469 => array(0x62), 0x1D46A => array(0x63), 0x1D46B => array(0x64), 0x1D46C => array(0x65), 0x1D46D => array(0x66), 0x1D46E => array(0x67), 0x1D46F => array(0x68), 0x1D470 => array(0x69), 0x1D471 => array(0x6A), 0x1D472 => array(0x6B), 0x1D473 => array(0x6C), 0x1D474 => array(0x6D), 0x1D475 => array(0x6E), 0x1D476 => array(0x6F), 0x1D477 => array(0x70), 0x1D478 => array(0x71), 0x1D479 => array(0x72), 0x1D47A => array(0x73), 0x1D47B => array(0x74), 0x1D47C => array(0x75), 0x1D47D => array(0x76), 0x1D47E => array(0x77), 0x1D47F => array(0x78), 0x1D480 => array(0x79), 0x1D481 => array(0x7A), 0x1D49C => array(0x61), 0x1D49E => array(0x63), 0x1D49F => array(0x64), 0x1D4A2 => array(0x67), 0x1D4A5 => array(0x6A), 0x1D4A6 => array(0x6B), 0x1D4A9 => array(0x6E), 0x1D4AA => array(0x6F), 0x1D4AB => array(0x70), 0x1D4AC => array(0x71), 0x1D4AE => array(0x73), 0x1D4AF => array(0x74), 0x1D4B0 => array(0x75), 0x1D4B1 => array(0x76), 0x1D4B2 => array(0x77), 0x1D4B3 => array(0x78), 0x1D4B4 => array(0x79), 0x1D4B5 => array(0x7A), 0x1D4D0 => array(0x61), 0x1D4D1 => array(0x62), 0x1D4D2 => array(0x63), 0x1D4D3 => array(0x64), 0x1D4D4 => array(0x65), 0x1D4D5 => array(0x66), 0x1D4D6 => array(0x67), 0x1D4D7 => array(0x68), 0x1D4D8 => array(0x69), 0x1D4D9 => array(0x6A), 0x1D4DA => array(0x6B), 0x1D4DB => array(0x6C), 0x1D4DC => array(0x6D), 0x1D4DD => array(0x6E), 0x1D4DE => array(0x6F), 0x1D4DF => array(0x70), 0x1D4E0 => array(0x71), 0x1D4E1 => array(0x72), 0x1D4E2 => array(0x73), 0x1D4E3 => array(0x74), 0x1D4E4 => array(0x75), 0x1D4E5 => array(0x76), 0x1D4E6 => array(0x77), 0x1D4E7 => array(0x78), 0x1D4E8 => array(0x79), 0x1D4E9 => array(0x7A), 0x1D504 => array(0x61), 0x1D505 => array(0x62), 0x1D507 => array(0x64), 0x1D508 => array(0x65), 0x1D509 => array(0x66), 0x1D50A => array(0x67), 0x1D50D => array(0x6A), 0x1D50E => array(0x6B), 0x1D50F => array(0x6C), 0x1D510 => array(0x6D), 0x1D511 => array(0x6E), 0x1D512 => array(0x6F), 0x1D513 => array(0x70), 0x1D514 => array(0x71), 0x1D516 => array(0x73), 0x1D517 => array(0x74), 0x1D518 => array(0x75), 0x1D519 => array(0x76), 0x1D51A => array(0x77), 0x1D51B => array(0x78), 0x1D51C => array(0x79), 0x1D538 => array(0x61), 0x1D539 => array(0x62), 0x1D53B => array(0x64), 0x1D53C => array(0x65), 0x1D53D => array(0x66), 0x1D53E => array(0x67), 0x1D540 => array(0x69), 0x1D541 => array(0x6A), 0x1D542 => array(0x6B), 0x1D543 => array(0x6C), 0x1D544 => array(0x6D), 0x1D546 => array(0x6F), 0x1D54A => array(0x73), 0x1D54B => array(0x74), 0x1D54C => array(0x75), 0x1D54D => array(0x76), 0x1D54E => array(0x77), 0x1D54F => array(0x78), 0x1D550 => array(0x79), 0x1D56C => array(0x61), 0x1D56D => array(0x62), 0x1D56E => array(0x63), 0x1D56F => array(0x64), 0x1D570 => array(0x65), 0x1D571 => array(0x66), 0x1D572 => array(0x67), 0x1D573 => array(0x68), 0x1D574 => array(0x69), 0x1D575 => array(0x6A), 0x1D576 => array(0x6B), 0x1D577 => array(0x6C), 0x1D578 => array(0x6D), 0x1D579 => array(0x6E), 0x1D57A => array(0x6F), 0x1D57B => array(0x70), 0x1D57C => array(0x71), 0x1D57D => array(0x72), 0x1D57E => array(0x73), 0x1D57F => array(0x74), 0x1D580 => array(0x75), 0x1D581 => array(0x76), 0x1D582 => array(0x77), 0x1D583 => array(0x78), 0x1D584 => array(0x79), 0x1D585 => array(0x7A), 0x1D5A0 => array(0x61), 0x1D5A1 => array(0x62), 0x1D5A2 => array(0x63), 0x1D5A3 => array(0x64), 0x1D5A4 => array(0x65), 0x1D5A5 => array(0x66), 0x1D5A6 => array(0x67), 0x1D5A7 => array(0x68), 0x1D5A8 => array(0x69), 0x1D5A9 => array(0x6A), 0x1D5AA => array(0x6B), 0x1D5AB => array(0x6C), 0x1D5AC => array(0x6D), 0x1D5AD => array(0x6E), 0x1D5AE => array(0x6F), 0x1D5AF => array(0x70), 0x1D5B0 => array(0x71), 0x1D5B1 => array(0x72), 0x1D5B2 => array(0x73), 0x1D5B3 => array(0x74), 0x1D5B4 => array(0x75), 0x1D5B5 => array(0x76), 0x1D5B6 => array(0x77), 0x1D5B7 => array(0x78), 0x1D5B8 => array(0x79), 0x1D5B9 => array(0x7A), 0x1D5D4 => array(0x61), 0x1D5D5 => array(0x62), 0x1D5D6 => array(0x63), 0x1D5D7 => array(0x64), 0x1D5D8 => array(0x65), 0x1D5D9 => array(0x66), 0x1D5DA => array(0x67), 0x1D5DB => array(0x68), 0x1D5DC => array(0x69), 0x1D5DD => array(0x6A), 0x1D5DE => array(0x6B), 0x1D5DF => array(0x6C), 0x1D5E0 => array(0x6D), 0x1D5E1 => array(0x6E), 0x1D5E2 => array(0x6F), 0x1D5E3 => array(0x70), 0x1D5E4 => array(0x71), 0x1D5E5 => array(0x72), 0x1D5E6 => array(0x73), 0x1D5E7 => array(0x74), 0x1D5E8 => array(0x75), 0x1D5E9 => array(0x76), 0x1D5EA => array(0x77), 0x1D5EB => array(0x78), 0x1D5EC => array(0x79), 0x1D5ED => array(0x7A), 0x1D608 => array(0x61), 0x1D609 => array(0x62), 0x1D60A => array(0x63), 0x1D60B => array(0x64), 0x1D60C => array(0x65), 0x1D60D => array(0x66), 0x1D60E => array(0x67), 0x1D60F => array(0x68), 0x1D610 => array(0x69), 0x1D611 => array(0x6A), 0x1D612 => array(0x6B), 0x1D613 => array(0x6C), 0x1D614 => array(0x6D), 0x1D615 => array(0x6E), 0x1D616 => array(0x6F), 0x1D617 => array(0x70), 0x1D618 => array(0x71), 0x1D619 => array(0x72), 0x1D61A => array(0x73), 0x1D61B => array(0x74), 0x1D61C => array(0x75), 0x1D61D => array(0x76), 0x1D61E => array(0x77), 0x1D61F => array(0x78), 0x1D620 => array(0x79), 0x1D621 => array(0x7A), 0x1D63C => array(0x61), 0x1D63D => array(0x62), 0x1D63E => array(0x63), 0x1D63F => array(0x64), 0x1D640 => array(0x65), 0x1D641 => array(0x66), 0x1D642 => array(0x67), 0x1D643 => array(0x68), 0x1D644 => array(0x69), 0x1D645 => array(0x6A), 0x1D646 => array(0x6B), 0x1D647 => array(0x6C), 0x1D648 => array(0x6D), 0x1D649 => array(0x6E), 0x1D64A => array(0x6F), 0x1D64B => array(0x70), 0x1D64C => array(0x71), 0x1D64D => array(0x72), 0x1D64E => array(0x73), 0x1D64F => array(0x74), 0x1D650 => array(0x75), 0x1D651 => array(0x76), 0x1D652 => array(0x77), 0x1D653 => array(0x78), 0x1D654 => array(0x79), 0x1D655 => array(0x7A), 0x1D670 => array(0x61), 0x1D671 => array(0x62), 0x1D672 => array(0x63), 0x1D673 => array(0x64), 0x1D674 => array(0x65), 0x1D675 => array(0x66), 0x1D676 => array(0x67), 0x1D677 => array(0x68), 0x1D678 => array(0x69), 0x1D679 => array(0x6A), 0x1D67A => array(0x6B), 0x1D67B => array(0x6C), 0x1D67C => array(0x6D), 0x1D67D => array(0x6E), 0x1D67E => array(0x6F), 0x1D67F => array(0x70), 0x1D680 => array(0x71), 0x1D681 => array(0x72), 0x1D682 => array(0x73), 0x1D683 => array(0x74), 0x1D684 => array(0x75), 0x1D685 => array(0x76), 0x1D686 => array(0x77), 0x1D687 => array(0x78), 0x1D688 => array(0x79), 0x1D689 => array(0x7A), 0x1D6A8 => array(0x3B1), 0x1D6A9 => array(0x3B2), 0x1D6AA => array(0x3B3), 0x1D6AB => array(0x3B4), 0x1D6AC => array(0x3B5), 0x1D6AD => array(0x3B6), 0x1D6AE => array(0x3B7), 0x1D6AF => array(0x3B8), 0x1D6B0 => array(0x3B9), 0x1D6B1 => array(0x3BA), 0x1D6B2 => array(0x3BB), 0x1D6B3 => array(0x3BC), 0x1D6B4 => array(0x3BD), 0x1D6B5 => array(0x3BE), 0x1D6B6 => array(0x3BF), 0x1D6B7 => array(0x3C0), 0x1D6B8 => array(0x3C1), 0x1D6B9 => array(0x3B8), 0x1D6BA => array(0x3C3), 0x1D6BB => array(0x3C4), 0x1D6BC => array(0x3C5), 0x1D6BD => array(0x3C6), 0x1D6BE => array(0x3C7), 0x1D6BF => array(0x3C8), 0x1D6C0 => array(0x3C9), 0x1D6D3 => array(0x3C3), 0x1D6E2 => array(0x3B1), 0x1D6E3 => array(0x3B2), 0x1D6E4 => array(0x3B3), 0x1D6E5 => array(0x3B4), 0x1D6E6 => array(0x3B5), 0x1D6E7 => array(0x3B6), 0x1D6E8 => array(0x3B7), 0x1D6E9 => array(0x3B8), 0x1D6EA => array(0x3B9), 0x1D6EB => array(0x3BA), 0x1D6EC => array(0x3BB), 0x1D6ED => array(0x3BC), 0x1D6EE => array(0x3BD), 0x1D6EF => array(0x3BE), 0x1D6F0 => array(0x3BF), 0x1D6F1 => array(0x3C0), 0x1D6F2 => array(0x3C1), 0x1D6F3 => array(0x3B8), 0x1D6F4 => array(0x3C3), 0x1D6F5 => array(0x3C4), 0x1D6F6 => array(0x3C5), 0x1D6F7 => array(0x3C6), 0x1D6F8 => array(0x3C7), 0x1D6F9 => array(0x3C8), 0x1D6FA => array(0x3C9), 0x1D70D => array(0x3C3), 0x1D71C => array(0x3B1), 0x1D71D => array(0x3B2), 0x1D71E => array(0x3B3), 0x1D71F => array(0x3B4), 0x1D720 => array(0x3B5), 0x1D721 => array(0x3B6), 0x1D722 => array(0x3B7), 0x1D723 => array(0x3B8), 0x1D724 => array(0x3B9), 0x1D725 => array(0x3BA), 0x1D726 => array(0x3BB), 0x1D727 => array(0x3BC), 0x1D728 => array(0x3BD), 0x1D729 => array(0x3BE), 0x1D72A => array(0x3BF), 0x1D72B => array(0x3C0), 0x1D72C => array(0x3C1), 0x1D72D => array(0x3B8), 0x1D72E => array(0x3C3), 0x1D72F => array(0x3C4), 0x1D730 => array(0x3C5), 0x1D731 => array(0x3C6), 0x1D732 => array(0x3C7), 0x1D733 => array(0x3C8), 0x1D734 => array(0x3C9), 0x1D747 => array(0x3C3), 0x1D756 => array(0x3B1), 0x1D757 => array(0x3B2), 0x1D758 => array(0x3B3), 0x1D759 => array(0x3B4), 0x1D75A => array(0x3B5), 0x1D75B => array(0x3B6), 0x1D75C => array(0x3B7), 0x1D75D => array(0x3B8), 0x1D75E => array(0x3B9), 0x1D75F => array(0x3BA), 0x1D760 => array(0x3BB), 0x1D761 => array(0x3BC), 0x1D762 => array(0x3BD), 0x1D763 => array(0x3BE), 0x1D764 => array(0x3BF), 0x1D765 => array(0x3C0), 0x1D766 => array(0x3C1), 0x1D767 => array(0x3B8), 0x1D768 => array(0x3C3), 0x1D769 => array(0x3C4), 0x1D76A => array(0x3C5), 0x1D76B => array(0x3C6), 0x1D76C => array(0x3C7), 0x1D76D => array(0x3C8), 0x1D76E => array(0x3C9), 0x1D781 => array(0x3C3), 0x1D790 => array(0x3B1), 0x1D791 => array(0x3B2), 0x1D792 => array(0x3B3), 0x1D793 => array(0x3B4), 0x1D794 => array(0x3B5), 0x1D795 => array(0x3B6), 0x1D796 => array(0x3B7), 0x1D797 => array(0x3B8), 0x1D798 => array(0x3B9), 0x1D799 => array(0x3BA), 0x1D79A => array(0x3BB), 0x1D79B => array(0x3BC), 0x1D79C => array(0x3BD), 0x1D79D => array(0x3BE), 0x1D79E => array(0x3BF), 0x1D79F => array(0x3C0), 0x1D7A0 => array(0x3C1), 0x1D7A1 => array(0x3B8), 0x1D7A2 => array(0x3C3), 0x1D7A3 => array(0x3C4), 0x1D7A4 => array(0x3C5), 0x1D7A5 => array(0x3C6), 0x1D7A6 => array(0x3C7), 0x1D7A7 => array(0x3C8), 0x1D7A8 => array(0x3C9), 0x1D7BB => array(0x3C3), 0x3F9 => array(0x3C3), 0x1D2C => array(0x61), 0x1D2D => array(0xE6), 0x1D2E => array(0x62), 0x1D30 => array(0x64), 0x1D31 => array(0x65), 0x1D32 => array(0x1DD), 0x1D33 => array(0x67), 0x1D34 => array(0x68), 0x1D35 => array(0x69), 0x1D36 => array(0x6A), 0x1D37 => array(0x6B), 0x1D38 => array(0x6C), 0x1D39 => array(0x6D), 0x1D3A => array(0x6E), 0x1D3C => array(0x6F), 0x1D3D => array(0x223), 0x1D3E => array(0x70), 0x1D3F => array(0x72), 0x1D40 => array(0x74), 0x1D41 => array(0x75), 0x1D42 => array(0x77), 0x213B => array(0x66, 0x61, 0x78), 0x3250 => array(0x70, 0x74, 0x65), 0x32CC => array(0x68, 0x67), 0x32CE => array(0x65, 0x76), 0x32CF => array(0x6C, 0x74, 0x64), 0x337A => array(0x69, 0x75), 0x33DE => array(0x76, 0x2215, 0x6D), 0x33DF => array(0x61, 0x2215, 0x6D) ); /** * Normalization Combining Classes; Code Points not listed * got Combining Class 0. * * @static * @var array * @access private */ private static $_np_norm_combcls = array( 0x334 => 1, 0x335 => 1, 0x336 => 1, 0x337 => 1, 0x338 => 1, 0x93C => 7, 0x9BC => 7, 0xA3C => 7, 0xABC => 7, 0xB3C => 7, 0xCBC => 7, 0x1037 => 7, 0x3099 => 8, 0x309A => 8, 0x94D => 9, 0x9CD => 9, 0xA4D => 9, 0xACD => 9, 0xB4D => 9, 0xBCD => 9, 0xC4D => 9, 0xCCD => 9, 0xD4D => 9, 0xDCA => 9, 0xE3A => 9, 0xF84 => 9, 0x1039 => 9, 0x1714 => 9, 0x1734 => 9, 0x17D2 => 9, 0x5B0 => 10, 0x5B1 => 11, 0x5B2 => 12, 0x5B3 => 13, 0x5B4 => 14, 0x5B5 => 15, 0x5B6 => 16, 0x5B7 => 17, 0x5B8 => 18, 0x5B9 => 19, 0x5BB => 20, 0x5Bc => 21, 0x5BD => 22, 0x5BF => 23, 0x5C1 => 24, 0x5C2 => 25, 0xFB1E => 26, 0x64B => 27, 0x64C => 28, 0x64D => 29, 0x64E => 30, 0x64F => 31, 0x650 => 32, 0x651 => 33, 0x652 => 34, 0x670 => 35, 0x711 => 36, 0xC55 => 84, 0xC56 => 91, 0xE38 => 103, 0xE39 => 103, 0xE48 => 107, 0xE49 => 107, 0xE4A => 107, 0xE4B => 107, 0xEB8 => 118, 0xEB9 => 118, 0xEC8 => 122, 0xEC9 => 122, 0xECA => 122, 0xECB => 122, 0xF71 => 129, 0xF72 => 130, 0xF7A => 130, 0xF7B => 130, 0xF7C => 130, 0xF7D => 130, 0xF80 => 130, 0xF74 => 132, 0x321 => 202, 0x322 => 202, 0x327 => 202, 0x328 => 202, 0x31B => 216, 0xF39 => 216, 0x1D165 => 216, 0x1D166 => 216, 0x1D16E => 216, 0x1D16F => 216, 0x1D170 => 216, 0x1D171 => 216, 0x1D172 => 216, 0x302A => 218, 0x316 => 220, 0x317 => 220, 0x318 => 220, 0x319 => 220, 0x31C => 220, 0x31D => 220, 0x31E => 220, 0x31F => 220, 0x320 => 220, 0x323 => 220, 0x324 => 220, 0x325 => 220, 0x326 => 220, 0x329 => 220, 0x32A => 220, 0x32B => 220, 0x32C => 220, 0x32D => 220, 0x32E => 220, 0x32F => 220, 0x330 => 220, 0x331 => 220, 0x332 => 220, 0x333 => 220, 0x339 => 220, 0x33A => 220, 0x33B => 220, 0x33C => 220, 0x347 => 220, 0x348 => 220, 0x349 => 220, 0x34D => 220, 0x34E => 220, 0x353 => 220, 0x354 => 220, 0x355 => 220, 0x356 => 220, 0x591 => 220, 0x596 => 220, 0x59B => 220, 0x5A3 => 220, 0x5A4 => 220, 0x5A5 => 220, 0x5A6 => 220, 0x5A7 => 220, 0x5AA => 220, 0x655 => 220, 0x656 => 220, 0x6E3 => 220, 0x6EA => 220, 0x6ED => 220, 0x731 => 220, 0x734 => 220, 0x737 => 220, 0x738 => 220, 0x739 => 220, 0x73B => 220, 0x73C => 220, 0x73E => 220, 0x742 => 220, 0x744 => 220, 0x746 => 220, 0x748 => 220, 0x952 => 220, 0xF18 => 220, 0xF19 => 220, 0xF35 => 220, 0xF37 => 220, 0xFC6 => 220, 0x193B => 220, 0x20E8 => 220, 0x1D17B => 220, 0x1D17C => 220, 0x1D17D => 220, 0x1D17E => 220, 0x1D17F => 220, 0x1D180 => 220, 0x1D181 => 220, 0x1D182 => 220, 0x1D18A => 220, 0x1D18B => 220, 0x59A => 222, 0x5AD => 222, 0x1929 => 222, 0x302D => 222, 0x302E => 224, 0x302F => 224, 0x1D16D => 226, 0x5AE => 228, 0x18A9 => 228, 0x302B => 228, 0x300 => 230, 0x301 => 230, 0x302 => 230, 0x303 => 230, 0x304 => 230, 0x305 => 230, 0x306 => 230, 0x307 => 230, 0x308 => 230, 0x309 => 230, 0x30A => 230, 0x30B => 230, 0x30C => 230, 0x30D => 230, 0x30E => 230, 0x30F => 230, 0x310 => 230, 0x311 => 230, 0x312 => 230, 0x313 => 230, 0x314 => 230, 0x33D => 230, 0x33E => 230, 0x33F => 230, 0x340 => 230, 0x341 => 230, 0x342 => 230, 0x343 => 230, 0x344 => 230, 0x346 => 230, 0x34A => 230, 0x34B => 230, 0x34C => 230, 0x350 => 230, 0x351 => 230, 0x352 => 230, 0x357 => 230, 0x363 => 230, 0x364 => 230, 0x365 => 230, 0x366 => 230, 0x367 => 230, 0x368 => 230, 0x369 => 230, 0x36A => 230, 0x36B => 230, 0x36C => 230, 0x36D => 230, 0x36E => 230, 0x36F => 230, 0x483 => 230, 0x484 => 230, 0x485 => 230, 0x486 => 230, 0x592 => 230, 0x593 => 230, 0x594 => 230, 0x595 => 230, 0x597 => 230, 0x598 => 230, 0x599 => 230, 0x59C => 230, 0x59D => 230, 0x59E => 230, 0x59F => 230, 0x5A0 => 230, 0x5A1 => 230, 0x5A8 => 230, 0x5A9 => 230, 0x5AB => 230, 0x5AC => 230, 0x5AF => 230, 0x5C4 => 230, 0x610 => 230, 0x611 => 230, 0x612 => 230, 0x613 => 230, 0x614 => 230, 0x615 => 230, 0x653 => 230, 0x654 => 230, 0x657 => 230, 0x658 => 230, 0x6D6 => 230, 0x6D7 => 230, 0x6D8 => 230, 0x6D9 => 230, 0x6DA => 230, 0x6DB => 230, 0x6DC => 230, 0x6DF => 230, 0x6E0 => 230, 0x6E1 => 230, 0x6E2 => 230, 0x6E4 => 230, 0x6E7 => 230, 0x6E8 => 230, 0x6EB => 230, 0x6EC => 230, 0x730 => 230, 0x732 => 230, 0x733 => 230, 0x735 => 230, 0x736 => 230, 0x73A => 230, 0x73D => 230, 0x73F => 230, 0x740 => 230, 0x741 => 230, 0x743 => 230, 0x745 => 230, 0x747 => 230, 0x749 => 230, 0x74A => 230, 0x951 => 230, 0x953 => 230, 0x954 => 230, 0xF82 => 230, 0xF83 => 230, 0xF86 => 230, 0xF87 => 230, 0x170D => 230, 0x193A => 230, 0x20D0 => 230, 0x20D1 => 230, 0x20D4 => 230, 0x20D5 => 230, 0x20D6 => 230, 0x20D7 => 230, 0x20DB => 230, 0x20DC => 230, 0x20E1 => 230, 0x20E7 => 230, 0x20E9 => 230, 0xFE20 => 230, 0xFE21 => 230, 0xFE22 => 230, 0xFE23 => 230, 0x1D185 => 230, 0x1D186 => 230, 0x1D187 => 230, 0x1D189 => 230, 0x1D188 => 230, 0x1D1AA => 230, 0x1D1AB => 230, 0x1D1AC => 230, 0x1D1AD => 230, 0x315 => 232, 0x31A => 232, 0x302C => 232, 0x35F => 233, 0x362 => 233, 0x35D => 234, 0x35E => 234, 0x360 => 234, 0x361 => 234, 0x345 => 240 ); // }}} // {{{ properties /** * @var string * @access private */ private $_punycode_prefix = 'xn--'; /** * @access private */ private $_invalid_ucs = 0x80000000; /** * @access private */ private $_max_ucs = 0x10FFFF; /** * @var int * @access private */ private $_base = 36; /** * @var int * @access private */ private $_tmin = 1; /** * @var int * @access private */ private $_tmax = 26; /** * @var int * @access private */ private $_skew = 38; /** * @var int * @access private */ private $_damp = 700; /** * @var int * @access private */ private $_initial_bias = 72; /** * @var int * @access private */ private $_initial_n = 0x80; /** * @var int * @access private */ private $_slast; /** * @access private */ private $_sbase = 0xAC00; /** * @access private */ private $_lbase = 0x1100; /** * @access private */ private $_vbase = 0x1161; /** * @access private */ private $_tbase = 0x11a7; /** * @var int * @access private */ private $_lcount = 19; /** * @var int * @access private */ private $_vcount = 21; /** * @var int * @access private */ private $_tcount = 28; /** * vcount * tcount * * @var int * @access private */ private $_ncount = 588; /** * lcount * tcount * vcount * * @var int * @access private */ private $_scount = 11172; /** * Default encoding for encode()'s input and decode()'s output is UTF-8; * Other possible encodings are ucs4_string and ucs4_array * See {@link setParams()} for how to select these * * @var bool * @access private */ private $_api_encoding = 'utf8'; /** * Overlong UTF-8 encodings are forbidden * * @var bool * @access private */ private $_allow_overlong = false; /** * Behave strict or not * * @var bool * @access private */ private $_strict_mode = false; /** * IDNA-version to use * * Values are "2003" and "2008". * Defaults to "2003", since that was the original version and for * compatibility with previous versions of this library. * If you need to encode "new" characters like the German "Eszett", * please switch to 2008 first before encoding. * * @var bool * @access private */ private $_version = '2003'; /** * Cached value indicating whether or not mbstring function overloading is * on for strlen * * This is cached for optimal performance. * * @var boolean * @see Net_IDNA2::_byteLength() */ private static $_mb_string_overload = null; // }}} // {{{ constructor /** * Constructor * * @param array $options Options to initialise the object with * * @access public * @see setParams() */ public function __construct($options = null) { $this->_slast = $this->_sbase + $this->_lcount * $this->_vcount * $this->_tcount; if (is_array($options)) { $this->setParams($options); } // populate mbstring overloading cache if not set if (self::$_mb_string_overload === null) { self::$_mb_string_overload = (extension_loaded('mbstring') && (ini_get('mbstring.func_overload') & 0x02) === 0x02); } } // }}} /** * Sets a new option value. Available options and values: * * [utf8 - Use either UTF-8 or ISO-8859-1 as input (true for UTF-8, false * otherwise); The output is always UTF-8] * [overlong - Unicode does not allow unnecessarily long encodings of chars, * to allow this, set this parameter to true, else to false; * default is false.] * [strict - true: strict mode, good for registration purposes - Causes errors * on failures; false: loose mode, ideal for "wildlife" applications * by silently ignoring errors and returning the original input instead] * * @param mixed $option Parameter to set (string: single parameter; array of Parameter => Value pairs) * @param string $value Value to use (if parameter 1 is a string) * * @return boolean true on success, false otherwise * @access public */ public function setParams($option, $value = false) { if (!is_array($option)) { $option = array($option => $value); } foreach ($option as $k => $v) { switch ($k) { case 'encoding': switch ($v) { case 'utf8': case 'ucs4_string': case 'ucs4_array': $this->_api_encoding = $v; break; default: throw new InvalidArgumentException('Set Parameter: Unknown parameter '.$v.' for option '.$k); } break; case 'overlong': $this->_allow_overlong = ($v) ? true : false; break; case 'strict': $this->_strict_mode = ($v) ? true : false; break; case 'version': if (in_array($v, array('2003', '2008'))) { $this->_version = $v; } else { throw new InvalidArgumentException('Set Parameter: Invalid parameter '.$v.' for option '.$k); } break; default: return false; } } return true; } /** * Encode a given UTF-8 domain name. * * @param string $decoded Domain name (UTF-8 or UCS-4) * @param string $one_time_encoding Desired input encoding, see {@link set_parameter} * If not given will use default-encoding * * @return string Encoded Domain name (ACE string) * @return mixed processed string * @throws Exception * @access public */ public function encode($decoded, $one_time_encoding = false) { // Forcing conversion of input to UCS4 array // If one time encoding is given, use this, else the objects property switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) { case 'utf8': $decoded = $this->_utf8_to_ucs4($decoded); break; case 'ucs4_string': $decoded = $this->_ucs4_string_to_ucs4($decoded); case 'ucs4_array': // No break; before this line. Catch case, but do nothing break; default: throw new InvalidArgumentException('Unsupported input format'); } // No input, no output, what else did you expect? if (empty($decoded)) return ''; // Anchors for iteration $last_begin = 0; // Output string $output = ''; foreach ($decoded as $k => $v) { // Make sure to use just the plain dot switch($v) { case 0x3002: case 0xFF0E: case 0xFF61: $decoded[$k] = 0x2E; // It's right, no break here // The codepoints above have to be converted to dots anyway // Stumbling across an anchoring character case 0x2E: case 0x2F: case 0x3A: case 0x3F: case 0x40: // Neither email addresses nor URLs allowed in strict mode if ($this->_strict_mode) { throw new InvalidArgumentException('Neither email addresses nor URLs are allowed in strict mode.'); } // Skip first char if ($k) { $encoded = ''; $encoded = $this->_encode(array_slice($decoded, $last_begin, (($k)-$last_begin))); if ($encoded) { $output .= $encoded; } else { $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($k)-$last_begin))); } $output .= chr($decoded[$k]); } $last_begin = $k + 1; } } // Catch the rest of the string if ($last_begin) { $inp_len = sizeof($decoded); $encoded = ''; $encoded = $this->_encode(array_slice($decoded, $last_begin, (($inp_len)-$last_begin))); if ($encoded) { $output .= $encoded; } else { $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($inp_len)-$last_begin))); } return $output; } if ($output = $this->_encode($decoded)) { return $output; } return $this->_ucs4_to_utf8($decoded); } /** * Decode a given ACE domain name. * * @param string $input Domain name (ACE string) * @param string $one_time_encoding Desired output encoding, see {@link set_parameter} * * @return string Decoded Domain name (UTF-8 or UCS-4) * @throws Exception * @access public */ public function decode($input, $one_time_encoding = false) { // Optionally set if ($one_time_encoding) { switch ($one_time_encoding) { case 'utf8': case 'ucs4_string': case 'ucs4_array': break; default: throw new InvalidArgumentException('Unknown encoding '.$one_time_encoding); } } // Make sure to drop any newline characters around $input = trim($input); // Negotiate input and try to determine, wether it is a plain string, // an email address or something like a complete URL if (strpos($input, '@')) { // Maybe it is an email address // No no in strict mode if ($this->_strict_mode) { throw new InvalidArgumentException('Only simple domain name parts can be handled in strict mode'); } list($email_pref, $input) = explode('@', $input, 2); $arr = explode('.', $input); foreach ($arr as $k => $v) { $conv = $this->_decode($v); if ($conv) $arr[$k] = $conv; } $return = $email_pref . '@' . join('.', $arr); } elseif (preg_match('![:\./]!', $input)) { // Or a complete domain name (with or without paths / parameters) // No no in strict mode if ($this->_strict_mode) { throw new InvalidArgumentException('Only simple domain name parts can be handled in strict mode'); } $parsed = parse_url($input); if (isset($parsed['host'])) { $arr = explode('.', $parsed['host']); foreach ($arr as $k => $v) { $conv = $this->_decode($v); if ($conv) $arr[$k] = $conv; } $parsed['host'] = join('.', $arr); if (isset($parsed['scheme'])) { $parsed['scheme'] .= (strtolower($parsed['scheme']) == 'mailto') ? ':' : '://'; } $return = $this->_unparse_url($parsed); } else { // parse_url seems to have failed, try without it $arr = explode('.', $input); foreach ($arr as $k => $v) { $conv = $this->_decode($v); if ($conv) $arr[$k] = $conv; } $return = join('.', $arr); } } else { // Otherwise we consider it being a pure domain name string $return = $this->_decode($input); } // The output is UTF-8 by default, other output formats need conversion here // If one time encoding is given, use this, else the objects property switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) { case 'utf8': return $return; break; case 'ucs4_string': return $this->_ucs4_to_ucs4_string($this->_utf8_to_ucs4($return)); break; case 'ucs4_array': return $this->_utf8_to_ucs4($return); break; default: throw new InvalidArgumentException('Unsupported output format'); } } // {{{ private /** * Opposite function to parse_url() * * Inspired by code from comments of php.net-documentation for parse_url() * * @param array $parts_arr parts (strings) as returned by parse_url() * * @return string * @access private */ private function _unparse_url($parts_arr) { if (!empty($parts_arr['scheme'])) { $ret_url = $parts_arr['scheme']; } if (!empty($parts_arr['user'])) { $ret_url .= $parts_arr['user']; if (!empty($parts_arr['pass'])) { $ret_url .= ':' . $parts_arr['pass']; } $ret_url .= '@'; } $ret_url .= $parts_arr['host']; if (!empty($parts_arr['port'])) { $ret_url .= ':' . $parts_arr['port']; } $ret_url .= $parts_arr['path']; if (!empty($parts_arr['query'])) { $ret_url .= '?' . $parts_arr['query']; } if (!empty($parts_arr['fragment'])) { $ret_url .= '#' . $parts_arr['fragment']; } return $ret_url; } /** * The actual encoding algorithm. * * @param string $decoded Decoded string which should be encoded * * @return string Encoded string * @throws Exception * @access private */ private function _encode($decoded) { // We cannot encode a domain name containing the Punycode prefix $extract = self::_byteLength($this->_punycode_prefix); $check_pref = $this->_utf8_to_ucs4($this->_punycode_prefix); $check_deco = array_slice($decoded, 0, $extract); if ($check_pref == $check_deco) { throw new InvalidArgumentException('This is already a punycode string'); } // We will not try to encode strings consisting of basic code points only $encodable = false; foreach ($decoded as $k => $v) { if ($v > 0x7a) { $encodable = true; break; } } if (!$encodable) { if ($this->_strict_mode) { throw new InvalidArgumentException('The given string does not contain encodable chars'); } return false; } // Do NAMEPREP $decoded = $this->_nameprep($decoded); $deco_len = count($decoded); // Empty array if (!$deco_len) { return false; } // How many chars have been consumed $codecount = 0; // Start with the prefix; copy it to output $encoded = $this->_punycode_prefix; $encoded = ''; // Copy all basic code points to output for ($i = 0; $i < $deco_len; ++$i) { $test = $decoded[$i]; // Will match [0-9a-zA-Z-] if ((0x2F < $test && $test < 0x40) || (0x40 < $test && $test < 0x5B) || (0x60 < $test && $test <= 0x7B) || (0x2D == $test) ) { $encoded .= chr($decoded[$i]); $codecount++; } } // All codepoints were basic ones if ($codecount == $deco_len) { return $encoded; } // Start with the prefix; copy it to output $encoded = $this->_punycode_prefix . $encoded; // If we have basic code points in output, add an hyphen to the end if ($codecount) { $encoded .= '-'; } // Now find and encode all non-basic code points $is_first = true; $cur_code = $this->_initial_n; $bias = $this->_initial_bias; $delta = 0; while ($codecount < $deco_len) { // Find the smallest code point >= the current code point and // remember the last ouccrence of it in the input for ($i = 0, $next_code = $this->_max_ucs; $i < $deco_len; $i++) { if ($decoded[$i] >= $cur_code && $decoded[$i] <= $next_code) { $next_code = $decoded[$i]; } } $delta += ($next_code - $cur_code) * ($codecount + 1); $cur_code = $next_code; // Scan input again and encode all characters whose code point is $cur_code for ($i = 0; $i < $deco_len; $i++) { if ($decoded[$i] < $cur_code) { $delta++; } else if ($decoded[$i] == $cur_code) { for ($q = $delta, $k = $this->_base; 1; $k += $this->_base) { $t = ($k <= $bias)? $this->_tmin : (($k >= $bias + $this->_tmax)? $this->_tmax : $k - $bias); if ($q < $t) { break; } $encoded .= $this->_encodeDigit(ceil($t + (($q - $t) % ($this->_base - $t)))); $q = ($q - $t) / ($this->_base - $t); } $encoded .= $this->_encodeDigit($q); $bias = $this->_adapt($delta, $codecount + 1, $is_first); $codecount++; $delta = 0; $is_first = false; } } $delta++; $cur_code++; } return $encoded; } /** * The actual decoding algorithm. * * @param string $encoded Encoded string which should be decoded * * @return string Decoded string * @throws Exception * @access private */ private function _decode($encoded) { // We do need to find the Punycode prefix if (!preg_match('!^' . preg_quote($this->_punycode_prefix, '!') . '!', $encoded)) { return false; } $encode_test = preg_replace('!^' . preg_quote($this->_punycode_prefix, '!') . '!', '', $encoded); // If nothing left after removing the prefix, it is hopeless if (!$encode_test) { return false; } // Find last occurence of the delimiter $delim_pos = strrpos($encoded, '-'); if ($delim_pos > self::_byteLength($this->_punycode_prefix)) { for ($k = self::_byteLength($this->_punycode_prefix); $k < $delim_pos; ++$k) { $decoded[] = ord($encoded{$k}); } } else { $decoded = array(); } $deco_len = count($decoded); $enco_len = self::_byteLength($encoded); // Wandering through the strings; init $is_first = true; $bias = $this->_initial_bias; $idx = 0; $char = $this->_initial_n; for ($enco_idx = ($delim_pos)? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) { for ($old_idx = $idx, $w = 1, $k = $this->_base; 1 ; $k += $this->_base) { $digit = $this->_decodeDigit($encoded{$enco_idx++}); $idx += $digit * $w; $t = ($k <= $bias) ? $this->_tmin : (($k >= $bias + $this->_tmax)? $this->_tmax : ($k - $bias)); if ($digit < $t) { break; } $w = (int)($w * ($this->_base - $t)); } $bias = $this->_adapt($idx - $old_idx, $deco_len + 1, $is_first); $is_first = false; $char += (int) ($idx / ($deco_len + 1)); $idx %= ($deco_len + 1); if ($deco_len > 0) { // Make room for the decoded char for ($i = $deco_len; $i > $idx; $i--) { $decoded[$i] = $decoded[($i - 1)]; } } $decoded[$idx++] = $char; } return $this->_ucs4_to_utf8($decoded); } /** * Adapt the bias according to the current code point and position. * * @param int $delta ... * @param int $npoints ... * @param boolean $is_first ... * * @return int * @access private */ private function _adapt($delta, $npoints, $is_first) { $delta = (int) ($is_first ? ($delta / $this->_damp) : ($delta / 2)); $delta += (int) ($delta / $npoints); for ($k = 0; $delta > (($this->_base - $this->_tmin) * $this->_tmax) / 2; $k += $this->_base) { $delta = (int) ($delta / ($this->_base - $this->_tmin)); } return (int) ($k + ($this->_base - $this->_tmin + 1) * $delta / ($delta + $this->_skew)); } /** * Encoding a certain digit. * * @param int $d One digit to encode * * @return char Encoded digit * @access private */ private function _encodeDigit($d) { return chr($d + 22 + 75 * ($d < 26)); } /** * Decode a certain digit. * * @param char $cp One digit (character) to decode * * @return int Decoded digit * @access private */ private function _decodeDigit($cp) { $cp = ord($cp); return ($cp - 48 < 10)? $cp - 22 : (($cp - 65 < 26)? $cp - 65 : (($cp - 97 < 26)? $cp - 97 : $this->_base)); } /** * Do Nameprep according to RFC3491 and RFC3454. * * @param array $input Unicode Characters * * @return string Unicode Characters, Nameprep'd * @throws Exception * @access private */ private function _nameprep($input) { $output = array(); // Walking through the input array, performing the required steps on each of // the input chars and putting the result into the output array // While mapping required chars we apply the cannonical ordering foreach ($input as $v) { // Map to nothing == skip that code point if (in_array($v, self::$_np_map_nothing)) { continue; } // Try to find prohibited input if (in_array($v, self::$_np_prohibit) || in_array($v, self::$_general_prohibited)) { throw new Net_IDNA2_Exception_Nameprep('Prohibited input U+' . sprintf('%08X', $v)); } foreach (self::$_np_prohibit_ranges as $range) { if ($range[0] <= $v && $v <= $range[1]) { throw new Net_IDNA2_Exception_Nameprep('Prohibited input U+' . sprintf('%08X', $v)); } } // Hangul syllable decomposition if (0xAC00 <= $v && $v <= 0xD7AF) { foreach ($this->_hangulDecompose($v) as $out) { $output[] = $out; } } else if (($this->_version == '2003') && isset(self::$_np_replacemaps[$v])) { // There's a decomposition mapping for that code point // Decompositions only in version 2003 (original) of IDNA foreach ($this->_applyCannonicalOrdering(self::$_np_replacemaps[$v]) as $out) { $output[] = $out; } } else { $output[] = $v; } } // Combine code points $last_class = 0; $last_starter = 0; $out_len = count($output); for ($i = 0; $i < $out_len; ++$i) { $class = $this->_getCombiningClass($output[$i]); if ((!$last_class || $last_class != $class) && $class) { // Try to match $seq_len = $i - $last_starter; $out = $this->_combine(array_slice($output, $last_starter, $seq_len)); // On match: Replace the last starter with the composed character and remove // the now redundant non-starter(s) if ($out) { $output[$last_starter] = $out; if (count($out) != $seq_len) { for ($j = $i + 1; $j < $out_len; ++$j) { $output[$j - 1] = $output[$j]; } unset($output[$out_len]); } // Rewind the for loop by one, since there can be more possible compositions $i--; $out_len--; $last_class = ($i == $last_starter)? 0 : $this->_getCombiningClass($output[$i - 1]); continue; } } // The current class is 0 if (!$class) { $last_starter = $i; } $last_class = $class; } return $output; } /** * Decomposes a Hangul syllable * (see http://www.unicode.org/unicode/reports/tr15/#Hangul). * * @param integer $char 32bit UCS4 code point * * @return array Either Hangul Syllable decomposed or original 32bit * value as one value array * @access private */ private function _hangulDecompose($char) { $sindex = $char - $this->_sbase; if ($sindex < 0 || $sindex >= $this->_scount) { return array($char); } $result = array(); $T = $this->_tbase + $sindex % $this->_tcount; $result[] = (int)($this->_lbase + $sindex / $this->_ncount); $result[] = (int)($this->_vbase + ($sindex % $this->_ncount) / $this->_tcount); if ($T != $this->_tbase) { $result[] = $T; } return $result; } /** * Ccomposes a Hangul syllable * (see http://www.unicode.org/unicode/reports/tr15/#Hangul). * * @param array $input Decomposed UCS4 sequence * * @return array UCS4 sequence with syllables composed * @access private */ private function _hangulCompose($input) { $inp_len = count($input); if (!$inp_len) { return array(); } $result = array(); $last = $input[0]; $result[] = $last; // copy first char from input to output for ($i = 1; $i < $inp_len; ++$i) { $char = $input[$i]; // Find out, wether two current characters from L and V $lindex = $last - $this->_lbase; if (0 <= $lindex && $lindex < $this->_lcount) { $vindex = $char - $this->_vbase; if (0 <= $vindex && $vindex < $this->_vcount) { // create syllable of form LV $last = ($this->_sbase + ($lindex * $this->_vcount + $vindex) * $this->_tcount); $out_off = count($result) - 1; $result[$out_off] = $last; // reset last // discard char continue; } } // Find out, wether two current characters are LV and T $sindex = $last - $this->_sbase; if (0 <= $sindex && $sindex < $this->_scount && ($sindex % $this->_tcount) == 0) { $tindex = $char - $this->_tbase; if (0 <= $tindex && $tindex <= $this->_tcount) { // create syllable of form LVT $last += $tindex; $out_off = count($result) - 1; $result[$out_off] = $last; // reset last // discard char continue; } } // if neither case was true, just add the character $last = $char; $result[] = $char; } return $result; } /** * Returns the combining class of a certain wide char. * * @param integer $char Wide char to check (32bit integer) * * @return integer Combining class if found, else 0 * @access private */ private function _getCombiningClass($char) { return isset(self::$_np_norm_combcls[$char])? self::$_np_norm_combcls[$char] : 0; } /** * Apllies the cannonical ordering of a decomposed UCS4 sequence. * * @param array $input Decomposed UCS4 sequence * * @return array Ordered USC4 sequence * @access private */ private function _applyCannonicalOrdering($input) { $swap = true; $size = count($input); while ($swap) { $swap = false; $last = $this->_getCombiningClass($input[0]); for ($i = 0; $i < $size - 1; ++$i) { $next = $this->_getCombiningClass($input[$i + 1]); if ($next != 0 && $last > $next) { // Move item leftward until it fits for ($j = $i + 1; $j > 0; --$j) { if ($this->_getCombiningClass($input[$j - 1]) <= $next) { break; } $t = $input[$j]; $input[$j] = $input[$j - 1]; $input[$j - 1] = $t; $swap = 1; } // Reentering the loop looking at the old character again $next = $last; } $last = $next; } } return $input; } /** * Do composition of a sequence of starter and non-starter. * * @param array $input UCS4 Decomposed sequence * * @return array Ordered USC4 sequence * @access private */ private function _combine($input) { $inp_len = count($input); // Is it a Hangul syllable? if (1 != $inp_len) { $hangul = $this->_hangulCompose($input); // This place is probably wrong if (count($hangul) != $inp_len) { return $hangul; } } foreach (self::$_np_replacemaps as $np_src => $np_target) { if ($np_target[0] != $input[0]) { continue; } if (count($np_target) != $inp_len) { continue; } $hit = false; foreach ($input as $k2 => $v2) { if ($v2 == $np_target[$k2]) { $hit = true; } else { $hit = false; break; } } if ($hit) { return $np_src; } } return false; } /** * This converts an UTF-8 encoded string to its UCS-4 (array) representation * By talking about UCS-4 we mean arrays of 32bit integers representing * each of the "chars". This is due to PHP not being able to handle strings with * bit depth different from 8. This applies to the reverse method _ucs4_to_utf8(), too. * The following UTF-8 encodings are supported: * * bytes bits representation * 1 7 0xxxxxxx * 2 11 110xxxxx 10xxxxxx * 3 16 1110xxxx 10xxxxxx 10xxxxxx * 4 21 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx * 5 26 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx * 6 31 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx * * Each x represents a bit that can be used to store character data. * * @param string $input utf8-encoded string * * @return array ucs4-encoded array * @throws Exception * @access private */ private function _utf8_to_ucs4($input) { $output = array(); $out_len = 0; $inp_len = self::_byteLength($input, '8bit'); $mode = 'next'; $test = 'none'; for ($k = 0; $k < $inp_len; ++$k) { $v = ord($input{$k}); // Extract byte from input string if ($v < 128) { // We found an ASCII char - put into stirng as is $output[$out_len] = $v; ++$out_len; if ('add' == $mode) { throw new UnexpectedValueException('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k); } continue; } if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char $start_byte = $v; $mode = 'add'; $test = 'range'; if ($v >> 5 == 6) { // &110xxxxx 10xxxxx $next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left $v = ($v - 192) << 6; } elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx $next_byte = 1; $v = ($v - 224) << 12; } elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx $next_byte = 2; $v = ($v - 240) << 18; } elseif ($v >> 2 == 62) { // &111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx $next_byte = 3; $v = ($v - 248) << 24; } elseif ($v >> 1 == 126) { // &1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx $next_byte = 4; $v = ($v - 252) << 30; } else { throw new UnexpectedValueException('This might be UTF-8, but I don\'t understand it at byte '.$k); } if ('add' == $mode) { $output[$out_len] = (int) $v; ++$out_len; continue; } } if ('add' == $mode) { if (!$this->_allow_overlong && $test == 'range') { $test = 'none'; if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) { throw new OutOfRangeException('Bogus UTF-8 character detected (out of legal range) at byte '.$k); } } if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx $v = ($v - 128) << ($next_byte * 6); $output[($out_len - 1)] += $v; --$next_byte; } else { throw new UnexpectedValueException('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k); } if ($next_byte < 0) { $mode = 'next'; } } } // for return $output; } /** * Convert UCS-4 array into UTF-8 string * * @param array $input ucs4-encoded array * * @return string utf8-encoded string * @throws Exception * @access private */ private function _ucs4_to_utf8($input) { $output = ''; foreach ($input as $v) { // $v = ord($v); if ($v < 128) { // 7bit are transferred literally $output .= chr($v); } else if ($v < 1 << 11) { // 2 bytes $output .= chr(192 + ($v >> 6)) . chr(128 + ($v & 63)); } else if ($v < 1 << 16) { // 3 bytes $output .= chr(224 + ($v >> 12)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63)); } else if ($v < 1 << 21) { // 4 bytes $output .= chr(240 + ($v >> 18)) . chr(128 + (($v >> 12) & 63)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63)); } else if ($v < 1 << 26) { // 5 bytes $output .= chr(248 + ($v >> 24)) . chr(128 + (($v >> 18) & 63)) . chr(128 + (($v >> 12) & 63)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63)); } else if ($v < 1 << 31) { // 6 bytes $output .= chr(252 + ($v >> 30)) . chr(128 + (($v >> 24) & 63)) . chr(128 + (($v >> 18) & 63)) . chr(128 + (($v >> 12) & 63)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63)); } else { throw new UnexpectedValueException('Conversion from UCS-4 to UTF-8 failed: malformed input'); } } return $output; } /** * Convert UCS-4 array into UCS-4 string * * @param array $input ucs4-encoded array * * @return string ucs4-encoded string * @throws Exception * @access private */ private function _ucs4_to_ucs4_string($input) { $output = ''; // Take array values and split output to 4 bytes per value // The bit mask is 255, which reads &11111111 foreach ($input as $v) { $output .= ($v & (255 << 24) >> 24) . ($v & (255 << 16) >> 16) . ($v & (255 << 8) >> 8) . ($v & 255); } return $output; } /** * Convert UCS-4 string into UCS-4 array * * @param string $input ucs4-encoded string * * @return array ucs4-encoded array * @throws InvalidArgumentException * @access private */ private function _ucs4_string_to_ucs4($input) { $output = array(); $inp_len = self::_byteLength($input); // Input length must be dividable by 4 if ($inp_len % 4) { throw new InvalidArgumentException('Input UCS4 string is broken'); } // Empty input - return empty output if (!$inp_len) { return $output; } for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) { // Increment output position every 4 input bytes if (!$i % 4) { $out_len++; $output[$out_len] = 0; } $output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) ); } return $output; } /** * Echo hex representation of UCS4 sequence. * * @param array $input UCS4 sequence * @param boolean $include_bit Include bitmask in output * * @return void * @static * @access private */ private static function _showHex($input, $include_bit = false) { foreach ($input as $k => $v) { echo '[', $k, '] => ', sprintf('%X', $v); if ($include_bit) { echo ' (', Net_IDNA2::_showBitmask($v), ')'; } echo "\n"; } } /** * Gives you a bit representation of given Byte (8 bits), Word (16 bits) or DWord (32 bits) * Output width is automagically determined * * @param int $octet ... * * @return string Bitmask-representation * @static * @access private */ private static function _showBitmask($octet) { if ($octet >= (1 << 16)) { $w = 31; } else if ($octet >= (1 << 8)) { $w = 15; } else { $w = 7; } $return = ''; for ($i = $w; $i > -1; $i--) { $return .= ($octet & (1 << $i))? '1' : '0'; } return $return; } /** * Gets the length of a string in bytes even if mbstring function * overloading is turned on * * @param string $string the string for which to get the length. * * @return integer the length of the string in bytes. * * @see Net_IDNA2::$_mb_string_overload */ private static function _byteLength($string) { if (self::$_mb_string_overload) { return mb_strlen($string, '8bit'); } return strlen((binary)$string); } // }}}} // {{{ factory /** * Attempts to return a concrete IDNA instance for either php4 or php5. * * @param array $params Set of paramaters * * @return Net_IDNA2 * @access public */ function getInstance($params = array()) { return new Net_IDNA2($params); } // }}} // {{{ singleton /** * Attempts to return a concrete IDNA instance for either php4 or php5, * only creating a new instance if no IDNA instance with the same * parameters currently exists. * * @param array $params Set of paramaters * * @return object Net_IDNA2 * @access public */ function singleton($params = array()) { static $instances; if (!isset($instances)) { $instances = array(); } $signature = serialize($params); if (!isset($instances[$signature])) { $instances[$signature] = Net_IDNA2::getInstance($params); } return $instances[$signature]; } // }}} } ?> PK!S66Net/IDNA2/Exception.phpnu[ * @author Damian Fernandez Sosa * @author Anish Mistry * @author Jan Schneider * @copyright 2002-2003 Richard Heyes * @copyright 2006-2008 Anish Mistry * @license http://www.opensource.org/licenses/bsd-license.php BSD * @link http://pear.php.net/package/Net_Sieve */ require_once 'PEAR.php'; require_once 'Net/Socket.php'; /** * Disconnected state * * @const NET_SIEVE_STATE_DISCONNECTED */ define('NET_SIEVE_STATE_DISCONNECTED', 1); /** * Authorisation state * * @const NET_SIEVE_STATE_AUTHORISATION */ define('NET_SIEVE_STATE_AUTHORISATION', 2); /** * Transaction state * * @const NET_SIEVE_STATE_TRANSACTION */ define('NET_SIEVE_STATE_TRANSACTION', 3); /** * A class for talking to the timsieved server which comes with Cyrus IMAP. * * @category Networking * @package Net_Sieve * @author Richard Heyes * @author Damian Fernandez Sosa * @author Anish Mistry * @author Jan Schneider * @author Neil Munday * @copyright 2002-2003 Richard Heyes * @copyright 2006-2008 Anish Mistry * @license http://www.opensource.org/licenses/bsd-license.php BSD * @version Release: 1.4.5 * @link http://pear.php.net/package/Net_Sieve * @link http://tools.ietf.org/html/rfc5228 RFC 5228 (Sieve: An Email * Filtering Language) * @link http://tools.ietf.org/html/rfc5804 RFC 5804 A Protocol for * Remotely Managing Sieve Scripts */ class Net_Sieve { /** * The authentication methods this class supports. * * Can be overwritten if having problems with certain methods. * * @var array */ var $supportedAuthMethods = array( 'DIGEST-MD5', 'CRAM-MD5', 'EXTERNAL', 'PLAIN' , 'LOGIN', 'GSSAPI', 'XOAUTH2' ); /** * SASL authentication methods that require Auth_SASL. * * @var array */ var $supportedSASLAuthMethods = array('DIGEST-MD5', 'CRAM-MD5'); /** * The socket handle. * * @var resource */ var $_sock; /** * Parameters and connection information. * * @var array */ var $_data; /** * Current state of the connection. * * One of the NET_SIEVE_STATE_* constants. * * @var integer */ var $_state; /** * PEAR object to avoid strict warnings. * * @var PEAR_Error */ var $_pear; /** * Constructor error. * * @var PEAR_Error */ var $_error; /** * Whether to enable debugging. * * @var boolean */ var $_debug = false; /** * Debug output handler. * * This has to be a valid callback. * * @var string|array */ var $_debug_handler = null; /** * Whether to pick up an already established connection. * * @var boolean */ var $_bypassAuth = false; /** * Whether to use TLS if available. * * @var boolean */ var $_useTLS = true; /** * Additional options for stream_context_create(). * * @var array */ var $_options = null; /** * Maximum number of referral loops * * @var array */ var $_maxReferralCount = 15; /** * Kerberos service principal to use for GSSAPI authentication. * * @var string */ var $_gssapiPrincipal = null; /** * Kerberos service cname to use for GSSAPI authentication. * * @var string */ var $_gssapiCN = null; /** * Constructor. * * Sets up the object, connects to the server and logs in. Stores any * generated error in $this->_error, which can be retrieved using the * getError() method. * * @param string $user Login username. * @param string $pass Login password. * @param string $host Hostname of server. * @param string $port Port of server. * @param string $logintype Type of login to perform (see * $supportedAuthMethods). * @param string $euser Effective user. If authenticating as an * administrator, login as this user. * @param boolean $debug Whether to enable debugging (@see setDebug()). * @param string $bypassAuth Skip the authentication phase. Useful if the * socket is already open. * @param boolean $useTLS Use TLS if available. * @param array $options Additional options for * stream_context_create(). * @param mixed $handler A callback handler for the debug output. * @param string $principal Kerberos service principal to use * with GSSAPI authentication. * @param string $cname Kerberos service cname to use * with GSSAPI authentication. */ function __construct($user = null, $pass = null, $host = 'localhost', $port = 2000, $logintype = '', $euser = '', $debug = false, $bypassAuth = false, $useTLS = true, $options = null, $handler = null, $principal = null, $cname = null ) { $this->_pear = new PEAR(); $this->_state = NET_SIEVE_STATE_DISCONNECTED; $this->_data['user'] = $user; $this->_data['pass'] = $pass; $this->_data['host'] = $host; $this->_data['port'] = $port; $this->_data['logintype'] = $logintype; $this->_data['euser'] = $euser; $this->_sock = new Net_Socket(); $this->_bypassAuth = $bypassAuth; $this->_useTLS = $useTLS; $this->_options = (array) $options; $this->_gssapiPrincipal = $principal; $this->_gssapiCN = $cname; $this->setDebug($debug, $handler); /* Try to include the Auth_SASL package. If the package is not * available, we disable the authentication methods that depend upon * it. */ if ((@include_once 'Auth/SASL.php') === false) { $this->_debug('Auth_SASL not present'); $this->supportedAuthMethods = array_diff( $this->supportedAuthMethods, $this->supportedSASLAuthMethods ); } if (strlen($user) && strlen($pass)) { $this->_error = $this->_handleConnectAndLogin(); } } /** * Returns any error that may have been generated in the constructor. * * @return boolean|PEAR_Error False if no error, PEAR_Error otherwise. */ function getError() { return is_a($this->_error, 'PEAR_Error') ? $this->_error : false; } /** * Sets the debug state and handler function. * * @param boolean $debug Whether to enable debugging. * @param string $handler A custom debug handler. Must be a valid callback. * * @return void */ function setDebug($debug = true, $handler = null) { $this->_debug = $debug; $this->_debug_handler = $handler; } /** * Sets the Kerberos service principal for use with GSSAPI * authentication. * * @param string $principal The Kerberos service principal * * @return void */ function setServicePrincipal($principal) { $this->_gssapiPrincipal = $principal; } /** * Sets the Kerberos service CName for use with GSSAPI * authentication. * * @param string $cname The Kerberos service principal * * @return void */ function setServiceCN($cname) { $this->_gssapiCN = $cname; } /** * Connects to the server and logs in. * * @return boolean True on success, PEAR_Error on failure. */ function _handleConnectAndLogin() { $res = $this->connect($this->_data['host'], $this->_data['port'], $this->_options, $this->_useTLS); if (is_a($res, 'PEAR_Error')) { return $res; } if ($this->_bypassAuth === false) { $res = $this->login($this->_data['user'], $this->_data['pass'], $this->_data['logintype'], $this->_data['euser'], $this->_bypassAuth); if (is_a($res, 'PEAR_Error')) { return $res; } } return true; } /** * Handles connecting to the server and checks the response validity. * * @param string $host Hostname of server. * @param string $port Port of server. * @param array $options List of options to pass to * stream_context_create(). * @param boolean $useTLS Use TLS if available. * * @return boolean True on success, PEAR_Error otherwise. */ function connect($host, $port, $options = null, $useTLS = true) { $this->_data['host'] = $host; $this->_data['port'] = $port; $this->_useTLS = $useTLS; if (is_array($options)) { $this->_options = array_merge($this->_options, $options); } if (NET_SIEVE_STATE_DISCONNECTED != $this->_state) { return $this->_pear->raiseError('Not currently in DISCONNECTED state', 1); } $res = $this->_sock->connect($host, $port, false, 5, $options); if (is_a($res, 'PEAR_Error')) { return $res; } if ($this->_bypassAuth) { $this->_state = NET_SIEVE_STATE_TRANSACTION; // Reset capabilities $this->_parseCapability(''); } else { $this->_state = NET_SIEVE_STATE_AUTHORISATION; $res = $this->_doCmd(); if (is_a($res, 'PEAR_Error')) { return $res; } // Reset capabilities (use unattended capabilities) $this->_parseCapability($res); } // Explicitly ask for the capabilities if needed if (empty($this->_capability['implementation'])) { $res = $this->_cmdCapability(); if (is_a($res, 'PEAR_Error')) { return $this->_pear->raiseError( 'Failed to connect, server said: ' . $res->getMessage(), 2 ); } } // Check if we can enable TLS via STARTTLS. if ($useTLS && !empty($this->_capability['starttls']) && function_exists('stream_socket_enable_crypto') ) { $res = $this->_startTLS(); if (is_a($res, 'PEAR_Error')) { return $res; } } return true; } /** * Disconnect from the Sieve server. * * @param boolean $sendLogoutCMD Whether to send LOGOUT command before * disconnecting. * * @return boolean True on success, PEAR_Error otherwise. */ function disconnect($sendLogoutCMD = true) { return $this->_cmdLogout($sendLogoutCMD); } /** * Logs into server. * * @param string $user Login username. * @param string $pass Login password. * @param string $logintype Type of login method to use. * @param string $euser Effective UID (perform on behalf of $euser). * @param boolean $bypassAuth Do not perform authentication. * * @return boolean True on success, PEAR_Error otherwise. */ function login($user, $pass, $logintype = null, $euser = '', $bypassAuth = false) { $this->_data['user'] = $user; $this->_data['pass'] = $pass; $this->_data['logintype'] = $logintype; $this->_data['euser'] = $euser; $this->_bypassAuth = $bypassAuth; if (NET_SIEVE_STATE_AUTHORISATION != $this->_state) { return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1); } if (!$bypassAuth ) { $res = $this->_cmdAuthenticate($user, $pass, $logintype, $euser); if (is_a($res, 'PEAR_Error')) { return $res; } } $this->_state = NET_SIEVE_STATE_TRANSACTION; return true; } /** * Returns an indexed array of scripts currently on the server. * * @param string $active Will be set to the name of the active script * * @return array Indexed array of scriptnames, PEAR_Error on failure */ function listScripts(&$active = null) { if (is_array($scripts = $this->_cmdListScripts())) { if (isset($scripts[1])) { $active = $scripts[1]; } return $scripts[0]; } return $scripts; } /** * Returns the active script. * * @return string The active scriptname. */ function getActive() { if (is_array($scripts = $this->_cmdListScripts())) { return $scripts[1]; } } /** * Sets the active script. * * @param string $scriptname The name of the script to be set as active. * * @return boolean True on success, PEAR_Error on failure. */ function setActive($scriptname) { return $this->_cmdSetActive($scriptname); } /** * Retrieves a script. * * @param string $scriptname The name of the script to be retrieved. * * @return string The script on success, PEAR_Error on failure. */ function getScript($scriptname) { return $this->_cmdGetScript($scriptname); } /** * Adds a script to the server. * * @param string $scriptname Name of the script. * @param string $script The script content. * @param boolean $makeactive Whether to make this the active script. * * @return boolean True on success, PEAR_Error on failure. */ function installScript($scriptname, $script, $makeactive = false) { $res = $this->_cmdPutScript($scriptname, $script); if (is_a($res, 'PEAR_Error')) { return $res; } if ($makeactive) { return $this->_cmdSetActive($scriptname); } return true; } /** * Removes a script from the server. * * @param string $scriptname Name of the script. * * @return boolean True on success, PEAR_Error on failure. */ function removeScript($scriptname) { return $this->_cmdDeleteScript($scriptname); } /** * Checks if the server has space to store the script by the server. * * @param string $scriptname The name of the script to mark as active. * @param integer $size The size of the script. * * @return boolean|PEAR_Error True if there is space, PEAR_Error otherwise. * * @todo Rename to hasSpace() */ function haveSpace($scriptname, $size) { if (NET_SIEVE_STATE_TRANSACTION != $this->_state) { return $this->_pear->raiseError('Not currently in TRANSACTION state', 1); } $res = $this->_doCmd(sprintf('HAVESPACE %s %d', $this->_escape($scriptname), $size)); if (is_a($res, 'PEAR_Error')) { return $res; } return true; } /** * Returns the list of extensions the server supports. * * @return array List of extensions or PEAR_Error on failure. */ function getExtensions() { if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { return $this->_pear->raiseError('Not currently connected', 7); } return $this->_capability['extensions']; } /** * Returns whether the server supports an extension. * * @param string $extension The extension to check. * * @return boolean Whether the extension is supported or PEAR_Error on * failure. */ function hasExtension($extension) { if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { return $this->_pear->raiseError('Not currently connected', 7); } $extension = trim($this->_toUpper($extension)); if (is_array($this->_capability['extensions'])) { foreach ($this->_capability['extensions'] as $ext) { if ($ext == $extension) { return true; } } } return false; } /** * Returns the list of authentication methods the server supports. * * @return array List of authentication methods or PEAR_Error on failure. */ function getAuthMechs() { if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { return $this->_pear->raiseError('Not currently connected', 7); } return $this->_capability['sasl']; } /** * Returns whether the server supports an authentication method. * * @param string $method The method to check. * * @return boolean Whether the method is supported or PEAR_Error on * failure. */ function hasAuthMech($method) { if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { return $this->_pear->raiseError('Not currently connected', 7); } $method = trim($this->_toUpper($method)); if (is_array($this->_capability['sasl'])) { foreach ($this->_capability['sasl'] as $sasl) { if ($sasl == $method) { return true; } } } return false; } /** * Handles the authentication using any known method. * * @param string $uid The userid to authenticate as. * @param string $pwd The password to authenticate with. * @param string $userMethod The method to use. If empty, the class chooses * the best (strongest) available method. * @param string $euser The effective uid to authenticate as. * * @return void */ function _cmdAuthenticate($uid, $pwd, $userMethod = null, $euser = '') { $method = $this->_getBestAuthMethod($userMethod); if (is_a($method, 'PEAR_Error')) { return $method; } switch ($method) { case 'DIGEST-MD5': return $this->_authDigestMD5($uid, $pwd, $euser); case 'CRAM-MD5': $result = $this->_authCRAMMD5($uid, $pwd, $euser); break; case 'LOGIN': $result = $this->_authLOGIN($uid, $pwd, $euser); break; case 'PLAIN': $result = $this->_authPLAIN($uid, $pwd, $euser); break; case 'EXTERNAL': $result = $this->_authEXTERNAL($uid, $pwd, $euser); break; case 'GSSAPI': $result = $this->_authGSSAPI($pwd); break; case 'XOAUTH2': $result = $this->_authXOAUTH2($uid, $pwd, $euser); break; default : $result = $this->_pear->raiseError( $method . ' is not a supported authentication method' ); break; } $res = $this->_doCmd(); if (is_a($res, 'PEAR_Error')) { return $res; } if ($this->_pear->isError($res = $this->_cmdCapability())) { return $this->_pear->raiseError( 'Failed to connect, server said: ' . $res->getMessage(), 2 ); } return $result; } /** * Authenticates the user using the PLAIN method. * * @param string $user The userid to authenticate as. * @param string $pass The password to authenticate with. * @param string $euser The effective uid to authenticate as. * * @return void */ function _authPLAIN($user, $pass, $euser) { return $this->_sendCmd( sprintf( 'AUTHENTICATE "PLAIN" "%s"', base64_encode($euser . chr(0) . $user . chr(0) . $pass) ) ); } /** * Authenticates the user using the GSSAPI method. * * @note the PHP krb5 extension is required and the service principal and cname * must have been set. * @see setServicePrincipal() * * @return void */ function _authGSSAPI() { if (!extension_loaded('krb5')) { return $this->_pear->raiseError('The krb5 extension is required for GSSAPI authentication', 2); } if (!$this->_gssapiPrincipal) { return $this->_pear->raiseError('No Kerberos service principal set', 2); } if (!$this->_gssapiCN) { return $this->_pear->raiseError('No Kerberos service CName set', 2); } putenv('KRB5CCNAME=' . $this->_gssapiCN); try { $ccache = new KRB5CCache(); $ccache->open($this->_gssapiCN); $gssapicontext = new GSSAPIContext(); $gssapicontext->acquireCredentials($ccache); $token = ''; $success = $gssapicontext->initSecContext($this->_gssapiPrincipal, null, null, null, $token); $token = base64_encode($token); } catch (Exception $e) { return $this->_pear->raiseError('GSSAPI authentication failed: ' . $e->getMessage()); } $this->_sendCmd("AUTHENTICATE \"GSSAPI\" {" . strlen($token) . "+}"); $response = $this->_doCmd($token, true); try { $challenge = base64_decode(substr($response, 1, -1)); $gssapicontext->unwrap($challenge, $challenge); $gssapicontext->wrap($challenge, $challenge, true); } catch (Exception $e) { return $this->_pear->raiseError('GSSAPI authentication failed: ' . $e->getMessage()); } $response = base64_encode($challenge); $this->_sendCmd("{" . strlen($response) . "+}"); return $this->_sendCmd($response); } /** * Authenticates the user using the LOGIN method. * * @param string $user The userid to authenticate as. * @param string $pass The password to authenticate with. * @param string $euser The effective uid to authenticate as. Not used. * * @return void */ function _authLOGIN($user, $pass, $euser) { $result = $this->_sendCmd('AUTHENTICATE "LOGIN"'); if (is_a($result, 'PEAR_Error')) { return $result; } $result = $this->_doCmd('"' . base64_encode($user) . '"', true); if (is_a($result, 'PEAR_Error')) { return $result; } return $this->_doCmd('"' . base64_encode($pass) . '"', true); } /** * Authenticates the user using the CRAM-MD5 method. * * @param string $user The userid to authenticate as. * @param string $pass The password to authenticate with. * @param string $euser The effective uid to authenticate as. Not used. * * @return void */ function _authCRAMMD5($user, $pass, $euser) { $challenge = $this->_doCmd('AUTHENTICATE "CRAM-MD5"', true); if (is_a($challenge, 'PEAR_Error')) { return $challenge; } $auth_sasl = new Auth_SASL; $cram = $auth_sasl->factory('crammd5'); $challenge = base64_decode(trim($challenge)); $response = $cram->getResponse($user, $pass, $challenge); if (is_a($response, 'PEAR_Error')) { return $response; } return $this->_sendStringResponse(base64_encode($response)); } /** * Authenticates the user using the DIGEST-MD5 method. * * @param string $user The userid to authenticate as. * @param string $pass The password to authenticate with. * @param string $euser The effective uid to authenticate as. * * @return void */ function _authDigestMD5($user, $pass, $euser) { $challenge = $this->_doCmd('AUTHENTICATE "DIGEST-MD5"', true); if (is_a($challenge, 'PEAR_Error')) { return $challenge; } $auth_sasl = new Auth_SASL; $digest = $auth_sasl->factory('digestmd5'); $challenge = base64_decode(trim($challenge)); // @todo Really 'localhost'? $response = $digest->getResponse($user, $pass, $challenge, 'localhost', 'sieve', $euser); if (is_a($response, 'PEAR_Error')) { return $response; } $result = $this->_sendStringResponse(base64_encode($response)); if (is_a($result, 'PEAR_Error')) { return $result; } $result = $this->_doCmd('', true); if (is_a($result, 'PEAR_Error')) { return $result; } if ($this->_toUpper(substr($result, 0, 2)) == 'OK') { return; } /* We don't use the protocol's third step because SIEVE doesn't allow * subsequent authentication, so we just silently ignore it. */ $result = $this->_sendStringResponse(''); if (is_a($result, 'PEAR_Error')) { return $result; } return $this->_doCmd(); } /** * Authenticates the user using the EXTERNAL method. * * @param string $user The userid to authenticate as. * @param string $pass The password to authenticate with. * @param string $euser The effective uid to authenticate as. * * @return void * * @since 1.1.7 */ function _authEXTERNAL($user, $pass, $euser) { $cmd = sprintf( 'AUTHENTICATE "EXTERNAL" "%s"', base64_encode(strlen($euser) ? $euser : $user) ); return $this->_sendCmd($cmd); } /** * Authenticates the user using the XOAUTH2 method. * * @param string $user The userid to authenticate as. * @param string $token The token to authenticate with. * @param string $euser The effective uid to authenticate as. * * @return void */ function _authXOAUTH2($user, $token, $euser) { // default to $user if $euser is not set if (! $euser) { $euser = $user; } $auth = base64_encode("user=$euser\001auth=$token\001\001"); return $this->_sendCmd("AUTHENTICATE \"XOAUTH2\" \"$auth\""); } /** * Removes a script from the server. * * @param string $scriptname Name of the script to delete. * * @return boolean True on success, PEAR_Error otherwise. */ function _cmdDeleteScript($scriptname) { if (NET_SIEVE_STATE_TRANSACTION != $this->_state) { return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1); } $res = $this->_doCmd(sprintf('DELETESCRIPT %s', $this->_escape($scriptname))); if (is_a($res, 'PEAR_Error')) { return $res; } return true; } /** * Retrieves the contents of the named script. * * @param string $scriptname Name of the script to retrieve. * * @return string The script if successful, PEAR_Error otherwise. */ function _cmdGetScript($scriptname) { if (NET_SIEVE_STATE_TRANSACTION != $this->_state) { return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1); } $res = $this->_doCmd(sprintf('GETSCRIPT %s', $this->_escape($scriptname))); if (is_a($res, 'PEAR_Error')) { return $res; } return preg_replace('/^{[0-9]+}\r\n/', '', $res); } /** * Sets the active script, i.e. the one that gets run on new mail by the * server. * * @param string $scriptname The name of the script to mark as active. * * @return boolean True on success, PEAR_Error otherwise. */ function _cmdSetActive($scriptname) { if (NET_SIEVE_STATE_TRANSACTION != $this->_state) { return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1); } $res = $this->_doCmd(sprintf('SETACTIVE %s', $this->_escape($scriptname))); if (is_a($res, 'PEAR_Error')) { return $res; } return true; } /** * Returns the list of scripts on the server. * * @return array An array with the list of scripts in the first element * and the active script in the second element on success, * PEAR_Error otherwise. */ function _cmdListScripts() { if (NET_SIEVE_STATE_TRANSACTION != $this->_state) { return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1); } $res = $this->_doCmd('LISTSCRIPTS'); if (is_a($res, 'PEAR_Error')) { return $res; } $scripts = array(); $activescript = null; $res = explode("\r\n", $res); foreach ($res as $value) { if (preg_match('/^"(.*)"( ACTIVE)?$/i', $value, $matches)) { $script_name = stripslashes($matches[1]); $scripts[] = $script_name; if (!empty($matches[2])) { $activescript = $script_name; } } } return array($scripts, $activescript); } /** * Adds a script to the server. * * @param string $scriptname Name of the new script. * @param string $scriptdata The new script. * * @return boolean True on success, PEAR_Error otherwise. */ function _cmdPutScript($scriptname, $scriptdata) { if (NET_SIEVE_STATE_TRANSACTION != $this->_state) { return $this->_pear->raiseError('Not currently in AUTHORISATION state', 1); } $stringLength = $this->_getLineLength($scriptdata); $command = sprintf( "PUTSCRIPT %s {%d+}\r\n%s", $this->_escape($scriptname), $stringLength, $scriptdata ); $res = $this->_doCmd($command); if (is_a($res, 'PEAR_Error')) { return $res; } return true; } /** * Logs out of the server and terminates the connection. * * @param boolean $sendLogoutCMD Whether to send LOGOUT command before * disconnecting. * * @return boolean True on success, PEAR_Error otherwise. */ function _cmdLogout($sendLogoutCMD = true) { if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { return $this->_pear->raiseError('Not currently connected', 1); } if ($sendLogoutCMD) { $res = $this->_doCmd('LOGOUT'); if (is_a($res, 'PEAR_Error')) { return $res; } } $this->_sock->disconnect(); $this->_state = NET_SIEVE_STATE_DISCONNECTED; return true; } /** * Sends the CAPABILITY command * * @return boolean True on success, PEAR_Error otherwise. */ function _cmdCapability() { if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { return $this->_pear->raiseError('Not currently connected', 1); } $res = $this->_doCmd('CAPABILITY'); if (is_a($res, 'PEAR_Error')) { return $res; } $this->_parseCapability($res); return true; } /** * Parses the response from the CAPABILITY command and stores the result * in $_capability. * * @param string $data The response from the capability command. * * @return void */ function _parseCapability($data) { // Clear the cached capabilities. $this->_capability = array('sasl' => array(), 'extensions' => array()); $data = preg_split('/\r?\n/', $this->_toUpper($data), -1, PREG_SPLIT_NO_EMPTY); for ($i = 0; $i < count($data); $i++) { if (!preg_match('/^"([A-Z]+)"( "(.*)")?$/', $data[$i], $matches)) { continue; } switch ($matches[1]) { case 'IMPLEMENTATION': $this->_capability['implementation'] = $matches[3]; break; case 'SASL': if (!empty($matches[3])) { $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]); } break; case 'SIEVE': if (!empty($matches[3])) { $this->_capability['extensions'] = preg_split('/\s+/', $matches[3]); } break; case 'STARTTLS': $this->_capability['starttls'] = true; break; } } } /** * Sends a command to the server * * @param string $cmd The command to send. * * @return void */ function _sendCmd($cmd) { $status = $this->_sock->getStatus(); if (is_a($status, 'PEAR_Error') || $status['eof']) { return $this->_pear->raiseError('Failed to write to socket: connection lost'); } $error = $this->_sock->write($cmd . "\r\n"); if (is_a($error, 'PEAR_Error')) { return $this->_pear->raiseError( 'Failed to write to socket: ' . $error->getMessage() ); } $this->_debug("C: $cmd"); } /** * Sends a string response to the server. * * @param string $str The string to send. * * @return void */ function _sendStringResponse($str) { return $this->_sendCmd('{' . $this->_getLineLength($str) . "+}\r\n" . $str); } /** * Receives a single line from the server. * * @return string The server response line. */ function _recvLn() { $lastline = $this->_sock->gets(8192); if (is_a($lastline, 'PEAR_Error')) { return $this->_pear->raiseError( 'Failed to read from socket: ' . $lastline->getMessage() ); } $lastline = rtrim($lastline); $this->_debug("S: $lastline"); if ($lastline === '') { return $this->_pear->raiseError('Failed to read from socket'); } return $lastline; } /** * Receives a number of bytes from the server. * * @param integer $length Number of bytes to read. * * @return string The server response. */ function _recvBytes($length) { $response = ''; $response_length = 0; while ($response_length < $length) { $response .= $this->_sock->read($length - $response_length); $response_length = $this->_getLineLength($response); } $this->_debug('S: ' . rtrim($response)); return $response; } /** * Send a command and retrieves a response from the server. * * @param string $cmd The command to send. * @param boolean $auth Whether this is an authentication command. * * @return string|PEAR_Error Reponse string if an OK response, PEAR_Error * if a NO response. */ function _doCmd($cmd = '', $auth = false) { $referralCount = 0; while ($referralCount < $this->_maxReferralCount) { if (strlen($cmd)) { $error = $this->_sendCmd($cmd); if (is_a($error, 'PEAR_Error')) { return $error; } } $response = ''; while (true) { $line = $this->_recvLn(); if (is_a($line, 'PEAR_Error')) { return $line; } if (preg_match('/^(OK|NO)/i', $line, $tag)) { // Check for string literal message. if (preg_match('/{([0-9]+)}$/', $line, $matches)) { $line = substr($line, 0, -(strlen($matches[1]) + 2)) . str_replace( "\r\n", ' ', $this->_recvBytes($matches[1] + 2) ); } if ('OK' == $this->_toUpper($tag[1])) { $response .= $line; return rtrim($response); } return $this->_pear->raiseError(trim($response . substr($line, 2)), 3); } if (preg_match('/^BYE/i', $line)) { $error = $this->disconnect(false); if (is_a($error, 'PEAR_Error')) { return $this->_pear->raiseError( 'Cannot handle BYE, the error was: ' . $error->getMessage(), 4 ); } // Check for referral, then follow it. Otherwise, carp an // error. if (preg_match('/^bye \(referral "(sieve:\/\/)?([^"]+)/i', $line, $matches)) { // Replace the old host with the referral host // preserving any protocol prefix. $this->_data['host'] = preg_replace( '/\w+(?!(\w|\:\/\/)).*/', $matches[2], $this->_data['host'] ); $error = $this->_handleConnectAndLogin(); if (is_a($error, 'PEAR_Error')) { return $this->_pear->raiseError( 'Cannot follow referral to ' . $this->_data['host'] . ', the error was: ' . $error->getMessage(), 5 ); } break; } return $this->_pear->raiseError(trim($response . $line), 6); } if (preg_match('/^{([0-9]+)}/', $line, $matches)) { // Matches literal string responses. $line = $this->_recvBytes($matches[1] + 2); if (!$auth) { // Receive the pending OK only if we aren't // authenticating since string responses during // authentication don't need an OK. $this->_recvLn(); } return $line; } if ($auth) { // String responses during authentication don't need an // OK. $response .= $line; return rtrim($response); } $response .= $line . "\r\n"; $referralCount++; } } return $this->_pear->raiseError('Max referral count (' . $referralCount . ') reached. Cyrus murder loop error?', 7); } /** * Returns the name of the best authentication method that the server * has advertised. * * @param string $userMethod Only consider this method as available. * * @return string The name of the best supported authentication method or * a PEAR_Error object on failure. */ function _getBestAuthMethod($userMethod = null) { if (!isset($this->_capability['sasl'])) { return $this->_pear->raiseError('This server doesn\'t support any authentication methods. SASL problem?'); } if (!$this->_capability['sasl']) { return $this->_pear->raiseError('This server doesn\'t support any authentication methods.'); } if ($userMethod) { if (in_array($userMethod, $this->_capability['sasl'])) { return $userMethod; } $msg = 'No supported authentication method found. The server supports these methods: %s, but we want to use: %s'; return $this->_pear->raiseError( sprintf($msg, implode(', ', $this->_capability['sasl']), $userMethod) ); } foreach ($this->supportedAuthMethods as $method) { if (in_array($method, $this->_capability['sasl'])) { return $method; } } $msg = 'No supported authentication method found. The server supports these methods: %s, but we only support: %s'; return $this->_pear->raiseError( sprintf($msg, implode(', ', $this->_capability['sasl']), implode(', ', $this->supportedAuthMethods)) ); } /** * Starts a TLS connection. * * @return boolean True on success, PEAR_Error on failure. */ function _startTLS() { $res = $this->_doCmd('STARTTLS'); if (is_a($res, 'PEAR_Error')) { return $res; } if (isset($this->_options['ssl']['crypto_method'])) { $crypto_method = $this->_options['ssl']['crypto_method']; } else { // There is no flag to enable all TLS methods. Net_SMTP // handles enabling TLS similarly. $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT | @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; } if (!stream_socket_enable_crypto($this->_sock->fp, true, $crypto_method)) { return $this->_pear->raiseError('Failed to establish TLS connection', 2); } $this->_debug('STARTTLS negotiation successful'); // The server should be sending a CAPABILITY response after // negotiating TLS. Read it, and ignore if it doesn't. // Unfortunately old Cyrus versions are broken and don't send a // CAPABILITY response, thus we would wait here forever. Parse the // Cyrus version and work around this broken behavior. if (!preg_match('/^CYRUS TIMSIEVED V([0-9.]+)/', $this->_capability['implementation'], $matches) || version_compare($matches[1], '2.3.10', '>=') ) { $res = $this->_doCmd(); } // Reset capabilities (use unattended capabilities) $this->_parseCapability(is_string($res) ? $res : ''); // Query the server capabilities again now that we are under encryption. if (empty($this->_capability['implementation'])) { $res = $this->_cmdCapability(); if (is_a($res, 'PEAR_Error')) { return $this->_pear->raiseError( 'Failed to connect, server said: ' . $res->getMessage(), 2 ); } } return true; } /** * Returns the length of a string. * * @param string $string A string. * * @return integer The length of the string. */ function _getLineLength($string) { if (extension_loaded('mbstring')) { return mb_strlen($string, '8bit'); } else { return strlen($string); } } /** * Locale independant strtoupper() implementation. * * @param string $string The string to convert to lowercase. * * @return string The lowercased string, based on ASCII encoding. */ function _toUpper($string) { $language = setlocale(LC_CTYPE, 0); setlocale(LC_CTYPE, 'C'); $string = strtoupper($string); setlocale(LC_CTYPE, $language); return $string; } /** * Converts strings into RFC's quoted-string or literal-c2s form. * * @param string $string The string to convert. * * @return string Result string. */ function _escape($string) { // Some implementations don't allow UTF-8 characters in quoted-string, // use literal-c2s. if (preg_match('/[^\x01-\x09\x0B-\x0C\x0E-\x7F]/', $string)) { return sprintf("{%d+}\r\n%s", $this->_getLineLength($string), $string); } return '"' . addcslashes($string, '\\"') . '"'; } /** * Write debug text to the current debug output handler. * * @param string $message Debug message text. * * @return void */ function _debug($message) { if ($this->_debug) { if ($this->_debug_handler) { call_user_func_array($this->_debug_handler, array(&$this, $message)); } else { echo "$message\n"; } } } } PK!³[KK Net/SMTP.phpnu[ | // | Jon Parise | // | Damian Alejandro Fernandez Sosa | // +----------------------------------------------------------------------+ require_once 'PEAR.php'; require_once 'Net/Socket.php'; /** * Provides an implementation of the SMTP protocol using PEAR's * Net_Socket:: class. * * @package Net_SMTP * @author Chuck Hagenbuch * @author Jon Parise * @author Damian Alejandro Fernandez Sosa * * @example basic.php A basic implementation of the Net_SMTP package. */ class Net_SMTP { /** * The server to connect to. * @var string * @access public */ var $host = 'localhost'; /** * The port to connect to. * @var int * @access public */ var $port = 25; /** * The value to give when sending EHLO or HELO. * @var string * @access public */ var $localhost = 'localhost'; /** * List of supported authentication methods, in preferential order. * @var array * @access public */ var $auth_methods = array(); /** * Use SMTP command pipelining (specified in RFC 2920) if the SMTP * server supports it. * * When pipeling is enabled, rcptTo(), mailFrom(), sendFrom(), * somlFrom() and samlFrom() do not wait for a response from the * SMTP server but return immediately. * * @var bool * @access public */ var $pipelining = false; /** * Number of pipelined commands. * @var int * @access private */ var $_pipelined_commands = 0; /** * Should debugging output be enabled? * @var boolean * @access private */ var $_debug = false; /** * Debug output handler. * @var callback * @access private */ var $_debug_handler = null; /** * The socket resource being used to connect to the SMTP server. * @var resource * @access private */ var $_socket = null; /** * Array of socket options that will be passed to Net_Socket::connect(). * @see stream_context_create() * @var array * @access private */ var $_socket_options = null; /** * The socket I/O timeout value in seconds. * @var int * @access private */ var $_timeout = 0; /** * The most recent server response code. * @var int * @access private */ var $_code = -1; /** * The most recent server response arguments. * @var array * @access private */ var $_arguments = array(); /** * Stores the SMTP server's greeting string. * @var string * @access private */ var $_greeting = null; /** * Stores detected features of the SMTP server. * @var array * @access private */ var $_esmtp = array(); /** * Instantiates a new Net_SMTP object, overriding any defaults * with parameters that are passed in. * * If you have SSL support in PHP, you can connect to a server * over SSL using an 'ssl://' prefix: * * // 465 is a common smtps port. * $smtp = new Net_SMTP('ssl://mail.host.com', 465); * $smtp->connect(); * * @param string $host The server to connect to. * @param integer $port The port to connect to. * @param string $localhost The value to give when sending EHLO or HELO. * @param boolean $pipeling Use SMTP command pipelining * @param integer $timeout Socket I/O timeout in seconds. * @param array $socket_options Socket stream_context_create() options. * * @access public * @since 1.0 */ function Net_SMTP($host = null, $port = null, $localhost = null, $pipelining = false, $timeout = 0, $socket_options = null) { if (isset($host)) { $this->host = $host; } if (isset($port)) { $this->port = $port; } if (isset($localhost)) { $this->localhost = $localhost; } $this->pipelining = $pipelining; $this->_socket = new Net_Socket(); $this->_socket_options = $socket_options; $this->_timeout = $timeout; /* Include the Auth_SASL package. If the package is available, we * enable the authentication methods that depend upon it. */ if (@include_once 'Auth/SASL.php') { $this->setAuthMethod('CRAM-MD5', array($this, '_authCram_MD5')); $this->setAuthMethod('DIGEST-MD5', array($this, '_authDigest_MD5')); } /* These standard authentication methods are always available. */ $this->setAuthMethod('LOGIN', array($this, '_authLogin'), false); $this->setAuthMethod('PLAIN', array($this, '_authPlain'), false); } /** * Set the socket I/O timeout value in seconds plus microseconds. * * @param integer $seconds Timeout value in seconds. * @param integer $microseconds Additional value in microseconds. * * @access public * @since 1.5.0 */ function setTimeout($seconds, $microseconds = 0) { return $this->_socket->setTimeout($seconds, $microseconds); } /** * Set the value of the debugging flag. * * @param boolean $debug New value for the debugging flag. * * @access public * @since 1.1.0 */ function setDebug($debug, $handler = null) { $this->_debug = $debug; $this->_debug_handler = $handler; } /** * Write the given debug text to the current debug output handler. * * @param string $message Debug mesage text. * * @access private * @since 1.3.3 */ function _debug($message) { if ($this->_debug) { if ($this->_debug_handler) { call_user_func_array($this->_debug_handler, array(&$this, $message)); } else { echo "DEBUG: $message\n"; } } } /** * Send the given string of data to the server. * * @param string $data The string of data to send. * * @return mixed The number of bytes that were actually written, * or a PEAR_Error object on failure. * * @access private * @since 1.1.0 */ function _send($data) { $this->_debug("Send: $data"); $result = $this->_socket->write($data); if (!$result || PEAR::isError($result)) { $msg = ($result) ? $result->getMessage() : "unknown error"; return PEAR::raiseError("Failed to write to socket: $msg", null, PEAR_ERROR_RETURN); } return $result; } /** * Send a command to the server with an optional string of * arguments. A carriage return / linefeed (CRLF) sequence will * be appended to each command string before it is sent to the * SMTP server - an error will be thrown if the command string * already contains any newline characters. Use _send() for * commands that must contain newlines. * * @param string $command The SMTP command to send to the server. * @param string $args A string of optional arguments to append * to the command. * * @return mixed The result of the _send() call. * * @access private * @since 1.1.0 */ function _put($command, $args = '') { if (!empty($args)) { $command .= ' ' . $args; } if (strcspn($command, "\r\n") !== strlen($command)) { return PEAR::raiseError('Commands cannot contain newlines', null, PEAR_ERROR_RETURN); } return $this->_send($command . "\r\n"); } /** * Read a reply from the SMTP server. The reply consists of a response * code and a response message. * * @param mixed $valid The set of valid response codes. These * may be specified as an array of integer * values or as a single integer value. * @param bool $later Do not parse the response now, but wait * until the last command in the pipelined * command group * * @return mixed True if the server returned a valid response code or * a PEAR_Error object is an error condition is reached. * * @access private * @since 1.1.0 * * @see getResponse */ function _parseResponse($valid, $later = false) { $this->_code = -1; $this->_arguments = array(); if ($later) { $this->_pipelined_commands++; return true; } for ($i = 0; $i <= $this->_pipelined_commands; $i++) { while ($line = $this->_socket->readLine()) { $this->_debug("Recv: $line"); /* If we receive an empty line, the connection was closed. */ if (empty($line)) { $this->disconnect(); return PEAR::raiseError('Connection was closed', null, PEAR_ERROR_RETURN); } /* Read the code and store the rest in the arguments array. */ $code = substr($line, 0, 3); $this->_arguments[] = trim(substr($line, 4)); /* Check the syntax of the response code. */ if (is_numeric($code)) { $this->_code = (int)$code; } else { $this->_code = -1; break; } /* If this is not a multiline response, we're done. */ if (substr($line, 3, 1) != '-') { break; } } } $this->_pipelined_commands = 0; /* Compare the server's response code with the valid code/codes. */ if (is_int($valid) && ($this->_code === $valid)) { return true; } elseif (is_array($valid) && in_array($this->_code, $valid, true)) { return true; } return PEAR::raiseError('Invalid response code received from server', $this->_code, PEAR_ERROR_RETURN); } /** * Issue an SMTP command and verify its response. * * @param string $command The SMTP command string or data. * @param mixed $valid The set of valid response codes. These * may be specified as an array of integer * values or as a single integer value. * * @return mixed True on success or a PEAR_Error object on failure. * * @access public * @since 1.6.0 */ function command($command, $valid) { if (PEAR::isError($error = $this->_put($command))) { return $error; } if (PEAR::isError($error = $this->_parseResponse($valid))) { return $error; } return true; } /** * Return a 2-tuple containing the last response from the SMTP server. * * @return array A two-element array: the first element contains the * response code as an integer and the second element * contains the response's arguments as a string. * * @access public * @since 1.1.0 */ function getResponse() { return array($this->_code, join("\n", $this->_arguments)); } /** * Return the SMTP server's greeting string. * * @return string A string containing the greeting string, or null if a * greeting has not been received. * * @access public * @since 1.3.3 */ function getGreeting() { return $this->_greeting; } /** * Attempt to connect to the SMTP server. * * @param int $timeout The timeout value (in seconds) for the * socket connection attempt. * @param bool $persistent Should a persistent socket connection * be used? * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function connect($timeout = null, $persistent = false) { $this->_greeting = null; $result = $this->_socket->connect($this->host, $this->port, $persistent, $timeout, $this->_socket_options); if (PEAR::isError($result)) { return PEAR::raiseError('Failed to connect socket: ' . $result->getMessage()); } /* * Now that we're connected, reset the socket's timeout value for * future I/O operations. This allows us to have different socket * timeout values for the initial connection (our $timeout parameter) * and all other socket operations. */ if ($this->_timeout > 0) { if (PEAR::isError($error = $this->setTimeout($this->_timeout))) { return $error; } } if (PEAR::isError($error = $this->_parseResponse(220))) { return $error; } /* Extract and store a copy of the server's greeting string. */ list(, $this->_greeting) = $this->getResponse(); if (PEAR::isError($error = $this->_negotiate())) { return $error; } return true; } /** * Attempt to disconnect from the SMTP server. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function disconnect() { if (PEAR::isError($error = $this->_put('QUIT'))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(221))) { return $error; } if (PEAR::isError($error = $this->_socket->disconnect())) { return PEAR::raiseError('Failed to disconnect socket: ' . $error->getMessage()); } return true; } /** * Attempt to send the EHLO command and obtain a list of ESMTP * extensions available, and failing that just send HELO. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * * @access private * @since 1.1.0 */ function _negotiate() { if (PEAR::isError($error = $this->_put('EHLO', $this->localhost))) { return $error; } if (PEAR::isError($this->_parseResponse(250))) { /* If the EHLO failed, try the simpler HELO command. */ if (PEAR::isError($error = $this->_put('HELO', $this->localhost))) { return $error; } if (PEAR::isError($this->_parseResponse(250))) { return PEAR::raiseError('HELO was not accepted: ', $this->_code, PEAR_ERROR_RETURN); } return true; } foreach ($this->_arguments as $argument) { $verb = strtok($argument, ' '); $arguments = substr($argument, strlen($verb) + 1, strlen($argument) - strlen($verb) - 1); $this->_esmtp[$verb] = $arguments; } if (!isset($this->_esmtp['PIPELINING'])) { $this->pipelining = false; } return true; } /** * Returns the name of the best authentication method that the server * has advertised. * * @return mixed Returns a string containing the name of the best * supported authentication method or a PEAR_Error object * if a failure condition is encountered. * @access private * @since 1.1.0 */ function _getBestAuthMethod() { $available_methods = explode(' ', $this->_esmtp['AUTH']); foreach ($this->auth_methods as $method => $callback) { if (in_array($method, $available_methods)) { return $method; } } return PEAR::raiseError('No supported authentication methods', null, PEAR_ERROR_RETURN); } /** * Attempt to do SMTP authentication. * * @param string The userid to authenticate as. * @param string The password to authenticate with. * @param string The requested authentication method. If none is * specified, the best supported method will be used. * @param bool Flag indicating whether or not TLS should be attempted. * @param string An optional authorization identifier. If specified, this * identifier will be used as the authorization proxy. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function auth($uid, $pwd , $method = '', $tls = true, $authz = '') { /* We can only attempt a TLS connection if one has been requested, * we're running PHP 5.1.0 or later, have access to the OpenSSL * extension, are connected to an SMTP server which supports the * STARTTLS extension, and aren't already connected over a secure * (SSL) socket connection. */ if ($tls && version_compare(PHP_VERSION, '5.1.0', '>=') && extension_loaded('openssl') && isset($this->_esmtp['STARTTLS']) && strncasecmp($this->host, 'ssl://', 6) !== 0) { /* Start the TLS connection attempt. */ if (PEAR::isError($result = $this->_put('STARTTLS'))) { return $result; } if (PEAR::isError($result = $this->_parseResponse(220))) { return $result; } if (PEAR::isError($result = $this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT))) { return $result; } elseif ($result !== true) { return PEAR::raiseError('STARTTLS failed'); } /* Send EHLO again to recieve the AUTH string from the * SMTP server. */ $this->_negotiate(); } if (empty($this->_esmtp['AUTH'])) { return PEAR::raiseError('SMTP server does not support authentication'); } /* If no method has been specified, get the name of the best * supported method advertised by the SMTP server. */ if (empty($method)) { if (PEAR::isError($method = $this->_getBestAuthMethod())) { /* Return the PEAR_Error object from _getBestAuthMethod(). */ return $method; } } else { $method = strtoupper($method); if (!array_key_exists($method, $this->auth_methods)) { return PEAR::raiseError("$method is not a supported authentication method"); } } if (!isset($this->auth_methods[$method])) { return PEAR::raiseError("$method is not a supported authentication method"); } if (!is_callable($this->auth_methods[$method], false)) { return PEAR::raiseError("$method authentication method cannot be called"); } if (is_array($this->auth_methods[$method])) { list($object, $method) = $this->auth_methods[$method]; $result = $object->{$method}($uid, $pwd, $authz, $this); } else { $func = $this->auth_methods[$method]; $result = $func($uid, $pwd, $authz, $this); } /* If an error was encountered, return the PEAR_Error object. */ if (PEAR::isError($result)) { return $result; } return true; } /** * Add a new authentication method. * * @param string The authentication method name (e.g. 'PLAIN') * @param mixed The authentication callback (given as the name of a * function or as an (object, method name) array). * @param bool Should the new method be prepended to the list of * available methods? This is the default behavior, * giving the new method the highest priority. * * @return mixed True on success or a PEAR_Error object on failure. * * @access public * @since 1.6.0 */ function setAuthMethod($name, $callback, $prepend = true) { if (!is_string($name)) { return PEAR::raiseError('Method name is not a string'); } if (!is_string($callback) && !is_array($callback)) { return PEAR::raiseError('Method callback must be string or array'); } if (is_array($callback)) { if (!is_object($callback[0]) || !is_string($callback[1])) return PEAR::raiseError('Bad mMethod callback array'); } if ($prepend) { $this->auth_methods = array_merge(array($name => $callback), $this->auth_methods); } else { $this->auth_methods[$name] = $callback; } return true; } /** * Authenticates the user using the DIGEST-MD5 method. * * @param string The userid to authenticate as. * @param string The password to authenticate with. * @param string The optional authorization proxy identifier. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access private * @since 1.1.0 */ function _authDigest_MD5($uid, $pwd, $authz = '') { if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) { return $error; } /* 334: Continue authentication request */ if (PEAR::isError($error = $this->_parseResponse(334))) { /* 503: Error: already authenticated */ if ($this->_code === 503) { return true; } return $error; } $challenge = base64_decode($this->_arguments[0]); $digest = &Auth_SASL::factory('digest-md5'); $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, $this->host, "smtp", $authz)); if (PEAR::isError($error = $this->_put($auth_str))) { return $error; } /* 334: Continue authentication request */ if (PEAR::isError($error = $this->_parseResponse(334))) { return $error; } /* We don't use the protocol's third step because SMTP doesn't * allow subsequent authentication, so we just silently ignore * it. */ if (PEAR::isError($error = $this->_put(''))) { return $error; } /* 235: Authentication successful */ if (PEAR::isError($error = $this->_parseResponse(235))) { return $error; } } /** * Authenticates the user using the CRAM-MD5 method. * * @param string The userid to authenticate as. * @param string The password to authenticate with. * @param string The optional authorization proxy identifier. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access private * @since 1.1.0 */ function _authCRAM_MD5($uid, $pwd, $authz = '') { if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) { return $error; } /* 334: Continue authentication request */ if (PEAR::isError($error = $this->_parseResponse(334))) { /* 503: Error: already authenticated */ if ($this->_code === 503) { return true; } return $error; } $challenge = base64_decode($this->_arguments[0]); $cram = &Auth_SASL::factory('cram-md5'); $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge)); if (PEAR::isError($error = $this->_put($auth_str))) { return $error; } /* 235: Authentication successful */ if (PEAR::isError($error = $this->_parseResponse(235))) { return $error; } } /** * Authenticates the user using the LOGIN method. * * @param string The userid to authenticate as. * @param string The password to authenticate with. * @param string The optional authorization proxy identifier. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access private * @since 1.1.0 */ function _authLogin($uid, $pwd, $authz = '') { if (PEAR::isError($error = $this->_put('AUTH', 'LOGIN'))) { return $error; } /* 334: Continue authentication request */ if (PEAR::isError($error = $this->_parseResponse(334))) { /* 503: Error: already authenticated */ if ($this->_code === 503) { return true; } return $error; } if (PEAR::isError($error = $this->_put(base64_encode($uid)))) { return $error; } /* 334: Continue authentication request */ if (PEAR::isError($error = $this->_parseResponse(334))) { return $error; } if (PEAR::isError($error = $this->_put(base64_encode($pwd)))) { return $error; } /* 235: Authentication successful */ if (PEAR::isError($error = $this->_parseResponse(235))) { return $error; } return true; } /** * Authenticates the user using the PLAIN method. * * @param string The userid to authenticate as. * @param string The password to authenticate with. * @param string The optional authorization proxy identifier. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access private * @since 1.1.0 */ function _authPlain($uid, $pwd, $authz = '') { if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) { return $error; } /* 334: Continue authentication request */ if (PEAR::isError($error = $this->_parseResponse(334))) { /* 503: Error: already authenticated */ if ($this->_code === 503) { return true; } return $error; } $auth_str = base64_encode($authz . chr(0) . $uid . chr(0) . $pwd); if (PEAR::isError($error = $this->_put($auth_str))) { return $error; } /* 235: Authentication successful */ if (PEAR::isError($error = $this->_parseResponse(235))) { return $error; } return true; } /** * Send the HELO command. * * @param string The domain name to say we are. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function helo($domain) { if (PEAR::isError($error = $this->_put('HELO', $domain))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(250))) { return $error; } return true; } /** * Return the list of SMTP service extensions advertised by the server. * * @return array The list of SMTP service extensions. * @access public * @since 1.3 */ function getServiceExtensions() { return $this->_esmtp; } /** * Send the MAIL FROM: command. * * @param string $sender The sender (reverse path) to set. * @param string $params String containing additional MAIL parameters, * such as the NOTIFY flags defined by RFC 1891 * or the VERP protocol. * * If $params is an array, only the 'verp' option * is supported. If 'verp' is true, the XVERP * parameter is appended to the MAIL command. If * the 'verp' value is a string, the full * XVERP=value parameter is appended. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function mailFrom($sender, $params = null) { $args = "FROM:<$sender>"; /* Support the deprecated array form of $params. */ if (is_array($params) && isset($params['verp'])) { /* XVERP */ if ($params['verp'] === true) { $args .= ' XVERP'; /* XVERP=something */ } elseif (trim($params['verp'])) { $args .= ' XVERP=' . $params['verp']; } } elseif (is_string($params) && !empty($params)) { $args .= ' ' . $params; } if (PEAR::isError($error = $this->_put('MAIL', $args))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } return true; } /** * Send the RCPT TO: command. * * @param string $recipient The recipient (forward path) to add. * @param string $params String containing additional RCPT parameters, * such as the NOTIFY flags defined by RFC 1891. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * * @access public * @since 1.0 */ function rcptTo($recipient, $params = null) { $args = "TO:<$recipient>"; if (is_string($params)) { $args .= ' ' . $params; } if (PEAR::isError($error = $this->_put('RCPT', $args))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(array(250, 251), $this->pipelining))) { return $error; } return true; } /** * Quote the data so that it meets SMTP standards. * * This is provided as a separate public function to facilitate * easier overloading for the cases where it is desirable to * customize the quoting behavior. * * @param string $data The message text to quote. The string must be passed * by reference, and the text will be modified in place. * * @access public * @since 1.2 */ function quotedata(&$data) { /* Because a single leading period (.) signifies an end to the * data, legitimate leading periods need to be "doubled" ('..'). */ $data = preg_replace('/^\./m', '..', $data); /* Change Unix (\n) and Mac (\r) linefeeds into CRLF's (\r\n). */ $data = preg_replace('/(?:\r\n|\n|\r(?!\n))/', "\r\n", $data); } /** * Send the DATA command. * * @param mixed $data The message data, either as a string or an open * file resource. * @param string $headers The message headers. If $headers is provided, * $data is assumed to contain only body data. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function data($data, $headers = null) { /* Verify that $data is a supported type. */ if (!is_string($data) && !is_resource($data)) { return PEAR::raiseError('Expected a string or file resource'); } /* Start by considering the size of the optional headers string. We * also account for the addition 4 character "\r\n\r\n" separator * sequence. */ $size = (is_null($headers)) ? 0 : strlen($headers) + 4; if (is_resource($data)) { $stat = fstat($data); if ($stat === false) { return PEAR::raiseError('Failed to get file size'); } $size += $stat['size']; } else { $size += strlen($data); } /* RFC 1870, section 3, subsection 3 states "a value of zero indicates * that no fixed maximum message size is in force". Furthermore, it * says that if "the parameter is omitted no information is conveyed * about the server's fixed maximum message size". */ $limit = (isset($this->_esmtp['SIZE'])) ? $this->_esmtp['SIZE'] : 0; if ($limit > 0 && $size >= $limit) { $this->disconnect(); return PEAR::raiseError('Message size exceeds server limit'); } /* Initiate the DATA command. */ if (PEAR::isError($error = $this->_put('DATA'))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(354))) { return $error; } /* If we have a separate headers string, send it first. */ if (!is_null($headers)) { $this->quotedata($headers); if (PEAR::isError($result = $this->_send($headers . "\r\n\r\n"))) { return $result; } } /* Now we can send the message body data. */ if (is_resource($data)) { /* Stream the contents of the file resource out over our socket * connection, line by line. Each line must be run through the * quoting routine. */ while (strlen($line = fread($data, 8192)) > 0) { /* If the last character is an newline, we need to grab the * next character to check to see if it is a period. */ while (!feof($data)) { $char = fread($data, 1); $line .= $char; if ($char != "\n") { break; } } $this->quotedata($line); if (PEAR::isError($result = $this->_send($line))) { return $result; } } $last = $line; } else { /* * Break up the data by sending one chunk (up to 512k) at a time. * This approach reduces our peak memory usage. */ for ($offset = 0; $offset < $size;) { $end = $offset + 512000; /* * Ensure we don't read beyond our data size or span multiple * lines. quotedata() can't properly handle character data * that's split across two line break boundaries. */ if ($end >= $size) { $end = $size; } else { for (; $end < $size; $end++) { if ($data[$end] != "\n") { break; } } } /* Extract our chunk and run it through the quoting routine. */ $chunk = substr($data, $offset, $end - $offset); $this->quotedata($chunk); /* If we run into a problem along the way, abort. */ if (PEAR::isError($result = $this->_send($chunk))) { return $result; } /* Advance the offset to the end of this chunk. */ $offset = $end; } $last = $chunk; } /* Don't add another CRLF sequence if it's already in the data */ $terminator = (substr($last, -2) == "\r\n" ? '' : "\r\n") . ".\r\n"; /* Finally, send the DATA terminator sequence. */ if (PEAR::isError($result = $this->_send($terminator))) { return $result; } /* Verify that the data was successfully received by the server. */ if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } return true; } /** * Send the SEND FROM: command. * * @param string The reverse path to send. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.2.6 */ function sendFrom($path) { if (PEAR::isError($error = $this->_put('SEND', "FROM:<$path>"))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } return true; } /** * Backwards-compatibility wrapper for sendFrom(). * * @param string The reverse path to send. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * * @access public * @since 1.0 * @deprecated 1.2.6 */ function send_from($path) { return sendFrom($path); } /** * Send the SOML FROM: command. * * @param string The reverse path to send. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.2.6 */ function somlFrom($path) { if (PEAR::isError($error = $this->_put('SOML', "FROM:<$path>"))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } return true; } /** * Backwards-compatibility wrapper for somlFrom(). * * @param string The reverse path to send. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * * @access public * @since 1.0 * @deprecated 1.2.6 */ function soml_from($path) { return somlFrom($path); } /** * Send the SAML FROM: command. * * @param string The reverse path to send. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.2.6 */ function samlFrom($path) { if (PEAR::isError($error = $this->_put('SAML', "FROM:<$path>"))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } return true; } /** * Backwards-compatibility wrapper for samlFrom(). * * @param string The reverse path to send. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * * @access public * @since 1.0 * @deprecated 1.2.6 */ function saml_from($path) { return samlFrom($path); } /** * Send the RSET command. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function rset() { if (PEAR::isError($error = $this->_put('RSET'))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { return $error; } return true; } /** * Send the VRFY command. * * @param string The string to verify * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function vrfy($string) { /* Note: 251 is also a valid response code */ if (PEAR::isError($error = $this->_put('VRFY', $string))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(array(250, 252)))) { return $error; } return true; } /** * Send the NOOP command. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function noop() { if (PEAR::isError($error = $this->_put('NOOP'))) { return $error; } if (PEAR::isError($error = $this->_parseResponse(250))) { return $error; } return true; } /** * Backwards-compatibility method. identifySender()'s functionality is * now handled internally. * * @return boolean This method always return true. * * @access public * @since 1.0 */ function identifySender() { return true; } } PK!6zNNNet/Socket.phpnu[ * Chuck Hagenbuch * * @category Net * @package Net_Socket * @author Stig Bakken * @author Chuck Hagenbuch * @copyright 1997-2003 The PHP Group * @license http://www.php.net/license/2_02.txt PHP 2.02 * @link http://pear.php.net/packages/Net_Socket */ require_once 'PEAR.php'; define('NET_SOCKET_READ', 1); define('NET_SOCKET_WRITE', 2); define('NET_SOCKET_ERROR', 4); /** * Generalized Socket class. * * @category Net * @package Net_Socket * @author Stig Bakken * @author Chuck Hagenbuch * @copyright 1997-2003 The PHP Group * @license http://www.php.net/license/2_02.txt PHP 2.02 * @link http://pear.php.net/packages/Net_Socket */ class Net_Socket extends PEAR { /** * Socket file pointer. * @var resource $fp */ var $fp = null; /** * Whether the socket is blocking. Defaults to true. * @var boolean $blocking */ var $blocking = true; /** * Whether the socket is persistent. Defaults to false. * @var boolean $persistent */ var $persistent = false; /** * The IP address to connect to. * @var string $addr */ var $addr = ''; /** * The port number to connect to. * @var integer $port */ var $port = 0; /** * Number of seconds to wait on socket operations before assuming * there's no more data. Defaults to no timeout. * @var integer|float $timeout */ var $timeout = null; /** * Number of bytes to read at a time in readLine() and * readAll(). Defaults to 2048. * @var integer $lineLength */ var $lineLength = 2048; /** * The string to use as a newline terminator. Usually "\r\n" or "\n". * @var string $newline */ var $newline = "\r\n"; /** * Connect to the specified port. If called when the socket is * already connected, it disconnects and connects again. * * @param string $addr IP address or host name (may be with protocol prefix). * @param integer $port TCP port number. * @param boolean $persistent (optional) Whether the connection is * persistent (kept open between requests * by the web server). * @param integer $timeout (optional) Connection socket timeout. * @param array $options See options for stream_context_create. * * @access public * * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. */ function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null) { if (is_resource($this->fp)) { @fclose($this->fp); $this->fp = null; } if (!$addr) { return $this->raiseError('$addr cannot be empty'); } else if (strspn($addr, ':.0123456789') == strlen($addr)) { $this->addr = strpos($addr, ':') !== false ? '['.$addr.']' : $addr; } else { $this->addr = $addr; } $this->port = $port % 65536; if ($persistent !== null) { $this->persistent = $persistent; } $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen'; $errno = 0; $errstr = ''; $old_track_errors = @ini_set('track_errors', 1); if ($timeout <= 0) { $timeout = @ini_get('default_socket_timeout'); } if ($options && function_exists('stream_context_create')) { $context = stream_context_create($options); // Since PHP 5 fsockopen doesn't allow context specification if (function_exists('stream_socket_client')) { $flags = STREAM_CLIENT_CONNECT; if ($this->persistent) { $flags = STREAM_CLIENT_PERSISTENT; } $addr = $this->addr . ':' . $this->port; $fp = stream_socket_client($addr, $errno, $errstr, $timeout, $flags, $context); } else { $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context); } } else { $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout); } if (!$fp) { if ($errno == 0 && !strlen($errstr) && isset($php_errormsg)) { $errstr = $php_errormsg; } @ini_set('track_errors', $old_track_errors); return $this->raiseError($errstr, $errno); } @ini_set('track_errors', $old_track_errors); $this->fp = $fp; $this->setTimeout(); return $this->setBlocking($this->blocking); } /** * Disconnects from the peer, closes the socket. * * @access public * @return mixed true on success or a PEAR_Error instance otherwise */ function disconnect() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } @fclose($this->fp); $this->fp = null; return true; } /** * Set the newline character/sequence to use. * * @param string $newline Newline character(s) * @return boolean True */ function setNewline($newline) { $this->newline = $newline; return true; } /** * Find out if the socket is in blocking mode. * * @access public * @return boolean The current blocking mode. */ function isBlocking() { return $this->blocking; } /** * Sets whether the socket connection should be blocking or * not. A read call to a non-blocking socket will return immediately * if there is no data available, whereas it will block until there * is data for blocking sockets. * * @param boolean $mode True for blocking sockets, false for nonblocking. * * @access public * @return mixed true on success or a PEAR_Error instance otherwise */ function setBlocking($mode) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $this->blocking = $mode; stream_set_blocking($this->fp, (int)$this->blocking); return true; } /** * Sets the timeout value on socket descriptor, * expressed in the sum of seconds and microseconds * * @param integer $seconds Seconds. * @param integer $microseconds Microseconds, optional. * * @access public * @return mixed True on success or false on failure or * a PEAR_Error instance when not connected */ function setTimeout($seconds = null, $microseconds = null) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } if ($seconds === null && $microseconds === null) { $seconds = (int) $this->timeout; $microseconds = (int) (($this->timeout - $seconds) * 1000000); } else { $this->timeout = $seconds + $microseconds/1000000; } if ($this->timeout > 0) { return stream_set_timeout($this->fp, (int) $seconds, (int) $microseconds); } else { return false; } } /** * Sets the file buffering size on the stream. * See php's stream_set_write_buffer for more information. * * @param integer $size Write buffer size. * * @access public * @return mixed on success or an PEAR_Error object otherwise */ function setWriteBuffer($size) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $returned = stream_set_write_buffer($this->fp, $size); if ($returned == 0) { return true; } return $this->raiseError('Cannot set write buffer.'); } /** * Returns information about an existing socket resource. * Currently returns four entries in the result array: * *

* timed_out (bool) - The socket timed out waiting for data
* blocked (bool) - The socket was blocked
* eof (bool) - Indicates EOF event
* unread_bytes (int) - Number of bytes left in the socket buffer
*

* * @access public * @return mixed Array containing information about existing socket * resource or a PEAR_Error instance otherwise */ function getStatus() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return stream_get_meta_data($this->fp); } /** * Get a specified line of data * * @param int $size Reading ends when size - 1 bytes have been read, * or a newline or an EOF (whichever comes first). * If no size is specified, it will keep reading from * the stream until it reaches the end of the line. * * @access public * @return mixed $size bytes of data from the socket, or a PEAR_Error if * not connected. If an error occurs, FALSE is returned. */ function gets($size = null) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } if (is_null($size)) { return @fgets($this->fp); } else { return @fgets($this->fp, $size); } } /** * Read a specified amount of data. This is guaranteed to return, * and has the added benefit of getting everything in one fread() * chunk; if you know the size of the data you're getting * beforehand, this is definitely the way to go. * * @param integer $size The number of bytes to read from the socket. * * @access public * @return $size bytes of data from the socket, or a PEAR_Error if * not connected. */ function read($size) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return @fread($this->fp, $size); } /** * Write a specified amount of data. * * @param string $data Data to write. * @param integer $blocksize Amount of data to write at once. * NULL means all at once. * * @access public * @return mixed If the socket is not connected, returns an instance of * PEAR_Error. * If the write succeeds, returns the number of bytes written. * If the write fails, returns false. * If the socket times out, returns an instance of PEAR_Error. */ function write($data, $blocksize = null) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } if (is_null($blocksize) && !OS_WINDOWS) { $written = @fwrite($this->fp, $data); // Check for timeout or lost connection if (!$written) { $meta_data = $this->getStatus(); if (!is_array($meta_data)) { return $meta_data; // PEAR_Error } if (!empty($meta_data['timed_out'])) { return $this->raiseError('timed out'); } } return $written; } else { if (is_null($blocksize)) { $blocksize = 1024; } $pos = 0; $size = strlen($data); while ($pos < $size) { $written = @fwrite($this->fp, substr($data, $pos, $blocksize)); // Check for timeout or lost connection if (!$written) { $meta_data = $this->getStatus(); if (!is_array($meta_data)) { return $meta_data; // PEAR_Error } if (!empty($meta_data['timed_out'])) { return $this->raiseError('timed out'); } return $written; } $pos += $written; } return $pos; } } /** * Write a line of data to the socket, followed by a trailing newline. * * @param string $data Data to write * * @access public * @return mixed fwrite() result, or PEAR_Error when not connected */ function writeLine($data) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return fwrite($this->fp, $data . $this->newline); } /** * Tests for end-of-file on a socket descriptor. * * Also returns true if the socket is disconnected. * * @access public * @return bool */ function eof() { return (!is_resource($this->fp) || feof($this->fp)); } /** * Reads a byte of data * * @access public * @return 1 byte of data from the socket, or a PEAR_Error if * not connected. */ function readByte() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return ord(@fread($this->fp, 1)); } /** * Reads a word of data * * @access public * @return 1 word of data from the socket, or a PEAR_Error if * not connected. */ function readWord() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $buf = @fread($this->fp, 2); return (ord($buf[0]) + (ord($buf[1]) << 8)); } /** * Reads an int of data * * @access public * @return integer 1 int of data from the socket, or a PEAR_Error if * not connected. */ function readInt() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $buf = @fread($this->fp, 4); return (ord($buf[0]) + (ord($buf[1]) << 8) + (ord($buf[2]) << 16) + (ord($buf[3]) << 24)); } /** * Reads a zero-terminated string of data * * @access public * @return string, or a PEAR_Error if * not connected. */ function readString() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $string = ''; while (($char = @fread($this->fp, 1)) != "\x00") { $string .= $char; } return $string; } /** * Reads an IP Address and returns it in a dot formatted string * * @access public * @return Dot formatted string, or a PEAR_Error if * not connected. */ function readIPAddress() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $buf = @fread($this->fp, 4); return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]), ord($buf[2]), ord($buf[3])); } /** * Read until either the end of the socket or a newline, whichever * comes first. Strips the trailing newline from the returned data. * * @access public * @return All available data up to a newline, without that * newline, or until the end of the socket, or a PEAR_Error if * not connected. */ function readLine() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $line = ''; $timeout = time() + $this->timeout; while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) { $line .= @fgets($this->fp, $this->lineLength); if (substr($line, -1) == "\n") { return rtrim($line, $this->newline); } } return $line; } /** * Read until the socket closes, or until there is no more data in * the inner PHP buffer. If the inner buffer is empty, in blocking * mode we wait for at least 1 byte of data. Therefore, in * blocking mode, if there is no data at all to be read, this * function will never exit (unless the socket is closed on the * remote end). * * @access public * * @return string All data until the socket closes, or a PEAR_Error if * not connected. */ function readAll() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $data = ''; while (!feof($this->fp)) { $data .= @fread($this->fp, $this->lineLength); } return $data; } /** * Runs the equivalent of the select() system call on the socket * with a timeout specified by tv_sec and tv_usec. * * @param integer $state Which of read/write/error to check for. * @param integer $tv_sec Number of seconds for timeout. * @param integer $tv_usec Number of microseconds for timeout. * * @access public * @return False if select fails, integer describing which of read/write/error * are ready, or PEAR_Error if not connected. */ function select($state, $tv_sec, $tv_usec = 0) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $read = null; $write = null; $except = null; if ($state & NET_SOCKET_READ) { $read[] = $this->fp; } if ($state & NET_SOCKET_WRITE) { $write[] = $this->fp; } if ($state & NET_SOCKET_ERROR) { $except[] = $this->fp; } if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) { return false; } $result = 0; if (count($read)) { $result |= NET_SOCKET_READ; } if (count($write)) { $result |= NET_SOCKET_WRITE; } if (count($except)) { $result |= NET_SOCKET_ERROR; } return $result; } /** * Turns encryption on/off on a connected socket. * * @param bool $enabled Set this parameter to true to enable encryption * and false to disable encryption. * @param integer $type Type of encryption. See stream_socket_enable_crypto() * for values. * * @see http://se.php.net/manual/en/function.stream-socket-enable-crypto.php * @access public * @return false on error, true on success and 0 if there isn't enough data * and the user should try again (non-blocking sockets only). * A PEAR_Error object is returned if the socket is not * connected */ function enableCrypto($enabled, $type) { if (version_compare(phpversion(), "5.1.0", ">=")) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return @stream_socket_enable_crypto($this->fp, $enabled, $type); } else { $msg = 'Net_Socket::enableCrypto() requires php version >= 5.1.0'; return $this->raiseError($msg); } } } PK!=YYArchive/Tar.phpnu[ * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @category File_Formats * @package Archive_Tar * @author Vincent Blavet * @copyright 1997-2010 The Authors * @license http://www.opensource.org/licenses/bsd-license.php New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/Archive_Tar */ // If the PEAR class cannot be loaded via the autoloader, // then try to require_once it from the PHP include path. if (!class_exists('PEAR')) { require_once 'PEAR.php'; } define('ARCHIVE_TAR_ATT_SEPARATOR', 90001); define('ARCHIVE_TAR_END_BLOCK', pack("a512", '')); if (!function_exists('gzopen') && function_exists('gzopen64')) { function gzopen($filename, $mode, $use_include_path = 0) { return gzopen64($filename, $mode, $use_include_path); } } if (!function_exists('gztell') && function_exists('gztell64')) { function gztell($zp) { return gztell64($zp); } } if (!function_exists('gzseek') && function_exists('gzseek64')) { function gzseek($zp, $offset, $whence = SEEK_SET) { return gzseek64($zp, $offset, $whence); } } /** * Creates a (compressed) Tar archive * * @package Archive_Tar * @author Vincent Blavet * @license http://www.opensource.org/licenses/bsd-license.php New BSD License * @version $Revision$ */ class Archive_Tar extends PEAR { /** * @var string Name of the Tar */ public $_tarname = ''; /** * @var boolean if true, the Tar file will be gzipped */ public $_compress = false; /** * @var string Type of compression : 'none', 'gz', 'bz2' or 'lzma2' */ public $_compress_type = 'none'; /** * @var string Explode separator */ public $_separator = ' '; /** * @var file descriptor */ public $_file = 0; /** * @var string Local Tar name of a remote Tar (http:// or ftp://) */ public $_temp_tarname = ''; /** * @var string regular expression for ignoring files or directories */ public $_ignore_regexp = ''; /** * @var object PEAR_Error object */ public $error_object = null; /** * Format for data extraction * * @var string */ public $_fmt = ''; /** * @var int Length of the read buffer in bytes */ protected $buffer_length; /** * Archive_Tar Class constructor. This flavour of the constructor only * declare a new Archive_Tar object, identifying it by the name of the * tar file. * If the compress argument is set the tar will be read or created as a * gzip or bz2 compressed TAR file. * * @param string $p_tarname The name of the tar archive to create * @param string $p_compress can be null, 'gz', 'bz2' or 'lzma2'. This * parameter indicates if gzip, bz2 or lzma2 compression * is required. For compatibility reason the * boolean value 'true' means 'gz'. * @param int $buffer_length Length of the read buffer in bytes * * @return bool */ public function __construct($p_tarname, $p_compress = null, $buffer_length = 512) { parent::__construct(); $this->_compress = false; $this->_compress_type = 'none'; if (($p_compress === null) || ($p_compress == '')) { if (@file_exists($p_tarname)) { if ($fp = @fopen($p_tarname, "rb")) { // look for gzip magic cookie $data = fread($fp, 2); fclose($fp); if ($data == "\37\213") { $this->_compress = true; $this->_compress_type = 'gz'; // No sure it's enought for a magic code .... } elseif ($data == "BZ") { $this->_compress = true; $this->_compress_type = 'bz2'; } elseif (file_get_contents($p_tarname, false, null, 1, 4) == '7zXZ') { $this->_compress = true; $this->_compress_type = 'lzma2'; } } } else { // probably a remote file or some file accessible // through a stream interface if (substr($p_tarname, -2) == 'gz') { $this->_compress = true; $this->_compress_type = 'gz'; } elseif ((substr($p_tarname, -3) == 'bz2') || (substr($p_tarname, -2) == 'bz') ) { $this->_compress = true; $this->_compress_type = 'bz2'; } else { if (substr($p_tarname, -2) == 'xz') { $this->_compress = true; $this->_compress_type = 'lzma2'; } } } } else { if (($p_compress === true) || ($p_compress == 'gz')) { $this->_compress = true; $this->_compress_type = 'gz'; } else { if ($p_compress == 'bz2') { $this->_compress = true; $this->_compress_type = 'bz2'; } else { if ($p_compress == 'lzma2') { $this->_compress = true; $this->_compress_type = 'lzma2'; } else { $this->_error( "Unsupported compression type '$p_compress'\n" . "Supported types are 'gz', 'bz2' and 'lzma2'.\n" ); return false; } } } } $this->_tarname = $p_tarname; if ($this->_compress) { // assert zlib or bz2 or xz extension support if ($this->_compress_type == 'gz') { $extname = 'zlib'; } else { if ($this->_compress_type == 'bz2') { $extname = 'bz2'; } else { if ($this->_compress_type == 'lzma2') { $extname = 'xz'; } } } if (!extension_loaded($extname)) { PEAR::loadExtension($extname); } if (!extension_loaded($extname)) { $this->_error( "The extension '$extname' couldn't be found.\n" . "Please make sure your version of PHP was built " . "with '$extname' support.\n" ); return false; } } if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) { $this->_fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" . "a8checksum/a1typeflag/a100link/a6magic/a2version/" . "a32uname/a32gname/a8devmajor/a8devminor/a131prefix"; } else { $this->_fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" . "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" . "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix"; } $this->buffer_length = $buffer_length; } public function __destruct() { $this->_close(); // ----- Look for a local copy to delete if ($this->_temp_tarname != '' && (bool) preg_match('/^tar[[:alnum:]]*\.tmp$/', $this->_temp_tarname)) { @unlink($this->_temp_tarname); } } /** * This method creates the archive file and add the files / directories * that are listed in $p_filelist. * If a file with the same name exist and is writable, it is replaced * by the new tar. * The method return false and a PEAR error text. * The $p_filelist parameter can be an array of string, each string * representing a filename or a directory name with their path if * needed. It can also be a single string with names separated by a * single blank. * For each directory added in the archive, the files and * sub-directories are also added. * See also createModify() method for more details. * * @param array $p_filelist An array of filenames and directory names, or a * single string with names separated by a single * blank space. * * @return true on success, false on error. * @see createModify() */ public function create($p_filelist) { return $this->createModify($p_filelist, '', ''); } /** * This method add the files / directories that are listed in $p_filelist in * the archive. If the archive does not exist it is created. * The method return false and a PEAR error text. * The files and directories listed are only added at the end of the archive, * even if a file with the same name is already archived. * See also createModify() method for more details. * * @param array $p_filelist An array of filenames and directory names, or a * single string with names separated by a single * blank space. * * @return true on success, false on error. * @see createModify() * @access public */ public function add($p_filelist) { return $this->addModify($p_filelist, '', ''); } /** * @param string $p_path * @param bool $p_preserve * @param bool $p_symlinks * @return bool */ public function extract($p_path = '', $p_preserve = false, $p_symlinks = true) { return $this->extractModify($p_path, '', $p_preserve, $p_symlinks); } /** * @return array|int */ public function listContent() { $v_list_detail = array(); if ($this->_openRead()) { if (!$this->_extractList('', $v_list_detail, "list", '', '')) { unset($v_list_detail); $v_list_detail = 0; } $this->_close(); } return $v_list_detail; } /** * This method creates the archive file and add the files / directories * that are listed in $p_filelist. * If the file already exists and is writable, it is replaced by the * new tar. It is a create and not an add. If the file exists and is * read-only or is a directory it is not replaced. The method return * false and a PEAR error text. * The $p_filelist parameter can be an array of string, each string * representing a filename or a directory name with their path if * needed. It can also be a single string with names separated by a * single blank. * The path indicated in $p_remove_dir will be removed from the * memorized path of each file / directory listed when this path * exists. By default nothing is removed (empty path '') * The path indicated in $p_add_dir will be added at the beginning of * the memorized path of each file / directory listed. However it can * be set to empty ''. The adding of a path is done after the removing * of path. * The path add/remove ability enables the user to prepare an archive * for extraction in a different path than the origin files are. * See also addModify() method for file adding properties. * * @param array $p_filelist An array of filenames and directory names, * or a single string with names separated by * a single blank space. * @param string $p_add_dir A string which contains a path to be added * to the memorized path of each element in * the list. * @param string $p_remove_dir A string which contains a path to be * removed from the memorized path of each * element in the list, when relevant. * * @return boolean true on success, false on error. * @see addModify() */ public function createModify($p_filelist, $p_add_dir, $p_remove_dir = '') { $v_result = true; if (!$this->_openWrite()) { return false; } if ($p_filelist != '') { if (is_array($p_filelist)) { $v_list = $p_filelist; } elseif (is_string($p_filelist)) { $v_list = explode($this->_separator, $p_filelist); } else { $this->_cleanFile(); $this->_error('Invalid file list'); return false; } $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir); } if ($v_result) { $this->_writeFooter(); $this->_close(); } else { $this->_cleanFile(); } return $v_result; } /** * This method add the files / directories listed in $p_filelist at the * end of the existing archive. If the archive does not yet exists it * is created. * The $p_filelist parameter can be an array of string, each string * representing a filename or a directory name with their path if * needed. It can also be a single string with names separated by a * single blank. * The path indicated in $p_remove_dir will be removed from the * memorized path of each file / directory listed when this path * exists. By default nothing is removed (empty path '') * The path indicated in $p_add_dir will be added at the beginning of * the memorized path of each file / directory listed. However it can * be set to empty ''. The adding of a path is done after the removing * of path. * The path add/remove ability enables the user to prepare an archive * for extraction in a different path than the origin files are. * If a file/dir is already in the archive it will only be added at the * end of the archive. There is no update of the existing archived * file/dir. However while extracting the archive, the last file will * replace the first one. This results in a none optimization of the * archive size. * If a file/dir does not exist the file/dir is ignored. However an * error text is send to PEAR error. * If a file/dir is not readable the file/dir is ignored. However an * error text is send to PEAR error. * * @param array $p_filelist An array of filenames and directory * names, or a single string with names * separated by a single blank space. * @param string $p_add_dir A string which contains a path to be * added to the memorized path of each * element in the list. * @param string $p_remove_dir A string which contains a path to be * removed from the memorized path of * each element in the list, when * relevant. * * @return true on success, false on error. */ public function addModify($p_filelist, $p_add_dir, $p_remove_dir = '') { $v_result = true; if (!$this->_isArchive()) { $v_result = $this->createModify( $p_filelist, $p_add_dir, $p_remove_dir ); } else { if (is_array($p_filelist)) { $v_list = $p_filelist; } elseif (is_string($p_filelist)) { $v_list = explode($this->_separator, $p_filelist); } else { $this->_error('Invalid file list'); return false; } $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir); } return $v_result; } /** * This method add a single string as a file at the * end of the existing archive. If the archive does not yet exists it * is created. * * @param string $p_filename A string which contains the full * filename path that will be associated * with the string. * @param string $p_string The content of the file added in * the archive. * @param bool|int $p_datetime A custom date/time (unix timestamp) * for the file (optional). * @param array $p_params An array of optional params: * stamp => the datetime (replaces * datetime above if it exists) * mode => the permissions on the * file (600 by default) * type => is this a link? See the * tar specification for details. * (default = regular file) * uid => the user ID of the file * (default = 0 = root) * gid => the group ID of the file * (default = 0 = root) * * @return true on success, false on error. */ public function addString($p_filename, $p_string, $p_datetime = false, $p_params = array()) { $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time()); $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600; $p_type = @$p_params["type"] ? $p_params["type"] : ""; $p_uid = @$p_params["uid"] ? $p_params["uid"] : ""; $p_gid = @$p_params["gid"] ? $p_params["gid"] : ""; $v_result = true; if (!$this->_isArchive()) { if (!$this->_openWrite()) { return false; } $this->_close(); } if (!$this->_openAppend()) { return false; } // Need to check the get back to the temporary file ? .... $v_result = $this->_addString($p_filename, $p_string, $p_datetime, $p_params); $this->_writeFooter(); $this->_close(); return $v_result; } /** * This method extract all the content of the archive in the directory * indicated by $p_path. When relevant the memorized path of the * files/dir can be modified by removing the $p_remove_path path at the * beginning of the file/dir path. * While extracting a file, if the directory path does not exists it is * created. * While extracting a file, if the file already exists it is replaced * without looking for last modification date. * While extracting a file, if the file already exists and is write * protected, the extraction is aborted. * While extracting a file, if a directory with the same name already * exists, the extraction is aborted. * While extracting a directory, if a file with the same name already * exists, the extraction is aborted. * While extracting a file/directory if the destination directory exist * and is write protected, or does not exist but can not be created, * the extraction is aborted. * If after extraction an extracted file does not show the correct * stored file size, the extraction is aborted. * When the extraction is aborted, a PEAR error text is set and false * is returned. However the result can be a partial extraction that may * need to be manually cleaned. * * @param string $p_path The path of the directory where the * files/dir need to by extracted. * @param string $p_remove_path Part of the memorized path that can be * removed if present at the beginning of * the file/dir path. * @param boolean $p_preserve Preserve user/group ownership of files * @param boolean $p_symlinks Allow symlinks. * * @return boolean true on success, false on error. * @see extractList() */ public function extractModify($p_path, $p_remove_path, $p_preserve = false, $p_symlinks = true) { $v_result = true; $v_list_detail = array(); if ($v_result = $this->_openRead()) { $v_result = $this->_extractList( $p_path, $v_list_detail, "complete", 0, $p_remove_path, $p_preserve, $p_symlinks ); $this->_close(); } return $v_result; } /** * This method extract from the archive one file identified by $p_filename. * The return value is a string with the file content, or NULL on error. * * @param string $p_filename The path of the file to extract in a string. * * @return a string with the file content or NULL. */ public function extractInString($p_filename) { if ($this->_openRead()) { $v_result = $this->_extractInString($p_filename); $this->_close(); } else { $v_result = null; } return $v_result; } /** * This method extract from the archive only the files indicated in the * $p_filelist. These files are extracted in the current directory or * in the directory indicated by the optional $p_path parameter. * If indicated the $p_remove_path can be used in the same way as it is * used in extractModify() method. * * @param array $p_filelist An array of filenames and directory names, * or a single string with names separated * by a single blank space. * @param string $p_path The path of the directory where the * files/dir need to by extracted. * @param string $p_remove_path Part of the memorized path that can be * removed if present at the beginning of * the file/dir path. * @param boolean $p_preserve Preserve user/group ownership of files * @param boolean $p_symlinks Allow symlinks. * * @return true on success, false on error. * @see extractModify() */ public function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false, $p_symlinks = true) { $v_result = true; $v_list_detail = array(); if (is_array($p_filelist)) { $v_list = $p_filelist; } elseif (is_string($p_filelist)) { $v_list = explode($this->_separator, $p_filelist); } else { $this->_error('Invalid string list'); return false; } if ($v_result = $this->_openRead()) { $v_result = $this->_extractList( $p_path, $v_list_detail, "partial", $v_list, $p_remove_path, $p_preserve, $p_symlinks ); $this->_close(); } return $v_result; } /** * This method set specific attributes of the archive. It uses a variable * list of parameters, in the format attribute code + attribute values : * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ','); * * @return true on success, false on error. */ public function setAttribute() { $v_result = true; // ----- Get the number of variable list of arguments if (($v_size = func_num_args()) == 0) { return true; } // ----- Get the arguments $v_att_list = func_get_args(); // ----- Read the attributes $i = 0; while ($i < $v_size) { // ----- Look for next option switch ($v_att_list[$i]) { // ----- Look for options that request a string value case ARCHIVE_TAR_ATT_SEPARATOR : // ----- Check the number of parameters if (($i + 1) >= $v_size) { $this->_error( 'Invalid number of parameters for ' . 'attribute ARCHIVE_TAR_ATT_SEPARATOR' ); return false; } // ----- Get the value $this->_separator = $v_att_list[$i + 1]; $i++; break; default : $this->_error('Unknown attribute code ' . $v_att_list[$i] . ''); return false; } // ----- Next attribute $i++; } return $v_result; } /** * This method sets the regular expression for ignoring files and directories * at import, for example: * $arch->setIgnoreRegexp("#CVS|\.svn#"); * * @param string $regexp regular expression defining which files or directories to ignore */ public function setIgnoreRegexp($regexp) { $this->_ignore_regexp = $regexp; } /** * This method sets the regular expression for ignoring all files and directories * matching the filenames in the array list at import, for example: * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool')); * * @param array $list a list of file or directory names to ignore * * @access public */ public function setIgnoreList($list) { $list = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list); $regexp = '#/' . join('$|/', $list) . '#'; $this->setIgnoreRegexp($regexp); } /** * @param string $p_message */ public function _error($p_message) { $this->error_object = $this->raiseError($p_message); } /** * @param string $p_message */ public function _warning($p_message) { $this->error_object = $this->raiseError($p_message); } /** * @param string $p_filename * @return bool */ public function _isArchive($p_filename = null) { if ($p_filename == null) { $p_filename = $this->_tarname; } clearstatcache(); return @is_file($p_filename) && !@is_link($p_filename); } /** * @return bool */ public function _openWrite() { if ($this->_compress_type == 'gz' && function_exists('gzopen')) { $this->_file = @gzopen($this->_tarname, "wb9"); } else { if ($this->_compress_type == 'bz2' && function_exists('bzopen')) { $this->_file = @bzopen($this->_tarname, "w"); } else { if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) { $this->_file = @xzopen($this->_tarname, 'w'); } else { if ($this->_compress_type == 'none') { $this->_file = @fopen($this->_tarname, "wb"); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); return false; } } } } if ($this->_file == 0) { $this->_error( 'Unable to open in write mode \'' . $this->_tarname . '\'' ); return false; } return true; } /** * @return bool */ public function _openRead() { if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') { // ----- Look if a local copy need to be done if ($this->_temp_tarname == '') { $this->_temp_tarname = uniqid('tar') . '.tmp'; if (!$v_file_from = @fopen($this->_tarname, 'rb')) { $this->_error( 'Unable to open in read mode \'' . $this->_tarname . '\'' ); $this->_temp_tarname = ''; return false; } if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) { $this->_error( 'Unable to open in write mode \'' . $this->_temp_tarname . '\'' ); $this->_temp_tarname = ''; return false; } while ($v_data = @fread($v_file_from, 1024)) { @fwrite($v_file_to, $v_data); } @fclose($v_file_from); @fclose($v_file_to); } // ----- File to open if the local copy $v_filename = $this->_temp_tarname; } else { // ----- File to open if the normal Tar file $v_filename = $this->_tarname; } if ($this->_compress_type == 'gz' && function_exists('gzopen')) { $this->_file = @gzopen($v_filename, "rb"); } else { if ($this->_compress_type == 'bz2' && function_exists('bzopen')) { $this->_file = @bzopen($v_filename, "r"); } else { if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) { $this->_file = @xzopen($v_filename, "r"); } else { if ($this->_compress_type == 'none') { $this->_file = @fopen($v_filename, "rb"); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); return false; } } } } if ($this->_file == 0) { $this->_error('Unable to open in read mode \'' . $v_filename . '\''); return false; } return true; } /** * @return bool */ public function _openReadWrite() { if ($this->_compress_type == 'gz') { $this->_file = @gzopen($this->_tarname, "r+b"); } else { if ($this->_compress_type == 'bz2') { $this->_error( 'Unable to open bz2 in read/write mode \'' . $this->_tarname . '\' (limitation of bz2 extension)' ); return false; } else { if ($this->_compress_type == 'lzma2') { $this->_error( 'Unable to open lzma2 in read/write mode \'' . $this->_tarname . '\' (limitation of lzma2 extension)' ); return false; } else { if ($this->_compress_type == 'none') { $this->_file = @fopen($this->_tarname, "r+b"); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); return false; } } } } if ($this->_file == 0) { $this->_error( 'Unable to open in read/write mode \'' . $this->_tarname . '\'' ); return false; } return true; } /** * @return bool */ public function _close() { //if (isset($this->_file)) { if (is_resource($this->_file)) { if ($this->_compress_type == 'gz') { @gzclose($this->_file); } else { if ($this->_compress_type == 'bz2') { @bzclose($this->_file); } else { if ($this->_compress_type == 'lzma2') { @xzclose($this->_file); } else { if ($this->_compress_type == 'none') { @fclose($this->_file); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } $this->_file = 0; } // ----- Look if a local copy need to be erase // Note that it might be interesting to keep the url for a time : ToDo if ($this->_temp_tarname != '') { @unlink($this->_temp_tarname); $this->_temp_tarname = ''; } return true; } /** * @return bool */ public function _cleanFile() { $this->_close(); // ----- Look for a local copy if ($this->_temp_tarname != '') { // ----- Remove the local copy but not the remote tarname @unlink($this->_temp_tarname); $this->_temp_tarname = ''; } else { // ----- Remove the local tarname file @unlink($this->_tarname); } $this->_tarname = ''; return true; } /** * @param mixed $p_binary_data * @param integer $p_len * @return bool */ public function _writeBlock($p_binary_data, $p_len = null) { if (is_resource($this->_file)) { if ($p_len === null) { if ($this->_compress_type == 'gz') { @gzputs($this->_file, $p_binary_data); } else { if ($this->_compress_type == 'bz2') { @bzwrite($this->_file, $p_binary_data); } else { if ($this->_compress_type == 'lzma2') { @xzwrite($this->_file, $p_binary_data); } else { if ($this->_compress_type == 'none') { @fputs($this->_file, $p_binary_data); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } } else { if ($this->_compress_type == 'gz') { @gzputs($this->_file, $p_binary_data, $p_len); } else { if ($this->_compress_type == 'bz2') { @bzwrite($this->_file, $p_binary_data, $p_len); } else { if ($this->_compress_type == 'lzma2') { @xzwrite($this->_file, $p_binary_data, $p_len); } else { if ($this->_compress_type == 'none') { @fputs($this->_file, $p_binary_data, $p_len); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } } } return true; } /** * @return null|string */ public function _readBlock() { $v_block = null; if (is_resource($this->_file)) { if ($this->_compress_type == 'gz') { $v_block = @gzread($this->_file, 512); } else { if ($this->_compress_type == 'bz2') { $v_block = @bzread($this->_file, 512); } else { if ($this->_compress_type == 'lzma2') { $v_block = @xzread($this->_file, 512); } else { if ($this->_compress_type == 'none') { $v_block = @fread($this->_file, 512); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } } return $v_block; } /** * @param null $p_len * @return bool */ public function _jumpBlock($p_len = null) { if (is_resource($this->_file)) { if ($p_len === null) { $p_len = 1; } if ($this->_compress_type == 'gz') { @gzseek($this->_file, gztell($this->_file) + ($p_len * 512)); } else { if ($this->_compress_type == 'bz2') { // ----- Replace missing bztell() and bzseek() for ($i = 0; $i < $p_len; $i++) { $this->_readBlock(); } } else { if ($this->_compress_type == 'lzma2') { // ----- Replace missing xztell() and xzseek() for ($i = 0; $i < $p_len; $i++) { $this->_readBlock(); } } else { if ($this->_compress_type == 'none') { @fseek($this->_file, $p_len * 512, SEEK_CUR); } else { $this->_error( 'Unknown or missing compression type (' . $this->_compress_type . ')' ); } } } } } return true; } /** * @return bool */ public function _writeFooter() { if (is_resource($this->_file)) { // ----- Write the last 0 filled block for end of archive $v_binary_data = pack('a1024', ''); $this->_writeBlock($v_binary_data); } return true; } /** * @param array $p_list * @param string $p_add_dir * @param string $p_remove_dir * @return bool */ public function _addList($p_list, $p_add_dir, $p_remove_dir) { $v_result = true; $v_header = array(); // ----- Remove potential windows directory separator $p_add_dir = $this->_translateWinPath($p_add_dir); $p_remove_dir = $this->_translateWinPath($p_remove_dir, false); if (!$this->_file) { $this->_error('Invalid file descriptor'); return false; } if (sizeof($p_list) == 0) { return true; } foreach ($p_list as $v_filename) { if (!$v_result) { break; } // ----- Skip the current tar name if ($v_filename == $this->_tarname) { continue; } if ($v_filename == '') { continue; } // ----- ignore files and directories matching the ignore regular expression if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/' . $v_filename)) { $this->_warning("File '$v_filename' ignored"); continue; } if (!file_exists($v_filename) && !is_link($v_filename)) { $this->_warning("File '$v_filename' does not exist"); continue; } // ----- Add the file or directory header if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) { return false; } if (@is_dir($v_filename) && !@is_link($v_filename)) { if (!($p_hdir = opendir($v_filename))) { $this->_warning("Directory '$v_filename' can not be read"); continue; } while (false !== ($p_hitem = readdir($p_hdir))) { if (($p_hitem != '.') && ($p_hitem != '..')) { if ($v_filename != ".") { $p_temp_list[0] = $v_filename . '/' . $p_hitem; } else { $p_temp_list[0] = $p_hitem; } $v_result = $this->_addList( $p_temp_list, $p_add_dir, $p_remove_dir ); } } unset($p_temp_list); unset($p_hdir); unset($p_hitem); } } return $v_result; } /** * @param string $p_filename * @param mixed $p_header * @param string $p_add_dir * @param string $p_remove_dir * @param null $v_stored_filename * @return bool */ public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null) { if (!$this->_file) { $this->_error('Invalid file descriptor'); return false; } if ($p_filename == '') { $this->_error('Invalid file name'); return false; } if (is_null($v_stored_filename)) { // ----- Calculate the stored filename $p_filename = $this->_translateWinPath($p_filename, false); $v_stored_filename = $p_filename; if (strcmp($p_filename, $p_remove_dir) == 0) { return true; } if ($p_remove_dir != '') { if (substr($p_remove_dir, -1) != '/') { $p_remove_dir .= '/'; } if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) { $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); } } $v_stored_filename = $this->_translateWinPath($v_stored_filename); if ($p_add_dir != '') { if (substr($p_add_dir, -1) == '/') { $v_stored_filename = $p_add_dir . $v_stored_filename; } else { $v_stored_filename = $p_add_dir . '/' . $v_stored_filename; } } $v_stored_filename = $this->_pathReduction($v_stored_filename); } if ($this->_isArchive($p_filename)) { if (($v_file = @fopen($p_filename, "rb")) == 0) { $this->_warning( "Unable to open file '" . $p_filename . "' in binary read mode" ); return true; } if (!$this->_writeHeader($p_filename, $v_stored_filename)) { return false; } while (($v_buffer = fread($v_file, $this->buffer_length)) != '') { $buffer_length = strlen("$v_buffer"); if ($buffer_length != $this->buffer_length) { $pack_size = ((int)($buffer_length / 512) + ($buffer_length % 512 !== 0 ? 1 : 0)) * 512; $pack_format = sprintf('a%d', $pack_size); } else { $pack_format = sprintf('a%d', $this->buffer_length); } $v_binary_data = pack($pack_format, "$v_buffer"); $this->_writeBlock($v_binary_data); } fclose($v_file); } else { // ----- Only header for dir if (!$this->_writeHeader($p_filename, $v_stored_filename)) { return false; } } return true; } /** * @param string $p_filename * @param string $p_string * @param bool $p_datetime * @param array $p_params * @return bool */ public function _addString($p_filename, $p_string, $p_datetime = false, $p_params = array()) { $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time()); $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600; $p_type = @$p_params["type"] ? $p_params["type"] : ""; $p_uid = @$p_params["uid"] ? $p_params["uid"] : 0; $p_gid = @$p_params["gid"] ? $p_params["gid"] : 0; if (!$this->_file) { $this->_error('Invalid file descriptor'); return false; } if ($p_filename == '') { $this->_error('Invalid file name'); return false; } // ----- Calculate the stored filename $p_filename = $this->_translateWinPath($p_filename, false); // ----- If datetime is not specified, set current time if ($p_datetime === false) { $p_datetime = time(); } if (!$this->_writeHeaderBlock( $p_filename, strlen($p_string), $p_stamp, $p_mode, $p_type, $p_uid, $p_gid ) ) { return false; } $i = 0; while (($v_buffer = substr($p_string, (($i++) * 512), 512)) != '') { $v_binary_data = pack("a512", $v_buffer); $this->_writeBlock($v_binary_data); } return true; } /** * @param string $p_filename * @param string $p_stored_filename * @return bool */ public function _writeHeader($p_filename, $p_stored_filename) { if ($p_stored_filename == '') { $p_stored_filename = $p_filename; } $v_reduced_filename = $this->_pathReduction($p_stored_filename); if (strlen($v_reduced_filename) > 99) { if (!$this->_writeLongHeader($v_reduced_filename, false)) { return false; } } $v_linkname = ''; if (@is_link($p_filename)) { $v_linkname = readlink($p_filename); } if (strlen($v_linkname) > 99) { if (!$this->_writeLongHeader($v_linkname, true)) { return false; } } $v_info = lstat($p_filename); $v_uid = sprintf("%07s", DecOct($v_info[4])); $v_gid = sprintf("%07s", DecOct($v_info[5])); $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777)); $v_mtime = sprintf("%011s", DecOct($v_info['mtime'])); if (@is_link($p_filename)) { $v_typeflag = '2'; $v_size = sprintf("%011s", DecOct(0)); } elseif (@is_dir($p_filename)) { $v_typeflag = "5"; $v_size = sprintf("%011s", DecOct(0)); } else { $v_typeflag = '0'; clearstatcache(); $v_size = sprintf("%011s", DecOct($v_info['size'])); } $v_magic = 'ustar '; $v_version = ' '; $v_uname = ''; $v_gname = ''; if (function_exists('posix_getpwuid')) { $userinfo = posix_getpwuid($v_info[4]); $groupinfo = posix_getgrgid($v_info[5]); if (isset($userinfo['name'])) { $v_uname = $userinfo['name']; } if (isset($groupinfo['name'])) { $v_gname = $groupinfo['name']; } } $v_devmajor = ''; $v_devminor = ''; $v_prefix = ''; $v_binary_data_first = pack( "a100a8a8a8a12a12", $v_reduced_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime ); $v_binary_data_last = pack( "a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '' ); // ----- Calculate the checksum $v_checksum = 0; // ..... First part of the header for ($i = 0; $i < 148; $i++) { $v_checksum += ord(substr($v_binary_data_first, $i, 1)); } // ..... Ignore the checksum value and replace it by ' ' (space) for ($i = 148; $i < 156; $i++) { $v_checksum += ord(' '); } // ..... Last part of the header for ($i = 156, $j = 0; $i < 512; $i++, $j++) { $v_checksum += ord(substr($v_binary_data_last, $j, 1)); } // ----- Write the first 148 bytes of the header in the archive $this->_writeBlock($v_binary_data_first, 148); // ----- Write the calculated checksum $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum)); $v_binary_data = pack("a8", $v_checksum); $this->_writeBlock($v_binary_data, 8); // ----- Write the last 356 bytes of the header in the archive $this->_writeBlock($v_binary_data_last, 356); return true; } /** * @param string $p_filename * @param int $p_size * @param int $p_mtime * @param int $p_perms * @param string $p_type * @param int $p_uid * @param int $p_gid * @return bool */ public function _writeHeaderBlock( $p_filename, $p_size, $p_mtime = 0, $p_perms = 0, $p_type = '', $p_uid = 0, $p_gid = 0 ) { $p_filename = $this->_pathReduction($p_filename); if (strlen($p_filename) > 99) { if (!$this->_writeLongHeader($p_filename, false)) { return false; } } if ($p_type == "5") { $v_size = sprintf("%011s", DecOct(0)); } else { $v_size = sprintf("%011s", DecOct($p_size)); } $v_uid = sprintf("%07s", DecOct($p_uid)); $v_gid = sprintf("%07s", DecOct($p_gid)); $v_perms = sprintf("%07s", DecOct($p_perms & 000777)); $v_mtime = sprintf("%11s", DecOct($p_mtime)); $v_linkname = ''; $v_magic = 'ustar '; $v_version = ' '; if (function_exists('posix_getpwuid')) { $userinfo = posix_getpwuid($p_uid); $groupinfo = posix_getgrgid($p_gid); if ($userinfo === false || $groupinfo === false) { $v_uname = ''; $v_gname = ''; } else { $v_uname = $userinfo['name']; $v_gname = $groupinfo['name']; } } else { $v_uname = ''; $v_gname = ''; } $v_devmajor = ''; $v_devminor = ''; $v_prefix = ''; $v_binary_data_first = pack( "a100a8a8a8a12A12", $p_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime ); $v_binary_data_last = pack( "a1a100a6a2a32a32a8a8a155a12", $p_type, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '' ); // ----- Calculate the checksum $v_checksum = 0; // ..... First part of the header for ($i = 0; $i < 148; $i++) { $v_checksum += ord(substr($v_binary_data_first, $i, 1)); } // ..... Ignore the checksum value and replace it by ' ' (space) for ($i = 148; $i < 156; $i++) { $v_checksum += ord(' '); } // ..... Last part of the header for ($i = 156, $j = 0; $i < 512; $i++, $j++) { $v_checksum += ord(substr($v_binary_data_last, $j, 1)); } // ----- Write the first 148 bytes of the header in the archive $this->_writeBlock($v_binary_data_first, 148); // ----- Write the calculated checksum $v_checksum = sprintf("%06s ", DecOct($v_checksum)); $v_binary_data = pack("a8", $v_checksum); $this->_writeBlock($v_binary_data, 8); // ----- Write the last 356 bytes of the header in the archive $this->_writeBlock($v_binary_data_last, 356); return true; } /** * @param string $p_filename * @return bool */ public function _writeLongHeader($p_filename, $is_link = false) { $v_uid = sprintf("%07s", 0); $v_gid = sprintf("%07s", 0); $v_perms = sprintf("%07s", 0); $v_size = sprintf("%'011s", DecOct(strlen($p_filename))); $v_mtime = sprintf("%011s", 0); $v_typeflag = ($is_link ? 'K' : 'L'); $v_linkname = ''; $v_magic = 'ustar '; $v_version = ' '; $v_uname = ''; $v_gname = ''; $v_devmajor = ''; $v_devminor = ''; $v_prefix = ''; $v_binary_data_first = pack( "a100a8a8a8a12a12", '././@LongLink', $v_perms, $v_uid, $v_gid, $v_size, $v_mtime ); $v_binary_data_last = pack( "a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, '' ); // ----- Calculate the checksum $v_checksum = 0; // ..... First part of the header for ($i = 0; $i < 148; $i++) { $v_checksum += ord(substr($v_binary_data_first, $i, 1)); } // ..... Ignore the checksum value and replace it by ' ' (space) for ($i = 148; $i < 156; $i++) { $v_checksum += ord(' '); } // ..... Last part of the header for ($i = 156, $j = 0; $i < 512; $i++, $j++) { $v_checksum += ord(substr($v_binary_data_last, $j, 1)); } // ----- Write the first 148 bytes of the header in the archive $this->_writeBlock($v_binary_data_first, 148); // ----- Write the calculated checksum $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum)); $v_binary_data = pack("a8", $v_checksum); $this->_writeBlock($v_binary_data, 8); // ----- Write the last 356 bytes of the header in the archive $this->_writeBlock($v_binary_data_last, 356); // ----- Write the filename as content of the block $i = 0; while (($v_buffer = substr($p_filename, (($i++) * 512), 512)) != '') { $v_binary_data = pack("a512", "$v_buffer"); $this->_writeBlock($v_binary_data); } return true; } /** * @param mixed $v_binary_data * @param mixed $v_header * @return bool */ public function _readHeader($v_binary_data, &$v_header) { if (strlen($v_binary_data) == 0) { $v_header['filename'] = ''; return true; } if (strlen($v_binary_data) != 512) { $v_header['filename'] = ''; $this->_error('Invalid block size : ' . strlen($v_binary_data)); return false; } if (!is_array($v_header)) { $v_header = array(); } // ----- Calculate the checksum $v_checksum = 0; // ..... First part of the header $v_binary_split = str_split($v_binary_data); $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 0, 148))); $v_checksum += array_sum(array_map('ord', array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',))); $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 156, 512))); $v_data = unpack($this->_fmt, $v_binary_data); if (strlen($v_data["prefix"]) > 0) { $v_data["filename"] = "$v_data[prefix]/$v_data[filename]"; } // ----- Extract the checksum $v_data_checksum = trim($v_data['checksum']); if (!preg_match('/^[0-7]*$/', $v_data_checksum)) { $this->_error( 'Invalid checksum for file "' . $v_data['filename'] . '" : ' . $v_data_checksum . ' extracted' ); return false; } $v_header['checksum'] = OctDec($v_data_checksum); if ($v_header['checksum'] != $v_checksum) { $v_header['filename'] = ''; // ----- Look for last block (empty block) if (($v_checksum == 256) && ($v_header['checksum'] == 0)) { return true; } $this->_error( 'Invalid checksum for file "' . $v_data['filename'] . '" : ' . $v_checksum . ' calculated, ' . $v_header['checksum'] . ' expected' ); return false; } // ----- Extract the properties $v_header['filename'] = rtrim($v_data['filename'], "\0"); if ($this->_isMaliciousFilename($v_header['filename'])) { $this->_error( 'Malicious .tar detected, file "' . $v_header['filename'] . '" will not install in desired directory tree' ); return false; } $v_header['mode'] = OctDec(trim($v_data['mode'])); $v_header['uid'] = OctDec(trim($v_data['uid'])); $v_header['gid'] = OctDec(trim($v_data['gid'])); $v_header['size'] = $this->_tarRecToSize($v_data['size']); $v_header['mtime'] = OctDec(trim($v_data['mtime'])); if (($v_header['typeflag'] = $v_data['typeflag']) == "5") { $v_header['size'] = 0; } $v_header['link'] = trim($v_data['link']); /* ----- All these fields are removed form the header because they do not carry interesting info $v_header[magic] = trim($v_data[magic]); $v_header[version] = trim($v_data[version]); $v_header[uname] = trim($v_data[uname]); $v_header[gname] = trim($v_data[gname]); $v_header[devmajor] = trim($v_data[devmajor]); $v_header[devminor] = trim($v_data[devminor]); */ return true; } /** * Convert Tar record size to actual size * * @param string $tar_size * @return size of tar record in bytes */ private function _tarRecToSize($tar_size) { /* * First byte of size has a special meaning if bit 7 is set. * * Bit 7 indicates base-256 encoding if set. * Bit 6 is the sign bit. * Bits 5:0 are most significant value bits. */ $ch = ord($tar_size[0]); if ($ch & 0x80) { // Full 12-bytes record is required. $rec_str = $tar_size . "\x00"; $size = ($ch & 0x40) ? -1 : 0; $size = ($size << 6) | ($ch & 0x3f); for ($num_ch = 1; $num_ch < 12; ++$num_ch) { $size = ($size * 256) + ord($rec_str[$num_ch]); } return $size; } else { return OctDec(trim($tar_size)); } } /** * Detect and report a malicious file name * * @param string $file * * @return bool */ private function _isMaliciousFilename($file) { if (strpos($file, '://') !== false) { return true; } if (strpos($file, '../') !== false || strpos($file, '..\\') !== false) { return true; } return false; } /** * @param $v_header * @return bool */ public function _readLongHeader(&$v_header) { $v_filename = ''; $v_filesize = $v_header['size']; $n = floor($v_header['size'] / 512); for ($i = 0; $i < $n; $i++) { $v_content = $this->_readBlock(); $v_filename .= $v_content; } if (($v_header['size'] % 512) != 0) { $v_content = $this->_readBlock(); $v_filename .= $v_content; } // ----- Read the next header $v_binary_data = $this->_readBlock(); if (!$this->_readHeader($v_binary_data, $v_header)) { return false; } $v_filename = rtrim(substr($v_filename, 0, $v_filesize), "\0"); $v_header['filename'] = $v_filename; if ($this->_isMaliciousFilename($v_filename)) { $this->_error( 'Malicious .tar detected, file "' . $v_filename . '" will not install in desired directory tree' ); return false; } return true; } /** * This method extract from the archive one file identified by $p_filename. * The return value is a string with the file content, or null on error. * * @param string $p_filename The path of the file to extract in a string. * * @return a string with the file content or null. */ private function _extractInString($p_filename) { $v_result_str = ""; while (strlen($v_binary_data = $this->_readBlock()) != 0) { if (!$this->_readHeader($v_binary_data, $v_header)) { return null; } if ($v_header['filename'] == '') { continue; } switch ($v_header['typeflag']) { case 'L': { if (!$this->_readLongHeader($v_header)) { return null; } } break; case 'K': { $v_link_header = $v_header; if (!$this->_readLongHeader($v_link_header)) { return null; } $v_header['link'] = $v_link_header['filename']; } break; } if ($v_header['filename'] == $p_filename) { if ($v_header['typeflag'] == "5") { $this->_error( 'Unable to extract in string a directory ' . 'entry {' . $v_header['filename'] . '}' ); return null; } else { $n = floor($v_header['size'] / 512); for ($i = 0; $i < $n; $i++) { $v_result_str .= $this->_readBlock(); } if (($v_header['size'] % 512) != 0) { $v_content = $this->_readBlock(); $v_result_str .= substr( $v_content, 0, ($v_header['size'] % 512) ); } return $v_result_str; } } else { $this->_jumpBlock(ceil(($v_header['size'] / 512))); } } return null; } /** * @param string $p_path * @param string $p_list_detail * @param string $p_mode * @param string $p_file_list * @param string $p_remove_path * @param bool $p_preserve * @param bool $p_symlinks * @return bool */ public function _extractList( $p_path, &$p_list_detail, $p_mode, $p_file_list, $p_remove_path, $p_preserve = false, $p_symlinks = true ) { $v_result = true; $v_nb = 0; $v_extract_all = true; $v_listing = false; $p_path = $this->_translateWinPath($p_path, false); if ($p_path == '' || (substr($p_path, 0, 1) != '/' && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':')) ) { $p_path = "./" . $p_path; } $p_remove_path = $this->_translateWinPath($p_remove_path); // ----- Look for path to remove format (should end by /) if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) { $p_remove_path .= '/'; } $p_remove_path_size = strlen($p_remove_path); switch ($p_mode) { case "complete" : $v_extract_all = true; $v_listing = false; break; case "partial" : $v_extract_all = false; $v_listing = false; break; case "list" : $v_extract_all = false; $v_listing = true; break; default : $this->_error('Invalid extract mode (' . $p_mode . ')'); return false; } clearstatcache(); while (strlen($v_binary_data = $this->_readBlock()) != 0) { $v_extract_file = false; $v_extraction_stopped = 0; if (!$this->_readHeader($v_binary_data, $v_header)) { return false; } if ($v_header['filename'] == '') { continue; } switch ($v_header['typeflag']) { case 'L': { if (!$this->_readLongHeader($v_header)) { return null; } } break; case 'K': { $v_link_header = $v_header; if (!$this->_readLongHeader($v_link_header)) { return null; } $v_header['link'] = $v_link_header['filename']; } break; } // ignore extended / pax headers if ($v_header['typeflag'] == 'x' || $v_header['typeflag'] == 'g') { $this->_jumpBlock(ceil(($v_header['size'] / 512))); continue; } if ((!$v_extract_all) && (is_array($p_file_list))) { // ----- By default no unzip if the file is not found $v_extract_file = false; for ($i = 0; $i < sizeof($p_file_list); $i++) { // ----- Look if it is a directory if (substr($p_file_list[$i], -1) == '/') { // ----- Look if the directory is in the filename path if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) == $p_file_list[$i]) ) { $v_extract_file = true; break; } } // ----- It is a file, so compare the file names elseif ($p_file_list[$i] == $v_header['filename']) { $v_extract_file = true; break; } } } else { $v_extract_file = true; } // ----- Look if this file need to be extracted if (($v_extract_file) && (!$v_listing)) { if (($p_remove_path != '') && (substr($v_header['filename'] . '/', 0, $p_remove_path_size) == $p_remove_path) ) { $v_header['filename'] = substr( $v_header['filename'], $p_remove_path_size ); if ($v_header['filename'] == '') { continue; } } if (($p_path != './') && ($p_path != '/')) { while (substr($p_path, -1) == '/') { $p_path = substr($p_path, 0, strlen($p_path) - 1); } if (substr($v_header['filename'], 0, 1) == '/') { $v_header['filename'] = $p_path . $v_header['filename']; } else { $v_header['filename'] = $p_path . '/' . $v_header['filename']; } } if (file_exists($v_header['filename'])) { if ((@is_dir($v_header['filename'])) && ($v_header['typeflag'] == '') ) { $this->_error( 'File ' . $v_header['filename'] . ' already exists as a directory' ); return false; } if (($this->_isArchive($v_header['filename'])) && ($v_header['typeflag'] == "5") ) { $this->_error( 'Directory ' . $v_header['filename'] . ' already exists as a file' ); return false; } if (!is_writeable($v_header['filename'])) { $this->_error( 'File ' . $v_header['filename'] . ' already exists and is write protected' ); return false; } if (filemtime($v_header['filename']) > $v_header['mtime']) { // To be completed : An error or silent no replace ? } } // ----- Check the directory availability and create it if necessary elseif (($v_result = $this->_dirCheck( ($v_header['typeflag'] == "5" ? $v_header['filename'] : dirname($v_header['filename'])) )) != 1 ) { $this->_error('Unable to create path for ' . $v_header['filename']); return false; } if ($v_extract_file) { if ($v_header['typeflag'] == "5") { if (!@file_exists($v_header['filename'])) { if (!@mkdir($v_header['filename'], 0777)) { $this->_error( 'Unable to create directory {' . $v_header['filename'] . '}' ); return false; } } } elseif ($v_header['typeflag'] == "2") { if (!$p_symlinks) { $this->_warning('Symbolic links are not allowed. ' . 'Unable to extract {' . $v_header['filename'] . '}' ); return false; } $absolute_link = FALSE; $link_depth = 0; if (strpos($v_header['link'], "/") === 0 || strpos($v_header['link'], ':') !== FALSE) { $absolute_link = TRUE; } else { $s_filename = preg_replace('@^' . preg_quote($p_path) . '@', "", $v_header['filename']); $s_linkname = str_replace('\\', '/', $v_header['link']); foreach (explode("/", $s_filename) as $dir) { if ($dir === "..") { $link_depth--; } elseif ($dir !== "" && $dir !== "." ) { $link_depth++; } } foreach (explode("/", $s_linkname) as $dir){ if ($link_depth <= 0) { break; } if ($dir === "..") { $link_depth--; } elseif ($dir !== "" && $dir !== ".") { $link_depth++; } } } if ($absolute_link || $link_depth <= 0) { $this->_error( 'Out-of-path file extraction {' . $v_header['filename'] . ' --> ' . $v_header['link'] . '}' ); return false; } if (@file_exists($v_header['filename'])) { @unlink($v_header['filename']); } if (!@symlink($v_header['link'], $v_header['filename'])) { $this->_error( 'Unable to extract symbolic link {' . $v_header['filename'] . '}' ); return false; } } else { if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { $this->_error( 'Error while opening {' . $v_header['filename'] . '} in write binary mode' ); return false; } else { $n = floor($v_header['size'] / 512); for ($i = 0; $i < $n; $i++) { $v_content = $this->_readBlock(); fwrite($v_dest_file, $v_content, 512); } if (($v_header['size'] % 512) != 0) { $v_content = $this->_readBlock(); fwrite($v_dest_file, $v_content, ($v_header['size'] % 512)); } @fclose($v_dest_file); if ($p_preserve) { @chown($v_header['filename'], $v_header['uid']); @chgrp($v_header['filename'], $v_header['gid']); } // ----- Change the file mode, mtime @touch($v_header['filename'], $v_header['mtime']); if ($v_header['mode'] & 0111) { // make file executable, obey umask $mode = fileperms($v_header['filename']) | (~umask() & 0111); @chmod($v_header['filename'], $mode); } } // ----- Check the file size clearstatcache(); if (!is_file($v_header['filename'])) { $this->_error( 'Extracted file ' . $v_header['filename'] . 'does not exist. Archive may be corrupted.' ); return false; } $filesize = filesize($v_header['filename']); if ($filesize != $v_header['size']) { $this->_error( 'Extracted file ' . $v_header['filename'] . ' does not have the correct file size \'' . $filesize . '\' (' . $v_header['size'] . ' expected). Archive may be corrupted.' ); return false; } } } else { $this->_jumpBlock(ceil(($v_header['size'] / 512))); } } else { $this->_jumpBlock(ceil(($v_header['size'] / 512))); } /* TBC : Seems to be unused ... if ($this->_compress) $v_end_of_file = @gzeof($this->_file); else $v_end_of_file = @feof($this->_file); */ if ($v_listing || $v_extract_file || $v_extraction_stopped) { // ----- Log extracted files if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename'] ) { $v_file_dir = ''; } if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) { $v_file_dir = '/'; } $p_list_detail[$v_nb++] = $v_header; if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) { return true; } } } return true; } /** * @return bool */ public function _openAppend() { if (filesize($this->_tarname) == 0) { return $this->_openWrite(); } if ($this->_compress) { $this->_close(); if (!@rename($this->_tarname, $this->_tarname . ".tmp")) { $this->_error( 'Error while renaming \'' . $this->_tarname . '\' to temporary file \'' . $this->_tarname . '.tmp\'' ); return false; } if ($this->_compress_type == 'gz') { $v_temp_tar = @gzopen($this->_tarname . ".tmp", "rb"); } elseif ($this->_compress_type == 'bz2') { $v_temp_tar = @bzopen($this->_tarname . ".tmp", "r"); } elseif ($this->_compress_type == 'lzma2') { $v_temp_tar = @xzopen($this->_tarname . ".tmp", "r"); } if ($v_temp_tar == 0) { $this->_error( 'Unable to open file \'' . $this->_tarname . '.tmp\' in binary read mode' ); @rename($this->_tarname . ".tmp", $this->_tarname); return false; } if (!$this->_openWrite()) { @rename($this->_tarname . ".tmp", $this->_tarname); return false; } if ($this->_compress_type == 'gz') { $end_blocks = 0; while (!@gzeof($v_temp_tar)) { $v_buffer = @gzread($v_temp_tar, 512); if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { $end_blocks++; // do not copy end blocks, we will re-make them // after appending continue; } elseif ($end_blocks > 0) { for ($i = 0; $i < $end_blocks; $i++) { $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); } $end_blocks = 0; } $v_binary_data = pack("a512", $v_buffer); $this->_writeBlock($v_binary_data); } @gzclose($v_temp_tar); } elseif ($this->_compress_type == 'bz2') { $end_blocks = 0; while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) { if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { $end_blocks++; // do not copy end blocks, we will re-make them // after appending continue; } elseif ($end_blocks > 0) { for ($i = 0; $i < $end_blocks; $i++) { $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); } $end_blocks = 0; } $v_binary_data = pack("a512", $v_buffer); $this->_writeBlock($v_binary_data); } @bzclose($v_temp_tar); } elseif ($this->_compress_type == 'lzma2') { $end_blocks = 0; while (strlen($v_buffer = @xzread($v_temp_tar, 512)) > 0) { if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { $end_blocks++; // do not copy end blocks, we will re-make them // after appending continue; } elseif ($end_blocks > 0) { for ($i = 0; $i < $end_blocks; $i++) { $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); } $end_blocks = 0; } $v_binary_data = pack("a512", $v_buffer); $this->_writeBlock($v_binary_data); } @xzclose($v_temp_tar); } if (!@unlink($this->_tarname . ".tmp")) { $this->_error( 'Error while deleting temporary file \'' . $this->_tarname . '.tmp\'' ); } } else { // ----- For not compressed tar, just add files before the last // one or two 512 bytes block if (!$this->_openReadWrite()) { return false; } clearstatcache(); $v_size = filesize($this->_tarname); // We might have zero, one or two end blocks. // The standard is two, but we should try to handle // other cases. fseek($this->_file, $v_size - 1024); if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { fseek($this->_file, $v_size - 1024); } elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { fseek($this->_file, $v_size - 512); } } return true; } /** * @param $p_filelist * @param string $p_add_dir * @param string $p_remove_dir * @return bool */ public function _append($p_filelist, $p_add_dir = '', $p_remove_dir = '') { if (!$this->_openAppend()) { return false; } if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) { $this->_writeFooter(); } $this->_close(); return true; } /** * Check if a directory exists and create it (including parent * dirs) if not. * * @param string $p_dir directory to check * * @return bool true if the directory exists or was created */ public function _dirCheck($p_dir) { clearstatcache(); if ((@is_dir($p_dir)) || ($p_dir == '')) { return true; } $p_parent_dir = dirname($p_dir); if (($p_parent_dir != $p_dir) && ($p_parent_dir != '') && (!$this->_dirCheck($p_parent_dir)) ) { return false; } if (!@mkdir($p_dir, 0777)) { $this->_error("Unable to create directory '$p_dir'"); return false; } return true; } /** * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar", * rand emove double slashes. * * @param string $p_dir path to reduce * * @return string reduced path */ private function _pathReduction($p_dir) { $v_result = ''; // ----- Look for not empty path if ($p_dir != '') { // ----- Explode path by directory names $v_list = explode('/', $p_dir); // ----- Study directories from last to first for ($i = sizeof($v_list) - 1; $i >= 0; $i--) { // ----- Look for current path if ($v_list[$i] == ".") { // ----- Ignore this directory // Should be the first $i=0, but no check is done } else { if ($v_list[$i] == "..") { // ----- Ignore it and ignore the $i-1 $i--; } else { if (($v_list[$i] == '') && ($i != (sizeof($v_list) - 1)) && ($i != 0) ) { // ----- Ignore only the double '//' in path, // but not the first and last / } else { $v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? '/' . $v_result : ''); } } } } } if (defined('OS_WINDOWS') && OS_WINDOWS) { $v_result = strtr($v_result, '\\', '/'); } return $v_result; } /** * @param $p_path * @param bool $p_remove_disk_letter * @return string */ public function _translateWinPath($p_path, $p_remove_disk_letter = true) { if (defined('OS_WINDOWS') && OS_WINDOWS) { // ----- Look for potential disk letter if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false) ) { $p_path = substr($p_path, $v_position + 1); } // ----- Change potential windows directory separator if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) { $p_path = strtr($p_path, '\\', '/'); } } return $p_path; } } PK!smmFile/MARCBASE.phpnu[ * @copyright 2007-2010 Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id: MARCXML.php 301727 2010-07-30 17:30:51Z dbs $ * @link http://pear.php.net/package/File_MARC * @example read.php Retrieve specific fields and subfields from a record * @example subfields.php Create new subfields and add them in specific order * @example marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension */ // {{{ class File_MARCBASE /** * The main File_MARCBASE class provides common methods for File_MARC and * File_MARCXML - primarily for generating MARCXML output. * * @category File_Formats * @package File_MARC * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARCBASE { /** * XMLWriter for writing collections * * @var XMLWriter */ protected $xmlwriter; // }}} // {{{ Constructor: function __construct() /** * Read in MARCXML records * * This function reads in files or strings that * contain one or more MARCXML records. * * * * * * @param string $source Name of the file, or a raw MARC string * @param int $type Source of the input, either SOURCE_FILE or SOURCE_STRING */ function __construct($source, $type) { $this->xmlwriter = new XMLWriter(); $this->xmlwriter->openMemory(); $this->xmlwriter->startDocument('1.0', 'UTF-8'); } // }}} // {{{ toXMLHeader() /** * Initializes the MARCXML output of a record or collection of records * * This method produces an XML representation of a MARC record that * attempts to adhere to the MARCXML standard documented at * http://www.loc.gov/standards/marcxml/ * * @return bool true if successful */ function toXMLHeader() { $this->xmlwriter->startElement("collection"); $this->xmlwriter->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim"); return true; } // }}} // {{{ getXMLWriter() /** * Returns the XMLWriter object * * This method produces an XML representation of a MARC record that * attempts to adhere to the MARCXML standard documented at * http://www.loc.gov/standards/marcxml/ * * @return XMLWriter XMLWriter instance */ function getXMLWriter() { return $this->xmlwriter; } // }}} // {{{ toXMLFooter() /** * Returns the MARCXML collection footer * * This method produces an XML representation of a MARC record that * attempts to adhere to the MARCXML standard documented at * http://www.loc.gov/standards/marcxml/ * * @return string representation of MARC record in MARCXML format */ function toXMLFooter() { $this->xmlwriter->endElement(); // end collection $this->xmlwriter->endDocument(); return $this->xmlwriter->outputMemory(); } // }}} } // }}} PK!6lFile/MARCXML.phpnu[ * @copyright 2007-2010 Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id$ * @link http://pear.php.net/package/File_MARC * @example read.php Retrieve specific fields and subfields from a record * @example subfields.php Create new subfields and add them in specific order * @example marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension */ require_once 'PEAR/Exception.php'; require_once 'Structures/LinkedList/Double.php'; require_once 'File/MARCBASE.php'; require_once 'File/MARC.php'; require_once 'File/MARC/Record.php'; require_once 'File/MARC/Field.php'; require_once 'File/MARC/Control_Field.php'; require_once 'File/MARC/Data_Field.php'; require_once 'File/MARC/Subfield.php'; require_once 'File/MARC/Exception.php'; require_once 'File/MARC/List.php'; // {{{ class File_MARCXML /** * The main File_MARCXML class enables you to return File_MARC_Record * objects from an XML stream or string. * * @category File_Formats * @package File_MARC * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARCXML extends File_MARCBASE { // {{{ constants /** * MARC records retrieved from a file */ const SOURCE_FILE = 1; /** * MARC records retrieved from a binary string */ const SOURCE_STRING = 2; // }}} // {{{ properties /** * Source containing raw records * * @var resource */ protected $source; /** * Source type (SOURCE_FILE or SOURCE_STRING) * * @var int */ protected $type; /** * Counter for MARCXML records in a collection * * @var int */ protected $counter; /** * XMLWriter for writing collections * * @var XMLWriter */ protected $xmlwriter; // }}} // {{{ Constructor: function __construct() /** * Read in MARCXML records * * This function reads in files or strings that * contain one or more MARCXML records. * * * * * * @param string $source Name of the file, or a raw MARC string * @param int $type Source of the input, either SOURCE_FILE or SOURCE_STRING */ function __construct($source, $type = self::SOURCE_FILE) { parent::__construct($source, $type); $this->counter = 0; switch ($type) { case self::SOURCE_FILE: $this->type = self::SOURCE_FILE; $this->source = simplexml_load_file($source); break; case self::SOURCE_STRING: $this->type = self::SOURCE_STRING; $this->source = simplexml_load_string($source); break; default: throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_SOURCE], File_MARC_Exception::ERROR_INVALID_SOURCE); } if (!$this->source) { $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_FILE], array('filename' => $source)); throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_FILE); } } // }}} // {{{ next() /** * Return next {@link File_MARC_Record} object * * Decodes the next MARCXML record and returns the {@link File_MARC_Record} * object. * * next()) { * print $record; * print "\n"; * } * * ?> * * * @return File_MARC_Record next record, or false if there are * no more records */ function next() { if (isset($this->source->record[$this->counter])) { $record = $this->source->record[$this->counter++]; } elseif ($this->source->getName() == "record" && $this->counter == 0) { $record = $this->source; $this->counter++; } else { return false; } if ($record) { return $this->_decode($record); } else { return false; } } // }}} // {{{ _decode() /** * Decode a given MARCXML record * * @param string $text MARCXML record element * * @return File_MARC_Record Decoded File_MARC_Record object */ private function _decode($text) { $marc = new File_MARC_Record($this); // Store leader $marc->setLeader($text->leader); // go through all the control fields foreach ($text->controlfield as $controlfield) { $marc->appendField(new File_MARC_Control_Field((string)$controlfield['tag'], $controlfield)); } // go through all the data fields foreach ($text->datafield as $datafield) { $subfield_data = array(); foreach ($datafield->subfield as $subfield) { $subfield_data[] = new File_MARC_Subfield((string)$subfield['code'], $subfield); } // If the data is invalid, let's just ignore the one field try { $new_field = new File_MARC_Data_Field((string)$datafield['tag'], $subfield_data, $datafield['ind1'], $datafield['ind2']); $marc->appendField($new_field); } catch (Exception $e) { $marc->addWarning($e->getMessage()); } } return $marc; } // }}} } // }}} PK! (7(7 File/MARC.phpnu[ * @author Dan Scott * @copyright 2003-2010 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id$ * @link http://pear.php.net/package/File_MARC * @example read.php Retrieve specific fields and subfields from a record * @example subfields.php Create new subfields and add them in specific order * @example marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension */ require_once 'PEAR/Exception.php'; require_once 'Structures/LinkedList/Double.php'; require_once 'File/MARCBASE.php'; require_once 'File/MARC/Record.php'; require_once 'File/MARC/Field.php'; require_once 'File/MARC/Control_Field.php'; require_once 'File/MARC/Data_Field.php'; require_once 'File/MARC/Subfield.php'; require_once 'File/MARC/Exception.php'; require_once 'File/MARC/List.php'; // {{{ class File_MARC /** * The main File_MARC class enables you to return File_MARC_Record * objects from a stream or string. * * @category File_Formats * @package File_MARC * @author Christoffer Landtman * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC extends File_MARCBASE { // {{{ constants /** * MARC records retrieved from a file */ const SOURCE_FILE = 1; /** * MARC records retrieved from a binary string */ const SOURCE_STRING = 2; /** * Hexadecimal value for Subfield indicator */ const SUBFIELD_INDICATOR = "\x1F"; /** * Hexadecimal value for End of Field */ const END_OF_FIELD = "\x1E"; /** * Hexadecimal value for End of Record */ const END_OF_RECORD = "\x1D"; /** * Length of the Directory */ const DIRECTORY_ENTRY_LEN = 12; /** * Length of the Leader */ const LEADER_LEN = 24; /** * Maximum record length */ const MAX_RECORD_LENGTH = 99999; // }}} // {{{ properties /** * Source containing raw records * * @var resource */ protected $source; /** * Source type (SOURCE_FILE or SOURCE_STRING) * * @var int */ protected $type; /** * XMLWriter for writing collections * * @var XMLWriter */ protected $xmlwriter; // }}} // {{{ Constructor: function __construct() /** * Read in MARC records * * This function reads in MARC record files or strings that * contain one or more MARC records. * * * * * * @param string $source Name of the file, or a raw MARC string * @param int $type Source of the input, either SOURCE_FILE or SOURCE_STRING */ function __construct($source, $type = self::SOURCE_FILE) { parent::__construct($source, $type); switch ($type) { case self::SOURCE_FILE: $this->type = self::SOURCE_FILE; $this->source = fopen($source, 'rb'); if (!$this->source) { $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_FILE], array('filename' => $source)); throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_FILE); } break; case self::SOURCE_STRING: $this->type = self::SOURCE_STRING; $this->source = explode(File_MARC::END_OF_RECORD, $source); break; default: throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_SOURCE], File_MARC_Exception::ERROR_INVALID_SOURCE); } } // }}} // {{{ nextRaw() /** * Return the next raw MARC record * * Returns the next raw MARC record, unless all records already have * been read. * * @return string Either a raw record or false */ function nextRaw() { if ($this->type == self::SOURCE_FILE) { $record = stream_get_line($this->source, File_MARC::MAX_RECORD_LENGTH, File_MARC::END_OF_RECORD); // Remove illegal stuff that sometimes occurs between records $record = preg_replace('/^[\\x0a\\x0d\\x00]+/', "", $record); } elseif ($this->type == self::SOURCE_STRING) { $record = array_shift($this->source); } // Exit if we are at the end of the file if (!$record) { return false; } // Append the end of record we lost during stream_get_line() or explode() $record .= File_MARC::END_OF_RECORD; return $record; } // }}} // {{{ next() /** * Return next {@link File_MARC_Record} object * * Decodes the next raw MARC record and returns the {@link File_MARC_Record} * object. * * next()) { * print $record; * print "\n"; * } * * ?> * * * @return File_MARC_Record next record, or false if there are * no more records */ function next() { $raw = $this->nextRaw(); if ($raw) { return $this->_decode($raw); } else { return false; } } // }}} // {{{ _decode() /** * Decode a given raw MARC record * * Port of Andy Lesters MARC::File::USMARC->decode() Perl function into PHP. * * @param string $text Raw MARC record * * @return File_MARC_Record Decoded File_MARC_Record object */ private function _decode($text) { $marc = new File_MARC_Record($this); // fallback on the actual byte length $record_length = strlen($text); $matches = array(); if (preg_match("/^(\d{5})/", $text, $matches)) { // Store record length $record_length = $matches[1]; if ($record_length != strlen($text)) { $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INCORRECT_LENGTH], array("record_length" => $record_length, "actual" => strlen($text)))); // Real beats declared byte length $record_length = strlen($text); } } else { $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_NONNUMERIC_LENGTH], array("record_length" => substr($text, 0, 5)))); } if (substr($text, -1, 1) != File_MARC::END_OF_RECORD) throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_TERMINATOR], File_MARC_Exception::ERROR_INVALID_TERMINATOR); // Store leader $marc->setLeader(substr($text, 0, File_MARC::LEADER_LEN)); // bytes 12 - 16 of leader give offset to the body of the record $data_start = 0 + substr($text, 12, 5); // immediately after the leader comes the directory (no separator) $dir = substr($text, File_MARC::LEADER_LEN, $data_start - File_MARC::LEADER_LEN - 1); // -1 to allow for \x1e at end of directory // character after the directory must be \x1e if (substr($text, $data_start-1, 1) != File_MARC::END_OF_FIELD) { $marc->addWarning(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_NO_DIRECTORY]); } // All directory entries 12 bytes long, so length % 12 must be 0 if (strlen($dir) % File_MARC::DIRECTORY_ENTRY_LEN != 0) { $marc->addWarning(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_LENGTH]); } // go through all the fields $nfields = strlen($dir) / File_MARC::DIRECTORY_ENTRY_LEN; for ($n=0; $n<$nfields; $n++) { // As pack returns to key 1, leave place 0 in list empty list(, $tag) = unpack("A3", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN)); list(, $len) = unpack("A3/A4", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN)); list(, $offset) = unpack("A3/A4/A5", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN)); // Check directory validity if (!preg_match("/^[0-9A-Za-z]{3}$/", $tag)) { $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_TAG], array("tag" => $tag))); } if (!preg_match("/^\d{4}$/", $len)) { $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_TAG_LENGTH], array("tag" => $tag, "len" => $len))); } if (!preg_match("/^\d{5}$/", $offset)) { $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_OFFSET], array("tag" => $tag, "offset" => $offset))); } if ($offset + $len > $record_length) { $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY], array("tag" => $tag))); } $tag_data = substr($text, $data_start + $offset, $len); if (substr($tag_data, -1, 1) == File_MARC::END_OF_FIELD) { /* get rid of the end-of-tag character */ $tag_data = substr($tag_data, 0, -1); $len--; } else { $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_FIELD_EOF], array("tag" => $tag))); } if (preg_match("/^\d+$/", $tag) and ($tag < 10)) { $marc->appendField(new File_MARC_Control_Field($tag, $tag_data)); } else { $subfields = explode(File_MARC::SUBFIELD_INDICATOR, $tag_data); $indicators = array_shift($subfields); if (strlen($indicators) != 2) { $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATORS], array("tag" => $tag, "indicators" => $indicators)); $marc->addWarning($errorMessage); // Do the best with the indicators we've got if (strlen($indicators) == 1) { $ind1 = $indicators; $ind2 = " "; } else { list($ind1,$ind2) = array(" ", " "); } } else { $ind1 = substr($indicators, 0, 1); $ind2 = substr($indicators, 1, 1); } // Split the subfield data into subfield name and data pairs $subfield_data = array(); foreach ($subfields as $subfield) { if (strlen($subfield) > 0) { $subfield_data[] = new File_MARC_Subfield(substr($subfield, 0, 1), substr($subfield, 1)); } else { $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_EMPTY_SUBFIELD], array("tag" => $tag)); $marc->addWarning($errorMessage); } } if (!isset($subfield_data)) { $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_EMPTY_SUBFIELD], array("tag" => $tag)); $marc->addWarning($errorMessage); } // If the data is invalid, let's just ignore the one field try { $new_field = new File_MARC_Data_Field($tag, $subfield_data, $ind1, $ind2); $marc->appendField($new_field); } catch (Exception $e) { $marc->addWarning($e->getMessage()); } } } return $marc; } // }}} } // }}} PK!zWWFile/MARC/Record.phpnu[ * @author Dan Scott * @copyright 2003-2008 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id$ * @link http://pear.php.net/package/File_MARC */ // {{{ class File_MARC_Record /** * Represents a single MARC record * * A MARC record contains a leader and zero or more fields held within a * linked list structure. Fields are represented by {@link File_MARC_Data_Field} * objects. * * @category File_Formats * @package File_MARC * @author Christoffer Landtman * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC_Record { // {{{ properties /** * Contains a linked list of {@link File_MARC_Data_Field} objects for * this record * @var File_MARC_List */ protected $fields; /** * Record leader * @var string */ protected $leader; /** * Non-fatal warnings generated during parsing * @var array */ protected $warnings; /** * XMLWriter for writing collections * * @var XMLWriter */ protected $marcxml; /** * MARC instance for access to the XML header/footer methods * We need this so that we can properly wrap a collection of MARC records. * * @var File_MARC */ protected $marc; // }}} // {{{ Constructor: function __construct() /** * Start function * * Set all variables to defaults to create new File_MARC_Record object * * @param File_MARC $marc MARC record from File_MARC or File_MARCXML * * @return true */ function __construct($marc = null) { $this->fields = new File_MARC_List(); $this->setLeader(str_repeat(' ', 24)); if (!$marc) { $marc = new File_MARC(null, File_MARC::SOURCE_STRING); // oh the hack } $this->marc = $marc; $this->marcxml = $marc->getXMLWriter(); } // }}} // {{{ Destructor: function __destruct() /** * Destroys the data field */ function __destruct() { $this->fields = null; $this->warnings = null; } // }}} // {{{ getLeader() /** * Get MARC leader * * Returns the leader for the MARC record. No validation * on the specified leader is performed. * * @return string returns the leader */ function getLeader() { return (string)$this->leader; } // }}} // {{{ setLeader() /** * Set MARC record leader * * Sets the leader for the MARC record. No validation * on the specified leader is performed. * * @param string $leader Leader * * @return string returns the leader */ function setLeader($leader) { $this->leader = $leader; return $this->leader; } // }}} // {{{ appendField() /** * Appends field to MARC record * * Adds a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field} * object to the end of the existing list of fields. * * @param File_MARC_Field $new_field The field to add * * @return File_MARC_Field The field that was added */ function appendField(File_MARC_Field $new_field) { /* Append as the last field in the record */ $this->fields->appendNode($new_field); return $new_field; } // }}} // {{{ prependField() /** * Prepends field to MARC record * * Adds a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field} * object to the start of to the existing list of fields. * * @param File_MARC_Field $new_field The field to add * * @return File_MARC_Field The field that was added */ function prependField(File_MARC_Field $new_field) { $this->fields->prependNode($new_field); return $new_field; } // }}} // {{{ insertField() /** * Inserts a field in the MARC record relative to an existing field * * Inserts a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field} * object before or after a specified existing field. * * * // Example: Insert a new field before the first 650 field * * // Create the new field * $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.'); * $new_field = new File_MARC_Data_Field('100', $subfields, 0, null); * * // Retrieve the target field for our insertion point * $subject = $record->getFields('650'); * * // Insert the new field * if (is_array($subject)) { * $record->insertField($new_field, $subject[0], true); * } * elseif ($subject) { * $record->insertField($new_field, $subject, true); * } * * * @param File_MARC_Field $new_field The field to add * @param File_MARC_Field $existing_field The target field * @param bool $before Insert the new field before the existing field if true, after the existing field if false * * @return File_MARC_Field The field that was added */ function insertField(File_MARC_Field $new_field, File_MARC_Field $existing_field, $before = false) { switch ($before) { /* Insert before the specified field in the record */ case true: $this->fields->insertNode($new_field, $existing_field, true); break; /* Insert after the specified field in the record */ case false: $this->fields->insertNode($new_field, $existing_field); break; default: $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INSERTFIELD_MODE], array("mode" => $before)); throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INSERTFIELD_MODE); } return $new_field; } // }}} // {{{ _buildDirectory() /** * Build record directory * * Generate the directory of the record according to the current contents * of the record. * * @return array Array ($fields, $directory, $total, $base_address) */ private function _buildDirectory() { // Vars $fields = array(); $directory = array(); $data_end = 0; foreach ($this->fields as $field) { // No empty fields allowed if (!$field->isEmpty()) { // Get data in raw format $str = $field->toRaw(); $fields[] = $str; // Create directory entry $len = strlen($str); $direntry = sprintf("%03s%04d%05d", $field->getTag(), $len, $data_end); $directory[] = $direntry; $data_end += $len; } } /** * Rules from MARC::Record::USMARC */ $base_address = File_MARC::LEADER_LEN + // better be 24 (count($directory) * File_MARC::DIRECTORY_ENTRY_LEN) + // all the directory entries 1; // end-of-field marker $total = $base_address + // stuff before first field $data_end + // Length of the fields 1; // End-of-record marker return array($fields, $directory, $total, $base_address); } // }}} // {{{ setLeaderLengths() /** * Set MARC record leader lengths * * Set the Leader lengths of the record according to defaults specified in * {@link http://www.loc.gov/marc/bibliographic/ecbdldrd.html} * * @param int $record_length Record length * @param int $base_address Base address of data * * @return bool Success or failure */ function setLeaderLengths($record_length, $base_address) { if (!is_int($record_length)) { return false; } if (!is_int($base_address)) { return false; } // Set record length $this->setLeader(substr_replace($this->getLeader(), sprintf("%05d", $record_length), 0, 5)); $this->setLeader(substr_replace($this->getLeader(), sprintf("%05d", $base_address), File_MARC::DIRECTORY_ENTRY_LEN, 5)); $this->setLeader(substr_replace($this->getLeader(), '22', 10, 2)); $this->setLeader(substr_replace($this->getLeader(), '4500', 20, 4)); if (strlen($this->getLeader()) > File_MARC::LEADER_LEN) { // Avoid incoming leaders that are mangled to be overly long $this->setLeader(substr($this->getLeader(), 0, File_MARC::LEADER_LEN)); $this->addWarning("Input leader was too long; truncated to " . File_MARC::LEADER_LEN . " characters"); } return true; } // }}} // {{{ getField() /** * Return the first {@link File_MARC_Data_Field} or * {@link File_MARC_Control_Field} object that matches the specified tag * name. Returns false if no match is found. * * @param string $spec tag name * @param bool $pcre if true, then match as a regular expression * * @return {@link File_MARC_Data_Field}|{@link File_MARC_Control_Field} first field that matches the requested tag name */ function getField($spec = null, $pcre = null) { foreach ($this->fields as $field) { if (($pcre && preg_match("/$spec/", $field->getTag())) || (!$pcre && $spec == $field->getTag()) ) { return $field; } } return false; } // }}} // {{{ getFields() /** * Return an array or {@link File_MARC_List} containing all * {@link File_MARC_Data_Field} or {@link File_MARC_Control_Field} objects * that match the specified tag name. If the tag name is omitted all * fields are returned. * * @param string $spec tag name * @param bool $pcre if true, then match as a regular expression * * @return File_MARC_List|array {@link File_MARC_Data_Field} or * {@link File_MARC_Control_Field} objects that match the requested tag name */ function getFields($spec = null, $pcre = null) { if (!$spec) { return $this->fields; } // Okay, we're actually looking for something specific $matches = array(); foreach ($this->fields as $field) { if (($pcre && preg_match("/$spec/", $field->getTag())) || (!$pcre && $spec == $field->getTag()) ) { $matches[] = $field; } } return $matches; } // }}} // {{{ deleteFields() /** * Delete all occurrences of a field matching a tag name from the record. * * @param string $tag tag for the fields to be deleted * @param bool $pcre if true, then match as a regular expression * * @return int number of fields that were deleted */ function deleteFields($tag, $pcre = null) { $cnt = 0; foreach ($this->getFields() as $field) { if (($pcre && preg_match("/$tag/", $field->getTag())) || (!$pcre && $tag == $field->getTag()) ) { $field->delete(); $cnt++; } } return $cnt; } // }}} // {{{ addWarning() /** * Add a warning to the MARC record that something non-fatal occurred during * parsing. * * @param string $warning warning message * * @return true */ public function addWarning($warning) { $this->warnings[] = $warning; } // }}} // {{{ getWarnings() /** * Return the array of warnings from the MARC record. * * @return array warning messages */ public function getWarnings() { return $this->warnings; } // }}} // {{{ output methods /** * ========== OUTPUT METHODS ========== */ // {{{ toRaw() /** * Return the record in raw MARC format. * * If you have modified an existing MARC record or created a new MARC * record, use this method to save the record for use in other programs * that accept the MARC format -- for example, your integrated library * system. * * * // Example: Modify a record and save the output to a file * $record->deleteFields('650'); * * // Now that the record has no subject fields, save it to disk * fopen($file, '/home/dan/no_subject.mrc', 'w'); * fwrite($file, $record->toRaw()); * fclose($file); * * * @return string Raw MARC data */ function toRaw() { list($fields, $directory, $record_length, $base_address) = $this->_buildDirectory(); $this->setLeaderLengths($record_length, $base_address); /** * Glue together all parts */ return $this->getLeader().implode("", $directory).File_MARC::END_OF_FIELD.implode("", $fields).File_MARC::END_OF_RECORD; } // }}} // {{{ __toString() /** * Return the MARC record in a pretty printed string * * This method produces an easy-to-read textual display of a MARC record. * * The structure is roughly: * _ * _ * * @return string Formatted representation of MARC record */ function __toString() { // Begin output $formatted = "LDR " . $this->getLeader() . "\n"; foreach ($this->fields as $field) { if (!$field->isEmpty()) { $formatted .= $field->__toString() . "\n"; } } return $formatted; } // }}} // {{{ toJSON() /** * Return the MARC record in JSON format * * This method produces a JSON representation of a MARC record. The input * encoding must be UTF8, otherwise the returned values will be corrupted. * * @return string representation of MARC record in JSON format * * @todo Fix encoding input / output issues (PHP 6.0 required?) */ function toJSON() { $json = new StdClass(); $json->leader = utf8_encode($this->getLeader()); /* Start fields */ $fields = array(); foreach ($this->fields as $field) { if (!$field->isEmpty()) { switch(get_class($field)) { case "File_MARC_Control_Field": $fields[] = array(utf8_encode($field->getTag()) => utf8_encode($field->getData())); break; case "File_MARC_Data_Field": $subs = array(); foreach ($field->getSubfields() as $sf) { $subs[] = array(utf8_encode($sf->getCode()) => utf8_encode($sf->getData())); } $contents = new StdClass(); $contents->ind1 = utf8_encode($field->getIndicator(1)); $contents->ind2 = utf8_encode($field->getIndicator(2)); $contents->subfields = $subs; $fields[] = array(utf8_encode($field->getTag()) => $contents); break; } } } /* End fields and record */ $json->fields = $fields; return json_encode($json); } // }}} // {{{ toJSONHash() /** * Return the MARC record in Bill Dueber's MARC-HASH JSON format * * This method produces a JSON representation of a MARC record as defined * at http://robotlibrarian.billdueber.com/new-interest-in-marc-hash-json/ * The input * encoding must be UTF8, otherwise the returned values will * be corrupted. * * @return string representation of MARC record in JSON format * * @todo Fix encoding input / output issues (PHP 6.0 required?) */ function toJSONHash() { $json = new StdClass(); $json->type = "marc-hash"; $json->version = array(1, 0); $json->leader = utf8_encode($this->getLeader()); /* Start fields */ $fields = array(); foreach ($this->fields as $field) { if (!$field->isEmpty()) { switch(get_class($field)) { case "File_MARC_Control_Field": $fields[] = array(utf8_encode($field->getTag()), utf8_encode($field->getData())); break; case "File_MARC_Data_Field": $subs = array(); foreach ($field->getSubfields() as $sf) { $subs[] = array(utf8_encode($sf->getCode()), utf8_encode($sf->getData())); } $contents = array( utf8_encode($field->getTag()), utf8_encode($field->getIndicator(1)), utf8_encode($field->getIndicator(2)), $subs ); $fields[] = $contents; break; } } } /* End fields and record */ $json->fields = $fields; return json_encode($json); } // }}} // {{{ toXML() /** * Return the MARC record in MARCXML format * * This method produces an XML representation of a MARC record that * attempts to adhere to the MARCXML standard documented at * http://www.loc.gov/standards/marcxml/ * * @param string $encoding output encoding for the MARCXML record * @param bool $indent pretty-print the MARCXML record * @param bool $single wrap the element in a element * * @return string representation of MARC record in MARCXML format * * @todo Fix encoding input / output issues (PHP 6.0 required?) */ function toXML($encoding = "UTF-8", $indent = true, $single = true) { $this->marcxml->setIndent($indent); if ($single) { $this->marcxml->startElement("collection"); $this->marcxml->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim"); $this->marcxml->startElement("record"); } else { $this->marcxml->startElement("record"); $this->marcxml->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim"); } // MARCXML schema has some strict requirements // We'll set reasonable defaults to avoid invalid MARCXML $xmlLeader = $this->getLeader(); // Record status if ($xmlLeader[5] == " ") { // Default to "n" (new record) $xmlLeader[5] = "n"; } // Type of record if ($xmlLeader[6] == " ") { // Default to "a" (language material) $xmlLeader[6] = "a"; } $this->marcxml->writeElement("leader", $xmlLeader); foreach ($this->fields as $field) { if (!$field->isEmpty()) { switch(get_class($field)) { case "File_MARC_Control_Field": $this->marcxml->startElement("controlfield"); $this->marcxml->writeAttribute("tag", $field->getTag()); $this->marcxml->text($field->getData()); $this->marcxml->endElement(); // end control field break; case "File_MARC_Data_Field": $this->marcxml->startElement("datafield"); $this->marcxml->writeAttribute("tag", $field->getTag()); $this->marcxml->writeAttribute("ind1", $field->getIndicator(1)); $this->marcxml->writeAttribute("ind2", $field->getIndicator(2)); foreach ($field->getSubfields() as $subfield) { $this->marcxml->startElement("subfield"); $this->marcxml->writeAttribute("code", $subfield->getCode()); $this->marcxml->text($subfield->getData()); $this->marcxml->endElement(); // end subfield } $this->marcxml->endElement(); // end data field break; } } } $this->marcxml->endElement(); // end record if ($single) { $this->marcxml->endElement(); // end collection $this->marcxml->endDocument(); } return $this->marcxml->outputMemory(); } // }}} } // }}} PK!(#~File/MARC/Exception.phpnu[ * @author Dan Scott * @copyright 2003-2008 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id$ * @link http://pear.php.net/package/File_MARC */ // {{{ class File_MARC_Exception extends PEAR_Exception /** * The File_MARC_Exception class enables error-handling * for the File_MARC package. * * @category File_Formats * @package File_MARC * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC_Exception extends PEAR_Exception { // {{{ Error codes /** * File could not be opened */ const ERROR_INVALID_FILE = -1; /** * User passed an unknown SOURCE_ constant */ const ERROR_INVALID_SOURCE = -2; /** * MARC record ended with an invalid terminator */ const ERROR_INVALID_TERMINATOR = -3; /** * No directory was found for the MARC record */ const ERROR_NO_DIRECTORY = -4; /** * An entry in the MARC directory was not 12 bytes */ const ERROR_INVALID_DIRECTORY_LENGTH = -5; /** * An entry in the MARC directory specified an invalid tag */ const ERROR_INVALID_DIRECTORY_TAG = -6; /** * An entry in the MARC directory specified an invalid tag length */ const ERROR_INVALID_DIRECTORY_TAG_LENGTH = -7; /** * An entry in the MARC directory specified an invalid field offset */ const ERROR_INVALID_DIRECTORY_OFFSET = -8; /** * An entry in the MARC directory runs past the end of the record */ const ERROR_INVALID_DIRECTORY = -9; /** * A field does not end with the expected end-of-field character */ const ERROR_FIELD_EOF = -10; /** * A field has invalid indicators */ const ERROR_INVALID_INDICATORS = -11; /** * A subfield is defined, but has no data */ const ERROR_EMPTY_SUBFIELD = -12; /** * An indicator other than 1 or 2 was requested */ const ERROR_INVALID_INDICATOR_REQUEST = -13; /** * An invalid mode for adding a field was specified */ const ERROR_INSERTFIELD_MODE = -14; /** * An invalid object was passed instead of a File_MARC_Field object */ const ERROR_INVALID_FIELD = -15; /** * An invalid object was passed instead of a File_MARC_Subfield object */ const ERROR_INVALID_SUBFIELD = -16; /** * An invalid mode for adding a subfield was specified */ const ERROR_INSERTSUBFIELD_MODE = -17; /** * The length in the MARC leader does not match the actual record length */ const ERROR_INCORRECT_LENGTH = -18; /** * The length field in the leader was less than five characters long */ const ERROR_MISSING_LENGTH = -19; /** * A five-digit length could not be found in the MARC leader */ const ERROR_NONNUMERIC_LENGTH = -20; /** * Tag does not adhere to MARC standards */ const ERROR_INVALID_TAG = -21; /** * A field has invalid indicators */ const ERROR_INVALID_INDICATOR = -22; // }}} // {{{ error messages public static $messages = array( self::ERROR_EMPTY_SUBFIELD => 'No subfield data found in tag "%tag%"', self::ERROR_FIELD_EOF => 'Field for tag "%tag%" does not end with an end of field character', self::ERROR_INCORRECT_LENGTH => 'Invalid record length: Leader says "%record_length%" bytes; actual record length is "%actual%"', self::ERROR_INSERTFIELD_MODE => 'insertField() mode "%mode%" was not recognized', self::ERROR_INSERTSUBFIELD_MODE => 'insertSubfield() mode "%mode%" was not recognized', self::ERROR_INVALID_DIRECTORY => 'Directory entry for tag "%tag%" runs past the end of the record', self::ERROR_INVALID_DIRECTORY_LENGTH => 'Invalid directory length', self::ERROR_INVALID_DIRECTORY_OFFSET => 'Invalid offset "%offset%" for tag "%tag%" in directory', self::ERROR_INVALID_DIRECTORY_TAG => 'Invalid tag "%tag%" in directory', self::ERROR_INVALID_DIRECTORY_TAG_LENGTH => 'Invalid length "%len%" in directory for tag "%tag%"', self::ERROR_INVALID_FIELD => 'Specified field must be a File_MARC_Data_Field or File_MARC_Control_Field object, but was "%field%"', self::ERROR_INVALID_FILE => 'Invalid input file "%filename%"', self::ERROR_INVALID_INDICATOR_REQUEST => 'Attempt to access indicator "%indicator%" failed; 1 and 2 are the only valid indicators', self::ERROR_INVALID_INDICATORS => 'Invalid indicators "%indicators%" forced to blanks for tag "%tag%"', self::ERROR_INVALID_SOURCE => "Invalid source for MARC records", self::ERROR_INVALID_SUBFIELD => 'Specified field must be a File_MARC_Subfield object, but was "%class%"', self::ERROR_INVALID_TAG => 'Tag "%tag%" is not a valid tag.', self::ERROR_INVALID_TERMINATOR => 'Invalid record terminator', self::ERROR_MISSING_LENGTH => "Couldn't find record length", self::ERROR_NO_DIRECTORY => 'No directory found', self::ERROR_NONNUMERIC_LENGTH => 'Record length "%record_length%" is not numeric', self::ERROR_INVALID_INDICATOR => 'Illegal indicator "%indicator%" in field "%tag%" forced to blank', ); // }}} // {{{ formatError() /** * Replaces placeholder tokens in an error message with actual values. * * This method enables you to internationalize the messages for the * File_MARC class by simply replacing the File_MARC_Exception::$messages * array with translated values for the messages. * * @param string $message Error message containing placeholders * @param array $errorValues Actual values to substitute for placeholders * * @return string Formatted message */ public static function formatError($message, $errorValues) { foreach ($errorValues as $token => $value) { $message = preg_replace("/\%$token\%/", $value, $message); } return $message; } // }}} } // }}} PK!灴4 File/MARC/List.phpnu[ * @author Dan Scott * @copyright 2003-2008 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id$ * @link http://pear.php.net/package/File_MARC */ // {{{ class File_MARC_List extends Structures_LinkedList_Double /** * The File_MARC_List class extends the Structures_LinkedList_Double class * to override the key() method in a meaningful way for foreach() iterators. * * For the list of {@link File_MARC_Field} objects in a {@link File_MARC_Record} * object, the key() method returns the tag name of the field. * * For the list of {@link File_MARC_Subfield} objects in a {@link * File_MARC_Data_Field} object, the key() method returns the code of * the subfield. * * * // Iterate through the fields in a record with key=>value iteration * foreach ($record->getFields() as $tag=>$value) { * print "$tag: "; * if ($value instanceof File_MARC_Control_Field) { * print $value->getData(); * } * else { * // Iterate through the subfields in this data field * foreach ($value->getSubfields() as $code=>$subdata) { * print "_$code"; * } * } * print "\n"; * } * * * @category File_Formats * @package File_MARC * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC_List extends Structures_LinkedList_Double { // {{{ key() /** * Returns the tag for a {@link File_MARC_Field} object, or the code * for a {@link File_MARC_Subfield} object. * * This method enables you to use a foreach iterator to retrieve * the tag or code as the key for the iterator. * * @return string returns the tag or code */ function key() { if ($this->current() instanceof File_MARC_Field) { return $this->current()->getTag(); } elseif ($this->current() instanceof File_MARC_Subfield) { return $this->current()->getCode(); } return false; } // }}} } // }}} PK!<`File/MARC/Field.phpnu[ * @author Dan Scott * @copyright 2003-2008 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id$ * @link http://pear.php.net/package/File_MARC */ // {{{ class File_MARC_Field extends Structures_LinkedList_DoubleNode /** * The File_MARC_Field class is expected to be extended to reflect the * requirements of control and data fields. * * Every MARC field contains a tag name. * * @category File_Formats * @package File_MARC * @author Christoffer Landtman * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC_Field extends Structures_LinkedList_DoubleNode { // {{{ properties /** * The tag name of the Field * @var string */ protected $tag; // }}} // {{{ Constructor: function __construct() /** * File_MARC_Field constructor * * Create a new {@link File_MARC_Field} object from passed arguments. We * define placeholders for the arguments required by child classes. * * @param string $tag tag * @param string $subfields placeholder for subfields or control data * @param string $ind1 placeholder for first indicator * @param string $ind2 placeholder for second indicator */ function __construct($tag, $subfields = null, $ind1 = null, $ind2 = null) { $this->tag = $tag; // Check if valid tag if (!preg_match("/^[0-9A-Za-z]{3}$/", $tag)) { $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_TAG], array("tag" => $tag)); throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_TAG); } } // }}} // {{{ Destructor: function __destruct() /** * Destroys the data field */ function __destruct() { $this->tag = null; parent::__destruct(); } // }}} // {{{ getTag() /** * Returns the tag for this {@link File_MARC_Field} object * * @return string returns the tag number of the field */ function getTag() { return (string)$this->tag; } // }}} // {{{ setTag() /** * Sets the tag for this {@link File_MARC_Field} object * * @param string $tag new value for the tag * * @return string returns the tag number of the field */ function setTag($tag) { $this->tag = $tag; return $this->getTag(); } // }}} // {{{ isEmpty() /** * Is empty * * Checks if the field is empty. * * @return bool Returns true if the field is empty, otherwise false */ function isEmpty() { if ($this->getTag()) { return false; } // It is empty return true; } // }}} // {{{ isControlField() /** * Is control field * * Checks if the field is a control field. * * @return bool Returns true if the field is a control field, otherwise false */ function isControlField() { if (get_class($this) == 'File_MARC_Control_Field') { return true; } return false; } // }}} // {{{ isDataField() /** * Is data field * * Checks if the field is a data field. * * @return bool Returns true if the field is a data field, otherwise false */ function isDataField() { if (get_class($this) == 'File_MARC_Data_Field') { return true; } return false; } // }}} /** * ========== OUTPUT METHODS ========== */ // {{{ __toString() /** * Return Field formatted * * Return Field as a formatted string. * * @return string Formatted output of Field */ function __toString() { return (string)$this->getTag(); } // }}} // {{{ toRaw() /** * Return field in raw MARC format (stub) * * Return the field formatted in raw MARC for saving into MARC files. This * stub method is extended by the child classes. * * @return bool Raw MARC */ function toRaw() { return false; } // }}} // {{{ formatField() /** * Pretty print a MARC_Field object without tags, indicators, etc. * * @param array $exclude Subfields to exclude from formatted output * * @return string Returns the formatted field data */ function formatField($exclude = array('2')) { if ($this->isControlField()) { return $this->getData(); } else { $out = ''; foreach ($this->getSubfields() as $subfield) { if (substr($this->getTag(), 0, 1) == '6' and (in_array($subfield->getCode(), array('v','x','y','z')))) { $out .= ' -- ' . $subfield->getData(); } elseif (!in_array($subfield->getCode(), $exclude)) { $out .= ' ' . $subfield->getData(); } } return trim($out); } } // }}} } // }}} PK!t;;File/MARC/Lint/CodeData.phpnu[ and available for download at * http://search.cpan.org/~eijabb/ * * Current MARC::Lint::CodeData version used as basis for this module: 1.28 * * PHP version 5 * * LICENSE: 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 2.1 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @category File_Formats * @package File_MARC * @author Demian Katz * @author Dan Scott * @copyright 2003-2008 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id: Record.php 308146 2011-02-08 20:36:20Z dbs $ * @link http://pear.php.net/package/File_MARC */ // {{{ class File_MARC_Lint /** * Contains codes from the MARC code lists for Geographic Areas, Languages, and * Countries. * * Code data is used for validating fields 008, 040, 041, and 043. * * Also, sources for subfield 2 in 600-651 and 655. * * Note: According to the official MARC documentation, Sears is not a valid 655 * term. The code data below treats it as valid, in anticipation of a change in * the official documentation. * * @category File_Formats * @package File_MARC * @author Demian Katz * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC_Lint_CodeData { // {{{ properties /** * Valid Geographic Area Codes * @var array */ public $geogAreaCodes; /** * Obsolete Geographic Area Codes * @var array */ public $obsoleteGeogAreaCodes; /** * Valid Language Codes * @var array */ public $languageCodes; /** * Obsolete Language Codes * @var array */ public $obsoleteLanguageCodes; /** * Valid Country Codes * @var array */ public $countryCodes; /** * Obsolete Country Codes * @var array */ public $obsoleteCountryCodes; /** * Valid sources for fields 600-651 * @var array */ public $sources600_651; /** * Obsolete sources for fields 600-651 * @var array */ public $obsoleteSources600_651; /** * Valid sources for field 655 * @var array */ public $sources655; /** * Obsolete sources for field 655 * @var array */ public $obsoleteSources655; // }}} // {{{ Constructor: function __construct() /** * Start function * * Initialize code arrays. * * @return true */ public function __construct() { // @codingStandardsIgnoreStart // fill the valid Geographic Area Codes array $this->geogAreaCodes = explode("\t", "a-af--- f------ fc----- fe----- fq----- ff----- fh----- fs----- fb----- fw----- n-us-al n-us-ak e-aa--- n-cn-ab f-ae--- ea----- sa----- poas--- aa----- sn----- e-an--- f-ao--- nwxa--- a-cc-an t------ nwaq--- nwla--- n-usa-- ma----- ar----- au----- r------ s-ag--- n-us-az n-us-ar a-ai--- nwaw--- lsai--- u-ac--- a------ ac----- as----- l------ fa----- u------ u-at--- u-at-ac e-au--- a-aj--- lnaz--- nwbf--- a-ba--- ed----- eb----- a-bg--- nwbb--- a-cc-pe e-bw--- e-be--- ncbh--- el----- ab----- f-dm--- lnbm--- a-bt--- mb----- a-ccp-- s-bo--- nwbn--- a-bn--- e-bn--- f-bs--- lsbv--- s-bl--- n-cn-bc i-bi--- nwvb--- a-bx--- e-bu--- f-uv--- a-br--- f-bd--- n-us-ca a-cb--- f-cm--- n-cn--- nccz--- lnca--- lncv--- cc----- poci--- ak----- e-urk-- e-urr-- nwcj--- f-cx--- nc----- e-urc-- f-cd--- s-cl--- a-cc--- a-cc-cq i-xa--- i-xb--- q------ s-ck--- n-us-co b------ i-cq--- f-cf--- f-cg--- fg----- n-us-ct pocw--- u-cs--- nccr--- e-ci--- nwcu--- nwco--- a-cy--- e-xr--- e-cs--- f-iv--- eo----- zd----- n-us-de e-dk--- dd----- d------ f-ft--- nwdq--- nwdr--- x------ n-usr-- ae----- an----- a-em--- poea--- xa----- s-ec--- f-ua--- nces--- e-uk-en f-eg--- f-ea--- e-er--- f-et--- me----- e------ ec----- ee----- en----- es----- ew----- lsfk--- lnfa--- pofj--- e-fi--- n-us-fl e-fr--- h------ s-fg--- pofp--- a-cc-fu f-go--- pogg--- f-gm--- a-cc-ka awgz--- n-us-ga a-gs--- e-gx--- e-ge--- e-gw--- f-gh--- e-gi--- e-uk--- e-uk-ui nl----- np----- fr----- e-gr--- n-gl--- nwgd--- nwgp--- pogu--- a-cc-kn a-cc-kc ncgt--- f-gv--- f-pg--- a-cc-kw s-gy--- a-cc-ha nwht--- n-us-hi i-hm--- a-cc-hp a-cc-he a-cc-ho ah----- nwhi--- ncho--- a-cc-hk a-cc-hh n-cnh-- a-cc-hu e-hu--- e-ic--- n-us-id n-us-il a-ii--- i------ n-us-in ai----- a-io--- a-cc-im m------ c------ n-us-ia a-ir--- a-iq--- e-ie--- a-is--- e-it--- nwjm--- lnjn--- a-ja--- a-cc-ku a-cc-ki a-cc-kr poji--- a-jo--- zju---- n-us-ks a-kz--- n-us-ky f-ke--- poki--- pokb--- a-kr--- a-kn--- a-ko--- a-cck-- a-ku--- a-kg--- a-ls--- cl----- e-lv--- a-le--- nwli--- f-lo--- a-cc-lp f-lb--- f-ly--- e-lh--- poln--- e-li--- n-us-la e-lu--- a-cc-mh e-xn--- f-mg--- lnma--- n-us-me f-mw--- am----- a-my--- i-xc--- f-ml--- e-mm--- n-cn-mb poxd--- n-cnm-- zma---- poxe--- nwmq--- n-us-md n-us-ma f-mu--- i-mf--- i-my--- mm----- ag----- pome--- zme---- n-mx--- nm----- n-us-mi pott--- pomi--- n-usl-- aw----- n-usc-- poxf--- n-us-mn n-us-ms n-usm-- n-us-mo n-uss-- e-mv--- e-mc--- a-mp--- n-us-mt nwmj--- zmo---- f-mr--- f-mz--- f-sx--- ponu--- n-us-nb a-np--- zne---- e-ne--- nwna--- n-us-nv n-cn-nk ponl--- n-usn-- a-nw--- n-us-nh n-us-nj n-us-nm u-at-ne n-us-ny u-nz--- n-cn-nf ncnq--- f-ng--- fi----- f-nr--- fl----- a-cc-nn poxh--- n------ ln----- n-us-nc n-us-nd pn----- n-use-- xb----- e-uk-ni u-at-no n-cn-nt e-no--- n-cn-ns n-cn-nu po----- n-us-oh n-uso-- n-us-ok a-mk--- n-cn-on n-us-or zo----- p------ a-pk--- popl--- ncpn--- a-pp--- aopf--- s-py--- n-us-pa ap----- s-pe--- a-ph--- popc--- zpl---- e-pl--- pops--- e-po--- n-cnp-- n-cn-pi nwpr--- ep----- a-qa--- a-cc-ts u-at-qn n-cn-qu mr----- er----- n-us-ri sp----- nr----- e-rm--- e-ru--- e-ur--- e-urf-- f-rw--- i-re--- nwsd--- fd----- nweu--- lsxj--- nwxi--- nwxk--- nwst--- n-xl--- nwxm--- pows--- posh--- e-sm--- f-sf--- n-cn-sn zsa---- a-su--- ev----- e-uk-st f-sg--- i-se--- a-cc-ss a-cc-sp a-cc-sm a-cc-sh e-urs-- e-ure-- e-urw-- a-cc-sz f-sl--- a-si--- e-xo--- e-xv--- i-xo--- zs----- pobp--- f-so--- f-sa--- s------ az----- ls----- u-at-sa n-us-sc ao----- n-us-sd lsxs--- ps----- xc----- n-usu-- n-ust-- e-urn-- e-sp--- f-sh--- aoxp--- a-ce--- f-sj--- fn----- fu----- zsu---- s-sr--- lnsb--- nwsv--- f-sq--- e-sw--- e-sz--- a-sy--- a-ch--- a-ta--- f-tz--- u-at-tm n-us-tn i-fs--- n-us-tx a-th--- af----- a-cc-tn a-cc-ti at----- f-tg--- potl--- poto--- nwtr--- lstd--- w------ f-ti--- a-tu--- a-tk--- nwtc--- potv--- f-ug--- e-un--- a-ts--- n-us--- nwuc--- poup--- e-uru-- zur---- s-uy--- n-us-ut a-uz--- ponn--- e-vc--- s-ve--- zve---- n-us-vt u-at-vi a-vt--- nwvi--- n-us-va e-urp-- fv----- powk--- e-uk-wl powf--- n-us-dc n-us-wa n-usp-- awba--- nw----- n-us-wv u-at-we xd----- f-ss--- nwwi--- n-us-wi n-us-wy a-ccs-- a-cc-su a-ccg-- a-ccy-- ay----- a-ye--- e-yu--- n-cn-yk a-cc-yu fz----- f-za--- a-cc-ch f-rh--- u-atc-- u-ate-- u-atn-- e-rb--- e-mo--- e-kv---"); // fill the obsolete Geographic Area Codes array $this->obsoleteGeogAreaCodes = explode("\t", "t-ay--- e-ur-ai e-ur-aj nwbc--- e-ur-bw f-by--- pocp--- e-url-- cr----- v------ e-ur-er et----- e-ur-gs pogn--- nwga--- nwgs--- a-hk--- ei----- f-if--- awiy--- awiw--- awiu--- e-ur-kz e-ur-kg e-ur-lv e-ur-li a-mh--- cm----- e-ur-mv n-usw-- a-ok--- a-pt--- e-ur-ru pory--- nwsb--- posc--- a-sk--- posn--- e-uro-- e-ur-ta e-ur-tk e-ur-un e-ur-uz a-vn--- a-vs--- nwvr--- e-urv-- a-ys---"); // fill the valid Language Codes array $this->languageCodes = explode("\t", " aar abk ace ach ada ady afa afh afr ain aka akk alb ale alg alt amh ang anp apa ara arc arg arm arn arp art arw asm ast ath aus ava ave awa aym aze bad bai bak bal bam ban baq bas bat bej bel bem ben ber bho bih bik bin bis bla bnt bos bra bre btk bua bug bul bur byn cad cai car cat cau ceb cel cha chb che chg chi chk chm chn cho chp chr chu chv chy cmc cop cor cos cpe cpf cpp cre crh crp csb cus cze dak dan dar day del den dgr din div doi dra dsb dua dum dut dyu dzo efi egy eka elx eng enm epo est ewe ewo fan fao fat fij fil fin fiu fon fre frm fro frr frs fry ful fur gaa gay gba gem geo ger gez gil gla gle glg glv gmh goh gon gor got grb grc gre grn gsw guj gwi hai hat hau haw heb her hil him hin hit hmn hmo hrv hsb hun hup iba ibo ice ido iii ijo iku ile ilo ina inc ind ine inh ipk ira iro ita jav jbo jpn jpr jrb kaa kab kac kal kam kan kar kas kau kaw kaz kbd kha khi khm kho kik kin kir kmb kok kom kon kor kos kpe krc krl kro kru kua kum kur kut lad lah lam lao lat lav lez lim lin lit lol loz ltz lua lub lug lui lun luo lus mac mad mag mah mai mak mal man mao map mar mas may mdf mdr men mga mic min mis mkh mlg mlt mnc mni mno moh mon mos mul mun mus mwl mwr myn myv nah nai nap nau nav nbl nde ndo nds nep new nia nic niu nno nob nog non nor nqo nso nub nwc nya nym nyn nyo nzi oci oji ori orm osa oss ota oto paa pag pal pam pan pap pau peo per phi phn pli pol pon por pra pro pus que raj rap rar roa roh rom rum run rup rus sad sag sah sai sal sam san sas sat scn sco sel sem sga sgn shn sid sin sio sit sla slo slv sma sme smi smj smn smo sms sna snd snk sog som son sot spa srd srn srp srr ssa ssw suk sun sus sux swa swe syc syr tah tai tam tat tel tem ter tet tgk tgl tha tib tig tir tiv tkl tlh tli tmh tog ton tpi tsi tsn tso tuk tum tup tur tut tvl twi tyv udm uga uig ukr umb und urd uzb vai ven vie vol vot wak wal war was wel wen wln wol xal xho yao yap yid yor ypk zap zbl zen zha znd zul zun zxx zza"); // fill the obsolete Language Codes array $this->obsoleteLanguageCodes = explode("\t", "ajm esk esp eth far fri gag gua int iri cam kus mla max mol lan gal lap sao gae scc scr sho snh sso swz tag taj tar tru tsw"); // fill the valid Country Codes array $this->countryCodes = explode("\t", "aca af alu aku aa abc ae as an ao am ay aq ag azu aru ai aw at au aj bf ba bg bb bw be bh dm bm bt bo bn bs bv bl bcc bi vb bx bu uv br bd cau cb cm xxc cv cj cx cd cl cc ch xa xb ck cou cq cf cg ctu cw cr ci cu cy xr iv deu dk dcu ft dq dr em ec ua es enk eg ea er et fk fa fj fi flu fr fg fp go gm gz gau gs gw gh gi gr gl gd gp gu gt gv pg gy ht hiu hm ho hu ic idu ilu ii inu io iau ir iq iy ie is it jm ja ji jo ksu kv kz kyu ke gb kn ko ku kg ls lv le lo lb ly lh li lau lu xn mg meu mw my xc ml mm mbc xe mq mdu mau mu mf ot mx miu fm xf mnu msu mou mv mc mp mtu mj mr mz sx nu nbu np ne na nvu nkc nl nhu nju nmu nyu nz nfc nq ng nr xh xx nx ncu ndu nik nw ntc no nsc nuc ohu oku mk onc oru pk pw pn pp pf py pau pe ph pc pl po pic pr qa qea quc riu rm ru rw re xj xd xk xl xm ws sm sf snc su stk sg rb mo se sl si xo xv bp so sa scu sdu xs sp sh xp ce sj sr sq sw sz sy ta tz tnu fs txu th tg tl tma to tr ti tu tk tc tv ug un ts xxk uik xxu uc up uy utu uz nn vp vc ve vtu vm vi vau vra wea wk wlk wf wau wj wvu ss wiu wyu xga xna xoa xra ye ykc za rh "); // fill the obsolete Country Codes array $this->obsoleteCountryCodes = explode("\t", "ai air ac ajr bwr cn cz cp ln cs err gsr ge gn hk iw iu jn kzr kgr lvr lir mh mvr nm pt rur ry xi sk xxr sb sv tar tt tkr unr uk ui us uzr vn vs wb ys yu "); // the codes cash, lcsh, lcshac, mesh, nal, and rvm are covered by 2nd // indicators in 600-655 // they are only used when indicators are not available $this->sources600_651 = explode("\t", "aass aat abne afset agrifors agrovoc agrovocf agrovocs aiatsisl aiatsisp aiatsiss aktp albt allars amg apaist asft asrcrfcd asrcseo asrctoa asth atla aucsh barn bella bet bgtchm bhammf bhashe bibalex biccbmc bicssc bidex bisacsh bisacmt bisacrt blmlsh bt cabt cash cct ccte cctf ceeus chirosh cht ciesiniv cilla conorsi csahssa csalsct csapa csh csht cstud czenas dacs dcs ddcrit dissao dit drama dtict ebfem eclas eet eflch eks embne ept ericd est eurovocen eurovocsl fast fgtpcm finmesh fire fmesh fnhl francis galestne gem georeft gst gtt hapi hkcan helecon henn hlasstg hoidokki huc iaat ica icpsr idas iescs iest ilot ilpt inist inspect ipat ipsp isis itglit itoamc itrt jhpb jhpk jlabsh kaa kao kaunokki kdm kitu kkts kssbar kta ktpt ktta kula kupu lacnaf larpcal lcsh lcshac lcstt lctgm lemac lemb liv lnmmbr local ltcsh lua maaq mar masa mech mesh mipfesd mmm mpirdes msh mtirdes musa muzeukc muzeukn muzeukv muzvukci nal nalnaf nasat ncjt ndllsh nicem nimacsc nlgaf nlgkk nlgsh nlmnaf nsbncf ntcpsc ntcsd ntissc nzggn nznb ogst onet opms pascal peri pha pkk pmbok pmcsg pmt poliscit popinte precis prvt psychit quiding qlsp qrma qrmak qtglit raam ram rasuqam renib reo rero rerovoc reveal rma rpe rswk rswkaf rugeo rurkp rvm sao sbiao scbi scgdst scisshl scot sears sfit sgc sgce shbe she sigle sipri sk skon slem smda snt socio sosa spines ssg swd swemesh taika taxhs tbit tesa test tgn tho thub tlka tlsh toit trt trtsa tsht ttka tucua ulan umitrist unbisn unbist unescot usaidt vmj waqaf watrest wgst wot wpicsh ysa"); $this->obsoleteSources600_651 = explode("\t", "cash lcsh lcshac mesh nal reroa rvm"); $this->sources655 = explode("\t", "aat afset aiatsisl aiatsisp aiatsiss aktp amg asrcrfcd asrcseo asrctoa asth aucsh barn bibalex biccbmc bgtchm bisacsh bisacmt bisacrt bt cash chirosh cct conorsi csht czenas dacs dcs dct eet eflch embne ept ericd estc eurovocen eurovocsl fast fbg finmesh fire galestne gem gmgpc gsafd gst gtlm hapi hkcan hoidokki ica ilot itglit itrt jhpb jhpk kkts lacnaf lcsh lcshac lcstt lctgm lemac local maaq mar marcgt mech mesh migfg mim msh muzeukc muzeukn muzeukv muzvukci nal nalnaf ngl nimafc nlgaf nlgkk nlgsh nlmnaf nmc nsbncf nzggn nznb onet opms pkk pmcsg pmt quiding qlsp qrmak qtglit raam radfg rbbin rbgenr rbpap rbpri rbprov rbpub rbtyp reo rerovoc reveal rma rswk rswkaf rugeo rvm sao scbi sears sgc sgce sgp sipri skon snt socio spines ssg swd swemesh tbit tesa tho thub toit tsht tucua ulan vmj waqaf"); $this->obsoleteSources655 = explode("\t", "cash ftamc lcsh lcshac mesh nal reroa rvm"); // @codingStandardsIgnoreEnd } // }}} } // }}} PK!j:j:File/MARC/Data_Field.phpnu[ * @author Dan Scott * @copyright 2003-2008 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id$ * @link http://pear.php.net/package/File_MARC */ // {{{ class File_MARC_Data_Field extends File_MARC_Field /** * The File_MARC_Data_Field class represents a single field in a MARC record. * * A MARC data field consists of a tag name, two indicators which may be null, * and zero or more subfields represented by {@link File_MARC_Subfield} objects. * Subfields are held within a linked list structure. * * @category File_Formats * @package File_MARC * @author Christoffer Landtman * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC_Data_Field extends File_MARC_Field { // {{{ properties /** * Value of the first indicator * @var string */ protected $ind1; /** * Value of the second indicator * @var string */ protected $ind2; /** * Linked list of subfields * @var File_MARC_List */ protected $subfields; // }}} // {{{ Constructor: function __construct() /** * {@link File_MARC_Data_Field} constructor * * Create a new {@link File_MARC_Data_Field} object. The only required * parameter is a tag. This enables programs to build up new fields * programmatically. * * * // Example: Create a new data field * * // We can optionally create an array of subfields first * $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.'); * * // Create the new 100 field complete with a _a subfield and an indicator * $new_field = new File_MARC_Data_Field('100', $subfields, 0, null); * * * @param string $tag tag * @param array $subfields array of {@link File_MARC_Subfield} objects * @param string $ind1 first indicator * @param string $ind2 second indicator */ function __construct($tag, array $subfields = null, $ind1 = null, $ind2 = null) { $this->subfields = new File_MARC_List(); parent::__construct($tag); $this->ind1 = $this->_validateIndicator($ind1); $this->ind2 = $this->_validateIndicator($ind2); // we'll let users add subfields after if they so desire if ($subfields) { $this->addSubfields($subfields); } } // }}} // {{{ Destructor: function __destruct() /** * Destroys the data field */ function __destruct() { $this->subfields = null; $this->ind1 = null; $this->ind2 = null; parent::__destruct(); } // }}} // {{{ Explicit destructor: function delete() /** * Destroys the data field * * @return true */ function delete() { $this->__destruct(); } // }}} // {{{ protected function _validateIndicator() /** * Validates an indicator field * * Validates the value passed in for an indicator. This routine ensures * that an indicator is a single character. If the indicator value is null, * then this method returns a single character. * * If the indicator value contains more than a single character, this * throws an exception. * * @param string $indicator Value of the indicator to be validated * * @return string Returns the indicator, or space if the indicator was null */ private function _validateIndicator($indicator) { if ($indicator == null) { $indicator = ' '; } elseif (strlen($indicator) > 1) { $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR], array("tag" => $this->getTag(), "indicator" => $indicator)); throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR); } return $indicator; } // }}} // {{{ appendSubfield() /** * Appends subfield to subfield list * * Adds a File_MARC_Subfield object to the end of the existing list * of subfields. * * @param File_MARC_Subfield $new_subfield The subfield to add * * @return File_MARC_Subfield the new File_MARC_Subfield object */ function appendSubfield(File_MARC_Subfield $new_subfield) { /* Append as the last field in the record */ $this->subfields->appendNode($new_subfield); return $new_subfield; } // }}} // {{{ prependSubfield() /** * Prepends subfield to subfield liss * * Adds a File_MARC_Subfield object to the start of the existing list * of subfields. * * @param File_MARC_Subfield $new_subfield The subfield to add * * @return File_MARC_Subfield the new File_MARC_Subfield object */ function prependSubfield(File_MARC_Subfield $new_subfield) { $this->subfields->prependNode($new_subfield); return $new_subfield; } // }}} // {{{ insertSubfield() /** * Inserts a field in the MARC record relative to an existing field * * Inserts a {@link File_MARC_Subfield} object before or after an existing * subfield. * * @param File_MARC_Subfield $new_field The subfield to add * @param File_MARC_Subfield $existing_field The target subfield * @param bool $before Insert the subfield before the existing subfield if true; after the existing subfield if false * * @return File_MARC_Subfield The new subfield */ function insertSubfield(File_MARC_Subfield $new_field, File_MARC_Subfield $existing_field, $before = false) { switch ($before) { /* Insert before the specified subfield in the record */ case true: $this->subfields->insertNode($new_field, $existing_field, true); break; /* Insert after the specified subfield in the record */ case false: $this->subfields->insertNode($new_field, $existing_field); break; default: $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INSERTSUBFIELD_MODE], array("mode" => $mode)); throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INSERTSUBFIELD_MODE); return false; } return $new_field; } // }}} // {{{ addSubfields() /** * Adds an array of subfields to a {@link File_MARC_Data_Field} object * * Appends subfields to existing subfields in the order in which * they appear in the array. For finer grained control of the subfield * order, use {@link appendSubfield()}, {@link prependSubfield()}, * or {@link insertSubfield()} to add each subfield individually. * * @param array $subfields array of {@link File_MARC_Subfield} objects * * @return int returns the number of subfields that were added */ function addSubfields(array $subfields) { /* * Just in case someone passes in a single File_MARC_Subfield * instead of an array */ if ($subfields instanceof File_MARC_Subfield) { $this->appendSubfield($subfields); return 1; } // Add subfields $cnt = 0; foreach ($subfields as $subfield) { $this->appendSubfield($subfield); $cnt++; } return $cnt; } // }}} // {{{ deleteSubfield() /** * Delete a subfield from the field. * * @param File_MARC_Subfield $subfield The subfield to delete * * @return bool Success or failure */ function deleteSubfield(File_MARC_Subfield $subfield) { if ($this->subfields->deleteNode($subfield)) { return true; } return false; } // }}} // {{{ getIndicator() /** * Get the value of an indicator * * @param int $ind number of the indicator (1 or 2) * * @return string returns indicator value if it exists, otherwise false */ function getIndicator($ind) { if ($ind == 1) { return (string)$this->ind1; } elseif ($ind == 2) { return (string)$this->ind2; } else { $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST], array("indicator" => $indicator)); throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST); } return false; } // }}} // {{{ setIndicator() /** * Set the value of an indicator * * @param int $ind number of the indicator (1 or 2) * @param string $value value of the indicator * * @return string returns indicator value if it exists, otherwise false */ function setIndicator($ind, $value) { switch ($ind) { case 1: $this->ind1 = $this->_validateIndicator($value); break; case 2: $this->ind2 = $this->_validateIndicator($value); break; default: $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST], array("indicator" => $ind)); throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST); return false; } return $this->getIndicator($ind); } // }}} // {{{ getSubfield() /** * Returns the first subfield that matches a requested code. * * @param string $code subfield code for which the * {@link File_MARC_Subfield} is retrieved * * @return File_MARC_Subfield returns the first subfield that matches * $code, or false if no codes match $code */ function getSubfield($code = null) { // iterate merrily through the subfields looking for the requested code foreach ($this->subfields as $sf) { if ($sf->getCode() == $code) { return $sf; } } // No matches were found return false; } // }}} // {{{ getSubfields() /** * Returns an array of subfields that match a requested code, * or a {@link File_MARC_List} that contains all of the subfields * if the requested code is null. * * @param string $code subfield code for which the * {@link File_MARC_Subfield} is retrieved * * @return File_MARC_List|array returns a linked list of all subfields * if $code is null, an array of {@link File_MARC_Subfield} objects if * one or more subfields match, or false if no codes match $code */ function getSubfields($code = null) { $results = array(); // return all subfields if no specific subfields were requested if ($code === null) { $results = $this->subfields; return $results; } // iterate merrily through the subfields looking for the requested code foreach ($this->subfields as $sf) { if ($sf->getCode() == $code) { $results[] = $sf; } } return $results; } // }}} // {{{ isEmpty() /** * Checks if the field is empty. * * Checks if the field is empty. If the field has at least one subfield * with data, it is not empty. * * @return bool Returns true if the field is empty, otherwise false */ function isEmpty() { // If $this->subfields is null, we must have deleted it if (!$this->subfields) { return true; } // Iterate through the subfields looking for some data foreach ($this->subfields as $subfield) { // Check if subfield has data if (!$subfield->isEmpty()) { return false; } } // It is empty return true; } // }}} /** * ========== OUTPUT METHODS ========== */ // {{{ __toString() /** * Return Field formatted * * Return Field as a formatted string. * * @return string Formatted output of Field */ function __toString() { // Variables $lines = array(); // Process tag and indicators $pre = sprintf("%3s %1s%1s", $this->tag, $this->ind1, $this->ind2); // Process subfields foreach ($this->subfields as $subfield) { $lines[] = sprintf("%6s _%1s%s", $pre, $subfield->getCode(), $subfield->getData()); $pre = ""; } return join("\n", $lines); } // }}} // {{{ toRaw() /** * Return Field in Raw MARC * * Return the Field formatted in Raw MARC for saving into MARC files * * @return string Raw MARC */ function toRaw() { $subfields = array(); foreach ($this->subfields as $subfield) { if (!$subfield->isEmpty()) { $subfields[] = $subfield->toRaw(); } } return (string)$this->ind1.$this->ind2.implode("", $subfields).File_MARC::END_OF_FIELD; } // }}} } // }}} PK!lz`File/MARC/Control_Field.phpnu[ * @author Dan Scott * @copyright 2003-2008 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id$ * @link http://pear.php.net/package/File_MARC */ // {{{ class File_MARC_Control_Field extends File_MARC_Field /** * The File_MARC_Control_Field class represents a single control field * in a MARC record. * * A MARC control field consists of a tag name and control data. * * @category File_Formats * @package File_MARC * @author Christoffer Landtman * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC_Control_Field extends File_MARC_Field { // {{{ Properties /** * Value of field, if field is a Control field * @var string */ protected $data; // }}} // {{{ Constructor: function __construct() /** * Field init function * * Create a new {@link File_MARC_Control_Field} object from passed arguments * * @param string $tag tag * @param string $data control field data * @param string $ind1 placeholder for class strictness * @param string $ind2 placeholder for class strictness */ function __construct($tag, $data, $ind1 = null, $ind2 = null) { $this->data = $data; parent::__construct($tag); } // }}} // {{{ Destructor: function __destruct() /** * Destroys the control field */ function __destruct() { $this->data = null; parent::__destruct(); } // }}} // {{{ Explicit destructor: function delete() /** * Destroys the control field * * @return true */ function delete() { $this->__destruct(); } // }}} // {{{ getData() /** * Get control field data * * @return string returns data in control field */ function getData() { return (string)$this->data; } // }}} // {{{ isEmpty() /** * Is empty * * Checks if the field contains data * * @return bool Returns true if the field is empty, otherwise false */ function isEmpty() { return ($this->data) ? false : true; } // }}} // {{{ setData() /** * Set control field data * * @param string $data data for the control field * * @return bool returns the new data in the control field */ function setData($data) { $this->data = $data; return $this->getData(); } // }}} // {{{ __toString() /** * Return as a formatted string * * Return the control field as a formatted string for pretty printing * * @return string Formatted output of control Field */ function __toString() { return sprintf("%3s %s", $this->tag, $this->data); } // }}} // {{{ toRaw() /** * Return as raw MARC * * Return the control field formatted in Raw MARC for saving into MARC files * * @return string Raw MARC */ function toRaw() { return (string)$this->data.File_MARC::END_OF_FIELD; } // }}} } // }}} PK!Ē˪File/MARC/Lint.phpnu[ and available at http://search.cpan.org/~eijabb/ * * Current MARC::Lint version used as basis for this module: 1.44 * * PHP version 5 * * LICENSE: 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 2.1 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * @category File_Formats * @package File_MARC * @author Demian Katz * @author Dan Scott * @copyright 2003-2008 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id: Record.php 308146 2011-02-08 20:36:20Z dbs $ * @link http://pear.php.net/package/File_MARC */ require_once 'File/MARC/Lint/CodeData.php'; require_once 'Validate/ISPN.php'; // {{{ class File_MARC_Lint /** * Class for testing validity of MARC records against MARC21 standard. * * @category File_Formats * @package File_MARC * @author Demian Katz * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC_Lint { // {{{ properties /** * Rules used for testing records * @var array */ protected $rules; /** * A File_MARC_Lint_CodeData object for validating codes * @var File_MARC_Lint_CodeData */ protected $data; /** * Warnings generated during analysis * @var array */ protected $warnings = array(); // }}} // {{{ Constructor: function __construct() /** * Start function * * Set up rules for testing MARC records. * * @return true */ public function __construct() { $this->parseRules(); $this->data = new File_MARC_Lint_CodeData(); } // }}} // {{{ getWarnings() /** * Check the provided MARC record and return an array of warning messages. * * @param File_MARC_Record $marc Record to check * * @return array */ public function checkRecord($marc) { // Reset warnings: $this->warnings = array(); // Fail if we didn't get a valid object: if (!is_a($marc, 'File_MARC_Record')) { $this->warn('Must pass a File_MARC_Record object to checkRecord'); } else { $this->checkDuplicate1xx($marc); $this->checkMissing245($marc); $this->standardFieldChecks($marc); } return $this->warnings; } // }}} // {{{ warn() /** * Add a warning. * * @param string $warning Warning to add * * @return void */ protected function warn($warning) { $this->warnings[] = $warning; } // }}} // {{{ checkDuplicate1xx() /** * Check for multiple 1xx fields. * * @param File_MARC_Record $marc Record to check * * @return void */ protected function checkDuplicate1xx($marc) { $result = $marc->getFields('1[0-9][0-9]', true); $count = count($result); if ($count > 1) { $this->warn( "1XX: Only one 1XX tag is allowed, but I found $count of them." ); } } // }}} // {{{ checkMissing245() /** * Check for missing 245 field. * * @param File_MARC_Record $marc Record to check * * @return void */ protected function checkMissing245($marc) { $result = $marc->getFields('245'); if (count($result) == 0) { $this->warn('245: No 245 tag.'); } } // }}} // {{{ standardFieldChecks() /** * Check all fields against the standard rules encoded in the class. * * @param File_MARC_Record $marc Record to check * * @return void */ protected function standardFieldChecks($marc) { $fieldsSeen = array(); foreach ($marc->getFields() as $current) { $tagNo = $current->getTag(); // if 880 field, inherit rules from tagno in subfield _6 if ($tagNo == 880) { if ($sub6 = $current->getSubfield(6)) { $tagNo = substr($sub6->getData(), 0, 3); $tagrules = isset($this->rules[$tagNo]) ? $this->rules[$tagNo] : null; // 880 is repeatable, but its linked field may not be if (isset($tagrules['repeatable']) && $tagrules['repeatable'] == 'NR' && isset($fieldsSeen['880.'.$tagNo]) ) { $this->warn("$tagNo: Field is not repeatable."); } $fieldsSeen['880.'.$tagNo] = isset($fieldsSeen['880.'.$tagNo]) ? $fieldsSeen['880.'.$tagNo] + 1 : 1; } else { $this->warn("880: No subfield 6."); $tagRules = null; } } else { // Default case -- not an 880 field: $tagrules = isset($this->rules[$tagNo]) ? $this->rules[$tagNo] : null; if (isset($tagrules['repeatable']) && $tagrules['repeatable'] == 'NR' && isset($fieldsSeen[$tagNo]) ) { $this->warn("$tagNo: Field is not repeatable."); } $fieldsSeen[$tagNo] = isset($fieldsSeen[$tagNo]) ? $fieldsSeen[$tagNo] + 1 : 1; } // Treat data fields differently from control fields: if (intval(ltrim($tagNo, '0')) >= 10) { if (!empty($tagrules)) { $this->checkIndicators($tagNo, $current, $tagrules); $this->checkSubfields($tagNo, $current, $tagrules); } } else { // Control field: if (strstr($current->toRaw(), chr(hexdec('1F')))) { $this->warn( "$tagNo: Subfields are not allowed in fields lower than 010" ); } } // Check to see if a checkxxx() function exists, and call it on the // field if it does $method = 'check' . $tagNo; if (method_exists($this, $method)) { $this->$method($current); } } } // }}} // {{{ checkIndicators() /** * Check the indicators for the provided field. * * @param string $tagNo Tag number being checked * @param File_MARC_Field $field Field to check * @param array $rules Rules to use for checking * * @return void */ protected function checkIndicators($tagNo, $field, $rules) { for ($i = 1; $i <= 2; $i++) { $ind = $field->getIndicator($i); if ($ind === false || $ind == ' ') { $ind = 'b'; } if (!strstr($rules['ind' . $i]['values'], $ind)) { // Make indicator blank value human-readable for message: if ($ind == 'b') { $ind = 'blank'; } $this->warn( "$tagNo: Indicator $i must be " . $rules['ind' . $i]['hr_values'] . " but it's \"$ind\"" ); } } } // }}} // {{{ checkSubfields() /** * Check the subfields for the provided field. * * @param string $tagNo Tag number being checked * @param File_MARC_Field $field Field to check * @param array $rules Rules to use for checking * * @return void */ protected function checkSubfields($tagNo, $field, $rules) { $subSeen = array(); foreach ($field->getSubfields() as $current) { $code = $current->getCode(); $data = $current->getData(); $subrules = isset($rules['sub' . $code]) ? $rules['sub' . $code] : null; if (empty($subrules)) { $this->warn("$tagNo: Subfield _$code is not allowed."); } elseif ($subrules['repeatable'] == 'NR' && isset($subSeen[$code])) { $this->warn("$tagNo: Subfield _$code is not repeatable."); } if (preg_match('/\r|\t|\n/', $data)) { $this->warn( "$tagNo: Subfield _$code has an invalid control character" ); } $subSeen[$code] = isset($subSeen[$code]) ? $subSeen[$code]++ : 1; } } // }}} // {{{ check020() /** * Looks at 020$a and reports errors if the check digit is wrong. * Looks at 020$z and validates number if hyphens are present. * * @param File_MARC_Field $field Field to check * * @return void */ protected function check020($field) { foreach ($field->getSubfields() as $current) { $data = $current->getData(); // remove any hyphens $isbn = str_replace('-', '', $data); // remove nondigits $isbn = preg_replace('/^\D*(\d{9,12}[X\d])\b.*$/', '$1', $isbn); if ($current->getCode() == 'a') { if ((substr($data, 0, strlen($isbn)) != $isbn)) { $this->warn("020: Subfield a may have invalid characters."); } // report error if no space precedes a qualifier in subfield a if (preg_match('/\(/', $data) && !preg_match('/[X0-9] \(/', $data)) { $this->warn( "020: Subfield a qualifier must be preceded by space, $data." ); } // report error if unable to find 10-13 digit string of digits in // subfield 'a' if (!preg_match('/(?:^\d{10}$)|(?:^\d{13}$)|(?:^\d{9}X$)/', $isbn)) { $this->warn( "020: Subfield a has the wrong number of digits, $data." ); } else { if (strlen($isbn) == 10) { if (!Validate_ISPN::isbn10($isbn)) { $this->warn("020: Subfield a has bad checksum, $data."); } } else if (strlen($isbn) == 13) { if (!Validate_ISPN::isbn13($isbn)) { $this->warn( "020: Subfield a has bad checksum (13 digit), $data." ); } } } } else if ($current->getCode() == 'z') { // look for valid isbn in 020$z if (preg_match('/^ISBN/', $data) || preg_match('/^\d*\-\d+/', $data) ) { // ################################################## // ## Turned on for now--Comment to unimplement #### // ################################################## if ((strlen($isbn) == 10) && (Validate_ISPN::isbn10($isbn) == 1) ) { $this->warn("020: Subfield z is numerically valid."); } } } } } // }}} // {{{ check041() /** * Warns if subfields are not evenly divisible by 3 unless second indicator is 7 * (future implementation would ensure that each subfield is exactly 3 characters * unless ind2 is 7--since subfields are now repeatable. This is not implemented * here due to the large number of records needing to be corrected.). Validates * against the MARC Code List for Languages (). * * @param File_MARC_Field $field Field to check * * @return void */ protected function check041($field) { // warn if length of each subfield is not divisible by 3 unless ind2 is 7 if ($field->getIndicator(2) != '7') { foreach ($field->getSubfields() as $sub) { $code = $sub->getCode(); $data = $sub->getData(); if (strlen($data) % 3 != 0) { $this->warn( "041: Subfield _$code must be evenly divisible by 3 or " . "exactly three characters if ind2 is not 7, ($data)." ); } else { for ($i = 0; $i < strlen($data); $i += 3) { $chk = substr($data, $i, 3); if (!in_array($chk, $this->data->languageCodes)) { $obs = $this->data->obsoleteLanguageCodes; if (in_array($chk, $obs)) { $this->warn( "041: Subfield _$code, $data, may be obsolete." ); } else { $this->warn( "041: Subfield _$code, $data ($chk)," . " is not valid." ); } } } } } } } // }}} // {{{ check043() /** * Warns if each subfield a is not exactly 7 characters. Validates each code * against the MARC code list for Geographic Areas (). * * @param File_MARC_Field $field Field to check * * @return void */ protected function check043($field) { foreach ($field->getSubfields('a') as $suba) { // warn if length of subfield a is not exactly 7 $data = $suba->getData(); if (strlen($data) != 7) { $this->warn("043: Subfield _a must be exactly 7 characters, $data"); } else if (!in_array($data, $this->data->geogAreaCodes)) { if (in_array($data, $this->data->obsoleteGeogAreaCodes)) { $this->warn("043: Subfield _a, $data, may be obsolete."); } else { $this->warn("043: Subfield _a, $data, is not valid."); } } } } // }}} // {{{ check245() /** * -Makes sure $a exists (and is first subfield). * -Warns if last character of field is not a period * --Follows LCRI 1.0C, Nov. 2003 rather than MARC21 rule * -Verifies that $c is preceded by / (space-/) * -Verifies that initials in $c are not spaced * -Verifies that $b is preceded by :;= (space-colon, space-semicolon, * space-equals) * -Verifies that $h is not preceded by space unless it is dash-space * -Verifies that data of $h is enclosed in square brackets * -Verifies that $n is preceded by . (period) * --As part of that, looks for no-space period, or dash-space-period * (for replaced elipses) * -Verifies that $p is preceded by , (no-space-comma) when following $n and * . (period) when following other subfields. * -Performs rudimentary article check of 245 2nd indicator vs. 1st word of * 245$a (for manual verification). * * Article checking is done by internal checkArticle method, which should work * for 130, 240, 245, 440, 630, 730, and 830. * * @param File_MARC_Field $field Field to check * * @return void */ protected function check245($field) { if (count($field->getSubfields('a')) == 0) { $this->warn("245: Must have a subfield _a."); } // Convert subfields to array and set flags indicating which subfields are // present while we're at it. $tmp = $field->getSubfields(); $hasSubfields = $subfields = array(); foreach ($tmp as $current) { $subfields[] = $current; $hasSubfields[$current->getCode()] = true; } // 245 must end in period (may want to make this less restrictive by allowing // trailing spaces) // do 2 checks--for final punctuation (MARC21 rule), and for period // (LCRI 1.0C, Nov. 2003) $lastChar = substr($subfields[count($subfields)-1]->getData(), -1); if (!in_array($lastChar, array('.', '?', '!'))) { $this->warn("245: Must end with . (period)."); } else if ($lastChar != '.') { $this->warn( "245: MARC21 allows ? or ! as final punctuation but LCRI 1.0C, Nov." . " 2003, requires period." ); } // Check for first subfield // subfield a should be first subfield (or 2nd if subfield '6' is present) if (isset($hasSubfields['6'])) { // make sure there are at least 2 subfields if (count($subfields) < 2) { $this->warn("245: May have too few subfields."); } else { $first = $subfields[0]->getCode(); $second = $subfields[1]->getCode(); if ($first != '6') { $this->warn("245: First subfield must be _6, but it is $first"); } if ($second != 'a') { $this->warn( "245: First subfield after subfield _6 must be _a, but it " . "is _$second" ); } } } else { // 1st subfield must be 'a' $first = $subfields[0]->getCode(); if ($first != 'a') { $this->warn("245: First subfield must be _a, but it is _$first"); } } // End check for first subfield // subfield c, if present, must be preceded by / // also look for space between initials if (isset($hasSubfields['c'])) { foreach ($subfields as $i => $current) { // 245 subfield c must be preceded by / (space-/) if ($current->getCode() == 'c') { if ($i > 0 && !preg_match('/\s\/$/', $subfields[$i-1]->getData()) ) { $this->warn("245: Subfield _c must be preceded by /"); } // 245 subfield c initials should not have space if (preg_match('/\b\w\. \b\w\./', $current->getData())) { $this->warn( "245: Subfield _c initials should not have a space." ); } break; } } } // each subfield b, if present, should be preceded by :;= (colon, semicolon, // or equals sign) if (isset($hasSubfields['b'])) { // 245 subfield b should be preceded by space-:;= (colon, semicolon, or // equals sign) foreach ($subfields as $i => $current) { if ($current->getCode() == 'b' && $i > 0 && !preg_match('/ [:;=]$/', $subfields[$i-1]->getData()) ) { $this->warn( "245: Subfield _b should be preceded by space-colon, " . "space-semicolon, or space-equals sign." ); } } } // each subfield h, if present, should be preceded by non-space if (isset($hasSubfields['h'])) { // 245 subfield h should not be preceded by space foreach ($subfields as $i => $current) { // report error if subfield 'h' is preceded by space (unless // dash-space) if ($current->getCode() == 'h') { $prev = $subfields[$i-1]->getData(); if ($i > 0 && !preg_match('/(\S$)|(\-\- $)/', $prev)) { $this->warn( "245: Subfield _h should not be preceded by space." ); } // report error if subfield 'h' does not start with open square // bracket with a matching close bracket; could have check // against list of valid values here $data = $current->getData(); if (!preg_match('/^\[\w*\s*\w*\]/', $data)) { $this->warn( "245: Subfield _h must have matching square brackets," . " $data." ); } } } } // each subfield n, if present, must be preceded by . (period) if (isset($hasSubfields['n'])) { // 245 subfield n must be preceded by . (period) foreach ($subfields as $i => $current) { // report error if subfield 'n' is not preceded by non-space-period // or dash-space-period if ($current->getCode() == 'n' && $i > 0) { $prev = $subfields[$i-1]->getData(); if (!preg_match('/(\S\.$)|(\-\- \.$)/', $prev)) { $this->warn( "245: Subfield _n must be preceded by . (period)." ); } } } } // each subfield p, if present, must be preceded by a , (no-space-comma) // if it follows subfield n, or by . (no-space-period or // dash-space-period) following other subfields if (isset($hasSubfields['p'])) { // 245 subfield p must be preceded by . (period) or , (comma) foreach ($subfields as $i => $current) { if ($current->getCode() == 'p' && $i > 0) { $prev = $subfields[$i-1]; // case for subfield 'n' being field before this one (allows // dash-space-comma) if ($prev->getCode() == 'n' && !preg_match('/(\S,$)|(\-\- ,$)/', $prev->getData()) ) { $this->warn( "245: Subfield _p must be preceded by , (comma) " . "when it follows subfield _n." ); } else if ($prev->getCode() != 'n' && !preg_match('/(\S\.$)|(\-\- \.$)/', $prev->getData()) ) { $this->warn( "245: Subfield _p must be preceded by . (period)" . " when it follows a subfield other than _n." ); } } } } // check for invalid 2nd indicator $this->checkArticle($field); } // }}} // {{{ checkArticle() /** * Check of articles is based on code from Ian Hamilton. This version is more * limited in that it focuses on English, Spanish, French, Italian and German * articles. Certain possible articles have been removed if they are valid * English non-articles. This version also disregards 008_language/041 codes * and just uses the list of articles to provide warnings/suggestions. * * source for articles = * * Should work with fields 130, 240, 245, 440, 630, 730, and 830. Reports error * if another field is passed in. * * @param File_MARC_Field $field Field to check * * @return void */ protected function checkArticle($field) { // add articles here as needed // Some omitted due to similarity with valid words (e.g. the German 'die'). static $article = array( 'a' => 'eng glg hun por', 'an' => 'eng', 'das' => 'ger', 'dem' => 'ger', 'der' => 'ger', 'ein' => 'ger', 'eine' => 'ger', 'einem' => 'ger', 'einen' => 'ger', 'einer' => 'ger', 'eines' => 'ger', 'el' => 'spa', 'en' => 'cat dan nor swe', 'gl' => 'ita', 'gli' => 'ita', 'il' => 'ita mlt', 'l' => 'cat fre ita mlt', 'la' => 'cat fre ita spa', 'las' => 'spa', 'le' => 'fre ita', 'les' => 'cat fre', 'lo' => 'ita spa', 'los' => 'spa', 'os' => 'por', 'the' => 'eng', 'um' => 'por', 'uma' => 'por', 'un' => 'cat spa fre ita', 'una' => 'cat spa ita', 'une' => 'fre', 'uno' => 'ita', ); // add exceptions here as needed // may want to make keys lowercase static $exceptions = array( 'A & E', 'A-', 'A+', 'A is ', 'A isn\'t ', 'A l\'', 'A la ', 'A posteriori', 'A priori', 'A to ', 'El Nino', 'El Salvador', 'L-', 'La Salle', 'Las Vegas', 'Lo mein', 'Los Alamos', 'Los Angeles', ); // get tagno to determine which indicator to check and for reporting $tagNo = $field->getTag(); // retrieve tagno from subfield 6 if 880 field if ($tagNo == '880' && ($sub6 = $field->getSubfield('6'))) { $tagNo = substr($sub6->getData(), 0, 3); } // $ind holds nonfiling character indicator value $ind = ''; // $first_or_second holds which indicator is for nonfiling char value $first_or_second = ''; if (in_array($tagNo, array(130, 630, 730))) { $ind = $field->getIndicator(1); $first_or_second = '1st'; } else if (in_array($tagNo, array(240, 245, 440, 830))) { $ind = $field->getIndicator(2); $first_or_second = '2nd'; } else { $this->warn( 'Internal error: ' . $tagNo . " is not a valid field for article checking\n" ); return; } if (!is_numeric($ind)) { $this->warn($tagNo . ": Non-filing indicator is non-numeric"); return; } // get subfield 'a' of the title field $titleField = $field->getSubfield('a'); $title = $titleField ? $titleField->getData() : ''; $char1_notalphanum = 0; // check for apostrophe, quote, bracket, or parenthesis, before first word // remove if found and add to non-word counter while (preg_match('/^["\'\[\(*]/', $title)) { $char1_notalphanum++; $title = preg_replace('/^["\'\[\(*]/', '', $title); } // split title into first word + rest on space, parens, bracket, apostrophe, // quote, or hyphen preg_match('/^([^ \(\)\[\]\'"\-]+)([ \(\)\[\]\'"\-])?(.*)/i', $title, $hits); $firstword = isset($hits[1]) ? $hits[1] : ''; $separator = isset($hits[2]) ? $hits[2] : ''; $etc = isset($hits[3]) ? $hits[3] : ''; // get length of first word plus the number of chars removed above plus one // for the separator $nonfilingchars = strlen($firstword) + $char1_notalphanum + 1; // check to see if first word is an exception $isan_exception = false; foreach ($exceptions as $current) { if (substr($title, 0, strlen($current)) == $current) { $isan_exception = true; break; } } // lowercase chars of $firstword for comparison with article list $firstword = strtolower($firstword); // see if first word is in the list of articles and not an exception $isan_article = !$isan_exception && isset($article[$firstword]); // if article then $nonfilingchars should match $ind if ($isan_article) { // account for quotes, apostrophes, parens, or brackets before 2nd word if (strlen($separator) && preg_match('/^[ \(\)\[\]\'"\-]+/', $etc)) { while (preg_match('/^[ "\'\[\]\(\)*]/', $etc)) { $nonfilingchars++; $etc = preg_replace('/^[ "\'\[\]\(\)*]/', '', $etc); } } if ($nonfilingchars != $ind) { $this->warn( $tagNo . ": First word, $firstword, may be an article, check " . "$first_or_second indicator ($ind)." ); } } else { // not an article so warn if $ind is not 0 if ($ind != '0') { $this->warn( $tagNo . ": First word, $firstword, does not appear to be an " . "article, check $first_or_second indicator ($ind)." ); } } } // }}} // {{{ parseRules() /** * Support method for constructor to load MARC rules. * * @return void */ protected function parseRules() { // Break apart the rule data on line breaks: $lines = explode("\n", $this->getRawRules()); // Each group of data is split by a blank line -- process one group // at a time: $currentGroup = array(); foreach ($lines as $currentLine) { if (empty($currentLine) && !empty($currentGroup)) { $this->processRuleGroup($currentGroup); $currentGroup = array(); } else { $currentGroup[] = preg_replace("/\s+/", " ", $currentLine); } } // Still have unprocessed data after the loop? Handle it now: if (!empty($currentGroup)) { $this->processRuleGroup($currentGroup); } } // }}} // {{{ processRuleGroup() /** * Support method for parseRules() -- process one group of lines representing * a single tag. * * @param array $rules Rule lines to process * * @return void */ protected function processRuleGroup($rules) { // The first line is guaranteed to exist and gives us some basic info: list($tag, $repeatable, $description) = explode(' ', $rules[0]); $this->rules[$tag] = array( 'repeatable' => $repeatable, 'desc' => $description ); // We may or may not have additional details: for ($i = 1; $i < count($rules); $i++) { list($key, $value, $lineDesc) = explode(' ', $rules[$i]); if (substr($key, 0, 3) == 'ind') { // Expand ranges: $value = str_replace('0-9', '0123456789', $value); $this->rules[$tag][$key] = array( 'values' => $value, 'hr_values' => $this->getHumanReadableIndicatorValues($value), 'desc'=> $lineDesc ); } else { if (strlen($key) <= 1) { $this->rules[$tag]['sub' . $key] = array( 'repeatable' => $value, 'desc' => $lineDesc ); } elseif (strstr($key, '-')) { list($startKey, $endKey) = explode('-', $key); for ($key = $startKey; $key <= $endKey; $key++) { $this->rules[$tag]['sub' . $key] = array( 'repeatable' => $value, 'desc' => $lineDesc ); } } } } } // }}} // {{{ getHumanReadableIndicatorValues() /** * Turn a set of indicator rules into a human-readable list. * * @param string $rules Indicator rules * * @return string */ protected function getHumanReadableIndicatorValues($rules) { // No processing needed for blank rule: if ($rules == 'blank') { return $rules; } // Create string: $string = ''; $length = strlen($rules); for ($i = 0; $i < $length; $i++) { $current = substr($rules, $i, 1); if ($current == 'b') { $current = 'blank'; } $string .= $current; if ($length - $i == 2) { $string .= ' or '; } else if ($length - $i > 2) { $string .= ', '; } } return $string; } // }}} // {{{ getRawRules() /** * Support method for parseRules() -- get the raw rules from MARC::Lint. * * @return string */ protected function getRawRules() { // When updating rules, don't forget to escape the dollar signs in the text! // It would be simpler to change from HEREDOC to NOWDOC syntax, but that // would raise the requirements to PHP 5.3. // @codingStandardsIgnoreStart return << * @author Dan Scott * @copyright 2003-2008 Oy Realnode Ab, Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version CVS: $Id$ * @link http://pear.php.net/package/File_MARC */ // {{{ class File_MARC_Subfield extends Structures_LinkedList_DoubleNode /** * The File_MARC_Subfield class represents a single subfield in a MARC * record field. * * Represents a subfield within a MARC field and implements all management * functions related to a single subfield. This class also implements * the possibility of duplicate subfields within a single field, for example * 650 _z Test1 _z Test2. * * @category File_Formats * @package File_MARC * @author Christoffer Landtman * @author Dan Scott * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear.php.net/package/File_MARC */ class File_MARC_Subfield extends Structures_LinkedList_DoubleNode { // {{{ properties /** * Subfield code, e.g. _a, _b * @var string */ protected $code; /** * Data contained by the subfield * @var string */ protected $data; // }}} // {{{ Constructor: function __construct() /** * File_MARC_Subfield constructor * * Create a new subfield to represent the code and data * * @param string $code Subfield code * @param string $data Subfield data */ function __construct($code, $data) { $this->code = $code; $this->data = $data; } // }}} // {{{ Destructor: function __destruct() /** * Destroys the subfield */ function __destruct() { $this->code = null; $this->data = null; parent::__destruct(); } // }}} // {{{ Explicit destructor: function delete() /** * Destroys the subfield * * @return true */ function delete() { $this->__destruct(); } // }}} // {{{ getCode() /** * Return code of the subfield * * @return string Tag name */ function getCode() { return (string)$this->code; } // }}} // {{{ getData() /** * Return data of the subfield * * @return string data */ function getData() { return (string)$this->data; } // }}} // {{{ __toString() /** * Return string representation of subfield * * @return string String representation */ public function __toString() { $pretty = '[' . $this->getCode() . ']: ' . $this->getData(); return $pretty; } // }}} // {{{ toRaw() /** * Return the USMARC representation of the subfield * * @return string USMARC representation */ function toRaw() { $result = File_MARC::SUBFIELD_INDICATOR.$this->code.$this->data; return (string)$result; } // }}} // {{{ setCode() /** * Sets code of the subfield * * @param string $code new code for the subfield * * @return string code */ function setCode($code) { if ($code) { // could check more stringently; m/[a-Z]/ or the likes $this->code = $code; } else { // code must be _something_; raise error return false; } return true; } // }}} // {{{ setData() /** * Sets data of the subfield * * @param string $data new data for the subfield * * @return string data */ function setData($data) { $this->data = $data; return true; } // }}} // {{{ isEmpty() /** * Checks whether the subfield is empty or not * * @return bool True or false */ function isEmpty() { // There is data if ($this->data) { return false; } // There is no data return true; } // }}} } // }}} PK!15test/Structures_LinkedList/tests/single_link_007.phptnu[--TEST-- single_link_007: Test many corner cases --FILE-- prependNode($tester1); print "Current: {$xyy->current()->getNumb()}\n"; // prepend to a list with only one element: 21 $xyy->prependNode($tester2); print "Current: {$xyy->current()->getNumb()}\n"; // insert after tail node corner case: 213 $xyy->insertNode($tester3, $tester1); print "Current: {$xyy->current()->getNumb()}\n"; // insert before root node corner case: 4213 $xyy->insertNode($tester4, $tester2, true); print "Current: {$xyy->current()->getNumb()}\n"; // insert before tail node corner case: 42153 $xyy->insertNode($tester5, $tester3, true); print "Current: {$xyy->current()->getNumb()}\n"; print "Foreach: "; foreach ($xyy as $node) { print $node->getNumb(); } print "\nWhile (in reverse): "; // test reverse iteration with while() $link = $xyy->end(); do { print $link->getNumb(); } while ($link = $xyy->previous()); ?> --EXPECT-- Current: 1 Current: 1 Current: 1 Current: 1 Current: 1 Foreach: 42153 While (in reverse): 35124 PK!Zx5test/Structures_LinkedList/tests/single_link_002.phptnu[--TEST-- single_link_002: Append links to an initially empty linked list --FILE-- appendNode($tester1); $xyy->appendNode($tester2); $xyy->appendNode($tester3); $xyy->insertNode($tester4, $tester2, true); $link = $xyy->current(); print $link->getNumb(); // test iteration with while() while ($link = $xyy->next()) { print $link->getNumb(); } $link = $xyy->rewind(); print "\n"; print $link->getNumb(); print "\n"; // test foreach() iteration foreach ($xyy as $bull) { print $bull->getNumb(); } ?> --EXPECT-- 1423 1 1423 PK!(  .test/Structures_LinkedList/tests/link_004.phptnu[--TEST-- link_004: Delete every link in the list --FILE-- appendNode($tester2); $xyy->appendNode($tester3); $xyy->appendNode($tester4); // Delete all nodes from the list while ($link = $xyy->rewind()) { print "Deleted " . $link->getNumb() . "\n"; $xyy->deleteNode($link); } $link = $xyy->rewind(); print "Done\n"; ?> --EXPECT-- Deleted 1 Deleted 2 Deleted 3 Deleted 4 Done PK!|5test/Structures_LinkedList/tests/SingleLinkTester.phpnu[_my_number = $num; } function getNumb() { return $this->_my_number; } function setNumb($numb) { $this->_my_number = $numb; } } $tester1 = new LinkTester(1); $tester2 = new LinkTester(2); $tester3 = new LinkTester(3); $tester4 = new LinkTester(4); $tester5 = new LinkTester(5); ?> PK!髂[5test/Structures_LinkedList/tests/single_link_006.phptnu[--TEST-- single_link_006: Corner case: add a node before the root --FILE-- prependNode($tester1); $xyy->appendNode($tester2); $xyy->appendNode($tester3); $xyy->insertNode($tester4, $tester2, true); // Ensure we can increment the current node without messing up the list print "\nCurrent: " . $xyy->current()->getNumb() . "\n"; $link = $xyy->next(); print "Current: " . $link->getNumb() . "\n"; $xyy->insertNode($tester5, $tester1, true); print "\n"; $link = $xyy->current(); print "Current: " . $link->getNumb(); print "\n\nWhile: "; // test iteration with while() $link = $xyy->rewind(); do { print $link->getNumb(); } while ($link = $xyy->next()); print "\n\nForeach: "; // test foreach() iteration foreach ($xyy as $bull) { print $bull->getNumb(); } ?> --EXPECT-- Current: 1 Current: 4 Current: 4 While: 51423 Foreach: 51423 PK!sDHH.test/Structures_LinkedList/tests/link_007.phptnu[--TEST-- link_007: Test many corner cases --FILE-- prependNode($tester1); print "Current: {$xyy->current()->getNumb()}\n"; // prepend to a list with only one element: 21 $xyy->prependNode($tester2); print "Current: {$xyy->current()->getNumb()}\n"; // insert after tail node corner case: 213 $xyy->insertNode($tester3, $tester1); print "Current: {$xyy->current()->getNumb()}\n"; // insert before root node corner case: 4213 $xyy->insertNode($tester4, $tester2, true); print "Current: {$xyy->current()->getNumb()}\n"; // insert before tail node corner case: 42153 $xyy->insertNode($tester5, $tester3, true); print "Current: {$xyy->current()->getNumb()}\n"; // insert after root node corner case: 421653 $xyy->insertNode($tester6, $tester1); print "Current: {$xyy->current()->getNumb()}\n"; print "Foreach: "; foreach ($xyy as $node) { print $node->getNumb(); } print "\nWhile (in reverse): "; // test reverse iteration with while() $link = $xyy->end(); do { print $link->getNumb(); } while ($link = $xyy->previous()); ?> --EXPECT-- Current: 1 Current: 1 Current: 1 Current: 1 Current: 1 Current: 1 Foreach: 421653 While (in reverse): 356124 PK!.test/Structures_LinkedList/tests/link_005.phptnu[--TEST-- link_005: Pass different class types to constructors --FILE-- _my_number = $num; parent::__construct($tester); } } class TesterFail { protected $summary; protected $fulltext; function __construct($summary, $fulltext) { $this->summary = $summary; $this->fulltext = $fulltext; } } // This should work: TesterExtend extends the Structure_LinkedList_DoubleNode class $tester_extend = new TesterExtend(null, 1); $xyy = new Structures_LinkedList_Double($tester_extend); print "Checking for errors in the expected success case:\n"; // This should fail print "Checking for errors in the expected failure case:\n"; $tester_fail = new TesterFail(null, 1); $xyy_fail = new Structures_LinkedList_Double($tester_fail); ?> --EXPECTF-- Checking for errors in the expected success case: Checking for errors in the expected failure case: %satal error: Argument 1 passed to Structures_LinkedList_Double::__construct() must be an instance of Structures_LinkedList_DoubleNode%s PK!#,E5test/Structures_LinkedList/tests/single_link_005.phptnu[--TEST-- single_link_005: Pass different class types to constructors --FILE-- _my_number = $num; parent::__construct($tester); } } class TesterFail { protected $summary; protected $fulltext; function __construct($summary, $fulltext) { $this->summary = $summary; $this->fulltext = $fulltext; } } // This should work: TesterExtend extends the Structure_LinkedList_SingleNode class $tester_extend = new TesterExtend(null, 1); $xyy = new Structures_LinkedList_Single($tester_extend); print "Checking for errors in the expected success case:\n"; // This should fail print "Checking for errors in the expected failure case:\n"; $tester_fail = new TesterFail(null, 1); $xyy_fail = new Structures_LinkedList_Single($tester_fail); ?> --EXPECTF-- Checking for errors in the expected success case: Checking for errors in the expected failure case: %satal error: Argument 1 passed to Structures_LinkedList_Single::__construct() must be an instance of Structures_LinkedList_SingleNode%s PK!/test/Structures_LinkedList/tests/LinkTester.phpnu[_my_number = $num; } function getNumb() { return $this->_my_number; } function setNumb($numb) { $this->_my_number = $numb; } } $tester1 = new LinkTester(1); $tester2 = new LinkTester(2); $tester3 = new LinkTester(3); $tester4 = new LinkTester(4); $tester5 = new LinkTester(5); $tester6 = new LinkTester(6); ?> PK! .test/Structures_LinkedList/tests/link_001.phptnu[--TEST-- link_001: Test linked list constructed with an initial link --FILE-- appendNode($tester2); $xyy->appendNode($tester3); $xyy->appendNode($tester4); $link = $xyy->current(); print "Current: " . $link->getNumb() . "\n"; print "While: "; // test iteration with while() do { print $link->getNumb(); } while ($link = $xyy->next()); print "\nRewind: "; $link = $xyy->rewind(); print $link->getNumb(); print "\n"; print "Foreach: "; // test foreach() iteration foreach ($xyy as $bull) { print $bull->getNumb(); } print "\nEnd: "; $link = $xyy->end(); print $link->getNumb(); print "\n"; print "While (in reverse): "; // test iteration with while() do { print $link->getNumb(); } while ($link = $xyy->previous()); ?> --EXPECT-- Current: 1 While: 1234 Rewind: 1 Foreach: 1234 End: 4 While (in reverse): 4321 PK!骗.test/Structures_LinkedList/tests/link_006.phptnu[--TEST-- link_006: Corner case: add a node before the root --FILE-- prependNode($tester1); $xyy->appendNode($tester2); $xyy->appendNode($tester3); $xyy->insertNode($tester4, $tester2, true); // Ensure we can increment the current node without messing up the list print "\nCurrent: " . $xyy->current()->getNumb() . "\n"; $link = $xyy->next(); print "Current: " . $link->getNumb() . "\n"; $xyy->insertNode($tester5, $tester1, true); print "\n"; $link = $xyy->current(); print "Current: " . $link->getNumb(); print "\n\nWhile: "; // test iteration with while() $link = $xyy->rewind(); do { print $link->getNumb(); } while ($link = $xyy->next()); print "\n\nForeach: "; // test foreach() iteration foreach ($xyy as $bull) { print $bull->getNumb(); } ?> --EXPECT-- Current: 1 Current: 4 Current: 4 While: 51423 Foreach: 51423 PK!).test/Structures_LinkedList/tests/link_002.phptnu[--TEST-- link_002: Append links to an initially empty linked list --FILE-- appendNode($tester1); $xyy->appendNode($tester2); $xyy->appendNode($tester3); $xyy->insertNode($tester4, $tester2, true); $link = $xyy->current(); print $link->getNumb(); // test iteration with while() while ($link = $xyy->next()) { print $link->getNumb(); } $link = $xyy->rewind(); print "\n"; print $link->getNumb(); print "\n"; // test foreach() iteration foreach ($xyy as $bull) { print $bull->getNumb(); } ?> --EXPECT-- 1423 1 1423 PK!45test/Structures_LinkedList/tests/single_link_001.phptnu[--TEST-- single_link_001: Test linked list constructed with an initial link --FILE-- appendNode($tester2); $xyy->appendNode($tester3); $xyy->appendNode($tester4); $link = $xyy->current(); print "Current: " . $link->getNumb() . "\n"; print "While: "; // test iteration with while() do { print $link->getNumb(); } while ($link = $xyy->next()); print "\nRewind: "; $link = $xyy->rewind(); print $link->getNumb(); print "\n"; print "Foreach: "; // test foreach() iteration foreach ($xyy as $bull) { print $bull->getNumb(); } print "\nEnd: "; $link = $xyy->end(); print $link->getNumb(); print "\n"; print "While (in reverse): "; // test iteration with while() do { print $link->getNumb(); } while ($link = $xyy->previous()); ?> --EXPECT-- Current: 1 While: 1234 Rewind: 1 Foreach: 1234 End: 4 While (in reverse): 4321 PK!)y--5test/Structures_LinkedList/tests/single_link_004.phptnu[--TEST-- single_link_004: Delete every link in the list --FILE-- appendNode($tester2); $xyy->appendNode($tester3); $xyy->appendNode($tester4); // Delete all nodes from the list while ($link = $xyy->rewind()) { print "Deleted " . $link->getNumb() . "\n"; $xyy->deleteNode($link); } $link = $xyy->rewind(); print "Done\n"; ?> --EXPECT-- Deleted 1 Deleted 2 Deleted 3 Deleted 4 Done PK!K5test/Structures_LinkedList/tests/single_link_003.phptnu[--TEST-- single_link_003: Append links in a specific order --FILE-- appendNode($tester1); print $tester1->getNumb() . "\n"; // add after initial link $xyy->appendNode($tester2); print $tester2->getNumb() . "\n"; // add after initial link, bumping #2 up $xyy->insertNode($tester3, $tester1); print $tester3->getNumb() . "\n"; // add after link #3, bumping #2 up again $xyy->insertNode($tester4, $tester3); print $tester4->getNumb() . "\n"; print "\n"; $link = $xyy->current(); print $link->getNumb(); print "\n"; // test iteration with while() while ($link = $xyy->next()) { print $link->getNumb(); print "\n"; } $link = $xyy->rewind(); print "\n"; print $link->getNumb(); print "\n"; // test foreach() iteration foreach ($xyy as $bull) { print $bull->getNumb(); } ?> --EXPECT-- 1 2 3 4 1 3 4 2 1 1342 PK!o.test/Structures_LinkedList/tests/link_003.phptnu[--TEST-- link_003: Append links in a specific order --FILE-- appendNode($tester1); print $tester1->getNumb() . "\n"; // add after initial link $xyy->appendNode($tester2); print $tester2->getNumb() . "\n"; // add after initial link, bumping #2 up $xyy->insertNode($tester3, $tester1); print $tester3->getNumb() . "\n"; // add after link #3, bumping #2 up again $xyy->insertNode($tester4, $tester3); print $tester4->getNumb() . "\n"; print "\n"; $link = $xyy->current(); print $link->getNumb(); print "\n"; // test iteration with while() while ($link = $xyy->next()) { print $link->getNumb(); print "\n"; } $link = $xyy->rewind(); print "\n"; print $link->getNumb(); print "\n"; // test foreach() iteration foreach ($xyy as $bull) { print $bull->getNumb(); } ?> --EXPECT-- 1 2 3 4 1 3 4 2 1 1342 PK!x`(test/Mail/tests/bug17317.phptnu[--TEST-- Mail_RFC822::parseAddressList invalid periods in mail address --FILE-- (test)'; $parser = new Mail_RFC822(); $result = $parser->parseAddressList($address, 'anydomain.com', TRUE); if (!PEAR::isError($result) && is_array($result) && is_object($result[0])) if ($result[0]->personal == '"Test Student"' && $result[0]->mailbox == "test" && $result[0]->host == "mydomain.com" && is_array($result[0]->comment) && $result[0]->comment[0] == 'test') { print("OK"); } ?> --EXPECT-- OK PK!ótest/Mail/tests/9137_2.phptnu[--TEST-- Mail: Test for bug #9137, take 2 --FILE-- '"John Doe" '), array('raw' => '"John Doe' . chr(92) . '" '), array('raw' => '"John Doe' . chr(92) . chr(92) . '" '), array('raw' => '"John Doe' . chr(92) . chr(92) . chr(92) . '" '), array('raw' => '"John Doe' . chr(92) . chr(92) . chr(92) . chr(92) . '" '), array('raw' => '"John Doe '), ); for ($i = 0; $i < count($addresses); $i++) { // construct the address $address = $addresses[$i]['raw']; $parsedAddresses = Mail_RFC822::parseAddressList($address); if (PEAR::isError($parsedAddresses)) { echo $address." :: Failed to validate\n"; } else { echo $address." :: Parsed\n"; } } --EXPECT-- "John Doe" :: Parsed "John Doe\" :: Failed to validate "John Doe\\" :: Parsed "John Doe\\\" :: Failed to validate "John Doe\\\\" :: Parsed "John Doe :: Failed to validate PK!wtest/Mail/tests/smtp_error.phptnu[--TEST-- Mail: SMTP Error Reporting --SKIPIF-- packageExists('Net_SMTP')) die("skip\n"); --FILE-- 'bogus.host.tld'); /* Create our SMTP-based mailer object. */ $mailer = Mail::factory('smtp', $params); /* Attempt to send an empty message in order to trigger an error. */ $e = $mailer->send(array(), array(), ''); if (is_a($e, 'PEAR_Error')) { $err = $e->getMessage(); if (preg_match('/Failed to connect to bogus.host.tld:25 \[SMTP: Failed to connect socket:.*/i', $err)) { echo "OK"; } } --EXPECT-- OKPK!)f$! ! test/Mail/tests/rfc822.phptnu[--TEST-- Mail_RFC822: Address Parsing --FILE-- parseAddressList($address, null, true, true)); /* Address groups. */ $address = 'My Group: "Richard" (A comment), ted@example.com (Ted Bloggs), Barney;'; print_r($parser->parseAddressList($address, null, true, true)); /* A valid address with spaces in the local part. */ $address = '<"Jon Parise"@php.net>'; print_r($parser->parseAddressList($address, null, true, true)); /* An invalid address with spaces in the local part. */ $address = ''; $result = $parser->parseAddressList($address, null, true, true); if (is_a($result, 'PEAR_Error')) echo $result->getMessage() . "\n"; /* A valid address with an uncommon TLD. */ $address = 'jon@host.longtld'; $result = $parser->parseAddressList($address, null, true, true); if (is_a($result, 'PEAR_Error')) echo $result->getMessage() . "\n"; --EXPECT-- Array ( [0] => stdClass Object ( [personal] => [comment] => Array ( ) [mailbox] => user [host] => example.com ) ) Array ( [0] => stdClass Object ( [groupname] => My Group [addresses] => Array ( [0] => stdClass Object ( [personal] => "Richard" [comment] => Array ( [0] => A comment ) [mailbox] => richard [host] => localhost ) [1] => stdClass Object ( [personal] => [comment] => Array ( [0] => Ted Bloggs ) [mailbox] => ted [host] => example.com ) [2] => stdClass Object ( [personal] => [comment] => Array ( ) [mailbox] => Barney [host] => localhost ) ) ) ) Array ( [0] => stdClass Object ( [personal] => [comment] => Array ( ) [mailbox] => "Jon Parise" [host] => php.net ) ) Validation failed for: PK!8xtest/Mail/tests/bug17178.phptnu[--TEST-- Mail_RFC822::parseAddressList does not accept RFC-valid group syntax --FILE-- 'John Doe', 'email' => 'test@example.com'), array('name' => 'John Doe\\', 'email' => 'test@example.com'), array('name' => 'John "Doe', 'email' => 'test@example.com'), array('name' => 'John "Doe\\', 'email' => 'test@example.com'), ); for ($i = 0; $i < count($addresses); $i++) { // construct the address $address = "\"" . addslashes($addresses[$i]['name']) . "\" ". "<".$addresses[$i]['email'].">"; $parsedAddresses = Mail_RFC822::parseAddressList($address); if (is_a($parsedAddresses, 'PEAR_Error')) { echo $address." :: Failed to validate\n"; } else { echo $address." :: Parsed\n"; } } --EXPECT-- "John Doe" :: Parsed "John Doe\\" :: Parsed "John \"Doe" :: Parsed "John \"Doe\\" :: Parsed PK!W8j#j#.test/Structures_Graph/tests/BasicGraphTest.phpnu[ | // +-----------------------------------------------------------------------------+ // require_once dirname(__FILE__) . '/helper.inc'; /** * @access private */ class BasicGraph extends PHPUnit_Framework_TestCase { var $_graph = null; function test_create_graph() { $this->_graph = new Structures_Graph(); $this->assertTrue(is_a($this->_graph, 'Structures_Graph')); } function test_add_node() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node($data); $this->_graph->addNode($node); $node = new Structures_Graph_Node($data); $this->_graph->addNode($node); $node = new Structures_Graph_Node($data); $this->_graph->addNode($node); } function test_connect_node() { $this->_graph = new Structures_Graph(); $data = 1; $node1 = new Structures_Graph_Node($data); $node2 = new Structures_Graph_Node($data); $this->_graph->addNode($node1); $this->_graph->addNode($node2); $node1->connectTo($node2); $node =& $this->_graph->getNodes(); $node =& $node[0]; $node = $node->getNeighbours(); $node =& $node[0]; /* ZE1 == and === operators fail on $node,$node2 because of the recursion introduced by the _graph field in the Node object. So, we'll use the stupid method for reference testing */ $node = true; $this->assertTrue($node2); $node = false; $this->assertFalse($node2); } function test_data_references() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node(); $node->setData($data); $this->_graph->addNode($node); $data = 2; $dataInNode =& $this->_graph->getNodes(); $dataInNode =& $dataInNode[0]; $dataInNode =& $dataInNode->getData(); $this->assertEquals($data, $dataInNode); } function test_metadata_references() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node(); $node->setMetadata('5', $data); $data = 2; $dataInNode =& $node->getMetadata('5'); $this->assertEquals($data, $dataInNode); } function test_metadata_key_exists() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node(); $node->setMetadata('5', $data); $this->assertTrue($node->metadataKeyExists('5')); $this->assertFalse($node->metadataKeyExists('1')); } function test_directed_degree() { $this->_graph = new Structures_Graph(true); $node = array(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $this->_graph->addNode($node[0]); $this->_graph->addNode($node[1]); $this->_graph->addNode($node[2]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs'); $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs'); $node[0]->connectTo($node[1]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc'); $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc'); $node[0]->connectTo($node[2]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs'); $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs'); $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs'); } function test_undirected_degree() { $this->_graph = new Structures_Graph(false); $node = array(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $this->_graph->addNode($node[0]); $this->_graph->addNode($node[1]); $this->_graph->addNode($node[2]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs'); $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs'); $node[0]->connectTo($node[1]); $this->assertEquals(1, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc'); $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc'); $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc'); $node[0]->connectTo($node[2]); $this->assertEquals(2, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs'); $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs'); $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs'); $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs'); $this->assertEquals(1, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs'); } } ?> PK!6:UU5test/Structures_Graph/tests/TopologicalSorterTest.phpnu[setData($name1); $graph->addNode($node1); $name11 = 'node11'; $node11 = new Structures_Graph_Node(); $node11->setData($name11); $graph->addNode($node11); $node1->connectTo($node11); $name12 = 'node12'; $node12 = new Structures_Graph_Node(); $node12->setData($name12); $graph->addNode($node12); $node1->connectTo($node12); $name121 = 'node121'; $node121 = new Structures_Graph_Node(); $node121->setData($name121); $graph->addNode($node121); $node12->connectTo($node121); $name2 = 'node2'; $node2 = new Structures_Graph_Node(); $node2->setData($name2); $graph->addNode($node2); $name21 = 'node21'; $node21 = new Structures_Graph_Node(); $node21->setData($name21); $graph->addNode($node21); $node2->connectTo($node21); $nodes = Structures_Graph_Manipulator_TopologicalSorter::sort($graph); $this->assertCount(2, $nodes[0]); $this->assertEquals('node1', $nodes[0][0]->getData()); $this->assertEquals('node2', $nodes[0][1]->getData()); $this->assertCount(3, $nodes[1]); $this->assertEquals('node11', $nodes[1][0]->getData()); $this->assertEquals('node12', $nodes[1][1]->getData()); $this->assertEquals('node21', $nodes[1][2]->getData()); $this->assertCount(1, $nodes[2]); $this->assertEquals('node121', $nodes[2][0]->getData()); } } ?> PK!V(test/Structures_Graph/tests/AllTests.phpnu[addTestFiles($dir); return $suite; } } PK!/test/Structures_Graph/tests/AcyclicTestTest.phpnu[addNode($node1); $node2 = new Structures_Graph_Node(); $graph->addNode($node2); $node1->connectTo($node2); $node3 = new Structures_Graph_Node(); $graph->addNode($node3); $node2->connectTo($node3); $node3->connectTo($node1); $this->assertFalse( Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph), 'Graph is cyclic' ); } public function testIsAcyclicTrue() { $graph = new Structures_Graph(); $node1 = new Structures_Graph_Node(); $graph->addNode($node1); $node2 = new Structures_Graph_Node(); $graph->addNode($node2); $node1->connectTo($node2); $node3 = new Structures_Graph_Node(); $graph->addNode($node3); $node2->connectTo($node3); $this->assertTrue( Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph), 'Graph is acyclic' ); } } ?> PK!`ii&test/Structures_Graph/tests/helper.incnu[ $d) { if ($i++ > 0) { print ", "; } print $d[0] . '=' . $d[1]; } print "\n"; print "params: " . implode(", ", $non_opts) . "\n"; print "\n"; } test("-abc", "abc"); test("-abc foo", "abc"); test("-abc foo", "abc:"); test("-abc foo bar gazonk", "abc"); test("-abc foo bar gazonk", "abc:"); test("-a -b -c", "abc"); test("-a -b -c", "abc:"); test("-abc", "ab:c"); test("-abc foo -bar gazonk", "abc"); ?> --EXPECT-- options: a=, b=, c= params: options: a=, b=, c= params: foo options: a=, b=, c=foo params: options: a=, b=, c= params: foo, bar, gazonk options: a=, b=, c=foo params: bar, gazonk options: a=, b=, c= params: Console_Getopt: option requires an argument --c options: a=, b=c params: options: a=, b=, c= params: foo, -bar, gazonk PK!'test/Console_Getopt/tests/bug11068.phptnu[--TEST-- Console_Getopt [bug 11068] --SKIPIF-- --FILE-- getMessage()."\n"; echo 'FATAL'; exit; } print_r($ret); ?> --EXPECT-- Array ( [0] => Array ( [0] => Array ( [0] => f [1] => jjohnston@mail.com ) [1] => Array ( [0] => --to [1] => hi ) ) [1] => Array ( [0] => - ) )PK!'test/Console_Getopt/tests/bug10557.phptnu[--TEST-- Console_Getopt [bug 10557] --SKIPIF-- --FILE-- getMessage()."\n"; echo 'FATAL'; exit; } print_r($ret); ?> --EXPECT-- Console_Getopt: option requires an argument --to FATALPK!|EE'test/Console_Getopt/tests/bug13140.phptnu[--TEST-- Console_Getopt [bug 13140] --SKIPIF-- --FILE-- getopt2($cg->readPHPArgv(), 't', array('test'), true)); print_r($cg->getopt2($cg->readPHPArgv(), 'bar', array('foo'), true)); ?> --EXPECT-- Array ( [0] => Array ( [0] => Array ( [0] => --test [1] => ) ) [1] => Array ( [0] => thisshouldbehere ) ) Array ( [0] => Array ( [0] => Array ( [0] => --foo [1] => ) [1] => Array ( [0] => b [1] => ) [2] => Array ( [0] => a [1] => ) [3] => Array ( [0] => r [1] => ) [4] => Array ( [0] => r [1] => ) ) [1] => Array ( [0] => thisshouldbehere ) ) PK!?7EE9test/Net_IDNA2/tests/draft-josefsson-idn-test-vectors.phpnu[idn = new Net_IDNA2(); } static function unichr($chr) { return mb_convert_encoding('&#' . intval($chr) . ';', 'UTF-8', 'HTML-ENTITIES'); } private function hexarray2string($arr) { return implode('', array_map(array('self', 'unichr'), $arr)); } public function testDecode1() { // Arabic (Egyptian) $expected = $this->hexarray2string(array( 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643, 0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A, 0x061F )); $result = $this->idn->decode(IDNA_ACE_PREFIX."egbpdaj6bu4bxfgehfvwxn"); $this->assertSame($expected, $result); } public function testDecode2() { // Chinese (simplified) $expected = $this->hexarray2string(array( 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D, 0x6587 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."ihqwcrb4cv8a8dqg056pqjye"); $this->assertSame($expected, $result); } public function testDecode3() { // Chinese (traditional) $expected = $this->hexarray2string(array( 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D, 0x6587 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."ihqwctvzc91f659drss3x8bo0yb"); $this->assertSame($expected, $result); } public function testDecode4() { // Czech $expected = $this->hexarray2string(array( 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073, 0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076, 0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."Proprostnemluvesky-uyb24dma41a"); $this->assertSame($expected, $result); } public function testDecode5() { // Hebrew $expected = $this->hexarray2string(array( 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5, 0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9, 0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA )); $result = $this->idn->decode(IDNA_ACE_PREFIX."4dbcagdahymbxekheh6e0a7fei0b"); $this->assertSame($expected, $result); } public function testDecode6() { // Hindi (Devanagari) $expected = $this->hexarray2string(array( 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928, 0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902, 0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938, 0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd"); $this->assertSame($expected, $result); } public function testDecode7() { // Japanese (kanji and hiragana) $expected = $this->hexarray2string(array( 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E, 0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044, 0x306E, 0x304B )); $result = $this->idn->decode(IDNA_ACE_PREFIX."n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa"); $this->assertSame($expected, $result); } public function testDecode8() { // Russian (Cyrillic) $expected = $this->hexarray2string(array( 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435, 0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432, 0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443, 0x0441, 0x0441, 0x043A, 0x0438 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."b1abfaaepdrnnbgefbadotcwatmq2g4l"); $this->assertSame($expected, $result); } public function testDecode9() { // Spanish $expected = $this->hexarray2string(array( 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F, 0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069, 0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074, 0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065, 0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F, 0x006C )); $result = $this->idn->decode(IDNA_ACE_PREFIX."PorqunopuedensimplementehablarenEspaol-fmd56a"); $this->assertSame($expected, $result); } public function testDecode10() { // Vietnamese $expected = $this->hexarray2string(array( 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD, 0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3, 0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069, 0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g"); $this->assertSame($expected, $result); } public function testDecode11() { // Japanese $expected = $this->hexarray2string(array( 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F )); $result = $this->idn->decode(IDNA_ACE_PREFIX."3B-ww4c5e180e575a65lsy2b"); $this->assertSame($expected, $result); } public function testDecode12() { // Japanese $expected = $this->hexarray2string(array( 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069, 0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052, 0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n"); $this->assertSame($expected, $result); } public function testDecode13() { // Japanese $expected = $this->hexarray2string(array( 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E, 0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061, 0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834, 0x6240 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."Hello-Another-Way--fc4qua05auwb3674vfr0b"); $this->assertSame($expected, $result); } public function testDecode14() { // Japanese $expected = $this->hexarray2string(array( 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."2-u9tlzr9756bt3uc0v"); $this->assertSame($expected, $result); } public function testDecode15() { // Japanese $expected = $this->hexarray2string(array( 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069, 0x3059, 0x308B, 0x0035, 0x79D2, 0x524D )); $result = $this->idn->decode(IDNA_ACE_PREFIX."MajiKoi5-783gue6qz075azm5e"); $this->assertSame($expected, $result); } public function testDecode16() { // Japanese $expected = $this->hexarray2string(array( 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."de-jg4avhby1noc0d"); $this->assertSame($expected, $result); } public function testDecode17() { // Japanese $expected = $this->hexarray2string(array( 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."d9juau41awczczp"); $this->assertSame($expected, $result); } public function testDecode18() { // Greek $expected = $this->hexarray2string(array( 0x03b5, 0x03bb, 0x03bb, 0x03b7, 0x03bd, 0x03b9, 0x03ba, 0x03ac )); $result = $this->idn->decode(IDNA_ACE_PREFIX."hxargifdar"); $this->assertSame($expected, $result); } public function testDecode19() { // Maltese (Malti) $expected = $this->hexarray2string(array( 0x0062, 0x006f, 0x006e, 0x0121, 0x0075, 0x0073, 0x0061, 0x0127, 0x0127, 0x0061 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."bonusaa-5bb1da"); $this->assertSame($expected, $result); } public function testDecode20() { // Russian (Cyrillic) $expected = $this->hexarray2string(array( 0x043f, 0x043e, 0x0447, 0x0435, 0x043c, 0x0443, 0x0436, 0x0435, 0x043e, 0x043d, 0x0438, 0x043d, 0x0435, 0x0433, 0x043e, 0x0432, 0x043e, 0x0440, 0x044f, 0x0442, 0x043f, 0x043e, 0x0440, 0x0443, 0x0441, 0x0441, 0x043a, 0x0438 )); $result = $this->idn->decode(IDNA_ACE_PREFIX."b1abfaaepdrnnbgefbadotcwatmq2g4l"); $this->assertSame($expected, $result); } public function testEncode1() { // Arabic (Egyptian) $idna = $this->hexarray2string(array( 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643, 0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A, 0x061F )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."egbpdaj6bu4bxfgehfvwxn", $result); } public function testEncode2() { // Chinese (simplified) $idna = $this->hexarray2string(array( 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D, 0x6587 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."ihqwcrb4cv8a8dqg056pqjye", $result); } public function testEncode3() { // Chinese (traditional) $idna = $this->hexarray2string(array( 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D, 0x6587 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."ihqwctvzc91f659drss3x8bo0yb", $result); } public function testEncode4() { // Czech $idna = $this->hexarray2string(array( 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073, 0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076, 0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."proprostnemluvesky-uyb24dma41a", $result); } public function testEncode5() { // Hebrew $idna = $this->hexarray2string(array( 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5, 0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9, 0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."4dbcagdahymbxekheh6e0a7fei0b", $result); } public function testEncode6() { // Hindi (Devanagari) $idna = $this->hexarray2string(array( 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928, 0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902, 0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938, 0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd", $result); } public function testEncode7() { // Japanese (kanji and hiragana) $idna = $this->hexarray2string(array( 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E, 0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044, 0x306E, 0x304B )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa", $result); } public function testEncode8() { // Russian (Cyrillic) $idna = $this->hexarray2string(array( 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435, 0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432, 0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443, 0x0441, 0x0441, 0x043A, 0x0438 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."b1abfaaepdrnnbgefbadotcwatmq2g4l", $result); } public function testEncode9() { // Spanish $idna = $this->hexarray2string(array( 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F, 0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069, 0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074, 0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065, 0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F, 0x006C )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."porqunopuedensimplementehablarenespaol-fmd56a", $result); } public function testEncode10() { // Vietnamese $idna = $this->hexarray2string(array( 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD, 0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3, 0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069, 0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."tisaohkhngthchnitingvit-kjcr8268qyxafd2f1b9g", $result); } public function testEncode11() { // Japanese $idna = $this->hexarray2string(array( 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."3b-ww4c5e180e575a65lsy2b", $result); } public function testEncode12() { // Japanese $idna = $this->hexarray2string(array( 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069, 0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052, 0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."-with-super-monkeys-pc58ag80a8qai00g7n9n", $result); } public function testEncode13() { // Japanese $idna = $this->hexarray2string(array( 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E, 0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061, 0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834, 0x6240 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."hello-another-way--fc4qua05auwb3674vfr0b", $result); } public function testEncode14() { // Japanese $idna = $this->hexarray2string(array( 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."2-u9tlzr9756bt3uc0v", $result); } public function testEncode15() { // Japanese $idna = $this->hexarray2string(array( 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069, 0x3059, 0x308B, 0x0035, 0x79D2, 0x524D )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."majikoi5-783gue6qz075azm5e", $result); } public function testEncode16() { // Japanese $idna = $this->hexarray2string(array( 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."de-jg4avhby1noc0d", $result); } public function testEncode17() { // Japanese $idna = $this->hexarray2string(array( 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."d9juau41awczczp", $result); } public function testEncode18() { // Greek $idna = $this->hexarray2string(array( 0x03b5, 0x03bb, 0x03bb, 0x03b7, 0x03bd, 0x03b9, 0x03ba, 0x03ac )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."hxargifdar", $result); } public function testEncode19() { // Maltese (Malti) $idna = $this->hexarray2string(array( 0x0062, 0x006f, 0x006e, 0x0121, 0x0075, 0x0073, 0x0061, 0x0127, 0x0127, 0x0061 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."bonusaa-5bb1da", $result); } public function testEncode20() { // Russian (Cyrillic) $idna = $this->hexarray2string(array( 0x043f, 0x043e, 0x0447, 0x0435, 0x043c, 0x0443, 0x0436, 0x0435, 0x043e, 0x043d, 0x0438, 0x043d, 0x0435, 0x0433, 0x043e, 0x0432, 0x043e, 0x0440, 0x044f, 0x0442, 0x043f, 0x043e, 0x0440, 0x0443, 0x0441, 0x0441, 0x043a, 0x0438 )); $result = $this->idn->encode($idna); $this->assertSame(IDNA_ACE_PREFIX."b1abfaaepdrnnbgefbadotcwatmq2g4l", $result); } } PK!K&test/Net_IDNA2/tests/Net_IDNA2Test.phpnu[idn = new Net_IDNA2(); } /** * Test if a complete URL consisting also of port-number etc. will be decoded just fine, test 1 * * @return void */ public function testShouldDecodePortNumbersFragmentsAndUrisCorrectly1() { $result = $this->idn->decode('http://www.xn--ml-6kctd8d6a.org:8080/test.php?arg1=1&arg2=2#fragment'); $this->assertSame("http://www.\xD0\xB5\xD1\x85\xD0\xB0m\xD1\x80l\xD0\xB5.org:8080/test.php?arg1=1&arg2=2#fragment", $result); } /** * Test if a complete URL consisting also of port-number etc. will be decoded just fine, test 2 * * @return void */ public function testShouldDecodePortNumbersFragmentsAndUrisCorrectly2() { $result = $this->idn->decode('http://xn--tst-qla.example.com:8080/test.php?arg1=1&arg2=2#fragment'); $this->assertSame("http://täst.example.com:8080/test.php?arg1=1&arg2=2#fragment", $result); } /** * Test encoding of German letter Eszett according to the original standard (IDNA2003) * * @return void */ public function testEncodingForGermanEszettUsingIDNA2003() { // make sure to use 2003-encoding $this->idn->setParams('version', '2003'); $result = $this->idn->encode('http://www.straße.example.com/'); $this->assertSame("http://www.strasse.example.com/", $result); } /** * Test encoding of German letter Eszett according to the "new" standard (IDNA2005/IDNAbis) * * @return void */ public function testEncodingForGermanEszettUsingIDNA2008() { // make sure to use 2008-encoding $this->idn->setParams('version', '2008'); $result = $this->idn->encode('http://www.straße.example.com/'); // switch back for other testcases $this->idn->setParams('version', '2003'); $this->assertSame("http://www.xn--strae-oqa.example.com/", $result); } } PK!. "test/XML_RPC/tests/extra-lines.phpnu[ * @copyright 2005-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version SVN: $Id: extra-lines.php 300958 2010-07-02 23:58:51Z danielc $ * @link http://pear.php.net/package/XML_RPC * @since File available since Release 1.4.4 */ /* * If the package version number is found in the left hand * portion of the if() expression below, that means this file has * come from the PEAR installer. Therefore, let's test the * installed version of XML_RPC which should be in the include path. * * If the version has not been substituted in the if() expression, * this file has likely come from a SVN checkout or a .tar file. * Therefore, we'll assume the tests should use the version of * XML_RPC that has come from there as well. */ if ('1.5.5' == '@'.'package_version'.'@') { ini_set('include_path', '../' . PATH_SEPARATOR . '.' . PATH_SEPARATOR . ini_get('include_path') ); } require_once 'XML/RPC.php'; $input = "First lfs\n\nSecond crlfs\r\n\r\nThird crs\r\rFourth line"; $expect_removed = "\r\n\r\nnada\r\n\r\n\r\nFirst lfs\r\nSecond crlfs\r\nThird crs\r\nFourth line\r\n\r\n\r\n\r\n"; $expect_not_removed = "\r\n\r\nnada\r\n\r\n\r\nFirst lfs\r\n\r\nSecond crlfs\r\n\r\nThird crs\r\n\r\nFourth line\r\n\r\n\r\n\r\n"; $msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input))); $msg->createPayload(); if ($msg->payload == $expect_removed) { echo "passed\n"; } else { echo "PROBLEM\n"; } $msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input))); $msg->remove_extra_lines = false; $msg->createPayload(); if ($msg->payload == $expect_not_removed) { echo "passed\n"; } else { echo "PROBLEM\n"; } PK!|E  )test/XML_RPC/tests/empty-value-struct.phpnu[ * @copyright 2005-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version SVN: $Id: empty-value-struct.php 300957 2010-07-02 23:55:00Z danielc $ * @link http://pear.php.net/package/XML_RPC * @since File available since Release 1.4.4 */ /* * If the package version number is found in the left hand * portion of the if() expression below, that means this file has * come from the PEAR installer. Therefore, let's test the * installed version of XML_RPC which should be in the include path. * * If the version has not been substituted in the if() expression, * this file has likely come from a SVN checkout or a .tar file. * Therefore, we'll assume the tests should use the version of * XML_RPC that has come from there as well. */ if ('1.5.5' == '@'.'package_version'.'@') { ini_set('include_path', '../' . PATH_SEPARATOR . '.' . PATH_SEPARATOR . ini_get('include_path') ); } require_once 'XML/RPC/Server.php'; $GLOBALS['HTTP_RAW_POST_DATA'] = << allgot fld1 EOPOST; $expect = << param 0: array ( 'fld1' => '', ) EOEXP; include './allgot.inc'; PK!3l** test/XML_RPC/tests/protoport.phpnu[ * @copyright 2005-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version SVN: $Id: protoport.php 300957 2010-07-02 23:55:00Z danielc $ * @link http://pear.php.net/package/XML_RPC * @since File available since Release 1.2 */ /* * If the package version number is found in the left hand * portion of the if() expression below, that means this file has * come from the PEAR installer. Therefore, let's test the * installed version of XML_RPC which should be in the include path. * * If the version has not been substituted in the if() expression, * this file has likely come from a SVN checkout or a .tar file. * Therefore, we'll assume the tests should use the version of * XML_RPC that has come from there as well. */ if ('1.5.5' == '@'.'package_version'.'@') { ini_set('include_path', '../' . PATH_SEPARATOR . '.' . PATH_SEPARATOR . ini_get('include_path') ); } require_once 'XML/RPC.php'; /** * Compare the test result to the expected result * * If the test fails, echo out the results. * * @param array $expect the array of object properties you expect * from the test * @param object $actual the object results from the test * @param string $test_name the name of the test * * @return void */ function compare($expect, $actual, $test_name) { $actual = get_object_vars($actual); if (count(array_diff($actual, $expect))) { echo "$test_name failed.\nExpect: "; print_r($expect); echo "Actual: "; print_r($actual); echo "\n"; } } if (php_sapi_name() != 'cli') { echo "
\n";
}


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver');
compare($x, $c, 'defaults');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'http://theserver');
compare($x, $c, 'defaults with http');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'https://theserver');
compare($x, $c, 'defaults with https');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'ssl://theserver');
compare($x, $c, 'defaults with ssl');


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 65,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 65);
compare($x, $c, 'port 65');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 65,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
compare($x, $c, 'port 65 with http');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 65,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
compare($x, $c, 'port 65 with https');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 65,
    'proxy' => '',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
compare($x, $c, 'port 65 with ssl');


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 0,
                        'theproxy');
compare($x, $c, 'defaults proxy');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'http://',
    'proxy_port' => 8080,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
                        'http://theproxy');
compare($x, $c, 'defaults with http proxy');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 443,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
                        'https://theproxy');
compare($x, $c, 'defaults with https proxy');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 443,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
                        'ssl://theproxy');
compare($x, $c, 'defaults with ssl proxy');


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 65,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'http://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 65,
                        'theproxy', 6565);
compare($x, $c, 'port 65 proxy 6565');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 65,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'http://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
                        'http://theproxy', 6565);
compare($x, $c, 'port 65 with http proxy 6565');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 65,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
                        'https://theproxy', 6565);
compare($x, $c, 'port 65 with https proxy 6565');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 65,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
                        'ssl://theproxy', 6565);
compare($x, $c, 'port 65 with ssl proxy 6565');


$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'ssl://',
    'port' => 443,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 443,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 443,
                        'theproxy', 443);
compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');

$x = array(
    'path' => 'thepath',
    'server' => 'theserver',
    'protocol' => 'http://',
    'port' => 80,
    'proxy' => 'theproxy',
    'proxy_protocol' => 'ssl://',
    'proxy_port' => 6565,
    'proxy_user' => '',
    'proxy_pass' => '',
    'errno' => 0,
    'errstring' => '',
    'debug' => 0,
    'username' => '',
    'password' => '',
);
$c = new XML_RPC_Client('thepath', 'theserver', 0,
                        'ssl://theproxy', 6565);
compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');

echo "\nIf no other output was produced, these tests passed.\n";
PK!Btest/XML_RPC/tests/allgot.incnu[
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: allgot.inc 293223 2010-01-07 15:32:19Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.4.4
 */

ob_start();

function returnAllGot($params) {
    $out = '';
    $count = count($params->params);
    for ($i = 0; $i < $count; $i++) {
        $param = $params->getParam($i);
        if (!XML_RPC_Value::isValue($param)) {
            $out .= "parameter $i was error: $param\n";
            continue;
        }
        $got = XML_RPC_Decode($param);
        $out .= "param $i: " . var_export($got, true) . "\n";
    }
    $val = new XML_RPC_Value($out, 'string');
    return new XML_RPC_Response($val);
}

$server = new XML_RPC_Server(
    array(
        'allgot' => array(
            'function' => 'returnAllGot',
        ),
    )
);

$got = ob_get_clean();

if ($got == $expect) {
    echo "passed\n";
} else {
    echo "FAILED\n";
    echo "Expected:\n$expect\n";
    echo "Got:\n$got\n";
}
PK!̢		test/XML_RPC/tests/types.phpnu[
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: types.php 300957 2010-07-02 23:55:00Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.4.4
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC/Server.php';


$GLOBALS['HTTP_RAW_POST_DATA'] = <<

 allgot
  
   default to string
   inside string
   8
   20050809T01:33:44

   
    
     
      
       
        a
       
       
        b
       
      
     
    
   

   
    
     
      
       a
       
        ay
       
      
      
       b
       
        be
       
      
     
    
   

  
 
EOPOST;

$expect = <<



param 0: 'default to string'
param 1: 'inside string'
param 2: '8'
param 3: '20050809T01:33:44'
param 4: array (
  0 => 'a',
  1 => 'b',
)
param 5: array (
  'a' => 'ay',
  'b' => 'be',
)




EOEXP;

include './allgot.inc';
PK!Jtest/XML_RPC/tests/encode.phpnu[
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: extra-lines.php 293218 2010-01-07 14:20:08Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.5.3
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC.php';


$input = array(10, 11, 12);

$expect = <<

nada




10
11
12





EOT;

$expect = trim(preg_replace("/\r\n/", "\n", $expect));

$msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input)));
$msg->createPayload();
$actual = trim(preg_replace("/\r\n/", "\n", $msg->payload));
if ($actual == $expect) {
    echo "passed\n";
} else {
    echo "PROBLEM\n";
    echo $actual;
}

$msg = new XML_RPC_Message('nada',
    array(
        new XML_RPC_Value(
            array(
                new XML_RPC_Value(10, 'int'),
                new XML_RPC_Value(11, 'int'),
                new XML_RPC_Value(12, 'int'),
            ),
            'array'
        )
    )
);
$msg->createPayload();
$actual = trim(preg_replace("/\r\n/", "\n", $msg->payload));
if ($actual == $expect) {
    echo "passed\n";
} else {
    echo "PROBLEM\n";
    echo $actual;
}
PK!XX test/XML_RPC/tests/test_Dump.phpnu[
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: test_Dump.php 300962 2010-07-03 02:24:24Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC/Dump.php';


$val = new XML_RPC_Value(array(
    'title'    =>new XML_RPC_Value('das ist der Titel', 'string'),
    'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
    'endDate'  =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
    'arkey'    => new XML_RPC_Value( array(
        new XML_RPC_Value('simple string'),
        new XML_RPC_Value(12345, 'int')
        ), 'array')
    )
    ,'struct');

XML_RPC_Dump($val);

echo '==============' . "\r\n";
$val2 = new XML_RPC_Value(44353, 'int');
XML_RPC_Dump($val2);

echo '==============' . "\r\n";
$val3 = new XML_RPC_Value('this should be a string', 'string');
XML_RPC_Dump($val3);

echo '==============' . "\r\n";
$val4 = new XML_RPC_Value(true, 'boolean');
XML_RPC_Dump($val4);

echo '==============' . "\r\n";
echo 'Next we will test the error handling...' . "\r\n";
$val5 = new XML_RPC_Value(array(
    'foo' => 'bar'
    ), 'struct');
XML_RPC_Dump($val5);

echo '==============' . "\r\n";
echo 'DONE' . "\r\n";
PK!$]"test/XML_RPC/tests/empty-value.phpnu[
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: empty-value.php 300957 2010-07-02 23:55:00Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.4.4
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC/Server.php';


$GLOBALS['HTTP_RAW_POST_DATA'] = <<

 allgot
  
   
   first
     
   
  
 
EOPOST;

$expect = <<



param 0: ''
param 1: 'first'
param 2: '  '
param 3: ''




EOEXP;

include './allgot.inc';
PK!b)))%test/XML_RPC/tests/actual-request.phpnu[
 * @copyright  2005-2010 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License
 * @version    SVN: $Id: actual-request.php 300957 2010-07-02 23:55:00Z danielc $
 * @link       http://pear.php.net/package/XML_RPC
 * @since      File available since Release 1.5.3
 */

/*
 * If the package version number is found in the left hand
 * portion of the if() expression below, that means this file has
 * come from the PEAR installer.  Therefore, let's test the
 * installed version of XML_RPC which should be in the include path.
 *
 * If the version has not been substituted in the if() expression,
 * this file has likely come from a SVN checkout or a .tar file.
 * Therefore, we'll assume the tests should use the version of
 * XML_RPC that has come from there as well.
 */
if ('1.5.5' == '@'.'package_version'.'@') {
    ini_set('include_path', '../'
            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
            . ini_get('include_path')
    );
}
require_once 'XML/RPC/Dump.php';


$debug = 0;

$params = array(
    new XML_RPC_Value('php.net', 'string'),
);
$msg = new XML_RPC_Message('domquery', $params);
$client = new XML_RPC_Client('/api/xmlrpc', 'www.adamsnames.com');
$client->setDebug($debug);

$resp = $client->send($msg);
if (!$resp) {
    echo 'Communication error: ' . $client->errstr;
    exit(1);
}
if ($resp->faultCode()) {
    /*
     * Display problems that have been gracefully cought and
     * reported by the xmlrpc.php script
     */
    echo 'Fault Code: ' . $resp->faultCode() . "\n";
    echo 'Fault Reason: ' . $resp->faultString() . "\n";
    exit(1);
}

$val = $resp->value();
XML_RPC_Dump($val);
PK!e>44/test/XML_Util/tests/CreateTagFromArrayTests.phpnu[ "foo:bar",
        );
        $expected = "";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespace()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
        );
        $expected = "";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributes()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
        );
        $expected = "";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContent()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expected = "I'm inside the tag";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndAttributesAndContent()
    {
        $original = array(
            "qname" => "foo:bar",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expected = "I'm inside the tag";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndContent()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "content"      => "I'm inside the tag",
        );
        $expected = "I'm inside the tag";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithEntitiesNone()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expected = "I'm inside the tag";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_ENTITIES_NONE));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntities()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expected = "I'm inside the tag";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineFalse()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = false;
        $expected = "I'm inside the tag";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrue()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $expected =
<<< EOF
I'm inside the tag
EOF;
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndent()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $indent = "  ";
        $expected =
<<< EOF
I'm inside the tag
EOF;
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreak()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $expected = "I'm inside the tag";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesTrue()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $sortAttributes = true;
        $expected = "I'm inside the tag";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesFalse()
    {
        $original = array(
            "qname" => "foo:bar",
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $multiline = true;
        $indent = "  ";
        $linebreak = "^";
        $sortAttributes = false;
        $expected = "I'm inside the tag";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithInvalidArray()
    {
        $badArray = array(
            "foo" => "bar",
        );
        $expectedError = "You must either supply a qualified name (qname) or local tag name (localPart).";
        $this->assertEquals($expectedError, XML_Util::createTagFromArray($badArray));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithNamespaceAndAttributesAndContentButWithoutQname()
    {
        $original = array(
            "namespaceUri" => "http://foo.com",
            "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
            "content"      => "I'm inside the tag",
        );
        $expectedError = "You must either supply a qualified name (qname) or local tag name (localPart).";
        $this->assertEquals($expectedError, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithNonScalarContent()
    {
        $badArray = array(
            'content' => array('foo', 'bar'),
        );
        $expectedError = "Supplied non-scalar value as tag content";
        $this->assertEquals($expectedError, XML_Util::createTagFromArray($badArray));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithArrayOfNamespaces()
    {
        $original = array(
            'qname'        => 'foo:bar',
            'namespaces'   => array('ns1' => 'uri1', 'ns2' => 'uri2'),
        );
        $expected = "";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameDerivedFromNamespaceUriAndLocalPart()
    {
        $original = array(
            'namespaceUri' => 'http://bar.org',
            'localPart'    => 'foo'
        );
        $expected = "";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameDerivedFromNamespaceAndLocalPart()
    {
        $original = array(
            'namespace'    => 'http://foo.org',
            'localPart'    => 'bar'
        );
        $expected = "";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithQnameDerivedFromLocalPart()
    {
        $original = array(
            'namespace'    => '',
            'localPart'    => 'bar'
        );
        $expected = "";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original));
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayWithImplicitlyEmptyContentAndCollapseNoneDoesNotCollapseTag()
    {
        $original = array('qname' => 'tag1');
        $expected = "";
        $actual = XML_Util::createTagFromArray(
            $original,
            XML_UTIL_REPLACE_ENTITIES,  // default $replaceEntities
            false,                      // default $multiline
            '_auto',                    // default $indent
            "\n",                       // default $linebreak
            true,                       // default $sortAttributes
            XML_UTIL_COLLAPSE_NONE
        );
        $this->assertEquals($expected, $actual);
    }

    /**
     * @covers XML_Util::createTagFromArray()
     */
    public function testCreateTagFromArrayForCdataWithExplicitlyEmptyContentDoesNotCollapseTag()
    {
        $original = array('qname' => 'tag1', 'content' => '');
        $expected = "";
        $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_CDATA_SECTION));
    }
}
PK!C,test/XML_Util/tests/ReplaceEntitiesTests.phpnu[.';
    }

    protected function getUtf8Data()
    {
        return 'This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê';
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleData()
    {
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData()));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithInvalidOptionReturnsOriginalData()
    {
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), 'INVALID_OPTION'));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesXml()
    {
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesXmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForUtf8DataWithEntitiesXmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesXmlRequired()
    {
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesXmlRequiredAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForUtf8DataWithEntitiesXmlRequiredAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesHtml()
    {
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForSimpleDataWithEntitiesHtmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This string contains < & >.";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML, $encoding));
    }

    /**
     * @covers XML_Util::replaceEntities()
     */
    public function testReplaceEntitiesForUtf8DataWithEntitiesHtmlAndEncoding()
    {
        $encoding = "UTF-8";
        $expected = "This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê";
        $this->assertEquals($expected, XML_Util::replaceEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_HTML, $encoding));
    }
}
PK!یu'test/XML_Util/tests/ApiVersionTests.phpnu[assertEquals('1.4', XML_Util::apiVersion());
    }
}PK!Gs$test/XML_Util/tests/Bug5392Tests.phpnu[, & and " as well as ä, ö, ß, à and ê';
        $replacedResult = XML_Util::replaceEntities($original, XML_UTIL_ENTITIES_HTML, "UTF-8");
        $reversedResult = XML_Util::reverseEntities($replacedResult, XML_UTIL_ENTITIES_HTML, "UTF-8");
        $this->assertEquals($original, $reversedResult, "Failed bugcheck.");
    }
}
PK!4ejj/test/XML_Util/tests/CreateCDataSectionTests.phpnu[";
        $this->assertEquals($expected, XML_Util::createCDataSection($original));
    }
}
PK!|\5.test/XML_Util/tests/CollapseEmptyTagsTests.phpnu[";
        $expected = "";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsBasicUsageAlongsideNonemptyTag()
    {
        $emptyTag = "";
        $otherTag = "baz";
        $expected = "baz";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagWithCollapseAll()
    {
        $emptyTag = "";
        $expected = "";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagWithCollapseAll()
    {
        $emptyTag = "";
        $otherTag = "baz";
        $expected = "baz";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagAlongsideEmptyTagWithCollapseAll()
    {
        $emptyTag = "";
        $otherTag = "baz";
        $expected = "baz";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag . $emptyTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyPrefixedTagAlongsideNonemptyTagAlongsideEmptyPrefixedTagWithCollapseAll()
    {
        $emptyTag = "";
        $otherTag = "baz";
        $expected = "baz";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag . $emptyTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyNsPrefixedTagAlongsideNonemptyTagAlongsideEmptyNsPrefixedTagWithCollapseAll()
    {
        $emptyTag = "";
        $otherTag = "baz";
        $expected = "baz";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag . $emptyTag, XML_UTIL_COLLAPSE_ALL));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagWithCollapseXhtml()
    {
        $emptyTag = "";
        $expected = "";
        $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_XHTML_ONLY));
    }

    /**
     * @covers XML_Util::collapseEmptyTags()
     */
    public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagWithCollapseXhtml()
    {
        $emptyTag = "";
        $otherTag = "baz";
        $xhtmlTag = "

"; $expected = "
baz"; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $xhtmlTag . $otherTag, XML_UTIL_COLLAPSE_XHTML_ONLY)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyTagWithCollapseNone() { $emptyTag = ""; $expected = ""; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_NONE)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagWithCollapseNone() { $emptyTag = ""; $otherTag = "baz"; $expected = "baz"; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag, XML_UTIL_COLLAPSE_NONE)); } } PK!GG/test/XML_Util/tests/SplitQualifiedNameTests.phpnu[ 'xslt', 'localPart' => 'stylesheet', ); $this->assertEquals($expected, XML_Util::splitQualifiedName($original)); } /** * @covers XML_Util::splitQualifiedName() */ public function testSplitQualifiedNameWithNamespace() { $original = "stylesheet"; $namespace = "myNs"; $expected = array( 'namespace' => 'myNs', 'localPart' => 'stylesheet', ); $this->assertEquals($expected, XML_Util::splitQualifiedName($original, $namespace)); } } PK!Yq%test/XML_Util/tests/Bug21184Tests.phpnu[one'; $this->assertEquals($xml, XML_Util::collapseEmptyTags($xml, XML_UTIL_COLLAPSE_ALL)); } } PK!>M$test/XML_Util/tests/Bug4950Tests.phpnu[ here!"; $namespaceUrl = null; $expected = " here!]]>"; $result = XML_Util::createTag($qname, $attributes, $content, $namespaceUrl, XML_UTIL_CDATA_SECTION); $this->assertEquals($expected, $result, "Failed bugcheck."); } } PK!YR""/test/XML_Util/tests/CreateStartElementTests.phpnu["; $this->assertEquals($expected, XML_Util::createStartElement($original)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributes() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $expected = ""; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithEmptyAttributes() { $originalTag = "myNs:myTag"; $originalAttributes = ""; $expected = ""; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespace() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = ""; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithEmptyAttributesAndNonUriNamespace() { $originalTag = "myTag"; $originalAttributes = ""; $originalNamespace = "foo"; $expected = ""; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultiline() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = <<< EOF EOF; $multiline = true; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndent() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = <<< EOF EOF; $multiline = true; $indent = " "; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndentAndLinebreak() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = ""; $multiline = true; $indent = " "; $linebreak = "^"; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent, $linebreak)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndentAndLinebreakAndSortAttributesIsTrue() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar", "boo" => "baz"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = ""; $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = true; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent, $linebreak, $sortAttributes)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndentAndLinebreakAndSortAttributesIsFalse() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar", "boo" => "baz"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = ""; $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = false; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent, $linebreak, $sortAttributes)); } } PK!ܬ$2test/XML_Util/tests/GetDocTypeDeclarationTests.phpnu["; $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag")); } /** * @covers XML_Util::getDocTypeDeclaration() */ public function testGetDocTypeDeclarationUsingRootAndStringUri() { $expected = ""; $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag", "myDocType.dtd")); } /** * @covers XML_Util::getDocTypeDeclaration() */ public function testGetDocTypeDeclarationUsingRootAndArrayUri() { $uri = array( 'uri' => 'http://pear.php.net/dtd/package-1.0', 'id' => '-//PHP//PEAR/DTD PACKAGE 0.1' ); $expected = ""; $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag", $uri)); } /** * @covers XML_Util::getDocTypeDeclaration() */ public function testGetDocTypeDeclarationUsingRootAndArrayUriAndInternalDtd() { $uri = array( 'uri' => 'http://pear.php.net/dtd/package-1.0', 'id' => '-//PHP//PEAR/DTD PACKAGE 0.1' ); $dtdEntry = ''; $expected = <<< EOF ]> EOF; $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag", $uri, $dtdEntry)); } } PK!G%test/XML_Util/tests/Bug21177Tests.phpnu['; return array( array('', ''), array('', ''), array('', ''), array('', ''), ); } /** * @dataProvider getTestCandidate() */ public function testCollapseEmptyTagsForBug21177($original, $expected) { $this->assertEquals($expected, XML_Util::collapseEmptyTags($original, XML_UTIL_COLLAPSE_ALL), "Failed bugcheck."); } } PK!۩%test/XML_Util/tests/Bug18343Tests.phpnu[ "install", "attributes" => array( "as" => "Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&s=Newsweek", "name" => "test/Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&s=Newsweek", ) ); public function getFlagsToTest() { new XML_Util(); // for constants to be declared return array( array('no flag', null), array('false', false), array('ENTITIES_NONE', XML_UTIL_ENTITIES_NONE), array('ENTITIES_XML', XML_UTIL_ENTITIES_XML), array('ENTITIES_XML_REQUIRED', XML_UTIL_ENTITIES_XML_REQUIRED), array('ENTITIES_HTML', XML_UTIL_ENTITIES_HTML), array('REPLACE_ENTITIES', XML_UTIL_REPLACE_ENTITIES), ); } /** * @dataProvider getFlagsToTest() */ public function testCreateTagFromArrayForBug18343($key, $flag) { // all flags for the candidate input should return the same result $expected = <<< EOF EOF; $this->assertEquals($expected, XML_Util::createTagFromArray($this->tagArray, $flag), "Failed bugcheck for $key."); } } PK!zt,test/XML_Util/tests/ReverseEntitiesTests.phpnu[."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData())); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithInvalidOptionReturnsOriginalData() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), 'INVALID_OPTION')); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesXml() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesXmlAndEncoding() { $encoding = "UTF-8"; $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML), $encoding); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForUtf8DataWithEntitiesXmlAndEncoding() { $encoding = "UTF-8"; $expected = "This data contains special chars like <, >, & and \" as well as ä, ö, ß, à and ê"; $this->assertEquals($expected, XML_Util::reverseEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML), $encoding); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesXmlRequired() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesXmlRequiredAndEncoding() { $encoding = "UTF-8"; $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForUtf8DataWithEntitiesXmlRequiredAndEncoding() { $encoding = "UTF-8"; $expected = "This data contains special chars like <, >, & and \" as well as ä, ö, ß, à and ê"; $this->assertEquals($expected, XML_Util::reverseEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesHtml() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesHtmlAndEncoding() { $encoding = "UTF-8"; $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML, $encoding)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForUtf8DataWithEntitiesHtmlAndEncoding() { $encoding = "UTF-8"; $expected = "This data contains special chars like <, >, & and \" as well as ä, ö, ß, à and ê"; $this->assertEquals($expected, XML_Util::reverseEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_HTML, $encoding)); } } PK!~$[ee-test/XML_Util/tests/CreateEndElementTests.phpnu["; $this->assertEquals($expected, XML_Util::createEndElement($original)); } /** * @covers XML_Util::createEndElement() */ public function testCreateEndElementWithNamespacedTag() { $original = "myNs:myTag"; $expected = ""; $this->assertEquals($expected, XML_Util::createEndElement($original)); } } PK!!)test/XML_Util/tests/AbstractUnitTests.phpnu[ "bar"); $expected = ""; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContent() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag"; $expected = "This is inside the tag"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespace() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag"; $originalNamespace = "http://www.w3c.org/myNs#"; $expected = "This is inside the tag"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithCDataSection() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $expected = " in it]]>"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_CDATA_SECTION)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntities() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineFalse() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = false; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrue() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $expected = <<< EOF This is inside the tag and has < & @ > in it EOF; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndent() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $indent = " "; $expected = <<< EOF This is inside the tag and has < & @ > in it EOF; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreak() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $indent = " "; $linebreak = "^"; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesTrue() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar", "boo" => "baz"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = true; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesFalse() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar", "boo" => "baz"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = false; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes)); } } PK!Df:.test/XML_Util/tests/GetXmlDeclarationTests.phpnu["; $this->assertEquals($expected, XML_Util::getXMLDeclaration($version)); } /** * @covers XML_Util::getXMLDeclaration() */ public function testGetXMLDeclarationUsingVersionAndEncodingAndStandalone() { $version = "1.0"; $encoding = "UTF-8"; $standalone = true; $expected = ""; $this->assertEquals($expected, XML_Util::getXMLDeclaration($version, $encoding, $standalone)); } /** * @covers XML_Util::getXMLDeclaration() */ public function testGetXMLDeclarationUsingVersionAndStandalone() { $version = "1.0"; $encoding = null; $standalone = true; $expected = ""; $this->assertEquals($expected, XML_Util::getXMLDeclaration($version, $encoding, $standalone)); } } PK!Zt/test/XML_Util/tests/AttributesToStringTests.phpnu[ 'bar','boo' => 'baz',); $expected = " boo=\"baz\" foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithExplicitSortTrue() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " boo=\"baz\" foo=\"bar\""; $sort = true; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithExplicitSortFalse() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " foo=\"bar\" boo=\"baz\""; $sort = false; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithMultilineFalse() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " boo=\"baz\" foo=\"bar\""; $sort = true; $multiline = false; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithMultilineTrue() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = <<< EOF boo="baz" foo="bar" EOF; $sort = true; $multiline = true; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithExplicitIndent() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " boo=\"baz\"\n foo=\"bar\""; $sort = true; $multiline = true; $indent = ' '; // 8 spaces $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $indent)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithExplicitLinebreak() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " boo=\"baz\"\n^foo=\"bar\""; $sort = true; $multiline = true; $linebreak = '^'; // some dummy character $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithOptionsThatIncludesSort() { $original = array('foo' => 'bar','boo' => 'baz',); $options = array( 'multiline' => true, 'indent' => '----', 'linebreak' => "^", 'entities' => XML_UTIL_ENTITIES_XML, 'sort' => true, ); $expected = " boo=\"baz\"\n----foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original, $options)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithOptionsThatExcludesSort() { $original = array('foo' => 'bar','boo' => 'baz',); $options = array( 'multiline' => true, 'indent' => '----', 'linebreak' => "^", 'entities' => XML_UTIL_ENTITIES_XML, ); $expected = " boo=\"baz\"\n----foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original, $options)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithEntitiesNone() { $original = array("foo" => "b@&r", "boo" => "b>assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_NONE)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithEntitiesXml() { $original = array("foo" => "b@&r", "boo" => "b>assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_XML)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithEntitiesXmlRequired() { $original = array("foo" => "b@&r", "boo" => "b><z\" foo=\"b@&r\""; $sort = true; $multiline = false; $linebreak = ' '; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_XML_REQUIRED)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithEntitiesHtml() { $original = array("foo" => "b@&r", "boo" => "b>assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_HTML)); } /** * Tag attributes should not be treated as CDATA, * so the operation will instead quietly use XML_UTIL_ENTITIES_XML. * * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithCDataSectionForSingleAttribute() { $original = array('foo' => 'bar'); // need exactly one attribute here $options = array( 'sort' => true, // doesn't matter for this testcase 'multiline' => false, // doesn't matter for this testcase 'indent' => null, // doesn't matter for this testcase 'linebreak' => null, // doesn't matter for this testcase 'entities' => XML_UTIL_CDATA_SECTION, // DOES matter for this testcase ); $expected = " foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original, $options)); } /** * Tag attributes should not be treated as CDATA, * so the operation will instead quietly use XML_UTIL_ENTITIES_XML. * * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithCDataSectionForMultipleAttributesAndMultilineFalse() { $original = array('foo' => 'bar', 'boo' => 'baz'); // need more than one attribute here $options = array( 'sort' => true, // doesn't matter for this testcase 'multiline' => false, // DOES matter for this testcase, must be false 'indent' => null, // doesn't matter for this testcase 'linebreak' => null, // doesn't matter for this testcase 'entities' => XML_UTIL_CDATA_SECTION, // DOES matter for this testcase ); $expected = " boo=\"baz\" foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original, $options)); } } PK!ݑh(test/XML_Util/tests/IsValidNameTests.phpnu[assertTrue($result); } /** * @covers XML_Util::isValidName() */ public function testIsValidNameForTagNameWithInvalidCharacter() { $tagName = "invalidTag?"; $result = XML_Util::isValidName($tagName); $this->assertInstanceOf('PEAR_Error', $result); $expectedError = "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores"; $this->assertEquals($expectedError, $result->getMessage()); } /** * @covers XML_Util::isValidName() */ public function testIsValidNameForTagNameWithInvalidStartingCharacter() { $tagName = "1234five"; $result = XML_Util::isValidName($tagName); $this->assertInstanceOf('PEAR_Error', $result); $expectedError = "XML names may only start with letter or underscore"; $this->assertEquals($expectedError, $result->getMessage()); } /** * @covers XML_Util::isValidName() */ public function testIsValidNameForInt() { $tagName = 1; $result = XML_Util::isValidName($tagName); $this->assertInstanceOf('PEAR_Error', $result); $expectedError = "XML names may only start with letter or underscore"; $this->assertEquals($expectedError, $result->getMessage()); } /** * @covers XML_Util::isValidName() */ public function testIsValidNameForEmptyString() { $tagName = ''; $result = XML_Util::isValidName($tagName); $this->assertInstanceOf('PEAR_Error', $result); $expectedError = "XML names may only start with letter or underscore"; $this->assertEquals($expectedError, $result->getMessage()); } } PK!TT*test/XML_Util/tests/CreateCommentTests.phpnu["; $this->assertEquals($expected, XML_Util::createComment($original)); } } PK!rv'test/XML_Util/tests/RaiseErrorTests.phpnu[assertInstanceOf('PEAR_Error', $error); $this->assertEquals($message, $error->getMessage()); $this->assertEquals($code, $error->getCode()); } } PK!<ȸB!!test/Net_SMTP/tests/auth.phptnu[--TEST-- Net_SMTP: SMTP Authentication --SKIPIF-- connect())) { die($e->getMessage() . "\n"); } if (PEAR::isError($e = $smtp->auth(TEST_AUTH_USER, TEST_AUTH_PASS))) { die("Authentication failure\n"); } $smtp->disconnect(); echo 'Success!'; --EXPECT-- Success! PK!Pgހ"test/Net_SMTP/tests/quotedata.phptnu[--TEST-- Net_SMTP: quotedata() --FILE-- "\r\n", "\r\n" => "\r\n", "\nxx" => "\r\nxx", "xx\n" => "xx\r\n", "xx\nxx" => "xx\r\nxx", "\n\nxx" => "\r\n\r\nxx", "xx\n\nxx" => "xx\r\n\r\nxx", "xx\n\n" => "xx\r\n\r\n", "\r\nxx" => "\r\nxx", "xx\r\n" => "xx\r\n", "xx\r\nxx" => "xx\r\nxx", "\r\n\r\nxx" => "\r\n\r\nxx", "xx\r\n\r\nxx" => "xx\r\n\r\nxx", "xx\r\n\r\n" => "xx\r\n\r\n", "\r\n\nxx" => "\r\n\r\nxx", "\n\r\nxx" => "\r\n\r\nxx", "xx\r\n\nxx" => "xx\r\n\r\nxx", "xx\n\r\nxx" => "xx\r\n\r\nxx", "xx\r\n\n" => "xx\r\n\r\n", "xx\n\r\n" => "xx\r\n\r\n", "\r" => "\r\n", "\rxx" => "\r\nxx", "xx\rxx" => "xx\r\nxx", "xx\r" => "xx\r\n", "\r\r" => "\r\n\r\n", "\r\rxx" => "\r\n\r\nxx", "xx\r\rxx" => "xx\r\n\r\nxx", "xx\r\r" => "xx\r\n\r\n", "xx\rxx\nxx\r\nxx" => "xx\r\nxx\r\nxx\r\nxx", "\r\r\n\n" => "\r\n\r\n\r\n", /* Dots */ "." => "..", "xxx\n." => "xxx\r\n..", "xxx\n.\nxxx" => "xxx\r\n..\r\nxxx", "xxx.\n.xxx" => "xxx.\r\n..xxx", ); function literal($x) { return str_replace(array("\r", "\n"), array('\r', '\n'), $x); } $error = false; foreach ($tests as $input => $expected) { $output = $input; Net_SMTP::quotedata($output); if ($output != $expected) { printf("Error: '%s' => '%s' (expected: '%s')", literal($input), literal($output), literal($expected)); $error = true; } } if (!$error) { echo "success\n"; } --EXPECT-- success PK!A-test/Net_SMTP/tests/basic.phptnu[--TEST-- Net_SMTP: Basic Functionality --SKIPIF-- connect())) { die($e->getMessage() . "\n"); } if (PEAR::isError($e = $smtp->auth(TEST_AUTH_USER, TEST_AUTH_PASS))) { die("Authentication failure\n"); } if (PEAR::isError($smtp->mailFrom(TEST_FROM))) { die('Unable to set sender to <' . TEST_FROM . ">\n"); } if (PEAR::isError($res = $smtp->rcptTo(TEST_TO))) { die('Unable to add recipient <' . TEST_TO . '>: ' . $res->getMessage() . "\n"); } if (PEAR::isError($smtp->data('Subject: ' . TEST_SUBJECT . "\r\n\r\n" . TEST_BODY))) { die("Unable to send data\n"); } $smtp->disconnect(); echo 'Success!'; --EXPECT-- Success! PK!6#test/Net_SMTP/tests/config.php.distnu[ * @copyright 2006 Anish Mistry * @license http://www.opensource.org/licenses/bsd-license.php BSD * @version SVN: $Id$ * @link http://pear.php.net/package/Net_Sieve */ require_once dirname(__FILE__) . '/../Sieve.php'; /** * PHPUnit test case for Net_Sieve. * * @category Networking * @package Net_Sieve * @author Anish Mistry * @copyright 2006 Anish Mistry * @license http://www.opensource.org/licenses/bsd-license.php BSD * @version Release: @package_version@ * @link http://pear.php.net/package/Net_Sieve */ class SieveTest extends PHPUnit\Framework\TestCase { // contains the object handle of the string class protected $fixture; protected function setUp() { if (!file_exists(dirname(__FILE__) . '/config.php')) { $this->markTestSkipped('Test configuration incomplete. Copy config.php.dist to config.php.'); } require_once dirname(__FILE__) . '/config.php'; // Create a new instance of Net_Sieve. $this->_pear = new PEAR(); $this->fixture = new Net_Sieve(); $this->scripts = array( 'test script1' => "require \"fileinto\";\r\nif header :contains \"From\" \"@cnba.uba.ar\" \r\n{fileinto \"INBOX.Test1\";}\r\nelse \r\n{fileinto \"INBOX\";}", 'test script2' => "require \"fileinto\";\r\nif header :contains \"From\" \"@cnba.uba.ar\" \r\n{fileinto \"INBOX.Test\";}\r\nelse \r\n{fileinto \"INBOX\";}", 'test"scriptäöü3' => "require \"vacation\";\nvacation\n:days 7\n:addresses [\"matthew@de-construct.com\"]\n:subject \"This is a test\"\n\"I'm on my holiday!\nsadfafs\";", 'test script4' => file_get_contents(dirname(__FILE__) . '/largescript.siv')); } protected function tearDown() { // Delete the instance. unset($this->fixture); } protected function login() { $result = $this->fixture->connect(HOST, PORT); $this->assertTrue($this->check($result), 'Can not connect'); $result = $this->fixture->login(USERNAME, PASSWORD, null, '', false); $this->assertTrue($this->check($result), 'Can not login'); } protected function logout() { $result = $this->fixture->disconnect(); $this->assertFalse($this->_pear->isError($result), 'Error on disconnect'); } protected function clear() { // Clear all the scripts in the account. $this->login(); $active = $this->fixture->getActive(); if (isset($this->scripts[$active])) { $this->fixture->setActive(null); } foreach (array_keys($this->scripts) as $script) { $this->fixture->removeScript($script); } $this->logout(); } protected function check($result) { if ($this->_pear->isError($result)) { throw new Exception($result->getMessage()); } return $result; } public function testConnect() { $result = $this->fixture->connect(HOST, PORT); $this->assertTrue($this->check($result), 'Cannot connect'); } public function testLogin() { $result = $this->fixture->connect(HOST, PORT); $this->assertTrue($this->check($result), 'Cannot connect'); $result = $this->fixture->login(USERNAME, PASSWORD, null, '', false); $this->assertTrue($this->check($result), 'Cannot login'); } public function testDisconnect() { $result = $this->fixture->connect(HOST, PORT); $this->assertFalse($this->_pear->isError($result), 'Cannot connect'); $result = $this->fixture->login(USERNAME, PASSWORD, null, '', false); $this->assertFalse($this->_pear->isError($result), 'Cannot login'); $result = $this->fixture->disconnect(); $this->assertFalse($this->_pear->isError($result), 'Error on disconnect'); } public function testListScripts() { $this->login(); $scripts = $this->fixture->listScripts(); $this->logout(); $this->assertFalse($this->_pear->isError($scripts), 'Can not list scripts'); } public function testInstallScript() { $this->clear(); $this->login(); // First script. $scriptname = 'test script1'; $before_scripts = $this->fixture->listScripts(); $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]); $this->assertFalse($this->_pear->isError($result), 'Can not install script ' . $scriptname); $after_scripts = $this->fixture->listScripts(); $diff_scripts = array_values(array_diff($after_scripts, $before_scripts)); $this->assertTrue(count($diff_scripts) > 0, 'Script not installed'); $this->assertEquals($scriptname, $diff_scripts[0], 'Added script has a different name'); // Second script (install and activate) $scriptname = 'test script2'; $before_scripts = $this->fixture->listScripts(); $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname], true); $this->assertFalse($this->_pear->isError($result), 'Can not install script ' . $scriptname); $after_scripts = $this->fixture->listScripts(); $diff_scripts = array_values(array_diff($after_scripts, $before_scripts)); $this->assertTrue(count($diff_scripts) > 0, 'Script not installed'); $this->assertEquals($scriptname, $diff_scripts[0], 'Added script has a different name'); $active_script = $this->fixture->getActive(); $this->assertEquals($scriptname, $active_script, 'Added script has a different name'); $this->logout(); } /** * There is a good chance that this test will fail since most servers have * a 32KB limit on uploaded scripts. */ public function testInstallScriptLarge() { $this->clear(); $this->login(); $scriptname = 'test script4'; $before_scripts = $this->fixture->listScripts(); $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]); $this->assertFalse($this->_pear->isError($result), 'Unable to upload large script (expected behavior for most servers)'); $after_scripts = $this->fixture->listScripts(); $diff_scripts = array_diff($after_scripts, $before_scripts); $this->assertEquals($scriptname, reset($diff_scripts), 'Added script has a different name'); $this->logout(); } /** * See bug #16691. */ public function testInstallNonAsciiScript() { $this->clear(); $this->login(); $scriptname = 'test"scriptäöü3'; $before_scripts = $this->fixture->listScripts(); $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]); $this->assertFalse($this->_pear->isError($result), 'Can not install script ' . $scriptname); $after_scripts = $this->fixture->listScripts(); $diff_scripts = array_values(array_diff($after_scripts, $before_scripts)); $this->assertTrue(count($diff_scripts) > 0, 'Script not installed'); $this->assertEquals($scriptname, $diff_scripts[0], 'Added script has a different name'); $this->logout(); } public function testGetScript() { $this->clear(); $this->login(); $scriptname = 'test script1'; $before_scripts = $this->fixture->listScripts(); $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]); $this->assertFalse($this->_pear->isError($result), 'Can not install script ' . $scriptname); $after_scripts = $this->fixture->listScripts(); $diff_scripts = array_values(array_diff($after_scripts, $before_scripts)); $this->assertTrue(count($diff_scripts) > 0); $this->assertEquals($scriptname, $diff_scripts[0], 'Added script has a different name'); $script = $this->fixture->getScript($scriptname); $this->assertEquals(trim($this->scripts[$scriptname]), trim($script), 'Script installed is not the same script retrieved'); $this->logout(); } public function testGetActive() { $this->clear(); $this->login(); $active_script = $this->fixture->getActive(); $this->assertFalse($this->_pear->isError($active_script), 'Error getting the active script'); $this->logout(); } public function testSetActive() { $this->clear(); $scriptname = 'test script1'; $this->login(); $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]); $result = $this->fixture->setActive($scriptname); $this->assertFalse($this->_pear->isError($result), 'Can not set active script'); $active_script = $this->fixture->getActive(); $this->assertEquals($scriptname, $active_script, 'Active script does not match'); // Test for non-existant script. $result = $this->fixture->setActive('non existant script'); $this->assertTrue($this->_pear->isError($result)); $this->logout(); } public function testRemoveScript() { $this->clear(); $scriptname = 'test script1'; $this->login(); $result = $this->fixture->installScript($scriptname, $this->scripts[$scriptname]); $result = $this->fixture->removeScript($scriptname); $this->assertFalse($this->_pear->isError($result), 'Error removing active script'); $this->logout(); } } PK!Ynpp$test/Net_Sieve/tests/config.php.distnu[test/Mail_mimeDecode/tests/semicolon_content_type_bug1724.phptnu[--TEST-- Bug #1724 Quoted Semicolons in Content-Type --SKIPIF-- --FILE-- setTXTBody('Test message.'); $Mime->addAttachment('test file contents', 'text/plain; testparam="test1;semicolon"', 'test.txt', FALSE); $body = $Mime->get(); $hdrs = ''; foreach ($Mime->headers() AS $name => $val) { $hdrs .= "$name: $val\n"; } $hdrs .= "To: Receiver \n"; $hdrs .= "From: Sender \n"; $hdrs .= "Subject: PEAR::Mail_Mime test mail\n"; require_once('Mail/mimeDecode.php'); $mime_message = "$hdrs\n$body"; $Decoder = new Mail_mimeDecode($mime_message); $params = array( 'include_bodies' => TRUE, 'decode_bodies' => TRUE, 'decode_headers' => TRUE ); $Decoded = $Decoder->decode($params); $test_param = $Decoded->parts[1]->ctype_parameters['testparam']; echo $test_param; ?> --EXPECT-- test1;semicolon PK!s%2test/Mail_mimeDecode/tests/parse_header_value.phptnu[--TEST-- Tests for _parseHeaderValue --SKIPIF-- --FILE-- setTXTBody('Test message.'); $contentAppend = 'testparam1="test1;semicolon";testparam2=two; testparam3="three"; ' .'testparam4="four\;4\;four"; testparam5=five\;5\;five; ' ."testparam6='six'; testparam7='seven;7';testparam8='eight\;8'; " .'testparam9="nine;9";testparam10="ten\;10"; ' .'testparam11=\'a "double" quote\'; testparam12="a \'simple\' quote"; ' .'testparam13=\'another " quote\'; testparam14="another \' quote";' .'testparam15=last'; $Mime->addAttachment('test file contents', "text/plain; $contentAppend", 'test.txt', FALSE); $body = $Mime->get(); $hdrs = ''; foreach ($Mime->headers() AS $name => $val) { $hdrs .= "$name: $val\n"; } $hdrs .= "To: Receiver \n"; $hdrs .= "From: Sender \n"; $hdrs .= "Subject: PEAR::Mail_Mime test mail\n"; require_once 'Mail/mimeDecode.php'; $mime_message = "$hdrs\n$body"; $Decoder = new Mail_mimeDecode($mime_message); $params = array( 'include_bodies' => TRUE, 'decode_bodies' => TRUE, 'decode_headers' => TRUE ); $Decoded = $Decoder->decode($params); $decodedParts = $Decoded->parts[1]->ctype_parameters; //Bug #4057: Content-type params now have a name attribute. unset($decodedParts['name']); print_r($decodedParts); ?> --EXPECT-- Array ( [testparam1] => test1;semicolon [testparam2] => two [testparam3] => three [testparam4] => four;4;four [testparam5] => five;5;five [testparam6] => six [testparam7] => seven;7 [testparam8] => eight;8 [testparam9] => nine;9 [testparam10] => ten;10 [testparam11] => a "double" quote [testparam12] => a 'simple' quote [testparam13] => another " quote [testparam14] => another ' quote [testparam15] => last ) PK!;{'test/Mail_Mime/tests/test_Bug_GH19.phptnu[--TEST-- Bug GH-19 Test boundary value with different headers()/get() call order --SKIPIF-- --FILE-- setHTMLBody('html'); $mime->setTXTBody('text'); $body = $mime->get(); $hdrs = $mime->headers(array( 'From' => 'test@domain.tld', 'Subject' => 'Subject', 'To' => 'to@domain.tld' )); preg_match('/boundary="([^"]+)/', $hdrs['Content-Type'], $matches); $boundary = $matches[1]; echo substr_count($body, "--$boundary") . "\n"; // Test headers() before get() $mime = new Mail_mime("\r\n"); $mime->setHTMLBody('html'); $mime->setTXTBody('text'); $hdrs = $mime->headers(array( 'From' => 'test@domain.tld', 'Subject' => 'Subject', 'To' => 'to@domain.tld' )); $body = $mime->get(); preg_match('/boundary="([^"]+)/', $hdrs['Content-Type'], $matches); $boundary = $matches[1]; echo substr_count($body, "--$boundary"); --EXPECT-- 3 3 PK!Eoo(test/Mail_Mime/tests/test_Bug_13962.phptnu[--TEST-- Bug #13962 Multiple header support --SKIPIF-- --FILE-- setFrom('user@from.example.com'); $r = $mime->txtHeaders(array('Received' => array('Received 1', 'Received 2'))); print_r($r); ?> --EXPECT-- Received: Received 1 Received: Received 2 MIME-Version: 1.0 From: user@from.example.com PK!Ԣ``(test/Mail_Mime/tests/test_Bug_21255.phptnu[--TEST-- Bug #21255 Boundary gets added twice --SKIPIF-- --FILE-- setHTMLBody('html'); $mime->setTXTBody('text'); $mime->setContentType('multipart/alternative', array('boundary' => 'something')); $msg = $mime->getMessage(); echo substr_count($msg, 'boundary='); ?> --EXPECT-- 1 PK!i;)test/Mail_Mime/tests/test_Bug_7561_1.phptnu[--TEST-- Bug #7561 Mail_mimePart::quotedPrintableEncode() misbehavior with mbstring overload --INI-- mbstring.language=Neutral mbstring.func_overload=6 mbstring.internal_encoding=UTF-8 mbstring.http_output=UTF-8 --SKIPIF-- '; $charset = 'ISO-2022-JP'; $encoding = 'base64'; foreach ($tests as $test) { $test = mb_convert_encoding($test, $charset, 'UTF-8'); print Mail_mimePart::encodeHeader("subject", $test, $charset, $encoding) . PHP_EOL; print Mail_mimePart::encodeHeader("to", $test.$addr, $charset, $encoding) . PHP_EOL; $test = '"' . $test . '"'; print Mail_mimePart::encodeHeader("subject", $test, $charset, $encoding) . PHP_EOL; print Mail_mimePart::encodeHeader("to", $test.$addr, $charset, $encoding) . PHP_EOL; } ?> --EXPECT-- =?ISO-2022-JP?B?GyRCIiI1fkVUSVwiIhsoQg==?= =?ISO-2022-JP?B?GyRCIiI1fkVUSVwiIhsoQg==?= =?ISO-2022-JP?B?GyRCIiI1fkVUSVwiIhsoQg==?= =?ISO-2022-JP?B?GyRCIiI1fkVUSVwiIhsoQg==?= =?ISO-2022-JP?B?GyRCIlwiXCJcIlwbKEI=?= =?ISO-2022-JP?B?GyRCIlwiXCJcIlwbKEI=?= =?ISO-2022-JP?B?GyRCIlwiXCJcIlwbKEI=?= =?ISO-2022-JP?B?GyRCIlwiXCJcIlwbKEI=?= PK!Y'test/Mail_Mime/tests/test_Bug_GH26.phptnu[--TEST-- Bug GH-26 Backward slash is getting added in headers --SKIPIF-- --FILE-- '; $to = <<,,t@mail.com EOT; $subject = "Test mime"; $mailbody = "hello world"; $mail_mime->setTxtBody($mailbody); $mail_mime->setHTMLBody($mailbody); $mail_mime->setSubject($subject); $mail_mime->setFrom($from); $body = $mail_mime->get(); $extra_headers = array(); $extra_headers["To"] = $to; $arr_hdrs = $mail_mime->headers($extra_headers); echo $arr_hdrs['From'] . "\n" . $arr_hdrs['To']; --EXPECT-- "George B@@Z" "austin test" , , t@mail.comPK!RoUU(test/Mail_Mime/tests/test_Bug_20226.phptnu[--TEST-- Bug #20226 Mail_mimePart::encodeHeader() and ISO-2022-JP encoding --SKIPIF-- --FILE-- encodeHeader('subject', $subject, 'ISO-2022-JP', 'base64'); ?> --EXPECT-- =?ISO-2022-JP?B?GyRCJT8lJCVIJWsbKEI=?= PK!g+(test/Mail_Mime/tests/test_Bug_13444.phptnu[--TEST-- Bug #9725 multipart/related & alternative wrong order --SKIPIF-- --FILE-- setTXTBody("test"); $mime->setHTMLBody("test"); $mime->addHTMLImage("test", 'application/octet-stream', '', false); $body = $mime->get(); $head = $mime->headers(); $headCT = $head['Content-Type']; $headCT = explode(";", $headCT); $headCT = $headCT[0]; $ct = preg_match_all('|Content-Type: ([^;\r\n]+)|', $body, $matches); print($headCT); print("\n"); foreach ($matches[1] as $match){ print($match); print("\n"); } --EXPECT-- multipart/alternative text/plain multipart/related text/html application/octet-stream PK!%BB'test/Mail_Mime/tests/test_Bug_GH16.phptnu[--TEST-- Bug GH-16 Test methods that write to a file --SKIPIF-- --FILE-- setHTMLBody('html'); $mime->setTXTBody('text'); $mime->setContentType('multipart/alternative', array('boundary' => 'something')); $temp_filename = dirname(__FILE__) . "/output1.tmp"; touch($temp_filename); $msg = $mime->saveMessageBody($temp_filename); echo file_get_contents($temp_filename); $temp_filename = dirname(__FILE__) . "/output2.tmp"; touch($temp_filename); $msg = $mime->saveMessage($temp_filename); echo file_get_contents($temp_filename); $temp_filename = dirname(__FILE__) . "/output3.tmp"; $mimePart = new Mail_mimePart('abc', array( 'content_type' => 'text/plain', 'encoding' => 'quoted-printable', )); $mimePart->encodeToFile($temp_filename); echo file_get_contents($temp_filename); ?> --CLEAN-- --EXPECT-- --something Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=ISO-8859-1 text --something Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=ISO-8859-1 html --something-- MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="something" --something Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=ISO-8859-1 text --something Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=ISO-8859-1 html --something-- Content-Transfer-Encoding: quoted-printable Content-Type: text/plain abc PK!-7c77)test/Mail_Mime/tests/test_Bug_3513_2.phptnu[--TEST-- Bug #3513 Support of RFC2231 in header fields. (UTF-8) --SKIPIF-- --FILE-- addAttachment('testfile',"text/plain", $test, FALSE, 'base64', 'attachment', 'UTF-8', 'de'); $content = $Mime->get(); $content = str_replace("\n", '', $content); if (preg_match_all('/filename([^\s]+)/i', $content, $matches)) { echo implode("\n", $matches[1]); } --EXPECT-- *0*=UTF-8'de'S%C3%BCper%20gr%C3%B6se%20tolle%20tolle%20gr%C3%BC; *1*=%C3%9Fe.txt; PK!(V,(test/Mail_Mime/tests/test_Bug_12411.phptnu[--TEST-- Bug #12411 RFC2047 encoded attachment filenames --SKIPIF-- --FILE-- addAttachment('testfile', "text/plain", $filename, FALSE, 'base64', 'attachment', 'ISO-8859-1', 'pl', '', 'quoted-printable', 'base64'); $content = $Mime->get(); $content = str_replace("\n", '', $content); if (preg_match_all('/(name|filename)=([^\s]+)/i', $content, $matches)) { echo implode("\n", $matches[2]); } ?> --EXPECT-- "=?ISO-8859-1?Q?=C5=9Bciema?=" "=?ISO-8859-1?B?xZtjaWVtYQ==?="; PK!qS*test/Mail_Mime/tests/test_Bug_10999_1.phptnu[--TEST-- Bug #10999 Bad Content-ID(cid) format --SKIPIF-- --FILE-- '; $mime->setHTMLBody($body); $mime->setFrom($from); $mime->addHTMLImage('','image/gif', 'test.gif', false); $msg=$mime->get(); $header = preg_match('|Content-ID: <[0-9a-fA-F]+@from.example.com>|', $msg); if (!$header){ print("FAIL:\n"); print($msg); }else{ print("OK"); } --EXPECT-- OK PK!29r'test/Mail_Mime/tests/encoding_case.phptnu[--TEST-- Bug #2364 Tabs in Mail_mimePart::quotedPrintableEncode() --SKIPIF-- --FILE-- --EXPECT-- Here's= =09 a tab PK!M-\(test/Mail_Mime/tests/test_Bug_17175.phptnu[--TEST-- Bug #17175 Content-Description support+ecoding --SKIPIF-- --FILE-- setTXTBody('Test message.'); $Mime->addAttachment('test file contents', "text/plain", 'test.txt', FALSE, 'base64', NULL, 'UTF-8', NULL, NULL, NULL, NULL, 'desc'); $Mime->addAttachment('test file contents', "text/plain", 'test2.txt', FALSE, 'base64', NULL, 'UTF-8', NULL, NULL, NULL, NULL, 'test unicode żąśź'); $body = $Mime->getMessage(); preg_match_all('/Content-Description: (.*)/', $body, $matches); foreach ($matches[1] as $value) echo $value."\n"; ?> --EXPECT-- desc =?UTF-8?Q?test_unicode_=C5=BC=C4=85=C5=9B=C5=BA?= PK!ّB *test/Mail_Mime/tests/qp_encoding_test.phptnu[--TEST-- qp comprehensive test --SKIPIF-- --FILE-- setSubject('test'); // A message with text/calendar only $mime->setCalendarBody('VCALENDAR'); echo $mime->getMessage(); echo "\n---\n"; // A message with alternative text $mime->setTXTBody('vcalendar'); $msg = $mime->getMessage(); echo preg_replace('/=_[0-9a-z]+/', '*', $msg); --EXPECT-- MIME-Version: 1.0 Subject: test Content-Type: text/calendar; charset=UTF-8; method=request Content-Transfer-Encoding: quoted-printable VCALENDAR --- MIME-Version: 1.0 Subject: test Content-Type: multipart/alternative; boundary="*" --* Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=ISO-8859-1 vcalendar --* Content-Transfer-Encoding: quoted-printable Content-Type: text/calendar; method=request; charset=UTF-8 VCALENDAR --*-- PK!2!B,test/Mail_Mime/tests/test_linebreak_dot.phptnu[--TEST-- Test for correct "." encoding when doing linebreaks --SKIPIF-- --FILE-- 'text/plain', 'encoding' => 'quoted-printable', ); for ($i=74; $i <= strlen($text); $i++) { $input = substr($text, 0, $i); $mimePart = new Mail_mimePart($input, $params); $encoded = $mimePart->encode(); $output = $encoded['body']; printf("input: %02d: %s\n", strlen($input), $input); $lines = explode("\r\n", $output); for($j=0; $j < count($lines); $j++) { $line = $lines[$j]; if ($j + 1 < count($lines)) { $line_vis = $line.'\r\n'; } else { $line_vis = $line; } printf("output:%02d: %s\n", strlen($line), $line_vis); } print("---\n"); } --EXPECT-- input: 74: 0123456789012345678901234567890123456789012345678901234567890123456789012. output:74: 0123456789012345678901234567890123456789012345678901234567890123456789012. --- input: 75: 0123456789012345678901234567890123456789012345678901234567890123456789012.. output:75: 0123456789012345678901234567890123456789012345678901234567890123456789012.. --- input: 76: 0123456789012345678901234567890123456789012345678901234567890123456789012... output:76: 0123456789012345678901234567890123456789012345678901234567890123456789012... --- input: 77: 0123456789012345678901234567890123456789012345678901234567890123456789012...6 output:76: 0123456789012345678901234567890123456789012345678901234567890123456789012..=\r\n output:04: =2E6 --- PK!B&(test/Mail_Mime/tests/test_Bug_12466.phptnu[--TEST-- Bug #12466 Content-Transfer-Encoding checking --SKIPIF-- --FILE-- '7bit', 'html_encoding' => '7bit', ); $mime = new Mail_mime($params); $mime->setTXTBody("ż"); $mime->setHTMLBody("z"); $body = $mime->getMessage(); preg_match_all('/Content-Transfer-Encoding: (.*)/', $body, $m); echo trim($m[1][0])."\n".trim($m[1][1]); ?> --EXPECT-- quoted-printable 7bit PK!MU..(test/Mail_Mime/tests/test_Bug_20273.phptnu[--TEST-- Bug #20273 Mail_mimePart::encodeHeader() and TAB character --SKIPIF-- --FILE-- \t"; $mime = new Mail_mimePart(); echo $mime->encodeHeader('References', $refs); ?> --EXPECT-- PK![b3test/Mail_Mime/tests/content_transfer_encoding.phptnu[--TEST-- Test empty Content-Transfer-Encoding on multipart messages --SKIPIF-- --FILE-- setParam('text_encoding', 'quoted-printable'); $mime->setParam('html_encoding', 'quoted-printable'); $mime->setParam('head_encoding', 'quoted-printable'); // This specific order used to set Content-Transfer-Encoding: quoted-printable // which is invalid according to RFC 2045 on multipart messages $mime->setTXTBody('text'); $mime->headers(array('From' => 'from@domain.tld')); $mime->addAttachment('file.pdf', 'application/pdf', 'file.pdf', false, 'base64', 'inline'); echo $mime->txtHeaders(); list ($header, $body) = explode("\r\n\r\n", $mime->getMessage()); echo $header; ?> --EXPECTF-- MIME-Version: 1.0 From: from@domain.tld Content-Type: multipart/mixed; boundary="=_%x" MIME-Version: 1.0 From: from@domain.tld Content-Type: multipart/mixed; boundary="=_%x" PK!k0(test/Mail_Mime/tests/test_Bug_20564.phptnu[--TEST-- Bug #20564 Unsetting headers --SKIPIF-- --FILE-- setSubject('test'); $headers = $mime->headers(array('Subject' => null), true); echo array_key_exists('Subject', $headers) ? '1' : '0'; --EXPECT-- 0PK!a[(test/Mail_Mime/tests/class-filename.phptnu[--TEST-- Test class filename (bug #24) --SKIPIF-- --FILE-- --EXPECT-- Include OK PK!o  (test/Mail_Mime/tests/test_Bug_14529.phptnu[--TEST-- Bug #14529 basename() workaround --SKIPIF-- --FILE-- addAttachment('testfile', "text/plain", $filename, FALSE, 'base64', 'attachment', 'ISO-8859-1'); $content = $Mime->get(); $content = str_replace("\n", '', $content); if (preg_match('/filename([^\s]+)/i', $content, $matches)) { echo $matches[1]; } ?> --EXPECT-- *=ISO-8859-1''%C5%9Bciema; PK!Cz2}}(test/Mail_Mime/tests/test_Bug_12165.phptnu[--TEST-- Bug #12165 Dot at the end of the line disappeared --SKIPIF-- --FILE-- setHTMLBody($string); print_r($mime->get()); --EXPECT-- http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa= =2Ecom PK!Yak!!8test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part1.phptnu[--TEST-- Bug #3488 Sleep/Wakeup EOL Consistency - Part 1 --SKIPIF-- --FILE-- setHTMLBody(''); $mm->setTxtBody('Blah blah'); if (version_compare(phpversion(), "5.0.0", '<')) { $mmCopy = $mm; } else { $mmCopy = clone($mm); } $mm->get(); $x = $mm->headers(); $smm = serialize(array('mm' => $mmCopy, 'header' => $x['Content-Type'])); $fp = fopen('sleep_wakeup_data', 'w'); fwrite($fp, $smm); fclose($fp); echo "Data written"; ?> --EXPECT-- Data written PK!@/NN(test/Mail_Mime/tests/test_Bug_21206.phptnu[--TEST-- Bug #21206 Handling quoted strings --SKIPIF-- --FILE-- , b ', '"c\\\\" , d ', ); foreach ($tests as $test) { $addrs = X::explodeQuotedString('[\t,]', $test); foreach ($addrs as $addr) { print trim($addr) . PHP_EOL; } } ?> --EXPECT-- "a" b "c\\" d PK!8)test/Mail_Mime/tests/test_Bug_3513_1.phptnu[--TEST-- Bug #3513 Support of RFC2231 in header fields. (ISO-8859-1) --SKIPIF-- --FILE-- addAttachment('testfile',"text/plain", $test, FALSE, 'base64', 'attachment', 'ISO-8859-1'); $content = $Mime->get(); $content = str_replace("\n", '', $content); if (preg_match('/filename([^\s]+)/i', $content, $matches)) { echo $matches[1]; } --EXPECT-- *=ISO-8859-1''F%F3%F3b%E6r.txt; PK!5(test/Mail_Mime/tests/test_Bug_21098.phptnu[--TEST-- Bug #21098 Handling of empty plain text parts --SKIPIF-- --FILE-- setTxtBody(''); $mime->setHTMLBody(''); $headers1 = $mime->txtHeaders(); $body = $mime->get(); $headers2 = $mime->txtHeaders(); print strpos($headers1, 'text/html') && strpos($headers2, 'text/html') ? 'OK' : 'NOT OK'; --EXPECT-- OK PK!v)test/Mail_Mime/tests/test_Bug_8541_1.phptnu[--TEST-- Bug #8541 mimePart.php line delimiter is \r --SKIPIF-- --FILE-- --FILE-- '), array('From', 'adresse@adresse.de'), array('From', 'Frank Do '), array('To', 'Frank Do , James Clark '), array('From', '"Frank Do" '), array('Cc', '"Frank Do" , "James Clark" '), array('Cc', ' , "Kuśmiderski Jan Krzysztof Janusz Długa nazwa" '), array('From', '"adresse@adresse.de" '), array('From', 'adresse@adresse.de '), array('From', '"German Umlauts öäü" '), array('Subject', 'German Umlauts öäü '), array('Subject', 'Short ASCII subject'), array('Subject', 'Long ASCII subject - multiline space separated words - too long for one line'), array('Subject', 'Short Unicode ż subject'), array('Subject', 'Long Unicode subject - zażółć gęślą jaźń - too long for one line'), array('References', ' <4b2e87ac$1@news.home.net.pl> '), array('To', '"Frank Do" ,, "James Clark" '), array('To', '"Frank \\" \\\\Do" '), array('To', 'Frank " \\Do '), array('Subject', "A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test"), array('Subject', "TEST Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir!!!?"), array('Subject', "Update: Microsoft Windows-Tool zum Entfernen bösartiger Software 3.6"), array('From', "test@nàme "), array('From', "Test <\"test test\"@domain.com>"), array('From', "\"test test\"@domain.com"), array('From', "<\"test test\"@domain.com>"), array('From', "Doe"), array('From', "\"John Doe\""), array('Mail-Reply-To', 'adresse@adresse.de '), array('Mail-Reply-To', '"öäü" '), ); $i = 1; foreach ($headers as $header) { $hdr = $mime->encodeHeader($header[0], $header[1], 'UTF-8', 'base64'); printf("[%02d] %s: %s\n", $i, $header[0], $hdr); $hdr = $mime->encodeHeader($header[0], $header[1], 'UTF-8', 'quoted-printable'); printf("[%02d] %s: %s\n", $i, $header[0], $hdr); $i++; } ?> --EXPECT-- [01] From: [01] From: [02] From: adresse@adresse.de [02] From: adresse@adresse.de [03] From: Frank Do [03] From: Frank Do [04] To: Frank Do , James Clark [04] To: Frank Do , James Clark [05] From: "Frank Do" [05] From: "Frank Do" [06] Cc: "Frank Do" , "James Clark" [06] Cc: "Frank Do" , "James Clark" [07] Cc: , =?UTF-8?B?S3XFm21pZGVyc2tpIEphbiBLcnp5c3p0b2Yg?= =?UTF-8?B?SmFudXN6IETFgnVnYSBuYXp3YQ==?= [07] Cc: , =?UTF-8?Q?Ku=C5=9Bmiderski_Jan_Krzysztof_Janusz_D?= =?UTF-8?Q?=C5=82uga_nazwa?= [08] From: "adresse@adresse.de" [08] From: "adresse@adresse.de" [09] From: "adresse@adresse.de" [09] From: "adresse@adresse.de" [10] From: =?UTF-8?B?R2VybWFuIFVtbGF1dHMgw7bDpMO8?= [10] From: =?UTF-8?Q?German_Umlauts_=C3=B6=C3=A4=C3=BC?= [11] Subject: =?UTF-8?B?R2VybWFuIFVtbGF1dHMgw7bDpMO8IDxhZHJlc3NlQGFkcmVzc2Uu?= =?UTF-8?B?ZGU+?= [11] Subject: =?UTF-8?Q?German_Umlauts_=C3=B6=C3=A4=C3=BC_=3Cadresse=40adresse?= =?UTF-8?Q?=2Ede=3E?= [12] Subject: Short ASCII subject [12] Subject: Short ASCII subject [13] Subject: Long ASCII subject - multiline space separated words - too long for one line [13] Subject: Long ASCII subject - multiline space separated words - too long for one line [14] Subject: =?UTF-8?B?U2hvcnQgVW5pY29kZSDFvCBzdWJqZWN0?= [14] Subject: =?UTF-8?Q?Short_Unicode_=C5=BC_subject?= [15] Subject: =?UTF-8?B?TG9uZyBVbmljb2RlIHN1YmplY3QgLSB6YcW8w7PFgsSHIGfEmcWb?= =?UTF-8?B?bMSFIGphxbrFhCAtIHRvbyBsb25nIGZvciBvbmUgbGluZQ==?= [15] Subject: =?UTF-8?Q?Long_Unicode_subject_-_za=C5=BC=C3=B3=C5=82=C4=87_g=C4?= =?UTF-8?Q?=99=C5=9Bl=C4=85_ja=C5=BA=C5=84_-_too_long_for_one_line?= [16] References: <4b2e87ac$1@news.home.net.pl> [16] References: <4b2e87ac$1@news.home.net.pl> [17] To: "Frank Do" , "James Clark" [17] To: "Frank Do" , "James Clark" [18] To: "Frank \" \\Do" [18] To: "Frank \" \\Do" [19] To: "Frank \" \\Do" [19] To: "Frank \" \\Do" [20] Subject: A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test [20] Subject: A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test [21] Subject: =?UTF-8?B?VEVTVCBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1p?= =?UTF-8?B?ciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIg?= =?UTF-8?B?Z3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRv?= =?UTF-8?B?bGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zD?= =?UTF-8?B?n2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1p?= =?UTF-8?B?ciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIg?= =?UTF-8?B?Z3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRv?= =?UTF-8?B?bGxlIGdyw7zDn2Ugdm9uIG1pciEhIT8=?= [21] Subject: =?UTF-8?Q?TEST_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir?= =?UTF-8?Q?_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_g?= =?UTF-8?Q?r=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tol?= =?UTF-8?Q?le_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC?= =?UTF-8?Q?=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_m?= =?UTF-8?Q?ir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper?= =?UTF-8?Q?_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_t?= =?UTF-8?Q?olle_gr=C3=BC=C3=9Fe_von_mir!!!=3F?= [22] Subject: =?UTF-8?B?VXBkYXRlOiBNaWNyb3NvZnQgV2luZG93cy1Ub29sIHp1bSBFbnRm?= =?UTF-8?B?ZXJuZW4gYsO2c2FydGlnZXIgU29mdHdhcmUgMy42?= [22] Subject: =?UTF-8?Q?Update=3A_Microsoft_Windows-Tool_zum_Entfernen_b=C3=B6sa?= =?UTF-8?Q?rtiger_Software_3=2E6?= [23] From: =?UTF-8?B?dGVzdEBuw6BtZQ==?= [23] From: =?UTF-8?Q?test=40n=C3=A0me?= [24] From: Test <"test test"@domain.com> [24] From: Test <"test test"@domain.com> [25] From: "test test"@domain.com [25] From: "test test"@domain.com [26] From: <"test test"@domain.com> [26] From: <"test test"@domain.com> [27] From: Doe [27] From: Doe [28] From: "John Doe" [28] From: "John Doe" [29] Mail-Reply-To: "adresse@adresse.de" [29] Mail-Reply-To: "adresse@adresse.de" [30] Mail-Reply-To: =?UTF-8?B?w7bDpMO8?= [30] Mail-Reply-To: =?UTF-8?Q?=C3=B6=C3=A4=C3=BC?= PK!(test/Mail_Mime/tests/test_Bug_21027.phptnu[--TEST-- Bug #21027 Calendar support along with attachments and html images --SKIPIF-- --FILE-- This is HTML body.'; $icsText = 'BEGIN:VCALENDAR VERSION:2.0 PRODID:-//icalcreator//NONSGML iCalcreator 2.22// METHOD:REQUEST BEGIN:VEVENT UID:77@localhost DTSTAMP:20160208T170811Z ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP= TRUE;CN=Jacob Alvarez:MAILTO:fake1@mailinator.com CREATED:20160208T170810Z DTSTART:20160215T180000Z DTEND:20160215T190000Z ORGANIZER;CN=-:MAILTO:fake2@mailinator.com SEQUENCE:1 STATUS:CONFIRMED SUMMARY:Prueba 69 TRANSP:OPAQUE URL:http://localhost/event/77 END:VEVENT END:VCALENDAR'; function printPartsStartAndEnd($body) { $matches = array(); preg_match_all('/--(=_[a-z0-9]+)--|Content-Type: ([^;\r\n]+)/', $body, $matches); $tab = " "; foreach ($matches[0] as $match){ if (strpos($match, '--') === false) { printf("%s%s\n", $tab, $match); if (stripos($match, "multipart")) { $tab .= " "; } } else { $tab = substr($tab, 0, -4); printf("%sEnd part\n", $tab); } } } function printHeaderContentType($headers) { $headerContentType = array(); preg_match('/([^;\r\n]+)/', $headers['Content-Type'], $headerContentType); printf("Content-Type: %s\n", $headerContentType[0]); } print "TEST: text\n"; $mime = new Mail_mime(); $mime->setTXTBody($txtBody); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: html\n"; $mime = new Mail_mime(); $mime->setHTMLBody($htmlBody); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: attachments\n"; $mime = new Mail_mime(); $mime->addAttachment($icsText, 'application/ics', 'invite.ics', false); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: text + attachments\n"; $mime = new Mail_mime(); $mime->setTXTBody($txtBody); $mime->addAttachment($icsText, 'application/ics', 'invite.ics', false); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: html + attachments\n"; $mime = new Mail_mime(); $mime->setHTMLBody($htmlBody); $mime->addAttachment($icsText, 'application/ics', 'invite.ics', false); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: html + inline images\n"; $mime = new Mail_mime(); $mime->setHTMLBody($htmlBody); $mime->addHTMLImage("aaaaaaaaaa", 'image/gif', 'image.gif', false, 'contentid'); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print("TEST: txt, html and attachment\n"); $mime = new Mail_mime(); $mime->setTXTBody($txtBody); $mime->setHTMLBody($htmlBody); $mime->addAttachment("test", 'application/octet-stream', 'attachment', false); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: calendar\n"; $mime = new Mail_mime(); $mime->setCalendarBody($icsText); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: txt + calendar\n"; $mime->setTXTBody($txtBody); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: txt, html, calendar\n"; $mime = new Mail_mime(); $mime->setTXTBody($txtBody); $mime->setHTMLBody($htmlBody); $mime->setCalendarBody($icsText); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: txt, html + html images, and calendar\n"; $mime = new Mail_mime(); $mime->setTXTBody($txtBody); $mime->setHTMLBody($htmlBody); $mime->addHTMLImage('testimage', 'image/gif', "bus.gif", false); $mime->setCalendarBody($icsText); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print("TEST: txt, html, calendar and attachment\n"); $mime = new Mail_mime(); $mime->setTXTBody($txtBody); $mime->setHTMLBody($htmlBody); $mime->setCalendarBody($icsText); $mime->addAttachment("test", 'application/octet-stream', 'attachment', false); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); print "TEST: txt, html + html images, calendar, and attachment\n"; $mime = new Mail_mime(); $mime->setTXTBody($txtBody); $mime->setHTMLBody($htmlBody); $mime->addHTMLImage('testimage', 'image/gif', "bus.gif", false); $mime->setCalendarBody($icsText); $mime->addAttachment($icsText, 'application/ics', 'invite.ics', false); $headers = $mime->headers(); $body = $mime->get(); printHeaderContentType($headers); printPartsStartAndEnd($body); print("\n"); ?> --EXPECT-- TEST: text Content-Type: text/plain TEST: html Content-Type: text/html TEST: attachments Content-Type: multipart/mixed Content-Type: application/ics End part TEST: text + attachments Content-Type: multipart/mixed Content-Type: text/plain Content-Type: application/ics End part TEST: html + attachments Content-Type: multipart/mixed Content-Type: text/html Content-Type: application/ics End part TEST: html + inline images Content-Type: multipart/related Content-Type: text/html Content-Type: image/gif End part TEST: txt, html and attachment Content-Type: multipart/mixed Content-Type: multipart/alternative Content-Type: text/plain Content-Type: text/html End part Content-Type: application/octet-stream End part TEST: calendar Content-Type: text/calendar TEST: txt + calendar Content-Type: multipart/alternative Content-Type: text/plain Content-Type: text/calendar End part TEST: txt, html, calendar Content-Type: multipart/alternative Content-Type: text/plain Content-Type: text/html Content-Type: text/calendar End part TEST: txt, html + html images, and calendar Content-Type: multipart/alternative Content-Type: text/plain Content-Type: multipart/related Content-Type: text/html Content-Type: image/gif End part Content-Type: text/calendar End part TEST: txt, html, calendar and attachment Content-Type: multipart/mixed Content-Type: multipart/alternative Content-Type: text/plain Content-Type: text/html Content-Type: text/calendar End part Content-Type: application/octet-stream End part TEST: txt, html + html images, calendar, and attachment Content-Type: multipart/mixed Content-Type: multipart/alternative Content-Type: text/plain Content-Type: multipart/related Content-Type: text/html Content-Type: image/gif End part Content-Type: text/calendar End part Content-Type: application/ics End part PK!`~@*test/Mail_Mime/tests/test_Bug_12385_1.phptnu[--TEST-- Bug #12385 Bad regex when replacing css style attachments --SKIPIF-- --FILE-- className { background-image: url('test.gif'); } "; $mime->setHTMLBody($body); $mime->setFrom($from); $mime->addHTMLImage('','image/gif', 'test.gif', false); $msg = $mime->get(); $cidtag = preg_match("|url\('cid:[^']*'\);|", $msg); if (!$cidtag){ print("FAIL:\n"); print($msg); }else{ print("OK"); } --EXPECT-- OK PK!zŬ(test/Mail_Mime/tests/test_Bug_11731.phptnu[--TEST-- Bug #11731 Full stops after soft line breaks are not encoded --SKIPIF-- --FILE-- 'text/plain', 'encoding' => 'quoted-printable', ); $mimePart = new Mail_mimePart($text, $params); $encoded = $mimePart->encode(); echo $encoded['body']; --EXPECT-- =2E123456789012345678901234567890123456789012345678901234567890123456789012= =2E3456 PK!Xb(test/Mail_Mime/tests/test_Bug_14779.phptnu[--TEST-- Bug #14779 Proper header-body separator for empty attachment --SKIPIF-- --FILE-- addAttachment('', "text/plain", 'file.txt', FALSE, 'base64', 'attachment'); $result = $m->get(); if (preg_match('/(Content.*)--=.*/s', $result, $matches)) { print_r($matches[1]."END"); } ?> --EXPECT-- Content-Transfer-Encoding: base64 Content-Type: text/plain; name=file.txt Content-Disposition: attachment; filename=file.txt END PK!Izz(test/Mail_Mime/tests/test_Bug_20563.phptnu[--TEST-- Bug #20563 isMultipart() method tests --SKIPIF-- --FILE-- isMultipart() ? 'TRUE' : 'FALSE') . "\n"; $mime->setTXTBody('test'); echo ($mime->isMultipart() ? 'TRUE' : 'FALSE') . "\n"; $mime->setHTMLBody('test'); echo ($mime->isMultipart() ? 'TRUE' : 'FALSE') . "\n"; --EXPECT-- FALSE FALSE TRUE PK!ZXHww)test/Mail_Mime/tests/test_Bug_3513_3.phptnu[--TEST-- Bug #3513 Support of RFC2231 in header fields. (ISO-2022-JP) --SKIPIF-- --FILE-- addAttachment('testfile',"text/plain", $test, FALSE, 'base64', 'attachment', 'iso-2022-jp', ''); $content = $Mime->get(); $content = str_replace("\n", '', $content); if (preg_match('/filename([^\s]+)/i', $content, $matches)) { echo $matches[1]; } ?> --EXPECT-- *=iso-2022-jp''%1B$BF|K%5C8l%1B%28B.txt; PK!(test/Mail_Mime/tests/test_Bug_15320.phptnu[--TEST-- Bug #15320 Charset parameter in Content-Type of mail parts --SKIPIF-- --FILE-- addAttachment('testfile', "text/plain", 'file.txt', FALSE, 'base64', 'attachment', 'ISO-8859-1'); $content = $Mime->get(); //$content = str_replace("\n", '', $content); if (preg_match('/Content-type:([^\n]+)/i', $content, $matches)) { echo $matches[1]; } ?> --EXPECT-- text/plain; charset=ISO-8859-1; PK!-b2(test/Mail_Mime/tests/test_Bug_13032.phptnu[--TEST-- Bug #13032 Proper (different) boundary for nested parts --SKIPIF-- --FILE-- setHTMLBody('html'); $mime->setTXTBody('text'); $mime->addAttachment('file.pdf', 'application/pdf', 'file.pdf', false, 'base64', 'inline'); $msg = $mime->getMessage(); if (preg_match_all('/boundary="([^"]+)"/', $msg, $matches)) { if (count($matches) == 2 && count($matches[1]) == 2 && $matches[1][0] != $matches[1][1]) { print('OK'); } } ?> --EXPECT-- OK PK!%+2PP(test/Mail_Mime/tests/test_Bug_18083.phptnu[--TEST-- Bug #18083 Separate charset for attachment's content and headers --SKIPIF-- --FILE-- addAttachment('testfile', "text/plain", base64_decode("xZtjaWVtYQ=="), FALSE, 'base64', 'attachment', 'ISO-8859-1', 'pl', '', 'quoted-printable', 'base64', '', 'UTF-8'); $content = $Mime->get(); $content = str_replace("\n", '', $content); if (preg_match_all('/(name|filename)=([^\s]+)/i', $content, $matches)) { echo implode("\n", $matches[2]); } ?> --EXPECT-- "=?UTF-8?Q?=C5=9Bciema?=" "=?UTF-8?B?xZtjaWVtYQ==?="; PK!Qi"--(test/Mail_Mime/tests/test_Bug_11381.phptnu[--TEST-- Bug #11381 Domain name is attached to content-id, trailing greater-than sign is not removed --SKIPIF-- --FILE-- '; require_once('Mail/mime.php'); $mime=new Mail_mime(); $body=''; $mime->setHTMLBody($body); $mime->setFrom($from); $mime->addHTMLImage('','image/gif', 'test.gif', false); $msg=$mime->get(); $header = preg_match('|Content-ID: <[0-9a-fA-F]+@from.example.com>|', $msg); if (!$header){ print("FAIL:\n"); print($msg); }else{ print("OK"); } --EXPECT-- OK PK!X##(test/Mail_Mime/tests/test_Bug_19497.phptnu[--TEST-- Bug #19497 Attachment filenames with a slash character --SKIPIF-- --FILE-- addAttachment('testfile', "text/plain", $filename, FALSE, 'base64', 'attachment', 'ISO-8859-1', '', '', 'quoted-printable', 'base64'); $content = $Mime->get(); $content = str_replace("\n", '', $content); if (preg_match_all('/(name|filename)=([^\s]+)/i', $content, $matches)) { echo implode("\n", $matches[2]); } ?> --EXPECT-- "test/file.txt" "test/file.txt"; PK!''')test/Mail_Mime/tests/test_Bug_8386_1.phptnu[--TEST-- Bug #8386 HTML body not correctly encoded if attachments present --SKIPIF-- --FILE-- $eol)); $encoder->setTXTBody('test'); $encoder->setHTMLBody('test'); $encoder->addAttachment('Just a test', 'application/octet-stream', 'test.txt', false); $body = $encoder->get(); if (strpos($body, '--' . $eol . '--=')){ print("FAILED\n"); print("Single delimiter() between 2 parts found.\n"); print($body); }else{ print("OK"); } ?> --EXPECT-- OK PK!1d(test/Mail_Mime/tests/test_Bug_17025.phptnu[--TEST-- Bug #16539 Headers longer than 998 characters --SKIPIF-- --FILE-- headers($headers); print_r($hdrs['From']); ?> --EXPECT-- aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhh PK!e@Q__(test/Mail_Mime/tests/test_Bug_14780.phptnu[--TEST-- Bug #14780 Invalid Content-Type when headers() is called before get() --SKIPIF-- --FILE-- setTXTBody("test"); $mime->setHTMLBody("test"); $head1 = $mime->headers(); $body = $mime->get(); $head2 = $mime->headers(); if ($head1 === $head2) { echo "OK"; } ?> --EXPECT-- OK PK! Ǟ  2test/Mail_Mime/tests/test_linebreak_larger_76.phptnu[--TEST-- Test for correct linebreaks for lines _longer_ than 76 chars. --SKIPIF-- --FILE-- 'text/plain', 'encoding' => 'quoted-printable', ); for ($i=74; $i <= strlen($text); $i++) { $input = substr($text, 0, $i); $mimePart = new Mail_mimePart($input, $params); $encoded = $mimePart->encode(); $output = $encoded['body']; printf("input: %02d: %s\n", strlen($input), $input); $lines = explode("\r\n", $output); for($j=0; $j < count($lines); $j++) { $line = $lines[$j]; if ($j + 1 < count($lines)) { $line_vis = $line.'\r\n'; } else { $line_vis = $line; } printf("output:%02d: %s\n", strlen($line), $line_vis); } print("---\n"); } --EXPECT-- input: 74: 12345678901234567890123456789012345678901234567890123456789012345678901234 output:74: 12345678901234567890123456789012345678901234567890123456789012345678901234 --- input: 75: 123456789012345678901234567890123456789012345678901234567890123456789012345 output:75: 123456789012345678901234567890123456789012345678901234567890123456789012345 --- input: 76: 1234567890123456789012345678901234567890123456789012345678901234567890123456 output:76: 1234567890123456789012345678901234567890123456789012345678901234567890123456 --- input: 77: 12345678901234567890123456789012345678901234567890123456789012345678901234567 output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n output:02: 67 --- input: 78: 123456789012345678901234567890123456789012345678901234567890123456789012345678 output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n output:03: 678 --- input: 79: 1234567890123456789012345678901234567890123456789012345678901234567890123456789 output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n output:04: 6789 --- input: 80: 12345678901234567890123456789012345678901234567890123456789012345678901234567890 output:76: 123456789012345678901234567890123456789012345678901234567890123456789012345=\r\n output:05: 67890 --- PK!ܶghh)test/Mail_Mime/tests/test_Bug_9722_1.phptnu[--TEST-- Bug #9722 quotedPrintableEncode does not encode dot at start of line on Windows platform --SKIPIF-- --FILE-- 'jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com', 'Subject' => 'jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com', ); echo $mime->txtHeaders($headers, true, true); ?> --EXPECT-- MIME-Version: 1.0 To: jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com, jskibbie@schawk.com Subject: jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.co m,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com,jskibbie@schawk.com PK! ((*test/Mail_Mime/tests/test_Bug_10596_1.phptnu[--TEST-- Bug #10596 Incorrect handling of text and html '0' bodies --SKIPIF-- --FILE-- setTxtBody('0'); $mime->setHTMLBody('0'); $body = $mime->get(); if ($body){ print("OK"); }else{ print("NO BODY FOUND"); } --EXPECT-- OK PK!9::*test/Mail_Mime/tests/test_Bug_10816_1.phptnu[--TEST-- Bug #10816 Unwanted linebreak at the end of output --SKIPIF-- --FILE-- $eol)); $encoder->setTXTBody('test'); $encoder->setHTMLBody('test'); $encoder->addAttachment('Just a test', 'application/octet-stream', 'test.txt', false); $body = $encoder->get(); $taillength = -1 * strlen($eol) * 2; if (substr($body, $taillength) == ($eol.$eol)){ print("FAILED\n"); print("Body:\n"); print("..." . substr($body, -10) . "\n"); }else{ print("OK\n"); } --EXPECT-- OK PK!᠗""/test/Mail_Mime/tests/headers_with_mbstring.phptnu[--TEST-- Multi-test for headers encoding using base64 and quoted-printable --SKIPIF-- --FILE-- '), array('From', 'adresse@adresse.de'), array('From', 'Frank Do '), array('To', 'Frank Do , James Clark '), array('From', '"Frank Do" '), array('Cc', '"Frank Do" , "James Clark" '), array('Cc', ' , "Kuśmiderski Jan Krzysztof Janusz Długa nazwa" '), array('From', '"adresse@adresse.de" '), array('From', 'adresse@adresse.de '), array('From', '"German Umlauts öäü" '), array('Subject', 'German Umlauts öäü '), array('Subject', 'Short ASCII subject'), array('Subject', 'Long ASCII subject - multiline space separated words - too long for one line'), array('Subject', 'Short Unicode ż subject'), array('Subject', 'Long Unicode subject - zażółć gęślą jaźń - too long for one line'), array('References', ' <4b2e87ac$1@news.home.net.pl> '), array('To', '"Frank Do" ,, "James Clark" '), array('To', '"Frank \\" \\\\Do" '), array('To', 'Frank " \\Do '), array('Subject', "A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test"), array('Subject', "TEST Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir Süper gröse tolle grüße von mir!!!?"), array('Subject', "Update: Microsoft Windows-Tool zum Entfernen bösartiger Software 3.6"), array('From', "test@nàme "), array('From', "Test <\"test test\"@domain.com>"), array('From', "\"test test\"@domain.com"), array('From', "<\"test test\"@domain.com>"), array('From', "Doe"), array('From', "\"John Doe\""), array('Mail-Reply-To', 'adresse@adresse.de '), array('Mail-Reply-To', '"öäü" '), array('Subject', mb_convert_encoding('㈱山﨑工業', 'ISO-2022-JP-MS', 'UTF-8'), 'ISO-2022-JP'), ); $i = 1; foreach ($headers as $header) { $charset = isset($header[2]) ? $header[2] : 'UTF-8'; $hdr = $mime->encodeHeader($header[0], $header[1], $charset, 'base64'); printf("[%02d] %s: %s\n", $i, $header[0], $hdr); $hdr = $mime->encodeHeader($header[0], $header[1], $charset, 'quoted-printable'); printf("[%02d] %s: %s\n", $i, $header[0], $hdr); $i++; } ?> --EXPECT-- [01] From: [01] From: [02] From: adresse@adresse.de [02] From: adresse@adresse.de [03] From: Frank Do [03] From: Frank Do [04] To: Frank Do , James Clark [04] To: Frank Do , James Clark [05] From: "Frank Do" [05] From: "Frank Do" [06] Cc: "Frank Do" , "James Clark" [06] Cc: "Frank Do" , "James Clark" [07] Cc: , =?UTF-8?B?S3XFm21pZGVyc2tpIEphbiBLcnp5c3p0b2Yg?= =?UTF-8?B?SmFudXN6IETFgnVnYSBuYXp3YQ==?= [07] Cc: , =?UTF-8?Q?Ku=C5=9Bmiderski_Jan_Krzysztof_Janusz?= =?UTF-8?Q?_D=C5=82uga_nazwa?= [08] From: "adresse@adresse.de" [08] From: "adresse@adresse.de" [09] From: "adresse@adresse.de" [09] From: "adresse@adresse.de" [10] From: =?UTF-8?B?R2VybWFuIFVtbGF1dHMgw7bDpMO8?= [10] From: =?UTF-8?Q?German_Umlauts_=C3=B6=C3=A4=C3=BC?= [11] Subject: =?UTF-8?B?R2VybWFuIFVtbGF1dHMgw7bDpMO8IDxhZHJlc3NlQGFkcmVzc2Uu?= =?UTF-8?B?ZGU+?= [11] Subject: =?UTF-8?Q?German_Umlauts_=C3=B6=C3=A4=C3=BC_=3Cadresse=40adresse?= =?UTF-8?Q?=2Ede=3E?= [12] Subject: Short ASCII subject [12] Subject: Short ASCII subject [13] Subject: Long ASCII subject - multiline space separated words - too long for one line [13] Subject: Long ASCII subject - multiline space separated words - too long for one line [14] Subject: =?UTF-8?B?U2hvcnQgVW5pY29kZSDFvCBzdWJqZWN0?= [14] Subject: =?UTF-8?Q?Short_Unicode_=C5=BC_subject?= [15] Subject: =?UTF-8?B?TG9uZyBVbmljb2RlIHN1YmplY3QgLSB6YcW8w7PFgsSHIGfEmcWb?= =?UTF-8?B?bMSFIGphxbrFhCAtIHRvbyBsb25nIGZvciBvbmUgbGluZQ==?= [15] Subject: =?UTF-8?Q?Long_Unicode_subject_-_za=C5=BC=C3=B3=C5=82=C4=87_g?= =?UTF-8?Q?=C4=99=C5=9Bl=C4=85_ja=C5=BA=C5=84_-_too_long_for_one_line?= [16] References: <4b2e87ac$1@news.home.net.pl> [16] References: <4b2e87ac$1@news.home.net.pl> [17] To: "Frank Do" , "James Clark" [17] To: "Frank Do" , "James Clark" [18] To: "Frank \" \\Do" [18] To: "Frank \" \\Do" [19] To: "Frank \" \\Do" [19] To: "Frank \" \\Do" [20] Subject: A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test [20] Subject: A REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALLY /REALLY/ LONG test [21] Subject: =?UTF-8?B?VEVTVCBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1p?= =?UTF-8?B?ciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIg?= =?UTF-8?B?Z3LDtnNlIHRvbGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRv?= =?UTF-8?B?bGxlIGdyw7zDn2Ugdm9uIG1pciBTw7xwZXIgZ3LDtnNlIHRvbGxlIGdyw7w=?= =?UTF-8?B?w59lIHZvbiBtaXIgU8O8cGVyIGdyw7ZzZSB0b2xsZSBncsO8w59lIHZvbiBt?= =?UTF-8?B?aXIgU8O8cGVyIGdyw7ZzZSB0b2xsZSBncsO8w59lIHZvbiBtaXIgU8O8cGVy?= =?UTF-8?B?IGdyw7ZzZSB0b2xsZSBncsO8w59lIHZvbiBtaXIgU8O8cGVyIGdyw7ZzZSB0?= =?UTF-8?B?b2xsZSBncsO8w59lIHZvbiBtaXIhISE/?= [21] Subject: =?UTF-8?Q?TEST_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_m?= =?UTF-8?Q?ir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCp?= =?UTF-8?Q?er_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6?= =?UTF-8?Q?se_tolle_gr=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr?= =?UTF-8?Q?=C3=BC=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC?= =?UTF-8?Q?=C3=9Fe_von_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von?= =?UTF-8?Q?_mir_S=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir_S?= =?UTF-8?Q?=C3=BCper_gr=C3=B6se_tolle_gr=C3=BC=C3=9Fe_von_mir!!!=3F?= [22] Subject: =?UTF-8?B?VXBkYXRlOiBNaWNyb3NvZnQgV2luZG93cy1Ub29sIHp1bSBFbnRm?= =?UTF-8?B?ZXJuZW4gYsO2c2FydGlnZXIgU29mdHdhcmUgMy42?= [22] Subject: =?UTF-8?Q?Update=3A_Microsoft_Windows-Tool_zum_Entfernen_b=C3=B6?= =?UTF-8?Q?sartiger_Software_3=2E6?= [23] From: =?UTF-8?B?dGVzdEBuw6BtZQ==?= [23] From: =?UTF-8?Q?test=40n=C3=A0me?= [24] From: Test <"test test"@domain.com> [24] From: Test <"test test"@domain.com> [25] From: "test test"@domain.com [25] From: "test test"@domain.com [26] From: <"test test"@domain.com> [26] From: <"test test"@domain.com> [27] From: Doe [27] From: Doe [28] From: "John Doe" [28] From: "John Doe" [29] Mail-Reply-To: "adresse@adresse.de" [29] Mail-Reply-To: "adresse@adresse.de" [30] Mail-Reply-To: =?UTF-8?B?w7bDpMO8?= [30] Mail-Reply-To: =?UTF-8?Q?=C3=B6=C3=A4=C3=BC?= [31] Subject: =?ISO-2022-JP?B?GyRCLWo7M3l1OSk2SBsoQg==?= [31] Subject: =?ISO-2022-JP?Q?=24B-j=28B=24B=3B3=28B=24Byu=28B?= =?ISO-2022-JP?Q?=24B9=29=28B=24B6H=28B?= PK!|JJ8test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part2.phptnu[--TEST-- Bug #3488 Sleep/Wakeup EOL Consistency - Part 2 --SKIPIF-- if (!is_readable('sleep_wakeup_data')) { echo "skip No data. Part 1 must run first.\n"; } --FILE-- get(); $x = $mmData['mm']->headers(); list($h1) = explode("\n", $mmData['header']); list($h2) = explode("\n", $x['Content-Type']); echo ($h1 == $h2) ? "Match" : "No Match"; ?> --EXPECT-- Match PK!:N *test/File_MARC/tests/marc_xml_rsinger.phptnu[--TEST-- marc_xml_rsinger2: iterate and pretty print a non-compliant MARC record (uppercase subfield codes) --SKIPIF-- --FILE-- next()) { print $marc_record; print "\n"; } ?> --EXPECT-- LDR 01850 a2200517 4500 001 0000000044 003 EMILDA 008 980120s1998 fi j 000 0 swe 005 20050204111518.0 020 _a9515008808 _cFIM 72:00 035 _99515008808 040 _aNB 042 _9NB _9SEE 084 _aHcd,u _2kssb/6 084 _5NB _auHc _2kssb 084 _5SEE _aHcf _2kssb/6 084 _5Q _aHcd,uf _2kssb/6 100 1 _aJansson, Tove, _d1914-2001 245 0 _aDet osynliga barnet och andra bert̃telser / _cTove Jansson 250 _a7. uppl. 260 _aHelsingfors : _bSchildt, _c1998 ; _e(Falun : _fScandbook) 440 0 _aMumin-biblioteket, _x99-0698931-9 500 _aOriginaluppl. 1962 599 _aLi: S 740 4 _aDet osynliga barnet 775 1 _z951-50-0385-7 _w9515003857 _907 841 _5Li _axa _b0201080u 0 4000uu |000000 _e1 841 _5SEE _axa _b0201080u 0 4000uu |000000 _e1 841 _5L _axa _b0201080u 0 4000uu |000000 _e1 841 _5NB _axa _b0201080u 0 4000uu |000000 _e1 841 _5Q _axa _b0201080u 0 4000uu |000000 _e1 841 _5S _axa _b0201080u 0 4000uu |000000 _e1 852 _5NB _bNB _cNB98:12 _hplikt _jR, 980520 852 _5Li _bLi _cCNB _hh,u 852 _5SEE _bSEE 852 _5Q _bQ _j98947 852 _5L _bL _c0100 _h98/ _j3043 H 852 _5S _bS _hSv97 _j7235 900 1s _aYanson, Tobe, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonov,̀ Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansone, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonova, Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 976 2 _aHcd,u _bSkn̲litteratur PK!a!"test/File_MARC/tests/namespace.xmlnu[ 00925njm 22002777a 4500 5637241 DLC 19920826084036.0 sdubumennmplu 910926s1957 nyuuun eng 91758335 1259 Atlantic DLC DLC Atlantic 1259 The Great Ray Charles [sound recording]. New York, N.Y. : Atlantic, [1957?] 1 sound disc : analog, 33 1/3 rpm ; 12 in. Ray Charles, piano & celeste. The Ray -- My melancholy baby -- Black coffee -- There's no you -- Doodlin' -- Sweet sixteen bars -- I surrender dear -- Undecided. Brief record. Jazz 1951-1960. Piano with jazz ensemble. Charles, Ray, 1930- prf 01832cmma 2200349 a 4500 12149120 20001005175443.0 cr ||| 000407m19949999dcu g m eng d 0 ibc copycat 1 ncip 20 y-gencompf undetermined web preservation project (wpp) vb07 (stars done) 08-19-00 to HLCD lk00; AA3s lk29 received for subject Aug 25, 2000; to DEWEY 08-25-00; aa11 08-28-00 00530046 (OCoLC)ocm44279786 IEU IEU N@F DLC lccopycat n-us-dc n-us--- F204.W5 975.3 13 The White House [computer file]. Computer data. Washington, D.C. : White House Web Team, 1994- Mode of access: Internet. Title from home page as viewed on Aug. 19, 2000. Features the White House. Highlights the Executive Office of the President, which includes senior policy advisors and offices responsible for the President's correspondence and communications, the Office of the Vice President, and the Office of the First Lady. Posts contact information via mailing address, telephone and fax numbers, and e-mail. Contains the Interactive Citizens' Handbook with information on health, travel and tourism, education and training, and housing. Provides a tour and the history of the White House. Links to White House for Kids. White House (Washington, D.C.) United States. Executive Office of the President. United States. Office of the Vice President. United States. Office of the First Lady. White House Web Team. http://www.whitehouse.gov http://lcweb.loc.gov/staff/wpp/whitehouse.html Web site archive PK!9;(test/File_MARC/tests/marc_field_003.phptnu[--TEST-- marc_field_003: Add subfields to an existing field --SKIPIF-- --FILE-- appendSubfield($subfield1); // insert a new subfield after the first subfield with code 'z' // expected order: a-z-k-g $sf = $field->getSubfields('z'); // we might get an array back; in this case, we want the first subfield if (is_array($sf)) { $field->insertSubfield($subfield2, $sf[0]); } else { $field->insertSubfield($subfield2, $sf); } // insert a new subfield prior to the first subfield with code 'z' // expected order: a-t-z-k-g $sf = $field->getSubfields('z'); // we might get an array back; in this case, we want the first subfield if (is_array($sf)) { $field->insertSubfield($subfield3, $sf[0], true); } else { $field->insertSubfield($subfield3, $sf, true); } // let's see the results print $field; print "\n"; ?> --EXPECT-- 100 0 _anothing _ta lot _zeverything _ka bit more _ga little PK!W1(test/File_MARC/tests/marc_xml_16642.phptnu[--TEST-- marc_xml_16642: Fix bug 16642: ensure tag and subfield values are returned as strings --SKIPIF-- --FILE-- next()) { foreach ($record->getFields() as $tag => $subfields) { // Skip everything except for 650 fields if ($tag == '650') { print "Subject:"; foreach ($subfields->getSubfields() as $code => $value) { print " $value"; } print "\n"; } } } ?> --EXPECT-- Subject: [a]: Arithmetic [x]: Juvenile poetry. Subject: [a]: Children's poetry, American. Subject: [a]: Arithmetic [x]: Poetry. Subject: [a]: American poetry. Subject: [a]: Visual perception. PK!è{{"test/File_MARC/tests/marc_020.phptnu[--TEST-- marc_020: Test MARC binary output --SKIPIF-- --FILE-- next(); // create some subfields $subfields[] = new File_MARC_Subfield('a', 'nothing'); $subfields[] = new File_MARC_Subfield('z', 'everything'); // create a data field $data_field = new File_MARC_Data_Field('100', $subfields, '0'); // append the data field $marc_record->appendField($data_field); // create a control field $ctrl_field = new File_MARC_Control_Field('001', '01234567890'); // prepend the control field $marc_record->prependField($ctrl_field); // reproduce test case reported by Mark Jordan $subfields_966_2[] = new File_MARC_Subfield('l', 'web'); $subfields_966_2[] = new File_MARC_Subfield('r', '0'); $subfields_966_2[] = new File_MARC_Subfield('s', 'b'); $subfields_966_2[] = new File_MARC_Subfield('i', '49'); $subfields_966_2[] = new File_MARC_Subfield('c', '1'); $field_966_2 = new File_MARC_Data_Field('966', $subfields_966_2, null, null); $marc_record->appendField($field_966_2); // let's see the results print convert_uuencode($marc_record->toRaw()); ?> --EXPECT-- M,#$Y-#,@("`@(#(R,#`U-3,@("`T-3`P,#`Q,#`Q,C`P,#`P,#`Q,#`Q,3`P M,#$R,#`S,#`P-S`P,#(S,#`X,#`S.3`P,#,P,#(P,#`R-C`P,#8Y,#,U,#`Q M-3`P,#DU,#0P,#`P-S`P,3$P,#0R,#`Q,C`P,3$W,#@T,#`Q.#`P,3(Y,#@T M,#`Q.#`P,30W,#@T,#`R,3`P,38U,#@T,#`R,C`P,3@V,3`P,#`S,#`P,C`X M,C0U,#`V,C`P,C,X,C4P,#`Q,S`P,S`P,C8P,#`U.#`P,S$S,S`P,#`S,S`P M,S14U)3$1!'CDX M,#$R,',Q.3DX("`@(&9I("`@("!J("`@("`@,#`P(#`@("`?.3DU,34P,#@X,#@>("`?84Y"'B`@'SE. M0A\Y4T5%'B`@'V%(8V0L=1\R:W-S8B\V'B`@'S5.0A]A=4AC'S)K6YL:6=A(&)A M(#`?84UU;6EN+6)I8FQI;W1E:V5T+!]X.3DM,#8Y.#DS M,2TY'B`@'V%/("`?84QI.B!3'C0@'V%$970@ M;W-Y;FQI9V$@8F%R;F5T'C$@'WHY-3$M-3`M,#,X-2TW'W("`?-4P?87AA'V(P,C`Q,#@P=2`@("`P("`@-#`P,'5U M("`@?#`P,#`P,!]E,1X@(!\U3D(?87AA'V(P,C`Q,#@P=2`@("`P("`@-#`P M,'5U("`@?#`P,#`P,!]E,1X@(!\U41]A>&$?8C`R,#$P.#!U("`@(#`@("`T M,#`P=74@("!\,#`P,#`P'V4Q'B`@'S53'V%X81]B,#(P,3`X,'4@("`@,"`@ M(#0P,#!U=2`@('PP,#`P,#`?93$>("`?-4Y"'V).0A]C3D(Y.#HQ,A]H<&QI M:W0?:E(L(#DX,#4R,!X@(!\U3&D?8DQI'V-#3D(?:&@L=1X@(!\U4T5%'V)3 M144>("`?-5$?8E$?:CDX.30W'B`@'S5,'V),'V,P,3`P'V@Y."\?:C,P-#,@ M2!X@(!\U4Q]B4Q]H4W8Y-Q]J-S(S-1XQ,7,?84IA;G-S;VXL(%1U=F4L M'V0Q.3$T+3(P,#$?=4IA;G-S;VXL(%1O=F4L'V0Q.3$T+3(P,#$>,7,?84IA M;G-S;VYO=F$L(%1O=F4L'V0Q.3$T+3(P,#$?=4IA;G-S;VXL(%1O=F4L'V0Q M.3$T+3(P,#$>(#(?84AC9"QU'V)3:_9N;&ET=&5R871U71H:6YG'B`@'VQW96(? --FILE-- next()) { print $marc_record; print "\n"; } ?> --EXPECT-- LDR 01853 a2200517 4500 001 0000000044 003 EMILDA 008 980120s1998 fi j 000 0 swe 020 _a9515008808 _cFIM 72:00 035 _99515008808 040 _aNB 042 _9NB _9SEE 084 _aHcd,u _2kssb/6 084 _5NB _auHc _2kssb 084 _5SEE _aHcf _2kssb/6 084 _5Q _aHcd,uf _2kssb/6 100 1 _aJansson, Tove, _d1914-2001 245 04 _aDet osynliga barnet och andra bert̃telser / _cTove Jansson 250 _a7. uppl. 260 _aHelsingfors : _bSchildt, _c1998 ; _e(Falun : _fScandbook) 440 0 _aMumin-biblioteket, _x99-0698931-9 500 _aOriginaluppl. 1962 599 _aLi: S 740 4 _aDet osynliga barnet 775 1 _z951-50-0385-7 _w9515003857 _907 841 _5Li _axa _b0201080u 0 4000uu |000000 _e1 841 _5SEE _axa _b0201080u 0 4000uu |000000 _e1 841 _5L _axa _b0201080u 0 4000uu |000000 _e1 841 _5NB _axa _b0201080u 0 4000uu |000000 _e1 841 _5Q _axa _b0201080u 0 4000uu |000000 _e1 841 _5S _axa _b0201080u 0 4000uu |000000 _e1 852 _5NB _bNB _cNB98:12 _hplikt _jR, 980520 852 _5Li _bLi _cCNB _hh,u 852 _5SEE _bSEE 852 _5Q _bQ _j98947 852 _5L _bL _c0100 _h98/ _j3043 H 852 _5S _bS _hSv97 _j7235 900 1s _aYanson, Tobe, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonov,̀ Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansone, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonova, Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 976 2 _aHcd,u _bSkn̲litteratur 005 20050204111518.0 PK!_(test/File_MARC/tests/marc_field_002.phptnu[--TEST-- marc_field_002: Create fields with invalid indicators --SKIPIF-- --FILE-- getMessage()}\n"; } --EXPECT-- Error: Illegal indicator "$@" in field "100" forced to blank PK!Ya3'test/File_MARC/tests/marc_lint_001.phptnu[--TEST-- marc_lint_001: Full test of Lint suite --SKIPIF-- --FILE-- next()) { $warnings = $marc_lint->checkRecord($marc_record); foreach ($warnings as $warning) { print $warning . "\n"; } } print "\nTest from a constructed record\n"; $rec = new File_MARC_Record(); $rec->setLeader("00000nam 22002538a 4500"); $rec->appendField( new File_MARC_Data_Field( '041', array( new File_MARC_Subfield('a', 'end'), new File_MARC_Subfield('a', 'fren') ), "0", "" ) ); $rec->appendField( new File_MARC_Data_Field( '043', array( new File_MARC_Subfield('a', 'n-us-pn') ), "", "" ) ); $rec->appendField( new File_MARC_Data_Field( '082', array( new File_MARC_Subfield('a', '005.13/3'), // typo 'R' for 'W' and missing 'b' subfield new File_MARC_Subfield('R', 'all'), new File_MARC_Subfield('2', '21') ), "0", "4" ) ); $rec->appendField( new File_MARC_Data_Field( '082', array( new File_MARC_Subfield('a', '005.13'), new File_MARC_Subfield('b', 'Wall'), new File_MARC_Subfield('2', '14') ), "1", "4" ) ); $rec->appendField( new File_MARC_Data_Field( '100', array( new File_MARC_Subfield('a', 'Wall, Larry') ), "1", "4" ) ); $rec->appendField( new File_MARC_Data_Field( '110', array( new File_MARC_Subfield('a', "O'Reilly & Associates.") ), "1", "" ) ); $rec->appendField( new File_MARC_Data_Field( '245', array( new File_MARC_Subfield('a', 'Programming Perl / '), new File_MARC_Subfield('a', 'Big Book of Perl /'), new File_MARC_Subfield('c', 'Larry Wall, Tom Christiansen & Jon Orwant.') ), "9", "0" ) ); $rec->appendField( new File_MARC_Data_Field( '250', array( new File_MARC_Subfield('a', '3rd ed.') ), "", "" ) ); $rec->appendField( new File_MARC_Data_Field( '250', array( new File_MARC_Subfield('a', '3rd ed.') ), "", "" ) ); $rec->appendField( new File_MARC_Data_Field( '260', array( new File_MARC_Subfield('a', 'Cambridge, Mass. : '), new File_MARC_Subfield('b', "O'Reilly, "), new File_MARC_Subfield('r', '2000.') ), "", "" ) ); $rec->appendField( new File_MARC_Data_Field( '590', array( new File_MARC_Subfield('a', 'Personally signed by Larry.') ), "4", "" ) ); $rec->appendField( new File_MARC_Data_Field( '650', array( new File_MARC_Subfield('a', 'Perl (Computer program language)'), new File_MARC_Subfield('0', '(DLC)sh 95010633') ), "", "0" ) ); $rec->appendField( new File_MARC_Data_Field( '856', array( new File_MARC_Subfield('u', 'http://www.perl.com/') ), "4", "3" ) ); $rec->appendField( new File_MARC_Data_Field( '886', array( new File_MARC_Subfield('4', 'Some foreign thing'), new File_MARC_Subfield('q', 'Another foreign thing') ), "0", "" ) ); $warnings = $marc_lint->checkRecord($rec); foreach ($warnings as $warning) { print $warning . "\n"; } ?> --EXPECT-- Test records in camel.mrc 100: Indicator 1 must be 0, 1 or 3 but it's "2" 007: Subfields are not allowed in fields lower than 010 Test from a constructed record 1XX: Only one 1XX tag is allowed, but I found 2 of them. 041: Subfield _a, end (end), is not valid. 041: Subfield _a must be evenly divisible by 3 or exactly three characters if ind2 is not 7, (fren). 043: Subfield _a, n-us-pn, is not valid. 082: Subfield _R is not allowed. 100: Indicator 2 must be blank but it's "4" 245: Indicator 1 must be 0 or 1 but it's "9" 245: Subfield _a is not repeatable. 250: Field is not repeatable. 260: Subfield _r is not allowed. 856: Indicator 2 must be blank, 0, 1, 2 or 8 but it's "3" PK! &test/File_MARC/tests/marc_xml_004.phptnu[--TEST-- marc_xml_004: test conversion to XML of subfields that need to be escaped --SKIPIF-- --FILE-- next()) { print $marc_record->toXML(); print "\n"; } ?> --EXPECT-- 00727nam 2200205 a 4500 03-0016458 19971103184734.0 970701s1997 oru u000 0 eng u (Sirsi) a351664 ML270.2 .A6 1997 Anthony, James R. French baroque music from Beaujoyeulx to Rameau Rev. and expanded ed. Portland, OR : Amadeus Press, 1997. 586 p. : music Music France 16th century History and criticism. Music France 17th century History and criticism. Music France 18th century History and criticism. ML 270.2 A6 1997 LC 30007006841505 Y BOOKS HUNT-CIRC HUNTINGTON 1 PK!a+test/File_MARC/tests/marc_subfield_001.phptnu[--TEST-- marc_subfield_001: Exercise basic methods for File_MARC_Subfield class --SKIPIF-- --FILE-- getCode() . "\n"; print "Data: " . $subfield->getData() . "\n"; // test __toString implementation print $subfield; print "\n"; // test raw output implementation print $subfield->toRaw() . "\n"; // test isEmpty() if ($subfield->isEmpty()) { print "Subfield is empty\n"; } else { print "Subfield is not empty\n"; } ?> --EXPECT-- Code: a Data: wasssup [a]: wasssup awasssup Subfield is not empty PK!L"test/File_MARC/tests/marc_006.phptnu[--TEST-- marc_006: test read.php --SKIPIF-- --FILE-- next(); // Retrieve a personal name field from the record $names = $marc_record->getFields('100'); foreach ($names as $name_field) { // Now print the $a subfield switch ($name_field->getIndicator(1)) { case 0: print "Forename: "; break; case 1: print "Surname: "; break; case 2: print "Family name: "; break; } $name = $name_field->getSubfields('a'); if (count($name) == 1) { print $name[0]->getData() . "\n"; } else { print "Error -- \$a subfield appears more than once in this field!"; } } // Retrieve all series statement fields // Series statement fields start with a 4 (PCRE) $subjects = $marc_record->getFields('^4', true); // Iterate through all of the returned series statement fields foreach ($subjects as $field) { // print with File_MARC_Field_Data's magic __toString() method print $field; } ?> --EXPECT-- Surname: Jansson, Tove, 440 0 _aMumin-biblioteket, _x99-0698931-9 PK!'test/File_MARC/tests/marc_lint_004.phptnu[--TEST-- marc_lint_004: Tests check_245() called separately --SKIPIF-- --FILE-- check245($field); } ?> --EXPECT-- 245: Must have a subfield _a. 245: First subfield must be _a, but it is _b 245: Must end with . (period). 245: MARC21 allows ? or ! as final punctuation but LCRI 1.0C, Nov. 2003, requires period. 245: MARC21 allows ? or ! as final punctuation but LCRI 1.0C, Nov. 2003, requires period. 245: Subfield _c must be preceded by / 245: Subfield _c must be preceded by / 245: Subfield _c initials should not have a space. 245: Subfield _b should be preceded by space-colon, space-semicolon, or space-equals sign. 245: Subfield _b should be preceded by space-colon, space-semicolon, or space-equals sign. 245: Subfield _b should be preceded by space-colon, space-semicolon, or space-equals sign. 245: Subfield _b should be preceded by space-colon, space-semicolon, or space-equals sign. 245: Subfield _h should not be preceded by space. 245: Subfield _h must have matching square brackets, videorecording :. 245: Subfield _n must be preceded by . (period). 245: Subfield _p must be preceded by , (comma) when it follows subfield _n. 245: Subfield _p must be preceded by . (period) when it follows a subfield other than _n. 245: Non-filing indicator is non-numeric 245: First word, the, may be an article, check 2nd indicator (0). 245: First word, an, may be an article, check 2nd indicator (2). 245: First word, l, may be an article, check 2nd indicator (0). 245: First word, a, does not appear to be an article, check 2nd indicator (2). PK!6N&test/File_MARC/tests/marc_xml_006.phptnu[--TEST-- marc_xml_006: test getFields() in XML --SKIPIF-- --FILE-- next(); // Retrieve a personal name field from the record $names = $marc_record->getFields('100'); foreach ($names as $name_field) { // Now print the $a subfield switch ($name_field->getIndicator(1)) { case 0: print "Forename: "; break; case 1: print "Surname: "; break; case 2: print "Family name: "; break; } $name = $name_field->getSubfields('a'); if (count($name) == 1) { print $name[0]->getData() . "\n"; } else { print "Error -- \$a subfield appears more than once in this field!"; } } // Retrieve all subject and genre fields // Series statement fields start with a 6 (PCRE) $subjects = $marc_record->getFields('^6', true); // Iterate through all of the returned subject fields foreach ($subjects as $field) { // print with File_MARC_Field_Data's magic __toString() method print "$field\n"; } ?> --EXPECT-- Surname: Sandburg, Carl, 650 0 _aArithmetic _xJuvenile poetry. 650 0 _aChildren's poetry, American. 650 1 _aArithmetic _xPoetry. 650 1 _aAmerican poetry. 650 1 _aVisual perception. PK! (test/File_MARC/tests/marc_field_005.phptnu[--TEST-- marc_field_005: Test method getContents --SKIPIF-- --FILE-- getSubfields('a'); // we might get an array back; in this case, we want the first subfield if (is_array($sf)) { $field->insertSubfield($subfield1, $sf[0], true); } else { $field->insertSubfield($subfield1, $sf, true); } // let's see the results print $field->getContents(); print "\n"; print $field->getContents('###'); print "\n"; ?> --EXPECT-- a littlenothingeverything a little###nothing###everything PK!ewWW"test/File_MARC/tests/marc_003.phptnu[--TEST-- marc_003: getFields() with various regular expressions --SKIPIF-- --FILE-- next()) { print "\nNext record:\n"; $fields = $marc_record->getFields('650'); foreach ($fields as $field) { print $field; print "\n"; } } print "\nTest with regular expression\n"; $marc_file = new File_MARC($dir . '/' . 'music.mrc'); while ($marc_record = $marc_file->next()) { print "\nNext record:\n"; $fields = $marc_record->getFields('00\d', true); foreach ($fields as $field) { print $field; print "\n"; } } ?> --EXPECT-- Test with a simple string Next record: 650 0 _aJazz. 650 0 _aMotion picture music _vExcerpts _vScores. Next record: 650 0 _aJazz _y1971-1980. Next record: 650 0 _aJazz. Test with regular expression Next record: 001 000073594 004 AAJ5802 005 20030415102100.0 008 801107s1977 nyujza Next record: 001 001878039 005 20050110174900.0 007 sd fungnn|||e| 008 940202r19931981nyujzn i d Next record: 001 001964482 005 20060626132700.0 007 sd fzngnn|m|e| 008 871211p19871957nyujzn d PK!(NNtest/File_MARC/tests/camel.mrcnu[00755cam 22002414a 4500001001300000003000600013005001700019008004100036010001700077020004300094040001800137042000800155050002600163082001700189100003100206245005400237260004200291300007200333500003300405650003700438630002500475630001300500fol05731351 IMchF20000613133448.0000107s2000 nyua 001 0 eng  a 00020737  a0471383147 (paper/cd-rom : alk. paper) aDLCcDLCdDLC apcc00aQA76.73.P22bM33 200000a005.13/32211 aMartinsson, Tobias,d1976-10aActivePerl with ASP and ADO /cTobias Martinsson. aNew York :bJohn Wiley & Sons,c2000. axxi, 289 p. :bill. ;c23 cm. +e1 computer laser disc (4 3/4 in.) a"Wiley Computer Publishing." 0aPerl (Computer program language)00aActive server pages.00aActiveX.00647pam 2200241 a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002600135082001500161100002600176245006700202260003800269263000900307300001100316650003700327650002500364700001600389fol05754809 IMchF20000601115601.0000203s2000 mau 001 0 eng  a 00022023  a1565926994 aDLCcDLCdDLC apcc00aQA76.73.P22bD47 200000a005.742211 aDescartes, Alligator.10aProgramming the Perl DBI /cAlligator Descartes and Tim Bunce. aCmabridge, MA :bO'Reilly,c2000. a1111 ap. cm. 0aPerl (Computer program language) 0aDatabase management.1 aBunce, Tim.00605cam 22002054a 4500001001300000003000600013005001700019008004100036010001700077040001800094042000800112050002700120082001700147100002100164245005500185260004500240300002600285504005100311650003700362fol05843555 IMchF20000525142739.0000318s1999 cau b 001 0 eng  a 00501349  aDLCcDLCdDLC apcc00aQA76.73.P22bB763 199900a005.13/32211 aBrown, Martin C.10aPerl :bprogrammer's reference /cMartin C. Brown. aBerkeley :bOsborne/McGraw-Hill,cc1999. axix, 380 p. ;c22 cm. aIncludes bibliographical references and index. 0aPerl (Computer program language)00579cam 22002054a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002700135082001700162100002100179245005500200260004500255300003600300650003700336fol05843579 IMchF20000525142716.0000318s1999 caua 001 0 eng  a 00502116  a0072120002 aDLCcDLCdDLC apcc00aQA76.73.P22bB762 199900a005.13/32211 aBrown, Martin C.10aPerl :bthe complete reference /cMartin C. Brown. aBerkeley :bOsborne/McGraw-Hill,cc1999. axxxv, 1179 p. :bill. ;c24 cm. 0aPerl (Computer program language)00801nam 22002778a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001800156100002000174245008800194250003200282260004100314263000900355300001100364650003700375650003600412650002600448700002500474700002400499fol05848297 IMchF20000524125727.0000518s2000 mau 001 0 eng  a 00041664  a1565924193 aDLCcDLC apcc00aQA76.73.P22bG84 200000a005.2/7622211 aGuelich, Scott.10aCGI programming with Perl /cScott Guelich, Shishir Gundavaram & Gunther Birznieks. a2nd ed., expanded & updated aCambridge, Mass. :bO'Reilly,c2000. a0006 ap. cm. 0aPerl (Computer program language) 0aCGI (Computer network protocol) 0aInternet programming.1 aGundavaram, Shishir.1 aBirznieks, Gunther.00665nam 22002298a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002700130082001700157111005200174245008600226250001200312260004100324263000900365300001100374650005000385fol05865950 IMchF20000615103017.0000612s2000 mau 100 0 eng  a 00055759  a0596000138 aDLCcDLC apcc00aQA76.73.P22bP475 200000a005.13/32212 aPerl Conference 4.0d(2000 :cMonterey, Calif.)10aProceedings of the Perl Conference 4.0 :bJuly 17-20, 2000, Monterey, California. a1st ed. aCambridge, Mass. :bO'Reilly,c2000. a0006 ap. cm. 0aPerl (Computer program language)vCongresses.00579nam 22002178a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001700156100002800173245006200201260004100263263000900304300001100313650003700324fol05865956 IMchF20000615102948.0000612s2000 mau 000 0 eng  a 00055770  a1565926099 aDLCcDLC apcc00aQA76.73.P22bB43 200000a005.13/32211 aBlank-Edelman, David N.10aPerl for system administration /cDavid N. Blank-Edelman. aCambridge, Mass. :bO'Reilly,c2000. a0006 ap. cm. 0aPerl (Computer program language)00661nam 22002538a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001700156100001700173245006700190250001200257260004100269263000900310300001100319650003700330700002300367700001700390fol05865967 IMchF20000615102611.0000614s2000 mau 000 0 eng  a 00055799  a0596000278 aDLCcDLC apcc00aQA76.73.P22bW35 200000a005.13/32211 aWall, Larry.10aProgramming Perl /cLarry Wall, Tom Christiansen & Jon Orwant. a3rd ed. aCambridge, Mass. :bO'Reilly,c2000. a0007 ap. cm. 0aPerl (Computer program language)1 aChristiansen, Tom.1 aOrwant, Jon.00603cam 22002054a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002600135082001700161100003200178245006000210260005700270300003300327650003700360fol05872355 IMchF20000706095105.0000315s1999 njua 001 0 eng  a 00500678  a013020868X aDLCcDLCdDLC apcc00aQA76.73.P22bL69 199900a005.13/32211 aLowe, Vincentq(Vincent D.)10aPerl programmer's interactive workbook /cVincent Lowe. aUpper Saddle River, NJ :bPrentice Hall PTP,cc1999. axx, 633 p. :bill. ;c23 cm. 0aPerl (Computer program language)00696nam 22002538a 4500001001300000003000600013005001700019008004100036010001700077020002800094040001300122042000800135050002600143082001700169100002600186245004400212260005100256263000900307300001100316500002000327650003700347650001700384650004100401fol05882032 IMchF20000707091904.0000630s2000 cau 001 0 eng  a 00058174  a0764547291 (alk. paper) aDLCcDLC apcc00aQA76.73.P22bF64 200000a005.13/32212 aFoster-Johnson, Eric.10aCross-platform Perl /cEric F. Johnson. aFoster City, CA :bIDG Books Worldwide,c2000. a0009 ap. cm. aIncludes index. 0aPerl (Computer program language) 0aWeb servers. 0aCross-platform software development.00399ngm 2200121 a 4500001001300000003000700013007002800020008004100048245005600089260003800145300006000183538003400243ttt05000099 TEST avbfc dcebfaghhoiu050224s2005 ilu999 vleng d00aTest subfields in control fieldsh[videorecording]. aOregon, Ill. :bB. Baldus,c2005. a1 videocassette (ca. 1000 min.) :bsd., col. ;c1/2 in. aVHS format, SP playback mode.PK!Ujڧ"test/File_MARC/tests/marc_007.phptnu[--TEST-- marc_007: Use key=>value iteration for tags and codes --SKIPIF-- --FILE-- next()) { foreach ($marc_record->getFields() as $tag=>$value) { print "$tag: "; if ($value instanceof File_MARC_Control_Field) { print $value->getData(); } else { foreach ($value->getSubfields() as $code=>$subdata) { print "_$code"; } } print "\n"; } } ?> --EXPECT-- 001: 0000000044 003: EMILDA 008: 980120s1998 fi j 000 0 swe 020: _a_c 035: _9 040: _a 042: _9_9 084: _a_2 084: _5_a_2 084: _5_a_2 084: _5_a_2 100: _a_d 245: _a_c 250: _a 260: _a_b_c_e_f 300: _a_b_c 440: _a_x 500: _a 599: _a 740: _a 775: _z_w_9 841: _5_a_b_e 841: _5_a_b_e 841: _5_a_b_e 841: _5_a_b_e 841: _5_a_b_e 841: _5_a_b_e 852: _5_b_c_h_j 852: _5_b_c_h 852: _5_b 852: _5_b_j 852: _5_b_c_h_j 852: _5_b_h_j 900: _a_d_u_d 900: _a_d_u_d 900: _a_d_u_d 900: _a_d_u_d 900: _a_d_u_d 900: _a_d_u_d 976: _a_b 005: 20050204111518.0 PK!t1t1&test/File_MARC/tests/marc_xml_008.phptnu[--TEST-- marc_xml_008: generate a single collection of MARCXML records from a MARCXML record --SKIPIF-- --FILE-- element $records->toXMLHeader(); // Iterate through the retrieved records while ($record = $records->next()) { // Change each 852 $c to "Audio-Visual" $holdings = $record->getFields('852'); foreach ($holdings as $holding) { // Get the $c subfields from this field $formats = $holding->getSubfields('c'); foreach ($formats as $format) { if ($format->getData('AV')) { $format->setData('Audio-Visual'); } } } // Generate the XML output for this record print $record->toXML('UTF-8', true, false); } // Add the closing element and dump the XMLWriter contents print $records->toXMLFooter(); --EXPECT-- 01145ncm a2200277 i 4500 000073594 AAJ5802 20030415102100.0 801107s1977 nyujza 77771106 (CaOTUIC)15460184 AAJ5802 LC M1366 .M62 M1527.2 The Modern Jazz Quartet : The legendary profile. -- New York : M.J.Q. Music, c1977. score (72 p.) ; 31 cm. For piano, vibraphone, drums, and double bass. Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B́Ư.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. Jazz. Motion picture music Excerpts Scores. Lewis, John, 1920- Selections. 1977. Jackson, Milt. Martyrs. 1977. Jackson, Milt. Legendary profile. 1977. The legendary profile. MUSIC Audio-Visual folio M1366 M62 1 Marvin Duchow Music 01293cjm a2200289 a 4500 001878039 20050110174900.0 sd fungnn|||e| 940202r19931981nyujzn i d 7464573372 JK 57337 Red Baron (OCoLC)29737267 SVP SVP LGG Desmond, Paul, 1924- Paul Desmond & the Modern Jazz Quartet [sound recording] New York, N.Y. : Red Baron : Manufactured by Sony Music Entertainment, p1993. 1 sound disc (39 min.) : digital ; 4 3/4 in. Paul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. All arrangements by John Lewis. Recorded live on December 25, 1971 at Town Hall, NYC. Originally released in 1981 by Finesse as LP FW 27487. Program notes by Irving Townsend, June 1981, on container insert. Greensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. Jazz 1971-1980. Lewis, John, 1920- Modern Jazz Quartet. Paul Desmond and the Modern Jazz Quartet. 01829cjm a2200385 a 4500 001964482 20060626132700.0 sd fzngnn|m|e| 871211p19871957nyujzn d 4228332902 833 290-2 Verve 19571027 6299 D56 196112-- 3804 N4 19571019 4104 C6 197107-- 6299 V7 (OCoLC)17222092 CPL CPL OCL LGG pz01 ka01 sd01 pd01 Modern Jazz Quartet. prf The Modern Jazz Quartet plus [sound recording]. [New York] : Verve, p1987. 1 sound disc : digital ; 4 3/4 in. Compact jazz Modern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. Recorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). Compact disc. Analog recording. The golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cort©·ge (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). Jazz. Jackson, Milt. prf Peterson, Oscar, 1925- prf Brown, Ray, 1926-2002. prf Thigpen, Ed. prf Hayes, Louis, 1937- prf MUSIC Audio-Visual CD 1131 Marvin Duchow Music Audio-Visual PK!uN9 "test/File_MARC/tests/marc_005.phptnu[--TEST-- marc_005: Ensure a duplicated record is a deep copy; test deleteFields() --SKIPIF-- --FILE-- next(); $copy_record = $marc_record; $duplicate_record = clone $marc_record; $num_deleted1 = $marc_record->deleteFields('020'); print "Deleted $num_deleted1 fields from the original record.\n"; $num_deleted2 = $copy_record->deleteFields('8\\d\\d', true); print "Deleted $num_deleted2 fields from the shallow copy record.\n"; $num_deleted3 = $duplicate_record->deleteFields('9\\d\\d', true); print "Deleted $num_deleted3 fields from the duplicate record.\n"; print "Original:\n"; print $marc_record; print "\nCopy:\n"; print $copy_record; print "\nDuplicate:\n"; print $duplicate_record; print "\n"; ?> --EXPECT-- Deleted 1 fields from the original record. Deleted 12 fields from the shallow copy record. Deleted 7 fields from the duplicate record. Original: LDR 01850 2200517 4500 001 0000000044 003 EMILDA 008 980120s1998 fi j 000 0 swe 035 _99515008808 040 _aNB 042 _9NB _9SEE 084 _aHcd,u _2kssb/6 084 _5NB _auHc _2kssb 084 _5SEE _aHcf _2kssb/6 084 _5Q _aHcd,uf _2kssb/6 100 1 _aJansson, Tove, _d1914-2001 245 04 _aDet osynliga barnet och andra berttelser / _cTove Jansson 250 _a7. uppl. 260 _aHelsingfors : _bSchildt, _c1998 ; _e(Falun : _fScandbook) 300 _a166, [4] s. : _bill. ; _c21 cm 440 0 _aMumin-biblioteket, _x99-0698931-9 500 _aOriginaluppl. 1962 599 _aLi: S 740 4 _aDet osynliga barnet 775 1 _z951-50-0385-7 _w9515003857 _907 005 20050204111518.0 Copy: LDR 01850 2200517 4500 001 0000000044 003 EMILDA 008 980120s1998 fi j 000 0 swe 035 _99515008808 040 _aNB 042 _9NB _9SEE 084 _aHcd,u _2kssb/6 084 _5NB _auHc _2kssb 084 _5SEE _aHcf _2kssb/6 084 _5Q _aHcd,uf _2kssb/6 100 1 _aJansson, Tove, _d1914-2001 245 04 _aDet osynliga barnet och andra berttelser / _cTove Jansson 250 _a7. uppl. 260 _aHelsingfors : _bSchildt, _c1998 ; _e(Falun : _fScandbook) 300 _a166, [4] s. : _bill. ; _c21 cm 440 0 _aMumin-biblioteket, _x99-0698931-9 500 _aOriginaluppl. 1962 599 _aLi: S 740 4 _aDet osynliga barnet 775 1 _z951-50-0385-7 _w9515003857 _907 005 20050204111518.0 Duplicate: LDR 01850 2200517 4500 001 0000000044 003 EMILDA 008 980120s1998 fi j 000 0 swe 035 _99515008808 040 _aNB 042 _9NB _9SEE 084 _aHcd,u _2kssb/6 084 _5NB _auHc _2kssb 084 _5SEE _aHcf _2kssb/6 084 _5Q _aHcd,uf _2kssb/6 100 1 _aJansson, Tove, _d1914-2001 245 04 _aDet osynliga barnet och andra berttelser / _cTove Jansson 250 _a7. uppl. 260 _aHelsingfors : _bSchildt, _c1998 ; _e(Falun : _fScandbook) 300 _a166, [4] s. : _bill. ; _c21 cm 440 0 _aMumin-biblioteket, _x99-0698931-9 500 _aOriginaluppl. 1962 599 _aLi: S 740 4 _aDet osynliga barnet 775 1 _z951-50-0385-7 _w9515003857 _907 005 20050204111518.0 PK! VU,,*test/File_MARC/tests/marc_field_21246.phptnu[--TEST-- marc_field_21246: Delete multiple subfields --SKIPIF-- --FILE-- getSubfields('9') as $subfield) { echo "Deleting subfield: $subfield\n"; $field->deleteSubfield($subfield); } echo "\n--- After: ---\n$field\n\n"; ?> --EXPECT-- --- Before: --- 650 _9test1 _9test2 _0test3 _9test4 Deleting subfield: [9]: test1 Deleting subfield: [9]: test2 Deleting subfield: [9]: test4 --- After: --- 650 _0test3 PK!d z= = 'test/File_MARC/tests/marc_lint_002.phptnu[--TEST-- marc_lint_002: Tests check041() and check043() called separately --SKIPIF-- --FILE-- check041($field); $field = new File_MARC_Data_Field( '041', array( new File_MARC_Subfield('a', 'endorviwo'), // invalid new File_MARC_Subfield('a', 'spanowpalasba') // too long and invalid ), "1", "" ); $marc_lint->check041($field); $field = new File_MARC_Data_Field( '043', array( new File_MARC_Subfield('a', 'n-----'), // 6 chars vs. 7 new File_MARC_Subfield('a', 'n-us----'), // 8 chars vs. 7 new File_MARC_Subfield('a', 'n-ma-us'), // invalid code new File_MARC_Subfield('a', 'e-ur-ai') // obsolete code ), "", "" ); $marc_lint->check043($field); ?> --EXPECT-- 041: Subfield _a, end (end), is not valid. 041: Subfield _a must be evenly divisible by 3 or exactly three characters if ind2 is not 7, (span). 041: Subfield _h, far, may be obsolete. 041: Subfield _a, endorviwo (end), is not valid. 041: Subfield _a, endorviwo (orv), is not valid. 041: Subfield _a, endorviwo (iwo), is not valid. 041: Subfield _a must be evenly divisible by 3 or exactly three characters if ind2 is not 7, (spanowpalasba). 043: Subfield _a must be exactly 7 characters, n----- 043: Subfield _a must be exactly 7 characters, n-us---- 043: Subfield _a, n-ma-us, is not valid. 043: Subfield _a, e-ur-ai, may be obsolete. PK!=O !test/File_MARC/tests/sandburg.xmlnu[ 01142cam 2200301 a 4500 92005291 DLC 19930521155141.9 920219s1993 caua j 000 0 eng 92005291 0152038655 : $15.95 DLC DLC DLC lcac PS3537.A618 A88 1993 811/.52 20 Sandburg, Carl, 1878-1967. Arithmetic / Carl Sandburg ; illustrated as an anamorphic adventure by Ted Rand. 1st ed. San Diego : Harcourt Brace Jovanovich, c1993. 1 v. (unpaged) : ill. (some col.) ; 26 cm. One Mylar sheet included in pocket. A poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone. Arithmetic Juvenile poetry. Children's poetry, American. Arithmetic Poetry. American poetry. Visual perception. Rand, Ted, ill. PK!s}3test/File_MARC/tests/marc_xml_namespace_prefix.phptnu[--TEST-- marc_xml_namespace: iterate and pretty print a MARC record --SKIPIF-- --FILE-- next()) { print $marc_record->getLeader(); print "\n"; $field = $marc_record->getField('050'); print $field->getIndicator(1); print "\n"; print $field->getIndicator(2); print "\n"; $subfield = $field->getSubfield('a'); print $subfield->getData(); print "\n"; } ?> --EXPECT-- 00925njm 22002777a 4500 0 0 Atlantic 1259 01832cmma 2200349 a 4500 0 0 F204.W5 PK!<&test/File_MARC/tests/marc_xml_001.phptnu[--TEST-- marc_xml_001: iterate and pretty print a MARC record --SKIPIF-- --FILE-- next()) { /* Note that this adds characters to the leader to satisfy MARCXML schema */ print $marc_record->toXML(); print "\n"; } ?> --EXPECT-- 01850na 2200517 4500 0000000044 EMILDA 980120s1998 fi j 000 0 swe 9515008808 FIM 72:00 9515008808 NB NB SEE Hcd,u kssb/6 NB uHc kssb SEE Hcf kssb/6 Q Hcd,uf kssb/6 Jansson, Tove, 1914-2001 Det osynliga barnet och andra berttelser / Tove Jansson 7. uppl. Helsingfors : Schildt, 1998 ; (Falun : Scandbook) 166, [4] s. : ill. ; 21 cm Mumin-biblioteket, 99-0698931-9 Originaluppl. 1962 Li: S Det osynliga barnet 951-50-0385-7 9515003857 07 Li xa 0201080u 0 4000uu |000000 1 SEE xa 0201080u 0 4000uu |000000 1 L xa 0201080u 0 4000uu |000000 1 NB xa 0201080u 0 4000uu |000000 1 Q xa 0201080u 0 4000uu |000000 1 S xa 0201080u 0 4000uu |000000 1 NB NB NB98:12 plikt R, 980520 Li Li CNB h,u SEE SEE Q Q 98947 L L 0100 98/ 3043 H S S Sv97 7235 Yanson, Tobe, 1914-2001 Jansson, Tove, 1914-2001 Janssonov, Tove, 1914-2001 Jansson, Tove, 1914-2001 Jansone, Tuve, 1914-2001 Jansson, Tove, 1914-2001 Janson, Tuve, 1914-2001 Jansson, Tove, 1914-2001 Jansson, Tuve, 1914-2001 Jansson, Tove, 1914-2001 Janssonova, Tove, 1914-2001 Jansson, Tove, 1914-2001 Hcd,u Sknlitteratur 20050204111518.0 PK!b|T%T%"test/File_MARC/tests/marc_004.phptnu[--TEST-- marc_004: Delete fields and subfields --SKIPIF-- --FILE-- next()) { print "\nNext record:\n"; $fields = $marc_record->getFields('650'); foreach ($fields as $field) { $field->delete(); } print $marc_record; } $marc_file = null; $marc_file = new File_MARC($dir . '/' . 'music.mrc'); print "\nDelete all subfields with code 'a' from fields with tag 650\n"; while ($marc_record = $marc_file->next()) { print "\nNext record:\n"; $fields = $marc_record->getFields('650'); foreach ($fields as $field) { $sf = $field->getSubfields('a'); foreach ($sf as $subfield) { $field->deleteSubfield($subfield); } } print $marc_record; } ?> --EXPECT-- Delete all fields with tag 650 Next record: LDR 01145ncm 2200277 i 4500 001 000073594 004 AAJ5802 005 20030415102100.0 008 801107s1977 nyujza 010 _a 77771106 035 _a(CaOTUIC)15460184 035 9 _aAAJ5802 040 _aLC 050 00 _aM1366 _b.M62 _dM1527.2 245 04 _aThe Modern Jazz Quartet : _bThe legendary profile. -- 260 _aNew York : _bM.J.Q. Music, _cc1977. 300 _ascore (72 p.) ; _c31 cm. 500 _aFor piano, vibraphone, drums, and double bass. 505 0 _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 700 12 _aLewis, John, _d1920- _tSelections. _f1977. 700 12 _aJackson, Milt. _tMartyrs. _f1977. 700 12 _aJackson, Milt. _tLegendary profile. _f1977. 740 4 _aThe legendary profile. 852 00 _bMUSIC _cMAIN _kfolio _hM1366 _iM62 _91 _4Marvin Duchow Music _5 Next record: LDR 01293cjm 2200289 a 4500 001 001878039 005 20050110174900.0 007 sd fungnn|||e| 008 940202r19931981nyujzn i d 024 1 _a7464573372 028 02 _aJK 57337 _bRed Baron 035 _a(OCoLC)29737267 040 _aSVP _cSVP _dLGG 100 1 _aDesmond, Paul, _d1924- 245 10 _aPaul Desmond & the Modern Jazz Quartet _h[sound recording] 260 _aNew York, N.Y. : _bRed Baron : _bManufactured by Sony Music Entertainment, _cp1993. 300 _a1 sound disc (39 min.) : _bdigital ; _c4 3/4 in. 511 0 _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. 500 _aAll arrangements by John Lewis. 518 _aRecorded live on December 25, 1971 at Town Hall, NYC. 500 _aOriginally released in 1981 by Finesse as LP FW 27487. 500 _aProgram notes by Irving Townsend, June 1981, on container insert. 505 0 _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 700 1 _aLewis, John, _d1920- 710 2 _aModern Jazz Quartet. 740 0 _aPaul Desmond and the Modern Jazz Quartet. Next record: LDR 01829cjm 2200385 a 4500 001 001964482 005 20060626132700.0 007 sd fzngnn|m|e| 008 871211p19871957nyujzn d 024 1 _a4228332902 028 01 _a833 290-2 _bVerve 033 0 _a19571027 _b6299 _cD56 033 0 _a196112-- _b3804 _cN4 033 0 _a19571019 _b4104 _cC6 033 0 _a197107-- _b6299 _cV7 035 _a(OCoLC)17222092 040 _aCPL _cCPL _dOCL _dLGG 048 _apz01 _aka01 _asd01 _apd01 110 2 _aModern Jazz Quartet. _4prf 245 14 _aThe Modern Jazz Quartet plus _h[sound recording]. 260 _a[New York] : _bVerve, _cp1987. 300 _a1 sound disc : _bdigital ; _c4 3/4 in. 440 0 _aCompact jazz 511 0 _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. 518 _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). 500 _aCompact disc. 500 _aAnalog recording. 505 0 _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 700 1 _aJackson, Milt. _4prf 700 1 _aPeterson, Oscar, _d1925- _4prf 700 1 _aBrown, Ray, _d1926-2002. _4prf 700 1 _aThigpen, Ed. _4prf 700 1 _aHayes, Louis, _d1937- _4prf 852 80 _bMUSIC _cAV _hCD 1131 _4Marvin Duchow Music _5Audio-Visual Delete all subfields with code 'a' from fields with tag 650 Next record: LDR 01145ncm 2200277 i 4500 001 000073594 004 AAJ5802 005 20030415102100.0 008 801107s1977 nyujza 010 _a 77771106 035 _a(CaOTUIC)15460184 035 9 _aAAJ5802 040 _aLC 050 00 _aM1366 _b.M62 _dM1527.2 245 04 _aThe Modern Jazz Quartet : _bThe legendary profile. -- 260 _aNew York : _bM.J.Q. Music, _cc1977. 300 _ascore (72 p.) ; _c31 cm. 500 _aFor piano, vibraphone, drums, and double bass. 505 0 _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 650 0 _vExcerpts _vScores. 700 12 _aLewis, John, _d1920- _tSelections. _f1977. 700 12 _aJackson, Milt. _tMartyrs. _f1977. 700 12 _aJackson, Milt. _tLegendary profile. _f1977. 740 4 _aThe legendary profile. 852 00 _bMUSIC _cMAIN _kfolio _hM1366 _iM62 _91 _4Marvin Duchow Music _5 Next record: LDR 01293cjm 2200289 a 4500 001 001878039 005 20050110174900.0 007 sd fungnn|||e| 008 940202r19931981nyujzn i d 024 1 _a7464573372 028 02 _aJK 57337 _bRed Baron 035 _a(OCoLC)29737267 040 _aSVP _cSVP _dLGG 100 1 _aDesmond, Paul, _d1924- 245 10 _aPaul Desmond & the Modern Jazz Quartet _h[sound recording] 260 _aNew York, N.Y. : _bRed Baron : _bManufactured by Sony Music Entertainment, _cp1993. 300 _a1 sound disc (39 min.) : _bdigital ; _c4 3/4 in. 511 0 _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. 500 _aAll arrangements by John Lewis. 518 _aRecorded live on December 25, 1971 at Town Hall, NYC. 500 _aOriginally released in 1981 by Finesse as LP FW 27487. 500 _aProgram notes by Irving Townsend, June 1981, on container insert. 505 0 _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 650 0 _y1971-1980. 700 1 _aLewis, John, _d1920- 710 2 _aModern Jazz Quartet. 740 0 _aPaul Desmond and the Modern Jazz Quartet. Next record: LDR 01829cjm 2200385 a 4500 001 001964482 005 20060626132700.0 007 sd fzngnn|m|e| 008 871211p19871957nyujzn d 024 1 _a4228332902 028 01 _a833 290-2 _bVerve 033 0 _a19571027 _b6299 _cD56 033 0 _a196112-- _b3804 _cN4 033 0 _a19571019 _b4104 _cC6 033 0 _a197107-- _b6299 _cV7 035 _a(OCoLC)17222092 040 _aCPL _cCPL _dOCL _dLGG 048 _apz01 _aka01 _asd01 _apd01 110 2 _aModern Jazz Quartet. _4prf 245 14 _aThe Modern Jazz Quartet plus _h[sound recording]. 260 _a[New York] : _bVerve, _cp1987. 300 _a1 sound disc : _bdigital ; _c4 3/4 in. 440 0 _aCompact jazz 511 0 _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. 518 _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). 500 _aCompact disc. 500 _aAnalog recording. 505 0 _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 700 1 _aJackson, Milt. _4prf 700 1 _aPeterson, Oscar, _d1925- _4prf 700 1 _aBrown, Ray, _d1926-2002. _4prf 700 1 _aThigpen, Ed. _4prf 700 1 _aHayes, Louis, _d1937- _4prf 852 80 _bMUSIC _cAV _hCD 1131 _4Marvin Duchow Music _5Audio-Visual PK!"test/File_MARC/tests/marc_015.phptnu[--TEST-- marc_015: ensure that pandemonium does not occur if a record doesn't have a given field --SKIPIF-- --FILE-- next()) { // Record #2 doesn't contain an 852; getField() returns false $mfhd = $marc_record->getField('852'); if ($mfhd) { $mfhd = $mfhd->getSubfield('b'); } print $marc_record; print "\n"; } ?> --EXPECT-- LDR 01145ncm 2200277 i 4500 001 000073594 004 AAJ5802 005 20030415102100.0 008 801107s1977 nyujza 010 _a 77771106 035 _a(CaOTUIC)15460184 035 9 _aAAJ5802 040 _aLC 050 00 _aM1366 _b.M62 _dM1527.2 245 04 _aThe Modern Jazz Quartet : _bThe legendary profile. -- 260 _aNew York : _bM.J.Q. Music, _cc1977. 300 _ascore (72 p.) ; _c31 cm. 500 _aFor piano, vibraphone, drums, and double bass. 505 0 _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 650 0 _aJazz. 650 0 _aMotion picture music _vExcerpts _vScores. 700 12 _aLewis, John, _d1920- _tSelections. _f1977. 700 12 _aJackson, Milt. _tMartyrs. _f1977. 700 12 _aJackson, Milt. _tLegendary profile. _f1977. 740 4 _aThe legendary profile. 852 00 _bMUSIC _cMAIN _kfolio _hM1366 _iM62 _91 _4Marvin Duchow Music _5 LDR 01293cjm 2200289 a 4500 001 001878039 005 20050110174900.0 007 sd fungnn|||e| 008 940202r19931981nyujzn i d 024 1 _a7464573372 028 02 _aJK 57337 _bRed Baron 035 _a(OCoLC)29737267 040 _aSVP _cSVP _dLGG 100 1 _aDesmond, Paul, _d1924- 245 10 _aPaul Desmond & the Modern Jazz Quartet _h[sound recording] 260 _aNew York, N.Y. : _bRed Baron : _bManufactured by Sony Music Entertainment, _cp1993. 300 _a1 sound disc (39 min.) : _bdigital ; _c4 3/4 in. 511 0 _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. 500 _aAll arrangements by John Lewis. 518 _aRecorded live on December 25, 1971 at Town Hall, NYC. 500 _aOriginally released in 1981 by Finesse as LP FW 27487. 500 _aProgram notes by Irving Townsend, June 1981, on container insert. 505 0 _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 650 0 _aJazz _y1971-1980. 700 1 _aLewis, John, _d1920- 710 2 _aModern Jazz Quartet. 740 0 _aPaul Desmond and the Modern Jazz Quartet. LDR 01829cjm 2200385 a 4500 001 001964482 005 20060626132700.0 007 sd fzngnn|m|e| 008 871211p19871957nyujzn d 024 1 _a4228332902 028 01 _a833 290-2 _bVerve 033 0 _a19571027 _b6299 _cD56 033 0 _a196112-- _b3804 _cN4 033 0 _a19571019 _b4104 _cC6 033 0 _a197107-- _b6299 _cV7 035 _a(OCoLC)17222092 040 _aCPL _cCPL _dOCL _dLGG 048 _apz01 _aka01 _asd01 _apd01 110 2 _aModern Jazz Quartet. _4prf 245 14 _aThe Modern Jazz Quartet plus _h[sound recording]. 260 _a[New York] : _bVerve, _cp1987. 300 _a1 sound disc : _bdigital ; _c4 3/4 in. 440 0 _aCompact jazz 511 0 _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. 518 _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). 500 _aCompact disc. 500 _aAnalog recording. 505 0 _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 650 0 _aJazz. 700 1 _aJackson, Milt. _4prf 700 1 _aPeterson, Oscar, _d1925- _4prf 700 1 _aBrown, Ray, _d1926-2002. _4prf 700 1 _aThigpen, Ed. _4prf 700 1 _aHayes, Louis, _d1937- _4prf 852 80 _bMUSIC _cAV _hCD 1131 _4Marvin Duchow Music _5Audio-Visual PK!X""test/File_MARC/tests/marc_009.phptnu[--TEST-- marc_009: Parse a record where leader record length != real record length --SKIPIF-- --FILE-- next()) { print $marc_record; print "\n"; print "WARNINGS:\n"; foreach ($marc_record->getWarnings() as $warning) { print " * $warning\n"; } } ?> --EXPECT-- LDR 00727nam 2200205 a 4500 001 03-0016458 005 19971103184734.0 008 970701s1997 oru u000 0 eng u 035 _a(Sirsi) a351664 050 00 _aML270.2 _b.A6 1997 100 1 _aAnthony, James R. 245 00 _aFrench baroque music from Beaujoyeulx to Rameau 250 _aRev. and expanded ed. 260 _aPortland, OR : _bAmadeus Press, _c1997. 300 _a586 p. : _bmusic 650 0 _aMusic _ --FILE-- next()) { print $marc_record->toJSONHash(); print "\n"; } ?> --EXPECT-- {"type":"marc-hash","version":[1,0],"leader":"01850 2200517 4500","fields":[["001","0000000044"],["003","EMILDA"],["008","980120s1998 fi j 000 0 swe"],["020"," "," ",[["a","9515008808"],["c","FIM 72:00"]]],["035"," "," ",[["9","9515008808"]]],["040"," "," ",[["a","NB"]]],["042"," "," ",[["9","NB"],["9","SEE"]]],["084"," "," ",[["a","Hcd,u"],["2","kssb\/6"]]],["084"," "," ",[["5","NB"],["a","uHc"],["2","kssb"]]],["084"," "," ",[["5","SEE"],["a","Hcf"],["2","kssb\/6"]]],["084"," "," ",[["5","Q"],["a","Hcd,uf"],["2","kssb\/6"]]],["100","1"," ",[["a","Jansson, Tove,"],["d","1914-2001"]]],["245","0","4",[["a","Det osynliga barnet och andra ber\u00e4ttelser \/"],["c","Tove Jansson"]]],["250"," "," ",[["a","7. uppl."]]],["260"," "," ",[["a","Helsingfors :"],["b","Schildt,"],["c","1998 ;"],["e","(Falun :"],["f","Scandbook)"]]],["300"," "," ",[["a","166, [4] s. :"],["b","ill. ;"],["c","21 cm"]]],["440"," ","0",[["a","Mumin-biblioteket,"],["x","99-0698931-9"]]],["500"," "," ",[["a","Originaluppl. 1962"]]],["599"," "," ",[["a","Li: S"]]],["740","4"," ",[["a","Det osynliga barnet"]]],["775","1"," ",[["z","951-50-0385-7"],["w","9515003857"],["9","07"]]],["841"," "," ",[["5","Li"],["a","xa"],["b","0201080u 0 4000uu |000000"],["e","1"]]],["841"," "," ",[["5","SEE"],["a","xa"],["b","0201080u 0 4000uu |000000"],["e","1"]]],["841"," "," ",[["5","L"],["a","xa"],["b","0201080u 0 4000uu |000000"],["e","1"]]],["841"," "," ",[["5","NB"],["a","xa"],["b","0201080u 0 4000uu |000000"],["e","1"]]],["841"," "," ",[["5","Q"],["a","xa"],["b","0201080u 0 4000uu |000000"],["e","1"]]],["841"," "," ",[["5","S"],["a","xa"],["b","0201080u 0 4000uu |000000"],["e","1"]]],["852"," "," ",[["5","NB"],["b","NB"],["c","NB98:12"],["h","plikt"],["j","R, 980520"]]],["852"," "," ",[["5","Li"],["b","Li"],["c","CNB"],["h","h,u"]]],["852"," "," ",[["5","SEE"],["b","SEE"]]],["852"," "," ",[["5","Q"],["b","Q"],["j","98947"]]],["852"," "," ",[["5","L"],["b","L"],["c","0100"],["h","98\/"],["j","3043 H"]]],["852"," "," ",[["5","S"],["b","S"],["h","Sv97"],["j","7235"]]],["900","1","s",[["a","Yanson, Tobe,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Janssonov\u00e1, Tove,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Jansone, Tuve,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Janson, Tuve,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Jansson, Tuve,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["900","1","s",[["a","Janssonova, Tove,"],["d","1914-2001"],["u","Jansson, Tove,"],["d","1914-2001"]]],["976"," ","2",[["a","Hcd,u"],["b","Sk\u00f6nlitteratur"]]],["005","20050204111518.0"]]} PK!  )test/File_MARC/tests/marc_record_001.phptnu[--TEST-- marc_record_001: create a MARC record from scratch --SKIPIF-- --FILE-- appendField(new File_MARC_Data_Field('245', array( new File_MARC_Subfield('a', 'Main title: '), new File_MARC_Subfield('b', 'subtitle'), new File_MARC_Subfield('c', 'author') ), null, null )); print $marc; ?> --EXPECT-- LDR 245 _aMain title: _bsubtitle _cauthor PK!ritest/File_MARC/tests/skipif.incnu[ PK!\.ivv!test/File_MARC/tests/sandburg.mrcnu[01142cam 2200301 a 4500001001300000003000400013005001700017008004100034010001700075020002500092040001800117042000900135050002600144082001600170100003200186245008600218250001200304260005200316300004900368500004000417520022800457650003300685650003300718650002400751650002100775650002300796700002100819 92005291 DLC19930521155141.9920219s1993 caua j 000 0 eng  a 92005291  a0152038655 :c$15.95 aDLCcDLCdDLC alcac00aPS3537.A618bA88 199300a811/.522201 aSandburg, Carl,d1878-1967.10aArithmetic /cCarl Sandburg ; illustrated as an anamorphic adventure by Ted Rand. a1st ed. aSan Diego :bHarcourt Brace Jovanovich,cc1993. a1 v. (unpaged) :bill. (some col.) ;c26 cm. aOne Mylar sheet included in pocket. aA poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone. 0aArithmeticxJuvenile poetry. 0aChildren's poetry, American. 1aArithmeticxPoetry. 1aAmerican poetry. 1aVisual perception.1 aRand, Ted,eill.PK!#c "test/File_MARC/tests/onerecord.xmlnu[ 01142cam 2200301 a 4500 92005291 DLC 19930521155141.9 920219s1993 caua j 000 0 eng 92005291 0152038655 : $15.95 DLC DLC DLC lcac PS3537.A618 A88 1993 811/.52 20 Sandburg, Carl, 1878-1967. Arithmetic / Carl Sandburg ; illustrated as an anamorphic adventure by Ted Rand. 1st ed. San Diego : Harcourt Brace Jovanovich, c1993. 1 v. (unpaged) : ill. (some col.) ; 26 cm. One Mylar sheet included in pocket. A poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone. Arithmetic Juvenile poetry. Children's poetry, American. Arithmetic Poetry. American poetry. Visual perception. Rand, Ted, ill. PK!<(test/File_MARC/tests/marc_field_004.phptnu[--TEST-- marc_field_004: Add subfields to an existing field (corner case) --SKIPIF-- --FILE-- getSubfields('a'); // we might get an array back; in this case, we want the first subfield if (is_array($sf)) { $field->insertSubfield($subfield1, $sf[0], true); } else { $field->insertSubfield($subfield1, $sf, true); } // let's see the results print $field; print "\n"; ?> --EXPECT-- 100 0 _ga little _anothing _zeverything PK!OVOO"test/File_MARC/tests/marc_010.phptnu[--TEST-- marc_010: iterate and pretty print MARC records from a stream --SKIPIF-- --FILE-- next()) { print $marc_record; print "\n"; } ?> --EXPECT-- LDR 01145ncm 2200277 i 4500 001 000073594 004 AAJ5802 005 20030415102100.0 008 801107s1977 nyujza 010 _a 77771106 035 _a(CaOTUIC)15460184 035 9 _aAAJ5802 040 _aLC 050 00 _aM1366 _b.M62 _dM1527.2 245 04 _aThe Modern Jazz Quartet : _bThe legendary profile. -- 260 _aNew York : _bM.J.Q. Music, _cc1977. 300 _ascore (72 p.) ; _c31 cm. 500 _aFor piano, vibraphone, drums, and double bass. 505 0 _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 650 0 _aJazz. 650 0 _aMotion picture music _vExcerpts _vScores. 700 12 _aLewis, John, _d1920- _tSelections. _f1977. 700 12 _aJackson, Milt. _tMartyrs. _f1977. 700 12 _aJackson, Milt. _tLegendary profile. _f1977. 740 4 _aThe legendary profile. 852 00 _bMUSIC _cMAIN _kfolio _hM1366 _iM62 _91 _4Marvin Duchow Music _5 LDR 01293cjm 2200289 a 4500 001 001878039 005 20050110174900.0 007 sd fungnn|||e| 008 940202r19931981nyujzn i d 024 1 _a7464573372 028 02 _aJK 57337 _bRed Baron 035 _a(OCoLC)29737267 040 _aSVP _cSVP _dLGG 100 1 _aDesmond, Paul, _d1924- 245 10 _aPaul Desmond & the Modern Jazz Quartet _h[sound recording] 260 _aNew York, N.Y. : _bRed Baron : _bManufactured by Sony Music Entertainment, _cp1993. 300 _a1 sound disc (39 min.) : _bdigital ; _c4 3/4 in. 511 0 _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. 500 _aAll arrangements by John Lewis. 518 _aRecorded live on December 25, 1971 at Town Hall, NYC. 500 _aOriginally released in 1981 by Finesse as LP FW 27487. 500 _aProgram notes by Irving Townsend, June 1981, on container insert. 505 0 _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 650 0 _aJazz _y1971-1980. 700 1 _aLewis, John, _d1920- 710 2 _aModern Jazz Quartet. 740 0 _aPaul Desmond and the Modern Jazz Quartet. LDR 01829cjm 2200385 a 4500 001 001964482 005 20060626132700.0 007 sd fzngnn|m|e| 008 871211p19871957nyujzn d 024 1 _a4228332902 028 01 _a833 290-2 _bVerve 033 0 _a19571027 _b6299 _cD56 033 0 _a196112-- _b3804 _cN4 033 0 _a19571019 _b4104 _cC6 033 0 _a197107-- _b6299 _cV7 035 _a(OCoLC)17222092 040 _aCPL _cCPL _dOCL _dLGG 048 _apz01 _aka01 _asd01 _apd01 110 2 _aModern Jazz Quartet. _4prf 245 14 _aThe Modern Jazz Quartet plus _h[sound recording]. 260 _a[New York] : _bVerve, _cp1987. 300 _a1 sound disc : _bdigital ; _c4 3/4 in. 440 0 _aCompact jazz 511 0 _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. 518 _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). 500 _aCompact disc. 500 _aAnalog recording. 505 0 _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 650 0 _aJazz. 700 1 _aJackson, Milt. _4prf 700 1 _aPeterson, Oscar, _d1925- _4prf 700 1 _aBrown, Ray, _d1926-2002. _4prf 700 1 _aThigpen, Ed. _4prf 700 1 _aHayes, Louis, _d1937- _4prf 852 80 _bMUSIC _cAV _hCD 1131 _4Marvin Duchow Music _5Audio-Visual PK!rOϋ 'test/File_MARC/tests/marc_lint_005.phptnu[--TEST-- marc_lint_005: Tests check_020() called separately --SKIPIF-- --FILE-- "154879473"), //too few digits array('a' => "1548794743"), //invalid checksum array('a' => "15487947443"), //11 digits array('a' => "15487947443324"), //14 digits array('a' => "9781548794743"), //13 digit valid array('a' => "9781548794745"), //13 digit invalid array('a' => "1548794740 (10 : good checksum)"), //10 digit valid with qualifier array('a' => "1548794745 (10 : bad checksum)"), //10 digit invalid with qualifier array('a' => "1-54879-474-0 (hyphens and good checksum)"), //10 digit invalid with hyphens and qualifier array('a' => "1-54879-474-5 (hyphens and bad checksum)"), //10 digit invalid with hyphens and qualifier array('a' => "1548794740(10 : unspaced qualifier)"), //10 valid without space before qualifier array('a' => "1548794745(10 : unspaced qualifier : bad checksum)"), //10 invalid without space before qualifier array('z' => "1548794743"), //subfield z ); foreach ($testData as $current) { $subfields = array(); foreach ($current as $key => $value) { $subfields[] = new File_MARC_Subfield($key, $value); } $field = new File_MARC_Data_Field('020', $subfields, '', ''); $marc_lint->check020($field); } ?> --EXPECT-- 020: Subfield a has the wrong number of digits, 154879473. 020: Subfield a has bad checksum, 1548794743. 020: Subfield a has the wrong number of digits, 15487947443. 020: Subfield a has the wrong number of digits, 15487947443324. 020: Subfield a has bad checksum (13 digit), 9781548794745. 020: Subfield a has bad checksum, 1548794745 (10 : bad checksum). 020: Subfield a may have invalid characters. 020: Subfield a may have invalid characters. 020: Subfield a has bad checksum, 1-54879-474-5 (hyphens and bad checksum). 020: Subfield a qualifier must be preceded by space, 1548794740(10 : unspaced qualifier). 020: Subfield a qualifier must be preceded by space, 1548794745(10 : unspaced qualifier : bad checksum). 020: Subfield a has bad checksum, 1548794745(10 : unspaced qualifier : bad checksum). PK!=.&test/File_MARC/tests/marc_xml_007.phptnu[--TEST-- marc_xml_007: test getTag(), isControlField(), and isDataField() convenience methods on MARCXML --SKIPIF-- --FILE-- next()) { $fields = $marc_record->getFields(); foreach ($fields as $field) { print $field->getTag(); if ($field->isControlField()) { print "\tControl field!"; } if ($field->isDataField()) { print "\tData field!"; } print "\n"; } } ?> --EXPECT-- 001 Control field! 003 Control field! 005 Control field! 006 Control field! 007 Control field! 008 Control field! 037 Data field! 040 Data field! 245 Data field! 246 Data field! 260 Data field! 300 Data field! 500 Data field! 500 Data field! 500 Data field! 510 Data field! 510 Data field! 533 Data field! 651 Data field! 830 Data field! 856 Data field! 909 Data field! PK!+6"test/File_MARC/tests/marc_008.phptnu[--TEST-- marc_008: Attempt to open a file that does not exist --SKIPIF-- --FILE-- getMessage(); } ?> --EXPECTF-- Warning: fopen(super_bogus_file): failed to open stream: No such file or directory in %sMARC.php on line %d Invalid input file "super_bogus_file" PK!+W #test/File_MARC/tests/bigarchive.xmlnu[ 00000nam 2200277 450099865026eUnM19961010163452.0m g dcr bn |||a|bb|940112s1649 enk s 00| | eng dCL0051000003ProQuest Information and Learning. 300 N. Zeeb Rd., Ann Arbor, MI 48106Cu-RivESCu-RivESCStRLINdcrbWaOLNThe VVelsh embassador, or the happy newes his vvorship hath brought to London.[electronic resource] :Togetherwith her thirteen articles of acreements, which her propounds to all her cousens in her principality of Wales,and her Cities of London.Happy newes his vvorship hath brought to London[London] :Printed for George Roberts, and are to be soldat the Maiden Head on Snow-Hill neer Holborn Conduit,1649.[2], 6 p.Place of publication from Wing.Annotation on Thomason copy: "May 4th".Reproduction of the original in the British Library.Wing (2nd ed.)W1315.ThomasonE.552[19].Electronic reproduction.Ann Arbor, Mich. :UMI,1999-(Early English books online)Digital version of: (Thomason Tracts ; 85:E552[19])s1999 miun sGreat BritainPolitics and government1642-1649Early works to 1800.Early English books online.E-book (Onsite access at NYPL Research Libraries)http://gateway.proquest.com/openurl?ctx_ver=Z39.88-2003&res_id=xri:eebo&rft_val_fmt=&rft_id=xri:eebo:image:117259Not for export in OCLC Reclamation Project PK!vh "test/File_MARC/tests/marc_014.phptnu[--TEST-- marc_014: Add fields to a MARC record --SKIPIF-- --FILE-- next(); // create some subfields $subfields[] = new File_MARC_Subfield('a', 'nothing'); $subfields[] = new File_MARC_Subfield('z', 'everything'); // create a data field $data_field = new File_MARC_Data_Field('100', $subfields, '0'); // append the data field $marc_record->appendField($data_field); // create a control field $ctrl_field = new File_MARC_Control_Field('001', '01234567890'); // prepend the control field $marc_record->prependField($ctrl_field); // let's see the results print utf8_encode($marc_record); print "\n"; ?> --EXPECT-- LDR 01850 2200517 4500 001 01234567890 001 0000000044 003 EMILDA 008 980120s1998 fi j 000 0 swe 020 _a9515008808 _cFIM 72:00 035 _99515008808 040 _aNB 042 _9NB _9SEE 084 _aHcd,u _2kssb/6 084 _5NB _auHc _2kssb 084 _5SEE _aHcf _2kssb/6 084 _5Q _aHcd,uf _2kssb/6 100 1 _aJansson, Tove, _d1914-2001 245 04 _aDet osynliga barnet och andra berättelser / _cTove Jansson 250 _a7. uppl. 260 _aHelsingfors : _bSchildt, _c1998 ; _e(Falun : _fScandbook) 300 _a166, [4] s. : _bill. ; _c21 cm 440 0 _aMumin-biblioteket, _x99-0698931-9 500 _aOriginaluppl. 1962 599 _aLi: S 740 4 _aDet osynliga barnet 775 1 _z951-50-0385-7 _w9515003857 _907 841 _5Li _axa _b0201080u 0 4000uu |000000 _e1 841 _5SEE _axa _b0201080u 0 4000uu |000000 _e1 841 _5L _axa _b0201080u 0 4000uu |000000 _e1 841 _5NB _axa _b0201080u 0 4000uu |000000 _e1 841 _5Q _axa _b0201080u 0 4000uu |000000 _e1 841 _5S _axa _b0201080u 0 4000uu |000000 _e1 852 _5NB _bNB _cNB98:12 _hplikt _jR, 980520 852 _5Li _bLi _cCNB _hh,u 852 _5SEE _bSEE 852 _5Q _bQ _j98947 852 _5L _bL _c0100 _h98/ _j3043 H 852 _5S _bS _hSv97 _j7235 900 1s _aYanson, Tobe, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonová, Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansone, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonova, Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 976 2 _aHcd,u _bSkönlitteratur 005 20050204111518.0 100 0 _anothing _zeverything PK!,test/File_MARC/tests/marc_xml_namespace.phptnu[--TEST-- marc_xml_namespace: iterate and pretty print a MARC record --SKIPIF-- --FILE-- next()) { print $marc_record->getLeader(); print "\n"; $field = $marc_record->getField('050'); print $field->getIndicator(1); print "\n"; print $field->getIndicator(2); print "\n"; $subfield = $field->getSubfield('a'); print $subfield->getData(); print "\n"; } ?> --EXPECT-- 00925njm 22002777a 4500 0 0 Atlantic 1259 01832cmma 2200349 a 4500 0 0 F204.W5 PK!a nn(test/File_MARC/tests/marc_field_001.phptnu[--TEST-- marc_field_001: Exercise basic methods for File_MARC_Field class --SKIPIF-- --FILE-- getTag() . "\n"; print "Get Ind1: " . $field->getIndicator(1) . "\n"; print "Get Ind2: " . $field->getIndicator(2) . "\n"; // test basic setter methods print "Set Ind1: " . $field->setIndicator(1, '3') . "\n"; // test pretty print print $field; print "\n"; // test raw print print $field->toRaw(); ?> --EXPECT-- Tag: 100 Get Ind1: 0 Get Ind2: Set Ind1: 3 100 3 _anothing _zeverything 3 anothingzeverything PK!CKK&test/File_MARC/tests/marc_xml_009.phptnu[--TEST-- marc_xml_009: convert a MARCXML record with an overly long leader to MARC --SKIPIF-- --FILE-- next()) { print $marc_record->toRaw(); } ?> --EXPECT-- 00749cam a2200241 454500001001400000003000600014005001700020008004100037020001800078020001500096035002100111040003600132050002400168100002500192245007800217260003700295300002100332504004100353650001700394650002200411852004800433901002600481LIBN539044247OCoLC20081030150430.0070630||||| ||| 000 0 eng d a9781856075442 a1856075443 a(OCoLC)156822300 aBTCTAcBTCTAdYDXCPdBAKERdEMT 4aBL2747.2b.W45 20061 aWhite, Stephen Ross.10aSpace for unknowing :bthe place of agnosis in faith /cStephen R. White. aDublin :bColumba Press,cc2006. a160 p. ;c22 cm. aIncludes bibliographical references. 0aAgnosticism. 0aBelief and doubt. a1h230 WHIp11111027105040t65112549p26.95 aLIBN539044247bSystem PK!~N0:: test/File_MARC/tests/example.mrcnu[01850 2200517 45000010011000000030007000110080039000180200026000570350015000830400007000980420012001050840018001170840018001350840021001530840022001741000030001962450062002262500013002882600058003013000033003594400037003925000023004295990010004527400024004627750034004868410048005208410049005688410047006178410048006648410047007128410047007598520038008068520021008448520013008658520016008788520028008948520021009229000056009439000060009999000057010599000056011169000057011729000060012299760026012890050017013150000000044EMILDA980120s1998 fi j 000 0 swe a9515008808cFIM 72:00 99515008808 aNB 9NB9SEE aHcd,u2kssb/6 5NBauHc2kssb 5SEEaHcf2kssb/6 5QaHcd,uf2kssb/61 aJansson, Tove,d1914-200104aDet osynliga barnet och andra berttelser /cTove Jansson a7. uppl. aHelsingfors :bSchildt,c1998 ;e(Falun :fScandbook) a166, [4] s. :bill. ;c21 cm 0aMumin-biblioteket,x99-0698931-9 aOriginaluppl. 1962 aLi: S4 aDet osynliga barnet1 z951-50-0385-7w9515003857907 5Liaxab0201080u 0 4000uu |000000e1 5SEEaxab0201080u 0 4000uu |000000e1 5Laxab0201080u 0 4000uu |000000e1 5NBaxab0201080u 0 4000uu |000000e1 5Qaxab0201080u 0 4000uu |000000e1 5Saxab0201080u 0 4000uu |000000e1 5NBbNBcNB98:12hpliktjR, 980520 5LibLicCNBhh,u 5SEEbSEE 5QbQj98947 5LbLc0100h98/j3043 H 5SbShSv97j72351saYanson, Tobe,d1914-2001uJansson, Tove,d1914-20011saJanssonov, Tove,d1914-2001uJansson, Tove,d1914-20011saJansone, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJansson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanssonova, Tove,d1914-2001uJansson, Tove,d1914-2001 2aHcd,ubSknlitteratur20050204111518.0PK!}۶\pp$test/File_MARC/tests/bad_example.xmlnu[ 01850 a2200517 4500 0000000044 EMILDA 980120s1998 fi j 000 0 swe 9515008808 FIM 72:00 9515008808 NB NB SEE Hcd,u kssb/6 NB uHc kssb SEE Hcf kssb/6 Q Hcd,uf kssb/6 Jansson, Tove, 1914-2001 Det osynliga barnet och andra bert̃telser / Tove Jansson 7. uppl. Helsingfors : Schildt, 1998 ; (Falun : Scandbook) 166, [4] s. : ill. ; 21 cm Mumin-biblioteket, 99-0698931-9 Originaluppl. 1962 Li: S Det osynliga barnet 951-50-0385-7 9515003857 07 Li xa 0201080u 0 4000uu |000000 1 SEE xa 0201080u 0 4000uu |000000 1 L xa 0201080u 0 4000uu |000000 1 NB xa 0201080u 0 4000uu |000000 1 Q xa 0201080u 0 4000uu |000000 1 S xa 0201080u 0 4000uu |000000 1 NB NB NB98:12 plikt R, 980520 Li Li CNB h,u SEE SEE Q Q 98947 L L 0100 98/ 3043 H S S Sv97 7235 Yanson, Tobe, 1914-2001 Jansson, Tove, 1914-2001 Janssonov,̀ Tove, 1914-2001 Jansson, Tove, 1914-2001 Jansone, Tuve, 1914-2001 Jansson, Tove, 1914-2001 Janson, Tuve, 1914-2001 Jansson, Tove, 1914-2001 Jansson, Tuve, 1914-2001 Jansson, Tove, 1914-2001 Janssonova, Tove, 1914-2001 Jansson, Tove, 1914-2001 Hcd,u Skn̲litteratur 20050204111518.0 PK!^Cg33"test/File_MARC/tests/marc_017.phptnu[--TEST-- marc_017: iterate and print a MARC record to JSON format --SKIPIF-- --FILE-- next()) { print $marc_record->toJSON(); print "\n"; } ?> --EXPECT-- {"leader":"01850 2200517 4500","fields":[{"001":"0000000044"},{"003":"EMILDA"},{"008":"980120s1998 fi j 000 0 swe"},{"020":{"ind1":" ","ind2":" ","subfields":[{"a":"9515008808"},{"c":"FIM 72:00"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"9":"9515008808"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"NB"}]}},{"042":{"ind1":" ","ind2":" ","subfields":[{"9":"NB"},{"9":"SEE"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"a":"Hcd,u"},{"2":"kssb\/6"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"a":"uHc"},{"2":"kssb"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"a":"Hcf"},{"2":"kssb\/6"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"a":"Hcd,uf"},{"2":"kssb\/6"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"245":{"ind1":"0","ind2":"4","subfields":[{"a":"Det osynliga barnet och andra ber\u00e4ttelser \/"},{"c":"Tove Jansson"}]}},{"250":{"ind1":" ","ind2":" ","subfields":[{"a":"7. uppl."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Helsingfors :"},{"b":"Schildt,"},{"c":"1998 ;"},{"e":"(Falun :"},{"f":"Scandbook)"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"166, [4] s. :"},{"b":"ill. ;"},{"c":"21 cm"}]}},{"440":{"ind1":" ","ind2":"0","subfields":[{"a":"Mumin-biblioteket,"},{"x":"99-0698931-9"}]}},{"500":{"ind1":" ","ind2":" ","subfields":[{"a":"Originaluppl. 1962"}]}},{"599":{"ind1":" ","ind2":" ","subfields":[{"a":"Li: S"}]}},{"740":{"ind1":"4","ind2":" ","subfields":[{"a":"Det osynliga barnet"}]}},{"775":{"ind1":"1","ind2":" ","subfields":[{"z":"951-50-0385-7"},{"w":"9515003857"},{"9":"07"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"Li"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"L"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"S"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"b":"NB"},{"c":"NB98:12"},{"h":"plikt"},{"j":"R, 980520"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"Li"},{"b":"Li"},{"c":"CNB"},{"h":"h,u"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"b":"SEE"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"b":"Q"},{"j":"98947"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"L"},{"b":"L"},{"c":"0100"},{"h":"98\/"},{"j":"3043 H"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"S"},{"b":"S"},{"h":"Sv97"},{"j":"7235"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Yanson, Tobe,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janssonov\u00e1, Tove,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Jansone, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janson, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Jansson, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janssonova, Tove,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"976":{"ind1":" ","ind2":"2","subfields":[{"a":"Hcd,u"},{"b":"Sk\u00f6nlitteratur"}]}},{"005":"20050204111518.0"}]} PK!^OXRR"test/File_MARC/tests/marc_002.phptnu[--TEST-- marc_002: iterate and pretty print MARC records from a file with multiple records --SKIPIF-- --FILE-- next()) { print $marc_record; print "\n"; } ?> --EXPECT-- LDR 01145ncm 2200277 i 4500 001 000073594 004 AAJ5802 005 20030415102100.0 008 801107s1977 nyujza 010 _a 77771106 035 _a(CaOTUIC)15460184 035 9 _aAAJ5802 040 _aLC 050 00 _aM1366 _b.M62 _dM1527.2 245 04 _aThe Modern Jazz Quartet : _bThe legendary profile. -- 260 _aNew York : _bM.J.Q. Music, _cc1977. 300 _ascore (72 p.) ; _c31 cm. 500 _aFor piano, vibraphone, drums, and double bass. 505 0 _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 650 0 _aJazz. 650 0 _aMotion picture music _vExcerpts _vScores. 700 12 _aLewis, John, _d1920- _tSelections. _f1977. 700 12 _aJackson, Milt. _tMartyrs. _f1977. 700 12 _aJackson, Milt. _tLegendary profile. _f1977. 740 4 _aThe legendary profile. 852 00 _bMUSIC _cMAIN _kfolio _hM1366 _iM62 _91 _4Marvin Duchow Music _5 LDR 01293cjm 2200289 a 4500 001 001878039 005 20050110174900.0 007 sd fungnn|||e| 008 940202r19931981nyujzn i d 024 1 _a7464573372 028 02 _aJK 57337 _bRed Baron 035 _a(OCoLC)29737267 040 _aSVP _cSVP _dLGG 100 1 _aDesmond, Paul, _d1924- 245 10 _aPaul Desmond & the Modern Jazz Quartet _h[sound recording] 260 _aNew York, N.Y. : _bRed Baron : _bManufactured by Sony Music Entertainment, _cp1993. 300 _a1 sound disc (39 min.) : _bdigital ; _c4 3/4 in. 511 0 _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. 500 _aAll arrangements by John Lewis. 518 _aRecorded live on December 25, 1971 at Town Hall, NYC. 500 _aOriginally released in 1981 by Finesse as LP FW 27487. 500 _aProgram notes by Irving Townsend, June 1981, on container insert. 505 0 _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 650 0 _aJazz _y1971-1980. 700 1 _aLewis, John, _d1920- 710 2 _aModern Jazz Quartet. 740 0 _aPaul Desmond and the Modern Jazz Quartet. LDR 01829cjm 2200385 a 4500 001 001964482 005 20060626132700.0 007 sd fzngnn|m|e| 008 871211p19871957nyujzn d 024 1 _a4228332902 028 01 _a833 290-2 _bVerve 033 0 _a19571027 _b6299 _cD56 033 0 _a196112-- _b3804 _cN4 033 0 _a19571019 _b4104 _cC6 033 0 _a197107-- _b6299 _cV7 035 _a(OCoLC)17222092 040 _aCPL _cCPL _dOCL _dLGG 048 _apz01 _aka01 _asd01 _apd01 110 2 _aModern Jazz Quartet. _4prf 245 14 _aThe Modern Jazz Quartet plus _h[sound recording]. 260 _a[New York] : _bVerve, _cp1987. 300 _a1 sound disc : _bdigital ; _c4 3/4 in. 440 0 _aCompact jazz 511 0 _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. 518 _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). 500 _aCompact disc. 500 _aAnalog recording. 505 0 _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 650 0 _aJazz. 700 1 _aJackson, Milt. _4prf 700 1 _aPeterson, Oscar, _d1925- _4prf 700 1 _aBrown, Ray, _d1926-2002. _4prf 700 1 _aThigpen, Ed. _4prf 700 1 _aHayes, Louis, _d1937- _4prf 852 80 _bMUSIC _cAV _hCD 1131 _4Marvin Duchow Music _5Audio-Visual PK! =&test/File_MARC/tests/marc_xml_005.phptnu[--TEST-- marc_xml_005: Round-trip a MARCXML record with a root element of "record" to MARC21 --SKIPIF-- --FILE-- next()) { print $marc_record->toRaw(); } ?> --EXPECT-- 01142cam 2200301 a 4500001001300000003000400013005001700017008004100034010001700075020002500092040001800117042000900135050002600144082001600170100003200186245008600218250001200304260005200316300004900368500004000417520022800457650003300685650003300718650002400751650002100775650002300796700002100819 92005291 DLC19930521155141.9920219s1993 caua j 000 0 eng  a 92005291  a0152038655 :c$15.95 aDLCcDLCdDLC alcac00aPS3537.A618bA88 199300a811/.522201 aSandburg, Carl,d1878-1967.10aArithmetic /cCarl Sandburg ; illustrated as an anamorphic adventure by Ted Rand. a1st ed. aSan Diego :bHarcourt Brace Jovanovich,cc1993. a1 v. (unpaged) :bill. (some col.) ;c26 cm. aOne Mylar sheet included in pocket. aA poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone. 0aArithmeticxJuvenile poetry. 0aChildren's poetry, American. 1aArithmeticxPoetry. 1aAmerican poetry. 1aVisual perception.1 aRand, Ted,eill. PK!5;--test/File_MARC/tests/music.xmlnu[ 01145ncm a2200277 i 4500 000073594 AAJ5802 20030415102100.0 801107s1977 nyujza 77771106 (CaOTUIC)15460184 AAJ5802 LC M1366 .M62 M1527.2 The Modern Jazz Quartet : The legendary profile. -- New York : M.J.Q. Music, c1977. score (72 p.) ; 31 cm. For piano, vibraphone, drums, and double bass. Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B́Ư.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. Jazz. Motion picture music Excerpts Scores. Lewis, John, 1920- Selections. 1977. Jackson, Milt. Martyrs. 1977. Jackson, Milt. Legendary profile. 1977. The legendary profile. MUSIC MAIN folio M1366 M62 1 Marvin Duchow Music 01293cjm a2200289 a 4500 001878039 20050110174900.0 sd fungnn|||e| 940202r19931981nyujzn i d 7464573372 JK 57337 Red Baron (OCoLC)29737267 SVP SVP LGG Desmond, Paul, 1924- Paul Desmond & the Modern Jazz Quartet [sound recording] New York, N.Y. : Red Baron : Manufactured by Sony Music Entertainment, p1993. 1 sound disc (39 min.) : digital ; 4 3/4 in. Paul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. All arrangements by John Lewis. Recorded live on December 25, 1971 at Town Hall, NYC. Originally released in 1981 by Finesse as LP FW 27487. Program notes by Irving Townsend, June 1981, on container insert. Greensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. Jazz 1971-1980. Lewis, John, 1920- Modern Jazz Quartet. Paul Desmond and the Modern Jazz Quartet. 01829cjm a2200385 a 4500 001964482 20060626132700.0 sd fzngnn|m|e| 871211p19871957nyujzn d 4228332902 833 290-2 Verve 19571027 6299 D56 196112-- 3804 N4 19571019 4104 C6 197107-- 6299 V7 (OCoLC)17222092 CPL CPL OCL LGG pz01 ka01 sd01 pd01 Modern Jazz Quartet. prf The Modern Jazz Quartet plus [sound recording]. [New York] : Verve, p1987. 1 sound disc : digital ; 4 3/4 in. Compact jazz Modern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. Recorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). Compact disc. Analog recording. The golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cort©·ge (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). Jazz. Jackson, Milt. prf Peterson, Oscar, 1925- prf Brown, Ray, 1926-2002. prf Thigpen, Ed. prf Hayes, Louis, 1937- prf MUSIC AV CD 1131 Marvin Duchow Music Audio-Visual PK!=d"test/File_MARC/tests/marc_012.phptnu[--TEST-- marc_012: test isControlField() and isDataField() convenience methods --SKIPIF-- --FILE-- next()) { $fields = $marc_record->getFields(); foreach ($fields as $field) { print $field->getTag(); if ($field->isControlField()) { print "\tControl field!"; } if ($field->isDataField()) { print "\tData field!"; } print "\n"; } } ?> --EXPECT-- 001 Control field! 004 Control field! 005 Control field! 008 Control field! 010 Data field! 035 Data field! 035 Data field! 040 Data field! 050 Data field! 245 Data field! 260 Data field! 300 Data field! 500 Data field! 505 Data field! 650 Data field! 650 Data field! 700 Data field! 700 Data field! 700 Data field! 740 Data field! 852 Data field! 001 Control field! 005 Control field! 007 Control field! 008 Control field! 024 Data field! 028 Data field! 035 Data field! 040 Data field! 100 Data field! 245 Data field! 260 Data field! 300 Data field! 511 Data field! 500 Data field! 518 Data field! 500 Data field! 500 Data field! 505 Data field! 650 Data field! 700 Data field! 710 Data field! 740 Data field! 001 Control field! 005 Control field! 007 Control field! 008 Control field! 024 Data field! 028 Data field! 033 Data field! 033 Data field! 033 Data field! 033 Data field! 035 Data field! 040 Data field! 048 Data field! 110 Data field! 245 Data field! 260 Data field! 300 Data field! 440 Data field! 511 Data field! 518 Data field! 500 Data field! 500 Data field! 505 Data field! 650 Data field! 700 Data field! 700 Data field! 700 Data field! 700 Data field! 700 Data field! 852 Data field! PK!S3  "test/File_MARC/tests/marc_021.phptnu[--TEST-- marc_021: test MARC-in-JSON serialization with subfield 0 --SKIPIF-- --FILE-- next()) { // create some subfields $subfields[] = new File_MARC_Subfield('0', 'nothing'); $subfields[] = new File_MARC_Subfield('1', 'everything'); $field = new File_MARC_Data_Field('999', $subfields, '', ''); $marc_record->appendField($field); $subfields = null; $field = null; $subfields[] = new File_MARC_Subfield('a', 'bee'); $subfields[] = new File_MARC_Subfield('0', 'cee'); $subfields[] = new File_MARC_Subfield('d', 'eee'); $field = new File_MARC_Data_Field('999', $subfields, '', ''); $marc_record->appendField($field); print $marc_record->toJSON(); print "\n"; } ?> --EXPECT-- {"leader":"01850 2200517 4500","fields":[{"001":"0000000044"},{"003":"EMILDA"},{"008":"980120s1998 fi j 000 0 swe"},{"020":{"ind1":" ","ind2":" ","subfields":[{"a":"9515008808"},{"c":"FIM 72:00"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"9":"9515008808"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"NB"}]}},{"042":{"ind1":" ","ind2":" ","subfields":[{"9":"NB"},{"9":"SEE"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"a":"Hcd,u"},{"2":"kssb\/6"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"a":"uHc"},{"2":"kssb"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"a":"Hcf"},{"2":"kssb\/6"}]}},{"084":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"a":"Hcd,uf"},{"2":"kssb\/6"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"245":{"ind1":"0","ind2":"4","subfields":[{"a":"Det osynliga barnet och andra ber\u00e4ttelser \/"},{"c":"Tove Jansson"}]}},{"250":{"ind1":" ","ind2":" ","subfields":[{"a":"7. uppl."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Helsingfors :"},{"b":"Schildt,"},{"c":"1998 ;"},{"e":"(Falun :"},{"f":"Scandbook)"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"166, [4] s. :"},{"b":"ill. ;"},{"c":"21 cm"}]}},{"440":{"ind1":" ","ind2":"0","subfields":[{"a":"Mumin-biblioteket,"},{"x":"99-0698931-9"}]}},{"500":{"ind1":" ","ind2":" ","subfields":[{"a":"Originaluppl. 1962"}]}},{"599":{"ind1":" ","ind2":" ","subfields":[{"a":"Li: S"}]}},{"740":{"ind1":"4","ind2":" ","subfields":[{"a":"Det osynliga barnet"}]}},{"775":{"ind1":"1","ind2":" ","subfields":[{"z":"951-50-0385-7"},{"w":"9515003857"},{"9":"07"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"Li"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"L"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"841":{"ind1":" ","ind2":" ","subfields":[{"5":"S"},{"a":"xa"},{"b":"0201080u 0 4000uu |000000"},{"e":"1"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"NB"},{"b":"NB"},{"c":"NB98:12"},{"h":"plikt"},{"j":"R, 980520"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"Li"},{"b":"Li"},{"c":"CNB"},{"h":"h,u"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"SEE"},{"b":"SEE"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"Q"},{"b":"Q"},{"j":"98947"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"L"},{"b":"L"},{"c":"0100"},{"h":"98\/"},{"j":"3043 H"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"5":"S"},{"b":"S"},{"h":"Sv97"},{"j":"7235"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Yanson, Tobe,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janssonov\u00e1, Tove,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Jansone, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janson, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Jansson, Tuve,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"900":{"ind1":"1","ind2":"s","subfields":[{"a":"Janssonova, Tove,"},{"d":"1914-2001"},{"u":"Jansson, Tove,"},{"d":"1914-2001"}]}},{"976":{"ind1":" ","ind2":"2","subfields":[{"a":"Hcd,u"},{"b":"Sk\u00f6nlitteratur"}]}},{"005":"20050204111518.0"},{"999":{"ind1":" ","ind2":" ","subfields":[{"0":"nothing"},{"1":"everything"}]}},{"999":{"ind1":" ","ind2":" ","subfields":[{"a":"bee"},{"0":"cee"},{"d":"eee"}]}}]} PK!3ը+test/File_MARC/tests/marc_subfield_002.phptnu[--TEST-- marc_subfield_002: Exercise setter and isEmpty() methods for File_MARC_Subfield class --SKIPIF-- --FILE-- isEmpty()) { print "empty.\n"; } else { print "not empty.\n"; } } $subfield = new File_MARC_Subfield('a', 'wasssup'); // test isEmpty() scenarios testEmpty($subfield); $subfield->setData(null); testEmpty($subfield); $subfield->setData('just hangin'); testEmpty($subfield); // test setCode() scenarios print "\nSet code to 'z'..."; if ($subfield->setCode('z')) { print "\n"; print $subfield; } print "\nSet code to ''..."; if ($subfield->setCode('')) { print "\n"; print $subfield; } print "\nSet code to null..."; if ($subfield->setCode(null)) { print "\n"; print $subfield; } ?> --EXPECT-- Subfield is not empty. Subfield is empty. Subfield is not empty. Set code to 'z'... [z]: just hangin Set code to ''... Set code to null... PK!f==$test/File_MARC/tests/bad_example.mrcnu[01853 a2200517 450000100110000000300070001100800390001802000260005703500150008304000070009804200120010508400180011708400180013508400210015308400220017410000300019624500630022625000130028926000580030230-0033003604400037003935000023004305990010004537400024004637750034004878410048005218410049005698410047006188410048006658410047007138410047007608520038008078520021008458520013008668520016008798520028008958520021009239000056009449000061010009000057010619000056011189000057011749000060012319760027012910050017013180000000044EMILDA980120s1998 fi j 000 0 swe a9515008808cFIM 72:00 99515008808 aNB 9NB9SEE aHcd,u2kssb/6 5NBauHc2kssb 5SEEaHcf2kssb/6 5QaHcd,uf2kssb/61 aJansson, Tove,d1914-200104aDet osynliga barnet och andra bert̃telser /cTove Jansson a7. uppl. aHelsingfors :bSchildt,c1998 ;e(Falun :fScandbook) a166, [4] s. :bill. ;c21 cm 0aMumin-biblioteket,x99-0698931-9 aOriginaluppl. 1962 aLi: S4 aDet osynliga barnet1 z951-50-0385-7w9515003857907 5Liaxab0201080u 0 4000uu |000000e1 5SEEaxab0201080u 0 4000uu |000000e1 5Laxab0201080u 0 4000uu |000000e1 5NBaxab0201080u 0 4000uu |000000e1 5Qaxab0201080u 0 4000uu |000000e1 5Saxab0201080u 0 4000uu |000000e1 5NBbNBcNB98:12hpliktjR, 980520 5LibLicCNBhh,u 5SEEbSEE 5QbQj98947 5LbLc0100h98/j3043 H 5SbShSv97j72351saYanson, Tobe,d1914-2001uJansson, Tove,d1914-20011saJanssonov,̀ Tove,d1914-2001uJansson, Tove,d1914-20011saJansone, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJansson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanssonova, Tove,d1914-2001uJansson, Tove,d1914-2001 2aHcd,ubSkn̲litteratur20050204111518.0PK!kP"test/File_MARC/tests/marc_023.phptnu[--TEST-- marc_023: test extended Record interface --SKIPIF-- --FILE-- getField('040')->getSubfield('a')->getData(); } } $marc_file = new File_MARC($dir . '/' . 'example.mrc', File_MARC::SOURCE_FILE, MyRecord::class); $rec = $marc_file->next(); print get_class($rec) . "\n"; print $rec->myNewMethod() . "\n"; ?> --EXPECT-- MyRecord NB PK!Yz"test/File_MARC/tests/marc_019.phptnu[--TEST-- marc_019: generate a MARCXML record not in a collection element --SKIPIF-- --FILE-- next(); // Change each 852 $c to "Audio-Visual" $holdings = $record->getFields('852'); foreach ($holdings as $holding) { // Get the $c subfields from this field $formats = $holding->getSubfields('c'); foreach ($formats as $format) { if ($format->getData('AV')) { $format->setData('Audio-Visual'); } } } // Generate the XML output for this record print($record->toXML('UTF-8', true, true)); --EXPECT-- 01145ncm 2200277 i 4500 000073594 AAJ5802 20030415102100.0 801107s1977 nyujza 77771106 (CaOTUIC)15460184 AAJ5802 LC M1366 .M62 M1527.2 The Modern Jazz Quartet : The legendary profile. -- New York : M.J.Q. Music, c1977. score (72 p.) ; 31 cm. For piano, vibraphone, drums, and double bass. Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. Jazz. Motion picture music Excerpts Scores. Lewis, John, 1920- Selections. 1977. Jackson, Milt. Martyrs. 1977. Jackson, Milt. Legendary profile. 1977. The legendary profile. MUSIC Audio-Visual folio M1366 M62 1 Marvin Duchow Music PK!泮test/File_MARC/tests/music.mrcnu[01145ncm 2200277 i 4500001001000000004000800010005001700018008004100035010001700076035002200093035001200115040000700127050002500134245005700159260003800216300002800254500005100282505026600333650001000599650004400609700004400653700003600697700004600733740002700779852006100806000073594AAJ580220030415102100.0801107s1977 nyujza  a 77771106  a(CaOTUIC)154601849 aAAJ5802 aLC00aM1366b.M62dM1527.204aThe Modern Jazz Quartet :bThe legendary profile. -- aNew York :bM.J.Q. Music,cc1977. ascore (72 p.) ;c31 cm. aFor piano, vibraphone, drums, and double bass.0 aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 0aJazz. 0aMotion picture musicvExcerptsvScores.12aLewis, John,d1920-tSelections.f1977.12aJackson, Milt.tMartyrs.f1977.12aJackson, Milt.tLegendary profile.f1977.4 aThe legendary profile.00bMUSICcMAINkfoliohM1366iM62914Marvin Duchow Music5 01293cjm 2200289 a 450000100100000000500170001000700150002700800410004202400150008302800240009803500200012204000180014210000260016024500620018626000850024830000510033351101380038450000360052251800580055850000590061650000700067550501420074565000210088770000240090871000250093274000460095700187803920050110174900.0sd fungnn|||e|940202r19931981nyujzn i d1 a746457337202aJK 57337bRed Baron a(OCoLC)29737267 aSVPcSVPdLGG1 aDesmond, Paul,d1924-10aPaul Desmond & the Modern Jazz Quarteth[sound recording] aNew York, N.Y. :bRed Baron :bManufactured by Sony Music Entertainment,cp1993. a1 sound disc (39 min.) :bdigital ;c4 3/4 in.0 aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. aAll arrangements by John Lewis. aRecorded live on December 25, 1971 at Town Hall, NYC. aOriginally released in 1981 by Finesse as LP FW 27487. aProgram notes by Irving Townsend, June 1981, on container insert.0 aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 0aJazzy1971-1980.1 aLewis, John,d1920-2 aModern Jazz Quartet.0 aPaul Desmond and the Modern Jazz Quartet. 01829cjm 2200385 a 450000100100000000500170001000700150002700800410004202400150008302800210009803300240011903300230014303300230016603300230018903500200021204000230023204800270025511000300028224500530031226000330036530000410039844000170043951102230045651802640067950000180094350000220096150502500098365000100123370000240124370000330126770000330130070000220133370000300135585200580138500196448220060626132700.0sd fzngnn|m|e|871211p19871957nyujzn d1 a422833290201a833 290-2bVerve0 a19571027b6299cD560 a196112--b3804cN40 a19571019b4104cC60 a197107--b6299cV7 a(OCoLC)17222092 aCPLcCPLdOCLdLGG apz01aka01asd01apd012 aModern Jazz Quartet.4prf14aThe Modern Jazz Quartet plush[sound recording]. a[New York] :bVerve,cp1987. a1 sound disc :bdigital ;c4 3/4 in. 0aCompact jazz0 aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). aCompact disc. aAnalog recording.0 aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 0aJazz.1 aJackson, Milt.4prf1 aPeterson, Oscar,d1925-4prf1 aBrown, Ray,d1926-2002.4prf1 aThigpen, Ed.4prf1 aHayes, Louis,d1937-4prf80bMUSICcAVhCD 11314Marvin Duchow Music5Audio-Visual PK! < "test/File_MARC/tests/marc_001.phptnu[--TEST-- marc_001: iterate and pretty print a MARC record --SKIPIF-- --FILE-- next()) { print $marc_record; print "\n"; } ?> --EXPECT-- LDR 01850 2200517 4500 001 0000000044 003 EMILDA 008 980120s1998 fi j 000 0 swe 020 _a9515008808 _cFIM 72:00 035 _99515008808 040 _aNB 042 _9NB _9SEE 084 _aHcd,u _2kssb/6 084 _5NB _auHc _2kssb 084 _5SEE _aHcf _2kssb/6 084 _5Q _aHcd,uf _2kssb/6 100 1 _aJansson, Tove, _d1914-2001 245 04 _aDet osynliga barnet och andra berttelser / _cTove Jansson 250 _a7. uppl. 260 _aHelsingfors : _bSchildt, _c1998 ; _e(Falun : _fScandbook) 300 _a166, [4] s. : _bill. ; _c21 cm 440 0 _aMumin-biblioteket, _x99-0698931-9 500 _aOriginaluppl. 1962 599 _aLi: S 740 4 _aDet osynliga barnet 775 1 _z951-50-0385-7 _w9515003857 _907 841 _5Li _axa _b0201080u 0 4000uu |000000 _e1 841 _5SEE _axa _b0201080u 0 4000uu |000000 _e1 841 _5L _axa _b0201080u 0 4000uu |000000 _e1 841 _5NB _axa _b0201080u 0 4000uu |000000 _e1 841 _5Q _axa _b0201080u 0 4000uu |000000 _e1 841 _5S _axa _b0201080u 0 4000uu |000000 _e1 852 _5NB _bNB _cNB98:12 _hplikt _jR, 980520 852 _5Li _bLi _cCNB _hh,u 852 _5SEE _bSEE 852 _5Q _bQ _j98947 852 _5L _bL _c0100 _h98/ _j3043 H 852 _5S _bS _hSv97 _j7235 900 1s _aYanson, Tobe, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonov, Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansone, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonova, Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 976 2 _aHcd,u _bSknlitteratur 005 20050204111518.0 PK!#" ) )"test/File_MARC/tests/marc_022.phptnu[--TEST-- marc_022: Insert fields --SKIPIF-- --FILE-- next()) { print "\nNext record:\n"; // Create the new field $subfields = null; $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.'); $new_field = new File_MARC_Data_Field('100', $subfields, 0, null); // Retrieve the target field for our insertion point $subject = $record->getFields('650'); // Insert the new field if (is_array($subject)) { $record->insertField($new_field, $subject[0], true); } elseif ($subject) { $record->insertField($new_field, $subject, true); } print $record; } $record = null; $marc_file = new File_MARC($dir . '/' . 'music.mrc'); print "\nInsert a new 100 field after the first 650\n"; while ($record = $marc_file->next()) { print "\nNext record:\n"; // Create the new field $subfields = null; $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.'); $new_field = new File_MARC_Data_Field('100', $subfields, 0, null); // Retrieve the target field for our insertion point $subject = $record->getFields('650'); // Insert the new field if (is_array($subject)) { $record->insertField($new_field, $subject[0]); } elseif ($subject) { $record->insertField($new_field, $subject); } print $record; } ?> --EXPECT-- Insert a new 100 field before the first 650 Next record: LDR 01145ncm 2200277 i 4500 001 000073594 004 AAJ5802 005 20030415102100.0 008 801107s1977 nyujza 010 _a 77771106 035 _a(CaOTUIC)15460184 035 9 _aAAJ5802 040 _aLC 050 00 _aM1366 _b.M62 _dM1527.2 245 04 _aThe Modern Jazz Quartet : _bThe legendary profile. -- 260 _aNew York : _bM.J.Q. Music, _cc1977. 300 _ascore (72 p.) ; _c31 cm. 500 _aFor piano, vibraphone, drums, and double bass. 505 0 _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 100 _aScott, Daniel. 650 0 _aJazz. 650 0 _aMotion picture music _vExcerpts _vScores. 700 12 _aLewis, John, _d1920- _tSelections. _f1977. 700 12 _aJackson, Milt. _tMartyrs. _f1977. 700 12 _aJackson, Milt. _tLegendary profile. _f1977. 740 4 _aThe legendary profile. 852 00 _bMUSIC _cMAIN _kfolio _hM1366 _iM62 _91 _4Marvin Duchow Music _5 Next record: LDR 01293cjm 2200289 a 4500 001 001878039 005 20050110174900.0 007 sd fungnn|||e| 008 940202r19931981nyujzn i d 024 1 _a7464573372 028 02 _aJK 57337 _bRed Baron 035 _a(OCoLC)29737267 040 _aSVP _cSVP _dLGG 100 1 _aDesmond, Paul, _d1924- 245 10 _aPaul Desmond & the Modern Jazz Quartet _h[sound recording] 260 _aNew York, N.Y. : _bRed Baron : _bManufactured by Sony Music Entertainment, _cp1993. 300 _a1 sound disc (39 min.) : _bdigital ; _c4 3/4 in. 511 0 _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. 500 _aAll arrangements by John Lewis. 518 _aRecorded live on December 25, 1971 at Town Hall, NYC. 500 _aOriginally released in 1981 by Finesse as LP FW 27487. 500 _aProgram notes by Irving Townsend, June 1981, on container insert. 505 0 _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 100 _aScott, Daniel. 650 0 _aJazz _y1971-1980. 700 1 _aLewis, John, _d1920- 710 2 _aModern Jazz Quartet. 740 0 _aPaul Desmond and the Modern Jazz Quartet. Next record: LDR 01829cjm 2200385 a 4500 001 001964482 005 20060626132700.0 007 sd fzngnn|m|e| 008 871211p19871957nyujzn d 024 1 _a4228332902 028 01 _a833 290-2 _bVerve 033 0 _a19571027 _b6299 _cD56 033 0 _a196112-- _b3804 _cN4 033 0 _a19571019 _b4104 _cC6 033 0 _a197107-- _b6299 _cV7 035 _a(OCoLC)17222092 040 _aCPL _cCPL _dOCL _dLGG 048 _apz01 _aka01 _asd01 _apd01 110 2 _aModern Jazz Quartet. _4prf 245 14 _aThe Modern Jazz Quartet plus _h[sound recording]. 260 _a[New York] : _bVerve, _cp1987. 300 _a1 sound disc : _bdigital ; _c4 3/4 in. 440 0 _aCompact jazz 511 0 _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. 518 _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). 500 _aCompact disc. 500 _aAnalog recording. 505 0 _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 100 _aScott, Daniel. 650 0 _aJazz. 700 1 _aJackson, Milt. _4prf 700 1 _aPeterson, Oscar, _d1925- _4prf 700 1 _aBrown, Ray, _d1926-2002. _4prf 700 1 _aThigpen, Ed. _4prf 700 1 _aHayes, Louis, _d1937- _4prf 852 80 _bMUSIC _cAV _hCD 1131 _4Marvin Duchow Music _5Audio-Visual Insert a new 100 field after the first 650 Next record: LDR 01145ncm 2200277 i 4500 001 000073594 004 AAJ5802 005 20030415102100.0 008 801107s1977 nyujza 010 _a 77771106 035 _a(CaOTUIC)15460184 035 9 _aAAJ5802 040 _aLC 050 00 _aM1366 _b.M62 _dM1527.2 245 04 _aThe Modern Jazz Quartet : _bThe legendary profile. -- 260 _aNew York : _bM.J.Q. Music, _cc1977. 300 _ascore (72 p.) ; _c31 cm. 500 _aFor piano, vibraphone, drums, and double bass. 505 0 _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 650 0 _aJazz. 100 _aScott, Daniel. 650 0 _aMotion picture music _vExcerpts _vScores. 700 12 _aLewis, John, _d1920- _tSelections. _f1977. 700 12 _aJackson, Milt. _tMartyrs. _f1977. 700 12 _aJackson, Milt. _tLegendary profile. _f1977. 740 4 _aThe legendary profile. 852 00 _bMUSIC _cMAIN _kfolio _hM1366 _iM62 _91 _4Marvin Duchow Music _5 Next record: LDR 01293cjm 2200289 a 4500 001 001878039 005 20050110174900.0 007 sd fungnn|||e| 008 940202r19931981nyujzn i d 024 1 _a7464573372 028 02 _aJK 57337 _bRed Baron 035 _a(OCoLC)29737267 040 _aSVP _cSVP _dLGG 100 1 _aDesmond, Paul, _d1924- 245 10 _aPaul Desmond & the Modern Jazz Quartet _h[sound recording] 260 _aNew York, N.Y. : _bRed Baron : _bManufactured by Sony Music Entertainment, _cp1993. 300 _a1 sound disc (39 min.) : _bdigital ; _c4 3/4 in. 511 0 _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. 500 _aAll arrangements by John Lewis. 518 _aRecorded live on December 25, 1971 at Town Hall, NYC. 500 _aOriginally released in 1981 by Finesse as LP FW 27487. 500 _aProgram notes by Irving Townsend, June 1981, on container insert. 505 0 _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 650 0 _aJazz _y1971-1980. 100 _aScott, Daniel. 700 1 _aLewis, John, _d1920- 710 2 _aModern Jazz Quartet. 740 0 _aPaul Desmond and the Modern Jazz Quartet. Next record: LDR 01829cjm 2200385 a 4500 001 001964482 005 20060626132700.0 007 sd fzngnn|m|e| 008 871211p19871957nyujzn d 024 1 _a4228332902 028 01 _a833 290-2 _bVerve 033 0 _a19571027 _b6299 _cD56 033 0 _a196112-- _b3804 _cN4 033 0 _a19571019 _b4104 _cC6 033 0 _a197107-- _b6299 _cV7 035 _a(OCoLC)17222092 040 _aCPL _cCPL _dOCL _dLGG 048 _apz01 _aka01 _asd01 _apd01 110 2 _aModern Jazz Quartet. _4prf 245 14 _aThe Modern Jazz Quartet plus _h[sound recording]. 260 _a[New York] : _bVerve, _cp1987. 300 _a1 sound disc : _bdigital ; _c4 3/4 in. 440 0 _aCompact jazz 511 0 _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. 518 _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). 500 _aCompact disc. 500 _aAnalog recording. 505 0 _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 650 0 _aJazz. 100 _aScott, Daniel. 700 1 _aJackson, Milt. _4prf 700 1 _aPeterson, Oscar, _d1925- _4prf 700 1 _aBrown, Ray, _d1926-2002. _4prf 700 1 _aThigpen, Ed. _4prf 700 1 _aHayes, Louis, _d1937- _4prf 852 80 _bMUSIC _cAV _hCD 1131 _4Marvin Duchow Music _5Audio-Visual PK! --FILE-- element $records->toXMLHeader(); // Iterate through the retrieved records while ($record = $records->next()) { // Change each 852 $c to "Audio-Visual" $holdings = $record->getFields('852'); foreach ($holdings as $holding) { // Get the $c subfields from this field $formats = $holding->getSubfields('c'); foreach ($formats as $format) { if ($format->getData('AV')) { $format->setData('Audio-Visual'); } } } // Generate the XML output for this record print $record->toXML('UTF-8', true, false); } // Add the closing element and dump the XMLWriter contents print $records->toXMLFooter(); --EXPECT-- 01145ncm 2200277 i 4500 000073594 AAJ5802 20030415102100.0 801107s1977 nyujza 77771106 (CaOTUIC)15460184 AAJ5802 LC M1366 .M62 M1527.2 The Modern Jazz Quartet : The legendary profile. -- New York : M.J.Q. Music, c1977. score (72 p.) ; 31 cm. For piano, vibraphone, drums, and double bass. Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. Jazz. Motion picture music Excerpts Scores. Lewis, John, 1920- Selections. 1977. Jackson, Milt. Martyrs. 1977. Jackson, Milt. Legendary profile. 1977. The legendary profile. MUSIC Audio-Visual folio M1366 M62 1 Marvin Duchow Music 01293cjm 2200289 a 4500 001878039 20050110174900.0 sd fungnn|||e| 940202r19931981nyujzn i d 7464573372 JK 57337 Red Baron (OCoLC)29737267 SVP SVP LGG Desmond, Paul, 1924- Paul Desmond & the Modern Jazz Quartet [sound recording] New York, N.Y. : Red Baron : Manufactured by Sony Music Entertainment, p1993. 1 sound disc (39 min.) : digital ; 4 3/4 in. Paul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. All arrangements by John Lewis. Recorded live on December 25, 1971 at Town Hall, NYC. Originally released in 1981 by Finesse as LP FW 27487. Program notes by Irving Townsend, June 1981, on container insert. Greensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. Jazz 1971-1980. Lewis, John, 1920- Modern Jazz Quartet. Paul Desmond and the Modern Jazz Quartet. 01829cjm 2200385 a 4500 001964482 20060626132700.0 sd fzngnn|m|e| 871211p19871957nyujzn d 4228332902 833 290-2 Verve 19571027 6299 D56 196112-- 3804 N4 19571019 4104 C6 197107-- 6299 V7 (OCoLC)17222092 CPL CPL OCL LGG pz01 ka01 sd01 pd01 Modern Jazz Quartet. prf The Modern Jazz Quartet plus [sound recording]. [New York] : Verve, p1987. 1 sound disc : digital ; 4 3/4 in. Compact jazz Modern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. Recorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). Compact disc. Analog recording. The golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). Jazz. Jackson, Milt. prf Peterson, Oscar, 1925- prf Brown, Ray, 1926-2002. prf Thigpen, Ed. prf Hayes, Louis, 1937- prf MUSIC Audio-Visual CD 1131 Marvin Duchow Music Audio-Visual PK!% :!:!"test/File_MARC/tests/marc_013.phptnu[--TEST-- marc_013: test formatField() convenience method --SKIPIF-- --FILE-- next()) { $fields = $marc_record->getFields(); foreach ($fields as $field) { print $field; print "\n"; print $field->formatField(); print "\n"; print $field->formatField(array('a', '2', 'c')); print "\n"; } } ?> --EXPECT-- 001 000073594 000073594 000073594 004 AAJ5802 AAJ5802 AAJ5802 005 20030415102100.0 20030415102100.0 20030415102100.0 008 801107s1977 nyujza 801107s1977 nyujza 801107s1977 nyujza 010 _a 77771106 77771106 035 _a(CaOTUIC)15460184 (CaOTUIC)15460184 035 9 _aAAJ5802 AAJ5802 040 _aLC LC 050 00 _aM1366 _b.M62 _dM1527.2 M1366 .M62 M1527.2 .M62 M1527.2 245 04 _aThe Modern Jazz Quartet : _bThe legendary profile. -- The Modern Jazz Quartet : The legendary profile. -- The legendary profile. -- 260 _aNew York : _bM.J.Q. Music, _cc1977. New York : M.J.Q. Music, c1977. M.J.Q. Music, 300 _ascore (72 p.) ; _c31 cm. score (72 p.) ; 31 cm. 500 _aFor piano, vibraphone, drums, and double bass. For piano, vibraphone, drums, and double bass. 505 0 _aLewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. Lewis, J. Django.--Lewis, J. Plastic dreams (music from the film Kemek).--Lewis, J. Dancing (music from the film Kemek).--Lewis, J. Blues in A minor.--Lewis, J. Blues in B♭.--Lewis, J. Precious joy.--Jackson, M. The martyr.--Jackson, M. The legendary profile. 650 0 _aJazz. Jazz. 650 0 _aMotion picture music _vExcerpts _vScores. Motion picture music -- Excerpts -- Scores. -- Excerpts -- Scores. 700 12 _aLewis, John, _d1920- _tSelections. _f1977. Lewis, John, 1920- Selections. 1977. 1920- Selections. 1977. 700 12 _aJackson, Milt. _tMartyrs. _f1977. Jackson, Milt. Martyrs. 1977. Martyrs. 1977. 700 12 _aJackson, Milt. _tLegendary profile. _f1977. Jackson, Milt. Legendary profile. 1977. Legendary profile. 1977. 740 4 _aThe legendary profile. The legendary profile. 852 00 _bMUSIC _cMAIN _kfolio _hM1366 _iM62 _91 _4Marvin Duchow Music _5 MUSIC MAIN folio M1366 M62 1 Marvin Duchow Music MUSIC folio M1366 M62 1 Marvin Duchow Music 001 001878039 001878039 001878039 005 20050110174900.0 20050110174900.0 20050110174900.0 007 sd fungnn|||e| sd fungnn|||e| sd fungnn|||e| 008 940202r19931981nyujzn i d 940202r19931981nyujzn i d 940202r19931981nyujzn i d 024 1 _a7464573372 7464573372 028 02 _aJK 57337 _bRed Baron JK 57337 Red Baron Red Baron 035 _a(OCoLC)29737267 (OCoLC)29737267 040 _aSVP _cSVP _dLGG SVP SVP LGG LGG 100 1 _aDesmond, Paul, _d1924- Desmond, Paul, 1924- 1924- 245 10 _aPaul Desmond & the Modern Jazz Quartet _h[sound recording] Paul Desmond & the Modern Jazz Quartet [sound recording] [sound recording] 260 _aNew York, N.Y. : _bRed Baron : _bManufactured by Sony Music Entertainment, _cp1993. New York, N.Y. : Red Baron : Manufactured by Sony Music Entertainment, p1993. Red Baron : Manufactured by Sony Music Entertainment, 300 _a1 sound disc (39 min.) : _bdigital ; _c4 3/4 in. 1 sound disc (39 min.) : digital ; 4 3/4 in. digital ; 511 0 _aPaul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. Paul Desmond, alto saxophone; Modern Jazz Quartet: John Lewis, piano; Milt Jackson, vibraphone; Percy Heath, bass; Connie Kay, drums. 500 _aAll arrangements by John Lewis. All arrangements by John Lewis. 518 _aRecorded live on December 25, 1971 at Town Hall, NYC. Recorded live on December 25, 1971 at Town Hall, NYC. 500 _aOriginally released in 1981 by Finesse as LP FW 27487. Originally released in 1981 by Finesse as LP FW 27487. 500 _aProgram notes by Irving Townsend, June 1981, on container insert. Program notes by Irving Townsend, June 1981, on container insert. 505 0 _aGreensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. Greensleeves -- You go to my head -- Blue dove -- Jesus Christ Superstar -- Here's that rainy day -- East of the sun -- Bags' new groove. 650 0 _aJazz _y1971-1980. Jazz -- 1971-1980. -- 1971-1980. 700 1 _aLewis, John, _d1920- Lewis, John, 1920- 1920- 710 2 _aModern Jazz Quartet. Modern Jazz Quartet. 740 0 _aPaul Desmond and the Modern Jazz Quartet. Paul Desmond and the Modern Jazz Quartet. 001 001964482 001964482 001964482 005 20060626132700.0 20060626132700.0 20060626132700.0 007 sd fzngnn|m|e| sd fzngnn|m|e| sd fzngnn|m|e| 008 871211p19871957nyujzn d 871211p19871957nyujzn d 871211p19871957nyujzn d 024 1 _a4228332902 4228332902 028 01 _a833 290-2 _bVerve 833 290-2 Verve Verve 033 0 _a19571027 _b6299 _cD56 19571027 6299 D56 6299 033 0 _a196112-- _b3804 _cN4 196112-- 3804 N4 3804 033 0 _a19571019 _b4104 _cC6 19571019 4104 C6 4104 033 0 _a197107-- _b6299 _cV7 197107-- 6299 V7 6299 035 _a(OCoLC)17222092 (OCoLC)17222092 040 _aCPL _cCPL _dOCL _dLGG CPL CPL OCL LGG OCL LGG 048 _apz01 _aka01 _asd01 _apd01 pz01 ka01 sd01 pd01 110 2 _aModern Jazz Quartet. _4prf Modern Jazz Quartet. prf prf 245 14 _aThe Modern Jazz Quartet plus _h[sound recording]. The Modern Jazz Quartet plus [sound recording]. [sound recording]. 260 _a[New York] : _bVerve, _cp1987. [New York] : Verve, p1987. Verve, 300 _a1 sound disc : _bdigital ; _c4 3/4 in. 1 sound disc : digital ; 4 3/4 in. digital ; 440 0 _aCompact jazz Compact jazz 511 0 _aModern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. Modern Jazz Quartet (principally) ; Milt Jackson, vibraphone (2nd and 8th works) ; Oscar Peterson, piano (2nd and 8th works) ; Ray Brown, bass (2nd and 8th works) ; Ed Thigpen (2nd work), Louis Hayes (8th work), drums. 518 _aRecorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). Recorded live, Oct. 27, 1957, at the Donaueschingen Jazz Festival (1st, 5th, 7th, and 10th works); Dec. 1961, in New York (2nd work); live, Oct. 19, 1957, at the Opera House, Chicago (3rd, 4th, 6th, and 9th works); July 1971, in Villingen, Germany (8th work). 500 _aCompact disc. Compact disc. 500 _aAnalog recording. Analog recording. 505 0 _aThe golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). The golden striker (4:08) -- On Green Dolphin Street (7:28) -- D & E (4:55) -- I'll remember April (4:51) -- Cortège (7:15) -- Now's the time (4:43) -- J.B. blues (5:09) -- Reunion blues (6:35) -- 'Round midnight (3:56) -- Three windows (7:20). 650 0 _aJazz. Jazz. 700 1 _aJackson, Milt. _4prf Jackson, Milt. prf prf 700 1 _aPeterson, Oscar, _d1925- _4prf Peterson, Oscar, 1925- prf 1925- prf 700 1 _aBrown, Ray, _d1926-2002. _4prf Brown, Ray, 1926-2002. prf 1926-2002. prf 700 1 _aThigpen, Ed. _4prf Thigpen, Ed. prf prf 700 1 _aHayes, Louis, _d1937- _4prf Hayes, Louis, 1937- prf 1937- prf 852 80 _bMUSIC _cAV _hCD 1131 _4Marvin Duchow Music _5Audio-Visual MUSIC AV CD 1131 Marvin Duchow Music Audio-Visual MUSIC CD 1131 Marvin Duchow Music Audio-Visual PK!b "test/File_MARC/tests/marc_011.phptnu[--TEST-- marc_011: iterate and pretty print a MARC record (SOURCE_STRING) --SKIPIF-- --FILE-- next()) { print $marc_record; print "\n"; } ?> --EXPECT-- LDR 01850 2200517 4500 001 0000000044 003 EMILDA 008 980120s1998 fi j 000 0 swe 020 _a9515008808 _cFIM 72:00 035 _99515008808 040 _aNB 042 _9NB _9SEE 084 _aHcd,u _2kssb/6 084 _5NB _auHc _2kssb 084 _5SEE _aHcf _2kssb/6 084 _5Q _aHcd,uf _2kssb/6 100 1 _aJansson, Tove, _d1914-2001 245 04 _aDet osynliga barnet och andra berttelser / _cTove Jansson 250 _a7. uppl. 260 _aHelsingfors : _bSchildt, _c1998 ; _e(Falun : _fScandbook) 300 _a166, [4] s. : _bill. ; _c21 cm 440 0 _aMumin-biblioteket, _x99-0698931-9 500 _aOriginaluppl. 1962 599 _aLi: S 740 4 _aDet osynliga barnet 775 1 _z951-50-0385-7 _w9515003857 _907 841 _5Li _axa _b0201080u 0 4000uu |000000 _e1 841 _5SEE _axa _b0201080u 0 4000uu |000000 _e1 841 _5L _axa _b0201080u 0 4000uu |000000 _e1 841 _5NB _axa _b0201080u 0 4000uu |000000 _e1 841 _5Q _axa _b0201080u 0 4000uu |000000 _e1 841 _5S _axa _b0201080u 0 4000uu |000000 _e1 852 _5NB _bNB _cNB98:12 _hplikt _jR, 980520 852 _5Li _bLi _cCNB _hh,u 852 _5SEE _bSEE 852 _5Q _bQ _j98947 852 _5L _bL _c0100 _h98/ _j3043 H 852 _5S _bS _hSv97 _j7235 900 1s _aYanson, Tobe, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonov, Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansone, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJansson, Tuve, _d1914-2001 _uJansson, Tove, _d1914-2001 900 1s _aJanssonova, Tove, _d1914-2001 _uJansson, Tove, _d1914-2001 976 2 _aHcd,u _bSknlitteratur 005 20050204111518.0 PK!h&test/File_MARC/tests/marc_xml_003.phptnu[--TEST-- marc_xml_003: Round-trip a MARCXML record to MARC21 (LOC standard) --SKIPIF-- --FILE-- next()) { print $marc_record->toRaw(); } ?> --EXPECT-- 01142cam 2200301 a 4500001001300000003000400013005001700017008004100034010001700075020002500092040001800117042000900135050002600144082001600170100003200186245008600218250001200304260005200316300004900368500004000417520022800457650003300685650003300718650002400751650002100775650002300796700002100819 92005291 DLC19930521155141.9920219s1993 caua j 000 0 eng  a 92005291  a0152038655 :c$15.95 aDLCcDLCdDLC alcac00aPS3537.A618bA88 199300a811/.522201 aSandburg, Carl,d1878-1967.10aArithmetic /cCarl Sandburg ; illustrated as an anamorphic adventure by Ted Rand. a1st ed. aSan Diego :bHarcourt Brace Jovanovich,cc1993. a1 v. (unpaged) :bill. (some col.) ;c26 cm. aOne Mylar sheet included in pocket. aA poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone. 0aArithmeticxJuvenile poetry. 0aChildren's poetry, American. 1aArithmeticxPoetry. 1aAmerican poetry. 1aVisual perception.1 aRand, Ted,eill. PK!f&test/File_MARC/tests/marc_xml_002.phptnu[--TEST-- marc_xml_002: iterate and pretty print a MARC record (LOC standard) --SKIPIF-- --FILE-- next()) { print $marc_record->toXML(); print "\n"; } ?> --EXPECT-- 01142cam 2200301 a 4500 92005291 DLC 19930521155141.9 920219s1993 caua j 000 0 eng 92005291 0152038655 : $15.95 DLC DLC DLC lcac PS3537.A618 A88 1993 811/.52 20 Sandburg, Carl, 1878-1967. Arithmetic / Carl Sandburg ; illustrated as an anamorphic adventure by Ted Rand. 1st ed. San Diego : Harcourt Brace Jovanovich, c1993. 1 v. (unpaged) : ill. (some col.) ; 26 cm. One Mylar sheet included in pocket. A poem about numbers and their characteristics. Features anamorphic, or distorted, drawings which can be restored to normal by viewing from a particular angle or by viewing the image's reflection in the provided Mylar cone. Arithmetic Juvenile poetry. Children's poetry, American. Arithmetic Poetry. American poetry. Visual perception. Rand, Ted, ill. PK!B 'test/File_MARC/tests/marc_lint_003.phptnu[--TEST-- marc_lint_003: Tests for field 880 and for subfield 6 --SKIPIF-- --FILE-- setLeader("00000nam 22002538a 4500"); $rec->appendField( new File_MARC_Control_Field( '001', 'ttt07000001 ' ) ); $rec->appendField( new File_MARC_Control_Field( '003', 'TEST ' ) ); $rec->appendField( new File_MARC_Control_Field( '008', '070520s2007 ilu 000 0 eng d' ) ); $rec->appendField( new File_MARC_Data_Field( '040', array( new File_MARC_Subfield('a', 'TEST'), new File_MARC_Subfield('c', 'TEST') ), "", "" ) ); $rec->appendField( new File_MARC_Data_Field( '050', array( new File_MARC_Subfield('a', 'RZ999'), new File_MARC_Subfield('b', '.J66 2007') ), "", "4" ) ); $rec->appendField( new File_MARC_Data_Field( '082', array( new File_MARC_Subfield('a', '615.8/9'), new File_MARC_Subfield('2', '22') ), "0", "4" ) ); $rec->appendField( new File_MARC_Data_Field( '100', array( new File_MARC_Subfield('a', 'Jones, John') ), "1", "" ) ); $rec->appendField( new File_MARC_Data_Field( '245', array( new File_MARC_Subfield('6', '880-02'), new File_MARC_Subfield('a', 'Test 880.') ), "1", "0" ) ); $rec->appendField( new File_MARC_Data_Field( '260', array( new File_MARC_Subfield('a', 'Mount Morris, Ill. :'), new File_MARC_Subfield('b', "B. Baldus,"), new File_MARC_Subfield('c', '2007.') ), "", "" ) ); $rec->appendField( new File_MARC_Data_Field( '300', array( new File_MARC_Subfield('a', '1 v. ;'), new File_MARC_Subfield('c', '23 cm.') ), "", "" ) ); $rec->appendField( new File_MARC_Data_Field( '880', array( new File_MARC_Subfield('6', '245-02/$1'), new File_MARC_Subfield('a', '.') ), "1", "0" ) ); $rec->appendField( new File_MARC_Data_Field( '880', array( new File_MARC_Subfield('6', '245-02/$1'), new File_MARC_Subfield('a', 'Illegal duplicate field.') ), "1", "0" ) ); $warnings = $marc_lint->checkRecord($rec); foreach ($warnings as $warning) { print $warning . "\n"; } ?> --EXPECT-- 245: Field is not repeatable. PK�������!�'7,������PEAR.phpnu�[��������<?php /** * PEAR, the PHP Extension and Application Repository * * PEAR class and PEAR_Error class * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Sterling Hughes <sterling@php.net> * @author Stig Bakken <ssb@php.net> * @author Tomas V.V.Cox <cox@idecnet.com> * @author Greg Beaver <cellog@php.net> * @copyright 1997-2010 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /**#@+ * ERROR constants */ define('PEAR_ERROR_RETURN', 1); define('PEAR_ERROR_PRINT', 2); define('PEAR_ERROR_TRIGGER', 4); define('PEAR_ERROR_DIE', 8); define('PEAR_ERROR_CALLBACK', 16); /** * WARNING: obsolete * @deprecated */ define('PEAR_ERROR_EXCEPTION', 32); /**#@-*/ if (substr(PHP_OS, 0, 3) == 'WIN') { define('OS_WINDOWS', true); define('OS_UNIX', false); define('PEAR_OS', 'Windows'); } else { define('OS_WINDOWS', false); define('OS_UNIX', true); define('PEAR_OS', 'Unix'); // blatant assumption } $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; $GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; $GLOBALS['_PEAR_destructor_object_list'] = array(); $GLOBALS['_PEAR_shutdown_funcs'] = array(); $GLOBALS['_PEAR_error_handler_stack'] = array(); if(function_exists('ini_set')) { @ini_set('track_errors', true); } /** * Base class for other PEAR classes. Provides rudimentary * emulation of destructors. * * If you want a destructor in your class, inherit PEAR and make a * destructor method called _yourclassname (same name as the * constructor, but with a "_" prefix). Also, in your constructor you * have to call the PEAR constructor: $this->PEAR();. * The destructor method will be called without parameters. Note that * at in some SAPI implementations (such as Apache), any output during * the request shutdown (in which destructors are called) seems to be * discarded. If you need to get any debug information from your * destructor, use error_log(), syslog() or something similar. * * IMPORTANT! To use the emulated destructors you need to create the * objects by reference: $obj =& new PEAR_child; * * @category pear * @package PEAR * @author Stig Bakken <ssb@php.net> * @author Tomas V.V. Cox <cox@idecnet.com> * @author Greg Beaver <cellog@php.net> * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @see PEAR_Error * @since Class available since PHP 4.0.2 * @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear */ class PEAR { /** * Whether to enable internal debug messages. * * @var bool * @access private */ var $_debug = false; /** * Default error mode for this object. * * @var int * @access private */ var $_default_error_mode = null; /** * Default error options used for this object when error mode * is PEAR_ERROR_TRIGGER. * * @var int * @access private */ var $_default_error_options = null; /** * Default error handler (callback) for this object, if error mode is * PEAR_ERROR_CALLBACK. * * @var string * @access private */ var $_default_error_handler = ''; /** * Which class to use for error objects. * * @var string * @access private */ var $_error_class = 'PEAR_Error'; /** * An array of expected errors. * * @var array * @access private */ var $_expected_errors = array(); /** * List of methods that can be called both statically and non-statically. * @var array */ protected static $bivalentMethods = array( 'setErrorHandling' => true, 'raiseError' => true, 'throwError' => true, 'pushErrorHandling' => true, 'popErrorHandling' => true, ); /** * Constructor. Registers this object in * $_PEAR_destructor_object_list for destructor emulation if a * destructor object exists. * * @param string $error_class (optional) which class to use for * error objects, defaults to PEAR_Error. * @access public * @return void */ function __construct($error_class = null) { $classname = strtolower(get_class($this)); if ($this->_debug) { print "PEAR constructor called, class=$classname\n"; } if ($error_class !== null) { $this->_error_class = $error_class; } while ($classname && strcasecmp($classname, "pear")) { $destructor = "_$classname"; if (method_exists($this, $destructor)) { global $_PEAR_destructor_object_list; $_PEAR_destructor_object_list[] = $this; if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { register_shutdown_function("_PEAR_call_destructors"); $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; } break; } else { $classname = get_parent_class($classname); } } } /** * Only here for backwards compatibility. * E.g. Archive_Tar calls $this->PEAR() in its constructor. * * @param string $error_class Which class to use for error objects, * defaults to PEAR_Error. */ public function PEAR($error_class = null) { self::__construct($error_class); } /** * Destructor (the emulated type of...). Does nothing right now, * but is included for forward compatibility, so subclass * destructors should always call it. * * See the note in the class desciption about output from * destructors. * * @access public * @return void */ function _PEAR() { if ($this->_debug) { printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); } } public function __call($method, $arguments) { if (!isset(self::$bivalentMethods[$method])) { trigger_error( 'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR ); } return call_user_func_array( array(__CLASS__, '_' . $method), array_merge(array($this), $arguments) ); } public static function __callStatic($method, $arguments) { if (!isset(self::$bivalentMethods[$method])) { trigger_error( 'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR ); } return call_user_func_array( array(__CLASS__, '_' . $method), array_merge(array(null), $arguments) ); } /** * If you have a class that's mostly/entirely static, and you need static * properties, you can use this method to simulate them. Eg. in your method(s) * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar'); * You MUST use a reference, or they will not persist! * * @param string $class The calling classname, to prevent clashes * @param string $var The variable to retrieve. * @return mixed A reference to the variable. If not set it will be * auto initialised to NULL. */ public static function &getStaticProperty($class, $var) { static $properties; if (!isset($properties[$class])) { $properties[$class] = array(); } if (!array_key_exists($var, $properties[$class])) { $properties[$class][$var] = null; } return $properties[$class][$var]; } /** * Use this function to register a shutdown method for static * classes. * * @param mixed $func The function name (or array of class/method) to call * @param mixed $args The arguments to pass to the function * * @return void */ public static function registerShutdownFunc($func, $args = array()) { // if we are called statically, there is a potential // that no shutdown func is registered. Bug #6445 if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { register_shutdown_function("_PEAR_call_destructors"); $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; } $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); } /** * Tell whether a value is a PEAR error. * * @param mixed $data the value to test * @param int $code if $data is an error object, return true * only if $code is a string and * $obj->getMessage() == $code or * $code is an integer and $obj->getCode() == $code * * @return bool true if parameter is an error */ public static function isError($data, $code = null) { if (!is_a($data, 'PEAR_Error')) { return false; } if (is_null($code)) { return true; } elseif (is_string($code)) { return $data->getMessage() == $code; } return $data->getCode() == $code; } /** * Sets how errors generated by this object should be handled. * Can be invoked both in objects and statically. If called * statically, setErrorHandling sets the default behaviour for all * PEAR objects. If called in an object, setErrorHandling sets * the default behaviour for that object. * * @param object $object * Object the method was called on (non-static mode) * * @param int $mode * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION. * * @param mixed $options * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). * * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected * to be the callback function or method. A callback * function is a string with the name of the function, a * callback method is an array of two elements: the element * at index 0 is the object, and the element at index 1 is * the name of the method to call in the object. * * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is * a printf format string used when printing the error * message. * * @access public * @return void * @see PEAR_ERROR_RETURN * @see PEAR_ERROR_PRINT * @see PEAR_ERROR_TRIGGER * @see PEAR_ERROR_DIE * @see PEAR_ERROR_CALLBACK * @see PEAR_ERROR_EXCEPTION * * @since PHP 4.0.5 */ protected static function _setErrorHandling( $object, $mode = null, $options = null ) { if ($object !== null) { $setmode = &$object->_default_error_mode; $setoptions = &$object->_default_error_options; } else { $setmode = &$GLOBALS['_PEAR_default_error_mode']; $setoptions = &$GLOBALS['_PEAR_default_error_options']; } switch ($mode) { case PEAR_ERROR_EXCEPTION: case PEAR_ERROR_RETURN: case PEAR_ERROR_PRINT: case PEAR_ERROR_TRIGGER: case PEAR_ERROR_DIE: case null: $setmode = $mode; $setoptions = $options; break; case PEAR_ERROR_CALLBACK: $setmode = $mode; // class/object method callback if (is_callable($options)) { $setoptions = $options; } else { trigger_error("invalid error callback", E_USER_WARNING); } break; default: trigger_error("invalid error mode", E_USER_WARNING); break; } } /** * This method is used to tell which errors you expect to get. * Expected errors are always returned with error mode * PEAR_ERROR_RETURN. Expected error codes are stored in a stack, * and this method pushes a new element onto it. The list of * expected errors are in effect until they are popped off the * stack with the popExpect() method. * * Note that this method can not be called statically * * @param mixed $code a single error code or an array of error codes to expect * * @return int the new depth of the "expected errors" stack * @access public */ function expectError($code = '*') { if (is_array($code)) { array_push($this->_expected_errors, $code); } else { array_push($this->_expected_errors, array($code)); } return count($this->_expected_errors); } /** * This method pops one element off the expected error codes * stack. * * @return array the list of error codes that were popped */ function popExpect() { return array_pop($this->_expected_errors); } /** * This method checks unsets an error code if available * * @param mixed error code * @return bool true if the error code was unset, false otherwise * @access private * @since PHP 4.3.0 */ function _checkDelExpect($error_code) { $deleted = false; foreach ($this->_expected_errors as $key => $error_array) { if (in_array($error_code, $error_array)) { unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); $deleted = true; } // clean up empty arrays if (0 == count($this->_expected_errors[$key])) { unset($this->_expected_errors[$key]); } } return $deleted; } /** * This method deletes all occurrences of the specified element from * the expected error codes stack. * * @param mixed $error_code error code that should be deleted * @return mixed list of error codes that were deleted or error * @access public * @since PHP 4.3.0 */ function delExpect($error_code) { $deleted = false; if ((is_array($error_code) && (0 != count($error_code)))) { // $error_code is a non-empty array here; we walk through it trying // to unset all values foreach ($error_code as $key => $error) { $deleted = $this->_checkDelExpect($error) ? true : false; } return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME } elseif (!empty($error_code)) { // $error_code comes alone, trying to unset it if ($this->_checkDelExpect($error_code)) { return true; } return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME } // $error_code is empty return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME } /** * This method is a wrapper that returns an instance of the * configured error class with this object's default error * handling applied. If the $mode and $options parameters are not * specified, the object's defaults are used. * * @param mixed $message a text error message or a PEAR error object * * @param int $code a numeric error code (it is up to your class * to define these if you want to use codes) * * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION. * * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter * specifies the PHP-internal error level (one of * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). * If $mode is PEAR_ERROR_CALLBACK, this * parameter specifies the callback function or * method. In other error modes this parameter * is ignored. * * @param string $userinfo If you need to pass along for example debug * information, this parameter is meant for that. * * @param string $error_class The returned error object will be * instantiated from this class, if specified. * * @param bool $skipmsg If true, raiseError will only pass error codes, * the error message parameter will be dropped. * * @return object a PEAR error object * @see PEAR::setErrorHandling * @since PHP 4.0.5 */ protected static function _raiseError($object, $message = null, $code = null, $mode = null, $options = null, $userinfo = null, $error_class = null, $skipmsg = false) { // The error is yet a PEAR error object if (is_object($message)) { $code = $message->getCode(); $userinfo = $message->getUserInfo(); $error_class = $message->getType(); $message->error_message_prefix = ''; $message = $message->getMessage(); } if ( $object !== null && isset($object->_expected_errors) && count($object->_expected_errors) > 0 && count($exp = end($object->_expected_errors)) ) { if ($exp[0] === "*" || (is_int(reset($exp)) && in_array($code, $exp)) || (is_string(reset($exp)) && in_array($message, $exp)) ) { $mode = PEAR_ERROR_RETURN; } } // No mode given, try global ones if ($mode === null) { // Class error handler if ($object !== null && isset($object->_default_error_mode)) { $mode = $object->_default_error_mode; $options = $object->_default_error_options; // Global error handler } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { $mode = $GLOBALS['_PEAR_default_error_mode']; $options = $GLOBALS['_PEAR_default_error_options']; } } if ($error_class !== null) { $ec = $error_class; } elseif ($object !== null && isset($object->_error_class)) { $ec = $object->_error_class; } else { $ec = 'PEAR_Error'; } if ($skipmsg) { $a = new $ec($code, $mode, $options, $userinfo); } else { $a = new $ec($message, $code, $mode, $options, $userinfo); } return $a; } /** * Simpler form of raiseError with fewer options. In most cases * message, code and userinfo are enough. * * @param mixed $message a text error message or a PEAR error object * * @param int $code a numeric error code (it is up to your class * to define these if you want to use codes) * * @param string $userinfo If you need to pass along for example debug * information, this parameter is meant for that. * * @return object a PEAR error object * @see PEAR::raiseError */ protected static function _throwError($object, $message = null, $code = null, $userinfo = null) { if ($object !== null) { $a = $object->raiseError($message, $code, null, null, $userinfo); return $a; } $a = PEAR::raiseError($message, $code, null, null, $userinfo); return $a; } public static function staticPushErrorHandling($mode, $options = null) { $stack = &$GLOBALS['_PEAR_error_handler_stack']; $def_mode = &$GLOBALS['_PEAR_default_error_mode']; $def_options = &$GLOBALS['_PEAR_default_error_options']; $stack[] = array($def_mode, $def_options); switch ($mode) { case PEAR_ERROR_EXCEPTION: case PEAR_ERROR_RETURN: case PEAR_ERROR_PRINT: case PEAR_ERROR_TRIGGER: case PEAR_ERROR_DIE: case null: $def_mode = $mode; $def_options = $options; break; case PEAR_ERROR_CALLBACK: $def_mode = $mode; // class/object method callback if (is_callable($options)) { $def_options = $options; } else { trigger_error("invalid error callback", E_USER_WARNING); } break; default: trigger_error("invalid error mode", E_USER_WARNING); break; } $stack[] = array($mode, $options); return true; } public static function staticPopErrorHandling() { $stack = &$GLOBALS['_PEAR_error_handler_stack']; $setmode = &$GLOBALS['_PEAR_default_error_mode']; $setoptions = &$GLOBALS['_PEAR_default_error_options']; array_pop($stack); list($mode, $options) = $stack[sizeof($stack) - 1]; array_pop($stack); switch ($mode) { case PEAR_ERROR_EXCEPTION: case PEAR_ERROR_RETURN: case PEAR_ERROR_PRINT: case PEAR_ERROR_TRIGGER: case PEAR_ERROR_DIE: case null: $setmode = $mode; $setoptions = $options; break; case PEAR_ERROR_CALLBACK: $setmode = $mode; // class/object method callback if (is_callable($options)) { $setoptions = $options; } else { trigger_error("invalid error callback", E_USER_WARNING); } break; default: trigger_error("invalid error mode", E_USER_WARNING); break; } return true; } /** * Push a new error handler on top of the error handler options stack. With this * you can easily override the actual error handler for some code and restore * it later with popErrorHandling. * * @param mixed $mode (same as setErrorHandling) * @param mixed $options (same as setErrorHandling) * * @return bool Always true * * @see PEAR::setErrorHandling */ protected static function _pushErrorHandling($object, $mode, $options = null) { $stack = &$GLOBALS['_PEAR_error_handler_stack']; if ($object !== null) { $def_mode = &$object->_default_error_mode; $def_options = &$object->_default_error_options; } else { $def_mode = &$GLOBALS['_PEAR_default_error_mode']; $def_options = &$GLOBALS['_PEAR_default_error_options']; } $stack[] = array($def_mode, $def_options); if ($object !== null) { $object->setErrorHandling($mode, $options); } else { PEAR::setErrorHandling($mode, $options); } $stack[] = array($mode, $options); return true; } /** * Pop the last error handler used * * @return bool Always true * * @see PEAR::pushErrorHandling */ protected static function _popErrorHandling($object) { $stack = &$GLOBALS['_PEAR_error_handler_stack']; array_pop($stack); list($mode, $options) = $stack[sizeof($stack) - 1]; array_pop($stack); if ($object !== null) { $object->setErrorHandling($mode, $options); } else { PEAR::setErrorHandling($mode, $options); } return true; } /** * OS independent PHP extension load. Remember to take care * on the correct extension name for case sensitive OSes. * * @param string $ext The extension name * @return bool Success or not on the dl() call */ public static function loadExtension($ext) { if (extension_loaded($ext)) { return true; } // if either returns true dl() will produce a FATAL error, stop that if ( function_exists('dl') === false || ini_get('enable_dl') != 1 ) { return false; } if (OS_WINDOWS) { $suffix = '.dll'; } elseif (PHP_OS == 'HP-UX') { $suffix = '.sl'; } elseif (PHP_OS == 'AIX') { $suffix = '.a'; } elseif (PHP_OS == 'OSX') { $suffix = '.bundle'; } else { $suffix = '.so'; } return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); } /** * Get SOURCE_DATE_EPOCH environment variable * See https://reproducible-builds.org/specs/source-date-epoch/ * * @return int * @access public */ static function getSourceDateEpoch() { if ($source_date_epoch = getenv('SOURCE_DATE_EPOCH')) { if (preg_match('/^\d+$/', $source_date_epoch)) { return (int) $source_date_epoch; } else { // "If the value is malformed, the build process SHOULD exit with a non-zero error code." self::raiseError("Invalid SOURCE_DATE_EPOCH: $source_date_epoch"); exit(1); } } else { return time(); } } } function _PEAR_call_destructors() { global $_PEAR_destructor_object_list; if (is_array($_PEAR_destructor_object_list) && sizeof($_PEAR_destructor_object_list)) { reset($_PEAR_destructor_object_list); $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo'); if ($destructLifoExists) { $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); } foreach ($_PEAR_destructor_object_list as $k => $objref) { $classname = get_class($objref); while ($classname) { $destructor = "_$classname"; if (method_exists($objref, $destructor)) { $objref->$destructor(); break; } else { $classname = get_parent_class($classname); } } } // Empty the object list to ensure that destructors are // not called more than once. $_PEAR_destructor_object_list = array(); } // Now call the shutdown functions if ( isset($GLOBALS['_PEAR_shutdown_funcs']) && is_array($GLOBALS['_PEAR_shutdown_funcs']) && !empty($GLOBALS['_PEAR_shutdown_funcs']) ) { foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { call_user_func_array($value[0], $value[1]); } } } /** * Standard PEAR error class for PHP 4 * * This class is supserseded by {@link PEAR_Exception} in PHP 5 * * @category pear * @package PEAR * @author Stig Bakken <ssb@php.net> * @author Tomas V.V. Cox <cox@idecnet.com> * @author Gregory Beaver <cellog@php.net> * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/manual/en/core.pear.pear-error.php * @see PEAR::raiseError(), PEAR::throwError() * @since Class available since PHP 4.0.2 */ class PEAR_Error { var $error_message_prefix = ''; var $mode = PEAR_ERROR_RETURN; var $level = E_USER_NOTICE; var $code = -1; var $message = ''; var $userinfo = ''; var $backtrace = null; var $callback = null; /** * PEAR_Error constructor * * @param string $message message * * @param int $code (optional) error code * * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER, * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION * * @param mixed $options (optional) error level, _OR_ in the case of * PEAR_ERROR_CALLBACK, the callback function or object/method * tuple. * * @param string $userinfo (optional) additional user/debug info * * @access public * */ function __construct($message = 'unknown error', $code = null, $mode = null, $options = null, $userinfo = null) { if ($mode === null) { $mode = PEAR_ERROR_RETURN; } $this->message = $message; $this->code = $code; $this->mode = $mode; $this->userinfo = $userinfo; $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace'); if (!$skiptrace) { $this->backtrace = debug_backtrace(); if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) { unset($this->backtrace[0]['object']); } } if ($mode & PEAR_ERROR_CALLBACK) { $this->level = E_USER_NOTICE; $this->callback = $options; } else { if ($options === null) { $options = E_USER_NOTICE; } $this->level = $options; $this->callback = null; } if ($this->mode & PEAR_ERROR_PRINT) { if (is_null($options) || is_int($options)) { $format = "%s"; } else { $format = $options; } printf($format, $this->getMessage()); } if ($this->mode & PEAR_ERROR_TRIGGER) { trigger_error($this->getMessage(), $this->level); } if ($this->mode & PEAR_ERROR_DIE) { $msg = $this->getMessage(); if (is_null($options) || is_int($options)) { $format = "%s"; if (substr($msg, -1) != "\n") { $msg .= "\n"; } } else { $format = $options; } printf($format, $msg); exit($code); } if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) { call_user_func($this->callback, $this); } if ($this->mode & PEAR_ERROR_EXCEPTION) { trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING); eval('$e = new Exception($this->message, $this->code);throw($e);'); } } /** * Only here for backwards compatibility. * * Class "Cache_Error" still uses it, among others. * * @param string $message Message * @param int $code Error code * @param int $mode Error mode * @param mixed $options See __construct() * @param string $userinfo Additional user/debug info */ public function PEAR_Error( $message = 'unknown error', $code = null, $mode = null, $options = null, $userinfo = null ) { self::__construct($message, $code, $mode, $options, $userinfo); } /** * Get the error mode from an error object. * * @return int error mode * @access public */ function getMode() { return $this->mode; } /** * Get the callback function/method from an error object. * * @return mixed callback function or object/method array * @access public */ function getCallback() { return $this->callback; } /** * Get the error message from an error object. * * @return string full error message * @access public */ function getMessage() { return ($this->error_message_prefix . $this->message); } /** * Get error code from an error object * * @return int error code * @access public */ function getCode() { return $this->code; } /** * Get the name of this error/exception. * * @return string error/exception name (type) * @access public */ function getType() { return get_class($this); } /** * Get additional user-supplied information. * * @return string user-supplied information * @access public */ function getUserInfo() { return $this->userinfo; } /** * Get additional debug information supplied by the application. * * @return string debug information * @access public */ function getDebugInfo() { return $this->getUserInfo(); } /** * Get the call backtrace from where the error was generated. * Supported with PHP 4.3.0 or newer. * * @param int $frame (optional) what frame to fetch * @return array Backtrace, or NULL if not available. * @access public */ function getBacktrace($frame = null) { if (defined('PEAR_IGNORE_BACKTRACE')) { return null; } if ($frame === null) { return $this->backtrace; } return $this->backtrace[$frame]; } function addUserInfo($info) { if (empty($this->userinfo)) { $this->userinfo = $info; } else { $this->userinfo .= " ** $info"; } } function __toString() { return $this->getMessage(); } /** * Make a string representation of this object. * * @return string a string with an object summary * @access public */ function toString() { $modes = array(); $levels = array(E_USER_NOTICE => 'notice', E_USER_WARNING => 'warning', E_USER_ERROR => 'error'); if ($this->mode & PEAR_ERROR_CALLBACK) { if (is_array($this->callback)) { $callback = (is_object($this->callback[0]) ? strtolower(get_class($this->callback[0])) : $this->callback[0]) . '::' . $this->callback[1]; } else { $callback = $this->callback; } return sprintf('[%s: message="%s" code=%d mode=callback '. 'callback=%s prefix="%s" info="%s"]', strtolower(get_class($this)), $this->message, $this->code, $callback, $this->error_message_prefix, $this->userinfo); } if ($this->mode & PEAR_ERROR_PRINT) { $modes[] = 'print'; } if ($this->mode & PEAR_ERROR_TRIGGER) { $modes[] = 'trigger'; } if ($this->mode & PEAR_ERROR_DIE) { $modes[] = 'die'; } if ($this->mode & PEAR_ERROR_RETURN) { $modes[] = 'return'; } return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. 'prefix="%s" info="%s"]', strtolower(get_class($this)), $this->message, $this->code, implode("|", $modes), $levels[$this->level], $this->error_message_prefix, $this->userinfo); } } /* * Local Variables: * mode: php * tab-width: 4 * c-basic-offset: 4 * End: */ PK�������!�oP��P�� ��System.phpnu�[��������<?php /** * File/Directory manipulation * * PHP versions 4 and 5 * * @category pear * @package System * @author Tomas V.V.Cox <cox@idecnet.com> * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ /** * base class */ require_once 'PEAR.php'; require_once 'Console/Getopt.php'; $GLOBALS['_System_temp_files'] = array(); /** * System offers cross platform compatible system functions * * Static functions for different operations. Should work under * Unix and Windows. The names and usage has been taken from its respectively * GNU commands. The functions will return (bool) false on error and will * trigger the error with the PHP trigger_error() function (you can silence * the error by prefixing a '@' sign after the function call, but this * is not recommended practice. Instead use an error handler with * {@link set_error_handler()}). * * Documentation on this class you can find in: * http://pear.php.net/manual/ * * Example usage: * if (!@System::rm('-r file1 dir1')) { * print "could not delete file1 or dir1"; * } * * In case you need to to pass file names with spaces, * pass the params as an array: * * System::rm(array('-r', $file1, $dir1)); * * @category pear * @package System * @author Tomas V.V. Cox <cox@idecnet.com> * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.10.16 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 * @static */ class System { /** * returns the commandline arguments of a function * * @param string $argv the commandline * @param string $short_options the allowed option short-tags * @param string $long_options the allowed option long-tags * @return array the given options and there values */ public static function _parseArgs($argv, $short_options, $long_options = null) { if (!is_array($argv) && $argv !== null) { /* // Quote all items that are a short option $av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); $offset = 0; foreach ($av as $a) { $b = trim($a[0]); if ($b[0] == '"' || $b[0] == "'") { continue; } $escape = escapeshellarg($b); $pos = $a[1] + $offset; $argv = substr_replace($argv, $escape, $pos, strlen($b)); $offset += 2; } */ // Find all items, quoted or otherwise preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av); $argv = $av[1]; foreach ($av[2] as $k => $a) { if (empty($a)) { continue; } $argv[$k] = trim($a) ; } } return Console_Getopt::getopt2($argv, $short_options, $long_options); } /** * Output errors with PHP trigger_error(). You can silence the errors * with prefixing a "@" sign to the function call: @System::mkdir(..); * * @param mixed $error a PEAR error or a string with the error message * @return bool false */ protected static function raiseError($error) { if (PEAR::isError($error)) { $error = $error->getMessage(); } trigger_error($error, E_USER_WARNING); return false; } /** * Creates a nested array representing the structure of a directory * * System::_dirToStruct('dir1', 0) => * Array * ( * [dirs] => Array * ( * [0] => dir1 * ) * * [files] => Array * ( * [0] => dir1/file2 * [1] => dir1/file3 * ) * ) * @param string $sPath Name of the directory * @param integer $maxinst max. deep of the lookup * @param integer $aktinst starting deep of the lookup * @param bool $silent if true, do not emit errors. * @return array the structure of the dir */ protected static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false) { $struct = array('dirs' => array(), 'files' => array()); if (($dir = @opendir($sPath)) === false) { if (!$silent) { System::raiseError("Could not open dir $sPath"); } return $struct; // XXX could not open error } $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ? $list = array(); while (false !== ($file = readdir($dir))) { if ($file != '.' && $file != '..') { $list[] = $file; } } closedir($dir); natsort($list); if ($aktinst < $maxinst || $maxinst == 0) { foreach ($list as $val) { $path = $sPath . DIRECTORY_SEPARATOR . $val; if (is_dir($path) && !is_link($path)) { $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent); $struct = array_merge_recursive($struct, $tmp); } else { $struct['files'][] = $path; } } } return $struct; } /** * Creates a nested array representing the structure of a directory and files * * @param array $files Array listing files and dirs * @return array * @static * @see System::_dirToStruct() */ protected static function _multipleToStruct($files) { $struct = array('dirs' => array(), 'files' => array()); settype($files, 'array'); foreach ($files as $file) { if (is_dir($file) && !is_link($file)) { $tmp = System::_dirToStruct($file, 0); $struct = array_merge_recursive($tmp, $struct); } else { if (!in_array($file, $struct['files'])) { $struct['files'][] = $file; } } } return $struct; } /** * The rm command for removing files. * Supports multiple files and dirs and also recursive deletes * * @param string $args the arguments for rm * @return mixed PEAR_Error or true for success * @static * @access public */ public static function rm($args) { $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-) if (PEAR::isError($opts)) { return System::raiseError($opts); } foreach ($opts[0] as $opt) { if ($opt[0] == 'r') { $do_recursive = true; } } $ret = true; if (isset($do_recursive)) { $struct = System::_multipleToStruct($opts[1]); foreach ($struct['files'] as $file) { if (!@unlink($file)) { $ret = false; } } rsort($struct['dirs']); foreach ($struct['dirs'] as $dir) { if (!@rmdir($dir)) { $ret = false; } } } else { foreach ($opts[1] as $file) { $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; if (!@$delete($file)) { $ret = false; } } } return $ret; } /** * Make directories. * * The -p option will create parent directories * @param string $args the name of the director(y|ies) to create * @return bool True for success */ public static function mkDir($args) { $opts = System::_parseArgs($args, 'pm:'); if (PEAR::isError($opts)) { return System::raiseError($opts); } $mode = 0777; // default mode foreach ($opts[0] as $opt) { if ($opt[0] == 'p') { $create_parents = true; } elseif ($opt[0] == 'm') { // if the mode is clearly an octal number (starts with 0) // convert it to decimal if (strlen($opt[1]) && $opt[1][0] == '0') { $opt[1] = octdec($opt[1]); } else { // convert to int $opt[1] += 0; } $mode = $opt[1]; } } $ret = true; if (isset($create_parents)) { foreach ($opts[1] as $dir) { $dirstack = array(); while ((!file_exists($dir) || !is_dir($dir)) && $dir != DIRECTORY_SEPARATOR) { array_unshift($dirstack, $dir); $dir = dirname($dir); } while ($newdir = array_shift($dirstack)) { if (!is_writeable(dirname($newdir))) { $ret = false; break; } if (!mkdir($newdir, $mode)) { $ret = false; } } } } else { foreach($opts[1] as $dir) { if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) { $ret = false; } } } return $ret; } /** * Concatenate files * * Usage: * 1) $var = System::cat('sample.txt test.txt'); * 2) System::cat('sample.txt test.txt > final.txt'); * 3) System::cat('sample.txt test.txt >> final.txt'); * * Note: as the class use fopen, urls should work also * * @param string $args the arguments * @return boolean true on success */ public static function &cat($args) { $ret = null; $files = array(); if (!is_array($args)) { $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); } $count_args = count($args); for ($i = 0; $i < $count_args; $i++) { if ($args[$i] == '>') { $mode = 'wb'; $outputfile = $args[$i+1]; break; } elseif ($args[$i] == '>>') { $mode = 'ab+'; $outputfile = $args[$i+1]; break; } else { $files[] = $args[$i]; } } $outputfd = false; if (isset($mode)) { if (!$outputfd = fopen($outputfile, $mode)) { $err = System::raiseError("Could not open $outputfile"); return $err; } $ret = true; } foreach ($files as $file) { if (!$fd = fopen($file, 'r')) { System::raiseError("Could not open $file"); continue; } while ($cont = fread($fd, 2048)) { if (is_resource($outputfd)) { fwrite($outputfd, $cont); } else { $ret .= $cont; } } fclose($fd); } if (is_resource($outputfd)) { fclose($outputfd); } return $ret; } /** * Creates temporary files or directories. This function will remove * the created files when the scripts finish its execution. * * Usage: * 1) $tempfile = System::mktemp("prefix"); * 2) $tempdir = System::mktemp("-d prefix"); * 3) $tempfile = System::mktemp(); * 4) $tempfile = System::mktemp("-t /var/tmp prefix"); * * prefix -> The string that will be prepended to the temp name * (defaults to "tmp"). * -d -> A temporary dir will be created instead of a file. * -t -> The target dir where the temporary (file|dir) will be created. If * this param is missing by default the env vars TMP on Windows or * TMPDIR in Unix will be used. If these vars are also missing * c:\windows\temp or /tmp will be used. * * @param string $args The arguments * @return mixed the full path of the created (file|dir) or false * @see System::tmpdir() */ public static function mktemp($args = null) { static $first_time = true; $opts = System::_parseArgs($args, 't:d'); if (PEAR::isError($opts)) { return System::raiseError($opts); } foreach ($opts[0] as $opt) { if ($opt[0] == 'd') { $tmp_is_dir = true; } elseif ($opt[0] == 't') { $tmpdir = $opt[1]; } } $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; if (!isset($tmpdir)) { $tmpdir = System::tmpdir(); } if (!System::mkDir(array('-p', $tmpdir))) { return false; } $tmp = tempnam($tmpdir, $prefix); if (isset($tmp_is_dir)) { unlink($tmp); // be careful possible race condition here if (!mkdir($tmp, 0700)) { return System::raiseError("Unable to create temporary directory $tmpdir"); } } $GLOBALS['_System_temp_files'][] = $tmp; if (isset($tmp_is_dir)) { //$GLOBALS['_System_temp_files'][] = dirname($tmp); } if ($first_time) { PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); $first_time = false; } return $tmp; } /** * Remove temporary files created my mkTemp. This function is executed * at script shutdown time */ public static function _removeTmpFiles() { if (count($GLOBALS['_System_temp_files'])) { $delete = $GLOBALS['_System_temp_files']; array_unshift($delete, '-r'); System::rm($delete); $GLOBALS['_System_temp_files'] = array(); } } /** * Get the path of the temporal directory set in the system * by looking in its environments variables. * Note: php.ini-recommended removes the "E" from the variables_order setting, * making unavaible the $_ENV array, that s why we do tests with _ENV * * @return string The temporary directory on the system */ public static function tmpdir() { if (OS_WINDOWS) { if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { return $var; } if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { return $var; } if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) { return $var; } if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { return $var; } return getenv('SystemRoot') . '\temp'; } if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { return $var; } return realpath(function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '/tmp'); } /** * The "which" command (show the full path of a command) * * @param string $program The command to search for * @param mixed $fallback Value to return if $program is not found * * @return mixed A string with the full path or false if not found * @author Stig Bakken <ssb@php.net> */ public static function which($program, $fallback = false) { // enforce API if (!is_string($program) || '' == $program) { return $fallback; } // full path given if (basename($program) != $program) { $path_elements[] = dirname($program); $program = basename($program); } else { $path = getenv('PATH'); if (!$path) { $path = getenv('Path'); // some OSes are just stupid enough to do this } $path_elements = explode(PATH_SEPARATOR, $path); } if (OS_WINDOWS) { $exe_suffixes = getenv('PATHEXT') ? explode(PATH_SEPARATOR, getenv('PATHEXT')) : array('.exe','.bat','.cmd','.com'); // allow passing a command.exe param if (strpos($program, '.') !== false) { array_unshift($exe_suffixes, ''); } } else { $exe_suffixes = array(''); } foreach ($exe_suffixes as $suff) { foreach ($path_elements as $dir) { $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; // It's possible to run a .bat on Windows that is_executable // would return false for. The is_executable check is meaningless... if (OS_WINDOWS) { if (file_exists($file)) { return $file; } } else { if (is_executable($file)) { return $file; } } } } return $fallback; } /** * The "find" command * * Usage: * * System::find($dir); * System::find("$dir -type d"); * System::find("$dir -type f"); * System::find("$dir -name *.php"); * System::find("$dir -name *.php -name *.htm*"); * System::find("$dir -maxdepth 1"); * * Params implemented: * $dir -> Start the search at this directory * -type d -> return only directories * -type f -> return only files * -maxdepth <n> -> max depth of recursion * -name <pattern> -> search pattern (bash style). Multiple -name param allowed * * @param mixed Either array or string with the command line * @return array Array of found files */ public static function find($args) { if (!is_array($args)) { $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); } $dir = realpath(array_shift($args)); if (!$dir) { return array(); } $patterns = array(); $depth = 0; $do_files = $do_dirs = true; $args_count = count($args); for ($i = 0; $i < $args_count; $i++) { switch ($args[$i]) { case '-type': if (in_array($args[$i+1], array('d', 'f'))) { if ($args[$i+1] == 'd') { $do_files = false; } else { $do_dirs = false; } } $i++; break; case '-name': $name = preg_quote($args[$i+1], '#'); // our magic characters ? and * have just been escaped, // so now we change the escaped versions to PCRE operators $name = strtr($name, array('\?' => '.', '\*' => '.*')); $patterns[] = '('.$name.')'; $i++; break; case '-maxdepth': $depth = $args[$i+1]; break; } } $path = System::_dirToStruct($dir, $depth, 0, true); if ($do_files && $do_dirs) { $files = array_merge($path['files'], $path['dirs']); } elseif ($do_dirs) { $files = $path['dirs']; } else { $files = $path['files']; } if (count($patterns)) { $dsq = preg_quote(DIRECTORY_SEPARATOR, '#'); $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#'; $ret = array(); $files_count = count($files); for ($i = 0; $i < $files_count; $i++) { // only search in the part of the file below the current directory $filepart = basename($files[$i]); if (preg_match($pattern, $filepart)) { $ret[] = $files[$i]; } } return $ret; } return $files; } } PK�������!�Oc��c�� ��peclcmd.phpnu�[��������<?php /** * PEAR, the PHP Extension and Application Repository * * Command line interface * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Stig Bakken <ssb@php.net> * @author Tomas V.V.Cox <cox@idecnet.com> * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR */ /** * @nodep Gtk */ //the space is needed for windows include paths with trailing backslash // http://pear.php.net/bugs/bug.php?id=19482 if ('/opt/alt/php84/usr/share/pear ' != '@'.'include_path'.'@ ') { ini_set('include_path', trim('/opt/alt/php84/usr/share/pear '). PATH_SEPARATOR . get_include_path()); $raw = false; } else { // this is a raw, uninstalled pear, either a cvs checkout, or php distro ini_set('include_path', __DIR__ . PATH_SEPARATOR . get_include_path()); $raw = true; } define('PEAR_RUNTYPE', 'pecl'); require_once 'pearcmd.php'; /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * indent-tabs-mode: nil * mode: php * End: */ // vim600:syn=php ?> PK�������!�ũ �� ����data/PEAR/package.dtdnu�[��������<!-- This is the PEAR package description, version 1.0. It should be used with the informal public identifier: "-//PHP Group//DTD PEAR Package 1.0//EN//XML" Copyright (c) 1997-2005 The PHP Group This source file is subject to the New BSD License, that is bundled with this package in the file LICENSE, and is available at through the world-wide-web at http://opensource.org/licenses/bsd-license.php. If you did not receive a copy of the New BSD License and are unable to obtain it through the world-wide-web, please send a note to license@php.net so we can mail you a copy immediately. Authors: Stig S. Bakken <ssb@fast.no> Gregory Beaver <cellog@php.net> --> <!ENTITY % NUMBER "CDATA"> <!ELEMENT package (name,summary,description,license?,maintainers,release,changelog?)> <!ATTLIST package type (source|binary|empty) "empty" version CDATA #REQUIRED packagerversion CDATA #IMPLIED> <!ELEMENT name (#PCDATA)> <!ELEMENT summary (#PCDATA)> <!ELEMENT license (#PCDATA)> <!ELEMENT description (#PCDATA)> <!ELEMENT maintainers (maintainer)+> <!ELEMENT maintainer (user|role|name|email)+> <!ELEMENT user (#PCDATA)> <!ELEMENT role (#PCDATA)> <!ELEMENT email (#PCDATA)> <!ELEMENT changelog (release)+> <!ELEMENT release (version,date,license,state,notes,warnings?,provides*,deps?,configureoptions?,filelist?)> <!ELEMENT version (#PCDATA)> <!ELEMENT date (#PCDATA)> <!ELEMENT state (#PCDATA)> <!ELEMENT notes (#PCDATA)> <!ELEMENT warnings (#PCDATA)> <!ELEMENT deps (dep*)> <!ELEMENT dep (#PCDATA)> <!ATTLIST dep type (pkg|ext|php) #REQUIRED rel (has|eq|lt|le|gt|ge) #IMPLIED version CDATA #IMPLIED optional (yes|no) 'no'> <!ELEMENT configureoptions (configureoption)+> <!ELEMENT configureoption EMPTY> <!ATTLIST configureoption name CDATA #REQUIRED default CDATA #IMPLIED prompt CDATA #REQUIRED> <!ELEMENT provides EMPTY> <!ATTLIST provides type (ext|prog|class|function|feature|api) #REQUIRED name CDATA #REQUIRED extends CDATA #IMPLIED> <!ELEMENT filelist (dir|file)+> <!ELEMENT dir (dir|file)+> <!ATTLIST dir name CDATA #REQUIRED role (php|ext|src|test|doc|data|script) 'php' baseinstalldir CDATA #IMPLIED> <!ELEMENT file (replace*)> <!ATTLIST file role (php|ext|src|test|doc|data|script) 'php' debug (na|on|off) 'na' format CDATA #IMPLIED baseinstalldir CDATA #IMPLIED platform CDATA #IMPLIED md5sum CDATA #IMPLIED name CDATA #REQUIRED install-as CDATA #IMPLIED> <!ELEMENT replace EMPTY> <!ATTLIST replace type (php-const|pear-config|package-info) #REQUIRED from CDATA #REQUIRED to CDATA #REQUIRED> PK�������!�������data/PEAR/template.specnu�[��������Summary: PEAR: @summary@ Name: @rpm_package@ Version: @version@ Release: 1 License: @release_license@ Group: Development/Libraries Source: http://@master_server@/get/@package@-%{version}.tgz BuildRoot: %{_tmppath}/%{name}-root URL: http://@master_server@/package/@package@ Prefix: %{_prefix} BuildArchitectures: @arch@ @extra_headers@ %description @description@ %prep rm -rf %{buildroot}/* %setup -c -T # XXX Source files location is missing here in pear cmd pear -v -c %{buildroot}/pearrc \ -d php_dir=%{_libdir}/php/pear \ -d doc_dir=/docs \ -d bin_dir=%{_bindir} \ -d data_dir=%{_libdir}/php/pear/data \ -d test_dir=%{_libdir}/php/pear/tests \ -d ext_dir=%{_libdir} \@extra_config@ -s %build echo BuildRoot=%{buildroot} %postun # if refcount = 0 then package has been removed (not upgraded) if [ "$1" -eq "0" ]; then pear uninstall --nodeps -r @possible_channel@@package@ rm @rpm_xml_dir@/@package@.xml fi %post # if refcount = 2 then package has been upgraded if [ "$1" -ge "2" ]; then pear upgrade --nodeps -r @rpm_xml_dir@/@package@.xml else pear install --nodeps -r @rpm_xml_dir@/@package@.xml fi %install pear -c %{buildroot}/pearrc install --nodeps -R %{buildroot} \ $RPM_SOURCE_DIR/@package@-%{version}.tgz rm %{buildroot}/pearrc rm %{buildroot}/%{_libdir}/php/pear/.filemap rm %{buildroot}/%{_libdir}/php/pear/.lock rm -rf %{buildroot}/%{_libdir}/php/pear/.registry if [ "@doc_files@" != "" ]; then mv %{buildroot}/docs/@package@/* . rm -rf %{buildroot}/docs fi mkdir -p %{buildroot}@rpm_xml_dir@ tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package@package2xml@.xml cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml #rm -rf %{buildroot}/* #pear -q install -R %{buildroot} -n package@package2xml@.xml #mkdir -p %{buildroot}@rpm_xml_dir@ #cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml %files %defattr(-,root,root) %doc @doc_files@ / PK�������!�6EW��W����data/Mail_mimeDecode/xmail.xslnu�[��������<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:output method="text" omit-xml-declaration="yes" indent="no"/> <xsl:preserve-space elements="headervalue paramvalue body"/> <xsl:template name="mimepart"> <xsl:variable name="boundary"> <xsl:for-each select="./header"> <xsl:if test="string(./headername) = 'Content-Type'"> <xsl:for-each select="./parameter"> <xsl:if test="string(./paramname) = 'boundary'"> <xsl:value-of select="paramvalue"/> </xsl:if> </xsl:for-each> </xsl:if> </xsl:for-each> </xsl:variable> <xsl:for-each select="header"> <xsl:value-of select="headername"/> <xsl:text>: </xsl:text> <xsl:value-of select="headervalue"/> <xsl:if test="count(./parameter) = 0"> <xsl:text> </xsl:text> </xsl:if> <xsl:for-each select="parameter"> <xsl:text>; </xsl:text> <xsl:value-of select="paramname"/> <xsl:text>="</xsl:text> <xsl:value-of select="paramvalue"/> <xsl:text>"</xsl:text> </xsl:for-each> <xsl:if test="count(./parameter) > 0"> <xsl:text> </xsl:text> </xsl:if> </xsl:for-each> <xsl:text> </xsl:text> <!-- Which to do, print a body or process subparts? --> <xsl:choose> <xsl:when test="count(./mimepart) = 0"> <xsl:value-of select="body"/> <xsl:text> </xsl:text> </xsl:when> <xsl:otherwise> <xsl:for-each select="mimepart"> <xsl:text>--</xsl:text><xsl:value-of select="$boundary"/><xsl:text> </xsl:text> <xsl:call-template name="mimepart"/> </xsl:for-each> <xsl:text>--</xsl:text><xsl:value-of select="$boundary"/><xsl:text>-- </xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- This is where the stylesheet really starts, matching the top level email element --> <xsl:template match="email"> <xsl:call-template name="mimepart"/> </xsl:template> </xsl:stylesheet>PK�������!� $v6��6����data/Mail_mimeDecode/xmail.dtdnu�[��������<?xml version="1.0" encoding="ISO-8859-1"?> <!ENTITY lt "&#60;"> <!ENTITY gt ">"> <!ENTITY amp "&#38;"> <!ENTITY apos "'"> <!ENTITY quot """> <!ENTITY crlf " "> <!ELEMENT email (header+, (body | mimepart+))> <!ELEMENT mimepart (header+, (body | mimepart+))> <!ELEMENT body (#PCDATA)> <!ELEMENT header ((headername|headervalue|parameter)*)> <!ELEMENT headername (#PCDATA)> <!ELEMENT headervalue (#PCDATA)> <!ELEMENT parameter ((paramname|paramvalue)+)> <!ELEMENT paramvalue (#PCDATA)> <!ELEMENT paramname (#PCDATA)> PK�������!�0AC5��C5����Console/Getopt.phpnu�[��������<?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ /** * PHP Version 5 * * Copyright (c) 2001-2015, The PEAR developers * * This source file is subject to the BSD-2-Clause license, * that is bundled with this package in the file LICENSE, and is * available through the world-wide-web at the following url: * http://opensource.org/licenses/bsd-license.php. * * @category Console * @package Console_Getopt * @author Andrei Zmievski <andrei@php.net> * @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause * @version CVS: $Id$ * @link http://pear.php.net/package/Console_Getopt */ require_once 'PEAR.php'; /** * Command-line options parsing class. * * @category Console * @package Console_Getopt * @author Andrei Zmievski <andrei@php.net> * @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause * @link http://pear.php.net/package/Console_Getopt */ class Console_Getopt { /** * Parses the command-line options. * * The first parameter to this function should be the list of command-line * arguments without the leading reference to the running program. * * The second parameter is a string of allowed short options. Each of the * option letters can be followed by a colon ':' to specify that the option * requires an argument, or a double colon '::' to specify that the option * takes an optional argument. * * The third argument is an optional array of allowed long options. The * leading '--' should not be included in the option name. Options that * require an argument should be followed by '=', and options that take an * option argument should be followed by '=='. * * The return value is an array of two elements: the list of parsed * options and the list of non-option command-line arguments. Each entry in * the list of parsed options is a pair of elements - the first one * specifies the option, and the second one specifies the option argument, * if there was one. * * Long and short options can be mixed. * * Most of the semantics of this function are based on GNU getopt_long(). * * @param array $args an array of command-line arguments * @param string $short_options specifies the list of allowed short options * @param array $long_options specifies the list of allowed long options * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option * * @return array two-element array containing the list of parsed options and * the non-option arguments */ public static function getopt2($args, $short_options, $long_options = null, $skip_unknown = false) { return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown); } /** * This function expects $args to start with the script name (POSIX-style). * Preserved for backwards compatibility. * * @param array $args an array of command-line arguments * @param string $short_options specifies the list of allowed short options * @param array $long_options specifies the list of allowed long options * * @see getopt2() * @return array two-element array containing the list of parsed options and * the non-option arguments */ public static function getopt($args, $short_options, $long_options = null, $skip_unknown = false) { return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown); } /** * The actual implementation of the argument parsing code. * * @param int $version Version to use * @param array $args an array of command-line arguments * @param string $short_options specifies the list of allowed short options * @param array $long_options specifies the list of allowed long options * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option * * @return array */ public static function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false) { // in case you pass directly readPHPArgv() as the first arg if (PEAR::isError($args)) { return $args; } if (empty($args)) { return array(array(), array()); } $non_opts = $opts = array(); settype($args, 'array'); if ($long_options) { sort($long_options); } /* * Preserve backwards compatibility with callers that relied on * erroneous POSIX fix. */ if ($version < 2) { if (isset($args[0][0]) && $args[0][0] != '-') { array_shift($args); } } for ($i = 0; $i < count($args); $i++) { $arg = $args[$i]; /* The special element '--' means explicit end of options. Treat the rest of the arguments as non-options and end the loop. */ if ($arg == '--') { $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); break; } if ($arg[0] != '-' || (strlen($arg) > 1 && $arg[1] == '-' && !$long_options)) { $non_opts = array_merge($non_opts, array_slice($args, $i)); break; } elseif (strlen($arg) > 1 && $arg[1] == '-') { $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $i, $args, $skip_unknown); if (PEAR::isError($error)) { return $error; } } elseif ($arg == '-') { // - is stdin $non_opts = array_merge($non_opts, array_slice($args, $i)); break; } else { $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $i, $args, $skip_unknown); if (PEAR::isError($error)) { return $error; } } } return array($opts, $non_opts); } /** * Parse short option * * @param string $arg Argument * @param string[] $short_options Available short options * @param string[][] &$opts * @param int &$argIdx * @param string[] $args * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option * * @return void */ protected static function _parseShortOption($arg, $short_options, &$opts, &$argIdx, $args, $skip_unknown) { for ($i = 0; $i < strlen($arg); $i++) { $opt = $arg[$i]; $opt_arg = null; /* Try to find the short option in the specifier string. */ if (($spec = strstr($short_options, $opt)) === false || $arg[$i] == ':') { if ($skip_unknown === true) { break; } $msg = "Console_Getopt: unrecognized option -- $opt"; return PEAR::raiseError($msg); } if (strlen($spec) > 1 && $spec[1] == ':') { if (strlen($spec) > 2 && $spec[2] == ':') { if ($i + 1 < strlen($arg)) { /* Option takes an optional argument. Use the remainder of the arg string if there is anything left. */ $opts[] = array($opt, substr($arg, $i + 1)); break; } } else { /* Option requires an argument. Use the remainder of the arg string if there is anything left. */ if ($i + 1 < strlen($arg)) { $opts[] = array($opt, substr($arg, $i + 1)); break; } else if (isset($args[++$argIdx])) { $opt_arg = $args[$argIdx]; /* Else use the next argument. */; if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { $msg = "option requires an argument --$opt"; return PEAR::raiseError("Console_Getopt: " . $msg); } } else { $msg = "option requires an argument --$opt"; return PEAR::raiseError("Console_Getopt: " . $msg); } } } $opts[] = array($opt, $opt_arg); } } /** * Checks if an argument is a short option * * @param string $arg Argument to check * * @return bool */ protected static function _isShortOpt($arg) { return strlen($arg) == 2 && $arg[0] == '-' && preg_match('/[a-zA-Z]/', $arg[1]); } /** * Checks if an argument is a long option * * @param string $arg Argument to check * * @return bool */ protected static function _isLongOpt($arg) { return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' && preg_match('/[a-zA-Z]+$/', substr($arg, 2)); } /** * Parse long option * * @param string $arg Argument * @param string[] $long_options Available long options * @param string[][] &$opts * @param int &$argIdx * @param string[] $args * * @return void|PEAR_Error */ protected static function _parseLongOption($arg, $long_options, &$opts, &$argIdx, $args, $skip_unknown) { @list($opt, $opt_arg) = explode('=', $arg, 2); $opt_len = strlen($opt); for ($i = 0; $i < count($long_options); $i++) { $long_opt = $long_options[$i]; $opt_start = substr($long_opt, 0, $opt_len); $long_opt_name = str_replace('=', '', $long_opt); /* Option doesn't match. Go on to the next one. */ if ($long_opt_name != $opt) { continue; } $opt_rest = substr($long_opt, $opt_len); /* Check that the options uniquely matches one of the allowed options. */ if ($i + 1 < count($long_options)) { $next_option_rest = substr($long_options[$i + 1], $opt_len); } else { $next_option_rest = ''; } if ($opt_rest != '' && $opt[0] != '=' && $i + 1 < count($long_options) && $opt == substr($long_options[$i+1], 0, $opt_len) && $next_option_rest != '' && $next_option_rest[0] != '=') { $msg = "Console_Getopt: option --$opt is ambiguous"; return PEAR::raiseError($msg); } if (substr($long_opt, -1) == '=') { if (substr($long_opt, -2) != '==') { /* Long option requires an argument. Take the next argument if one wasn't specified. */; if (!strlen($opt_arg)) { if (!isset($args[++$argIdx])) { $msg = "Console_Getopt: option requires an argument --$opt"; return PEAR::raiseError($msg); } $opt_arg = $args[$argIdx]; } if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { $msg = "Console_Getopt: option requires an argument --$opt"; return PEAR::raiseError($msg); } } } else if ($opt_arg) { $msg = "Console_Getopt: option --$opt doesn't allow an argument"; return PEAR::raiseError($msg); } $opts[] = array('--' . $opt, $opt_arg); return; } if ($skip_unknown === true) { return; } return PEAR::raiseError("Console_Getopt: unrecognized option --$opt"); } /** * Safely read the $argv PHP array across different PHP configurations. * Will take care on register_globals and register_argc_argv ini directives * * @return mixed the $argv PHP array or PEAR error if not registered */ public static function readPHPArgv() { global $argv; if (!is_array($argv)) { if (!@is_array($_SERVER['argv'])) { if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { $msg = "Could not read cmd args (register_argc_argv=Off?)"; return PEAR::raiseError("Console_Getopt: " . $msg); } return $GLOBALS['HTTP_SERVER_VARS']['argv']; } return $_SERVER['argv']; } return $argv; } } PK�������!�P'hB&��&����Mail.phpnu�[��������<?php /** * PEAR's Mail:: interface. * * PHP version 5 * * LICENSE: * * Copyright (c) 1997-2017, Chuck Hagenbuch & Richard Heyes * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @category Mail * @package Mail * @author Chuck Hagenbuch <chuck@horde.org> * @copyright 1997-2017 Chuck Hagenbuch * @license http://opensource.org/licenses/BSD-3-Clause New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/Mail/ */ require_once 'PEAR.php'; /** * PEAR's Mail:: interface. Defines the interface for implementing * mailers under the PEAR hierarchy, and provides supporting functions * useful in multiple mailer backends. * * @version $Revision$ * @package Mail */ class Mail { /** * Line terminator used for separating header lines. * @var string */ public $sep = "\r\n"; /** * Provides an interface for generating Mail:: objects of various * types * * @param string $driver The kind of Mail:: object to instantiate. * @param array $params The parameters to pass to the Mail:: object. * * @return object Mail a instance of the driver class or if fails a PEAR Error */ public static function factory($driver, $params = array()) { $driver = strtolower($driver); @include_once 'Mail/' . $driver . '.php'; $class = 'Mail_' . $driver; if (class_exists($class)) { $mailer = new $class($params); return $mailer; } else { return PEAR::raiseError('Unable to find class for driver ' . $driver); } } /** * Implements Mail::send() function using php's built-in mail() * command. * * @param mixed $recipients Either a comma-seperated list of recipients * (RFC822 compliant), or an array of recipients, * each RFC822 valid. This may contain recipients not * specified in the headers, for Bcc:, resending * messages, etc. * * @param array $headers The array of headers to send with the mail, in an * associative array, where the array key is the * header name (ie, 'Subject'), and the array value * is the header value (ie, 'test'). The header * produced from those values would be 'Subject: * test'. * * @param string $body The full text of the message body, including any * Mime parts, etc. * * @return mixed Returns true on success, or a PEAR_Error * containing a descriptive error message on * failure. * * @deprecated use Mail_mail::send instead */ public function send($recipients, $headers, $body) { if (!is_array($headers)) { return PEAR::raiseError('$headers must be an array'); } $result = $this->_sanitizeHeaders($headers); if (is_a($result, 'PEAR_Error')) { return $result; } // if we're passed an array of recipients, implode it. if (is_array($recipients)) { $recipients = implode(', ', $recipients); } // get the Subject out of the headers array so that we can // pass it as a seperate argument to mail(). $subject = ''; if (isset($headers['Subject'])) { $subject = $headers['Subject']; unset($headers['Subject']); } // flatten the headers out. list(, $text_headers) = Mail::prepareHeaders($headers); return mail($recipients, $subject, $body, $text_headers); } /** * Sanitize an array of mail headers by removing any additional header * strings present in a legitimate header's value. The goal of this * filter is to prevent mail injection attacks. * * @param array $headers The associative array of headers to sanitize. */ protected function _sanitizeHeaders(&$headers) { foreach ($headers as $key => $value) { $headers[$key] = preg_replace('=((<CR>|<LF>|0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i', null, $value); } } /** * Take an array of mail headers and return a string containing * text usable in sending a message. * * @param array $headers The array of headers to prepare, in an associative * array, where the array key is the header name (ie, * 'Subject'), and the array value is the header * value (ie, 'test'). The header produced from those * values would be 'Subject: test'. * * @return mixed Returns false if it encounters a bad address, * otherwise returns an array containing two * elements: Any From: address found in the headers, * and the plain text version of the headers. */ protected function prepareHeaders($headers) { $lines = array(); $from = null; foreach ($headers as $key => $value) { if (strcasecmp($key, 'From') === 0) { include_once 'Mail/RFC822.php'; $parser = new Mail_RFC822(); $addresses = $parser->parseAddressList($value, 'localhost', false); if (is_a($addresses, 'PEAR_Error')) { return $addresses; } $from = $addresses[0]->mailbox . '@' . $addresses[0]->host; // Reject envelope From: addresses with spaces. if (strstr($from, ' ')) { return false; } $lines[] = $key . ': ' . $value; } elseif (strcasecmp($key, 'Received') === 0) { $received = array(); if (is_array($value)) { foreach ($value as $line) { $received[] = $key . ': ' . $line; } } else { $received[] = $key . ': ' . $value; } // Put Received: headers at the top. Spam detectors often // flag messages with Received: headers after the Subject: // as spam. $lines = array_merge($received, $lines); } else { // If $value is an array (i.e., a list of addresses), convert // it to a comma-delimited string of its elements (addresses). if (is_array($value)) { $value = implode(', ', $value); } $lines[] = $key . ': ' . $value; } } return array($from, join($this->sep, $lines)); } /** * Take a set of recipients and parse them, returning an array of * bare addresses (forward paths) that can be passed to sendmail * or an smtp server with the rcpt to: command. * * @param mixed Either a comma-seperated list of recipients * (RFC822 compliant), or an array of recipients, * each RFC822 valid. * * @return mixed An array of forward paths (bare addresses) or a PEAR_Error * object if the address list could not be parsed. */ protected function parseRecipients($recipients) { include_once 'Mail/RFC822.php'; // if we're passed an array, assume addresses are valid and // implode them before parsing. if (is_array($recipients)) { $recipients = implode(', ', $recipients); } // Parse recipients, leaving out all personal info. This is // for smtp recipients, etc. All relevant personal information // should already be in the headers. $Mail_RFC822 = new Mail_RFC822(); $addresses = $Mail_RFC822->parseAddressList($recipients, 'localhost', false); // If parseAddressList() returned a PEAR_Error object, just return it. if (is_a($addresses, 'PEAR_Error')) { return $addresses; } $recipients = array(); if (is_array($addresses)) { foreach ($addresses as $ob) { $recipients[] = $ob->mailbox . '@' . $ob->host; } } return $recipients; } } PK�������!�ȗ����!��.pkgxml/Pear_Net_Socket-1.2.2.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.3" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>Net_Socket</name> <channel>pear.php.net</channel> <summary>Network Socket Interface</summary> <description>Net_Socket is a class interface to TCP sockets. It provides blocking and non-blocking operation, with different reading and writing modes (byte-wise, block-wise, line-wise and special formats like network byte-order ip addresses).</description> <lead> <name>Chuck Hagenbuch</name> <user>chagenbu</user> <email>chuck@horde.org</email> <active>no</active> </lead> <lead> <name>Stig Bakken</name> <user>ssb</user> <email>stig@php.net</email> <active>no</active> </lead> <lead> <name>Aleksander Machniak</name> <user>alec</user> <email>alec@php.net</email> <active>no</active> </lead> <date>2017-04-13</date> <time>17:15:33</time> <version> <release>1.2.2</release> <api>1.2.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD-2-Clause</license> <notes> * Bug #21178: $php_errormsg is deprecated in PHP 7.2 </notes> <contents> <dir baseinstalldir="/" name="/"> <file baseinstalldir="/" md5sum="f99081ef3a69bcc1faa0d90a9a616788" name="Net/Socket.php" role="php" /> <file baseinstalldir="/" md5sum="61a9ed8d1604a739e6997149ea34e701" name="README.md" role="doc" /> <file baseinstalldir="/" md5sum="28575b04f4f2014316245d83e27343e1" name="LICENSE" role="doc" /> </dir> </contents> <dependencies> <required> <php> <min>5.4.0</min> </php> <pearinstaller> <min>1.10.1</min> </pearinstaller> </required> </dependencies> <phprelease /> </package> PK�������!�/h����"��.pkgxml/Pear_Mail_Mime-1.10.11.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.12" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>Mail_Mime</name> <channel>pear.php.net</channel> <summary>Mail_Mime provides classes to create MIME messages.</summary> <description>Mail_Mime provides classes to deal with the creation and manipulation of MIME messages. It allows people to create e-mail messages consisting of: * Text Parts * HTML Parts * Inline HTML Images * Attachments * Attached messages It supports big messages, base64 and quoted-printable encodings and non-ASCII characters in filenames, subjects, recipients, etc. encoded using RFC2047 and/or RFC2231.</description> <lead> <name>Cipriano Groenendal</name> <user>cipri</user> <email>cipri@php.net</email> <active>no</active> </lead> <lead> <name>Aleksander Machniak</name> <user>alec</user> <email>alec@php.net</email> <active>yes</active> </lead> <date>2021-09-05</date> <time>08:43:21</time> <version> <release>1.10.11</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix PHP 8.1: strlen(): Passing null to parameter #1 ($string) of type string is deprecated [alec] * Fix encoding recipient names with @ character and no space between name and address [alec] * Fix the license label in composer.json [jnkowa-gfk] </notes> <contents> <dir name="/"> <file baseinstalldir="Mail" md5sum="edd138f6c5497ae2b5d63620a67a931e" name="tests/class-filename.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="7ec986391d0af058316f66e5a507e059" name="tests/content_transfer_encoding.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="c1a43360d9b2cb5f9542503a4355c277" name="tests/encoding_case.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="bf50a200190cad5e2d4aae4e120ea09f" name="tests/headers_with_mbstring.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="9a2d207f873317125ff43c092f3f0d25" name="tests/headers_without_mbstring.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="25d4c5b9fdeaabc7810c26e6f89e95ca" name="tests/qp_encoding_test.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="958197f31b4a20c91dd42662595e7516" name="tests/sleep_wakeup_EOL-bug3488-part1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="46675529f1f021b51a1aa0ae6c971cd2" name="tests/sleep_wakeup_EOL-bug3488-part2.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="f8c05910737e451c7a9d4737b8d9f095" name="tests/test_Bug_3513_1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="edb467a375ddf09e777a9388e2e8cbb5" name="tests/test_Bug_3513_2.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="70c2456445eaaa80779206e9e245d685" name="tests/test_Bug_3513_3.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="4cda500d0d7925e81a299f1d3db132a9" name="tests/test_Bug_7561_1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="42a214e7e3d3afa07f8996b235222611" name="tests/test_Bug_8386_1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="ed78099563499f60386a128cb7b96925" name="tests/test_Bug_8541_1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="5250a0693599b945e8642a1a289d7275" name="tests/test_Bug_9722_1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="b7f58f54e1485c23a60c83cd3cc5563e" name="tests/test_Bug_10596_1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="ccb53d80e7f5c9f28b11abce5fe5d490" name="tests/test_Bug_10816_1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="f3d92a1fff099173b8600fb3646d0614" name="tests/test_Bug_10999_1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="3f2757d5db43abd8f177f094f4d53625" name="tests/test_Bug_11381.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="c64d675e73bc02fc94f5d03b3117cfa0" name="tests/test_Bug_11731.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="8c9305ca05f5ed2d7cd7e31e4836f17a" name="tests/test_Bug_12165.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="2aa2c3dfbe44500809e79da994272611" name="tests/test_Bug_12385_1.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="ef1d726233dbd3360c540fd6a959b0d0" name="tests/test_Bug_12411.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="a862a57ff622fcbb2328be6c805e2d05" name="tests/test_Bug_12466.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="4eddeeac08f351feb147ab6fda439526" name="tests/test_Bug_13032.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="de15a0657a83694bc6991c4184ccf9bd" name="tests/test_Bug_13444.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="80afe9fced03288884e9d302d1e65b2d" name="tests/test_Bug_13962.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="89bf87e798f4a149a150d4c2a505f976" name="tests/test_Bug_14529.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="5f9100adb1c609110ed495fafa819975" name="tests/test_Bug_14779.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="45eb42fe4e325da64f1ae8f149e2a396" name="tests/test_Bug_14780.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="609dad2083c54ba56ea691c488ca20e2" name="tests/test_Bug_15320.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="f4ef08e416e775558e8075b531bbc814" name="tests/test_Bug_16539.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="ed1bd0fc9067b3fb8b95808bfa315916" name="tests/test_Bug_17025.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="8a37de74fb39fed4566617a7ea38bb69" name="tests/test_Bug_17175.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="b9dee3c7c45d8c6c22f860e93c3769b9" name="tests/test_Bug_18083.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="96ce23ad1a1d6417facfcdd2baa9c8eb" name="tests/test_Bug_18772.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="dd98307b3224b173f7b54f7e403865a4" name="tests/test_Bug_19497.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="e1194180cb6a218fab69db90f88d1cb2" name="tests/test_Bug_20226.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="1b7919174edcd1cf5d5fd5a622fdac9b" name="tests/test_Bug_20273.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="6513c4b0c9e962c900d020124752333e" name="tests/test_Bug_20563.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="7c7a00818cb0f01fa6c52c920b9e76c6" name="tests/test_Bug_20564.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="b9e31a9c24b05dfb6166512e04e2f056" name="tests/test_Bug_21027.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="b634a5e99aa26a8b6df8fcfae07051b4" name="tests/test_Bug_21098.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="b21be5b099a69428bd37e60589cdd485" name="tests/test_Bug_21205.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="bc152c12839964fba15da5673d25c4db" name="tests/test_Bug_21206.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="ccf732525be42c955eea18e78490c3e1" name="tests/test_Bug_21255.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="579f1e11da6c8074dbf508dc1f1dedfa" name="tests/test_Bug_GH16.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="df32d66d9fccf7a0956422811283272a" name="tests/test_Bug_GH19.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="b7b5b5bacc6a599cfaece35ad202ad1a" name="tests/test_Bug_GH26.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="e08958f1bb60561f072a3508b8fd3e2e" name="tests/test_linebreak_dot.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="8398e9bfea0bc7c4ff0770ae3d6279fe" name="tests/test_linebreak_larger_76.phpt" role="test" /> <file baseinstalldir="/" md5sum="e5c9ac7f32e53afdeafd1a84343a89ae" name="Mail/mime.php" role="php" /> <file baseinstalldir="/" md5sum="36128789ad1101d39d13b06ca2585576" name="Mail/mimePart.php" role="php" /> </dir> </contents> <dependencies> <required> <php> <min>5.2.0</min> </php> <pearinstaller> <min>1.6.0</min> </pearinstaller> </required> </dependencies> <phprelease /> <changelog> <release> <version> <release>1.0</release> <api>1.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2001-12-28</date> <license uri="http://www.php.net/license">PHP</license> <notes> This is the initial release of the Mime_Mail package. </notes> </release> <release> <version> <release>1.1</release> <api>1.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2002-04-03</date> <license uri="http://www.php.net/license">PHP</license> <notes> This is a maintenance release with various bugfixes and minor enhancements. </notes> </release> <release> <version> <release>1.2</release> <api>1.2</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2002-07-14</date> <license uri="http://www.php.net/license">PHP</license> <notes> * Added header encoding * Altered mimePart to put boundary parameter on newline * Changed addFrom() to setFrom() * Added setSubject() * Made mimePart inherit crlf setting from mime </notes> </release> <release> <version> <release>1.2.1</release> <api>1.2.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2002-07-27</date> <license uri="http://www.php.net/license">PHP</license> <notes> * License change * Applied a few changes From Ilia Alshanetsky </notes> </release> <release> <version> <release>1.3.0RC1</release> <api>1.3.0RC1</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <date>2005-03-20</date> <license uri="http://www.php.net/license">PHP</license> <notes> * First release in over 2.5 years (!) * MANY bugfixes (see the bugtracker) * added a few tests </notes> </release> <release> <version> <release>1.3.0</release> <api>1.3.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2005-04-01</date> <license uri="http://www.php.net/license">PHP</license> <notes> * First (stable) release in over 2.5 years (!) * MANY bugfixes (see the bugtracker) * added a few tests * one small fix after RC1 (bug #3940) </notes> </release> <release> <version> <release>1.3.1</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2005-07-13</date> <license uri="http://www.php.net/license">PHP</license> <notes> </notes> </release> <release> <version> <release>1.4.0a1</release> <api>1.3.1</api> </version> <stability> <release>alpha</release> <api>stable</api> </stability> <date>2007-03-08</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license> <notes> * Changed License to BSD Style license, as that's what the code was since the beginning [cipri] * Fix Bug #30: Mail_Mime: _encodeHeaders is not RFC-2047 compliant. [cipri] * Fix Bug #3513: support of RFC2231 in header fields. [cipri] * Fix Bug #4696: addAttachment crash [cipri] * Fix Bug #5333: Only variables should be returned by reference; triggers notices since php 4.4.0 [cipri] * Fix Bug #7561: Mail_mimePart::_quotedPrintableEncode() misbehavior with mbstring overload [cipri] * Fix Bug #8223: Incorrectly encoded quoted-printable headers [cipri] * Fix Bug #8386: HTML body not correctly encoded if attachments present [cipri] * Fix Bug #8541: mimePart.php line delimiter is \r [cipri] * Fix Bug #9347: Notices about references [cweiske] * Fix Bug #9558: Broken multiline headers [cipri] * Fix Bug #9956: Notices being thrown [cipri] * Fix Bug #9976: Subject encoded twice [cipri] * Implement Feature #2952: Mail_mime::headers() saves extra headers [cipri] * Implement Feature #3636: Allow specification of charsets and encoding [cipri] * Implement Feature #4057: Mail_Mime: Add name parameter for Content-Type [cipri] * Implement Feature #4504: addHTMLImage does not work in cases when filename contains a path [cipri] * Implement Feature #5837: Mail_Mime: Build message for Net_SMTP [cipri] * Implement Feature #5934: Mail_Mime: choice for content disposition [cipri] * Implement Feature #6568: Mail_Mime: inline images referenced in CSS definitions not replaced. [cipri] </notes> </release> <release> <version> <release>1.4.0a2</release> <api>1.3.1</api> </version> <stability> <release>alpha</release> <api>stable</api> </stability> <date>2007-04-05</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license> <notes> * Fix Bug #9722: _quotedPrintableEncode does not encode dot at start of line on Windows platform [cipri] * Fix Bug #9725: multipart/related & alternative wrong order [cipri] * Fix Bug #10146: mbstring fails to recognize encodings. [cipri] * Fix Bug #10158: Inline images not displayed on Mozilla Thunderbird [cipri] * Fix Bug #10298: Mail_mime, double Quotes and Specialchars in from and to Adress [cipri] * Fix Bug #10306: Strings with Double Quotes get encoded wrongly [cipri] * Fix Bug #10596: Incorrect handling of text and html '0' bodies [cipri] </notes> </release> <release> <version> <release>1.4.0a3</release> <api>1.3.1</api> </version> <stability> <release>alpha</release> <api>stable</api> </stability> <date>2007-04-05</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license> <notes> * Fix Bug #10298: Mail_mime, double Quotes and Specialchars in from and to Adress [cipri] * Fix Bug #10306: Strings with Double Quotes get encoded wrongly [cipri] </notes> </release> <release> <version> <release>1.4.0RC1</release> <api>1.3.1</api> </version> <stability> <release>beta</release> <api>stable</api> </stability> <date>2007-04-12</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license> <notes> * Fix Bug #10232: Gmail creates double line break when \r\n is used [cipri] </notes> </release> <release> <version> <release>1.4.0RC2</release> <api>1.3.1</api> </version> <stability> <release>beta</release> <api>stable</api> </stability> <date>2007-04-22</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license> <notes> * Fix Bug #10791: Unit tests fail [cipri] * Fix Bug #10792: No unit tests for recently fixed bugs [cipri] * Fix Bug #10793: Long headers don't get wrapped since fix for Bug #10298 [cipri] </notes> </release> <release> <version> <release>1.4.0RC3</release> <api>1.3.1</api> </version> <stability> <release>beta</release> <api>stable</api> </stability> <date>2007-04-24</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license> <notes> * Fix Bug #10816: Unwanted linebreak at the end of output [cipri] </notes> </release> <release> <version> <release>1.4.0RC4</release> <api>1.3.1</api> </version> <stability> <release>beta</release> <api>stable</api> </stability> <date>2007-04-28</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license> <notes> * Fix Bug #3513: support of RFC2231 in header fields. [cipri] * Fix Bug #10838: bad use of MIME encoding in header. [cipri] </notes> </release> <release> <version> <release>1.4.0</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2007-05-05</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Release notes: * No more notices in PHP 5 /4.4.0. * Improved inline HTML image function. * Improved header encoding with foreign charsets. * Improved long header rendering. * More control over used Charsets and encoding schemes. * More configurable attachments and inline images. * Full RFC 2047 Support * Full RFC 2231 Support * Unit-tests Fixed bugs: * Fix Bug #30: Mail_Mime: _encodeHeaders is not RFC-2047 compliant. [cipri] * Fix Bug #3513: support of RFC2231 in header fields. [cipri] * Fix Bug #4696: addAttachment crash [cipri] * Fix Bug #5333: Only variables should be returned by reference; triggers notices since php 4.4.0 [cipri] * Fix Bug #5400: Do not return function reference [cipri] * Fix Bug #5710: Little reference bugs [cipri] * Fix Bug #5890: Only variable references should be returned by reference [cipri] * Fix Bug #6260: Just a notice with PHP5 [cipri] * Fix Bug #6261: php 5.1.1 upgrade [cipri] * Fix Bug #6663: Notice about reference passing [cipri] * Fix Bug #7561: Mail_mimePart::_quotedPrintableEncode() misbehavior with mbstring overload [cipri] * Fix Bug #7713: PHP5 Notice: Only variable references should be returned by reference [cipri] * Fix Bug #8223: Incorrectly encoded quoted-printable headers [cipri] * Fix Bug #8386: HTML body not correctly encoded if attachments present [cipri] * Fix Bug #8541: mimePart.php line delimiter is \r [cipri] * Fix Bug #8812: user header updates overwritten [cipri] * Fix Bug #9347: Notices about references [cweiske] * Fix Bug #9558: Broken multiline headers [cipri] * Fix Bug #9722: _quotedPrintableEncode does not encode dot at start of line on Windows platform [cipri] * Fix Bug #9725: multipart/related & alternative wrong order [cipri] * Fix Bug #9956: Notices being thrown [cipri] * Fix Bug #9976: Subject encoded twice [cipri] * Fix Bug #10146: mbstring fails to recognize encodings. [cipri] * Fix Bug #10158: Inline images not displayed on Mozilla Thunderbird [cipri] * Fix Bug #10232: Gmail creates double line break when \r\n is used [cipri] * Fix Bug #10298: Mail_mime, double Quotes and Specialchars in from and to Adress [cipri] * Fix Bug #10306: Strings with Double Quotes get encoded wrongly [cipri] * Fix Bug #10596: Incorrect handling of text and html '0' bodies [cipri] * Fix Bug #10791: Unit tests fail [cipri] * Fix Bug #10792: No unit tests for recently fixed bugs [cipri] * Fix Bug #10793: Long headers don't get wrapped since fix for Bug #10298 [cipri] * Fix Bug #10816: Unwanted linebreak at the end of output [cipri] * Fix Bug #10838: bad use of MIME encoding in header. [cipri] Implemented Features: * Implement Feature #2952: Mail_mime::headers() saves extra headers [cipri] * Implement Feature #3636: Allow specification of charsets and encoding [cipri] * Implement Feature #4057: Mail_Mime: Add name parameter for Content-Type [cipri] * Implement Feature #4504: addHTMLImage does not work in cases when filename contains a path [cipri] * Implement Feature #5837: Mail_Mime: Build message for Net_SMTP [cipri] * Implement Feature #5934: Mail_Mime: choice for content disposition [cipri] * Implement Feature #6568: Mail_Mime: inline images referenced in CSS definitions not replaced. [cipri] * Implement Feature #10604: Put an option to specify Content-Location in the header [cipri] </notes> </release> <release> <version> <release>1.5.0a1</release> <api>1.3.1</api> </version> <stability> <release>alpha</release> <api>stable</api> </stability> <date>2007-06-10</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Split off mail_MimeDecode </notes> </release> <release> <version> <release>1.5.0RC1</release> <api>1.3.1</api> </version> <stability> <release>beta</release> <api>stable</api> </stability> <date>2007-06-10</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Split off mail_MimeDecode </notes> </release> <release> <version> <release>1.5.0</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2007-06-17</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Split off Mail_MimeDecode </notes> </release> <release> <version> <release>1.5.1</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2007-06-20</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix Bug #11344: Error at line 644 in mime.php [cipri] </notes> </release> <release> <version> <release>1.5.2</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2007-06-21</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix Bug #11381: domain name is attached to content-id, trailing greater-than sign is not remove [cipri] </notes> </release> <release> <version> <release>1.5.3</release> <api>1.3.2</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2009-12-29</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Fixed bugs: * Fix Bug #14678: srand() lowers security [clockwerx] * Fix Bug #12921: _file2str not binary safe [walter] * Fix Bug #12385: Bad regex when replacing css style attachments [cipri] * Fix Bug #16911: Excessive semicolon in MIME header [alec] * Fix Bug #15320: Attachment charset is not set in Content-Type header [alec] * Fix Bug #16911: Lack of semicolon separator for MIME header parameters [alec] * Fix Bug #16846: Use preg_replace_callback() instead of /e modifier [alec] * Fix Bug #14779: Problem with an empty attachment [alec] * Fix Bug #15913: Optimize the memory used by Mail_mimePart::encode. Avoid having attachments data duplicated in memory [alec] * Fix Bug #16539: Headers longer than 998 characters aren't wrapped [alec] * Fix Bug #11238: Wrong encoding of structured headers [alec] * Fix Bug #13641: iconv_mime_encode() seems to work different/errorious than the build in logic. Removed 'ignore_iconv' param. [alec] * Fix Bug #16706: Incorrect double-quotes RFC 2231-encoded parameter values [alec] * Fix Bug #14232: RFC2231: tspecials encoding in _buildHeaderParam() [alec] Implemented Features: * Implement Feature #10438: Function (encodeHeader) for encoding of given header [alec] </notes> </release> <release> <version> <release>1.6.0</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2010-01-27</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Bugs Fixed: * Don't break specified headers folding [alec] * Bug #17025: Wrong headers() result for long unwrapable header value [alec] Implemented Features: * Allow setting Content-ID for HTML Images [alec] * Added one setParam() in place of many set*() functions [alec] * Added getParam(), getTXTBody(), getHTMLBody() [alec] * Skip RFC2231's charset if filename contains only ASCII characters [alec] * Make sure that Received: headers are returned on the top [alec] * Added saveMessageBody() and getMessageBody() functions [alec] </notes> </release> <release> <version> <release>1.6.1</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2010-03-08</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Bugs Fixed: * Fix encoding of Return-Receipt-To and Disposition-Notification-To headers [alec] Implemented Features: * Implement Feature #12466: Build parameters validation [alec] * Implement Feature #17175: Content-Description support for attachments [alec] </notes> </release> <release> <version> <release>1.6.2</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2010-03-23</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Bugs Fixed: * Fix Bug #17226: Non RFC-compliant quoted-printable encoding of structured headers [alec] </notes> </release> <release> <version> <release>1.7.0</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2010-04-12</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Implemented Features: * Added Mail_mime::setContentType() function with possibility to set various types in Content-Type header (also fixes problem with boundary parameter when Content-Type header was specified by user) [alec] </notes> </release> <release> <date>2010-07-29</date> <version> <release>1.8.0</release> <api>1.4.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Bugs Fixed: * Double-addition of e-mail domain to content ID in HTML images [alec] * #17311: Multi-octet characters are split across adjacent 'encoded-word's [alec] * #17573: Place charset parameter in first line of Content-Type header (if possible) [alec] Implemented Features: * #17518: addTo() method [alec] </notes> </release> <release> <date>2010-12-01</date> <version> <release>1.8.1</release> <api>1.4.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Bugs Fixed: * #18083: Not possible to set separate charset for attachment content and headers [alec] </notes> </release> <release> <date>2011-08-10</date> <version> <release>1.8.2</release> <api>1.4.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Bugs Fixed: * #18426: Fixed backward compatibility for "dfilename" parameter [alec] * Removed xmail.dtd, xmail.xsl from the package [alec] * Fixed handling of email addresses with quoted local part [alec] </notes> </release> <release> <date>2012-03-12</date> <version> <release>1.8.3</release> <api>1.4.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Request #19009: Remove error_reporting from tests [alec] * Fixed Bug #19094: Email addresses do not have to contain a space between the name and address part [alec] * Fixed Bug #19328: Wrong encoding of filenames with comma [alec] </notes> </release> <release> <date>2012-05-17</date> <version> <release>1.8.4</release> <api>1.4.2</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Request #19406: Allow to set individual attachment part headers [alec] * Fixed Bug #18982: Non-static method Mail_mimePart::encodeHeader() should not be called statically [alec] </notes> </release> <release> <date>2012-06-09</date> <version> <release>1.8.5</release> <api>1.4.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Added possibility to set additional parameters of message part header, e.g. attachment size [alec] * Added automatic setting of attachment size via Content-Disposition header size parameter [alec] </notes> </release> <release> <date>2012-10-23</date> <version> <release>1.8.6</release> <api>1.4.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Bug #19473: PEAR::isError() compatibility problem with PHP 5.4 [alec] * Bug #19497: Attachment filename is cut on slash character [alec] * Bug #19665: Add Mail-Reply-To and Mail-Followup-To to structured recipient headers list [alec] </notes> </release> <release> <date>2012-12-25</date> <version> <release>1.8.7</release> <api>1.4.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Bug #5333: Fix more return by reference errors [alec] * Bug #19754: Fix compatibility with PHP4 [alec] </notes> </release> <release> <date>2013-07-05</date> <version> <release>1.8.8</release> <api>1.4.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fixed warning/notice on (static vs. non-static) PEAR::raiseError() usage [alec] * Fixed Bug #19761: PHP5 warnings about return by reference [alec] * Fixed Bug #19770: Make cid generator more unique on Windows [alec] * Fixed Bug #19987: E_STRICT warning when null is passed by reference [alec] </notes> </release> <release> <date>2014-05-14</date> <version> <release>1.8.9</release> <api>1.4.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fixed Bug #20273: Incorrect handling of HTAB in encodeHeader() [alec] * Fixed Bug #20226: Mail_mimePart::encodeHeader does not encode ISO-2022-JP string [alec] * Fixed Bug #20222: Broken Compatybility with PHP4 [alec] </notes> </release> <release> <date>2015-07-05</date> <time>12:50:00</time> <version> <release>1.9.0RC1</release> <api>2.0.0</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Drop PHP4 support, Fix warnings on PHP7 [alec] * Request #20564: Added possibility to unset headers [alec] * Request #20563: Added isMultipart() method [alec] * Request #20565: Accept also a file pointer in Mail_mimePart::encodeToFile(), Mail_mime::get() and Mail_mime::saveMessageBody() [alec] </notes> </release> <release> <date>2015-08-06</date> <time>12:00:00</time> <version> <release>1.9.0</release> <api>1.9.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Bug #20921: Make Mail_mimePart::encodeHeaderValue() a static method [alec] * Bug #20931: Really remove unset headers [alec] * Request #18772: Added methods for creating text/calendar messages [alec] </notes> </release> <release> <date>2015-09-13</date> <time>12:00:00</time> <version> <release>1.10.0</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Add possibility to add externally created Mail_mimePart objects as attachments [alec] * Add possibility to set preamble text for multipart messages [alec] </notes> </release> <release> <date>2017-05-21</date> <time>12:00:00</time> <version> <release>1.10.1</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix Bug 21206: explodeQuotedString() does not handle quoted strings correctly [dfukagaw28] * Fix Bug 21205: Invalid encoding of headers with quoted multibyte strings in non-unicode charset [dfukagaw28] * Fix Bug 21098: Discrepancy in handling of empty (but set) plain text part [alec] </notes> </release> <release> <date>2017-11-17</date> <time>11:00:00</time> <version> <release>1.10.2</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix Bug #21255: Boundary gets added twice when using setContentType() [alec] * PHP 7.2 compatibility fixes [alec] </notes> </release> <release> <date>2019-09-25</date> <time>08:00:00</time> <version> <release>1.10.3</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix deprecation warning for get_magic_quotes_runtime() use on PHP 7.4 [alec] </notes> </release> <release> <date>2019-10-13</date> <time>11:00:00</time> <version> <release>1.10.4</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix E_STRICT errors introduced in the previous release [alec] </notes> </release> <release> <date>2020-01-24</date> <time>19:00:00</time> <version> <release>1.10.5</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Make sure to not set Content-Transfer-Encoding on multipart messages [alec] * Added support for calendar invitations with attachments/html/images [jacalben] </notes> </release> <release> <date>2020-01-30</date> <time>08:25:00</time> <version> <release>1.10.6</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix different boundary in headers and body when using headers() after get() [alec] * Removed phail.php script [alec] </notes> </release> <release> <date>2020-03-01</date> <time>08:50:00</time> <version> <release>1.10.7</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix invalid Content-Type for messages with only html part and inline images [alec] </notes> </release> <release> <date>2020-06-13</date> <time>08:50:00</time> <version> <release>1.10.8</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Fix encoding issues with ISO-2022-JP-MS input labelled with ISO-2022-JP [shirosaki] </notes> </release> <release> <date>2020-06-27</date> <time>10:30:00</time> <version> <release>1.10.9</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Added a workaround for an opcache bug on OpenSuse 15.1 [alec] </notes> </release> <release> <date>2021-01-17</date> <time>09:25:00</time> <version> <release>1.10.10</release> <api>1.10.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> * Compatibility fixes for PHP 5.2 and 5.3 [alec] * Corrected soft line breaks handling to be RFC compliant [ixs] * Corrected line breaks for lines ending in dots and length more than 74 [ixs] </notes> </release> </changelog> </package> PK�������!�7pK��K����.pkgxml/XML_Util.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.5" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>XML_Util</name> <channel>pear.php.net</channel> <summary>XML utility class</summary> <description>Selection of methods that are often needed when working with XML documents. Functionality includes creating of attribute lists from arrays, creation of tags, validation of XML names and more.</description> <lead> <name>Chuck Burgess</name> <user>ashnazg</user> <email>ashnazg@php.net</email> <active>yes</active> </lead> <lead> <name>Stephan Schmidt</name> <user>schst</user> <email>schst@php-tools.net</email> <active>no</active> </lead> <helper> <name>Davey Shafik</name> <user>davey</user> <email>davey@php.net</email> <active>no</active> </helper> <date>2020-04-19</date> <time>14:54:10</time> <version> <release>1.4.5</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> * PR #12: fix Trying to access array offset on value of type int </notes> <contents> <dir baseinstalldir="/" name="/"> <file baseinstalldir="/" md5sum="af2746028ae4395f549855a5e444ada7" name="examples/example.php" role="doc" /> <file baseinstalldir="/" md5sum="b9e52f4aa372c4067c609f49c2285b8f" name="examples/example2.php" role="doc" /> <file baseinstalldir="/" md5sum="d0af9354df0962e70e9e2215b5611b9c" name="tests/AbstractUnitTests.php" role="test" /> <file baseinstalldir="/" md5sum="57ce547d64d6e1f2986c313407deffef" name="tests/ApiVersionTests.php" role="test" /> <file baseinstalldir="/" md5sum="2d0427db94790df7ada24a744547edf5" name="tests/AttributesToStringTests.php" role="test" /> <file baseinstalldir="/" md5sum="673d1438c4718a70c5da3fe019027db4" name="tests/CollapseEmptyTagsTests.php" role="test" /> <file baseinstalldir="/" md5sum="46b981f91edd163f1cd021cfef5d1bb1" name="tests/CreateCDataSectionTests.php" role="test" /> <file baseinstalldir="/" md5sum="6aa925b879572e9b3f1885b7cdbb223b" name="tests/CreateCommentTests.php" role="test" /> <file baseinstalldir="/" md5sum="dbc083b62a020fa245fde5a7828a4806" name="tests/CreateEndElementTests.php" role="test" /> <file baseinstalldir="/" md5sum="f58e38343ecf60811c842d4cfc8194ae" name="tests/CreateStartElementTests.php" role="test" /> <file baseinstalldir="/" md5sum="9385fba272f4ebccf4c95d43d16dcff4" name="tests/CreateTagTests.php" role="test" /> <file baseinstalldir="/" md5sum="51e7ba1390e6dadc3c0be0c960bf171d" name="tests/CreateTagFromArrayTests.php" role="test" /> <file baseinstalldir="/" md5sum="6bbb54ef4cf56dc2c0b558b295de5668" name="tests/GetDocTypeDeclarationTests.php" role="test" /> <file baseinstalldir="/" md5sum="825b440b0ee8abd10b4df017c08bf15f" name="tests/GetXmlDeclarationTests.php" role="test" /> <file baseinstalldir="/" md5sum="e6783bb330f8f2ae7225f02d56f194e4" name="tests/IsValidNameTests.php" role="test" /> <file baseinstalldir="/" md5sum="b273525b905ae6d5fc53adcb3ce0b8d9" name="tests/RaiseErrorTests.php" role="test" /> <file baseinstalldir="/" md5sum="20befbef5e55639539336761a17c64f3" name="tests/ReplaceEntitiesTests.php" role="test" /> <file baseinstalldir="/" md5sum="a3ceff3302e31f90130be01c312b33b3" name="tests/ReverseEntitiesTests.php" role="test" /> <file baseinstalldir="/" md5sum="aeb95108896180ef77a7dce3c310a3b8" name="tests/SplitQualifiedNameTests.php" role="test" /> <file baseinstalldir="/" md5sum="e93010b1eff68f889fefcb006bf20b63" name="tests/Bug4950Tests.php" role="test" /> <file baseinstalldir="/" md5sum="748ffb640e13e7b960385c7e12413782" name="tests/Bug5392Tests.php" role="test" /> <file baseinstalldir="/" md5sum="01e68b66e27a6fdb197d572c67ae6bc5" name="tests/Bug18343Tests.php" role="test" /> <file baseinstalldir="/" md5sum="d945220c38344bc773b18244439bb0cc" name="tests/Bug21177Tests.php" role="test" /> <file baseinstalldir="/" md5sum="af2672bb90875c2e00f93f563bfafe70" name="tests/Bug21184Tests.php" role="test" /> <file baseinstalldir="/" md5sum="0db6fa9c169bf6904aa7e588c2325a13" name="XML/Util.php" role="php"> <tasks:replace from="@version@" to="version" type="package-info" /> </file> </dir> </contents> <dependencies> <required> <php> <min>5.4.0</min> </php> <pearinstaller> <min>1.9.0</min> </pearinstaller> <extension> <name>pcre</name> </extension> </required> </dependencies> <phprelease /> <changelog> <release> <version> <release>0.1</release> <api>0.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-08-01</date> <license uri="http://www.php.net/license">PHP License</license> <notes> inital release </notes> </release> <release> <version> <release>0.1.1</release> <api>0.1.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-08-02</date> <license uri="http://www.php.net/license">PHP License</license> <notes> bugfix: removed bug in createTagFromArray </notes> </release> <release> <version> <release>0.2</release> <api>0.2</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-08-12</date> <license uri="http://www.php.net/license">PHP License</license> <notes> added XML_Util::getDocTypeDeclaration() </notes> </release> <release> <version> <release>0.2.1</release> <api>0.2.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-09-05</date> <license uri="http://www.php.net/license">PHP License</license> <notes> fixed bug with zero as tag content in createTagFromArray and createTag </notes> </release> <release> <version> <release>0.3</release> <api>0.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-09-12</date> <license uri="http://www.php.net/license">PHP License</license> <notes> added createStartElement() and createEndElement() </notes> </release> <release> <version> <release>0.4</release> <api>0.4</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-09-21</date> <license uri="http://www.php.net/license">PHP License</license> <notes> added createCDataSection(), added support for CData sections in createTag* methods, fixed bug #23, fixed bug in splitQualifiedName() </notes> </release> <release> <version> <release>0.5</release> <api>0.5</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-09-23</date> <license uri="http://www.php.net/license">PHP License</license> <notes> added support for multiline attributes in attributesToString(), createTag*() and createStartElement (requested by Yavor Shahpasov for XML_Serializer), added createComment </notes> </release> <release> <version> <release>0.5.1</release> <api>0.5.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-09-26</date> <license uri="http://www.php.net/license">PHP License</license> <notes> added default namespace parameter (optional) in splitQualifiedName() (requested by Sebastian Bergmann) </notes> </release> <release> <version> <release>0.5.2</release> <api>0.5.2</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-11-22</date> <license uri="http://www.php.net/license">PHP License</license> <notes> now creates XHTML compliant empty tags (Davey), minor whitespace fixes (Davey) </notes> </release> <release> <version> <release>0.6.0beta1</release> <api>0.6.0beta1</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <date>2004-05-24</date> <license uri="http://www.php.net/license">PHP License</license> <notes> - Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey) - added optional parameter to replaceEntities() to define the set of entities to replace - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann) - allowed second parameter to XML_Util::attributesToString() to be an array containing options (easier to use, if you only need to set the last parameter) - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error </notes> </release> <release> <version> <release>0.6.0</release> <api>0.6.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2004-06-07</date> <license uri="http://www.php.net/license">PHP License</license> <notes> - Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey) - added optional parameter to replaceEntities() to define the set of entities to replace - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann) - allowed second parameter to XML_Util::attributesToString() to be an array containing options (easier to use, if you only need to set the last parameter) - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error </notes> </release> <release> <version> <release>0.6.1</release> <api>0.6.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2004-10-28</date> <license uri="http://www.php.net/license">PHP License</license> <notes> - Added check for tag name (either as local part or qualified name) in createTagFromArray() (bug #1083) </notes> </release> <release> <version> <release>1.0.0</release> <api>1.0.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2004-10-28</date> <license uri="http://www.php.net/license">PHP License</license> <notes> - Added reverseEntities() (request #2639) </notes> </release> <release> <version> <release>1.1.0</release> <api>1.1.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2004-11-19</date> <license uri="http://www.php.net/license">PHP License</license> <notes> - Added collapseEmptyTags (patch by Sebastian Bergmann and Thomas Duffey) </notes> </release> <release> <version> <release>1.1.1</release> <api>1.1.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2004-12-23</date> <license uri="http://www.php.net/license">PHP License</license> <notes> - fixed bug in replaceEntities() and reverseEntities() in conjunction with XML_UTIL_ENTITIES_HTML - createTag() and createTagFromArray() now accept XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML, XML_UTIL_ENTITIES_NONE and XML_UTIL_CDATA_SECTION as $replaceEntities parameter </notes> </release> <release> <version> <release>1.1.2</release> <api>1.1.2</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2006-12-01</date> <license uri="http://www.php.net/license">PHP License</license> <notes> - fixed bug #5419: isValidName() now checks for character classes - implemented request #8196: added optional parameter to influence array sorting to createTag() createTagFromArray() and createStartElement() </notes> </release> <release> <version> <release>1.1.4</release> <api>1.1.4</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2006-12-16</date> <license uri="http://www.php.net/license">PHP License</license> <notes> - Fixed bug #9561: Not allowing underscores in middle of tags </notes> </release> <release> <version> <release>1.2.0a1</release> <api>1.2.0</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <date>2008-05-04</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|ja.doma] </notes> </release> <release> <version> <release>1.2.0a2</release> <api>1.2.0</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <date>2008-05-22</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry] Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry] -- (this fix differs from the one in v1.2.0a1) </notes> </release> <release> <version> <release>1.2.0RC1</release> <api>1.2.0</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <date>2008-07-12</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry] Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry] -- (this fix differs from the one in v1.2.0a1) </notes> </release> <release> <version> <release>1.2.0</release> <api>1.2.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2008-07-26</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> Changed license to New BSD License (Req #13826 [ashnazg]) Added a test suite against all API methods [ashnazg] Switch to package.xml v2 [ashnazg] Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry] Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg] Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry] -- (this fix differs from the one in v1.2.0a1) </notes> </release> <release> <version> <release>1.2.1</release> <api>1.2.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2011-12-31</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> Fixed Bug #14760: Bug in getDocTypeDeclaration() [ashnazg|fpospisil] </notes> </release> <release> <version> <release>1.2.2</release> <api>1.2.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2014-06-07</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> QA release Bug #18343 Entities in file names decoded during packaging Bug #19174 upgrade PHPUnit require statements & other fixes (for PEAR QA Team) Request #19750 examples/example.php encoding </notes> </release> <release> <version> <release>1.2.3</release> <api>1.2.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2014-06-07</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> Bug #20293 Broken installation for 1.2.2 </notes> </release> <release> <version> <release>1.3.0</release> <api>1.3.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2015-02-27</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> * Set minimum PHP version to 5.3.0 * Mark static methods with static keyword </notes> </release> <release> <version> <release>1.4.0</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2017-02-03</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> * Set minimum PHP version to 5.4.0 * Set minimum PEAR version to 1.10.1 * Adds a new XML_UTIL_COLLAPSE_NONE option for preventing empty tag collapsing. * Request #15467 CDATA sections and blank nodes </notes> </release> <release> <version> <release>1.4.1</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2017-02-07</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> * Bug #21177 XML_Util::collapseEmptyTags() can return NULL </notes> </release> <release> <version> <release>1.4.2</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2017-02-22</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> * Bug #21184 Collapse issue </notes> </release> <release> <version> <release>1.4.3</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2017-06-28</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> * Decrease minimum PEAR version to 1.9.0 to allow PEAR upgrades </notes> </release> <release> <version> <release>1.4.4</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2019-12-05</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> * PR #11: fix phplint warning </notes> </release> <release> <version> <release>1.4.5</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2020-04-19</date> <license uri="http://opensource.org/licenses/bsd-license">BSD License</license> <notes> * PR #12: fix Trying to access array offset on value of type int </notes> </release> </changelog> </package> PK�������!�%ONO����&��.pkgxml/Pear_Mail_mimeDecode-1.5.6.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>Mail_mimeDecode</name> <channel>pear.php.net</channel> <summary>Provides a class to decode mime messages.</summary> <description>Provides a class to deal with the decoding and interpreting of mime messages. This package used to be part of the Mail_Mime package, but has been split off.</description> <lead> <name>Cipriano Groenendal</name> <user>cipri</user> <email>cipri@php.net</email> <active>yes</active> </lead> <lead> <name>Alan Knowles</name> <user>alan_k</user> <email>alan@akbkhome.com</email> <active>yes</active> </lead> <developer> <name>George Schlossnagle</name> <user>gschlossnagle</user> <email>george@omniti.com</email> <active>no</active> </developer> <date>2016-08-29</date> <time>03:04:25</time> <version> <release>1.5.6</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Minor Bug fix release. #20431 - support for android #19762 - multipart signed not split correctly on line breaks #20027 - replace /e with preg_replace_callback #19762 - multipart/signed eating of new line, and expose sig_hdr etc. </notes> <contents> <dir baseinstalldir="/" name="/"> <file baseinstalldir="/" md5sum="05c45d0b58718ebe73860ebfe494dcef" name="Mail/mimeDecode.php" role="php" /> <file baseinstalldir="Mail" md5sum="642acc06cdb217b6e64506182449d8f8" name="tests/parse_header_value.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="a0bc0c9b68e62a19202bd8fb26104f3c" name="tests/semicolon_content_type_bug1724.phpt" role="test" /> <file baseinstalldir="Mail" md5sum="194810c478066eaeb28f51116b88e25a" name="xmail.dtd" role="data" /> <file baseinstalldir="Mail" md5sum="61cea06fb6b4bd3a4b5e2d37384e14a9" name="xmail.xsl" role="data" /> </dir> </contents> <dependencies> <required> <php> <min>4.3.0</min> </php> <pearinstaller> <min>1.6.0</min> </pearinstaller> <package> <name>Mail_Mime</name> <channel>pear.php.net</channel> <min>1.4.0</min> <exclude>1.4.0</exclude> </package> </required> </dependencies> <phprelease /> <changelog> <release> <version> <release>0.1.0</release> <api>1.3.1</api> </version> <stability> <release>alpha</release> <api>stable</api> </stability> <date>2007-06-10</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Initial Release </notes> </release> <release> <version> <release>1.0.0RC1</release> <api>1.3.1</api> </version> <stability> <release>beta</release> <api>stable</api> </stability> <date>2007-06-10</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Initial Release </notes> </release> <release> <date>2007-06-17</date> <time>17:20:44</time> <version> <release>1.5.0</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> First release of mail_mimeDecode as a seperate package. </notes> </release> <release> <date>2009-12-03</date> <version> <release>1.5.1</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Minor Bugfix release. Bug Fixes #----- - fix bug in getSendArray() - not handling multiple recipents #14129 - E_NOTICE fixes Requests #12365 - Add option to also include raw attached messages patched on the request of till </notes> </release> <release> <date>2010-09-02</date> <version> <release>1.5.2</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Minor Bugfix release. Bug Fixes #4739 - regexp parsing of header values does not balance quoting correctly - Fix sponsored by http://webyog.com #17325 - empty body messages are valid messages #17276 - remove &new usage which throws errors now </notes> </release> <release> <date>2010-09-05</date> <version> <release>1.5.3</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Major Bugfix release. Apart from a major cleanout of the bug tracker for this package, this release includes a revamped parseHeaderValue which removes the rather flakey regex, with a real parser, which should be considerably more robust. Bug Fixes #17844 - all regression tests fixed - remove the last of the while list each() .. this is 2010 ;)... #11410 - support wap multipart #9616 - long strings as filename etc.. aaa*0=.... aaa*1=.... aaa*2=.... (merged into aaa=.....) #9100 - change to preg_split for mime boundary detection , in theory should catch boundaries in nested situations better... #7709 - check for last element on boundary split to see if its usable #7065 - wrapped header lines with encoding should be concated without spaces #6495 - missing body in decoded object #11537 - better decode and multi-line support </notes> </release> <release> <date>2010-09-14</date> <version> <release>1.5.4</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Critical Security release. It is highly recommended that users of 1.5.3 upgrade to this release, a change in the boundary detection code introduced a potential denial of service attack. Bug Fixes #17862 - quote boundary preg_split code </notes> </release> <release> <version> <release>1.5.5</release> <api>1.3.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2011-11-16</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license> <notes> Minor Bug fix release. #17959 - Boundaries ending with non-word characters - patch by Alex Adriaanese ------ - ignore whitespace and trailing cr/lf in last section of split ------ - correct spacing on multi-line headers. now only striped for encoded data. (on previous line) </notes> </release> </changelog> </package> PK�������!�0$-��-�� ��.pkgxml/Pear_File_MARC-1.4.1.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>File_MARC</name> <channel>pear.php.net</channel> <summary>Parse, modify, and create MARC records</summary> <description>The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records. This package is based on the PHP MARC package, originally called "php-marc", that is part of the Emilda Project (http://www.emilda.org). Christoffer Landtman generously agreed to make the "php-marc" code available under the GNU LGPL so it could be used as the basis of this PEAR package.</description> <lead> <name>Dan Scott</name> <user>dbs</user> <email>dbs@php.net</email> <active>yes</active> </lead> <date>2019-11-13</date> <time>17:33:33</time> <version> <release>1.4.1</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</license> <notes> 1.4.1 * Reintroduce include_path to composer.json </notes> <contents> <dir baseinstalldir="File" name="/"> <file baseinstalldir="/" md5sum="ffe2590635f404af055fe731da105939" name="File/MARC/Lint/CodeData.php" role="php" /> <file baseinstalldir="/" md5sum="a3b9e1c817e67f59add05593500d463e" name="File/MARC/Control_Field.php" role="php" /> <file baseinstalldir="/" md5sum="acba4463f8e40d6ee4e7ba1f2dc53123" name="File/MARC/Data_Field.php" role="php" /> <file baseinstalldir="/" md5sum="378f483ec1fd161cd9dfb9b05db58d66" name="File/MARC/Exception.php" role="php" /> <file baseinstalldir="/" md5sum="a9ba69030cbf4847292b9975e9d922c6" name="File/MARC/Field.php" role="php" /> <file baseinstalldir="/" md5sum="c37351c7c80927ce6bb1e662510f9183" name="File/MARC/Lint.php" role="php" /> <file baseinstalldir="/" md5sum="c5ac39e3d25eb0108b9dd5ad8466c821" name="File/MARC/List.php" role="php" /> <file baseinstalldir="/" md5sum="7af6ce78cde4bb246e4e96709e90d2c0" name="File/MARC/Record.php" role="php" /> <file baseinstalldir="/" md5sum="df5f97139685f0ad04e47fdbb67e3968" name="File/MARC/Subfield.php" role="php" /> <file baseinstalldir="/" md5sum="6e102262dfd5d65d8d5a6221dfc74edd" name="File/MARC.php" role="php" /> <file baseinstalldir="/" md5sum="8b64040d2d18ac4b994595a148266a66" name="File/MARCBASE.php" role="php" /> <file baseinstalldir="/" md5sum="f5a17a60d34e84e2ee7ca1e5c5c6c620" name="File/MARCXML.php" role="php" /> <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="examples/example.mrc" role="doc" /> <file baseinstalldir="File" md5sum="1aea40df9f1c2e32f8e065fe8da0a3b5" name="examples/marc_yaz.php" role="doc" /> <file baseinstalldir="File" md5sum="70ae317e0890d5896e3ffccdd293369a" name="examples/read.php" role="doc" /> <file baseinstalldir="File" md5sum="54efb9d920ac775bfc847a83a2dec73a" name="examples/subfields.php" role="doc" /> <file baseinstalldir="File" md5sum="14297da35b510c496cd1f328cf3bb301" name="tests/bad_example.mrc" role="test" /> <file baseinstalldir="File" md5sum="0dd4c6dbad6e8608d0ebf9d24425955d" name="tests/bad_example.xml" role="test" /> <file baseinstalldir="File" md5sum="216a6f9d53f6d3d8e22d81fdc10f4bc1" name="tests/camel.mrc" role="test" /> <file baseinstalldir="File" md5sum="6af971fd9ff5ef3e5fcba8a64a0e7a49" name="tests/example.mrc" role="test" /> <file baseinstalldir="File" md5sum="9455aec3371f79cf7d31281fd03f5171" name="tests/marc_001.phpt" role="test" /> <file baseinstalldir="File" md5sum="577e2f5f89fd48cf1a3576a29d2958f8" name="tests/marc_002.phpt" role="test" /> <file baseinstalldir="File" md5sum="a6a586354b9a06c880c2a7470dd828d7" name="tests/marc_003.phpt" role="test" /> <file baseinstalldir="File" md5sum="b1c7e2fc5572a0f9362a771c260a1fe3" name="tests/marc_004.phpt" role="test" /> <file baseinstalldir="File" md5sum="84f85ac7f8a2532e4e90ccde7764556a" name="tests/marc_005.phpt" role="test" /> <file baseinstalldir="File" md5sum="889e5e906a97de7a0e94b0c5f30e70e7" name="tests/marc_006.phpt" role="test" /> <file baseinstalldir="File" md5sum="be823dc8a8efb408de06371ab802efcc" name="tests/marc_007.phpt" role="test" /> <file baseinstalldir="File" md5sum="af44490aafea44e5120f881cb81cdad9" name="tests/marc_008.phpt" role="test" /> <file baseinstalldir="File" md5sum="ac9f2a7aeb24900a11f5102744179ae3" name="tests/marc_009.phpt" role="test" /> <file baseinstalldir="File" md5sum="5e43eb5cddbb4f2bd0d6405cd95b80aa" name="tests/marc_010.phpt" role="test" /> <file baseinstalldir="File" md5sum="2e1cd8509c0bf04ec77fc0f51375f611" name="tests/marc_011.phpt" role="test" /> <file baseinstalldir="File" md5sum="bc49ca48623102c8ac07679fa77a3dd9" name="tests/marc_012.phpt" role="test" /> <file baseinstalldir="File" md5sum="245a3b20e0da1973535503e28efd1d3a" name="tests/marc_013.phpt" role="test" /> <file baseinstalldir="File" md5sum="ce69aa734856dd40d60d30c77bdef53a" name="tests/marc_014.phpt" role="test" /> <file baseinstalldir="File" md5sum="7b61cdd31035e60682fa92c5d519d997" name="tests/marc_015.phpt" role="test" /> <file baseinstalldir="File" md5sum="7f4f597fe1adaa3507eb87fc4875dbd2" name="tests/marc_016.phpt" role="test" /> <file baseinstalldir="File" md5sum="4262efd5fcacbd7503323681f4552430" name="tests/marc_017.phpt" role="test" /> <file baseinstalldir="File" md5sum="ee1623d7bda54ba4f741b2319b158f82" name="tests/marc_018.phpt" role="test" /> <file baseinstalldir="File" md5sum="8006c03fbab0f04377342086fafd3982" name="tests/marc_019.phpt" role="test" /> <file baseinstalldir="File" md5sum="f5ae5b25e0ac1104314433d9e5b1f7fe" name="tests/marc_020.phpt" role="test" /> <file baseinstalldir="File" md5sum="94d8f99e86585671a1b2d3043aeb6360" name="tests/marc_021.phpt" role="test" /> <file baseinstalldir="File" md5sum="bb891a890effe0e77e1759043f4846d8" name="tests/marc_022.phpt" role="test" /> <file baseinstalldir="File" md5sum="faf77dcb5cdd002c09169a14bfded65e" name="tests/marc_023.phpt" role="test" /> <file baseinstalldir="File" md5sum="0e6c4a23f5da7df64fdd4b3b1149bbee" name="tests/marc_16783.phpt" role="test" /> <file baseinstalldir="File" md5sum="4ea8b3520beda378db15960f1c50493a" name="tests/marc_field_001.phpt" role="test" /> <file baseinstalldir="File" md5sum="743850ef61df69c4340be44a03bccb5a" name="tests/marc_field_002.phpt" role="test" /> <file baseinstalldir="File" md5sum="8c765f1398b49df257d86d22ac6e4f8d" name="tests/marc_field_003.phpt" role="test" /> <file baseinstalldir="File" md5sum="d4216cf930a308e0d02553bd3914f294" name="tests/marc_field_004.phpt" role="test" /> <file baseinstalldir="File" md5sum="dd59514b474b78371ad522a3e13b76b7" name="tests/marc_field_005.phpt" role="test" /> <file baseinstalldir="File" md5sum="5295bfd02a8424acac1c91de26b552c7" name="tests/marc_field_21246.phpt" role="test" /> <file baseinstalldir="File" md5sum="6f95f09442ccf6b93df92986f58b270d" name="tests/marc_lint_001.phpt" role="test" /> <file baseinstalldir="File" md5sum="18d721f8871edd925624ccbdd15444fb" name="tests/marc_lint_002.phpt" role="test" /> <file baseinstalldir="File" md5sum="4eb86a2f4e0a74dedcb0bf2511da6ca1" name="tests/marc_lint_003.phpt" role="test" /> <file baseinstalldir="File" md5sum="10430fee0a1352d0528f1507b34c57e1" name="tests/marc_lint_004.phpt" role="test" /> <file baseinstalldir="File" md5sum="0dcd07a18577d7b22392a2214cd6436c" name="tests/marc_lint_005.phpt" role="test" /> <file baseinstalldir="File" md5sum="fd17798fc535562e5e64461f449516b2" name="tests/marc_record_001.phpt" role="test" /> <file baseinstalldir="File" md5sum="141b455ccf67a60c4eac44c77960f2e2" name="tests/marc_subfield_001.phpt" role="test" /> <file baseinstalldir="File" md5sum="b1e23464ee0eec47ddca2af9a9922926" name="tests/marc_subfield_002.phpt" role="test" /> <file baseinstalldir="File" md5sum="1d7903e8c244d647220b318b4bc758d1" name="tests/marc_xml_001.phpt" role="test" /> <file baseinstalldir="File" md5sum="22cae3c752d843b78f583dcd92801534" name="tests/marc_xml_002.phpt" role="test" /> <file baseinstalldir="File" md5sum="c0716d23e0f960abf8d53ad6014a413a" name="tests/marc_xml_003.phpt" role="test" /> <file baseinstalldir="File" md5sum="7645fa19e28aca041a124fc5e2c12bd3" name="tests/marc_xml_004.phpt" role="test" /> <file baseinstalldir="File" md5sum="b08b28c3251625b8b6e4d7ab376b0185" name="tests/marc_xml_005.phpt" role="test" /> <file baseinstalldir="File" md5sum="6cd0934ddbf65d2d7e9ea5d108977ff7" name="tests/marc_xml_006.phpt" role="test" /> <file baseinstalldir="File" md5sum="ffdce4aa190268fa7cbbf3bb45383abf" name="tests/marc_xml_007.phpt" role="test" /> <file baseinstalldir="File" md5sum="998a4c1ce00ff100f39ffa9fc49a212f" name="tests/marc_xml_008.phpt" role="test" /> <file baseinstalldir="File" md5sum="a38a67c590869f2b0a4859a910fd9e89" name="tests/marc_xml_009.phpt" role="test" /> <file baseinstalldir="File" md5sum="db39c5055a570fcda12bb7c5fa1e3b4d" name="tests/marc_xml_16642.phpt" role="test" /> <file baseinstalldir="File" md5sum="dc075f4a271bd7182378a3874bd5b39e" name="tests/marc_xml_namespace.phpt" role="test" /> <file baseinstalldir="File" md5sum="208200d9a979ac360c4d326e9789b6b7" name="tests/marc_xml_namespace_prefix.phpt" role="test" /> <file baseinstalldir="File" md5sum="d87774ede82222cfc12b2c2a06f57a3a" name="tests/marc_xml_rsinger.phpt" role="test" /> <file baseinstalldir="File" md5sum="fb44e3eb69f1a37115235fc829c39542" name="tests/namespace.xml" role="test" /> <file baseinstalldir="File" md5sum="e6de4d809b0af5dd99fd352eb60616a1" name="tests/skipif.inc" role="test" /> <file baseinstalldir="File" md5sum="a0166a4ff0bc0bb283e854f11beaa793" name="tests/music.mrc" role="test" /> <file baseinstalldir="File" md5sum="993ce494befbc25dc1326527b30b4782" name="tests/music.xml" role="test" /> <file baseinstalldir="File" md5sum="6b0c87f0cd459ed7322c25d403b164cc" name="tests/bigarchive.xml" role="test" /> <file baseinstalldir="File" md5sum="be850aa6ab4ac52b8c6c214c30b574af" name="tests/onerecord.xml" role="test" /> <file baseinstalldir="File" md5sum="4f43fec7b276267eec5258044853ccc8" name="tests/sandburg.mrc" role="test" /> <file baseinstalldir="File" md5sum="e216b95f905dd240c9bde372950e4073" name="tests/sandburg.xml" role="test" /> <file baseinstalldir="File" md5sum="e81a92188ea0dcd9c108a63fb32b3f4f" name="tests/xmlescape.mrc" role="test" /> <file baseinstalldir="File" md5sum="8f9f63ed6a80191d89a2296fa4c1a30b" name="CHANGELOG" role="doc" /> <file baseinstalldir="File" md5sum="fbc093901857fcd118f065f900982c24" name="LICENSE" role="doc" /> </dir> </contents> <dependencies> <required> <php> <min>5.6</min> </php> <pearinstaller> <min>1.4.0</min> </pearinstaller> </required> <optional> <package> <name>Validate_ISPN</name> <channel>pear.php.net</channel> </package> </optional> </dependencies> <phprelease /> </package> PK�������!�#r �� �� ��.pkgxml/Pear_Net_SMTP-1.10.0.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.12" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>Net_SMTP</name> <channel>pear.php.net</channel> <summary>An implementation of the SMTP protocol</summary> <description>Provides an implementation of the SMTP protocol using PEAR's Net_Socket class.</description> <lead> <name>Jon Parise</name> <user>jon</user> <email>jon@php.net</email> <active>yes</active> </lead> <lead> <name>Chuck Hagenbuch</name> <user>chagenbu</user> <email>chuck@horde.org</email> <active>yes</active> </lead> <date>2021-03-19</date> <time>18:39:33</time> <version> <release>1.10.0</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="https://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license> <notes> * Add the starttls() method </notes> <contents> <dir baseinstalldir="/" name="/"> <file baseinstalldir="/" md5sum="5ef820d1bc73898b55a153576953fe70" name="examples/basic.php" role="doc" /> <file baseinstalldir="/" md5sum="0cd9a0c35d1ea17d46de9b5a39fb771d" name="tests/auth.phpt" role="test" /> <file baseinstalldir="/" md5sum="89135826a107455d336071f3570ccd13" name="tests/basic.phpt" role="test" /> <file baseinstalldir="/" md5sum="8517c458ae5094ee3c31a545d51c69c8" name="tests/config.php.dist" role="test" /> <file baseinstalldir="/" md5sum="15c9cb4ef93e0aee232b503e12fc21ee" name="tests/quotedata.phpt" role="test" /> <file baseinstalldir="/" md5sum="00f931f5dd61430e6057f895decdb6af" name="LICENSE" role="doc" /> <file baseinstalldir="/" md5sum="9ddd7d9135cfe6e573cd757edf6855f2" name="README.rst" role="doc" /> <file baseinstalldir="/" md5sum="a157897ae2efc43eabd961597557243a" name="Net/SMTP.php" role="php" /> </dir> </contents> <dependencies> <required> <php> <min>5.4.0</min> </php> <pearinstaller> <min>1.10.1</min> </pearinstaller> <package> <name>Net_Socket</name> <channel>pear.php.net</channel> <min>1.0.7</min> </package> </required> <optional> <package> <name>Auth_SASL</name> <channel>pear.php.net</channel> <min>1.0.5</min> </package> </optional> </dependencies> <phprelease /> </package> PK�������!�Q?��?�� ��.pkgxml/Pear_Net_Sieve-1.4.5.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.12" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>Net_Sieve</name> <channel>pear.php.net</channel> <summary>Handles talking to a sieve server.</summary> <description>This package provides an API to talk to servers implementing the managesieve protocol. It can be used to install and remove sieve scripts, mark them active etc.</description> <lead> <name>Aleksander Machniak</name> <user>alec</user> <email>alec@alec.pl</email> <active>yes</active> </lead> <lead> <name>Jan Schneider</name> <user>yunosh</user> <email>jan@horde.org</email> <active>no</active> </lead> <lead> <name>Richard Heyes</name> <user>richard</user> <email>richard@php.net</email> <active>no</active> </lead> <lead> <name>Damian Fernandez Sosa</name> <user>damian</user> <email>damlists@cnba.uba.ar</email> <active>no</active> </lead> <lead> <name>Anish Mistry</name> <user>amistry</user> <email>amistry@am-productions.biz</email> <active>no</active> </lead> <date>2021-04-24</date> <time>13:33:52</time> <version> <release>1.4.5</release> <api>1.4.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Support XOAUTH2 authorization method </notes> <contents> <dir baseinstalldir="Net" name="/"> <file baseinstalldir="Net" md5sum="ef8cd688674fba85cc067e06c221e43b" name="tests/largescript.siv" role="test" /> <file baseinstalldir="Net" md5sum="7d772fe47ee45bdb521dd581281f38c3" name="tests/config.php.dist" role="test" /> <file baseinstalldir="Net" md5sum="6050fac5e66a4a6bbed7913f826974ed" name="tests/SieveTest.php" role="test" /> <file baseinstalldir="Net" md5sum="2a45a03c042351957f3435929a17bca3" name="Sieve.php" role="php"> <tasks:replace from="@package_version@" to="version" type="package-info" /> </file> </dir> </contents> <dependencies> <required> <php> <min>5.0.0</min> </php> <pearinstaller> <min>1.4.0b1</min> </pearinstaller> <package> <name>Net_Socket</name> <channel>pear.php.net</channel> <min>1.0</min> </package> </required> <optional> <package> <name>Auth_SASL</name> <channel>pear.php.net</channel> <min>1.0</min> </package> </optional> </dependencies> <phprelease /> <changelog> <release> <date>2018-03-04</date> <version> <release>1.4.3</release> <api>1.4.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Support GSSAPI authentication </notes> </release> <release> <date>2018-02-14</date> <version> <release>1.4.2</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Composer: Fix license identifier, don't use unbound version numbers for deps </notes> </release> <release> <date>2017-05-26</date> <version> <release>1.4.1</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Use 8bit instead of latin1 for string length in bytes calculation * Extend listScripts() so it's possible to get an active script name in one go * Request #20491: Skip redundant CAPABILITY requests </notes> </release> <release> <date>2017-05-21</date> <version> <release>1.4.0</release> <api>1.4.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Dropped PHP4 support, fixed PHP7 warnings * Fixed E_DEPRECATED warning on Auth_SASL::factory() call * Enable later TLS versions </notes> </release> <release> <date>2015-01-20</date> <version> <release>1.3.4</release> <api>1.3.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Remove erroneous and unnecessary active script caching (Bug #20472). </notes> </release> <release> <date>2014-09-24</date> <version> <release>1.3.3</release> <api>1.3.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fix notices from non-static calling of PEAR methods. * Fix reading OK responses with string literal messages. </notes> </release> <release> <date>2011-08-06</date> <version> <release>1.3.2</release> <api>1.3.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fix referrals if host data or user credentials are passed to connect() and login() instead of the constructor (Aleksander Machniak, Bug #17107). </notes> </release> <release> <date>2011-08-05</date> <version> <release>1.3.1</release> <api>1.3.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Query capabilities again after successful authentication (Jesse Crawford, Request #18382). * Escape quotes and backslashes in script names, and use literal strings for script names with non-ASCII characters (Aleksander Machniak, Bug #16691). * Work around broken STARTTLS behavior in Cyrus versions before 2.3.10 (Aleksander Machniak, Bug #18241). * Improve string literal parsing (Aleksander Machniak, Bug #18228). </notes> </release> <release> <date>2010-07-01</date> <version> <release>1.3.0</release> <api>1.3.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Add debug handler parameter to constructor. * Fix LOGIN authentication (Agustín Eijo, Aleksander Machniak, Bug #17527). </notes> </release> <release> <date>2010-06-13</date> <version> <release>1.2.2</release> <api>1.2.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fix SASL authentication without Auth_SASL (Bug #17489). </notes> </release> <release> <date>2010-04-19</date> <version> <release>1.2.1</release> <api>1.2.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fix DIGEST-MD5 authentication with Dovecot (Stef Simoens, Bug #17320). </notes> </release> <release> <date>2010-04-01</date> <version> <release>1.2.0</release> <api>1.2.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> Changes since version 1.2.0b1: * Fix DIGEST-MD5 authentication (Aleksander Machniak, Bug #17285). * Don't try to call dl() if mbstring extension isn't loaded (Bug #17038). Changes since version 1.1.7: * Added support for adding a custom debug handler (Aleksander Machniak, Request #16681). * Fix breakage with certain locales, especially Turkish. * Fix reading authentication responses without literals (Bug #16647). * Code cleanup. </notes> </release> <release> <date>2009-10-07</date> <version> <release>1.2.0b1</release> <api>1.2.0</api> </version> <stability> <release>beta</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Added support for adding a custom debug handler (Aleksander Machniak, Request #16681). * Fix breakage with certain locales, especially Turkish. * Fix reading authentication responses without literals (Bug #16647). * Code cleanup. </notes> </release> <release> <date>2009-07-24</date> <version> <release>1.1.7</release> <api>1.1.6</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed STARTTLS support (Bug #14205). * Added connect options and EXTERNAL authentication. </notes> </release> <release> <date>2008-03-22</date> <version> <release>1.1.6</release> <api>1.1.6</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed Bug #9273 * Fixed copy/paste error in CRAM and DIGEST authentication error case. </notes> </release> <release> <date>2006-10-24</date> <version> <release>1.1.5</release> <api>1.1.5</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed Bug connect() bug * Fixed Request #8071 </notes> </release> <release> <date>2006-09-09</date> <version> <release>1.1.4</release> <api>1.1.4</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed Bug #8452 Unterminated read loop * Fixed Bug #7845 Add mbstring support * Added Request #8071 Enable the ability to toggle TLS support if available. * Added Request #8453 Clean up PHPDoc and comments </notes> </release> <release> <date>2006-05-21</date> <version> <release>1.1.3</release> <api>1.1.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Correctly Fixed Bug #3519 Net_Sieve w/ externally established sockets * Fixed Bug #7197 getScript() truncates long scripts * Added PHPUnit2 regression test script </notes> </release> <release> <date>2006-02-09</date> <version> <release>1.1.2</release> <api>1.1.2</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed Request #4053 Added STARTTLS support for PHP 5.1 and above * Fixed Bug #3519 Net_Sieve w/ externally established sockets * Fixed Bug #4794 drops protocol prefix, e.g. "ssl://" in referrals * Fixed STARTTLS detection * Allow $options[] to be passed to Net_Socket </notes> </release> <release> <version> <release>1.1.1</release> <api>1.1.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2005-02-02</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed Bug #3242 cyrus murder referrals not followed </notes> </release> <release> <version> <release>1.1.0</release> <api>1.1.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2004-12-18</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed Bug #2728 Linebreaks not being read using getScript() </notes> </release> <release> <version> <release>1.0.1</release> <api>1.0.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2004-03-13</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed BUG #1006 </notes> </release> <release> <version> <release>1.0.0</release> <api>1.0.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2004-03-10</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed DIGEST-MD5 sasl version handling (sasl v1.xx responses are diferent than v2.xx) * Fixed LOGIN Method </notes> </release> <release> <version> <release>0.9.1</release> <api>0.9.1</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <date>2004-02-29</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * There is an issue whith the DIGEST-MD5 method. in one installation it does not work but in my server it works perfect! please send me debug info to solve the problem if it affects you or disable DIGEST-MD5 * some optimizations to the code * added haveSpace() to check if the server has space to store the script. Use with care HAVESPACE seems to be broken in cyrus 2.0.16 * added hasExtension() * added getExtensions() * added referral support and automatic following of them. (it also handles the following of multireferrals). * removed _getResponse replaced by _doCmd. (thanks to Etienne Goyer for this) * added supportsAuthMech() * if installed automatically uses Auth_SASL * added CRAM-MD5 auth Method * added DIGEST-MD5 auth Method * added getAuthMechs() returns an array containing all the auth methods the server supports * added hasAuthMech() to check if the server has a particular auth method * _connect --> connect: now is a public method (without breaking BC) * _login --> login: now is a public method (without breaking BC) * fix typo cmdAuthenticate() ---> _cmdAuthenticate() * _doCmd() now parses string responses also. </notes> </release> <release> <version> <release>0.9.0</release> <api>0.9.0</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <date>2004-01-31</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Added setDebug() method and debugging capabilities * added disconnect() method * added sample file test_sieve.php * fixed bug #591 * automagically selects the best auth method </notes> </release> <release> <version> <release>0.8.1</release> <api>0.8.1</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <date>2002-07-27</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> Initial release </notes> </release> <release> <version> <release>0.8</release> <api>0.8</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <date>2002-05-10</date> <license uri="http://www.php.net/license">PHP</license> <notes> Initial release </notes> </release> <release> <date>2018-09-09</date> <version> <release>1.4.4</release> <api>1.4.2</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fix PHP 7.3: Declaration of case-insensitive constants is deprecated </notes> </release> </changelog> </package> PK�������!�c���� ��.pkgxml/Pear_Auth_SASL-1.1.0.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.3" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>Auth_SASL</name> <channel>pear.php.net</channel> <summary>Abstraction of various SASL mechanism responses</summary> <description>Provides code to generate responses to common SASL mechanisms, including: - Digest-MD5 - Cram-MD5 - Plain - Anonymous - Login (Pseudo mechanism) - SCRAM</description> <lead> <name>Anish Mistry</name> <user>amistry</user> <email>amistry@am-productions.biz</email> <active>no</active> </lead> <lead> <name>Richard Heyes</name> <user>richard</user> <email>richard@php.net</email> <active>no</active> </lead> <lead> <name>Michael Bretterklieber</name> <user>mbretter</user> <email>michael@bretterklieber.com</email> <active>no</active> </lead> <date>2017-03-07</date> <time>14:04:34</time> <version> <release>1.1.0</release> <api>1.1.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Set minimum PHP version to 5.4.0 * Set minimum PEAR version to 1.10.1 * Request #21033: PHP warning depreciated </notes> <contents> <dir name="/"> <file md5sum="60f7b5ba4d05fe0e518292963b14bddb" name="Auth/SASL/Anonymous.php" role="php" /> <file md5sum="c2c817e4775b6f63f07ddb0c9cbd88b5" name="Auth/SASL/Common.php" role="php" /> <file md5sum="c6b3b3a4e0aec6a4e0728732ef6babc9" name="Auth/SASL/CramMD5.php" role="php" /> <file md5sum="509e431141489a77a991401d64f15e9e" name="Auth/SASL/DigestMD5.php" role="php" /> <file md5sum="1d7478dd9dc5734ec9e16c158dcb6f76" name="Auth/SASL/External.php" role="php" /> <file md5sum="3a0abcf277374b24262807150451b55e" name="Auth/SASL/Login.php" role="php" /> <file md5sum="bde1dcf2780d042c1de12e20a696e945" name="Auth/SASL/Plain.php" role="php" /> <file md5sum="e99f9f71abc36d64ca8e17ad6e5e7631" name="Auth/SASL/SCRAM.php" role="php" /> <file md5sum="b93e37947e1dd90e5fb639a1734f7a71" name="Auth/SASL.php" role="php" /> </dir> </contents> <dependencies> <required> <php> <min>5.4.0</min> </php> <pearinstaller> <min>1.10.1</min> </pearinstaller> </required> </dependencies> <phprelease /> <changelog> <release> <version> <release>1.1.0</release> <api>1.1.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2017-03-07</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Set minimum PHP version to 5.4.0 * Set minimum PEAR version to 1.10.1 * Request #21033: PHP warning depreciated </notes> </release> <release> <version> <release>1.0.6</release> <api>1.0.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2011-09-27</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> QA release * Bug #18856: Authentication warnings because of wrong Auth_SASL::factory argument [kguest] </notes> </release> <release> <version> <release>1.0.5</release> <api>1.0.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2011-09-04</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> QA release * Added support for any mechanism of the SCRAM family; with thanks to Jehan Pagès. [kguest] * crammd5 and digestmd5 mechanisms name deprecated in favour of IANA registered names 'cram-md5' and 'digest-md5'; with thanks to Jehan Pagès. [kguest] </notes> </release> <release> <version> <release>1.0.4</release> <api>1.0.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2010-02-07</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> QA release * Fix bug #16624: open_basedir restriction warning in DigestMD5.php [till] </notes> </release> <release> <version> <release>1.0.3</release> <api>1.0.3</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2009-08-05</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> QA release * Move SVN to proper directory structure [cweiske] * Fix Bug #8775: Error in package.xml * Fix Bug #14671: Security issue due to seeding random number generator [cweiske] </notes> </release> <release> <version> <release>1.0.2</release> <api>1.0.2</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2006-05-21</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Fixed Bug #2143 Auth_SASL_DigestMD5::getResponse() generates invalid response * Fixed Bug #6611 Suppress PHP 5 Notice Errors * Fixed Bug #2154 realm isn't contained in challange </notes> </release> <release> <version> <release>1.0.1</release> <api>1.0.1</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <date>2003-09-11</date> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license> <notes> * Added authcid/authzid separation in PLAIN and DIGEST-MD5. </notes> </release> </changelog> </package> PK�������!�zWzD ��D �� ��.pkgxml/Pear_Net_IDNA2-0.2.0.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.3" version="2.0" xmlns="https://pear.php.net/dtd/package-2.0" xmlns:tasks="https://pear.php.net/dtd/tasks-1.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://pear.php.net/dtd/tasks-1.0 https://pear.php.net/dtd/tasks-1.0.xsd https://pear.php.net/dtd/package-2.0 https://pear.php.net/dtd/package-2.0.xsd"> <name>Net_IDNA2</name> <channel>pear.php.net</channel> <summary>Punycode encoding and decoding.</summary> <description>This package helps you to encode and decode punycode strings easily.</description> <lead> <name>Stefan Neufeind</name> <user>neufeind</user> <email>pear.neufeind@speedpartner.de</email> <active>yes</active> </lead> <lead> <name>Daniel O'Connor</name> <user>doconnor</user> <email>daniel.oconnor@gmail.com</email> <active>no</active> </lead> <date>2017-03-06</date> <time>20:40:58</time> <version> <release>0.2.0</release> <api>0.2.0</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <license uri="https://www.gnu.org/copyleft/lesser.html">LGPL</license> <notes> * Set minimum PHP version to 5.4.0 * Set minimum PEAR version to 1.10.1 * Bug #19375: Add static to the fuction getInstance * Bug #21123: Signing the source package </notes> <contents> <dir baseinstalldir="/" name="/"> <file baseinstalldir="/" md5sum="41766020ff8f63f695c9bf7e86040e70" name="Net/IDNA2.php" role="php" /> <file baseinstalldir="/" md5sum="72f605f2f6d9d56e07bb6bcec099d03a" name="Net/IDNA2/Exception.php" role="php" /> <file baseinstalldir="/" md5sum="06c4217024082f0f3b6c5a7e61ac7130" name="Net/IDNA2/Exception/Nameprep.php" role="php" /> <file baseinstalldir="/" md5sum="999210e6bd489aba06e5121a2788956f" name="tests/Net_IDNA2Test.php" role="test" /> <file baseinstalldir="/" md5sum="2996ea57df9e5e3153da8a94fbb3c603" name="tests/draft-josefsson-idn-test-vectors.php" role="test" /> </dir> </contents> <dependencies> <required> <php> <min>5.4.0</min> </php> <pearinstaller> <min>1.10.1</min> </pearinstaller> </required> </dependencies> <phprelease /> <changelog> <release> <version> <release>0.1.0</release> <api>0.1.0</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <date>2010-06-03</date> <license uri="https://www.gnu.org/copyleft/lesser.html">LGPL</license> <notes> QA Release Bug #17430 Multiple Net_IDNA class declarations Warning: This package is now split between Net_IDNA (php4) and Net_IDNA2 (php5) </notes> </release> <release> <version> <release>0.2.0</release> <api>0.2.0</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <date>2017-03-06</date> <license uri="https://www.gnu.org/copyleft/lesser.html">LGPL</license> <notes> * Set minimum PHP version to 5.4.0 * Set minimum PEAR version to 1.10.1 * Bug #19375: Add static to the fuction getInstance * Bug #21123: Signing the source package </notes> </release> </changelog> </package> PK�������!���������.pkgxml/Pear.listnu�[��������pear.php.net/Auth_SASL pear.php.net/File_MARC pear.php.net/Mail pear.php.net/Mail_Mime pear.php.net/Mail_mimeDecode pear.php.net/Net_IDNA2 pear.php.net/Net_SMTP pear.php.net/Net_Sieve pear.php.net/Net_Socket pear.php.net/Structures_LinkedList PK�������!�3-��-��,��.pkgxml/Pear_Structures_LinkedList-0.2.2.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.9.0" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>Structures_LinkedList</name> <channel>pear.php.net</channel> <summary>Implements singly and doubly-linked lists</summary> <description>A singly-linked list offers the ability to insert or delete nodes at any point within the list. A doubly-linked list also offers the ability to request previous nodes in the list.</description> <lead> <name>Dan Scott</name> <user>dbs</user> <email>dbs@php.net</email> <active>yes</active> </lead> <date>2010-08-15</date> <time>10:13:00</time> <version> <release>0.2.2</release> <api>0.2.0</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <license uri="http://apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</license> <notes> * Fix package layout </notes> <contents> <dir baseinstalldir="Structures/LinkedList" name="/"> <file baseinstalldir="/" md5sum="b7ac5a9d6d9a3eb2c3cbb1db76ad75a3" name="Structures/LinkedList/Double.php" role="php" /> <file baseinstalldir="/" md5sum="310eefdff99016e4a3282dd02d5a7efa" name="Structures/LinkedList/Single.php" role="php" /> <file baseinstalldir="Structures/LinkedList" md5sum="9b1565a45687bb631a452b152e0d3d15" name="examples/double_link_example.php" role="doc" /> <file baseinstalldir="Structures/LinkedList" md5sum="56d8c9a65cf967f09136a1b5b42fb787" name="examples/single_link_example.php" role="doc" /> <file baseinstalldir="Structures/LinkedList" md5sum="54a63c64625c0b1785d890cc0ecb6957" name="tests/LinkTester.php" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="6138a89189609d8b0c35a69ce6995457" name="tests/SingleLinkTester.php" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="c7a6ad89f79222cf62148893e88a0b5a" name="tests/link_001.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="960408b3ea85cfe453f7d4b1814784ea" name="tests/link_002.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="392d4c38523f764091433fdf19cf4943" name="tests/link_003.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="88bfd20fe97800c4f69ec7577abd2ecd" name="tests/link_004.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="dac8403b1df9d64e16e45e87121a74fa" name="tests/link_005.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="bfc84666dbe64008101adadecf008677" name="tests/link_006.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="1a7eb8c8a63ec97fdb0154214c679cfa" name="tests/link_007.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="86f0c12acf2706a82d0d0dc625ab3608" name="tests/single_link_001.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="19c3e9b406dffe9c315e0264e0d257f8" name="tests/single_link_002.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="d4029576a49c41f18c35f72bdb37da7e" name="tests/single_link_003.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="574cb63523d7716f37fad368eefc695b" name="tests/single_link_004.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="4712a8421da2369e72ec789e0fe3993f" name="tests/single_link_005.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="a7f31515a9a3260aa1c17e003a4c352c" name="tests/single_link_006.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="6fe94be57c862475367ed91a7284a6b2" name="tests/single_link_007.phpt" role="test" /> <file baseinstalldir="Structures/LinkedList" md5sum="6e8edc55d5a37acbe96ed9860b8680cc" name="CHANGELOG" role="doc" /> <file baseinstalldir="Structures/LinkedList" md5sum="3b83ef96387f14655fc854ddc3c6bd57" name="LICENSE" role="doc" /> </dir> </contents> <dependencies> <required> <php> <min>5.0</min> </php> <pearinstaller> <min>1.4.0</min> </pearinstaller> </required> </dependencies> <phprelease /> </package> PK�������!�Z2iH��H����.pkgxml/Pear_Mail-1.4.1.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.3" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>Mail</name> <channel>pear.php.net</channel> <summary>Class that provides multiple interfaces for sending emails</summary> <description>PEAR's Mail package defines an interface for implementing mailers under the PEAR hierarchy. It also provides supporting functions useful to multiple mailer backends. Currently supported backends include: PHP's native mail() function, sendmail, and SMTP. This package also provides a RFC822 email address list validation utility class.</description> <lead> <name>Chuck Hagenbuch</name> <user>chagenbu</user> <email>chuck@horde.org</email> <active>no</active> </lead> <developer> <name>Richard Heyes</name> <user>richard</user> <email>richard@phpguru.org</email> <active>no</active> </developer> <developer> <name>Aleksander Machniak</name> <user>alec</user> <email>alec@alec.pl</email> <active>yes</active> </developer> <date>2017-04-11</date> <time>17:26:44</time> <version> <release>1.4.1</release> <api>1.3.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> <license uri="https://opensource.org/licenses/BSD-3-Clause">New BSD License</license> <notes> * Loosen recognition of "queued as" server response (PR #10) * Bug #20463: domain-literal parsing error * Bug #20513: Mail_smtp::send() doesn't close socket for smtp connection </notes> <contents> <dir baseinstalldir="/" name="/"> <file baseinstalldir="/" md5sum="8210c33901d415a2692944291632bf34" name="LICENSE" role="doc" /> <file baseinstalldir="/" md5sum="4e86cd3b980f73ef320988a1b299ee07" name="Mail/mail.php" role="php" /> <file baseinstalldir="/" md5sum="360b7b613c98c7703151c50a6e74c367" name="Mail/mock.php" role="php" /> <file baseinstalldir="/" md5sum="30ce63a4a2c4558b3752b1c302e6e508" name="Mail/null.php" role="php" /> <file baseinstalldir="/" md5sum="7199f4e7b07919082a804edb8680c811" name="Mail/RFC822.php" role="php" /> <file baseinstalldir="/" md5sum="5dd0b6ff126608818f44f5866b61b3d0" name="Mail/sendmail.php" role="php" /> <file baseinstalldir="/" md5sum="1d236356d52f3dfa13b740a48a821586" name="Mail/smtp.php" role="php" /> <file baseinstalldir="/" md5sum="853b55cf4803df8caaaa0dca363971ff" name="Mail/smtpmx.php" role="php" /> <file baseinstalldir="/" md5sum="3077f0c01f72cc29a6f8f0175e7fc8a7" name="Mail.php" role="php" /> <file baseinstalldir="/" md5sum="d66aa2a2f0bfe33f8a67d749a1a4d345" name="tests/9137.phpt" role="test" /> <file baseinstalldir="/" md5sum="75d10361f686f1cc16637a9364e3eab7" name="tests/9137_2.phpt" role="test" /> <file baseinstalldir="/" md5sum="63715aad2b5b3ae35c6b05acf04d9ad7" name="tests/13659.phpt" role="test" /> <file baseinstalldir="/" md5sum="e99f00d8f07232e0f129dd77ae9699c7" name="tests/bug17178.phpt" role="test" /> <file baseinstalldir="/" md5sum="c2036980390981cd6b89c1e5c903913e" name="tests/bug17317.phpt" role="test" /> <file baseinstalldir="/" md5sum="7b0eae971fe7595e7c1a563fbfcfee90" name="tests/rfc822.phpt" role="test" /> <file baseinstalldir="/" md5sum="67becdb1027cefcb8dff1b691da630ab" name="tests/smtp_error.phpt" role="test" /> </dir> </contents> <dependencies> <required> <php> <min>5.2.1</min> </php> <pearinstaller> <min>1.5.6</min> </pearinstaller> </required> <optional> <package> <name>Net_SMTP</name> <channel>pear.php.net</channel> <min>1.4.1</min> </package> </optional> </dependencies> <phprelease /> </package> PK�������!�kK)��)����.registry/mail.regnu�[��������a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:6:"1.10.3";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:4:"Mail";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:58:"Class that provides multiple interfaces for sending emails";s:11:"description";s:337:"PEAR's Mail package defines an interface for implementing mailers under the PEAR hierarchy. It also provides supporting functions useful to multiple mailer backends. Currently supported backends include: PHP's native mail() function, sendmail, and SMTP. This package also provides a RFC822 email address list validation utility class.";s:4:"lead";a:4:{s:4:"name";s:15:"Chuck Hagenbuch";s:4:"user";s:8:"chagenbu";s:5:"email";s:15:"chuck@horde.org";s:6:"active";s:2:"no";}s:9:"developer";a:2:{i:0;a:4:{s:4:"name";s:13:"Richard Heyes";s:4:"user";s:7:"richard";s:5:"email";s:19:"richard@phpguru.org";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:19:"Aleksander Machniak";s:4:"user";s:4:"alec";s:5:"email";s:12:"alec@alec.pl";s:6:"active";s:3:"yes";}}s:4:"date";s:10:"2017-04-11";s:4:"time";s:8:"17:26:44";s:7:"version";a:2:{s:7:"release";s:5:"1.4.1";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:44:"https://opensource.org/licenses/BSD-3-Clause";}s:8:"_content";s:15:"New BSD License";}s:5:"notes";s:177:"* Loosen recognition of "queued as" server response (PR #10) * Bug #20463: domain-literal parsing error * Bug #20513: Mail_smtp::send() doesn't close socket for smtp connection";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:16:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8210c33901d415a2692944291632bf34";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4e86cd3b980f73ef320988a1b299ee07";s:4:"name";s:13:"Mail/mail.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"360b7b613c98c7703151c50a6e74c367";s:4:"name";s:13:"Mail/mock.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"30ce63a4a2c4558b3752b1c302e6e508";s:4:"name";s:13:"Mail/null.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7199f4e7b07919082a804edb8680c811";s:4:"name";s:15:"Mail/RFC822.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5dd0b6ff126608818f44f5866b61b3d0";s:4:"name";s:17:"Mail/sendmail.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1d236356d52f3dfa13b740a48a821586";s:4:"name";s:13:"Mail/smtp.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"853b55cf4803df8caaaa0dca363971ff";s:4:"name";s:15:"Mail/smtpmx.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3077f0c01f72cc29a6f8f0175e7fc8a7";s:4:"name";s:8:"Mail.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d66aa2a2f0bfe33f8a67d749a1a4d345";s:4:"name";s:15:"tests/9137.phpt";s:4:"role";s:4:"test";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"75d10361f686f1cc16637a9364e3eab7";s:4:"name";s:17:"tests/9137_2.phpt";s:4:"role";s:4:"test";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"63715aad2b5b3ae35c6b05acf04d9ad7";s:4:"name";s:16:"tests/13659.phpt";s:4:"role";s:4:"test";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e99f00d8f07232e0f129dd77ae9699c7";s:4:"name";s:19:"tests/bug17178.phpt";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c2036980390981cd6b89c1e5c903913e";s:4:"name";s:19:"tests/bug17317.phpt";s:4:"role";s:4:"test";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7b0eae971fe7595e7c1a563fbfcfee90";s:4:"name";s:17:"tests/rfc822.phpt";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"67becdb1027cefcb8dff1b691da630ab";s:4:"name";s:21:"tests/smtp_error.phpt";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.2.1";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.5.6";}}s:8:"optional";a:1:{s:7:"package";a:3:{s:4:"name";s:8:"Net_SMTP";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.1";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:16:{s:7:"LICENSE";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8210c33901d415a2692944291632bf34";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:46:"/opt/alt/php52/usr/share/doc/pear/Mail/LICENSE";}s:13:"Mail/mail.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4e86cd3b980f73ef320988a1b299ee07";s:4:"name";s:13:"Mail/mail.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php52/usr/share/pear/Mail/mail.php";}s:13:"Mail/mock.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"360b7b613c98c7703151c50a6e74c367";s:4:"name";s:13:"Mail/mock.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php52/usr/share/pear/Mail/mock.php";}s:13:"Mail/null.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"30ce63a4a2c4558b3752b1c302e6e508";s:4:"name";s:13:"Mail/null.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php52/usr/share/pear/Mail/null.php";}s:15:"Mail/RFC822.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7199f4e7b07919082a804edb8680c811";s:4:"name";s:15:"Mail/RFC822.php";s:4:"role";s:3:"php";s:12:"installed_as";s:45:"/opt/alt/php52/usr/share/pear/Mail/RFC822.php";}s:17:"Mail/sendmail.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5dd0b6ff126608818f44f5866b61b3d0";s:4:"name";s:17:"Mail/sendmail.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php52/usr/share/pear/Mail/sendmail.php";}s:13:"Mail/smtp.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1d236356d52f3dfa13b740a48a821586";s:4:"name";s:13:"Mail/smtp.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php52/usr/share/pear/Mail/smtp.php";}s:15:"Mail/smtpmx.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"853b55cf4803df8caaaa0dca363971ff";s:4:"name";s:15:"Mail/smtpmx.php";s:4:"role";s:3:"php";s:12:"installed_as";s:45:"/opt/alt/php52/usr/share/pear/Mail/smtpmx.php";}s:8:"Mail.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3077f0c01f72cc29a6f8f0175e7fc8a7";s:4:"name";s:8:"Mail.php";s:4:"role";s:3:"php";s:12:"installed_as";s:38:"/opt/alt/php52/usr/share/pear/Mail.php";}s:15:"tests/9137.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d66aa2a2f0bfe33f8a67d749a1a4d345";s:4:"name";s:15:"tests/9137.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:55:"/opt/alt/php52/usr/share/pear/test/Mail/tests/9137.phpt";}s:17:"tests/9137_2.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"75d10361f686f1cc16637a9364e3eab7";s:4:"name";s:17:"tests/9137_2.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:57:"/opt/alt/php52/usr/share/pear/test/Mail/tests/9137_2.phpt";}s:16:"tests/13659.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"63715aad2b5b3ae35c6b05acf04d9ad7";s:4:"name";s:16:"tests/13659.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:56:"/opt/alt/php52/usr/share/pear/test/Mail/tests/13659.phpt";}s:19:"tests/bug17178.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e99f00d8f07232e0f129dd77ae9699c7";s:4:"name";s:19:"tests/bug17178.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:59:"/opt/alt/php52/usr/share/pear/test/Mail/tests/bug17178.phpt";}s:19:"tests/bug17317.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c2036980390981cd6b89c1e5c903913e";s:4:"name";s:19:"tests/bug17317.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:59:"/opt/alt/php52/usr/share/pear/test/Mail/tests/bug17317.phpt";}s:17:"tests/rfc822.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7b0eae971fe7595e7c1a563fbfcfee90";s:4:"name";s:17:"tests/rfc822.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:57:"/opt/alt/php52/usr/share/pear/test/Mail/tests/rfc822.phpt";}s:21:"tests/smtp_error.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"67becdb1027cefcb8dff1b691da630ab";s:4:"name";s:21:"tests/smtp_error.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:61:"/opt/alt/php52/usr/share/pear/test/Mail/tests/smtp_error.phpt";}}s:12:"_lastversion";N;s:7:"dirtree";a:8:{s:38:"/opt/alt/php52/usr/share/doc/pear/Mail";b:1;s:38:"/opt/alt/php52//usr/share/doc/pearMail";b:1;s:34:"/opt/alt/php52/usr/share/pear/Mail";b:1;s:34:"/opt/alt/php52///usr/share/pearail";b:1;s:29:"/opt/alt/php52/usr/share/pear";b:1;s:45:"/opt/alt/php52/usr/share/pear/test/Mail/tests";b:1;s:45:"/opt/alt/php52///usr/share/pear/testail/tests";b:1;s:39:"/opt/alt/php52///usr/share/pear/testail";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.4.1";s:12:"release_date";s:10:"2017-04-11";s:13:"release_state";s:6:"stable";s:15:"release_license";s:15:"New BSD License";s:13:"release_notes";s:177:"* Loosen recognition of "queued as" server response (PR #10) * Bug #20463: domain-literal parsing error * Bug #20513: Mail_smtp::send() doesn't close socket for smtp connection";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.2.1";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.5.6";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:8:"Net_SMTP";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.1";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:3:{i:0;a:5:{s:4:"name";s:15:"Chuck Hagenbuch";s:5:"email";s:15:"chuck@horde.org";s:6:"active";s:2:"no";s:6:"handle";s:8:"chagenbu";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:13:"Richard Heyes";s:5:"email";s:19:"richard@phpguru.org";s:6:"active";s:2:"no";s:6:"handle";s:7:"richard";s:4:"role";s:9:"developer";}i:2;a:5:{s:4:"name";s:19:"Aleksander Machniak";s:5:"email";s:12:"alec@alec.pl";s:6:"active";s:3:"yes";s:6:"handle";s:4:"alec";s:4:"role";s:9:"developer";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506464;}PK�������!�C~N��N����.registry/net_sieve.regnu�[��������a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:7:"1.10.12";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:9:"Net_Sieve";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:34:"Handles talking to a sieve server.";s:11:"description";s:160:"This package provides an API to talk to servers implementing the managesieve protocol. It can be used to install and remove sieve scripts, mark them active etc.";s:4:"lead";a:5:{i:0;a:4:{s:4:"name";s:19:"Aleksander Machniak";s:4:"user";s:4:"alec";s:5:"email";s:12:"alec@alec.pl";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:13:"Jan Schneider";s:4:"user";s:6:"yunosh";s:5:"email";s:13:"jan@horde.org";s:6:"active";s:2:"no";}i:2;a:4:{s:4:"name";s:13:"Richard Heyes";s:4:"user";s:7:"richard";s:5:"email";s:15:"richard@php.net";s:6:"active";s:2:"no";}i:3;a:4:{s:4:"name";s:21:"Damian Fernandez Sosa";s:4:"user";s:6:"damian";s:5:"email";s:20:"damlists@cnba.uba.ar";s:6:"active";s:2:"no";}i:4;a:4:{s:4:"name";s:12:"Anish Mistry";s:4:"user";s:7:"amistry";s:5:"email";s:26:"amistry@am-productions.biz";s:6:"active";s:2:"no";}}s:4:"date";s:10:"2021-04-24";s:4:"time";s:8:"13:33:52";s:7:"version";a:2:{s:7:"release";s:5:"1.4.5";s:3:"api";s:5:"1.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:38:"* Support XOAUTH2 authorization method";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:3:"Net";s:4:"name";s:1:"/";}s:4:"file";a:4:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:3:"Net";s:6:"md5sum";s:32:"ef8cd688674fba85cc067e06c221e43b";s:4:"name";s:21:"tests/largescript.siv";s:4:"role";s:4:"test";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:3:"Net";s:6:"md5sum";s:32:"7d772fe47ee45bdb521dd581281f38c3";s:4:"name";s:21:"tests/config.php.dist";s:4:"role";s:4:"test";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:3:"Net";s:6:"md5sum";s:32:"6050fac5e66a4a6bbed7913f826974ed";s:4:"name";s:19:"tests/SieveTest.php";s:4:"role";s:4:"test";}}i:3;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:3:"Net";s:6:"md5sum";s:32:"2a45a03c042351957f3435929a17bca3";s:4:"name";s:9:"Sieve.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}}}}s:12:"dependencies";a:2:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.0.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:7:"1.4.0b1";}s:7:"package";a:3:{s:4:"name";s:10:"Net_Socket";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.0";}}s:8:"optional";a:1:{s:7:"package";a:3:{s:4:"name";s:9:"Auth_SASL";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.0";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:28:{i:0;a:5:{s:4:"date";s:10:"2018-03-04";s:7:"version";a:2:{s:7:"release";s:5:"1.4.3";s:3:"api";s:5:"1.4.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:31:"* Support GSSAPI authentication";}i:1;a:5:{s:4:"date";s:10:"2018-02-14";s:7:"version";a:2:{s:7:"release";s:5:"1.4.2";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:78:"* Composer: Fix license identifier, don't use unbound version numbers for deps";}i:2;a:5:{s:4:"date";s:10:"2017-05-26";s:7:"version";a:2:{s:7:"release";s:5:"1.4.1";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:199:"* Use 8bit instead of latin1 for string length in bytes calculation * Extend listScripts() so it's possible to get an active script name in one go * Request #20491: Skip redundant CAPABILITY requests";}i:3;a:5:{s:4:"date";s:10:"2017-05-21";s:7:"version";a:2:{s:7:"release";s:5:"1.4.0";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:129:"* Dropped PHP4 support, fixed PHP7 warnings * Fixed E_DEPRECATED warning on Auth_SASL::factory() call * Enable later TLS versions";}i:4;a:5:{s:4:"date";s:10:"2015-01-20";s:7:"version";a:2:{s:7:"release";s:5:"1.3.4";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:70:"* Remove erroneous and unnecessary active script caching (Bug #20472).";}i:5;a:5:{s:4:"date";s:10:"2014-09-24";s:7:"version";a:2:{s:7:"release";s:5:"1.3.3";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:111:"* Fix notices from non-static calling of PEAR methods. * Fix reading OK responses with string literal messages.";}i:6;a:5:{s:4:"date";s:10:"2011-08-06";s:7:"version";a:2:{s:7:"release";s:5:"1.3.2";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:146:"* Fix referrals if host data or user credentials are passed to connect() and login() instead of the constructor (Aleksander Machniak, Bug #17107).";}i:7;a:5:{s:4:"date";s:10:"2011-08-05";s:7:"version";a:2:{s:7:"release";s:5:"1.3.1";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:417:"* Query capabilities again after successful authentication (Jesse Crawford, Request #18382). * Escape quotes and backslashes in script names, and use literal strings for script names with non-ASCII characters (Aleksander Machniak, Bug #16691). * Work around broken STARTTLS behavior in Cyrus versions before 2.3.10 (Aleksander Machniak, Bug #18241). * Improve string literal parsing (Aleksander Machniak, Bug #18228).";}i:8;a:5:{s:4:"date";s:10:"2010-07-01";s:7:"version";a:2:{s:7:"release";s:5:"1.3.0";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:122:"* Add debug handler parameter to constructor. * Fix LOGIN authentication (Agustín Eijo, Aleksander Machniak, Bug #17527).";}i:9;a:5:{s:4:"date";s:10:"2010-06-13";s:7:"version";a:2:{s:7:"release";s:5:"1.2.2";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:57:"* Fix SASL authentication without Auth_SASL (Bug #17489).";}i:10;a:5:{s:4:"date";s:10:"2010-04-19";s:7:"version";a:2:{s:7:"release";s:5:"1.2.1";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:72:"* Fix DIGEST-MD5 authentication with Dovecot (Stef Simoens, Bug #17320).";}i:11;a:5:{s:4:"date";s:10:"2010-04-01";s:7:"version";a:2:{s:7:"release";s:5:"1.2.0";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:432:"Changes since version 1.2.0b1: * Fix DIGEST-MD5 authentication (Aleksander Machniak, Bug #17285). * Don't try to call dl() if mbstring extension isn't loaded (Bug #17038). Changes since version 1.1.7: * Added support for adding a custom debug handler (Aleksander Machniak, Request #16681). * Fix breakage with certain locales, especially Turkish. * Fix reading authentication responses without literals (Bug #16647). * Code cleanup.";}i:12;a:5:{s:4:"date";s:10:"2009-10-07";s:7:"version";a:2:{s:7:"release";s:7:"1.2.0b1";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:231:"* Added support for adding a custom debug handler (Aleksander Machniak, Request #16681). * Fix breakage with certain locales, especially Turkish. * Fix reading authentication responses without literals (Bug #16647). * Code cleanup.";}i:13;a:5:{s:4:"date";s:10:"2009-07-24";s:7:"version";a:2:{s:7:"release";s:5:"1.1.7";s:3:"api";s:5:"1.1.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:91:"* Fixed STARTTLS support (Bug #14205). * Added connect options and EXTERNAL authentication.";}i:14;a:5:{s:4:"date";s:10:"2008-03-22";s:7:"version";a:2:{s:7:"release";s:5:"1.1.6";s:3:"api";s:5:"1.1.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:88:"* Fixed Bug #9273 * Fixed copy/paste error in CRAM and DIGEST authentication error case.";}i:15;a:5:{s:4:"date";s:10:"2006-10-24";s:7:"version";a:2:{s:7:"release";s:5:"1.1.5";s:3:"api";s:5:"1.1.5";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:47:"* Fixed Bug connect() bug * Fixed Request #8071";}i:16;a:5:{s:4:"date";s:10:"2006-09-09";s:7:"version";a:2:{s:7:"release";s:5:"1.1.4";s:3:"api";s:5:"1.1.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:207:"* Fixed Bug #8452 Unterminated read loop * Fixed Bug #7845 Add mbstring support * Added Request #8071 Enable the ability to toggle TLS support if available. * Added Request #8453 Clean up PHPDoc and comments";}i:17;a:5:{s:4:"date";s:10:"2006-05-21";s:7:"version";a:2:{s:7:"release";s:5:"1.1.3";s:3:"api";s:5:"1.1.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:164:"* Correctly Fixed Bug #3519 Net_Sieve w/ externally established sockets * Fixed Bug #7197 getScript() truncates long scripts * Added PHPUnit2 regression test script";}i:18;a:5:{s:4:"date";s:10:"2006-02-09";s:7:"version";a:2:{s:7:"release";s:5:"1.1.2";s:3:"api";s:5:"1.1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:285:"* Fixed Request #4053 Added STARTTLS support for PHP 5.1 and above * Fixed Bug #3519 Net_Sieve w/ externally established sockets * Fixed Bug #4794 drops protocol prefix, e.g. "ssl://" in referrals * Fixed STARTTLS detection * Allow $options[] to be passed to Net_Socket";}i:19;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.1";s:3:"api";s:5:"1.1.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-02-02";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:53:"* Fixed Bug #3242 cyrus murder referrals not followed";}i:20;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.0";s:3:"api";s:5:"1.1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-12-18";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:61:"* Fixed Bug #2728 Linebreaks not being read using getScript()";}i:21;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.1";s:3:"api";s:5:"1.0.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-03-13";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:17:"* Fixed BUG #1006";}i:22;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.0";s:3:"api";s:5:"1.0.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-03-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:108:"* Fixed DIGEST-MD5 sasl version handling (sasl v1.xx responses are diferent than v2.xx) * Fixed LOGIN Method";}i:23;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.9.1";s:3:"api";s:5:"0.9.1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2004-02-29";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:1138:"* There is an issue whith the DIGEST-MD5 method. in one installation it does not work but in my server it works perfect! please send me debug info to solve the problem if it affects you or disable DIGEST-MD5 * some optimizations to the code * added haveSpace() to check if the server has space to store the script. Use with care HAVESPACE seems to be broken in cyrus 2.0.16 * added hasExtension() * added getExtensions() * added referral support and automatic following of them. (it also handles the following of multireferrals). * removed _getResponse replaced by _doCmd. (thanks to Etienne Goyer for this) * added supportsAuthMech() * if installed automatically uses Auth_SASL * added CRAM-MD5 auth Method * added DIGEST-MD5 auth Method * added getAuthMechs() returns an array containing all the auth methods the server supports * added hasAuthMech() to check if the server has a particular auth method * _connect --> connect: now is a public method (without breaking BC) * _login --> login: now is a public method (without breaking BC) * fix typo cmdAuthenticate() ---> _cmdAuthenticate() * _doCmd() now parses string responses also.";}i:24;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.9.0";s:3:"api";s:5:"0.9.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2004-01-31";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:177:"* Added setDebug() method and debugging capabilities * added disconnect() method * added sample file test_sieve.php * fixed bug #591 * automagically selects the best auth method";}i:25;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.8.1";s:3:"api";s:5:"0.8.1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2002-07-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:15:"Initial release";}i:26;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.8";s:3:"api";s:3:"0.8";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2002-05-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:3:"PHP";}s:5:"notes";s:15:"Initial release";}i:27;a:5:{s:4:"date";s:10:"2018-09-09";s:7:"version";a:2:{s:7:"release";s:5:"1.4.4";s:3:"api";s:5:"1.4.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:70:"* Fix PHP 7.3: Declaration of case-insensitive constants is deprecated";}}}s:8:"filelist";a:4:{s:21:"tests/largescript.siv";a:5:{s:14:"baseinstalldir";s:3:"Net";s:6:"md5sum";s:32:"ef8cd688674fba85cc067e06c221e43b";s:4:"name";s:21:"tests/largescript.siv";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/opt/alt/php52/usr/share/pear/test/Net_Sieve/tests/largescript.siv";}s:21:"tests/config.php.dist";a:5:{s:14:"baseinstalldir";s:3:"Net";s:6:"md5sum";s:32:"7d772fe47ee45bdb521dd581281f38c3";s:4:"name";s:21:"tests/config.php.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/opt/alt/php52/usr/share/pear/test/Net_Sieve/tests/config.php.dist";}s:19:"tests/SieveTest.php";a:5:{s:14:"baseinstalldir";s:3:"Net";s:6:"md5sum";s:32:"6050fac5e66a4a6bbed7913f826974ed";s:4:"name";s:19:"tests/SieveTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/Net_Sieve/tests/SieveTest.php";}s:9:"Sieve.php";a:5:{s:14:"baseinstalldir";s:3:"Net";s:6:"md5sum";s:32:"2a45a03c042351957f3435929a17bca3";s:4:"name";s:9:"Sieve.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php52/usr/share/pear/Net/Sieve.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:5:{s:50:"/opt/alt/php52/usr/share/pear/test/Net_Sieve/tests";b:1;s:50:"/opt/alt/php52///usr/share/pear/testet_Sieve/tests";b:1;s:44:"/opt/alt/php52///usr/share/pear/testet_Sieve";b:1;s:33:"/opt/alt/php52/usr/share/pear/Net";b:1;s:33:"/opt/alt/php52///usr/share/pearet";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.4.5";s:12:"release_date";s:10:"2021-04-24";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"BSD";s:13:"release_notes";s:38:"* Support XOAUTH2 authorization method";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.0.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:7:"1.4.0b1";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:10:"Net_Socket";s:3:"rel";s:2:"ge";s:7:"version";s:3:"1.0";s:8:"optional";s:2:"no";}i:3;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:9:"Auth_SASL";s:3:"rel";s:2:"ge";s:7:"version";s:3:"1.0";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:5:{i:0;a:5:{s:4:"name";s:19:"Aleksander Machniak";s:5:"email";s:12:"alec@alec.pl";s:6:"active";s:3:"yes";s:6:"handle";s:4:"alec";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:13:"Jan Schneider";s:5:"email";s:13:"jan@horde.org";s:6:"active";s:2:"no";s:6:"handle";s:6:"yunosh";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:13:"Richard Heyes";s:5:"email";s:15:"richard@php.net";s:6:"active";s:2:"no";s:6:"handle";s:7:"richard";s:4:"role";s:4:"lead";}i:3;a:5:{s:4:"name";s:21:"Damian Fernandez Sosa";s:5:"email";s:20:"damlists@cnba.uba.ar";s:6:"active";s:2:"no";s:6:"handle";s:6:"damian";s:4:"role";s:4:"lead";}i:4;a:5:{s:4:"name";s:12:"Anish Mistry";s:5:"email";s:26:"amistry@am-productions.biz";s:6:"active";s:2:"no";s:6:"handle";s:7:"amistry";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506465;}PK�������!�VwJ������.registry/file_marc.regnu�[��������a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:9:"File_MARC";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:38:"Parse, modify, and create MARC records";s:11:"description";s:574:"The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records. This package is based on the PHP MARC package, originally called "php-marc", that is part of the Emilda Project (http://www.emilda.org). Christoffer Landtman generously agreed to make the "php-marc" code available under the GNU LGPL so it could be used as the basis of this PEAR package.";s:4:"lead";a:4:{s:4:"name";s:9:"Dan Scott";s:4:"user";s:3:"dbs";s:5:"email";s:11:"dbs@php.net";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2013-09-13";s:4:"time";s:8:"16:28:02";s:7:"version";a:2:{s:7:"release";s:5:"0.7.3";s:3:"api";s:5:"0.7.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:39:"http://www.gnu.org/copyleft/lesser.html";}s:8:"_content";s:33:"GNU Lesser General Public License";}s:5:"notes";s:115:"0.7.3-beta * Merge patch from Karen Coombs (librarywebchic@gmail.com) adding default namespace to record elements";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:4:"File";s:4:"name";s:1:"/";}s:4:"file";a:73:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dcb3f441aca2cb3d6428eaeaa0e94b68";s:4:"name";s:27:"File/MARC/Lint/CodeData.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a3b9e1c817e67f59add05593500d463e";s:4:"name";s:27:"File/MARC/Control_Field.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c1ee8d71ca95c73b64b1d28ddc7fef1f";s:4:"name";s:24:"File/MARC/Data_Field.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"378f483ec1fd161cd9dfb9b05db58d66";s:4:"name";s:23:"File/MARC/Exception.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4e064fa8c8e8043199febb2631f7aba3";s:4:"name";s:19:"File/MARC/Field.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4ac07dafa2adb185c6a3f6008a09c193";s:4:"name";s:18:"File/MARC/Lint.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"878718697ef84120847c5a573bf6d3d1";s:4:"name";s:18:"File/MARC/List.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"28ec2ffcf32f0080b4425f261e90b73e";s:4:"name";s:20:"File/MARC/Record.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"461993cfef76891b37cbc074bcdc5a48";s:4:"name";s:22:"File/MARC/Subfield.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b545a092661bf2519077caf1004422fb";s:4:"name";s:13:"File/MARC.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3f4846324e799ecec63a2989bada4625";s:4:"name";s:17:"File/MARCBASE.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4c850abc99ac13f99bcd25729377fc22";s:4:"name";s:16:"File/MARCXML.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"6af971fd9ff5ef3e5fcba8a64a0e7a49";s:4:"name";s:20:"examples/example.mrc";s:4:"role";s:3:"doc";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"ea4abff91135a87ed40c10a3d6fb60e7";s:4:"name";s:21:"examples/marc_yaz.php";s:4:"role";s:3:"doc";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"542df3337b18e2c947ac6d16ec16cb02";s:4:"name";s:17:"examples/read.php";s:4:"role";s:3:"doc";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"24c4f473ea31e6a5da9c178136a03011";s:4:"name";s:22:"examples/subfields.php";s:4:"role";s:3:"doc";}}i:16;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"14297da35b510c496cd1f328cf3bb301";s:4:"name";s:21:"tests/bad_example.mrc";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"0dd4c6dbad6e8608d0ebf9d24425955d";s:4:"name";s:21:"tests/bad_example.xml";s:4:"role";s:4:"test";}}i:18;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"216a6f9d53f6d3d8e22d81fdc10f4bc1";s:4:"name";s:15:"tests/camel.mrc";s:4:"role";s:4:"test";}}i:19;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"6af971fd9ff5ef3e5fcba8a64a0e7a49";s:4:"name";s:17:"tests/example.mrc";s:4:"role";s:4:"test";}}i:20;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"0312720ce5366add32eba9e7217a4bcc";s:4:"name";s:19:"tests/marc_001.phpt";s:4:"role";s:4:"test";}}i:21;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"9460a960e0547f36e72f3dbf6e5f700b";s:4:"name";s:19:"tests/marc_002.phpt";s:4:"role";s:4:"test";}}i:22;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"dacfae00b3047c7aa0438a8fc86ad42e";s:4:"name";s:19:"tests/marc_003.phpt";s:4:"role";s:4:"test";}}i:23;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"a006e9f35c229a8f28f08abfadc4b182";s:4:"name";s:19:"tests/marc_004.phpt";s:4:"role";s:4:"test";}}i:24;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"023c66506bae9d44888d78956719a519";s:4:"name";s:19:"tests/marc_005.phpt";s:4:"role";s:4:"test";}}i:25;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"3ddbddcdad471d7d76a0fa3f845edf7a";s:4:"name";s:19:"tests/marc_006.phpt";s:4:"role";s:4:"test";}}i:26;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"2719b272866125ca8f24fe07e6c3e27f";s:4:"name";s:19:"tests/marc_007.phpt";s:4:"role";s:4:"test";}}i:27;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"67ffd3895e1e420ec58326432852a809";s:4:"name";s:19:"tests/marc_008.phpt";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"fe6d2f8e31f8127f00ff962c563812da";s:4:"name";s:19:"tests/marc_009.phpt";s:4:"role";s:4:"test";}}i:29;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"8b05449b21e678bdfba8e193f5b719f1";s:4:"name";s:19:"tests/marc_010.phpt";s:4:"role";s:4:"test";}}i:30;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"8567ad11befac111b6c60ff296dd9a2a";s:4:"name";s:19:"tests/marc_011.phpt";s:4:"role";s:4:"test";}}i:31;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"a15be7dfd9b67ca5559500993400b944";s:4:"name";s:19:"tests/marc_012.phpt";s:4:"role";s:4:"test";}}i:32;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"3beedaacfb578e2d5af505a75fc7e257";s:4:"name";s:19:"tests/marc_013.phpt";s:4:"role";s:4:"test";}}i:33;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"b384da6d8520f9c727ba1b8d3a5e552f";s:4:"name";s:19:"tests/marc_014.phpt";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"741cb6b43b8fa1a83e44c0af3d9f86d1";s:4:"name";s:19:"tests/marc_015.phpt";s:4:"role";s:4:"test";}}i:35;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"370e394e4809dc9282829c994dc877ef";s:4:"name";s:19:"tests/marc_016.phpt";s:4:"role";s:4:"test";}}i:36;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"83a96d6fbcf0e69b1c58aa53257f6613";s:4:"name";s:19:"tests/marc_017.phpt";s:4:"role";s:4:"test";}}i:37;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"5f320f57979d4a84ef5951e889373a32";s:4:"name";s:19:"tests/marc_018.phpt";s:4:"role";s:4:"test";}}i:38;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"eb8b2475935fec34db0a4553d0adf1ae";s:4:"name";s:19:"tests/marc_019.phpt";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"f49e4fa6607fae0de65cf1abbaefa47a";s:4:"name";s:21:"tests/marc_16783.phpt";s:4:"role";s:4:"test";}}i:40;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"fe8e67ea3ded16228c680397cc32df55";s:4:"name";s:25:"tests/marc_field_001.phpt";s:4:"role";s:4:"test";}}i:41;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"7a6a3913222e8b4ca3ea3bf9677633c1";s:4:"name";s:25:"tests/marc_field_002.phpt";s:4:"role";s:4:"test";}}i:42;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"d02ae37382295cdfdcfed2e98fdec17b";s:4:"name";s:25:"tests/marc_field_003.phpt";s:4:"role";s:4:"test";}}i:43;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"61bfc433ec56dbf7003dd07bb96e710b";s:4:"name";s:25:"tests/marc_field_004.phpt";s:4:"role";s:4:"test";}}i:44;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"500718b6f4601215c2b901a1b9ab7fc5";s:4:"name";s:24:"tests/marc_lint_001.phpt";s:4:"role";s:4:"test";}}i:45;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"f39e3d380e11ccec2cdf019bd1d71de8";s:4:"name";s:24:"tests/marc_lint_002.phpt";s:4:"role";s:4:"test";}}i:46;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"da83532b80eb4b150e3fd9990a9109ad";s:4:"name";s:24:"tests/marc_lint_003.phpt";s:4:"role";s:4:"test";}}i:47;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"c846a9a9f3f6d290db128cc7c22682a3";s:4:"name";s:24:"tests/marc_lint_004.phpt";s:4:"role";s:4:"test";}}i:48;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"bc3131973fea49398b450537890fab96";s:4:"name";s:24:"tests/marc_lint_005.phpt";s:4:"role";s:4:"test";}}i:49;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"e815fb648e4f981b3aed9960f52e9825";s:4:"name";s:26:"tests/marc_record_001.phpt";s:4:"role";s:4:"test";}}i:50;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"d5daba7d119809b6915e8e2e91348bc1";s:4:"name";s:28:"tests/marc_subfield_001.phpt";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"7883ef833ee5a7a93c375c1ba8f2a61d";s:4:"name";s:28:"tests/marc_subfield_002.phpt";s:4:"role";s:4:"test";}}i:52;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"9f42ac506429e936680d93f85b22c79c";s:4:"name";s:23:"tests/marc_xml_001.phpt";s:4:"role";s:4:"test";}}i:53;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"b53ceea50b9013d2acf8f8cb2f181da9";s:4:"name";s:23:"tests/marc_xml_002.phpt";s:4:"role";s:4:"test";}}i:54;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"0e0063b4bf375fe39b4ab817639fd617";s:4:"name";s:23:"tests/marc_xml_003.phpt";s:4:"role";s:4:"test";}}i:55;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"860e9f54d11c7c1970d56703fc182be3";s:4:"name";s:23:"tests/marc_xml_004.phpt";s:4:"role";s:4:"test";}}i:56;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"226ff0e47856b2ba52deae52d5947bec";s:4:"name";s:23:"tests/marc_xml_005.phpt";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"4bd4c256ad4137496483645da036f4c7";s:4:"name";s:23:"tests/marc_xml_006.phpt";s:4:"role";s:4:"test";}}i:58;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"013026441c0ac2ec4e6d3b41f16ed926";s:4:"name";s:23:"tests/marc_xml_007.phpt";s:4:"role";s:4:"test";}}i:59;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"7a5425e1e4729737968a683295abc575";s:4:"name";s:23:"tests/marc_xml_008.phpt";s:4:"role";s:4:"test";}}i:60;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"13cf2bd9f1a40a07f8124398ecc83b19";s:4:"name";s:23:"tests/marc_xml_009.phpt";s:4:"role";s:4:"test";}}i:61;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"7b71d7b02467746a677493bb9b830ead";s:4:"name";s:25:"tests/marc_xml_16642.phpt";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"f07691aa1aac98df286bc796ee77d3f7";s:4:"name";s:27:"tests/marc_xml_rsinger.phpt";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"a0ed82899955c005d80a4a88cc984bc4";s:4:"name";s:16:"tests/skipif.inc";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"a0166a4ff0bc0bb283e854f11beaa793";s:4:"name";s:15:"tests/music.mrc";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"993ce494befbc25dc1326527b30b4782";s:4:"name";s:15:"tests/music.xml";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"6b0c87f0cd459ed7322c25d403b164cc";s:4:"name";s:20:"tests/bigarchive.xml";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"be850aa6ab4ac52b8c6c214c30b574af";s:4:"name";s:19:"tests/onerecord.xml";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"4f43fec7b276267eec5258044853ccc8";s:4:"name";s:18:"tests/sandburg.mrc";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"e216b95f905dd240c9bde372950e4073";s:4:"name";s:18:"tests/sandburg.xml";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"e81a92188ea0dcd9c108a63fb32b3f4f";s:4:"name";s:19:"tests/xmlescape.mrc";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"89507dc252ecdbccfbb40b4a96b4d90e";s:4:"name";s:9:"CHANGELOG";s:4:"role";s:3:"doc";}}i:72;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"fbc093901857fcd118f065f900982c24";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:3:"5.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}s:7:"package";a:2:{s:4:"name";s:21:"Structures_LinkedList";s:7:"channel";s:12:"pear.php.net";}}s:8:"optional";a:1:{s:7:"package";a:2:{s:4:"name";s:13:"Validate_ISPN";s:7:"channel";s:12:"pear.php.net";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:73:{s:27:"File/MARC/Lint/CodeData.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dcb3f441aca2cb3d6428eaeaa0e94b68";s:4:"name";s:27:"File/MARC/Lint/CodeData.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php52/usr/share/pear/File/MARC/Lint/CodeData.php";}s:27:"File/MARC/Control_Field.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a3b9e1c817e67f59add05593500d463e";s:4:"name";s:27:"File/MARC/Control_Field.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php52/usr/share/pear/File/MARC/Control_Field.php";}s:24:"File/MARC/Data_Field.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c1ee8d71ca95c73b64b1d28ddc7fef1f";s:4:"name";s:24:"File/MARC/Data_Field.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/opt/alt/php52/usr/share/pear/File/MARC/Data_Field.php";}s:23:"File/MARC/Exception.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"378f483ec1fd161cd9dfb9b05db58d66";s:4:"name";s:23:"File/MARC/Exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php52/usr/share/pear/File/MARC/Exception.php";}s:19:"File/MARC/Field.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4e064fa8c8e8043199febb2631f7aba3";s:4:"name";s:19:"File/MARC/Field.php";s:4:"role";s:3:"php";s:12:"installed_as";s:49:"/opt/alt/php52/usr/share/pear/File/MARC/Field.php";}s:18:"File/MARC/Lint.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4ac07dafa2adb185c6a3f6008a09c193";s:4:"name";s:18:"File/MARC/Lint.php";s:4:"role";s:3:"php";s:12:"installed_as";s:48:"/opt/alt/php52/usr/share/pear/File/MARC/Lint.php";}s:18:"File/MARC/List.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"878718697ef84120847c5a573bf6d3d1";s:4:"name";s:18:"File/MARC/List.php";s:4:"role";s:3:"php";s:12:"installed_as";s:48:"/opt/alt/php52/usr/share/pear/File/MARC/List.php";}s:20:"File/MARC/Record.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"28ec2ffcf32f0080b4425f261e90b73e";s:4:"name";s:20:"File/MARC/Record.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/opt/alt/php52/usr/share/pear/File/MARC/Record.php";}s:22:"File/MARC/Subfield.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"461993cfef76891b37cbc074bcdc5a48";s:4:"name";s:22:"File/MARC/Subfield.php";s:4:"role";s:3:"php";s:12:"installed_as";s:52:"/opt/alt/php52/usr/share/pear/File/MARC/Subfield.php";}s:13:"File/MARC.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b545a092661bf2519077caf1004422fb";s:4:"name";s:13:"File/MARC.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php52/usr/share/pear/File/MARC.php";}s:17:"File/MARCBASE.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3f4846324e799ecec63a2989bada4625";s:4:"name";s:17:"File/MARCBASE.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php52/usr/share/pear/File/MARCBASE.php";}s:16:"File/MARCXML.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4c850abc99ac13f99bcd25729377fc22";s:4:"name";s:16:"File/MARCXML.php";s:4:"role";s:3:"php";s:12:"installed_as";s:46:"/opt/alt/php52/usr/share/pear/File/MARCXML.php";}s:20:"examples/example.mrc";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"6af971fd9ff5ef3e5fcba8a64a0e7a49";s:4:"name";s:20:"examples/example.mrc";s:4:"role";s:3:"doc";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/doc/pear/File_MARC/examples/example.mrc";}s:21:"examples/marc_yaz.php";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"ea4abff91135a87ed40c10a3d6fb60e7";s:4:"name";s:21:"examples/marc_yaz.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:65:"/opt/alt/php52/usr/share/doc/pear/File_MARC/examples/marc_yaz.php";}s:17:"examples/read.php";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"542df3337b18e2c947ac6d16ec16cb02";s:4:"name";s:17:"examples/read.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:61:"/opt/alt/php52/usr/share/doc/pear/File_MARC/examples/read.php";}s:22:"examples/subfields.php";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"24c4f473ea31e6a5da9c178136a03011";s:4:"name";s:22:"examples/subfields.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:66:"/opt/alt/php52/usr/share/doc/pear/File_MARC/examples/subfields.php";}s:21:"tests/bad_example.mrc";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"14297da35b510c496cd1f328cf3bb301";s:4:"name";s:21:"tests/bad_example.mrc";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/bad_example.mrc";}s:21:"tests/bad_example.xml";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"0dd4c6dbad6e8608d0ebf9d24425955d";s:4:"name";s:21:"tests/bad_example.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/bad_example.xml";}s:15:"tests/camel.mrc";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"216a6f9d53f6d3d8e22d81fdc10f4bc1";s:4:"name";s:15:"tests/camel.mrc";s:4:"role";s:4:"test";s:12:"installed_as";s:60:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/camel.mrc";}s:17:"tests/example.mrc";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"6af971fd9ff5ef3e5fcba8a64a0e7a49";s:4:"name";s:17:"tests/example.mrc";s:4:"role";s:4:"test";s:12:"installed_as";s:62:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/example.mrc";}s:19:"tests/marc_001.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"0312720ce5366add32eba9e7217a4bcc";s:4:"name";s:19:"tests/marc_001.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_001.phpt";}s:19:"tests/marc_002.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"9460a960e0547f36e72f3dbf6e5f700b";s:4:"name";s:19:"tests/marc_002.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_002.phpt";}s:19:"tests/marc_003.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"dacfae00b3047c7aa0438a8fc86ad42e";s:4:"name";s:19:"tests/marc_003.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_003.phpt";}s:19:"tests/marc_004.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"a006e9f35c229a8f28f08abfadc4b182";s:4:"name";s:19:"tests/marc_004.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_004.phpt";}s:19:"tests/marc_005.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"023c66506bae9d44888d78956719a519";s:4:"name";s:19:"tests/marc_005.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_005.phpt";}s:19:"tests/marc_006.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"3ddbddcdad471d7d76a0fa3f845edf7a";s:4:"name";s:19:"tests/marc_006.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_006.phpt";}s:19:"tests/marc_007.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"2719b272866125ca8f24fe07e6c3e27f";s:4:"name";s:19:"tests/marc_007.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_007.phpt";}s:19:"tests/marc_008.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"67ffd3895e1e420ec58326432852a809";s:4:"name";s:19:"tests/marc_008.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_008.phpt";}s:19:"tests/marc_009.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"fe6d2f8e31f8127f00ff962c563812da";s:4:"name";s:19:"tests/marc_009.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_009.phpt";}s:19:"tests/marc_010.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"8b05449b21e678bdfba8e193f5b719f1";s:4:"name";s:19:"tests/marc_010.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_010.phpt";}s:19:"tests/marc_011.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"8567ad11befac111b6c60ff296dd9a2a";s:4:"name";s:19:"tests/marc_011.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_011.phpt";}s:19:"tests/marc_012.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"a15be7dfd9b67ca5559500993400b944";s:4:"name";s:19:"tests/marc_012.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_012.phpt";}s:19:"tests/marc_013.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"3beedaacfb578e2d5af505a75fc7e257";s:4:"name";s:19:"tests/marc_013.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_013.phpt";}s:19:"tests/marc_014.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"b384da6d8520f9c727ba1b8d3a5e552f";s:4:"name";s:19:"tests/marc_014.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_014.phpt";}s:19:"tests/marc_015.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"741cb6b43b8fa1a83e44c0af3d9f86d1";s:4:"name";s:19:"tests/marc_015.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_015.phpt";}s:19:"tests/marc_016.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"370e394e4809dc9282829c994dc877ef";s:4:"name";s:19:"tests/marc_016.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_016.phpt";}s:19:"tests/marc_017.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"83a96d6fbcf0e69b1c58aa53257f6613";s:4:"name";s:19:"tests/marc_017.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_017.phpt";}s:19:"tests/marc_018.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"5f320f57979d4a84ef5951e889373a32";s:4:"name";s:19:"tests/marc_018.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_018.phpt";}s:19:"tests/marc_019.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"eb8b2475935fec34db0a4553d0adf1ae";s:4:"name";s:19:"tests/marc_019.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_019.phpt";}s:21:"tests/marc_16783.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"f49e4fa6607fae0de65cf1abbaefa47a";s:4:"name";s:21:"tests/marc_16783.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_16783.phpt";}s:25:"tests/marc_field_001.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"fe8e67ea3ded16228c680397cc32df55";s:4:"name";s:25:"tests/marc_field_001.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_field_001.phpt";}s:25:"tests/marc_field_002.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"7a6a3913222e8b4ca3ea3bf9677633c1";s:4:"name";s:25:"tests/marc_field_002.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_field_002.phpt";}s:25:"tests/marc_field_003.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"d02ae37382295cdfdcfed2e98fdec17b";s:4:"name";s:25:"tests/marc_field_003.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_field_003.phpt";}s:25:"tests/marc_field_004.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"61bfc433ec56dbf7003dd07bb96e710b";s:4:"name";s:25:"tests/marc_field_004.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_field_004.phpt";}s:24:"tests/marc_lint_001.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"500718b6f4601215c2b901a1b9ab7fc5";s:4:"name";s:24:"tests/marc_lint_001.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_lint_001.phpt";}s:24:"tests/marc_lint_002.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"f39e3d380e11ccec2cdf019bd1d71de8";s:4:"name";s:24:"tests/marc_lint_002.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_lint_002.phpt";}s:24:"tests/marc_lint_003.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"da83532b80eb4b150e3fd9990a9109ad";s:4:"name";s:24:"tests/marc_lint_003.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_lint_003.phpt";}s:24:"tests/marc_lint_004.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"c846a9a9f3f6d290db128cc7c22682a3";s:4:"name";s:24:"tests/marc_lint_004.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_lint_004.phpt";}s:24:"tests/marc_lint_005.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"bc3131973fea49398b450537890fab96";s:4:"name";s:24:"tests/marc_lint_005.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_lint_005.phpt";}s:26:"tests/marc_record_001.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"e815fb648e4f981b3aed9960f52e9825";s:4:"name";s:26:"tests/marc_record_001.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_record_001.phpt";}s:28:"tests/marc_subfield_001.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"d5daba7d119809b6915e8e2e91348bc1";s:4:"name";s:28:"tests/marc_subfield_001.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:73:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_subfield_001.phpt";}s:28:"tests/marc_subfield_002.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"7883ef833ee5a7a93c375c1ba8f2a61d";s:4:"name";s:28:"tests/marc_subfield_002.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:73:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_subfield_002.phpt";}s:23:"tests/marc_xml_001.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"9f42ac506429e936680d93f85b22c79c";s:4:"name";s:23:"tests/marc_xml_001.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_001.phpt";}s:23:"tests/marc_xml_002.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"b53ceea50b9013d2acf8f8cb2f181da9";s:4:"name";s:23:"tests/marc_xml_002.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_002.phpt";}s:23:"tests/marc_xml_003.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"0e0063b4bf375fe39b4ab817639fd617";s:4:"name";s:23:"tests/marc_xml_003.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_003.phpt";}s:23:"tests/marc_xml_004.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"860e9f54d11c7c1970d56703fc182be3";s:4:"name";s:23:"tests/marc_xml_004.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_004.phpt";}s:23:"tests/marc_xml_005.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"226ff0e47856b2ba52deae52d5947bec";s:4:"name";s:23:"tests/marc_xml_005.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_005.phpt";}s:23:"tests/marc_xml_006.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"4bd4c256ad4137496483645da036f4c7";s:4:"name";s:23:"tests/marc_xml_006.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_006.phpt";}s:23:"tests/marc_xml_007.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"013026441c0ac2ec4e6d3b41f16ed926";s:4:"name";s:23:"tests/marc_xml_007.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_007.phpt";}s:23:"tests/marc_xml_008.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"7a5425e1e4729737968a683295abc575";s:4:"name";s:23:"tests/marc_xml_008.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_008.phpt";}s:23:"tests/marc_xml_009.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"13cf2bd9f1a40a07f8124398ecc83b19";s:4:"name";s:23:"tests/marc_xml_009.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_009.phpt";}s:25:"tests/marc_xml_16642.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"7b71d7b02467746a677493bb9b830ead";s:4:"name";s:25:"tests/marc_xml_16642.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_16642.phpt";}s:27:"tests/marc_xml_rsinger.phpt";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"f07691aa1aac98df286bc796ee77d3f7";s:4:"name";s:27:"tests/marc_xml_rsinger.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:72:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/marc_xml_rsinger.phpt";}s:16:"tests/skipif.inc";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"a0ed82899955c005d80a4a88cc984bc4";s:4:"name";s:16:"tests/skipif.inc";s:4:"role";s:4:"test";s:12:"installed_as";s:61:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/skipif.inc";}s:15:"tests/music.mrc";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"a0166a4ff0bc0bb283e854f11beaa793";s:4:"name";s:15:"tests/music.mrc";s:4:"role";s:4:"test";s:12:"installed_as";s:60:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/music.mrc";}s:15:"tests/music.xml";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"993ce494befbc25dc1326527b30b4782";s:4:"name";s:15:"tests/music.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:60:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/music.xml";}s:20:"tests/bigarchive.xml";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"6b0c87f0cd459ed7322c25d403b164cc";s:4:"name";s:20:"tests/bigarchive.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/bigarchive.xml";}s:19:"tests/onerecord.xml";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"be850aa6ab4ac52b8c6c214c30b574af";s:4:"name";s:19:"tests/onerecord.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/onerecord.xml";}s:18:"tests/sandburg.mrc";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"4f43fec7b276267eec5258044853ccc8";s:4:"name";s:18:"tests/sandburg.mrc";s:4:"role";s:4:"test";s:12:"installed_as";s:63:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/sandburg.mrc";}s:18:"tests/sandburg.xml";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"e216b95f905dd240c9bde372950e4073";s:4:"name";s:18:"tests/sandburg.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:63:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/sandburg.xml";}s:19:"tests/xmlescape.mrc";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"e81a92188ea0dcd9c108a63fb32b3f4f";s:4:"name";s:19:"tests/xmlescape.mrc";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests/xmlescape.mrc";}s:9:"CHANGELOG";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"89507dc252ecdbccfbb40b4a96b4d90e";s:4:"name";s:9:"CHANGELOG";s:4:"role";s:3:"doc";s:12:"installed_as";s:53:"/opt/alt/php52/usr/share/doc/pear/File_MARC/CHANGELOG";}s:7:"LICENSE";a:5:{s:14:"baseinstalldir";s:4:"File";s:6:"md5sum";s:32:"fbc093901857fcd118f065f900982c24";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:51:"/opt/alt/php52/usr/share/doc/pear/File_MARC/LICENSE";}}s:12:"_lastversion";N;s:7:"dirtree";a:13:{s:44:"/opt/alt/php52/usr/share/pear/File/MARC/Lint";b:1;s:44:"/opt/alt/php52///usr/share/pearile/MARC/Lint";b:1;s:39:"/opt/alt/php52///usr/share/pearile/MARC";b:1;s:34:"/opt/alt/php52///usr/share/pearile";b:1;s:39:"/opt/alt/php52/usr/share/pear/File/MARC";b:1;s:34:"/opt/alt/php52/usr/share/pear/File";b:1;s:52:"/opt/alt/php52/usr/share/doc/pear/File_MARC/examples";b:1;s:52:"/opt/alt/php52//usr/share/doc/pearFile_MARC/examples";b:1;s:43:"/opt/alt/php52//usr/share/doc/pearFile_MARC";b:1;s:50:"/opt/alt/php52/usr/share/pear/test/File_MARC/tests";b:1;s:50:"/opt/alt/php52///usr/share/pear/testile_MARC/tests";b:1;s:44:"/opt/alt/php52///usr/share/pear/testile_MARC";b:1;s:43:"/opt/alt/php52/usr/share/doc/pear/File_MARC";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"0.7.3";s:12:"release_date";s:10:"2013-09-13";s:13:"release_state";s:4:"beta";s:15:"release_license";s:33:"GNU Lesser General Public License";s:13:"release_notes";s:115:"0.7.3-beta * Merge patch from Karen Coombs (librarywebchic@gmail.com) adding default namespace to record elements";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:3:"5.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:21:"Structures_LinkedList";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:13:"Validate_ISPN";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:9:"Dan Scott";s:5:"email";s:11:"dbs@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:3:"dbs";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506464;}PK�������!�.:+��+����.registry/mail_mimedecode.regnu�[��������a:23:{s:7:"attribs";a:6:{s:15:"packagerversion";s:6:"1.10.1";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:160:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:15:"Mail_mimeDecode";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:41:"Provides a class to decode mime messages.";s:11:"description";s:157:"Provides a class to deal with the decoding and interpreting of mime messages. This package used to be part of the Mail_Mime package, but has been split off.";s:4:"lead";a:2:{i:0;a:4:{s:4:"name";s:19:"Cipriano Groenendal";s:4:"user";s:5:"cipri";s:5:"email";s:13:"cipri@php.net";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:12:"Alan Knowles";s:4:"user";s:6:"alan_k";s:5:"email";s:17:"alan@akbkhome.com";s:6:"active";s:3:"yes";}}s:9:"developer";a:4:{s:4:"name";s:19:"George Schlossnagle";s:4:"user";s:13:"gschlossnagle";s:5:"email";s:17:"george@omniti.com";s:6:"active";s:2:"no";}s:4:"date";s:10:"2016-08-29";s:4:"time";s:8:"03:04:25";s:7:"version";a:2:{s:7:"release";s:5:"1.5.6";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:245:"Minor Bug fix release. #20431 - support for android #19762 - multipart signed not split correctly on line breaks #20027 - replace /e with preg_replace_callback #19762 - multipart/signed eating of new line, and expose sig_hdr etc.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:5:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"05c45d0b58718ebe73860ebfe494dcef";s:4:"name";s:19:"Mail/mimeDecode.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"642acc06cdb217b6e64506182449d8f8";s:4:"name";s:29:"tests/parse_header_value.phpt";s:4:"role";s:4:"test";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"a0bc0c9b68e62a19202bd8fb26104f3c";s:4:"name";s:41:"tests/semicolon_content_type_bug1724.phpt";s:4:"role";s:4:"test";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"194810c478066eaeb28f51116b88e25a";s:4:"name";s:9:"xmail.dtd";s:4:"role";s:4:"data";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"61cea06fb6b4bd3a4b5e2d37384e14a9";s:4:"name";s:9:"xmail.xsl";s:4:"role";s:4:"data";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.6.0";}s:7:"package";a:4:{s:4:"name";s:9:"Mail_Mime";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";s:7:"exclude";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:8:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.1.0";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-06-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:15:"Initial Release";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.0.0RC1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-06-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:15:"Initial Release";}i:2;a:6:{s:4:"date";s:10:"2007-06-17";s:4:"time";s:8:"17:20:44";s:7:"version";a:2:{s:7:"release";s:5:"1.5.0";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:55:"First release of mail_mimeDecode as a seperate package.";}i:3;a:5:{s:4:"date";s:10:"2009-12-03";s:7:"version";a:2:{s:7:"release";s:5:"1.5.1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:245:"Minor Bugfix release. Bug Fixes #----- - fix bug in getSendArray() - not handling multiple recipents #14129 - E_NOTICE fixes Requests #12365 - Add option to also include raw attached messages patched on the request of till";}i:4;a:5:{s:4:"date";s:10:"2010-09-02";s:7:"version";a:2:{s:7:"release";s:5:"1.5.2";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:271:"Minor Bugfix release. Bug Fixes #4739 - regexp parsing of header values does not balance quoting correctly - Fix sponsored by http://webyog.com #17325 - empty body messages are valid messages #17276 - remove &new usage which throws errors now";}i:5;a:5:{s:4:"date";s:10:"2010-09-05";s:7:"version";a:2:{s:7:"release";s:5:"1.5.3";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:919:"Major Bugfix release. Apart from a major cleanout of the bug tracker for this package, this release includes a revamped parseHeaderValue which removes the rather flakey regex, with a real parser, which should be considerably more robust. Bug Fixes #17844 - all regression tests fixed - remove the last of the while list each() .. this is 2010 ;)... #11410 - support wap multipart #9616 - long strings as filename etc.. aaa*0=.... aaa*1=.... aaa*2=.... (merged into aaa=.....) #9100 - change to preg_split for mime boundary detection , in theory should catch boundaries in nested situations better... #7709 - check for last element on boundary split to see if its usable #7065 - wrapped header lines with encoding should be concated without spaces #6495 - missing body in decoded object #11537 - better decode and multi-line support";}i:6;a:5:{s:4:"date";s:10:"2010-09-14";s:7:"version";a:2:{s:7:"release";s:5:"1.5.4";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:268:"Critical Security release. It is highly recommended that users of 1.5.3 upgrade to this release, a change in the boundary detection code introduced a potential denial of service attack. Bug Fixes #17862 - quote boundary preg_split code";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.5";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2011-11-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:287:"Minor Bug fix release. #17959 - Boundaries ending with non-word characters - patch by Alex Adriaanese ------ - ignore whitespace and trailing cr/lf in last section of split ------ - correct spacing on multi-line headers. now only striped for encoded data. (on previous line)";}}}s:8:"filelist";a:5:{s:19:"Mail/mimeDecode.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"05c45d0b58718ebe73860ebfe494dcef";s:4:"name";s:19:"Mail/mimeDecode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:49:"/opt/alt/php52/usr/share/pear/Mail/mimeDecode.php";}s:29:"tests/parse_header_value.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"642acc06cdb217b6e64506182449d8f8";s:4:"name";s:29:"tests/parse_header_value.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:80:"/opt/alt/php52/usr/share/pear/test/Mail_mimeDecode/tests/parse_header_value.phpt";}s:41:"tests/semicolon_content_type_bug1724.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"a0bc0c9b68e62a19202bd8fb26104f3c";s:4:"name";s:41:"tests/semicolon_content_type_bug1724.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php52/usr/share/pear/test/Mail_mimeDecode/tests/semicolon_content_type_bug1724.phpt";}s:9:"xmail.dtd";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"194810c478066eaeb28f51116b88e25a";s:4:"name";s:9:"xmail.dtd";s:4:"role";s:4:"data";s:12:"installed_as";s:60:"/opt/alt/php52/usr/share/pear/data/Mail_mimeDecode/xmail.dtd";}s:9:"xmail.xsl";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"61cea06fb6b4bd3a4b5e2d37384e14a9";s:4:"name";s:9:"xmail.xsl";s:4:"role";s:4:"data";s:12:"installed_as";s:60:"/opt/alt/php52/usr/share/pear/data/Mail_mimeDecode/xmail.xsl";}}s:12:"_lastversion";N;s:7:"dirtree";a:7:{s:34:"/opt/alt/php52/usr/share/pear/Mail";b:1;s:34:"/opt/alt/php52///usr/share/pearail";b:1;s:56:"/opt/alt/php52/usr/share/pear/test/Mail_mimeDecode/tests";b:1;s:56:"/opt/alt/php52///usr/share/pear/testail_mimeDecode/tests";b:1;s:50:"/opt/alt/php52///usr/share/pear/testail_mimeDecode";b:1;s:50:"/opt/alt/php52/usr/share/pear/data/Mail_mimeDecode";b:1;s:50:"/opt/alt/php52///usr/share/pear/dataail_mimeDecode";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.5.6";s:12:"release_date";s:10:"2016-08-29";s:13:"release_state";s:6:"stable";s:15:"release_license";s:9:"BSD Style";s:13:"release_notes";s:245:"Minor Bug fix release. #20431 - support for android #19762 - multipart signed not split correctly on line breaks #20027 - replace /e with preg_replace_callback #19762 - multipart/signed eating of new line, and expose sig_hdr etc.";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.3.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.6.0";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:9:"Mail_Mime";s:3:"rel";s:2:"gt";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:3:{i:0;a:5:{s:4:"name";s:19:"Cipriano Groenendal";s:5:"email";s:13:"cipri@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:5:"cipri";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:12:"Alan Knowles";s:5:"email";s:17:"alan@akbkhome.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"alan_k";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:19:"George Schlossnagle";s:5:"email";s:17:"george@omniti.com";s:6:"active";s:2:"no";s:6:"handle";s:13:"gschlossnagle";s:4:"role";s:9:"developer";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506465;}PK�������!�q������.registry/net_smtp.regnu�[��������a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.5";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:8:"Net_SMTP";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:38:"An implementation of the SMTP protocol";s:11:"description";s:78:"Provides an implementation of the SMTP protocol using PEAR's Net_Socket class.";s:4:"lead";a:2:{i:0;a:4:{s:4:"name";s:10:"Jon Parise";s:4:"user";s:3:"jon";s:5:"email";s:11:"jon@php.net";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:15:"Chuck Hagenbuch";s:4:"user";s:8:"chagenbu";s:5:"email";s:15:"chuck@horde.org";s:6:"active";s:3:"yes";}}s:4:"date";s:10:"2015-08-02";s:4:"time";s:8:"17:21:09";s:7:"version";a:2:{s:7:"release";s:5:"1.6.3";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:113:"- Fix redundant CRLF terminator sequence. - Add a note about $socket_options and OpenSSL. - Add Composer support.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:7:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2baaf24fc450480e7f00f4db86f29e0e";s:4:"name";s:14:"docs/guide.txt";s:4:"role";s:3:"doc";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5ef820d1bc73898b55a153576953fe70";s:4:"name";s:18:"examples/basic.php";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0cd9a0c35d1ea17d46de9b5a39fb771d";s:4:"name";s:15:"tests/auth.phpt";s:4:"role";s:4:"test";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7c529009553889322a2bc4d2bc7eb84a";s:4:"name";s:16:"tests/basic.phpt";s:4:"role";s:4:"test";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8517c458ae5094ee3c31a545d51c69c8";s:4:"name";s:21:"tests/config.php.dist";s:4:"role";s:4:"test";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"747cf1bc82c9f47ec3189371ec18ac8d";s:4:"name";s:20:"tests/quotedata.phpt";s:4:"role";s:4:"test";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8466d8f3eb23134bc8120c8462d17883";s:4:"name";s:12:"Net/SMTP.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.0.5";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.3";}s:7:"package";a:3:{s:4:"name";s:10:"Net_Socket";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.7";}}s:8:"optional";a:1:{s:7:"package";a:3:{s:4:"name";s:9:"Auth_SASL";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.5";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:7:{s:14:"docs/guide.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2baaf24fc450480e7f00f4db86f29e0e";s:4:"name";s:14:"docs/guide.txt";s:4:"role";s:3:"doc";s:12:"installed_as";s:57:"/opt/alt/php52/usr/share/doc/pear/Net_SMTP/docs/guide.txt";}s:18:"examples/basic.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5ef820d1bc73898b55a153576953fe70";s:4:"name";s:18:"examples/basic.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:61:"/opt/alt/php52/usr/share/doc/pear/Net_SMTP/examples/basic.php";}s:15:"tests/auth.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0cd9a0c35d1ea17d46de9b5a39fb771d";s:4:"name";s:15:"tests/auth.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:59:"/opt/alt/php52/usr/share/pear/test/Net_SMTP/tests/auth.phpt";}s:16:"tests/basic.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7c529009553889322a2bc4d2bc7eb84a";s:4:"name";s:16:"tests/basic.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:60:"/opt/alt/php52/usr/share/pear/test/Net_SMTP/tests/basic.phpt";}s:21:"tests/config.php.dist";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8517c458ae5094ee3c31a545d51c69c8";s:4:"name";s:21:"tests/config.php.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/opt/alt/php52/usr/share/pear/test/Net_SMTP/tests/config.php.dist";}s:20:"tests/quotedata.phpt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"747cf1bc82c9f47ec3189371ec18ac8d";s:4:"name";s:20:"tests/quotedata.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php52/usr/share/pear/test/Net_SMTP/tests/quotedata.phpt";}s:12:"Net/SMTP.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8466d8f3eb23134bc8120c8462d17883";s:4:"name";s:12:"Net/SMTP.php";s:4:"role";s:3:"php";s:12:"installed_as";s:42:"/opt/alt/php52/usr/share/pear/Net/SMTP.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:10:{s:47:"/opt/alt/php52/usr/share/doc/pear/Net_SMTP/docs";b:1;s:47:"/opt/alt/php52//usr/share/doc/pearNet_SMTP/docs";b:1;s:42:"/opt/alt/php52//usr/share/doc/pearNet_SMTP";b:1;s:51:"/opt/alt/php52/usr/share/doc/pear/Net_SMTP/examples";b:1;s:51:"/opt/alt/php52//usr/share/doc/pearNet_SMTP/examples";b:1;s:49:"/opt/alt/php52/usr/share/pear/test/Net_SMTP/tests";b:1;s:49:"/opt/alt/php52///usr/share/pear/testet_SMTP/tests";b:1;s:43:"/opt/alt/php52///usr/share/pear/testet_SMTP";b:1;s:33:"/opt/alt/php52/usr/share/pear/Net";b:1;s:33:"/opt/alt/php52///usr/share/pearet";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.6.3";s:12:"release_date";s:10:"2015-08-02";s:13:"release_state";s:6:"stable";s:15:"release_license";s:11:"PHP License";s:13:"release_notes";s:113:"- Fix redundant CRLF terminator sequence. - Add a note about $socket_options and OpenSSL. - Add Composer support.";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.0.5";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.3";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:10:"Net_Socket";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.0.7";s:8:"optional";s:2:"no";}i:3;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:9:"Auth_SASL";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.0.5";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:2:{i:0;a:5:{s:4:"name";s:10:"Jon Parise";s:5:"email";s:11:"jon@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:3:"jon";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:15:"Chuck Hagenbuch";s:5:"email";s:15:"chuck@horde.org";s:6:"active";s:3:"yes";s:6:"handle";s:8:"chagenbu";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506465;}PK�������!�=��=����.registry/net_idna2.regnu�[��������a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.1";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:9:"Net_IDNA2";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:31:"Punycode encoding and decoding.";s:11:"description";s:68:"This package helps you to encode and decode punycode strings easily.";s:4:"lead";a:2:{i:0;a:4:{s:4:"name";s:15:"Stefan Neufeind";s:4:"user";s:8:"neufeind";s:5:"email";s:29:"pear.neufeind@speedpartner.de";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:15:"Daniel O'Connor";s:4:"user";s:8:"doconnor";s:5:"email";s:24:"daniel.oconnor@gmail.com";s:6:"active";s:2:"no";}}s:4:"date";s:10:"2010-12-09";s:4:"time";s:8:"17:32:13";s:7:"version";a:2:{s:7:"release";s:5:"0.1.1";s:3:"api";s:5:"0.1.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:39:"http://www.gnu.org/copyleft/lesser.html";}s:8:"_content";s:4:"LGPL";}s:5:"notes";s:784:"* Added initial support for IDNA2008. This is needed for characters like the German "Eszett" which would otherwise be turned into "ss" during nameprep. Use $n->setParams('version', '2008') to use the "new" IDNA-encoding. Default is still IDNA2003 for backwards-compatibility. Further aspects of IDNA2008-encoding (for example some checks) should be added later according to RFCs. * #16466: Unit tests (testcaseses from draft-josefsson-idn-test-vectors; thanks to Daniel) * Unit tests (coverage, refactoring/cleanup, more tests) * #17542: URIs get mangled when decoding (UTF8-fix) * Codingstyle fixes * fixed handling of URLs with more than a domain-name (fixed opposite of parse_url()) * Added specialized and spl exceptions * #17533: Releases and roles do not seem to work.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:6:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"def073c649f1033d8a75189f6a99cf9d";s:4:"name";s:13:"Net/IDNA2.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"72f605f2f6d9d56e07bb6bcec099d03a";s:4:"name";s:23:"Net/IDNA2/Exception.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"06c4217024082f0f3b6c5a7e61ac7130";s:4:"name";s:32:"Net/IDNA2/Exception/Nameprep.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9ccee505f9ac173b5a31a1cfb5ef2a35";s:4:"name";s:29:"docs/examples/example_web.php";s:4:"role";s:3:"doc";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6f236309ef8b74d40c137f3191d6de3b";s:4:"name";s:18:"tests/AllTests.php";s:4:"role";s:4:"test";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5f8a705f1d3e13ff60ec55ee77d275de";s:4:"name";s:23:"tests/Net_IDNA2Test.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.2.1";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.9.0";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.1.0";s:3:"api";s:5:"0.1.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2010-06-03";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:39:"http://www.gnu.org/copyleft/lesser.html";}s:8:"_content";s:4:"LGPL";}s:5:"notes";s:139:"QA Release Bug #17430 Multiple Net_IDNA class declarations Warning: This package is now split between Net_IDNA (php4) and Net_IDNA2 (php5)";}}s:8:"filelist";a:6:{s:13:"Net/IDNA2.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"def073c649f1033d8a75189f6a99cf9d";s:4:"name";s:13:"Net/IDNA2.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php52/usr/share/pear/Net/IDNA2.php";}s:23:"Net/IDNA2/Exception.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"72f605f2f6d9d56e07bb6bcec099d03a";s:4:"name";s:23:"Net/IDNA2/Exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php52/usr/share/pear/Net/IDNA2/Exception.php";}s:32:"Net/IDNA2/Exception/Nameprep.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"06c4217024082f0f3b6c5a7e61ac7130";s:4:"name";s:32:"Net/IDNA2/Exception/Nameprep.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php52/usr/share/pear/Net/IDNA2/Exception/Nameprep.php";}s:29:"docs/examples/example_web.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9ccee505f9ac173b5a31a1cfb5ef2a35";s:4:"name";s:29:"docs/examples/example_web.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:73:"/opt/alt/php52/usr/share/doc/pear/Net_IDNA2/docs/examples/example_web.php";}s:18:"tests/AllTests.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6f236309ef8b74d40c137f3191d6de3b";s:4:"name";s:18:"tests/AllTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:63:"/opt/alt/php52/usr/share/pear/test/Net_IDNA2/tests/AllTests.php";}s:23:"tests/Net_IDNA2Test.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5f8a705f1d3e13ff60ec55ee77d275de";s:4:"name";s:23:"tests/Net_IDNA2Test.php";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/opt/alt/php52/usr/share/pear/test/Net_IDNA2/tests/Net_IDNA2Test.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:13:{s:33:"/opt/alt/php52/usr/share/pear/Net";b:1;s:33:"/opt/alt/php52///usr/share/pearet";b:1;s:39:"/opt/alt/php52/usr/share/pear/Net/IDNA2";b:1;s:39:"/opt/alt/php52///usr/share/pearet/IDNA2";b:1;s:49:"/opt/alt/php52/usr/share/pear/Net/IDNA2/Exception";b:1;s:49:"/opt/alt/php52///usr/share/pearet/IDNA2/Exception";b:1;s:57:"/opt/alt/php52/usr/share/doc/pear/Net_IDNA2/docs/examples";b:1;s:57:"/opt/alt/php52//usr/share/doc/pearNet_IDNA2/docs/examples";b:1;s:48:"/opt/alt/php52//usr/share/doc/pearNet_IDNA2/docs";b:1;s:43:"/opt/alt/php52//usr/share/doc/pearNet_IDNA2";b:1;s:50:"/opt/alt/php52/usr/share/pear/test/Net_IDNA2/tests";b:1;s:50:"/opt/alt/php52///usr/share/pear/testet_IDNA2/tests";b:1;s:44:"/opt/alt/php52///usr/share/pear/testet_IDNA2";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"0.1.1";s:12:"release_date";s:10:"2010-12-09";s:13:"release_state";s:4:"beta";s:15:"release_license";s:4:"LGPL";s:13:"release_notes";s:784:"* Added initial support for IDNA2008. This is needed for characters like the German "Eszett" which would otherwise be turned into "ss" during nameprep. Use $n->setParams('version', '2008') to use the "new" IDNA-encoding. Default is still IDNA2003 for backwards-compatibility. Further aspects of IDNA2008-encoding (for example some checks) should be added later according to RFCs. * #16466: Unit tests (testcaseses from draft-josefsson-idn-test-vectors; thanks to Daniel) * Unit tests (coverage, refactoring/cleanup, more tests) * #17542: URIs get mangled when decoding (UTF8-fix) * Codingstyle fixes * fixed handling of URLs with more than a domain-name (fixed opposite of parse_url()) * Added specialized and spl exceptions * #17533: Releases and roles do not seem to work.";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.2.1";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.9.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:2:{i:0;a:5:{s:4:"name";s:15:"Stefan Neufeind";s:5:"email";s:29:"pear.neufeind@speedpartner.de";s:6:"active";s:3:"yes";s:6:"handle";s:8:"neufeind";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:15:"Daniel O'Connor";s:5:"email";s:24:"daniel.oconnor@gmail.com";s:6:"active";s:2:"no";s:6:"handle";s:8:"doconnor";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506464;}PK�������!�Ru������.registry/mail_mime.regnu�[��������a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:7:"1.10.12";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:9:"Mail_Mime";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:51:"Mail_Mime provides classes to create MIME messages.";s:11:"description";s:395:"Mail_Mime provides classes to deal with the creation and manipulation of MIME messages. It allows people to create e-mail messages consisting of: * Text Parts * HTML Parts * Inline HTML Images * Attachments * Attached messages It supports big messages, base64 and quoted-printable encodings and non-ASCII characters in filenames, subjects, recipients, etc. encoded using RFC2047 and/or RFC2231.";s:4:"lead";a:2:{i:0;a:4:{s:4:"name";s:19:"Cipriano Groenendal";s:4:"user";s:5:"cipri";s:5:"email";s:13:"cipri@php.net";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:19:"Aleksander Machniak";s:4:"user";s:4:"alec";s:5:"email";s:12:"alec@php.net";s:6:"active";s:3:"yes";}}s:4:"date";s:10:"2021-09-05";s:4:"time";s:8:"08:43:21";s:7:"version";a:2:{s:7:"release";s:7:"1.10.11";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:246:"* Fix PHP 8.1: strlen(): Passing null to parameter #1 ($string) of type string is deprecated [alec] * Fix encoding recipient names with @ character and no space between name and address [alec] * Fix the license label in composer.json [jnkowa-gfk]";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:53:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"edd138f6c5497ae2b5d63620a67a931e";s:4:"name";s:25:"tests/class-filename.phpt";s:4:"role";s:4:"test";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"7ec986391d0af058316f66e5a507e059";s:4:"name";s:36:"tests/content_transfer_encoding.phpt";s:4:"role";s:4:"test";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"c1a43360d9b2cb5f9542503a4355c277";s:4:"name";s:24:"tests/encoding_case.phpt";s:4:"role";s:4:"test";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"bf50a200190cad5e2d4aae4e120ea09f";s:4:"name";s:32:"tests/headers_with_mbstring.phpt";s:4:"role";s:4:"test";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"9a2d207f873317125ff43c092f3f0d25";s:4:"name";s:35:"tests/headers_without_mbstring.phpt";s:4:"role";s:4:"test";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"25d4c5b9fdeaabc7810c26e6f89e95ca";s:4:"name";s:27:"tests/qp_encoding_test.phpt";s:4:"role";s:4:"test";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"958197f31b4a20c91dd42662595e7516";s:4:"name";s:41:"tests/sleep_wakeup_EOL-bug3488-part1.phpt";s:4:"role";s:4:"test";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"46675529f1f021b51a1aa0ae6c971cd2";s:4:"name";s:41:"tests/sleep_wakeup_EOL-bug3488-part2.phpt";s:4:"role";s:4:"test";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"f8c05910737e451c7a9d4737b8d9f095";s:4:"name";s:26:"tests/test_Bug_3513_1.phpt";s:4:"role";s:4:"test";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"edb467a375ddf09e777a9388e2e8cbb5";s:4:"name";s:26:"tests/test_Bug_3513_2.phpt";s:4:"role";s:4:"test";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"70c2456445eaaa80779206e9e245d685";s:4:"name";s:26:"tests/test_Bug_3513_3.phpt";s:4:"role";s:4:"test";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"4cda500d0d7925e81a299f1d3db132a9";s:4:"name";s:26:"tests/test_Bug_7561_1.phpt";s:4:"role";s:4:"test";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"42a214e7e3d3afa07f8996b235222611";s:4:"name";s:26:"tests/test_Bug_8386_1.phpt";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ed78099563499f60386a128cb7b96925";s:4:"name";s:26:"tests/test_Bug_8541_1.phpt";s:4:"role";s:4:"test";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"5250a0693599b945e8642a1a289d7275";s:4:"name";s:26:"tests/test_Bug_9722_1.phpt";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b7f58f54e1485c23a60c83cd3cc5563e";s:4:"name";s:27:"tests/test_Bug_10596_1.phpt";s:4:"role";s:4:"test";}}i:16;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ccb53d80e7f5c9f28b11abce5fe5d490";s:4:"name";s:27:"tests/test_Bug_10816_1.phpt";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"f3d92a1fff099173b8600fb3646d0614";s:4:"name";s:27:"tests/test_Bug_10999_1.phpt";s:4:"role";s:4:"test";}}i:18;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"3f2757d5db43abd8f177f094f4d53625";s:4:"name";s:25:"tests/test_Bug_11381.phpt";s:4:"role";s:4:"test";}}i:19;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"c64d675e73bc02fc94f5d03b3117cfa0";s:4:"name";s:25:"tests/test_Bug_11731.phpt";s:4:"role";s:4:"test";}}i:20;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"8c9305ca05f5ed2d7cd7e31e4836f17a";s:4:"name";s:25:"tests/test_Bug_12165.phpt";s:4:"role";s:4:"test";}}i:21;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"2aa2c3dfbe44500809e79da994272611";s:4:"name";s:27:"tests/test_Bug_12385_1.phpt";s:4:"role";s:4:"test";}}i:22;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ef1d726233dbd3360c540fd6a959b0d0";s:4:"name";s:25:"tests/test_Bug_12411.phpt";s:4:"role";s:4:"test";}}i:23;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"a862a57ff622fcbb2328be6c805e2d05";s:4:"name";s:25:"tests/test_Bug_12466.phpt";s:4:"role";s:4:"test";}}i:24;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"4eddeeac08f351feb147ab6fda439526";s:4:"name";s:25:"tests/test_Bug_13032.phpt";s:4:"role";s:4:"test";}}i:25;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"de15a0657a83694bc6991c4184ccf9bd";s:4:"name";s:25:"tests/test_Bug_13444.phpt";s:4:"role";s:4:"test";}}i:26;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"80afe9fced03288884e9d302d1e65b2d";s:4:"name";s:25:"tests/test_Bug_13962.phpt";s:4:"role";s:4:"test";}}i:27;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"89bf87e798f4a149a150d4c2a505f976";s:4:"name";s:25:"tests/test_Bug_14529.phpt";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"5f9100adb1c609110ed495fafa819975";s:4:"name";s:25:"tests/test_Bug_14779.phpt";s:4:"role";s:4:"test";}}i:29;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"45eb42fe4e325da64f1ae8f149e2a396";s:4:"name";s:25:"tests/test_Bug_14780.phpt";s:4:"role";s:4:"test";}}i:30;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"609dad2083c54ba56ea691c488ca20e2";s:4:"name";s:25:"tests/test_Bug_15320.phpt";s:4:"role";s:4:"test";}}i:31;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"f4ef08e416e775558e8075b531bbc814";s:4:"name";s:25:"tests/test_Bug_16539.phpt";s:4:"role";s:4:"test";}}i:32;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ed1bd0fc9067b3fb8b95808bfa315916";s:4:"name";s:25:"tests/test_Bug_17025.phpt";s:4:"role";s:4:"test";}}i:33;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"8a37de74fb39fed4566617a7ea38bb69";s:4:"name";s:25:"tests/test_Bug_17175.phpt";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b9dee3c7c45d8c6c22f860e93c3769b9";s:4:"name";s:25:"tests/test_Bug_18083.phpt";s:4:"role";s:4:"test";}}i:35;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"96ce23ad1a1d6417facfcdd2baa9c8eb";s:4:"name";s:25:"tests/test_Bug_18772.phpt";s:4:"role";s:4:"test";}}i:36;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"dd98307b3224b173f7b54f7e403865a4";s:4:"name";s:25:"tests/test_Bug_19497.phpt";s:4:"role";s:4:"test";}}i:37;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"e1194180cb6a218fab69db90f88d1cb2";s:4:"name";s:25:"tests/test_Bug_20226.phpt";s:4:"role";s:4:"test";}}i:38;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"1b7919174edcd1cf5d5fd5a622fdac9b";s:4:"name";s:25:"tests/test_Bug_20273.phpt";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"6513c4b0c9e962c900d020124752333e";s:4:"name";s:25:"tests/test_Bug_20563.phpt";s:4:"role";s:4:"test";}}i:40;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"7c7a00818cb0f01fa6c52c920b9e76c6";s:4:"name";s:25:"tests/test_Bug_20564.phpt";s:4:"role";s:4:"test";}}i:41;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b9e31a9c24b05dfb6166512e04e2f056";s:4:"name";s:25:"tests/test_Bug_21027.phpt";s:4:"role";s:4:"test";}}i:42;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b634a5e99aa26a8b6df8fcfae07051b4";s:4:"name";s:25:"tests/test_Bug_21098.phpt";s:4:"role";s:4:"test";}}i:43;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b21be5b099a69428bd37e60589cdd485";s:4:"name";s:25:"tests/test_Bug_21205.phpt";s:4:"role";s:4:"test";}}i:44;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"bc152c12839964fba15da5673d25c4db";s:4:"name";s:25:"tests/test_Bug_21206.phpt";s:4:"role";s:4:"test";}}i:45;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ccf732525be42c955eea18e78490c3e1";s:4:"name";s:25:"tests/test_Bug_21255.phpt";s:4:"role";s:4:"test";}}i:46;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"579f1e11da6c8074dbf508dc1f1dedfa";s:4:"name";s:24:"tests/test_Bug_GH16.phpt";s:4:"role";s:4:"test";}}i:47;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"df32d66d9fccf7a0956422811283272a";s:4:"name";s:24:"tests/test_Bug_GH19.phpt";s:4:"role";s:4:"test";}}i:48;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b7b5b5bacc6a599cfaece35ad202ad1a";s:4:"name";s:24:"tests/test_Bug_GH26.phpt";s:4:"role";s:4:"test";}}i:49;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"e08958f1bb60561f072a3508b8fd3e2e";s:4:"name";s:29:"tests/test_linebreak_dot.phpt";s:4:"role";s:4:"test";}}i:50;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"8398e9bfea0bc7c4ff0770ae3d6279fe";s:4:"name";s:35:"tests/test_linebreak_larger_76.phpt";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e5c9ac7f32e53afdeafd1a84343a89ae";s:4:"name";s:13:"Mail/mime.php";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"36128789ad1101d39d13b06ca2585576";s:4:"name";s:17:"Mail/mimePart.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.2.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.6.0";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:48:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.0";s:3:"api";s:3:"1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2001-12-28";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:3:"PHP";}s:5:"notes";s:53:"This is the initial release of the Mime_Mail package.";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.1";s:3:"api";s:3:"1.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-04-03";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:3:"PHP";}s:5:"notes";s:75:"This is a maintenance release with various bugfixes and minor enhancements.";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.2";s:3:"api";s:3:"1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-07-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:3:"PHP";}s:5:"notes";s:180:"* Added header encoding * Altered mimePart to put boundary parameter on newline * Changed addFrom() to setFrom() * Added setSubject() * Made mimePart inherit crlf setting from mime";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.1";s:3:"api";s:5:"1.2.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-07-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:3:"PHP";}s:5:"notes";s:62:"* License change * Applied a few changes From Ilia Alshanetsky";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.3.0RC1";s:3:"api";s:8:"1.3.0RC1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-03-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:3:"PHP";}s:5:"notes";s:94:"* First release in over 2.5 years (!) * MANY bugfixes (see the bugtracker) * added a few tests";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.0";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-04-01";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:3:"PHP";}s:5:"notes";s:141:"* First (stable) release in over 2.5 years (!) * MANY bugfixes (see the bugtracker) * added a few tests * one small fix after RC1 (bug #3940)";}i:6;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-07-13";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:3:"PHP";}s:5:"notes";s:0:"";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:7:"1.4.0a1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-03-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"bsd style";}s:5:"notes";s:1481:"* Changed License to BSD Style license, as that's what the code was since the beginning [cipri] * Fix Bug #30: Mail_Mime: _encodeHeaders is not RFC-2047 compliant. [cipri] * Fix Bug #3513: support of RFC2231 in header fields. [cipri] * Fix Bug #4696: addAttachment crash [cipri] * Fix Bug #5333: Only variables should be returned by reference; triggers notices since php 4.4.0 [cipri] * Fix Bug #7561: Mail_mimePart::_quotedPrintableEncode() misbehavior with mbstring overload [cipri] * Fix Bug #8223: Incorrectly encoded quoted-printable headers [cipri] * Fix Bug #8386: HTML body not correctly encoded if attachments present [cipri] * Fix Bug #8541: mimePart.php line delimiter is \r [cipri] * Fix Bug #9347: Notices about references [cweiske] * Fix Bug #9558: Broken multiline headers [cipri] * Fix Bug #9956: Notices being thrown [cipri] * Fix Bug #9976: Subject encoded twice [cipri] * Implement Feature #2952: Mail_mime::headers() saves extra headers [cipri] * Implement Feature #3636: Allow specification of charsets and encoding [cipri] * Implement Feature #4057: Mail_Mime: Add name parameter for Content-Type [cipri] * Implement Feature #4504: addHTMLImage does not work in cases when filename contains a path [cipri] * Implement Feature #5837: Mail_Mime: Build message for Net_SMTP [cipri] * Implement Feature #5934: Mail_Mime: choice for content disposition [cipri] * Implement Feature #6568: Mail_Mime: inline images referenced in CSS definitions not replaced. [cipri]";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:7:"1.4.0a2";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-04-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"bsd style";}s:5:"notes";s:553:"* Fix Bug #9722: _quotedPrintableEncode does not encode dot at start of line on Windows platform [cipri] * Fix Bug #9725: multipart/related & alternative wrong order [cipri] * Fix Bug #10146: mbstring fails to recognize encodings. [cipri] * Fix Bug #10158: Inline images not displayed on Mozilla Thunderbird [cipri] * Fix Bug #10298: Mail_mime, double Quotes and Specialchars in from and to Adress [cipri] * Fix Bug #10306: Strings with Double Quotes get encoded wrongly [cipri] * Fix Bug #10596: Incorrect handling of text and html '0' bodies [cipri]";}i:9;a:5:{s:7:"version";a:2:{s:7:"release";s:7:"1.4.0a3";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-04-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"bsd style";}s:5:"notes";s:162:"* Fix Bug #10298: Mail_mime, double Quotes and Specialchars in from and to Adress [cipri] * Fix Bug #10306: Strings with Double Quotes get encoded wrongly [cipri]";}i:10;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.4.0RC1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-04-12";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"bsd style";}s:5:"notes";s:75:"* Fix Bug #10232: Gmail creates double line break when \r\n is used [cipri]";}i:11;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.4.0RC2";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-04-22";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"bsd style";}s:5:"notes";s:187:"* Fix Bug #10791: Unit tests fail [cipri] * Fix Bug #10792: No unit tests for recently fixed bugs [cipri] * Fix Bug #10793: Long headers don't get wrapped since fix for Bug #10298 [cipri]";}i:12;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.4.0RC3";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-04-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"bsd style";}s:5:"notes";s:65:"* Fix Bug #10816: Unwanted linebreak at the end of output [cipri]";}i:13;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.4.0RC4";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-04-28";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"bsd style";}s:5:"notes";s:123:"* Fix Bug #3513: support of RFC2231 in header fields. [cipri] * Fix Bug #10838: bad use of MIME encoding in header. [cipri]";}i:14;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.0";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-05-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:3343:"Release notes: * No more notices in PHP 5 /4.4.0. * Improved inline HTML image function. * Improved header encoding with foreign charsets. * Improved long header rendering. * More control over used Charsets and encoding schemes. * More configurable attachments and inline images. * Full RFC 2047 Support * Full RFC 2231 Support * Unit-tests Fixed bugs: * Fix Bug #30: Mail_Mime: _encodeHeaders is not RFC-2047 compliant. [cipri] * Fix Bug #3513: support of RFC2231 in header fields. [cipri] * Fix Bug #4696: addAttachment crash [cipri] * Fix Bug #5333: Only variables should be returned by reference; triggers notices since php 4.4.0 [cipri] * Fix Bug #5400: Do not return function reference [cipri] * Fix Bug #5710: Little reference bugs [cipri] * Fix Bug #5890: Only variable references should be returned by reference [cipri] * Fix Bug #6260: Just a notice with PHP5 [cipri] * Fix Bug #6261: php 5.1.1 upgrade [cipri] * Fix Bug #6663: Notice about reference passing [cipri] * Fix Bug #7561: Mail_mimePart::_quotedPrintableEncode() misbehavior with mbstring overload [cipri] * Fix Bug #7713: PHP5 Notice: Only variable references should be returned by reference [cipri] * Fix Bug #8223: Incorrectly encoded quoted-printable headers [cipri] * Fix Bug #8386: HTML body not correctly encoded if attachments present [cipri] * Fix Bug #8541: mimePart.php line delimiter is \r [cipri] * Fix Bug #8812: user header updates overwritten [cipri] * Fix Bug #9347: Notices about references [cweiske] * Fix Bug #9558: Broken multiline headers [cipri] * Fix Bug #9722: _quotedPrintableEncode does not encode dot at start of line on Windows platform [cipri] * Fix Bug #9725: multipart/related & alternative wrong order [cipri] * Fix Bug #9956: Notices being thrown [cipri] * Fix Bug #9976: Subject encoded twice [cipri] * Fix Bug #10146: mbstring fails to recognize encodings. [cipri] * Fix Bug #10158: Inline images not displayed on Mozilla Thunderbird [cipri] * Fix Bug #10232: Gmail creates double line break when \r\n is used [cipri] * Fix Bug #10298: Mail_mime, double Quotes and Specialchars in from and to Adress [cipri] * Fix Bug #10306: Strings with Double Quotes get encoded wrongly [cipri] * Fix Bug #10596: Incorrect handling of text and html '0' bodies [cipri] * Fix Bug #10791: Unit tests fail [cipri] * Fix Bug #10792: No unit tests for recently fixed bugs [cipri] * Fix Bug #10793: Long headers don't get wrapped since fix for Bug #10298 [cipri] * Fix Bug #10816: Unwanted linebreak at the end of output [cipri] * Fix Bug #10838: bad use of MIME encoding in header. [cipri] Implemented Features: * Implement Feature #2952: Mail_mime::headers() saves extra headers [cipri] * Implement Feature #3636: Allow specification of charsets and encoding [cipri] * Implement Feature #4057: Mail_Mime: Add name parameter for Content-Type [cipri] * Implement Feature #4504: addHTMLImage does not work in cases when filename contains a path [cipri] * Implement Feature #5837: Mail_Mime: Build message for Net_SMTP [cipri] * Implement Feature #5934: Mail_Mime: choice for content disposition [cipri] * Implement Feature #6568: Mail_Mime: inline images referenced in CSS definitions not replaced. [cipri] * Implement Feature #10604: Put an option to specify Content-Location in the header [cipri]";}i:15;a:5:{s:7:"version";a:2:{s:7:"release";s:7:"1.5.0a1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-06-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:25:"Split off mail_MimeDecode";}i:16;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.5.0RC1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-06-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:25:"Split off mail_MimeDecode";}i:17;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.0";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-06-17";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:25:"Split off Mail_MimeDecode";}i:18;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-06-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:55:"* Fix Bug #11344: Error at line 644 in mime.php [cipri]";}i:19;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.2";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-06-21";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:107:"* Fix Bug #11381: domain name is attached to content-id, trailing greater-than sign is not remove [cipri]";}i:20;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.3";s:3:"api";s:5:"1.3.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-12-29";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:1264:"Fixed bugs: * Fix Bug #14678: srand() lowers security [clockwerx] * Fix Bug #12921: _file2str not binary safe [walter] * Fix Bug #12385: Bad regex when replacing css style attachments [cipri] * Fix Bug #16911: Excessive semicolon in MIME header [alec] * Fix Bug #15320: Attachment charset is not set in Content-Type header [alec] * Fix Bug #16911: Lack of semicolon separator for MIME header parameters [alec] * Fix Bug #16846: Use preg_replace_callback() instead of /e modifier [alec] * Fix Bug #14779: Problem with an empty attachment [alec] * Fix Bug #15913: Optimize the memory used by Mail_mimePart::encode. Avoid having attachments data duplicated in memory [alec] * Fix Bug #16539: Headers longer than 998 characters aren't wrapped [alec] * Fix Bug #11238: Wrong encoding of structured headers [alec] * Fix Bug #13641: iconv_mime_encode() seems to work different/errorious than the build in logic. Removed 'ignore_iconv' param. [alec] * Fix Bug #16706: Incorrect double-quotes RFC 2231-encoded parameter values [alec] * Fix Bug #14232: RFC2231: tspecials encoding in _buildHeaderParam() [alec] Implemented Features: * Implement Feature #10438: Function (encodeHeader) for encoding of given header [alec]";}i:21;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.6.0";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-01-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:540:"Bugs Fixed: * Don't break specified headers folding [alec] * Bug #17025: Wrong headers() result for long unwrapable header value [alec] Implemented Features: * Allow setting Content-ID for HTML Images [alec] * Added one setParam() in place of many set*() functions [alec] * Added getParam(), getTXTBody(), getHTMLBody() [alec] * Skip RFC2231's charset if filename contains only ASCII characters [alec] * Make sure that Received: headers are returned on the top [alec] * Added saveMessageBody() and getMessageBody() functions [alec]";}i:22;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.6.1";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-03-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:262:"Bugs Fixed: * Fix encoding of Return-Receipt-To and Disposition-Notification-To headers [alec] Implemented Features: * Implement Feature #12466: Build parameters validation [alec] * Implement Feature #17175: Content-Description support for attachments [alec]";}i:23;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.6.2";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-03-23";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:103:"Bugs Fixed: * Fix Bug #17226: Non RFC-compliant quoted-printable encoding of structured headers [alec]";}i:24;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.7.0";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-04-12";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:233:"Implemented Features: * Added Mail_mime::setContentType() function with possibility to set various types in Content-Type header (also fixes problem with boundary parameter when Content-Type header was specified by user) [alec]";}i:25;a:5:{s:4:"date";s:10:"2010-07-29";s:7:"version";a:2:{s:7:"release";s:5:"1.8.0";s:3:"api";s:5:"1.4.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:314:"Bugs Fixed: * Double-addition of e-mail domain to content ID in HTML images [alec] * #17311: Multi-octet characters are split across adjacent 'encoded-word's [alec] * #17573: Place charset parameter in first line of Content-Type header (if possible) [alec] Implemented Features: * #17518: addTo() method [alec]";}i:26;a:5:{s:4:"date";s:10:"2010-12-01";s:7:"version";a:2:{s:7:"release";s:5:"1.8.1";s:3:"api";s:5:"1.4.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:101:"Bugs Fixed: * #18083: Not possible to set separate charset for attachment content and headers [alec]";}i:27;a:5:{s:4:"date";s:10:"2011-08-10";s:7:"version";a:2:{s:7:"release";s:5:"1.8.2";s:3:"api";s:5:"1.4.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:207:"Bugs Fixed: * #18426: Fixed backward compatibility for "dfilename" parameter [alec] * Removed xmail.dtd, xmail.xsl from the package [alec] * Fixed handling of email addresses with quoted local part [alec]";}i:28;a:5:{s:4:"date";s:10:"2012-03-12";s:7:"version";a:2:{s:7:"release";s:5:"1.8.3";s:3:"api";s:5:"1.4.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:232:"* Request #19009: Remove error_reporting from tests [alec] * Fixed Bug #19094: Email addresses do not have to contain a space between the name and address part [alec] * Fixed Bug #19328: Wrong encoding of filenames with comma [alec]";}i:29;a:5:{s:4:"date";s:10:"2012-05-17";s:7:"version";a:2:{s:7:"release";s:5:"1.8.4";s:3:"api";s:5:"1.4.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:179:"* Request #19406: Allow to set individual attachment part headers [alec] * Fixed Bug #18982: Non-static method Mail_mimePart::encodeHeader() should not be called statically [alec]";}i:30;a:5:{s:4:"date";s:10:"2012-06-09";s:7:"version";a:2:{s:7:"release";s:5:"1.8.5";s:3:"api";s:5:"1.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:198:"* Added possibility to set additional parameters of message part header, e.g. attachment size [alec] * Added automatic setting of attachment size via Content-Disposition header size parameter [alec]";}i:31;a:5:{s:4:"date";s:10:"2012-10-23";s:7:"version";a:2:{s:7:"release";s:5:"1.8.6";s:3:"api";s:5:"1.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:235:"* Bug #19473: PEAR::isError() compatibility problem with PHP 5.4 [alec] * Bug #19497: Attachment filename is cut on slash character [alec] * Bug #19665: Add Mail-Reply-To and Mail-Followup-To to structured recipient headers list [alec]";}i:32;a:5:{s:4:"date";s:10:"2012-12-25";s:7:"version";a:2:{s:7:"release";s:5:"1.8.7";s:3:"api";s:5:"1.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:104:"* Bug #5333: Fix more return by reference errors [alec] * Bug #19754: Fix compatibility with PHP4 [alec]";}i:33;a:5:{s:4:"date";s:10:"2013-07-05";s:7:"version";a:2:{s:7:"release";s:5:"1.8.8";s:3:"api";s:5:"1.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:294:"* Fixed warning/notice on (static vs. non-static) PEAR::raiseError() usage [alec] * Fixed Bug #19761: PHP5 warnings about return by reference [alec] * Fixed Bug #19770: Make cid generator more unique on Windows [alec] * Fixed Bug #19987: E_STRICT warning when null is passed by reference [alec]";}i:34;a:5:{s:4:"date";s:10:"2014-05-14";s:7:"version";a:2:{s:7:"release";s:5:"1.8.9";s:3:"api";s:5:"1.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:219:"* Fixed Bug #20273: Incorrect handling of HTAB in encodeHeader() [alec] * Fixed Bug #20226: Mail_mimePart::encodeHeader does not encode ISO-2022-JP string [alec] * Fixed Bug #20222: Broken Compatybility with PHP4 [alec]";}i:35;a:6:{s:4:"date";s:10:"2015-07-05";s:4:"time";s:8:"12:50:00";s:7:"version";a:2:{s:7:"release";s:8:"1.9.0RC1";s:3:"api";s:5:"2.0.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:314:"* Drop PHP4 support, Fix warnings on PHP7 [alec] * Request #20564: Added possibility to unset headers [alec] * Request #20563: Added isMultipart() method [alec] * Request #20565: Accept also a file pointer in Mail_mimePart::encodeToFile(), Mail_mime::get() and Mail_mime::saveMessageBody() [alec]";}i:36;a:6:{s:4:"date";s:10:"2015-08-06";s:4:"time";s:8:"12:00:00";s:7:"version";a:2:{s:7:"release";s:5:"1.9.0";s:3:"api";s:5:"1.9.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:200:"* Bug #20921: Make Mail_mimePart::encodeHeaderValue() a static method [alec] * Bug #20931: Really remove unset headers [alec] * Request #18772: Added methods for creating text/calendar messages [alec]";}i:37;a:6:{s:4:"date";s:10:"2015-09-13";s:4:"time";s:8:"12:00:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.0";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:156:"* Add possibility to add externally created Mail_mimePart objects as attachments [alec] * Add possibility to set preamble text for multipart messages [alec]";}i:38;a:6:{s:4:"date";s:10:"2017-05-21";s:4:"time";s:8:"12:00:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.1";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:286:"* Fix Bug 21206: explodeQuotedString() does not handle quoted strings correctly [dfukagaw28] * Fix Bug 21205: Invalid encoding of headers with quoted multibyte strings in non-unicode charset [dfukagaw28] * Fix Bug 21098: Discrepancy in handling of empty (but set) plain text part [alec]";}i:39;a:6:{s:4:"date";s:10:"2017-11-17";s:4:"time";s:8:"11:00:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.2";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:115:"* Fix Bug #21255: Boundary gets added twice when using setContentType() [alec] * PHP 7.2 compatibility fixes [alec]";}i:40;a:6:{s:4:"date";s:10:"2019-09-25";s:4:"time";s:8:"08:00:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.3";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:78:"* Fix deprecation warning for get_magic_quotes_runtime() use on PHP 7.4 [alec]";}i:41;a:6:{s:4:"date";s:10:"2019-10-13";s:4:"time";s:8:"11:00:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.4";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:63:"* Fix E_STRICT errors introduced in the previous release [alec]";}i:42;a:6:{s:4:"date";s:10:"2020-01-24";s:4:"time";s:8:"19:00:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.5";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:158:"* Make sure to not set Content-Transfer-Encoding on multipart messages [alec] * Added support for calendar invitations with attachments/html/images [jacalben]";}i:43;a:6:{s:4:"date";s:10:"2020-01-30";s:4:"time";s:8:"08:25:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.6";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:118:"* Fix different boundary in headers and body when using headers() after get() [alec] * Removed phail.php script [alec]";}i:44;a:6:{s:4:"date";s:10:"2020-03-01";s:4:"time";s:8:"08:50:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.7";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:84:"* Fix invalid Content-Type for messages with only html part and inline images [alec]";}i:45;a:6:{s:4:"date";s:10:"2020-06-13";s:4:"time";s:8:"08:50:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.8";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:85:"* Fix encoding issues with ISO-2022-JP-MS input labelled with ISO-2022-JP [shirosaki]";}i:46;a:6:{s:4:"date";s:10:"2020-06-27";s:4:"time";s:8:"10:30:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.9";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:63:"* Added a workaround for an opcache bug on OpenSuse 15.1 [alec]";}i:47;a:6:{s:4:"date";s:10:"2021-01-17";s:4:"time";s:8:"09:25:00";s:7:"version";a:2:{s:7:"release";s:7:"1.10.10";s:3:"api";s:6:"1.10.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:9:"BSD Style";}s:5:"notes";s:191:"* Compatibility fixes for PHP 5.2 and 5.3 [alec] * Corrected soft line breaks handling to be RFC compliant [ixs] * Corrected line breaks for lines ending in dots and length more than 74 [ixs]";}}}s:8:"filelist";a:53:{s:25:"tests/class-filename.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"edd138f6c5497ae2b5d63620a67a931e";s:4:"name";s:25:"tests/class-filename.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/class-filename.phpt";}s:36:"tests/content_transfer_encoding.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"7ec986391d0af058316f66e5a507e059";s:4:"name";s:36:"tests/content_transfer_encoding.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:81:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/content_transfer_encoding.phpt";}s:24:"tests/encoding_case.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"c1a43360d9b2cb5f9542503a4355c277";s:4:"name";s:24:"tests/encoding_case.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/encoding_case.phpt";}s:32:"tests/headers_with_mbstring.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"bf50a200190cad5e2d4aae4e120ea09f";s:4:"name";s:32:"tests/headers_with_mbstring.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/headers_with_mbstring.phpt";}s:35:"tests/headers_without_mbstring.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"9a2d207f873317125ff43c092f3f0d25";s:4:"name";s:35:"tests/headers_without_mbstring.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:80:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/headers_without_mbstring.phpt";}s:27:"tests/qp_encoding_test.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"25d4c5b9fdeaabc7810c26e6f89e95ca";s:4:"name";s:27:"tests/qp_encoding_test.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:72:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/qp_encoding_test.phpt";}s:41:"tests/sleep_wakeup_EOL-bug3488-part1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"958197f31b4a20c91dd42662595e7516";s:4:"name";s:41:"tests/sleep_wakeup_EOL-bug3488-part1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:86:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part1.phpt";}s:41:"tests/sleep_wakeup_EOL-bug3488-part2.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"46675529f1f021b51a1aa0ae6c971cd2";s:4:"name";s:41:"tests/sleep_wakeup_EOL-bug3488-part2.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:86:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part2.phpt";}s:26:"tests/test_Bug_3513_1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"f8c05910737e451c7a9d4737b8d9f095";s:4:"name";s:26:"tests/test_Bug_3513_1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_3513_1.phpt";}s:26:"tests/test_Bug_3513_2.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"edb467a375ddf09e777a9388e2e8cbb5";s:4:"name";s:26:"tests/test_Bug_3513_2.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_3513_2.phpt";}s:26:"tests/test_Bug_3513_3.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"70c2456445eaaa80779206e9e245d685";s:4:"name";s:26:"tests/test_Bug_3513_3.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_3513_3.phpt";}s:26:"tests/test_Bug_7561_1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"4cda500d0d7925e81a299f1d3db132a9";s:4:"name";s:26:"tests/test_Bug_7561_1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_7561_1.phpt";}s:26:"tests/test_Bug_8386_1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"42a214e7e3d3afa07f8996b235222611";s:4:"name";s:26:"tests/test_Bug_8386_1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_8386_1.phpt";}s:26:"tests/test_Bug_8541_1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ed78099563499f60386a128cb7b96925";s:4:"name";s:26:"tests/test_Bug_8541_1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_8541_1.phpt";}s:26:"tests/test_Bug_9722_1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"5250a0693599b945e8642a1a289d7275";s:4:"name";s:26:"tests/test_Bug_9722_1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_9722_1.phpt";}s:27:"tests/test_Bug_10596_1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b7f58f54e1485c23a60c83cd3cc5563e";s:4:"name";s:27:"tests/test_Bug_10596_1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:72:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_10596_1.phpt";}s:27:"tests/test_Bug_10816_1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ccb53d80e7f5c9f28b11abce5fe5d490";s:4:"name";s:27:"tests/test_Bug_10816_1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:72:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_10816_1.phpt";}s:27:"tests/test_Bug_10999_1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"f3d92a1fff099173b8600fb3646d0614";s:4:"name";s:27:"tests/test_Bug_10999_1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:72:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_10999_1.phpt";}s:25:"tests/test_Bug_11381.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"3f2757d5db43abd8f177f094f4d53625";s:4:"name";s:25:"tests/test_Bug_11381.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_11381.phpt";}s:25:"tests/test_Bug_11731.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"c64d675e73bc02fc94f5d03b3117cfa0";s:4:"name";s:25:"tests/test_Bug_11731.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_11731.phpt";}s:25:"tests/test_Bug_12165.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"8c9305ca05f5ed2d7cd7e31e4836f17a";s:4:"name";s:25:"tests/test_Bug_12165.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_12165.phpt";}s:27:"tests/test_Bug_12385_1.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"2aa2c3dfbe44500809e79da994272611";s:4:"name";s:27:"tests/test_Bug_12385_1.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:72:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_12385_1.phpt";}s:25:"tests/test_Bug_12411.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ef1d726233dbd3360c540fd6a959b0d0";s:4:"name";s:25:"tests/test_Bug_12411.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_12411.phpt";}s:25:"tests/test_Bug_12466.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"a862a57ff622fcbb2328be6c805e2d05";s:4:"name";s:25:"tests/test_Bug_12466.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_12466.phpt";}s:25:"tests/test_Bug_13032.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"4eddeeac08f351feb147ab6fda439526";s:4:"name";s:25:"tests/test_Bug_13032.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_13032.phpt";}s:25:"tests/test_Bug_13444.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"de15a0657a83694bc6991c4184ccf9bd";s:4:"name";s:25:"tests/test_Bug_13444.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_13444.phpt";}s:25:"tests/test_Bug_13962.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"80afe9fced03288884e9d302d1e65b2d";s:4:"name";s:25:"tests/test_Bug_13962.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_13962.phpt";}s:25:"tests/test_Bug_14529.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"89bf87e798f4a149a150d4c2a505f976";s:4:"name";s:25:"tests/test_Bug_14529.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_14529.phpt";}s:25:"tests/test_Bug_14779.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"5f9100adb1c609110ed495fafa819975";s:4:"name";s:25:"tests/test_Bug_14779.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_14779.phpt";}s:25:"tests/test_Bug_14780.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"45eb42fe4e325da64f1ae8f149e2a396";s:4:"name";s:25:"tests/test_Bug_14780.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_14780.phpt";}s:25:"tests/test_Bug_15320.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"609dad2083c54ba56ea691c488ca20e2";s:4:"name";s:25:"tests/test_Bug_15320.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_15320.phpt";}s:25:"tests/test_Bug_16539.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"f4ef08e416e775558e8075b531bbc814";s:4:"name";s:25:"tests/test_Bug_16539.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_16539.phpt";}s:25:"tests/test_Bug_17025.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ed1bd0fc9067b3fb8b95808bfa315916";s:4:"name";s:25:"tests/test_Bug_17025.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_17025.phpt";}s:25:"tests/test_Bug_17175.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"8a37de74fb39fed4566617a7ea38bb69";s:4:"name";s:25:"tests/test_Bug_17175.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_17175.phpt";}s:25:"tests/test_Bug_18083.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b9dee3c7c45d8c6c22f860e93c3769b9";s:4:"name";s:25:"tests/test_Bug_18083.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_18083.phpt";}s:25:"tests/test_Bug_18772.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"96ce23ad1a1d6417facfcdd2baa9c8eb";s:4:"name";s:25:"tests/test_Bug_18772.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_18772.phpt";}s:25:"tests/test_Bug_19497.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"dd98307b3224b173f7b54f7e403865a4";s:4:"name";s:25:"tests/test_Bug_19497.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_19497.phpt";}s:25:"tests/test_Bug_20226.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"e1194180cb6a218fab69db90f88d1cb2";s:4:"name";s:25:"tests/test_Bug_20226.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_20226.phpt";}s:25:"tests/test_Bug_20273.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"1b7919174edcd1cf5d5fd5a622fdac9b";s:4:"name";s:25:"tests/test_Bug_20273.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_20273.phpt";}s:25:"tests/test_Bug_20563.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"6513c4b0c9e962c900d020124752333e";s:4:"name";s:25:"tests/test_Bug_20563.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_20563.phpt";}s:25:"tests/test_Bug_20564.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"7c7a00818cb0f01fa6c52c920b9e76c6";s:4:"name";s:25:"tests/test_Bug_20564.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_20564.phpt";}s:25:"tests/test_Bug_21027.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b9e31a9c24b05dfb6166512e04e2f056";s:4:"name";s:25:"tests/test_Bug_21027.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_21027.phpt";}s:25:"tests/test_Bug_21098.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b634a5e99aa26a8b6df8fcfae07051b4";s:4:"name";s:25:"tests/test_Bug_21098.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_21098.phpt";}s:25:"tests/test_Bug_21205.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b21be5b099a69428bd37e60589cdd485";s:4:"name";s:25:"tests/test_Bug_21205.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_21205.phpt";}s:25:"tests/test_Bug_21206.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"bc152c12839964fba15da5673d25c4db";s:4:"name";s:25:"tests/test_Bug_21206.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_21206.phpt";}s:25:"tests/test_Bug_21255.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"ccf732525be42c955eea18e78490c3e1";s:4:"name";s:25:"tests/test_Bug_21255.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_21255.phpt";}s:24:"tests/test_Bug_GH16.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"579f1e11da6c8074dbf508dc1f1dedfa";s:4:"name";s:24:"tests/test_Bug_GH16.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_GH16.phpt";}s:24:"tests/test_Bug_GH19.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"df32d66d9fccf7a0956422811283272a";s:4:"name";s:24:"tests/test_Bug_GH19.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_GH19.phpt";}s:24:"tests/test_Bug_GH26.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"b7b5b5bacc6a599cfaece35ad202ad1a";s:4:"name";s:24:"tests/test_Bug_GH26.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_Bug_GH26.phpt";}s:29:"tests/test_linebreak_dot.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"e08958f1bb60561f072a3508b8fd3e2e";s:4:"name";s:29:"tests/test_linebreak_dot.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:74:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_linebreak_dot.phpt";}s:35:"tests/test_linebreak_larger_76.phpt";a:5:{s:14:"baseinstalldir";s:4:"Mail";s:6:"md5sum";s:32:"8398e9bfea0bc7c4ff0770ae3d6279fe";s:4:"name";s:35:"tests/test_linebreak_larger_76.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:80:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests/test_linebreak_larger_76.phpt";}s:13:"Mail/mime.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e5c9ac7f32e53afdeafd1a84343a89ae";s:4:"name";s:13:"Mail/mime.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php52/usr/share/pear/Mail/mime.php";}s:17:"Mail/mimePart.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"36128789ad1101d39d13b06ca2585576";s:4:"name";s:17:"Mail/mimePart.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php52/usr/share/pear/Mail/mimePart.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:5:{s:50:"/opt/alt/php52/usr/share/pear/test/Mail_Mime/tests";b:1;s:50:"/opt/alt/php52///usr/share/pear/testail_Mime/tests";b:1;s:44:"/opt/alt/php52///usr/share/pear/testail_Mime";b:1;s:34:"/opt/alt/php52/usr/share/pear/Mail";b:1;s:34:"/opt/alt/php52///usr/share/pearail";b:1;}s:3:"old";a:7:{s:7:"version";s:7:"1.10.11";s:12:"release_date";s:10:"2021-09-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:9:"BSD Style";s:13:"release_notes";s:246:"* Fix PHP 8.1: strlen(): Passing null to parameter #1 ($string) of type string is deprecated [alec] * Fix encoding recipient names with @ character and no space between name and address [alec] * Fix the license label in composer.json [jnkowa-gfk]";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.2.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.6.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:2:{i:0;a:5:{s:4:"name";s:19:"Cipriano Groenendal";s:5:"email";s:13:"cipri@php.net";s:6:"active";s:2:"no";s:6:"handle";s:5:"cipri";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:19:"Aleksander Machniak";s:5:"email";s:12:"alec@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:4:"alec";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506464;}PK�������!�QxE7��E7��#��.registry/structures_linkedlist.regnu�[��������a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.0";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:21:"Structures_LinkedList";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:41:"Implements singly and doubly-linked lists";s:11:"description";s:181:"A singly-linked list offers the ability to insert or delete nodes at any point within the list. A doubly-linked list also offers the ability to request previous nodes in the list.";s:4:"lead";a:4:{s:4:"name";s:9:"Dan Scott";s:4:"user";s:3:"dbs";s:5:"email";s:11:"dbs@php.net";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2010-08-15";s:4:"time";s:8:"10:13:00";s:7:"version";a:2:{s:7:"release";s:5:"0.2.2";s:3:"api";s:5:"0.2.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:38:"http://apache.org/licenses/LICENSE-2.0";}s:8:"_content";s:27:"Apache License, Version 2.0";}s:5:"notes";s:20:"* Fix package layout";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:4:"name";s:1:"/";}s:4:"file";a:22:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b7ac5a9d6d9a3eb2c3cbb1db76ad75a3";s:4:"name";s:32:"Structures/LinkedList/Double.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"310eefdff99016e4a3282dd02d5a7efa";s:4:"name";s:32:"Structures/LinkedList/Single.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"9b1565a45687bb631a452b152e0d3d15";s:4:"name";s:32:"examples/double_link_example.php";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"56d8c9a65cf967f09136a1b5b42fb787";s:4:"name";s:32:"examples/single_link_example.php";s:4:"role";s:3:"doc";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"54a63c64625c0b1785d890cc0ecb6957";s:4:"name";s:20:"tests/LinkTester.php";s:4:"role";s:4:"test";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"6138a89189609d8b0c35a69ce6995457";s:4:"name";s:26:"tests/SingleLinkTester.php";s:4:"role";s:4:"test";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"c7a6ad89f79222cf62148893e88a0b5a";s:4:"name";s:19:"tests/link_001.phpt";s:4:"role";s:4:"test";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"960408b3ea85cfe453f7d4b1814784ea";s:4:"name";s:19:"tests/link_002.phpt";s:4:"role";s:4:"test";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"392d4c38523f764091433fdf19cf4943";s:4:"name";s:19:"tests/link_003.phpt";s:4:"role";s:4:"test";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"88bfd20fe97800c4f69ec7577abd2ecd";s:4:"name";s:19:"tests/link_004.phpt";s:4:"role";s:4:"test";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"dac8403b1df9d64e16e45e87121a74fa";s:4:"name";s:19:"tests/link_005.phpt";s:4:"role";s:4:"test";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"bfc84666dbe64008101adadecf008677";s:4:"name";s:19:"tests/link_006.phpt";s:4:"role";s:4:"test";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"1a7eb8c8a63ec97fdb0154214c679cfa";s:4:"name";s:19:"tests/link_007.phpt";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"86f0c12acf2706a82d0d0dc625ab3608";s:4:"name";s:26:"tests/single_link_001.phpt";s:4:"role";s:4:"test";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"19c3e9b406dffe9c315e0264e0d257f8";s:4:"name";s:26:"tests/single_link_002.phpt";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"d4029576a49c41f18c35f72bdb37da7e";s:4:"name";s:26:"tests/single_link_003.phpt";s:4:"role";s:4:"test";}}i:16;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"574cb63523d7716f37fad368eefc695b";s:4:"name";s:26:"tests/single_link_004.phpt";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"4712a8421da2369e72ec789e0fe3993f";s:4:"name";s:26:"tests/single_link_005.phpt";s:4:"role";s:4:"test";}}i:18;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"a7f31515a9a3260aa1c17e003a4c352c";s:4:"name";s:26:"tests/single_link_006.phpt";s:4:"role";s:4:"test";}}i:19;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"6fe94be57c862475367ed91a7284a6b2";s:4:"name";s:26:"tests/single_link_007.phpt";s:4:"role";s:4:"test";}}i:20;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"6e8edc55d5a37acbe96ed9860b8680cc";s:4:"name";s:9:"CHANGELOG";s:4:"role";s:3:"doc";}}i:21;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"3b83ef96387f14655fc854ddc3c6bd57";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:3:"5.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:22:{s:32:"Structures/LinkedList/Double.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b7ac5a9d6d9a3eb2c3cbb1db76ad75a3";s:4:"name";s:32:"Structures/LinkedList/Double.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php52/usr/share/pear/Structures/LinkedList/Double.php";}s:32:"Structures/LinkedList/Single.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"310eefdff99016e4a3282dd02d5a7efa";s:4:"name";s:32:"Structures/LinkedList/Single.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php52/usr/share/pear/Structures/LinkedList/Single.php";}s:32:"examples/double_link_example.php";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"9b1565a45687bb631a452b152e0d3d15";s:4:"name";s:32:"examples/double_link_example.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:88:"/opt/alt/php52/usr/share/doc/pear/Structures_LinkedList/examples/double_link_example.php";}s:32:"examples/single_link_example.php";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"56d8c9a65cf967f09136a1b5b42fb787";s:4:"name";s:32:"examples/single_link_example.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:88:"/opt/alt/php52/usr/share/doc/pear/Structures_LinkedList/examples/single_link_example.php";}s:20:"tests/LinkTester.php";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"54a63c64625c0b1785d890cc0ecb6957";s:4:"name";s:20:"tests/LinkTester.php";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/LinkTester.php";}s:26:"tests/SingleLinkTester.php";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"6138a89189609d8b0c35a69ce6995457";s:4:"name";s:26:"tests/SingleLinkTester.php";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/SingleLinkTester.php";}s:19:"tests/link_001.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"c7a6ad89f79222cf62148893e88a0b5a";s:4:"name";s:19:"tests/link_001.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/link_001.phpt";}s:19:"tests/link_002.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"960408b3ea85cfe453f7d4b1814784ea";s:4:"name";s:19:"tests/link_002.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/link_002.phpt";}s:19:"tests/link_003.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"392d4c38523f764091433fdf19cf4943";s:4:"name";s:19:"tests/link_003.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/link_003.phpt";}s:19:"tests/link_004.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"88bfd20fe97800c4f69ec7577abd2ecd";s:4:"name";s:19:"tests/link_004.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/link_004.phpt";}s:19:"tests/link_005.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"dac8403b1df9d64e16e45e87121a74fa";s:4:"name";s:19:"tests/link_005.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/link_005.phpt";}s:19:"tests/link_006.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"bfc84666dbe64008101adadecf008677";s:4:"name";s:19:"tests/link_006.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/link_006.phpt";}s:19:"tests/link_007.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"1a7eb8c8a63ec97fdb0154214c679cfa";s:4:"name";s:19:"tests/link_007.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:76:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/link_007.phpt";}s:26:"tests/single_link_001.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"86f0c12acf2706a82d0d0dc625ab3608";s:4:"name";s:26:"tests/single_link_001.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/single_link_001.phpt";}s:26:"tests/single_link_002.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"19c3e9b406dffe9c315e0264e0d257f8";s:4:"name";s:26:"tests/single_link_002.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/single_link_002.phpt";}s:26:"tests/single_link_003.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"d4029576a49c41f18c35f72bdb37da7e";s:4:"name";s:26:"tests/single_link_003.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/single_link_003.phpt";}s:26:"tests/single_link_004.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"574cb63523d7716f37fad368eefc695b";s:4:"name";s:26:"tests/single_link_004.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/single_link_004.phpt";}s:26:"tests/single_link_005.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"4712a8421da2369e72ec789e0fe3993f";s:4:"name";s:26:"tests/single_link_005.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/single_link_005.phpt";}s:26:"tests/single_link_006.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"a7f31515a9a3260aa1c17e003a4c352c";s:4:"name";s:26:"tests/single_link_006.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/single_link_006.phpt";}s:26:"tests/single_link_007.phpt";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"6fe94be57c862475367ed91a7284a6b2";s:4:"name";s:26:"tests/single_link_007.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests/single_link_007.phpt";}s:9:"CHANGELOG";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"6e8edc55d5a37acbe96ed9860b8680cc";s:4:"name";s:9:"CHANGELOG";s:4:"role";s:3:"doc";s:12:"installed_as";s:65:"/opt/alt/php52/usr/share/doc/pear/Structures_LinkedList/CHANGELOG";}s:7:"LICENSE";a:5:{s:14:"baseinstalldir";s:21:"Structures/LinkedList";s:6:"md5sum";s:32:"3b83ef96387f14655fc854ddc3c6bd57";s:4:"name";s:7:"LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:63:"/opt/alt/php52/usr/share/doc/pear/Structures_LinkedList/LICENSE";}}s:12:"_lastversion";N;s:7:"dirtree";a:10:{s:51:"/opt/alt/php52/usr/share/pear/Structures/LinkedList";b:1;s:51:"/opt/alt/php52///usr/share/peartructures/LinkedList";b:1;s:40:"/opt/alt/php52///usr/share/peartructures";b:1;s:64:"/opt/alt/php52/usr/share/doc/pear/Structures_LinkedList/examples";b:1;s:64:"/opt/alt/php52//usr/share/doc/pearStructures_LinkedList/examples";b:1;s:55:"/opt/alt/php52//usr/share/doc/pearStructures_LinkedList";b:1;s:62:"/opt/alt/php52/usr/share/pear/test/Structures_LinkedList/tests";b:1;s:62:"/opt/alt/php52///usr/share/pear/testtructures_LinkedList/tests";b:1;s:56:"/opt/alt/php52///usr/share/pear/testtructures_LinkedList";b:1;s:55:"/opt/alt/php52/usr/share/doc/pear/Structures_LinkedList";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"0.2.2";s:12:"release_date";s:10:"2010-08-15";s:13:"release_state";s:4:"beta";s:15:"release_license";s:27:"Apache License, Version 2.0";s:13:"release_notes";s:20:"* Fix package layout";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:3:"5.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:9:"Dan Scott";s:5:"email";s:11:"dbs@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:3:"dbs";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506464;}PK�������!�Z1{��1{����.registry/xml_rpc.regnu�[��������a:23:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:7:"XML_RPC";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:42:"PHP implementation of the XML-RPC protocol";s:11:"description";s:123:"A PEAR-ified version of Useful Inc's XML-RPC for PHP. It has support for HTTP/HTTPS transport, proxies and authentication.";s:4:"lead";a:2:{i:0;a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:16:"Daniel Convissor";s:4:"user";s:7:"danielc";s:5:"email";s:15:"danielc@php.net";s:6:"active";s:2:"no";}}s:4:"date";s:10:"2011-08-27";s:4:"time";s:8:"01:36:28";s:7:"version";a:2:{s:7:"release";s:5:"1.5.5";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:92:"* Adjust is_a() usage due to change in PHP 5.3.7. * Fix error populating headers. Bug 18653.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:12:{i:0;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"41158fbcb2d49755fdaf877f92e85362";s:4:"name";s:24:"tests/actual-request.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e9a0aa974052ee47c41ad0274c728dc6";s:4:"name";s:16:"tests/allgot.inc";s:4:"role";s:4:"test";}}i:2;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"60cd6342dd96bf0be4d4d3cbb7813cf4";s:4:"name";s:28:"tests/empty-value-struct.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:3;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2bdf63e6eba97ea12ac4f5a3a92fdc3a";s:4:"name";s:21:"tests/empty-value.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:4;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"94ab1218006a7dc8fdd362dffc48777f";s:4:"name";s:16:"tests/encode.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:5;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"74921ba059a82e2ec9c7734c187a3f2c";s:4:"name";s:21:"tests/extra-lines.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:6;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3e200b7a09217395196987f1e948871a";s:4:"name";s:19:"tests/protoport.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:7;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f3af6b2112368d543f80907f1b040b77";s:4:"name";s:19:"tests/test_Dump.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:8;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6fb82404a22f0e751697c8ffe0557a6a";s:4:"name";s:15:"tests/types.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b361011f028738d20e8905cfa2fcefc5";s:4:"name";s:11:"XML/RPC.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2036a5c5c6e965b93533cd050442fa98";s:4:"name";s:16:"XML/RPC/Dump.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8a0123129ef7eb5615505b95d0f0b72f";s:4:"name";s:18:"XML/RPC/Server.php";s:4:"role";s:3:"php";}}}}}s:10:"compatible";a:4:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:7:"1.4.0a1";s:3:"max";s:5:"1.4.9";}s:12:"dependencies";a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.2.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:7:"1.4.0a1";}s:9:"extension";a:1:{s:4:"name";s:3:"xml";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:39:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.1";s:3:"api";s:5:"1.0.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2001-09-25";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:132:"This is a PEAR-ified version of Useful Inc's 1.0.1 release. Includes an urgent security fix identified by Dan Libby <dan@libby.com>.";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.2";s:3:"api";s:5:"1.0.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-04-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:48:"* E_ALL fixes * fix HTTP response header parsing";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.3";s:3:"api";s:5:"1.0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-05-19";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:51:"* fix bug when parsing responses with boolean types";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.4";s:3:"api";s:5:"1.0.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-10-02";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:68:"* added HTTP proxy authorization support (thanks to Arnaud Limbourg)";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.0";s:3:"api";s:5:"1.1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-03-15";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:517:"* Added support for sequential arrays to XML_RPC_encode() (mroch) * Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre) * Remove "require_once 'PEAR.php'", include only when needed to raise an error * Replace echo and error_log() with raiseError() (mroch) * Make all classes extend XML_RPC_Base, which will handle common functions (mroch) * be tolerant of junk after methodResponse (Luca Mariano, mroch) * Silent notice even in the error log (pierre) * fix include of shared xml extension on win32 (pierre)";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC1";s:3:"api";s:8:"1.2.0RC1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2004-12-30";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:1187:"* Make things work with SSL. Bug 2489. (nkukard lbsd net) * Allow array function callbacks (Matt Kane) * Some minor speed-ups (Matt Kane) * Add Dump.php to the package (Christian Weiske) * Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc) * Silence fsockopen() errors. Bug 1714. (danielc) * Encode empty arrays as an array. Bug 1493. (danielc) * Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc) * Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc) * Prepend "XML_RPC_" to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc) * Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc) * Allow raiseError() to be called statically. (danielc) * Stop double escaping of character entities. Bug 987. (danielc) NOTICE: the following have been removed: * XML_RPC_dh() * $GLOBALS['XML_RPC_entities'] * XML_RPC_entity_decode() * XML_RPC_lookup_entity() * Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)";}i:6;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC2";s:3:"api";s:8:"1.2.0RC2";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-11";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:162:"* Handle ssl:// in the $server string. (danielc) * Also default to port 445 for ssl:// requests as well. (danielc) * Enhance debugging in the server. (danielc)";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC3";s:3:"api";s:8:"1.2.0RC3";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-19";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:29:"* ssl uses port 443, not 445.";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC4";s:3:"api";s:8:"1.2.0RC4";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:388:"* When a connection attempt fails, have the method return 0. (danielc) * Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc) * Add tests for setting the client properties. (danielc) * Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc) * Bundle the tests with the package. (danielc)";}i:9;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC5";s:3:"api";s:8:"1.2.0RC5";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:91:"* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.";}i:10;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC6";s:3:"api";s:8:"1.2.0RC6";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-25";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:71:"* Don't put the protocol in the Host field of the POST data. (danielc)";}i:11;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC7";s:3:"api";s:8:"1.2.0RC7";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-02-22";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:346:"* Add the setSendEncoding() method and $send_encoding property to XML_RPC_Message. Request 3537. * Allow class methods to be mapped using either syntax: 'function' => 'hello::sayHello', or 'function' => array('hello', 'sayhello'), Bug 3363. * Use 8192 instead of 32768 for bytes in fread() in parseResponseFile(). Bug 3340.";}i:12;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.0";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-02-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:160:"* Provide the "stable" release. * Add package2.xml for compatibility with PEAR 1.4.0. * For changes since 1.1.0, see the changelogs for the various RC releases.";}i:13;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.1";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-03-01";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:65:"* Add isset() check before examining the dispatch map. Bug 3658.";}i:14;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.2";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-03-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:122:"* When using a proxy, add the protocol to the Request-URI, making it an "absoluteURI" as per the HTTP 1.0 spec. Bug 3679.";}i:15;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.3.0RC1";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-04-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:818:"* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963. * Add Fault Code 6: "The requested method didn't return an XML_RPC_Response object." Request 4032. * Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121. * As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set. * Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782. * Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.";}i:16;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.3.0RC2";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-05-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:383:"* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE. * Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231. * Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116. * Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.";}i:17;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.3.0RC3";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-05-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:724:"* When verifying requests against function signatures, if the number of parameters don't match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231. * XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2. * Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object. * If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0. * Improve cross-platform operation by using PEAR::loadExtension() instead of dl(). * Use <br /> instead of <br> in XML_RPC_Value::dump().";}i:18;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.0";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-06-13";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:64:"* Stable release. See earlier releases for changes since 1.2.2.";}i:19;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.1";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-06-29";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:42:"* Security fix. Update highly recommended!";}i:20;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.2";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-07-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:584:"* Eliminate path disclosure vulnerabilities by suppressing error messages when eval()'ing. * Eliminate path disclosure vulnerability by catching bogus parameters submitted to XML_RPC_Value::serializeval(). * In XML_RPC_Server::service(), only call createServerPayload() and createServerHeaders() if necessary. Fixes compatibility issue introduced in Release 1.3.0RC1 for users who set the $serviceNow parameter of XML_RPC_Server() to 0. Bug 4757. * Change "var $errstring" to "var $errstr". Bug 4582. Was put into CVS version 1.75 of RPC.php but didn't make it into RELEASE_1_3_1.";}i:21;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.3";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-07-15";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:220:"* Eliminate memory leak by resetting $XML_RPC_xh each time parseResponse() is called. Bug 4780. * Using socket_set_timeout() because stream_set_timeout() was introduced in 4.3.0, but we need to support 4.2.0. Bug 4805.";}i:22;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.0";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-08-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:171:"* MAJOR SECURITY FIX: eliminate use of eval(). * Using socket_get_status() because stream_get_meta_data() was introduced in 4.3.0, but we need to support 4.2.0. Bug 4805.";}i:23;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.1";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-09-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:158:"* Don't add debug info unless debug is on. Bug 5136. * Use is_a() instead of class_name() so people can use their own XML_RPC_Message objects. Request 5002.";}i:24;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.2";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-09-18";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:53:"* Allow empty <value>'s without <types>'s. Bug 5315.";}i:25;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.3";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-09-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:72:"* Make XML_RPC_encode() properly handle dateTime.iso8601. Request 5117.";}i:26;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.4";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-10-15";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:46:"* Properly deal with empty values in struct's.";}i:27;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.5";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-01-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:114:"* Have server send headers individualy as opposed to sending them all at once. Necessary due to changes PHP 4.4.2.";}i:28;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.6";s:3:"api";s:5:"1.4.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-04-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:209:"* Add XML_RPC_Message::$remove_extra_lines property. Defaults to true. If set to false, extra lines are left in place. Bug 7088. * Add XML_RPC_Message::$response_payload property. Makes logging responses easy.";}i:29;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.7";s:3:"api";s:5:"1.4.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-04-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:132:"* Add include_once for PEAR if need to load xml extension. Bug 7358. * Add dependency for xml extension in package file. Bug 7358.";}i:30;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.8";s:3:"api";s:5:"1.4.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-04-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:129:"* Characters other than alpha-numeric, punctuation, SP, TAB, LF and CR break the XML parser, encode value via Base 64. Bug 7376.";}i:31;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.5.0RC1";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2006-06-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:749:"* Provide complete multi-byte string support for systems with the mbstring extension enabled. Bug 7837. * If PHP's mbstring extension is enabled, use mb_convert_encoding() to ensure the client payload matches the intended encoding. This is a better resolution of Bug 7376. * Turn off the default of automatically base64 encoding strings that can generate fatal errors in PHP's SAX parser. The automatic base64 encoding can be turned on via the new XML_RPC_Client::setAutoBase64() method. The auto-encoding is a workaround for systems that don't have PHP's mbstring extension available. (The automatic base64 encoding was added in the prior release, 1.4.8, and caused problems for users who don't control the receiving end of the requests.) Bug 7837.";}i:32;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.5.0RC2";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2006-06-21";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:127:"* If PHP's mbstring extension is enabled, use mb_convert_encoding() to ensure the server payload matches the intended encoding.";}i:33;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.0";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-07-11";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:134:"No changes from 1.5.0RC2. The primary change from 1.4.8 is improved multi-byte support. See the change log for complete information.";}i:34;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.1";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-10-28";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:280:"* Turn passing payload through mb_convert_encoding() off by default. Use new XML_RPC_Message::setConvertPayloadEncoding() and XML_RPC_Server::setConvertPayloadEncoding() to turn it on. Bug 8632. * Have XML_RPC_Value::scalarval() return FALSE if value is not a scalar. Bug 8251.";}i:35;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.2";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-08-18";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:64:"* Change license in empty-value-struct.php from PHP 3.0 to 3.01.";}i:36;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.3";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-01-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:242:"* Make licenses consistent. Bug 12575. * Fix serializedata() for non-sequentially indexed arrays. Bug 16780. * Show request information in debug mode. Request 8240. * Creating the payload before opening a socket connection. Request 11981.";}i:37;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.4";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-07-03";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:209:"* Change ereg functions to preg due to deprecation (Request 17546 and then some.) * Fix bugs in XML_RPC_Dump error detection process. * Escape XML special characters in key names of struct elements. Bug 17368.";}i:38;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.5";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2011-08-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:92:"* Adjust is_a() usage due to change in PHP 5.3.7. * Fix error populating headers. Bug 18653.";}}}s:8:"filelist";a:12:{s:24:"tests/actual-request.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"41158fbcb2d49755fdaf877f92e85362";s:4:"name";s:24:"tests/actual-request.php";s:4:"role";s:4:"test";s:12:"installed_as";s:67:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests/actual-request.php";}s:16:"tests/allgot.inc";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e9a0aa974052ee47c41ad0274c728dc6";s:4:"name";s:16:"tests/allgot.inc";s:4:"role";s:4:"test";s:12:"installed_as";s:59:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests/allgot.inc";}s:28:"tests/empty-value-struct.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"60cd6342dd96bf0be4d4d3cbb7813cf4";s:4:"name";s:28:"tests/empty-value-struct.php";s:4:"role";s:4:"test";s:12:"installed_as";s:71:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests/empty-value-struct.php";}s:21:"tests/empty-value.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2bdf63e6eba97ea12ac4f5a3a92fdc3a";s:4:"name";s:21:"tests/empty-value.php";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests/empty-value.php";}s:16:"tests/encode.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"94ab1218006a7dc8fdd362dffc48777f";s:4:"name";s:16:"tests/encode.php";s:4:"role";s:4:"test";s:12:"installed_as";s:59:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests/encode.php";}s:21:"tests/extra-lines.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"74921ba059a82e2ec9c7734c187a3f2c";s:4:"name";s:21:"tests/extra-lines.php";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests/extra-lines.php";}s:19:"tests/protoport.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3e200b7a09217395196987f1e948871a";s:4:"name";s:19:"tests/protoport.php";s:4:"role";s:4:"test";s:12:"installed_as";s:62:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests/protoport.php";}s:19:"tests/test_Dump.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f3af6b2112368d543f80907f1b040b77";s:4:"name";s:19:"tests/test_Dump.php";s:4:"role";s:4:"test";s:12:"installed_as";s:62:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests/test_Dump.php";}s:15:"tests/types.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6fb82404a22f0e751697c8ffe0557a6a";s:4:"name";s:15:"tests/types.php";s:4:"role";s:4:"test";s:12:"installed_as";s:58:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests/types.php";}s:11:"XML/RPC.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b361011f028738d20e8905cfa2fcefc5";s:4:"name";s:11:"XML/RPC.php";s:4:"role";s:3:"php";s:12:"installed_as";s:41:"/opt/alt/php84/usr/share/pear/XML/RPC.php";}s:16:"XML/RPC/Dump.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2036a5c5c6e965b93533cd050442fa98";s:4:"name";s:16:"XML/RPC/Dump.php";s:4:"role";s:3:"php";s:12:"installed_as";s:46:"/opt/alt/php84/usr/share/pear/XML/RPC/Dump.php";}s:18:"XML/RPC/Server.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8a0123129ef7eb5615505b95d0f0b72f";s:4:"name";s:18:"XML/RPC/Server.php";s:4:"role";s:3:"php";s:12:"installed_as";s:48:"/opt/alt/php84/usr/share/pear/XML/RPC/Server.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:4:{s:48:"/opt/alt/php84/usr/share/pear/test/XML_RPC/tests";b:1;s:42:"/opt/alt/php84/usr/share/pear/test/XML_RPC";b:1;s:33:"/opt/alt/php84/usr/share/pear/XML";b:1;s:37:"/opt/alt/php84/usr/share/pear/XML/RPC";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.5.5";s:12:"release_date";s:10:"2011-08-27";s:13:"release_state";s:6:"stable";s:15:"release_license";s:11:"PHP License";s:13:"release_notes";s:92:"* Adjust is_a() usage due to change in PHP 5.3.7. * Fix error populating headers. Bug 18653.";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.2.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:7:"1.4.0a1";s:8:"optional";s:2:"no";}i:2;a:4:{s:4:"type";s:3:"ext";s:4:"name";s:3:"xml";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:2:{i:0;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:16:"Daniel Convissor";s:5:"email";s:15:"danielc@php.net";s:6:"active";s:2:"no";s:6:"handle";s:7:"danielc";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1747073454;}PK�������!�6 �� ����.registry/net_socket.regnu�[��������a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:10:"Net_Socket";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:24:"Network Socket Interface";s:11:"description";s:237:"Net_Socket is a class interface to TCP sockets. It provides blocking and non-blocking operation, with different reading and writing modes (byte-wise, block-wise, line-wise and special formats like network byte-order ip addresses).";s:4:"lead";a:3:{i:0;a:4:{s:4:"name";s:15:"Chuck Hagenbuch";s:4:"user";s:8:"chagenbu";s:5:"email";s:15:"chuck@horde.org";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}i:2;a:4:{s:4:"name";s:19:"Aleksander Machniak";s:4:"user";s:4:"alec";s:5:"email";s:12:"alec@php.net";s:6:"active";s:3:"yes";}}s:4:"date";s:10:"2013-05-24";s:4:"time";s:8:"18:08:42";s:7:"version";a:2:{s:7:"release";s:6:"1.0.14";s:3:"api";s:6:"1.0.10";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/2_02.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:72:"- Fix connecting when host is specified with protocol prefix e.g. ssl://";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"057d5c52b2dd9cfb2a458d532d95cfbb";s:4:"name";s:14:"Net/Socket.php";s:4:"role";s:3:"php";}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:7:"1.4.0b1";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:1:{s:14:"Net/Socket.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"057d5c52b2dd9cfb2a458d532d95cfbb";s:4:"name";s:14:"Net/Socket.php";s:4:"role";s:3:"php";s:12:"installed_as";s:44:"/opt/alt/php52/usr/share/pear/Net/Socket.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:2:{s:33:"/opt/alt/php52/usr/share/pear/Net";b:1;s:33:"/opt/alt/php52///usr/share/pearet";b:1;}s:3:"old";a:7:{s:7:"version";s:6:"1.0.14";s:12:"release_date";s:10:"2013-05-24";s:13:"release_state";s:6:"stable";s:15:"release_license";s:11:"PHP License";s:13:"release_notes";s:72:"- Fix connecting when host is specified with protocol prefix e.g. ssl://";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.3.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:7:"1.4.0b1";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:3:{i:0;a:5:{s:4:"name";s:15:"Chuck Hagenbuch";s:5:"email";s:15:"chuck@horde.org";s:6:"active";s:3:"yes";s:6:"handle";s:8:"chagenbu";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:19:"Aleksander Machniak";s:5:"email";s:12:"alec@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:4:"alec";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506464;}PK�������!�o%��%����.registry/auth_sasl.regnu�[��������a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:153:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:9:"Auth_SASL";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:47:"Abstraction of various SASL mechanism responses";s:11:"description";s:152:"Provides code to generate responses to common SASL mechanisms, including: - Digest-MD5 - Cram-MD5 - Plain - Anonymous - Login (Pseudo mechanism) - SCRAM";s:4:"lead";a:3:{i:0;a:4:{s:4:"name";s:12:"Anish Mistry";s:4:"user";s:7:"amistry";s:5:"email";s:26:"amistry@am-productions.biz";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:13:"Richard Heyes";s:4:"user";s:7:"richard";s:5:"email";s:15:"richard@php.net";s:6:"active";s:2:"no";}i:2;a:4:{s:4:"name";s:22:"Michael Bretterklieber";s:4:"user";s:8:"mbretter";s:5:"email";s:26:"michael@bretterklieber.com";s:6:"active";s:2:"no";}}s:4:"date";s:10:"2011-09-27";s:4:"time";s:8:"14:33:19";s:7:"version";a:2:{s:7:"release";s:5:"1.0.6";s:3:"api";s:5:"1.0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:102:"QA release * Bug #18856: Authentication warnings because of wrong Auth_SASL::factory argument [kguest]";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:9:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"60f7b5ba4d05fe0e518292963b14bddb";s:4:"name";s:23:"Auth/SASL/Anonymous.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2c817e4775b6f63f07ddb0c9cbd88b5";s:4:"name";s:20:"Auth/SASL/Common.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c6b3b3a4e0aec6a4e0728732ef6babc9";s:4:"name";s:21:"Auth/SASL/CramMD5.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"509e431141489a77a991401d64f15e9e";s:4:"name";s:23:"Auth/SASL/DigestMD5.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1d7478dd9dc5734ec9e16c158dcb6f76";s:4:"name";s:22:"Auth/SASL/External.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a0abcf277374b24262807150451b55e";s:4:"name";s:19:"Auth/SASL/Login.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bde1dcf2780d042c1de12e20a696e945";s:4:"name";s:19:"Auth/SASL/Plain.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e99f9f71abc36d64ca8e17ad6e5e7631";s:4:"name";s:19:"Auth/SASL/SCRAM.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d94238eb9907ccb911419a17e10880d";s:4:"name";s:13:"Auth/SASL.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"4.2.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.3";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:6:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.6";s:3:"api";s:5:"1.0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2011-09-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:102:"QA release * Bug #18856: Authentication warnings because of wrong Auth_SASL::factory argument [kguest]";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.5";s:3:"api";s:5:"1.0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2011-09-04";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:256:"QA release * Added support for any mechanism of the SCRAM family; with thanks to Jehan Pagès. [kguest] * crammd5 and digestmd5 mechanisms name deprecated in favour of IANA registered names 'cram-md5' and 'digest-md5'; with thanks to Jehan Pagès. [kguest]";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.4";s:3:"api";s:5:"1.0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-02-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:85:"QA release * Fix bug #16624: open_basedir restriction warning in DigestMD5.php [till]";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.3";s:3:"api";s:5:"1.0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-08-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:181:"QA release * Move SVN to proper directory structure [cweiske] * Fix Bug #8775: Error in package.xml * Fix Bug #14671: Security issue due to seeding random number generator [cweiske]";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.2";s:3:"api";s:5:"1.0.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-05-21";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:179:"* Fixed Bug #2143 Auth_SASL_DigestMD5::getResponse() generates invalid response * Fixed Bug #6611 Suppress PHP 5 Notice Errors * Fixed Bug #2154 realm isn't contained in challange";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.1";s:3:"api";s:5:"1.0.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-09-11";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/bsd-license.php";}s:8:"_content";s:3:"BSD";}s:5:"notes";s:59:"* Added authcid/authzid separation in PLAIN and DIGEST-MD5.";}}}s:8:"filelist";a:9:{s:23:"Auth/SASL/Anonymous.php";a:4:{s:6:"md5sum";s:32:"60f7b5ba4d05fe0e518292963b14bddb";s:4:"name";s:23:"Auth/SASL/Anonymous.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php52/usr/share/pear/Auth/SASL/Anonymous.php";}s:20:"Auth/SASL/Common.php";a:4:{s:6:"md5sum";s:32:"c2c817e4775b6f63f07ddb0c9cbd88b5";s:4:"name";s:20:"Auth/SASL/Common.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/opt/alt/php52/usr/share/pear/Auth/SASL/Common.php";}s:21:"Auth/SASL/CramMD5.php";a:4:{s:6:"md5sum";s:32:"c6b3b3a4e0aec6a4e0728732ef6babc9";s:4:"name";s:21:"Auth/SASL/CramMD5.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php52/usr/share/pear/Auth/SASL/CramMD5.php";}s:23:"Auth/SASL/DigestMD5.php";a:4:{s:6:"md5sum";s:32:"509e431141489a77a991401d64f15e9e";s:4:"name";s:23:"Auth/SASL/DigestMD5.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php52/usr/share/pear/Auth/SASL/DigestMD5.php";}s:22:"Auth/SASL/External.php";a:4:{s:6:"md5sum";s:32:"1d7478dd9dc5734ec9e16c158dcb6f76";s:4:"name";s:22:"Auth/SASL/External.php";s:4:"role";s:3:"php";s:12:"installed_as";s:52:"/opt/alt/php52/usr/share/pear/Auth/SASL/External.php";}s:19:"Auth/SASL/Login.php";a:4:{s:6:"md5sum";s:32:"3a0abcf277374b24262807150451b55e";s:4:"name";s:19:"Auth/SASL/Login.php";s:4:"role";s:3:"php";s:12:"installed_as";s:49:"/opt/alt/php52/usr/share/pear/Auth/SASL/Login.php";}s:19:"Auth/SASL/Plain.php";a:4:{s:6:"md5sum";s:32:"bde1dcf2780d042c1de12e20a696e945";s:4:"name";s:19:"Auth/SASL/Plain.php";s:4:"role";s:3:"php";s:12:"installed_as";s:49:"/opt/alt/php52/usr/share/pear/Auth/SASL/Plain.php";}s:19:"Auth/SASL/SCRAM.php";a:4:{s:6:"md5sum";s:32:"e99f9f71abc36d64ca8e17ad6e5e7631";s:4:"name";s:19:"Auth/SASL/SCRAM.php";s:4:"role";s:3:"php";s:12:"installed_as";s:49:"/opt/alt/php52/usr/share/pear/Auth/SASL/SCRAM.php";}s:13:"Auth/SASL.php";a:4:{s:6:"md5sum";s:32:"7d94238eb9907ccb911419a17e10880d";s:4:"name";s:13:"Auth/SASL.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/opt/alt/php52/usr/share/pear/Auth/SASL.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:4:{s:39:"/opt/alt/php52/usr/share/pear/Auth/SASL";b:1;s:39:"/opt/alt/php52///usr/share/pearuth/SASL";b:1;s:34:"/opt/alt/php52///usr/share/pearuth";b:1;s:34:"/opt/alt/php52/usr/share/pear/Auth";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.0.6";s:12:"release_date";s:10:"2011-09-27";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"BSD";s:13:"release_notes";s:102:"QA release * Bug #18856: Authentication warnings because of wrong Auth_SASL::factory argument [kguest]";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.2.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.3";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:3:{i:0;a:5:{s:4:"name";s:12:"Anish Mistry";s:5:"email";s:26:"amistry@am-productions.biz";s:6:"active";s:2:"no";s:6:"handle";s:7:"amistry";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:13:"Richard Heyes";s:5:"email";s:15:"richard@php.net";s:6:"active";s:2:"no";s:6:"handle";s:7:"richard";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:22:"Michael Bretterklieber";s:5:"email";s:26:"michael@bretterklieber.com";s:6:"active";s:2:"no";s:6:"handle";s:8:"mbretter";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506464;}PK�������!�GJW��W����XML/RPC/Server.phpnu�[��������<?php /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** * Server commands for our PHP implementation of the XML-RPC protocol * * This is a PEAR-ified version of Useful inc's XML-RPC for PHP. * It has support for HTTP transport, proxies and authentication. * * PHP versions 4 and 5 * * @category Web Services * @package XML_RPC * @author Edd Dumbill <edd@usefulinc.com> * @author Stig Bakken <stig@php.net> * @author Martin Jansen <mj@php.net> * @author Daniel Convissor <danielc@php.net> * @copyright 1999-2001 Edd Dumbill, 2001-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version SVN: $Id: Server.php 315558 2011-08-26 14:42:51Z danielc $ * @link http://pear.php.net/package/XML_RPC */ /** * Pull in the XML_RPC class */ require_once 'XML/RPC.php'; /** * signature for system.listMethods: return = array, * parameters = a string or nothing * @global array $GLOBALS['XML_RPC_Server_listMethods_sig'] */ $GLOBALS['XML_RPC_Server_listMethods_sig'] = array( array($GLOBALS['XML_RPC_Array'], $GLOBALS['XML_RPC_String'] ), array($GLOBALS['XML_RPC_Array']) ); /** * docstring for system.listMethods * @global string $GLOBALS['XML_RPC_Server_listMethods_doc'] */ $GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the' . ' methods that the XML-RPC server knows how to dispatch'; /** * signature for system.methodSignature: return = array, * parameters = string * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig'] */ $GLOBALS['XML_RPC_Server_methodSignature_sig'] = array( array($GLOBALS['XML_RPC_Array'], $GLOBALS['XML_RPC_String'] ) ); /** * docstring for system.methodSignature * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc'] */ $GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known' . ' signatures (an array of arrays) for the method name passed. If' . ' no signatures are known, returns a none-array (test for type !=' . ' array to detect missing signature)'; /** * signature for system.methodHelp: return = string, * parameters = string * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig'] */ $GLOBALS['XML_RPC_Server_methodHelp_sig'] = array( array($GLOBALS['XML_RPC_String'], $GLOBALS['XML_RPC_String'] ) ); /** * docstring for methodHelp * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc'] */ $GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined' . ' for the method passed, otherwise returns an empty string'; /** * dispatch map for the automatically declared XML-RPC methods. * @global array $GLOBALS['XML_RPC_Server_dmap'] */ $GLOBALS['XML_RPC_Server_dmap'] = array( 'system.listMethods' => array( 'function' => 'XML_RPC_Server_listMethods', 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'], 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc'] ), 'system.methodHelp' => array( 'function' => 'XML_RPC_Server_methodHelp', 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'], 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc'] ), 'system.methodSignature' => array( 'function' => 'XML_RPC_Server_methodSignature', 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'], 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc'] ) ); /** * @global string $GLOBALS['XML_RPC_Server_debuginfo'] */ $GLOBALS['XML_RPC_Server_debuginfo'] = ''; /** * Lists all the methods that the XML-RPC server knows how to dispatch * * @return object a new XML_RPC_Response object */ function XML_RPC_Server_listMethods($server, $m) { global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; $v = new XML_RPC_Value(); $outAr = array(); foreach ($server->dmap as $key => $val) { $outAr[] = new XML_RPC_Value($key, 'string'); } foreach ($XML_RPC_Server_dmap as $key => $val) { $outAr[] = new XML_RPC_Value($key, 'string'); } $v->addArray($outAr); return new XML_RPC_Response($v); } /** * Returns an array of known signatures (an array of arrays) * for the given method * * If no signatures are known, returns a none-array * (test for type != array to detect missing signature) * * @return object a new XML_RPC_Response object */ function XML_RPC_Server_methodSignature($server, $m) { global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; $methName = $m->getParam(0); $methName = $methName->scalarval(); if (strpos($methName, 'system.') === 0) { $dmap = $XML_RPC_Server_dmap; $sysCall = 1; } else { $dmap = $server->dmap; $sysCall = 0; } // print "<!-- ${methName} -->\n"; if (isset($dmap[$methName])) { if ($dmap[$methName]['signature']) { $sigs = array(); $thesigs = $dmap[$methName]['signature']; for ($i = 0; $i < sizeof($thesigs); $i++) { $cursig = array(); $inSig = $thesigs[$i]; for ($j = 0; $j < sizeof($inSig); $j++) { $cursig[] = new XML_RPC_Value($inSig[$j], 'string'); } $sigs[] = new XML_RPC_Value($cursig, 'array'); } $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array')); } else { $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string')); } } else { $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], $XML_RPC_str['introspect_unknown']); } return $r; } /** * Returns help text if defined for the method passed, otherwise returns * an empty string * * @return object a new XML_RPC_Response object */ function XML_RPC_Server_methodHelp($server, $m) { global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; $methName = $m->getParam(0); $methName = $methName->scalarval(); if (strpos($methName, 'system.') === 0) { $dmap = $XML_RPC_Server_dmap; $sysCall = 1; } else { $dmap = $server->dmap; $sysCall = 0; } if (isset($dmap[$methName])) { if ($dmap[$methName]['docstring']) { $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']), 'string'); } else { $r = new XML_RPC_Response(new XML_RPC_Value('', 'string')); } } else { $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], $XML_RPC_str['introspect_unknown']); } return $r; } /** * @return void */ function XML_RPC_Server_debugmsg($m) { global $XML_RPC_Server_debuginfo; $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n"; } /** * A server for receiving and replying to XML RPC requests * * <code> * $server = new XML_RPC_Server( * array( * 'isan8' => * array( * 'function' => 'is_8', * 'signature' => * array( * array('boolean', 'int'), * array('boolean', 'int', 'boolean'), * array('boolean', 'string'), * array('boolean', 'string', 'boolean'), * ), * 'docstring' => 'Is the value an 8?' * ), * ), * 1, * 0 * ); * </code> * * @category Web Services * @package XML_RPC * @author Edd Dumbill <edd@usefulinc.com> * @author Stig Bakken <stig@php.net> * @author Martin Jansen <mj@php.net> * @author Daniel Convissor <danielc@php.net> * @copyright 1999-2001 Edd Dumbill, 2001-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_RPC */ class XML_RPC_Server { /** * Should the payload's content be passed through mb_convert_encoding()? * * @see XML_RPC_Server::setConvertPayloadEncoding() * @since Property available since Release 1.5.1 * @var boolean */ var $convert_payload_encoding = false; /** * The dispatch map, listing the methods this server provides. * @var array */ var $dmap = array(); /** * The present response's encoding * @var string * @see XML_RPC_Message::getEncoding() */ var $encoding = ''; /** * Debug mode (0 = off, 1 = on) * @var integer */ var $debug = 0; /** * The response's HTTP headers * @var string */ var $server_headers = ''; /** * The response's XML payload * @var string */ var $server_payload = ''; /** * Constructor for the XML_RPC_Server class * * @param array $dispMap the dispatch map. An associative array * explaining each function. The keys of the main * array are the procedure names used by the * clients. The value is another associative array * that contains up to three elements: * + The 'function' element's value is the name * of the function or method that gets called. * To define a class' method: 'class::method'. * + The 'signature' element (optional) is an * array describing the return values and * parameters * + The 'docstring' element (optional) is a * string describing what the method does * @param int $serviceNow should the HTTP response be sent now? * (1 = yes, 0 = no) * @param int $debug should debug output be displayed? * (1 = yes, 0 = no) * * @return void */ function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0) { global $HTTP_RAW_POST_DATA; if ($debug) { $this->debug = 1; } else { $this->debug = 0; } $this->dmap = $dispMap; if ($serviceNow) { $this->service(); } else { $this->createServerPayload(); $this->createServerHeaders(); } } /** * @return string the debug information if debug debug mode is on */ function serializeDebug() { global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA; if ($this->debug) { XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n" . $HTTP_RAW_POST_DATA . "\n" . '^^^ END POST DATA ^^^'); } if ($XML_RPC_Server_debuginfo != '') { return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n" . str_replace('--', '- - ', $XML_RPC_Server_debuginfo) . "-->\n"; } else { return ''; } } /** * Sets whether the payload's content gets passed through * mb_convert_encoding() * * Returns PEAR_ERROR object if mb_convert_encoding() isn't available. * * @param int $in where 1 = on, 0 = off * * @return void * * @see XML_RPC_Message::getEncoding() * @since Method available since Release 1.5.1 */ function setConvertPayloadEncoding($in) { if ($in && !function_exists('mb_convert_encoding')) { return $this->raiseError('mb_convert_encoding() is not available', XML_RPC_ERROR_PROGRAMMING); } $this->convert_payload_encoding = $in; } /** * Sends the response * * The encoding and content-type are determined by * XML_RPC_Message::getEncoding() * * @return void * * @uses XML_RPC_Server::createServerPayload(), * XML_RPC_Server::createServerHeaders() */ function service() { if (!$this->server_payload) { $this->createServerPayload(); } if (!$this->server_headers) { $this->createServerHeaders(); } /* * $server_headers needs to remain a string for compatibility with * old scripts using this package, but PHP 4.4.2 no longer allows * line breaks in header() calls. So, we split each header into * an individual call. The initial replace handles the off chance * that someone composed a single header with multiple lines, which * the RFCs allow. */ $this->server_headers = preg_replace("@[\r\n]+[ \t]+@", ' ', trim($this->server_headers)); $headers = preg_split("@[\r\n]+@", $this->server_headers); foreach ($headers as $header) { header($header); } print $this->server_payload; } /** * Generates the payload and puts it in the $server_payload property * * If XML_RPC_Server::setConvertPayloadEncoding() was set to true, * the payload gets passed through mb_convert_encoding() * to ensure the payload matches the encoding set in the * XML declaration. The encoding type can be manually set via * XML_RPC_Message::setSendEncoding(). * * @return void * * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding, * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug() * @see XML_RPC_Server::setConvertPayloadEncoding() */ function createServerPayload() { $r = $this->parseRequest(); $this->server_payload = '<?xml version="1.0" encoding="' . $this->encoding . '"?>' . "\n" . $this->serializeDebug() . $r->serialize(); if ($this->convert_payload_encoding) { $this->server_payload = mb_convert_encoding($this->server_payload, $this->encoding); } } /** * Determines the HTTP headers and puts them in the $server_headers * property * * @return boolean TRUE if okay, FALSE if $server_payload isn't set. * * @uses XML_RPC_Server::createServerPayload(), * XML_RPC_Server::$server_headers */ function createServerHeaders() { if (!$this->server_payload) { return false; } $this->server_headers = 'Content-Length: ' . strlen($this->server_payload) . "\r\n" . 'Content-Type: text/xml;' . ' charset=' . $this->encoding; return true; } /** * @return array */ function verifySignature($in, $sig) { for ($i = 0; $i < sizeof($sig); $i++) { // check each possible signature in turn $cursig = $sig[$i]; if (sizeof($cursig) == $in->getNumParams() + 1) { $itsOK = 1; for ($n = 0; $n < $in->getNumParams(); $n++) { $p = $in->getParam($n); // print "<!-- $p -->\n"; if ($p->kindOf() == 'scalar') { $pt = $p->scalartyp(); } else { $pt = $p->kindOf(); } // $n+1 as first type of sig is return type if ($pt != $cursig[$n+1]) { $itsOK = 0; $pno = $n+1; $wanted = $cursig[$n+1]; $got = $pt; break; } } if ($itsOK) { return array(1); } } } if (isset($wanted)) { return array(0, "Wanted ${wanted}, got ${got} at param ${pno}"); } else { $allowed = array(); foreach ($sig as $val) { end($val); $allowed[] = key($val); } $allowed = array_unique($allowed); $last = count($allowed) - 1; if ($last > 0) { $allowed[$last] = 'or ' . $allowed[$last]; } return array(0, 'Signature permits ' . implode(', ', $allowed) . ' parameters but the request had ' . $in->getNumParams()); } } /** * @return object a new XML_RPC_Response object * * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding */ function parseRequest($data = '') { global $XML_RPC_xh, $HTTP_RAW_POST_DATA, $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml, $XML_RPC_defencoding, $XML_RPC_Server_dmap; if ($data == '') { $data = $HTTP_RAW_POST_DATA; } $this->encoding = XML_RPC_Message::getEncoding($data); $parser_resource = xml_parser_create($this->encoding); $parser = (int) $parser_resource; $XML_RPC_xh[$parser] = array(); $XML_RPC_xh[$parser]['cm'] = 0; $XML_RPC_xh[$parser]['isf'] = 0; $XML_RPC_xh[$parser]['params'] = array(); $XML_RPC_xh[$parser]['method'] = ''; $XML_RPC_xh[$parser]['stack'] = array(); $XML_RPC_xh[$parser]['valuestack'] = array(); $plist = ''; // decompose incoming XML into request structure xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee'); xml_set_character_data_handler($parser_resource, 'XML_RPC_cd'); if (!xml_parse($parser_resource, $data, 1)) { // return XML error as a faultCode $r = new XML_RPC_Response(0, $XML_RPC_errxml+xml_get_error_code($parser_resource), sprintf('XML error: %s at line %d', xml_error_string(xml_get_error_code($parser_resource)), xml_get_current_line_number($parser_resource))); xml_parser_free($parser_resource); } elseif ($XML_RPC_xh[$parser]['isf']>1) { $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_request'], $XML_RPC_str['invalid_request'] . ': ' . $XML_RPC_xh[$parser]['isf_reason']); xml_parser_free($parser_resource); } else { xml_parser_free($parser_resource); $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']); // now add parameters in for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) { // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n"; $plist .= "$i - " . var_export($XML_RPC_xh[$parser]['params'][$i], true) . " \n"; $m->addParam($XML_RPC_xh[$parser]['params'][$i]); } if ($this->debug) { XML_RPC_Server_debugmsg($plist); } // now to deal with the method $methName = $XML_RPC_xh[$parser]['method']; if (strpos($methName, 'system.') === 0) { $dmap = $XML_RPC_Server_dmap; $sysCall = 1; } else { $dmap = $this->dmap; $sysCall = 0; } if (isset($dmap[$methName]['function']) && is_string($dmap[$methName]['function']) && strpos($dmap[$methName]['function'], '::') !== false) { $dmap[$methName]['function'] = explode('::', $dmap[$methName]['function']); } if (isset($dmap[$methName]['function']) && is_callable($dmap[$methName]['function'])) { // dispatch if exists if (isset($dmap[$methName]['signature'])) { $sr = $this->verifySignature($m, $dmap[$methName]['signature'] ); } if (!isset($dmap[$methName]['signature']) || $sr[0]) { // if no signature or correct signature if ($sysCall) { $r = call_user_func($dmap[$methName]['function'], $this, $m); } else { $r = call_user_func($dmap[$methName]['function'], $m); } if (!is_object($r) || !is_a($r, 'XML_RPC_Response')) { $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'], $XML_RPC_str['not_response_object']); } } else { $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'], $XML_RPC_str['incorrect_params'] . ': ' . $sr[1]); } } else { // else prepare error response $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'], $XML_RPC_str['unknown_method']); } } return $r; } /** * Echos back the input packet as a string value * * @return void * * Useful for debugging. */ function echoInput() { global $HTTP_RAW_POST_DATA; $r = new XML_RPC_Response(0); $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string'); print $r->serialize(); } } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * c-hanging-comment-ender-p: nil * End: */ ?> PK�������!�ioK������XML/RPC/Dump.phpnu�[��������<?php /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** * Function and class to dump XML_RPC_Value objects in a nice way * * Should be helpful as a normal var_dump(..) displays all internals which * doesn't really give you an overview due to too much information. * * @category Web Services * @package XML_RPC * @author Christian Weiske <cweiske@php.net> * @license http://www.php.net/license/3_01.txt PHP License * @version SVN: $Id: Dump.php 300962 2010-07-03 02:24:24Z danielc $ * @link http://pear.php.net/package/XML_RPC */ /** * Pull in the XML_RPC class */ require_once 'XML/RPC.php'; /** * Generates the dump of the XML_RPC_Value and echoes it * * @param object $value the XML_RPC_Value object to dump * * @return void */ function XML_RPC_Dump($value) { $dumper = new XML_RPC_Dump(); echo $dumper->generateDump($value); } /** * Class which generates a dump of a XML_RPC_Value object * * @category Web Services * @package XML_RPC * @author Christian Weiske <cweiske@php.net> * @license http://www.php.net/license/3_01.txt PHP License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_RPC */ class XML_RPC_Dump { /** * The indentation array cache * @var array */ var $arIndent = array(); /** * The spaces used for indenting the XML * @var string */ var $strBaseIndent = ' '; /** * Returns the dump in XML format without printing it out * * @param object $value the XML_RPC_Value object to dump * @param int $nLevel the level of indentation * * @return string the dump */ function generateDump($value, $nLevel = 0) { if (!is_object($value) || strtolower(get_class($value)) != 'xml_rpc_value') { require_once 'PEAR.php'; PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n", 0, PEAR_ERROR_PRINT); if (is_object($value)) { $strType = get_class($value); } else { $strType = gettype($value); } return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: ' . $strType . "\r\n"; } switch ($value->kindOf()) { case 'struct': $ret = $this->genStruct($value, $nLevel); break; case 'array': $ret = $this->genArray($value, $nLevel); break; case 'scalar': $ret = $this->genScalar($value->scalarval(), $nLevel); break; default: require_once 'PEAR.php'; PEAR::raiseError('Illegal type "' . $value->kindOf() . '" in XML_RPC_Value' . "\r\n", 0, PEAR_ERROR_PRINT); } return $ret; } /** * Returns the scalar value dump * * @param object $value the scalar XML_RPC_Value object to dump * @param int $nLevel the level of indentation * * @return string Dumped version of the scalar value */ function genScalar($value, $nLevel) { if (gettype($value) == 'object') { $strClass = ' ' . get_class($value); } else { $strClass = ''; } return $this->getIndent($nLevel) . gettype($value) . $strClass . ' ' . $value . "\r\n"; } /** * Returns the dump of a struct * * @param object $value the struct XML_RPC_Value object to dump * @param int $nLevel the level of indentation * * @return string Dumped version of the scalar value */ function genStruct($value, $nLevel) { $value->structreset(); $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n"; while (list($key, $keyval) = $value->structeach()) { $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n"; $strOutput .= $this->generateDump($keyval, $nLevel + 2); } return $strOutput; } /** * Returns the dump of an array * * @param object $value the array XML_RPC_Value object to dump * @param int $nLevel the level of indentation * * @return string Dumped version of the scalar value */ function genArray($value, $nLevel) { $nSize = $value->arraysize(); $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n"; for($nA = 0; $nA < $nSize; $nA++) { $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n"; $strOutput .= $this->generateDump($value->arraymem($nA), $nLevel + 2); } return $strOutput; } /** * Returns the indent for a specific level and caches it for faster use * * @param int $nLevel the level * * @return string the indented string */ function getIndent($nLevel) { if (!isset($this->arIndent[$nLevel])) { $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel); } return $this->arIndent[$nLevel]; } } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * c-hanging-comment-ender-p: nil * End: */ ?> PK�������!�/=���� ��XML/RPC.phpnu�[��������<?php /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** * PHP implementation of the XML-RPC protocol * * This is a PEAR-ified version of Useful inc's XML-RPC for PHP. * It has support for HTTP transport, proxies and authentication. * * PHP versions 4 and 5 * * @category Web Services * @package XML_RPC * @author Edd Dumbill <edd@usefulinc.com> * @author Stig Bakken <stig@php.net> * @author Martin Jansen <mj@php.net> * @author Daniel Convissor <danielc@php.net> * @copyright 1999-2001 Edd Dumbill, 2001-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version SVN: $Id: RPC.php 315594 2011-08-27 01:03:57Z danielc $ * @link http://pear.php.net/package/XML_RPC */ if (!function_exists('xml_parser_create')) { include_once 'PEAR.php'; PEAR::loadExtension('xml'); } /**#@+ * Error constants */ /** * Parameter values don't match parameter types */ define('XML_RPC_ERROR_INVALID_TYPE', 101); /** * Parameter declared to be numeric but the values are not */ define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102); /** * Communication error */ define('XML_RPC_ERROR_CONNECTION_FAILED', 103); /** * The array or struct has already been started */ define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104); /** * Incorrect parameters submitted */ define('XML_RPC_ERROR_INCORRECT_PARAMS', 105); /** * Programming error by developer */ define('XML_RPC_ERROR_PROGRAMMING', 106); /**#@-*/ /** * Data types * @global string $GLOBALS['XML_RPC_I4'] */ $GLOBALS['XML_RPC_I4'] = 'i4'; /** * Data types * @global string $GLOBALS['XML_RPC_Int'] */ $GLOBALS['XML_RPC_Int'] = 'int'; /** * Data types * @global string $GLOBALS['XML_RPC_Boolean'] */ $GLOBALS['XML_RPC_Boolean'] = 'boolean'; /** * Data types * @global string $GLOBALS['XML_RPC_Double'] */ $GLOBALS['XML_RPC_Double'] = 'double'; /** * Data types * @global string $GLOBALS['XML_RPC_String'] */ $GLOBALS['XML_RPC_String'] = 'string'; /** * Data types * @global string $GLOBALS['XML_RPC_DateTime'] */ $GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601'; /** * Data types * @global string $GLOBALS['XML_RPC_Base64'] */ $GLOBALS['XML_RPC_Base64'] = 'base64'; /** * Data types * @global string $GLOBALS['XML_RPC_Array'] */ $GLOBALS['XML_RPC_Array'] = 'array'; /** * Data types * @global string $GLOBALS['XML_RPC_Struct'] */ $GLOBALS['XML_RPC_Struct'] = 'struct'; /** * Data type meta-types * @global array $GLOBALS['XML_RPC_Types'] */ $GLOBALS['XML_RPC_Types'] = array( $GLOBALS['XML_RPC_I4'] => 1, $GLOBALS['XML_RPC_Int'] => 1, $GLOBALS['XML_RPC_Boolean'] => 1, $GLOBALS['XML_RPC_String'] => 1, $GLOBALS['XML_RPC_Double'] => 1, $GLOBALS['XML_RPC_DateTime'] => 1, $GLOBALS['XML_RPC_Base64'] => 1, $GLOBALS['XML_RPC_Array'] => 2, $GLOBALS['XML_RPC_Struct'] => 3, ); /** * Error message numbers * @global array $GLOBALS['XML_RPC_err'] */ $GLOBALS['XML_RPC_err'] = array( 'unknown_method' => 1, 'invalid_return' => 2, 'incorrect_params' => 3, 'introspect_unknown' => 4, 'http_error' => 5, 'not_response_object' => 6, 'invalid_request' => 7, ); /** * Error message strings * @global array $GLOBALS['XML_RPC_str'] */ $GLOBALS['XML_RPC_str'] = array( 'unknown_method' => 'Unknown method', 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload', 'incorrect_params' => 'Incorrect parameters passed to method', 'introspect_unknown' => 'Can\'t introspect: method unknown', 'http_error' => 'Didn\'t receive 200 OK from remote server.', 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.', 'invalid_request' => 'Invalid request payload', ); /** * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII) * @global string $GLOBALS['XML_RPC_defencoding'] */ $GLOBALS['XML_RPC_defencoding'] = 'UTF-8'; /** * User error codes start at 800 * @global int $GLOBALS['XML_RPC_erruser'] */ $GLOBALS['XML_RPC_erruser'] = 800; /** * XML parse error codes start at 100 * @global int $GLOBALS['XML_RPC_errxml'] */ $GLOBALS['XML_RPC_errxml'] = 100; /** * Compose backslashes for escaping regexp * @global string $GLOBALS['XML_RPC_backslash'] */ $GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92); /** * Should we automatically base64 encode strings that contain characters * which can cause PHP's SAX-based XML parser to break? * @global boolean $GLOBALS['XML_RPC_auto_base64'] */ $GLOBALS['XML_RPC_auto_base64'] = false; /** * Valid parents of XML elements * @global array $GLOBALS['XML_RPC_valid_parents'] */ $GLOBALS['XML_RPC_valid_parents'] = array( 'BOOLEAN' => array('VALUE'), 'I4' => array('VALUE'), 'INT' => array('VALUE'), 'STRING' => array('VALUE'), 'DOUBLE' => array('VALUE'), 'DATETIME.ISO8601' => array('VALUE'), 'BASE64' => array('VALUE'), 'ARRAY' => array('VALUE'), 'STRUCT' => array('VALUE'), 'PARAM' => array('PARAMS'), 'METHODNAME' => array('METHODCALL'), 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), 'MEMBER' => array('STRUCT'), 'NAME' => array('MEMBER'), 'DATA' => array('ARRAY'), 'FAULT' => array('METHODRESPONSE'), 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'), ); /** * Stores state during parsing * * quick explanation of components: * + ac = accumulates values * + qt = decides if quotes are needed for evaluation * + cm = denotes struct or array (comma needed) * + isf = indicates a fault * + lv = indicates "looking for a value": implements the logic * to allow values with no types to be strings * + params = stores parameters in method calls * + method = stores method name * * @global array $GLOBALS['XML_RPC_xh'] */ $GLOBALS['XML_RPC_xh'] = array(); /** * Start element handler for the XML parser * * @return void */ function XML_RPC_se($parser_resource, $name, $attrs) { global $XML_RPC_xh, $XML_RPC_valid_parents; $parser = (int) $parser_resource; // if invalid xmlrpc already detected, skip all processing if ($XML_RPC_xh[$parser]['isf'] >= 2) { return; } // check for correct element nesting // top level element can only be of 2 types if (count($XML_RPC_xh[$parser]['stack']) == 0) { if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') { $XML_RPC_xh[$parser]['isf'] = 2; $XML_RPC_xh[$parser]['isf_reason'] = 'missing top level xmlrpc element'; return; } } else { // not top level element: see if parent is OK if (!in_array($XML_RPC_xh[$parser]['stack'][0], $XML_RPC_valid_parents[$name])) { $name = preg_replace('@[^a-zA-Z0-9._-]@', '', $name); $XML_RPC_xh[$parser]['isf'] = 2; $XML_RPC_xh[$parser]['isf_reason'] = "xmlrpc element $name cannot be child of {$XML_RPC_xh[$parser]['stack'][0]}"; return; } } switch ($name) { case 'STRUCT': $XML_RPC_xh[$parser]['cm']++; // turn quoting off $XML_RPC_xh[$parser]['qt'] = 0; $cur_val = array(); $cur_val['value'] = array(); $cur_val['members'] = 1; array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); break; case 'ARRAY': $XML_RPC_xh[$parser]['cm']++; // turn quoting off $XML_RPC_xh[$parser]['qt'] = 0; $cur_val = array(); $cur_val['value'] = array(); $cur_val['members'] = 0; array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); break; case 'NAME': $XML_RPC_xh[$parser]['ac'] = ''; break; case 'FAULT': $XML_RPC_xh[$parser]['isf'] = 1; break; case 'PARAM': $XML_RPC_xh[$parser]['valuestack'] = array(); break; case 'VALUE': $XML_RPC_xh[$parser]['lv'] = 1; $XML_RPC_xh[$parser]['vt'] = $GLOBALS['XML_RPC_String']; $XML_RPC_xh[$parser]['ac'] = ''; $XML_RPC_xh[$parser]['qt'] = 0; // look for a value: if this is still 1 by the // time we reach the first data segment then the type is string // by implication and we need to add in a quote break; case 'I4': case 'INT': case 'STRING': case 'BOOLEAN': case 'DOUBLE': case 'DATETIME.ISO8601': case 'BASE64': $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator if ($name == 'DATETIME.ISO8601' || $name == 'STRING') { $XML_RPC_xh[$parser]['qt'] = 1; if ($name == 'DATETIME.ISO8601') { $XML_RPC_xh[$parser]['vt'] = $GLOBALS['XML_RPC_DateTime']; } } elseif ($name == 'BASE64') { $XML_RPC_xh[$parser]['qt'] = 2; } else { // No quoting is required here -- but // at the end of the element we must check // for data format errors. $XML_RPC_xh[$parser]['qt'] = 0; } break; case 'MEMBER': $XML_RPC_xh[$parser]['ac'] = ''; break; case 'DATA': case 'METHODCALL': case 'METHODNAME': case 'METHODRESPONSE': case 'PARAMS': // valid elements that add little to processing break; } // Save current element to stack array_unshift($XML_RPC_xh[$parser]['stack'], $name); if ($name != 'VALUE') { $XML_RPC_xh[$parser]['lv'] = 0; } } /** * End element handler for the XML parser * * @return void */ function XML_RPC_ee($parser_resource, $name) { global $XML_RPC_xh; $parser = (int) $parser_resource; if ($XML_RPC_xh[$parser]['isf'] >= 2) { return; } // push this element from stack // NB: if XML validates, correct opening/closing is guaranteed and // we do not have to check for $name == $curr_elem. // we also checked for proper nesting at start of elements... $curr_elem = array_shift($XML_RPC_xh[$parser]['stack']); switch ($name) { case 'STRUCT': case 'ARRAY': $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); $XML_RPC_xh[$parser]['value'] = $cur_val['value']; $XML_RPC_xh[$parser]['vt'] = strtolower($name); $XML_RPC_xh[$parser]['cm']--; break; case 'NAME': $XML_RPC_xh[$parser]['valuestack'][0]['name'] = $XML_RPC_xh[$parser]['ac']; break; case 'BOOLEAN': // special case here: we translate boolean 1 or 0 into PHP // constants true or false if ($XML_RPC_xh[$parser]['ac'] == '1') { $XML_RPC_xh[$parser]['ac'] = 'true'; } else { $XML_RPC_xh[$parser]['ac'] = 'false'; } $XML_RPC_xh[$parser]['vt'] = strtolower($name); // Drop through intentionally. case 'I4': case 'INT': case 'STRING': case 'DOUBLE': case 'DATETIME.ISO8601': case 'BASE64': if ($XML_RPC_xh[$parser]['qt'] == 1) { // we use double quotes rather than single so backslashification works OK $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; } elseif ($XML_RPC_xh[$parser]['qt'] == 2) { $XML_RPC_xh[$parser]['value'] = base64_decode($XML_RPC_xh[$parser]['ac']); } elseif ($name == 'BOOLEAN') { $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; } else { // we have an I4, INT or a DOUBLE // we must check that only 0123456789-.<space> are characters here if (!preg_match("@^[+-]?[0123456789 \t\.]+$@", $XML_RPC_xh[$parser]['ac'])) { XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE', XML_RPC_ERROR_NON_NUMERIC_FOUND); $XML_RPC_xh[$parser]['value'] = XML_RPC_ERROR_NON_NUMERIC_FOUND; } else { // it's ok, add it on $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; } } $XML_RPC_xh[$parser]['ac'] = ''; $XML_RPC_xh[$parser]['qt'] = 0; $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value break; case 'VALUE': if ($XML_RPC_xh[$parser]['vt'] == $GLOBALS['XML_RPC_String']) { if (strlen($XML_RPC_xh[$parser]['ac']) > 0) { $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; } elseif ($XML_RPC_xh[$parser]['lv'] == 1) { // The <value> element was empty. $XML_RPC_xh[$parser]['value'] = ''; } } $temp = new XML_RPC_Value($XML_RPC_xh[$parser]['value'], $XML_RPC_xh[$parser]['vt']); $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); if (is_array($cur_val)) { if ($cur_val['members']==0) { $cur_val['value'][] = $temp; } else { $XML_RPC_xh[$parser]['value'] = $temp; } array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); } else { $XML_RPC_xh[$parser]['value'] = $temp; } break; case 'MEMBER': $XML_RPC_xh[$parser]['ac'] = ''; $XML_RPC_xh[$parser]['qt'] = 0; $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); if (is_array($cur_val)) { if ($cur_val['members']==1) { $cur_val['value'][$cur_val['name']] = $XML_RPC_xh[$parser]['value']; } array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); } break; case 'DATA': $XML_RPC_xh[$parser]['ac'] = ''; $XML_RPC_xh[$parser]['qt'] = 0; break; case 'PARAM': $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['value']; break; case 'METHODNAME': case 'RPCMETHODNAME': $XML_RPC_xh[$parser]['method'] = preg_replace("@^[\n\r\t ]+@", '', $XML_RPC_xh[$parser]['ac']); break; } // if it's a valid type name, set the type if (isset($GLOBALS['XML_RPC_Types'][strtolower($name)])) { $XML_RPC_xh[$parser]['vt'] = strtolower($name); } } /** * Character data handler for the XML parser * * @return void */ function XML_RPC_cd($parser_resource, $data) { global $XML_RPC_xh, $XML_RPC_backslash; $parser = (int) $parser_resource; if ($XML_RPC_xh[$parser]['lv'] != 3) { // "lookforvalue==3" means that we've found an entire value // and should discard any further character data if ($XML_RPC_xh[$parser]['lv'] == 1) { // if we've found text and we're just in a <value> then // turn quoting on, as this will be a string $XML_RPC_xh[$parser]['qt'] = 1; // and say we've found a value $XML_RPC_xh[$parser]['lv'] = 2; } // replace characters that eval would // do special things with if (!isset($XML_RPC_xh[$parser]['ac'])) { $XML_RPC_xh[$parser]['ac'] = ''; } $XML_RPC_xh[$parser]['ac'] .= $data; } } /** * The common methods and properties for all of the XML_RPC classes * * @category Web Services * @package XML_RPC * @author Edd Dumbill <edd@usefulinc.com> * @author Stig Bakken <stig@php.net> * @author Martin Jansen <mj@php.net> * @author Daniel Convissor <danielc@php.net> * @copyright 1999-2001 Edd Dumbill, 2001-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_RPC */ class XML_RPC_Base { /** * PEAR Error handling * * @return object PEAR_Error object */ function raiseError($msg, $code) { include_once 'PEAR.php'; if (is_object(@$this)) { return PEAR::raiseError(get_class($this) . ': ' . $msg, $code); } else { return PEAR::raiseError('XML_RPC: ' . $msg, $code); } } /** * Tell whether something is a PEAR_Error object * * @param mixed $value the item to check * * @return bool whether $value is a PEAR_Error object or not * * @access public */ function isError($value) { return is_object($value) && is_a($value, 'PEAR_Error'); } } /** * The methods and properties for submitting XML RPC requests * * @category Web Services * @package XML_RPC * @author Edd Dumbill <edd@usefulinc.com> * @author Stig Bakken <stig@php.net> * @author Martin Jansen <mj@php.net> * @author Daniel Convissor <danielc@php.net> * @copyright 1999-2001 Edd Dumbill, 2001-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_RPC */ class XML_RPC_Client extends XML_RPC_Base { /** * The path and name of the RPC server script you want the request to go to * @var string */ var $path = ''; /** * The name of the remote server to connect to * @var string */ var $server = ''; /** * The protocol to use in contacting the remote server * @var string */ var $protocol = 'http://'; /** * The port for connecting to the remote server * * The default is 80 for http:// connections * and 443 for https:// and ssl:// connections. * * @var integer */ var $port = 80; /** * A user name for accessing the RPC server * @var string * @see XML_RPC_Client::setCredentials() */ var $username = ''; /** * A password for accessing the RPC server * @var string * @see XML_RPC_Client::setCredentials() */ var $password = ''; /** * The name of the proxy server to use, if any * @var string */ var $proxy = ''; /** * The protocol to use in contacting the proxy server, if any * @var string */ var $proxy_protocol = 'http://'; /** * The port for connecting to the proxy server * * The default is 8080 for http:// connections * and 443 for https:// and ssl:// connections. * * @var integer */ var $proxy_port = 8080; /** * A user name for accessing the proxy server * @var string */ var $proxy_user = ''; /** * A password for accessing the proxy server * @var string */ var $proxy_pass = ''; /** * The error number, if any * @var integer */ var $errno = 0; /** * The error message, if any * @var string */ var $errstr = ''; /** * The current debug mode (1 = on, 0 = off) * @var integer */ var $debug = 0; /** * The HTTP headers for the current request. * @var string */ var $headers = ''; /** * Sets the object's properties * * @param string $path the path and name of the RPC server script * you want the request to go to * @param string $server the URL of the remote server to connect to. * If this parameter doesn't specify a * protocol and $port is 443, ssl:// is * assumed. * @param integer $port a port for connecting to the remote server. * Defaults to 80 for http:// connections and * 443 for https:// and ssl:// connections. * @param string $proxy the URL of the proxy server to use, if any. * If this parameter doesn't specify a * protocol and $port is 443, ssl:// is * assumed. * @param integer $proxy_port a port for connecting to the remote server. * Defaults to 8080 for http:// connections and * 443 for https:// and ssl:// connections. * @param string $proxy_user a user name for accessing the proxy server * @param string $proxy_pass a password for accessing the proxy server * * @return void */ function XML_RPC_Client($path, $server, $port = 0, $proxy = '', $proxy_port = 0, $proxy_user = '', $proxy_pass = '') { $this->path = $path; $this->proxy_user = $proxy_user; $this->proxy_pass = $proxy_pass; preg_match('@^(http://|https://|ssl://)?(.*)$@', $server, $match); if ($match[1] == '') { if ($port == 443) { $this->server = $match[2]; $this->protocol = 'ssl://'; $this->port = 443; } else { $this->server = $match[2]; if ($port) { $this->port = $port; } } } elseif ($match[1] == 'http://') { $this->server = $match[2]; if ($port) { $this->port = $port; } } else { $this->server = $match[2]; $this->protocol = 'ssl://'; if ($port) { $this->port = $port; } else { $this->port = 443; } } if ($proxy) { preg_match('@^(http://|https://|ssl://)?(.*)$@', $proxy, $match); if ($match[1] == '') { if ($proxy_port == 443) { $this->proxy = $match[2]; $this->proxy_protocol = 'ssl://'; $this->proxy_port = 443; } else { $this->proxy = $match[2]; if ($proxy_port) { $this->proxy_port = $proxy_port; } } } elseif ($match[1] == 'http://') { $this->proxy = $match[2]; if ($proxy_port) { $this->proxy_port = $proxy_port; } } else { $this->proxy = $match[2]; $this->proxy_protocol = 'ssl://'; if ($proxy_port) { $this->proxy_port = $proxy_port; } else { $this->proxy_port = 443; } } } } /** * Change the current debug mode * * @param int $in where 1 = on, 0 = off * * @return void */ function setDebug($in) { if ($in) { $this->debug = 1; } else { $this->debug = 0; } } /** * Sets whether strings that contain characters which may cause PHP's * SAX-based XML parser to break should be automatically base64 encoded * * This is is a workaround for systems that don't have PHP's mbstring * extension available. * * @param int $in where 1 = on, 0 = off * * @return void */ function setAutoBase64($in) { if ($in) { $GLOBALS['XML_RPC_auto_base64'] = true; } else { $GLOBALS['XML_RPC_auto_base64'] = false; } } /** * Set username and password properties for connecting to the RPC server * * @param string $u the user name * @param string $p the password * * @return void * * @see XML_RPC_Client::$username, XML_RPC_Client::$password */ function setCredentials($u, $p) { $this->username = $u; $this->password = $p; } /** * Transmit the RPC request via HTTP 1.0 protocol * * @param object $msg the XML_RPC_Message object * @param int $timeout how many seconds to wait for the request * * @return object an XML_RPC_Response object. 0 is returned if any * problems happen. * * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(), * XML_RPC_Client::setCredentials() */ function send($msg, $timeout = 0) { if (!is_object($msg) || !is_a($msg, 'XML_RPC_Message')) { $this->errstr = 'send()\'s $msg parameter must be an' . ' XML_RPC_Message object.'; $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING); return 0; } $msg->debug = $this->debug; return $this->sendPayloadHTTP10($msg, $this->server, $this->port, $timeout, $this->username, $this->password); } /** * Transmit the RPC request via HTTP 1.0 protocol * * Requests should be sent using XML_RPC_Client send() rather than * calling this method directly. * * @param object $msg the XML_RPC_Message object * @param string $server the server to send the request to * @param int $port the server port send the request to * @param int $timeout how many seconds to wait for the request * before giving up * @param string $username a user name for accessing the RPC server * @param string $password a password for accessing the RPC server * * @return object an XML_RPC_Response object. 0 is returned if any * problems happen. * * @access protected * @see XML_RPC_Client::send() */ function sendPayloadHTTP10($msg, $server, $port, $timeout = 0, $username = '', $password = '') { // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly if ($username != $this->username) { $this->setCredentials($username, $password); } // Only create the payload if it was not created previously if (empty($msg->payload)) { $msg->createPayload(); } $this->createHeaders($msg); $op = $this->headers . "\r\n\r\n"; $op .= $msg->payload; if ($this->debug) { print "\n<pre>---SENT---\n"; print $op; print "\n---END---</pre>\n"; } /* * If we're using a proxy open a socket to the proxy server * instead to the xml-rpc server */ if ($this->proxy) { if ($this->proxy_protocol == 'http://') { $protocol = ''; } else { $protocol = $this->proxy_protocol; } if ($timeout > 0) { $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port, $this->errno, $this->errstr, $timeout); } else { $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port, $this->errno, $this->errstr); } } else { if ($this->protocol == 'http://') { $protocol = ''; } else { $protocol = $this->protocol; } if ($timeout > 0) { $fp = @fsockopen($protocol . $server, $port, $this->errno, $this->errstr, $timeout); } else { $fp = @fsockopen($protocol . $server, $port, $this->errno, $this->errstr); } } /* * Just raising the error without returning it is strange, * but keep it here for backwards compatibility. */ if (!$fp && $this->proxy) { $this->raiseError('Connection to proxy server ' . $this->proxy . ':' . $this->proxy_port . ' failed. ' . $this->errstr, XML_RPC_ERROR_CONNECTION_FAILED); return 0; } elseif (!$fp) { $this->raiseError('Connection to RPC server ' . $server . ':' . $port . ' failed. ' . $this->errstr, XML_RPC_ERROR_CONNECTION_FAILED); return 0; } if ($timeout) { /* * Using socket_set_timeout() because stream_set_timeout() * was introduced in 4.3.0, but we need to support 4.2.0. */ socket_set_timeout($fp, $timeout); } if (!fputs($fp, $op, strlen($op))) { $this->errstr = 'Write error'; return 0; } $resp = $msg->parseResponseFile($fp); $meta = socket_get_status($fp); if ($meta['timed_out']) { fclose($fp); $this->errstr = 'RPC server did not send response before timeout.'; $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED); return 0; } fclose($fp); return $resp; } /** * Determines the HTTP headers and puts it in the $headers property * * @param object $msg the XML_RPC_Message object * * @return boolean TRUE if okay, FALSE if the message payload isn't set. * * @access protected */ function createHeaders($msg) { if (empty($msg->payload)) { return false; } if ($this->proxy) { $this->headers = 'POST ' . $this->protocol . $this->server; if ($this->proxy_port) { $this->headers .= ':' . $this->port; } } else { $this->headers = 'POST '; } $this->headers .= $this->path. " HTTP/1.0\r\n"; $this->headers .= "User-Agent: PEAR XML_RPC\r\n"; $this->headers .= 'Host: ' . $this->server . "\r\n"; if ($this->proxy && $this->proxy_user) { $this->headers .= 'Proxy-Authorization: Basic ' . base64_encode("$this->proxy_user:$this->proxy_pass") . "\r\n"; } // thanks to Grant Rauscher <grant7@firstworld.net> for this if ($this->username) { $this->headers .= 'Authorization: Basic ' . base64_encode("$this->username:$this->password") . "\r\n"; } $this->headers .= "Content-Type: text/xml\r\n"; $this->headers .= 'Content-Length: ' . strlen($msg->payload); return true; } } /** * The methods and properties for interpreting responses to XML RPC requests * * @category Web Services * @package XML_RPC * @author Edd Dumbill <edd@usefulinc.com> * @author Stig Bakken <stig@php.net> * @author Martin Jansen <mj@php.net> * @author Daniel Convissor <danielc@php.net> * @copyright 1999-2001 Edd Dumbill, 2001-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_RPC */ class XML_RPC_Response extends XML_RPC_Base { var $xv; var $fn; var $fs; var $hdrs; /** * @return void */ function XML_RPC_Response($val, $fcode = 0, $fstr = '') { if ($fcode != 0) { $this->fn = $fcode; $this->fs = htmlspecialchars($fstr); } else { $this->xv = $val; } } /** * @return int the error code */ function faultCode() { if (isset($this->fn)) { return $this->fn; } else { return 0; } } /** * @return string the error string */ function faultString() { return $this->fs; } /** * @return mixed the value */ function value() { return $this->xv; } /** * @return string the error message in XML format */ function serialize() { $rs = "<methodResponse>\n"; if ($this->fn) { $rs .= "<fault> <value> <struct> <member> <name>faultCode</name> <value><int>" . $this->fn . "</int></value> </member> <member> <name>faultString</name> <value><string>" . $this->fs . "</string></value> </member> </struct> </value> </fault>"; } else { $rs .= "<params>\n<param>\n" . $this->xv->serialize() . "</param>\n</params>"; } $rs .= "\n</methodResponse>"; return $rs; } } /** * The methods and properties for composing XML RPC messages * * @category Web Services * @package XML_RPC * @author Edd Dumbill <edd@usefulinc.com> * @author Stig Bakken <stig@php.net> * @author Martin Jansen <mj@php.net> * @author Daniel Convissor <danielc@php.net> * @copyright 1999-2001 Edd Dumbill, 2001-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_RPC */ class XML_RPC_Message extends XML_RPC_Base { /** * Should the payload's content be passed through mb_convert_encoding()? * * @see XML_RPC_Message::setConvertPayloadEncoding() * @since Property available since Release 1.5.1 * @var boolean */ var $convert_payload_encoding = false; /** * The current debug mode (1 = on, 0 = off) * @var integer */ var $debug = 0; /** * The encoding to be used for outgoing messages * * Defaults to the value of <var>$GLOBALS['XML_RPC_defencoding']</var> * * @var string * @see XML_RPC_Message::setSendEncoding(), * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header() */ var $send_encoding = ''; /** * The method presently being evaluated * @var string */ var $methodname = ''; /** * @var array */ var $params = array(); /** * The XML message being generated * @var string */ var $payload = ''; /** * Should extra line breaks be removed from the payload? * @since Property available since Release 1.4.6 * @var boolean */ var $remove_extra_lines = true; /** * The XML response from the remote server * @since Property available since Release 1.4.6 * @var string */ var $response_payload = ''; /** * @return void */ function XML_RPC_Message($meth, $pars = 0) { $this->methodname = $meth; if (is_array($pars) && sizeof($pars) > 0) { for ($i = 0; $i < sizeof($pars); $i++) { $this->addParam($pars[$i]); } } } /** * Produces the XML declaration including the encoding attribute * * The encoding is determined by this class' <var>$send_encoding</var> * property. If the <var>$send_encoding</var> property is not set, use * <var>$GLOBALS['XML_RPC_defencoding']</var>. * * @return string the XML declaration and <methodCall> element * * @see XML_RPC_Message::setSendEncoding(), * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding'] */ function xml_header() { global $XML_RPC_defencoding; if (!$this->send_encoding) { $this->send_encoding = $XML_RPC_defencoding; } return '<?xml version="1.0" encoding="' . $this->send_encoding . '"?>' . "\n<methodCall>\n"; } /** * @return string the closing </methodCall> tag */ function xml_footer() { return "</methodCall>\n"; } /** * Fills the XML_RPC_Message::$payload property * * Part of the process makes sure all line endings are in DOS format * (CRLF), which is probably required by specifications. * * If XML_RPC_Message::setConvertPayloadEncoding() was set to true, * the payload gets passed through mb_convert_encoding() * to ensure the payload matches the encoding set in the * XML declaration. The encoding type can be manually set via * XML_RPC_Message::setSendEncoding(). * * @return void * * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer() * @see XML_RPC_Message::setSendEncoding(), $GLOBALS['XML_RPC_defencoding'], * XML_RPC_Message::setConvertPayloadEncoding() */ function createPayload() { $this->payload = $this->xml_header(); $this->payload .= '<methodName>' . $this->methodname . "</methodName>\n"; $this->payload .= "<params>\n"; for ($i = 0; $i < sizeof($this->params); $i++) { $p = $this->params[$i]; $this->payload .= "<param>\n" . $p->serialize() . "</param>\n"; } $this->payload .= "</params>\n"; $this->payload .= $this->xml_footer(); if ($this->remove_extra_lines) { $this->payload = preg_replace("@[\r\n]+@", "\r\n", $this->payload); } else { $this->payload = preg_replace("@\r\n|\n|\r|\n\r@", "\r\n", $this->payload); } if ($this->convert_payload_encoding) { $this->payload = mb_convert_encoding($this->payload, $this->send_encoding); } } /** * @return string the name of the method */ function method($meth = '') { if ($meth != '') { $this->methodname = $meth; } return $this->methodname; } /** * @return string the payload */ function serialize() { $this->createPayload(); return $this->payload; } /** * @return void */ function addParam($par) { $this->params[] = $par; } /** * Obtains an XML_RPC_Value object for the given parameter * * @param int $i the index number of the parameter to obtain * * @return object the XML_RPC_Value object. * If the parameter doesn't exist, an XML_RPC_Response object. * * @since Returns XML_RPC_Response object on error since Release 1.3.0 */ function getParam($i) { global $XML_RPC_err, $XML_RPC_str; if (isset($this->params[$i])) { return $this->params[$i]; } else { $this->raiseError('The submitted request did not contain this parameter', XML_RPC_ERROR_INCORRECT_PARAMS); return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'], $XML_RPC_str['incorrect_params']); } } /** * @return int the number of parameters */ function getNumParams() { return sizeof($this->params); } /** * Sets whether the payload's content gets passed through * mb_convert_encoding() * * Returns PEAR_ERROR object if mb_convert_encoding() isn't available. * * @param int $in where 1 = on, 0 = off * * @return void * * @see XML_RPC_Message::setSendEncoding() * @since Method available since Release 1.5.1 */ function setConvertPayloadEncoding($in) { if ($in && !function_exists('mb_convert_encoding')) { return $this->raiseError('mb_convert_encoding() is not available', XML_RPC_ERROR_PROGRAMMING); } $this->convert_payload_encoding = $in; } /** * Sets the XML declaration's encoding attribute * * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII) * * @return void * * @see XML_RPC_Message::setConvertPayloadEncoding(), XML_RPC_Message::xml_header() * @since Method available since Release 1.2.0 */ function setSendEncoding($type) { $this->send_encoding = $type; } /** * Determine the XML's encoding via the encoding attribute * in the XML declaration * * If the encoding parameter is not set or is not ISO-8859-1, UTF-8 * or US-ASCII, $XML_RPC_defencoding will be returned. * * @param string $data the XML that will be parsed * * @return string the encoding to be used * * @link http://php.net/xml_parser_create * @since Method available since Release 1.2.0 */ function getEncoding($data) { global $XML_RPC_defencoding; if (preg_match('@<\?xml[^>]*\s*encoding\s*=\s*[\'"]([^"\']*)[\'"]@', $data, $match)) { $match[1] = trim(strtoupper($match[1])); switch ($match[1]) { case 'ISO-8859-1': case 'UTF-8': case 'US-ASCII': return $match[1]; break; default: return $XML_RPC_defencoding; } } else { return $XML_RPC_defencoding; } } /** * @return object a new XML_RPC_Response object */ function parseResponseFile($fp) { $ipd = ''; while ($data = @fread($fp, 8192)) { $ipd .= $data; } return $this->parseResponse($ipd); } /** * @return object a new XML_RPC_Response object */ function parseResponse($data = '') { global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding; $encoding = $this->getEncoding($data); $parser_resource = xml_parser_create($encoding); $parser = (int) $parser_resource; $XML_RPC_xh = array(); $XML_RPC_xh[$parser] = array(); $XML_RPC_xh[$parser]['cm'] = 0; $XML_RPC_xh[$parser]['isf'] = 0; $XML_RPC_xh[$parser]['ac'] = ''; $XML_RPC_xh[$parser]['qt'] = ''; $XML_RPC_xh[$parser]['stack'] = array(); $XML_RPC_xh[$parser]['valuestack'] = array(); xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee'); xml_set_character_data_handler($parser_resource, 'XML_RPC_cd'); $hdrfnd = 0; if ($this->debug) { print "\n<pre>---GOT---\n"; print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data; print "\n---END---</pre>\n"; } // See if response is a 200 or a 100 then a 200, else raise error. // But only do this if we're using the HTTP protocol. if (preg_match('@^HTTP@', $data) && !preg_match('@^HTTP/[0-9\.]+ 200 @', $data) && !preg_match('@^HTTP/[0-9\.]+ 10[0-9]([A-Z ]+)?[\r\n]+HTTP/[0-9\.]+ 200@', $data)) { $errstr = substr($data, 0, strpos($data, "\n") - 1); error_log('HTTP error, got response: ' . $errstr); $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'], $XML_RPC_str['http_error'] . ' (' . $errstr . ')'); xml_parser_free($parser_resource); return $r; } // gotta get rid of headers here if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) { $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos); $data = substr($data, $brpos + 4); $hdrfnd = 1; } /* * be tolerant of junk after methodResponse * (e.g. javascript automatically inserted by free hosts) * thanks to Luca Mariano <luca.mariano@email.it> */ $data = substr($data, 0, strpos($data, "</methodResponse>") + 17); $this->response_payload = $data; if (!xml_parse($parser_resource, $data, sizeof($data))) { // thanks to Peter Kocks <peter.kocks@baygate.com> if (xml_get_current_line_number($parser_resource) == 1) { $errstr = 'XML error at line 1, check URL'; } else { $errstr = sprintf('XML error: %s at line %d', xml_error_string(xml_get_error_code($parser_resource)), xml_get_current_line_number($parser_resource)); } error_log($errstr); $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], $XML_RPC_str['invalid_return']); xml_parser_free($parser_resource); return $r; } xml_parser_free($parser_resource); if ($this->debug) { print "\n<pre>---PARSED---\n"; var_dump($XML_RPC_xh[$parser]['value']); print "---END---</pre>\n"; } if ($XML_RPC_xh[$parser]['isf'] > 1) { $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], $XML_RPC_str['invalid_return'].' '.$XML_RPC_xh[$parser]['isf_reason']); } elseif (!is_object($XML_RPC_xh[$parser]['value'])) { // then something odd has happened // and it's time to generate a client side error // indicating something odd went on $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], $XML_RPC_str['invalid_return']); } else { $v = $XML_RPC_xh[$parser]['value']; if ($XML_RPC_xh[$parser]['isf']) { $f = $v->structmem('faultCode'); $fs = $v->structmem('faultString'); $r = new XML_RPC_Response($v, $f->scalarval(), $fs->scalarval()); } else { $r = new XML_RPC_Response($v); } } $r->hdrs = preg_split("@\r?\n@", $XML_RPC_xh[$parser]['ha']); return $r; } } /** * The methods and properties that represent data in XML RPC format * * @category Web Services * @package XML_RPC * @author Edd Dumbill <edd@usefulinc.com> * @author Stig Bakken <stig@php.net> * @author Martin Jansen <mj@php.net> * @author Daniel Convissor <danielc@php.net> * @copyright 1999-2001 Edd Dumbill, 2001-2010 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_RPC */ class XML_RPC_Value extends XML_RPC_Base { var $me = array(); var $mytype = 0; /** * @return void */ function XML_RPC_Value($val = -1, $type = '') { $this->me = array(); $this->mytype = 0; if ($val != -1 || $type != '') { if ($type == '') { $type = 'string'; } if (!array_key_exists($type, $GLOBALS['XML_RPC_Types'])) { // XXX // need some way to report this error } elseif ($GLOBALS['XML_RPC_Types'][$type] == 1) { $this->addScalar($val, $type); } elseif ($GLOBALS['XML_RPC_Types'][$type] == 2) { $this->addArray($val); } elseif ($GLOBALS['XML_RPC_Types'][$type] == 3) { $this->addStruct($val); } } } /** * @return int returns 1 if successful or 0 if there are problems */ function addScalar($val, $type = 'string') { if ($this->mytype == 1) { $this->raiseError('Scalar can have only one value', XML_RPC_ERROR_INVALID_TYPE); return 0; } $typeof = $GLOBALS['XML_RPC_Types'][$type]; if ($typeof != 1) { $this->raiseError("Not a scalar type (${typeof})", XML_RPC_ERROR_INVALID_TYPE); return 0; } if ($type == $GLOBALS['XML_RPC_Boolean']) { if (strcasecmp($val, 'true') == 0 || $val == 1 || ($val == true && strcasecmp($val, 'false'))) { $val = 1; } else { $val = 0; } } if ($this->mytype == 2) { // we're adding to an array here $ar = $this->me['array']; $ar[] = new XML_RPC_Value($val, $type); $this->me['array'] = $ar; } else { // a scalar, so set the value and remember we're scalar $this->me[$type] = $val; $this->mytype = $typeof; } return 1; } /** * @return int returns 1 if successful or 0 if there are problems */ function addArray($vals) { if ($this->mytype != 0) { $this->raiseError( 'Already initialized as a [' . $this->kindOf() . ']', XML_RPC_ERROR_ALREADY_INITIALIZED); return 0; } $this->mytype = $GLOBALS['XML_RPC_Types']['array']; $this->me['array'] = $vals; return 1; } /** * @return int returns 1 if successful or 0 if there are problems */ function addStruct($vals) { if ($this->mytype != 0) { $this->raiseError( 'Already initialized as a [' . $this->kindOf() . ']', XML_RPC_ERROR_ALREADY_INITIALIZED); return 0; } $this->mytype = $GLOBALS['XML_RPC_Types']['struct']; $this->me['struct'] = $vals; return 1; } /** * @return void */ function dump($ar) { reset($ar); foreach ($ar as $key => $val) { echo "$key => $val<br />"; if ($key == 'array') { foreach ($val as $key2 => $val2) { echo "-- $key2 => $val2<br />"; } } } } /** * @return string the data type of the current value */ function kindOf() { switch ($this->mytype) { case 3: return 'struct'; case 2: return 'array'; case 1: return 'scalar'; default: return 'undef'; } } /** * @return string the data in XML format */ function serializedata($typ, $val) { $rs = ''; if (!array_key_exists($typ, $GLOBALS['XML_RPC_Types'])) { // XXX // need some way to report this error return; } switch ($GLOBALS['XML_RPC_Types'][$typ]) { case 3: // struct $rs .= "<struct>\n"; reset($val); foreach ($val as $key2 => $val2) { $rs .= "<member><name>" . htmlspecialchars($key2) . "</name>\n"; $rs .= $this->serializeval($val2); $rs .= "</member>\n"; } $rs .= '</struct>'; break; case 2: // array $rs .= "<array>\n<data>\n"; foreach ($val as $value) { $rs .= $this->serializeval($value); } $rs .= "</data>\n</array>"; break; case 1: switch ($typ) { case $GLOBALS['XML_RPC_Base64']: $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>"; break; case $GLOBALS['XML_RPC_Boolean']: $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>"; break; case $GLOBALS['XML_RPC_String']: $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>"; break; default: $rs .= "<${typ}>${val}</${typ}>"; } } return $rs; } /** * @return string the data in XML format */ function serialize() { return $this->serializeval($this); } /** * @return string the data in XML format */ function serializeval($o) { if (!is_object($o) || empty($o->me) || !is_array($o->me)) { return ''; } $ar = $o->me; reset($ar); list($typ, $val) = each($ar); return '<value>' . $this->serializedata($typ, $val) . "</value>\n"; } /** * @return mixed the contents of the element requested */ function structmem($m) { return $this->me['struct'][$m]; } /** * @return void */ function structreset() { reset($this->me['struct']); } /** * @return the key/value pair of the struct's current element */ function structeach() { return each($this->me['struct']); } /** * @return mixed the current value */ function getval() { // UNSTABLE reset($this->me); $b = current($this->me); // contributed by I Sofer, 2001-03-24 // add support for nested arrays to scalarval // i've created a new method here, so as to // preserve back compatibility if (is_array($b)) { foreach ($b as $id => $cont) { $b[$id] = $cont->scalarval(); } } // add support for structures directly encoding php objects if (is_object($b)) { $t = get_object_vars($b); foreach ($t as $id => $cont) { $t[$id] = $cont->scalarval(); } foreach ($t as $id => $cont) { $b->$id = $cont; } } // end contrib return $b; } /** * @return mixed the current element's scalar value. If the value is * not scalar, FALSE is returned. */ function scalarval() { reset($this->me); $v = current($this->me); if (!is_scalar($v)) { $v = false; } return $v; } /** * @return string */ function scalartyp() { reset($this->me); $a = key($this->me); if ($a == $GLOBALS['XML_RPC_I4']) { $a = $GLOBALS['XML_RPC_Int']; } return $a; } /** * @return mixed the struct's current element */ function arraymem($m) { return $this->me['array'][$m]; } /** * @return int the number of elements in the array */ function arraysize() { reset($this->me); list($a, $b) = each($this->me); return sizeof($b); } /** * Determines if the item submitted is an XML_RPC_Value object * * @param mixed $val the variable to be evaluated * * @return bool TRUE if the item is an XML_RPC_Value object * * @static * @since Method available since Release 1.3.0 */ function isValue($val) { return (strtolower(get_class($val)) == 'xml_rpc_value'); } } /** * Return an ISO8601 encoded string * * While timezones ought to be supported, the XML-RPC spec says: * * "Don't assume a timezone. It should be specified by the server in its * documentation what assumptions it makes about timezones." * * This routine always assumes localtime unless $utc is set to 1, in which * case UTC is assumed and an adjustment for locale is made when encoding. * * @return string the formatted date */ function XML_RPC_iso8601_encode($timet, $utc = 0) { if (!$utc) { $t = strftime('%Y%m%dT%H:%M:%S', $timet); } else { if (function_exists('gmstrftime')) { // gmstrftime doesn't exist in some versions // of PHP $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet); } else { $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z')); } } return $t; } /** * Convert a datetime string into a Unix timestamp * * While timezones ought to be supported, the XML-RPC spec says: * * "Don't assume a timezone. It should be specified by the server in its * documentation what assumptions it makes about timezones." * * This routine always assumes localtime unless $utc is set to 1, in which * case UTC is assumed and an adjustment for locale is made when encoding. * * @return int the unix timestamp of the date submitted */ function XML_RPC_iso8601_decode($idate, $utc = 0) { $t = 0; if (preg_match('@([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})@', $idate, $regs)) { if ($utc) { $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); } else { $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); } } return $t; } /** * Converts an XML_RPC_Value object into native PHP types * * @param object $XML_RPC_val the XML_RPC_Value object to decode * * @return mixed the PHP values */ function XML_RPC_decode($XML_RPC_val) { $kind = $XML_RPC_val->kindOf(); if ($kind == 'scalar') { return $XML_RPC_val->scalarval(); } elseif ($kind == 'array') { $size = $XML_RPC_val->arraysize(); $arr = array(); for ($i = 0; $i < $size; $i++) { $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i)); } return $arr; } elseif ($kind == 'struct') { $XML_RPC_val->structreset(); $arr = array(); while (list($key, $value) = $XML_RPC_val->structeach()) { $arr[$key] = XML_RPC_decode($value); } return $arr; } } /** * Converts native PHP types into an XML_RPC_Value object * * @param mixed $php_val the PHP value or variable you want encoded * * @return object the XML_RPC_Value object */ function XML_RPC_encode($php_val) { $type = gettype($php_val); $XML_RPC_val = new XML_RPC_Value; switch ($type) { case 'array': if (empty($php_val)) { $XML_RPC_val->addArray($php_val); break; } $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1)); if (empty($tmp)) { $arr = array(); foreach ($php_val as $k => $v) { $arr[$k] = XML_RPC_encode($v); } $XML_RPC_val->addArray($arr); break; } // fall though if it's not an enumerated array case 'object': $arr = array(); foreach ($php_val as $k => $v) { $arr[$k] = XML_RPC_encode($v); } $XML_RPC_val->addStruct($arr); break; case 'integer': $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Int']); break; case 'double': $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Double']); break; case 'string': case 'NULL': if (preg_match('@^[0-9]{8}\T{1}[0-9]{2}\:[0-9]{2}\:[0-9]{2}$@', $php_val)) { $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_DateTime']); } elseif ($GLOBALS['XML_RPC_auto_base64'] && preg_match("@[^ -~\t\r\n]@", $php_val)) { // Characters other than alpha-numeric, punctuation, SP, TAB, // LF and CR break the XML parser, encode value via Base 64. $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Base64']); } else { $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_String']); } break; case 'boolean': // Add support for encoding/decoding of booleans, since they // are supported in PHP // by <G_Giunta_2001-02-29> $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Boolean']); break; case 'unknown type': default: $XML_RPC_val = false; } return $XML_RPC_val; } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * c-hanging-comment-ender-p: nil * End: */ ?> PK�������!�c}��}�� ��XML/Util.phpnu�[��������<?php /** * XML_Util * * XML Utilities package * * PHP versions 4 and 5 * * LICENSE: * * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * The name of the author may not 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. * * @category XML * @package XML_Util * @author Stephan Schmidt <schst@php.net> * @copyright 2003-2008 Stephan Schmidt <schst@php.net> * @license http://opensource.org/licenses/bsd-license New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/XML_Util */ /** * Error code for invalid chars in XML name */ define('XML_UTIL_ERROR_INVALID_CHARS', 51); /** * Error code for invalid chars in XML name */ define('XML_UTIL_ERROR_INVALID_START', 52); /** * Error code for non-scalar tag content */ define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60); /** * Error code for missing tag name */ define('XML_UTIL_ERROR_NO_TAG_NAME', 61); /** * Replace XML entities */ define('XML_UTIL_REPLACE_ENTITIES', 1); /** * Embedd content in a CData Section */ define('XML_UTIL_CDATA_SECTION', 5); /** * Do not replace entitites */ define('XML_UTIL_ENTITIES_NONE', 0); /** * Replace all XML entitites * This setting will replace <, >, ", ' and & */ define('XML_UTIL_ENTITIES_XML', 1); /** * Replace only required XML entitites * This setting will replace <, " and & */ define('XML_UTIL_ENTITIES_XML_REQUIRED', 2); /** * Replace HTML entitites * @link http://www.php.net/htmlentities */ define('XML_UTIL_ENTITIES_HTML', 3); /** * Do not collapse any empty tags. */ define('XML_UTIL_COLLAPSE_NONE', 0); /** * Collapse all empty tags. */ define('XML_UTIL_COLLAPSE_ALL', 1); /** * Collapse only empty XHTML tags that have no end tag. */ define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2); /** * Utility class for working with XML documents * * @category XML * @package XML_Util * @author Stephan Schmidt <schst@php.net> * @copyright 2003-2008 Stephan Schmidt <schst@php.net> * @license http://opensource.org/licenses/bsd-license New BSD License * @version Release: 1.4.5 * @link http://pear.php.net/package/XML_Util */ class XML_Util { /** * Return API version * * @return string $version API version */ public static function apiVersion() { return '1.4'; } /** * Replace XML entities * * With the optional second parameter, you may select, which * entities should be replaced. * * <code> * require_once 'XML/Util.php'; * * // replace XML entites: * $string = XML_Util::replaceEntities('This string contains < & >.'); * </code> * * With the optional third parameter, you may pass the character encoding * <code> * require_once 'XML/Util.php'; * * // replace XML entites in UTF-8: * $string = XML_Util::replaceEntities( * 'This string contains < & > as well as ä, ö, ß, à and ê', * XML_UTIL_ENTITIES_HTML, * 'UTF-8' * ); * </code> * * @param string $string string where XML special chars * should be replaced * @param int $replaceEntities setting for entities in attribute values * (one of XML_UTIL_ENTITIES_XML, * XML_UTIL_ENTITIES_XML_REQUIRED, * XML_UTIL_ENTITIES_HTML) * @param string $encoding encoding value (if any)... * must be a valid encoding as determined * by the htmlentities() function * * @return string string with replaced chars * @see reverseEntities() */ public static function replaceEntities( $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1' ) { switch ($replaceEntities) { case XML_UTIL_ENTITIES_XML: return strtr( $string, array( '&' => '&', '>' => '>', '<' => '<', '"' => '"', '\'' => ''' ) ); break; case XML_UTIL_ENTITIES_XML_REQUIRED: return strtr( $string, array( '&' => '&', '<' => '<', '"' => '"' ) ); break; case XML_UTIL_ENTITIES_HTML: return htmlentities($string, ENT_COMPAT, $encoding); break; } return $string; } /** * Reverse XML entities * * With the optional second parameter, you may select, which * entities should be reversed. * * <code> * require_once 'XML/Util.php'; * * // reverse XML entites: * $string = XML_Util::reverseEntities('This string contains < & >.'); * </code> * * With the optional third parameter, you may pass the character encoding * <code> * require_once 'XML/Util.php'; * * // reverse XML entites in UTF-8: * $string = XML_Util::reverseEntities( * 'This string contains < & > as well as' * . ' ä, ö, ß, à and ê', * XML_UTIL_ENTITIES_HTML, * 'UTF-8' * ); * </code> * * @param string $string string where XML special chars * should be replaced * @param int $replaceEntities setting for entities in attribute values * (one of XML_UTIL_ENTITIES_XML, * XML_UTIL_ENTITIES_XML_REQUIRED, * XML_UTIL_ENTITIES_HTML) * @param string $encoding encoding value (if any)... * must be a valid encoding as determined * by the html_entity_decode() function * * @return string string with replaced chars * @see replaceEntities() */ public static function reverseEntities( $string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1' ) { switch ($replaceEntities) { case XML_UTIL_ENTITIES_XML: return strtr( $string, array( '&' => '&', '>' => '>', '<' => '<', '"' => '"', ''' => '\'' ) ); break; case XML_UTIL_ENTITIES_XML_REQUIRED: return strtr( $string, array( '&' => '&', '<' => '<', '"' => '"' ) ); break; case XML_UTIL_ENTITIES_HTML: return html_entity_decode($string, ENT_COMPAT, $encoding); break; } return $string; } /** * Build an xml declaration * * <code> * require_once 'XML/Util.php'; * * // get an XML declaration: * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true); * </code> * * @param string $version xml version * @param string $encoding character encoding * @param bool $standalone document is standalone (or not) * * @return string xml declaration * @uses attributesToString() to serialize the attributes of the * XML declaration */ public static function getXMLDeclaration( $version = '1.0', $encoding = null, $standalone = null ) { $attributes = array( 'version' => $version, ); // add encoding if ($encoding !== null) { $attributes['encoding'] = $encoding; } // add standalone, if specified if ($standalone !== null) { $attributes['standalone'] = $standalone ? 'yes' : 'no'; } return sprintf( '<?xml%s?>', XML_Util::attributesToString($attributes, false) ); } /** * Build a document type declaration * * <code> * require_once 'XML/Util.php'; * * // get a doctype declaration: * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd'); * </code> * * @param string $root name of the root tag * @param string $uri uri of the doctype definition * (or array with uri and public id) * @param string $internalDtd internal dtd entries * * @return string doctype declaration * @since 0.2 */ public static function getDocTypeDeclaration( $root, $uri = null, $internalDtd = null ) { if (is_array($uri)) { $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']); } elseif (!empty($uri)) { $ref = sprintf(' SYSTEM "%s"', $uri); } else { $ref = ''; } if (empty($internalDtd)) { return sprintf('<!DOCTYPE %s%s>', $root, $ref); } else { return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd); } } /** * Create string representation of an attribute list * * <code> * require_once 'XML/Util.php'; * * // build an attribute string * $att = array( * 'foo' => 'bar', * 'argh' => 'tomato' * ); * * $attList = XML_Util::attributesToString($att); * </code> * * @param array $attributes attribute array * @param bool|array $sort sort attribute list alphabetically, * may also be an assoc array containing * the keys 'sort', 'multiline', 'indent', * 'linebreak' and 'entities' * @param bool $multiline use linebreaks, if more than * one attribute is given * @param string $indent string used for indentation of * multiline attributes * @param string $linebreak string used for linebreaks of * multiline attributes * @param int $entities setting for entities in attribute values * (one of XML_UTIL_ENTITIES_NONE, * XML_UTIL_ENTITIES_XML, * XML_UTIL_ENTITIES_XML_REQUIRED, * XML_UTIL_ENTITIES_HTML) * * @return string string representation of the attributes * @uses replaceEntities() to replace XML entities in attribute values * @todo allow sort also to be an options array */ public static function attributesToString( $attributes, $sort = true, $multiline = false, $indent = ' ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML ) { /* * second parameter may be an array */ if (is_array($sort)) { if (isset($sort['multiline'])) { $multiline = $sort['multiline']; } if (isset($sort['indent'])) { $indent = $sort['indent']; } if (isset($sort['linebreak'])) { $multiline = $sort['linebreak']; } if (isset($sort['entities'])) { $entities = $sort['entities']; } if (isset($sort['sort'])) { $sort = $sort['sort']; } else { $sort = true; } } $string = ''; if (is_array($attributes) && !empty($attributes)) { if ($sort) { ksort($attributes); } if (!$multiline || count($attributes) == 1) { foreach ($attributes as $key => $value) { if ($entities != XML_UTIL_ENTITIES_NONE) { if ($entities === XML_UTIL_CDATA_SECTION) { $entities = XML_UTIL_ENTITIES_XML; } $value = XML_Util::replaceEntities($value, $entities); } $string .= ' ' . $key . '="' . $value . '"'; } } else { $first = true; foreach ($attributes as $key => $value) { if ($entities != XML_UTIL_ENTITIES_NONE) { $value = XML_Util::replaceEntities($value, $entities); } if ($first) { $string .= ' ' . $key . '="' . $value . '"'; $first = false; } else { $string .= $linebreak . $indent . $key . '="' . $value . '"'; } } } } return $string; } /** * Collapses empty tags. * * @param string $xml XML * @param int $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL) * or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones. * * @return string XML */ public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL) { if (preg_match('~<([^>])+/>~s', $xml, $matches)) { // it's already an empty tag return $xml; } switch ($mode) { case XML_UTIL_COLLAPSE_ALL: $preg1 = '~<' . '(?:' . '(https?://[^:\s]+:\w+)' . // <http://foo.com:bar ($1) '|(\w+:\w+)' . // <foo:bar ($2) '|(\w+)' . // <foo ($3) ')+' . '([^>]*)' . // attributes ($4) '>' . '<\/(\1|\2|\3)>' . // 1, 2, or 3 again ($5) '~s' ; $preg2 = '<' . '${1}${2}${3}' . // tag (only one should have been populated) '${4}' . // attributes ' />' ; return (preg_replace($preg1, $preg2, $xml)?:$xml); break; case XML_UTIL_COLLAPSE_XHTML_ONLY: return ( preg_replace( '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|' . 'param)([^>]*)><\/\\1>/s', '<\\1\\2 />', $xml ) ?: $xml ); break; case XML_UTIL_COLLAPSE_NONE: // fall thru default: return $xml; } } /** * Create a tag * * This method will call XML_Util::createTagFromArray(), which * is more flexible. * * <code> * require_once 'XML/Util.php'; * * // create an XML tag: * $tag = XML_Util::createTag('myNs:myTag', * array('foo' => 'bar'), * 'This is inside the tag', * 'http://www.w3c.org/myNs#'); * </code> * * @param string $qname qualified tagname (including namespace) * @param array $attributes array containg attributes * @param mixed $content the content * @param string $namespaceUri URI of the namespace * @param int $replaceEntities whether to replace XML special chars in * content, embedd it in a CData section * or none of both * @param bool $multiline whether to create a multiline tag where * each attribute gets written to a single line * @param string $indent string used to indent attributes * (_auto indents attributes so they start * at the same column) * @param string $linebreak string used for linebreaks * @param bool $sortAttributes Whether to sort the attributes or not * @param int $collapseTagMode How to handle a content-less, and thus collapseable, tag * * @return string XML tag * @see createTagFromArray() * @uses createTagFromArray() to create the tag */ public static function createTag( $qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = '_auto', $linebreak = "\n", $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL ) { $tag = array( 'qname' => $qname, 'attributes' => $attributes ); // add tag content if ($content !== null) { $tag['content'] = $content; } // add namespace Uri if ($namespaceUri !== null) { $tag['namespaceUri'] = $namespaceUri; } return XML_Util::createTagFromArray( $tag, $replaceEntities, $multiline, $indent, $linebreak, $sortAttributes, $collapseTagMode ); } /** * Create a tag from an array. * This method awaits an array in the following format * <pre> * array( * // qualified name of the tag * 'qname' => $qname * * // namespace prefix (optional, if qname is specified or no namespace) * 'namespace' => $namespace * * // local part of the tagname (optional, if qname is specified) * 'localpart' => $localpart, * * // array containing all attributes (optional) * 'attributes' => array(), * * // tag content (optional) * 'content' => $content, * * // namespaceUri for the given namespace (optional) * 'namespaceUri' => $namespaceUri * ) * </pre> * * <code> * require_once 'XML/Util.php'; * * $tag = array( * 'qname' => 'foo:bar', * 'namespaceUri' => 'http://foo.com', * 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'), * 'content' => 'I\'m inside the tag', * ); * // creating a tag with qualified name and namespaceUri * $string = XML_Util::createTagFromArray($tag); * </code> * * @param array $tag tag definition * @param int $replaceEntities whether to replace XML special chars in * content, embedd it in a CData section * or none of both * @param bool $multiline whether to create a multiline tag where each * attribute gets written to a single line * @param string $indent string used to indent attributes * (_auto indents attributes so they start * at the same column) * @param string $linebreak string used for linebreaks * @param bool $sortAttributes Whether to sort the attributes or not * @param int $collapseTagMode How to handle a content-less, and thus collapseable, tag * * @return string XML tag * * @see createTag() * @uses attributesToString() to serialize the attributes of the tag * @uses splitQualifiedName() to get local part and namespace of a qualified name * @uses createCDataSection() * @uses collapseEmptyTags() * @uses raiseError() */ public static function createTagFromArray( $tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = '_auto', $linebreak = "\n", $sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL ) { if (isset($tag['content']) && !is_scalar($tag['content'])) { return XML_Util::raiseError( 'Supplied non-scalar value as tag content', XML_UTIL_ERROR_NON_SCALAR_CONTENT ); } if (!isset($tag['qname']) && !isset($tag['localPart'])) { return XML_Util::raiseError( 'You must either supply a qualified name ' . '(qname) or local tag name (localPart).', XML_UTIL_ERROR_NO_TAG_NAME ); } // if no attributes hav been set, use empty attributes if (!isset($tag['attributes']) || !is_array($tag['attributes'])) { $tag['attributes'] = array(); } if (isset($tag['namespaces'])) { foreach ($tag['namespaces'] as $ns => $uri) { $tag['attributes']['xmlns:' . $ns] = $uri; } } if (!isset($tag['qname'])) { // qualified name is not given // check for namespace if (isset($tag['namespace']) && !empty($tag['namespace'])) { $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart']; } else { $tag['qname'] = $tag['localPart']; } } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) { // namespace URI is set, but no namespace $parts = XML_Util::splitQualifiedName($tag['qname']); $tag['localPart'] = $parts['localPart']; if (isset($parts['namespace'])) { $tag['namespace'] = $parts['namespace']; } } if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) { // is a namespace given if (isset($tag['namespace']) && !empty($tag['namespace'])) { $tag['attributes']['xmlns:' . $tag['namespace']] = $tag['namespaceUri']; } else { // define this Uri as the default namespace $tag['attributes']['xmlns'] = $tag['namespaceUri']; } } if (!array_key_exists('content', $tag)) { $tag['content'] = ''; } // check for multiline attributes if ($multiline === true) { if ($indent === '_auto') { $indent = str_repeat(' ', (strlen($tag['qname'])+2)); } } // create attribute list $attList = XML_Util::attributesToString( $tag['attributes'], $sortAttributes, $multiline, $indent, $linebreak ); switch ($replaceEntities) { case XML_UTIL_ENTITIES_NONE: break; case XML_UTIL_CDATA_SECTION: $tag['content'] = XML_Util::createCDataSection($tag['content']); break; default: $tag['content'] = XML_Util::replaceEntities( $tag['content'], $replaceEntities ); break; } $tag = sprintf( '<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'], $tag['qname'] ); return self::collapseEmptyTags($tag, $collapseTagMode); } /** * Create a start element * * <code> * require_once 'XML/Util.php'; * * // create an XML start element: * $tag = XML_Util::createStartElement('myNs:myTag', * array('foo' => 'bar') ,'http://www.w3c.org/myNs#'); * </code> * * @param string $qname qualified tagname (including namespace) * @param array $attributes array containg attributes * @param string $namespaceUri URI of the namespace * @param bool $multiline whether to create a multiline tag where each * attribute gets written to a single line * @param string $indent string used to indent attributes (_auto indents * attributes so they start at the same column) * @param string $linebreak string used for linebreaks * @param bool $sortAttributes Whether to sort the attributes or not * * @return string XML start element * @see createEndElement(), createTag() */ public static function createStartElement( $qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n", $sortAttributes = true ) { // if no attributes hav been set, use empty attributes if (!isset($attributes) || !is_array($attributes)) { $attributes = array(); } if ($namespaceUri != null) { $parts = XML_Util::splitQualifiedName($qname); } // check for multiline attributes if ($multiline === true) { if ($indent === '_auto') { $indent = str_repeat(' ', (strlen($qname)+2)); } } if ($namespaceUri != null) { // is a namespace given if (isset($parts['namespace']) && !empty($parts['namespace'])) { $attributes['xmlns:' . $parts['namespace']] = $namespaceUri; } else { // define this Uri as the default namespace $attributes['xmlns'] = $namespaceUri; } } // create attribute list $attList = XML_Util::attributesToString( $attributes, $sortAttributes, $multiline, $indent, $linebreak ); $element = sprintf('<%s%s>', $qname, $attList); return $element; } /** * Create an end element * * <code> * require_once 'XML/Util.php'; * * // create an XML start element: * $tag = XML_Util::createEndElement('myNs:myTag'); * </code> * * @param string $qname qualified tagname (including namespace) * * @return string XML end element * @see createStartElement(), createTag() */ public static function createEndElement($qname) { $element = sprintf('</%s>', $qname); return $element; } /** * Create an XML comment * * <code> * require_once 'XML/Util.php'; * * // create an XML start element: * $tag = XML_Util::createComment('I am a comment'); * </code> * * @param string $content content of the comment * * @return string XML comment */ public static function createComment($content) { $comment = sprintf('<!-- %s -->', $content); return $comment; } /** * Create a CData section * * <code> * require_once 'XML/Util.php'; * * // create a CData section * $tag = XML_Util::createCDataSection('I am content.'); * </code> * * @param string $data data of the CData section * * @return string CData section with content */ public static function createCDataSection($data) { return sprintf( '<![CDATA[%s]]>', preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data)) ); } /** * Split qualified name and return namespace and local part * * <code> * require_once 'XML/Util.php'; * * // split qualified tag * $parts = XML_Util::splitQualifiedName('xslt:stylesheet'); * </code> * the returned array will contain two elements: * <pre> * array( * 'namespace' => 'xslt', * 'localPart' => 'stylesheet' * ); * </pre> * * @param string $qname qualified tag name * @param string $defaultNs default namespace (optional) * * @return array array containing namespace and local part */ public static function splitQualifiedName($qname, $defaultNs = null) { if (strstr($qname, ':')) { $tmp = explode(':', $qname); return array( 'namespace' => $tmp[0], 'localPart' => $tmp[1] ); } return array( 'namespace' => $defaultNs, 'localPart' => $qname ); } /** * Check, whether string is valid XML name * * <p>XML names are used for tagname, attribute names and various * other, lesser known entities.</p> * <p>An XML name may only consist of alphanumeric characters, * dashes, undescores and periods, and has to start with a letter * or an underscore.</p> * * <code> * require_once 'XML/Util.php'; * * // verify tag name * $result = XML_Util::isValidName('invalidTag?'); * if (is_a($result, 'PEAR_Error')) { * print 'Invalid XML name: ' . $result->getMessage(); * } * </code> * * @param string $string string that should be checked * * @return mixed true, if string is a valid XML name, PEAR error otherwise * * @todo support for other charsets * @todo PEAR CS - unable to avoid 85-char limit on second preg_match */ public static function isValidName($string) { // check for invalid chars if (!is_string($string) || !strlen($string) || !preg_match('/^[[:alpha:]_]\\z/', $string[0])) { return XML_Util::raiseError( 'XML names may only start with letter or underscore', XML_UTIL_ERROR_INVALID_START ); } // check for invalid chars $match = preg_match( '/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?' . '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/', $string ); if (!$match) { return XML_Util::raiseError( 'XML names may only contain alphanumeric ' . 'chars, period, hyphen, colon and underscores', XML_UTIL_ERROR_INVALID_CHARS ); } // XML name is valid return true; } /** * Replacement for XML_Util::raiseError * * Avoids the necessity to always require * PEAR.php * * @param string $msg error message * @param int $code error code * * @return PEAR_Error * @todo PEAR CS - should this use include_once instead? */ public static function raiseError($msg, $code) { include_once 'PEAR.php'; return PEAR::raiseError($msg, $code); } } ?> PK�������!�,8:��:�� ��pearcmd.phpnu�[��������<?php /** * PEAR, the PHP Extension and Application Repository * * Command line interface * * PHP versions 4 and 5 * * @category pear * @package PEAR * @author Stig Bakken <ssb@php.net> * @author Tomas V.V.Cox <cox@idecnet.com> * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link http://pear.php.net/package/PEAR */ @ob_end_clean(); if (!defined('PEAR_RUNTYPE')) { // this is defined in peclcmd.php as 'pecl' define('PEAR_RUNTYPE', 'pear'); } define('PEAR_IGNORE_BACKTRACE', 1); /** * @nodep Gtk */ //the space is needed for windows include paths with trailing backslash // http://pear.php.net/bugs/bug.php?id=19482 if ('/opt/alt/php84/usr/share/pear ' != '@'.'include_path'.'@ ') { ini_set('include_path', trim('/opt/alt/php84/usr/share/pear '). PATH_SEPARATOR . get_include_path()); $raw = false; } else { // this is a raw, uninstalled pear, either a cvs checkout, or php distro ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . get_include_path()); $raw = true; } @ini_set('allow_url_fopen', true); @set_time_limit(0); ob_implicit_flush(true); @ini_set('track_errors', true); @ini_set('html_errors', false); $_PEAR_PHPDIR = '#$%^&*'; set_error_handler('error_handler'); $pear_package_version = "1.10.16"; require_once 'PEAR.php'; require_once 'PEAR/Frontend.php'; require_once 'PEAR/Config.php'; require_once 'PEAR/Command.php'; require_once 'Console/Getopt.php'; PEAR_Command::setFrontendType('CLI'); $all_commands = PEAR_Command::getCommands(); $argv = Console_Getopt::readPHPArgv(); // fix CGI sapi oddity - the -- in pear.bat/pear is not removed if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') { unset($argv[1]); $argv = array_values($argv); } $progname = PEAR_RUNTYPE; array_shift($argv); $options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV"); if (PEAR::isError($options)) { usage($options); } $opts = $options[0]; $fetype = 'CLI'; if ($progname == 'gpear' || $progname == 'pear-gtk') { $fetype = 'Gtk2'; } else { foreach ($opts as $opt) { if ($opt[0] == 'G') { $fetype = 'Gtk2'; } } } $pear_user_config = ''; $pear_system_config = ''; $store_user_config = false; $store_system_config = false; $verbose = 1; foreach ($opts as $opt) { switch ($opt[0]) { case 'c': $pear_user_config = $opt[1]; break; case 'C': $pear_system_config = $opt[1]; break; } } PEAR_Command::setFrontendType($fetype); $ui = &PEAR_Command::getFrontendObject(); $config = &PEAR_Config::singleton($pear_user_config, $pear_system_config); if (PEAR::isError($config)) { $_file = ''; if ($pear_user_config !== false) { $_file .= $pear_user_config; } if ($pear_system_config !== false) { $_file .= '/' . $pear_system_config; } if ($_file == '/') { $_file = 'The default config file'; } $config->getMessage(); $ui->outputData("ERROR: $_file is not a valid config file or is corrupted."); // We stop, we have no idea where we are :) exit(1); } // this is used in the error handler to retrieve a relative path $_PEAR_PHPDIR = $config->get('php_dir'); $ui->setConfig($config); PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")); $verbose = $config->get("verbose"); $cmdopts = array(); if ($raw) { if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) { $found = false; foreach ($opts as $opt) { if ($opt[0] == 'd' || $opt[0] == 'D') { // the user knows what they are doing, and are setting config values $found = true; } } if (!$found) { // no prior runs, try to install PEAR $parent = dirname(__FILE__); if (strpos($parent, 'scripts')) { $grandparent = dirname($parent); $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml'; $pearbase = $grandparent; } else { $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml'; $pearbase = $parent; } if (file_exists($packagexml)) { $options[1] = array( 'install', $packagexml ); $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php'); $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data'); $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs'); $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests'); $config->set( 'ext_dir', $pearbase . DIRECTORY_SEPARATOR . 'extensions' ); $config->set('bin_dir', $pearbase); $config->mergeConfigFile($pearbase . 'pear.ini', false); $config->store(); $config->set('auto_discover', 1); } } } } foreach ($opts as $opt) { $param = !empty($opt[1]) ? $opt[1] : true; switch ($opt[0]) { case 'd': if ($param === true) { die( 'Invalid usage of "-d" option, expected -d config_value=value, ' . 'received "-d"' . "\n" ); } $possible = explode('=', $param); if (count($possible) != 2) { die( 'Invalid usage of "-d" option, expected ' . '-d config_value=value, received "' . $param . '"' . "\n" ); } list($key, $value) = explode('=', $param); $config->set($key, $value, 'user'); break; case 'D': if ($param === true) { die( 'Invalid usage of "-d" option, expected ' . '-d config_value=value, received "-d"' . "\n" ); } $possible = explode('=', $param); if (count($possible) != 2) { die( 'Invalid usage of "-d" option, expected ' . '-d config_value=value, received "' . $param . '"' . "\n" ); } list($key, $value) = explode('=', $param); $config->set($key, $value, 'system'); break; case 's': $store_user_config = true; break; case 'S': $store_system_config = true; break; case 'u': $config->remove($param, 'user'); break; case 'v': $config->set('verbose', $config->get('verbose') + 1); break; case 'q': $config->set('verbose', $config->get('verbose') - 1); break; case 'V': usage(null, 'version'); case 'c': case 'C': break; default: // all non pear params goes to the command $cmdopts[$opt[0]] = $param; break; } } if ($store_system_config) { $config->store('system'); } if ($store_user_config) { $config->store('user'); } $command = (isset($options[1][0])) ? $options[1][0] : null; if (empty($command) && ($store_user_config || $store_system_config)) { exit; } if ($fetype == 'Gtk2') { if (!$config->validConfiguration()) { PEAR::raiseError( "CRITICAL ERROR: no existing valid configuration files found in " . "files '$pear_user_config' or '$pear_system_config', " . "please copy an existing configuration file to one of these " . "locations, or use the -c and -s options to create one" ); } Gtk::main(); } else { do { if ($command == 'help') { usage(null, isset($options[1][1]) ? $options[1][1] : null); } if (!$config->validConfiguration()) { PEAR::raiseError( "CRITICAL ERROR: no existing valid configuration files found " . "in files '$pear_user_config' or '$pear_system_config', " . "please copy an existing configuration file to one of " . "these locations, or use the -c and -s options to create one" ); } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $cmd = PEAR_Command::factory($command, $config); PEAR::popErrorHandling(); if (PEAR::isError($cmd)) { usage(null, isset($options[1][0]) ? $options[1][0] : null); } $short_args = $long_args = null; PEAR_Command::getGetoptArgs($command, $short_args, $long_args); array_shift($options[1]); $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args); if (PEAR::isError($tmp)) { break; } list($tmpopt, $params) = $tmp; $opts = array(); foreach ($tmpopt as $foo => $tmp2) { list($opt, $value) = $tmp2; if ($value === null) { $value = true; // options without args } if (strlen($opt) == 1) { $cmdoptions = $cmd->getOptions($command); foreach ($cmdoptions as $o => $d) { if (isset($d['shortopt']) && $d['shortopt'] == $opt) { $opts[$o] = $value; } } } else { if (substr($opt, 0, 2) == '--') { $opts[substr($opt, 2)] = $value; } } } $ok = $cmd->run($command, $opts, $params); if ($ok === false) { PEAR::raiseError("unknown command `$command'"); } if (PEAR::isError($ok)) { PEAR::setErrorHandling( PEAR_ERROR_CALLBACK, array($ui, "displayFatalError") ); PEAR::raiseError($ok); } } while (false); } // {{{ usage() /** * Display usage information * * @param mixed $error Optional error message * @param mixed $helpsubject Optional subject/command to display help for * * @return void */ function usage($error = null, $helpsubject = null) { global $progname, $all_commands; $stdout = fopen('php://stdout', 'w'); if (PEAR::isError($error)) { fputs($stdout, $error->getMessage() . "\n"); } elseif ($error !== null) { fputs($stdout, "$error\n"); } if ($helpsubject != null) { $put = cmdHelp($helpsubject); } else { $put = "Commands:\n"; $maxlen = max(array_map("strlen", $all_commands)); $formatstr = "%-{$maxlen}s %s\n"; ksort($all_commands); foreach ($all_commands as $cmd => $class) { $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd)); } $put .= "Usage: $progname [options] command [command-options] <parameters>\n". "Type \"$progname help options\" to list all options.\n". "Type \"$progname help shortcuts\" to list all command shortcuts.\n". "Type \"$progname help version\" or ". "\"$progname version\" to list version information.\n". "Type \"$progname help <command>\" to get the help ". "for the specified command."; } fputs($stdout, "$put\n"); fclose($stdout); if ($error === null) { exit(0); } exit(1); } /** * Return help string for specified command * * @param string $command Command to return help for * * @return void */ function cmdHelp($command) { global $progname, $all_commands, $config; if ($command == "options") { return "Options:\n". " -v increase verbosity level (default 1)\n". " -q be quiet, decrease verbosity level\n". " -c file find user configuration in `file'\n". " -C file find system configuration in `file'\n". " -d foo=bar set user config variable `foo' to `bar'\n". " -D foo=bar set system config variable `foo' to `bar'\n". " -G start in graphical (Gtk) mode\n". " -s store user configuration\n". " -S store system configuration\n". " -u foo unset `foo' in the user configuration\n". " -h, -? display help/usage (this message)\n". " -V version information\n"; } elseif ($command == "shortcuts") { $sc = PEAR_Command::getShortcuts(); $ret = "Shortcuts:\n"; foreach ($sc as $s => $c) { $ret .= sprintf(" %-8s %s\n", $s, $c); } return $ret; } elseif ($command == "version") { return "PEAR Version: ".$GLOBALS['pear_package_version']. "\nPHP Version: ".phpversion(). "\nZend Engine Version: ".zend_version(). "\nRunning on: ".php_uname(); } elseif ($help = PEAR_Command::getHelp($command)) { if (is_string($help)) { return "$progname $command [options] $help\n"; } if ($help[1] === null) { return "$progname $command $help[0]"; } return "$progname $command [options] $help[0]\n$help[1]"; } return "Command '$command' is not valid, try '$progname help'"; } // }}} /** * error_handler * * @param mixed $errno Error number * @param mixed $errmsg Message * @param mixed $file Filename * @param mixed $line Line number * * @access public * @return boolean */ function error_handler($errno, $errmsg, $file, $line) { if ((!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) && ($errno & E_STRICT)) { return; // E_STRICT } if ($errno & E_DEPRECATED) { return; // E_DEPRECATED } if (!(error_reporting() & $errno) && isset($GLOBALS['config']) && $GLOBALS['config']->get('verbose') < 4 ) { return false; // @silenced error, show all if debug is high enough } $errortype = array ( E_DEPRECATED => 'Deprecated Warning', E_ERROR => "Error", E_WARNING => "Warning", E_PARSE => "Parsing Error", E_NOTICE => "Notice", E_CORE_ERROR => "Core Error", E_CORE_WARNING => "Core Warning", E_COMPILE_ERROR => "Compile Error", E_COMPILE_WARNING => "Compile Warning", E_USER_ERROR => "User Error", E_USER_WARNING => "User Warning", E_USER_NOTICE => "User Notice" ); if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 80400) { $errortype[E_STRICT] = 'Strict Warning'; } $prefix = $errortype[$errno]; global $_PEAR_PHPDIR; if (stristr($file, $_PEAR_PHPDIR)) { $file = substr($file, strlen($_PEAR_PHPDIR) + 1); } else { $file = basename($file); } print "\n$prefix: $errmsg in $file on line $line\n"; return false; } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * indent-tabs-mode: nil * mode: php * End: */ // vim600:syn=php PK�������!�J?jf ��f ����pkgxml/alt-php72-vld.xmlnu�[��������<?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.10.12" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>vld</name> <channel>pecl.php.net</channel> <summary>Provides functionality to dump the internal representation of PHP scripts</summary> <description>The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script.</description> <lead> <name>Derick Rethans</name> <user>derick</user> <email>derick@xdebug.org</email> <active>yes</active> </lead> <date>2021-01-11</date> <time>14:39:16</time> <version> <release>0.17.1</release> <api>0.17.1</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD style</license> <notes> - Added support for PHP 8.0. </notes> <contents> <dir name="/"> <file md5sum="07c8a931c445845cd3c4447cd63e9602" name="branchinfo.c" role="src" /> <file md5sum="33fa9200791fdced7579f4213e7d3d07" name="branchinfo.h" role="src" /> <file md5sum="24ee28790811e701ed638f18b6836ac5" name="Changelog" role="doc" /> <file md5sum="c4242d8d5af2d183a852ce5f41f17fbd" name="config.m4" role="src" /> <file md5sum="d593048fddad29e35374fe313148b362" name="config.w32" role="src" /> <file md5sum="2ff4bed9def897f2e3e7b97b0c7a9bbb" name="CREDITS" role="doc" /> <file md5sum="a6c3175094f39c92adebcb40c89a18f3" name="LICENSE" role="src" /> <file md5sum="51f68176e059d4acc76236dcaab047d6" name="README.rst" role="doc" /> <file md5sum="4a457fcf7b75bd09ac9faf2f45b94efe" name="Makefile.in" role="src" /> <file md5sum="acfc5fea66b523f6d4cc94d2122da1bc" name="php_vld.h" role="src" /> <file md5sum="9750929c2ab85cc6407759ea3c84c710" name="set.c" role="src" /> <file md5sum="17c57cde6ffb1e8cb26f2b0763bc929d" name="set.h" role="src" /> <file md5sum="8610b6d440c0f83e884e350b9ed0201a" name="srm_oparray.c" role="src" /> <file md5sum="7ed01788f15907de365a0bf42b605856" name="srm_oparray.h" role="src" /> <file md5sum="68ac1e9634d5da9333c2d6e9acdd4718" name="vld.c" role="src" /> </dir> </contents> <dependencies> <required> <php> <min>7.0.0</min> </php> <pearinstaller> <min>1.4.0b1</min> </pearinstaller> </required> </dependencies> <providesextension>vld</providesextension> <extsrcrelease /> </package> PK�������!�DGe������Structures_Graph/LICENSEnu�[�������� GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. PK�������!�x ����E��Structures_Graph/docs/tutorials/Structures_Graph/Structures_Graph.pkgnu�[��������<refentry id="{@id package.database.structures_graph.tutorial}"> <refnamediv> <refname><classname>Structures_Graph</classname> Tutorial</refname> <refpurpose>A first tour of graph datastructure manipulation</refpurpose> </refnamediv> <refsect1 id="{@id package.database.structures_graph.tutorial.intro}"> <title>Introduction Structures_Graph is a package for creating and manipulating graph datastructures. A graph is a set of objects, called nodes, connected by arcs. When used as a datastructure, usually nodes contain data, and arcs represent relationships between nodes. When arcs have a direction, and can be travelled only one way, graphs are said to be directed. When arcs have no direction, and can always be travelled both ways, graphs are said to be non directed. Structures_Graph provides an object oriented API to create and directly query a graph, as well as a set of Manipulator classes to extract information from the graph. Creating a Graph Creating a graph is done using the simple constructor: and passing the constructor a flag telling it whether the graph should be directed. A directed graph will always be directed during its lifetime. It's a permanent characteristic. To fill out the graph, we'll need to create some nodes, and then call Graph::addNode. addNode(&$nodeOne); $directedGraph->addNode(&$nodeTwo); $directedGraph->addNode(&$nodeThree); ]]> and then setup the arcs: connectTo($nodeTwo); $nodeOne->connectTo($nodeThree); ]]> Note that arcs can only be created after the nodes have been inserted into the graph. Associating Data Graphs are only useful as datastructures if they can hold data. Structure_Graph stores data in nodes. Each node contains a setter and a getter for its data. setData("Node One's Data is a String"); $nodeTwo->setData(1976); $nodeThree->setData('Some other string'); print("NodeTwo's Data is an integer: " . $nodeTwo->getData()); ]]> Structure_Graph nodes can also store metadata, alongside with the main data. Metadata differs from regular data just because it is stored under a key, making it possible to store more than one data reference per node. The metadata getter and setter need the key to perform the operation: setMetadata('example key', "Node One's Sample Metadata"); print("Metadata stored under key 'example key' in node one: " . $nodeOne->getMetadata('example key')); $nodeOne->unsetMetadata('example key'); ]]> Querying a Graph Structures_Graph provides for basic querying of the graph: inDegree()); print("NodeOne's outDegree: " . $nodeOne->outDegree()); // and naturally, nodes can report on their arcs $arcs = $nodeOne->getNeighbours(); for ($i=0;$igetData()); } ]]> PK! xx PEAR/INSTALLnu[PEAR - The PEAR Installer ========================= Installing the PEAR Installer. You should install PEAR on a local development machine first. Installing PEAR on a remote production machine should only be done after you are familiar with PEAR and have tested code using PEAR on your development machine. There are two methods of installing PEAR - PEAR bundled in PHP - go-pear We will first examine how to install PEAR that is bundled with PHP. Microsoft Windows ================= If you are running PHP 5.2.0 or newer, simply download and run the windows installer (.msi) and PEAR can be automatically installed. Otherwise, for older PHP versions, download the .zip of windows, there is a script included with your PHP distribution that is called "go-pear". You must open a command box in order to run it. Click "start" then click "Run..." and type "cmd.exe" to open a command box. Use "cd" to change directory to the location of PHP where you unzipped it, and run the go-pear command. Unix ==== When compiling PHP from source, you simply need to include the --with-pear directive on the "./configure" command. This is "on" by default in most PHP versions, but it doesn't hurt to list it explicitly. You should also consider enabling the zlib extension via --enable-zlib, so that the PEAR installer will be able to handle gzipped files (i.e. smaller package files for faster downloads). Later, when you run "make install" to install PHP itself, part of the process will be prompts that ask you where you want PEAR to be installed. go-pear ======= For users who cannot perform the above steps, or who wish to obtain the latest PEAR with a slightly higher risk of failure, use go-pear. go-pear is obtained by downloading http://pear.php.net/go-pear and saving it as go-pear.php. After downloading, simply run "php go-pear.php" or open it in a web browser (windows only) to download and install PEAR. You can always ask general installation questions on pear-general@lists.php.net, a public mailing list devoted to support for PEAR packages and installation- related issues. Happy PHPing, we hope PEAR will be a great tool for your development work! PK!E PEAR/README.rstnu[************************* PEAR - The PEAR Installer ************************* .. image:: https://travis-ci.org/pear/pear-core.svg?branch=stable :target: https://travis-ci.org/pear/pear-core ========================================= What is the PEAR Installer? What is PEAR? ========================================= PEAR is the PHP Extension and Application Repository, found at http://pear.php.net. The **PEAR Installer** is this software, which contains executable files and PHP code that is used to **download and install** PEAR code from pear.php.net. PEAR contains useful **software libraries and applications** such as MDB2 (database abstraction), HTML_QuickForm (HTML forms management), PhpDocumentor (auto-documentation generator), DB_DataObject (Data Access Abstraction), and many hundreds more. Browse all available packages at http://pear.php.net, the list is constantly growing and updating to reflect improvements in the PHP language. .. warning:: Do not run PEAR without installing it - if you downloaded this tarball manually, you MUST install it. Read the instructions in INSTALL prior to use. ============= Documentation ============= Documentation for PEAR can be found at http://pear.php.net/manual/. Installation documentation can be found in the INSTALL file included in this tarball. ===== Tests ===== Run the tests without installation as follows:: $ ./scripts/pear.sh run-tests -r tests You should have the ``Text_Diff`` package installed to get nicer error output. To run the tests with another PHP version, modify ``php_bin`` and set the ``PHP_PEAR_PHP_BIN`` environment variable:: $ pear config-set php_bin /usr/local/bin/php7 $ PHP_PEAR_PHP_BIN=/usr/local/bin/php7 ./scripts/pear.sh run-tests -r tests Happy PHPing, we hope PEAR will be a great tool for your development work! Test dependencies ================= * ``zlib`` ========= Releasing ========= Create a PEAR package, as well as phars for pear-less installation, simply run ``build-release.sh``). ``go-pear.phar`` contains the PEAR installer installer that asks where to install it. It is available from http://pear.php.net/go-pear.phar. ``install-pear-nozlib.phar`` installs PEAR automatically without asking anything. It is shipped with PHP itself. PK!u PEAR/LICENSEnu[Copyright (c) 1997-2009, Stig Bakken , Gregory Beaver , Helgi Þormar Þorbjörnsson , Tomas V.V.Cox , Martin Jansen . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PK! r¦JJ Archive_Tar/docs/Archive_Tar.txtnu[Documentation for class Archive_Tar =================================== Last update : 2001-08-15 Overview : ---------- The Archive_Tar class helps in creating and managing GNU TAR format files compressed by GNU ZIP or not. The class offers basic functions like creating an archive, adding files in the archive, extracting files from the archive and listing the archive content. It also provide advanced functions that allow the adding and extraction of files with path manipulation. Sample : -------- // ----- Creating the object (uncompressed archive) $tar_object = new Archive_Tar("tarname.tar"); $tar_object->setErrorHandling(PEAR_ERROR_PRINT); // ----- Creating the archive $v_list[0]="file.txt"; $v_list[1]="data/"; $v_list[2]="file.log"; $tar_object->create($v_list); // ----- Adding files $v_list[0]="dev/file.txt"; $v_list[1]="dev/data/"; $v_list[2]="log/file.log"; $tar_object->add($v_list); // ----- Adding more files $tar_object->add("release/newfile.log release/readme.txt"); // ----- Listing the content if (($v_list = $tar_object->listContent()) != 0) for ($i=0; $i"; echo " .size :'".$v_list[$i][size]."'
"; echo " .mtime :'".$v_list[$i][mtime]."' (".date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")
"; echo " .mode :'".$v_list[$i][mode]."'
"; echo " .uid :'".$v_list[$i][uid]."'
"; echo " .gid :'".$v_list[$i][gid]."'
"; echo " .typeflag :'".$v_list[$i][typeflag]."'
"; } // ----- Extracting the archive in directory "install" $tar_object->extract("install"); Public arguments : ------------------ None Public Methods : ---------------- Method : Archive_Tar($p_tarname, $compress = null) Description : Archive_Tar Class constructor. This flavour of the constructor only declare a new Archive_Tar object, identifying it by the name of the tar file. If the compress argument is set the tar will be read or created as a gzip or bz2 compressed TAR file. Arguments : $p_tarname : A valid filename for the tar archive file. $p_compress : can be null, 'gz' or 'bz2'. For compatibility reason it can also be true. This parameter indicates if gzip or bz2 compression is required. Return value : The Archive_Tar object. Sample : $tar_object = new Archive_Tar("tarname.tar"); $tar_object_compressed = new Archive_Tar("tarname.tgz", true); How it works : Initialize the object. Method : create($p_filelist) Description : This method creates the archive file and add the files / directories that are listed in $p_filelist. If the file already exists and is writable, it is replaced by the new tar. It is a create and not an add. If the file exists and is read-only or is a directory it is not replaced. The method return false and a PEAR error text. The $p_filelist parameter can be an array of string, each string representing a filename or a directory name with their path if needed. It can also be a single string with names separated by a single blank. See also createModify() method for more details. Arguments : $p_filelist : An array of filenames and directory names, or a single string with names separated by a single blank space. Return value : true on success, false on error. Sample 1 : $tar_object = new Archive_Tar("tarname.tar"); $tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling $v_list[0]="file.txt"; $v_list[1]="data/"; (Optional '/' at the end) $v_list[2]="file.log"; $tar_object->create($v_list); Sample 2 : $tar_object = new Archive_Tar("tarname.tar"); $tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling $tar_object->create("file.txt data/ file.log"); How it works : Just calling the createModify() method with the right parameters. Method : createModify($p_filelist, $p_add_dir, $p_remove_dir = "") Description : This method creates the archive file and add the files / directories that are listed in $p_filelist. If the file already exists and is writable, it is replaced by the new tar. It is a create and not an add. If the file exists and is read-only or is a directory it is not replaced. The method return false and a PEAR error text. The $p_filelist parameter can be an array of string, each string representing a filename or a directory name with their path if needed. It can also be a single string with names separated by a single blank. The path indicated in $p_remove_dir will be removed from the memorized path of each file / directory listed when this path exists. By default nothing is removed (empty path "") The path indicated in $p_add_dir will be added at the beginning of the memorized path of each file / directory listed. However it can be set to empty "". The adding of a path is done after the removing of path. The path add/remove ability enables the user to prepare an archive for extraction in a different path than the origin files are. See also addModify() method for file adding properties. Arguments : $p_filelist : An array of filenames and directory names, or a single string with names separated by a single blank space. $p_add_dir : A string which contains a path to be added to the memorized path of each element in the list. $p_remove_dir : A string which contains a path to be removed from the memorized path of each element in the list, when relevant. Return value : true on success, false on error. Sample 1 : $tar_object = new Archive_Tar("tarname.tar"); $tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling $v_list[0]="file.txt"; $v_list[1]="data/"; (Optional '/' at the end) $v_list[2]="file.log"; $tar_object->createModify($v_list, "install"); // files are stored in the archive as : // install/file.txt // install/data // install/data/file1.txt // install/data/... all the files and sub-dirs of data/ // install/file.log Sample 2 : $tar_object = new Archive_Tar("tarname.tar"); $tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling $v_list[0]="dev/file.txt"; $v_list[1]="dev/data/"; (Optional '/' at the end) $v_list[2]="log/file.log"; $tar_object->createModify($v_list, "install", "dev"); // files are stored in the archive as : // install/file.txt // install/data // install/data/file1.txt // install/data/... all the files and sub-dirs of data/ // install/log/file.log How it works : Open the file in write mode (erasing the existing one if one), call the _addList() method for adding the files in an empty archive, add the tar footer (512 bytes block), close the tar file. Method : addModify($p_filelist, $p_add_dir, $p_remove_dir="") Description : This method add the files / directories listed in $p_filelist at the end of the existing archive. If the archive does not yet exists it is created. The $p_filelist parameter can be an array of string, each string representing a filename or a directory name with their path if needed. It can also be a single string with names separated by a single blank. The path indicated in $p_remove_dir will be removed from the memorized path of each file / directory listed when this path exists. By default nothing is removed (empty path "") The path indicated in $p_add_dir will be added at the beginning of the memorized path of each file / directory listed. However it can be set to empty "". The adding of a path is done after the removing of path. The path add/remove ability enables the user to prepare an archive for extraction in a different path than the origin files are. If a file/dir is already in the archive it will only be added at the end of the archive. There is no update of the existing archived file/dir. However while extracting the archive, the last file will replace the first one. This results in a none optimization of the archive size. If a file/dir does not exist the file/dir is ignored. However an error text is send to PEAR error. If a file/dir is not readable the file/dir is ignored. However an error text is send to PEAR error. If the resulting filename/dirname (after the add/remove option or not) string is greater than 99 char, the file/dir is ignored. However an error text is send to PEAR error. Arguments : $p_filelist : An array of filenames and directory names, or a single string with names separated by a single blank space. $p_add_dir : A string which contains a path to be added to the memorized path of each element in the list. $p_remove_dir : A string which contains a path to be removed from the memorized path of each element in the list, when relevant. Return value : true on success, false on error. Sample 1 : $tar_object = new Archive_Tar("tarname.tar"); [...] $v_list[0]="dev/file.txt"; $v_list[1]="dev/data/"; (Optional '/' at the end) $v_list[2]="log/file.log"; $tar_object->addModify($v_list, "install"); // files are stored in the archive as : // install/file.txt // install/data // install/data/file1.txt // install/data/... all the files and sub-dirs of data/ // install/file.log Sample 2 : $tar_object = new Archive_Tar("tarname.tar"); [...] $v_list[0]="dev/file.txt"; $v_list[1]="dev/data/"; (Optional '/' at the end) $v_list[2]="log/file.log"; $tar_object->addModify($v_list, "install", "dev"); // files are stored in the archive as : // install/file.txt // install/data // install/data/file1.txt // install/data/... all the files and sub-dirs of data/ // install/log/file.log How it works : If the archive does not exists it create it and add the files. If the archive does exists and is not compressed, it open it, jump before the last empty 512 bytes block (tar footer) and add the files at this point. If the archive does exists and is compressed, a temporary copy file is created. This temporary file is then 'gzip' read block by block until the last empty block. The new files are then added in the compressed file. The adding of files is done by going through the file/dir list, adding files per files, in a recursive way through the directory. Each time a path need to be added/removed it is done before writing the file header in the archive. Method : add($p_filelist) Description : This method add the files / directories listed in $p_filelist at the end of the existing archive. If the archive does not yet exists it is created. The $p_filelist parameter can be an array of string, each string representing a filename or a directory name with their path if needed. It can also be a single string with names separated by a single blank. See addModify() method for details and limitations. Arguments : $p_filelist : An array of filenames and directory names, or a single string with names separated by a single blank space. Return value : true on success, false on error. Sample 1 : $tar_object = new Archive_Tar("tarname.tar"); [...] $v_list[0]="dev/file.txt"; $v_list[1]="dev/data/"; (Optional '/' at the end) $v_list[2]="log/file.log"; $tar_object->add($v_list); Sample 2 : $tar_object = new Archive_Tar("tarname.tgz", true); [...] $v_list[0]="dev/file.txt"; $v_list[1]="dev/data/"; (Optional '/' at the end) $v_list[2]="log/file.log"; $tar_object->add($v_list); How it works : Simply call the addModify() method with the right parameters. Method : addString($p_filename, $p_string, $p_datetime, $p_params) Description : This method add a single string as a file at the end of the existing archive. If the archive does not yet exists it is created. Arguments : $p_filename : A string which contains the full filename path that will be associated with the string. $p_string : The content of the file added in the archive. $p_datetime : (Optional) Timestamp of the file (default = now) $p_params : (Optional) Various file metadata: stamp - As above, timestamp of the file mode - UNIX-style permissions (default 0600) type - Is this a regular file or link (see TAR format spec for how to create a hard/symlink) uid - UNIX-style user ID (default 0 = root) gid - UNIX-style group ID (default 0 = root) Return value : true on success, false on error. Sample 1 : $v_archive = & new Archive_Tar($p_filename); $v_archive->setErrorHandling(PEAR_ERROR_PRINT); $v_result = $v_archive->addString('data/test.txt', 'This is the text of the string'); $v_result = $v_archive->addString( 'data/test.sh', "#!/bin/sh\necho 'Hello'", time(), array( "mode" => 0755, "uid" => 34 ) ); Method : extract($p_path = "") Description : This method extract all the content of the archive in the directory indicated by $p_path.If $p_path is optional, if not set the archive is extracted in the current directory. While extracting a file, if the directory path does not exists it is created. See extractModify() for details and limitations. Arguments : $p_path : Optional path where the files/dir need to by extracted. Return value : true on success, false on error. Sample : $tar_object = new Archive_Tar("tarname.tar"); $tar_object->extract(); How it works : Simply call the extractModify() method with appropriate parameters. Method : extractModify($p_path, $p_remove_path) Description : This method extract all the content of the archive in the directory indicated by $p_path. When relevant the memorized path of the files/dir can be modified by removing the $p_remove_path path at the beginning of the file/dir path. While extracting a file, if the directory path does not exists it is created. While extracting a file, if the file already exists it is replaced without looking for last modification date. While extracting a file, if the file already exists and is write protected, the extraction is aborted. While extracting a file, if a directory with the same name already exists, the extraction is aborted. While extracting a directory, if a file with the same name already exists, the extraction is aborted. While extracting a file/directory if the destination directory exist and is write protected, or does not exist but can not be created, the extraction is aborted. If after extraction an extracted file does not show the correct stored file size, the extraction is aborted. When the extraction is aborted, a PEAR error text is set and false is returned. However the result can be a partial extraction that may need to be manually cleaned. Arguments : $p_path : The path of the directory where the files/dir need to by extracted. $p_remove_path : Part of the memorized path that can be removed if present at the beginning of the file/dir path. Return value : true on success, false on error. Sample : // Imagine tarname.tar with files : // dev/data/file.txt // dev/data/log.txt // readme.txt $tar_object = new Archive_Tar("tarname.tar"); $tar_object->extractModify("install", "dev"); // Files will be extracted there : // install/data/file.txt // install/data/log.txt // install/readme.txt How it works : Open the archive and call a more generic function that can extract only a part of the archive or all the archive. See extractList() method for more details. Method : extractInString($p_filename) Description : This method extract from the archive one file identified by $p_filename. The return value is a string with the file content, or NULL on error. Arguments : $p_filename : The path of the file to extract in a string. Return value : a string with the file content or NULL. Sample : // Imagine tarname.tar with files : // dev/data/file.txt // dev/data/log.txt // dev/readme.txt $v_archive = & new Archive_Tar('tarname.tar'); $v_archive->setErrorHandling(PEAR_ERROR_PRINT); $v_string = $v_archive->extractInString('dev/readme.txt'); echo $v_string; Method : listContent() Description : This method returns an array of arrays that describe each file/directory present in the archive. The array is not sorted, so it show the position of the file in the archive. The file informations are : $file[filename] : Name and path of the file/dir. $file[mode] : File permissions (result of fileperms()) $file[uid] : user id $file[gid] : group id $file[size] : filesize $file[mtime] : Last modification time (result of filemtime()) $file[typeflag] : "" for file, "5" for directory Arguments : Return value : An array of arrays or 0 on error. Sample : $tar_object = new Archive_Tar("tarname.tar"); if (($v_list = $tar_object->listContent()) != 0) for ($i=0; $i"; echo " .size :'".$v_list[$i][size]."'
"; echo " .mtime :'".$v_list[$i][mtime]."' (". date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")
"; echo " .mode :'".$v_list[$i][mode]."'
"; echo " .uid :'".$v_list[$i][uid]."'
"; echo " .gid :'".$v_list[$i][gid]."'
"; echo " .typeflag :'".$v_list[$i][typeflag]."'
"; } How it works : Call the same function as an extract however with a flag to only go through the archive without extracting the files. Method : extractList($p_filelist, $p_path = "", $p_remove_path = "") Description : This method extract from the archive only the files indicated in the $p_filelist. These files are extracted in the current directory or in the directory indicated by the optional $p_path parameter. If indicated the $p_remove_path can be used in the same way as it is used in extractModify() method. Arguments : $p_filelist : An array of filenames and directory names, or a single string with names separated by a single blank space. $p_path : The path of the directory where the files/dir need to by extracted. $p_remove_path : Part of the memorized path that can be removed if present at the beginning of the file/dir path. Return value : true on success, false on error. Sample : // Imagine tarname.tar with files : // dev/data/file.txt // dev/data/log.txt // readme.txt $tar_object = new Archive_Tar("tarname.tar"); $tar_object->extractList("dev/data/file.txt readme.txt", "install", "dev"); // Files will be extracted there : // install/data/file.txt // install/readme.txt How it works : Go through the archive and extract only the files present in the list. PK!fXML_Util/examples/example2.phpnu[ * 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. * * The name of the author may not 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. * * @category XML * @package XML_Util * @subpackage Examples * @author Stephan Schmidt * @copyright 2003-2008 Stephan Schmidt * @license http://opensource.org/licenses/bsd-license New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/XML_Util */ /** * set error level */ error_reporting(E_ALL); require_once 'XML/Util.php'; /** * creating a start element */ print 'creating a start element:
'; print htmlentities(XML_Util::createStartElement('myNs:myTag', array('foo' => 'bar'), 'http://www.w3c.org/myNs#')); print "\n

\n"; /** * creating a start element */ print 'creating a start element:
'; print htmlentities(XML_Util::createStartElement('myTag', array(), 'http://www.w3c.org/myNs#')); print "\n

\n"; /** * creating a start element */ print 'creating a start element:
'; print '
';
    print htmlentities(XML_Util::createStartElement('myTag', 
        array('foo' => 'bar', 'argh' => 'tomato'), 
        'http://www.w3c.org/myNs#', true));
    print '
'; print "\n

\n"; /** * creating an end element */ print 'creating an end element:
'; print htmlentities(XML_Util::createEndElement('myNs:myTag')); print "\n

\n"; /** * creating a CData section */ print 'creating a CData section:
'; print htmlentities(XML_Util::createCDataSection('I am content.')); print "\n

\n"; /** * creating a comment */ print 'creating a comment:
'; print htmlentities(XML_Util::createComment('I am a comment.')); print "\n

\n"; /** * creating an XML tag with multiline mode */ $tag = array( 'qname' => 'foo:bar', 'namespaceUri' => 'http://foo.com', 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'), 'content' => 'I\'m inside the tag & contain dangerous chars' ); print 'creating a tag with qualified name and namespaceUri:
'; print '
';
    print htmlentities(XML_Util::createTagFromArray($tag, 
        XML_UTIL_REPLACE_ENTITIES, true));
    print '
'; print "\n

\n"; /** * create an attribute string without replacing the entities */ $atts = array('series' => 'Starsky & Hutch', 'channel' => 'ABC'); print 'creating a attribute string, ' . 'entities in values already had been replaced:
'; print htmlentities(XML_Util::attributesToString($atts, true, false, false, false, XML_UTIL_ENTITIES_NONE)); print "\n

\n"; /** * using the array-syntax for attributesToString() */ $atts = array('series' => 'Starsky & Hutch', 'channel' => 'ABC'); print 'using the array-syntax for attributesToString()
'; print htmlentities(XML_Util::attributesToString($atts, array('entities' => XML_UTIL_ENTITIES_NONE))); print "\n

\n"; ?> PK!5k##XML_Util/examples/example.phpnu[ * 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. * * The name of the author may not 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. * * @category XML * @package XML_Util * @subpackage Examples * @author Stephan Schmidt * @copyright 2003-2008 Stephan Schmidt * @license http://opensource.org/licenses/bsd-license New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/XML_Util */ /** * set error level */ error_reporting(E_ALL); require_once 'XML/Util.php'; /** * replacing XML entities */ print 'replace XML entities:
'; print XML_Util::replaceEntities('This string contains < & >.'); print "\n

\n"; /** * reversing XML entities */ print 'replace XML entities:
'; print XML_Util::reverseEntities('This string contains < & >.'); print "\n

\n"; /** * building XML declaration */ print 'building XML declaration:
'; print htmlspecialchars(XML_Util::getXMLDeclaration()); print "\n

\n"; print 'building XML declaration with additional attributes:
'; print htmlspecialchars(XML_Util::getXMLDeclaration('1.0', 'UTF-8', true)); print "\n

\n"; /** * building document type declaration */ print 'building DocType declaration:
'; print htmlspecialchars(XML_Util::getDocTypeDeclaration('package', 'http://pear.php.net/dtd/package-1.0')); print "\n

\n"; print 'building DocType declaration with public ID (does not exist):
'; print htmlspecialchars(XML_Util::getDocTypeDeclaration('package', array('uri' => 'http://pear.php.net/dtd/package-1.0', 'id' => '-//PHP//PEAR/DTD PACKAGE 0.1'))); print "\n

\n"; print 'building DocType declaration with internal DTD:
'; print '
';
    print htmlspecialchars(XML_Util::getDocTypeDeclaration('package', 
        'http://pear.php.net/dtd/package-1.0', 
        ''));
    print '
'; print "\n

\n"; /** * creating an attribute string */ $att = array( 'foo' => 'bar', 'argh' => 'tomato' ); print 'converting array to string:
'; print XML_Util::attributesToString($att); print "\n

\n"; /** * creating an attribute string with linebreaks */ $att = array( 'foo' => 'bar', 'argh' => 'tomato' ); print 'converting array to string (including line breaks):
'; print '
';
    print XML_Util::attributesToString($att, true, true);
    print '
'; print "\n

\n"; /** * splitting a qualified tag name */ print 'splitting qualified tag name:
'; print '
';
    print_r(XML_Util::splitQualifiedName('xslt:stylesheet'));
    print '
'; print "\n
\n"; /** * splitting a qualified tag name (no namespace) */ print 'splitting qualified tag name (no namespace):
'; print '
';
    print_r(XML_Util::splitQualifiedName('foo'));
    print '
'; print "\n
\n"; /** * splitting a qualified tag name (no namespace, but default namespace specified) */ print 'splitting qualified tag name ' . '(no namespace, but default namespace specified):
'; print '
';
    print_r(XML_Util::splitQualifiedName('foo', 'bar'));
    print '
'; print "\n
\n"; /** * verifying XML names */ print 'verifying \'My private tag\':
'; print '
';
    print_r(XML_Util::isValidname('My Private Tag'));
    print '
'; print "\n

\n"; print 'verifying \'-MyTag\':
'; print '
';
    print_r(XML_Util::isValidname('-MyTag'));
    print '
'; print "\n

\n"; /** * creating an XML tag */ $tag = array( 'namespace' => 'foo', 'localPart' => 'bar', 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'), 'content' => 'I\'m inside the tag' ); print 'creating a tag with namespace and local part:
'; print htmlentities(XML_Util::createTagFromArray($tag)); print "\n

\n"; /** * creating an XML tag */ $tag = array( 'qname' => 'foo:bar', 'namespaceUri' => 'http://foo.com', 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'), 'content' => 'I\'m inside the tag' ); print 'creating a tag with qualified name and namespaceUri:
'; print htmlentities(XML_Util::createTagFromArray($tag)); print "\n

\n"; /** * creating an XML tag */ $tag = array( 'qname' => 'bar', 'namespaceUri' => 'http://foo.com', 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable') ); print 'creating an empty tag without namespace but namespace Uri:
'; print htmlentities(XML_Util::createTagFromArray($tag)); print "\n

\n"; /** * creating an XML tag with more namespaces */ $tag = array( 'namespace' => 'foo', 'localPart' => 'bar', 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'), 'content' => 'I\'m inside the tag', 'namespaces' => array( 'bar' => 'http://bar.com', 'pear' => 'http://pear.php.net', ) ); print 'creating an XML tag with more namespaces:
'; print htmlentities(XML_Util::createTagFromArray($tag)); print "\n

\n"; /** * creating an XML tag with a CData Section */ $tag = array( 'qname' => 'foo', 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'), 'content' => 'I\'m inside the tag' ); print 'creating a tag with CData section:
'; print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_CDATA_SECTION)); print "\n

\n"; /** * creating an XML tag with a CData Section */ $tag = array( 'qname' => 'foo', 'attributes' => array('key' => 'value', 'argh' => 'tt'), 'content' => 'Also XHTML-tags can be created ' . 'and HTML entities can be replaced <>.' ); print 'creating a tag with HTML entities:
'; print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_ENTITIES_HTML)); print "\n

\n"; /** * creating an XML tag with createTag */ print 'creating a tag with createTag:
'; print htmlentities(XML_Util::createTag('myNs:myTag', array('foo' => 'bar'), 'This is inside the tag', 'http://www.w3c.org/myNs#')); print "\n

\n"; /** * trying to create an XML tag with an array as content */ $tag = array( 'qname' => 'bar', 'content' => array('foo' => 'bar') ); print 'trying to create an XML tag with an array as content:
'; print '
';
    print_r(XML_Util::createTagFromArray($tag));
    print '
'; print "\n

\n"; /** * trying to create an XML tag without a name */ $tag = array( 'attributes' => array('foo' => 'bar'), ); print 'trying to create an XML tag without a name:
'; print '
';
    print_r(XML_Util::createTagFromArray($tag));
    print '
'; print "\n

\n"; ?> PK!a pkgxml/alt-php82-vld.xmlnu[ vld pecl.php.net Provides functionality to dump the internal representation of PHP scripts The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. Derick Rethans derick derick@xdebug.org yes 2022-09-16 0.18.0 0.18.0 beta beta BSD style - Add support for new PHP 8.1 opcodes with examples - Add support for PHP 8.2 (by removing JMPZNZ opcode) 7.0.0 1.4.0b1 vld PK!`f3##)Structures_Graph/tests/BasicGraphTest.phpnu[ | // +-----------------------------------------------------------------------------+ // require_once dirname(__FILE__) . '/helper.inc'; /** * @access private */ class BasicGraph extends \PHPUnit\Framework\TestCase { var $_graph = null; function test_create_graph() { $this->_graph = new Structures_Graph(); $this->assertTrue(is_a($this->_graph, 'Structures_Graph')); } function test_add_node() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node($data); $this->_graph->addNode($node); $node = new Structures_Graph_Node($data); $this->_graph->addNode($node); $node = new Structures_Graph_Node($data); $this->_graph->addNode($node); $this->assertTrue(true); } function test_connect_node() { $this->_graph = new Structures_Graph(); $data = 1; $node1 = new Structures_Graph_Node($data); $node2 = new Structures_Graph_Node($data); $this->_graph->addNode($node1); $this->_graph->addNode($node2); $node1->connectTo($node2); $node =& $this->_graph->getNodes(); $node =& $node[0]; $node = $node->getNeighbours(); $node =& $node[0]; /* ZE1 == and === operators fail on $node,$node2 because of the recursion introduced by the _graph field in the Node object. So, we'll use the stupid method for reference testing */ $node = true; $this->assertTrue($node2); $node = false; $this->assertFalse($node2); } function test_data_references() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node(); $node->setData($data); $this->_graph->addNode($node); $data = 2; $dataInNode =& $this->_graph->getNodes(); $dataInNode =& $dataInNode[0]; $dataInNode =& $dataInNode->getData(); $this->assertEquals($data, $dataInNode); } function test_metadata_references() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node(); $node->setMetadata('5', $data); $data = 2; $dataInNode =& $node->getMetadata('5'); $this->assertEquals($data, $dataInNode); } function test_metadata_key_exists() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node(); $node->setMetadata('5', $data); $this->assertTrue($node->metadataKeyExists('5')); $this->assertFalse($node->metadataKeyExists('1')); } function test_directed_degree() { $this->_graph = new Structures_Graph(true); $node = array(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $this->_graph->addNode($node[0]); $this->_graph->addNode($node[1]); $this->_graph->addNode($node[2]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs'); $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs'); $node[0]->connectTo($node[1]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc'); $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc'); $node[0]->connectTo($node[2]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs'); $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs'); $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs'); } function test_undirected_degree() { $this->_graph = new Structures_Graph(false); $node = array(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $this->_graph->addNode($node[0]); $this->_graph->addNode($node[1]); $this->_graph->addNode($node[2]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs'); $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs'); $node[0]->connectTo($node[1]); $this->assertEquals(1, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc'); $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc'); $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc'); $node[0]->connectTo($node[2]); $this->assertEquals(2, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs'); $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs'); $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs'); $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs'); $this->assertEquals(1, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs'); } } ?> PK! ;VV0Structures_Graph/tests/TopologicalSorterTest.phpnu[setData($name1); $graph->addNode($node1); $name11 = 'node11'; $node11 = new Structures_Graph_Node(); $node11->setData($name11); $graph->addNode($node11); $node1->connectTo($node11); $name12 = 'node12'; $node12 = new Structures_Graph_Node(); $node12->setData($name12); $graph->addNode($node12); $node1->connectTo($node12); $name121 = 'node121'; $node121 = new Structures_Graph_Node(); $node121->setData($name121); $graph->addNode($node121); $node12->connectTo($node121); $name2 = 'node2'; $node2 = new Structures_Graph_Node(); $node2->setData($name2); $graph->addNode($node2); $name21 = 'node21'; $node21 = new Structures_Graph_Node(); $node21->setData($name21); $graph->addNode($node21); $node2->connectTo($node21); $nodes = Structures_Graph_Manipulator_TopologicalSorter::sort($graph); $this->assertCount(2, $nodes[0]); $this->assertEquals('node1', $nodes[0][0]->getData()); $this->assertEquals('node2', $nodes[0][1]->getData()); $this->assertCount(3, $nodes[1]); $this->assertEquals('node11', $nodes[1][0]->getData()); $this->assertEquals('node12', $nodes[1][1]->getData()); $this->assertEquals('node21', $nodes[1][2]->getData()); $this->assertCount(1, $nodes[2]); $this->assertEquals('node121', $nodes[2][0]->getData()); } } ?> PK!e*Structures_Graph/tests/AcyclicTestTest.phpnu[addNode($node1); $node2 = new Structures_Graph_Node(); $graph->addNode($node2); $node1->connectTo($node2); $node3 = new Structures_Graph_Node(); $graph->addNode($node3); $node2->connectTo($node3); $node3->connectTo($node1); $this->assertFalse( Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph), 'Graph is cyclic' ); } public function testIsAcyclicTrue() { $graph = new Structures_Graph(); $node1 = new Structures_Graph_Node(); $graph->addNode($node1); $node2 = new Structures_Graph_Node(); $graph->addNode($node2); $node1->connectTo($node2); $node3 = new Structures_Graph_Node(); $graph->addNode($node3); $node2->connectTo($node3); $this->assertTrue( Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph), 'Graph is acyclic' ); } } ?> PK!Att!Structures_Graph/tests/helper.incnu[ $d) { if ($i++ > 0) { print ", "; } print $d[0] . '=' . $d[1]; } print "\n"; print "params: " . implode(", ", $non_opts) . "\n"; print "\n"; } test("-abc", "abc"); test("-abc foo", "abc"); test("-abc foo", "abc:"); test("-abc foo bar gazonk", "abc"); test("-abc foo bar gazonk", "abc:"); test("-a -b -c", "abc"); test("-a -b -c", "abc:"); test("-abc", "ab:c"); test("-abc foo -bar gazonk", "abc"); ?> --EXPECT-- options: a=, b=, c= params: options: a=, b=, c= params: foo options: a=, b=, c=foo params: options: a=, b=, c= params: foo, bar, gazonk options: a=, b=, c=foo params: bar, gazonk options: a=, b=, c= params: Console_Getopt: option requires an argument --c options: a=, b=c params: options: a=, b=, c= params: foo, -bar, gazonk PK!"Console_Getopt/tests/bug11068.phptnu[--TEST-- Console_Getopt [bug 11068] --SKIPIF-- --FILE-- getMessage()."\n"; echo 'FATAL'; exit; } print_r($ret); ?> --EXPECT-- Array ( [0] => Array ( [0] => Array ( [0] => f [1] => jjohnston@mail.com ) [1] => Array ( [0] => --to [1] => hi ) ) [1] => Array ( [0] => - ) )PK!"Console_Getopt/tests/bug10557.phptnu[--TEST-- Console_Getopt [bug 10557] --SKIPIF-- --FILE-- getMessage()."\n"; echo 'FATAL'; exit; } print_r($ret); ?> --EXPECT-- Console_Getopt: option requires an argument --to FATALPK!|EE"Console_Getopt/tests/bug13140.phptnu[--TEST-- Console_Getopt [bug 13140] --SKIPIF-- --FILE-- getopt2($cg->readPHPArgv(), 't', array('test'), true)); print_r($cg->getopt2($cg->readPHPArgv(), 'bar', array('foo'), true)); ?> --EXPECT-- Array ( [0] => Array ( [0] => Array ( [0] => --test [1] => ) ) [1] => Array ( [0] => thisshouldbehere ) ) Array ( [0] => Array ( [0] => Array ( [0] => --foo [1] => ) [1] => Array ( [0] => b [1] => ) [2] => Array ( [0] => a [1] => ) [3] => Array ( [0] => r [1] => ) [4] => Array ( [0] => r [1] => ) ) [1] => Array ( [0] => thisshouldbehere ) ) PK!e>44*XML_Util/tests/CreateTagFromArrayTests.phpnu[ "foo:bar", ); $expected = ""; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespace() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", ); $expected = ""; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributes() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), ); $expected = ""; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContent() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $expected = "I'm inside the tag"; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndAttributesAndContent() { $original = array( "qname" => "foo:bar", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $expected = "I'm inside the tag"; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndContent() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "content" => "I'm inside the tag", ); $expected = "I'm inside the tag"; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithEntitiesNone() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $expected = "I'm inside the tag"; $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_ENTITIES_NONE)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntities() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $expected = "I'm inside the tag"; $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineFalse() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $multiline = false; $expected = "I'm inside the tag"; $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrue() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $multiline = true; $expected = <<< EOF I'm inside the tag EOF; $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndent() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $multiline = true; $indent = " "; $expected = <<< EOF I'm inside the tag EOF; $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreak() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $multiline = true; $indent = " "; $linebreak = "^"; $expected = "I'm inside the tag"; $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesTrue() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = true; $expected = "I'm inside the tag"; $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameAndNamespaceAndAttributesAndContentWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesFalse() { $original = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = false; $expected = "I'm inside the tag"; $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithInvalidArray() { $badArray = array( "foo" => "bar", ); $expectedError = "You must either supply a qualified name (qname) or local tag name (localPart)."; $this->assertEquals($expectedError, XML_Util::createTagFromArray($badArray)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithNamespaceAndAttributesAndContentButWithoutQname() { $original = array( "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $expectedError = "You must either supply a qualified name (qname) or local tag name (localPart)."; $this->assertEquals($expectedError, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithNonScalarContent() { $badArray = array( 'content' => array('foo', 'bar'), ); $expectedError = "Supplied non-scalar value as tag content"; $this->assertEquals($expectedError, XML_Util::createTagFromArray($badArray)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithArrayOfNamespaces() { $original = array( 'qname' => 'foo:bar', 'namespaces' => array('ns1' => 'uri1', 'ns2' => 'uri2'), ); $expected = ""; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameDerivedFromNamespaceUriAndLocalPart() { $original = array( 'namespaceUri' => 'http://bar.org', 'localPart' => 'foo' ); $expected = ""; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameDerivedFromNamespaceAndLocalPart() { $original = array( 'namespace' => 'http://foo.org', 'localPart' => 'bar' ); $expected = ""; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithQnameDerivedFromLocalPart() { $original = array( 'namespace' => '', 'localPart' => 'bar' ); $expected = ""; $this->assertEquals($expected, XML_Util::createTagFromArray($original)); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayWithImplicitlyEmptyContentAndCollapseNoneDoesNotCollapseTag() { $original = array('qname' => 'tag1'); $expected = ""; $actual = XML_Util::createTagFromArray( $original, XML_UTIL_REPLACE_ENTITIES, // default $replaceEntities false, // default $multiline '_auto', // default $indent "\n", // default $linebreak true, // default $sortAttributes XML_UTIL_COLLAPSE_NONE ); $this->assertEquals($expected, $actual); } /** * @covers XML_Util::createTagFromArray() */ public function testCreateTagFromArrayForCdataWithExplicitlyEmptyContentDoesNotCollapseTag() { $original = array('qname' => 'tag1', 'content' => ''); $expected = ""; $this->assertEquals($expected, XML_Util::createTagFromArray($original, XML_UTIL_CDATA_SECTION)); } } PK!C'XML_Util/tests/ReplaceEntitiesTests.phpnu[.'; } protected function getUtf8Data() { return 'This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê'; } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForSimpleData() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData())); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForSimpleDataWithInvalidOptionReturnsOriginalData() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), 'INVALID_OPTION')); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForSimpleDataWithEntitiesXml() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML)); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForSimpleDataWithEntitiesXmlAndEncoding() { $encoding = "UTF-8"; $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML, $encoding)); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForUtf8DataWithEntitiesXmlAndEncoding() { $encoding = "UTF-8"; $expected = "This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê"; $this->assertEquals($expected, XML_Util::replaceEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML, $encoding)); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForSimpleDataWithEntitiesXmlRequired() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED)); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForSimpleDataWithEntitiesXmlRequiredAndEncoding() { $encoding = "UTF-8"; $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding)); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForUtf8DataWithEntitiesXmlRequiredAndEncoding() { $encoding = "UTF-8"; $expected = "This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê"; $this->assertEquals($expected, XML_Util::replaceEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding)); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForSimpleDataWithEntitiesHtml() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML)); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForSimpleDataWithEntitiesHtmlAndEncoding() { $encoding = "UTF-8"; $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::replaceEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML, $encoding)); } /** * @covers XML_Util::replaceEntities() */ public function testReplaceEntitiesForUtf8DataWithEntitiesHtmlAndEncoding() { $encoding = "UTF-8"; $expected = "This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê"; $this->assertEquals($expected, XML_Util::replaceEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_HTML, $encoding)); } } PK!یu"XML_Util/tests/ApiVersionTests.phpnu[assertEquals('1.4', XML_Util::apiVersion()); } }PK!GsXML_Util/tests/Bug5392Tests.phpnu[, & and " as well as ä, ö, ß, à and ê'; $replacedResult = XML_Util::replaceEntities($original, XML_UTIL_ENTITIES_HTML, "UTF-8"); $reversedResult = XML_Util::reverseEntities($replacedResult, XML_UTIL_ENTITIES_HTML, "UTF-8"); $this->assertEquals($original, $reversedResult, "Failed bugcheck."); } } PK!4ejj*XML_Util/tests/CreateCDataSectionTests.phpnu["; $this->assertEquals($expected, XML_Util::createCDataSection($original)); } } PK!|\5)XML_Util/tests/CollapseEmptyTagsTests.phpnu["; $expected = ""; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsBasicUsageAlongsideNonemptyTag() { $emptyTag = ""; $otherTag = "baz"; $expected = "baz"; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyTagWithCollapseAll() { $emptyTag = ""; $expected = ""; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_ALL)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagWithCollapseAll() { $emptyTag = ""; $otherTag = "baz"; $expected = "baz"; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag, XML_UTIL_COLLAPSE_ALL)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagAlongsideEmptyTagWithCollapseAll() { $emptyTag = ""; $otherTag = "baz"; $expected = "baz"; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag . $emptyTag, XML_UTIL_COLLAPSE_ALL)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyPrefixedTagAlongsideNonemptyTagAlongsideEmptyPrefixedTagWithCollapseAll() { $emptyTag = ""; $otherTag = "baz"; $expected = "baz"; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag . $emptyTag, XML_UTIL_COLLAPSE_ALL)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyNsPrefixedTagAlongsideNonemptyTagAlongsideEmptyNsPrefixedTagWithCollapseAll() { $emptyTag = ""; $otherTag = "baz"; $expected = "baz"; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag . $emptyTag, XML_UTIL_COLLAPSE_ALL)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyTagWithCollapseXhtml() { $emptyTag = ""; $expected = ""; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_XHTML_ONLY)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagWithCollapseXhtml() { $emptyTag = ""; $otherTag = "baz"; $xhtmlTag = "

"; $expected = "
baz"; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $xhtmlTag . $otherTag, XML_UTIL_COLLAPSE_XHTML_ONLY)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyTagWithCollapseNone() { $emptyTag = ""; $expected = ""; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_NONE)); } /** * @covers XML_Util::collapseEmptyTags() */ public function testCollapseEmptyTagsOnOneEmptyTagAlongsideNonemptyTagWithCollapseNone() { $emptyTag = ""; $otherTag = "baz"; $expected = "baz"; $this->assertEquals($expected, XML_Util::collapseEmptyTags($emptyTag . $otherTag, XML_UTIL_COLLAPSE_NONE)); } } PK!GG*XML_Util/tests/SplitQualifiedNameTests.phpnu[ 'xslt', 'localPart' => 'stylesheet', ); $this->assertEquals($expected, XML_Util::splitQualifiedName($original)); } /** * @covers XML_Util::splitQualifiedName() */ public function testSplitQualifiedNameWithNamespace() { $original = "stylesheet"; $namespace = "myNs"; $expected = array( 'namespace' => 'myNs', 'localPart' => 'stylesheet', ); $this->assertEquals($expected, XML_Util::splitQualifiedName($original, $namespace)); } } PK!Yq XML_Util/tests/Bug21184Tests.phpnu[one'; $this->assertEquals($xml, XML_Util::collapseEmptyTags($xml, XML_UTIL_COLLAPSE_ALL)); } } PK!>MXML_Util/tests/Bug4950Tests.phpnu[ here!"; $namespaceUrl = null; $expected = " here!]]>"; $result = XML_Util::createTag($qname, $attributes, $content, $namespaceUrl, XML_UTIL_CDATA_SECTION); $this->assertEquals($expected, $result, "Failed bugcheck."); } } PK!YR""*XML_Util/tests/CreateStartElementTests.phpnu["; $this->assertEquals($expected, XML_Util::createStartElement($original)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributes() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $expected = ""; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithEmptyAttributes() { $originalTag = "myNs:myTag"; $originalAttributes = ""; $expected = ""; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespace() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = ""; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithEmptyAttributesAndNonUriNamespace() { $originalTag = "myTag"; $originalAttributes = ""; $originalNamespace = "foo"; $expected = ""; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultiline() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = <<< EOF EOF; $multiline = true; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndent() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = <<< EOF EOF; $multiline = true; $indent = " "; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndentAndLinebreak() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = ""; $multiline = true; $indent = " "; $linebreak = "^"; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent, $linebreak)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndentAndLinebreakAndSortAttributesIsTrue() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar", "boo" => "baz"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = ""; $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = true; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent, $linebreak, $sortAttributes)); } /** * @covers XML_Util::createStartElement() */ public function testCreateStartElementForTagWithAttributesAndNamespaceWithMultilineAndIndentAndLinebreakAndSortAttributesIsFalse() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar", "boo" => "baz"); $originalNamespace = "http://www.w3c.org/myNs#"; $expected = ""; $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = false; $this->assertEquals($expected, XML_Util::createStartElement($originalTag, $originalAttributes, $originalNamespace, $multiline, $indent, $linebreak, $sortAttributes)); } } PK!ܬ$-XML_Util/tests/GetDocTypeDeclarationTests.phpnu["; $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag")); } /** * @covers XML_Util::getDocTypeDeclaration() */ public function testGetDocTypeDeclarationUsingRootAndStringUri() { $expected = ""; $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag", "myDocType.dtd")); } /** * @covers XML_Util::getDocTypeDeclaration() */ public function testGetDocTypeDeclarationUsingRootAndArrayUri() { $uri = array( 'uri' => 'http://pear.php.net/dtd/package-1.0', 'id' => '-//PHP//PEAR/DTD PACKAGE 0.1' ); $expected = ""; $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag", $uri)); } /** * @covers XML_Util::getDocTypeDeclaration() */ public function testGetDocTypeDeclarationUsingRootAndArrayUriAndInternalDtd() { $uri = array( 'uri' => 'http://pear.php.net/dtd/package-1.0', 'id' => '-//PHP//PEAR/DTD PACKAGE 0.1' ); $dtdEntry = ''; $expected = <<< EOF ]> EOF; $this->assertEquals($expected, XML_Util::getDocTypeDeclaration("rootTag", $uri, $dtdEntry)); } } PK!G XML_Util/tests/Bug21177Tests.phpnu['; return array( array('', ''), array('', ''), array('', ''), array('', ''), ); } /** * @dataProvider getTestCandidate() */ public function testCollapseEmptyTagsForBug21177($original, $expected) { $this->assertEquals($expected, XML_Util::collapseEmptyTags($original, XML_UTIL_COLLAPSE_ALL), "Failed bugcheck."); } } PK!۩ XML_Util/tests/Bug18343Tests.phpnu[ "install", "attributes" => array( "as" => "Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&s=Newsweek", "name" => "test/Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&s=Newsweek", ) ); public function getFlagsToTest() { new XML_Util(); // for constants to be declared return array( array('no flag', null), array('false', false), array('ENTITIES_NONE', XML_UTIL_ENTITIES_NONE), array('ENTITIES_XML', XML_UTIL_ENTITIES_XML), array('ENTITIES_XML_REQUIRED', XML_UTIL_ENTITIES_XML_REQUIRED), array('ENTITIES_HTML', XML_UTIL_ENTITIES_HTML), array('REPLACE_ENTITIES', XML_UTIL_REPLACE_ENTITIES), ); } /** * @dataProvider getFlagsToTest() */ public function testCreateTagFromArrayForBug18343($key, $flag) { // all flags for the candidate input should return the same result $expected = <<< EOF EOF; $this->assertEquals($expected, XML_Util::createTagFromArray($this->tagArray, $flag), "Failed bugcheck for $key."); } } PK!zt'XML_Util/tests/ReverseEntitiesTests.phpnu[."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData())); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithInvalidOptionReturnsOriginalData() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), 'INVALID_OPTION')); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesXml() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesXmlAndEncoding() { $encoding = "UTF-8"; $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML), $encoding); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForUtf8DataWithEntitiesXmlAndEncoding() { $encoding = "UTF-8"; $expected = "This data contains special chars like <, >, & and \" as well as ä, ö, ß, à and ê"; $this->assertEquals($expected, XML_Util::reverseEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML), $encoding); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesXmlRequired() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesXmlRequiredAndEncoding() { $encoding = "UTF-8"; $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForUtf8DataWithEntitiesXmlRequiredAndEncoding() { $encoding = "UTF-8"; $expected = "This data contains special chars like <, >, & and \" as well as ä, ö, ß, à and ê"; $this->assertEquals($expected, XML_Util::reverseEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_XML_REQUIRED, $encoding)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesHtml() { $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForSimpleDataWithEntitiesHtmlAndEncoding() { $encoding = "UTF-8"; $expected = "This string contains < & >."; $this->assertEquals($expected, XML_Util::reverseEntities($this->getSimpleData(), XML_UTIL_ENTITIES_HTML, $encoding)); } /** * @covers XML_Util::reverseEntities() */ public function testReverseEntitiesForUtf8DataWithEntitiesHtmlAndEncoding() { $encoding = "UTF-8"; $expected = "This data contains special chars like <, >, & and \" as well as ä, ö, ß, à and ê"; $this->assertEquals($expected, XML_Util::reverseEntities($this->getUtf8Data(), XML_UTIL_ENTITIES_HTML, $encoding)); } } PK!~$[ee(XML_Util/tests/CreateEndElementTests.phpnu["; $this->assertEquals($expected, XML_Util::createEndElement($original)); } /** * @covers XML_Util::createEndElement() */ public function testCreateEndElementWithNamespacedTag() { $original = "myNs:myTag"; $expected = ""; $this->assertEquals($expected, XML_Util::createEndElement($original)); } } PK!!$XML_Util/tests/AbstractUnitTests.phpnu[ "bar"); $expected = ""; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContent() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag"; $expected = "This is inside the tag"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespace() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag"; $originalNamespace = "http://www.w3c.org/myNs#"; $expected = "This is inside the tag"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithCDataSection() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $expected = " in it]]>"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_CDATA_SECTION)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntities() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineFalse() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = false; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrue() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $expected = <<< EOF This is inside the tag and has < & @ > in it EOF; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndent() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $indent = " "; $expected = <<< EOF This is inside the tag and has < & @ > in it EOF; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreak() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $indent = " "; $linebreak = "^"; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesTrue() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar", "boo" => "baz"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = true; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes)); } /** * @covers XML_Util::createTag() */ public function testCreateTagForTagWithAttributesAndContentAndNamespaceWithReplaceEntitiesAndMultilineTrueAndIndentAndLinebreakAndSortAttributesFalse() { $originalTag = "myNs:myTag"; $originalAttributes = array("foo" => "bar", "boo" => "baz"); $originalContent = "This is inside the tag and has < & @ > in it"; $originalNamespace = "http://www.w3c.org/myNs#"; $multiline = true; $indent = " "; $linebreak = "^"; $sortAttributes = false; $expected = "This is inside the tag and has < & @ > in it"; $this->assertEquals($expected, XML_Util::createTag($originalTag, $originalAttributes, $originalContent, $originalNamespace, XML_UTIL_REPLACE_ENTITIES, $multiline, $indent, $linebreak, $sortAttributes)); } } PK!Df:)XML_Util/tests/GetXmlDeclarationTests.phpnu["; $this->assertEquals($expected, XML_Util::getXMLDeclaration($version)); } /** * @covers XML_Util::getXMLDeclaration() */ public function testGetXMLDeclarationUsingVersionAndEncodingAndStandalone() { $version = "1.0"; $encoding = "UTF-8"; $standalone = true; $expected = ""; $this->assertEquals($expected, XML_Util::getXMLDeclaration($version, $encoding, $standalone)); } /** * @covers XML_Util::getXMLDeclaration() */ public function testGetXMLDeclarationUsingVersionAndStandalone() { $version = "1.0"; $encoding = null; $standalone = true; $expected = ""; $this->assertEquals($expected, XML_Util::getXMLDeclaration($version, $encoding, $standalone)); } } PK!Zt*XML_Util/tests/AttributesToStringTests.phpnu[ 'bar','boo' => 'baz',); $expected = " boo=\"baz\" foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithExplicitSortTrue() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " boo=\"baz\" foo=\"bar\""; $sort = true; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithExplicitSortFalse() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " foo=\"bar\" boo=\"baz\""; $sort = false; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithMultilineFalse() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " boo=\"baz\" foo=\"bar\""; $sort = true; $multiline = false; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithMultilineTrue() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = <<< EOF boo="baz" foo="bar" EOF; $sort = true; $multiline = true; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithExplicitIndent() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " boo=\"baz\"\n foo=\"bar\""; $sort = true; $multiline = true; $indent = ' '; // 8 spaces $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $indent)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithExplicitLinebreak() { $original = array('foo' => 'bar','boo' => 'baz',); $expected = " boo=\"baz\"\n^foo=\"bar\""; $sort = true; $multiline = true; $linebreak = '^'; // some dummy character $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithOptionsThatIncludesSort() { $original = array('foo' => 'bar','boo' => 'baz',); $options = array( 'multiline' => true, 'indent' => '----', 'linebreak' => "^", 'entities' => XML_UTIL_ENTITIES_XML, 'sort' => true, ); $expected = " boo=\"baz\"\n----foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original, $options)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithOptionsThatExcludesSort() { $original = array('foo' => 'bar','boo' => 'baz',); $options = array( 'multiline' => true, 'indent' => '----', 'linebreak' => "^", 'entities' => XML_UTIL_ENTITIES_XML, ); $expected = " boo=\"baz\"\n----foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original, $options)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithEntitiesNone() { $original = array("foo" => "b@&r", "boo" => "b>assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_NONE)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithEntitiesXml() { $original = array("foo" => "b@&r", "boo" => "b>assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_XML)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithEntitiesXmlRequired() { $original = array("foo" => "b@&r", "boo" => "b><z\" foo=\"b@&r\""; $sort = true; $multiline = false; $linebreak = ' '; $this->assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_XML_REQUIRED)); } /** * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithEntitiesHtml() { $original = array("foo" => "b@&r", "boo" => "b>assertEquals($expected, XML_Util::attributesToString($original, $sort, $multiline, $linebreak, PHP_EOL, XML_UTIL_ENTITIES_HTML)); } /** * Tag attributes should not be treated as CDATA, * so the operation will instead quietly use XML_UTIL_ENTITIES_XML. * * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithCDataSectionForSingleAttribute() { $original = array('foo' => 'bar'); // need exactly one attribute here $options = array( 'sort' => true, // doesn't matter for this testcase 'multiline' => false, // doesn't matter for this testcase 'indent' => null, // doesn't matter for this testcase 'linebreak' => null, // doesn't matter for this testcase 'entities' => XML_UTIL_CDATA_SECTION, // DOES matter for this testcase ); $expected = " foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original, $options)); } /** * Tag attributes should not be treated as CDATA, * so the operation will instead quietly use XML_UTIL_ENTITIES_XML. * * @covers XML_Util::attributesToString() */ public function testAttributesToStringWithCDataSectionForMultipleAttributesAndMultilineFalse() { $original = array('foo' => 'bar', 'boo' => 'baz'); // need more than one attribute here $options = array( 'sort' => true, // doesn't matter for this testcase 'multiline' => false, // DOES matter for this testcase, must be false 'indent' => null, // doesn't matter for this testcase 'linebreak' => null, // doesn't matter for this testcase 'entities' => XML_UTIL_CDATA_SECTION, // DOES matter for this testcase ); $expected = " boo=\"baz\" foo=\"bar\""; $this->assertEquals($expected, XML_Util::attributesToString($original, $options)); } } PK!ݑh#XML_Util/tests/IsValidNameTests.phpnu[assertTrue($result); } /** * @covers XML_Util::isValidName() */ public function testIsValidNameForTagNameWithInvalidCharacter() { $tagName = "invalidTag?"; $result = XML_Util::isValidName($tagName); $this->assertInstanceOf('PEAR_Error', $result); $expectedError = "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores"; $this->assertEquals($expectedError, $result->getMessage()); } /** * @covers XML_Util::isValidName() */ public function testIsValidNameForTagNameWithInvalidStartingCharacter() { $tagName = "1234five"; $result = XML_Util::isValidName($tagName); $this->assertInstanceOf('PEAR_Error', $result); $expectedError = "XML names may only start with letter or underscore"; $this->assertEquals($expectedError, $result->getMessage()); } /** * @covers XML_Util::isValidName() */ public function testIsValidNameForInt() { $tagName = 1; $result = XML_Util::isValidName($tagName); $this->assertInstanceOf('PEAR_Error', $result); $expectedError = "XML names may only start with letter or underscore"; $this->assertEquals($expectedError, $result->getMessage()); } /** * @covers XML_Util::isValidName() */ public function testIsValidNameForEmptyString() { $tagName = ''; $result = XML_Util::isValidName($tagName); $this->assertInstanceOf('PEAR_Error', $result); $expectedError = "XML names may only start with letter or underscore"; $this->assertEquals($expectedError, $result->getMessage()); } } PK!TT%XML_Util/tests/CreateCommentTests.phpnu["; $this->assertEquals($expected, XML_Util::createComment($original)); } } PK!rv"XML_Util/tests/RaiseErrorTests.phpnu[assertInstanceOf('PEAR_Error', $error); $this->assertEquals($message, $error->getMessage()); $this->assertEquals($code, $error->getCode()); } } PK! Xxo -Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Logger; use Psr\Log\LoggerInterface; use Symfony\Component\Stopwatch\Stopwatch; use Doctrine\DBAL\Logging\SQLLogger; /** * DbalLogger. * * @author Fabien Potencier */ class DbalLogger implements SQLLogger { const MAX_STRING_LENGTH = 32; const BINARY_DATA_VALUE = '(binary value)'; protected $logger; protected $stopwatch; /** * Constructor. * * @param LoggerInterface $logger A LoggerInterface instance * @param Stopwatch $stopwatch A Stopwatch instance */ public function __construct(LoggerInterface $logger = null, Stopwatch $stopwatch = null) { $this->logger = $logger; $this->stopwatch = $stopwatch; } /** * {@inheritdoc} */ public function startQuery($sql, array $params = null, array $types = null) { if (null !== $this->stopwatch) { $this->stopwatch->start('doctrine', 'doctrine'); } if (is_array($params)) { foreach ($params as $index => $param) { if (!is_string($params[$index])) { continue; } // non utf-8 strings break json encoding if (!preg_match('#[\p{L}\p{N} ]#u', $params[$index])) { $params[$index] = self::BINARY_DATA_VALUE; continue; } // detect if the too long string must be shorten if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($params[$index])) { if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], $encoding)) { $params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, $encoding).' [...]'; continue; } } else { if (self::MAX_STRING_LENGTH < strlen($params[$index])) { $params[$index] = substr($params[$index], 0, self::MAX_STRING_LENGTH - 6).' [...]'; continue; } } } } if (null !== $this->logger) { $this->log($sql, null === $params ? array() : $params); } } /** * {@inheritdoc} */ public function stopQuery() { if (null !== $this->stopwatch) { $this->stopwatch->stop('doctrine'); } } /** * Logs a message. * * @param string $message A message to log * @param array $params The context */ protected function log($message, array $params) { $this->logger->debug($message, $params); } } PK!eOO&Symfony/Bridge/Doctrine/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\CacheWarmer; use Doctrine\Common\Persistence\ManagerRegistry; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; /** * The proxy generator cache warmer generates all entity proxies. * * In the process of generating proxies the cache for all the metadata is primed also, * since this information is necessary to build the proxies in the first place. * * @author Benjamin Eberlei */ class ProxyCacheWarmer implements CacheWarmerInterface { private $registry; /** * Constructor. * * @param ManagerRegistry $registry A ManagerRegistry instance */ public function __construct(ManagerRegistry $registry) { $this->registry = $registry; } /** * This cache warmer is not optional, without proxies fatal error occurs! * * @return false */ public function isOptional() { return false; } /** * {@inheritdoc} */ public function warmUp($cacheDir) { foreach ($this->registry->getManagers() as $em) { // we need the directory no matter the proxy cache generation strategy if (!is_dir($proxyCacheDir = $em->getConfiguration()->getProxyDir())) { if (false === @mkdir($proxyCacheDir, 0777, true)) { throw new \RuntimeException(sprintf('Unable to create the Doctrine Proxy directory "%s".', $proxyCacheDir)); } } elseif (!is_writable($proxyCacheDir)) { throw new \RuntimeException(sprintf('The Doctrine Proxy directory "%s" is not writeable for the current system user.', $proxyCacheDir)); } // if proxies are autogenerated we don't need to generate them in the cache warmer if ($em->getConfiguration()->getAutoGenerateProxyClasses()) { continue; } $classes = $em->getMetadataFactory()->getAllMetadata(); $em->getProxyFactory()->generateProxyClasses($classes); } } } PK! 9,5Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form; use Doctrine\Common\Persistence\ManagerRegistry; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\PropertyAccess\PropertyAccess; class DoctrineOrmExtension extends AbstractExtension { protected $registry; public function __construct(ManagerRegistry $registry) { $this->registry = $registry; } protected function loadTypes() { return array( new Type\EntityType($this->registry, PropertyAccess::createPropertyAccessor()), ); } protected function loadTypeGuesser() { return new DoctrineOrmTypeGuesser($this->registry); } } PK!0NSymfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\EventListener; use Doctrine\Common\Collections\Collection; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Merge changes from the request to a Doctrine\Common\Collections\Collection instance. * * This works with ORM, MongoDB and CouchDB instances of the collection interface. * * @author Bernhard Schussek * * @see Doctrine\Common\Collections\Collection */ class MergeDoctrineCollectionListener implements EventSubscriberInterface { public static function getSubscribedEvents() { // Higher priority than core MergeCollectionListener so that this one // is called before return array(FormEvents::SUBMIT => array('onBind', 10)); } public function onBind(FormEvent $event) { $collection = $event->getForm()->getData(); $data = $event->getData(); // If all items were removed, call clear which has a higher // performance on persistent collections if ($collection instanceof Collection && count($data) === 0) { $collection->clear(); } } } PK!!%d==ASymfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\ChoiceList; /** * Custom loader for entities in the choice list. * * @author Benjamin Eberlei */ interface EntityLoaderInterface { /** * Returns an array of entities that are valid choices in the corresponding choice list. * * @return array The entities. */ public function getEntities(); /** * Returns an array of entities matching the given identifiers. * * @param string $identifier The identifier field of the object. This method * is not applicable for fields with multiple * identifiers. * @param array $values The values of the identifiers. * * @return array The entities. */ public function getEntitiesByIds($identifier, array $values); } PK! ?x77<Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\ChoiceList; use Symfony\Component\Form\Exception\RuntimeException; use Symfony\Component\Form\Exception\StringCastException; use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; /** * A choice list presenting a list of Doctrine entities as choices * * @author Bernhard Schussek */ class EntityChoiceList extends ObjectChoiceList { /** * @var ObjectManager */ private $em; /** * @var string */ private $class; /** * @var \Doctrine\Common\Persistence\Mapping\ClassMetadata */ private $classMetadata; /** * Contains the query builder that builds the query for fetching the * entities * * This property should only be accessed through queryBuilder. * * @var EntityLoaderInterface */ private $entityLoader; /** * The identifier field, if the identifier is not composite * * @var array */ private $idField = null; /** * Whether to use the identifier for index generation * * @var Boolean */ private $idAsIndex = false; /** * Whether to use the identifier for value generation * * @var Boolean */ private $idAsValue = false; /** * Whether the entities have already been loaded. * * @var Boolean */ private $loaded = false; /** * The preferred entities. * * @var array */ private $preferredEntities = array(); /** * Creates a new entity choice list. * * @param ObjectManager $manager An EntityManager instance * @param string $class The class name * @param string $labelPath The property path used for the label * @param EntityLoaderInterface $entityLoader An optional query builder * @param array $entities An array of choices * @param array $preferredEntities An array of preferred choices * @param string $groupPath A property path pointing to the property used * to group the choices. Only allowed if * the choices are given as flat array. * @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths. */ public function __construct(ObjectManager $manager, $class, $labelPath = null, EntityLoaderInterface $entityLoader = null, $entities = null, array $preferredEntities = array(), $groupPath = null, PropertyAccessorInterface $propertyAccessor = null) { $this->em = $manager; $this->entityLoader = $entityLoader; $this->classMetadata = $manager->getClassMetadata($class); $this->class = $this->classMetadata->getName(); $this->loaded = is_array($entities) || $entities instanceof \Traversable; $this->preferredEntities = $preferredEntities; $identifier = $this->classMetadata->getIdentifierFieldNames(); if (1 === count($identifier)) { $this->idField = $identifier[0]; $this->idAsValue = true; if (in_array($this->classMetadata->getTypeOfField($this->idField), array('integer', 'smallint', 'bigint'))) { $this->idAsIndex = true; } } if (!$this->loaded) { // Make sure the constraints of the parent constructor are // fulfilled $entities = array(); } parent::__construct($entities, $labelPath, $preferredEntities, $groupPath, null, $propertyAccessor); } /** * Returns the list of entities * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getChoices() { if (!$this->loaded) { $this->load(); } return parent::getChoices(); } /** * Returns the values for the entities * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getValues() { if (!$this->loaded) { $this->load(); } return parent::getValues(); } /** * Returns the choice views of the preferred choices as nested array with * the choice groups as top-level keys. * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getPreferredViews() { if (!$this->loaded) { $this->load(); } return parent::getPreferredViews(); } /** * Returns the choice views of the choices that are not preferred as nested * array with the choice groups as top-level keys. * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getRemainingViews() { if (!$this->loaded) { $this->load(); } return parent::getRemainingViews(); } /** * Returns the entities corresponding to the given values. * * @param array $values * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getChoicesForValues(array $values) { // Performance optimization // Also prevents the generation of "WHERE id IN ()" queries through the // entity loader. At least with MySQL and on the development machine // this was tested on, no exception was thrown for such invalid // statements, consequently no test fails when this code is removed. // https://github.com/symfony/symfony/pull/8981#issuecomment-24230557 if (empty($values)) { return array(); } if (!$this->loaded) { // Optimize performance in case we have an entity loader and // a single-field identifier if ($this->idAsValue && $this->entityLoader) { $unorderedEntities = $this->entityLoader->getEntitiesByIds($this->idField, $values); $entitiesByValue = array(); $entities = array(); // Maintain order and indices from the given $values // An alternative approach to the following loop is to add the // "INDEX BY" clause to the Doctrine query in the loader, // but I'm not sure whether that's doable in a generic fashion. foreach ($unorderedEntities as $entity) { $value = $this->fixValue(current($this->getIdentifierValues($entity))); $entitiesByValue[$value] = $entity; } foreach ($values as $i => $value) { if (isset($entitiesByValue[$value])) { $entities[$i] = $entitiesByValue[$value]; } } return $entities; } $this->load(); } return parent::getChoicesForValues($values); } /** * Returns the values corresponding to the given entities. * * @param array $entities * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getValuesForChoices(array $entities) { // Performance optimization if (empty($entities)) { return array(); } if (!$this->loaded) { // Optimize performance for single-field identifiers. We already // know that the IDs are used as values // Attention: This optimization does not check choices for existence if ($this->idAsValue) { $values = array(); foreach ($entities as $i => $entity) { if ($entity instanceof $this->class) { // Make sure to convert to the right format $values[$i] = $this->fixValue(current($this->getIdentifierValues($entity))); } } return $values; } $this->load(); } return parent::getValuesForChoices($entities); } /** * Returns the indices corresponding to the given entities. * * @param array $entities * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $entities) { // Performance optimization if (empty($entities)) { return array(); } if (!$this->loaded) { // Optimize performance for single-field identifiers. We already // know that the IDs are used as indices // Attention: This optimization does not check choices for existence if ($this->idAsIndex) { $indices = array(); foreach ($entities as $i => $entity) { if ($entity instanceof $this->class) { // Make sure to convert to the right format $indices[$i] = $this->fixIndex(current($this->getIdentifierValues($entity))); } } return $indices; } $this->load(); } return parent::getIndicesForChoices($entities); } /** * Returns the entities corresponding to the given values. * * @param array $values * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { // Performance optimization if (empty($values)) { return array(); } if (!$this->loaded) { // Optimize performance for single-field identifiers. // Attention: This optimization does not check values for existence if ($this->idAsIndex && $this->idAsValue) { return $this->fixIndices($values); } $this->load(); } return parent::getIndicesForValues($values); } /** * Creates a new unique index for this entity. * * If the entity has a single-field identifier, this identifier is used. * * Otherwise a new integer is generated. * * @param mixed $entity The choice to create an index for * * @return integer|string A unique index containing only ASCII letters, * digits and underscores. */ protected function createIndex($entity) { if ($this->idAsIndex) { return $this->fixIndex(current($this->getIdentifierValues($entity))); } return parent::createIndex($entity); } /** * Creates a new unique value for this entity. * * If the entity has a single-field identifier, this identifier is used. * * Otherwise a new integer is generated. * * @param mixed $entity The choice to create a value for * * @return integer|string A unique value without character limitations. */ protected function createValue($entity) { if ($this->idAsValue) { return (string) current($this->getIdentifierValues($entity)); } return parent::createValue($entity); } /** * {@inheritdoc} */ protected function fixIndex($index) { $index = parent::fixIndex($index); // If the ID is a single-field integer identifier, it is used as // index. Replace any leading minus by underscore to make it a valid // form name. if ($this->idAsIndex && $index < 0) { $index = strtr($index, '-', '_'); } return $index; } /** * Loads the list with entities. */ private function load() { if ($this->entityLoader) { $entities = $this->entityLoader->getEntities(); } else { $entities = $this->em->getRepository($this->class)->findAll(); } try { // The second parameter $labels is ignored by ObjectChoiceList parent::initialize($entities, array(), $this->preferredEntities); } catch (StringCastException $e) { throw new StringCastException(str_replace('argument $labelPath', 'option "property"', $e->getMessage()), null, $e); } $this->loaded = true; } /** * Returns the values of the identifier fields of an entity. * * Doctrine must know about this entity, that is, the entity must already * be persisted or added to the identity map before. Otherwise an * exception is thrown. * * @param object $entity The entity for which to get the identifier * * @return array The identifier values * * @throws RuntimeException If the entity does not exist in Doctrine's identity map */ private function getIdentifierValues($entity) { if (!$this->em->contains($entity)) { throw new RuntimeException( 'Entities passed to the choice field must be managed. Maybe ' . 'persist them in the entity manager?' ); } $this->em->initializeObject($entity); return $this->classMetadata->getIdentifierValues($entity); } } PK!GCt ASymfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\ChoiceList; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Doctrine\ORM\QueryBuilder; use Doctrine\DBAL\Connection; use Doctrine\ORM\EntityManager; /** * Getting Entities through the ORM QueryBuilder */ class ORMQueryBuilderLoader implements EntityLoaderInterface { /** * Contains the query builder that builds the query for fetching the * entities * * This property should only be accessed through queryBuilder. * * @var QueryBuilder */ private $queryBuilder; /** * Construct an ORM Query Builder Loader * * @param QueryBuilder|\Closure $queryBuilder * @param EntityManager $manager * @param string $class * * @throws UnexpectedTypeException */ public function __construct($queryBuilder, $manager = null, $class = null) { // If a query builder was passed, it must be a closure or QueryBuilder // instance if (!($queryBuilder instanceof QueryBuilder || $queryBuilder instanceof \Closure)) { throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder or \Closure'); } if ($queryBuilder instanceof \Closure) { if (!$manager instanceof EntityManager) { throw new UnexpectedTypeException($manager, 'Doctrine\ORM\EntityManager'); } $queryBuilder = $queryBuilder($manager->getRepository($class)); if (!$queryBuilder instanceof QueryBuilder) { throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder'); } } $this->queryBuilder = $queryBuilder; } /** * {@inheritDoc} */ public function getEntities() { return $this->queryBuilder->getQuery()->execute(); } /** * {@inheritDoc} */ public function getEntitiesByIds($identifier, array $values) { $qb = clone ($this->queryBuilder); $alias = current($qb->getRootAliases()); $parameter = 'ORMQueryBuilderLoader_getEntitiesByIds_'.$identifier; $where = $qb->expr()->in($alias.'.'.$identifier, ':'.$parameter); // Guess type $entity = current($qb->getRootEntities()); $metadata = $qb->getEntityManager()->getClassMetadata($entity); if (in_array($metadata->getTypeOfField($identifier), array('integer', 'bigint', 'smallint'))) { $parameterType = Connection::PARAM_INT_ARRAY; } else { $parameterType = Connection::PARAM_STR_ARRAY; } return $qb->andWhere($where) ->getQuery() ->setParameter($parameter, $values, $parameterType) ->getResult(); } } PK!`. qpp7Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form; use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\Common\Persistence\Mapping\MappingException; use Doctrine\ORM\Mapping\MappingException as LegacyMappingException; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; use Symfony\Component\Form\Guess\ValueGuess; use Doctrine\Common\Util\ClassUtils; class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface { protected $registry; private $cache = array(); public function __construct(ManagerRegistry $registry) { $this->registry = $registry; } /** * {@inheritDoc} */ public function guessType($class, $property) { if (!$ret = $this->getMetadata($class)) { return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); } list($metadata, $name) = $ret; if ($metadata->hasAssociation($property)) { $multiple = $metadata->isCollectionValuedAssociation($property); $mapping = $metadata->getAssociationMapping($property); return new TypeGuess('entity', array('em' => $name, 'class' => $mapping['targetEntity'], 'multiple' => $multiple), Guess::HIGH_CONFIDENCE); } switch ($metadata->getTypeOfField($property)) { case 'array': return new TypeGuess('collection', array(), Guess::MEDIUM_CONFIDENCE); case 'boolean': return new TypeGuess('checkbox', array(), Guess::HIGH_CONFIDENCE); case 'datetime': case 'vardatetime': case 'datetimetz': return new TypeGuess('datetime', array(), Guess::HIGH_CONFIDENCE); case 'date': return new TypeGuess('date', array(), Guess::HIGH_CONFIDENCE); case 'time': return new TypeGuess('time', array(), Guess::HIGH_CONFIDENCE); case 'decimal': case 'float': return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE); case 'integer': case 'bigint': case 'smallint': return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE); case 'string': return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE); case 'text': return new TypeGuess('textarea', array(), Guess::MEDIUM_CONFIDENCE); default: return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); } } /** * {@inheritDoc} */ public function guessRequired($class, $property) { $classMetadatas = $this->getMetadata($class); if (!$classMetadatas) { return null; } /** @var ClassMetadataInfo $classMetadata */ $classMetadata = $classMetadatas[0]; // Check whether the field exists and is nullable or not if ($classMetadata->hasField($property)) { if (!$classMetadata->isNullable($property)) { return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } return new ValueGuess(false, Guess::MEDIUM_CONFIDENCE); } // Check whether the association exists, is a to-one association and its // join column is nullable or not if ($classMetadata->isAssociationWithSingleJoinColumn($property)) { $mapping = $classMetadata->getAssociationMapping($property); if (!isset($mapping['joinColumns'][0]['nullable'])) { // The "nullable" option defaults to true, in that case the // field should not be required. return new ValueGuess(false, Guess::HIGH_CONFIDENCE); } return new ValueGuess(!$mapping['joinColumns'][0]['nullable'], Guess::HIGH_CONFIDENCE); } return null; } /** * {@inheritDoc} */ public function guessMaxLength($class, $property) { $ret = $this->getMetadata($class); if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) { $mapping = $ret[0]->getFieldMapping($property); if (isset($mapping['length'])) { return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE); } if (in_array($ret[0]->getTypeOfField($property), array('decimal', 'float'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } } } /** * {@inheritDoc} */ public function guessPattern($class, $property) { $ret = $this->getMetadata($class); if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) { if (in_array($ret[0]->getTypeOfField($property), array('decimal', 'float'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } } } protected function getMetadata($class) { // normalize class name $class = ClassUtils::getRealClass(ltrim($class, '\\')); if (array_key_exists($class, $this->cache)) { return $this->cache[$class]; } $this->cache[$class] = null; foreach ($this->registry->getManagers() as $name => $em) { try { return $this->cache[$class] = array($em->getClassMetadata($class), $name); } catch (MappingException $e) { // not an entity or mapped super class } catch (LegacyMappingException $e) { // not an entity or mapped super class, using Doctrine ORM 2.2 } } } } PK!CiPPMSymfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\DataTransformerInterface; use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection; /** * @author Bernhard Schussek */ class CollectionToArrayTransformer implements DataTransformerInterface { /** * Transforms a collection into an array. * * @param Collection $collection A collection of entities * * @return mixed An array of entities * * @throws TransformationFailedException */ public function transform($collection) { if (null === $collection) { return array(); } // For cases when the collection getter returns $collection->toArray() // in order to prevent modifications of the returned collection if (is_array($collection)) { return $collection; } if (!$collection instanceof Collection) { throw new TransformationFailedException('Expected a Doctrine\Common\Collections\Collection object.'); } return $collection->toArray(); } /** * Transforms choice keys into entities. * * @param mixed $array An array of entities * * @return Collection A collection of entities */ public function reverseTransform($array) { if ('' === $array || null === $array) { $array = array(); } else { $array = (array) $array; } return new ArrayCollection($array); } } PK!憝0Symfony/Bridge/Doctrine/Form/Type/EntityType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\Type; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; class EntityType extends DoctrineType { /** * Return the default loader object. * * @param ObjectManager $manager * @param mixed $queryBuilder * @param string $class * @return ORMQueryBuilderLoader */ public function getLoader(ObjectManager $manager, $queryBuilder, $class) { return new ORMQueryBuilderLoader( $queryBuilder, $manager, $class ); } public function getName() { return 'entity'; } } PK!S;,:2Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\Type; use Doctrine\Common\Persistence\ManagerRegistry; use Symfony\Component\Form\Exception\RuntimeException; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList; use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface; use Symfony\Bridge\Doctrine\Form\EventListener\MergeDoctrineCollectionListener; use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; abstract class DoctrineType extends AbstractType { /** * @var ManagerRegistry */ protected $registry; /** * @var array */ private $choiceListCache = array(); /** * @var PropertyAccessorInterface */ private $propertyAccessor; public function __construct(ManagerRegistry $registry, PropertyAccessorInterface $propertyAccessor = null) { $this->registry = $registry; $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } public function buildForm(FormBuilderInterface $builder, array $options) { if ($options['multiple']) { $builder ->addEventSubscriber(new MergeDoctrineCollectionListener()) ->addViewTransformer(new CollectionToArrayTransformer(), true) ; } } public function setDefaultOptions(OptionsResolverInterface $resolver) { $choiceListCache =& $this->choiceListCache; $registry = $this->registry; $propertyAccessor = $this->propertyAccessor; $type = $this; $loader = function (Options $options) use ($type) { if (null !== $options['query_builder']) { return $type->getLoader($options['em'], $options['query_builder'], $options['class']); } return null; }; $choiceList = function (Options $options) use (&$choiceListCache, $propertyAccessor) { // Support for closures $propertyHash = is_object($options['property']) ? spl_object_hash($options['property']) : $options['property']; $choiceHashes = $options['choices']; // Support for recursive arrays if (is_array($choiceHashes)) { // A second parameter ($key) is passed, so we cannot use // spl_object_hash() directly (which strictly requires // one parameter) array_walk_recursive($choiceHashes, function (&$value) { $value = spl_object_hash($value); }); } elseif ($choiceHashes instanceof \Traversable) { $hashes = array(); foreach ($choiceHashes as $value) { $hashes[] = spl_object_hash($value); } $choiceHashes = $hashes; } $preferredChoiceHashes = $options['preferred_choices']; if (is_array($preferredChoiceHashes)) { array_walk_recursive($preferredChoiceHashes, function (&$value) { $value = spl_object_hash($value); }); } // Support for custom loaders (with query builders) $loaderHash = is_object($options['loader']) ? spl_object_hash($options['loader']) : $options['loader']; // Support for closures $groupByHash = is_object($options['group_by']) ? spl_object_hash($options['group_by']) : $options['group_by']; $hash = hash('sha256', json_encode(array( spl_object_hash($options['em']), $options['class'], $propertyHash, $loaderHash, $choiceHashes, $preferredChoiceHashes, $groupByHash ))); if (!isset($choiceListCache[$hash])) { $choiceListCache[$hash] = new EntityChoiceList( $options['em'], $options['class'], $options['property'], $options['loader'], $options['choices'], $options['preferred_choices'], $options['group_by'], $propertyAccessor ); } return $choiceListCache[$hash]; }; $emNormalizer = function (Options $options, $em) use ($registry) { /* @var ManagerRegistry $registry */ if (null !== $em) { return $registry->getManager($em); } $em = $registry->getManagerForClass($options['class']); if (null === $em) { throw new RuntimeException(sprintf( 'Class "%s" seems not to be a managed Doctrine entity. ' . 'Did you forget to map it?', $options['class'] )); } return $em; }; $resolver->setDefaults(array( 'em' => null, 'property' => null, 'query_builder' => null, 'loader' => $loader, 'choices' => null, 'choice_list' => $choiceList, 'group_by' => null, )); $resolver->setRequired(array('class')); $resolver->setNormalizers(array( 'em' => $emNormalizer, )); $resolver->setAllowedTypes(array( 'loader' => array('null', 'Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface'), )); } /** * Return the default loader object. * * @param ObjectManager $manager * @param mixed $queryBuilder * @param string $class * * @return EntityLoaderInterface */ abstract public function getLoader(ObjectManager $manager, $queryBuilder, $class); public function getParent() { return 'choice'; } } PK!W&v<Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Security\User; use Doctrine\Common\Persistence\ManagerRegistry; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; /** * Wrapper around a Doctrine ObjectManager. * * Provides easy to use provisioning for Doctrine entity users. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class EntityUserProvider implements UserProviderInterface { private $class; private $repository; private $property; private $metadata; public function __construct(ManagerRegistry $registry, $class, $property = null, $managerName = null) { $em = $registry->getManager($managerName); $this->class = $class; $this->metadata = $em->getClassMetadata($class); if (false !== strpos($this->class, ':')) { $this->class = $this->metadata->getName(); } $this->repository = $em->getRepository($class); $this->property = $property; } /** * {@inheritdoc} */ public function loadUserByUsername($username) { if (null !== $this->property) { $user = $this->repository->findOneBy(array($this->property => $username)); } else { if (!$this->repository instanceof UserProviderInterface) { throw new \InvalidArgumentException(sprintf('The Doctrine repository "%s" must implement UserProviderInterface.', get_class($this->repository))); } $user = $this->repository->loadUserByUsername($username); } if (null === $user) { throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username)); } return $user; } /** * {@inheritDoc} */ public function refreshUser(UserInterface $user) { if (!$user instanceof $this->class) { throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); } if ($this->repository instanceof UserProviderInterface) { $refreshedUser = $this->repository->refreshUser($user); } else { // The user must be reloaded via the primary key as all other data // might have changed without proper persistence in the database. // That's the case when the user has been changed by a form with // validation errors. if (!$id = $this->metadata->getIdentifierValues($user)) { throw new \InvalidArgumentException("You cannot refresh a user ". "from the EntityUserProvider that does not contain an identifier. ". "The user object has to be serialized with its own identifier " . "mapped by Doctrine." ); } $refreshedUser = $this->repository->find($id); if (null === $refreshedUser) { throw new UsernameNotFoundException(sprintf('User with id %s not found', json_encode($id))); } } return $refreshedUser; } /** * {@inheritDoc} */ public function supportsClass($class) { return $class === $this->class || is_subclass_of($class, $this->class); } } PK!ESymfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Security\RememberMe; use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; use Symfony\Component\Security\Core\Exception\TokenNotFoundException; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Types\Type as DoctrineType; use PDO, DateTime; /** * This class provides storage for the tokens that is set in "remember me" * cookies. This way no password secrets will be stored in the cookies on * the client machine, and thus the security is improved. * * This depends only on doctrine in order to get a database connection * and to do the conversion of the datetime column. * * In order to use this class, you need the following table in your database: * CREATE TABLE `rememberme_token` ( * `series` char(88) UNIQUE PRIMARY KEY NOT NULL, * `value` char(88) NOT NULL, * `lastUsed` datetime NOT NULL, * `class` varchar(100) NOT NULL, * `username` varchar(200) NOT NULL * ); */ class DoctrineTokenProvider implements TokenProviderInterface { /** * Doctrine DBAL database connection * F.ex. service id: doctrine.dbal.default_connection * * @var \Doctrine\DBAL\Connection */ private $conn; /** * new DoctrineTokenProvider for the RememberMe authentication service * * @param \Doctrine\DBAL\Connection $conn */ public function __construct(Connection $conn) { $this->conn = $conn; } /** * {@inheritdoc} */ public function loadTokenBySeries($series) { $sql = 'SELECT class, username, value, lastUsed' . ' FROM rememberme_token WHERE series=:series'; $paramValues = array('series' => $series); $paramTypes = array('series' => PDO::PARAM_STR); $stmt = $this->conn->executeQuery($sql, $paramValues, $paramTypes); $row = $stmt->fetch(PDO::FETCH_ASSOC); if ($row) { return new PersistentToken($row['class'], $row['username'], $series, $row['value'], new DateTime($row['lastUsed']) ); } throw new TokenNotFoundException('No token found.'); } /** * {@inheritdoc} */ public function deleteTokenBySeries($series) { $sql = 'DELETE FROM rememberme_token WHERE series=:series'; $paramValues = array('series' => $series); $paramTypes = array('series' => PDO::PARAM_STR); $this->conn->executeUpdate($sql, $paramValues, $paramTypes); } /** * {@inheritdoc} */ public function updateToken($series, $tokenValue, DateTime $lastUsed) { $sql = 'UPDATE rememberme_token SET value=:value, lastUsed=:lastUsed' . ' WHERE series=:series'; $paramValues = array('value' => $tokenValue, 'lastUsed' => $lastUsed, 'series' => $series); $paramTypes = array('value' => PDO::PARAM_STR, 'lastUsed' => DoctrineType::DATETIME, 'series' => PDO::PARAM_STR); $updated = $this->conn->executeUpdate($sql, $paramValues, $paramTypes); if ($updated < 1) { throw new TokenNotFoundException('No token found.'); } } /** * {@inheritdoc} */ public function createNewToken(PersistentTokenInterface $token) { $sql = 'INSERT INTO rememberme_token' . ' (class, username, series, value, lastUsed)' . ' VALUES (:class, :username, :series, :value, :lastUsed)'; $paramValues = array('class' => $token->getClass(), 'username' => $token->getUsername(), 'series' => $token->getSeries(), 'value' => $token->getTokenValue(), 'lastUsed' => $token->getLastUsed()); $paramTypes = array('class' => PDO::PARAM_STR, 'username' => PDO::PARAM_STR, 'series' => PDO::PARAM_STR, 'value' => PDO::PARAM_STR, 'lastUsed' => DoctrineType::DATETIME); $this->conn->executeUpdate($sql, $paramValues, $paramTypes); } } PK!(y9Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Validator; use Doctrine\Common\Persistence\ManagerRegistry; use Symfony\Component\Validator\ObjectInitializerInterface; /** * Automatically loads proxy object before validation. * * @author Fabien Potencier */ class DoctrineInitializer implements ObjectInitializerInterface { protected $registry; public function __construct(ManagerRegistry $registry) { $this->registry = $registry; } public function initialize($object) { $manager = $this->registry->getManagerForClass(get_class($object)); if (null !== $manager) { $manager->initializeObject($object); } } } PK!QГ>Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * Constraint for the Unique Entity validator * * @Annotation * @author Benjamin Eberlei */ class UniqueEntity extends Constraint { public $message = 'This value is already used.'; public $service = 'doctrine.orm.validator.unique'; public $em = null; public $repositoryMethod = 'findBy'; public $fields = array(); public $errorPath = null; public $ignoreNull = true; public function getRequiredOptions() { return array('fields'); } /** * The validator must be defined as a service with this name. * * @return string */ public function validatedBy() { return $this->service; } /** * {@inheritDoc} */ public function getTargets() { return self::CLASS_CONSTRAINT; } public function getDefaultOption() { return 'fields'; } } PK!:dGSymfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Validator\Constraints; use Doctrine\Common\Persistence\ManagerRegistry; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\ConstraintValidator; /** * Unique Entity Validator checks if one or a set of fields contain unique values. * * @author Benjamin Eberlei */ class UniqueEntityValidator extends ConstraintValidator { /** * @var ManagerRegistry */ private $registry; /** * @param ManagerRegistry $registry */ public function __construct(ManagerRegistry $registry) { $this->registry = $registry; } /** * @param object $entity * @param Constraint $constraint * * @throws UnexpectedTypeException * @throws ConstraintDefinitionException */ public function validate($entity, Constraint $constraint) { if (!is_array($constraint->fields) && !is_string($constraint->fields)) { throw new UnexpectedTypeException($constraint->fields, 'array'); } if (null !== $constraint->errorPath && !is_string($constraint->errorPath)) { throw new UnexpectedTypeException($constraint->errorPath, 'string or null'); } $fields = (array) $constraint->fields; if (0 === count($fields)) { throw new ConstraintDefinitionException('At least one field has to be specified.'); } if ($constraint->em) { $em = $this->registry->getManager($constraint->em); if (!$em) { throw new ConstraintDefinitionException(sprintf('Object manager "%s" does not exist.', $constraint->em)); } } else { $em = $this->registry->getManagerForClass(get_class($entity)); if (!$em) { throw new ConstraintDefinitionException(sprintf('Unable to find the object manager associated with an entity of class "%s".', get_class($entity))); } } $class = $em->getClassMetadata(get_class($entity)); /* @var $class \Doctrine\Common\Persistence\Mapping\ClassMetadata */ $criteria = array(); foreach ($fields as $fieldName) { if (!$class->hasField($fieldName) && !$class->hasAssociation($fieldName)) { throw new ConstraintDefinitionException(sprintf("The field '%s' is not mapped by Doctrine, so it cannot be validated for uniqueness.", $fieldName)); } $criteria[$fieldName] = $class->reflFields[$fieldName]->getValue($entity); if ($constraint->ignoreNull && null === $criteria[$fieldName]) { return; } if (null !== $criteria[$fieldName] && $class->hasAssociation($fieldName)) { /* Ensure the Proxy is initialized before using reflection to * read its identifiers. This is necessary because the wrapped * getter methods in the Proxy are being bypassed. */ $em->initializeObject($criteria[$fieldName]); $relatedClass = $em->getClassMetadata($class->getAssociationTargetClass($fieldName)); $relatedId = $relatedClass->getIdentifierValues($criteria[$fieldName]); if (count($relatedId) > 1) { throw new ConstraintDefinitionException( "Associated entities are not allowed to have more than one identifier field to be " . "part of a unique constraint in: ".$class->getName()."#".$fieldName ); } $criteria[$fieldName] = array_pop($relatedId); } } $repository = $em->getRepository(get_class($entity)); $result = $repository->{$constraint->repositoryMethod}($criteria); /* If the result is a MongoCursor, it must be advanced to the first * element. Rewinding should have no ill effect if $result is another * iterator implementation. */ if ($result instanceof \Iterator) { $result->rewind(); } elseif (is_array($result)) { reset($result); } /* If no entity matched the query criteria or a single entity matched, * which is the same as the entity being validated, the criteria is * unique. */ if (0 === count($result) || (1 === count($result) && $entity === ($result instanceof \Iterator ? $result->current() : current($result)))) { return; } $errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0]; $this->context->addViolationAt($errorPath, $constraint->message, array(), $criteria[$fields[0]]); } } PK!Ta==BSymfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\ExpressionLanguage; use Doctrine\Common\Cache\Cache; use Symfony\Component\ExpressionLanguage\ParsedExpression; use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface; /** * @author Adrien Brault */ class DoctrineParserCache implements ParserCacheInterface { /** * @var Cache */ private $cache; public function __construct(Cache $cache) { $this->cache = $cache; } /** * {@inheritdoc} */ public function fetch($key) { if (false === $value = $this->cache->fetch($key)) { return null; } return $value; } /** * {@inheritdoc} */ public function save($key, ParsedExpression $expression) { $this->cache->save($key, $expression); } } PK!qm m -Symfony/Bridge/Doctrine/RegistryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine; use Doctrine\Common\Persistence\ManagerRegistry as ManagerRegistryInterface; use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManager; /** * References Doctrine connections and entity managers. * * @author Fabien Potencier */ interface RegistryInterface extends ManagerRegistryInterface { /** * Gets the default entity manager name. * * @return string The default entity manager name */ public function getDefaultEntityManagerName(); /** * Gets a named entity manager. * * @param string $name The entity manager name (null for the default one) * * @return EntityManager */ public function getEntityManager($name = null); /** * Gets an array of all registered entity managers * * @return array An array of EntityManager instances */ public function getEntityManagers(); /** * Resets a named entity manager. * * This method is useful when an entity manager has been closed * because of a rollbacked transaction AND when you think that * it makes sense to get a new one to replace the closed one. * * Be warned that you will get a brand new entity manager as * the existing one is not useable anymore. This means that any * other object with a dependency on this entity manager will * hold an obsolete reference. You can inject the registry instead * to avoid this problem. * * @param string $name The entity manager name (null for the default one) * * @return EntityManager */ public function resetEntityManager($name = null); /** * Resolves a registered namespace alias to the full namespace. * * This method looks for the alias in all registered entity managers. * * @param string $alias The alias * * @return string The full namespace * * @see Configuration::getEntityNamespace */ public function getEntityNamespace($alias); /** * Gets all connection names. * * @return array An array of connection names */ public function getEntityManagerNames(); /** * Gets the entity manager associated with a given class. * * @param string $class A Doctrine Entity class name * * @return EntityManager|null */ public function getEntityManagerForClass($class); } PK!lf/qq=Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\DataFixtures; use Doctrine\Common\DataFixtures\FixtureInterface; use Doctrine\Common\DataFixtures\Loader; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Doctrine data fixtures loader that injects the service container into * fixture objects that implement ContainerAwareInterface. * * Note: Use of this class requires the Doctrine data fixtures extension, which * is a suggested dependency for Symfony. */ class ContainerAwareLoader extends Loader { /** * @var ContainerInterface */ private $container; /** * Constructor. * * @param ContainerInterface $container A ContainerInterface instance */ public function __construct(ContainerInterface $container) { $this->container = $container; } /** * {@inheritdoc} */ public function addFixture(FixtureInterface $fixture) { if ($fixture instanceof ContainerAwareInterface) { $fixture->setContainer($this->container); } parent::addFixture($fixture); } } PK!=Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\HttpFoundation; use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Driver\Connection; /** * DBAL based session storage. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class DbalSessionHandler implements \SessionHandlerInterface { /** * @var Connection */ private $con; /** * @var string */ private $tableName; /** * Constructor. * * @param Connection $con An instance of Connection. * @param string $tableName Table name. */ public function __construct(Connection $con, $tableName = 'sessions') { $this->con = $con; $this->tableName = $tableName; } /** * {@inheritdoc} */ public function open($path = null, $name = null) { return true; } /** * {@inheritdoc} */ public function close() { // do nothing return true; } /** * {@inheritdoc} */ public function destroy($id) { try { $this->con->executeQuery("DELETE FROM {$this->tableName} WHERE sess_id = :id", array( 'id' => $id, )); } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e); } return true; } /** * {@inheritdoc} */ public function gc($lifetime) { try { $this->con->executeQuery("DELETE FROM {$this->tableName} WHERE sess_time < :time", array( 'time' => time() - $lifetime, )); } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e); } return true; } /** * {@inheritdoc} */ public function read($id) { try { $data = $this->con->executeQuery("SELECT sess_data FROM {$this->tableName} WHERE sess_id = :id", array( 'id' => $id, ))->fetchColumn(); if (false !== $data) { return base64_decode($data); } // session does not exist, create it $this->createNewSession($id); return ''; } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to read the session data: %s', $e->getMessage()), 0, $e); } } /** * {@inheritdoc} */ public function write($id, $data) { $platform = $this->con->getDatabasePlatform(); // this should maybe be abstracted in Doctrine DBAL if ($platform instanceof MySqlPlatform) { $sql = "INSERT INTO {$this->tableName} (sess_id, sess_data, sess_time) VALUES (%1\$s, %2\$s, %3\$d) " ."ON DUPLICATE KEY UPDATE sess_data = VALUES(sess_data), sess_time = CASE WHEN sess_time = %3\$d THEN (VALUES(sess_time) + 1) ELSE VALUES(sess_time) END"; } else { $sql = "UPDATE {$this->tableName} SET sess_data = %2\$s, sess_time = %3\$d WHERE sess_id = %1\$s"; } try { $rowCount = $this->con->exec(sprintf( $sql, $this->con->quote($id), //session data can contain non binary safe characters so we need to encode it $this->con->quote(base64_encode($data)), time() )); if (!$rowCount) { // No session exists in the database to update. This happens when we have called // session_regenerate_id() $this->createNewSession($id, $data); } } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e); } return true; } /** * Creates a new session with the given $id and $data * * @param string $id * @param string $data * * @return Boolean */ private function createNewSession($id, $data = '') { $this->con->exec(sprintf("INSERT INTO {$this->tableName} (sess_id, sess_data, sess_time) VALUES (%s, %s, %d)", $this->con->quote($id), //session data can contain non binary safe characters so we need to encode it $this->con->quote(base64_encode($data)), time() )); return true; } } PK!CSymfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\HttpFoundation; use Doctrine\DBAL\Schema\Schema; /** * DBAL Session Storage Schema. * * @author Johannes M. Schmitt */ final class DbalSessionHandlerSchema extends Schema { private $tableName; public function __construct($tableName = 'sessions') { parent::__construct(); $this->tableName = $tableName; $this->addSessionTable(); } public function addToSchema(Schema $schema) { foreach ($this->getTables() as $table) { $schema->_addTable($table); } } private function addSessionTable() { $table = $this->createTable($this->tableName); $table->addColumn('sess_id', 'string'); $table->addColumn('sess_data', 'text')->setNotNull(true); $table->addColumn('sess_time', 'integer')->setNotNull(true)->setUnsigned(true); $table->setPrimaryKey(array('sess_id')); } } PK!OlQ996Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine; use Doctrine\Common\EventArgs; use Doctrine\Common\EventManager; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Allows lazy loading of listener services. * * @author Johannes M. Schmitt */ class ContainerAwareEventManager extends EventManager { /** * Map of registered listeners. * => * * @var array */ private $listeners = array(); private $initialized = array(); private $container; public function __construct(ContainerInterface $container) { $this->container = $container; } /** * Dispatches an event to all registered listeners. * * @param string $eventName The name of the event to dispatch. The name of the event is * the name of the method that is invoked on listeners. * @param EventArgs $eventArgs The event arguments to pass to the event handlers/listeners. * If not supplied, the single empty EventArgs instance is used. * @return boolean */ public function dispatchEvent($eventName, EventArgs $eventArgs = null) { if (isset($this->listeners[$eventName])) { $eventArgs = $eventArgs === null ? EventArgs::getEmptyInstance() : $eventArgs; $initialized = isset($this->initialized[$eventName]); foreach ($this->listeners[$eventName] as $hash => $listener) { if (!$initialized && is_string($listener)) { $this->listeners[$eventName][$hash] = $listener = $this->container->get($listener); } $listener->$eventName($eventArgs); } $this->initialized[$eventName] = true; } } /** * Gets the listeners of a specific event or all listeners. * * @param string $event The name of the event. * * @return array The event listeners for the specified event, or all event listeners. */ public function getListeners($event = null) { return $event ? $this->listeners[$event] : $this->listeners; } /** * Checks whether an event has any registered listeners. * * @param string $event * * @return boolean TRUE if the specified event has any listeners, FALSE otherwise. */ public function hasListeners($event) { return isset($this->listeners[$event]) && $this->listeners[$event]; } /** * Adds an event listener that listens on the specified events. * * @param string|array $events The event(s) to listen on. * @param object|string $listener The listener object. * * @throws \RuntimeException */ public function addEventListener($events, $listener) { if (is_string($listener)) { if ($this->initialized) { throw new \RuntimeException('Adding lazy-loading listeners after construction is not supported.'); } $hash = '_service_'.$listener; } else { // Picks the hash code related to that listener $hash = spl_object_hash($listener); } foreach ((array) $events as $event) { // Overrides listener if a previous one was associated already // Prevents duplicate listeners on same event (same instance only) $this->listeners[$event][$hash] = $listener; } } /** * Removes an event listener from the specified events. * * @param string|array $events * @param object|string $listener */ public function removeEventListener($events, $listener) { if (is_string($listener)) { $hash = '_service_'.$listener; } else { // Picks the hash code related to that listener $hash = spl_object_hash($listener); } foreach ((array) $events as $event) { // Check if actually have this listener associated if (isset($this->listeners[$event][$hash])) { unset($this->listeners[$event][$hash]); } } } } PK!؈3Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Test; use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\ORM\Mapping\Driver\AnnotationDriver; use Doctrine\ORM\EntityManager; /** * Provides utility functions needed in tests. * * @author Bernhard Schussek */ class DoctrineTestHelper { /** * Returns an entity manager for testing. * * @return EntityManager */ public static function createTestEntityManager() { if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) { \PHPUnit_Framework_TestCase::markTestSkipped('This test requires SQLite support in your environment'); } $config = new \Doctrine\ORM\Configuration(); $config->setEntityNamespaces(array('SymfonyTestsDoctrine' => 'Symfony\Bridge\Doctrine\Tests\Fixtures')); $config->setAutoGenerateProxyClasses(true); $config->setProxyDir(\sys_get_temp_dir()); $config->setProxyNamespace('SymfonyTests\Doctrine'); $config->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader())); $config->setQueryCacheImpl(new \Doctrine\Common\Cache\ArrayCache()); $config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache()); $params = array( 'driver' => 'pdo_sqlite', 'memory' => true, ); return EntityManager::create($params, $config); } /** * This class cannot be instantiated. */ private function __construct() { } } PK!̳֨+Symfony/Bridge/Doctrine/ManagerRegistry.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Doctrine\Common\Persistence\AbstractManagerRegistry; /** * References Doctrine connections and entity/document managers. * * @author Lukas Kahwe Smith */ abstract class ManagerRegistry extends AbstractManagerRegistry implements ContainerAwareInterface { /** * @var ContainerInterface */ protected $container; /** * @inheritdoc */ protected function getService($name) { return $this->container->get($name); } /** * @inheritdoc */ protected function resetService($name) { $this->container->set($name, null); } /** * @inheritdoc */ public function setContainer(ContainerInterface $container = null) { $this->container = $container; } } PK!+çxAA?Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\DataCollector; use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\DBAL\Logging\DebugStack; use Doctrine\DBAL\Types\Type; use Symfony\Component\HttpKernel\DataCollector\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * DoctrineDataCollector. * * @author Fabien Potencier */ class DoctrineDataCollector extends DataCollector { private $registry; private $connections; private $managers; private $loggers = array(); public function __construct(ManagerRegistry $registry) { $this->registry = $registry; $this->connections = $registry->getConnectionNames(); $this->managers = $registry->getManagerNames(); } /** * Adds the stack logger for a connection. * * @param string $name * @param DebugStack $logger */ public function addLogger($name, DebugStack $logger) { $this->loggers[$name] = $logger; } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { $queries = array(); foreach ($this->loggers as $name => $logger) { $queries[$name] = $this->sanitizeQueries($name, $logger->queries); } $this->data = array( 'queries' => $queries, 'connections' => $this->connections, 'managers' => $this->managers, ); } public function getManagers() { return $this->data['managers']; } public function getConnections() { return $this->data['connections']; } public function getQueryCount() { return array_sum(array_map('count', $this->data['queries'])); } public function getQueries() { return $this->data['queries']; } public function getTime() { $time = 0; foreach ($this->data['queries'] as $queries) { foreach ($queries as $query) { $time += $query['executionMS']; } } return $time; } /** * {@inheritdoc} */ public function getName() { return 'db'; } private function sanitizeQueries($connectionName, $queries) { foreach ($queries as $i => $query) { $queries[$i] = $this->sanitizeQuery($connectionName, $query); } return $queries; } private function sanitizeQuery($connectionName, $query) { $query['explainable'] = true; $query['params'] = (array) $query['params']; foreach ($query['params'] as $j => &$param) { if (isset($query['types'][$j])) { // Transform the param according to the type $type = $query['types'][$j]; if (is_string($type)) { $type = Type::getType($type); } if ($type instanceof Type) { $query['types'][$j] = $type->getBindingType(); $param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform()); } } list($param, $explainable) = $this->sanitizeParam($param); if (!$explainable) { $query['explainable'] = false; } } return $query; } /** * Sanitizes a param. * * The return value is an array with the sanitized value and a boolean * indicating if the original value was kept (allowing to use the sanitized * value to explain the query). * * @param mixed $var * * @return array */ private function sanitizeParam($var) { if (is_object($var)) { return array(sprintf('Object(%s)', get_class($var)), false); } if (is_array($var)) { $a = array(); $original = true; foreach ($var as $k => $v) { list($value, $orig) = $this->sanitizeParam($v); $original = $original && $orig; $a[$k] = $value; } return array($a, $original); } if (is_resource($var)) { return array(sprintf('Resource(%s)', get_resource_type($var)), false); } return array($var, true); } } PK!*+JJISymfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\DependencyInjection; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Config\Resource\FileResource; /** * This abstract classes groups common code that Doctrine Object Manager extensions (ORM, MongoDB, CouchDB) need. * * @author Benjamin Eberlei */ abstract class AbstractDoctrineExtension extends Extension { /** * Used inside metadata driver method to simplify aggregation of data. * * @var array */ protected $aliasMap = array(); /** * Used inside metadata driver method to simplify aggregation of data. * * @var array */ protected $drivers = array(); /** * @param array $objectManager A configured object manager. * @param ContainerBuilder $container A ContainerBuilder instance * * @throws \InvalidArgumentException */ protected function loadMappingInformation(array $objectManager, ContainerBuilder $container) { if ($objectManager['auto_mapping']) { // automatically register bundle mappings foreach (array_keys($container->getParameter('kernel.bundles')) as $bundle) { if (!isset($objectManager['mappings'][$bundle])) { $objectManager['mappings'][$bundle] = array( 'mapping' => true, 'is_bundle' => true, ); } } } foreach ($objectManager['mappings'] as $mappingName => $mappingConfig) { if (null !== $mappingConfig && false === $mappingConfig['mapping']) { continue; } $mappingConfig = array_replace(array( 'dir' => false, 'type' => false, 'prefix' => false, ), (array) $mappingConfig); $mappingConfig['dir'] = $container->getParameterBag()->resolveValue($mappingConfig['dir']); // a bundle configuration is detected by realizing that the specified dir is not absolute and existing if (!isset($mappingConfig['is_bundle'])) { $mappingConfig['is_bundle'] = !is_dir($mappingConfig['dir']); } if ($mappingConfig['is_bundle']) { $bundle = null; foreach ($container->getParameter('kernel.bundles') as $name => $class) { if ($mappingName === $name) { $bundle = new \ReflectionClass($class); break; } } if (null === $bundle) { throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled.', $mappingName)); } $mappingConfig = $this->getMappingDriverBundleConfigDefaults($mappingConfig, $bundle, $container); if (!$mappingConfig) { continue; } } $this->assertValidMappingConfiguration($mappingConfig, $objectManager['name']); $this->setMappingDriverConfig($mappingConfig, $mappingName); $this->setMappingDriverAlias($mappingConfig, $mappingName); } } /** * Register the alias for this mapping driver. * * Aliases can be used in the Query languages of all the Doctrine object managers to simplify writing tasks. * * @param array $mappingConfig * @param string $mappingName */ protected function setMappingDriverAlias($mappingConfig, $mappingName) { if (isset($mappingConfig['alias'])) { $this->aliasMap[$mappingConfig['alias']] = $mappingConfig['prefix']; } else { $this->aliasMap[$mappingName] = $mappingConfig['prefix']; } } /** * Register the mapping driver configuration for later use with the object managers metadata driver chain. * * @param array $mappingConfig * @param string $mappingName * * @throws \InvalidArgumentException */ protected function setMappingDriverConfig(array $mappingConfig, $mappingName) { if (is_dir($mappingConfig['dir'])) { $this->drivers[$mappingConfig['type']][$mappingConfig['prefix']] = realpath($mappingConfig['dir']); } else { throw new \InvalidArgumentException(sprintf('Invalid Doctrine mapping path given. Cannot load Doctrine mapping/bundle named "%s".', $mappingName)); } } /** * If this is a bundle controlled mapping all the missing information can be autodetected by this method. * * Returns false when autodetection failed, an array of the completed information otherwise. * * @param array $bundleConfig * @param \ReflectionClass $bundle * @param ContainerBuilder $container A ContainerBuilder instance * * @return array|false */ protected function getMappingDriverBundleConfigDefaults(array $bundleConfig, \ReflectionClass $bundle, ContainerBuilder $container) { $bundleDir = dirname($bundle->getFilename()); if (!$bundleConfig['type']) { $bundleConfig['type'] = $this->detectMetadataDriver($bundleDir, $container); } if (!$bundleConfig['type']) { // skip this bundle, no mapping information was found. return false; } if (!$bundleConfig['dir']) { if (in_array($bundleConfig['type'], array('annotation', 'staticphp'))) { $bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingObjectDefaultName(); } else { $bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingResourceConfigDirectory(); } } else { $bundleConfig['dir'] = $bundleDir.'/'.$bundleConfig['dir']; } if (!$bundleConfig['prefix']) { $bundleConfig['prefix'] = $bundle->getNamespaceName().'\\'.$this->getMappingObjectDefaultName(); } return $bundleConfig; } /** * Register all the collected mapping information with the object manager by registering the appropriate mapping drivers. * * @param array $objectManager * @param ContainerBuilder $container A ContainerBuilder instance */ protected function registerMappingDrivers($objectManager, ContainerBuilder $container) { // configure metadata driver for each bundle based on the type of mapping files found if ($container->hasDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'))) { $chainDriverDef = $container->getDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver')); } else { $chainDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.driver_chain.class%')); $chainDriverDef->setPublic(false); } foreach ($this->drivers as $driverType => $driverPaths) { $mappingService = $this->getObjectManagerElementName($objectManager['name'].'_'.$driverType.'_metadata_driver'); if ($container->hasDefinition($mappingService)) { $mappingDriverDef = $container->getDefinition($mappingService); $args = $mappingDriverDef->getArguments(); if ($driverType == 'annotation') { $args[1] = array_merge(array_values($driverPaths), $args[1]); } else { $args[0] = array_merge(array_values($driverPaths), $args[0]); } $mappingDriverDef->setArguments($args); } elseif ($driverType == 'annotation') { $mappingDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.'.$driverType.'.class%'), array( new Reference($this->getObjectManagerElementName('metadata.annotation_reader')), array_values($driverPaths) )); } else { $mappingDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.'.$driverType.'.class%'), array( array_values($driverPaths) )); } $mappingDriverDef->setPublic(false); if (false !== strpos($mappingDriverDef->getClass(), 'yml') || false !== strpos($mappingDriverDef->getClass(), 'xml')) { $mappingDriverDef->setArguments(array(array_flip($driverPaths))); $mappingDriverDef->addMethodCall('setGlobalBasename', array('mapping')); } $container->setDefinition($mappingService, $mappingDriverDef); foreach ($driverPaths as $prefix => $driverPath) { $chainDriverDef->addMethodCall('addDriver', array(new Reference($mappingService), $prefix)); } } $container->setDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'), $chainDriverDef); } /** * Assertion if the specified mapping information is valid. * * @param array $mappingConfig * @param string $objectManagerName * * @throws \InvalidArgumentException */ protected function assertValidMappingConfiguration(array $mappingConfig, $objectManagerName) { if (!$mappingConfig['type'] || !$mappingConfig['dir'] || !$mappingConfig['prefix']) { throw new \InvalidArgumentException(sprintf('Mapping definitions for Doctrine manager "%s" require at least the "type", "dir" and "prefix" options.', $objectManagerName)); } if (!is_dir($mappingConfig['dir'])) { throw new \InvalidArgumentException(sprintf('Specified non-existing directory "%s" as Doctrine mapping source.', $mappingConfig['dir'])); } if (!in_array($mappingConfig['type'], array('xml', 'yml', 'annotation', 'php', 'staticphp'))) { throw new \InvalidArgumentException(sprintf('Can only configure "xml", "yml", "annotation", "php" or '. '"staticphp" through the DoctrineBundle. Use your own bundle to configure other metadata drivers. '. 'You can register them by adding a new driver to the '. '"%s" service definition.', $this->getObjectManagerElementName($objectManagerName.'.metadata_driver') )); } } /** * Detects what metadata driver to use for the supplied directory. * * @param string $dir A directory path * @param ContainerBuilder $container A ContainerBuilder instance * * @return string|null A metadata driver short name, if one can be detected */ protected function detectMetadataDriver($dir, ContainerBuilder $container) { // add the closest existing directory as a resource $configPath = $this->getMappingResourceConfigDirectory(); $resource = $dir.'/'.$configPath; while (!is_dir($resource)) { $resource = dirname($resource); } $container->addResource(new FileResource($resource)); $extension = $this->getMappingResourceExtension(); if (($files = glob($dir.'/'.$configPath.'/*.'.$extension.'.xml')) && count($files)) { return 'xml'; } elseif (($files = glob($dir.'/'.$configPath.'/*.'.$extension.'.yml')) && count($files)) { return 'yml'; } elseif (($files = glob($dir.'/'.$configPath.'/*.'.$extension.'.php')) && count($files)) { return 'php'; } // add the directory itself as a resource $container->addResource(new FileResource($dir)); if (is_dir($dir.'/'.$this->getMappingObjectDefaultName())) { return 'annotation'; } return null; } /** * Loads a configured object manager metadata, query or result cache driver. * * @param array $objectManager A configured object manager. * @param ContainerBuilder $container A ContainerBuilder instance. * @param string $cacheName * * @throws \InvalidArgumentException In case of unknown driver type. */ protected function loadObjectManagerCacheDriver(array $objectManager, ContainerBuilder $container, $cacheName) { $cacheDriver = $objectManager[$cacheName.'_driver']; $cacheDriverService = $this->getObjectManagerElementName($objectManager['name'].'_'.$cacheName); switch ($cacheDriver['type']) { case 'service': $container->setAlias($cacheDriverService, new Alias($cacheDriver['id'], false)); return; case 'memcache': $memcacheClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcache.class').'%'; $memcacheInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcache_instance.class').'%'; $memcacheHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcache_host').'%'; $memcachePort = !empty($cacheDriver['port']) || (isset($cacheDriver['port']) && $cacheDriver['port'] === 0) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcache_port').'%'; $cacheDef = new Definition($memcacheClass); $memcacheInstance = new Definition($memcacheInstanceClass); $memcacheInstance->addMethodCall('connect', array( $memcacheHost, $memcachePort )); $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_memcache_instance', $objectManager['name'])), $memcacheInstance); $cacheDef->addMethodCall('setMemcache', array(new Reference($this->getObjectManagerElementName(sprintf('%s_memcache_instance', $objectManager['name']))))); break; case 'memcached': $memcachedClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcached.class').'%'; $memcachedInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcached_instance.class').'%'; $memcachedHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcached_host').'%'; $memcachedPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcached_port').'%'; $cacheDef = new Definition($memcachedClass); $memcachedInstance = new Definition($memcachedInstanceClass); $memcachedInstance->addMethodCall('addServer', array( $memcachedHost, $memcachedPort )); $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManager['name'])), $memcachedInstance); $cacheDef->addMethodCall('setMemcached', array(new Reference($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManager['name']))))); break; case 'redis': $redisClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.redis.class').'%'; $redisInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.redis_instance.class').'%'; $redisHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.redis_host').'%'; $redisPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.redis_port').'%'; $cacheDef = new Definition($redisClass); $redisInstance = new Definition($redisInstanceClass); $redisInstance->addMethodCall('connect', array( $redisHost, $redisPort )); $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManager['name'])), $redisInstance); $cacheDef->addMethodCall('setRedis', array(new Reference($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManager['name']))))); break; case 'apc': case 'array': case 'xcache': case 'wincache': case 'zenddata': $cacheDef = new Definition('%'.$this->getObjectManagerElementName(sprintf('cache.%s.class', $cacheDriver['type'])).'%'); break; default: throw new \InvalidArgumentException(sprintf('"%s" is an unrecognized Doctrine cache driver.', $cacheDriver['type'])); } $cacheDef->setPublic(false); if (!isset($cacheDriver['namespace'])) { // generate a unique namespace for the given application $cacheDriver['namespace'] = 'sf2'.$this->getMappingResourceExtension().'_'.$objectManager['name'].'_'.hash('sha256',($container->getParameter('kernel.root_dir').$container->getParameter('kernel.environment'))); } $cacheDef->addMethodCall('setNamespace', array($cacheDriver['namespace'])); $container->setDefinition($cacheDriverService, $cacheDef); } /** * Prefixes the relative dependency injection container path with the object manager prefix. * * @example $name is 'entity_manager' then the result would be 'doctrine.orm.entity_manager' * * @param string $name * * @return string */ abstract protected function getObjectManagerElementName($name); /** * Noun that describes the mapped objects such as Entity or Document. * * Will be used for autodetection of persistent objects directory. * * @return string */ abstract protected function getMappingObjectDefaultName(); /** * Relative path from the bundle root to the directory where mapping files reside. * * @return string */ abstract protected function getMappingResourceConfigDirectory(); /** * Extension used by the mapping files. * * @return string */ abstract protected function getMappingResourceExtension(); } PK!*SSymfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\DependencyInjection\Security\UserProvider; use Symfony\Component\Config\Definition\Builder\NodeDefinition; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * EntityFactory creates services for Doctrine user provider. * * @author Fabien Potencier * @author Christophe Coevoet */ class EntityFactory implements UserProviderFactoryInterface { private $key; private $providerId; public function __construct($key, $providerId) { $this->key = $key; $this->providerId = $providerId; } public function create(ContainerBuilder $container, $id, $config) { $container ->setDefinition($id, new DefinitionDecorator($this->providerId)) ->addArgument($config['class']) ->addArgument($config['property']) ->addArgument($config['manager_name']) ; } public function getKey() { return $this->key; } public function addConfiguration(NodeDefinition $node) { $node ->children() ->scalarNode('class')->isRequired()->cannotBeEmpty()->end() ->scalarNode('property')->defaultNull()->end() ->scalarNode('manager_name')->defaultNull()->end() ->end() ; } } PK!㛕QSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; /** * Base class for the doctrine bundles to provide a compiler pass class that * helps to register doctrine mappings. * * The compiler pass is meant to register the mappings with the metadata * chain driver corresponding to one of the object managers. * * For concrete implementations that are easy to use, see the * RegisterXyMappingsPass classes in the DoctrineBundle resp. * DoctrineMongodbBundle, DoctrineCouchdbBundle and DoctrinePhpcrBundle. * * @author David Buchmann */ abstract class RegisterMappingsPass implements CompilerPassInterface { /** * DI object for the driver to use, either a service definition for a * private service or a reference for a public service. * @var Definition|Reference */ protected $driver; /** * List of namespaces handled by the driver * @var string[] */ protected $namespaces; /** * List of potential container parameters that hold the object manager name * to register the mappings with the correct metadata driver, for example * array('acme.manager', 'doctrine.default_entity_manager') * @var string[] */ protected $managerParameters; /** * Naming pattern of the metadata chain driver service ids, for example * 'doctrine.orm.%s_metadata_driver' * @var string */ protected $driverPattern; /** * A name for a parameter in the container. If set, this compiler pass will * only do anything if the parameter is present. (But regardless of the * value of that parameter. * @var string */ protected $enabledParameter; /** * @param Definition|Reference $driver driver DI definition or reference * @param string[] $namespaces list of namespaces handled by $driver * @param string[] $managerParameters list of container parameters * that could hold the manager name * @param string $driverPattern pattern to get the metadata driver service names * @param string $enabledParameter service container parameter that must be * present to enable the mapping. Set to false * to not do any check, optional. */ public function __construct($driver, array $namespaces, array $managerParameters, $driverPattern, $enabledParameter = false) { $this->driver = $driver; $this->namespaces = $namespaces; $this->managerParameters = $managerParameters; $this->driverPattern = $driverPattern; $this->enabledParameter = $enabledParameter; } /** * Register mappings with the metadata drivers. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { if (!$this->enabled($container)) { return; } $mappingDriverDef = $this->getDriver($container); $chainDriverDefService = $this->getChainDriverServiceName($container); $chainDriverDef = $container->getDefinition($chainDriverDefService); foreach ($this->namespaces as $namespace) { $chainDriverDef->addMethodCall('addDriver', array($mappingDriverDef, $namespace)); } } /** * Get the service name of the metadata chain driver that the mappings * should be registered with. The default implementation loops over the * managerParameters and applies the first non-empty parameter it finds to * the driverPattern. * * @param ContainerBuilder $container * * @return string a service definition name * * @throws ParameterNotFoundException if non of the managerParameters has a * non-empty value. */ protected function getChainDriverServiceName(ContainerBuilder $container) { foreach ($this->managerParameters as $param) { if ($container->hasParameter($param)) { $name = $container->getParameter($param); if ($name) { return sprintf($this->driverPattern, $name); } } } throw new ParameterNotFoundException('None of the managerParameters resulted in a valid name'); } /** * Create the service definition for the metadata driver. * * @param ContainerBuilder $container passed on in case an extending class * needs access to the container. * * @return Definition|Reference the metadata driver to add to all chain drivers */ protected function getDriver(ContainerBuilder $container) { return $this->driver; } /** * Determine whether this mapping should be activated or not. This allows * to take this decision with the container builder available. * * This default implementation checks if the class has the enabledParameter * configured and if so if that parameter is present in the container. * * @param ContainerBuilder $container * * @return boolean whether this compiler pass really should register the mappings */ protected function enabled(ContainerBuilder $container) { return !$this->enabledParameter || $container->hasParameter($this->enabledParameter); } } PK!~YAAeSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; /** * Registers event listeners and subscribers to the available doctrine connections. * * @author Jeremy Mikola * @author Alexander */ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface { private $connections; private $container; private $eventManagers; private $managerTemplate; private $tagPrefix; /** * Constructor. * * @param string $connections Parameter ID for connections * @param string $managerTemplate sprintf() template for generating the event * manager's service ID for a connection name * @param string $tagPrefix Tag prefix for listeners and subscribers */ public function __construct($connections, $managerTemplate, $tagPrefix) { $this->connections = $connections; $this->managerTemplate = $managerTemplate; $this->tagPrefix = $tagPrefix; } /** * {@inheritDoc} */ public function process(ContainerBuilder $container) { if (!$container->hasParameter($this->connections)) { return; } $taggedSubscribers = $container->findTaggedServiceIds($this->tagPrefix.'.event_subscriber'); $taggedListeners = $container->findTaggedServiceIds($this->tagPrefix.'.event_listener'); if (empty($taggedSubscribers) && empty($taggedListeners)) { return; } $this->container = $container; $this->connections = $container->getParameter($this->connections); $sortFunc = function ($a, $b) { $a = isset($a['priority']) ? $a['priority'] : 0; $b = isset($b['priority']) ? $b['priority'] : 0; return $a > $b ? -1 : 1; }; if (!empty($taggedSubscribers)) { $subscribersPerCon = $this->groupByConnection($taggedSubscribers); foreach ($subscribersPerCon as $con => $subscribers) { $em = $this->getEventManager($con); uasort($subscribers, $sortFunc); foreach ($subscribers as $id => $instance) { $em->addMethodCall('addEventSubscriber', array(new Reference($id))); } } } if (!empty($taggedListeners)) { $listenersPerCon = $this->groupByConnection($taggedListeners, true); foreach ($listenersPerCon as $con => $listeners) { $em = $this->getEventManager($con); uasort($listeners, $sortFunc); foreach ($listeners as $id => $instance) { $em->addMethodCall('addEventListener', array( array_unique($instance['event']), isset($instance['lazy']) && $instance['lazy'] ? $id : new Reference($id), )); } } } } private function groupByConnection(array $services, $isListener = false) { $grouped = array(); foreach ($allCons = array_keys($this->connections) as $con) { $grouped[$con] = array(); } foreach ($services as $id => $instances) { foreach ($instances as $instance) { if ($isListener) { if (!isset($instance['event'])) { throw new \InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id)); } $instance['event'] = array($instance['event']); if (isset($instance['lazy']) && $instance['lazy']) { $this->container->getDefinition($id)->setPublic(true); } } $cons = isset($instance['connection']) ? array($instance['connection']) : $allCons; foreach ($cons as $con) { if (!isset($grouped[$con])) { throw new \RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections)))); } if ($isListener && isset($grouped[$con][$id])) { $grouped[$con][$id]['event'] = array_merge($grouped[$con][$id]['event'], $instance['event']); } else { $grouped[$con][$id] = $instance; } } } } return $grouped; } private function getEventManager($name) { if (null === $this->eventManagers) { $this->eventManagers = array(); foreach ($this->connections as $n => $id) { $this->eventManagers[$n] = $this->container->getDefinition(sprintf($this->managerTemplate, $n)); } } return $this->eventManagers[$name]; } } PK!,SSymfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\Config\Resource\FileResource; /** * Registers additional validators * * @author Benjamin Eberlei */ class DoctrineValidationPass implements CompilerPassInterface { /** * @var string */ private $managerType; public function __construct($managerType) { $this->managerType = $managerType; } /** * {@inheritDoc} */ public function process(ContainerBuilder $container) { $this->updateValidatorMappingFiles($container, 'xml', 'xml'); $this->updateValidatorMappingFiles($container, 'yaml', 'yml'); } /** * Gets the validation mapping files for the format and extends them with * files matching a doctrine search pattern (Resources/config/validation.orm.xml) * * @param ContainerBuilder $container * @param string $mapping * @param string $extension */ private function updateValidatorMappingFiles(ContainerBuilder $container, $mapping, $extension) { if (!$container->hasParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files')) { return; } $files = $container->getParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files'); $validationPath = 'Resources/config/validation.'.$this->managerType.'.'.$extension; foreach ($container->getParameter('kernel.bundles') as $bundle) { $reflection = new \ReflectionClass($bundle); if (is_file($file = dirname($reflection->getFilename()).'/'.$validationPath)) { $files[] = realpath($file); $container->addResource(new FileResource($file)); } } $container->setParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files', $files); } } PK!4NN%Symfony/Bridge/Monolog/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog\Handler; use Monolog\Handler\FirePHPHandler as BaseFirePHPHandler; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpFoundation\Response; /** * FirePHPHandler. * * @author Jordi Boggiano */ class FirePHPHandler extends BaseFirePHPHandler { /** * @var array */ private $headers = array(); /** * @var Response */ private $response; /** * Adds the headers to the response once it's created */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest()) { return; } if (!preg_match('{\bFirePHP/\d+\.\d+\b}', $event->getRequest()->headers->get('User-Agent')) && !$event->getRequest()->headers->has('X-FirePHP-Version')) { $this->sendHeaders = false; $this->headers = array(); return; } $this->response = $event->getResponse(); foreach ($this->headers as $header => $content) { $this->response->headers->set($header, $content); } $this->headers = array(); } /** * {@inheritDoc} */ protected function sendHeader($header, $content) { if (!$this->sendHeaders) { return; } if ($this->response) { $this->response->headers->set($header, $content); } else { $this->headers[$header] = $content; } } /** * Override default behavior since we check the user agent in onKernelResponse */ protected function headersAccepted() { return true; } } PK!Zv/Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog\Handler; use Monolog\Logger; use Monolog\Handler\TestHandler; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; /** * DebugLogger. * * @author Jordi Boggiano */ class DebugHandler extends TestHandler implements DebugLoggerInterface { /** * {@inheritdoc} */ public function getLogs() { $records = array(); foreach ($this->records as $record) { $records[] = array( 'timestamp' => $record['datetime']->getTimestamp(), 'message' => $record['message'], 'priority' => $record['level'], 'priorityName' => $record['level_name'], 'context' => $record['context'], ); } return $records; } /** * {@inheritdoc} */ public function countErrors() { $cnt = 0; $levels = array(Logger::ERROR, Logger::CRITICAL, Logger::ALERT, Logger::EMERGENCY); foreach ($levels as $level) { if (isset($this->recordsByLevel[$level])) { $cnt += count($this->recordsByLevel[$level]); } } return $cnt; } } PK!y1Symfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog\Handler; use Monolog\Handler\AbstractProcessingHandler; use Monolog\Logger; use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter; use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Writes logs to the console output depending on its verbosity setting. * * It is disabled by default and gets activated as soon as a command is executed. * Instead of listening to the console events, the output can also be set manually. * * The minimum logging level at which this handler will be triggered depends on the * verbosity setting of the console output. The default mapping is: * - OutputInterface::VERBOSITY_NORMAL will show all WARNING and higher logs * - OutputInterface::VERBOSITY_VERBOSE (-v) will show all NOTICE and higher logs * - OutputInterface::VERBOSITY_VERY_VERBOSE (-vv) will show all INFO and higher logs * - OutputInterface::VERBOSITY_DEBUG (-vvv) will show all DEBUG and higher logs, i.e. all logs * * This mapping can be customized with the $verbosityLevelMap constructor parameter. * * @author Tobias Schultze */ class ConsoleHandler extends AbstractProcessingHandler implements EventSubscriberInterface { /** * @var OutputInterface|null */ private $output; /** * @var array */ private $verbosityLevelMap = array( OutputInterface::VERBOSITY_NORMAL => Logger::WARNING, OutputInterface::VERBOSITY_VERBOSE => Logger::NOTICE, OutputInterface::VERBOSITY_VERY_VERBOSE => Logger::INFO, OutputInterface::VERBOSITY_DEBUG => Logger::DEBUG ); /** * Constructor. * * @param OutputInterface|null $output The console output to use (the handler remains disabled when passing null * until the output is set, e.g. by using console events) * @param Boolean $bubble Whether the messages that are handled can bubble up the stack * @param array $verbosityLevelMap Array that maps the OutputInterface verbosity to a minimum logging * level (leave empty to use the default mapping) */ public function __construct(OutputInterface $output = null, $bubble = true, array $verbosityLevelMap = array()) { parent::__construct(Logger::DEBUG, $bubble); $this->output = $output; if ($verbosityLevelMap) { $this->verbosityLevelMap = $verbosityLevelMap; } } /** * {@inheritdoc} */ public function isHandling(array $record) { return $this->updateLevel() && parent::isHandling($record); } /** * {@inheritdoc} */ public function handle(array $record) { // we have to update the logging level each time because the verbosity of the // console output might have changed in the meantime (it is not immutable) return $this->updateLevel() && parent::handle($record); } /** * Sets the console output to use for printing logs. * * @param OutputInterface $output The console output to use */ public function setOutput(OutputInterface $output) { $this->output = $output; } /** * Disables the output. */ public function close() { $this->output = null; parent::close(); } /** * Before a command is executed, the handler gets activated and the console output * is set in order to know where to write the logs. * * @param ConsoleCommandEvent $event */ public function onCommand(ConsoleCommandEvent $event) { $this->setOutput($event->getOutput()); } /** * After a command has been executed, it disables the output. * * @param ConsoleTerminateEvent $event */ public function onTerminate(ConsoleTerminateEvent $event) { $this->close(); } /** * {@inheritdoc} */ public static function getSubscribedEvents() { return array( ConsoleEvents::COMMAND => 'onCommand', ConsoleEvents::TERMINATE => 'onTerminate' ); } /** * {@inheritdoc} */ protected function write(array $record) { if ($record['level'] >= Logger::ERROR && $this->output instanceof ConsoleOutputInterface) { $this->output->getErrorOutput()->write((string) $record['formatted']); } else { $this->output->write((string) $record['formatted']); } } /** * {@inheritdoc} */ protected function getDefaultFormatter() { return new ConsoleFormatter(); } /** * Updates the logging level based on the verbosity setting of the console output. * * @return Boolean Whether the handler is enabled and verbosity is not set to quiet. */ private function updateLevel() { if (null === $this->output || OutputInterface::VERBOSITY_QUIET === $verbosity = $this->output->getVerbosity()) { return false; } if (isset($this->verbosityLevelMap[$verbosity])) { $this->setLevel($this->verbosityLevelMap[$verbosity]); } else { $this->setLevel(Logger::DEBUG); } return true; } } PK!*vv5Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog\Handler; use Monolog\Handler\SwiftMailerHandler as BaseSwiftMailerHandler; use Symfony\Component\HttpKernel\Event\PostResponseEvent; /** * Extended SwiftMailerHandler that flushes mail queue if necessary * * @author Philipp Kräutli */ class SwiftMailerHandler extends BaseSwiftMailerHandler { protected $transport; protected $instantFlush = false; /** * @param \Swift_Transport $transport */ public function setTransport(\Swift_Transport $transport) { $this->transport = $transport; } /** * After the kernel has been terminated we will always flush messages * * @param PostResponseEvent $event */ public function onKernelTerminate(PostResponseEvent $event) { $this->instantFlush = true; } /** * {@inheritdoc} */ protected function send($content, array $records) { parent::send($content, $records); if ($this->instantFlush) { $this->flushMemorySpool(); } } /** * Flushes the mail queue if a memory spool is used */ private function flushMemorySpool() { $mailerTransport = $this->mailer->getTransport(); if (!$mailerTransport instanceof \Swift_Transport_SpoolTransport) { return; } $spool = $mailerTransport->getSpool(); if (!$spool instanceof \Swift_MemorySpool) { return; } if (null === $this->transport) { throw new \Exception('No transport available to flush mail queue'); } $spool->flushQueue($this->transport); } } PK!"II3Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog\Handler; use Monolog\Handler\ChromePHPHandler as BaseChromePhpHandler; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; /** * ChromePhpHandler. * * @author Christophe Coevoet */ class ChromePhpHandler extends BaseChromePhpHandler { /** * @var array */ private $headers = array(); /** * @var Response */ private $response; /** * Adds the headers to the response once it's created */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest()) { return; } if (!preg_match('{\bChrome/\d+[\.\d+]*\b}', $event->getRequest()->headers->get('User-Agent'))) { $this->sendHeaders = false; $this->headers = array(); return; } $this->response = $event->getResponse(); foreach ($this->headers as $header => $content) { $this->response->headers->set($header, $content); } $this->headers = array(); } /** * {@inheritDoc} */ protected function sendHeader($header, $content) { if (!$this->sendHeaders) { return; } if ($this->response) { $this->response->headers->set($header, $content); } else { $this->headers[$header] = $content; } } /** * Override default behavior since we check it in onKernelResponse */ protected function headersAccepted() { return true; } } PK!; !Symfony/Bridge/Monolog/Logger.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog; use Monolog\Logger as BaseLogger; use Symfony\Component\HttpKernel\Log\LoggerInterface; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; /** * Logger. * * @author Fabien Potencier */ class Logger extends BaseLogger implements LoggerInterface, DebugLoggerInterface { /** * @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible. */ public function emerg($message, array $context = array()) { return parent::addRecord(BaseLogger::EMERGENCY, $message, $context); } /** * @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible. */ public function crit($message, array $context = array()) { return parent::addRecord(BaseLogger::CRITICAL, $message, $context); } /** * @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible. */ public function err($message, array $context = array()) { return parent::addRecord(BaseLogger::ERROR, $message, $context); } /** * @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible. */ public function warn($message, array $context = array()) { return parent::addRecord(BaseLogger::WARNING, $message, $context); } /** * @see Symfony\Component\HttpKernel\Log\DebugLoggerInterface */ public function getLogs() { if ($logger = $this->getDebugLogger()) { return $logger->getLogs(); } return array(); } /** * @see Symfony\Component\HttpKernel\Log\DebugLoggerInterface */ public function countErrors() { if ($logger = $this->getDebugLogger()) { return $logger->countErrors(); } return 0; } /** * Returns a DebugLoggerInterface instance if one is registered with this logger. * * @return DebugLoggerInterface|null A DebugLoggerInterface instance or null if none is registered */ private function getDebugLogger() { foreach ($this->handlers as $handler) { if ($handler instanceof DebugLoggerInterface) { return $handler; } } } } PK!b115Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog\Formatter; use Monolog\Formatter\LineFormatter; use Monolog\Logger; /** * Formats incoming records for console output by coloring them depending on log level. * * @author Tobias Schultze */ class ConsoleFormatter extends LineFormatter { const SIMPLE_FORMAT = "%start_tag%[%datetime%] %channel%.%level_name%:%end_tag% %message% %context% %extra%\n"; /** * {@inheritdoc} */ public function format(array $record) { if ($record['level'] >= Logger::ERROR) { $record['start_tag'] = ''; $record['end_tag'] = ''; } elseif ($record['level'] >= Logger::NOTICE) { $record['start_tag'] = ''; $record['end_tag'] = ''; } elseif ($record['level'] >= Logger::INFO) { $record['start_tag'] = ''; $record['end_tag'] = ''; } else { $record['start_tag'] = ''; $record['end_tag'] = ''; } return parent::format($record); } } PK!,1Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog\Processor; use Monolog\Processor\WebProcessor as BaseWebProcessor; use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** * WebProcessor override to read from the HttpFoundation's Request * * @author Jordi Boggiano */ class WebProcessor extends BaseWebProcessor { public function __construct() { // Pass an empty array as the default null value would access $_SERVER parent::__construct(array()); } public function onKernelRequest(GetResponseEvent $event) { if ($event->isMasterRequest()) { $this->serverData = $event->getRequest()->server->all(); } } } PK!$KK"Symfony/Bridge/Twig/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Translation; use Symfony\Component\Finder\Finder; use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\MessageCatalogue; /** * TwigExtractor extracts translation messages from a twig template. * * @author Michel Salib * @author Fabien Potencier */ class TwigExtractor implements ExtractorInterface { /** * Default domain for found messages. * * @var string */ private $defaultDomain = 'messages'; /** * Prefix for found message. * * @var string */ private $prefix = ''; /** * The twig environment. * * @var \Twig_Environment */ private $twig; public function __construct(\Twig_Environment $twig) { $this->twig = $twig; } /** * {@inheritDoc} */ public function extract($directory, MessageCatalogue $catalogue) { // load any existing translation files $finder = new Finder(); $files = $finder->files()->name('*.twig')->sortByName()->in($directory); foreach ($files as $file) { $this->extractTemplate(file_get_contents($file->getPathname()), $catalogue); } } /** * {@inheritDoc} */ public function setPrefix($prefix) { $this->prefix = $prefix; } protected function extractTemplate($template, MessageCatalogue $catalogue) { $visitor = $this->twig->getExtension('translator')->getTranslationNodeVisitor(); $visitor->enable(); $this->twig->parse($this->twig->tokenize($template)); foreach ($visitor->getMessages() as $message) { $catalogue->set(trim($message[0]), $this->prefix.trim($message[0]), $message[1] ? $message[1] : $this->defaultDomain); } $visitor->disable(); } } PK!6 DZ77*Symfony/Bridge/Twig/Node/StopwatchNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Node; /** * Represents a stopwatch node. * * @author Wouter J */ class StopwatchNode extends \Twig_Node { public function __construct(\Twig_NodeInterface $name, $body, \Twig_Node_Expression_AssignName $var, $lineno = 0, $tag = null) { parent::__construct(array('body' => $body, 'name' => $name, 'var' => $var), array(), $lineno, $tag); } public function compile(\Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write('') ->subcompile($this->getNode('var')) ->raw(' = ') ->subcompile($this->getNode('name')) ->write(";\n") ->write("\$this->env->getExtension('stopwatch')->getStopwatch()->start(") ->subcompile($this->getNode('var')) ->raw(", 'template');\n") ->subcompile($this->getNode('body')) ->write("\$this->env->getExtension('stopwatch')->getStopwatch()->stop(") ->subcompile($this->getNode('var')) ->raw(");\n") ; } } PK!, @5Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Node; /** * @author Bernhard Schussek */ class SearchAndRenderBlockNode extends \Twig_Node_Expression_Function { public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); $compiler->raw('$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock('); preg_match('/_([^_]+)$/', $this->getAttribute('name'), $matches); $label = null; $arguments = iterator_to_array($this->getNode('arguments')); $blockNameSuffix = $matches[1]; if (isset($arguments[0])) { $compiler->subcompile($arguments[0]); $compiler->raw(', \''.$blockNameSuffix.'\''); if (isset($arguments[1])) { if ('label' === $blockNameSuffix) { // The "label" function expects the label in the second and // the variables in the third argument $label = $arguments[1]; $variables = isset($arguments[2]) ? $arguments[2] : null; $lineno = $label->getLine(); if ($label instanceof \Twig_Node_Expression_Constant) { // If the label argument is given as a constant, we can either // strip it away if it is empty, or integrate it into the array // of variables at compile time. $labelIsExpression = false; // Only insert the label into the array if it is not empty if (!twig_test_empty($label->getAttribute('value'))) { $originalVariables = $variables; $variables = new \Twig_Node_Expression_Array(array(), $lineno); $labelKey = new \Twig_Node_Expression_Constant('label', $lineno); if (null !== $originalVariables) { foreach ($originalVariables->getKeyValuePairs() as $pair) { // Don't copy the original label attribute over if it exists if ((string) $labelKey !== (string) $pair['key']) { $variables->addElement($pair['value'], $pair['key']); } } } // Insert the label argument into the array $variables->addElement($label, $labelKey); } } else { // The label argument is not a constant, but some kind of // expression. This expression needs to be evaluated at runtime. // Depending on the result (whether it is null or not), the // label in the arguments should take precedence over the label // in the attributes or not. $labelIsExpression = true; } } else { // All other functions than "label" expect the variables // in the second argument $label = null; $variables = $arguments[1]; $labelIsExpression = false; } if (null !== $variables || $labelIsExpression) { $compiler->raw(', '); if (null !== $variables) { $compiler->subcompile($variables); } if ($labelIsExpression) { if (null !== $variables) { $compiler->raw(' + '); } // Check at runtime whether the label is empty. // If not, add it to the array at runtime. $compiler->raw('(twig_test_empty($_label_ = '); $compiler->subcompile($label); $compiler->raw(') ? array() : array("label" => $_label_))'); } } } } $compiler->raw(")"); } } PK! s>>*Symfony/Bridge/Twig/Node/FormThemeNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Node; /** * @author Fabien Potencier */ class FormThemeNode extends \Twig_Node { public function __construct(\Twig_NodeInterface $form, \Twig_NodeInterface $resources, $lineno, $tag = null) { parent::__construct(array('form' => $form, 'resources' => $resources), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param \Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(\Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write('$this->env->getExtension(\'form\')->renderer->setTheme(') ->subcompile($this->getNode('form')) ->raw(', ') ->subcompile($this->getNode('resources')) ->raw(");\n"); ; } } PK!PIAA3Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Node; /** * @author Fabien Potencier */ class TransDefaultDomainNode extends \Twig_Node { public function __construct(\Twig_Node_Expression $expr, $lineno = 0, $tag = null) { parent::__construct(array('expr' => $expr), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param \Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(\Twig_Compiler $compiler) { // noop as this node is just a marker for TranslationDefaultDomainNodeVisitor } } PK!U,tt,Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Node; /** * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * the helper "form_start()" instead. */ class FormEnctypeNode extends SearchAndRenderBlockNode { public function compile(\Twig_Compiler $compiler) { parent::compile($compiler); // Uncomment this as soon as the deprecation note should be shown // $compiler->write('trigger_error(\'The helper form_enctype(form) is deprecated since version 2.3 and will be removed in 3.0. Use form_start(form) instead.\', E_USER_DEPRECATED)'); } } PK!ʦ\G G &Symfony/Bridge/Twig/Node/TransNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Node; /** * @author Fabien Potencier */ class TransNode extends \Twig_Node { public function __construct(\Twig_NodeInterface $body, \Twig_NodeInterface $domain = null, \Twig_Node_Expression $count = null, \Twig_Node_Expression $vars = null, \Twig_Node_Expression $locale = null, $lineno = 0, $tag = null) { parent::__construct(array('count' => $count, 'body' => $body, 'domain' => $domain, 'vars' => $vars, 'locale' => $locale), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param \Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); $vars = $this->getNode('vars'); $defaults = new \Twig_Node_Expression_Array(array(), -1); if ($vars instanceof \Twig_Node_Expression_Array) { $defaults = $this->getNode('vars'); $vars = null; } list($msg, $defaults) = $this->compileString($this->getNode('body'), $defaults); $method = null === $this->getNode('count') ? 'trans' : 'transChoice'; $compiler ->write('echo $this->env->getExtension(\'translator\')->getTranslator()->'.$method.'(') ->subcompile($msg) ; $compiler->raw(', '); if (null !== $this->getNode('count')) { $compiler ->subcompile($this->getNode('count')) ->raw(', ') ; } if (null !== $vars) { $compiler ->raw('array_merge(') ->subcompile($defaults) ->raw(', ') ->subcompile($this->getNode('vars')) ->raw(')') ; } else { $compiler->subcompile($defaults); } $compiler->raw(', '); if (null === $this->getNode('domain')) { $compiler->repr('messages'); } else { $compiler->subcompile($this->getNode('domain')); } if (null !== $this->getNode('locale')) { $compiler ->raw(', ') ->subcompile($this->getNode('locale')) ; } $compiler->raw(");\n"); } protected function compileString(\Twig_NodeInterface $body, \Twig_Node_Expression_Array $vars) { if ($body instanceof \Twig_Node_Expression_Constant) { $msg = $body->getAttribute('value'); } elseif ($body instanceof \Twig_Node_Text) { $msg = $body->getAttribute('data'); } else { return array($body, $vars); } preg_match_all('/(?getLine()); if (!$vars->hasElement($key)) { $vars->addElement(new \Twig_Node_Expression_Name($var, $body->getLine()), $key); } } return array(new \Twig_Node_Expression_Constant(str_replace('%%', '%', trim($msg)), $body->getLine()), $vars); } } PK!^,Symfony/Bridge/Twig/Node/RenderBlockNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Node; /** * Compiles a call to {@link FormRendererInterface::renderBlock()}. * * The function name is used as block name. For example, if the function name * is "foo", the block "foo" will be rendered. * * @author Bernhard Schussek */ class RenderBlockNode extends \Twig_Node_Expression_Function { public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); $arguments = iterator_to_array($this->getNode('arguments')); $compiler->write('$this->env->getExtension(\'form\')->renderer->renderBlock('); if (isset($arguments[0])) { $compiler->subcompile($arguments[0]); $compiler->raw(', \'' . $this->getAttribute('name') . '\''); if (isset($arguments[1])) { $compiler->raw(', '); $compiler->subcompile($arguments[1]); } } $compiler->raw(')'); } } PK!vq)Symfony/Bridge/Twig/Form/TwigRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * @author Bernhard Schussek */ class TwigRenderer extends FormRenderer implements TwigRendererInterface { /** * @var TwigRendererEngineInterface */ private $engine; public function __construct(TwigRendererEngineInterface $engine, $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } parent::__construct($engine, $csrfTokenManager); $this->engine = $engine; } /** * {@inheritdoc} */ public function setEnvironment(\Twig_Environment $environment) { $this->engine->setEnvironment($environment); } } PK!b3}}8Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\FormRendererEngineInterface; /** * @author Bernhard Schussek */ interface TwigRendererEngineInterface extends FormRendererEngineInterface { /** * Sets Twig's environment. * * @param \Twig_Environment $environment */ public function setEnvironment(\Twig_Environment $environment); } PK!Qkk2Symfony/Bridge/Twig/Form/TwigRendererInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\FormRendererInterface; /** * @author Bernhard Schussek */ interface TwigRendererInterface extends FormRendererInterface { /** * Sets Twig's environment. * * @param \Twig_Environment $environment */ public function setEnvironment(\Twig_Environment $environment); } PK!</Symfony/Bridge/Twig/Form/TwigRendererEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\AbstractRendererEngine; use Symfony\Component\Form\FormView; /** * @author Bernhard Schussek */ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererEngineInterface { /** * @var \Twig_Environment */ private $environment; /** * @var \Twig_Template */ private $template; /** * {@inheritdoc} */ public function setEnvironment(\Twig_Environment $environment) { $this->environment = $environment; } /** * {@inheritdoc} */ public function renderBlock(FormView $view, $resource, $blockName, array $variables = array()) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; $context = $this->environment->mergeGlobals($variables); ob_start(); // By contract,This method can only be called after getting the resource // (which is passed to the method). Getting a resource for the first time // (with an empty cache) is guaranteed to invoke loadResourcesFromTheme(), // where the property $template is initialized. // We do not call renderBlock here to avoid too many nested level calls // (XDebug limits the level to 100 by default) $this->template->displayBlock($blockName, $context, $this->resources[$cacheKey]); return ob_get_clean(); } /** * Loads the cache with the resource for a given block name. * * This implementation eagerly loads all blocks of the themes assigned to the given view * and all of its ancestors views. This is necessary, because Twig receives the * list of blocks later. At that point, all blocks must already be loaded, for the * case that the function "block()" is used in the Twig template. * * @see getResourceForBlock() * * @param string $cacheKey The cache key of the form view. * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * * @return Boolean True if the resource could be loaded, false otherwise. */ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName) { // The caller guarantees that $this->resources[$cacheKey][$block] is // not set, but it doesn't have to check whether $this->resources[$cacheKey] // is set. If $this->resources[$cacheKey] is set, all themes for this // $cacheKey are already loaded (due to the eager population, see doc comment). if (isset($this->resources[$cacheKey])) { // As said in the previous, the caller guarantees that // $this->resources[$cacheKey][$block] is not set. Since the themes are // already loaded, it can only be a non-existing block. $this->resources[$cacheKey][$blockName] = false; return false; } // Recursively try to find the block in the themes assigned to $view, // then of its parent view, then of the parent view of the parent and so on. // When the root view is reached in this recursion, also the default // themes are taken into account. // Check each theme whether it contains the searched block if (isset($this->themes[$cacheKey])) { for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) { $this->loadResourcesFromTheme($cacheKey, $this->themes[$cacheKey][$i]); // CONTINUE LOADING (see doc comment) } } // Check the default themes once we reach the root view without success if (!$view->parent) { for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { $this->loadResourcesFromTheme($cacheKey, $this->defaultThemes[$i]); // CONTINUE LOADING (see doc comment) } } // Proceed with the themes of the parent view if ($view->parent) { $parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR]; if (!isset($this->resources[$parentCacheKey])) { $this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName); } // EAGER CACHE POPULATION (see doc comment) foreach ($this->resources[$parentCacheKey] as $nestedBlockName => $resource) { if (!isset($this->resources[$cacheKey][$nestedBlockName])) { $this->resources[$cacheKey][$nestedBlockName] = $resource; } } } // Even though we loaded the themes, it can happen that none of them // contains the searched block if (!isset($this->resources[$cacheKey][$blockName])) { // Cache that we didn't find anything to speed up further accesses $this->resources[$cacheKey][$blockName] = false; } return false !== $this->resources[$cacheKey][$blockName]; } /** * Loads the resources for all blocks in a theme. * * @param string $cacheKey The cache key for storing the resource. * @param mixed $theme The theme to load the block from. This parameter * is passed by reference, because it might be necessary * to initialize the theme first. Any changes made to * this variable will be kept and be available upon * further calls to this method using the same theme. */ protected function loadResourcesFromTheme($cacheKey, &$theme) { if (!$theme instanceof \Twig_Template) { /* @var \Twig_Template $theme */ $theme = $this->environment->loadTemplate($theme); } if (null === $this->template) { // Store the first \Twig_Template instance that we find so that // we can call displayBlock() later on. It doesn't matter *which* // template we use for that, since we pass the used blocks manually // anyway. $this->template = $theme; } // Use a separate variable for the inheritance traversal, because // theme is a reference and we don't want to change it. $currentTheme = $theme; $context = $this->environment->mergeGlobals(array()); // The do loop takes care of template inheritance. // Add blocks from all templates in the inheritance tree, but avoid // overriding blocks already set. do { foreach ($currentTheme->getBlocks() as $block => $blockData) { if (!isset($this->resources[$cacheKey][$block])) { // The resource given back is the key to the bucket that // contains this block. $this->resources[$cacheKey][$block] = $blockData; } } } while (false !== $currentTheme = $currentTheme->getParent($context)); } } PK!  GSymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\NodeVisitor; use Symfony\Bridge\Twig\Node\TransNode; use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; /** * TranslationDefaultDomainNodeVisitor. * * @author Fabien Potencier */ class TranslationDefaultDomainNodeVisitor implements \Twig_NodeVisitorInterface { /** * @var Scope */ private $scope; /** * Constructor. */ public function __construct() { $this->scope = new Scope(); } /** * {@inheritdoc} */ public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) { if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) { $this->scope = $this->scope->enter(); } if ($node instanceof TransDefaultDomainNode) { if ($node->getNode('expr') instanceof \Twig_Node_Expression_Constant) { $this->scope->set('domain', $node->getNode('expr')); return $node; } else { $var = $env->getParser()->getVarName(); $name = new \Twig_Node_Expression_AssignName($var, $node->getLine()); $this->scope->set('domain', new \Twig_Node_Expression_Name($var, $node->getLine())); return new \Twig_Node_Set(false, new \Twig_Node(array($name)), new \Twig_Node(array($node->getNode('expr'))), $node->getLine()); } } if (!$this->scope->has('domain')) { return $node; } if ($node instanceof \Twig_Node_Expression_Filter && in_array($node->getNode('filter')->getAttribute('value'), array('trans', 'transchoice'))) { $ind = 'trans' === $node->getNode('filter')->getAttribute('value') ? 1 : 2; $arguments = $node->getNode('arguments'); if (!$arguments->hasNode($ind)) { if (!$arguments->hasNode($ind - 1)) { $arguments->setNode($ind - 1, new \Twig_Node_Expression_Array(array(), $node->getLine())); } $arguments->setNode($ind, $this->scope->get('domain')); } } elseif ($node instanceof TransNode) { if (null === $node->getNode('domain')) { $node->setNode('domain', $this->scope->get('domain')); } } return $node; } /** * {@inheritdoc} */ public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) { if ($node instanceof TransDefaultDomainNode) { return false; } if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) { $this->scope = $this->scope->leave(); } return $node; } /** * {@inheritdoc} */ public function getPriority() { return -10; } } PK!)[n n )Symfony/Bridge/Twig/NodeVisitor/Scope.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\NodeVisitor; /** * @author Jean-François Simon */ class Scope { /** * @var Scope|null */ private $parent; /** * @var Scope[] */ private $children; /** * @var array */ private $data = array(); /** * @var boolean */ private $left = false; /** * @param Scope $parent */ public function __construct(Scope $parent = null) { $this->parent = $parent; } /** * Opens a new child scope. * * @return Scope */ public function enter() { $child = new self($this); $this->children[] = $child; return $child; } /** * Closes current scope and returns parent one. * * @return Scope|null */ public function leave() { $this->left = true; return $this->parent; } /** * Stores data into current scope. * * @param string $key * @param mixed $value * * @throws \LogicException * * @return Scope Current scope */ public function set($key, $value) { if ($this->left) { throw new \LogicException('Left scope is not mutable.'); } $this->data[$key] = $value; return $this; } /** * Tests if a data is visible from current scope. * * @param string $key * * @return boolean */ public function has($key) { if (array_key_exists($key, $this->data)) { return true; } if (null === $this->parent) { return false; } return $this->parent->has($key); } /** * Returns data visible from current scope. * * @param string $key * @param mixed $default * * @return mixed */ public function get($key, $default = null) { if (array_key_exists($key, $this->data)) { return $this->data[$key]; } if (null === $this->parent) { return $default; } return $this->parent->get($key, $default); } } PK!tA:Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\NodeVisitor; use Symfony\Bridge\Twig\Node\TransNode; /** * TranslationNodeVisitor extracts translation messages. * * @author Fabien Potencier */ class TranslationNodeVisitor implements \Twig_NodeVisitorInterface { const UNDEFINED_DOMAIN = '_undefined'; private $enabled = false; private $messages = array(); public function enable() { $this->enabled = true; $this->messages = array(); } public function disable() { $this->enabled = false; $this->messages = array(); } public function getMessages() { return $this->messages; } /** * {@inheritdoc} */ public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) { if (!$this->enabled) { return $node; } if ( $node instanceof \Twig_Node_Expression_Filter && 'trans' === $node->getNode('filter')->getAttribute('value') && $node->getNode('node') instanceof \Twig_Node_Expression_Constant ) { // extract constant nodes with a trans filter $this->messages[] = array( $node->getNode('node')->getAttribute('value'), $this->getReadDomainFromArguments($node->getNode('arguments'), 1), ); } elseif ( $node instanceof \Twig_Node_Expression_Filter && 'transchoice' === $node->getNode('filter')->getAttribute('value') && $node->getNode('node') instanceof \Twig_Node_Expression_Constant ) { // extract constant nodes with a trans filter $this->messages[] = array( $node->getNode('node')->getAttribute('value'), $this->getReadDomainFromArguments($node->getNode('arguments'), 2), ); } elseif ($node instanceof TransNode) { // extract trans nodes $this->messages[] = array( $node->getNode('body')->getAttribute('data'), $this->getReadDomainFromNode($node->getNode('domain')), ); } return $node; } /** * {@inheritdoc} */ public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) { return $node; } /** * {@inheritdoc} */ public function getPriority() { return 0; } /** * @param \Twig_Node $arguments * @param int $index * * @return string|null */ private function getReadDomainFromArguments(\Twig_Node $arguments, $index) { if ($arguments->hasNode('domain')) { $argument = $arguments->getNode('domain'); } elseif ($arguments->hasNode($index)) { $argument = $arguments->getNode($index); } else { return null; } return $this->getReadDomainFromNode($argument); } /** * @param \Twig_Node $node * * @return string|null */ private function getReadDomainFromNode(\Twig_Node $node = null) { if (null === $node) { return null; } if ($node instanceof \Twig_Node_Expression_Constant) { return $node->getAttribute('value'); } return self::UNDEFINED_DOMAIN; } } PK! 9292BSymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu[{# Widgets #} {% block form_widget %} {% spaceless %} {% if compound %} {{ block('form_widget_compound') }} {% else %} {{ block('form_widget_simple') }} {% endif %} {% endspaceless %} {% endblock form_widget %} {% block form_widget_simple %} {% spaceless %} {% set type = type|default('text') %} {% endspaceless %} {% endblock form_widget_simple %} {% block form_widget_compound %} {% spaceless %}
{% if form.parent is empty %} {{ form_errors(form) }} {% endif %} {{ block('form_rows') }} {{ form_rest(form) }}
{% endspaceless %} {% endblock form_widget_compound %} {% block collection_widget %} {% spaceless %} {% if prototype is defined %} {% set attr = attr|merge({'data-prototype': form_row(prototype) }) %} {% endif %} {{ block('form_widget') }} {% endspaceless %} {% endblock collection_widget %} {% block textarea_widget %} {% spaceless %} {% endspaceless %} {% endblock textarea_widget %} {% block choice_widget %} {% spaceless %} {% if expanded %} {{ block('choice_widget_expanded') }} {% else %} {{ block('choice_widget_collapsed') }} {% endif %} {% endspaceless %} {% endblock choice_widget %} {% block choice_widget_expanded %} {% spaceless %}
{% for child in form %} {{ form_widget(child) }} {{ form_label(child) }} {% endfor %}
{% endspaceless %} {% endblock choice_widget_expanded %} {% block choice_widget_collapsed %} {% spaceless %} {% if required and empty_value is none and not empty_value_in_choices and not multiple %} {% set required = false %} {% endif %} {% endspaceless %} {% endblock choice_widget_collapsed %} {% block choice_widget_options %} {% spaceless %} {% for group_label, choice in options %} {% if choice is iterable %} {% set options = choice %} {{ block('choice_widget_options') }} {% else %} {% endif %} {% endfor %} {% endspaceless %} {% endblock choice_widget_options %} {% block checkbox_widget %} {% spaceless %} {% endspaceless %} {% endblock checkbox_widget %} {% block radio_widget %} {% spaceless %} {% endspaceless %} {% endblock radio_widget %} {% block datetime_widget %} {% spaceless %} {% if widget == 'single_text' %} {{ block('form_widget_simple') }} {% else %}
{{ form_errors(form.date) }} {{ form_errors(form.time) }} {{ form_widget(form.date) }} {{ form_widget(form.time) }}
{% endif %} {% endspaceless %} {% endblock datetime_widget %} {% block date_widget %} {% spaceless %} {% if widget == 'single_text' %} {{ block('form_widget_simple') }} {% else %}
{{ date_pattern|replace({ '{{ year }}': form_widget(form.year), '{{ month }}': form_widget(form.month), '{{ day }}': form_widget(form.day), })|raw }}
{% endif %} {% endspaceless %} {% endblock date_widget %} {% block time_widget %} {% spaceless %} {% if widget == 'single_text' %} {{ block('form_widget_simple') }} {% else %} {% set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} %}
{{ form_widget(form.hour, vars) }}{% if with_minutes %}:{{ form_widget(form.minute, vars) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, vars) }}{% endif %}
{% endif %} {% endspaceless %} {% endblock time_widget %} {% block number_widget %} {% spaceless %} {# type="number" doesn't work with floats #} {% set type = type|default('text') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock number_widget %} {% block integer_widget %} {% spaceless %} {% set type = type|default('number') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock integer_widget %} {% block money_widget %} {% spaceless %} {{ money_pattern|replace({ '{{ widget }}': block('form_widget_simple') })|raw }} {% endspaceless %} {% endblock money_widget %} {% block url_widget %} {% spaceless %} {% set type = type|default('url') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock url_widget %} {% block search_widget %} {% spaceless %} {% set type = type|default('search') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock search_widget %} {% block percent_widget %} {% spaceless %} {% set type = type|default('text') %} {{ block('form_widget_simple') }} % {% endspaceless %} {% endblock percent_widget %} {% block password_widget %} {% spaceless %} {% set type = type|default('password') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock password_widget %} {% block hidden_widget %} {% spaceless %} {% set type = type|default('hidden') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock hidden_widget %} {% block email_widget %} {% spaceless %} {% set type = type|default('email') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock email_widget %} {% block button_widget %} {% spaceless %} {% if label is empty %} {% set label = name|humanize %} {% endif %} {% endspaceless %} {% endblock button_widget %} {% block submit_widget %} {% spaceless %} {% set type = type|default('submit') %} {{ block('button_widget') }} {% endspaceless %} {% endblock submit_widget %} {% block reset_widget %} {% spaceless %} {% set type = type|default('reset') %} {{ block('button_widget') }} {% endspaceless %} {% endblock reset_widget %} {# Labels #} {% block form_label %} {% spaceless %} {% if label is not sameas(false) %} {% if not compound %} {% set label_attr = label_attr|merge({'for': id}) %} {% endif %} {% if required %} {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %} {% endif %} {% if label is empty %} {% set label = name|humanize %} {% endif %} {{ label|trans({}, translation_domain) }} {% endif %} {% endspaceless %} {% endblock form_label %} {% block button_label %}{% endblock %} {# Rows #} {% block repeated_row %} {% spaceless %} {# No need to render the errors here, as all errors are mapped to the first child (see RepeatedTypeValidatorExtension). #} {{ block('form_rows') }} {% endspaceless %} {% endblock repeated_row %} {% block form_row %} {% spaceless %}
{{ form_label(form) }} {{ form_errors(form) }} {{ form_widget(form) }}
{% endspaceless %} {% endblock form_row %} {% block button_row %} {% spaceless %}
{{ form_widget(form) }}
{% endspaceless %} {% endblock button_row %} {% block hidden_row %} {{ form_widget(form) }} {% endblock hidden_row %} {# Misc #} {% block form %} {% spaceless %} {{ form_start(form) }} {{ form_widget(form) }} {{ form_end(form) }} {% endspaceless %} {% endblock form %} {% block form_start %} {% spaceless %} {% set method = method|upper %} {% if method in ["GET", "POST"] %} {% set form_method = method %} {% else %} {% set form_method = "POST" %} {% endif %}
{% if form_method != method %} {% endif %} {% endspaceless %} {% endblock form_start %} {% block form_end %} {% spaceless %} {% if not render_rest is defined or render_rest %} {{ form_rest(form) }} {% endif %}
{% endspaceless %} {% endblock form_end %} {% block form_enctype %} {% spaceless %} {% if multipart %}enctype="multipart/form-data"{% endif %} {% endspaceless %} {% endblock form_enctype %} {% block form_errors %} {% spaceless %} {% if errors|length > 0 %}
    {% for error in errors %}
  • {{ error.message }}
  • {% endfor %}
{% endif %} {% endspaceless %} {% endblock form_errors %} {% block form_rest %} {% spaceless %} {% for child in form %} {% if not child.rendered %} {{ form_row(child) }} {% endif %} {% endfor %} {% endspaceless %} {% endblock form_rest %} {# Support #} {% block form_rows %} {% spaceless %} {% for child in form %} {{ form_row(child) }} {% endfor %} {% endspaceless %} {% endblock form_rows %} {% block widget_attributes %} {% spaceless %} id="{{ id }}" name="{{ full_name }}" {%- if read_only %} readonly="readonly"{% endif -%} {%- if disabled %} disabled="disabled"{% endif -%} {%- if required %} required="required"{% endif -%} {%- if max_length %} maxlength="{{ max_length }}"{% endif -%} {%- if pattern %} pattern="{{ pattern }}"{% endif -%} {%- for attrname, attrvalue in attr -%} {{- " " -}} {%- if attrname in ['placeholder', 'title'] -%} {{- attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {%- elseif attrvalue is sameas(true) -%} {{- attrname }}="{{ attrname }}" {%- elseif attrvalue is not sameas(false) -%} {{- attrname }}="{{ attrvalue }}" {%- endif -%} {%- endfor -%} {% endspaceless %} {% endblock widget_attributes %} {% block widget_container_attributes %} {% spaceless %} {%- if id is not empty %}id="{{ id }}"{% endif -%} {%- for attrname, attrvalue in attr -%} {{- " " -}} {%- if attrname in ['placeholder', 'title'] -%} {{- attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {%- elseif attrvalue is sameas(true) -%} {{- attrname }}="{{ attrname }}" {%- elseif attrvalue is not sameas(false) -%} {{- attrname }}="{{ attrvalue }}" {%- endif -%} {%- endfor -%} {% endspaceless %} {% endblock widget_container_attributes %} {% block button_attributes %} {% spaceless %} id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif -%} {%- for attrname, attrvalue in attr -%} {{- " " -}} {%- if attrname in ['placeholder', 'title'] -%} {{- attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {%- elseif attrvalue is sameas(true) -%} {{- attrname }}="{{ attrname }}" {%- elseif attrvalue is not sameas(false) -%} {{- attrname }}="{{ attrvalue }}" {%- endif -%} {%- endfor -%} {% endspaceless %} {% endblock button_attributes %} PK![[DSymfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu[{% use "form_div_layout.html.twig" %} {% block form_row %} {% spaceless %} {{ form_label(form) }} {{ form_errors(form) }} {{ form_widget(form) }} {% endspaceless %} {% endblock form_row %} {% block button_row %} {% spaceless %} {{ form_widget(form) }} {% endspaceless %} {% endblock button_row %} {% block hidden_row %} {% spaceless %} {{ form_widget(form) }} {% endspaceless %} {% endblock hidden_row %} {% block form_widget_compound %} {% spaceless %} {% if form.parent is empty and errors|length > 0 %} {% endif %} {{ block('form_rows') }} {{ form_rest(form) }}
{{ form_errors(form) }}
{% endspaceless %} {% endblock form_widget_compound %} PK!.8Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\StopwatchNode; /** * Token Parser for the stopwatch tag. * * @author Wouter J */ class StopwatchTokenParser extends \Twig_TokenParser { protected $stopwatchIsAvailable; public function __construct($stopwatchIsAvailable) { $this->stopwatchIsAvailable = $stopwatchIsAvailable; } public function parse(\Twig_Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); // {% stopwatch 'bar' %} $name = $this->parser->getExpressionParser()->parseExpression(); $stream->expect(\Twig_Token::BLOCK_END_TYPE); // {% endstopwatch %} $body = $this->parser->subparse(array($this, 'decideStopwatchEnd'), true); $stream->expect(\Twig_Token::BLOCK_END_TYPE); if ($this->stopwatchIsAvailable) { return new StopwatchNode($name, $body, new \Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $lineno, $this->getTag()); } return $body; } public function decideStopwatchEnd(\Twig_Token $token) { return $token->test('endstopwatch'); } public function getTag() { return 'stopwatch'; } } PK!%] 4Symfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\TransNode; /** * Token Parser for the 'trans' tag. * * @author Fabien Potencier */ class TransTokenParser extends \Twig_TokenParser { /** * Parses a token and returns a node. * * @param \Twig_Token $token A Twig_Token instance * * @return \Twig_NodeInterface A Twig_NodeInterface instance * * @throws \Twig_Error_Syntax */ public function parse(\Twig_Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); $vars = new \Twig_Node_Expression_Array(array(), $lineno); $domain = null; $locale = null; if (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) { if ($stream->test('with')) { // {% trans with vars %} $stream->next(); $vars = $this->parser->getExpressionParser()->parseExpression(); } if ($stream->test('from')) { // {% trans from "messages" %} $stream->next(); $domain = $this->parser->getExpressionParser()->parseExpression(); } if ($stream->test('into')) { // {% trans into "fr" %} $stream->next(); $locale = $this->parser->getExpressionParser()->parseExpression(); } elseif (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) { throw new \Twig_Error_Syntax('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getFilename()); } } // {% trans %}message{% endtrans %} $stream->expect(\Twig_Token::BLOCK_END_TYPE); $body = $this->parser->subparse(array($this, 'decideTransFork'), true); if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) { throw new \Twig_Error_Syntax('A message inside a trans tag must be a simple text.', $body->getLine(), $stream->getFilename()); } $stream->expect(\Twig_Token::BLOCK_END_TYPE); return new TransNode($body, $domain, null, $vars, $locale, $lineno, $this->getTag()); } public function decideTransFork($token) { return $token->test(array('endtrans')); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'trans'; } } PK!/ :Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\TransNode; /** * Token Parser for the 'transchoice' tag. * * @author Fabien Potencier */ class TransChoiceTokenParser extends TransTokenParser { /** * Parses a token and returns a node. * * @param \Twig_Token $token A Twig_Token instance * * @return \Twig_NodeInterface A Twig_NodeInterface instance * * @throws \Twig_Error_Syntax */ public function parse(\Twig_Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); $vars = new \Twig_Node_Expression_Array(array(), $lineno); $count = $this->parser->getExpressionParser()->parseExpression(); $domain = null; $locale = null; if ($stream->test('with')) { // {% transchoice count with vars %} $stream->next(); $vars = $this->parser->getExpressionParser()->parseExpression(); } if ($stream->test('from')) { // {% transchoice count from "messages" %} $stream->next(); $domain = $this->parser->getExpressionParser()->parseExpression(); } if ($stream->test('into')) { // {% transchoice count into "fr" %} $stream->next(); $locale = $this->parser->getExpressionParser()->parseExpression(); } $stream->expect(\Twig_Token::BLOCK_END_TYPE); $body = $this->parser->subparse(array($this, 'decideTransChoiceFork'), true); if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) { throw new \Twig_Error_Syntax('A message inside a transchoice tag must be a simple text.', $body->getLine(), $stream->getFilename()); } $stream->expect(\Twig_Token::BLOCK_END_TYPE); return new TransNode($body, $domain, $count, $vars, $locale, $lineno, $this->getTag()); } public function decideTransChoiceFork($token) { return $token->test(array('endtranschoice')); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'transchoice'; } } PK!>8Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\FormThemeNode; /** * Token Parser for the 'form_theme' tag. * * @author Fabien Potencier */ class FormThemeTokenParser extends \Twig_TokenParser { /** * Parses a token and returns a node. * * @param \Twig_Token $token A Twig_Token instance * * @return \Twig_NodeInterface A Twig_NodeInterface instance */ public function parse(\Twig_Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); $form = $this->parser->getExpressionParser()->parseExpression(); if ($this->parser->getStream()->test(\Twig_Token::NAME_TYPE, 'with')) { $this->parser->getStream()->next(); $resources = $this->parser->getExpressionParser()->parseExpression(); } else { $resources = new \Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); do { $resources->addElement($this->parser->getExpressionParser()->parseExpression()); } while (!$stream->test(\Twig_Token::BLOCK_END_TYPE)); } $stream->expect(\Twig_Token::BLOCK_END_TYPE); return new FormThemeNode($form, $resources, $lineno, $this->getTag()); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'form_theme'; } } PK!ʶ̭ASymfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; /** * Token Parser for the 'trans_default_domain' tag. * * @author Fabien Potencier */ class TransDefaultDomainTokenParser extends \Twig_TokenParser { /** * Parses a token and returns a node. * * @param \Twig_Token $token A Twig_Token instance * * @return \Twig_NodeInterface A Twig_NodeInterface instance */ public function parse(\Twig_Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); $this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE); return new TransDefaultDomainNode($expr, $token->getLine(), $this->getTag()); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'trans_default_domain'; } } PK!9=KK/Symfony/Bridge/Twig/Extension/FormExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Extension; use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; use Symfony\Bridge\Twig\Form\TwigRendererInterface; use Symfony\Component\Form\Extension\Core\View\ChoiceView; /** * FormExtension extends Twig with form capabilities. * * @author Fabien Potencier * @author Bernhard Schussek */ class FormExtension extends \Twig_Extension { /** * This property is public so that it can be accessed directly from compiled * templates without having to call a getter, which slightly decreases performance. * * @var TwigRendererInterface */ public $renderer; public function __construct(TwigRendererInterface $renderer) { $this->renderer = $renderer; } /** * {@inheritdoc} */ public function initRuntime(\Twig_Environment $environment) { $this->renderer->setEnvironment($environment); } /** * {@inheritdoc} */ public function getTokenParsers() { return array( // {% form_theme form "SomeBundle::widgets.twig" %} new FormThemeTokenParser(), ); } /** * {@inheritdoc} */ public function getFunctions() { return array( 'form_enctype' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\FormEnctypeNode', array('is_safe' => array('html'))), 'form_widget' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))), 'form_errors' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))), 'form_label' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))), 'form_row' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))), 'form_rest' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', array('is_safe' => array('html'))), 'form' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))), 'form_start' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))), 'form_end' => new \Twig_Function_Node('Symfony\Bridge\Twig\Node\RenderBlockNode', array('is_safe' => array('html'))), 'csrf_token' => new \Twig_Function_Method($this, 'renderer->renderCsrfToken'), ); } /** * {@inheritdoc} */ public function getFilters() { return array( new \Twig_SimpleFilter('humanize', array($this->renderer, 'humanize')), ); } /** * {@inheritdoc} */ public function getTests() { return array( new \Twig_SimpleTest('selectedchoice', array($this, 'isSelectedChoice')), ); } /** * Returns whether a choice is selected for a given form value. * * Unfortunately Twig does not support an efficient way to execute the * "is_selected" closure passed to the template by ChoiceType. It is faster * to implement the logic here (around 65ms for a specific form). * * Directly implementing the logic here is also faster than doing so in * ChoiceView (around 30ms). * * The worst option tested so far is to implement the logic in ChoiceView * and access the ChoiceView method directly in the template. Doing so is * around 220ms slower than doing the method call here in the filter. Twig * seems to be much more efficient at executing filters than at executing * methods of an object. * * @param ChoiceView $choice The choice to check. * @param string|array $selectedValue The selected value to compare. * * @return Boolean Whether the choice is selected. * * @see ChoiceView::isSelected() */ public function isSelectedChoice(ChoiceView $choice, $selectedValue) { if (is_array($selectedValue)) { return false !== array_search($choice->value, $selectedValue, true); } return $choice->value === $selectedValue; } /** * {@inheritdoc} */ public function getName() { return 'form'; } } PK!|/Symfony/Bridge/Twig/Extension/YamlExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\Yaml\Dumper as YamlDumper; /** * Provides integration of the Yaml component with Twig. * * @author Fabien Potencier */ class YamlExtension extends \Twig_Extension { /** * {@inheritdoc} */ public function getFilters() { return array( new \Twig_SimpleFilter('yaml_encode', array($this, 'encode')), new \Twig_SimpleFilter('yaml_dump', array($this, 'dump')), ); } public function encode($input, $inline = 0, $dumpObjects = false) { static $dumper; if (null === $dumper) { $dumper = new YamlDumper(); } return $dumper->dump($input, $inline, false, $dumpObjects); } public function dump($value, $inline = 0, $dumpObjects = false) { if (is_resource($value)) { return '%Resource%'; } if (is_array($value) || is_object($value)) { return '%'.gettype($value).'% '.$this->encode($value, $inline, $dumpObjects); } return $this->encode($value, $inline, $dumpObjects); } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'yaml'; } } PK!&a a 5Symfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\HttpKernel\Fragment\FragmentHandler; use Symfony\Component\HttpKernel\Controller\ControllerReference; /** * Provides integration with the HttpKernel component. * * @author Fabien Potencier */ class HttpKernelExtension extends \Twig_Extension { private $handler; /** * Constructor. * * @param FragmentHandler $handler A FragmentHandler instance */ public function __construct(FragmentHandler $handler) { $this->handler = $handler; } public function getFunctions() { return array( new \Twig_SimpleFunction('render',array($this, 'renderFragment'), array('is_safe' => array('html'))), new \Twig_SimpleFunction('render_*', array($this, 'renderFragmentStrategy'), array('is_safe' => array('html'))), new \Twig_SimpleFunction('controller', array($this, 'controller')), ); } /** * Renders a fragment. * * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance * @param array $options An array of options * * @return string The fragment content * * @see Symfony\Component\HttpKernel\Fragment\FragmentHandler::render() */ public function renderFragment($uri, $options = array()) { $strategy = isset($options['strategy']) ? $options['strategy'] : 'inline'; unset($options['strategy']); return $this->handler->render($uri, $strategy, $options); } /** * Renders a fragment. * * @param string $strategy A strategy name * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance * @param array $options An array of options * * @return string The fragment content * * @see Symfony\Component\HttpKernel\Fragment\FragmentHandler::render() */ public function renderFragmentStrategy($strategy, $uri, $options = array()) { return $this->handler->render($uri, $strategy, $options); } public function controller($controller, $attributes = array(), $query = array()) { return new ControllerReference($controller, $attributes, $query); } public function getName() { return 'http_kernel'; } } PK!KΙ5Symfony/Bridge/Twig/Extension/ExpressionExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\ExpressionLanguage\Expression; /** * ExpressionExtension gives a way to create Expressions from a template. * * @author Fabien Potencier */ class ExpressionExtension extends \Twig_Extension { /** * {@inheritdoc} */ public function getFunctions() { return array( new \Twig_SimpleFunction('expression', array($this, 'createExpression')), ); } public function createExpression($expression) { return new Expression($expression); } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'expression'; } } PK!`fS..2Symfony/Bridge/Twig/Extension/RoutingExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; /** * Provides integration of the Routing component with Twig. * * @author Fabien Potencier */ class RoutingExtension extends \Twig_Extension { private $generator; public function __construct(UrlGeneratorInterface $generator) { $this->generator = $generator; } /** * Returns a list of functions to add to the existing list. * * @return array An array of functions */ public function getFunctions() { return array( new \Twig_SimpleFunction('url', array($this, 'getUrl'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), new \Twig_SimpleFunction('path', array($this, 'getPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), ); } public function getPath($name, $parameters = array(), $relative = false) { return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH); } public function getUrl($name, $parameters = array(), $schemeRelative = false) { return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL); } /** * Determines at compile time whether the generated URL will be safe and thus * saving the unneeded automatic escaping for performance reasons. * * The URL generation process percent encodes non-alphanumeric characters. So there is no risk * that malicious/invalid characters are part of the URL. The only character within an URL that * must be escaped in html is the ampersand ("&") which separates query params. So we cannot mark * the URL generation as always safe, but only when we are sure there won't be multiple query * params. This is the case when there are none or only one constant parameter given. * E.g. we know beforehand this will be safe: * - path('route') * - path('route', {'param': 'value'}) * But the following may not: * - path('route', var) * - path('route', {'param': ['val1', 'val2'] }) // a sub-array * - path('route', {'param1': 'value1', 'param2': 'value2'}) * If param1 and param2 reference placeholder in the route, it would still be safe. But we don't know. * * @param \Twig_Node $argsNode The arguments of the path/url function * * @return array An array with the contexts the URL is safe */ public function isUrlGenerationSafe(\Twig_Node $argsNode) { // support named arguments $paramsNode = $argsNode->hasNode('parameters') ? $argsNode->getNode('parameters') : ( $argsNode->hasNode(1) ? $argsNode->getNode(1) : null ); if (null === $paramsNode || $paramsNode instanceof \Twig_Node_Expression_Array && count($paramsNode) <= 2 && (!$paramsNode->hasNode(1) || $paramsNode->getNode(1) instanceof \Twig_Node_Expression_Constant) ) { return array('html'); } return array(); } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'routing'; } } PK!5mm4Symfony/Bridge/Twig/Extension/StopwatchExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Bridge\Twig\TokenParser\StopwatchTokenParser; /** * Twig extension for the stopwatch helper. * * @author Wouter J */ class StopwatchExtension extends \Twig_Extension { private $stopwatch; public function __construct(Stopwatch $stopwatch = null) { $this->stopwatch = $stopwatch; } public function getStopwatch() { return $this->stopwatch; } public function getTokenParsers() { return array( /* * {% stopwatch foo %} * Some stuff which will be recorded on the timeline * {% endstopwatch %} */ new StopwatchTokenParser($this->stopwatch !== null), ); } public function getName() { return 'stopwatch'; } } PK!? 6Symfony/Bridge/Twig/Extension/TranslationExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Extension; use Symfony\Bridge\Twig\TokenParser\TransTokenParser; use Symfony\Bridge\Twig\TokenParser\TransChoiceTokenParser; use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor; use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor; /** * Provides integration of the Translation component with Twig. * * @author Fabien Potencier */ class TranslationExtension extends \Twig_Extension { private $translator; private $translationNodeVisitor; public function __construct(TranslatorInterface $translator, \Twig_NodeVisitorInterface $translationNodeVisitor = null) { if (!$translationNodeVisitor) { $translationNodeVisitor = new TranslationNodeVisitor(); } $this->translator = $translator; $this->translationNodeVisitor = $translationNodeVisitor; } public function getTranslator() { return $this->translator; } /** * {@inheritdoc} */ public function getFilters() { return array( new \Twig_SimpleFilter('trans', array($this, 'trans')), new \Twig_SimpleFilter('transchoice', array($this, 'transchoice')), ); } /** * Returns the token parser instance to add to the existing list. * * @return array An array of Twig_TokenParser instances */ public function getTokenParsers() { return array( // {% trans %}Symfony is great!{% endtrans %} new TransTokenParser(), // {% transchoice count %} // {0} There is no apples|{1} There is one apple|]1,Inf] There is {{ count }} apples // {% endtranschoice %} new TransChoiceTokenParser(), // {% trans_default_domain "foobar" %} new TransDefaultDomainTokenParser(), ); } /** * {@inheritdoc} */ public function getNodeVisitors() { return array($this->translationNodeVisitor, new TranslationDefaultDomainNodeVisitor()); } public function getTranslationNodeVisitor() { return $this->translationNodeVisitor; } public function trans($message, array $arguments = array(), $domain = null, $locale = null) { if (null === $domain) { $domain = 'messages'; } return $this->translator->trans($message, $arguments, $domain, $locale); } public function transchoice($message, $count, array $arguments = array(), $domain = null, $locale = null) { if (null === $domain) { $domain = 'messages'; } return $this->translator->transChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale); } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'translator'; } } PK!doo3Symfony/Bridge/Twig/Extension/SecurityExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\Security\Acl\Voter\FieldVote; use Symfony\Component\Security\Core\SecurityContextInterface; /** * SecurityExtension exposes security context features. * * @author Fabien Potencier */ class SecurityExtension extends \Twig_Extension { private $context; public function __construct(SecurityContextInterface $context = null) { $this->context = $context; } public function isGranted($role, $object = null, $field = null) { if (null === $this->context) { return false; } if (null !== $field) { $object = new FieldVote($object, $field); } return $this->context->isGranted($role, $object); } /** * {@inheritdoc} */ public function getFunctions() { return array( new \Twig_SimpleFunction('is_granted', array($this, 'isGranted')), ); } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'security'; } } PK! /Symfony/Bridge/Twig/Extension/CodeExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Extension; if (!defined('ENT_SUBSTITUTE')) { define('ENT_SUBSTITUTE', 8); } /** * Twig extension relate to PHP code and used by the profiler and the default exception templates. * * @author Fabien Potencier */ class CodeExtension extends \Twig_Extension { private $fileLinkFormat; private $rootDir; private $charset; /** * Constructor. * * @param string $fileLinkFormat The format for links to source files * @param string $rootDir The project root directory * @param string $charset The charset */ public function __construct($fileLinkFormat, $rootDir, $charset) { $this->fileLinkFormat = empty($fileLinkFormat) ? ini_get('xdebug.file_link_format') : $fileLinkFormat; $this->rootDir = str_replace('\\', '/', $rootDir).'/'; $this->charset = $charset; } /** * {@inheritdoc} */ public function getFilters() { return array( new \Twig_SimpleFilter('abbr_class', array($this, 'abbrClass'), array('is_safe' => array('html'))), new \Twig_SimpleFilter('abbr_method', array($this, 'abbrMethod'), array('is_safe' => array('html'))), new \Twig_SimpleFilter('format_args', array($this, 'formatArgs'), array('is_safe' => array('html'))), new \Twig_SimpleFilter('format_args_as_text', array($this, 'formatArgsAsText')), new \Twig_SimpleFilter('file_excerpt', array($this, 'fileExcerpt'), array('is_safe' => array('html'))), new \Twig_SimpleFilter('format_file', array($this, 'formatFile'), array('is_safe' => array('html'))), new \Twig_SimpleFilter('format_file_from_text', array($this, 'formatFileFromText'), array('is_safe' => array('html'))), new \Twig_SimpleFilter('file_link', array($this, 'getFileLink'), array('is_safe' => array('html'))), ); } public function abbrClass($class) { $parts = explode('\\', $class); $short = array_pop($parts); return sprintf("%s", $class, $short); } public function abbrMethod($method) { if (false !== strpos($method, '::')) { list($class, $method) = explode('::', $method, 2); $result = sprintf("%s::%s()", $this->abbrClass($class), $method); } elseif ('Closure' === $method) { $result = sprintf("%s", $method, $method); } else { $result = sprintf("%s()", $method, $method); } return $result; } /** * Formats an array as a string. * * @param array $args The argument array * * @return string */ public function formatArgs($args) { $result = array(); foreach ($args as $key => $item) { if ('object' === $item[0]) { $parts = explode('\\', $item[1]); $short = array_pop($parts); $formattedValue = sprintf("object(%s)", $item[1], $short); } elseif ('array' === $item[0]) { $formattedValue = sprintf("array(%s)", is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); } elseif ('string' === $item[0]) { $formattedValue = sprintf("'%s'", htmlspecialchars($item[1], ENT_QUOTES, $this->charset)); } elseif ('null' === $item[0]) { $formattedValue = 'null'; } elseif ('boolean' === $item[0]) { $formattedValue = ''.strtolower(var_export($item[1], true)).''; } elseif ('resource' === $item[0]) { $formattedValue = 'resource'; } else { $formattedValue = str_replace("\n", '', var_export(htmlspecialchars((string) $item[1], ENT_QUOTES, $this->charset), true)); } $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue); } return implode(', ', $result); } /** * Formats an array as a string. * * @param array $args The argument array * * @return string */ public function formatArgsAsText($args) { return strip_tags($this->formatArgs($args)); } /** * Returns an excerpt of a code file around the given line number. * * @param string $file A file path * @param int $line The selected line number * * @return string An HTML string */ public function fileExcerpt($file, $line) { if (is_readable($file)) { // highlight_file could throw warnings // see https://bugs.php.net/bug.php?id=25725 $code = @highlight_file($file, true); // remove main code/span tags $code = preg_replace('#^\s*(.*)\s*
#s', '\\1', $code); $content = preg_split('#
#', $code); $lines = array(); for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; $i++) { $lines[] = ''.self::fixCodeMarkup($content[$i - 1]).''; } return '
    '.implode("\n", $lines).'
'; } } /** * Formats a file path. * * @param string $file An absolute file path * @param integer $line The line number * @param string $text Use this text for the link rather than the file path * * @return string */ public function formatFile($file, $line, $text = null) { if (null === $text) { $file = trim($file); $text = $file; if (0 === strpos($text, $this->rootDir)) { $text = str_replace($this->rootDir, '', str_replace('\\', '/', $text)); $text = sprintf('kernel.root_dir/%s', $this->rootDir, $text); } } $text = "$text at line $line"; if (false !== $link = $this->getFileLink($file, $line)) { return sprintf('%s', htmlspecialchars($link, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset), $text); } return $text; } /** * Returns the link for a given file/line pair. * * @param string $file An absolute file path * @param integer $line The line number * * @return string A link of false */ public function getFileLink($file, $line) { if ($this->fileLinkFormat && is_file($file)) { return strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line)); } return false; } public function formatFileFromText($text) { $that = $this; return preg_replace_callback('/in ("|")?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) use ($that) { return 'in '.$that->formatFile($match[2], $match[3]); }, $text); } public function getName() { return 'code'; } protected static function fixCodeMarkup($line) { // ending tag from previous line $opening = strpos($line, ''); if (false !== $closing && (false === $opening || $closing < $opening)) { $line = substr_replace($line, '', $closing, 7); } // missing tag at the end of line $opening = strpos($line, ''); if (false !== $opening && (false === $closing || $closing > $opening)) { $line .= ''; } return $line; } } PK!^Ddd"Symfony/Bridge/Twig/TwigEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig; use Symfony\Component\Templating\EngineInterface; use Symfony\Component\Templating\StreamingEngineInterface; use Symfony\Component\Templating\TemplateNameParserInterface; use Symfony\Component\Templating\TemplateReferenceInterface; /** * This engine knows how to render Twig templates. * * @author Fabien Potencier */ class TwigEngine implements EngineInterface, StreamingEngineInterface { protected $environment; protected $parser; /** * Constructor. * * @param \Twig_Environment $environment A \Twig_Environment instance * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance */ public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser) { $this->environment = $environment; $this->parser = $parser; } /** * {@inheritdoc} * * It also supports \Twig_Template as name parameter. * * @throws \Twig_Error if something went wrong like a thrown exception while rendering the template */ public function render($name, array $parameters = array()) { return $this->load($name)->render($parameters); } /** * {@inheritdoc} * * It also supports \Twig_Template as name parameter. * * @throws \Twig_Error if something went wrong like a thrown exception while rendering the template */ public function stream($name, array $parameters = array()) { $this->load($name)->display($parameters); } /** * {@inheritdoc} * * It also supports \Twig_Template as name parameter. */ public function exists($name) { if ($name instanceof \Twig_Template) { return true; } $loader = $this->environment->getLoader(); if ($loader instanceof \Twig_ExistsLoaderInterface) { return $loader->exists((string) $name); } try { // cast possible TemplateReferenceInterface to string because the // EngineInterface supports them but Twig_LoaderInterface does not $loader->getSource((string) $name); } catch (\Twig_Error_Loader $e) { return false; } return true; } /** * {@inheritdoc} * * It also supports \Twig_Template as name parameter. */ public function supports($name) { if ($name instanceof \Twig_Template) { return true; } $template = $this->parser->parse($name); return 'twig' === $template->get('engine'); } /** * Loads the given template. * * @param string|TemplateReferenceInterface|\Twig_Template $name A template name or an instance of * TemplateReferenceInterface or \Twig_Template * * @return \Twig_TemplateInterface A \Twig_TemplateInterface instance * * @throws \InvalidArgumentException if the template does not exist */ protected function load($name) { if ($name instanceof \Twig_Template) { return $name; } try { return $this->environment->loadTemplate((string) $name); } catch (\Twig_Error_Loader $e) { throw new \InvalidArgumentException($e->getMessage(), $e->getCode(), $e); } } } PK!4˵(Symfony/Component/Finder/Shell/Shell.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Shell; /** * @author Jean-François Simon */ class Shell { const TYPE_UNIX = 1; const TYPE_DARWIN = 2; const TYPE_CYGWIN = 3; const TYPE_WINDOWS = 4; const TYPE_BSD = 5; /** * @var string|null */ private $type; /** * Returns guessed OS type. * * @return int */ public function getType() { if (null === $this->type) { $this->type = $this->guessType(); } return $this->type; } /** * Tests if a command is available. * * @param string $command * * @return bool */ public function testCommand($command) { if (self::TYPE_WINDOWS === $this->type) { // todo: find a way to test if Windows command exists return false; } if (!function_exists('exec')) { return false; } // todo: find a better way (command could not be available) exec('command -v '.$command, $output, $code); return 0 === $code && count($output) > 0; } /** * Guesses OS type. * * @return int */ private function guessType() { $os = strtolower(PHP_OS); if (false !== strpos($os, 'cygwin')) { return self::TYPE_CYGWIN; } if (false !== strpos($os, 'darwin')) { return self::TYPE_DARWIN; } if (false !== strpos($os, 'bsd')) { return self::TYPE_BSD; } if (0 === strpos($os, 'win')) { return self::TYPE_WINDOWS; } return self::TYPE_UNIX; } } PK!5K*Symfony/Component/Finder/Shell/Command.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Shell; /** * @author Jean-François Simon */ class Command { /** * @var Command|null */ private $parent; /** * @var array */ private $bits = array(); /** * @var array */ private $labels = array(); /** * @var \Closure|null */ private $errorHandler; /** * Constructor. * * @param Command|null $parent Parent command */ public function __construct(Command $parent = null) { $this->parent = $parent; } /** * Returns command as string. * * @return string */ public function __toString() { return $this->join(); } /** * Creates a new Command instance. * * @param Command|null $parent Parent command * * @return Command New Command instance */ public static function create(Command $parent = null) { return new self($parent); } /** * Escapes special chars from input. * * @param string $input A string to escape * * @return string The escaped string */ public static function escape($input) { return escapeshellcmd($input); } /** * Quotes input. * * @param string $input An argument string * * @return string The quoted string */ public static function quote($input) { return escapeshellarg($input); } /** * Appends a string or a Command instance. * * @param string|Command $bit * * @return Command The current Command instance */ public function add($bit) { $this->bits[] = $bit; return $this; } /** * Prepends a string or a command instance. * * @param string|Command $bit * * @return Command The current Command instance */ public function top($bit) { array_unshift($this->bits, $bit); foreach ($this->labels as $label => $index) { $this->labels[$label] += 1; } return $this; } /** * Appends an argument, will be quoted. * * @param string $arg * * @return Command The current Command instance */ public function arg($arg) { $this->bits[] = self::quote($arg); return $this; } /** * Appends escaped special command chars. * * @param string $esc * * @return Command The current Command instance */ public function cmd($esc) { $this->bits[] = self::escape($esc); return $this; } /** * Inserts a labeled command to feed later. * * @param string $label The unique label * * @return Command The current Command instance * * @throws \RuntimeException If label already exists */ public function ins($label) { if (isset($this->labels[$label])) { throw new \RuntimeException(sprintf('Label "%s" already exists.', $label)); } $this->bits[] = self::create($this); $this->labels[$label] = count($this->bits)-1; return $this->bits[$this->labels[$label]]; } /** * Retrieves a previously labeled command. * * @param string $label * * @return Command The labeled command * * @throws \RuntimeException */ public function get($label) { if (!isset($this->labels[$label])) { throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label)); } return $this->bits[$this->labels[$label]]; } /** * Returns parent command (if any). * * @return Command Parent command * * @throws \RuntimeException If command has no parent */ public function end() { if (null === $this->parent) { throw new \RuntimeException('Calling end on root command doesn\'t make sense.'); } return $this->parent; } /** * Counts bits stored in command. * * @return int The bits count */ public function length() { return count($this->bits); } /** * @param \Closure $errorHandler * * @return Command */ public function setErrorHandler(\Closure $errorHandler) { $this->errorHandler = $errorHandler; return $this; } /** * @return \Closure|null */ public function getErrorHandler() { return $this->errorHandler; } /** * Executes current command. * * @return array The command result * * @throws \RuntimeException */ public function execute() { if (null === $this->errorHandler) { exec($this->join(), $output); } else { $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes); $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY); if ($error = stream_get_contents($pipes[2])) { call_user_func($this->errorHandler, $error); } proc_close($process); } return $output ?: array(); } /** * Joins bits. * * @return string */ public function join() { return implode(' ', array_filter( array_map(function ($bit) { return $bit instanceof Command ? $bit->join() : ($bit ?: null); }, $this->bits), function ($bit) { return null !== $bit; } )); } /** * Insert a string or a Command instance before the bit at given position $index (index starts from 0). * * @param string|Command $bit * @param integer $index * * @return Command The current Command instance */ public function addAtIndex($bit, $index) { array_splice($this->bits, $index, 0, $bit); return $this; } } PK!59(Symfony/Component/Finder/SplFileInfo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Extends \SplFileInfo to support relative paths * * @author Fabien Potencier */ class SplFileInfo extends \SplFileInfo { private $relativePath; private $relativePathname; /** * Constructor * * @param string $file The file name * @param string $relativePath The relative path * @param string $relativePathname The relative path name */ public function __construct($file, $relativePath, $relativePathname) { parent::__construct($file); $this->relativePath = $relativePath; $this->relativePathname = $relativePathname; } /** * Returns the relative path * * @return string the relative path */ public function getRelativePath() { return $this->relativePath; } /** * Returns the relative path name * * @return string the relative path name */ public function getRelativePathname() { return $this->relativePathname; } /** * Returns the contents of the file * * @return string the contents of the file * * @throws \RuntimeException */ public function getContents() { $level = error_reporting(0); $content = file_get_contents($this->getPathname()); error_reporting($level); if (false === $content) { $error = error_get_last(); throw new \RuntimeException($error['message']); } return $content; } } PK!%uMPP'Symfony/Component/Finder/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; use Symfony\Component\Finder\Adapter\AdapterInterface; use Symfony\Component\Finder\Shell\Command; /** * @author Jean-François Simon */ class ShellCommandFailureException extends AdapterFailureException { /** * @var Command */ private $command; /** * @param AdapterInterface $adapter * @param Command $command * @param \Exception|null $previous */ public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null) { $this->command = $command; parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous); } /** * @return Command */ public function getCommand() { return $this->command; } } PK!79Symfony/Component/Finder/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ interface ExceptionInterface { /** * @return \Symfony\Component\Finder\Adapter\AdapterInterface */ public function getAdapter(); } PK!cWޫ<Symfony/Component/Finder/Exception/AccessDeniedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ class AccessDeniedException extends \UnexpectedValueException { } PK!>@>Symfony/Component/Finder/Exception/AdapterFailureException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; use Symfony\Component\Finder\Adapter\AdapterInterface; /** * Base exception for all adapter failures. * * @author Jean-François Simon */ class AdapterFailureException extends \RuntimeException implements ExceptionInterface { /** * @var \Symfony\Component\Finder\Adapter\AdapterInterface */ private $adapter; /** * @param AdapterInterface $adapter * @param string|null $message * @param \Exception|null $previous */ public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null) { $this->adapter = $adapter; parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous); } /** * {@inheritdoc} */ public function getAdapter() { return $this->adapter; } } PK!PDSymfony/Component/Finder/Exception/OperationNotPermitedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ class OperationNotPermitedException extends AdapterFailureException { } PK! 6Symfony/Component/Finder/Comparator/DateComparator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * DateCompare compiles date comparisons. * * @author Fabien Potencier */ class DateComparator extends Comparator { /** * Constructor. * * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood */ public function __construct($test) { if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); } try { $date = new \DateTime($matches[2]); $target = $date->format('U'); } catch (\Exception $e) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); } $operator = isset($matches[1]) ? $matches[1] : '=='; if ('since' === $operator || 'after' === $operator) { $operator = '>'; } if ('until' === $operator || 'before' === $operator) { $operator = '<'; } $this->setOperator($operator); $this->setTarget($target); } } PK!|Fz  2Symfony/Component/Finder/Comparator/Comparator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * Comparator. * * @author Fabien Potencier */ class Comparator { private $target; private $operator = '=='; /** * Gets the target value. * * @return string The target value */ public function getTarget() { return $this->target; } /** * Sets the target value. * * @param string $target The target value */ public function setTarget($target) { $this->target = $target; } /** * Gets the comparison operator. * * @return string The operator */ public function getOperator() { return $this->operator; } /** * Sets the comparison operator. * * @param string $operator A valid operator * * @throws \InvalidArgumentException */ public function setOperator($operator) { if (!$operator) { $operator = '=='; } if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) { throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); } $this->operator = $operator; } /** * Tests against the target. * * @param mixed $test A test value * * @return Boolean */ public function test($test) { switch ($this->operator) { case '>': return $test > $this->target; case '>=': return $test >= $this->target; case '<': return $test < $this->target; case '<=': return $test <= $this->target; case '!=': return $test != $this->target; } return $test == $this->target; } } PK!P  8Symfony/Component/Finder/Comparator/NumberComparator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * NumberComparator compiles a simple comparison to an anonymous * subroutine, which you can call with a value to be tested again. * * Now this would be very pointless, if NumberCompare didn't understand * magnitudes. * * The target value may use magnitudes of kilobytes (k, ki), * megabytes (m, mi), or gigabytes (g, gi). Those suffixed * with an i use the appropriate 2**n version in accordance with the * IEC standard: http://physics.nist.gov/cuu/Units/binary.html * * Based on the Perl Number::Compare module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp * * @see http://physics.nist.gov/cuu/Units/binary.html */ class NumberComparator extends Comparator { /** * Constructor. * * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood */ public function __construct($test) { if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test)); } $target = $matches[2]; if (!is_numeric($target)) { throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); } if (isset($matches[3])) { // magnitude switch (strtolower($matches[3])) { case 'k': $target *= 1000; break; case 'ki': $target *= 1024; break; case 'm': $target *= 1000000; break; case 'mi': $target *= 1024*1024; break; case 'g': $target *= 1000000000; break; case 'gi': $target *= 1024*1024*1024; break; } } $this->setTarget($target); $this->setOperator(isset($matches[1]) ? $matches[1] : '=='); } } PK!g@Mb b !Symfony/Component/Finder/Glob.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Glob matches globbing patterns against text. * * if match_glob("foo.*", "foo.bar") echo "matched\n"; * * // prints foo.bar and foo.baz * $regex = glob_to_regex("foo.*"); * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t) * { * if (/$regex/) echo "matched: $car\n"; * } * * Glob implements glob(3) style matching that can be used to match * against text, rather than fetching names from a filesystem. * * Based on the Perl Text::Glob module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp */ class Glob { /** * Returns a regexp which is the equivalent of the glob pattern. * * @param string $glob The glob pattern * @param Boolean $strictLeadingDot * @param Boolean $strictWildcardSlash * * @return string regex The regexp */ public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true) { $firstByte = true; $escaping = false; $inCurlies = 0; $regex = ''; $sizeGlob = strlen($glob); for ($i = 0; $i < $sizeGlob; $i++) { $car = $glob[$i]; if ($firstByte) { if ($strictLeadingDot && '.' !== $car) { $regex .= '(?=[^\.])'; } $firstByte = false; } if ('/' === $car) { $firstByte = true; } if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { $regex .= "\\$car"; } elseif ('*' === $car) { $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); } elseif ('?' === $car) { $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); } elseif ('{' === $car) { $regex .= $escaping ? '\\{' : '('; if (!$escaping) { ++$inCurlies; } } elseif ('}' === $car && $inCurlies) { $regex .= $escaping ? '}' : ')'; if (!$escaping) { --$inCurlies; } } elseif (',' === $car && $inCurlies) { $regex .= $escaping ? ',' : '|'; } elseif ('\\' === $car) { if ($escaping) { $regex .= '\\\\'; $escaping = false; } else { $escaping = true; } continue; } else { $regex .= $car; } $escaping = false; } return '#^'.$regex.'$#'; } } PK!dVV#Symfony/Component/Finder/Finder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; use Symfony\Component\Finder\Adapter\AdapterInterface; use Symfony\Component\Finder\Adapter\GnuFindAdapter; use Symfony\Component\Finder\Adapter\BsdFindAdapter; use Symfony\Component\Finder\Adapter\PhpAdapter; use Symfony\Component\Finder\Exception\ExceptionInterface; /** * Finder allows to build rules to find files and directories. * * It is a thin wrapper around several specialized iterator classes. * * All rules may be invoked several times. * * All methods return the current Finder object to allow easy chaining: * * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); * * @author Fabien Potencier * * @api */ class Finder implements \IteratorAggregate, \Countable { const IGNORE_VCS_FILES = 1; const IGNORE_DOT_FILES = 2; private $mode = 0; private $names = array(); private $notNames = array(); private $exclude = array(); private $filters = array(); private $depths = array(); private $sizes = array(); private $followLinks = false; private $sort = false; private $ignore = 0; private $dirs = array(); private $dates = array(); private $iterators = array(); private $contains = array(); private $notContains = array(); private $adapters = array(); private $paths = array(); private $notPaths = array(); private $ignoreUnreadableDirs = false; private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'); /** * Constructor. */ public function __construct() { $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; $this ->addAdapter(new GnuFindAdapter()) ->addAdapter(new BsdFindAdapter()) ->addAdapter(new PhpAdapter(), -50) ->setAdapter('php') ; } /** * Creates a new Finder. * * @return Finder A new Finder instance * * @api */ public static function create() { return new static(); } /** * Registers a finder engine implementation. * * @param AdapterInterface $adapter An adapter instance * @param integer $priority Highest is selected first * * @return Finder The current Finder instance */ public function addAdapter(Adapter\AdapterInterface $adapter, $priority = 0) { $this->adapters[$adapter->getName()] = array( 'adapter' => $adapter, 'priority' => $priority, 'selected' => false, ); return $this->sortAdapters(); } /** * Sets the selected adapter to the best one according to the current platform the code is run on. * * @return Finder The current Finder instance */ public function useBestAdapter() { $this->resetAdapterSelection(); return $this->sortAdapters(); } /** * Selects the adapter to use. * * @param string $name * * @throws \InvalidArgumentException * * @return Finder The current Finder instance */ public function setAdapter($name) { if (!isset($this->adapters[$name])) { throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name)); } $this->resetAdapterSelection(); $this->adapters[$name]['selected'] = true; return $this->sortAdapters(); } /** * Removes all adapters registered in the finder. * * @return Finder The current Finder instance */ public function removeAdapters() { $this->adapters = array(); return $this; } /** * Returns registered adapters ordered by priority without extra information. * * @return AdapterInterface[] */ public function getAdapters() { return array_values(array_map(function (array $adapter) { return $adapter['adapter']; }, $this->adapters)); } /** * Restricts the matching to directories only. * * @return Finder The current Finder instance * * @api */ public function directories() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; return $this; } /** * Restricts the matching to files only. * * @return Finder The current Finder instance * * @api */ public function files() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; return $this; } /** * Adds tests for the directory depth. * * Usage: * * $finder->depth('> 1') // the Finder will start matching at level 1. * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. * * @param int $level The depth level expression * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\DepthRangeFilterIterator * @see Symfony\Component\Finder\Comparator\NumberComparator * * @api */ public function depth($level) { $this->depths[] = new Comparator\NumberComparator($level); return $this; } /** * Adds tests for file dates (last modified). * * The date must be something that strtotime() is able to parse: * * $finder->date('since yesterday'); * $finder->date('until 2 days ago'); * $finder->date('> now - 2 hours'); * $finder->date('>= 2005-10-15'); * * @param string $date A date rage string * * @return Finder The current Finder instance * * @see strtotime * @see Symfony\Component\Finder\Iterator\DateRangeFilterIterator * @see Symfony\Component\Finder\Comparator\DateComparator * * @api */ public function date($date) { $this->dates[] = new Comparator\DateComparator($date); return $this; } /** * Adds rules that files must match. * * You can use patterns (delimited with / sign), globs or simple strings. * * $finder->name('*.php') * $finder->name('/\.php$/') // same as above * $finder->name('test.php') * * @param string $pattern A pattern (a regexp, a glob, or a string) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator * * @api */ public function name($pattern) { $this->names[] = $pattern; return $this; } /** * Adds rules that files must not match. * * @param string $pattern A pattern (a regexp, a glob, or a string) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator * * @api */ public function notName($pattern) { $this->notNames[] = $pattern; return $this; } /** * Adds tests that file contents must match. * * Strings or PCRE patterns can be used: * * $finder->contains('Lorem ipsum') * $finder->contains('/Lorem ipsum/i') * * @param string $pattern A pattern (string or regexp) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator */ public function contains($pattern) { $this->contains[] = $pattern; return $this; } /** * Adds tests that file contents must not match. * * Strings or PCRE patterns can be used: * * $finder->notContains('Lorem ipsum') * $finder->notContains('/Lorem ipsum/i') * * @param string $pattern A pattern (string or regexp) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator */ public function notContains($pattern) { $this->notContains[] = $pattern; return $this; } /** * Adds rules that filenames must match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->path('some/special/dir') * $finder->path('/some\/special\/dir/') // same as above * * Use only / as dirname separator. * * @param string $pattern A pattern (a regexp or a string) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator */ public function path($pattern) { $this->paths[] = $pattern; return $this; } /** * Adds rules that filenames must not match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->notPath('some/special/dir') * $finder->notPath('/some\/special\/dir/') // same as above * * Use only / as dirname separator. * * @param string $pattern A pattern (a regexp or a string) * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator */ public function notPath($pattern) { $this->notPaths[] = $pattern; return $this; } /** * Adds tests for file sizes. * * $finder->size('> 10K'); * $finder->size('<= 1Ki'); * $finder->size(4); * * @param string $size A size range string * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SizeRangeFilterIterator * @see Symfony\Component\Finder\Comparator\NumberComparator * * @api */ public function size($size) { $this->sizes[] = new Comparator\NumberComparator($size); return $this; } /** * Excludes directories. * * @param string|array $dirs A directory path or an array of directories * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator * * @api */ public function exclude($dirs) { $this->exclude = array_merge($this->exclude, (array) $dirs); return $this; } /** * Excludes "hidden" directories and files (starting with a dot). * * @param Boolean $ignoreDotFiles Whether to exclude "hidden" files or not * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator * * @api */ public function ignoreDotFiles($ignoreDotFiles) { if ($ignoreDotFiles) { $this->ignore = $this->ignore | static::IGNORE_DOT_FILES; } else { $this->ignore = $this->ignore & ~static::IGNORE_DOT_FILES; } return $this; } /** * Forces the finder to ignore version control directories. * * @param Boolean $ignoreVCS Whether to exclude VCS files or not * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator * * @api */ public function ignoreVCS($ignoreVCS) { if ($ignoreVCS) { $this->ignore = $this->ignore | static::IGNORE_VCS_FILES; } else { $this->ignore = $this->ignore & ~static::IGNORE_VCS_FILES; } return $this; } /** * Adds VCS patterns. * * @see ignoreVCS * * @param string|string[] $pattern VCS patterns to ignore */ public static function addVCSPattern($pattern) { foreach ((array) $pattern as $p) { self::$vcsPatterns[] = $p; } self::$vcsPatterns = array_unique(self::$vcsPatterns); } /** * Sorts files and directories by an anonymous function. * * The anonymous function receives two \SplFileInfo instances to compare. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @param \Closure $closure An anonymous function * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sort(\Closure $closure) { $this->sort = $closure; return $this; } /** * Sorts files and directories by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByName() { $this->sort = Iterator\SortableIterator::SORT_BY_NAME; return $this; } /** * Sorts files and directories by type (directories before files), then by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByType() { $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; return $this; } /** * Sorts files and directories by the last accessed time. * * This is the time that the file was last accessed, read or written to. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByAccessedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; return $this; } /** * Sorts files and directories by the last inode changed time. * * This is the time that the inode information was last modified (permissions, owner, group or other metadata). * * On Windows, since inode is not available, changed time is actually the file creation time. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByChangedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; return $this; } /** * Sorts files and directories by the last modified time. * * This is the last time the actual contents of the file were last modified. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\SortableIterator * * @api */ public function sortByModifiedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; return $this; } /** * Filters the iterator with an anonymous function. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @param \Closure $closure An anonymous function * * @return Finder The current Finder instance * * @see Symfony\Component\Finder\Iterator\CustomFilterIterator * * @api */ public function filter(\Closure $closure) { $this->filters[] = $closure; return $this; } /** * Forces the following of symlinks. * * @return Finder The current Finder instance * * @api */ public function followLinks() { $this->followLinks = true; return $this; } /** * Tells finder to ignore unreadable directories. * * By default, scanning unreadable directories content throws an AccessDeniedException. * * @param boolean $ignore * * @return Finder The current Finder instance */ public function ignoreUnreadableDirs($ignore = true) { $this->ignoreUnreadableDirs = (Boolean) $ignore; return $this; } /** * Searches files and directories which match defined rules. * * @param string|array $dirs A directory path or an array of directories * * @return Finder The current Finder instance * * @throws \InvalidArgumentException if one of the directories does not exist * * @api */ public function in($dirs) { $resolvedDirs = array(); foreach ((array) $dirs as $dir) { if (is_dir($dir)) { $resolvedDirs[] = $dir; } elseif ($glob = glob($dir, GLOB_ONLYDIR)) { $resolvedDirs = array_merge($resolvedDirs, $glob); } else { throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir)); } } $this->dirs = array_merge($this->dirs, $resolvedDirs); return $this; } /** * Returns an Iterator for the current Finder configuration. * * This method implements the IteratorAggregate interface. * * @return \Iterator An iterator * * @throws \LogicException if the in() method has not been called */ public function getIterator() { if (0 === count($this->dirs) && 0 === count($this->iterators)) { throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); } if (1 === count($this->dirs) && 0 === count($this->iterators)) { return $this->searchInDirectory($this->dirs[0]); } $iterator = new \AppendIterator(); foreach ($this->dirs as $dir) { $iterator->append($this->searchInDirectory($dir)); } foreach ($this->iterators as $it) { $iterator->append($it); } return $iterator; } /** * Appends an existing set of files/directories to the finder. * * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. * * @param mixed $iterator * * @return Finder The finder * * @throws \InvalidArgumentException When the given argument is not iterable. */ public function append($iterator) { if ($iterator instanceof \IteratorAggregate) { $this->iterators[] = $iterator->getIterator(); } elseif ($iterator instanceof \Iterator) { $this->iterators[] = $iterator; } elseif ($iterator instanceof \Traversable || is_array($iterator)) { $it = new \ArrayIterator(); foreach ($iterator as $file) { $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file)); } $this->iterators[] = $it; } else { throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); } return $this; } /** * Counts all the results collected by the iterators. * * @return int */ public function count() { return iterator_count($this->getIterator()); } /** * @return Finder The current Finder instance */ private function sortAdapters() { uasort($this->adapters, function (array $a, array $b) { if ($a['selected'] || $b['selected']) { return $a['selected'] ? -1 : 1; } return $a['priority'] > $b['priority'] ? -1 : 1; }); return $this; } /** * @param $dir * * @return \Iterator * * @throws \RuntimeException When none of the adapters are supported */ private function searchInDirectory($dir) { if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { $this->exclude = array_merge($this->exclude, self::$vcsPatterns); } if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { $this->notPaths[] = '#(^|/)\..+(/|$)#'; } foreach ($this->adapters as $adapter) { if ($adapter['adapter']->isSupported()) { try { return $this ->buildAdapter($adapter['adapter']) ->searchInDirectory($dir); } catch (ExceptionInterface $e) {} } } throw new \RuntimeException('No supported adapter found.'); } /** * @param AdapterInterface $adapter * * @return AdapterInterface */ private function buildAdapter(AdapterInterface $adapter) { return $adapter ->setFollowLinks($this->followLinks) ->setDepths($this->depths) ->setMode($this->mode) ->setExclude($this->exclude) ->setNames($this->names) ->setNotNames($this->notNames) ->setContains($this->contains) ->setNotContains($this->notContains) ->setSizes($this->sizes) ->setDates($this->dates) ->setFilters($this->filters) ->setSort($this->sort) ->setPath($this->paths) ->setNotPath($this->notPaths) ->ignoreUnreadableDirs($this->ignoreUnreadableDirs); } /** * Unselects all adapters. */ private function resetAdapterSelection() { $this->adapters = array_map(function (array $properties) { $properties['selected'] = false; return $properties; }, $this->adapters); } } PK!ils_>Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * DepthRangeFilterIterator limits the directory depth. * * @author Fabien Potencier */ class DepthRangeFilterIterator extends FilterIterator { private $minDepth = 0; /** * Constructor. * * @param \RecursiveIteratorIterator $iterator The Iterator to filter * @param int $minDepth The min depth * @param int $maxDepth The max depth */ public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX) { $this->minDepth = $minDepth; $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { return $this->getInnerIterator()->getDepth() >= $this->minDepth; } } PK!ɔ 7Symfony/Component/Finder/Iterator/FilePathsIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\SplFileInfo; /** * Iterate over shell command result. * * @author Jean-François Simon */ class FilePathsIterator extends \ArrayIterator { /** * @var string */ private $baseDir; /** * @var int */ private $baseDirLength; /** * @var string */ private $subPath; /** * @var string */ private $subPathname; /** * @var SplFileInfo */ private $current; /** * @param array $paths List of paths returned by shell command * @param string $baseDir Base dir for relative path building */ public function __construct(array $paths, $baseDir) { $this->baseDir = $baseDir; $this->baseDirLength = strlen($baseDir); parent::__construct($paths); } /** * @param string $name * @param array $arguments * * @return mixed */ public function __call($name, array $arguments) { return call_user_func_array(array($this->current(), $name), $arguments); } /** * Return an instance of SplFileInfo with support for relative paths. * * @return SplFileInfo File information */ public function current() { return $this->current; } /** * @return string */ public function key() { return $this->current->getPathname(); } public function next() { parent::next(); $this->buildProperties(); } public function rewind() { parent::rewind(); $this->buildProperties(); } /** * @return string */ public function getSubPath() { return $this->subPath; } /** * @return string */ public function getSubPathname() { return $this->subPathname; } private function buildProperties() { $absolutePath = parent::current(); if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) { $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\'); $dir = dirname($this->subPathname); $this->subPath = '.' === $dir ? '' : $dir; } else { $this->subPath = $this->subPathname = ''; } $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname); } } PK!,G4Symfony/Component/Finder/Iterator/FilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * This iterator just overrides the rewind method in order to correct a PHP bug. * * @see https://bugs.php.net/bug.php?id=49104 * * @author Alex Bogomazov */ abstract class FilterIterator extends \FilterIterator { /** * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after * rewind in some cases. * * @see FilterIterator::rewind() */ public function rewind() { $iterator = $this; while ($iterator instanceof \OuterIterator) { $innerIterator = $iterator->getInnerIterator(); if ($innerIterator instanceof RecursiveDirectoryIterator) { if ($innerIterator->isRewindable()) { $innerIterator->next(); $innerIterator->rewind(); } } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) { $iterator->getInnerIterator()->next(); $iterator->getInnerIterator()->rewind(); } $iterator = $iterator->getInnerIterator(); } parent::rewind(); } } PK!ʽ?Symfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). * * @author Fabien Potencier * @author Włodzimierz Gajda */ class FilecontentFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { if (!$this->matchRegexps && !$this->noMatchRegexps) { return true; } $fileinfo = $this->current(); if ($fileinfo->isDir() || !$fileinfo->isReadable()) { return false; } $content = $fileinfo->getContents(); if (!$content) { return false; } // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $content)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $content)) { return true; } } } return $match; } /** * Converts string to regexp if necessary. * * @param string $str Pattern: string or regexp * * @return string regexp corresponding to a given string or regexp */ protected function toRegex($str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } PK! @Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Expression\Expression; /** * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). * * @author Fabien Potencier */ abstract class MultiplePcreFilterIterator extends FilterIterator { protected $matchRegexps = array(); protected $noMatchRegexps = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $matchPatterns An array of patterns that need to match * @param array $noMatchPatterns An array of patterns that need to not match */ public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) { foreach ($matchPatterns as $pattern) { $this->matchRegexps[] = $this->toRegex($pattern); } foreach ($noMatchPatterns as $pattern) { $this->noMatchRegexps[] = $this->toRegex($pattern); } parent::__construct($iterator); } /** * Checks whether the string is a regex. * * @param string $str * * @return Boolean Whether the given string is a regex */ protected function isRegex($str) { return Expression::create($str)->isRegex(); } /** * Converts string into regexp. * * @param string $str Pattern * * @return string regexp corresponding to a given string */ abstract protected function toRegex($str); } PK!z":Symfony/Component/Finder/Iterator/CustomFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * CustomFilterIterator filters files by applying anonymous functions. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @author Fabien Potencier */ class CustomFilterIterator extends FilterIterator { private $filters = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $filters An array of PHP callbacks * * @throws \InvalidArgumentException */ public function __construct(\Iterator $iterator, array $filters) { foreach ($filters as $filter) { if (!is_callable($filter)) { throw new \InvalidArgumentException('Invalid PHP callback.'); } } $this->filters = $filters; parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); foreach ($this->filters as $filter) { if (false === call_user_func($filter, $fileinfo)) { return false; } } return true; } } PK!{^ǽ<Symfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Expression\Expression; /** * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). * * @author Fabien Potencier */ class FilenameFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $filename = $this->current()->getFilename(); // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $filename)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $filename)) { return true; } } } return $match; } /** * Converts glob to regexp. * * PCRE patterns are left unchanged. * Glob strings are transformed with Glob::toRegex(). * * @param string $str Pattern: glob or regexp * * @return string regexp corresponding to a given glob or regexp */ protected function toRegex($str) { return Expression::create($str)->getRegex()->render(); } } PK!dDSymfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * ExcludeDirectoryFilterIterator filters out directories. * * @author Fabien Potencier */ class ExcludeDirectoryFilterIterator extends FilterIterator { private $patterns = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $directories An array of directories to exclude */ public function __construct(\Iterator $iterator, array $directories) { foreach ($directories as $directory) { $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#'; } parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); $path = strtr($path, '\\', '/'); foreach ($this->patterns as $pattern) { if (preg_match($pattern, $path)) { return false; } } return true; } } PK!xP=Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\NumberComparator; /** * SizeRangeFilterIterator filters out files that are not in the given size range. * * @author Fabien Potencier */ class SizeRangeFilterIterator extends FilterIterator { private $comparators = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param NumberComparator[] $comparators An array of NumberComparator instances */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (!$fileinfo->isFile()) { return true; } $filesize = $fileinfo->getSize(); foreach ($this->comparators as $compare) { if (!$compare->test($filesize)) { return false; } } return true; } } PK! U=Symfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\DateComparator; /** * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). * * @author Fabien Potencier */ class DateRangeFilterIterator extends FilterIterator { private $comparators = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param DateComparator[] $comparators An array of DateComparator instances */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (!$fileinfo->isFile()) { return true; } $filedate = $fileinfo->getMTime(); foreach ($this->comparators as $compare) { if (!$compare->test($filedate)) { return false; } } return true; } } PK!n bb<Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FileTypeFilterIterator only keeps files, directories, or both. * * @author Fabien Potencier */ class FileTypeFilterIterator extends FilterIterator { const ONLY_FILES = 1; const ONLY_DIRECTORIES = 2; private $mode; /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param integer $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) */ public function __construct(\Iterator $iterator, $mode) { $this->mode = $mode; parent::__construct($iterator); } /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { return false; } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { return false; } return true; } } PK!j 6Symfony/Component/Finder/Iterator/SortableIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * SortableIterator applies a sort on a given Iterator. * * @author Fabien Potencier */ class SortableIterator implements \IteratorAggregate { const SORT_BY_NAME = 1; const SORT_BY_TYPE = 2; const SORT_BY_ACCESSED_TIME = 3; const SORT_BY_CHANGED_TIME = 4; const SORT_BY_MODIFIED_TIME = 5; private $iterator; private $sort; /** * Constructor. * * @param \Traversable $iterator The Iterator to filter * @param integer|callback $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) * * @throws \InvalidArgumentException */ public function __construct(\Traversable $iterator, $sort) { $this->iterator = $iterator; if (self::SORT_BY_NAME === $sort) { $this->sort = function ($a, $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }; } elseif (self::SORT_BY_TYPE === $sort) { $this->sort = function ($a, $b) { if ($a->isDir() && $b->isFile()) { return -1; } elseif ($a->isFile() && $b->isDir()) { return 1; } return strcmp($a->getRealpath(), $b->getRealpath()); }; } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getATime() > $b->getATime()); }; } elseif (self::SORT_BY_CHANGED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getCTime() > $b->getCTime()); }; } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getMTime() > $b->getMTime()); }; } elseif (is_callable($sort)) { $this->sort = $sort; } else { throw new \InvalidArgumentException('The SortableIterator takes a PHP callback or a valid built-in sort algorithm as an argument.'); } } public function getIterator() { $array = iterator_to_array($this->iterator, true); uasort($array, $this->sort); return new \ArrayIterator($array); } } PK!)8Symfony/Component/Finder/Iterator/PathFilterIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * PathFilterIterator filters files by path patterns (e.g. some/special/dir). * * @author Fabien Potencier * @author Włodzimierz Gajda */ class PathFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return Boolean true if the value should be kept, false otherwise */ public function accept() { $filename = $this->current()->getRelativePathname(); if (defined('PHP_WINDOWS_VERSION_MAJOR')) { $filename = strtr($filename, '\\', '/'); } // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $filename)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $filename)) { return true; } } } return $match; } /** * Converts strings to regexp. * * PCRE patterns are left unchanged. * * Default conversion: * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' * * Use only / as directory separator (on Windows also). * * @param string $str Pattern: regexp or dirname. * * @return string regexp corresponding to a given string or regexp */ protected function toRegex($str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } PK!6s @Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Exception\AccessDeniedException; use Symfony\Component\Finder\SplFileInfo; /** * Extends the \RecursiveDirectoryIterator to support relative paths * * @author Victor Berchet */ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator { /** * @var boolean */ private $ignoreUnreadableDirs; /** * @var Boolean */ private $rewindable; /** * Constructor. * * @param string $path * @param int $flags * @param boolean $ignoreUnreadableDirs * * @throws \RuntimeException */ public function __construct($path, $flags, $ignoreUnreadableDirs = false) { if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { throw new \RuntimeException('This iterator only support returning current as fileinfo.'); } parent::__construct($path, $flags); $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; } /** * Return an instance of SplFileInfo with support for relative paths * * @return SplFileInfo File information */ public function current() { return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname()); } /** * @return \RecursiveIterator * * @throws AccessDeniedException */ public function getChildren() { try { return parent::getChildren(); } catch (\UnexpectedValueException $e) { if ($this->ignoreUnreadableDirs) { // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. return new \RecursiveArrayIterator(array()); } else { throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); } } } /** * Do nothing for non rewindable stream */ public function rewind() { if (false === $this->isRewindable()) { return; } // @see https://bugs.php.net/bug.php?id=49104 parent::next(); parent::rewind(); } /** * Checks if the stream is rewindable. * * @return Boolean true when the stream is rewindable, false otherwise */ public function isRewindable() { if (null !== $this->rewindable) { return $this->rewindable; } if (false !== $stream = @opendir($this->getPath())) { $infos = stream_get_meta_data($stream); closedir($stream); if ($infos['seekable']) { return $this->rewindable = true; } } return $this->rewindable = false; } } PK! & & 2Symfony/Component/Finder/Expression/Expression.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Expression implements ValueInterface { const TYPE_REGEX = 1; const TYPE_GLOB = 2; /** * @var ValueInterface */ private $value; /** * @param string $expr * * @return Expression */ public static function create($expr) { return new self($expr); } /** * @param string $expr */ public function __construct($expr) { try { $this->value = Regex::create($expr); } catch (\InvalidArgumentException $e) { $this->value = new Glob($expr); } } /** * @return string */ public function __toString() { return $this->render(); } /** * {@inheritdoc} */ public function render() { return $this->value->render(); } /** * {@inheritdoc} */ public function renderPattern() { return $this->value->renderPattern(); } /** * @return bool */ public function isCaseSensitive() { return $this->value->isCaseSensitive(); } /** * @return int */ public function getType() { return $this->value->getType(); } /** * {@inheritdoc} */ public function prepend($expr) { $this->value->prepend($expr); return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->value->append($expr); return $this; } /** * @return bool */ public function isRegex() { return self::TYPE_REGEX === $this->value->getType(); } /** * @return bool */ public function isGlob() { return self::TYPE_GLOB === $this->value->getType(); } /** * @throws \LogicException * * @return Glob */ public function getGlob() { if (self::TYPE_GLOB !== $this->value->getType()) { throw new \LogicException('Regex can\'t be transformed to glob.'); } return $this->value; } /** * @return Regex */ public function getRegex() { return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex(); } } PK!"HH6Symfony/Component/Finder/Expression/ValueInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ interface ValueInterface { /** * Renders string representation of expression. * * @return string */ public function render(); /** * Renders string representation of pattern. * * @return string */ public function renderPattern(); /** * Returns value case sensitivity. * * @return bool */ public function isCaseSensitive(); /** * Returns expression type. * * @return int */ public function getType(); /** * @param string $expr * * @return ValueInterface */ public function prepend($expr); /** * @param string $expr * * @return ValueInterface */ public function append($expr); } PK!E,Symfony/Component/Finder/Expression/Glob.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Glob implements ValueInterface { /** * @var string */ private $pattern; /** * @param string $pattern */ public function __construct($pattern) { $this->pattern = $pattern; } /** * {@inheritdoc} */ public function render() { return $this->pattern; } /** * {@inheritdoc} */ public function renderPattern() { return $this->pattern; } /** * {@inheritdoc} */ public function getType() { return Expression::TYPE_GLOB; } /** * {@inheritdoc} */ public function isCaseSensitive() { return true; } /** * {@inheritdoc} */ public function prepend($expr) { $this->pattern = $expr.$this->pattern; return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->pattern .= $expr; return $this; } /** * Tests if glob is expandable ("*.{a,b}" syntax). * * @return bool */ public function isExpandable() { return false !== strpos($this->pattern, '{') && false !== strpos($this->pattern, '}'); } /** * @param bool $strictLeadingDot * @param bool $strictWildcardSlash * * @return Regex */ public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true) { $firstByte = true; $escaping = false; $inCurlies = 0; $regex = ''; $sizeGlob = strlen($this->pattern); for ($i = 0; $i < $sizeGlob; $i++) { $car = $this->pattern[$i]; if ($firstByte) { if ($strictLeadingDot && '.' !== $car) { $regex .= '(?=[^\.])'; } $firstByte = false; } if ('/' === $car) { $firstByte = true; } if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { $regex .= "\\$car"; } elseif ('*' === $car) { $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); } elseif ('?' === $car) { $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); } elseif ('{' === $car) { $regex .= $escaping ? '\\{' : '('; if (!$escaping) { ++$inCurlies; } } elseif ('}' === $car && $inCurlies) { $regex .= $escaping ? '}' : ')'; if (!$escaping) { --$inCurlies; } } elseif (',' === $car && $inCurlies) { $regex .= $escaping ? ',' : '|'; } elseif ('\\' === $car) { if ($escaping) { $regex .= '\\\\'; $escaping = false; } else { $escaping = true; } continue; } else { $regex .= $car; } $escaping = false; } return new Regex('^'.$regex.'$'); } } PK!(-Symfony/Component/Finder/Expression/Regex.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Regex implements ValueInterface { const START_FLAG = '^'; const END_FLAG = '$'; const BOUNDARY = '~'; const JOKER = '.*'; const ESCAPING = '\\'; /** * @var string */ private $pattern; /** * @var array */ private $options; /** * @var bool */ private $startFlag; /** * @var bool */ private $endFlag; /** * @var bool */ private $startJoker; /** * @var bool */ private $endJoker; /** * @param string $expr * * @return Regex * * @throws \InvalidArgumentException */ public static function create($expr) { if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) { $start = substr($m[1], 0, 1); $end = substr($m[1], -1); if ( ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) || ($start === '{' && $end === '}') || ($start === '(' && $end === ')') ) { return new self(substr($m[1], 1, -1), $m[2], $end); } } throw new \InvalidArgumentException('Given expression is not a regex.'); } /** * @param string $pattern * @param string $options * @param string $delimiter */ public function __construct($pattern, $options = '', $delimiter = null) { if (null !== $delimiter) { // removes delimiter escaping $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern); } $this->parsePattern($pattern); $this->options = $options; } /** * @return string */ public function __toString() { return $this->render(); } /** * {@inheritdoc} */ public function render() { return self::BOUNDARY .$this->renderPattern() .self::BOUNDARY .$this->options; } /** * {@inheritdoc} */ public function renderPattern() { return ($this->startFlag ? self::START_FLAG : '') .($this->startJoker ? self::JOKER : '') .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern) .($this->endJoker ? self::JOKER : '') .($this->endFlag ? self::END_FLAG : ''); } /** * {@inheritdoc} */ public function isCaseSensitive() { return !$this->hasOption('i'); } /** * {@inheritdoc} */ public function getType() { return Expression::TYPE_REGEX; } /** * {@inheritdoc} */ public function prepend($expr) { $this->pattern = $expr.$this->pattern; return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->pattern .= $expr; return $this; } /** * @param string $option * * @return bool */ public function hasOption($option) { return false !== strpos($this->options, $option); } /** * @param string $option * * @return Regex */ public function addOption($option) { if (!$this->hasOption($option)) { $this->options.= $option; } return $this; } /** * @param string $option * * @return Regex */ public function removeOption($option) { $this->options = str_replace($option, '', $this->options); return $this; } /** * @param bool $startFlag * * @return Regex */ public function setStartFlag($startFlag) { $this->startFlag = $startFlag; return $this; } /** * @return bool */ public function hasStartFlag() { return $this->startFlag; } /** * @param bool $endFlag * * @return Regex */ public function setEndFlag($endFlag) { $this->endFlag = (bool) $endFlag; return $this; } /** * @return bool */ public function hasEndFlag() { return $this->endFlag; } /** * @param bool $startJoker * * @return Regex */ public function setStartJoker($startJoker) { $this->startJoker = $startJoker; return $this; } /** * @return bool */ public function hasStartJoker() { return $this->startJoker; } /** * @param bool $endJoker * * @return Regex */ public function setEndJoker($endJoker) { $this->endJoker = (bool) $endJoker; return $this; } /** * @return bool */ public function hasEndJoker() { return $this->endJoker; } /** * @param array $replacement * * @return Regex */ public function replaceJokers($replacement) { $replace = function ($subject) use ($replacement) { $subject = $subject[0]; $replace = 0 === substr_count($subject, '\\') % 2; return $replace ? str_replace('.', $replacement, $subject) : $subject; }; $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern); return $this; } /** * @param string $pattern */ private function parsePattern($pattern) { if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) { $pattern = substr($pattern, 1); } if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) { $pattern = substr($pattern, 2); } if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) { $pattern = substr($pattern, 0, -1); } if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) { $pattern = substr($pattern, 0, -2); } $this->pattern = $pattern; } } PK!9!2{ { /Symfony/Component/Finder/Adapter/PhpAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Iterator; /** * PHP finder engine implementation. * * @author Jean-François Simon */ class PhpAdapter extends AbstractAdapter { /** * {@inheritdoc} */ public function searchInDirectory($dir) { $flags = \RecursiveDirectoryIterator::SKIP_DOTS; if ($this->followLinks) { $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; } $iterator = new \RecursiveIteratorIterator( new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs), \RecursiveIteratorIterator::SELF_FIRST ); if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) { $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth); } if ($this->mode) { $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); } if ($this->exclude) { $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); } if ($this->names || $this->notNames) { $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); } if ($this->contains || $this->notContains) { $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->sizes) { $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); } if ($this->dates) { $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); } if ($this->filters) { $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if ($this->sort) { $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); $iterator = $iteratorAggregate->getIterator(); } if ($this->paths || $this->notPaths) { $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); } return $iterator; } /** * {@inheritdoc} */ public function getName() { return 'php'; } /** * {@inheritdoc} */ protected function canBeUsed() { return true; } } PK! 5Symfony/Component/Finder/Adapter/AdapterInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; /** * @author Jean-François Simon */ interface AdapterInterface { /** * @param Boolean $followLinks * * @return AdapterInterface Current instance */ public function setFollowLinks($followLinks); /** * @param integer $mode * * @return AdapterInterface Current instance */ public function setMode($mode); /** * @param array $exclude * * @return AdapterInterface Current instance */ public function setExclude(array $exclude); /** * @param array $depths * * @return AdapterInterface Current instance */ public function setDepths(array $depths); /** * @param array $names * * @return AdapterInterface Current instance */ public function setNames(array $names); /** * @param array $notNames * * @return AdapterInterface Current instance */ public function setNotNames(array $notNames); /** * @param array $contains * * @return AdapterInterface Current instance */ public function setContains(array $contains); /** * @param array $notContains * * @return AdapterInterface Current instance */ public function setNotContains(array $notContains); /** * @param array $sizes * * @return AdapterInterface Current instance */ public function setSizes(array $sizes); /** * @param array $dates * * @return AdapterInterface Current instance */ public function setDates(array $dates); /** * @param array $filters * * @return AdapterInterface Current instance */ public function setFilters(array $filters); /** * @param \Closure|integer $sort * * @return AdapterInterface Current instance */ public function setSort($sort); /** * @param array $paths * * @return AdapterInterface Current instance */ public function setPath(array $paths); /** * @param array $notPaths * * @return AdapterInterface Current instance */ public function setNotPath(array $notPaths); /** * @param boolean $ignore * * @return AdapterInterface Current instance */ public function ignoreUnreadableDirs($ignore = true); /** * @param string $dir * * @return \Iterator Result iterator */ public function searchInDirectory($dir); /** * Tests adapter support for current platform. * * @return Boolean */ public function isSupported(); /** * Returns adapter name. * * @return string */ public function getName(); } PK!kA 3Symfony/Component/Finder/Adapter/BsdFindAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using BSD find command. * * @author Jean-François Simon */ class BsdFindAdapter extends AbstractFindAdapter { /** * {@inheritdoc} */ public function getName() { return 'bsd_find'; } /** * {@inheritdoc} */ protected function canBeUsed() { return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed(); } /** * {@inheritdoc} */ protected function buildFormatSorting(Command $command, $sort) { switch ($sort) { case SortableIterator::SORT_BY_NAME: $command->ins('sort')->add('| sort'); return; case SortableIterator::SORT_BY_TYPE: $format = '%HT'; break; case SortableIterator::SORT_BY_ACCESSED_TIME: $format = '%a'; break; case SortableIterator::SORT_BY_CHANGED_TIME: $format = '%c'; break; case SortableIterator::SORT_BY_MODIFIED_TIME: $format = '%m'; break; default: throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); } $command ->add('-print0 | xargs -0 stat -f') ->arg($format.'%t%N') ->add('| sort | cut -f 2'); } /** * {@inheritdoc} */ protected function buildFindCommand(Command $command, $dir) { parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1); return $command; } /** * {@inheritdoc} */ protected function buildContentFiltering(Command $command, array $contains, $not = false) { foreach ($contains as $contain) { $expr = Expression::create($contain); // todo: avoid forking process for each $pattern by using multiple -e options $command ->add('| grep -v \'^$\'') ->add('| xargs -I{} grep -I') ->add($expr->isCaseSensitive() ? null : '-i') ->add($not ? '-L' : '-l') ->add('-Ee')->arg($expr->renderPattern()) ->add('{}') ; } } } PK!}] 3Symfony/Component/Finder/Adapter/GnuFindAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using GNU find command. * * @author Jean-François Simon */ class GnuFindAdapter extends AbstractFindAdapter { /** * {@inheritdoc} */ public function getName() { return 'gnu_find'; } /** * {@inheritdoc} */ protected function buildFormatSorting(Command $command, $sort) { switch ($sort) { case SortableIterator::SORT_BY_NAME: $command->ins('sort')->add('| sort'); return; case SortableIterator::SORT_BY_TYPE: $format = '%y'; break; case SortableIterator::SORT_BY_ACCESSED_TIME: $format = '%A@'; break; case SortableIterator::SORT_BY_CHANGED_TIME: $format = '%C@'; break; case SortableIterator::SORT_BY_MODIFIED_TIME: $format = '%T@'; break; default: throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); } $command ->get('find') ->add('-printf') ->arg($format.' %h/%f\\n') ->add('| sort | cut') ->arg('-d ') ->arg('-f2-') ; } /** * {@inheritdoc} */ protected function canBeUsed() { return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed(); } /** * {@inheritdoc} */ protected function buildFindCommand(Command $command, $dir) { return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended'); } /** * {@inheritdoc} */ protected function buildContentFiltering(Command $command, array $contains, $not = false) { foreach ($contains as $contain) { $expr = Expression::create($contain); // todo: avoid forking process for each $pattern by using multiple -e options $command ->add('| xargs -I{} -r grep -I') ->add($expr->isCaseSensitive() ? null : '-i') ->add($not ? '-L' : '-l') ->add('-Ee')->arg($expr->renderPattern()) ->add('{}') ; } } } PK!QJ))8Symfony/Component/Finder/Adapter/AbstractFindAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Exception\AccessDeniedException; use Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Expression\Expression; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Comparator\NumberComparator; use Symfony\Component\Finder\Comparator\DateComparator; /** * Shell engine implementation using GNU find command. * * @author Jean-François Simon */ abstract class AbstractFindAdapter extends AbstractAdapter { /** * @var Shell */ protected $shell; /** * Constructor. */ public function __construct() { $this->shell = new Shell(); } /** * {@inheritdoc} */ public function searchInDirectory($dir) { // having "/../" in path make find fail $dir = realpath($dir); // searching directories containing or not containing strings leads to no result if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) { return new Iterator\FilePathsIterator(array(), $dir); } $command = Command::create(); $find = $this->buildFindCommand($command, $dir); if ($this->followLinks) { $find->add('-follow'); } $find->add('-mindepth')->add($this->minDepth + 1); if (PHP_INT_MAX !== $this->maxDepth) { $find->add('-maxdepth')->add($this->maxDepth + 1); } if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) { $find->add('-type d'); } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) { $find->add('-type f'); } $this->buildNamesFiltering($find, $this->names); $this->buildNamesFiltering($find, $this->notNames, true); $this->buildPathsFiltering($find, $dir, $this->paths); $this->buildPathsFiltering($find, $dir, $this->notPaths, true); $this->buildSizesFiltering($find, $this->sizes); $this->buildDatesFiltering($find, $this->dates); $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs'); $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut'); if ($useGrep && ($this->contains || $this->notContains)) { $grep = $command->ins('grep'); $this->buildContentFiltering($grep, $this->contains); $this->buildContentFiltering($grep, $this->notContains, true); } if ($useSort) { $this->buildSorting($command, $this->sort); } $command->setErrorHandler( $this->ignoreUnreadableDirs // If directory is unreadable and finder is set to ignore it, `stderr` is ignored. ? function ($stderr) { return; } : function ($stderr) { throw new AccessDeniedException($stderr); } ); $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute()); $iterator = new Iterator\FilePathsIterator($paths, $dir); if ($this->exclude) { $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); } if (!$useGrep && ($this->contains || $this->notContains)) { $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->filters) { $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if (!$useSort && $this->sort) { $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); $iterator = $iteratorAggregate->getIterator(); } return $iterator; } /** * {@inheritdoc} */ protected function canBeUsed() { return $this->shell->testCommand('find'); } /** * @param Command $command * @param string $dir * * @return Command */ protected function buildFindCommand(Command $command, $dir) { return $command ->ins('find') ->add('find ') ->arg($dir) ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions } /** * @param Command $command * @param string[] $names * @param Boolean $not */ private function buildNamesFiltering(Command $command, array $names, $not = false) { if (0 === count($names)) { return; } $command->add($not ? '-not' : null)->cmd('('); foreach ($names as $i => $name) { $expr = Expression::create($name); // Find does not support expandable globs ("*.{a,b}" syntax). if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { $expr = Expression::create($expr->getGlob()->toRegex(false)); } // Fixes 'not search' and 'full path matching' regex problems. // - Jokers '.' are replaced by [^/]. // - We add '[^/]*' before and after regex (if no ^|$ flags are present). if ($expr->isRegex()) { $regex = $expr->getRegex(); $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*') ->setStartFlag(false) ->setStartJoker(true) ->replaceJokers('[^/]'); if (!$regex->hasEndFlag() || $regex->hasEndJoker()) { $regex->setEndJoker(false)->append('[^/]*'); } } $command ->add($i > 0 ? '-or' : null) ->add($expr->isRegex() ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') : ($expr->isCaseSensitive() ? '-name' : '-iname') ) ->arg($expr->renderPattern()); } $command->cmd(')'); } /** * @param Command $command * @param string $dir * @param string[] $paths * @param Boolean $not */ private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false) { if (0 === count($paths)) { return; } $command->add($not ? '-not' : null)->cmd('('); foreach ($paths as $i => $path) { $expr = Expression::create($path); // Find does not support expandable globs ("*.{a,b}" syntax). if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { $expr = Expression::create($expr->getGlob()->toRegex(false)); } // Fixes 'not search' regex problems. if ($expr->isRegex()) { $regex = $expr->getRegex(); $regex->prepend($regex->hasStartFlag() ? $dir.DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag()); } else { $expr->prepend('*')->append('*'); } $command ->add($i > 0 ? '-or' : null) ->add($expr->isRegex() ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') : ($expr->isCaseSensitive() ? '-path' : '-ipath') ) ->arg($expr->renderPattern()); } $command->cmd(')'); } /** * @param Command $command * @param NumberComparator[] $sizes */ private function buildSizesFiltering(Command $command, array $sizes) { foreach ($sizes as $i => $size) { $command->add($i > 0 ? '-and' : null); switch ($size->getOperator()) { case '<=': $command->add('-size -'.($size->getTarget() + 1).'c'); break; case '>=': $command->add('-size +'. ($size->getTarget() - 1).'c'); break; case '>': $command->add('-size +'.$size->getTarget().'c'); break; case '!=': $command->add('-size -'.$size->getTarget().'c'); $command->add('-size +'.$size->getTarget().'c'); case '<': default: $command->add('-size -'.$size->getTarget().'c'); } } } /** * @param Command $command * @param DateComparator[] $dates */ private function buildDatesFiltering(Command $command, array $dates) { foreach ($dates as $i => $date) { $command->add($i > 0 ? '-and' : null); $mins = (int) round((time()-$date->getTarget()) / 60); if (0 > $mins) { // mtime is in the future $command->add(' -mmin -0'); // we will have no result so we don't need to continue return; } switch ($date->getOperator()) { case '<=': $command->add('-mmin +'.($mins - 1)); break; case '>=': $command->add('-mmin -'.($mins + 1)); break; case '>': $command->add('-mmin -'.$mins); break; case '!=': $command->add('-mmin +'.$mins.' -or -mmin -'.$mins); break; case '<': default: $command->add('-mmin +'.$mins); } } } /** * @param Command $command * @param string $sort * * @throws \InvalidArgumentException */ private function buildSorting(Command $command, $sort) { $this->buildFormatSorting($command, $sort); } /** * @param Command $command * @param string $sort */ abstract protected function buildFormatSorting(Command $command, $sort); /** * @param Command $command * @param array $contains * @param Boolean $not */ abstract protected function buildContentFiltering(Command $command, array $contains, $not = false); } PK! 4Symfony/Component/Finder/Adapter/AbstractAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; /** * Interface for finder engine implementations. * * @author Jean-François Simon */ abstract class AbstractAdapter implements AdapterInterface { protected $followLinks = false; protected $mode = 0; protected $minDepth = 0; protected $maxDepth = PHP_INT_MAX; protected $exclude = array(); protected $names = array(); protected $notNames = array(); protected $contains = array(); protected $notContains = array(); protected $sizes = array(); protected $dates = array(); protected $filters = array(); protected $sort = false; protected $paths = array(); protected $notPaths = array(); protected $ignoreUnreadableDirs = false; private static $areSupported = array(); /** * {@inheritDoc} */ public function isSupported() { $name = $this->getName(); if (!array_key_exists($name, self::$areSupported)) { self::$areSupported[$name] = $this->canBeUsed(); } return self::$areSupported[$name]; } /** * {@inheritdoc} */ public function setFollowLinks($followLinks) { $this->followLinks = $followLinks; return $this; } /** * {@inheritdoc} */ public function setMode($mode) { $this->mode = $mode; return $this; } /** * {@inheritdoc} */ public function setDepths(array $depths) { $this->minDepth = 0; $this->maxDepth = PHP_INT_MAX; foreach ($depths as $comparator) { switch ($comparator->getOperator()) { case '>': $this->minDepth = $comparator->getTarget() + 1; break; case '>=': $this->minDepth = $comparator->getTarget(); break; case '<': $this->maxDepth = $comparator->getTarget() - 1; break; case '<=': $this->maxDepth = $comparator->getTarget(); break; default: $this->minDepth = $this->maxDepth = $comparator->getTarget(); } } return $this; } /** * {@inheritdoc} */ public function setExclude(array $exclude) { $this->exclude = $exclude; return $this; } /** * {@inheritdoc} */ public function setNames(array $names) { $this->names = $names; return $this; } /** * {@inheritdoc} */ public function setNotNames(array $notNames) { $this->notNames = $notNames; return $this; } /** * {@inheritdoc} */ public function setContains(array $contains) { $this->contains = $contains; return $this; } /** * {@inheritdoc} */ public function setNotContains(array $notContains) { $this->notContains = $notContains; return $this; } /** * {@inheritdoc} */ public function setSizes(array $sizes) { $this->sizes = $sizes; return $this; } /** * {@inheritdoc} */ public function setDates(array $dates) { $this->dates = $dates; return $this; } /** * {@inheritdoc} */ public function setFilters(array $filters) { $this->filters = $filters; return $this; } /** * {@inheritdoc} */ public function setSort($sort) { $this->sort = $sort; return $this; } /** * {@inheritdoc} */ public function setPath(array $paths) { $this->paths = $paths; return $this; } /** * {@inheritdoc} */ public function setNotPath(array $notPaths) { $this->notPaths = $notPaths; return $this; } /** * {@inheritdoc} */ public function ignoreUnreadableDirs($ignore = true) { $this->ignoreUnreadableDirs = (Boolean) $ignore; return $this; } /** * Returns whether the adapter is supported in the current environment. * * This method should be implemented in all adapters. Do not implement * isSupported in the adapters as the generic implementation provides a cache * layer. * * @see isSupported * * @return Boolean Whether the adapter is supported */ abstract protected function canBeUsed(); } PK!:Symfony/Component/Translation/Extractor/ChainExtractor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Extractor; use Symfony\Component\Translation\MessageCatalogue; /** * ChainExtractor extracts translation messages from template files. * * @author Michel Salib */ class ChainExtractor implements ExtractorInterface { /** * The extractors. * * @var ExtractorInterface[] */ private $extractors = array(); /** * Adds a loader to the translation extractor. * * @param string $format The format of the loader * @param ExtractorInterface $extractor The loader */ public function addExtractor($format, ExtractorInterface $extractor) { $this->extractors[$format] = $extractor; } /** * {@inheritDoc} */ public function setPrefix($prefix) { foreach ($this->extractors as $extractor) { $extractor->setPrefix($prefix); } } /** * {@inheritDoc} */ public function extract($directory, MessageCatalogue $catalogue) { foreach ($this->extractors as $extractor) { $extractor->extract($directory, $catalogue); } } } PK!ArP>Symfony/Component/Translation/Extractor/ExtractorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Extractor; use Symfony\Component\Translation\MessageCatalogue; /** * Extracts translation messages from a template directory to the catalogue. * New found messages are injected to the catalogue using the prefix. * * @author Michel Salib */ interface ExtractorInterface { /** * Extracts translation messages from a template directory to the catalogue. * * @param string $directory The path to look into * @param MessageCatalogue $catalogue The catalogue */ public function extract($directory, MessageCatalogue $catalogue); /** * Sets the prefix that should be used for new found messages. * * @param string $prefix The prefix */ public function setPrefix($prefix); } PK!b*0oo4Symfony/Component/Translation/PluralizationRules.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * Returns the plural rules for a given locale. * * @author Fabien Potencier */ class PluralizationRules { // @codeCoverageIgnoreStart private static $rules = array(); /** * Returns the plural position to use for the given locale and number. * * @param integer $number The number * @param string $locale The locale * * @return integer The plural position */ public static function get($number, $locale) { if ('pt_BR' === $locale) { // temporary set a locale for brazilian $locale = 'xbr'; } if (strlen($locale) > 3) { $locale = substr($locale, 0, -strlen(strrchr($locale, '_'))); } if (isset(self::$rules[$locale])) { $return = call_user_func(self::$rules[$locale], $number); if (!is_int($return) || $return < 0) { return 0; } return $return; } /* * 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) */ switch ($locale) { case 'bo': case 'dz': case 'id': case 'ja': case 'jv': case 'ka': case 'km': case 'kn': case 'ko': case 'ms': case 'th': case 'tr': case 'vi': case 'zh': return 0; break; case 'af': case 'az': 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 '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 ($number == 1) ? 0 : 1; case 'am': case 'bh': case 'fil': case 'fr': case 'gun': case 'hi': case 'ln': case 'mg': case 'nso': case 'xbr': case 'ti': case 'wa': return (($number == 0) || ($number == 1)) ? 0 : 1; case 'be': case 'bs': case 'hr': case 'ru': case 'sr': case 'uk': return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'cs': case 'sk': return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); case 'ga': return ($number == 1) ? 0 : (($number == 2) ? 1 : 2); case 'lt': return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'sl': return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3)); case 'mk': return ($number % 10 == 1) ? 0 : 1; case 'mt': return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); case 'lv': return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2); case 'pl': return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); case 'cy': return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3)); case 'ro': return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); case 'ar': return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number >= 3) && ($number <= 10)) ? 3 : ((($number >= 11) && ($number <= 99)) ? 4 : 5)))); default: return 0; } } /** * Overrides the default plural rule for a given locale. * * @param string $rule A PHP callable * @param string $locale The locale * * @throws \LogicException */ public static function set($rule, $locale) { if ('pt_BR' === $locale) { // temporary set a locale for brazilian $locale = 'xbr'; } if (strlen($locale) > 3) { $locale = substr($locale, 0, -strlen(strrchr($locale, '_'))); } if (!is_callable($rule)) { throw new \LogicException('The given rule can not be called'); } self::$rules[$locale] = $rule; } // @codeCoverageIgnoreEnd } PK!qUU,Symfony/Component/Translation/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * MessageSelector. * * @author Fabien Potencier * @author Bernhard Schussek * * @api */ class MessageSelector { /** * 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 * * @param string $message The message being translated * @param integer $number The number of items represented for the message * @param string $locale The locale to use for choosing * * @return string * * @throws \InvalidArgumentException * * @api */ public function choose($message, $number, $locale) { $parts = explode('|', $message); $explicitRules = array(); $standardRules = array(); foreach ($parts as $part) { $part = trim($part); if (preg_match('/^(?P'.Interval::getIntervalRegexp().')\s*(?P.*?)$/x', $part, $matches)) { $explicitRules[$matches['interval']] = $matches['message']; } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) { $standardRules[] = $matches[1]; } else { $standardRules[] = $part; } } // try to match an explicit rule, then fallback to the standard ones foreach ($explicitRules as $interval => $m) { if (Interval::test($number, $interval)) { return $m; } } $position = PluralizationRules::get($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 $standardRules[0]; } throw new \InvalidArgumentException(sprintf('Unable to choose a translation for "%s" with locale "%s". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $message, $locale)); } return $standardRules[$position]; } } PK!س:Symfony/Component/Translation/Catalogue/MergeOperation.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; /** * Merge operation between two catalogues. * * @author Jean-François Simon */ class MergeOperation extends AbstractOperation { /** * {@inheritdoc} */ protected function processDomain($domain) { $this->messages[$domain] = array( 'all' => array(), 'new' => array(), 'obsolete' => array(), ); foreach ($this->source->all($domain) as $id => $message) { $this->messages[$domain]['all'][$id] = $message; $this->result->add(array($id => $message), $domain); } foreach ($this->target->all($domain) as $id => $message) { if (!$this->source->has($id, $domain)) { $this->messages[$domain]['all'][$id] = $message; $this->messages[$domain]['new'][$id] = $message; $this->result->add(array($id => $message), $domain); } } } } PK!Y[  >Symfony/Component/Translation/Catalogue/OperationInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; use Symfony\Component\Translation\MessageCatalogueInterface; /** * Represents an operation on catalogue(s). * * @author Jean-François Simon */ interface OperationInterface { /** * Returns domains affected by operation. * * @return array */ public function getDomains(); /** * Returns all valid messages after operation. * * @param string $domain * * @return array */ public function getMessages($domain); /** * Returns new messages after operation. * * @param string $domain * * @return array */ public function getNewMessages($domain); /** * Returns obsolete messages after operation. * * @param string $domain * * @return array */ public function getObsoleteMessages($domain); /** * Returns resulting catalogue. * * @return MessageCatalogueInterface */ public function getResult(); } PK!fb =Symfony/Component/Translation/Catalogue/AbstractOperation.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\MessageCatalogueInterface; /** * Base catalogues binary operation class. * * @author Jean-François Simon */ abstract class AbstractOperation implements OperationInterface { /** * @var MessageCatalogueInterface */ protected $source; /** * @var MessageCatalogueInterface */ protected $target; /** * @var MessageCatalogue */ protected $result; /** * @var null|array */ private $domains; /** * @var array */ protected $messages; /** * @param MessageCatalogueInterface $source * @param MessageCatalogueInterface $target * * @throws \LogicException */ public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target) { if ($source->getLocale() !== $target->getLocale()) { throw new \LogicException('Operated catalogues must belong to the same locale.'); } $this->source = $source; $this->target = $target; $this->result = new MessageCatalogue($source->getLocale()); $this->domains = null; $this->messages = array(); } /** * {@inheritdoc} */ public function getDomains() { if (null === $this->domains) { $this->domains = array_values(array_unique(array_merge($this->source->getDomains(), $this->target->getDomains()))); } return $this->domains; } /** * {@inheritdoc} */ public function getMessages($domain) { if (!in_array($domain, $this->getDomains())) { throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain)); } if (!isset($this->messages[$domain]['all'])) { $this->processDomain($domain); } return $this->messages[$domain]['all']; } /** * {@inheritdoc} */ public function getNewMessages($domain) { if (!in_array($domain, $this->getDomains())) { throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain)); } if (!isset($this->messages[$domain]['new'])) { $this->processDomain($domain); } return $this->messages[$domain]['new']; } /** * {@inheritdoc} */ public function getObsoleteMessages($domain) { if (!in_array($domain, $this->getDomains())) { throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain)); } if (!isset($this->messages[$domain]['obsolete'])) { $this->processDomain($domain); } return $this->messages[$domain]['obsolete']; } /** * {@inheritdoc} */ public function getResult() { foreach ($this->getDomains() as $domain) { if (!isset($this->messages[$domain])) { $this->processDomain($domain); } } return $this->result; } /** * @param string $domain */ abstract protected function processDomain($domain); } PK!ӄ9Symfony/Component/Translation/Catalogue/DiffOperation.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; /** * Diff operation between two catalogues. * * @author Jean-François Simon */ class DiffOperation extends AbstractOperation { /** * {@inheritdoc} */ protected function processDomain($domain) { $this->messages[$domain] = array( 'all' => array(), 'new' => array(), 'obsolete' => array(), ); foreach ($this->source->all($domain) as $id => $message) { if ($this->target->has($id, $domain)) { $this->messages[$domain]['all'][$id] = $message; $this->result->add(array($id => $message), $domain); } else { $this->messages[$domain]['obsolete'][$id] = $message; } } foreach ($this->target->all($domain) as $id => $message) { if (!$this->source->has($id, $domain)) { $this->messages[$domain]['all'][$id] = $message; $this->messages[$domain]['new'][$id] = $message; $this->result->add(array($id => $message), $domain); } } } } PK!6">Symfony/Component/Translation/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Fabien Potencier * * @api */ interface ExceptionInterface { } PK!DŽDSymfony/Component/Translation/Exception/InvalidResourceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Exception; /** * Thrown when a resource cannot be loaded. * * @author Fabien Potencier * * @api */ class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface { } PK!2BESymfony/Component/Translation/Exception/NotFoundResourceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Exception; /** * Thrown when a resource does not exist. * * @author Fabien Potencier * * @api */ class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface { } PK!y42Symfony/Component/Translation/MessageCatalogue.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; use Symfony\Component\Config\Resource\ResourceInterface; /** * MessageCatalogue. * * @author Fabien Potencier * * @api */ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface { private $messages = array(); private $metadata = array(); private $resources = array(); private $locale; private $fallbackCatalogue; private $parent; /** * Constructor. * * @param string $locale The locale * @param array $messages An array of messages classified by domain * * @api */ public function __construct($locale, array $messages = array()) { $this->locale = $locale; $this->messages = $messages; } /** * {@inheritdoc} * * @api */ public function getLocale() { return $this->locale; } /** * {@inheritdoc} * * @api */ public function getDomains() { return array_keys($this->messages); } /** * {@inheritdoc} * * @api */ public function all($domain = null) { if (null === $domain) { return $this->messages; } return isset($this->messages[$domain]) ? $this->messages[$domain] : array(); } /** * {@inheritdoc} * * @api */ public function set($id, $translation, $domain = 'messages') { $this->add(array($id => $translation), $domain); } /** * {@inheritdoc} * * @api */ public function has($id, $domain = 'messages') { if (isset($this->messages[$domain][$id])) { return true; } if (null !== $this->fallbackCatalogue) { return $this->fallbackCatalogue->has($id, $domain); } return false; } /** * {@inheritdoc} */ public function defines($id, $domain = 'messages') { return isset($this->messages[$domain][$id]); } /** * {@inheritdoc} * * @api */ public function get($id, $domain = 'messages') { if (isset($this->messages[$domain][$id])) { return $this->messages[$domain][$id]; } if (null !== $this->fallbackCatalogue) { return $this->fallbackCatalogue->get($id, $domain); } return $id; } /** * {@inheritdoc} * * @api */ public function replace($messages, $domain = 'messages') { $this->messages[$domain] = array(); $this->add($messages, $domain); } /** * {@inheritdoc} * * @api */ public function add($messages, $domain = 'messages') { if (!isset($this->messages[$domain])) { $this->messages[$domain] = $messages; } else { $this->messages[$domain] = array_replace($this->messages[$domain], $messages); } } /** * {@inheritdoc} * * @api */ public function addCatalogue(MessageCatalogueInterface $catalogue) { if ($catalogue->getLocale() !== $this->locale) { throw new \LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s"', $catalogue->getLocale(), $this->locale)); } foreach ($catalogue->all() as $domain => $messages) { $this->add($messages, $domain); } foreach ($catalogue->getResources() as $resource) { $this->addResource($resource); } if ($catalogue instanceof MetadataAwareInterface) { $metadata = $catalogue->getMetadata('', ''); $this->addMetadata($metadata); } } /** * {@inheritdoc} * * @api */ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue) { // detect circular references $c = $this; do { if ($c->getLocale() === $catalogue->getLocale()) { throw new \LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale())); } } while ($c = $c->parent); $catalogue->parent = $this; $this->fallbackCatalogue = $catalogue; foreach ($catalogue->getResources() as $resource) { $this->addResource($resource); } } /** * {@inheritdoc} * * @api */ public function getFallbackCatalogue() { return $this->fallbackCatalogue; } /** * {@inheritdoc} * * @api */ public function getResources() { return array_values($this->resources); } /** * {@inheritdoc} * * @api */ public function addResource(ResourceInterface $resource) { $this->resources[$resource->__toString()] = $resource; } /** * {@inheritdoc} */ public function getMetadata($key = '', $domain = 'messages') { if ('' == $domain) { return $this->metadata; } if (isset($this->metadata[$domain])) { if ('' == $key) { return $this->metadata[$domain]; } if (isset($this->metadata[$domain][$key])) { return $this->metadata[$domain][$key]; } } return null; } /** * {@inheritdoc} */ public function setMetadata($key, $value, $domain = 'messages') { $this->metadata[$domain][$key] = $value; } /** * {@inheritdoc} */ public function deleteMetadata($key = '', $domain = 'messages') { if ('' == $domain) { $this->metadata = array(); } elseif ('' == $key) { unset($this->metadata[$domain]); } else { unset($this->metadata[$domain][$key]); } } /** * Adds current values with the new values. * * @param array $values Values to add */ private function addMetadata(array $values) { foreach ($values as $domain => $keys) { foreach ($keys as $key => $value) { $this->setMetadata($key, $value, $domain); } } } } PK!%Mt8Symfony/Component/Translation/MetadataAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * MetadataAwareInterface. * * @author Fabien Potencier */ interface MetadataAwareInterface { /** * Gets metadata for the given domain and key. * * Passing an empty domain will return an array with all metadata indexed by * domain and then by key. Passing an empty key will return an array with all * metadata for the given domain. * * @param string $domain The domain name * @param string $key The key * * @return mixed The value that was set or an array with the domains/keys or null */ public function getMetadata($key = '', $domain = 'messages'); /** * Adds metadata to a message domain. * * @param string $key The key * @param mixed $value The value * @param string $domain The domain name */ public function setMetadata($key, $value, $domain = 'messages'); /** * Deletes metadata for the given key and domain. * * Passing an empty domain will delete all metadata. Passing an empty key will * delete all metadata for the given domain. * * @param string $domain The domain name * @param string $key The key */ public function deleteMetadata($key = '', $domain = 'messages'); } PK!d<<4Symfony/Component/Translation/IdentityTranslator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * IdentityTranslator does not translate anything. * * @author Fabien Potencier * * @api */ class IdentityTranslator implements TranslatorInterface { private $selector; private $locale; /** * Constructor. * * @param MessageSelector|null $selector The message selector for pluralization * * @api */ public function __construct(MessageSelector $selector = null) { $this->selector = $selector ?: new MessageSelector(); } /** * {@inheritdoc} * * @api */ public function setLocale($locale) { $this->locale = $locale; } /** * {@inheritdoc} * * @api */ public function getLocale() { return $this->locale ?: \Locale::getDefault(); } /** * {@inheritdoc} * * @api */ public function trans($id, array $parameters = array(), $domain = null, $locale = null) { return strtr((string) $id, $parameters); } /** * {@inheritdoc} * * @api */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { return strtr($this->selector->choose((string) $id, (int) $number, $locale ?: $this->getLocale()), $parameters); } } PK!eG,Symfony/Component/Translation/Translator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; use Symfony\Component\Translation\Loader\LoaderInterface; use Symfony\Component\Translation\Exception\NotFoundResourceException; /** * Translator. * * @author Fabien Potencier * * @api */ class Translator implements TranslatorInterface { /** * @var MessageCatalogueInterface[] */ protected $catalogues = array(); /** * @var string */ protected $locale; /** * @var array */ private $fallbackLocales = array(); /** * @var LoaderInterface[] */ private $loaders = array(); /** * @var array */ private $resources = array(); /** * @var MessageSelector */ private $selector; /** * Constructor. * * @param string $locale The locale * @param MessageSelector|null $selector The message selector for pluralization * * @api */ public function __construct($locale, MessageSelector $selector = null) { $this->locale = $locale; $this->selector = $selector ?: new MessageSelector(); } /** * Adds a Loader. * * @param string $format The name of the loader (@see addResource()) * @param LoaderInterface $loader A LoaderInterface instance * * @api */ public function addLoader($format, LoaderInterface $loader) { $this->loaders[$format] = $loader; } /** * Adds a Resource. * * @param string $format The name of the loader (@see addLoader()) * @param mixed $resource The resource name * @param string $locale The locale * @param string $domain The domain * * @api */ public function addResource($format, $resource, $locale, $domain = null) { if (null === $domain) { $domain = 'messages'; } $this->resources[$locale][] = array($format, $resource, $domain); if (in_array($locale, $this->fallbackLocales)) { $this->catalogues = array(); } else { unset($this->catalogues[$locale]); } } /** * {@inheritdoc} * * @api */ public function setLocale($locale) { $this->locale = $locale; } /** * {@inheritdoc} * * @api */ public function getLocale() { return $this->locale; } /** * Sets the fallback locale(s). * * @param string|array $locales The fallback locale(s) * * @deprecated since 2.3, to be removed in 3.0. Use setFallbackLocales() instead. * * @api */ public function setFallbackLocale($locales) { $this->setFallbackLocales(is_array($locales) ? $locales : array($locales)); } /** * Sets the fallback locales. * * @param array $locales The fallback locales * * @api */ public function setFallbackLocales(array $locales) { // needed as the fallback locales are linked to the already loaded catalogues $this->catalogues = array(); $this->fallbackLocales = $locales; } /** * Gets the fallback locales. * * @return array $locales The fallback locales * * @api */ public function getFallbackLocales() { return $this->fallbackLocales; } /** * {@inheritdoc} * * @api */ public function trans($id, array $parameters = array(), $domain = null, $locale = null) { if (null === $locale) { $locale = $this->getLocale(); } if (null === $domain) { $domain = 'messages'; } if (!isset($this->catalogues[$locale])) { $this->loadCatalogue($locale); } return strtr($this->catalogues[$locale]->get((string) $id, $domain), $parameters); } /** * {@inheritdoc} * * @api */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { if (null === $locale) { $locale = $this->getLocale(); } if (null === $domain) { $domain = 'messages'; } if (!isset($this->catalogues[$locale])) { $this->loadCatalogue($locale); } $id = (string) $id; $catalogue = $this->catalogues[$locale]; while (!$catalogue->defines($id, $domain)) { if ($cat = $catalogue->getFallbackCatalogue()) { $catalogue = $cat; $locale = $catalogue->getLocale(); } else { break; } } return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters); } /** * Gets the loaders. * * @return array LoaderInterface[] */ protected function getLoaders() { return $this->loaders; } protected function loadCatalogue($locale) { try { $this->doLoadCatalogue($locale); } catch (NotFoundResourceException $e) { if (!$this->computeFallbackLocales($locale)) { throw $e; } } $this->loadFallbackCatalogues($locale); } private function doLoadCatalogue($locale) { $this->catalogues[$locale] = new MessageCatalogue($locale); if (isset($this->resources[$locale])) { foreach ($this->resources[$locale] as $resource) { if (!isset($this->loaders[$resource[0]])) { throw new \RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0])); } $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2])); } } } private function loadFallbackCatalogues($locale) { $current = $this->catalogues[$locale]; foreach ($this->computeFallbackLocales($locale) as $fallback) { if (!isset($this->catalogues[$fallback])) { $this->doLoadCatalogue($fallback); } $current->addFallbackCatalogue($this->catalogues[$fallback]); $current = $this->catalogues[$fallback]; } } protected function computeFallbackLocales($locale) { $locales = array(); foreach ($this->fallbackLocales as $fallback) { if ($fallback === $locale) { continue; } $locales[] = $fallback; } if (strrchr($locale, '_') !== false) { array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_')))); } return array_unique($locales); } } PK!֛;Symfony/Component/Translation/MessageCatalogueInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; use Symfony\Component\Config\Resource\ResourceInterface; /** * MessageCatalogueInterface. * * @author Fabien Potencier * * @api */ interface MessageCatalogueInterface { /** * Gets the catalogue locale. * * @return string The locale * * @api */ public function getLocale(); /** * Gets the domains. * * @return array An array of domains * * @api */ public function getDomains(); /** * Gets the messages within a given domain. * * If $domain is null, it returns all messages. * * @param string $domain The domain name * * @return array An array of messages * * @api */ public function all($domain = null); /** * Sets a message translation. * * @param string $id The message id * @param string $translation The messages translation * @param string $domain The domain name * * @api */ public function set($id, $translation, $domain = 'messages'); /** * Checks if a message has a translation. * * @param string $id The message id * @param string $domain The domain name * * @return Boolean true if the message has a translation, false otherwise * * @api */ public function has($id, $domain = 'messages'); /** * Checks if a message has a translation (it does not take into account the fallback mechanism). * * @param string $id The message id * @param string $domain The domain name * * @return Boolean true if the message has a translation, false otherwise * * @api */ public function defines($id, $domain = 'messages'); /** * Gets a message translation. * * @param string $id The message id * @param string $domain The domain name * * @return string The message translation * * @api */ public function get($id, $domain = 'messages'); /** * Sets translations for a given domain. * * @param array $messages An array of translations * @param string $domain The domain name * * @api */ public function replace($messages, $domain = 'messages'); /** * Adds translations for a given domain. * * @param array $messages An array of translations * @param string $domain The domain name * * @api */ public function add($messages, $domain = 'messages'); /** * Merges translations from the given Catalogue into the current one. * * The two catalogues must have the same locale. * * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance * * @api */ public function addCatalogue(MessageCatalogueInterface $catalogue); /** * Merges translations from the given Catalogue into the current one * only when the translation does not exist. * * This is used to provide default translations when they do not exist for the current locale. * * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance * * @api */ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue); /** * Gets the fallback catalogue. * * @return MessageCatalogueInterface|null A MessageCatalogueInterface instance or null when no fallback has been set * * @api */ public function getFallbackCatalogue(); /** * Returns an array of resources loaded to build this collection. * * @return ResourceInterface[] An array of resources * * @api */ public function getResources(); /** * Adds a resource for this collection. * * @param ResourceInterface $resource A resource instance * * @api */ public function addResource(ResourceInterface $resource); } PK!M 9Symfony/Component/Translation/Dumper/IcuResFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue. * * @author Stealth35 */ class IcuResFileDumper implements DumperInterface { /** * {@inheritDoc} */ public function dump(MessageCatalogue $messages, $options = array()) { if (!array_key_exists('path', $options)) { throw new \InvalidArgumentException('The file dumper need a path options.'); } // save a file for each domain foreach ($messages->getDomains() as $domain) { $file = $messages->getLocale().'.'.$this->getExtension(); $path = $options['path'].'/'.$domain.'/'; if (!file_exists($path)) { mkdir($path); } // backup if (file_exists($path.$file)) { copy($path.$file, $path.$file.'~'); } // save file file_put_contents($path.$file, $this->format($messages, $domain)); } } /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $data = $indexes = $resources = ''; foreach ($messages->all($domain) as $source => $target) { $indexes .= pack('v', strlen($data) + 28); $data .= $source."\0"; } $data .= $this->writePadding($data); $keyTop = $this->getPosition($data); foreach ($messages->all($domain) as $source => $target) { $resources .= pack('V', $this->getPosition($data)); $data .= pack('V', strlen($target)) .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8') .$this->writePadding($data) ; } $resOffset = $this->getPosition($data); $data .= pack('v', count($messages)) .$indexes .$this->writePadding($data) .$resources ; $bundleTop = $this->getPosition($data); $root = pack('V7', $resOffset + (2 << 28), // Resource Offset + Resource Type 6, // Index length $keyTop, // Index keys top $bundleTop, // Index resources top $bundleTop, // Index bundle top count($messages), // Index max table length 0 // Index attributes ); $header = pack('vC2v4C12@32', 32, // Header size 0xDA, 0x27, // Magic number 1 and 2 20, 0, 0, 2, // Rest of the header, ..., Size of a char 0x52, 0x65, 0x73, 0x42, // Data format identifier 1, 2, 0, 0, // Data version 1, 4, 0, 0 // Unicode version ); $output = $header .$root .$data; return $output; } private function writePadding($data) { $padding = strlen($data) % 4; if ($padding) { return str_repeat("\xAA", 4 - $padding); } } private function getPosition($data) { $position = (strlen($data) + 28) / 4; return $position; } /** * {@inheritDoc} */ protected function getExtension() { return 'res'; } } PK!ਪ(5Symfony/Component/Translation/Dumper/PoFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * PoFileDumper generates a gettext formatted string representation of a message catalogue. * * @author Stealth35 */ class PoFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $output = 'msgid ""'."\n"; $output .= 'msgstr ""'."\n"; $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n"; $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n"; $output .= '"Language: '.$messages->getLocale().'\n"'."\n"; $output .= "\n"; $newLine = false; foreach ($messages->all($domain) as $source => $target) { if ($newLine) { $output .= "\n"; } else { $newLine = true; } $output .= sprintf('msgid "%s"'."\n", $this->escape($source)); $output .= sprintf('msgstr "%s"', $this->escape($target)); } return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'po'; } private function escape($str) { return addcslashes($str, "\0..\37\42\134"); } } PK!%LL6Symfony/Component/Translation/Dumper/PhpFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * PhpFileDumper generates PHP files from a message catalogue. * * @author Michel Salib */ class PhpFileDumper extends FileDumper { /** * {@inheritDoc} */ protected function format(MessageCatalogue $messages, $domain) { $output = "all($domain), true).";\n"; return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'php'; } } PK!<̧8Symfony/Component/Translation/Dumper/XliffFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * XliffFileDumper generates xliff files from a message catalogue. * * @author Michel Salib */ class XliffFileDumper extends FileDumper { /** * {@inheritDoc} */ protected function format(MessageCatalogue $messages, $domain) { $dom = new \DOMDocument('1.0', 'utf-8'); $dom->formatOutput = true; $xliff = $dom->appendChild($dom->createElement('xliff')); $xliff->setAttribute('version', '1.2'); $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2'); $xliffFile = $xliff->appendChild($dom->createElement('file')); $xliffFile->setAttribute('source-language', $messages->getLocale()); $xliffFile->setAttribute('datatype', 'plaintext'); $xliffFile->setAttribute('original', 'file.ext'); $xliffBody = $xliffFile->appendChild($dom->createElement('body')); foreach ($messages->all($domain) as $source => $target) { $translation = $dom->createElement('trans-unit'); $translation->setAttribute('id', md5($source)); $translation->setAttribute('resname', $source); $s = $translation->appendChild($dom->createElement('source')); $s->appendChild($dom->createTextNode($source)); $t = $translation->appendChild($dom->createElement('target')); $t->appendChild($dom->createTextNode($target)); $xliffBody->appendChild($translation); } return $dom->saveXML(); } /** * {@inheritDoc} */ protected function getExtension() { return 'xlf'; } } PK!>{GG5Symfony/Component/Translation/Dumper/QtFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * QtFileDumper generates ts files from a message catalogue. * * @author Benjamin Eberlei */ class QtFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain) { $dom = new \DOMDocument('1.0', 'utf-8'); $dom->formatOutput = true; $ts = $dom->appendChild($dom->createElement('TS')); $context = $ts->appendChild($dom->createElement('context')); $context->appendChild($dom->createElement('name', $domain)); foreach ($messages->all($domain) as $source => $target) { $message = $context->appendChild($dom->createElement('message')); $message->appendChild($dom->createElement('source', $source)); $message->appendChild($dom->createElement('translation', $target)); } return $dom->saveXML(); } /** * {@inheritDoc} */ protected function getExtension() { return 'ts'; } } PK!667Symfony/Component/Translation/Dumper/YamlFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Yaml\Yaml; /** * YamlFileDumper generates yaml files from a message catalogue. * * @author Michel Salib */ class YamlFileDumper extends FileDumper { /** * {@inheritDoc} */ protected function format(MessageCatalogue $messages, $domain) { return Yaml::dump($messages->all($domain)); } /** * {@inheritDoc} */ protected function getExtension() { return 'yml'; } } PK!oB6Symfony/Component/Translation/Dumper/CsvFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * CsvFileDumper generates a csv formatted string representation of a message catalogue. * * @author Stealth35 */ class CsvFileDumper extends FileDumper { private $delimiter = ';'; private $enclosure = '"'; /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $handle = fopen('php://memory', 'rb+'); foreach ($messages->all($domain) as $source => $target) { fputcsv($handle, array($source, $target), $this->delimiter, $this->enclosure); } rewind($handle); $output = stream_get_contents($handle); fclose($handle); return $output; } /** * Sets the delimiter and escape character for CSV. * * @param string $delimiter delimiter character * @param string $enclosure enclosure character */ public function setCsvControl($delimiter = ';', $enclosure = '"') { $this->delimiter = $delimiter; $this->enclosure = $enclosure; } /** * {@inheritDoc} */ protected function getExtension() { return 'csv'; } } PK!B^[[3Symfony/Component/Translation/Dumper/FileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s). * Performs backup of already existing files. * * Options: * - path (mandatory): the directory where the files should be saved * * @author Michel Salib */ abstract class FileDumper implements DumperInterface { /** * {@inheritDoc} */ public function dump(MessageCatalogue $messages, $options = array()) { if (!array_key_exists('path', $options)) { throw new \InvalidArgumentException('The file dumper needs a path option.'); } // save a file for each domain foreach ($messages->getDomains() as $domain) { $file = $domain.'.'.$messages->getLocale().'.'.$this->getExtension(); // backup $fullpath = $options['path'].'/'.$file; if (file_exists($fullpath)) { copy($fullpath, $fullpath.'~'); } // save file file_put_contents($fullpath, $this->format($messages, $domain)); } } /** * Transforms a domain of a message catalogue to its string representation. * * @param MessageCatalogue $messages * @param string $domain * * @return string representation */ abstract protected function format(MessageCatalogue $messages, $domain); /** * Gets the file extension of the dumper. * * @return string file extension */ abstract protected function getExtension(); } PK!:$}}7Symfony/Component/Translation/Dumper/JsonFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; if (!defined('JSON_PRETTY_PRINT')) { define('JSON_PRETTY_PRINT', 128); } /** * JsonFileDumper generates an json formatted string representation of a message catalogue. * * @author singles */ class JsonFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { return json_encode($messages->all($domain), JSON_PRETTY_PRINT); } /** * {@inheritDoc} */ protected function getExtension() { return 'json'; } } PK!&X6Symfony/Component/Translation/Dumper/IniFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * IniFileDumper generates an ini formatted string representation of a message catalogue. * * @author Stealth35 */ class IniFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $output = ''; foreach ($messages->all($domain) as $source => $target) { $escapeTarget = str_replace('"', '\"', $target); $output .= $source.'="'.$escapeTarget."\"\n"; } return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'ini'; } } PK!<**8Symfony/Component/Translation/Dumper/DumperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * DumperInterface is the interface implemented by all translation dumpers. * There is no common option. * * @author Michel Salib */ interface DumperInterface { /** * Dumps the message catalogue. * * @param MessageCatalogue $messages The message catalogue * @param array $options Options that are used by the dumper */ public function dump(MessageCatalogue $messages, $options = array()); } PK!A A 5Symfony/Component/Translation/Dumper/MoFileDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Loader\MoFileLoader; /** * MoFileDumper generates a gettext formatted string representation of a message catalogue. * * @author Stealth35 */ class MoFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $output = $sources = $targets = $sourceOffsets = $targetOffsets = ''; $offsets = array(); $size = 0; foreach ($messages->all($domain) as $source => $target) { $offsets[] = array_map('strlen', array($sources, $source, $targets, $target)); $sources .= "\0".$source; $targets .= "\0".$target; ++$size; } $header = array( 'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC, 'formatRevision' => 0, 'count' => $size, 'offsetId' => MoFileLoader::MO_HEADER_SIZE, 'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size), 'sizeHashes' => 0, 'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size), ); $sourcesSize = strlen($sources); $sourcesStart = $header['offsetHashes'] + 1; foreach ($offsets as $offset) { $sourceOffsets .= $this->writeLong($offset[1]) .$this->writeLong($offset[0] + $sourcesStart); $targetOffsets .= $this->writeLong($offset[3]) .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize); } $output = implode(array_map(array($this, 'writeLong'), $header)) .$sourceOffsets .$targetOffsets .$sources .$targets ; return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'mo'; } private function writeLong($str) { return pack('V*', $str); } } PK!g?Z *Symfony/Component/Translation/Interval.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * Tests if a given number belongs to a given math interval. * * 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. * * @author Fabien Potencier * * @see http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation */ class Interval { /** * Tests if the given number is in the math interval. * * @param integer $number A number * @param string $interval An interval * * @return Boolean * * @throws \InvalidArgumentException */ public static function test($number, $interval) { $interval = trim($interval); if (!preg_match('/^'.self::getIntervalRegexp().'$/x', $interval, $matches)) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid interval.', $interval)); } if ($matches[1]) { foreach (explode(',', $matches[2]) as $n) { if ($number == $n) { return true; } } } else { $leftNumber = self::convertNumber($matches['left']); $rightNumber = self::convertNumber($matches['right']); return ('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber) && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber) ; } return false; } /** * Returns a Regexp that matches valid intervals. * * @return string A Regexp (without the delimiters) */ public static function getIntervalRegexp() { return <<[\[\]]) \s* (?P-Inf|\-?\d+(\.\d+)?) \s*,\s* (?P\+?Inf|\-?\d+(\.\d+)?) \s* (?P[\[\]]) EOF; } private static function convertNumber($number) { if ('-Inf' === $number) { return log(0); } elseif ('+Inf' === $number || 'Inf' === $number) { return -log(0); } return (float) $number; } } PK!35Symfony/Component/Translation/TranslatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * TranslatorInterface. * * @author Fabien Potencier * * @api */ interface TranslatorInterface { /** * Translates the given message. * * @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 * * @api */ public function trans($id, array $parameters = array(), $domain = null, $locale = null); /** * Translates the given choice message by choosing a translation according to a number. * * @param string $id The message id (may also be an object that can be cast to string) * @param integer $number The number to use to find the indice of the message * @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 * * @api */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null); /** * Sets the current locale. * * @param string $locale The locale * * @api */ public function setLocale($locale); /** * Returns the current locale. * * @return string The locale * * @api */ public function getLocale(); } PK!P?}}:Symfony/Component/Translation/Writer/TranslationWriter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Writer; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Dumper\DumperInterface; /** * TranslationWriter writes translation messages. * * @author Michel Salib */ class TranslationWriter { /** * Dumpers used for export. * * @var array */ private $dumpers = array(); /** * Adds a dumper to the writer. * * @param string $format The format of the dumper * @param DumperInterface $dumper The dumper */ public function addDumper($format, DumperInterface $dumper) { $this->dumpers[$format] = $dumper; } /** * Obtains the list of supported formats. * * @return array */ public function getFormats() { return array_keys($this->dumpers); } /** * Writes translation from the catalogue according to the selected format. * * @param MessageCatalogue $catalogue The message catalogue to dump * @param string $format The format to use to dump the messages * @param array $options Options that are passed to the dumper * * @throws \InvalidArgumentException */ public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array()) { if (!isset($this->dumpers[$format])) { throw new \InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format)); } // get the right dumper $dumper = $this->dumpers[$format]; // save $dumper->dump($catalogue, $options); } } PK!N@ 6Symfony/Component/Translation/Loader/IniFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * IniFileLoader loads translations from an ini file. * * @author stealth35 */ class IniFileLoader extends ArrayLoader implements LoaderInterface { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = parse_ini_file($resource, true); $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } } PK!TÏ9Symfony/Component/Translation/Loader/IcuDatFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * IcuResFileLoader loads translations from a resource bundle. * * @author stealth35 */ class IcuDatFileLoader extends IcuResFileLoader { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource.'.dat')) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource.'.dat')) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $rb = new \ResourceBundle($locale, $resource); if (!$rb) { throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource)); } elseif (intl_is_failure($rb->getErrorCode())) { throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); } $messages = $this->flatten($rb); $catalogue = new MessageCatalogue($locale); $catalogue->add($messages, $domain); $catalogue->addResource(new FileResource($resource.'.dat')); return $catalogue; } } PK!CSz z 9Symfony/Component/Translation/Loader/IcuResFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\DirectoryResource; /** * IcuResFileLoader loads translations from a resource bundle. * * @author stealth35 */ class IcuResFileLoader implements LoaderInterface { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!is_dir($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $rb = new \ResourceBundle($locale, $resource); if (!$rb) { throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource)); } elseif (intl_is_failure($rb->getErrorCode())) { throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); } $messages = $this->flatten($rb); $catalogue = new MessageCatalogue($locale); $catalogue->add($messages, $domain); $catalogue->addResource(new DirectoryResource($resource)); return $catalogue; } /** * Flattens an ResourceBundle * * The scheme used is: * key { key2 { key3 { "value" } } } * Becomes: * 'key.key2.key3' => 'value' * * This function takes an array by reference and will modify it * * @param \ResourceBundle $rb the ResourceBundle that will be flattened * @param array $messages used internally for recursive calls * @param string $path current path being parsed, used internally for recursive calls * * @return array the flattened ResourceBundle */ protected function flatten(\ResourceBundle $rb, array &$messages = array(), $path = null) { foreach ($rb as $key => $value) { $nodePath = $path ? $path.'.'.$key : $key; if ($value instanceof \ResourceBundle) { $this->flatten($value, $messages, $nodePath); } else { $messages[$nodePath] = $value; } } return $messages; } } PK!v5Symfony/Component/Translation/Loader/MoFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/) */ class MoFileLoader extends ArrayLoader implements LoaderInterface { /** * Magic used for validating the format of a MO file as well as * detecting if the machine used to create that file was little endian. * * @var float */ const MO_LITTLE_ENDIAN_MAGIC = 0x950412de; /** * Magic used for validating the format of a MO file as well as * detecting if the machine used to create that file was big endian. * * @var float */ const MO_BIG_ENDIAN_MAGIC = 0xde120495; /** * The size of the header of a MO file in bytes. * * @var integer Number of bytes. */ const MO_HEADER_SIZE = 28; public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = $this->parse($resource); // empty file if (null === $messages) { $messages = array(); } // not an array if (!is_array($messages)) { throw new InvalidResourceException(sprintf('The file "%s" must contain a valid mo file.', $resource)); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Parses machine object (MO) format, independent of the machine's endian it * was created on. Both 32bit and 64bit systems are supported. * * @param resource $resource * * @return array * @throws InvalidResourceException If stream content has an invalid format. */ private function parse($resource) { $stream = fopen($resource, 'r'); $stat = fstat($stream); if ($stat['size'] < self::MO_HEADER_SIZE) { throw new InvalidResourceException("MO stream content has an invalid format."); } $magic = unpack('V1', fread($stream, 4)); $magic = hexdec(substr(dechex(current($magic)), -8)); if ($magic == self::MO_LITTLE_ENDIAN_MAGIC) { $isBigEndian = false; } elseif ($magic == self::MO_BIG_ENDIAN_MAGIC) { $isBigEndian = true; } else { throw new InvalidResourceException("MO stream content has an invalid format."); } // formatRevision $this->readLong($stream, $isBigEndian); $count = $this->readLong($stream, $isBigEndian); $offsetId = $this->readLong($stream, $isBigEndian); $offsetTranslated = $this->readLong($stream, $isBigEndian); // sizeHashes $this->readLong($stream, $isBigEndian); // offsetHashes $this->readLong($stream, $isBigEndian); $messages = array(); for ($i = 0; $i < $count; $i++) { $singularId = $pluralId = null; $translated = null; fseek($stream, $offsetId + $i * 8); $length = $this->readLong($stream, $isBigEndian); $offset = $this->readLong($stream, $isBigEndian); if ($length < 1) { continue; } fseek($stream, $offset); $singularId = fread($stream, $length); if (strpos($singularId, "\000") !== false) { list($singularId, $pluralId) = explode("\000", $singularId); } fseek($stream, $offsetTranslated + $i * 8); $length = $this->readLong($stream, $isBigEndian); $offset = $this->readLong($stream, $isBigEndian); fseek($stream, $offset); $translated = fread($stream, $length); if (strpos($translated, "\000") !== false) { $translated = explode("\000", $translated); } $ids = array('singular' => $singularId, 'plural' => $pluralId); $item = compact('ids', 'translated'); if (is_array($item['translated'])) { $messages[$item['ids']['singular']] = stripcslashes($item['translated'][0]); if (isset($item['ids']['plural'])) { $plurals = array(); foreach ($item['translated'] as $plural => $translated) { $plurals[] = sprintf('{%d} %s', $plural, $translated); } $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals)); } } elseif (!empty($item['ids']['singular'])) { $messages[$item['ids']['singular']] = stripcslashes($item['translated']); } } fclose($stream); return array_filter($messages); } /** * Reads an unsigned long from stream respecting endianess. * * @param resource $stream * @param boolean $isBigEndian * @return integer */ private function readLong($stream, $isBigEndian) { $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4)); $result = current($result); return (integer) substr($result, -8); } } PK!R4Symfony/Component/Translation/Loader/ArrayLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; /** * ArrayLoader loads translations from a PHP array. * * @author Fabien Potencier * * @api */ class ArrayLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { $this->flatten($resource); $catalogue = new MessageCatalogue($locale); $catalogue->add($resource, $domain); return $catalogue; } /** * Flattens an nested array of translations * * The scheme used is: * 'key' => array('key2' => array('key3' => 'value')) * Becomes: * 'key.key2.key3' => 'value' * * This function takes an array by reference and will modify it * * @param array &$messages The array that will be flattened * @param array $subnode Current subnode being parsed, used internally for recursive calls * @param string $path Current path being parsed, used internally for recursive calls */ private function flatten(array &$messages, array $subnode = null, $path = null) { if (null === $subnode) { $subnode =& $messages; } foreach ($subnode as $key => $value) { if (is_array($value)) { $nodePath = $path ? $path.'.'.$key : $key; $this->flatten($messages, $value, $nodePath); if (null === $path) { unset($messages[$key]); } } elseif (null !== $path) { $messages[$path.'.'.$key] = $value; } } } } PK!'su u 7Symfony/Component/Translation/Loader/JsonFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * JsonFileLoader loads translations from an json file. * * @author singles */ class JsonFileLoader extends ArrayLoader implements LoaderInterface { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = json_decode(file_get_contents($resource), true); if (0 < $errorCode = json_last_error()) { throw new InvalidResourceException(sprintf('Error parsing JSON - %s', $this->getJSONErrorMessage($errorCode))); } if (null === $messages) { $messages = array(); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Translates JSON_ERROR_* constant into meaningful message. * * @param integer $errorCode Error code returned by json_last_error() call * * @return string Message string */ private function getJSONErrorMessage($errorCode) { switch ($errorCode) { case JSON_ERROR_DEPTH: return 'Maximum stack depth exceeded'; case JSON_ERROR_STATE_MISMATCH: return 'Underflow or the modes mismatch'; case JSON_ERROR_CTRL_CHAR: return 'Unexpected control character found'; case JSON_ERROR_SYNTAX: return 'Syntax error, malformed JSON'; case JSON_ERROR_UTF8: return 'Malformed UTF-8 characters, possibly incorrectly encoded'; default: return 'Unknown error'; } } } PK!i3" " 6Symfony/Component/Translation/Loader/CsvFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * CsvFileLoader loads translations from CSV files. * * @author Saša Stamenković * * @api */ class CsvFileLoader extends ArrayLoader implements LoaderInterface { private $delimiter = ';'; private $enclosure = '"'; private $escape = '\\'; /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = array(); try { $file = new \SplFileObject($resource, 'rb'); } catch (\RuntimeException $e) { throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e); } $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY); $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape); foreach ($file as $data) { if (substr($data[0], 0, 1) === '#') { continue; } if (!isset($data[1])) { continue; } if (count($data) == 2) { $messages[$data[0]] = $data[1]; } else { continue; } } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Sets the delimiter, enclosure, and escape character for CSV. * * @param string $delimiter delimiter character * @param string $enclosure enclosure character * @param string $escape escape character */ public function setCsvControl($delimiter = ';', $enclosure = '"', $escape = '\\') { $this->delimiter = $delimiter; $this->enclosure = $enclosure; $this->escape = $escape; } } PK!_BB8Symfony/Component/Translation/Loader/XliffFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * XliffFileLoader loads translations from XLIFF files. * * @author Fabien Potencier * * @api */ class XliffFileLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } list($xml, $encoding) = $this->parseFile($resource); $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2'); $catalogue = new MessageCatalogue($locale); foreach ($xml->xpath('//xliff:trans-unit') as $translation) { $attributes = $translation->attributes(); if (!(isset($attributes['resname']) || isset($translation->source)) || !isset($translation->target)) { continue; } $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source; $target = (string) $translation->target; // If the xlf file has another encoding specified, try to convert it because // simple_xml will always return utf-8 encoded values if ('UTF-8' !== $encoding && !empty($encoding)) { if (function_exists('mb_convert_encoding')) { $target = mb_convert_encoding($target, $encoding, 'UTF-8'); } elseif (function_exists('iconv')) { $target = iconv('UTF-8', $encoding, $target); } else { throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); } } $catalogue->set((string) $source, $target, $domain); } $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Validates and parses the given file into a SimpleXMLElement * * @param string $file * * @throws \RuntimeException * * @return \SimpleXMLElement * * @throws InvalidResourceException */ private function parseFile($file) { try { $dom = XmlUtils::loadFile($file); } catch (\InvalidArgumentException $e) { throw new InvalidResourceException(sprintf('Unable to load "%s": %s', $file, $e->getMessage()), $e->getCode(), $e); } $internalErrors = libxml_use_internal_errors(true); $location = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd'; $parts = explode('/', $location); if (0 === stripos($location, 'phar://')) { $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); if ($tmpfile) { copy($location, $tmpfile); $parts = explode('/', str_replace('\\', '/', $tmpfile)); } } $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts)); $source = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-1.2-strict.xsd'); $source = str_replace('http://www.w3.org/2001/xml.xsd', $location, $source); if (!@$dom->schemaValidateSource($source)) { throw new InvalidResourceException(implode("\n", $this->getXmlErrors($internalErrors))); } $dom->normalizeDocument(); libxml_use_internal_errors($internalErrors); return array(simplexml_import_dom($dom), strtoupper($dom->encoding)); } /** * Returns the XML errors of the internal XML parser * * @param Boolean $internalErrors * * @return array An array of errors */ private function getXmlErrors($internalErrors) { $errors = array(); foreach (libxml_get_errors() as $error) { $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', $error->code, trim($error->message), $error->file ? $error->file : 'n/a', $error->line, $error->column ); } libxml_clear_errors(); libxml_use_internal_errors($internalErrors); return $errors; } } PK!l#tt8Symfony/Component/Translation/Loader/LoaderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; /** * LoaderInterface is the interface implemented by all translation loaders. * * @author Fabien Potencier * * @api */ interface LoaderInterface { /** * Loads a locale. * * @param mixed $resource A resource * @param string $locale A locale * @param string $domain The domain * * @return MessageCatalogue A MessageCatalogue instance * * @api * * @throws NotFoundResourceException when the resource cannot be found * @throws InvalidResourceException when the resource cannot be loaded */ public function load($resource, $locale, $domain = 'messages'); } PK!*5Symfony/Component/Translation/Loader/PoFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/) * @copyright Copyright (c) 2012, Clemens Tolboom */ class PoFileLoader extends ArrayLoader implements LoaderInterface { public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = $this->parse($resource); // empty file if (null === $messages) { $messages = array(); } // not an array if (!is_array($messages)) { throw new InvalidResourceException(sprintf('The file "%s" must contain a valid po file.', $resource)); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Parses portable object (PO) format. * * From http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files * we should be able to parse files having: * * white-space * # translator-comments * #. extracted-comments * #: reference... * #, flag... * #| msgid previous-untranslated-string * msgid untranslated-string * msgstr translated-string * * extra or different lines are: * * #| msgctxt previous-context * #| msgid previous-untranslated-string * msgctxt context * * #| msgid previous-untranslated-string-singular * #| msgid_plural previous-untranslated-string-plural * msgid untranslated-string-singular * msgid_plural untranslated-string-plural * msgstr[0] translated-string-case-0 * ... * msgstr[N] translated-string-case-n * * The definition states: * - white-space and comments are optional. * - msgid "" that an empty singleline defines a header. * * This parser sacrifices some features of the reference implementation the * differences to that implementation are as follows. * - No support for comments spanning multiple lines. * - Translator and extracted comments are treated as being the same type. * - Message IDs are allowed to have other encodings as just US-ASCII. * * Items with an empty id are ignored. * * @param resource $resource * * @return array */ private function parse($resource) { $stream = fopen($resource, 'r'); $defaults = array( 'ids' => array(), 'translated' => null, ); $messages = array(); $item = $defaults; while ($line = fgets($stream)) { $line = trim($line); if ($line === '') { // Whitespace indicated current item is done $this->addMessage($messages, $item); $item = $defaults; } elseif (substr($line, 0, 7) === 'msgid "') { // We start a new msg so save previous // TODO: this fails when comments or contexts are added $this->addMessage($messages, $item); $item = $defaults; $item['ids']['singular'] = substr($line, 7, -1); } elseif (substr($line, 0, 8) === 'msgstr "') { $item['translated'] = substr($line, 8, -1); } elseif ($line[0] === '"') { $continues = isset($item['translated']) ? 'translated' : 'ids'; if (is_array($item[$continues])) { end($item[$continues]); $item[$continues][key($item[$continues])] .= substr($line, 1, -1); } else { $item[$continues] .= substr($line, 1, -1); } } elseif (substr($line, 0, 14) === 'msgid_plural "') { $item['ids']['plural'] = substr($line, 14, -1); } elseif (substr($line, 0, 7) === 'msgstr[') { $size = strpos($line, ']'); $item['translated'][(integer) substr($line, 7, 1)] = substr($line, $size + 3, -1); } } // save last item $this->addMessage($messages, $item); fclose($stream); return $messages; } /** * Save a translation item to the messages. * * A .po file could contain by error missing plural indexes. We need to * fix these before saving them. * * @param array $messages * @param array $item */ private function addMessage(array &$messages, array $item) { if (is_array($item['translated'])) { $messages[$item['ids']['singular']] = stripslashes($item['translated'][0]); if (isset($item['ids']['plural'])) { $plurals = $item['translated']; // PO are by definition indexed so sort by index. ksort($plurals); // Make sure every index is filled. end($plurals); $count = key($plurals); // Fill missing spots with '-'. $empties = array_fill(0, $count+1, '-'); $plurals += $empties; ksort($plurals); $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals)); } } elseif (!empty($item['ids']['singular'])) { $messages[$item['ids']['singular']] = stripslashes($item['translated']); } } } PK!r;;6Symfony/Component/Translation/Loader/PhpFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * PhpFileLoader loads translations from PHP files returning an array of translations. * * @author Fabien Potencier * * @api */ class PhpFileLoader extends ArrayLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = require($resource); $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } } PK!: Z""BSymfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsdnu[

About the XML namespace

This schema document describes the XML namespace, in a form suitable for import by other schema documents.

See http://www.w3.org/XML/1998/namespace.html and http://www.w3.org/TR/REC-xml for information about this namespace.

Note that local names in this namespace are intended to be defined only by the World Wide Web Consortium or its subgroups. The names currently defined in this namespace are listed below. They should not be used with conflicting semantics by any Working Group, specification, or document instance.

See further below in this document for more information about how to refer to this schema document from your own XSD schema documents and about the namespace-versioning policy governing this schema document.

lang (as an attribute name)

denotes an attribute whose value is a language code for the natural language of the content of any element; its value is inherited. This name is reserved by virtue of its definition in the XML specification.

Notes

Attempting to install the relevant ISO 2- and 3-letter codes as the enumerated possible values is probably never going to be a realistic possibility.

See BCP 47 at http://www.rfc-editor.org/rfc/bcp/bcp47.txt and the IANA language subtag registry at http://www.iana.org/assignments/language-subtag-registry for further information.

The union allows for the 'un-declaration' of xml:lang with the empty string.

space (as an attribute name)

denotes an attribute whose value is a keyword indicating what whitespace processing discipline is intended for the content of the element; its value is inherited. This name is reserved by virtue of its definition in the XML specification.

base (as an attribute name)

denotes an attribute whose value provides a URI to be used as the base for interpreting any relative URIs in the scope of the element on which it appears; its value is inherited. This name is reserved by virtue of its definition in the XML Base specification.

See http://www.w3.org/TR/xmlbase/ for information about this attribute.

id (as an attribute name)

denotes an attribute whose value should be interpreted as if declared to be of type ID. This name is reserved by virtue of its definition in the xml:id specification.

See http://www.w3.org/TR/xml-id/ for information about this attribute.

Father (in any context at all)

denotes Jon Bosak, the chair of the original XML Working Group. This name is reserved by the following decision of the W3C XML Plenary and XML Coordination groups:

In appreciation for his vision, leadership and dedication the W3C XML Plenary on this 10th day of February, 2000, reserves for Jon Bosak in perpetuity the XML name "xml:Father".

About this schema document

This schema defines attributes and an attribute group suitable for use by schemas wishing to allow xml:base, xml:lang, xml:space or xml:id attributes on elements they define.

To enable this, such a schema must import this schema for the XML namespace, e.g. as follows:

          <schema.. .>
          .. .
           <import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
     

or


           <import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
     

Subsequently, qualified reference to any of the attributes or the group defined below will have the desired effect, e.g.

          <type.. .>
          .. .
           <attributeGroup ref="xml:specialAttrs"/>
     

will define a type which will schema-validate an instance element with any of those attributes.

Versioning policy for this schema document

In keeping with the XML Schema WG's standard versioning policy, this schema document will persist at http://www.w3.org/2009/01/xml.xsd.

At the date of issue it can also be found at http://www.w3.org/2001/xml.xsd.

The schema document at that URI may however change in the future, in order to remain compatible with the latest version of XML Schema itself, or with the XML namespace itself. In other words, if the XML Schema or XML namespaces change, the version of this document at http://www.w3.org/2001/xml.xsd will change accordingly; the version at http://www.w3.org/2009/01/xml.xsd will not change.

Previous dated (and unchanging) versions of this schema document are at:

PK!xOTSymfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsdnu[ Values for the attribute 'context-type'. Indicates a database content. Indicates the content of an element within an XML document. Indicates the name of an element within an XML document. Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found. Indicates a the number of parameters contained within the <source>. Indicates notes pertaining to the parameters in the <source>. Indicates the content of a record within a database. Indicates the name of a record within a database. Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file. Values for the attribute 'count-type'. Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts. Indicates the count units are translation units existing already in the same document. Indicates a total count. Values for the attribute 'ctype' when used other elements than <ph> or <x>. Indicates a run of bolded text. Indicates a run of text in italics. Indicates a run of underlined text. Indicates a run of hyper-text. Values for the attribute 'ctype' when used with <ph> or <x>. Indicates a inline image. Indicates a page break. Indicates a line break. Values for the attribute 'datatype'. Indicates Active Server Page data. Indicates C source file data. Indicates Channel Definition Format (CDF) data. Indicates ColdFusion data. Indicates C++ source file data. Indicates C-Sharp data. Indicates strings from C, ASM, and driver files data. Indicates comma-separated values data. Indicates database data. Indicates portions of document that follows data and contains metadata. Indicates portions of document that precedes data and contains metadata. Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import). Indicates standard user input screen data. Indicates HyperText Markup Language (HTML) data - document instance. Indicates content within an HTML document’s <body> element. Indicates Windows INI file data. Indicates Interleaf data. Indicates Java source file data (extension '.java'). Indicates Java property resource bundle data. Indicates Java list resource bundle data. Indicates JavaScript source file data. Indicates JScript source file data. Indicates information relating to formatting. Indicates LISP source file data. Indicates information relating to margin formats. Indicates a file containing menu. Indicates numerically identified string table. Indicates Maker Interchange Format (MIF) data. Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute. Indicates GNU Machine Object data. Indicates Message Librarian strings created by Novell's Message Librarian Tool. Indicates information to be displayed at the bottom of each page of a document. Indicates information to be displayed at the top of each page of a document. Indicates a list of property values (e.g., settings within INI files or preferences dialog). Indicates Pascal source file data. Indicates Hypertext Preprocessor data. Indicates plain text file (no formatting other than, possibly, wrapping). Indicates GNU Portable Object file. Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc. Indicates Windows .NET binary resources. Indicates Windows .NET Resources. Indicates Rich Text Format (RTF) data. Indicates Standard Generalized Markup Language (SGML) data - document instance. Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD). Indicates Scalable Vector Graphic (SVG) data. Indicates VisualBasic Script source file. Indicates warning message. Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file). Indicates Extensible HyperText Markup Language (XHTML) data - document instance. Indicates Extensible Markup Language (XML) data - document instance. Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD). Indicates Extensible Stylesheet Language (XSL) data. Indicates XUL elements. Values for the attribute 'mtype'. Indicates the marked text is an abbreviation. ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept. ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective'). ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging'). ISO-12620: A proper-name term, such as the name of an agency or other proper entity. ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another. ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language. Indicates the marked text is a date and/or time. ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign. ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form. ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula. ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record. ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy'). ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body. ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages. ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like. ISO-12620 2.1.17: A unit to track object. Indicates the marked text is a name. ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others. ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system. Indicates the marked text is a phrase. ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase. Indicates the marked text should not be translated. ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet. Indicates that the marked text represents a segment. ISO-12620 2.1.18.2: A fixed, lexicalized phrase. ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs'). ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system. ISO-12620 2.1.19: A fixed chunk of recurring text. ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof. ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry. ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language. Indicates the marked text is a term. ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted. ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system. ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza'). ISO-12620 2.1.9: One of the alternate forms of a term. Values for the attribute 'restype'. Indicates a Windows RC AUTO3STATE control. Indicates a Windows RC AUTOCHECKBOX control. Indicates a Windows RC AUTORADIOBUTTON control. Indicates a Windows RC BEDIT control. Indicates a bitmap, for example a BITMAP resource in Windows. Indicates a button object, for example a BUTTON control Windows. Indicates a caption, such as the caption of a dialog box. Indicates the cell in a table, for example the content of the <td> element in HTML. Indicates check box object, for example a CHECKBOX control in Windows. Indicates a menu item with an associated checkbox. Indicates a list box, but with a check-box for each item. Indicates a color selection dialog. Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows. Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234). Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403). Indicates a UI base class element that cannot be represented by any other element. Indicates a context menu. Indicates a Windows RC CTEXT control. Indicates a cursor, for example a CURSOR resource in Windows. Indicates a date/time picker. Indicates a Windows RC DEFPUSHBUTTON control. Indicates a dialog box. Indicates a Windows RC DLGINIT resource block. Indicates an edit box object, for example an EDIT control in Windows. Indicates a filename. Indicates a file dialog. Indicates a footnote. Indicates a font name. Indicates a footer. Indicates a frame object. Indicates a XUL grid element. Indicates a groupbox object, for example a GROUPBOX control in Windows. Indicates a header item. Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML. Indicates a Windows RC HEDIT control. Indicates a horizontal scrollbar. Indicates an icon, for example an ICON resource in Windows. Indicates a Windows RC IEDIT control. Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF. Indicates a label object. Indicates a label that is also a HTML link (not necessarily a URL). Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML). Indicates a listbox object, for example an LISTBOX control in Windows. Indicates an list item (an entry in a list). Indicates a Windows RC LTEXT control. Indicates a menu (a group of menu-items). Indicates a toolbar containing one or more tope level menus. Indicates a menu item (an entry in a menu). Indicates a XUL menuseparator element. Indicates a message, for example an entry in a MESSAGETABLE resource in Windows. Indicates a calendar control. Indicates an edit box beside a spin control. Indicates a catch all for rectangular areas. Indicates a standalone menu not necessarily associated with a menubar. Indicates a pushbox object, for example a PUSHBOX control in Windows. Indicates a Windows RC PUSHBUTTON control. Indicates a radio button object. Indicates a menuitem with associated radio button. Indicates raw data resources for an application. Indicates a row in a table. Indicates a Windows RC RTEXT control. Indicates a user navigable container used to show a portion of a document. Indicates a generic divider object (e.g. menu group separator). Windows accelerators, shortcuts in resource or property files. Indicates a UI control to indicate process activity but not progress. Indicates a splitter bar. Indicates a Windows RC STATE3 control. Indicates a window for providing feedback to the users, like 'read-only', etc. Indicates a string, for example an entry in a STRINGTABLE resource in Windows. Indicates a layers of controls with a tab to select layers. Indicates a display and edits regular two-dimensional tables of cells. Indicates a XUL textbox element. Indicates a UI button that can be toggled to on or off state. Indicates an array of controls, usually buttons. Indicates a pop up tool tip text. Indicates a bar with a pointer indicating a position within a certain range. Indicates a control that displays a set of hierarchical data. Indicates a URI (URN or URL). Indicates a Windows RC USERBUTTON control. Indicates a user-defined control like CONTROL control in Windows. Indicates the text of a variable. Indicates version information about a resource like VERSIONINFO in Windows. Indicates a vertical scrollbar. Indicates a graphical window. Values for the attribute 'size-unit'. Indicates a size in 8-bit bytes. Indicates a size in Unicode characters. Indicates a size in columns. Used for HTML text area. Indicates a size in centimeters. Indicates a size in dialog units, as defined in Windows resources. Indicates a size in 'font-size' units (as defined in CSS). Indicates a size in 'x-height' units (as defined in CSS). Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster' Indicates a size in inches. Indicates a size in millimeters. Indicates a size in percentage. Indicates a size in pixels. Indicates a size in point. Indicates a size in rows. Used for HTML text area. Values for the attribute 'state'. Indicates the terminating state. Indicates only non-textual information needs adaptation. Indicates both text and non-textual information needs adaptation. Indicates only non-textual information needs review. Indicates both text and non-textual information needs review. Indicates that only the text of the item needs to be reviewed. Indicates that the item needs to be translated. Indicates that the item is new. For example, translation units that were not in a previous version of the document. Indicates that changes are reviewed and approved. Indicates that the item has been translated. Values for the attribute 'state-qualifier'. Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously. Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.). Indicates a match based on matching IDs (in addition to matching text). Indicates a translation derived from a glossary. Indicates a translation derived from existing translation. Indicates a translation derived from machine translation. Indicates a translation derived from a translation repository. Indicates a translation derived from a translation memory. Indicates the translation is suggested by machine translation. Indicates that the item has been rejected because of incorrect grammar. Indicates that the item has been rejected because it is incorrect. Indicates that the item has been rejected because it is too long or too short. Indicates that the item has been rejected because of incorrect spelling. Indicates the translation is suggested by translation memory. Values for the attribute 'unit'. Refers to words. Refers to pages. Refers to <trans-unit> elements. Refers to <bin-unit> elements. Refers to glyphs. Refers to <trans-unit> and/or <bin-unit> elements. Refers to the occurrences of instances defined by the count-type value. Refers to characters. Refers to lines. Refers to sentences. Refers to paragraphs. Refers to segments. Refers to placeables (inline elements). Values for the attribute 'priority'. Highest priority. High priority. High priority, but not as important as 2. High priority, but not as important as 3. Medium priority, but more important than 6. Medium priority, but less important than 5. Low priority, but more important than 8. Low priority, but more important than 9. Low priority. Lowest priority. This value indicates that all properties can be reformatted. This value must be used alone. This value indicates that no properties should be reformatted. This value must be used alone. This value indicates that all information in the coord attribute can be modified. This value indicates that the x information in the coord attribute can be modified. This value indicates that the y information in the coord attribute can be modified. This value indicates that the cx information in the coord attribute can be modified. This value indicates that the cy information in the coord attribute can be modified. This value indicates that all the information in the font attribute can be modified. This value indicates that the name information in the font attribute can be modified. This value indicates that the size information in the font attribute can be modified. This value indicates that the weight information in the font attribute can be modified. This value indicates that the information in the css-style attribute can be modified. This value indicates that the information in the style attribute can be modified. This value indicates that the information in the exstyle attribute can be modified. Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document. Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed. Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed. Represents a translation proposal from a translation memory or other resource. Represents a previous version of the target element. Represents a rejected version of the target element. Represents a translation to be used for reference purposes only, for example from a related product or a different language. Represents a proposed translation that was used for the translation of the trans-unit, possibly modified. Values for the attribute 'coord'. Version values: 1.0 and 1.1 are allowed for backward compatibility. PK!)-d+ 5Symfony/Component/Translation/Loader/QtFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * QtFileLoader loads translations from QT Translations XML files. * * @author Benjamin Eberlei * * @api */ class QtFileLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } try { $dom = XmlUtils::loadFile($resource); } catch (\InvalidArgumentException $e) { throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e); } $internalErrors = libxml_use_internal_errors(true); libxml_clear_errors(); $xpath = new \DOMXPath($dom); $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]'); $catalogue = new MessageCatalogue($locale); if ($nodes->length == 1) { $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message'); foreach ($translations as $translation) { $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue; if (!empty($translationValue)) { $catalogue->set( (string) $translation->getElementsByTagName('source')->item(0)->nodeValue, $translationValue, $domain ); } $translation = $translation->nextSibling; } $catalogue->addResource(new FileResource($resource)); } libxml_use_internal_errors($internalErrors); return $catalogue; } } PK!:7Symfony/Component/Translation/Loader/YamlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\Yaml\Exception\ParseException; /** * YamlFileLoader loads translations from Yaml files. * * @author Fabien Potencier * * @api */ class YamlFileLoader extends ArrayLoader implements LoaderInterface { private $yamlParser; /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } try { $messages = $this->yamlParser->parse(file_get_contents($resource)); } catch (ParseException $e) { throw new InvalidResourceException('Error parsing YAML.', 0, $e); } // empty file if (null === $messages) { $messages = array(); } // not an array if (!is_array($messages)) { throw new InvalidResourceException(sprintf('The file "%s" must contain a YAML array.', $resource)); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } } PK!V˽ .Symfony/Component/Routing/Annotation/Route.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Annotation; /** * Annotation class for @Route(). * * @Annotation * * @author Fabien Potencier */ class Route { private $path; private $name; private $requirements = array(); private $options = array(); private $defaults = array(); private $host; private $methods = array(); private $schemes = array(); private $condition; /** * Constructor. * * @param array $data An array of key/value parameters. * * @throws \BadMethodCallException */ public function __construct(array $data) { if (isset($data['value'])) { $data['path'] = $data['value']; unset($data['value']); } foreach ($data as $key => $value) { $method = 'set'.str_replace('_', '', $key); if (!method_exists($this, $method)) { throw new \BadMethodCallException(sprintf("Unknown property '%s' on annotation '%s'.", $key, get_class($this))); } $this->$method($value); } } /** * @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead. */ public function setPattern($pattern) { $this->path = $pattern; } /** * @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead. */ public function getPattern() { return $this->path; } public function setPath($path) { $this->path = $path; } public function getPath() { return $this->path; } public function setHost($pattern) { $this->host = $pattern; } public function getHost() { return $this->host; } public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } public function setRequirements($requirements) { $this->requirements = $requirements; } public function getRequirements() { return $this->requirements; } public function setOptions($options) { $this->options = $options; } public function getOptions() { return $this->options; } public function setDefaults($defaults) { $this->defaults = $defaults; } public function getDefaults() { return $this->defaults; } public function setSchemes($schemes) { $this->schemes = is_array($schemes) ? $schemes : array($schemes); } public function getSchemes() { return $this->schemes; } public function setMethods($methods) { $this->methods = is_array($methods) ? $methods : array($methods); } public function getMethods() { return $this->methods; } public function setCondition($condition) { $this->condition = $condition; } public function getCondition() { return $this->condition; } } PK!<ѹ +Symfony/Component/Routing/CompiledRoute.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * CompiledRoutes are returned by the RouteCompiler class. * * @author Fabien Potencier */ class CompiledRoute { private $variables; private $tokens; private $staticPrefix; private $regex; private $pathVariables; private $hostVariables; private $hostRegex; private $hostTokens; /** * Constructor. * * @param string $staticPrefix The static prefix of the compiled route * @param string $regex The regular expression to use to match this route * @param array $tokens An array of tokens to use to generate URL for this route * @param array $pathVariables An array of path variables * @param string|null $hostRegex Host regex * @param array $hostTokens Host tokens * @param array $hostVariables An array of host variables * @param array $variables An array of variables (variables defined in the path and in the host patterns) */ public function __construct($staticPrefix, $regex, array $tokens, array $pathVariables, $hostRegex = null, array $hostTokens = array(), array $hostVariables = array(), array $variables = array()) { $this->staticPrefix = (string) $staticPrefix; $this->regex = $regex; $this->tokens = $tokens; $this->pathVariables = $pathVariables; $this->hostRegex = $hostRegex; $this->hostTokens = $hostTokens; $this->hostVariables = $hostVariables; $this->variables = $variables; } /** * Returns the static prefix. * * @return string The static prefix */ public function getStaticPrefix() { return $this->staticPrefix; } /** * Returns the regex. * * @return string The regex */ public function getRegex() { return $this->regex; } /** * Returns the host regex * * @return string|null The host regex or null */ public function getHostRegex() { return $this->hostRegex; } /** * Returns the tokens. * * @return array The tokens */ public function getTokens() { return $this->tokens; } /** * Returns the host tokens. * * @return array The tokens */ public function getHostTokens() { return $this->hostTokens; } /** * Returns the variables. * * @return array The variables */ public function getVariables() { return $this->variables; } /** * Returns the path variables. * * @return array The variables */ public function getPathVariables() { return $this->pathVariables; } /** * Returns the host variables. * * @return array The variables */ public function getHostVariables() { return $this->hostVariables; } } PK!U8-Symfony/Component/Routing/RouterInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; /** * RouterInterface is the interface that all Router classes must implement. * * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. * * @author Fabien Potencier */ interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface { /** * Gets the RouteCollection instance associated with this Router. * * @return RouteCollection A RouteCollection instance */ public function getRouteCollection(); } PK!UcQQ(Symfony/Component/Routing/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * RouteCompiler compiles Route instances to CompiledRoute instances. * * @author Fabien Potencier * @author Tobias Schultze */ class RouteCompiler implements RouteCompilerInterface { const REGEX_DELIMITER = '#'; /** * This string defines the characters that are automatically considered separators in front of * optional placeholders (with default and no static text following). Such a single separator * can be left out together with the optional placeholder from matching and generating URLs. */ const SEPARATORS = '/,;.:-_~+*=@|'; /** * {@inheritDoc} * * @throws \LogicException If a variable is referenced more than once * @throws \DomainException If a variable name is numeric because PHP raises an error for such * subpatterns in PCRE and thus would break matching, e.g. "(?P<123>.+)". */ public static function compile(Route $route) { $staticPrefix = null; $hostVariables = array(); $pathVariables = array(); $variables = array(); $tokens = array(); $regex = null; $hostRegex = null; $hostTokens = array(); if ('' !== $host = $route->getHost()) { $result = self::compilePattern($route, $host, true); $hostVariables = $result['variables']; $variables = array_merge($variables, $hostVariables); $hostTokens = $result['tokens']; $hostRegex = $result['regex']; } $path = $route->getPath(); $result = self::compilePattern($route, $path, false); $staticPrefix = $result['staticPrefix']; $pathVariables = $result['variables']; $variables = array_merge($variables, $pathVariables); $tokens = $result['tokens']; $regex = $result['regex']; return new CompiledRoute( $staticPrefix, $regex, $tokens, $pathVariables, $hostRegex, $hostTokens, $hostVariables, array_unique($variables) ); } private static function compilePattern(Route $route, $pattern, $isHost) { $tokens = array(); $variables = array(); $matches = array(); $pos = 0; $defaultSeparator = $isHost ? '.' : '/'; // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself. preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); foreach ($matches as $match) { $varName = substr($match[0][0], 1, -1); // get all static text preceding the current variable $precedingText = substr($pattern, $pos, $match[0][1] - $pos); $pos = $match[0][1] + strlen($match[0][0]); $precedingChar = strlen($precedingText) > 0 ? substr($precedingText, -1) : ''; $isSeparator = '' !== $precedingChar && false !== strpos(static::SEPARATORS, $precedingChar); if (is_numeric($varName)) { throw new \DomainException(sprintf('Variable name "%s" cannot be numeric in route pattern "%s". Please use a different name.', $varName, $pattern)); } if (in_array($varName, $variables)) { throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); } if ($isSeparator && strlen($precedingText) > 1) { $tokens[] = array('text', substr($precedingText, 0, -1)); } elseif (!$isSeparator && strlen($precedingText) > 0) { $tokens[] = array('text', $precedingText); } $regexp = $route->getRequirement($varName); if (null === $regexp) { $followingPattern = (string) substr($pattern, $pos); // Find the next static character after the variable that functions as a separator. By default, this separator and '/' // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are // the same that will be matched. Example: new Route('/{page}.{_format}', array('_format' => 'html')) // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. $nextSeparator = self::findNextSeparator($followingPattern); $regexp = sprintf( '[^%s%s]+', preg_quote($defaultSeparator, self::REGEX_DELIMITER), $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator, self::REGEX_DELIMITER) : '' ); if (('' !== $nextSeparator && !preg_match('#^\{\w+\}#', $followingPattern)) || '' === $followingPattern) { // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns. // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is // directly adjacent, e.g. '/{x}{y}'. $regexp .= '+'; } } $tokens[] = array('variable', $isSeparator ? $precedingChar : '', $regexp, $varName); $variables[] = $varName; } if ($pos < strlen($pattern)) { $tokens[] = array('text', substr($pattern, $pos)); } // find the first optional token $firstOptional = PHP_INT_MAX; if (!$isHost) { for ($i = count($tokens) - 1; $i >= 0; $i--) { $token = $tokens[$i]; if ('variable' === $token[0] && $route->hasDefault($token[3])) { $firstOptional = $i; } else { break; } } } // compute the matching regexp $regexp = ''; for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) { $regexp .= self::computeRegexp($tokens, $i, $firstOptional); } return array( 'staticPrefix' => 'text' === $tokens[0][0] ? $tokens[0][1] : '', 'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s', 'tokens' => array_reverse($tokens), 'variables' => $variables, ); } /** * Returns the next static character in the Route pattern that will serve as a separator. * * @param string $pattern The route pattern * * @return string The next static character that functions as separator (or empty string when none available) */ private static function findNextSeparator($pattern) { if ('' == $pattern) { // return empty string if pattern is empty or false (false which can be returned by substr) return ''; } // first remove all placeholders from the pattern so we can find the next real static character $pattern = preg_replace('#\{\w+\}#', '', $pattern); return isset($pattern[0]) && false !== strpos(static::SEPARATORS, $pattern[0]) ? $pattern[0] : ''; } /** * Computes the regexp used to match a specific token. It can be static text or a subpattern. * * @param array $tokens The route tokens * @param integer $index The index of the current token * @param integer $firstOptional The index of the first optional token * * @return string The regexp pattern for a single token */ private static function computeRegexp(array $tokens, $index, $firstOptional) { $token = $tokens[$index]; if ('text' === $token[0]) { // Text tokens return preg_quote($token[1], self::REGEX_DELIMITER); } else { // Variable tokens if (0 === $index && 0 === $firstOptional) { // When the only token is an optional variable token, the separator is required return sprintf('%s(?P<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); } else { $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); if ($index >= $firstOptional) { // Enclose each optional token in a subpattern to make it optional. // "?:" means it is non-capturing, i.e. the portion of the subject string that // matched the optional subpattern is not passed back. $regexp = "(?:$regexp"; $nbTokens = count($tokens); if ($nbTokens - 1 == $index) { // Close the optional subpatterns $regexp .= str_repeat(")?", $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); } } return $regexp; } } } } PK! %%$Symfony/Component/Routing/Router.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\ConfigCache; use Psr\Log\LoggerInterface; use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; use Symfony\Component\HttpFoundation\Request; /** * The Router class is an example of the integration of all pieces of the * routing system for easier use. * * @author Fabien Potencier */ class Router implements RouterInterface, RequestMatcherInterface { /** * @var UrlMatcherInterface|null */ protected $matcher; /** * @var UrlGeneratorInterface|null */ protected $generator; /** * @var RequestContext */ protected $context; /** * @var LoaderInterface */ protected $loader; /** * @var RouteCollection|null */ protected $collection; /** * @var mixed */ protected $resource; /** * @var array */ protected $options = array(); /** * @var LoggerInterface|null */ protected $logger; /** * Constructor. * * @param LoaderInterface $loader A LoaderInterface instance * @param mixed $resource The main resource to load * @param array $options An array of options * @param RequestContext $context The context * @param LoggerInterface $logger A logger instance */ public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null) { $this->loader = $loader; $this->resource = $resource; $this->logger = $logger; $this->context = $context ?: new RequestContext(); $this->setOptions($options); } /** * Sets options. * * Available options: * * * cache_dir: The cache directory (or null to disable caching) * * debug: Whether to enable debugging or not (false by default) * * resource_type: Type hint for the main resource (optional) * * @param array $options An array of options * * @throws \InvalidArgumentException When unsupported option is provided */ public function setOptions(array $options) { $this->options = array( 'cache_dir' => null, 'debug' => false, 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', 'generator_base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper', 'generator_cache_class' => 'ProjectUrlGenerator', 'matcher_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', 'matcher_base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper', 'matcher_cache_class' => 'ProjectUrlMatcher', 'resource_type' => null, 'strict_requirements' => true, ); // check option names and live merge, if errors are encountered Exception will be thrown $invalid = array(); foreach ($options as $key => $value) { if (array_key_exists($key, $this->options)) { $this->options[$key] = $value; } else { $invalid[] = $key; } } if ($invalid) { throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid))); } } /** * Sets an option. * * @param string $key The key * @param mixed $value The value * * @throws \InvalidArgumentException */ public function setOption($key, $value) { if (!array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } $this->options[$key] = $value; } /** * Gets an option value. * * @param string $key The key * * @return mixed The value * * @throws \InvalidArgumentException */ public function getOption($key) { if (!array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } return $this->options[$key]; } /** * {@inheritdoc} */ public function getRouteCollection() { if (null === $this->collection) { $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); } return $this->collection; } /** * {@inheritdoc} */ public function setContext(RequestContext $context) { $this->context = $context; if (null !== $this->matcher) { $this->getMatcher()->setContext($context); } if (null !== $this->generator) { $this->getGenerator()->setContext($context); } } /** * {@inheritdoc} */ public function getContext() { return $this->context; } /** * {@inheritdoc} */ public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) { return $this->getGenerator()->generate($name, $parameters, $referenceType); } /** * {@inheritdoc} */ public function match($pathinfo) { return $this->getMatcher()->match($pathinfo); } /** * {@inheritdoc} */ public function matchRequest(Request $request) { $matcher = $this->getMatcher(); if (!$matcher instanceof RequestMatcherInterface) { // fallback to the default UrlMatcherInterface return $matcher->match($request->getPathInfo()); } return $matcher->matchRequest($request); } /** * Gets the UrlMatcher instance associated with this Router. * * @return UrlMatcherInterface A UrlMatcherInterface instance */ public function getMatcher() { if (null !== $this->matcher) { return $this->matcher; } if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context); } $class = $this->options['matcher_cache_class']; $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); if (!$cache->isFresh()) { $dumper = $this->getMatcherDumperInstance(); $options = array( 'class' => $class, 'base_class' => $this->options['matcher_base_class'], ); $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); } require_once $cache; return $this->matcher = new $class($this->context); } /** * Gets the UrlGenerator instance associated with this Router. * * @return UrlGeneratorInterface A UrlGeneratorInterface instance */ public function getGenerator() { if (null !== $this->generator) { return $this->generator; } if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger); } else { $class = $this->options['generator_cache_class']; $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); if (!$cache->isFresh()) { $dumper = $this->getGeneratorDumperInstance(); $options = array( 'class' => $class, 'base_class' => $this->options['generator_base_class'], ); $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); } require_once $cache; $this->generator = new $class($this->context, $this->logger); } if ($this->generator instanceof ConfigurableRequirementsInterface) { $this->generator->setStrictRequirements($this->options['strict_requirements']); } return $this->generator; } /** * @return GeneratorDumperInterface */ protected function getGeneratorDumperInstance() { return new $this->options['generator_dumper_class']($this->getRouteCollection()); } /** * @return MatcherDumperInterface */ protected function getMatcherDumperInstance() { return new $this->options['matcher_dumper_class']($this->getRouteCollection()); } } PK!q q 6Symfony/Component/Routing/Matcher/ApacheUrlMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\MethodNotAllowedException; /** * ApacheUrlMatcher matches URL based on Apache mod_rewrite matching (see ApacheMatcherDumper). * * @author Fabien Potencier * @author Arnaud Le Blanc */ class ApacheUrlMatcher extends UrlMatcher { /** * Tries to match a URL based on Apache mod_rewrite matching. * * Returns false if no route matches the URL. * * @param string $pathinfo The pathinfo to be parsed * * @return array An array of parameters * * @throws MethodNotAllowedException If the current method is not allowed */ public function match($pathinfo) { $parameters = array(); $defaults = array(); $allow = array(); $route = null; foreach ($this->denormalizeValues($_SERVER) as $key => $value) { $name = $key; // skip non-routing variables // this improves performance when $_SERVER contains many usual // variables like HTTP_*, DOCUMENT_ROOT, REQUEST_URI, ... if (false === strpos($name, '_ROUTING_')) { continue; } while (0 === strpos($name, 'REDIRECT_')) { $name = substr($name, 9); } // expect _ROUTING__ // or _ROUTING_ if (0 !== strpos($name, '_ROUTING_')) { continue; } if (false !== $pos = strpos($name, '_', 9)) { $type = substr($name, 9, $pos-9); $name = substr($name, $pos+1); } else { $type = substr($name, 9); } if ('param' === $type) { if ('' !== $value) { $parameters[$name] = $value; } } elseif ('default' === $type) { $defaults[$name] = $value; } elseif ('route' === $type) { $route = $value; } elseif ('allow' === $type) { $allow[] = $name; } unset($_SERVER[$key]); } if (null !== $route) { $parameters['_route'] = $route; return $this->mergeDefaults($parameters, $defaults); } elseif (0 < count($allow)) { throw new MethodNotAllowedException($allow); } else { return parent::match($pathinfo); } } /** * Denormalizes an array of values. * * @param string[] $values * * @return array */ private function denormalizeValues(array $values) { $normalizedValues = array(); foreach ($values as $key => $value) { if (preg_match('~^(.*)\[(\d+)\]$~', $key, $matches)) { if (!isset($normalizedValues[$matches[1]])) { $normalizedValues[$matches[1]] = array(); } $normalizedValues[$matches[1]][(int) $matches[2]] = $value; } else { $normalizedValues[$key] = $value; } } return $normalizedValues; } } PK! ڗ9Symfony/Component/Routing/Matcher/UrlMatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\MethodNotAllowedException; /** * UrlMatcherInterface is the interface that all URL matcher classes must implement. * * @author Fabien Potencier * * @api */ interface UrlMatcherInterface extends RequestContextAwareInterface { /** * Tries to match a URL path with a set of routes. * * If the matcher can not find information, it must throw one of the exceptions documented * below. * * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) * * @return array An array of parameters * * @throws ResourceNotFoundException If the resource could not be found * @throws MethodNotAllowedException If the resource was found but the request method is not allowed * * @api */ public function match($pathinfo); } PK!`u=Symfony/Component/Routing/Matcher/RequestMatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\MethodNotAllowedException; /** * RequestMatcherInterface is the interface that all request matcher classes must implement. * * @author Fabien Potencier */ interface RequestMatcherInterface { /** * Tries to match a request with a set of routes. * * If the matcher can not find information, it must throw one of the exceptions documented * below. * * @param Request $request The request to match * * @return array An array of parameters * * @throws ResourceNotFoundException If no matching resource could be found * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed */ public function matchRequest(Request $request); } PK![zdd<Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Route; /** * @author Fabien Potencier * * @api */ abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface { /** * {@inheritdoc} */ public function match($pathinfo) { try { $parameters = parent::match($pathinfo); } catch (ResourceNotFoundException $e) { if ('/' === substr($pathinfo, -1) || !in_array($this->context->getMethod(), array('HEAD', 'GET'))) { throw $e; } try { parent::match($pathinfo.'/'); return $this->redirect($pathinfo.'/', null); } catch (ResourceNotFoundException $e2) { throw $e; } } return $parameters; } /** * {@inheritDoc} */ protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { return array(self::REQUIREMENT_MISMATCH, null); } // check HTTP scheme requirement $scheme = $route->getRequirement('_scheme'); if ($scheme && $this->context->getScheme() !== $scheme) { return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, $scheme)); } return array(self::REQUIREMENT_MATCH, null); } } PK!?|{:Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\RouteCollection; /** * MatcherDumper is the abstract class for all built-in matcher dumpers. * * @author Fabien Potencier */ abstract class MatcherDumper implements MatcherDumperInterface { /** * @var RouteCollection */ private $routes; /** * Constructor. * * @param RouteCollection $routes The RouteCollection to dump */ public function __construct(RouteCollection $routes) { $this->routes = $routes; } /** * {@inheritdoc} */ public function getRoutes() { return $this->routes; } } PK!x}44=Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; /** * PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes. * * @author Fabien Potencier * @author Tobias Schultze * @author Arnaud Le Blanc */ class PhpMatcherDumper extends MatcherDumper { private $expressionLanguage; /** * Dumps a set of routes to a PHP class. * * Available options: * * * class: The class name * * base_class: The base class name * * @param array $options An array of options * * @return string A PHP class representing the matcher class */ public function dump(array $options = array()) { $options = array_replace(array( 'class' => 'ProjectUrlMatcher', 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', ), $options); // trailing slash support is only enabled if we know how to redirect the user $interfaces = class_implements($options['base_class']); $supportsRedirections = isset($interfaces['Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface']); return <<context = \$context; } {$this->generateMatchMethod($supportsRedirections)} } EOF; } /** * Generates the code for the match method implementing UrlMatcherInterface. * * @param Boolean $supportsRedirections Whether redirections are supported by the base class * * @return string Match method as PHP code */ private function generateMatchMethod($supportsRedirections) { $code = rtrim($this->compileRoutes($this->getRoutes(), $supportsRedirections), "\n"); return <<context; \$request = \$this->request; $code throw 0 < count(\$allow) ? new MethodNotAllowedException(array_unique(\$allow)) : new ResourceNotFoundException(); } EOF; } /** * Generates PHP code to match a RouteCollection with all its routes. * * @param RouteCollection $routes A RouteCollection instance * @param Boolean $supportsRedirections Whether redirections are supported by the base class * * @return string PHP code */ private function compileRoutes(RouteCollection $routes, $supportsRedirections) { $fetchedHost = false; $groups = $this->groupRoutesByHostRegex($routes); $code = ''; foreach ($groups as $collection) { if (null !== $regex = $collection->getAttribute('host_regex')) { if (!$fetchedHost) { $code .= " \$host = \$this->context->getHost();\n\n"; $fetchedHost = true; } $code .= sprintf(" if (preg_match(%s, \$host, \$hostMatches)) {\n", var_export($regex, true)); } $tree = $this->buildPrefixTree($collection); $groupCode = $this->compilePrefixRoutes($tree, $supportsRedirections); if (null !== $regex) { // apply extra indention at each line (except empty ones) $groupCode = preg_replace('/^.{2,}$/m', ' $0', $groupCode); $code .= $groupCode; $code .= " }\n\n"; } else { $code .= $groupCode; } } return $code; } /** * Generates PHP code recursively to match a tree of routes * * @param DumperPrefixCollection $collection A DumperPrefixCollection instance * @param Boolean $supportsRedirections Whether redirections are supported by the base class * @param string $parentPrefix Prefix of the parent collection * * @return string PHP code */ private function compilePrefixRoutes(DumperPrefixCollection $collection, $supportsRedirections, $parentPrefix = '') { $code = ''; $prefix = $collection->getPrefix(); $optimizable = 1 < strlen($prefix) && 1 < count($collection->all()); $optimizedPrefix = $parentPrefix; if ($optimizable) { $optimizedPrefix = $prefix; $code .= sprintf(" if (0 === strpos(\$pathinfo, %s)) {\n", var_export($prefix, true)); } foreach ($collection as $route) { if ($route instanceof DumperCollection) { $code .= $this->compilePrefixRoutes($route, $supportsRedirections, $optimizedPrefix); } else { $code .= $this->compileRoute($route->getRoute(), $route->getName(), $supportsRedirections, $optimizedPrefix)."\n"; } } if ($optimizable) { $code .= " }\n\n"; // apply extra indention at each line (except empty ones) $code = preg_replace('/^.{2,}$/m', ' $0', $code); } return $code; } /** * Compiles a single Route to PHP code used to match it against the path info. * * @param Route $route A Route instance * @param string $name The name of the Route * @param Boolean $supportsRedirections Whether redirections are supported by the base class * @param string|null $parentPrefix The prefix of the parent collection used to optimize the code * * @return string PHP code * * @throws \LogicException */ private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) { $code = ''; $compiledRoute = $route->compile(); $conditions = array(); $hasTrailingSlash = false; $matches = false; $hostMatches = false; $methods = array(); if ($req = $route->getRequirement('_method')) { $methods = explode('|', strtoupper($req)); // GET and HEAD are equivalent if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { $methods[] = 'HEAD'; } } $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods)); if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#', $compiledRoute->getRegex(), $m)) { if ($supportsTrailingSlash && substr($m['url'], -1) === '/') { $conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); $hasTrailingSlash = true; } else { $conditions[] = sprintf("\$pathinfo === %s", var_export(str_replace('\\', '', $m['url']), true)); } } else { if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() !== $parentPrefix) { $conditions[] = sprintf("0 === strpos(\$pathinfo, %s)", var_export($compiledRoute->getStaticPrefix(), true)); } $regex = $compiledRoute->getRegex(); if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) { $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); $hasTrailingSlash = true; } $conditions[] = sprintf("preg_match(%s, \$pathinfo, \$matches)", var_export($regex, true)); $matches = true; } if ($compiledRoute->getHostVariables()) { $hostMatches = true; } if ($route->getCondition()) { $conditions[] = $this->getExpressionLanguage()->compile($route->getCondition(), array('context', 'request')); } $conditions = implode(' && ', $conditions); $code .= <<context->getMethod() != '$methods[0]') { \$allow[] = '$methods[0]'; goto $gotoname; } EOF; } else { $methods = implode("', '", $methods); $code .= <<context->getMethod(), array('$methods'))) { \$allow = array_merge(\$allow, array('$methods')); goto $gotoname; } EOF; } } if ($hasTrailingSlash) { $code .= <<redirect(\$pathinfo.'/', '$name'); } EOF; } if ($scheme = $route->getRequirement('_scheme')) { if (!$supportsRedirections) { throw new \LogicException('The "_scheme" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.'); } $code .= <<context->getScheme() !== '$scheme') { return \$this->redirect(\$pathinfo, '$name', '$scheme'); } EOF; } // optimize parameters array if ($matches || $hostMatches) { $vars = array(); if ($hostMatches) { $vars[] = '$hostMatches'; } if ($matches) { $vars[] = '$matches'; } $vars[] = "array('_route' => '$name')"; $code .= sprintf(" return \$this->mergeDefaults(array_replace(%s), %s);\n" , implode(', ', $vars), str_replace("\n", '', var_export($route->getDefaults(), true))); } elseif ($route->getDefaults()) { $code .= sprintf(" return %s;\n", str_replace("\n", '', var_export(array_replace($route->getDefaults(), array('_route' => $name)), true))); } else { $code .= sprintf(" return array('_route' => '%s');\n", $name); } $code .= " }\n"; if ($methods) { $code .= " $gotoname:\n"; } return $code; } /** * Groups consecutive routes having the same host regex. * * The result is a collection of collections of routes having the same host regex. * * @param RouteCollection $routes A flat RouteCollection * * @return DumperCollection A collection with routes grouped by host regex in sub-collections */ private function groupRoutesByHostRegex(RouteCollection $routes) { $groups = new DumperCollection(); $currentGroup = new DumperCollection(); $currentGroup->setAttribute('host_regex', null); $groups->add($currentGroup); foreach ($routes as $name => $route) { $hostRegex = $route->compile()->getHostRegex(); if ($currentGroup->getAttribute('host_regex') !== $hostRegex) { $currentGroup = new DumperCollection(); $currentGroup->setAttribute('host_regex', $hostRegex); $groups->add($currentGroup); } $currentGroup->add(new DumperRoute($name, $route)); } return $groups; } /** * Organizes the routes into a prefix tree. * * Routes order is preserved such that traversing the tree will traverse the * routes in the origin order. * * @param DumperCollection $collection A collection of routes * * @return DumperPrefixCollection */ private function buildPrefixTree(DumperCollection $collection) { $tree = new DumperPrefixCollection(); $current = $tree; foreach ($collection as $route) { $current = $current->addPrefixRoute($route); } $tree->mergeSlashNodes(); return $tree; } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK! bz#z#@Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\Route; /** * Dumps a set of Apache mod_rewrite rules. * * @author Fabien Potencier * @author Kris Wallsmith */ class ApacheMatcherDumper extends MatcherDumper { /** * Dumps a set of Apache mod_rewrite rules. * * Available options: * * * script_name: The script name (app.php by default) * * base_uri: The base URI ("" by default) * * @param array $options An array of options * * @return string A string to be used as Apache rewrite rules * * @throws \LogicException When the route regex is invalid */ public function dump(array $options = array()) { $options = array_merge(array( 'script_name' => 'app.php', 'base_uri' => '', ), $options); $options['script_name'] = self::escape($options['script_name'], ' ', '\\'); $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]"); $methodVars = array(); $hostRegexUnique = 0; $prevHostRegex = ''; foreach ($this->getRoutes()->all() as $name => $route) { if ($route->getCondition()) { throw new \LogicException(sprintf('Unable to dump the routes for Apache as route "%s" has a condition.', $name)); } $compiledRoute = $route->compile(); $hostRegex = $compiledRoute->getHostRegex(); if (null !== $hostRegex && $prevHostRegex !== $hostRegex) { $prevHostRegex = $hostRegex; $hostRegexUnique++; $rule = array(); $regex = $this->regexToApacheRegex($hostRegex); $regex = self::escape($regex, ' ', '\\'); $rule[] = sprintf('RewriteCond %%{HTTP:Host} %s', $regex); $variables = array(); $variables[] = sprintf('E=__ROUTING_host_%s:1', $hostRegexUnique); foreach ($compiledRoute->getHostVariables() as $i => $variable) { $variables[] = sprintf('E=__ROUTING_host_%s_%s:%%%d', $hostRegexUnique, $variable, $i+1); } $variables = implode(',', $variables); $rule[] = sprintf('RewriteRule .? - [%s]', $variables); $rules[] = implode("\n", $rule); } $rules[] = $this->dumpRoute($name, $route, $options, $hostRegexUnique); if ($req = $route->getRequirement('_method')) { $methods = explode('|', strtoupper($req)); $methodVars = array_merge($methodVars, $methods); } } if (0 < count($methodVars)) { $rule = array('# 405 Method Not Allowed'); $methodVars = array_values(array_unique($methodVars)); if (in_array('GET', $methodVars) && !in_array('HEAD', $methodVars)) { $methodVars[] = 'HEAD'; } foreach ($methodVars as $i => $methodVar) { $rule[] = sprintf('RewriteCond %%{ENV:_ROUTING__allow_%s} =1%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : ''); } $rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']); $rules[] = implode("\n", $rule); } return implode("\n\n", $rules)."\n"; } /** * Dumps a single route * * @param string $name Route name * @param Route $route The route * @param array $options Options * @param bool $hostRegexUnique Unique identifier for the host regex * * @return string The compiled route */ private function dumpRoute($name, $route, array $options, $hostRegexUnique) { $compiledRoute = $route->compile(); // prepare the apache regex $regex = $this->regexToApacheRegex($compiledRoute->getRegex()); $regex = '^'.self::escape(preg_quote($options['base_uri']).substr($regex, 1), ' ', '\\'); $methods = $this->getRouteMethods($route); $hasTrailingSlash = (!$methods || in_array('HEAD', $methods)) && '/$' === substr($regex, -2) && '^/$' !== $regex; $variables = array('E=_ROUTING_route:'.$name); foreach ($compiledRoute->getHostVariables() as $variable) { $variables[] = sprintf('E=_ROUTING_param_%s:%%{ENV:__ROUTING_host_%s_%s}', $variable, $hostRegexUnique, $variable); } foreach ($compiledRoute->getPathVariables() as $i => $variable) { $variables[] = 'E=_ROUTING_param_'.$variable.':%'.($i + 1); } foreach ($this->normalizeValues($route->getDefaults()) as $key => $value) { $variables[] = 'E=_ROUTING_default_'.$key.':'.strtr($value, array( ':' => '\\:', '=' => '\\=', '\\' => '\\\\', ' ' => '\\ ', )); } $variables = implode(',', $variables); $rule = array("# $name"); // method mismatch if (0 < count($methods)) { $allow = array(); foreach ($methods as $method) { $allow[] = 'E=_ROUTING_allow_'.$method.':1'; } if ($compiledRoute->getHostRegex()) { $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique); } $rule[] = "RewriteCond %{REQUEST_URI} $regex"; $rule[] = sprintf("RewriteCond %%{REQUEST_METHOD} !^(%s)$ [NC]", implode('|', $methods)); $rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow)); } // redirect with trailing slash appended if ($hasTrailingSlash) { if ($compiledRoute->getHostRegex()) { $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique); } $rule[] = 'RewriteCond %{REQUEST_URI} '.substr($regex, 0, -2).'$'; $rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]'; } // the main rule if ($compiledRoute->getHostRegex()) { $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique); } $rule[] = "RewriteCond %{REQUEST_URI} $regex"; $rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,$variables]"; return implode("\n", $rule); } /** * Returns methods allowed for a route * * @param Route $route The route * * @return array The methods */ private function getRouteMethods(Route $route) { $methods = array(); if ($req = $route->getRequirement('_method')) { $methods = explode('|', strtoupper($req)); // GET and HEAD are equivalent if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { $methods[] = 'HEAD'; } } return $methods; } /** * Converts a regex to make it suitable for mod_rewrite * * @param string $regex The regex * * @return string The converted regex */ private function regexToApacheRegex($regex) { $regexPatternEnd = strrpos($regex, $regex[0]); return preg_replace('/\?P<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1)); } /** * Escapes a string. * * @param string $string The string to be escaped * @param string $char The character to be escaped * @param string $with The character to be used for escaping * * @return string The escaped string */ private static function escape($string, $char, $with) { $escaped = false; $output = ''; foreach (str_split($string) as $symbol) { if ($escaped) { $output .= $symbol; $escaped = false; continue; } if ($symbol === $char) { $output .= $with.$char; continue; } if ($symbol === $with) { $escaped = true; } $output .= $symbol; } return $output; } /** * Normalizes an array of values. * * @param array $values * * @return string[] */ private function normalizeValues(array $values) { $normalizedValues = array(); foreach ($values as $key => $value) { if (is_array($value)) { foreach ($value as $index => $bit) { $normalizedValues[sprintf('%s[%s]', $key, $index)] = $bit; } } else { $normalizedValues[$key] = (string) $value; } } return $normalizedValues; } } PK!`=Symfony/Component/Routing/Matcher/Dumper/DumperCollection.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; /** * Collection of routes. * * @author Arnaud Le Blanc */ class DumperCollection implements \IteratorAggregate { /** * @var DumperCollection|null */ private $parent; /** * @var (DumperCollection|DumperRoute)[] */ private $children = array(); /** * @var array */ private $attributes = array(); /** * Returns the children routes and collections. * * @return (DumperCollection|DumperRoute)[] Array of DumperCollection|DumperRoute */ public function all() { return $this->children; } /** * Adds a route or collection * * @param DumperRoute|DumperCollection The route or collection */ public function add($child) { if ($child instanceof DumperCollection) { $child->setParent($this); } $this->children[] = $child; } /** * Sets children. * * @param array $children The children */ public function setAll(array $children) { foreach ($children as $child) { if ($child instanceof DumperCollection) { $child->setParent($this); } } $this->children = $children; } /** * Returns an iterator over the children. * * @return \Iterator The iterator */ public function getIterator() { return new \ArrayIterator($this->children); } /** * Returns the root of the collection. * * @return DumperCollection The root collection */ public function getRoot() { return (null !== $this->parent) ? $this->parent->getRoot() : $this; } /** * Returns the parent collection. * * @return DumperCollection|null The parent collection or null if the collection has no parent */ protected function getParent() { return $this->parent; } /** * Sets the parent collection. * * @param DumperCollection $parent The parent collection */ protected function setParent(DumperCollection $parent) { $this->parent = $parent; } /** * Returns true if the attribute is defined. * * @param string $name The attribute name * * @return Boolean true if the attribute is defined, false otherwise */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * Returns an attribute by name. * * @param string $name The attribute name * @param mixed $default Default value is the attribute doesn't exist * * @return mixed The attribute value */ public function getAttribute($name, $default = null) { return $this->hasAttribute($name) ? $this->attributes[$name] : $default; } /** * Sets an attribute by name. * * @param string $name The attribute name * @param mixed $value The attribute value */ public function setAttribute($name, $value) { $this->attributes[$name] = $value; } /** * Sets multiple attributes. * * @param array $attributes The attributes */ public function setAttributes($attributes) { $this->attributes = $attributes; } } PK!N CSymfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; /** * Prefix tree of routes preserving routes order. * * @author Arnaud Le Blanc */ class DumperPrefixCollection extends DumperCollection { /** * @var string */ private $prefix = ''; /** * Returns the prefix. * * @return string The prefix */ public function getPrefix() { return $this->prefix; } /** * Sets the prefix. * * @param string $prefix The prefix */ public function setPrefix($prefix) { $this->prefix = $prefix; } /** * Adds a route in the tree. * * @param DumperRoute $route The route * * @return DumperPrefixCollection The node the route was added to * * @throws \LogicException */ public function addPrefixRoute(DumperRoute $route) { $prefix = $route->getRoute()->compile()->getStaticPrefix(); for ($collection = $this; null !== $collection; $collection = $collection->getParent()) { // Same prefix, add to current leave if ($collection->prefix === $prefix) { $collection->add($route); return $collection; } // Prefix starts with route's prefix if ('' === $collection->prefix || 0 === strpos($prefix, $collection->prefix)) { $child = new DumperPrefixCollection(); $child->setPrefix(substr($prefix, 0, strlen($collection->prefix)+1)); $collection->add($child); return $child->addPrefixRoute($route); } } // Reached only if the root has a non empty prefix throw new \LogicException("The collection root must not have a prefix"); } /** * Merges nodes whose prefix ends with a slash * * Children of a node whose prefix ends with a slash are moved to the parent node */ public function mergeSlashNodes() { $children = array(); foreach ($this as $child) { if ($child instanceof self) { $child->mergeSlashNodes(); if ('/' === substr($child->prefix, -1)) { $children = array_merge($children, $child->all()); } else { $children[] = $child; } } else { $children[] = $child; } } $this->setAll($children); } } PK!( CSymfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\RouteCollection; /** * MatcherDumperInterface is the interface that all matcher dumper classes must implement. * * @author Fabien Potencier */ interface MatcherDumperInterface { /** * Dumps a set of routes to a string representation of executable code * that can then be used to match a request against these routes. * * @param array $options An array of options * * @return string Executable code */ public function dump(array $options = array()); /** * Gets the routes to dump. * * @return RouteCollection A RouteCollection instance */ public function getRoutes(); } PK!YIWW8Symfony/Component/Routing/Matcher/Dumper/DumperRoute.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\Route; /** * Container for a Route. * * @author Arnaud Le Blanc */ class DumperRoute { /** * @var string */ private $name; /** * @var Route */ private $route; /** * Constructor. * * @param string $name The route name * @param Route $route The route */ public function __construct($name, Route $route) { $this->name = $name; $this->route = $route; } /** * Returns the route name. * * @return string The route name */ public function getName() { return $this->name; } /** * Returns the route. * * @return Route The route */ public function getRoute() { return $this->route; } } PK!'9Symfony/Component/Routing/Matcher/TraceableUrlMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\ExceptionInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * TraceableUrlMatcher helps debug path info matching by tracing the match. * * @author Fabien Potencier */ class TraceableUrlMatcher extends UrlMatcher { const ROUTE_DOES_NOT_MATCH = 0; const ROUTE_ALMOST_MATCHES = 1; const ROUTE_MATCHES = 2; protected $traces; public function getTraces($pathinfo) { $this->traces = array(); try { $this->match($pathinfo); } catch (ExceptionInterface $e) { } return $this->traces; } protected function matchCollection($pathinfo, RouteCollection $routes) { foreach ($routes as $name => $route) { $compiledRoute = $route->compile(); if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { // does it match without any requirements? $r = new Route($route->getPath(), $route->getDefaults(), array(), $route->getOptions()); $cr = $r->compile(); if (!preg_match($cr->getRegex(), $pathinfo)) { $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); continue; } foreach ($route->getRequirements() as $n => $regex) { $r = new Route($route->getPath(), $route->getDefaults(), array($n => $regex), $route->getOptions()); $cr = $r->compile(); if (in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); continue 2; } } continue; } // check host requirement $hostMatches = array(); if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } // check HTTP method requirement if ($req = $route->getRequirement('_method')) { // HEAD and GET are equivalent as per RFC if ('HEAD' === $method = $this->context->getMethod()) { $method = 'GET'; } if (!in_array($method, $req = explode('|', strtoupper($req)))) { $this->allow = array_merge($this->allow, $req); $this->addTrace(sprintf('Method "%s" does not match the requirement ("%s")', $this->context->getMethod(), implode(', ', $req)), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } } // check condition if ($condition = $route->getCondition()) { if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) { $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } } // check HTTP scheme requirement if ($scheme = $route->getRequirement('_scheme')) { if ($this->context->getScheme() !== $scheme) { $this->addTrace(sprintf('Scheme "%s" does not match the requirement ("%s"); the user will be redirected', $this->context->getScheme(), $scheme), self::ROUTE_ALMOST_MATCHES, $name, $route); return true; } } $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); return true; } } private function addTrace($log, $level = self::ROUTE_DOES_NOT_MATCH, $name = null, $route = null) { $this->traces[] = array( 'log' => $log, 'name' => $name, 'level' => $level, 'path' => null !== $route ? $route->getPath() : null, ); } } PK!GjC""0Symfony/Component/Routing/Matcher/UrlMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; /** * UrlMatcher matches URL based on a set of routes. * * @author Fabien Potencier * * @api */ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface { const REQUIREMENT_MATCH = 0; const REQUIREMENT_MISMATCH = 1; const ROUTE_MATCH = 2; /** * @var RequestContext */ protected $context; /** * @var array */ protected $allow = array(); /** * @var RouteCollection */ protected $routes; protected $request; protected $expressionLanguage; /** * Constructor. * * @param RouteCollection $routes A RouteCollection instance * @param RequestContext $context The context * * @api */ public function __construct(RouteCollection $routes, RequestContext $context) { $this->routes = $routes; $this->context = $context; } /** * {@inheritdoc} */ public function setContext(RequestContext $context) { $this->context = $context; } /** * {@inheritdoc} */ public function getContext() { return $this->context; } /** * {@inheritdoc} */ public function match($pathinfo) { $this->allow = array(); if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) { return $ret; } throw 0 < count($this->allow) ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow))) : new ResourceNotFoundException(); } /** * {@inheritdoc} */ public function matchRequest(Request $request) { $this->request = $request; $ret = $this->match($request->getPathInfo()); $this->request = null; return $ret; } /** * Tries to match a URL with a set of routes. * * @param string $pathinfo The path info to be parsed * @param RouteCollection $routes The set of routes * * @return array An array of parameters * * @throws ResourceNotFoundException If the resource could not be found * @throws MethodNotAllowedException If the resource was found but the request method is not allowed */ protected function matchCollection($pathinfo, RouteCollection $routes) { foreach ($routes as $name => $route) { $compiledRoute = $route->compile(); // check the static prefix of the URL first. Only use the more expensive preg_match when it matches if ('' !== $compiledRoute->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute->getStaticPrefix())) { continue; } if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { continue; } $hostMatches = array(); if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { continue; } // check HTTP method requirement if ($req = $route->getRequirement('_method')) { // HEAD and GET are equivalent as per RFC if ('HEAD' === $method = $this->context->getMethod()) { $method = 'GET'; } if (!in_array($method, $req = explode('|', strtoupper($req)))) { $this->allow = array_merge($this->allow, $req); continue; } } $status = $this->handleRouteRequirements($pathinfo, $name, $route); if (self::ROUTE_MATCH === $status[0]) { return $status[1]; } if (self::REQUIREMENT_MISMATCH === $status[0]) { continue; } return $this->getAttributes($route, $name, array_replace($matches, $hostMatches)); } } /** * Returns an array of values to use as request attributes. * * As this method requires the Route object, it is not available * in matchers that do not have access to the matched Route instance * (like the PHP and Apache matcher dumpers). * * @param Route $route The route we are matching against * @param string $name The name of the route * @param array $attributes An array of attributes from the matcher * * @return array An array of parameters */ protected function getAttributes(Route $route, $name, array $attributes) { $attributes['_route'] = $name; return $this->mergeDefaults($attributes, $route->getDefaults()); } /** * Handles specific route requirements. * * @param string $pathinfo The path * @param string $name The route name * @param Route $route The route * * @return array The first element represents the status, the second contains additional information */ protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { return array(self::REQUIREMENT_MISMATCH, null); } // check HTTP scheme requirement $scheme = $route->getRequirement('_scheme'); $status = $scheme && $scheme !== $this->context->getScheme() ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH; return array($status, null); } /** * Get merged default parameters. * * @param array $params The parameters * @param array $defaults The defaults * * @return array Merged default parameters */ protected function mergeDefaults($params, $defaults) { foreach ($params as $key => $value) { if (!is_int($key)) { $defaults[$key] = $value; } } return $defaults; } protected function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK! ffESymfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; /** * RedirectableUrlMatcherInterface knows how to redirect the user. * * @author Fabien Potencier * * @api */ interface RedirectableUrlMatcherInterface { /** * Redirects the user to another URL. * * @param string $path The path info to redirect to. * @param string $route The route name that matched * @param string|null $scheme The URL scheme (null to keep the current one) * * @return array An array of parameters * * @api */ public function redirect($path, $route, $scheme = null); } PK!==KSymfony/Component/Routing/Exception/MissingMandatoryParametersException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when a route cannot be generated because of missing * mandatory parameters. * * @author Alexandre Salomé * * @api */ class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface { } PK!j`jASymfony/Component/Routing/Exception/InvalidParameterException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when a parameter is not valid * * @author Alexandre Salomé * * @api */ class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface { } PK!njW>Symfony/Component/Routing/Exception/RouteNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when a route does not exist * * @author Alexandre Salomé * * @api */ class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface { } PK!):Symfony/Component/Routing/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * ExceptionInterface * * @author Alexandre Salomé * * @api */ interface ExceptionInterface { } PK!JJASymfony/Component/Routing/Exception/MethodNotAllowedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * The resource was found but the request method is not allowed. * * This exception should trigger an HTTP 405 response in your application code. * * @author Kris Wallsmith * * @api */ class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface { /** * @var array */ protected $allowedMethods = array(); public function __construct(array $allowedMethods, $message = null, $code = 0, \Exception $previous = null) { $this->allowedMethods = array_map('strtoupper', $allowedMethods); parent::__construct($message, $code, $previous); } /** * Gets the allowed HTTP methods. * * @return array */ public function getAllowedMethods() { return $this->allowedMethods; } } PK!?]//ASymfony/Component/Routing/Exception/ResourceNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * The resource was not found. * * This exception should trigger an HTTP 404 response in your application code. * * @author Kris Wallsmith * * @api */ class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface { } PK!^==#Symfony/Component/Routing/Route.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * A Route describes a route and its parameters. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class Route implements \Serializable { /** * @var string */ private $path = '/'; /** * @var string */ private $host = ''; /** * @var array */ private $schemes = array(); /** * @var array */ private $methods = array(); /** * @var array */ private $defaults = array(); /** * @var array */ private $requirements = array(); /** * @var array */ private $options = array(); /** * @var null|CompiledRoute */ private $compiled; private $condition; /** * Constructor. * * Available options: * * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) * * @param string $path The path pattern to match * @param array $defaults An array of default parameter values * @param array $requirements An array of requirements for parameters (regexes) * @param array $options An array of options * @param string $host The host pattern to match * @param string|array $schemes A required URI scheme or an array of restricted schemes * @param string|array $methods A required HTTP method or an array of restricted methods * @param string $condition A condition that should evaluate to true for the route to match * * @api */ public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array(), $condition = null) { $this->setPath($path); $this->setDefaults($defaults); $this->setRequirements($requirements); $this->setOptions($options); $this->setHost($host); // The conditions make sure that an initial empty $schemes/$methods does not override the corresponding requirement. // They can be removed when the BC layer is removed. if ($schemes) { $this->setSchemes($schemes); } if ($methods) { $this->setMethods($methods); } $this->setCondition($condition); } public function serialize() { return serialize(array( 'path' => $this->path, 'host' => $this->host, 'defaults' => $this->defaults, 'requirements' => $this->requirements, 'options' => $this->options, 'schemes' => $this->schemes, 'methods' => $this->methods, 'condition' => $this->condition, )); } public function unserialize($data) { $data = unserialize($data); $this->path = $data['path']; $this->host = $data['host']; $this->defaults = $data['defaults']; $this->requirements = $data['requirements']; $this->options = $data['options']; $this->schemes = $data['schemes']; $this->methods = $data['methods']; $this->condition = $data['condition']; } /** * Returns the pattern for the path. * * @return string The pattern * * @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead. */ public function getPattern() { return $this->path; } /** * Sets the pattern for the path. * * This method implements a fluent interface. * * @param string $pattern The path pattern * * @return Route The current Route instance * * @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead. */ public function setPattern($pattern) { return $this->setPath($pattern); } /** * Returns the pattern for the path. * * @return string The path pattern */ public function getPath() { return $this->path; } /** * Sets the pattern for the path. * * This method implements a fluent interface. * * @param string $pattern The path pattern * * @return Route The current Route instance */ public function setPath($pattern) { // A pattern must start with a slash and must not have multiple slashes at the beginning because the // generated path for this route would be confused with a network path, e.g. '//domain.com/path'. $this->path = '/'.ltrim(trim($pattern), '/'); $this->compiled = null; return $this; } /** * Returns the pattern for the host. * * @return string The host pattern */ public function getHost() { return $this->host; } /** * Sets the pattern for the host. * * This method implements a fluent interface. * * @param string $pattern The host pattern * * @return Route The current Route instance */ public function setHost($pattern) { $this->host = (string) $pattern; $this->compiled = null; return $this; } /** * Returns the lowercased schemes this route is restricted to. * So an empty array means that any scheme is allowed. * * @return array The schemes */ public function getSchemes() { return $this->schemes; } /** * Sets the schemes (e.g. 'https') this route is restricted to. * So an empty array means that any scheme is allowed. * * This method implements a fluent interface. * * @param string|array $schemes The scheme or an array of schemes * * @return Route The current Route instance */ public function setSchemes($schemes) { $this->schemes = array_map('strtolower', (array) $schemes); // this is to keep BC and will be removed in a future version if ($this->schemes) { $this->requirements['_scheme'] = implode('|', $this->schemes); } else { unset($this->requirements['_scheme']); } $this->compiled = null; return $this; } /** * Returns the uppercased HTTP methods this route is restricted to. * So an empty array means that any method is allowed. * * @return array The schemes */ public function getMethods() { return $this->methods; } /** * Sets the HTTP methods (e.g. 'POST') this route is restricted to. * So an empty array means that any method is allowed. * * This method implements a fluent interface. * * @param string|array $methods The method or an array of methods * * @return Route The current Route instance */ public function setMethods($methods) { $this->methods = array_map('strtoupper', (array) $methods); // this is to keep BC and will be removed in a future version if ($this->methods) { $this->requirements['_method'] = implode('|', $this->methods); } else { unset($this->requirements['_method']); } $this->compiled = null; return $this; } /** * Returns the options. * * @return array The options */ public function getOptions() { return $this->options; } /** * Sets the options. * * This method implements a fluent interface. * * @param array $options The options * * @return Route The current Route instance */ public function setOptions(array $options) { $this->options = array( 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', ); return $this->addOptions($options); } /** * Adds options. * * This method implements a fluent interface. * * @param array $options The options * * @return Route The current Route instance */ public function addOptions(array $options) { foreach ($options as $name => $option) { $this->options[$name] = $option; } $this->compiled = null; return $this; } /** * Sets an option value. * * This method implements a fluent interface. * * @param string $name An option name * @param mixed $value The option value * * @return Route The current Route instance * * @api */ public function setOption($name, $value) { $this->options[$name] = $value; $this->compiled = null; return $this; } /** * Get an option value. * * @param string $name An option name * * @return mixed The option value or null when not given */ public function getOption($name) { return isset($this->options[$name]) ? $this->options[$name] : null; } /** * Checks if an option has been set * * @param string $name An option name * * @return Boolean true if the option is set, false otherwise */ public function hasOption($name) { return array_key_exists($name, $this->options); } /** * Returns the defaults. * * @return array The defaults */ public function getDefaults() { return $this->defaults; } /** * Sets the defaults. * * This method implements a fluent interface. * * @param array $defaults The defaults * * @return Route The current Route instance */ public function setDefaults(array $defaults) { $this->defaults = array(); return $this->addDefaults($defaults); } /** * Adds defaults. * * This method implements a fluent interface. * * @param array $defaults The defaults * * @return Route The current Route instance */ public function addDefaults(array $defaults) { foreach ($defaults as $name => $default) { $this->defaults[$name] = $default; } $this->compiled = null; return $this; } /** * Gets a default value. * * @param string $name A variable name * * @return mixed The default value or null when not given */ public function getDefault($name) { return isset($this->defaults[$name]) ? $this->defaults[$name] : null; } /** * Checks if a default value is set for the given variable. * * @param string $name A variable name * * @return Boolean true if the default value is set, false otherwise */ public function hasDefault($name) { return array_key_exists($name, $this->defaults); } /** * Sets a default value. * * @param string $name A variable name * @param mixed $default The default value * * @return Route The current Route instance * * @api */ public function setDefault($name, $default) { $this->defaults[$name] = $default; $this->compiled = null; return $this; } /** * Returns the requirements. * * @return array The requirements */ public function getRequirements() { return $this->requirements; } /** * Sets the requirements. * * This method implements a fluent interface. * * @param array $requirements The requirements * * @return Route The current Route instance */ public function setRequirements(array $requirements) { $this->requirements = array(); return $this->addRequirements($requirements); } /** * Adds requirements. * * This method implements a fluent interface. * * @param array $requirements The requirements * * @return Route The current Route instance */ public function addRequirements(array $requirements) { foreach ($requirements as $key => $regex) { $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); } $this->compiled = null; return $this; } /** * Returns the requirement for the given key. * * @param string $key The key * * @return string|null The regex or null when not given */ public function getRequirement($key) { return isset($this->requirements[$key]) ? $this->requirements[$key] : null; } /** * Checks if a requirement is set for the given key. * * @param string $key A variable name * * @return Boolean true if a requirement is specified, false otherwise */ public function hasRequirement($key) { return array_key_exists($key, $this->requirements); } /** * Sets a requirement for the given key. * * @param string $key The key * @param string $regex The regex * * @return Route The current Route instance * * @api */ public function setRequirement($key, $regex) { $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); $this->compiled = null; return $this; } /** * Returns the condition. * * @return string The condition */ public function getCondition() { return $this->condition; } /** * Sets the condition. * * This method implements a fluent interface. * * @param string $condition The condition * * @return Route The current Route instance */ public function setCondition($condition) { $this->condition = (string) $condition; $this->compiled = null; return $this; } /** * Compiles the route. * * @return CompiledRoute A CompiledRoute instance * * @throws \LogicException If the Route cannot be compiled because the * path or host pattern is invalid * * @see RouteCompiler which is responsible for the compilation process */ public function compile() { if (null !== $this->compiled) { return $this->compiled; } $class = $this->getOption('compiler_class'); return $this->compiled = $class::compile($this); } private function sanitizeRequirement($key, $regex) { if (!is_string($regex)) { throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" must be a string.', $key)); } if ('' !== $regex && '^' === $regex[0]) { $regex = (string) substr($regex, 1); // returns false for a single character } if ('$' === substr($regex, -1)) { $regex = substr($regex, 0, -1); } if ('' === $regex) { throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key)); } // this is to keep BC and will be removed in a future version if ('_scheme' === $key) { $this->setSchemes(explode('|', $regex)); } elseif ('_method' === $key) { $this->setMethods(explode('|', $regex)); } return $regex; } } PK!r:Symfony/Component/Routing/RequestContextAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * @api */ interface RequestContextAwareInterface { /** * Sets the request context. * * @param RequestContext $context The context * * @api */ public function setContext(RequestContext $context); /** * Gets the request context. * * @return RequestContext The context * * @api */ public function getContext(); } PK!|,{Ȫ-Symfony/Component/Routing/RouteCollection.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Config\Resource\ResourceInterface; /** * A RouteCollection represents a set of Route instances. * * When adding a route at the end of the collection, an existing route * with the same name is removed first. So there can only be one route * with a given name. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class RouteCollection implements \IteratorAggregate, \Countable { /** * @var Route[] */ private $routes = array(); /** * @var array */ private $resources = array(); public function __clone() { foreach ($this->routes as $name => $route) { $this->routes[$name] = clone $route; } } /** * Gets the current RouteCollection as an Iterator that includes all routes. * * It implements \IteratorAggregate. * * @see all() * * @return \ArrayIterator An \ArrayIterator object for iterating over routes */ public function getIterator() { return new \ArrayIterator($this->routes); } /** * Gets the number of Routes in this collection. * * @return int The number of routes */ public function count() { return count($this->routes); } /** * Adds a route. * * @param string $name The route name * @param Route $route A Route instance * * @api */ public function add($name, Route $route) { unset($this->routes[$name]); $this->routes[$name] = $route; } /** * Returns all routes in this collection. * * @return Route[] An array of routes */ public function all() { return $this->routes; } /** * Gets a route by name. * * @param string $name The route name * * @return Route|null A Route instance or null when not found */ public function get($name) { return isset($this->routes[$name]) ? $this->routes[$name] : null; } /** * Removes a route or an array of routes by name from the collection * * @param string|array $name The route name or an array of route names */ public function remove($name) { foreach ((array) $name as $n) { unset($this->routes[$n]); } } /** * Adds a route collection at the end of the current set by appending all * routes of the added collection. * * @param RouteCollection $collection A RouteCollection instance * * @api */ public function addCollection(RouteCollection $collection) { // we need to remove all routes with the same names first because just replacing them // would not place the new route at the end of the merged array foreach ($collection->all() as $name => $route) { unset($this->routes[$name]); $this->routes[$name] = $route; } $this->resources = array_merge($this->resources, $collection->getResources()); } /** * Adds a prefix to the path of all child routes. * * @param string $prefix An optional prefix to add before each pattern of the route collection * @param array $defaults An array of default values * @param array $requirements An array of requirements * * @api */ public function addPrefix($prefix, array $defaults = array(), array $requirements = array()) { $prefix = trim(trim($prefix), '/'); if ('' === $prefix) { return; } foreach ($this->routes as $route) { $route->setPath('/'.$prefix.$route->getPath()); $route->addDefaults($defaults); $route->addRequirements($requirements); } } /** * Sets the host pattern on all routes. * * @param string $pattern The pattern * @param array $defaults An array of default values * @param array $requirements An array of requirements */ public function setHost($pattern, array $defaults = array(), array $requirements = array()) { foreach ($this->routes as $route) { $route->setHost($pattern); $route->addDefaults($defaults); $route->addRequirements($requirements); } } /** * Sets a condition on all routes. * * Existing conditions will be overridden. * * @param string $condition The condition */ public function setCondition($condition) { foreach ($this->routes as $route) { $route->setCondition($condition); } } /** * Adds defaults to all routes. * * An existing default value under the same name in a route will be overridden. * * @param array $defaults An array of default values */ public function addDefaults(array $defaults) { if ($defaults) { foreach ($this->routes as $route) { $route->addDefaults($defaults); } } } /** * Adds requirements to all routes. * * An existing requirement under the same name in a route will be overridden. * * @param array $requirements An array of requirements */ public function addRequirements(array $requirements) { if ($requirements) { foreach ($this->routes as $route) { $route->addRequirements($requirements); } } } /** * Adds options to all routes. * * An existing option value under the same name in a route will be overridden. * * @param array $options An array of options */ public function addOptions(array $options) { if ($options) { foreach ($this->routes as $route) { $route->addOptions($options); } } } /** * Sets the schemes (e.g. 'https') all child routes are restricted to. * * @param string|array $schemes The scheme or an array of schemes */ public function setSchemes($schemes) { foreach ($this->routes as $route) { $route->setSchemes($schemes); } } /** * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to. * * @param string|array $methods The method or an array of methods */ public function setMethods($methods) { foreach ($this->routes as $route) { $route->setMethods($methods); } } /** * Returns an array of resources loaded to build this collection. * * @return ResourceInterface[] An array of resources */ public function getResources() { return array_unique($this->resources); } /** * Adds a resource for this collection. * * @param ResourceInterface $resource A resource instance */ public function addResource(ResourceInterface $resource) { $this->resources[] = $resource; } } PK!h,Symfony/Component/Routing/RequestContext.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\HttpFoundation\Request; /** * Holds information about the current request. * * @author Fabien Potencier * * @api */ class RequestContext { private $baseUrl; private $pathInfo; private $method; private $host; private $scheme; private $httpPort; private $httpsPort; private $queryString; /** * @var array */ private $parameters = array(); /** * Constructor. * * @param string $baseUrl The base URL * @param string $method The HTTP method * @param string $host The HTTP host name * @param string $scheme The HTTP scheme * @param integer $httpPort The HTTP port * @param integer $httpsPort The HTTPS port * @param string $path The path * @param string $queryString The query string * * @api */ public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443, $path = '/', $queryString = '') { $this->baseUrl = $baseUrl; $this->method = strtoupper($method); $this->host = $host; $this->scheme = strtolower($scheme); $this->httpPort = $httpPort; $this->httpsPort = $httpsPort; $this->pathInfo = $path; $this->queryString = $queryString; } public function fromRequest(Request $request) { $this->setBaseUrl($request->getBaseUrl()); $this->setPathInfo($request->getPathInfo()); $this->setMethod($request->getMethod()); $this->setHost($request->getHost()); $this->setScheme($request->getScheme()); $this->setHttpPort($request->isSecure() ? $this->httpPort : $request->getPort()); $this->setHttpsPort($request->isSecure() ? $request->getPort() : $this->httpsPort); $this->setQueryString($request->server->get('QUERY_STRING')); } /** * Gets the base URL. * * @return string The base URL */ public function getBaseUrl() { return $this->baseUrl; } /** * Sets the base URL. * * @param string $baseUrl The base URL * * @api */ public function setBaseUrl($baseUrl) { $this->baseUrl = $baseUrl; } /** * Gets the path info. * * @return string The path info */ public function getPathInfo() { return $this->pathInfo; } /** * Sets the path info. * * @param string $pathInfo The path info */ public function setPathInfo($pathInfo) { $this->pathInfo = $pathInfo; } /** * Gets the HTTP method. * * The method is always an uppercased string. * * @return string The HTTP method */ public function getMethod() { return $this->method; } /** * Sets the HTTP method. * * @param string $method The HTTP method * * @api */ public function setMethod($method) { $this->method = strtoupper($method); } /** * Gets the HTTP host. * * @return string The HTTP host */ public function getHost() { return $this->host; } /** * Sets the HTTP host. * * @param string $host The HTTP host * * @api */ public function setHost($host) { $this->host = $host; } /** * Gets the HTTP scheme. * * @return string The HTTP scheme */ public function getScheme() { return $this->scheme; } /** * Sets the HTTP scheme. * * @param string $scheme The HTTP scheme * * @api */ public function setScheme($scheme) { $this->scheme = strtolower($scheme); } /** * Gets the HTTP port. * * @return string The HTTP port */ public function getHttpPort() { return $this->httpPort; } /** * Sets the HTTP port. * * @param string $httpPort The HTTP port * * @api */ public function setHttpPort($httpPort) { $this->httpPort = $httpPort; } /** * Gets the HTTPS port. * * @return string The HTTPS port */ public function getHttpsPort() { return $this->httpsPort; } /** * Sets the HTTPS port. * * @param string $httpsPort The HTTPS port * * @api */ public function setHttpsPort($httpsPort) { $this->httpsPort = $httpsPort; } /** * Gets the query string. * * @return string The query string */ public function getQueryString() { return $this->queryString; } /** * Sets the query string. * * @param string $queryString The query string * * @api */ public function setQueryString($queryString) { $this->queryString = $queryString; } /** * Returns the parameters. * * @return array The parameters */ public function getParameters() { return $this->parameters; } /** * Sets the parameters. * * This method implements a fluent interface. * * @param array $parameters The parameters * * @return Route The current Route instance */ public function setParameters(array $parameters) { $this->parameters = $parameters; return $this; } /** * Gets a parameter value. * * @param string $name A parameter name * * @return mixed The parameter value */ public function getParameter($name) { return isset($this->parameters[$name]) ? $this->parameters[$name] : null; } /** * Checks if a parameter value is set for the given parameter. * * @param string $name A parameter name * * @return Boolean true if the parameter value is set, false otherwise */ public function hasParameter($name) { return array_key_exists($name, $this->parameters); } /** * Sets a parameter value. * * @param string $name A parameter name * @param mixed $parameter The parameter value * * @api */ public function setParameter($name, $parameter) { $this->parameters[$name] = $parameter; } } PK!մISymfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; /** * ConfigurableRequirementsInterface must be implemented by URL generators that * can be configured whether an exception should be generated when the parameters * do not match the requirements. It is also possible to disable the requirements * check for URL generation completely. * * The possible configurations and use-cases: * - setStrictRequirements(true): Throw an exception for mismatching requirements. This * is mostly useful in development environment. * - setStrictRequirements(false): Don't throw an exception but return null as URL for * mismatching requirements and log the problem. Useful when you cannot control all * params because they come from third party libs but don't want to have a 404 in * production environment. It should log the mismatch so one can review it. * - setStrictRequirements(null): Return the URL with the given parameters without * checking the requirements at all. When generating a URL you should either trust * your params or you validated them beforehand because otherwise it would break your * link anyway. So in production environment you should know that params always pass * the requirements. Thus this option allows to disable the check on URL generation for * performance reasons (saving a preg_match for each requirement every time a URL is * generated). * * @author Fabien Potencier * @author Tobias Schultze */ interface ConfigurableRequirementsInterface { /** * Enables or disables the exception on incorrect parameters. * Passing null will deactivate the requirements check completely. * * @param Boolean|null $enabled */ public function setStrictRequirements($enabled); /** * Returns whether to throw an exception on incorrect parameters. * Null means the requirements check is deactivated completely. * * @return Boolean|null */ public function isStrictRequirements(); } PK! 114Symfony/Component/Routing/Generator/UrlGenerator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Exception\InvalidParameterException; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; use Psr\Log\LoggerInterface; /** * UrlGenerator can generate a URL or a path for any route in the RouteCollection * based on the passed parameters. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface { /** * @var RouteCollection */ protected $routes; /** * @var RequestContext */ protected $context; /** * @var Boolean|null */ protected $strictRequirements = true; /** * @var LoggerInterface|null */ protected $logger; /** * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL. * * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g. * "?" and "#" (would be interpreted wrongly as query and fragment identifier), * "'" and """ (are used as delimiters in HTML). */ protected $decodedChars = array( // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning // some webservers don't allow the slash in encoded form in the path for security reasons anyway // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss '%2F' => '/', // the following chars are general delimiters in the URI specification but have only special meaning in the authority component // so they can safely be used in the path in unencoded form '%40' => '@', '%3A' => ':', // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability '%3B' => ';', '%2C' => ',', '%3D' => '=', '%2B' => '+', '%21' => '!', '%2A' => '*', '%7C' => '|', ); /** * Constructor. * * @param RouteCollection $routes A RouteCollection instance * @param RequestContext $context The context * @param LoggerInterface|null $logger A logger instance * * @api */ public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null) { $this->routes = $routes; $this->context = $context; $this->logger = $logger; } /** * {@inheritdoc} */ public function setContext(RequestContext $context) { $this->context = $context; } /** * {@inheritdoc} */ public function getContext() { return $this->context; } /** * {@inheritdoc} */ public function setStrictRequirements($enabled) { $this->strictRequirements = null === $enabled ? null : (Boolean) $enabled; } /** * {@inheritdoc} */ public function isStrictRequirements() { return $this->strictRequirements; } /** * {@inheritDoc} */ public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) { if (null === $route = $this->routes->get($name)) { throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); } // the Route has a cache of its own and is not recompiled as long as it does not get modified $compiledRoute = $route->compile(); return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens()); } /** * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route * @throws InvalidParameterException When a parameter value for a placeholder is not correct because * it does not match the requirement */ protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens) { $variables = array_flip($variables); $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); // all params must be given if ($diff = array_diff_key($variables, $mergedParams)) { throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name)); } $url = ''; $optional = true; foreach ($tokens as $token) { if ('variable' === $token[0]) { if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) { // check requirement if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) { $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]); if ($this->strictRequirements) { throw new InvalidParameterException($message); } if ($this->logger) { $this->logger->error($message); } return null; } $url = $token[1].$mergedParams[$token[3]].$url; $optional = false; } } else { // static text $url = $token[1].$url; $optional = false; } } if ('' === $url) { $url = '/'; } // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request) $url = strtr(rawurlencode($url), $this->decodedChars); // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 // so we need to encode them as they are not used for this purpose here // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/')); if ('/..' === substr($url, -3)) { $url = substr($url, 0, -2).'%2E%2E'; } elseif ('/.' === substr($url, -2)) { $url = substr($url, 0, -1).'%2E'; } $schemeAuthority = ''; if ($host = $this->context->getHost()) { $scheme = $this->context->getScheme(); if (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme !== $req) { $referenceType = self::ABSOLUTE_URL; $scheme = $req; } if ($hostTokens) { $routeHost = ''; foreach ($hostTokens as $token) { if ('variable' === $token[0]) { if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) { $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]); if ($this->strictRequirements) { throw new InvalidParameterException($message); } if ($this->logger) { $this->logger->error($message); } return null; } $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; } else { $routeHost = $token[1].$routeHost; } } if ($routeHost !== $host) { $host = $routeHost; if (self::ABSOLUTE_URL !== $referenceType) { $referenceType = self::NETWORK_PATH; } } } if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { $port = ''; if ('http' === $scheme && 80 != $this->context->getHttpPort()) { $port = ':'.$this->context->getHttpPort(); } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { $port = ':'.$this->context->getHttpsPort(); } $schemeAuthority = self::NETWORK_PATH === $referenceType ? '//' : "$scheme://"; $schemeAuthority .= $host.$port; } } if (self::RELATIVE_PATH === $referenceType) { $url = self::getRelativePath($this->context->getPathInfo(), $url); } else { $url = $schemeAuthority.$this->context->getBaseUrl().$url; } // add a query string if needed $extra = array_diff_key($parameters, $variables, $defaults); if ($extra && $query = http_build_query($extra, '', '&')) { $url .= '?'.$query; } return $url; } /** * Returns the target path as relative reference from the base path. * * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash. * Both paths must be absolute and not contain relative parts. * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. * Furthermore, they can be used to reduce the link size in documents. * * Example target paths, given a base path of "/a/b/c/d": * - "/a/b/c/d" -> "" * - "/a/b/c/" -> "./" * - "/a/b/" -> "../" * - "/a/b/c/other" -> "other" * - "/a/x/y" -> "../../x/y" * * @param string $basePath The base path * @param string $targetPath The target path * * @return string The relative target path */ public static function getRelativePath($basePath, $targetPath) { if ($basePath === $targetPath) { return ''; } $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath); array_pop($sourceDirs); $targetFile = array_pop($targetDirs); foreach ($sourceDirs as $i => $dir) { if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { unset($sourceDirs[$i], $targetDirs[$i]); } else { break; } } $targetDirs[] = $targetFile; $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs); // A reference to the same base directory or an empty subdirectory must be prefixed with "./". // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used // as the first segment of a relative-path reference, as it would be mistaken for a scheme name // (see http://tools.ietf.org/html/rfc3986#section-4.2). return '' === $path || '/' === $path[0] || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) ? "./$path" : $path; } } PK!1O ASymfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator\Dumper; /** * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class PhpGeneratorDumper extends GeneratorDumper { /** * Dumps a set of routes to a PHP class. * * Available options: * * * class: The class name * * base_class: The base class name * * @param array $options An array of options * * @return string A PHP class representing the generator class * * @api */ public function dump(array $options = array()) { $options = array_merge(array( 'class' => 'ProjectUrlGenerator', 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', ), $options); return <<generateDeclaredRoutes()}; /** * Constructor. */ public function __construct(RequestContext \$context, LoggerInterface \$logger = null) { \$this->context = \$context; \$this->logger = \$logger; } {$this->generateGenerateMethod()} } EOF; } /** * Generates PHP code representing an array of defined routes * together with the routes properties (e.g. requirements). * * @return string PHP code */ private function generateDeclaredRoutes() { $routes = "array(\n"; foreach ($this->getRoutes()->all() as $name => $route) { $compiledRoute = $route->compile(); $properties = array(); $properties[] = $compiledRoute->getVariables(); $properties[] = $route->getDefaults(); $properties[] = $route->getRequirements(); $properties[] = $compiledRoute->getTokens(); $properties[] = $compiledRoute->getHostTokens(); $routes .= sprintf(" '%s' => %s,\n", $name, str_replace("\n", '', var_export($properties, true))); } $routes .= ' )'; return $routes; } /** * Generates PHP code representing the `generate` method that implements the UrlGeneratorInterface. * * @return string PHP code */ private function generateGenerateMethod() { return <<doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$referenceType, \$hostTokens); } EOF; } } PK!u '>Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator\Dumper; use Symfony\Component\Routing\RouteCollection; /** * GeneratorDumper is the base class for all built-in generator dumpers. * * @author Fabien Potencier */ abstract class GeneratorDumper implements GeneratorDumperInterface { /** * @var RouteCollection */ private $routes; /** * Constructor. * * @param RouteCollection $routes The RouteCollection to dump */ public function __construct(RouteCollection $routes) { $this->routes = $routes; } /** * {@inheritdoc} */ public function getRoutes() { return $this->routes; } } PK!4GSymfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator\Dumper; use Symfony\Component\Routing\RouteCollection; /** * GeneratorDumperInterface is the interface that all generator dumper classes must implement. * * @author Fabien Potencier * * @api */ interface GeneratorDumperInterface { /** * Dumps a set of routes to a string representation of executable code * that can then be used to generate a URL of such a route. * * @param array $options An array of options * * @return string Executable code */ public function dump(array $options = array()); /** * Gets the routes to dump. * * @return RouteCollection A RouteCollection instance */ public function getRoutes(); } PK!@@=Symfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; use Symfony\Component\Routing\Exception\InvalidParameterException; use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\RequestContextAwareInterface; /** * UrlGeneratorInterface is the interface that all URL generator classes must implement. * * The constants in this interface define the different types of resource references that * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986 * We are using the term "URL" instead of "URI" as this is more common in web applications * and we do not need to distinguish them as the difference is mostly semantical and * less technical. Generating URIs, i.e. representation-independent resource identifiers, * is also possible. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ interface UrlGeneratorInterface extends RequestContextAwareInterface { /** * Generates an absolute URL, e.g. "http://example.com/dir/file". */ const ABSOLUTE_URL = true; /** * Generates an absolute path, e.g. "/dir/file". */ const ABSOLUTE_PATH = false; /** * Generates a relative path based on the current request path, e.g. "../parent-file". * @see UrlGenerator::getRelativePath() */ const RELATIVE_PATH = 'relative'; /** * Generates a network path, e.g. "//example.com/dir/file". * Such reference reuses the current scheme but specifies the host. */ const NETWORK_PATH = 'network'; /** * Generates a URL or path for a specific route based on the given parameters. * * Parameters that reference placeholders in the route pattern will substitute them in the * path or host. Extra params are added as query string to the URL. * * When the passed reference type cannot be generated for the route because it requires a different * host or scheme than the current one, the method will return a more comprehensive reference * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH * but the route requires the https scheme whereas the current scheme is http, it will instead return an * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches * the route in any case. * * If there is no route with the given name, the generator must throw the RouteNotFoundException. * * @param string $name The name of the route * @param mixed $parameters An array of parameters * @param Boolean|string $referenceType The type of reference to be generated (one of the constants) * * @return string The generated URL * * @throws RouteNotFoundException If the named route doesn't exist * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route * @throws InvalidParameterException When a parameter value for a placeholder is not correct because * it does not match the requirement * * @api */ public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH); } PK!nhh2Symfony/Component/Routing/Loader/ClosureLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\Routing\RouteCollection; /** * ClosureLoader loads routes from a PHP closure. * * The Closure must return a RouteCollection instance. * * @author Fabien Potencier * * @api */ class ClosureLoader extends Loader { /** * Loads a Closure. * * @param \Closure $closure A Closure * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @api */ public function load($closure, $type = null) { return call_user_func($closure); } /** * {@inheritdoc} * * @api */ public function supports($resource, $type = null) { return $resource instanceof \Closure && (!$type || 'closure' === $type); } } PK!? >Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Config\Resource\DirectoryResource; /** * AnnotationDirectoryLoader loads routing information from annotations set * on PHP classes and methods. * * @author Fabien Potencier */ class AnnotationDirectoryLoader extends AnnotationFileLoader { /** * Loads from annotations from a directory. * * @param string $path A directory path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed */ public function load($path, $type = null) { $dir = $this->locator->locate($path); $collection = new RouteCollection(); $collection->addResource(new DirectoryResource($dir, '/\.php$/')); $files = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY)); usort($files, function (\SplFileInfo $a, \SplFileInfo $b) { return (string) $a > (string) $b ? 1 : -1; }); foreach ($files as $file) { if (!$file->isFile() || '.php' !== substr($file->getFilename(), -4)) { continue; } if ($class = $this->findClass($file)) { $refl = new \ReflectionClass($class); if ($refl->isAbstract()) { continue; } $collection->addCollection($this->loader->load($class, $type)); } } return $collection; } /** * {@inheritdoc} */ public function supports($resource, $type = null) { try { $path = $this->locator->locate($resource); } catch (\Exception $e) { return false; } return is_string($resource) && is_dir($path) && (!$type || 'annotation' === $type); } } PK!~ޟ 9Symfony/Component/Routing/Loader/AnnotationFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\FileLocatorInterface; /** * AnnotationFileLoader loads routing information from annotations set * on a PHP class and its methods. * * @author Fabien Potencier */ class AnnotationFileLoader extends FileLoader { protected $loader; /** * Constructor. * * @param FileLocatorInterface $locator A FileLocator instance * @param AnnotationClassLoader $loader An AnnotationClassLoader instance * * @throws \RuntimeException */ public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader) { if (!function_exists('token_get_all')) { throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.'); } parent::__construct($locator); $this->loader = $loader; } /** * Loads from annotations from a file. * * @param string $file A PHP file path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed */ public function load($file, $type = null) { $path = $this->locator->locate($file); $collection = new RouteCollection(); if ($class = $this->findClass($path)) { $collection->addResource(new FileResource($path)); $collection->addCollection($this->loader->load($class, $type)); } return $collection; } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); } /** * Returns the full class name for the first class in the file. * * @param string $file A PHP file path * * @return string|false Full class name if found, false otherwise */ protected function findClass($file) { $class = false; $namespace = false; $tokens = token_get_all(file_get_contents($file)); for ($i = 0, $count = count($tokens); $i < $count; $i++) { $token = $tokens[$i]; if (!is_array($token)) { continue; } if (true === $class && T_STRING === $token[0]) { return $namespace.'\\'.$token[1]; } if (true === $namespace && T_STRING === $token[0]) { $namespace = ''; do { $namespace .= $token[1]; $token = $tokens[++$i]; } while ($i < $count && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING))); } if (T_CLASS === $token[0]) { $class = true; } if (T_NAMESPACE === $token[0]) { $namespace = true; } } return false; } } PK!~LW:Symfony/Component/Routing/Loader/AnnotationClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Doctrine\Common\Annotations\Reader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderResolverInterface; /** * AnnotationClassLoader loads routing information from a PHP class and its methods. * * You need to define an implementation for the getRouteDefaults() method. Most of the * time, this method should define some PHP callable to be called for the route * (a controller in MVC speak). * * The @Route annotation can be set on the class (for global parameters), * and on each method. * * The @Route annotation main value is the route path. The annotation also * recognizes several parameters: requirements, options, defaults, schemes, * methods, host, and name. The name parameter is mandatory. * Here is an example of how you should be able to use it: * * /** * * @Route("/Blog") * * / * class Blog * { * /** * * @Route("/", name="blog_index") * * / * public function index() * { * } * * /** * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) * * / * public function show() * { * } * } * * @author Fabien Potencier */ abstract class AnnotationClassLoader implements LoaderInterface { /** * @var Reader */ protected $reader; /** * @var string */ protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route'; /** * @var integer */ protected $defaultRouteIndex = 0; /** * Constructor. * * @param Reader $reader */ public function __construct(Reader $reader) { $this->reader = $reader; } /** * Sets the annotation class to read route properties from. * * @param string $class A fully-qualified class name */ public function setRouteAnnotationClass($class) { $this->routeAnnotationClass = $class; } /** * Loads from annotations from a class. * * @param string $class A class name * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When route can't be parsed */ public function load($class, $type = null) { if (!class_exists($class)) { throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); } $globals = array( 'path' => '', 'requirements' => array(), 'options' => array(), 'defaults' => array(), 'schemes' => array(), 'methods' => array(), 'host' => '', 'condition' => '', ); $class = new \ReflectionClass($class); if ($class->isAbstract()) { throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class)); } if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { // for BC reasons if (null !== $annot->getPath()) { $globals['path'] = $annot->getPath(); } elseif (null !== $annot->getPattern()) { $globals['path'] = $annot->getPattern(); } if (null !== $annot->getRequirements()) { $globals['requirements'] = $annot->getRequirements(); } if (null !== $annot->getOptions()) { $globals['options'] = $annot->getOptions(); } if (null !== $annot->getDefaults()) { $globals['defaults'] = $annot->getDefaults(); } if (null !== $annot->getSchemes()) { $globals['schemes'] = $annot->getSchemes(); } if (null !== $annot->getMethods()) { $globals['methods'] = $annot->getMethods(); } if (null !== $annot->getHost()) { $globals['host'] = $annot->getHost(); } if (null !== $annot->getCondition()) { $globals['condition'] = $annot->getCondition(); } } $collection = new RouteCollection(); $collection->addResource(new FileResource($class->getFileName())); foreach ($class->getMethods() as $method) { $this->defaultRouteIndex = 0; foreach ($this->reader->getMethodAnnotations($method) as $annot) { if ($annot instanceof $this->routeAnnotationClass) { $this->addRoute($collection, $annot, $globals, $class, $method); } } } return $collection; } protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method) { $name = $annot->getName(); if (null === $name) { $name = $this->getDefaultRouteName($class, $method); } $defaults = array_replace($globals['defaults'], $annot->getDefaults()); foreach ($method->getParameters() as $param) { if (!isset($defaults[$param->getName()]) && $param->isOptional()) { $defaults[$param->getName()] = $param->getDefaultValue(); } } $requirements = array_replace($globals['requirements'], $annot->getRequirements()); $options = array_replace($globals['options'], $annot->getOptions()); $schemes = array_replace($globals['schemes'], $annot->getSchemes()); $methods = array_replace($globals['methods'], $annot->getMethods()); $host = $annot->getHost(); if (null === $host) { $host = $globals['host']; } $condition = $annot->getCondition(); if (null === $condition) { $condition = $globals['condition']; } $route = new Route($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods, $condition); $this->configureRoute($route, $class, $method, $annot); $collection->add($name, $route); } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); } /** * {@inheritdoc} */ public function setResolver(LoaderResolverInterface $resolver) { } /** * {@inheritdoc} */ public function getResolver() { } /** * Gets the default route name for a class method. * * @param \ReflectionClass $class * @param \ReflectionMethod $method * * @return string */ protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) { $name = strtolower(str_replace('\\', '_', $class->name).'_'.$method->name); if ($this->defaultRouteIndex > 0) { $name .= '_'.$this->defaultRouteIndex; } $this->defaultRouteIndex++; return $name; } abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot); } PK!Pi{2Symfony/Component/Routing/Loader/PhpFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\RouteCollection; /** * PhpFileLoader loads routes from a PHP file. * * The file must return a RouteCollection instance. * * @author Fabien Potencier * * @api */ class PhpFileLoader extends FileLoader { /** * Loads a PHP file. * * @param string $file A PHP file path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @api */ public function load($file, $type = null) { // the loader variable is exposed to the included file below $loader = $this; $path = $this->locator->locate($file); $this->setCurrentDir(dirname($path)); $collection = include $path; $collection->addResource(new FileResource($path)); return $collection; } /** * {@inheritdoc} * * @api */ public function supports($resource, $type = null) { return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type); } } PK!?-[ ?Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu[ PK!أ2D$D$2Symfony/Component/Routing/Loader/XmlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Util\XmlUtils; /** * XmlFileLoader loads XML routing files. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class XmlFileLoader extends FileLoader { const NAMESPACE_URI = 'http://symfony.com/schema/routing'; const SCHEME_PATH = '/schema/routing/routing-1.0.xsd'; /** * Loads an XML file. * * @param string $file An XML file path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When the file cannot be loaded or when the XML cannot be * parsed because it does not validate against the scheme. * * @api */ public function load($file, $type = null) { $path = $this->locator->locate($file); $xml = $this->loadFile($path); $collection = new RouteCollection(); $collection->addResource(new FileResource($path)); // process routes and imports foreach ($xml->documentElement->childNodes as $node) { if (!$node instanceof \DOMElement) { continue; } $this->parseNode($collection, $node, $path, $file); } return $collection; } /** * Parses a node from a loaded XML file. * * @param RouteCollection $collection Collection to associate with the node * @param \DOMElement $node Element to parse * @param string $path Full path of the XML file being processed * @param string $file Loaded file name * * @throws \InvalidArgumentException When the XML is invalid */ protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file) { if (self::NAMESPACE_URI !== $node->namespaceURI) { return; } switch ($node->localName) { case 'route': $this->parseRoute($collection, $node, $path); break; case 'import': $this->parseImport($collection, $node, $path, $file); break; default: throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path)); } } /** * {@inheritdoc} * * @api */ public function supports($resource, $type = null) { return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type); } /** * Parses a route and adds it to the RouteCollection. * * @param RouteCollection $collection RouteCollection instance * @param \DOMElement $node Element to parse that represents a Route * @param string $path Full path of the XML file being processed * * @throws \InvalidArgumentException When the XML is invalid */ protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path) { if ('' === ($id = $node->getAttribute('id')) || (!$node->hasAttribute('pattern') && !$node->hasAttribute('path'))) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have an "id" and a "path" attribute.', $path)); } if ($node->hasAttribute('pattern')) { if ($node->hasAttribute('path')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path)); } $node->setAttribute('path', $node->getAttribute('pattern')); $node->removeAttribute('pattern'); } $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY); $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY); list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path); $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); $collection->add($id, $route); } /** * Parses an import and adds the routes in the resource to the RouteCollection. * * @param RouteCollection $collection RouteCollection instance * @param \DOMElement $node Element to parse that represents a Route * @param string $path Full path of the XML file being processed * @param string $file Loaded file name * * @throws \InvalidArgumentException When the XML is invalid */ protected function parseImport(RouteCollection $collection, \DOMElement $node, $path, $file) { if ('' === $resource = $node->getAttribute('resource')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "resource" attribute.', $path)); } $type = $node->getAttribute('type'); $prefix = $node->getAttribute('prefix'); $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null; $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null; $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null; list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path); $this->setCurrentDir(dirname($path)); $subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file); /* @var $subCollection RouteCollection */ $subCollection->addPrefix($prefix); if (null !== $host) { $subCollection->setHost($host); } if (null !== $condition) { $subCollection->setCondition($condition); } if (null !== $schemes) { $subCollection->setSchemes($schemes); } if (null !== $methods) { $subCollection->setMethods($methods); } $subCollection->addDefaults($defaults); $subCollection->addRequirements($requirements); $subCollection->addOptions($options); $collection->addCollection($subCollection); } /** * Loads an XML file. * * @param string $file An XML file path * * @return \DOMDocument * * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors * or when the XML structure is not as expected by the scheme - * see validate() */ protected function loadFile($file) { return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH); } /** * Parses the config elements (default, requirement, option). * * @param \DOMElement $node Element to parse that contains the configs * @param string $path Full path of the XML file being processed * * @return array An array with the defaults as first item, requirements as second and options as third. * * @throws \InvalidArgumentException When the XML is invalid */ private function parseConfigs(\DOMElement $node, $path) { $defaults = array(); $requirements = array(); $options = array(); $condition = null; foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { switch ($n->localName) { case 'default': if ($n->hasAttribute('xsi:nil') && 'true' == $n->getAttribute('xsi:nil')) { $defaults[$n->getAttribute('key')] = null; } else { $defaults[$n->getAttribute('key')] = trim($n->textContent); } break; case 'requirement': $requirements[$n->getAttribute('key')] = trim($n->textContent); break; case 'option': $options[$n->getAttribute('key')] = trim($n->textContent); break; case 'condition': $condition = trim($n->textContent); break; default: throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path)); } } return array($defaults, $requirements, $options, $condition); } } PK!pBQ Q 3Symfony/Component/Routing/Loader/YamlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\Config\Loader\FileLoader; /** * YamlFileLoader loads Yaml routing files. * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class YamlFileLoader extends FileLoader { private static $availableKeys = array( 'resource', 'type', 'prefix', 'pattern', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition' ); private $yamlParser; /** * Loads a Yaml file. * * @param string $file A Yaml file path * @param string|null $type The resource type * * @return RouteCollection A RouteCollection instance * * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid * * @api */ public function load($file, $type = null) { $path = $this->locator->locate($file); if (!stream_is_local($path)) { throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path)); } if (!file_exists($path)) { throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } $config = $this->yamlParser->parse(file_get_contents($path)); $collection = new RouteCollection(); $collection->addResource(new FileResource($path)); // empty file if (null === $config) { return $collection; } // not an array if (!is_array($config)) { throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); } foreach ($config as $name => $config) { if (isset($config['pattern'])) { if (isset($config['path'])) { throw new \InvalidArgumentException(sprintf('The file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path)); } $config['path'] = $config['pattern']; unset($config['pattern']); } $this->validate($config, $name, $path); if (isset($config['resource'])) { $this->parseImport($collection, $config, $path, $file); } else { $this->parseRoute($collection, $name, $config, $path); } } return $collection; } /** * {@inheritdoc} * * @api */ public function supports($resource, $type = null) { return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'yaml' === $type); } /** * Parses a route and adds it to the RouteCollection. * * @param RouteCollection $collection A RouteCollection instance * @param string $name Route name * @param array $config Route definition * @param string $path Full path of the YAML file being processed */ protected function parseRoute(RouteCollection $collection, $name, array $config, $path) { $defaults = isset($config['defaults']) ? $config['defaults'] : array(); $requirements = isset($config['requirements']) ? $config['requirements'] : array(); $options = isset($config['options']) ? $config['options'] : array(); $host = isset($config['host']) ? $config['host'] : ''; $schemes = isset($config['schemes']) ? $config['schemes'] : array(); $methods = isset($config['methods']) ? $config['methods'] : array(); $condition = isset($config['condition']) ? $config['condition'] : null; $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition); $collection->add($name, $route); } /** * Parses an import and adds the routes in the resource to the RouteCollection. * * @param RouteCollection $collection A RouteCollection instance * @param array $config Route definition * @param string $path Full path of the YAML file being processed * @param string $file Loaded file name */ protected function parseImport(RouteCollection $collection, array $config, $path, $file) { $type = isset($config['type']) ? $config['type'] : null; $prefix = isset($config['prefix']) ? $config['prefix'] : ''; $defaults = isset($config['defaults']) ? $config['defaults'] : array(); $requirements = isset($config['requirements']) ? $config['requirements'] : array(); $options = isset($config['options']) ? $config['options'] : array(); $host = isset($config['host']) ? $config['host'] : null; $condition = isset($config['condition']) ? $config['condition'] : null; $schemes = isset($config['schemes']) ? $config['schemes'] : null; $methods = isset($config['methods']) ? $config['methods'] : null; $this->setCurrentDir(dirname($path)); $subCollection = $this->import($config['resource'], $type, false, $file); /* @var $subCollection RouteCollection */ $subCollection->addPrefix($prefix); if (null !== $host) { $subCollection->setHost($host); } if (null !== $condition) { $subCollection->setCondition($condition); } if (null !== $schemes) { $subCollection->setSchemes($schemes); } if (null !== $methods) { $subCollection->setMethods($methods); } $subCollection->addDefaults($defaults); $subCollection->addRequirements($requirements); $subCollection->addOptions($options); $collection->addCollection($subCollection); } /** * Validates the route configuration. * * @param array $config A resource config * @param string $name The config key * @param string $path The loaded file path * * @throws \InvalidArgumentException If one of the provided config keys is not supported, * something is missing or the combination is nonsense */ protected function validate($config, $name, $path) { if (!is_array($config)) { throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); } if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) { throw new \InvalidArgumentException(sprintf( 'The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys) )); } if (isset($config['resource']) && isset($config['path'])) { throw new \InvalidArgumentException(sprintf( 'The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name )); } if (!isset($config['resource']) && isset($config['type'])) { throw new \InvalidArgumentException(sprintf( 'The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path )); } if (!isset($config['resource']) && !isset($config['path'])) { throw new \InvalidArgumentException(sprintf( 'You must define a "path" for the route "%s" in file "%s".', $name, $path )); } } } PK!qF>>4Symfony/Component/Routing/RouteCompilerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * RouteCompilerInterface is the interface that all RouteCompiler classes must implement. * * @author Fabien Potencier */ interface RouteCompilerInterface { /** * Compiles the current route instance. * * @param Route $route A Route instance * * @return CompiledRoute A CompiledRoute instance * * @throws \LogicException If the Route cannot be compiled because the * path or host pattern is invalid */ public static function compile(Route $route); } PK!0QQ(Symfony/Component/Process/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\RuntimeException; /** * ProcessPipes manages descriptors and pipes for the use of proc_open. */ class ProcessPipes { /** @var array */ public $pipes = array(); /** @var array */ private $files = array(); /** @var array */ private $fileHandles = array(); /** @var array */ private $readBytes = array(); /** @var Boolean */ private $useFiles; /** @var Boolean */ private $ttyMode; const CHUNK_SIZE = 16384; public function __construct($useFiles, $ttyMode) { $this->useFiles = (Boolean) $useFiles; $this->ttyMode = (Boolean) $ttyMode; // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. // Workaround for this problem is to use temporary files instead of pipes on Windows platform. // // @see https://bugs.php.net/bug.php?id=51800 if ($this->useFiles) { $this->files = array( Process::STDOUT => tempnam(sys_get_temp_dir(), 'sf_proc_stdout'), Process::STDERR => tempnam(sys_get_temp_dir(), 'sf_proc_stderr'), ); foreach ($this->files as $offset => $file) { $this->fileHandles[$offset] = fopen($this->files[$offset], 'rb'); if (false === $this->fileHandles[$offset]) { throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable'); } } $this->readBytes = array( Process::STDOUT => 0, Process::STDERR => 0, ); } } public function __destruct() { $this->close(); $this->removeFiles(); } /** * Sets non-blocking mode on pipes. */ public function unblock() { foreach ($this->pipes as $pipe) { stream_set_blocking($pipe, 0); } } /** * Closes file handles and pipes. */ public function close() { $this->closeUnixPipes(); foreach ($this->fileHandles as $handle) { fclose($handle); } $this->fileHandles = array(); } /** * Closes Unix pipes. * * Nothing happens in case file handles are used. */ public function closeUnixPipes() { foreach ($this->pipes as $pipe) { fclose($pipe); } $this->pipes = array(); } /** * Returns an array of descriptors for the use of proc_open. * * @return array */ public function getDescriptors() { if ($this->useFiles) { // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800) // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650 // So we redirect output within the commandline and pass the nul device to the process return array( array('pipe', 'r'), array('file', 'NUL', 'w'), array('file', 'NUL', 'w'), ); } if ($this->ttyMode) { return array( array('file', '/dev/tty', 'r'), array('file', '/dev/tty', 'w'), array('file', '/dev/tty', 'w'), ); } return array( array('pipe', 'r'), // stdin array('pipe', 'w'), // stdout array('pipe', 'w'), // stderr ); } /** * Returns an array of filenames indexed by their related stream in case these pipes use temporary files. * * @return array */ public function getFiles() { if ($this->useFiles) { return $this->files; } return array(); } /** * Reads data in file handles and pipes. * * @param Boolean $blocking Whether to use blocking calls or not. * * @return array An array of read data indexed by their fd. */ public function read($blocking) { return array_replace($this->readStreams($blocking), $this->readFileHandles()); } /** * Reads data in file handles and pipes, closes them if EOF is reached. * * @param Boolean $blocking Whether to use blocking calls or not. * * @return array An array of read data indexed by their fd. */ public function readAndCloseHandles($blocking) { return array_replace($this->readStreams($blocking, true), $this->readFileHandles(true)); } /** * Returns if the current state has open file handles or pipes. * * @return Boolean */ public function hasOpenHandles() { if (!$this->useFiles) { return (Boolean) $this->pipes; } return (Boolean) $this->pipes && (Boolean) $this->fileHandles; } /** * Writes stdin data. * * @param Boolean $blocking Whether to use blocking calls or not. * @param string|null $stdin The data to write. */ public function write($blocking, $stdin) { if (null === $stdin) { fclose($this->pipes[0]); unset($this->pipes[0]); return; } $writePipes = array($this->pipes[0]); unset($this->pipes[0]); $stdinLen = strlen($stdin); $stdinOffset = 0; while ($writePipes) { $r = null; $w = $writePipes; $e = null; if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(Process::TIMEOUT_PRECISION * 1E6) : 0)) { // if a system call has been interrupted, forget about it, let's try again if ($this->hasSystemCallBeenInterrupted()) { continue; } break; } // nothing has changed, let's wait until the process is ready if (0 === $n) { continue; } if ($w) { $written = fwrite($writePipes[0], (binary) substr($stdin, $stdinOffset), 8192); if (false !== $written) { $stdinOffset += $written; } if ($stdinOffset >= $stdinLen) { fclose($writePipes[0]); $writePipes = null; } } } } /** * Reads data in file handles. * * @param Boolean $close Whether to close file handles or not. * * @return array An array of read data indexed by their fd. */ private function readFileHandles($close = false) { $read = array(); $fh = $this->fileHandles; foreach ($fh as $type => $fileHandle) { if (0 !== fseek($fileHandle, $this->readBytes[$type])) { continue; } $data = ''; $dataread = null; while (!feof($fileHandle)) { if (false !== $dataread = fread($fileHandle, self::CHUNK_SIZE)) { $data .= $dataread; } } if (0 < $length = strlen($data)) { $this->readBytes[$type] += $length; $read[$type] = $data; } if (false === $dataread || (true === $close && feof($fileHandle) && '' === $data)) { fclose($this->fileHandles[$type]); unset($this->fileHandles[$type]); } } return $read; } /** * Reads data in file pipes streams. * * @param Boolean $blocking Whether to use blocking calls or not. * @param Boolean $close Whether to close file handles or not. * * @return array An array of read data indexed by their fd. */ private function readStreams($blocking, $close = false) { if (empty($this->pipes)) { return array(); } $read = array(); $r = $this->pipes; $w = null; $e = null; // let's have a look if something changed in streams if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(Process::TIMEOUT_PRECISION * 1E6) : 0)) { // if a system call has been interrupted, forget about it, let's try again // otherwise, an error occurred, let's reset pipes if (!$this->hasSystemCallBeenInterrupted()) { $this->pipes = array(); } return $read; } // nothing has changed if (0 === $n) { return $read; } foreach ($r as $pipe) { $type = array_search($pipe, $this->pipes); $data = ''; while ($dataread = fread($pipe, self::CHUNK_SIZE)) { $data .= $dataread; } if ($data) { $read[$type] = $data; } if (false === $data || (true === $close && feof($pipe) && '' === $data)) { fclose($this->pipes[$type]); unset($this->pipes[$type]); } } return $read; } /** * Returns true if a system call has been interrupted. * * @return Boolean */ private function hasSystemCallBeenInterrupted() { $lastError = error_get_last(); // stream_select returns false when the `select` system call is interrupted by an incoming signal return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call'); } /** * Removes temporary files */ private function removeFiles() { foreach ($this->files as $filename) { if (file_exists($filename)) { @unlink($filename); } } $this->files = array(); } } PK!2{{@Symfony/Component/Process/Exception/ProcessTimedOutException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; use Symfony\Component\Process\Process; /** * Exception that is thrown when a process times out. * * @author Johannes M. Schmitt */ class ProcessTimedOutException extends RuntimeException { const TYPE_GENERAL = 1; const TYPE_IDLE = 2; private $process; private $timeoutType; public function __construct(Process $process, $timeoutType) { $this->process = $process; $this->timeoutType = $timeoutType; parent::__construct(sprintf( 'The process "%s" exceeded the timeout of %s seconds.', $process->getCommandLine(), $this->getExceededTimeout() )); } public function getProcess() { return $this->process; } public function isGeneralTimeout() { return $this->timeoutType === self::TYPE_GENERAL; } public function isIdleTimeout() { return $this->timeoutType === self::TYPE_IDLE; } public function getExceededTimeout() { switch ($this->timeoutType) { case self::TYPE_GENERAL: return $this->process->getTimeout(); case self::TYPE_IDLE: return $this->process->getIdleTimeout(); default: throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType)); } } } PK!<:Symfony/Component/Process/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * Marker Interface for the Process Component. * * @author Johannes M. Schmitt */ interface ExceptionInterface { } PK!>H8Symfony/Component/Process/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * RuntimeException for the Process Component. * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK!W6Symfony/Component/Process/Exception/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * LogicException for the Process Component. * * @author Romain Neutron */ class LogicException extends \LogicException implements ExceptionInterface { } PK!˅@Symfony/Component/Process/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * InvalidArgumentException for the Process Component. * * @author Romain Neutron */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK!_>Symfony/Component/Process/Exception/ProcessFailedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; use Symfony\Component\Process\Process; /** * Exception for failed processes. * * @author Johannes M. Schmitt */ class ProcessFailedException extends RuntimeException { private $process; public function __construct(Process $process) { if ($process->isSuccessful()) { throw new InvalidArgumentException('Expected a failed process, but the given process was successful.'); } parent::__construct( sprintf( 'The command "%s" failed.'."\nExit Code: %s(%s)\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s", $process->getCommandLine(), $process->getExitCode(), $process->getExitCodeText(), $process->getOutput(), $process->getErrorOutput() ) ); $this->process = $process; } public function getProcess() { return $this->process; } } PK!@s(Symfony/Component/Process/PhpProcess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\RuntimeException; /** * PhpProcess runs a PHP script in an independent process. * * $p = new PhpProcess(''); * $p->run(); * print $p->getOutput()."\n"; * * @author Fabien Potencier * * @api */ class PhpProcess extends Process { private $executableFinder; /** * Constructor. * * @param string $script The PHP script to run (as a string) * @param string $cwd The working directory * @param array $env The environment variables * @param integer $timeout The timeout in seconds * @param array $options An array of options for proc_open * * @api */ public function __construct($script, $cwd = null, array $env = array(), $timeout = 60, array $options = array()) { parent::__construct(null, $cwd, $env, $script, $timeout, $options); $this->executableFinder = new PhpExecutableFinder(); } /** * Sets the path to the PHP binary to use. * * @api */ public function setPhpBinary($php) { $this->setCommandLine($php); } /** * {@inheritdoc} */ public function start($callback = null) { if (null === $this->getCommandLine()) { if (false === $php = $this->executableFinder->find()) { throw new RuntimeException('Unable to find the PHP executable.'); } $this->setCommandLine($php); } parent::start($callback); } } PK!nL L *Symfony/Component/Process/ProcessUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * ProcessUtils is a bunch of utility methods. * * This class contains static methods only and is not meant to be instantiated. * * @author Martin Hasoň */ class ProcessUtils { /** * This class should not be instantiated */ private function __construct() { } /** * Escapes a string to be used as a shell argument. * * @param string $argument The argument that will be escaped * * @return string The escaped argument */ 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 (defined('PHP_WINDOWS_VERSION_BUILD')) { if ('' === $argument) { return escapeshellarg($argument); } $escapedArgument = ''; $quote = false; foreach (preg_split('/(")/i', $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 escapeshellarg($argument); } private static function isSurroundedBy($arg, $char) { return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1]; } } PK!!,$  .Symfony/Component/Process/ExecutableFinder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * Generic executable finder. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class ExecutableFinder { private $suffixes = array('.exe', '.bat', '.cmd', '.com'); /** * Replaces default suffixes of executable. * * @param array $suffixes */ public function setSuffixes(array $suffixes) { $this->suffixes = $suffixes; } /** * Adds new possible suffix to check for executable. * * @param string $suffix */ public function addSuffix($suffix) { $this->suffixes[] = $suffix; } /** * Finds an executable by name. * * @param string $name The executable name (without the extension) * @param string $default The default to return if no executable is found * @param array $extraDirs Additional dirs to check into * * @return string The executable path or default value */ public function find($name, $default = null, array $extraDirs = array()) { if (ini_get('open_basedir')) { $searchPath = explode(PATH_SEPARATOR, getenv('open_basedir')); $dirs = array(); foreach ($searchPath as $path) { if (is_dir($path)) { $dirs[] = $path; } else { $file = str_replace(dirname($path), '', $path); if ($file == $name && is_executable($path)) { return $path; } } } } else { $dirs = array_merge( explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), $extraDirs ); } $suffixes = array(''); if (defined('PHP_WINDOWS_VERSION_BUILD')) { $pathExt = getenv('PATHEXT'); $suffixes = $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes; } foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { if (is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && (defined('PHP_WINDOWS_VERSION_BUILD') || is_executable($file))) { return $file; } } } return $default; } } PK!!/,Symfony/Component/Process/ProcessBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\InvalidArgumentException; use Symfony\Component\Process\Exception\LogicException; /** * Process builder. * * @author Kris Wallsmith */ class ProcessBuilder { private $arguments; private $cwd; private $env = array(); private $stdin; private $timeout = 60; private $options = array(); private $inheritEnv = true; private $prefix = array(); public function __construct(array $arguments = array()) { $this->arguments = $arguments; } public static function create(array $arguments = array()) { return new static($arguments); } /** * Adds an unescaped argument to the command string. * * @param string $argument A command argument * * @return ProcessBuilder */ public function add($argument) { $this->arguments[] = $argument; return $this; } /** * Adds an unescaped prefix to the command string. * * The prefix is preserved when resetting arguments. * * @param string|array $prefix A command prefix or an array of command prefixes * * @return ProcessBuilder */ public function setPrefix($prefix) { $this->prefix = is_array($prefix) ? $prefix : array($prefix); return $this; } /** * @param array $arguments * * @return ProcessBuilder */ public function setArguments(array $arguments) { $this->arguments = $arguments; return $this; } public function setWorkingDirectory($cwd) { $this->cwd = $cwd; return $this; } public function inheritEnvironmentVariables($inheritEnv = true) { $this->inheritEnv = $inheritEnv; return $this; } public function setEnv($name, $value) { $this->env[$name] = $value; return $this; } public function addEnvironmentVariables(array $variables) { $this->env = array_replace($this->env, $variables); return $this; } public function setInput($stdin) { $this->stdin = $stdin; return $this; } /** * Sets the process timeout. * * To disable the timeout, set this value to null. * * @param float|null * * @return ProcessBuilder * * @throws InvalidArgumentException */ public function setTimeout($timeout) { if (null === $timeout) { $this->timeout = null; return $this; } $timeout = (float) $timeout; if ($timeout < 0) { throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); } $this->timeout = $timeout; return $this; } public function setOption($name, $value) { $this->options[$name] = $value; return $this; } public function getProcess() { if (0 === count($this->prefix) && 0 === count($this->arguments)) { throw new LogicException('You must add() command arguments before calling getProcess().'); } $options = $this->options; $arguments = array_merge($this->prefix, $this->arguments); $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments)); if ($this->inheritEnv) { // include $_ENV for BC purposes $env = array_replace($_ENV, $_SERVER, $this->env); } else { $env = $this->env; } return new Process($script, $this->cwd, $env, $this->stdin, $this->timeout, $options); } } PK!y>81Symfony/Component/Process/PhpExecutableFinder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * An executable finder specifically designed for the PHP executable. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class PhpExecutableFinder { private $executableFinder; public function __construct() { $this->executableFinder = new ExecutableFinder(); } /** * Finds The PHP executable. * * @return string|false The PHP executable path or false if it cannot be found */ public function find() { // HHVM support if (defined('HHVM_VERSION') && false !== $hhvm = getenv('PHP_BINARY')) { return $hhvm; } // PHP_BINARY return the current sapi executable if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server')) && is_file(PHP_BINARY)) { return PHP_BINARY; } if ($php = getenv('PHP_PATH')) { if (!is_executable($php)) { return false; } return $php; } if ($php = getenv('PHP_PEAR_PHP_BIN')) { if (is_executable($php)) { return $php; } } $dirs = array(PHP_BINDIR); if (defined('PHP_WINDOWS_VERSION_BUILD')) { $dirs[] = 'C:\xampp\php\\'; } return $this->executableFinder->find('php', false, $dirs); } } PK!M%Symfony/Component/Process/Process.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\InvalidArgumentException; use Symfony\Component\Process\Exception\LogicException; use Symfony\Component\Process\Exception\ProcessTimedOutException; use Symfony\Component\Process\Exception\RuntimeException; /** * Process is a thin wrapper around proc_* functions to easily * start independent PHP processes. * * @author Fabien Potencier * * @api */ class Process { const ERR = 'err'; const OUT = 'out'; const STATUS_READY = 'ready'; const STATUS_STARTED = 'started'; const STATUS_TERMINATED = 'terminated'; const STDIN = 0; const STDOUT = 1; const STDERR = 2; // Timeout Precision in seconds. const TIMEOUT_PRECISION = 0.2; private $callback; private $commandline; private $cwd; private $env; private $stdin; private $starttime; private $lastOutputTime; private $timeout; private $idleTimeout; private $options; private $exitcode; private $fallbackExitcode; private $processInformation; private $stdout; private $stderr; private $enhanceWindowsCompatibility; private $enhanceSigchildCompatibility; private $process; private $status = self::STATUS_READY; private $incrementalOutputOffset = 0; private $incrementalErrorOutputOffset = 0; private $tty; private $useFileHandles = false; /** @var ProcessPipes */ private $processPipes; private static $sigchild; /** * Exit codes translation table. * * User-defined errors must use exit codes in the 64-113 range. * * @var array */ public static $exitCodes = array( 0 => 'OK', 1 => 'General error', 2 => 'Misuse of shell builtins', 126 => 'Invoked command cannot execute', 127 => 'Command not found', 128 => 'Invalid exit argument', // signals 129 => 'Hangup', 130 => 'Interrupt', 131 => 'Quit and dump core', 132 => 'Illegal instruction', 133 => 'Trace/breakpoint trap', 134 => 'Process aborted', 135 => 'Bus error: "access to undefined portion of memory object"', 136 => 'Floating point exception: "erroneous arithmetic operation"', 137 => 'Kill (terminate immediately)', 138 => 'User-defined 1', 139 => 'Segmentation violation', 140 => 'User-defined 2', 141 => 'Write to pipe with no one reading', 142 => 'Signal raised by alarm', 143 => 'Termination (request to terminate)', // 144 - not defined 145 => 'Child process terminated, stopped (or continued*)', 146 => 'Continue if stopped', 147 => 'Stop executing temporarily', 148 => 'Terminal stop signal', 149 => 'Background process attempting to read from tty ("in")', 150 => 'Background process attempting to write to tty ("out")', 151 => 'Urgent data available on socket', 152 => 'CPU time limit exceeded', 153 => 'File size limit exceeded', 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"', 155 => 'Profiling timer expired', // 156 - not defined 157 => 'Pollable event', // 158 - not defined 159 => 'Bad syscall', ); /** * Constructor. * * @param string $commandline The command line to run * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to inherit * @param string|null $stdin The STDIN content * @param integer|float|null $timeout The timeout in seconds or null to disable * @param array $options An array of options for proc_open * * @throws RuntimeException When proc_open is not installed * * @api */ public function __construct($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array()) { if (!function_exists('proc_open')) { throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.'); } $this->commandline = $commandline; $this->cwd = $cwd; // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected // @see : https://bugs.php.net/bug.php?id=51800 // @see : https://bugs.php.net/bug.php?id=50524 if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || defined('PHP_WINDOWS_VERSION_BUILD'))) { $this->cwd = getcwd(); } if (null !== $env) { $this->setEnv($env); } else { $this->env = null; } $this->stdin = $stdin; $this->setTimeout($timeout); $this->useFileHandles = defined('PHP_WINDOWS_VERSION_BUILD'); $this->enhanceWindowsCompatibility = true; $this->enhanceSigchildCompatibility = !defined('PHP_WINDOWS_VERSION_BUILD') && $this->isSigchildEnabled(); $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options); } public function __destruct() { // stop() will check if we have a process running. $this->stop(); } public function __clone() { $this->resetProcessData(); } /** * Runs the process. * * The callback receives the type of output (out or err) and * some bytes from the output in real-time. It allows to have feedback * from the independent process during execution. * * The STDOUT and STDERR are also available after the process is finished * via the getOutput() and getErrorOutput() methods. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return integer The exit status code * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process stopped after receiving signal * * @api */ public function run($callback = null) { $this->start($callback); return $this->wait(); } /** * Starts the process and returns after sending the STDIN. * * This method blocks until all STDIN data is sent to the process then it * returns while the process runs in the background. * * The termination of the process can be awaited with wait(). * * The callback receives the type of output (out or err) and some bytes from * the output in real-time while writing the standard input to the process. * It allows to have feedback from the independent process during execution. * If there is no callback passed, the wait() method can be called * with true as a second parameter then the callback will get all data occurred * in (and since) the start call. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The process itself * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running */ public function start($callback = null) { if ($this->isRunning()) { throw new RuntimeException('Process is already running'); } $this->resetProcessData(); $this->starttime = $this->lastOutputTime = microtime(true); $this->callback = $this->buildCallback($callback); $descriptors = $this->getDescriptors(); $commandline = $this->commandline; if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->enhanceWindowsCompatibility) { $commandline = 'cmd /V:ON /E:ON /C "('.$commandline.')"'; foreach ($this->processPipes->getFiles() as $offset => $filename) { $commandline .= ' '.$offset.'>'.$filename; } if (!isset($this->options['bypass_shell'])) { $this->options['bypass_shell'] = true; } } $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options); if (!is_resource($this->process)) { throw new RuntimeException('Unable to launch a new process.'); } $this->status = self::STATUS_STARTED; $this->processPipes->unblock(); if ($this->tty) { return; } $this->processPipes->write(false, $this->stdin); $this->updateStatus(false); $this->checkTimeout(); } /** * Restarts the process. * * Be warned that the process is cloned before being started. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The new process * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running * * @see start() */ public function restart($callback = null) { if ($this->isRunning()) { throw new RuntimeException('Process is already running'); } $process = clone $this; $process->start($callback); return $process; } /** * Waits for the process to terminate. * * The callback receives the type of output (out or err) and some bytes * from the output in real-time while writing the standard input to the process. * It allows to have feedback from the independent process during execution. * * @param callable|null $callback A valid PHP callback * * @return integer The exitcode of the process * * @throws RuntimeException When process timed out * @throws RuntimeException When process stopped after receiving signal * @throws LogicException When process is not yet started */ public function wait($callback = null) { $this->requireProcessIsStarted(__FUNCTION__); $this->updateStatus(false); if (null !== $callback) { $this->callback = $this->buildCallback($callback); } do { $this->checkTimeout(); $running = defined('PHP_WINDOWS_VERSION_BUILD') ? $this->isRunning() : $this->processPipes->hasOpenHandles(); $close = !defined('PHP_WINDOWS_VERSION_BUILD') || !$running;; $this->readPipes(true, $close); } while ($running); while ($this->isRunning()) { usleep(1000); } if ($this->processInformation['signaled']) { throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig'])); } return $this->exitcode; } /** * Returns the Pid (process identifier), if applicable. * * @return integer|null The process id if running, null otherwise * * @throws RuntimeException In case --enable-sigchild is activated */ public function getPid() { if ($this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.'); } $this->updateStatus(false); return $this->isRunning() ? $this->processInformation['pid'] : null; } /** * Sends a POSIX signal to the process. * * @param integer $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) * * @return Process * * @throws LogicException In case the process is not running * @throws RuntimeException In case --enable-sigchild is activated * @throws RuntimeException In case of failure */ public function signal($signal) { $this->doSignal($signal, true); return $this; } /** * Returns the current output of the process (STDOUT). * * @return string The process output * * @throws LogicException In case the process is not started * * @api */ public function getOutput() { $this->requireProcessIsStarted(__FUNCTION__); $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true); return $this->stdout; } /** * Returns the output incrementally. * * In comparison with the getOutput method which always return the whole * output, this one returns the new output since the last call. * * @throws LogicException In case the process is not started * * @return string The process output since the last call */ public function getIncrementalOutput() { $this->requireProcessIsStarted(__FUNCTION__); $data = $this->getOutput(); $latest = substr($data, $this->incrementalOutputOffset); $this->incrementalOutputOffset = strlen($data); return $latest; } /** * Clears the process output. * * @return Process */ public function clearOutput() { $this->stdout = ''; $this->incrementalOutputOffset = 0; return $this; } /** * Returns the current error output of the process (STDERR). * * @return string The process error output * * @throws LogicException In case the process is not started * * @api */ public function getErrorOutput() { $this->requireProcessIsStarted(__FUNCTION__); $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true); return $this->stderr; } /** * Returns the errorOutput incrementally. * * In comparison with the getErrorOutput method which always return the * whole error output, this one returns the new error output since the last * call. * * @throws LogicException In case the process is not started * * @return string The process error output since the last call */ public function getIncrementalErrorOutput() { $this->requireProcessIsStarted(__FUNCTION__); $data = $this->getErrorOutput(); $latest = substr($data, $this->incrementalErrorOutputOffset); $this->incrementalErrorOutputOffset = strlen($data); return $latest; } /** * Clears the process output. * * @return Process */ public function clearErrorOutput() { $this->stderr = ''; $this->incrementalErrorOutputOffset = 0; return $this; } /** * Returns the exit code returned by the process. * * @return null|integer The exit status code, null if the Process is not terminated * * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled * * @api */ public function getExitCode() { if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); } $this->updateStatus(false); return $this->exitcode; } /** * Returns a string representation for the exit code returned by the process. * * This method relies on the Unix exit code status standardization * and might not be relevant for other operating systems. * * @return null|string A string representation for the exit status code, null if the Process is not terminated. * * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled * * @see http://tldp.org/LDP/abs/html/exitcodes.html * @see http://en.wikipedia.org/wiki/Unix_signal */ public function getExitCodeText() { if (null === $exitcode = $this->getExitCode()) { return; } return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error'; } /** * Checks if the process ended successfully. * * @return Boolean true if the process ended successfully, false otherwise * * @api */ public function isSuccessful() { return 0 === $this->getExitCode(); } /** * Returns true if the child process has been terminated by an uncaught signal. * * It always returns false on Windows. * * @return Boolean * * @throws RuntimeException In case --enable-sigchild is activated * @throws LogicException In case the process is not terminated * * @api */ public function hasBeenSignaled() { $this->requireProcessIsTerminated(__FUNCTION__); if ($this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } $this->updateStatus(false); return $this->processInformation['signaled']; } /** * Returns the number of the signal that caused the child process to terminate its execution. * * It is only meaningful if hasBeenSignaled() returns true. * * @return integer * * @throws RuntimeException In case --enable-sigchild is activated * @throws LogicException In case the process is not terminated * * @api */ public function getTermSignal() { $this->requireProcessIsTerminated(__FUNCTION__); if ($this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } $this->updateStatus(false); return $this->processInformation['termsig']; } /** * Returns true if the child process has been stopped by a signal. * * It always returns false on Windows. * * @return Boolean * * @throws LogicException In case the process is not terminated * * @api */ public function hasBeenStopped() { $this->requireProcessIsTerminated(__FUNCTION__); $this->updateStatus(false); return $this->processInformation['stopped']; } /** * Returns the number of the signal that caused the child process to stop its execution. * * It is only meaningful if hasBeenStopped() returns true. * * @return integer * * @throws LogicException In case the process is not terminated * * @api */ public function getStopSignal() { $this->requireProcessIsTerminated(__FUNCTION__); $this->updateStatus(false); return $this->processInformation['stopsig']; } /** * Checks if the process is currently running. * * @return Boolean true if the process is currently running, false otherwise */ public function isRunning() { if (self::STATUS_STARTED !== $this->status) { return false; } $this->updateStatus(false); return $this->processInformation['running']; } /** * Checks if the process has been started with no regard to the current state. * * @return Boolean true if status is ready, false otherwise */ public function isStarted() { return $this->status != self::STATUS_READY; } /** * Checks if the process is terminated. * * @return Boolean true if process is terminated, false otherwise */ public function isTerminated() { $this->updateStatus(false); return $this->status == self::STATUS_TERMINATED; } /** * Gets the process status. * * The status is one of: ready, started, terminated. * * @return string The current process status */ public function getStatus() { $this->updateStatus(false); return $this->status; } /** * Stops the process. * * @param integer|float $timeout The timeout in seconds * @param integer $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL * * @return integer The exit-code of the process * * @throws RuntimeException if the process got signaled */ public function stop($timeout = 10, $signal = null) { $timeoutMicro = microtime(true) + $timeout; if ($this->isRunning()) { if (defined('PHP_WINDOWS_VERSION_BUILD') && !$this->isSigchildEnabled()) { exec(sprintf("taskkill /F /T /PID %d 2>&1", $this->getPid()), $output, $exitCode); if ($exitCode > 0) { throw new RuntimeException('Unable to kill the process'); } } proc_terminate($this->process); do { usleep(1000); } while ($this->isRunning() && microtime(true) < $timeoutMicro); if ($this->isRunning() && !$this->isSigchildEnabled()) { if (null !== $signal || defined('SIGKILL')) { // avoid exception here : // process is supposed to be running, but it might have stop // just after this line. // in any case, let's silently discard the error, we can not do anything $this->doSignal($signal ?: SIGKILL, false); } } } $this->updateStatus(false); if ($this->processInformation['running']) { $this->close(); } return $this->exitcode; } /** * Adds a line to the STDOUT stream. * * @param string $line The line to append */ public function addOutput($line) { $this->lastOutputTime = microtime(true); $this->stdout .= $line; } /** * Adds a line to the STDERR stream. * * @param string $line The line to append */ public function addErrorOutput($line) { $this->lastOutputTime = microtime(true); $this->stderr .= $line; } /** * Gets the command line to be executed. * * @return string The command to execute */ public function getCommandLine() { return $this->commandline; } /** * Sets the command line to be executed. * * @param string $commandline The command to execute * * @return self The current Process instance */ public function setCommandLine($commandline) { $this->commandline = $commandline; return $this; } /** * Gets the process timeout (max. runtime). * * @return float|null The timeout in seconds or null if it's disabled */ public function getTimeout() { return $this->timeout; } /** * Gets the process idle timeout (max. time since last output). * * @return float|null The timeout in seconds or null if it's disabled */ public function getIdleTimeout() { return $this->idleTimeout; } /** * Sets the process timeout (max. runtime). * * To disable the timeout, set this value to null. * * @param integer|float|null $timeout The timeout in seconds * * @return self The current Process instance * * @throws InvalidArgumentException if the timeout is negative */ public function setTimeout($timeout) { $this->timeout = $this->validateTimeout($timeout); return $this; } /** * Sets the process idle timeout (max. time since last output). * * To disable the timeout, set this value to null. * * @param integer|float|null $timeout The timeout in seconds * * @return self The current Process instance. * * @throws InvalidArgumentException if the timeout is negative */ public function setIdleTimeout($timeout) { $this->idleTimeout = $this->validateTimeout($timeout); return $this; } /** * Enables or disables the TTY mode. * * @param boolean $tty True to enabled and false to disable * * @return self The current Process instance */ public function setTty($tty) { $this->tty = (Boolean) $tty; return $this; } /** * Checks if the TTY mode is enabled. * * @return Boolean true if the TTY mode is enabled, false otherwise */ public function isTty() { return $this->tty; } /** * Gets the working directory. * * @return string|null The current working directory or null on failure */ public function getWorkingDirectory() { if (null === $this->cwd) { // getcwd() will return false if any one of the parent directories does not have // the readable or search mode set, even if the current directory does return getcwd() ?: null; } return $this->cwd; } /** * Sets the current working directory. * * @param string $cwd The new working directory * * @return self The current Process instance */ public function setWorkingDirectory($cwd) { $this->cwd = $cwd; return $this; } /** * Gets the environment variables. * * @return array The current environment variables */ public function getEnv() { return $this->env; } /** * Sets the environment variables. * * An environment variable value should be a string. * If it is an array, the variable is ignored. * * That happens in PHP when 'argv' is registered into * the $_ENV array for instance. * * @param array $env The new environment variables * * @return self The current Process instance */ public function setEnv(array $env) { // Process can not handle env values that are arrays $env = array_filter($env, function ($value) { return !is_array($value); }); $this->env = array(); foreach ($env as $key => $value) { $this->env[(binary) $key] = (binary) $value; } return $this; } /** * Gets the contents of STDIN. * * @return string|null The current contents */ public function getStdin() { return $this->stdin; } /** * Sets the contents of STDIN. * * @param string|null $stdin The new contents * * @return self The current Process instance */ public function setStdin($stdin) { $this->stdin = $stdin; return $this; } /** * Gets the options for proc_open. * * @return array The current options */ public function getOptions() { return $this->options; } /** * Sets the options for proc_open. * * @param array $options The new options * * @return self The current Process instance */ public function setOptions(array $options) { $this->options = $options; return $this; } /** * Gets whether or not Windows compatibility is enabled. * * This is true by default. * * @return Boolean */ public function getEnhanceWindowsCompatibility() { return $this->enhanceWindowsCompatibility; } /** * Sets whether or not Windows compatibility is enabled. * * @param Boolean $enhance * * @return self The current Process instance */ public function setEnhanceWindowsCompatibility($enhance) { $this->enhanceWindowsCompatibility = (Boolean) $enhance; return $this; } /** * Returns whether sigchild compatibility mode is activated or not. * * @return Boolean */ public function getEnhanceSigchildCompatibility() { return $this->enhanceSigchildCompatibility; } /** * Activates sigchild compatibility mode. * * Sigchild compatibility mode is required to get the exit code and * determine the success of a process when PHP has been compiled with * the --enable-sigchild option * * @param Boolean $enhance * * @return self The current Process instance */ public function setEnhanceSigchildCompatibility($enhance) { $this->enhanceSigchildCompatibility = (Boolean) $enhance; return $this; } /** * Performs a check between the timeout definition and the time the process started. * * In case you run a background process (with the start method), you should * trigger this method regularly to ensure the process timeout * * @throws ProcessTimedOutException In case the timeout was reached */ public function checkTimeout() { if ($this->status !== self::STATUS_STARTED) { return; } if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL); } if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE); } } /** * Creates the descriptors needed by the proc_open. * * @return array */ private function getDescriptors() { $this->processPipes = new ProcessPipes($this->useFileHandles, $this->tty); $descriptors = $this->processPipes->getDescriptors(); if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { // last exit code is output on the fourth pipe and caught to work around --enable-sigchild $descriptors = array_merge($descriptors, array(array('pipe', 'w'))); $this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code'; } return $descriptors; } /** * Builds up the callback used by wait(). * * The callbacks adds all occurred output to the specific buffer and calls * the user callback (if present) with the received output. * * @param callable|null $callback The user defined PHP callback * * @return callable A PHP callable */ protected function buildCallback($callback) { $that = $this; $out = self::OUT; $err = self::ERR; $callback = function ($type, $data) use ($that, $callback, $out, $err) { if ($out == $type) { $that->addOutput($data); } else { $that->addErrorOutput($data); } if (null !== $callback) { call_user_func($callback, $type, $data); } }; return $callback; } /** * Updates the status of the process, reads pipes. * * @param Boolean $blocking Whether to use a blocking read call. */ protected function updateStatus($blocking) { if (self::STATUS_STARTED !== $this->status) { return; } $this->processInformation = proc_get_status($this->process); $this->captureExitCode(); $this->readPipes($blocking, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true); if (!$this->processInformation['running']) { $this->close(); } } /** * Returns whether PHP has been compiled with the '--enable-sigchild' option or not. * * @return Boolean */ protected function isSigchildEnabled() { if (null !== self::$sigchild) { return self::$sigchild; } if (!function_exists('phpinfo')) { return self::$sigchild = false; } ob_start(); phpinfo(INFO_GENERAL); return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild'); } /** * Validates and returns the filtered timeout. * * @param integer|float|null $timeout * * @return float|null */ private function validateTimeout($timeout) { $timeout = (float) $timeout; if (0.0 === $timeout) { $timeout = null; } elseif ($timeout < 0) { throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); } return $timeout; } /** * Reads pipes, executes callback. * * @param Boolean $blocking Whether to use blocking calls or not. * @param Boolean $close Whether to close file handles or not. */ private function readPipes($blocking, $close) { if ($close) { $result = $this->processPipes->readAndCloseHandles($blocking); } else { $result = $this->processPipes->read($blocking); } foreach ($result as $type => $data) { if (3 == $type) { $this->fallbackExitcode = (int) $data; } else { call_user_func($this->callback, $type === self::STDOUT ? self::OUT : self::ERR, $data); } } } /** * Captures the exitcode if mentioned in the process information. */ private function captureExitCode() { if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) { $this->exitcode = $this->processInformation['exitcode']; } } /** * Closes process resource, closes file handles, sets the exitcode. * * @return Integer The exitcode */ private function close() { $this->processPipes->close(); if (is_resource($this->process)) { $exitcode = proc_close($this->process); } else { $exitcode = -1; } $this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1); $this->status = self::STATUS_TERMINATED; if (-1 === $this->exitcode && null !== $this->fallbackExitcode) { $this->exitcode = $this->fallbackExitcode; } elseif (-1 === $this->exitcode && $this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) { // if process has been signaled, no exitcode but a valid termsig, apply Unix convention $this->exitcode = 128 + $this->processInformation['termsig']; } return $this->exitcode; } /** * Resets data related to the latest run of the process. */ private function resetProcessData() { $this->starttime = null; $this->callback = null; $this->exitcode = null; $this->fallbackExitcode = null; $this->processInformation = null; $this->stdout = null; $this->stderr = null; $this->process = null; $this->status = self::STATUS_READY; $this->incrementalOutputOffset = 0; $this->incrementalErrorOutputOffset = 0; } /** * Sends a POSIX signal to the process. * * @param integer $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) * @param Boolean $throwException Whether to throw exception in case signal failed * * @return Boolean True if the signal was sent successfully, false otherwise * * @throws LogicException In case the process is not running * @throws RuntimeException In case --enable-sigchild is activated * @throws RuntimeException In case of failure */ private function doSignal($signal, $throwException) { if (!$this->isRunning()) { if ($throwException) { throw new LogicException('Can not send signal on a non running process.'); } return false; } if ($this->isSigchildEnabled()) { if ($throwException) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.'); } return false; } if (true !== @proc_terminate($this->process, $signal)) { if ($throwException) { throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal)); } return false; } return true; } /** * Ensures the process is running or terminated, throws a LogicException if the process has a not started. * * @param $functionName The function name that was called. * * @throws LogicException If the process has not run. */ private function requireProcessIsStarted($functionName) { if (!$this->isStarted()) { throw new LogicException(sprintf('Process must be started before calling %s.', $functionName)); } } /** * Ensures the process is terminated, throws a LogicException if the process has a status different than `terminated`. * * @param $functionName The function name that was called. * * @throws LogicException If the process is not yet terminated. */ private function requireProcessIsTerminated($functionName) { if (!$this->isTerminated()) { throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName)); } } } PK![i55ESymfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\SerializerAwareInterface; /** * SerializerAware Normalizer implementation * * @author Jordi Boggiano */ abstract class SerializerAwareNormalizer implements SerializerAwareInterface { /** * @var SerializerInterface */ protected $serializer; /** * {@inheritdoc} */ public function setSerializer(SerializerInterface $serializer) { $this->serializer = $serializer; } } PK!=Vxe::ASymfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * Defines the most basic interface a class must implement to be normalizable * * If a normalizer is registered for the class and it doesn't implement * the Normalizable interfaces, the normalizer will be used instead * * @author Jordi Boggiano */ interface NormalizableInterface { /** * Normalizes the object into an array of scalars|arrays. * * It is important to understand that the normalize() call should normalize * recursively all child objects of the implementor. * * @param NormalizerInterface $normalizer The normalizer is given so that you * can use it to normalize objects contained within this object. * @param string|null $format The format is optionally given to be able to normalize differently * based on different output formats. * @param array $context Options for normalizing this object * * @return array|scalar */ public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array()); } PK!SVV<Symfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * @author Jordi Boggiano */ class CustomNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface { /** * {@inheritdoc} */ public function normalize($object, $format = null, array $context = array()) { return $object->normalize($this->serializer, $format, $context); } /** * {@inheritdoc} */ public function denormalize($data, $class, $format = null, array $context = array()) { $object = new $class(); $object->denormalize($this->serializer, $data, $format, $context); return $object; } /** * Checks if the given class implements the NormalizableInterface. * * @param mixed $data Data to normalize. * @param string $format The format being (de-)serialized from or into. * * @return Boolean */ public function supportsNormalization($data, $format = null) { return $data instanceof NormalizableInterface; } /** * Checks if the given class implements the NormalizableInterface. * * @param mixed $data Data to denormalize from. * @param string $type The class to which the data should be denormalized. * @param string $format The format being deserialized from. * * @return Boolean */ public function supportsDenormalization($data, $type, $format = null) { $class = new \ReflectionClass($type); return $class->isSubclassOf('Symfony\Component\Serializer\Normalizer\DenormalizableInterface'); } } PK! ,,BSymfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\RuntimeException; /** * Converts between objects with getter and setter methods and arrays. * * The normalization process looks at all public methods and calls the ones * which have a name starting with get and take no parameters. The result is a * map from property names (method name stripped of the get prefix and converted * to lower case) to property values. Property values are normalized through the * serializer. * * The denormalization first looks at the constructor of the given class to see * if any of the parameters have the same name as one of the properties. The * constructor is then called with all parameters or an exception is thrown if * any required parameters were not present as properties. Then the denormalizer * walks through the given map of property names to property values to see if a * setter method exists for any of the properties. If a setter exists it is * called with the property value. No automatic denormalization of the value * takes place. * * @author Nils Adermann */ class GetSetMethodNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface { protected $callbacks = array(); protected $ignoredAttributes = array(); protected $camelizedAttributes = array(); /** * Set normalization callbacks. * * @param callable[] $callbacks help normalize the result * * @throws InvalidArgumentException if a non-callable callback is set */ public function setCallbacks(array $callbacks) { foreach ($callbacks as $attribute => $callback) { if (!is_callable($callback)) { throw new InvalidArgumentException(sprintf('The given callback for attribute "%s" is not callable.', $attribute)); } } $this->callbacks = $callbacks; } /** * Set ignored attributes for normalization * * @param array $ignoredAttributes */ public function setIgnoredAttributes(array $ignoredAttributes) { $this->ignoredAttributes = $ignoredAttributes; } /** * Set attributes to be camelized on denormalize * * @param array $camelizedAttributes */ public function setCamelizedAttributes(array $camelizedAttributes) { $this->camelizedAttributes = $camelizedAttributes; } /** * {@inheritdoc} */ public function normalize($object, $format = null, array $context = array()) { $reflectionObject = new \ReflectionObject($object); $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC); $attributes = array(); foreach ($reflectionMethods as $method) { if ($this->isGetMethod($method)) { $attributeName = lcfirst(substr($method->name, 3)); if (in_array($attributeName, $this->ignoredAttributes)) { continue; } $attributeValue = $method->invoke($object); if (array_key_exists($attributeName, $this->callbacks)) { $attributeValue = call_user_func($this->callbacks[$attributeName], $attributeValue); } if (null !== $attributeValue && !is_scalar($attributeValue)) { if (!$this->serializer instanceof NormalizerInterface) { throw new \LogicException(sprintf('Cannot normalize attribute "%s" because injected serializer is not a normalizer', $attributeName)); } $attributeValue = $this->serializer->normalize($attributeValue, $format); } $attributes[$attributeName] = $attributeValue; } } return $attributes; } /** * {@inheritdoc} */ public function denormalize($data, $class, $format = null, array $context = array()) { $reflectionClass = new \ReflectionClass($class); $constructor = $reflectionClass->getConstructor(); if ($constructor) { $constructorParameters = $constructor->getParameters(); $params = array(); foreach ($constructorParameters as $constructorParameter) { $paramName = lcfirst($this->formatAttribute($constructorParameter->name)); if (isset($data[$paramName])) { $params[] = $data[$paramName]; // don't run set for a parameter passed to the constructor unset($data[$paramName]); } elseif (!$constructorParameter->isOptional()) { throw new RuntimeException( 'Cannot create an instance of '.$class. ' from serialized data because its constructor requires '. 'parameter "'.$constructorParameter->name. '" to be present.'); } } $object = $reflectionClass->newInstanceArgs($params); } else { $object = new $class; } foreach ($data as $attribute => $value) { $setter = 'set'.$this->formatAttribute($attribute); if (method_exists($object, $setter)) { $object->$setter($value); } } return $object; } /** * Format attribute name to access parameters or methods * As option, if attribute name is found on camelizedAttributes array * returns attribute name in camelcase format * * @param string $attributeName * @return string */ protected function formatAttribute($attributeName) { if (in_array($attributeName, $this->camelizedAttributes)) { return preg_replace_callback( '/(^|_|\.)+(.)/', function ($match) { return ('.' === $match[1] ? '_' : '').strtoupper($match[2]); }, $attributeName ); } return $attributeName; } /** * {@inheritDoc} */ public function supportsNormalization($data, $format = null) { return is_object($data) && $this->supports(get_class($data)); } /** * {@inheritDoc} */ public function supportsDenormalization($data, $type, $format = null) { return $this->supports($type); } /** * Checks if the given class has any get{Property} method. * * @param string $class * * @return Boolean */ private function supports($class) { $class = new \ReflectionClass($class); $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC); foreach ($methods as $method) { if ($this->isGetMethod($method)) { return true; } } return false; } /** * Checks if a method's name is get.* and can be called without parameters. * * @param \ReflectionMethod $method the method to check * * @return Boolean whether the method is a getter. */ private function isGetMethod(\ReflectionMethod $method) { return ( 0 === strpos($method->name, 'get') && 3 < strlen($method->name) && 0 === $method->getNumberOfRequiredParameters() ); } } PK!"pyy?Symfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * Defines the interface of normalizers. * * @author Jordi Boggiano */ interface NormalizerInterface { /** * Normalizes an object into a set of arrays/scalars * * @param object $object object to normalize * @param string $format format the normalization result will be encoded as * @param array $context Context options for the normalizer * * @return array|scalar */ public function normalize($object, $format = null, array $context = array()); /** * Checks whether the given class is supported for normalization by this normalizer * * @param mixed $data Data to normalize. * @param string $format The format being (de-)serialized from or into. * * @return Boolean */ public function supportsNormalization($data, $format = null); } PK!qUCSymfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * Defines the most basic interface a class must implement to be denormalizable * * If a denormalizer is registered for the class and it doesn't implement * the Denormalizable interfaces, the normalizer will be used instead * * @author Jordi Boggiano */ interface DenormalizableInterface { /** * Denormalizes the object back from an array of scalars|arrays. * * It is important to understand that the denormalize() call should denormalize * recursively all child objects of the implementor. * * @param DenormalizerInterface $denormalizer The denormalizer is given so that you * can use it to denormalize objects contained within this object. * @param array|scalar $data The data from which to re-create the object. * @param string|null $format The format is optionally given to be able to denormalize differently * based on different input formats. * @param array $context options for denormalizing */ public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array()); } PK!ASymfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Normalizer; /** * Defines the interface of denormalizers. * * @author Jordi Boggiano */ interface DenormalizerInterface { /** * Denormalizes data back into an object of the given class * * @param mixed $data data to restore * @param string $class the expected class to instantiate * @param string $format format the given data was extracted from * @param array $context options available to the denormalizer * * @return object */ public function denormalize($data, $class, $format = null, array $context = array()); /** * Checks whether the given class is supported for denormalization by this normalizer * * @param mixed $data Data to denormalize from. * @param string $type The class to which the data should be denormalized. * @param string $format The format being deserialized from. * * @return Boolean */ public function supportsDenormalization($data, $type, $format = null); } PK!OO9Symfony/Component/Serializer/SerializerAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer; /** * Defines the interface of encoders * * @author Jordi Boggiano */ interface SerializerAwareInterface { /** * Sets the owning Serializer object * * @param SerializerInterface $serializer */ public function setSerializer(SerializerInterface $serializer); } PK!TT+Symfony/Component/Serializer/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer; /** * Defines the interface of the Serializer * * @author Jordi Boggiano */ interface SerializerInterface { /** * Serializes data in the appropriate format * * @param mixed $data any data * @param string $format format name * @param array $context options normalizers/encoders have access to * * @return string */ public function serialize($data, $format, array $context = array()); /** * Deserializes data into the given type. * * @param mixed $data * @param string $type * @param string $format * @param array $context * * @return object */ public function deserialize($data, $type, $format, array $context = array()); } PK!,c9Symfony/Component/Serializer/Encoder/EncoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Defines the interface of encoders * * @author Jordi Boggiano */ interface EncoderInterface { /** * Encodes data into the given format * * @param mixed $data Data to encode * @param string $format Format name * @param array $context options that normalizers/encoders have access to. * * @return scalar */ public function encode($data, $format, array $context = array()); /** * Checks whether the serializer can encode to given format * * @param string $format format name * * @return Boolean */ public function supportsEncoding($format); } PK![553Symfony/Component/Serializer/Encoder/XmlEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; use Symfony\Component\Serializer\Exception\UnexpectedValueException; /** * Encodes XML data * * @author Jordi Boggiano * @author John Wards * @author Fabian Vogler */ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, DecoderInterface, NormalizationAwareInterface { private $dom; private $format; private $context; private $rootNodeName = 'response'; /** * Construct new XmlEncoder and allow to change the root node element name. * * @param string $rootNodeName */ public function __construct($rootNodeName = 'response') { $this->rootNodeName = $rootNodeName; } /** * {@inheritdoc} */ public function encode($data, $format, array $context = array()) { if ($data instanceof \DOMDocument) { return $data->saveXML(); } $xmlRootNodeName = $this->resolveXmlRootName($context); $this->dom = $this->createDomDocument($context); $this->format = $format; $this->context = $context; if (null !== $data && !is_scalar($data)) { $root = $this->dom->createElement($xmlRootNodeName); $this->dom->appendChild($root); $this->buildXml($root, $data, $xmlRootNodeName); } else { $this->appendNode($this->dom, $data, $xmlRootNodeName); } return $this->dom->saveXML(); } /** * {@inheritdoc} */ public function decode($data, $format, array $context = array()) { if ('' === trim($data)) { throw new UnexpectedValueException('Invalid XML data, it can not be empty.'); } $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); libxml_clear_errors(); $dom = new \DOMDocument(); $dom->loadXML($data, LIBXML_NONET); libxml_use_internal_errors($internalErrors); libxml_disable_entity_loader($disableEntities); if ($error = libxml_get_last_error()) { libxml_clear_errors(); throw new UnexpectedValueException($error->message); } foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { throw new UnexpectedValueException('Document types are not allowed.'); } } $xml = simplexml_import_dom($dom); if ($error = libxml_get_last_error()) { throw new UnexpectedValueException($error->message); } if (!$xml->count()) { if (!$xml->attributes()) { return (string) $xml; } $data = array(); foreach ($xml->attributes() as $attrkey => $attr) { $data['@'.$attrkey] = (string) $attr; } $data['#'] = (string) $xml; return $data; } return $this->parseXml($xml); } /** * {@inheritdoc} */ public function supportsEncoding($format) { return 'xml' === $format; } /** * {@inheritdoc} */ public function supportsDecoding($format) { return 'xml' === $format; } /** * Sets the root node name * * @param string $name root node name */ public function setRootNodeName($name) { $this->rootNodeName = $name; } /** * Returns the root node name * @return string */ public function getRootNodeName() { return $this->rootNodeName; } /** * @param \DOMNode $node * @param string $val * * @return Boolean */ final protected function appendXMLString(\DOMNode $node, $val) { if (strlen($val) > 0) { $frag = $this->dom->createDocumentFragment(); $frag->appendXML($val); $node->appendChild($frag); return true; } return false; } /** * @param \DOMNode $node * @param string $val * * @return Boolean */ final protected function appendText(\DOMNode $node, $val) { $nodeText = $this->dom->createTextNode($val); $node->appendChild($nodeText); return true; } /** * @param \DOMNode $node * @param string $val * * @return Boolean */ final protected function appendCData(\DOMNode $node, $val) { $nodeText = $this->dom->createCDATASection($val); $node->appendChild($nodeText); return true; } /** * @param \DOMNode $node * @param \DOMDocumentFragment $fragment * * @return Boolean */ final protected function appendDocumentFragment(\DOMNode $node, $fragment) { if ($fragment instanceof \DOMDocumentFragment) { $node->appendChild($fragment); return true; } return false; } /** * Checks the name is a valid xml element name * * @param string $name * * @return Boolean */ final protected function isElementNameValid($name) { return $name && false === strpos($name, ' ') && preg_match('#^[\pL_][\pL0-9._-]*$#ui', $name); } /** * Parse the input SimpleXmlElement into an array. * * @param \SimpleXmlElement $node xml to parse * * @return array */ private function parseXml(\SimpleXmlElement $node) { $data = array(); if ($node->attributes()) { foreach ($node->attributes() as $attrkey => $attr) { $data['@'.$attrkey] = (string) $attr; } } foreach ($node->children() as $key => $subnode) { if ($subnode->count()) { $value = $this->parseXml($subnode); } elseif ($subnode->attributes()) { $value = array(); foreach ($subnode->attributes() as $attrkey => $attr) { $value['@'.$attrkey] = (string) $attr; } $value['#'] = (string) $subnode; } else { $value = (string) $subnode; } if ($key === 'item') { if (isset($value['@key'])) { if (isset($value['#'])) { $data[$value['@key']] = $value['#']; } else { $data[$value['@key']] = $value; } } else { $data['item'][] = $value; } } elseif (array_key_exists($key, $data) || $key == "entry") { if ((false === is_array($data[$key])) || (false === isset($data[$key][0]))) { $data[$key] = array($data[$key]); } $data[$key][] = $value; } else { $data[$key] = $value; } } return $data; } /** * Parse the data and convert it to DOMElements * * @param \DOMNode $parentNode * @param array|object $data * @param string|null $xmlRootNodeName * * @return Boolean * * @throws UnexpectedValueException */ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) { $append = true; if (is_array($data) || $data instanceof \Traversable) { foreach ($data as $key => $data) { //Ah this is the magic @ attribute types. if (0 === strpos($key, "@") && is_scalar($data) && $this->isElementNameValid($attributeName = substr($key, 1))) { $parentNode->setAttribute($attributeName, $data); } elseif ($key === '#') { $append = $this->selectNodeType($parentNode, $data); } elseif (is_array($data) && false === is_numeric($key)) { /** * Is this array fully numeric keys? */ if (ctype_digit(implode('', array_keys($data)))) { /** * Create nodes to append to $parentNode based on the $key of this array * Produces 01 * From array("item" => array(0,1)); */ foreach ($data as $subData) { $append = $this->appendNode($parentNode, $subData, $key); } } else { $append = $this->appendNode($parentNode, $data, $key); } } elseif (is_numeric($key) || !$this->isElementNameValid($key)) { $append = $this->appendNode($parentNode, $data, "item", $key); } else { $append = $this->appendNode($parentNode, $data, $key); } } return $append; } if (is_object($data)) { $data = $this->serializer->normalize($data, $this->format, $this->context); if (null !== $data && !is_scalar($data)) { return $this->buildXml($parentNode, $data, $xmlRootNodeName); } // top level data object was normalized into a scalar if (!$parentNode->parentNode->parentNode) { $root = $parentNode->parentNode; $root->removeChild($parentNode); return $this->appendNode($root, $data, $xmlRootNodeName); } return $this->appendNode($parentNode, $data, 'data'); } throw new UnexpectedValueException(sprintf('An unexpected value could not be serialized: %s', var_export($data, true))); } /** * Selects the type of node to create and appends it to the parent. * * @param \DOMNode $parentNode * @param array|object $data * @param string $nodeName * @param string $key * * @return Boolean */ private function appendNode(\DOMNode $parentNode, $data, $nodeName, $key = null) { $node = $this->dom->createElement($nodeName); if (null !== $key) { $node->setAttribute('key', $key); } $appendNode = $this->selectNodeType($node, $data); // we may have decided not to append this node, either in error or if its $nodeName is not valid if ($appendNode) { $parentNode->appendChild($node); } return $appendNode; } /** * Checks if a value contains any characters which would require CDATA wrapping. * * @param string $val * * @return Boolean */ private function needsCdataWrapping($val) { return preg_match('/[<>&]/', $val); } /** * Tests the value being passed and decide what sort of element to create * * @param \DOMNode $node * @param mixed $val * * @return Boolean */ private function selectNodeType(\DOMNode $node, $val) { if (is_array($val)) { return $this->buildXml($node, $val); } elseif ($val instanceof \SimpleXMLElement) { $child = $this->dom->importNode(dom_import_simplexml($val), true); $node->appendChild($child); } elseif ($val instanceof \Traversable) { $this->buildXml($node, $val); } elseif (is_object($val)) { return $this->buildXml($node, $this->serializer->normalize($val, $this->format, $this->context)); } elseif (is_numeric($val)) { return $this->appendText($node, (string) $val); } elseif (is_string($val) && $this->needsCdataWrapping($val)) { return $this->appendCData($node, $val); } elseif (is_string($val)) { return $this->appendText($node, $val); } elseif (is_bool($val)) { return $this->appendText($node, (int) $val); } elseif ($val instanceof \DOMNode) { $child = $this->dom->importNode($val, true); $node->appendChild($child); } return true; } /** * Get real XML root node name, taking serializer options into account. */ private function resolveXmlRootName(array $context = array()) { return isset($context['xml_root_node_name']) ? $context['xml_root_node_name'] : $this->rootNodeName; } /** * Create a DOM document, taking serializer options into account. * * @param array $context options that the encoder has access to. * * @return \DOMDocument */ private function createDomDocument(array $context) { $document = new \DOMDocument(); // Set an attribute on the DOM document specifying, as part of the XML declaration, $xmlOptions = array( // the version number of the document 'xml_version' => 'xmlVersion', // the encoding of the document 'xml_encoding' => 'encoding', // whether the document is standalone 'xml_standalone' => 'xmlStandalone', ); foreach ($xmlOptions as $xmlOption => $documentProperty) { if (isset($context[$xmlOption])) { $document->$documentProperty = $context[$xmlOption]; } } return $document; } } PK!<=ggDSymfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Defines the interface of encoders that will normalize data themselves * * Implementing this interface essentially just tells the Serializer that the * data should not be pre-normalized before being passed to this Encoder. * * @author Jordi Boggiano */ interface NormalizationAwareInterface { } PK!VO5Symfony/Component/Serializer/Encoder/ChainDecoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; use Symfony\Component\Serializer\Exception\RuntimeException; /** * Decoder delegating the decoding to a chain of decoders. * * @author Jordi Boggiano * @author Johannes M. Schmitt * @author Lukas Kahwe Smith */ class ChainDecoder implements DecoderInterface { protected $decoders = array(); protected $decoderByFormat = array(); public function __construct(array $decoders = array()) { $this->decoders = $decoders; } /** * {@inheritdoc} */ final public function decode($data, $format, array $context = array()) { return $this->getDecoder($format)->decode($data, $format, $context); } /** * {@inheritdoc} */ public function supportsDecoding($format) { try { $this->getDecoder($format); } catch (RuntimeException $e) { return false; } return true; } /** * Gets the decoder supporting the format. * * @param string $format * * @return DecoderInterface * @throws RuntimeException if no decoder is found */ private function getDecoder($format) { if (isset($this->decoderByFormat[$format]) && isset($this->decoders[$this->decoderByFormat[$format]]) ) { return $this->decoders[$this->decoderByFormat[$format]]; } foreach ($this->decoders as $i => $decoder) { if ($decoder->supportsDecoding($format)) { $this->decoderByFormat[$format] = $i; return $decoder; } } throw new RuntimeException(sprintf('No decoder found for format "%s".', $format)); } } PK!=?Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\SerializerAwareInterface; /** * SerializerAware Encoder implementation * * @author Jordi Boggiano */ abstract class SerializerAwareEncoder implements SerializerAwareInterface { protected $serializer; /** * {@inheritdoc} */ public function setSerializer(SerializerInterface $serializer) { $this->serializer = $serializer; } } PK!v:hh3Symfony/Component/Serializer/Encoder/JsonEncode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Encodes JSON data * * @author Sander Coolen */ class JsonEncode implements EncoderInterface { private $options ; private $lastError = JSON_ERROR_NONE; public function __construct($bitmask = 0) { $this->options = $bitmask; } /** * Returns the last encoding error (if any) * * @return integer * * @see http://php.net/manual/en/function.json-last-error.php json_last_error */ public function getLastError() { return $this->lastError; } /** * Encodes PHP data to a JSON string * * {@inheritdoc} */ public function encode($data, $format, array $context = array()) { $context = $this->resolveContext($context); $encodedJson = json_encode($data, $context['json_encode_options']); $this->lastError = json_last_error(); return $encodedJson; } /** * {@inheritdoc} */ public function supportsEncoding($format) { return JsonEncoder::FORMAT === $format; } /** * Merge default json encode options with context. * * @param array $context * @return array */ private function resolveContext(array $context = array()) { return array_merge(array('json_encode_options' => $this->options), $context); } } PK!@3Symfony/Component/Serializer/Encoder/JsonDecode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Decodes JSON data * * @author Sander Coolen */ class JsonDecode implements DecoderInterface { /** * Specifies if the returned result should be an associative array or a nested stdClass object hierarchy. * * @var Boolean */ private $associative; /** * Specifies the recursion depth. * * @var integer */ private $recursionDepth; private $lastError = JSON_ERROR_NONE; protected $serializer; /** * Constructs a new JsonDecode instance. * * @param Boolean $associative True to return the result associative array, false for a nested stdClass hierarchy * @param integer $depth Specifies the recursion depth */ public function __construct($associative = false, $depth = 512) { $this->associative = $associative; $this->recursionDepth = (int) $depth; } /** * Returns the last decoding error (if any). * * @return integer * * @see http://php.net/manual/en/function.json-last-error.php json_last_error */ public function getLastError() { return $this->lastError; } /** * Decodes data. * * @param string $data The encoded JSON string to decode * @param string $format Must be set to JsonEncoder::FORMAT * @param array $context An optional set of options for the JSON decoder; see below * * The $context array is a simple key=>value array, with the following supported keys: * * json_decode_associative: boolean * If true, returns the object as associative array. * If false, returns the object as nested stdClass * If not specified, this method will use the default set in JsonDecode::__construct * * json_decode_recursion_depth: integer * Specifies the maximum recursion depth * If not specified, this method will use the default set in JsonDecode::__construct * * json_decode_options: integer * Specifies additional options as per documentation for json_decode. Only supported with PHP 5.4.0 and higher * * @return mixed * * @see http://php.net/json_decode json_decode */ public function decode($data, $format, array $context = array()) { $context = $this->resolveContext($context); $associative = $context['json_decode_associative']; $recursionDepth = $context['json_decode_recursion_depth']; $options = $context['json_decode_options']; if (version_compare(PHP_VERSION, '5.4.0') >= 0) { $decodedData = json_decode($data, $associative, $recursionDepth, $options); } else { $decodedData = json_decode($data, $associative, $recursionDepth); } $this->lastError = json_last_error(); return $decodedData; } /** * {@inheritdoc} */ public function supportsDecoding($format) { return JsonEncoder::FORMAT === $format; } /** * Merges the default options of the Json Decoder with the passed context. * * @param array $context * * @return array */ private function resolveContext(array $context) { $defaultOptions = array( 'json_decode_associative' => $this->associative, 'json_decode_recursion_depth' => $this->recursionDepth, 'json_decode_options' => 0 ); return array_merge($defaultOptions, $context); } } PK!S R 5Symfony/Component/Serializer/Encoder/ChainEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; use Symfony\Component\Serializer\Exception\RuntimeException; /** * Encoder delegating the decoding to a chain of encoders. * * @author Jordi Boggiano * @author Johannes M. Schmitt * @author Lukas Kahwe Smith */ class ChainEncoder implements EncoderInterface { protected $encoders = array(); protected $encoderByFormat = array(); public function __construct(array $encoders = array()) { $this->encoders = $encoders; } /** * {@inheritdoc} */ final public function encode($data, $format, array $context = array()) { return $this->getEncoder($format)->encode($data, $format, $context); } /** * {@inheritdoc} */ public function supportsEncoding($format) { try { $this->getEncoder($format); } catch (RuntimeException $e) { return false; } return true; } /** * Checks whether the normalization is needed for the given format. * * @param string $format * * @return Boolean */ public function needsNormalization($format) { $encoder = $this->getEncoder($format); if (!$encoder instanceof NormalizationAwareInterface) { return true; } if ($encoder instanceof self) { return $encoder->needsNormalization($format); } return false; } /** * Gets the encoder supporting the format. * * @param string $format * * @return EncoderInterface * @throws RuntimeException if no encoder is found */ private function getEncoder($format) { if (isset($this->encoderByFormat[$format]) && isset($this->encoders[$this->encoderByFormat[$format]]) ) { return $this->encoders[$this->encoderByFormat[$format]]; } foreach ($this->encoders as $i => $encoder) { if ($encoder->supportsEncoding($format)) { $this->encoderByFormat[$format] = $i; return $encoder; } } throw new RuntimeException(sprintf('No encoder found for format "%s".', $format)); } } PK! ovv4Symfony/Component/Serializer/Encoder/JsonEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Encodes JSON data * * @author Jordi Boggiano */ class JsonEncoder implements EncoderInterface, DecoderInterface { const FORMAT = 'json'; /** * @var JsonEncode */ protected $encodingImpl; /** * @var JsonDecode */ protected $decodingImpl; public function __construct(JsonEncode $encodingImpl = null, JsonDecode $decodingImpl = null) { $this->encodingImpl = $encodingImpl ?: new JsonEncode(); $this->decodingImpl = $decodingImpl ?: new JsonDecode(true); } /** * Returns the last encoding error (if any) * * @return integer */ public function getLastEncodingError() { return $this->encodingImpl->getLastError(); } /** * Returns the last decoding error (if any) * * @return integer */ public function getLastDecodingError() { return $this->decodingImpl->getLastError(); } /** * {@inheritdoc} */ public function encode($data, $format, array $context = array()) { return $this->encodingImpl->encode($data, self::FORMAT, $context); } /** * {@inheritdoc} */ public function decode($data, $format, array $context = array()) { return $this->decodingImpl->decode($data, self::FORMAT, $context); } /** * {@inheritdoc} */ public function supportsEncoding($format) { return self::FORMAT === $format; } /** * {@inheritdoc} */ public function supportsDecoding($format) { return self::FORMAT === $format; } } PK!|ͼ9Symfony/Component/Serializer/Encoder/DecoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Encoder; /** * Defines the interface of decoders * * @author Jordi Boggiano */ interface DecoderInterface { /** * Decodes a string into PHP data. * * @param scalar $data Data to decode * @param string $format Format name * @param array $context options that decoders have access to. * * The format parameter specifies which format the data is in; valid values * depend on the specific implementation. Authors implementing this interface * are encouraged to document which formats they support in a non-inherited * phpdoc comment. * * @return mixed */ public function decode($data, $format, array $context = array()); /** * Checks whether the deserializer can decode from given format. * * @param string $format format name * * @return Boolean */ public function supportsDecoding($format); } PK!AA 4Symfony/Component/Serializer/Exception/Exception.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * Base exception * * @author Johannes M. Schmitt */ interface Exception { } PK!^L?Symfony/Component/Serializer/Exception/UnsupportedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * UnsupportedException * * @author Johannes M. Schmitt */ class UnsupportedException extends InvalidArgumentException { } PK!h=;Symfony/Component/Serializer/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * RuntimeException * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements Exception { } PK!J9Symfony/Component/Serializer/Exception/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * LogicException * * @author Lukas Kahwe Smith */ class LogicException extends \LogicException implements Exception { } PK!TYCSymfony/Component/Serializer/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * InvalidArgumentException * * @author Johannes M. Schmitt */ class InvalidArgumentException extends \InvalidArgumentException implements Exception { } PK![CSymfony/Component/Serializer/Exception/UnexpectedValueException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer\Exception; /** * UnexpectedValueException * * @author Lukas Kahwe Smith */ class UnexpectedValueException extends \UnexpectedValueException implements Exception { } PK!ʪ2 /&/&+Symfony/Component/Serializer/Serializer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Serializer; use Symfony\Component\Serializer\Encoder\ChainDecoder; use Symfony\Component\Serializer\Encoder\ChainEncoder; use Symfony\Component\Serializer\Encoder\EncoderInterface; use Symfony\Component\Serializer\Encoder\DecoderInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; /** * Serializer serializes and deserializes data * * objects are turned into arrays by normalizers * arrays are turned into various output formats by encoders * * $serializer->serialize($obj, 'xml') * $serializer->decode($data, 'xml') * $serializer->denormalize($data, 'Class', 'xml') * * @author Jordi Boggiano * @author Johannes M. Schmitt * @author Lukas Kahwe Smith */ class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface { protected $encoder; protected $decoder; protected $normalizers = array(); protected $normalizerCache = array(); protected $denormalizerCache = array(); public function __construct(array $normalizers = array(), array $encoders = array()) { foreach ($normalizers as $normalizer) { if ($normalizer instanceof SerializerAwareInterface) { $normalizer->setSerializer($this); } } $this->normalizers = $normalizers; $decoders = array(); $realEncoders = array(); foreach ($encoders as $encoder) { if ($encoder instanceof SerializerAwareInterface) { $encoder->setSerializer($this); } if ($encoder instanceof DecoderInterface) { $decoders[] = $encoder; } if ($encoder instanceof EncoderInterface) { $realEncoders[] = $encoder; } } $this->encoder = new ChainEncoder($realEncoders); $this->decoder = new ChainDecoder($decoders); } /** * {@inheritdoc} */ final public function serialize($data, $format, array $context = array()) { if (!$this->supportsEncoding($format)) { throw new UnexpectedValueException(sprintf('Serialization for the format %s is not supported', $format)); } if ($this->encoder->needsNormalization($format)) { $data = $this->normalize($data, $format, $context); } return $this->encode($data, $format, $context); } /** * {@inheritdoc} */ final public function deserialize($data, $type, $format, array $context = array()) { if (!$this->supportsDecoding($format)) { throw new UnexpectedValueException(sprintf('Deserialization for the format %s is not supported', $format)); } $data = $this->decode($data, $format, $context); return $this->denormalize($data, $type, $format, $context); } /** * {@inheritdoc} */ public function normalize($data, $format = null, array $context = array()) { if (null === $data || is_scalar($data)) { return $data; } if (is_object($data) && $this->supportsNormalization($data, $format)) { return $this->normalizeObject($data, $format, $context); } if ($data instanceof \Traversable) { $normalized = array(); foreach ($data as $key => $val) { $normalized[$key] = $this->normalize($val, $format, $context); } return $normalized; } if (is_object($data)) { return $this->normalizeObject($data, $format, $context); } if (is_array($data)) { foreach ($data as $key => $val) { $data[$key] = $this->normalize($val, $format, $context); } return $data; } throw new UnexpectedValueException(sprintf('An unexpected value could not be normalized: %s', var_export($data, true))); } /** * {@inheritdoc} */ public function denormalize($data, $type, $format = null, array $context = array()) { return $this->denormalizeObject($data, $type, $format, $context); } /** * {@inheritdoc} */ public function supportsNormalization($data, $format = null) { try { $this->getNormalizer($data, $format); } catch (RuntimeException $e) { return false; } return true; } /** * {@inheritdoc} */ public function supportsDenormalization($data, $type, $format = null) { try { $this->getDenormalizer($data, $type, $format = null); } catch (RuntimeException $e) { return false; } return true; } /** * {@inheritdoc} */ private function getNormalizer($data, $format = null) { foreach ($this->normalizers as $normalizer) { if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($data, $format)) { return $normalizer; } } throw new RuntimeException(sprintf('No normalizer found for format "%s".', $format)); } /** * {@inheritdoc} */ private function getDenormalizer($data, $type, $format = null) { foreach ($this->normalizers as $normalizer) { if ($normalizer instanceof DenormalizerInterface && $normalizer->supportsDenormalization($data, $type, $format)) { return $normalizer; } } throw new RuntimeException(sprintf('No denormalizer found for format "%s".', $format)); } /** * {@inheritdoc} */ final public function encode($data, $format, array $context = array()) { return $this->encoder->encode($data, $format, $context); } /** * {@inheritdoc} */ final public function decode($data, $format, array $context = array()) { return $this->decoder->decode($data, $format, $context); } /** * Normalizes an object into a set of arrays/scalars * * @param object $object object to normalize * @param string $format format name, present to give the option to normalizers to act differently based on formats * @param array $context The context data for this particular normalization * * @return array|scalar * * @throws LogicException * @throws UnexpectedValueException */ private function normalizeObject($object, $format = null, array $context = array()) { if (!$this->normalizers) { throw new LogicException('You must register at least one normalizer to be able to normalize objects.'); } $class = get_class($object); if (isset($this->normalizerCache[$class][$format])) { return $this->normalizerCache[$class][$format]->normalize($object, $format, $context); } foreach ($this->normalizers as $normalizer) { if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($object, $format)) { $this->normalizerCache[$class][$format] = $normalizer; return $normalizer->normalize($object, $format, $context); } } throw new UnexpectedValueException(sprintf('Could not normalize object of type %s, no supporting normalizer found.', $class)); } /** * Denormalizes data back into an object of the given class * * @param mixed $data data to restore * @param string $class the expected class to instantiate * @param string $format format name, present to give the option to normalizers to act differently based on formats * @param array $context The context data for this particular denormalization * * @return object * * @throws LogicException * @throws UnexpectedValueException */ private function denormalizeObject($data, $class, $format = null, array $context = array()) { if (!$this->normalizers) { throw new LogicException('You must register at least one normalizer to be able to denormalize objects.'); } if (isset($this->denormalizerCache[$class][$format])) { return $this->denormalizerCache[$class][$format]->denormalize($data, $class, $format, $context); } foreach ($this->normalizers as $normalizer) { if ($normalizer instanceof DenormalizerInterface && $normalizer->supportsDenormalization($data, $class, $format)) { $this->denormalizerCache[$class][$format] = $normalizer; return $normalizer->denormalize($data, $class, $format, $context); } } throw new UnexpectedValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $class)); } /** * {@inheritdoc} */ public function supportsEncoding($format) { return $this->encoder->supportsEncoding($format); } /** * {@inheritdoc} */ public function supportsDecoding($format) { return $this->decoder->supportsDecoding($format); } } PK!FPPP'Symfony/Component/Locale/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Exception; use Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException as BaseMethodArgumentNotImplementedException; /** * Alias of {@link \Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Exception\MethodArgumentNotImplementedException} * instead. */ class MethodArgumentNotImplementedException extends BaseMethodArgumentNotImplementedException { } PK! E>Symfony/Component/Locale/Exception/NotImplementedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Exception; use Symfony\Component\Intl\Exception\NotImplementedException as BaseNotImplementedException; /** * Alias of {@link \Symfony\Component\Intl\Exception\NotImplementedException}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Exception\NotImplementedException} * instead. */ class NotImplementedException extends BaseNotImplementedException { } PK!S?a%%DSymfony/Component/Locale/Exception/MethodNotImplementedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Exception; use Symfony\Component\Intl\Exception\MethodNotImplementedException as BaseMethodNotImplementedException; /** * Alias of {@link \Symfony\Component\Intl\Exception\MethodNotImplementedException}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Exception\MethodNotImplementedException} * instead. */ class MethodNotImplementedException extends BaseMethodNotImplementedException { } PK!ssQSymfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Exception; use Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException as BaseMethodArgumentValueNotImplementedException; /** * Alias of {@link \Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException} * instead. */ class MethodArgumentValueNotImplementedException extends BaseMethodArgumentValueNotImplementedException { } PK!C*Symfony/Component/Locale/Stub/StubIntl.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Intl\Globals\IntlGlobals; /** * Alias of {@link \Symfony\Component\Intl\Globals\IntlGlobals}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Globals\IntlGlobals} instead. */ abstract class StubIntl extends IntlGlobals { } PK!&5Symfony/Component/Locale/Stub/StubNumberFormatter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Intl\NumberFormatter\NumberFormatter; /** * Alias of {@link \Symfony\Component\Intl\NumberFormatter\NumberFormatter}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\NumberFormatter\NumberFormatter} * instead. */ class StubNumberFormatter extends NumberFormatter { } PK!v/@Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Hour2401Transformer as BaseHour2401Transformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2401Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2401Transformer} * instead. */ class Hour2401Transformer extends BaseHour2401Transformer { } PK!S@Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\TimeZoneTransformer as BaseTimeZoneTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\TimeZoneTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\TimeZoneTransformer} * instead. */ class TimeZoneTransformer extends BaseTimeZoneTransformer { } PK!} ""ASymfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\DayOfYearTransformer as BaseDayOfYearTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfYearTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfYearTransformer} * instead. */ class DayOfYearTransformer extends BaseDayOfYearTransformer { } PK!X<Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\AmPmTransformer as BaseAmPmTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\AmPmTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\AmPmTransformer} * instead. */ class AmPmTransformer extends BaseAmPmTransformer { } PK!<Symfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\YearTransformer as BaseYearTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\YearTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\YearTransformer} * instead. */ class YearTransformer extends BaseYearTransformer { } PK!mў?Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\QuarterTransformer as BaseQuarterTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\QuarterTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\QuarterTransformer} * instead. */ class QuarterTransformer extends BaseQuarterTransformer { } PK!g[ep>Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\MinuteTransformer as BaseMinuteTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MinuteTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MinuteTransformer} * instead. */ class MinuteTransformer extends BaseMinuteTransformer { } PK!:6""ASymfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\DayOfWeekTransformer as BaseDayOfWeekTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfWeekTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayOfWeekTransformer} * instead. */ class DayOfWeekTransformer extends BaseDayOfWeekTransformer { } PK! 9u@Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Hour1200Transformer as BaseHour1200Transformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1200Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1200Transformer} * instead. */ class Hour1200Transformer extends BaseHour1200Transformer { } PK!k&"M@Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Hour1201Transformer as BaseHour1201Transformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1201Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour1201Transformer} * instead. */ class Hour1201Transformer extends BaseHour1201Transformer { } PK!;Symfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\DayTransformer as BaseDayTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\DayTransformer} * instead. */ class DayTransformer extends BaseDayTransformer { } PK!@Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Hour2400Transformer as BaseHour2400Transformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2400Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Hour2400Transformer} * instead. */ class Hour2400Transformer extends BaseHour2400Transformer { } PK!Ed8Symfony/Component/Locale/Stub/DateFormat/Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\Transformer as BaseTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Transformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\Transformer} * instead. */ abstract class Transformer extends BaseTransformer { } PK!tz  =Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer as BaseMonthTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\MonthTransformer} * instead. */ class MonthTransformer extends BaseMonthTransformer { } PK!kH<Symfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer as BaseFullTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\FullTransformer} * instead. */ class FullTransformer extends BaseFullTransformer { } PK!3X>Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\SecondTransformer as BaseSecondTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\SecondTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\SecondTransformer} * instead. */ class SecondTransformer extends BaseSecondTransformer { } PK!   <Symfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub\DateFormat; use Symfony\Component\Intl\DateFormatter\DateFormat\HourTransformer as BaseHourTransformer; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\DateFormat\HourTransformer}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\DateFormat\HourTransformer} * instead. */ abstract class HourTransformer extends BaseHourTransformer { } PK!?.Symfony/Component/Locale/Stub/StubCollator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Intl\Collator\Collator; /** * Alias of {@link \Symfony\Component\Intl\Collator\Collator}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Collator\Collator} instead. */ class StubCollator extends Collator { } PK!q*( ( ,Symfony/Component/Locale/Stub/StubLocale.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Icu\IcuData; use Symfony\Component\Intl\Intl; use Symfony\Component\Intl\Locale\Locale; /** * Alias of {@link \Symfony\Component\Intl\Locale\Locale}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\Locale\Locale} and * {@link \Symfony\Component\Intl\Intl} instead. */ class StubLocale extends Locale { /** * Caches the currencies * * @var array */ protected static $currencies; /** * Caches the currencies names * * @var array */ protected static $currenciesNames; /** * Returns the currencies data * * @param string $locale * * @return array The currencies data */ public static function getCurrenciesData($locale) { if (null === self::$currencies) { self::prepareCurrencies($locale); } return self::$currencies; } /** * Returns the currencies names for a locale * * @param string $locale The locale to use for the currencies names * * @return array The currencies names with their codes as keys * * @throws \InvalidArgumentException When the locale is different than 'en' */ public static function getDisplayCurrencies($locale) { if (null === self::$currenciesNames) { self::prepareCurrencies($locale); } return self::$currenciesNames; } /** * Returns all available currencies codes * * @return array The currencies codes */ public static function getCurrencies() { return array_keys(self::getCurrenciesData(self::getDefault())); } public static function getDataDirectory() { return IcuData::getResourceDirectory(); } private static function prepareCurrencies($locale) { self::$currencies = array(); self::$currenciesNames = array(); $bundle = Intl::getCurrencyBundle(); foreach ($bundle->getCurrencyNames($locale) as $currency => $name) { self::$currencies[$currency] = array( 'name' => $name, 'symbol' => $bundle->getCurrencySymbol($currency, $locale), 'fractionDigits' => $bundle->getFractionDigits($currency), 'roundingIncrement' => $bundle->getRoundingIncrement($currency) ); self::$currenciesNames[$currency] = $name; } } } PK! S7Symfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale\Stub; use Symfony\Component\Intl\DateFormatter\IntlDateFormatter; /** * Alias of {@link \Symfony\Component\Intl\DateFormatter\IntlDateFormatter}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Intl\DateFormatter\IntlDateFormatter} * instead. */ class StubIntlDateFormatter extends IntlDateFormatter { } PK!ll#Symfony/Component/Locale/Locale.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Locale; use Symfony\Component\Icu\IcuData; use Symfony\Component\Intl\Intl; /** * Helper class for dealing with locale strings. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link \Locale} and {@link \Symfony\Component\Intl\Intl} instead. */ class Locale extends \Locale { /** * Caches the countries in different locales * @var array */ protected static $countries = array(); /** * Caches the languages in different locales * @var array */ protected static $languages = array(); /** * Caches the different locales * @var array */ protected static $locales = array(); /** * Returns the country names for a locale * * @param string $locale The locale to use for the country names * * @return array The country names with their codes as keys * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getDisplayCountries($locale) { if (!isset(self::$countries[$locale])) { self::$countries[$locale] = Intl::getRegionBundle()->getCountryNames($locale); } return self::$countries[$locale]; } /** * Returns all available country codes * * @return array The country codes * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getCountries() { return array_keys(self::getDisplayCountries(self::getDefault())); } /** * Returns the language names for a locale * * @param string $locale The locale to use for the language names * * @return array The language names with their codes as keys * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getDisplayLanguages($locale) { if (!isset(self::$languages[$locale])) { self::$languages[$locale] = Intl::getLanguageBundle()->getLanguageNames($locale); } return self::$languages[$locale]; } /** * Returns all available language codes * * @return array The language codes * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getLanguages() { return array_keys(self::getDisplayLanguages(self::getDefault())); } /** * Returns the locale names for a locale * * @param string $locale The locale to use for the locale names * * @return array The locale names with their codes as keys * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getDisplayLocales($locale) { if (!isset(self::$locales[$locale])) { self::$locales[$locale] = Intl::getLocaleBundle()->getLocaleNames($locale); } return self::$locales[$locale]; } /** * Returns all available locale codes * * @return array The locale codes * * @throws \RuntimeException When the resource bundles cannot be loaded */ public static function getLocales() { return array_keys(self::getDisplayLocales(self::getDefault())); } /** * Returns the ICU version as defined by the intl extension * * @return string|null The ICU version */ public static function getIntlIcuVersion() { return Intl::getIcuVersion(); } /** * Returns the ICU Data version as defined by the intl extension * * @return string|null The ICU Data version */ public static function getIntlIcuDataVersion() { return Intl::getIcuDataVersion(); } /** * Returns the ICU data version that ships with Symfony. If the environment variable USE_INTL_ICU_DATA_VERSION is * defined, it will try use the ICU data version as defined by the intl extension, if available. * * @return string The ICU data version that ships with Symfony */ public static function getIcuDataVersion() { return Intl::getIcuDataVersion(); } /** * Returns the directory path of the ICU data that ships with Symfony * * @return string The path to the ICU data directory */ public static function getIcuDataDirectory() { return IcuData::getResourceDirectory(); } /** * Returns the fallback locale for a given locale, if any * * @param string $locale The locale to find the fallback for. * * @return string|null The fallback locale, or null if no parent exists */ protected static function getFallbackLocale($locale) { if (false === $pos = strrpos($locale, '_')) { return null; } return substr($locale, 0, $pos); } } PK!tTT+Symfony/Component/Filesystem/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * Exception class thrown when a file couldn't be found * * @author Fabien Potencier * @author Christian Gärtner */ class FileNotFoundException extends IOException { public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null) { if (null === $message) { if (null === $path) { $message = 'File could not be found.'; } else { $message = sprintf('File "%s" could not be found.', $path); } } parent::__construct($message, $code, $previous, $path); } } PK!3{=Symfony/Component/Filesystem/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Romain Neutron * * @api */ interface ExceptionInterface { } PK!oC~?Symfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * IOException interface for file and input/output stream related exceptions thrown by the component. * * @author Christian Gärtner */ interface IOExceptionInterface extends ExceptionInterface { /** * Returns the associated path for the exception * * @return string The path. */ public function getPath(); } PK!;{6Symfony/Component/Filesystem/Exception/IOException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * Exception class thrown when a filesystem operation failure happens * * @author Romain Neutron * @author Christian Gärtner * @author Fabien Potencier * * @api */ class IOException extends \RuntimeException implements IOExceptionInterface { private $path; public function __construct($message, $code = 0, \Exception $previous = null, $path = null) { $this->path = $path; parent::__construct($message, $code, $previous); } /** * {@inheritdoc} */ public function getPath() { return $this->path; } } PK!OظGG+Symfony/Component/Filesystem/Filesystem.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Exception\FileNotFoundException; /** * Provides basic utility to manipulate the file system. * * @author Fabien Potencier */ class Filesystem { /** * Copies a file. * * This method only copies the file if the origin file is newer than the target file. * * By default, if the target already exists, it is not overridden. * * @param string $originFile The original filename * @param string $targetFile The target filename * @param boolean $override Whether to override an existing file or not * * @throws FileNotFoundException When originFile doesn't exist * @throws IOException When copy fails */ public function copy($originFile, $targetFile, $override = false) { if (stream_is_local($originFile) && !is_file($originFile)) { throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile); } $this->mkdir(dirname($targetFile)); if (!$override && is_file($targetFile) && null === parse_url($originFile, PHP_URL_HOST)) { $doCopy = filemtime($originFile) > filemtime($targetFile); } else { $doCopy = true; } if ($doCopy) { // https://bugs.php.net/bug.php?id=64634 $source = fopen($originFile, 'r'); $target = fopen($targetFile, 'w'); stream_copy_to_stream($source, $target); fclose($source); fclose($target); unset($source, $target); if (!is_file($targetFile)) { throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile); } } } /** * Creates a directory recursively. * * @param string|array|\Traversable $dirs The directory path * @param integer $mode The directory mode * * @throws IOException On any directory creation failure */ public function mkdir($dirs, $mode = 0777) { foreach ($this->toIterator($dirs) as $dir) { if (is_dir($dir)) { continue; } if (true !== @mkdir($dir, $mode, true)) { throw new IOException(sprintf('Failed to create "%s".', $dir), 0, null, $dir); } } } /** * Checks the existence of files or directories. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check * * @return Boolean true if the file exists, false otherwise */ public function exists($files) { foreach ($this->toIterator($files) as $file) { if (!file_exists($file)) { return false; } } return true; } /** * Sets access and modification time of file. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create * @param integer $time The touch time as a Unix timestamp * @param integer $atime The access time as a Unix timestamp * * @throws IOException When touch fails */ public function touch($files, $time = null, $atime = null) { foreach ($this->toIterator($files) as $file) { $touch = $time ? @touch($file, $time, $atime) : @touch($file); if (true !== $touch) { throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file); } } } /** * Removes files or directories. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove * * @throws IOException When removal fails */ public function remove($files) { $files = iterator_to_array($this->toIterator($files)); $files = array_reverse($files); foreach ($files as $file) { if (!file_exists($file) && !is_link($file)) { continue; } if (is_dir($file) && !is_link($file)) { $this->remove(new \FilesystemIterator($file)); if (true !== @rmdir($file)) { throw new IOException(sprintf('Failed to remove directory "%s".', $file), 0, null, $file); } } else { // https://bugs.php.net/bug.php?id=52176 if (defined('PHP_WINDOWS_VERSION_MAJOR') && is_dir($file)) { if (true !== @rmdir($file)) { throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file); } } else { if (true !== @unlink($file)) { throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file); } } } } } /** * Change mode for an array of files or directories. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode * @param integer $mode The new mode (octal) * @param integer $umask The mode mask (octal) * @param Boolean $recursive Whether change the mod recursively or not * * @throws IOException When the change fail */ public function chmod($files, $mode, $umask = 0000, $recursive = false) { foreach ($this->toIterator($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chmod(new \FilesystemIterator($file), $mode, $umask, true); } if (true !== @chmod($file, $mode & ~$umask)) { throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file); } } } /** * Change the owner of an array of files or directories * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change owner * @param string $user The new owner user name * @param Boolean $recursive Whether change the owner recursively or not * * @throws IOException When the change fail */ public function chown($files, $user, $recursive = false) { foreach ($this->toIterator($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chown(new \FilesystemIterator($file), $user, true); } if (is_link($file) && function_exists('lchown')) { if (true !== @lchown($file, $user)) { throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); } } else { if (true !== @chown($file, $user)) { throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); } } } } /** * Change the group of an array of files or directories * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change group * @param string $group The group name * @param Boolean $recursive Whether change the group recursively or not * * @throws IOException When the change fail */ public function chgrp($files, $group, $recursive = false) { foreach ($this->toIterator($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chgrp(new \FilesystemIterator($file), $group, true); } if (is_link($file) && function_exists('lchgrp')) { if (true !== @lchgrp($file, $group)) { throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); } } else { if (true !== @chgrp($file, $group)) { throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); } } } } /** * Renames a file or a directory. * * @param string $origin The origin filename or directory * @param string $target The new filename or directory * @param Boolean $overwrite Whether to overwrite the target if it already exists * * @throws IOException When target file or directory already exists * @throws IOException When origin cannot be renamed */ public function rename($origin, $target, $overwrite = false) { // we check that target does not exist if (!$overwrite && is_readable($target)) { throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target); } if (true !== @rename($origin, $target)) { throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target); } } /** * Creates a symbolic link or copy a directory. * * @param string $originDir The origin directory path * @param string $targetDir The symbolic link name * @param Boolean $copyOnWindows Whether to copy files if on Windows * * @throws IOException When symlink fails */ public function symlink($originDir, $targetDir, $copyOnWindows = false) { if (!function_exists('symlink') && $copyOnWindows) { $this->mirror($originDir, $targetDir); return; } $this->mkdir(dirname($targetDir)); $ok = false; if (is_link($targetDir)) { if (readlink($targetDir) != $originDir) { $this->remove($targetDir); } else { $ok = true; } } if (!$ok) { if (true !== @symlink($originDir, $targetDir)) { $report = error_get_last(); if (is_array($report)) { if (defined('PHP_WINDOWS_VERSION_MAJOR') && false !== strpos($report['message'], 'error code(1314)')) { throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?'); } } throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir); } } } /** * Given an existing path, convert it to a path relative to a given starting path * * @param string $endPath Absolute path of target * @param string $startPath Absolute path where traversal begins * * @return string Path of target relative to starting path */ public function makePathRelative($endPath, $startPath) { // Normalize separators on Windows if (defined('PHP_WINDOWS_VERSION_MAJOR')) { $endPath = strtr($endPath, '\\', '/'); $startPath = strtr($startPath, '\\', '/'); } // Split the paths into arrays $startPathArr = explode('/', trim($startPath, '/')); $endPathArr = explode('/', trim($endPath, '/')); // Find for which directory the common path stops $index = 0; while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) { $index++; } // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels) $depth = count($startPathArr) - $index; // Repeated "../" for each level need to reach the common path $traverser = str_repeat('../', $depth); $endPathRemainder = implode('/', array_slice($endPathArr, $index)); // Construct $endPath from traversing to the common path, then to the remaining $endPath $relativePath = $traverser.(strlen($endPathRemainder) > 0 ? $endPathRemainder.'/' : ''); return (strlen($relativePath) === 0) ? './' : $relativePath; } /** * Mirrors a directory to another. * * @param string $originDir The origin directory * @param string $targetDir The target directory * @param \Traversable $iterator A Traversable instance * @param array $options An array of boolean options * Valid options are: * - $options['override'] Whether to override an existing file on copy or not (see copy()) * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink()) * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) * * @throws IOException When file type is unknown */ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()) { $targetDir = rtrim($targetDir, '/\\'); $originDir = rtrim($originDir, '/\\'); // Iterate in destination folder to remove obsolete entries if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) { $deleteIterator = $iterator; if (null === $deleteIterator) { $flags = \FilesystemIterator::SKIP_DOTS; $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST); } foreach ($deleteIterator as $file) { $origin = str_replace($targetDir, $originDir, $file->getPathname()); if (!$this->exists($origin)) { $this->remove($file); } } } $copyOnWindows = false; if (isset($options['copy_on_windows']) && !function_exists('symlink')) { $copyOnWindows = $options['copy_on_windows']; } if (null === $iterator) { $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS; $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST); } foreach ($iterator as $file) { $target = str_replace($originDir, $targetDir, $file->getPathname()); if ($copyOnWindows) { if (is_link($file) || is_file($file)) { $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); } elseif (is_dir($file)) { $this->mkdir($target); } else { throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); } } else { if (is_link($file)) { $this->symlink($file->getLinkTarget(), $target); } elseif (is_dir($file)) { $this->mkdir($target); } elseif (is_file($file)) { $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); } else { throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); } } } } /** * Returns whether the file path is an absolute path. * * @param string $file A file path * * @return Boolean */ public function isAbsolutePath($file) { if (strspn($file, '/\\', 0, 1) || (strlen($file) > 3 && ctype_alpha($file[0]) && substr($file, 1, 1) === ':' && (strspn($file, '/\\', 2, 1)) ) || null !== parse_url($file, PHP_URL_SCHEME) ) { return true; } return false; } /** * Atomically dumps content into a file. * * @param string $filename The file to be written to. * @param string $content The data to write into the file. * @param null|integer $mode The file mode (octal). If null, file permissions are not modified * Deprecated since version 2.3.12, to be removed in 3.0. * @throws IOException If the file cannot be written to. */ public function dumpFile($filename, $content, $mode = 0666) { $dir = dirname($filename); if (!is_dir($dir)) { $this->mkdir($dir); } elseif (!is_writable($dir)) { throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); } $tmpFile = tempnam($dir, basename($filename)); if (false === @file_put_contents($tmpFile, $content)) { throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); } $this->rename($tmpFile, $filename, true); if (null !== $mode) { $this->chmod($filename, $mode); } } /** * @param mixed $files * * @return \Traversable */ private function toIterator($files) { if (!$files instanceof \Traversable) { $files = new \ArrayObject(is_array($files) ? $files : array($files)); } return $files; } } PK!)..'Symfony/Component/Form/FormRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Renders a form into HTML using a rendering engine. * * @author Bernhard Schussek */ class FormRenderer implements FormRendererInterface { const CACHE_KEY_VAR = 'unique_block_prefix'; /** * @var FormRendererEngineInterface */ private $engine; /** * @var CsrfTokenManagerInterface */ private $csrfTokenManager; /** * @var array */ private $blockNameHierarchyMap = array(); /** * @var array */ private $hierarchyLevelMap = array(); /** * @var array */ private $variableStack = array(); /** * Constructor. * * @param FormRendererEngineInterface $engine * @param CsrfTokenManagerInterface|null $csrfTokenManager * * @throws UnexpectedTypeException */ public function __construct(FormRendererEngineInterface $engine, $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface or null'); } $this->engine = $engine; $this->csrfTokenManager = $csrfTokenManager; } /** * {@inheritdoc} */ public function getEngine() { return $this->engine; } /** * {@inheritdoc} */ public function setTheme(FormView $view, $themes) { $this->engine->setTheme($view, $themes); } /** * {@inheritdoc} */ public function renderCsrfToken($tokenId) { if (null === $this->csrfTokenManager) { throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenManagerInterface is injected in FormRenderer::__construct().'); } return $this->csrfTokenManager->getToken($tokenId)->getValue(); } /** * {@inheritdoc} */ public function renderBlock(FormView $view, $blockName, array $variables = array()) { $resource = $this->engine->getResourceForBlockName($view, $blockName); if (!$resource) { throw new LogicException(sprintf('No block "%s" found while rendering the form.', $blockName)); } $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; // The variables are cached globally for a view (instead of for the // current suffix) if (!isset($this->variableStack[$viewCacheKey])) { $this->variableStack[$viewCacheKey] = array(); // The default variable scope contains all view variables, merged with // the variables passed explicitly to the helper $scopeVariables = $view->vars; $varInit = true; } else { // Reuse the current scope and merge it with the explicitly passed variables $scopeVariables = end($this->variableStack[$viewCacheKey]); $varInit = false; } // Merge the passed with the existing attributes if (isset($variables['attr']) && isset($scopeVariables['attr'])) { $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']); } // Merge the passed with the exist *label* attributes if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) { $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']); } // Do not use array_replace_recursive(), otherwise array variables // cannot be overwritten $variables = array_replace($scopeVariables, $variables); $this->variableStack[$viewCacheKey][] = $variables; // Do the rendering $html = $this->engine->renderBlock($view, $resource, $blockName, $variables); // Clear the stack array_pop($this->variableStack[$viewCacheKey]); if ($varInit) { unset($this->variableStack[$viewCacheKey]); } return $html; } /** * {@inheritdoc} */ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $variables = array()) { $renderOnlyOnce = 'row' === $blockNameSuffix || 'widget' === $blockNameSuffix; if ($renderOnlyOnce && $view->isRendered()) { return ''; } // The cache key for storing the variables and types $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; $viewAndSuffixCacheKey = $viewCacheKey.$blockNameSuffix; // In templates, we have to deal with two kinds of block hierarchies: // // +---------+ +---------+ // | Theme B | -------> | Theme A | // +---------+ +---------+ // // form_widget -------> form_widget // ^ // | // choice_widget -----> choice_widget // // The first kind of hierarchy is the theme hierarchy. This allows to // override the block "choice_widget" from Theme A in the extending // Theme B. This kind of inheritance needs to be supported by the // template engine and, for example, offers "parent()" or similar // functions to fall back from the custom to the parent implementation. // // The second kind of hierarchy is the form type hierarchy. This allows // to implement a custom "choice_widget" block (no matter in which theme), // or to fallback to the block of the parent type, which would be // "form_widget" in this example (again, no matter in which theme). // If the designer wants to explicitly fallback to "form_widget" in his // custom "choice_widget", for example because he only wants to wrap // a
around the original implementation, he can simply call the // widget() function again to render the block for the parent type. // // The second kind is implemented in the following blocks. if (!isset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey])) { // INITIAL CALL // Calculate the hierarchy of template blocks and start on // the bottom level of the hierarchy (= "__
" block) $blockNameHierarchy = array(); foreach ($view->vars['block_prefixes'] as $blockNamePrefix) { $blockNameHierarchy[] = $blockNamePrefix.'_'.$blockNameSuffix; } $hierarchyLevel = count($blockNameHierarchy) - 1; $hierarchyInit = true; } else { // RECURSIVE CALL // If a block recursively calls searchAndRenderBlock() again, resume rendering // using the parent type in the hierarchy. $blockNameHierarchy = $this->blockNameHierarchyMap[$viewAndSuffixCacheKey]; $hierarchyLevel = $this->hierarchyLevelMap[$viewAndSuffixCacheKey] - 1; $hierarchyInit = false; } // The variables are cached globally for a view (instead of for the // current suffix) if (!isset($this->variableStack[$viewCacheKey])) { $this->variableStack[$viewCacheKey] = array(); // The default variable scope contains all view variables, merged with // the variables passed explicitly to the helper $scopeVariables = $view->vars; $varInit = true; } else { // Reuse the current scope and merge it with the explicitly passed variables $scopeVariables = end($this->variableStack[$viewCacheKey]); $varInit = false; } // Load the resource where this block can be found $resource = $this->engine->getResourceForBlockNameHierarchy($view, $blockNameHierarchy, $hierarchyLevel); // Update the current hierarchy level to the one at which the resource was // found. For example, if looking for "choice_widget", but only a resource // is found for its parent "form_widget", then the level is updated here // to the parent level. $hierarchyLevel = $this->engine->getResourceHierarchyLevel($view, $blockNameHierarchy, $hierarchyLevel); // The actually existing block name in $resource $blockName = $blockNameHierarchy[$hierarchyLevel]; // Escape if no resource exists for this block if (!$resource) { throw new LogicException(sprintf( 'Unable to render the form as none of the following blocks exist: "%s".', implode('", "', array_reverse($blockNameHierarchy)) )); } // Merge the passed with the existing attributes if (isset($variables['attr']) && isset($scopeVariables['attr'])) { $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']); } // Merge the passed with the exist *label* attributes if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) { $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']); } // Do not use array_replace_recursive(), otherwise array variables // cannot be overwritten $variables = array_replace($scopeVariables, $variables); // In order to make recursive calls possible, we need to store the block hierarchy, // the current level of the hierarchy and the variables so that this method can // resume rendering one level higher of the hierarchy when it is called recursively. // // We need to store these values in maps (associative arrays) because within a // call to widget() another call to widget() can be made, but for a different view // object. These nested calls should not override each other. $this->blockNameHierarchyMap[$viewAndSuffixCacheKey] = $blockNameHierarchy; $this->hierarchyLevelMap[$viewAndSuffixCacheKey] = $hierarchyLevel; // We also need to store the variables for the view so that we can render other // blocks for the same view using the same variables as in the outer block. $this->variableStack[$viewCacheKey][] = $variables; // Do the rendering $html = $this->engine->renderBlock($view, $resource, $blockName, $variables); // Clear the stack array_pop($this->variableStack[$viewCacheKey]); // Clear the caches if they were filled for the first time within // this function call if ($hierarchyInit) { unset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey]); unset($this->hierarchyLevelMap[$viewAndSuffixCacheKey]); } if ($varInit) { unset($this->variableStack[$viewCacheKey]); } if ($renderOnlyOnce) { $view->setRendered(); } return $html; } /** * {@inheritdoc} */ public function humanize($text) { return ucfirst(trim(strtolower(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text)))); } } PK!C.Symfony/Component/Form/ButtonTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A type that should be converted into a {@link Button} instance. * * @author Bernhard Schussek */ interface ButtonTypeInterface extends FormTypeInterface { } PK!K'$&Symfony/Component/Form/FormBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * A builder for creating {@link Form} instances. * * @author Bernhard Schussek */ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormBuilderInterface { /** * The children of the form builder. * * @var FormBuilderInterface[] */ private $children = array(); /** * The data of children who haven't been converted to form builders yet. * * @var array */ private $unresolvedChildren = array(); /** * Creates a new form builder. * * @param string $name * @param string $dataClass * @param EventDispatcherInterface $dispatcher * @param FormFactoryInterface $factory * @param array $options */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, FormFactoryInterface $factory, array $options = array()) { parent::__construct($name, $dataClass, $dispatcher, $options); $this->setFormFactory($factory); } /** * {@inheritdoc} */ public function add($child, $type = null, array $options = array()) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($child instanceof self) { $this->children[$child->getName()] = $child; // In case an unresolved child with the same name exists unset($this->unresolvedChildren[$child->getName()]); return $this; } if (!is_string($child) && !is_int($child)) { throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormBuilder'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); } // Add to "children" to maintain order $this->children[$child] = null; $this->unresolvedChildren[$child] = array( 'type' => $type, 'options' => $options, ); return $this; } /** * {@inheritdoc} */ public function create($name, $type = null, array $options = array()) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (null === $type && null === $this->getDataClass()) { $type = 'text'; } if (null !== $type) { return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options); } return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options); } /** * {@inheritdoc} */ public function get($name) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (isset($this->unresolvedChildren[$name])) { return $this->resolveChild($name); } if (isset($this->children[$name])) { return $this->children[$name]; } throw new InvalidArgumentException(sprintf('The child with the name "%s" does not exist.', $name)); } /** * {@inheritdoc} */ public function remove($name) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } unset($this->unresolvedChildren[$name]); if (array_key_exists($name, $this->children)) { unset($this->children[$name]); } return $this; } /** * {@inheritdoc} */ public function has($name) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (isset($this->unresolvedChildren[$name])) { return true; } if (isset($this->children[$name])) { return true; } return false; } /** * {@inheritdoc} */ public function all() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->resolveChildren(); return $this->children; } /** * {@inheritdoc} */ public function count() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return count($this->children); } /** * {@inheritdoc} */ public function getFormConfig() { $config = parent::getFormConfig(); $config->children = array(); $config->unresolvedChildren = array(); return $config; } /** * {@inheritdoc} */ public function getForm() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->resolveChildren(); $form = new Form($this->getFormConfig()); foreach ($this->children as $child) { // Automatic initialization is only supported on root forms $form->add($child->setAutoInitialize(false)->getForm()); } if ($this->getAutoInitialize()) { // Automatically initialize the form if it is configured so $form->initialize(); } return $form; } /** * {@inheritdoc} */ public function getIterator() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return new \ArrayIterator($this->children); } /** * Converts an unresolved child into a {@link FormBuilder} instance. * * @param string $name The name of the unresolved child. * * @return FormBuilder The created instance. */ private function resolveChild($name) { $info = $this->unresolvedChildren[$name]; $child = $this->create($name, $info['type'], $info['options']); $this->children[$name] = $child; unset($this->unresolvedChildren[$name]); return $child; } /** * Converts all unresolved children into {@link FormBuilder} instances. */ private function resolveChildren() { foreach ($this->unresolvedChildren as $name => $info) { $this->children[$name] = $this->create($name, $info['type'], $info['options']); } $this->unresolvedChildren = array(); } } PK!&"̰TT,Symfony/Component/Form/FormConfigBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\ImmutableEventDispatcher; /** * A basic form configuration. * * @author Bernhard Schussek */ class FormConfigBuilder implements FormConfigBuilderInterface { /** * Caches a globally unique {@link NativeRequestHandler} instance. * * @var NativeRequestHandler */ private static $nativeRequestProcessor; /** * The accepted request methods. * * @var array */ private static $allowedMethods = array( 'GET', 'PUT', 'POST', 'DELETE', 'PATCH' ); /** * @var Boolean */ protected $locked = false; /** * @var EventDispatcherInterface */ private $dispatcher; /** * @var string */ private $name; /** * @var PropertyPathInterface */ private $propertyPath; /** * @var Boolean */ private $mapped = true; /** * @var Boolean */ private $byReference = true; /** * @var Boolean */ private $inheritData = false; /** * @var Boolean */ private $compound = false; /** * @var ResolvedFormTypeInterface */ private $type; /** * @var array */ private $viewTransformers = array(); /** * @var array */ private $modelTransformers = array(); /** * @var DataMapperInterface */ private $dataMapper; /** * @var Boolean */ private $required = true; /** * @var Boolean */ private $disabled = false; /** * @var Boolean */ private $errorBubbling = false; /** * @var mixed */ private $emptyData; /** * @var array */ private $attributes = array(); /** * @var mixed */ private $data; /** * @var string */ private $dataClass; /** * @var Boolean */ private $dataLocked; /** * @var FormFactoryInterface */ private $formFactory; /** * @var string */ private $action; /** * @var string */ private $method = 'POST'; /** * @var RequestHandlerInterface */ private $requestHandler; /** * @var Boolean */ private $autoInitialize = false; /** * @var array */ private $options; /** * Creates an empty form configuration. * * @param string|integer $name The form name * @param string $dataClass The class of the form's data * @param EventDispatcherInterface $dispatcher The event dispatcher * @param array $options The form options * * @throws InvalidArgumentException If the data class is not a valid class or if * the name contains invalid characters. */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, array $options = array()) { self::validateName($name); if (null !== $dataClass && !class_exists($dataClass)) { throw new InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass)); } $this->name = (string) $name; $this->dataClass = $dataClass; $this->dispatcher = $dispatcher; $this->options = $options; } /** * {@inheritdoc} */ public function addEventListener($eventName, $listener, $priority = 0) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dispatcher->addListener($eventName, $listener, $priority); return $this; } /** * {@inheritdoc} */ public function addEventSubscriber(EventSubscriberInterface $subscriber) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dispatcher->addSubscriber($subscriber); return $this; } /** * {@inheritdoc} */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($forcePrepend) { array_unshift($this->viewTransformers, $viewTransformer); } else { $this->viewTransformers[] = $viewTransformer; } return $this; } /** * {@inheritdoc} */ public function resetViewTransformers() { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->viewTransformers = array(); return $this; } /** * {@inheritdoc} */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($forceAppend) { $this->modelTransformers[] = $modelTransformer; } else { array_unshift($this->modelTransformers, $modelTransformer); } return $this; } /** * {@inheritdoc} */ public function resetModelTransformers() { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->modelTransformers = array(); return $this; } /** * {@inheritdoc} */ public function getEventDispatcher() { if ($this->locked && !$this->dispatcher instanceof ImmutableEventDispatcher) { $this->dispatcher = new ImmutableEventDispatcher($this->dispatcher); } return $this->dispatcher; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * {@inheritdoc} */ public function getPropertyPath() { return $this->propertyPath; } /** * {@inheritdoc} */ public function getMapped() { return $this->mapped; } /** * {@inheritdoc} */ public function getByReference() { return $this->byReference; } /** * {@inheritdoc} */ public function getInheritData() { return $this->inheritData; } /** * Alias of {@link getInheritData()}. * * @return FormConfigBuilder The configuration object. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link getInheritData()} instead. */ public function getVirtual() { // Uncomment this as soon as the deprecation note should be shown // trigger_error('getVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use getInheritData() instead.', E_USER_DEPRECATED); return $this->getInheritData(); } /** * {@inheritdoc} */ public function getCompound() { return $this->compound; } /** * {@inheritdoc} */ public function getType() { return $this->type; } /** * {@inheritdoc} */ public function getViewTransformers() { return $this->viewTransformers; } /** * {@inheritdoc} */ public function getModelTransformers() { return $this->modelTransformers; } /** * {@inheritdoc} */ public function getDataMapper() { return $this->dataMapper; } /** * {@inheritdoc} */ public function getRequired() { return $this->required; } /** * {@inheritdoc} */ public function getDisabled() { return $this->disabled; } /** * {@inheritdoc} */ public function getErrorBubbling() { return $this->errorBubbling; } /** * {@inheritdoc} */ public function getEmptyData() { return $this->emptyData; } /** * {@inheritdoc} */ public function getAttributes() { return $this->attributes; } /** * {@inheritdoc} */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * {@inheritdoc} */ public function getAttribute($name, $default = null) { return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** * {@inheritdoc} */ public function getData() { return $this->data; } /** * {@inheritdoc} */ public function getDataClass() { return $this->dataClass; } /** * {@inheritdoc} */ public function getDataLocked() { return $this->dataLocked; } /** * {@inheritdoc} */ public function getFormFactory() { return $this->formFactory; } /** * {@inheritdoc} */ public function getAction() { return $this->action; } /** * {@inheritdoc} */ public function getMethod() { return $this->method; } /** * {@inheritdoc} */ public function getRequestHandler() { if (null === $this->requestHandler) { if (null === self::$nativeRequestProcessor) { self::$nativeRequestProcessor = new NativeRequestHandler(); } $this->requestHandler = self::$nativeRequestProcessor; } return $this->requestHandler; } /** * {@inheritdoc} */ public function getAutoInitialize() { return $this->autoInitialize; } /** * {@inheritdoc} */ public function getOptions() { return $this->options; } /** * {@inheritdoc} */ public function hasOption($name) { return array_key_exists($name, $this->options); } /** * {@inheritdoc} */ public function getOption($name, $default = null) { return array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** * {@inheritdoc} */ public function setAttribute($name, $value) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->attributes[$name] = $value; return $this; } /** * {@inheritdoc} */ public function setAttributes(array $attributes) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->attributes = $attributes; return $this; } /** * {@inheritdoc} */ public function setDataMapper(DataMapperInterface $dataMapper = null) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dataMapper = $dataMapper; return $this; } /** * {@inheritdoc} */ public function setDisabled($disabled) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->disabled = (Boolean) $disabled; return $this; } /** * {@inheritdoc} */ public function setEmptyData($emptyData) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->emptyData = $emptyData; return $this; } /** * {@inheritdoc} */ public function setErrorBubbling($errorBubbling) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling; return $this; } /** * {@inheritdoc} */ public function setRequired($required) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->required = (Boolean) $required; return $this; } /** * {@inheritdoc} */ public function setPropertyPath($propertyPath) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (null !== $propertyPath && !$propertyPath instanceof PropertyPathInterface) { $propertyPath = new PropertyPath($propertyPath); } $this->propertyPath = $propertyPath; return $this; } /** * {@inheritdoc} */ public function setMapped($mapped) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->mapped = $mapped; return $this; } /** * {@inheritdoc} */ public function setByReference($byReference) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->byReference = $byReference; return $this; } /** * {@inheritdoc} */ public function setInheritData($inheritData) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->inheritData = $inheritData; return $this; } /** * Alias of {@link setInheritData()}. * * @param Boolean $inheritData Whether the form should inherit its parent's data. * * @return FormConfigBuilder The configuration object. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link setInheritData()} instead. */ public function setVirtual($inheritData) { // Uncomment this as soon as the deprecation note should be shown // trigger_error('setVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use setInheritData() instead.', E_USER_DEPRECATED); $this->setInheritData($inheritData); } /** * {@inheritdoc} */ public function setCompound($compound) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->compound = $compound; return $this; } /** * {@inheritdoc} */ public function setType(ResolvedFormTypeInterface $type) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->type = $type; return $this; } /** * {@inheritdoc} */ public function setData($data) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->data = $data; return $this; } /** * {@inheritdoc} */ public function setDataLocked($locked) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dataLocked = $locked; return $this; } /** * {@inheritdoc} */ public function setFormFactory(FormFactoryInterface $formFactory) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->formFactory = $formFactory; return $this; } /** * {@inheritdoc} */ public function setAction($action) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } $this->action = $action; return $this; } /** * {@inheritdoc} */ public function setMethod($method) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } $upperCaseMethod = strtoupper($method); if (!in_array($upperCaseMethod, self::$allowedMethods)) { throw new InvalidArgumentException(sprintf( 'The form method is "%s", but should be one of "%s".', $method, implode('", "', self::$allowedMethods) )); } $this->method = $upperCaseMethod; return $this; } /** * {@inheritdoc} */ public function setRequestHandler(RequestHandlerInterface $requestHandler) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } $this->requestHandler = $requestHandler; return $this; } /** * {@inheritdoc} */ public function setAutoInitialize($initialize) { $this->autoInitialize = (Boolean) $initialize; return $this; } /** * {@inheritdoc} */ public function getFormConfig() { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } // This method should be idempotent, so clone the builder $config = clone $this; $config->locked = true; return $config; } /** * Validates whether the given variable is a valid form name. * * @param string|integer $name The tested form name. * * @throws UnexpectedTypeException If the name is not a string or an integer. * @throws InvalidArgumentException If the name contains invalid characters. */ public static function validateName($name) { if (null !== $name && !is_string($name) && !is_int($name)) { throw new UnexpectedTypeException($name, 'string, integer or null'); } if (!self::isValidName($name)) { throw new InvalidArgumentException(sprintf( 'The name "%s" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").', $name )); } } /** * Returns whether the given variable contains a valid form name. * * A name is accepted if it * * * is empty * * starts with a letter, digit or underscore * * contains only letters, digits, numbers, underscores ("_"), * hyphens ("-") and colons (":") * * @param string $name The tested form name. * * @return Boolean Whether the name is valid. */ public static function isValidName($name) { return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name); } } PK!E1'4Symfony/Component/Form/SubmitButtonTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A type that should be converted into a {@link SubmitButton} instance. * * @author Bernhard Schussek */ interface SubmitButtonTypeInterface extends FormTypeInterface { } PK!d'Symfony/Component/Form/FormRegistry.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\ExceptionInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * The central registry of the Form component. * * @author Bernhard Schussek */ class FormRegistry implements FormRegistryInterface { /** * Extensions * * @var FormExtensionInterface[] An array of FormExtensionInterface */ private $extensions = array(); /** * @var array */ private $types = array(); /** * @var FormTypeGuesserInterface|false|null */ private $guesser = false; /** * @var ResolvedFormTypeFactoryInterface */ private $resolvedTypeFactory; /** * Constructor. * * @param FormExtensionInterface[] $extensions An array of FormExtensionInterface * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory The factory for resolved form types. * * @throws UnexpectedTypeException if any extension does not implement FormExtensionInterface */ public function __construct(array $extensions, ResolvedFormTypeFactoryInterface $resolvedTypeFactory) { foreach ($extensions as $extension) { if (!$extension instanceof FormExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormExtensionInterface'); } } $this->extensions = $extensions; $this->resolvedTypeFactory = $resolvedTypeFactory; } /** * {@inheritdoc} */ public function getType($name) { if (!is_string($name)) { throw new UnexpectedTypeException($name, 'string'); } if (!isset($this->types[$name])) { /** @var FormTypeInterface $type */ $type = null; foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ if ($extension->hasType($name)) { $type = $extension->getType($name); break; } } if (!$type) { throw new InvalidArgumentException(sprintf('Could not load type "%s"', $name)); } $this->resolveAndAddType($type); } return $this->types[$name]; } /** * Wraps a type into a ResolvedFormTypeInterface implementation and connects * it with its parent type. * * @param FormTypeInterface $type The type to resolve. * * @return ResolvedFormTypeInterface The resolved type. */ private function resolveAndAddType(FormTypeInterface $type) { $parentType = $type->getParent(); if ($parentType instanceof FormTypeInterface) { $this->resolveAndAddType($parentType); $parentType = $parentType->getName(); } $typeExtensions = array(); foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ $typeExtensions = array_merge( $typeExtensions, $extension->getTypeExtensions($type->getName()) ); } $this->types[$type->getName()] = $this->resolvedTypeFactory->createResolvedType( $type, $typeExtensions, $parentType ? $this->getType($parentType) : null ); } /** * {@inheritdoc} */ public function hasType($name) { if (isset($this->types[$name])) { return true; } try { $this->getType($name); } catch (ExceptionInterface $e) { return false; } return true; } /** * {@inheritdoc} */ public function getTypeGuesser() { if (false === $this->guesser) { $guessers = array(); foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ $guesser = $extension->getTypeGuesser(); if ($guesser) { $guessers[] = $guesser; } } $this->guesser = !empty($guessers) ? new FormTypeGuesserChain($guessers) : null; } return $this->guesser; } /** * {@inheritdoc} */ public function getExtensions() { return $this->extensions; } } PK!ÊM'%%.Symfony/Component/Form/FormConfigInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * The configuration of a {@link Form} object. * * @author Bernhard Schussek */ interface FormConfigInterface { /** * Returns the event dispatcher used to dispatch form events. * * @return \Symfony\Component\EventDispatcher\EventDispatcherInterface The dispatcher. */ public function getEventDispatcher(); /** * Returns the name of the form used as HTTP parameter. * * @return string The form name. */ public function getName(); /** * Returns the property path that the form should be mapped to. * * @return null|\Symfony\Component\PropertyAccess\PropertyPathInterface The property path. */ public function getPropertyPath(); /** * Returns whether the form should be mapped to an element of its * parent's data. * * @return Boolean Whether the form is mapped. */ public function getMapped(); /** * Returns whether the form's data should be modified by reference. * * @return Boolean Whether to modify the form's data by reference. */ public function getByReference(); /** * Returns whether the form should read and write the data of its parent. * * @return Boolean Whether the form should inherit its parent's data. */ public function getInheritData(); /** * Returns whether the form is compound. * * This property is independent of whether the form actually has * children. A form can be compound and have no children at all, like * for example an empty collection form. * * @return Boolean Whether the form is compound. */ public function getCompound(); /** * Returns the form types used to construct the form. * * @return ResolvedFormTypeInterface The form's type. */ public function getType(); /** * Returns the view transformers of the form. * * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances. */ public function getViewTransformers(); /** * Returns the model transformers of the form. * * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances. */ public function getModelTransformers(); /** * Returns the data mapper of the form. * * @return DataMapperInterface The data mapper. */ public function getDataMapper(); /** * Returns whether the form is required. * * @return Boolean Whether the form is required. */ public function getRequired(); /** * Returns whether the form is disabled. * * @return Boolean Whether the form is disabled. */ public function getDisabled(); /** * Returns whether errors attached to the form will bubble to its parent. * * @return Boolean Whether errors will bubble up. */ public function getErrorBubbling(); /** * Returns the data that should be returned when the form is empty. * * @return mixed The data returned if the form is empty. */ public function getEmptyData(); /** * Returns additional attributes of the form. * * @return array An array of key-value combinations. */ public function getAttributes(); /** * Returns whether the attribute with the given name exists. * * @param string $name The attribute name. * * @return Boolean Whether the attribute exists. */ public function hasAttribute($name); /** * Returns the value of the given attribute. * * @param string $name The attribute name. * @param mixed $default The value returned if the attribute does not exist. * * @return mixed The attribute value. */ public function getAttribute($name, $default = null); /** * Returns the initial data of the form. * * @return mixed The initial form data. */ public function getData(); /** * Returns the class of the form data or null if the data is scalar or an array. * * @return string The data class or null. */ public function getDataClass(); /** * Returns whether the form's data is locked. * * A form with locked data is restricted to the data passed in * this configuration. The data can only be modified then by * submitting the form. * * @return Boolean Whether the data is locked. */ public function getDataLocked(); /** * Returns the form factory used for creating new forms. * * @return FormFactoryInterface The form factory. */ public function getFormFactory(); /** * Returns the target URL of the form. * * @return string The target URL of the form. */ public function getAction(); /** * Returns the HTTP method used by the form. * * @return string The HTTP method of the form. */ public function getMethod(); /** * Returns the request handler used by the form. * * @return RequestHandlerInterface The request handler. */ public function getRequestHandler(); /** * Returns whether the form should be initialized upon creation. * * @return Boolean Returns true if the form should be initialized * when created, false otherwise. */ public function getAutoInitialize(); /** * Returns all options passed during the construction of the form. * * @return array The passed options. */ public function getOptions(); /** * Returns whether a specific option exists. * * @param string $name The option name, * * @return Boolean Whether the option exists. */ public function hasOption($name); /** * Returns the value of a specific option. * * @param string $name The option name. * @param mixed $default The value returned if the option does not exist. * * @return mixed The option value. */ public function getOption($name, $default = null); } PK!@ @ /Symfony/Component/Form/FormTypeGuesserChain.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Exception\UnexpectedTypeException; class FormTypeGuesserChain implements FormTypeGuesserInterface { private $guessers = array(); /** * Constructor. * * @param FormTypeGuesserInterface[] $guessers Guessers as instances of FormTypeGuesserInterface * * @throws UnexpectedTypeException if any guesser does not implement FormTypeGuesserInterface */ public function __construct(array $guessers) { foreach ($guessers as $guesser) { if (!$guesser instanceof FormTypeGuesserInterface) { throw new UnexpectedTypeException($guesser, 'Symfony\Component\Form\FormTypeGuesserInterface'); } if ($guesser instanceof self) { $this->guessers = array_merge($this->guessers, $guesser->guessers); } else { $this->guessers[] = $guesser; } } } /** * {@inheritDoc} */ public function guessType($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessType($class, $property); }); } /** * {@inheritDoc} */ public function guessRequired($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessRequired($class, $property); }); } /** * {@inheritDoc} */ public function guessMaxLength($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessMaxLength($class, $property); }); } /** * {@inheritDoc} */ public function guessPattern($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessPattern($class, $property); }); } /** * Executes a closure for each guesser and returns the best guess from the * return values * * @param \Closure $closure The closure to execute. Accepts a guesser * as argument and should return a Guess instance * * @return Guess|null The guess with the highest confidence */ private function guess(\Closure $closure) { $guesses = array(); foreach ($this->guessers as $guesser) { if ($guess = $closure($guesser)) { $guesses[] = $guess; } } return Guess::getBestGuess($guesses); } } PK!R+Symfony/Component/Form/Guess/ValueGuess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Guess; /** * Contains a guessed value * * @author Bernhard Schussek */ class ValueGuess extends Guess { /** * The guessed value * @var array */ private $value; /** * Constructor * * @param string $value The guessed value * @param integer $confidence The confidence that the guessed class name * is correct */ public function __construct($value, $confidence) { parent::__construct($confidence); $this->value = $value; } /** * Returns the guessed value * * @return mixed */ public function getValue() { return $this->value; } } PK!51 1 &Symfony/Component/Form/Guess/Guess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Guess; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * Base class for guesses made by TypeGuesserInterface implementation * * Each instance contains a confidence value about the correctness of the guess. * Thus an instance with confidence HIGH_CONFIDENCE is more likely to be * correct than an instance with confidence LOW_CONFIDENCE. * * @author Bernhard Schussek */ abstract class Guess { /** * Marks an instance with a value that is extremely likely to be correct * @var integer */ const VERY_HIGH_CONFIDENCE = 3; /** * Marks an instance with a value that is very likely to be correct * @var integer */ const HIGH_CONFIDENCE = 2; /** * Marks an instance with a value that is likely to be correct * @var integer */ const MEDIUM_CONFIDENCE = 1; /** * Marks an instance with a value that may be correct * @var integer */ const LOW_CONFIDENCE = 0; /** * The confidence about the correctness of the value * * One of VERY_HIGH_CONFIDENCE, HIGH_CONFIDENCE, MEDIUM_CONFIDENCE * and LOW_CONFIDENCE. * * @var integer */ private $confidence; /** * Returns the guess most likely to be correct from a list of guesses. * * If there are multiple guesses with the same, highest confidence, the * returned guess is any of them. * * @param Guess[] $guesses An array of guesses * * @return Guess|null The guess with the highest confidence */ public static function getBestGuess(array $guesses) { $result = null; $maxConfidence = -1; foreach ($guesses as $guess) { if ($maxConfidence < $confidence = $guess->getConfidence()) { $maxConfidence = $confidence; $result = $guess; } } return $result; } /** * Constructor. * * @param integer $confidence The confidence * * @throws InvalidArgumentException if the given value of confidence is unknown */ public function __construct($confidence) { if (self::VERY_HIGH_CONFIDENCE !== $confidence && self::HIGH_CONFIDENCE !== $confidence && self::MEDIUM_CONFIDENCE !== $confidence && self::LOW_CONFIDENCE !== $confidence) { throw new InvalidArgumentException('The confidence should be one of the constants defined in Guess.'); } $this->confidence = $confidence; } /** * Returns the confidence that the guessed value is correct. * * @return integer One of the constants VERY_HIGH_CONFIDENCE, * HIGH_CONFIDENCE, MEDIUM_CONFIDENCE and LOW_CONFIDENCE */ public function getConfidence() { return $this->confidence; } } PK!  *Symfony/Component/Form/Guess/TypeGuess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Guess; /** * Contains a guessed class name and a list of options for creating an instance * of that class * * @author Bernhard Schussek */ class TypeGuess extends Guess { /** * The guessed field type * @var string */ private $type; /** * The guessed options for creating an instance of the guessed class * @var array */ private $options; /** * Constructor * * @param string $type The guessed field type * @param array $options The options for creating instances of the * guessed class * @param integer $confidence The confidence that the guessed class name * is correct */ public function __construct($type, array $options, $confidence) { parent::__construct($confidence); $this->type = $type; $this->options = $options; } /** * Returns the guessed field type * * @return string */ public function getType() { return $this->type; } /** * Returns the guessed options for creating instances of the guessed type * * @return array */ public function getOptions() { return $this->options; } } PK!0\ZZ.Symfony/Component/Form/CallbackTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\TransformationFailedException; class CallbackTransformer implements DataTransformerInterface { /** * The callback used for forward transform * @var \Closure */ private $transform; /** * The callback used for reverse transform * @var \Closure */ private $reverseTransform; /** * Constructor. * * @param \Closure $transform The forward transform callback * @param \Closure $reverseTransform The reverse transform callback */ public function __construct(\Closure $transform, \Closure $reverseTransform) { $this->transform = $transform; $this->reverseTransform = $reverseTransform; } /** * Transforms a value from the original representation to a transformed representation. * * @param mixed $data The value in the original representation * * @return mixed The value in the transformed representation * * @throws UnexpectedTypeException when the argument is not a string * @throws TransformationFailedException when the transformation fails */ public function transform($data) { return call_user_func($this->transform, $data); } /** * Transforms a value from the transformed representation to its original * representation. * * @param mixed $data The value in the transformed representation * * @return mixed The value in the original representation * * @throws UnexpectedTypeException when the argument is not of the expected type * @throws TransformationFailedException when the transformation fails */ public function reverseTransform($data) { return call_user_func($this->reverseTransform, $data); } } PK!4Nz"z"!Symfony/Component/Form/Button.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\AlreadySubmittedException; use Symfony\Component\Form\Exception\BadMethodCallException; /** * A form button. * * @author Bernhard Schussek */ class Button implements \IteratorAggregate, FormInterface { /** * @var FormInterface|null */ private $parent; /** * @var FormConfigInterface */ private $config; /** * @var Boolean */ private $submitted = false; /** * Creates a new button from a form configuration. * * @param FormConfigInterface $config The button's configuration. */ public function __construct(FormConfigInterface $config) { $this->config = $config; } /** * Unsupported method. * * @param mixed $offset * * @return Boolean Always returns false. */ public function offsetExists($offset) { return false; } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $offset * * @throws BadMethodCallException */ public function offsetGet($offset) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $offset * @param mixed $value * * @throws BadMethodCallException */ public function offsetSet($offset, $value) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $offset * * @throws BadMethodCallException */ public function offsetUnset($offset) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * {@inheritdoc} */ public function setParent(FormInterface $parent = null) { $this->parent = $parent; } /** * {@inheritdoc} */ public function getParent() { return $this->parent; } /** * Unsupported method. * * This method should not be invoked. * * @param int|string|FormInterface $child * @param null $type * @param array $options * * @throws BadMethodCallException */ public function add($child, $type = null, array $options = array()) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function get($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * @param string $name * * @return Boolean Always returns false. */ public function has($name) { return false; } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function remove($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * {@inheritdoc} */ public function all() { return array(); } /** * {@inheritdoc} */ public function getErrors() { return array(); } /** * Unsupported method. * * This method should not be invoked. * * @param string $modelData * * @throws BadMethodCallException */ public function setData($modelData) { // called during initialization of the form tree // noop } /** * Unsupported method. * * @return null Always returns null. */ public function getData() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getNormData() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getViewData() { return null; } /** * Unsupported method. * * @return array Always returns an empty array. */ public function getExtraData() { return array(); } /** * Returns the button's configuration. * * @return FormConfigInterface The configuration. */ public function getConfig() { return $this->config; } /** * Returns whether the button is submitted. * * @return Boolean true if the button was submitted. */ public function isSubmitted() { return $this->submitted; } /** * Returns the name by which the button is identified in forms. * * @return string The name of the button. */ public function getName() { return $this->config->getName(); } /** * Unsupported method. * * @return null Always returns null. */ public function getPropertyPath() { return null; } /** * Unsupported method. * * @param FormError $error * * @throws BadMethodCallException */ public function addError(FormError $error) { throw new BadMethodCallException('Buttons cannot have errors.'); } /** * Unsupported method. * * @return Boolean Always returns true. */ public function isValid() { return true; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function isRequired() { return false; } /** * {@inheritdoc} */ public function isDisabled() { return $this->config->getDisabled(); } /** * Unsupported method. * * @return Boolean Always returns true. */ public function isEmpty() { return true; } /** * Unsupported method. * * @return Boolean Always returns true. */ public function isSynchronized() { return true; } /** * Unsupported method. * * @throws BadMethodCallException */ public function initialize() { throw new BadMethodCallException('Buttons cannot be initialized. Call initialize() on the root form instead.'); } /** * Unsupported method. * * @param mixed $request * * @throws BadMethodCallException */ public function handleRequest($request = null) { throw new BadMethodCallException('Buttons cannot handle requests. Call handleRequest() on the root form instead.'); } /** * Submits data to the button. * * @param null|string $submittedData The data. * @param Boolean $clearMissing Not used. * * @return Button The button instance * * @throws Exception\AlreadySubmittedException If the button has already been submitted. */ public function submit($submittedData, $clearMissing = true) { if ($this->submitted) { throw new AlreadySubmittedException('A form can only be submitted once'); } $this->submitted = true; return $this; } /** * {@inheritdoc} */ public function getRoot() { return $this->parent ? $this->parent->getRoot() : $this; } /** * {@inheritdoc} */ public function isRoot() { return null === $this->parent; } /** * {@inheritdoc} */ public function createView(FormView $parent = null) { if (null === $parent && $this->parent) { $parent = $this->parent->createView(); } $type = $this->config->getType(); $options = $this->config->getOptions(); $view = $type->createView($this, $parent); $type->buildView($view, $this, $options); $type->finishView($view, $this, $options); return $view; } /** * Unsupported method. * * @return integer Always returns 0. */ public function count() { return 0; } /** * Unsupported method. * * @return \EmptyIterator Always returns an empty iterator. */ public function getIterator() { return new \EmptyIterator(); } } PK!-9NN%Symfony/Component/Form/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ final class FormEvents { const PRE_SUBMIT = 'form.pre_bind'; const SUBMIT = 'form.bind'; const POST_SUBMIT = 'form.post_bind'; const PRE_SET_DATA = 'form.pre_set_data'; const POST_SET_DATA = 'form.post_set_data'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link PRE_SUBMIT} instead. */ const PRE_BIND = 'form.pre_bind'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link SUBMIT} instead. */ const BIND = 'form.bind'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link POST_SUBMIT} instead. */ const POST_BIND = 'form.post_bind'; private function __construct() { } } PK! ,Symfony/Component/Form/FormTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ interface FormTypeInterface { /** * Builds the form. * * This method is called for each type in the hierarchy starting form the * top most type. Type extensions can further modify the form. * * @see FormTypeExtensionInterface::buildForm() * * @param FormBuilderInterface $builder The form builder * @param array $options The options */ public function buildForm(FormBuilderInterface $builder, array $options); /** * Builds the form view. * * This method is called for each type in the hierarchy starting form the * top most type. Type extensions can further modify the view. * * A view of a form is built before the views of the child forms are built. * This means that you cannot access child views in this method. If you need * to do so, move your logic to {@link finishView()} instead. * * @see FormTypeExtensionInterface::buildView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes the form view. * * This method gets called for each type in the hierarchy starting form the * top most type. Type extensions can further modify the view. * * When this method is called, views of the form's children have already * been built and finished and can be accessed. You should only implement * such logic in this method that actually accesses child views. For everything * else you are recommended to implement {@link buildView()} instead. * * @see FormTypeExtensionInterface::finishView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options); /** * Sets the default options for this type. * * @param OptionsResolverInterface $resolver The resolver for the options. */ public function setDefaultOptions(OptionsResolverInterface $resolver); /** * Returns the name of the parent type. * * You can also return a type instance from this method, although doing so * is discouraged because it leads to a performance penalty. The support * for returning type instances may be dropped from future releases. * * @return string|null|FormTypeInterface The name of the parent type if any, null otherwise. */ public function getParent(); /** * Returns the name of this type. * * @return string The name of this type */ public function getName(); } PK!>0Symfony/Component/Form/FormRegistryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * The central registry of the Form component. * * @author Bernhard Schussek */ interface FormRegistryInterface { /** * Returns a form type by name. * * This methods registers the type extensions from the form extensions. * * @param string $name The name of the type * * @return ResolvedFormTypeInterface The type * * @throws Exception\UnexpectedTypeException if the passed name is not a string * @throws Exception\InvalidArgumentException if the type can not be retrieved from any extension */ public function getType($name); /** * Returns whether the given form type is supported. * * @param string $name The name of the type * * @return Boolean Whether the type is supported */ public function hasType($name); /** * Returns the guesser responsible for guessing types. * * @return FormTypeGuesserInterface|null */ public function getTypeGuesser(); /** * Returns the extensions loaded by the framework. * * @return FormExtensionInterface[] */ public function getExtensions(); } PK!?zz3Symfony/Component/Form/FormTypeGuesserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface FormTypeGuesserInterface { /** * Returns a field guess for a property name of a class * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\TypeGuess|null A guess for the field's type and options */ public function guessType($class, $property); /** * Returns a guess whether a property of a class is required * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\ValueGuess A guess for the field's required setting */ public function guessRequired($class, $property); /** * Returns a guess about the field's maximum length * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\ValueGuess|null A guess for the field's maximum length */ public function guessMaxLength($class, $property); /** * Returns a guess about the field's pattern * * - When you have a min value, you guess a min length of this min (LOW_CONFIDENCE) , lines below * - If this value is a float type, this is wrong so you guess null with MEDIUM_CONFIDENCE to override the previous guess. * Example: * You want a float greater than 5, 4.512313 is not valid but length(4.512314) > length(5) * @link https://github.com/symfony/symfony/pull/3927 * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\ValueGuess|null A guess for the field's required pattern */ public function guessPattern($class, $property); } PK!*+Symfony/Component/Form/ResolvedFormType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolver; /** * A wrapper for a form type and its extensions. * * @author Bernhard Schussek */ class ResolvedFormType implements ResolvedFormTypeInterface { /** * @var FormTypeInterface */ private $innerType; /** * @var FormTypeExtensionInterface[] */ private $typeExtensions; /** * @var ResolvedFormTypeInterface|null */ private $parent; /** * @var OptionsResolver */ private $optionsResolver; public function __construct(FormTypeInterface $innerType, array $typeExtensions = array(), ResolvedFormTypeInterface $parent = null) { if (!preg_match('/^[a-z0-9_]*$/i', $innerType->getName())) { throw new InvalidArgumentException(sprintf( 'The "%s" form type name ("%s") is not valid. Names must only contain letters, numbers, and "_".', get_class($innerType), $innerType->getName() )); } foreach ($typeExtensions as $extension) { if (!$extension instanceof FormTypeExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface'); } } $this->innerType = $innerType; $this->typeExtensions = $typeExtensions; $this->parent = $parent; } /** * {@inheritdoc} */ public function getName() { return $this->innerType->getName(); } /** * {@inheritdoc} */ public function getParent() { return $this->parent; } /** * {@inheritdoc} */ public function getInnerType() { return $this->innerType; } /** * {@inheritdoc} */ public function getTypeExtensions() { // BC if ($this->innerType instanceof AbstractType) { return $this->innerType->getExtensions(); } return $this->typeExtensions; } /** * {@inheritdoc} */ public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()) { $options = $this->getOptionsResolver()->resolve($options); // Should be decoupled from the specific option at some point $dataClass = isset($options['data_class']) ? $options['data_class'] : null; $builder = $this->newBuilder($name, $dataClass, $factory, $options); $builder->setType($this); return $builder; } /** * {@inheritdoc} */ public function createView(FormInterface $form, FormView $parent = null) { return $this->newView($parent); } /** * Configures a form builder for the type hierarchy. * * @param FormBuilderInterface $builder The builder to configure. * @param array $options The options used for the configuration. */ public function buildForm(FormBuilderInterface $builder, array $options) { if (null !== $this->parent) { $this->parent->buildForm($builder, $options); } $this->innerType->buildForm($builder, $options); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->buildForm($builder, $options); } } /** * Configures a form view for the type hierarchy. * * This method is called before the children of the view are built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function buildView(FormView $view, FormInterface $form, array $options) { if (null !== $this->parent) { $this->parent->buildView($view, $form, $options); } $this->innerType->buildView($view, $form, $options); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->buildView($view, $form, $options); } } /** * Finishes a form view for the type hierarchy. * * This method is called after the children of the view have been built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function finishView(FormView $view, FormInterface $form, array $options) { if (null !== $this->parent) { $this->parent->finishView($view, $form, $options); } $this->innerType->finishView($view, $form, $options); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->finishView($view, $form, $options); } } /** * Returns the configured options resolver used for this type. * * @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver. */ public function getOptionsResolver() { if (null === $this->optionsResolver) { if (null !== $this->parent) { $this->optionsResolver = clone $this->parent->getOptionsResolver(); } else { $this->optionsResolver = new OptionsResolver(); } $this->innerType->setDefaultOptions($this->optionsResolver); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->setDefaultOptions($this->optionsResolver); } } return $this->optionsResolver; } /** * Creates a new builder instance. * * Override this method if you want to customize the builder class. * * @param string $name The name of the builder. * @param string $dataClass The data class. * @param FormFactoryInterface $factory The current form factory. * @param array $options The builder options. * * @return FormBuilderInterface The new builder instance. */ protected function newBuilder($name, $dataClass, FormFactoryInterface $factory, array $options) { if ($this->innerType instanceof ButtonTypeInterface) { return new ButtonBuilder($name, $options); } if ($this->innerType instanceof SubmitButtonTypeInterface) { return new SubmitButtonBuilder($name, $options); } return new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options); } /** * Creates a new view instance. * * Override this method if you want to customize the view class. * * @param FormView|null $parent The parent view, if available. * * @return FormView A new view instance. */ protected function newView(FormView $parent = null) { return new FormView($parent); } } PK!ObXqq'Symfony/Component/Form/SubmitButton.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A button that submits the form. * * @author Bernhard Schussek */ class SubmitButton extends Button implements ClickableInterface { /** * @var Boolean */ private $clicked = false; /** * {@inheritdoc} */ public function isClicked() { return $this->clicked; } /** * Submits data to the button. * * @param null|string $submittedData The data. * @param Boolean $clearMissing Not used. * * @return SubmitButton The button instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function submit($submittedData, $clearMissing = true) { parent::submit($submittedData, $clearMissing); $this->clicked = null !== $submittedData; return $this; } } PK!p1Symfony/Component/Form/AbstractRendererEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Default implementation of {@link FormRendererEngineInterface}. * * @author Bernhard Schussek */ abstract class AbstractRendererEngine implements FormRendererEngineInterface { /** * The variable in {@link FormView} used as cache key. */ const CACHE_KEY_VAR = 'cache_key'; /** * @var array */ protected $defaultThemes; /** * @var array */ protected $themes = array(); /** * @var array */ protected $resources = array(); /** * @var array */ private $resourceHierarchyLevels = array(); /** * Creates a new renderer engine. * * @param array $defaultThemes The default themes. The type of these * themes is open to the implementation. */ public function __construct(array $defaultThemes = array()) { $this->defaultThemes = $defaultThemes; } /** * {@inheritdoc} */ public function setTheme(FormView $view, $themes) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; // Do not cast, as casting turns objects into arrays of properties $this->themes[$cacheKey] = is_array($themes) ? $themes : array($themes); // Unset instead of resetting to an empty array, in order to allow // implementations (like TwigRendererEngine) to check whether $cacheKey // is set at all. unset($this->resources[$cacheKey]); unset($this->resourceHierarchyLevels[$cacheKey]); } /** * {@inheritdoc} */ public function getResourceForBlockName(FormView $view, $blockName) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; if (!isset($this->resources[$cacheKey][$blockName])) { $this->loadResourceForBlockName($cacheKey, $view, $blockName); } return $this->resources[$cacheKey][$blockName]; } /** * {@inheritdoc} */ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, $hierarchyLevel) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; $blockName = $blockNameHierarchy[$hierarchyLevel]; if (!isset($this->resources[$cacheKey][$blockName])) { $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel); } return $this->resources[$cacheKey][$blockName]; } /** * {@inheritdoc} */ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; $blockName = $blockNameHierarchy[$hierarchyLevel]; if (!isset($this->resources[$cacheKey][$blockName])) { $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel); } // If $block was previously rendered loaded with loadTemplateForBlock(), the template // is cached but the hierarchy level is not. In this case, we know that the block // exists at this very hierarchy level, so we can just set it. if (!isset($this->resourceHierarchyLevels[$cacheKey][$blockName])) { $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel; } return $this->resourceHierarchyLevels[$cacheKey][$blockName]; } /** * Loads the cache with the resource for a given block name. * * @see getResourceForBlock() * * @param string $cacheKey The cache key of the form view. * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * * @return Boolean True if the resource could be loaded, false otherwise. */ abstract protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName); /** * Loads the cache with the resource for a specific level of a block hierarchy. * * @see getResourceForBlockHierarchy() * * @param string $cacheKey The cache key used for storing the * resource. * @param FormView $view The form view for finding the applying * themes. * @param array $blockNameHierarchy The block hierarchy, with the most * specific block name at the end. * @param integer $hierarchyLevel The level in the block hierarchy that * should be loaded. * * @return Boolean True if the resource could be loaded, false otherwise. */ private function loadResourceForBlockNameHierarchy($cacheKey, FormView $view, array $blockNameHierarchy, $hierarchyLevel) { $blockName = $blockNameHierarchy[$hierarchyLevel]; // Try to find a template for that block if ($this->loadResourceForBlockName($cacheKey, $view, $blockName)) { // If loadTemplateForBlock() returns true, it was able to populate the // cache. The only missing thing is to set the hierarchy level at which // the template was found. $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel; return true; } if ($hierarchyLevel > 0) { $parentLevel = $hierarchyLevel - 1; $parentBlockName = $blockNameHierarchy[$parentLevel]; // The next two if statements contain slightly duplicated code. This is by intention // and tries to avoid execution of unnecessary checks in order to increase performance. if (isset($this->resources[$cacheKey][$parentBlockName])) { // It may happen that the parent block is already loaded, but its level is not. // In this case, the parent block must have been loaded by loadResourceForBlock(), // which does not check the hierarchy of the block. Subsequently the block must have // been found directly on the parent level. if (!isset($this->resourceHierarchyLevels[$cacheKey][$parentBlockName])) { $this->resourceHierarchyLevels[$cacheKey][$parentBlockName] = $parentLevel; } // Cache the shortcuts for further accesses $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName]; $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName]; return true; } if ($this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $parentLevel)) { // Cache the shortcuts for further accesses $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName]; $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName]; return true; } } // Cache the result for further accesses $this->resources[$cacheKey][$blockName] = false; $this->resourceHierarchyLevels[$cacheKey][$blockName] = false; return false; } } PK!DjN,Symfony/Component/Form/AbstractExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ abstract class AbstractExtension implements FormExtensionInterface { /** * The types provided by this extension * @var FormTypeInterface[] An array of FormTypeInterface */ private $types; /** * The type extensions provided by this extension * @var FormTypeExtensionInterface[] An array of FormTypeExtensionInterface */ private $typeExtensions; /** * The type guesser provided by this extension * @var FormTypeGuesserInterface */ private $typeGuesser; /** * Whether the type guesser has been loaded * @var Boolean */ private $typeGuesserLoaded = false; /** * {@inheritdoc} */ public function getType($name) { if (null === $this->types) { $this->initTypes(); } if (!isset($this->types[$name])) { throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; } /** * {@inheritdoc} */ public function hasType($name) { if (null === $this->types) { $this->initTypes(); } return isset($this->types[$name]); } /** * {@inheritdoc} */ public function getTypeExtensions($name) { if (null === $this->typeExtensions) { $this->initTypeExtensions(); } return isset($this->typeExtensions[$name]) ? $this->typeExtensions[$name] : array(); } /** * {@inheritdoc} */ public function hasTypeExtensions($name) { if (null === $this->typeExtensions) { $this->initTypeExtensions(); } return isset($this->typeExtensions[$name]) && count($this->typeExtensions[$name]) > 0; } /** * {@inheritdoc} */ public function getTypeGuesser() { if (!$this->typeGuesserLoaded) { $this->initTypeGuesser(); } return $this->typeGuesser; } /** * Registers the types. * * @return FormTypeInterface[] An array of FormTypeInterface instances */ protected function loadTypes() { return array(); } /** * Registers the type extensions. * * @return FormTypeExtensionInterface[] An array of FormTypeExtensionInterface instances */ protected function loadTypeExtensions() { return array(); } /** * Registers the type guesser. * * @return FormTypeGuesserInterface|null A type guesser */ protected function loadTypeGuesser() { return null; } /** * Initializes the types. * * @throws UnexpectedTypeException if any registered type is not an instance of FormTypeInterface */ private function initTypes() { $this->types = array(); foreach ($this->loadTypes() as $type) { if (!$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'Symfony\Component\Form\FormTypeInterface'); } $this->types[$type->getName()] = $type; } } /** * Initializes the type extensions. * * @throws UnexpectedTypeException if any registered type extension is not * an instance of FormTypeExtensionInterface */ private function initTypeExtensions() { $this->typeExtensions = array(); foreach ($this->loadTypeExtensions() as $extension) { if (!$extension instanceof FormTypeExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface'); } $type = $extension->getExtendedType(); $this->typeExtensions[$type][] = $extension; } } /** * Initializes the type guesser. * * @throws UnexpectedTypeException if the type guesser is not an instance of FormTypeGuesserInterface */ private function initTypeGuesser() { $this->typeGuesserLoaded = true; $this->typeGuesser = $this->loadTypeGuesser(); if (null !== $this->typeGuesser && !$this->typeGuesser instanceof FormTypeGuesserInterface) { throw new UnexpectedTypeException($this->typeGuesser, 'Symfony\Component\Form\FormTypeGuesserInterface'); } } } PK!f#jK6Symfony/Component/Form/FormRendererEngineInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Adapter for rendering form templates with a specific templating engine. * * @author Bernhard Schussek */ interface FormRendererEngineInterface { /** * Sets the theme(s) to be used for rendering a view and its children. * * @param FormView $view The view to assign the theme(s) to. * @param mixed $themes The theme(s). The type of these themes * is open to the implementation. */ public function setTheme(FormView $view, $themes); /** * Returns the resource for a block name. * * The resource is first searched in the themes attached to $view, then * in the themes of its parent view and so on, until a resource was found. * * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * * @param FormView $view The view for determining the used themes. * First the themes attached directly to the * view with {@link setTheme()} are considered, * then the ones of its parent etc. * @param string $blockName The name of the block to render. * * @return mixed The renderer resource or false, if none was found. */ public function getResourceForBlockName(FormView $view, $blockName); /** * Returns the resource for a block hierarchy. * * A block hierarchy is an array which starts with the root of the hierarchy * and continues with the child of that root, the child of that child etc. * The following is an example for a block hierarchy: * * * form_widget * text_widget * url_widget * * * In this example, "url_widget" is the most specific block, while the other * blocks are its ancestors in the hierarchy. * * The second parameter $hierarchyLevel determines the level of the hierarchy * that should be rendered. For example, if $hierarchyLevel is 2 for the * above hierarchy, the engine will first look for the block "url_widget", * then, if that does not exist, for the block "text_widget" etc. * * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * * @param FormView $view The view for determining the * used themes. First the themes * attached directly to the view * with {@link setTheme()} are * considered, then the ones of * its parent etc. * @param array $blockNameHierarchy The block name hierarchy, with * the root block at the beginning. * @param integer $hierarchyLevel The level in the hierarchy at * which to start looking. Level 0 * indicates the root block, i.e. * the first element of * $blockNameHierarchy. * * @return mixed The renderer resource or false, if none was found. */ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, $hierarchyLevel); /** * Returns the hierarchy level at which a resource can be found. * * A block hierarchy is an array which starts with the root of the hierarchy * and continues with the child of that root, the child of that child etc. * The following is an example for a block hierarchy: * * * form_widget * text_widget * url_widget * * * The second parameter $hierarchyLevel determines the level of the hierarchy * that should be rendered. * * If we call this method with the hierarchy level 2, the engine will first * look for a resource for block "url_widget". If such a resource exists, * the method returns 2. Otherwise it tries to find a resource for block * "text_widget" (at level 1) and, again, returns 1 if a resource was found. * The method continues to look for resources until the root level was * reached and nothing was found. In this case false is returned. * * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * * @param FormView $view The view for determining the * used themes. First the themes * attached directly to the view * with {@link setTheme()} are * considered, then the ones of * its parent etc. * @param array $blockNameHierarchy The block name hierarchy, with * the root block at the beginning. * @param integer $hierarchyLevel The level in the hierarchy at * which to start looking. Level 0 * indicates the root block, i.e. * the first element of * $blockNameHierarchy. * * @return integer|Boolean The hierarchy level or false, if no resource was found. */ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel); /** * Renders a block in the given renderer resource. * * The resource can be obtained by calling {@link getResourceForBlock()} * or {@link getResourceForBlockHierarchy()}. The type of the resource is * decided by the implementation. * * @param FormView $view The view to render. * @param mixed $resource The renderer resource. * @param string $blockName The name of the block to render. * @param array $variables The variables to pass to the template. * * @return string The HTML markup. */ public function renderBlock(FormView $view, $resource, $blockName, array $variables = array()); } PK!11Symfony/Component/Form/Form.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\RuntimeException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\AlreadySubmittedException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\Form\Util\FormUtil; use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\Form\Util\OrderedHashMap; use Symfony\Component\PropertyAccess\PropertyPath; /** * Form represents a form. * * To implement your own form fields, you need to have a thorough understanding * of the data flow within a form. A form stores its data in three different * representations: * * (1) the "model" format required by the form's object * (2) the "normalized" format for internal processing * (3) the "view" format used for display * * A date field, for example, may store a date as "Y-m-d" string (1) in the * object. To facilitate processing in the field, this value is normalized * to a DateTime object (2). In the HTML representation of your form, a * localized string (3) is presented to and modified by the user. * * In most cases, format (1) and format (2) will be the same. For example, * a checkbox field uses a Boolean value for both internal processing and * storage in the object. In these cases you simply need to set a value * transformer to convert between formats (2) and (3). You can do this by * calling addViewTransformer(). * * In some cases though it makes sense to make format (1) configurable. To * demonstrate this, let's extend our above date field to store the value * either as "Y-m-d" string or as timestamp. Internally we still want to * use a DateTime object for processing. To convert the data from string/integer * to DateTime you can set a normalization transformer by calling * addNormTransformer(). The normalized data is then converted to the displayed * data as described before. * * The conversions (1) -> (2) -> (3) use the transform methods of the transformers. * The conversions (3) -> (2) -> (1) use the reverseTransform methods of the transformers. * * @author Fabien Potencier * @author Bernhard Schussek */ class Form implements \IteratorAggregate, FormInterface { /** * The form's configuration * @var FormConfigInterface */ private $config; /** * The parent of this form * @var FormInterface */ private $parent; /** * The children of this form * @var FormInterface[] A map of FormInterface instances */ private $children; /** * The errors of this form * @var FormError[] An array of FormError instances */ private $errors = array(); /** * Whether this form was submitted * @var Boolean */ private $submitted = false; /** * The button that was used to submit the form * @var Button */ private $clickedButton; /** * The form data in model format * @var mixed */ private $modelData; /** * The form data in normalized format * @var mixed */ private $normData; /** * The form data in view format * @var mixed */ private $viewData; /** * The submitted values that don't belong to any children * @var array */ private $extraData = array(); /** * Whether the data in model, normalized and view format is * synchronized. Data may not be synchronized if transformation errors * occur. * @var Boolean */ private $synchronized = true; /** * Whether the form's data has been initialized. * * When the data is initialized with its default value, that default value * is passed through the transformer chain in order to synchronize the * model, normalized and view format for the first time. This is done * lazily in order to save performance when {@link setData()} is called * manually, making the initialization with the configured default value * superfluous. * * @var Boolean */ private $defaultDataSet = false; /** * Whether setData() is currently being called. * @var Boolean */ private $lockSetData = false; /** * Creates a new form based on the given configuration. * * @param FormConfigInterface $config The form configuration. * * @throws LogicException if a data mapper is not provided for a compound form */ public function __construct(FormConfigInterface $config) { // Compound forms always need a data mapper, otherwise calls to // `setData` and `add` will not lead to the correct population of // the child forms. if ($config->getCompound() && !$config->getDataMapper()) { throw new LogicException('Compound forms need a data mapper'); } // If the form inherits the data from its parent, it is not necessary // to call setData() with the default data. if ($config->getInheritData()) { $this->defaultDataSet = true; } $this->config = $config; $this->children = new OrderedHashMap(); } public function __clone() { $this->children = clone $this->children; foreach ($this->children as $key => $child) { $this->children[$key] = clone $child; } } /** * {@inheritdoc} */ public function getConfig() { return $this->config; } /** * {@inheritdoc} */ public function getName() { return $this->config->getName(); } /** * {@inheritdoc} */ public function getPropertyPath() { if (null !== $this->config->getPropertyPath()) { return $this->config->getPropertyPath(); } if (null === $this->getName() || '' === $this->getName()) { return null; } $parent = $this->parent; while ($parent && $parent->getConfig()->getInheritData()) { $parent = $parent->getParent(); } if ($parent && null === $parent->getConfig()->getDataClass()) { return new PropertyPath('['.$this->getName().']'); } return new PropertyPath($this->getName()); } /** * {@inheritdoc} */ public function isRequired() { if (null === $this->parent || $this->parent->isRequired()) { return $this->config->getRequired(); } return false; } /** * {@inheritDoc} */ public function isDisabled() { if (null === $this->parent || !$this->parent->isDisabled()) { return $this->config->getDisabled(); } return true; } /** * {@inheritdoc} */ public function setParent(FormInterface $parent = null) { if ($this->submitted) { throw new AlreadySubmittedException('You cannot set the parent of a submitted form'); } if (null !== $parent && '' === $this->config->getName()) { throw new LogicException('A form with an empty name cannot have a parent form.'); } $this->parent = $parent; return $this; } /** * {@inheritdoc} */ public function getParent() { return $this->parent; } /** * {@inheritdoc} */ public function getRoot() { return $this->parent ? $this->parent->getRoot() : $this; } /** * {@inheritdoc} */ public function isRoot() { return null === $this->parent; } /** * {@inheritdoc} */ public function setData($modelData) { // If the form is submitted while disabled, it is set to submitted, but the data is not // changed. In such cases (i.e. when the form is not initialized yet) don't // abort this method. if ($this->submitted && $this->defaultDataSet) { throw new AlreadySubmittedException('You cannot change the data of a submitted form.'); } // If the form inherits its parent's data, disallow data setting to // prevent merge conflicts if ($this->config->getInheritData()) { throw new RuntimeException('You cannot change the data of a form inheriting its parent data.'); } // Don't allow modifications of the configured data if the data is locked if ($this->config->getDataLocked() && $modelData !== $this->config->getData()) { return $this; } if (is_object($modelData) && !$this->config->getByReference()) { $modelData = clone $modelData; } if ($this->lockSetData) { throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.'); } $this->lockSetData = true; $dispatcher = $this->config->getEventDispatcher(); // Hook to change content of the data if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA)) { $event = new FormEvent($this, $modelData); $dispatcher->dispatch(FormEvents::PRE_SET_DATA, $event); $modelData = $event->getData(); } // Treat data as strings unless a value transformer exists if (!$this->config->getViewTransformers() && !$this->config->getModelTransformers() && is_scalar($modelData)) { $modelData = (string) $modelData; } // Synchronize representations - must not change the content! $normData = $this->modelToNorm($modelData); $viewData = $this->normToView($normData); // Validate if view data matches data class (unless empty) if (!FormUtil::isEmpty($viewData)) { $dataClass = $this->config->getDataClass(); $actualType = is_object($viewData) ? 'an instance of class '.get_class($viewData) : ' a(n) '.gettype($viewData); if (null === $dataClass && is_object($viewData) && !$viewData instanceof \ArrayAccess) { $expectedType = 'scalar, array or an instance of \ArrayAccess'; throw new LogicException( 'The form\'s view data is expected to be of type '.$expectedType.', ' . 'but is '.$actualType.'. You ' . 'can avoid this error by setting the "data_class" option to ' . '"'.get_class($viewData).'" or by adding a view transformer ' . 'that transforms '.$actualType.' to '.$expectedType.'.' ); } if (null !== $dataClass && !$viewData instanceof $dataClass) { throw new LogicException( 'The form\'s view data is expected to be an instance of class ' . $dataClass.', but is '. $actualType.'. You can avoid this error ' . 'by setting the "data_class" option to null or by adding a view ' . 'transformer that transforms '.$actualType.' to an instance of ' . $dataClass.'.' ); } } $this->modelData = $modelData; $this->normData = $normData; $this->viewData = $viewData; $this->defaultDataSet = true; $this->lockSetData = false; // It is not necessary to invoke this method if the form doesn't have children, // even if the form is compound. if (count($this->children) > 0) { // Update child forms from the data $iterator = new InheritDataAwareIterator($this->children); $iterator = new \RecursiveIteratorIterator($iterator); $this->config->getDataMapper()->mapDataToForms($viewData, $iterator); } if ($dispatcher->hasListeners(FormEvents::POST_SET_DATA)) { $event = new FormEvent($this, $modelData); $dispatcher->dispatch(FormEvents::POST_SET_DATA, $event); } return $this; } /** * {@inheritdoc} */ public function getData() { if ($this->config->getInheritData()) { if (!$this->parent) { throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); } return $this->parent->getData(); } if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this->modelData; } /** * {@inheritdoc} */ public function getNormData() { if ($this->config->getInheritData()) { if (!$this->parent) { throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); } return $this->parent->getNormData(); } if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this->normData; } /** * {@inheritdoc} */ public function getViewData() { if ($this->config->getInheritData()) { if (!$this->parent) { throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); } return $this->parent->getViewData(); } if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this->viewData; } /** * {@inheritdoc} */ public function getExtraData() { return $this->extraData; } /** * {@inheritdoc} */ public function initialize() { if (null !== $this->parent) { throw new RuntimeException('Only root forms should be initialized.'); } // Guarantee that the *_SET_DATA events have been triggered once the // form is initialized. This makes sure that dynamically added or // removed fields are already visible after initialization. if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this; } /** * {@inheritdoc} */ public function handleRequest($request = null) { $this->config->getRequestHandler()->handleRequest($this, $request); return $this; } /** * {@inheritdoc} */ public function submit($submittedData, $clearMissing = true) { if ($this->submitted) { throw new AlreadySubmittedException('A form can only be submitted once'); } // Initialize errors in the very beginning so that we don't lose any // errors added during listeners $this->errors = array(); // Obviously, a disabled form should not change its data upon submission. if ($this->isDisabled()) { $this->submitted = true; return $this; } // The data must be initialized if it was not initialized yet. // This is necessary to guarantee that the *_SET_DATA listeners // are always invoked before submit() takes place. if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } // Treat false as NULL to support binding false to checkboxes. // Don't convert NULL to a string here in order to determine later // whether an empty value has been submitted or whether no value has // been submitted at all. This is important for processing checkboxes // and radio buttons with empty values. if (false === $submittedData) { $submittedData = null; } elseif (is_scalar($submittedData)) { $submittedData = (string) $submittedData; } $dispatcher = $this->config->getEventDispatcher(); $modelData = null; $normData = null; $viewData = null; try { // Hook to change content of the data submitted by the browser if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { $event = new FormEvent($this, $submittedData); $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event); $submittedData = $event->getData(); } // Check whether the form is compound. // This check is preferable over checking the number of children, // since forms without children may also be compound. // (think of empty collection forms) if ($this->config->getCompound()) { if (null === $submittedData) { $submittedData = array(); } if (!is_array($submittedData)) { throw new TransformationFailedException('Compound forms expect an array or NULL on submission.'); } foreach ($this->children as $name => $child) { if (array_key_exists($name, $submittedData) || $clearMissing) { $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); unset($submittedData[$name]); if (null !== $this->clickedButton) { continue; } if ($child instanceof ClickableInterface && $child->isClicked()) { $this->clickedButton = $child; continue; } if (method_exists($child, 'getClickedButton') && null !== $child->getClickedButton()) { $this->clickedButton = $child->getClickedButton(); } } } $this->extraData = $submittedData; } // Forms that inherit their parents' data also are not processed, // because then it would be too difficult to merge the changes in // the child and the parent form. Instead, the parent form also takes // changes in the grandchildren (i.e. children of the form that inherits // its parent's data) into account. // (see InheritDataAwareIterator below) if (!$this->config->getInheritData()) { // If the form is compound, the default data in view format // is reused. The data of the children is merged into this // default data using the data mapper. // If the form is not compound, the submitted data is also the data in view format. $viewData = $this->config->getCompound() ? $this->viewData : $submittedData; if (FormUtil::isEmpty($viewData)) { $emptyData = $this->config->getEmptyData(); if ($emptyData instanceof \Closure) { /* @var \Closure $emptyData */ $emptyData = $emptyData($this, $viewData); } $viewData = $emptyData; } // Merge form data from children into existing view data // It is not necessary to invoke this method if the form has no children, // even if it is compound. if (count($this->children) > 0) { // Use InheritDataAwareIterator to process children of // descendants that inherit this form's data. // These descendants will not be submitted normally (see the check // for $this->config->getInheritData() above) $childrenIterator = new InheritDataAwareIterator($this->children); $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); $this->config->getDataMapper()->mapFormsToData($childrenIterator, $viewData); } // Normalize data to unified representation $normData = $this->viewToNorm($viewData); // Hook to change content of the data in the normalized // representation if ($dispatcher->hasListeners(FormEvents::SUBMIT)) { $event = new FormEvent($this, $normData); $dispatcher->dispatch(FormEvents::SUBMIT, $event); $normData = $event->getData(); } // Synchronize representations - must not change the content! $modelData = $this->normToModel($normData); $viewData = $this->normToView($normData); } } catch (TransformationFailedException $e) { $this->synchronized = false; // If $viewData was not yet set, set it to $submittedData so that // the erroneous data is accessible on the form. // Forms that inherit data never set any data, because the getters // forward to the parent form's getters anyway. if (null === $viewData && !$this->config->getInheritData()) { $viewData = $submittedData; } } $this->submitted = true; $this->modelData = $modelData; $this->normData = $normData; $this->viewData = $viewData; if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) { $event = new FormEvent($this, $viewData); $dispatcher->dispatch(FormEvents::POST_SUBMIT, $event); } return $this; } /** * Alias of {@link submit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link submit()} instead. */ public function bind($submittedData) { return $this->submit($submittedData); } /** * {@inheritdoc} */ public function addError(FormError $error) { if ($this->parent && $this->config->getErrorBubbling()) { $this->parent->addError($error); } else { $this->errors[] = $error; } return $this; } /** * {@inheritdoc} */ public function isSubmitted() { return $this->submitted; } /** * Alias of {@link isSubmitted()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link isSubmitted()} instead. */ public function isBound() { return $this->submitted; } /** * {@inheritdoc} */ public function isSynchronized() { return $this->synchronized; } /** * {@inheritdoc} */ public function isEmpty() { foreach ($this->children as $child) { if (!$child->isEmpty()) { return false; } } return FormUtil::isEmpty($this->modelData) || // arrays, countables 0 === count($this->modelData) || // traversables that are not countable ($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData)); } /** * {@inheritdoc} */ public function isValid() { if (!$this->submitted) { return false; } if (count($this->errors) > 0) { return false; } if ($this->isDisabled()) { return true; } foreach ($this->children as $child) { if ($child->isSubmitted() && !$child->isValid()) { return false; } } return true; } /** * Returns the button that was used to submit the form. * * @return Button|null The clicked button or NULL if the form was not * submitted */ public function getClickedButton() { if ($this->clickedButton) { return $this->clickedButton; } if ($this->parent && method_exists($this->parent, 'getClickedButton')) { return $this->parent->getClickedButton(); } return null; } /** * {@inheritdoc} */ public function getErrors() { return $this->errors; } /** * Returns a string representation of all form errors (including children errors). * * This method should only be used to help debug a form. * * @param integer $level The indentation level (used internally) * * @return string A string representation of all errors */ public function getErrorsAsString($level = 0) { $errors = ''; foreach ($this->errors as $error) { $errors .= str_repeat(' ', $level).'ERROR: '.$error->getMessage()."\n"; } foreach ($this->children as $key => $child) { $errors .= str_repeat(' ', $level).$key.":\n"; if ($child instanceof self && $err = $child->getErrorsAsString($level + 4)) { $errors .= $err; } else { $errors .= str_repeat(' ', $level + 4)."No errors\n"; } } return $errors; } /** * {@inheritdoc} */ public function all() { return iterator_to_array($this->children); } /** * {@inheritdoc} */ public function add($child, $type = null, array $options = array()) { if ($this->submitted) { throw new AlreadySubmittedException('You cannot add children to a submitted form'); } if (!$this->config->getCompound()) { throw new LogicException('You cannot add children to a simple form. Maybe you should set the option "compound" to true?'); } // Obtain the view data $viewData = null; // If setData() is currently being called, there is no need to call // mapDataToForms() here, as mapDataToForms() is called at the end // of setData() anyway. Not doing this check leads to an endless // recursion when initializing the form lazily and an event listener // (such as ResizeFormListener) adds fields depending on the data: // // * setData() is called, the form is not initialized yet // * add() is called by the listener (setData() is not complete, so // the form is still not initialized) // * getViewData() is called // * setData() is called since the form is not initialized yet // * ... endless recursion ... // // Also skip data mapping if setData() has not been called yet. // setData() will be called upon form initialization and data mapping // will take place by then. if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { $viewData = $this->getViewData(); } if (!$child instanceof FormInterface) { if (!is_string($child) && !is_int($child)) { throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormInterface'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); } // Never initialize child forms automatically $options['auto_initialize'] = false; if (null === $type) { $child = $this->config->getFormFactory()->createForProperty($this->config->getDataClass(), $child, null, $options); } else { $child = $this->config->getFormFactory()->createNamed($child, $type, null, $options); } } elseif ($child->getConfig()->getAutoInitialize()) { throw new RuntimeException(sprintf( 'Automatic initialization is only supported on root forms. You '. 'should set the "auto_initialize" option to false on the field "%s".', $child->getName() )); } $this->children[$child->getName()] = $child; $child->setParent($this); if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { $iterator = new InheritDataAwareIterator(new \ArrayIterator(array($child))); $iterator = new \RecursiveIteratorIterator($iterator); $this->config->getDataMapper()->mapDataToForms($viewData, $iterator); } return $this; } /** * {@inheritdoc} */ public function remove($name) { if ($this->submitted) { throw new AlreadySubmittedException('You cannot remove children from a submitted form'); } if (isset($this->children[$name])) { $this->children[$name]->setParent(null); unset($this->children[$name]); } return $this; } /** * {@inheritdoc} */ public function has($name) { return isset($this->children[$name]); } /** * {@inheritdoc} */ public function get($name) { if (isset($this->children[$name])) { return $this->children[$name]; } throw new OutOfBoundsException(sprintf('Child "%s" does not exist.', $name)); } /** * Returns whether a child with the given name exists (implements the \ArrayAccess interface). * * @param string $name The name of the child * * @return Boolean */ public function offsetExists($name) { return $this->has($name); } /** * Returns the child with the given name (implements the \ArrayAccess interface). * * @param string $name The name of the child * * @return FormInterface The child form * * @throws \OutOfBoundsException If the named child does not exist. */ public function offsetGet($name) { return $this->get($name); } /** * Adds a child to the form (implements the \ArrayAccess interface). * * @param string $name Ignored. The name of the child is used. * @param FormInterface $child The child to be added. * * @throws AlreadySubmittedException If the form has already been submitted. * @throws LogicException When trying to add a child to a non-compound form. * * @see self::add() */ public function offsetSet($name, $child) { $this->add($child); } /** * Removes the child with the given name from the form (implements the \ArrayAccess interface). * * @param string $name The name of the child to remove * * @throws AlreadySubmittedException If the form has already been submitted. */ public function offsetUnset($name) { $this->remove($name); } /** * Returns the iterator for this group. * * @return \Traversable */ public function getIterator() { return $this->children; } /** * Returns the number of form children (implements the \Countable interface). * * @return integer The number of embedded form children */ public function count() { return count($this->children); } /** * {@inheritdoc} */ public function createView(FormView $parent = null) { if (null === $parent && $this->parent) { $parent = $this->parent->createView(); } $type = $this->config->getType(); $options = $this->config->getOptions(); // The methods createView(), buildView() and finishView() are called // explicitly here in order to be able to override either of them // in a custom resolved form type. $view = $type->createView($this, $parent); $type->buildView($view, $this, $options); foreach ($this->children as $name => $child) { $view->children[$name] = $child->createView($view); } $type->finishView($view, $this, $options); return $view; } /** * Normalizes the value if a normalization transformer is set. * * @param mixed $value The value to transform * * @return mixed */ private function modelToNorm($value) { foreach ($this->config->getModelTransformers() as $transformer) { $value = $transformer->transform($value); } return $value; } /** * Reverse transforms a value if a normalization transformer is set. * * @param string $value The value to reverse transform * * @return mixed */ private function normToModel($value) { $transformers = $this->config->getModelTransformers(); for ($i = count($transformers) - 1; $i >= 0; --$i) { $value = $transformers[$i]->reverseTransform($value); } return $value; } /** * Transforms the value if a value transformer is set. * * @param mixed $value The value to transform * * @return mixed */ private function normToView($value) { // Scalar values should be converted to strings to // facilitate differentiation between empty ("") and zero (0). // Only do this for simple forms, as the resulting value in // compound forms is passed to the data mapper and thus should // not be converted to a string before. if (!$this->config->getViewTransformers() && !$this->config->getCompound()) { return null === $value || is_scalar($value) ? (string) $value : $value; } foreach ($this->config->getViewTransformers() as $transformer) { $value = $transformer->transform($value); } return $value; } /** * Reverse transforms a value if a value transformer is set. * * @param string $value The value to reverse transform * * @return mixed */ private function viewToNorm($value) { $transformers = $this->config->getViewTransformers(); if (!$transformers) { return '' === $value ? null : $value; } for ($i = count($transformers) - 1; $i >= 0; --$i) { $value = $transformers[$i]->reverseTransform($value); } return $value; } } PK!di;Symfony/Component/Form/Exception/BadMethodCallException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base BadMethodCallException for the Form component. * * @author Bernhard Schussek */ class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface { } PK!W  :Symfony/Component/Form/Exception/AlreadyBoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Alias of {@link AlreadySubmittedException}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link AlreadySubmittedException} instead. */ class AlreadyBoundException extends LogicException { } PK!(ddBSymfony/Component/Form/Exception/InvalidConfigurationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class InvalidConfigurationException extends InvalidArgumentException { } PK!_c==<Symfony/Component/Form/Exception/UnexpectedTypeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class UnexpectedTypeException extends InvalidArgumentException { public function __construct($value, $expectedType) { parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value))); } } PK!SDBSymfony/Component/Form/Exception/TransformationFailedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Indicates a value transformation error. * * @author Bernhard Schussek */ class TransformationFailedException extends RuntimeException { } PK!é9Symfony/Component/Form/Exception/OutOfBoundsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base OutOfBoundsException for Form component. * * @author Alexander Kotynia */ class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface { } PK!yu7Symfony/Component/Form/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base ExceptionInterface for the Form component. * * @author Bernhard Schussek */ interface ExceptionInterface { } PK!N5Symfony/Component/Form/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base RuntimeException for the Form component. * * @author Bernhard Schussek */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK!K9>Symfony/Component/Form/Exception/AlreadySubmittedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Thrown when an operation is called that is not acceptable after submitting * a form. * * @author Bernhard Schussek */ class AlreadySubmittedException extends AlreadyBoundException { } PK!1;TT:Symfony/Component/Form/Exception/ErrorMappingException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class ErrorMappingException extends RuntimeException { } PK!+RR8Symfony/Component/Form/Exception/StringCastException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class StringCastException extends RuntimeException { } PK!X3Symfony/Component/Form/Exception/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base LogicException for Form component. * * @author Alexander Kotynia */ class LogicException extends \LogicException implements ExceptionInterface { } PK!gBz=Symfony/Component/Form/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base InvalidArgumentException for the Form component. * * @author Bernhard Schussek */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK!188'Symfony/Component/Form/AbstractType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ abstract class AbstractType implements FormTypeInterface { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { } /** * {@inheritdoc} */ public function getParent() { return 'form'; } } PK!I 66.Symfony/Component/Form/Util/OrderedHashMap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * A hash map which keeps track of deletions and additions. * * Like in associative arrays, elements can be mapped to integer or string keys. * Unlike associative arrays, the map keeps track of the order in which keys * were added and removed. This order is reflected during iteration. * * The map supports concurrent modification during iteration. That means that * you can insert and remove elements from within a foreach loop and the * iterator will reflect those changes accordingly. * * While elements that are added during the loop are recognized by the iterator, * changed elements are not. Otherwise the loop could be infinite if each loop * changes the current element: * * $map = new OrderedHashMap(); * $map[1] = 1; * $map[2] = 2; * $map[3] = 3; * * foreach ($map as $index => $value) { * echo "$index: $value\n" * if (1 === $index) { * $map[1] = 4; * $map[] = 5; * } * } * * print_r(iterator_to_array($map)); * * // => 1: 1 * // 2: 2 * // 3: 3 * // 4: 5 * // Array * // ( * // [1] => 4 * // [2] => 2 * // [3] => 3 * // [4] => 5 * // ) * * The map also supports multiple parallel iterators. That means that you can * nest foreach loops without affecting each other's iteration: * * foreach ($map as $index => $value) { * foreach ($map as $index2 => $value2) { * // ... * } * } * * @author Bernhard Schussek * * @since 2.2.6 */ class OrderedHashMap implements \ArrayAccess, \IteratorAggregate, \Countable { /** * The elements of the map, indexed by their keys. * * @var array */ private $elements = array(); /** * The keys of the map in the order in which they were inserted or changed. * * @var array */ private $orderedKeys = array(); /** * References to the cursors of all open iterators. * * @var array */ private $managedCursors = array(); /** * Creates a new map. * * @param array $elements The elements to insert initially. * * @since 2.2.6 */ public function __construct(array $elements = array()) { $this->elements = $elements; $this->orderedKeys = array_keys($elements); } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetExists($key) { return isset($this->elements[$key]); } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetGet($key) { if (!isset($this->elements[$key])) { throw new \OutOfBoundsException('The offset "' . $key . '" does not exist.'); } return $this->elements[$key]; } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetSet($key, $value) { if (null === $key || !isset($this->elements[$key])) { if (null === $key) { $key = array() === $this->orderedKeys // If the array is empty, use 0 as key ? 0 // Imitate PHP's behavior of generating a key that equals // the highest existing integer key + 1 : max($this->orderedKeys) + 1; } $this->orderedKeys[] = $key; } $this->elements[$key] = $value; } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetUnset($key) { if (false !== ($position = array_search($key, $this->orderedKeys))) { array_splice($this->orderedKeys, $position, 1); unset($this->elements[$key]); foreach ($this->managedCursors as $i => $cursor) { if ($cursor >= $position) { --$this->managedCursors[$i]; } } } } /** * {@inheritdoc} * * @since 2.2.6 */ public function getIterator() { return new OrderedHashMapIterator($this->elements, $this->orderedKeys, $this->managedCursors); } /** * {@inheritdoc} * * @since 2.2.6 */ public function count() { return count($this->elements); } } PK!h''6Symfony/Component/Form/Util/OrderedHashMapIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * Iterator for {@link OrderedHashMap} objects. * * This class is internal and should not be used. * * @author Bernhard Schussek * * @since 2.2.6 */ class OrderedHashMapIterator implements \Iterator { /** * @var array */ private $elements; /** * @var array */ private $orderedKeys; /** * @var integer */ private $cursor; /** * @var integer */ private $cursorId; /** * @var array */ private $managedCursors; /** * @var string|integer|null */ private $key; /** * @var mixed */ private $current; /** * Creates a new iterator. * * @param array $elements The elements of the map, indexed by their * keys. * @param array $orderedKeys The keys of the map in the order in which * they should be iterated. * @param array $managedCursors An array from which to reference the * iterator's cursor as long as it is alive. * This array is managed by the corresponding * {@link OrderedHashMap} instance to support * recognizing the deletion of elements. * * @since 2.2.6 */ public function __construct(array &$elements, array &$orderedKeys, array &$managedCursors) { $this->elements = &$elements; $this->orderedKeys = &$orderedKeys; $this->managedCursors = &$managedCursors; $this->cursorId = count($managedCursors); $this->managedCursors[$this->cursorId] = &$this->cursor; } /** * Removes the iterator's cursors from the managed cursors of the * corresponding {@link OrderedHashMap} instance. * * @since 2.2.6 */ public function __destruct() { // Use array_splice() instead of isset() to prevent holes in the // array indices, which would break the initialization of $cursorId array_splice($this->managedCursors, $this->cursorId, 1); } /** *{@inheritdoc} * * @since 2.2.6 */ public function current() { return $this->current; } /** * {@inheritdoc} * * @since 2.2.6 */ public function next() { ++$this->cursor; if (isset($this->orderedKeys[$this->cursor])) { $this->key = $this->orderedKeys[$this->cursor]; $this->current = $this->elements[$this->key]; } else { $this->key = null; $this->current = null; } } /** *{@inheritdoc} * * @since 2.2.6 */ public function key() { return $this->key; } /** *{@inheritdoc} * * @since 2.2.6 */ public function valid() { return null !== $this->key; } /** *{@inheritdoc} * * @since 2.2.6 */ public function rewind() { $this->cursor = 0; if (isset($this->orderedKeys[0])) { $this->key = $this->orderedKeys[0]; $this->current = $this->elements[$this->key]; } else { $this->key = null; $this->current = null; } } } PK!F228Symfony/Component/Form/Util/VirtualFormAwareIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * Iterator that traverses an array of forms. * * You can wrap the iterator into a {@link \RecursiveIterator} in order to * enter any child form that inherits its parent's data and iterate the children * of that form as well. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link InheritDataAwareIterator} instead. */ class VirtualFormAwareIterator extends \IteratorIterator implements \RecursiveIterator { /** * {@inheritdoc} */ public function getChildren() { return new static($this->current()); } /** *{@inheritdoc} */ public function hasChildren() { return (bool) $this->current()->getConfig()->getInheritData(); } } PK!y$$(Symfony/Component/Form/Util/FormUtil.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * @author Bernhard Schussek */ class FormUtil { /** * This class should not be instantiated */ private function __construct() {} /** * Returns whether the given data is empty. * * This logic is reused multiple times throughout the processing of * a form and needs to be consistent. PHP's keyword `empty` cannot * be used as it also considers 0 and "0" to be empty. * * @param mixed $data * * @return Boolean */ public static function isEmpty($data) { // Should not do a check for array() === $data!!! // This method is used in occurrences where arrays are // not considered to be empty, ever. return null === $data || '' === $data; } } PK!<8Symfony/Component/Form/Util/InheritDataAwareIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * Iterator that traverses an array of forms. * * Contrary to \ArrayIterator, this iterator recognizes changes in the original * array during iteration. * * You can wrap the iterator into a {@link \RecursiveIterator} in order to * enter any child form that inherits its parent's data and iterate the children * of that form as well. * * @author Bernhard Schussek */ class InheritDataAwareIterator extends VirtualFormAwareIterator { } PK!QTpp.Symfony/Component/Form/SubmitButtonBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A builder for {@link SubmitButton} instances. * * @author Bernhard Schussek */ class SubmitButtonBuilder extends ButtonBuilder { /** * Creates the button. * * @return SubmitButton The button */ public function getForm() { return new SubmitButton($this->getFormConfig()); } } PK!z52Symfony/Component/Form/ResolvedFormTypeFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ class ResolvedFormTypeFactory implements ResolvedFormTypeFactoryInterface { /** * {@inheritdoc} */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null) { return new ResolvedFormType($type, $typeExtensions, $parent); } } PK!Sf -Symfony/Component/Form/PreloadedExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * A form extension with preloaded types, type exceptions and type guessers. * * @author Bernhard Schussek */ class PreloadedExtension implements FormExtensionInterface { /** * @var array */ private $types = array(); /** * @var array */ private $typeExtensions = array(); /** * @var FormTypeGuesserInterface */ private $typeGuesser; /** * Creates a new preloaded extension. * * @param FormTypeInterface[] $types The types that the extension should support. * @param array[FormTypeExtensionInterface[]] typeExtensions The type extensions that the extension should support. * @param FormTypeGuesserInterface|null $typeGuesser The guesser that the extension should support. */ public function __construct(array $types, array $typeExtensions, FormTypeGuesserInterface $typeGuesser = null) { $this->types = $types; $this->typeExtensions = $typeExtensions; $this->typeGuesser = $typeGuesser; } /** * {@inheritdoc} */ public function getType($name) { if (!isset($this->types[$name])) { throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; } /** * {@inheritdoc} */ public function hasType($name) { return isset($this->types[$name]); } /** * {@inheritdoc} */ public function getTypeExtensions($name) { return isset($this->typeExtensions[$name]) ? $this->typeExtensions[$name] : array(); } /** * {@inheritdoc} */ public function hasTypeExtensions($name) { return !empty($this->typeExtensions[$name]); } /** * {@inheritdoc} */ public function getTypeGuesser() { return $this->typeGuesser; } } PK!>*ii&Symfony/Component/Form/FormFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; class FormFactory implements FormFactoryInterface { /** * @var FormRegistryInterface */ private $registry; /** * @var ResolvedFormTypeFactoryInterface */ private $resolvedTypeFactory; public function __construct(FormRegistryInterface $registry, ResolvedFormTypeFactoryInterface $resolvedTypeFactory) { $this->registry = $registry; $this->resolvedTypeFactory = $resolvedTypeFactory; } /** * {@inheritdoc} */ public function create($type = 'form', $data = null, array $options = array()) { return $this->createBuilder($type, $data, $options)->getForm(); } /** * {@inheritdoc} */ public function createNamed($name, $type = 'form', $data = null, array $options = array()) { return $this->createNamedBuilder($name, $type, $data, $options)->getForm(); } /** * {@inheritdoc} */ public function createForProperty($class, $property, $data = null, array $options = array()) { return $this->createBuilderForProperty($class, $property, $data, $options)->getForm(); } /** * {@inheritdoc} */ public function createBuilder($type = 'form', $data = null, array $options = array()) { $name = $type instanceof FormTypeInterface || $type instanceof ResolvedFormTypeInterface ? $type->getName() : $type; return $this->createNamedBuilder($name, $type, $data, $options); } /** * {@inheritdoc} */ public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array()) { if (null !== $data && !array_key_exists('data', $options)) { $options['data'] = $data; } if ($type instanceof FormTypeInterface) { $type = $this->resolveType($type); } elseif (is_string($type)) { $type = $this->registry->getType($type); } elseif (!$type instanceof ResolvedFormTypeInterface) { throw new UnexpectedTypeException($type, 'string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface'); } $builder = $type->createBuilder($this, $name, $options); // Explicitly call buildForm() in order to be able to override either // createBuilder() or buildForm() in the resolved form type $type->buildForm($builder, $builder->getOptions()); return $builder; } /** * {@inheritdoc} */ public function createBuilderForProperty($class, $property, $data = null, array $options = array()) { if (null === $guesser = $this->registry->getTypeGuesser()) { return $this->createNamedBuilder($property, 'text', $data, $options); } $typeGuess = $guesser->guessType($class, $property); $maxLengthGuess = $guesser->guessMaxLength($class, $property); $requiredGuess = $guesser->guessRequired($class, $property); $patternGuess = $guesser->guessPattern($class, $property); $type = $typeGuess ? $typeGuess->getType() : 'text'; $maxLength = $maxLengthGuess ? $maxLengthGuess->getValue() : null; $pattern = $patternGuess ? $patternGuess->getValue() : null; if (null !== $pattern) { $options = array_merge(array('pattern' => $pattern), $options); } if (null !== $maxLength) { $options = array_merge(array('max_length' => $maxLength), $options); } if ($requiredGuess) { $options = array_merge(array('required' => $requiredGuess->getValue()), $options); } // user options may override guessed options if ($typeGuess) { $options = array_merge($typeGuess->getOptions(), $options); } return $this->createNamedBuilder($property, $type, $data, $options); } /** * Wraps a type into a ResolvedFormTypeInterface implementation and connects * it with its parent type. * * @param FormTypeInterface $type The type to resolve. * * @return ResolvedFormTypeInterface The resolved type. */ private function resolveType(FormTypeInterface $type) { $parentType = $type->getParent(); if ($parentType instanceof FormTypeInterface) { $parentType = $this->resolveType($parentType); } elseif (null !== $parentType) { $parentType = $this->registry->getType($parentType); } return $this->resolvedTypeFactory->createResolvedType( $type, // Type extensions are not supported for unregistered type instances, // i.e. type instances that are passed to the FormFactory directly, // nor for their parents, if getParent() also returns a type instance. array(), $parentType ); } } PK!\g2Symfony/Component/Form/RequestHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Submits forms if they were submitted. * * @author Bernhard Schussek */ interface RequestHandlerInterface { /** * Submits a form if it was submitted. * * @param FormInterface $form The form to submit. * @param mixed $request The current request. */ public function handleRequest(FormInterface $form, $request = null); } PK!+qDAA7Symfony/Component/Form/Test/FormPerformanceTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; /** * Base class for performance tests. * * Copied from Doctrine 2's OrmPerformanceTestCase. * * @author robo * @author Bernhard Schussek */ abstract class FormPerformanceTestCase extends FormIntegrationTestCase { /** * @var integer */ protected $maxRunningTime = 0; /** */ protected function runTest() { $s = microtime(true); parent::runTest(); $time = microtime(true) - $s; if ($this->maxRunningTime != 0 && $time > $this->maxRunningTime) { $this->fail( sprintf( 'expected running time: <= %s but was: %s', $this->maxRunningTime, $time ) ); } } /** * @param integer $maxRunningTime * @throws \InvalidArgumentException */ public function setMaxRunningTime($maxRunningTime) { if (is_integer($maxRunningTime) && $maxRunningTime >= 0) { $this->maxRunningTime = $maxRunningTime; } else { throw new \InvalidArgumentException(); } } /** * @return integer * @since Method available since Release 2.3.0 */ public function getMaxRunningTime() { return $this->maxRunningTime; } } PK!sŪ,Symfony/Component/Form/Test/TypeTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\FormBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; abstract class TypeTestCase extends FormIntegrationTestCase { /** * @var FormBuilder */ protected $builder; /** * @var EventDispatcher */ protected $dispatcher; protected function setUp() { parent::setUp(); $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory); } public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) { self::assertEquals($expected->format('c'), $actual->format('c')); } } PK!,7//7Symfony/Component/Form/Test/DeprecationErrorHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\FormEvent; class DeprecationErrorHandler { public static function handle($errorNumber, $message, $file, $line, $context) { if ($errorNumber & E_USER_DEPRECATED) { return true; } return \PHPUnit_Util_ErrorHandler::handleError($errorNumber, $message, $file, $line); } public static function handleBC($errorNumber, $message, $file, $line, $context) { if ($errorNumber & E_USER_DEPRECATED) { return true; } return false; } public static function preBind($listener, FormEvent $event) { set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $listener->preBind($event); restore_error_handler(); } } PK!B4I++7Symfony/Component/Form/Test/FormIntegrationTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\Forms; /** * @author Bernhard Schussek */ abstract class FormIntegrationTestCase extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\Form\FormFactoryInterface */ protected $factory; protected function setUp() { $this->factory = Forms::createFormFactoryBuilder() ->addExtensions($this->getExtensions()) ->getFormFactory(); } protected function getExtensions() { return array(); } } PK!myy4Symfony/Component/Form/Test/FormBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; interface FormBuilderInterface extends \Iterator, \Symfony\Component\Form\FormBuilderInterface { } PK!a(0kk-Symfony/Component/Form/Test/FormInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; interface FormInterface extends \Iterator, \Symfony\Component\Form\FormInterface { } PK!n1Symfony/Component/Form/FormExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Interface for extensions which provide types, type extensions and a guesser. */ interface FormExtensionInterface { /** * Returns a type by name. * * @param string $name The name of the type * * @return FormTypeInterface The type * * @throws Exception\InvalidArgumentException if the given type is not supported by this extension */ public function getType($name); /** * Returns whether the given type is supported. * * @param string $name The name of the type * * @return Boolean Whether the type is supported by this extension */ public function hasType($name); /** * Returns the extensions for the given type. * * @param string $name The name of the type * * @return FormTypeExtensionInterface[] An array of extensions as FormTypeExtensionInterface instances */ public function getTypeExtensions($name); /** * Returns whether this extension provides type extensions for the given type. * * @param string $name The name of the type * * @return Boolean Whether the given type has extensions */ public function hasTypeExtensions($name); /** * Returns the type guesser provided by this extension. * * @return FormTypeGuesserInterface|null The type guesser */ public function getTypeGuesser(); } PK!|G 4Symfony/Component/Form/ResolvedFormTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A wrapper for a form type and its extensions. * * @author Bernhard Schussek */ interface ResolvedFormTypeInterface { /** * Returns the name of the type. * * @return string The type name. */ public function getName(); /** * Returns the parent type. * * @return ResolvedFormTypeInterface|null The parent type or null. */ public function getParent(); /** * Returns the wrapped form type. * * @return FormTypeInterface The wrapped form type. */ public function getInnerType(); /** * Returns the extensions of the wrapped form type. * * @return FormTypeExtensionInterface[] An array of {@link FormTypeExtensionInterface} instances. */ public function getTypeExtensions(); /** * Creates a new form builder for this type. * * @param FormFactoryInterface $factory The form factory. * @param string $name The name for the builder. * @param array $options The builder options. * * @return FormBuilderInterface The created form builder. */ public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()); /** * Creates a new form view for a form of this type. * * @param FormInterface $form The form to create a view for. * @param FormView $parent The parent view or null. * * @return FormView The created form view. */ public function createView(FormInterface $form, FormView $parent = null); /** * Configures a form builder for the type hierarchy. * * @param FormBuilderInterface $builder The builder to configure. * @param array $options The options used for the configuration. */ public function buildForm(FormBuilderInterface $builder, array $options); /** * Configures a form view for the type hierarchy. * * It is called before the children of the view are built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes a form view for the type hierarchy. * * It is called after the children of the view have been built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function finishView(FormView $view, FormInterface $form, array $options); /** * Returns the configured options resolver used for this type. * * @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver. */ public function getOptionsResolver(); } PK!{d!!5Symfony/Component/Form/FormConfigBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * @author Bernhard Schussek */ interface FormConfigBuilderInterface extends FormConfigInterface { /** * Adds an event listener to an event on this form. * * @param string $eventName The name of the event to listen to. * @param callable $listener The listener to execute. * @param integer $priority The priority of the listener. Listeners * with a higher priority are called before * listeners with a lower priority. * * @return self The configuration object. */ public function addEventListener($eventName, $listener, $priority = 0); /** * Adds an event subscriber for events on this form. * * @param EventSubscriberInterface $subscriber The subscriber to attach. * * @return self The configuration object. */ public function addEventSubscriber(EventSubscriberInterface $subscriber); /** * Appends / prepends a transformer to the view transformer chain. * * The transform method of the transformer is used to convert data from the * normalized to the view format. * The reverseTransform method of the transformer is used to convert from the * view to the normalized format. * * @param DataTransformerInterface $viewTransformer * @param Boolean $forcePrepend if set to true, prepend instead of appending * * @return self The configuration object. */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false); /** * Clears the view transformers. * * @return self The configuration object. */ public function resetViewTransformers(); /** * Prepends / appends a transformer to the normalization transformer chain. * * The transform method of the transformer is used to convert data from the * model to the normalized format. * The reverseTransform method of the transformer is used to convert from the * normalized to the model format. * * @param DataTransformerInterface $modelTransformer * @param Boolean $forceAppend if set to true, append instead of prepending * * @return self The configuration object. */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false); /** * Clears the normalization transformers. * * @return self The configuration object. */ public function resetModelTransformers(); /** * Sets the value for an attribute. * * @param string $name The name of the attribute * @param string $value The value of the attribute * * @return self The configuration object. */ public function setAttribute($name, $value); /** * Sets the attributes. * * @param array $attributes The attributes. * * @return self The configuration object. */ public function setAttributes(array $attributes); /** * Sets the data mapper used by the form. * * @param DataMapperInterface $dataMapper * * @return self The configuration object. */ public function setDataMapper(DataMapperInterface $dataMapper = null); /** * Set whether the form is disabled. * * @param Boolean $disabled Whether the form is disabled * * @return self The configuration object. */ public function setDisabled($disabled); /** * Sets the data used for the client data when no value is submitted. * * @param mixed $emptyData The empty data. * * @return self The configuration object. */ public function setEmptyData($emptyData); /** * Sets whether errors bubble up to the parent. * * @param Boolean $errorBubbling * * @return self The configuration object. */ public function setErrorBubbling($errorBubbling); /** * Sets whether this field is required to be filled out when submitted. * * @param Boolean $required * * @return self The configuration object. */ public function setRequired($required); /** * Sets the property path that the form should be mapped to. * * @param null|string|\Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath * The property path or null if the path should be set * automatically based on the form's name. * * @return self The configuration object. */ public function setPropertyPath($propertyPath); /** * Sets whether the form should be mapped to an element of its * parent's data. * * @param Boolean $mapped Whether the form should be mapped. * * @return self The configuration object. */ public function setMapped($mapped); /** * Sets whether the form's data should be modified by reference. * * @param Boolean $byReference Whether the data should be * modified by reference. * * @return self The configuration object. */ public function setByReference($byReference); /** * Sets whether the form should read and write the data of its parent. * * @param Boolean $inheritData Whether the form should inherit its parent's data. * * @return self The configuration object. */ public function setInheritData($inheritData); /** * Sets whether the form should be compound. * * @param Boolean $compound Whether the form should be compound. * * @return self The configuration object. * * @see FormConfigInterface::getCompound() */ public function setCompound($compound); /** * Set the types. * * @param ResolvedFormTypeInterface $type The type of the form. * * @return self The configuration object. */ public function setType(ResolvedFormTypeInterface $type); /** * Sets the initial data of the form. * * @param array $data The data of the form in application format. * * @return self The configuration object. */ public function setData($data); /** * Locks the form's data to the data passed in the configuration. * * A form with locked data is restricted to the data passed in * this configuration. The data can only be modified then by * submitting the form. * * @param Boolean $locked Whether to lock the default data. * * @return self The configuration object. */ public function setDataLocked($locked); /** * Sets the form factory used for creating new forms. * * @param FormFactoryInterface $formFactory The form factory. */ public function setFormFactory(FormFactoryInterface $formFactory); /** * Sets the target URL of the form. * * @param string $action The target URL of the form. * * @return self The configuration object. */ public function setAction($action); /** * Sets the HTTP method used by the form. * * @param string $method The HTTP method of the form. * * @return self The configuration object. */ public function setMethod($method); /** * Sets the request handler used by the form. * * @param RequestHandlerInterface $requestHandler * * @return self The configuration object. */ public function setRequestHandler(RequestHandlerInterface $requestHandler); /** * Sets whether the form should be initialized automatically. * * Should be set to true only for root forms. * * @param Boolean $initialize True to initialize the form automatically, * false to suppress automatic initialization. * In the second case, you need to call * {@link FormInterface::initialize()} manually. * * @return self The configuration object. */ public function setAutoInitialize($initialize); /** * Builds and returns the form configuration. * * @return FormConfigInterface */ public function getFormConfig(); } PK!ɃT 6Symfony/Component/Form/FormFactoryBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A builder for FormFactoryInterface objects. * * @author Bernhard Schussek */ interface FormFactoryBuilderInterface { /** * Sets the factory for creating ResolvedFormTypeInterface instances. * * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory * * @return FormFactoryBuilderInterface The builder. */ public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory); /** * Adds an extension to be loaded by the factory. * * @param FormExtensionInterface $extension The extension. * * @return FormFactoryBuilderInterface The builder. */ public function addExtension(FormExtensionInterface $extension); /** * Adds a list of extensions to be loaded by the factory. * * @param FormExtensionInterface[] $extensions The extensions. * * @return FormFactoryBuilderInterface The builder. */ public function addExtensions(array $extensions); /** * Adds a form type to the factory. * * @param FormTypeInterface $type The form type. * * @return FormFactoryBuilderInterface The builder. */ public function addType(FormTypeInterface $type); /** * Adds a list of form types to the factory. * * @param FormTypeInterface[] $types The form types. * * @return FormFactoryBuilderInterface The builder. */ public function addTypes(array $types); /** * Adds a form type extension to the factory. * * @param FormTypeExtensionInterface $typeExtension The form type extension. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeExtension(FormTypeExtensionInterface $typeExtension); /** * Adds a list of form type extensions to the factory. * * @param FormTypeExtensionInterface[] $typeExtensions The form type extensions. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeExtensions(array $typeExtensions); /** * Adds a type guesser to the factory. * * @param FormTypeGuesserInterface $typeGuesser The type guesser. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser); /** * Adds a list of type guessers to the factory. * * @param FormTypeGuesserInterface[] $typeGuessers The type guessers. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeGuessers(array $typeGuessers); /** * Builds and returns the factory. * * @return FormFactoryInterface The form factory. */ public function getFormFactory(); } PK!N̷;Symfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Creates ResolvedFormTypeInterface instances. * * This interface allows you to use your custom ResolvedFormTypeInterface * implementation, within which you can customize the concrete FormBuilderInterface * implementations or FormView subclasses that are used by the framework. * * @author Bernhard Schussek */ interface ResolvedFormTypeFactoryInterface { /** * Resolves a form type. * * @param FormTypeInterface $type * @param FormTypeExtensionInterface[] $typeExtensions * @param ResolvedFormTypeInterface|null $parent * * @return ResolvedFormTypeInterface * * @throws Exception\UnexpectedTypeException if the types parent {@link FormTypeInterface::getParent()} is not a string * @throws Exception\InvalidArgumentException if the types parent can not be retrieved from any extension */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null); } PK!2-Symfony/Component/Form/FormFactoryBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * The default implementation of FormFactoryBuilderInterface. * * @author Bernhard Schussek */ class FormFactoryBuilder implements FormFactoryBuilderInterface { /** * @var ResolvedFormTypeFactoryInterface */ private $resolvedTypeFactory; /** * @var array */ private $extensions = array(); /** * @var array */ private $types = array(); /** * @var array */ private $typeExtensions = array(); /** * @var array */ private $typeGuessers = array(); /** * {@inheritdoc} */ public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory) { $this->resolvedTypeFactory = $resolvedTypeFactory; return $this; } /** * {@inheritdoc} */ public function addExtension(FormExtensionInterface $extension) { $this->extensions[] = $extension; return $this; } /** * {@inheritdoc} */ public function addExtensions(array $extensions) { $this->extensions = array_merge($this->extensions, $extensions); return $this; } /** * {@inheritdoc} */ public function addType(FormTypeInterface $type) { $this->types[$type->getName()] = $type; return $this; } /** * {@inheritdoc} */ public function addTypes(array $types) { foreach ($types as $type) { $this->types[$type->getName()] = $type; } return $this; } /** * {@inheritdoc} */ public function addTypeExtension(FormTypeExtensionInterface $typeExtension) { $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension; return $this; } /** * {@inheritdoc} */ public function addTypeExtensions(array $typeExtensions) { foreach ($typeExtensions as $typeExtension) { $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension; } return $this; } /** * {@inheritdoc} */ public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser) { $this->typeGuessers[] = $typeGuesser; return $this; } /** * {@inheritdoc} */ public function addTypeGuessers(array $typeGuessers) { $this->typeGuessers = array_merge($this->typeGuessers, $typeGuessers); return $this; } /** * {@inheritdoc} */ public function getFormFactory() { $extensions = $this->extensions; if (count($this->types) > 0 || count($this->typeExtensions) > 0 || count($this->typeGuessers) > 0) { if (count($this->typeGuessers) > 1) { $typeGuesser = new FormTypeGuesserChain($this->typeGuessers); } else { $typeGuesser = isset($this->typeGuessers[0]) ? $this->typeGuessers[0] : null; } $extensions[] = new PreloadedExtension($this->types, $this->typeExtensions, $typeGuesser); } $resolvedTypeFactory = $this->resolvedTypeFactory ?: new ResolvedFormTypeFactory(); $registry = new FormRegistry($extensions, $resolvedTypeFactory); return new FormFactory($registry, $resolvedTypeFactory); } } PK!C0Symfony/Component/Form/AbstractTypeExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ abstract class AbstractTypeExtension implements FormTypeExtensionInterface { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { } } PK!E 0Symfony/Component/Form/FormRendererInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Renders a form into HTML. * * @author Bernhard Schussek */ interface FormRendererInterface { /** * Returns the engine used by this renderer. * * @return FormRendererEngineInterface The renderer engine. */ public function getEngine(); /** * Sets the theme(s) to be used for rendering a view and its children. * * @param FormView $view The view to assign the theme(s) to. * @param mixed $themes The theme(s). The type of these themes * is open to the implementation. */ public function setTheme(FormView $view, $themes); /** * Renders a named block of the form theme. * * @param FormView $view The view for which to render the block. * @param string $blockName The name of the block. * @param array $variables The variables to pass to the template. * * @return string The HTML markup */ public function renderBlock(FormView $view, $blockName, array $variables = array()); /** * Searches and renders a block for a given name suffix. * * The block is searched by combining the block names stored in the * form view with the given suffix. If a block name is found, that * block is rendered. * * If this method is called recursively, the block search is continued * where a block was found before. * * @param FormView $view The view for which to render the block. * @param string $blockNameSuffix The suffix of the block name. * @param array $variables The variables to pass to the template. * * @return string The HTML markup */ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $variables = array()); /** * Renders a CSRF token. * * Use this helper for CSRF protection without the overhead of creating a * form. * * * * * * Check the token in your action using the same token ID. * * * $csrfProvider = $this->get('security.csrf.token_generator'); * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) { * throw new \RuntimeException('CSRF attack detected.'); * } * * * @param string $tokenId The ID of the CSRF token * * @return string A CSRF token */ public function renderCsrfToken($tokenId); /** * Makes a technical name human readable. * * Sequences of underscores are replaced by single spaces. The first letter * of the resulting string is capitalized, while all other letters are * turned to lowercase. * * @param string $text The text to humanize. * * @return string The humanized text. */ public function humanize($text); } PK!:  /Symfony/Component/Form/FormBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuilderInterface { /** * Adds a new field to this group. A field must have a unique name within * the group. Otherwise the existing field is overwritten. * * If you add a nested group, this group should also be represented in the * object hierarchy. * * @param string|integer|FormBuilderInterface $child * @param string|FormTypeInterface $type * @param array $options * * @return FormBuilderInterface The builder object. */ public function add($child, $type = null, array $options = array()); /** * Creates a form builder. * * @param string $name The name of the form or the name of the property * @param string|FormTypeInterface $type The type of the form or null if name is a property * @param array $options The options * * @return FormBuilderInterface The created builder. */ public function create($name, $type = null, array $options = array()); /** * Returns a child by name. * * @param string $name The name of the child * * @return FormBuilderInterface The builder for the child * * @throws Exception\InvalidArgumentException if the given child does not exist */ public function get($name); /** * Removes the field with the given name. * * @param string $name * * @return FormBuilderInterface The builder object. */ public function remove($name); /** * Returns whether a field with the given name exists. * * @param string $name * * @return Boolean */ public function has($name); /** * Returns the children. * * @return array */ public function all(); /** * Creates the form. * * @return Form The form */ public function getForm(); } PK!Z)/Symfony/Component/Form/FormFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface FormFactoryInterface { /** * Returns a form. * * @see createBuilder() * * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormInterface The form named after the type * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function create($type = 'form', $data = null, array $options = array()); /** * Returns a form. * * @see createNamedBuilder() * * @param string|integer $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormInterface The form * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createNamed($name, $type = 'form', $data = null, array $options = array()); /** * Returns a form for a property of a class. * * @see createBuilderForProperty() * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * @param mixed $data The initial data * @param array $options The options for the builder * * @return FormInterface The form named after the property * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type */ public function createForProperty($class, $property, $data = null, array $options = array()); /** * Returns a form builder. * * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormBuilderInterface The form builder * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createBuilder($type = 'form', $data = null, array $options = array()); /** * Returns a form builder. * * @param string|integer $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormBuilderInterface The form builder * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array()); /** * Returns a form builder for a property of a class. * * If any of the 'max_length', 'required' and type options can be guessed, * and are not provided in the options argument, the guessed value is used. * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * @param mixed $data The initial data * @param array $options The options for the builder * * @return FormBuilderInterface The form builder named after the property * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type */ public function createBuilderForProperty($class, $property, $data = null, array $options = array()); } PK!YB.Symfony/Component/Form/ReversedTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Reverses a transformer * * When the transform() method is called, the reversed transformer's * reverseTransform() method is called and vice versa. * * @author Bernhard Schussek */ class ReversedTransformer implements DataTransformerInterface { /** * The reversed transformer * @var DataTransformerInterface */ protected $reversedTransformer; /** * Reverses this transformer * * @param DataTransformerInterface $reversedTransformer */ public function __construct(DataTransformerInterface $reversedTransformer) { $this->reversedTransformer = $reversedTransformer; } /** * {@inheritDoc} */ public function transform($value) { return $this->reversedTransformer->reverseTransform($value); } /** * {@inheritDoc} */ public function reverseTransform($value) { return $this->reversedTransformer->transform($value); } } PK!rW W 3Symfony/Component/Form/DataTransformerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms a value between different representations. * * @author Bernhard Schussek */ interface DataTransformerInterface { /** * Transforms a value from the original representation to a transformed representation. * * This method is called on two occasions inside a form field: * * 1. When the form field is initialized with the data attached from the datasource (object or array). * 2. When data from a request is submitted using {@link Form::submit()} to transform the new input data * back into the renderable format. For example if you have a date field and submit '2009-10-10' * you might accept this value because its easily parsed, but the transformer still writes back * "2009/10/10" onto the form field (for further displaying or other purposes). * * This method must be able to deal with empty values. Usually this will * be NULL, but depending on your implementation other empty values are * possible as well (such as empty strings). The reasoning behind this is * that value transformers must be chainable. If the transform() method * of the first value transformer outputs NULL, the second value transformer * must be able to process that value. * * By convention, transform() should return an empty string if NULL is * passed. * * @param mixed $value The value in the original representation * * @return mixed The value in the transformed representation * * @throws TransformationFailedException When the transformation fails. */ public function transform($value); /** * Transforms a value from the transformed representation to its original * representation. * * This method is called when {@link Form::submit()} is called to transform the requests tainted data * into an acceptable format for your data processing/model layer. * * This method must be able to deal with empty values. Usually this will * be an empty string, but depending on your implementation other empty * values are possible as well (such as empty strings). The reasoning behind * this is that value transformers must be chainable. If the * reverseTransform() method of the first value transformer outputs an * empty string, the second value transformer must be able to process that * value. * * By convention, reverseTransform() should return NULL if an empty string * is passed. * * @param mixed $value The value in the transformed representation * * @return mixed The value in the original representation * * @throws TransformationFailedException When the transformation fails. */ public function reverseTransform($value); } PK!Wb[H[H(Symfony/Component/Form/ButtonBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\BadMethodCallException; /** * A builder for {@link Button} instances. * * @author Bernhard Schussek */ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface { /** * @var Boolean */ protected $locked = false; /** * @var Boolean */ private $disabled; /** * @var ResolvedFormTypeInterface */ private $type; /** * @var string */ private $name; /** * @var array */ private $attributes = array(); /** * @var array */ private $options; /** * Creates a new button builder. * * @param string $name The name of the button. * @param array $options The button's options. * * @throws InvalidArgumentException If the name is empty. */ public function __construct($name, array $options = array()) { if (empty($name) && 0 != $name) { throw new InvalidArgumentException('Buttons cannot have empty names.'); } $this->name = (string) $name; $this->options = $options; } /** * Unsupported method. * * This method should not be invoked. * * @param string|integer|FormBuilderInterface $child * @param string|FormTypeInterface $type * @param array $options * * @throws BadMethodCallException */ public function add($child, $type = null, array $options = array()) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * @param string|FormTypeInterface $type * @param array $options * * @throws BadMethodCallException */ public function create($name, $type = null, array $options = array()) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function get($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function remove($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * @param string $name * * @return Boolean Always returns false. */ public function has($name) { return false; } /** * Returns the children. * * @return array Always returns an empty array. */ public function all() { return array(); } /** * Creates the button. * * @return Button The button */ public function getForm() { return new Button($this->getFormConfig()); } /** * Unsupported method. * * This method should not be invoked. * * @param string $eventName * @param callable $listener * @param integer $priority * * @throws BadMethodCallException */ public function addEventListener($eventName, $listener, $priority = 0) { throw new BadMethodCallException('Buttons do not support event listeners.'); } /** * Unsupported method. * * This method should not be invoked. * * @param EventSubscriberInterface $subscriber * * @throws BadMethodCallException */ public function addEventSubscriber(EventSubscriberInterface $subscriber) { throw new BadMethodCallException('Buttons do not support event subscribers.'); } /** * Unsupported method. * * This method should not be invoked. * * @param DataTransformerInterface $viewTransformer * @param Boolean $forcePrepend * * @throws BadMethodCallException */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * Unsupported method. * * This method should not be invoked. * * @throws BadMethodCallException */ public function resetViewTransformers() { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * Unsupported method. * * This method should not be invoked. * * @param DataTransformerInterface $modelTransformer * @param Boolean $forceAppend * * @throws BadMethodCallException */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * Unsupported method. * * This method should not be invoked. * * @throws BadMethodCallException */ public function resetModelTransformers() { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * {@inheritdoc} */ public function setAttribute($name, $value) { $this->attributes[$name] = $value; } /** * {@inheritdoc} */ public function setAttributes(array $attributes) { $this->attributes = $attributes; } /** * Unsupported method. * * This method should not be invoked. * * @param DataMapperInterface $dataMapper * * @throws BadMethodCallException */ public function setDataMapper(DataMapperInterface $dataMapper = null) { throw new BadMethodCallException('Buttons do not support data mappers.'); } /** * Set whether the button is disabled. * * @param Boolean $disabled Whether the button is disabled * * @return ButtonBuilder The button builder. */ public function setDisabled($disabled) { $this->disabled = $disabled; } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $emptyData * * @throws BadMethodCallException */ public function setEmptyData($emptyData) { throw new BadMethodCallException('Buttons do not support empty data.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $errorBubbling * * @throws BadMethodCallException */ public function setErrorBubbling($errorBubbling) { throw new BadMethodCallException('Buttons do not support error bubbling.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $required * * @throws BadMethodCallException */ public function setRequired($required) { throw new BadMethodCallException('Buttons cannot be required.'); } /** * Unsupported method. * * This method should not be invoked. * * @param null $propertyPath * * @throws BadMethodCallException */ public function setPropertyPath($propertyPath) { throw new BadMethodCallException('Buttons do not support property paths.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $mapped * * @throws BadMethodCallException */ public function setMapped($mapped) { throw new BadMethodCallException('Buttons do not support data mapping.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $byReference * * @throws BadMethodCallException */ public function setByReference($byReference) { throw new BadMethodCallException('Buttons do not support data mapping.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $virtual * * @throws BadMethodCallException */ public function setVirtual($virtual) { throw new BadMethodCallException('Buttons cannot be virtual.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $compound * * @throws BadMethodCallException */ public function setCompound($compound) { throw new BadMethodCallException('Buttons cannot be compound.'); } /** * Sets the type of the button. * * @param ResolvedFormTypeInterface $type The type of the button. * * @return ButtonBuilder The button builder. */ public function setType(ResolvedFormTypeInterface $type) { $this->type = $type; } /** * Unsupported method. * * This method should not be invoked. * * @param array $data * * @throws BadMethodCallException */ public function setData($data) { throw new BadMethodCallException('Buttons do not support data.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $locked * * @throws BadMethodCallException */ public function setDataLocked($locked) { throw new BadMethodCallException('Buttons do not support data locking.'); } /** * Unsupported method. * * This method should not be invoked. * * @param FormFactoryInterface $formFactory * * @return void * * @throws BadMethodCallException */ public function setFormFactory(FormFactoryInterface $formFactory) { throw new BadMethodCallException('Buttons do not support form factories.'); } /** * Unsupported method. * * @param string $action * * @throws BadMethodCallException */ public function setAction($action) { throw new BadMethodCallException('Buttons do not support actions.'); } /** * Unsupported method. * * @param string $method * * @throws BadMethodCallException */ public function setMethod($method) { throw new BadMethodCallException('Buttons do not support methods.'); } /** * Unsupported method. * * @param RequestHandlerInterface $requestHandler * * @throws BadMethodCallException */ public function setRequestHandler(RequestHandlerInterface $requestHandler) { throw new BadMethodCallException('Buttons do not support form processors.'); } /** * Unsupported method. * * @param Boolean $initialize * * @throws BadMethodCallException */ public function setAutoInitialize($initialize) { if (true === $initialize) { throw new BadMethodCallException('Buttons do not support automatic initialization.'); } return $this; } /** * Unsupported method. * * @param Boolean $inheritData * * @throws BadMethodCallException */ public function setInheritData($inheritData) { throw new BadMethodCallException('Buttons do not support data inheritance.'); } /** * Builds and returns the button configuration. * * @return FormConfigInterface */ public function getFormConfig() { // This method should be idempotent, so clone the builder $config = clone $this; $config->locked = true; return $config; } /** * Unsupported method. * * @return null Always returns null. */ public function getEventDispatcher() { return null; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * Unsupported method. * * @return null Always returns null. */ public function getPropertyPath() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getMapped() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getByReference() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getVirtual() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getCompound() { return false; } /** * Returns the form type used to construct the button. * * @return ResolvedFormTypeInterface The button's type. */ public function getType() { return $this->type; } /** * Unsupported method. * * @return array Always returns an empty array. */ public function getViewTransformers() { return array(); } /** * Unsupported method. * * @return array Always returns an empty array. */ public function getModelTransformers() { return array(); } /** * Unsupported method. * * @return null Always returns null. */ public function getDataMapper() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getRequired() { return false; } /** * Returns whether the button is disabled. * * @return Boolean Whether the button is disabled. */ public function getDisabled() { return $this->disabled; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getErrorBubbling() { return false; } /** * Unsupported method. * * @return null Always returns null. */ public function getEmptyData() { return null; } /** * Returns additional attributes of the button. * * @return array An array of key-value combinations. */ public function getAttributes() { return $this->attributes; } /** * Returns whether the attribute with the given name exists. * * @param string $name The attribute name. * * @return Boolean Whether the attribute exists. */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * Returns the value of the given attribute. * * @param string $name The attribute name. * @param mixed $default The value returned if the attribute does not exist. * * @return mixed The attribute value. */ public function getAttribute($name, $default = null) { return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** * Unsupported method. * * @return null Always returns null. */ public function getData() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getDataClass() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getDataLocked() { return false; } /** * Unsupported method. * * @return null Always returns null. */ public function getFormFactory() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getAction() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getMethod() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getRequestHandler() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getAutoInitialize() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getInheritData() { return false; } /** * Returns all options passed during the construction of the button. * * @return array The passed options. */ public function getOptions() { return $this->options; } /** * Returns whether a specific option exists. * * @param string $name The option name, * * @return Boolean Whether the option exists. */ public function hasOption($name) { return array_key_exists($name, $this->options); } /** * Returns the value of a specific option. * * @param string $name The option name. * @param mixed $default The value returned if the option does not exist. * * @return mixed The option value. */ public function getOption($name, $default = null) { return array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** * Unsupported method. * * @return integer Always returns 0. */ public function count() { return 0; } /** * Unsupported method. * * @return \EmptyIterator Always returns an empty iterator. */ public function getIterator() { return new \EmptyIterator(); } } PK!n?Symfony/Component/Form/Resources/translations/validators.en.xlfnu[ This form should not contain extra fields. This form should not contain extra fields. The uploaded file was too large. Please try to upload a smaller file. The uploaded file was too large. Please try to upload a smaller file. The CSRF token is invalid. Please try to resubmit the form. The CSRF token is invalid. Please try to resubmit the form. PK!誫?Symfony/Component/Form/Resources/translations/validators.sk.xlfnu[ This form should not contain extra fields. Polia by nemali obsahovať ďalšie prvky. The uploaded file was too large. Please try to upload a smaller file. Odoslaný súbor je príliš veľký. Prosím odošlite súbor s menšou veľkosťou. The CSRF token is invalid. Please try to resubmit the form. CSRF token je neplatný. Prosím skúste znovu odoslať formulár. PK!<yy?Symfony/Component/Form/Resources/translations/validators.uk.xlfnu[ This form should not contain extra fields. Ця форма не повинна містити додаткових полів. The uploaded file was too large. Please try to upload a smaller file. Завантажений файл занадто великий. Будь-ласка, спробуйте завантажити файл меншого розміру. The CSRF token is invalid. Please try to resubmit the form. CSRF значення недопустиме. Будь-ласка, спробуйте відправити форму знову. PK!:?Symfony/Component/Form/Resources/translations/validators.pl.xlfnu[ This form should not contain extra fields. Ten formularz nie powinien zawierać dodatkowych pól. The uploaded file was too large. Please try to upload a smaller file. Wgrany plik był za duży. Proszę spróbować wgrać mniejszy plik. The CSRF token is invalid. Please try to resubmit the form. Token CSRF jest nieprawidłowy. Proszę spróbować wysłać formularz ponownie. PK! ?Symfony/Component/Form/Resources/translations/validators.pt.xlfnu[ This form should not contain extra fields. Este formulário não deveria conter campos extra. The uploaded file was too large. Please try to upload a smaller file. O arquivo enviado é muito grande. Por favor, tente enviar um ficheiro mais pequeno. The CSRF token is invalid. Please try to resubmit the form. O token CSRF é inválido. Por favor submeta o formulário novamente. PK!%?Symfony/Component/Form/Resources/translations/validators.lv.xlfnu[ This form should not contain extra fields. Šajā veidlapā nevajadzētu būt papildus ievades laukiem. The uploaded file was too large. Please try to upload a smaller file. Augšupielādētā faila izmērs bija par lielu. Lūdzu mēģiniet augšupielādēt mazāka izmēra failu. The CSRF token is invalid. Please try to resubmit the form. Dotais CSRF talons nav derīgs. Lūdzu mēģiniet vēlreiz iesniegt veidlapu. PK!္o33DSymfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu[ This form should not contain extra fields. Овај формулар не треба да садржи додатна поља. The uploaded file was too large. Please try to upload a smaller file. Отпремљена датотека је била превелика. Молим покушајте отпремање мање датотеке. The CSRF token is invalid. Please try to resubmit the form. CSRF вредност је невалидна. Покушајте поново. PK!?Symfony/Component/Form/Resources/translations/validators.fi.xlfnu[ This field group should not contain extra fields. Tämä kenttäryhmä ei voi sisältää ylimääräisiä kenttiä. The uploaded file was too large. Please try to upload a smaller file. Ladattu tiedosto on liian iso. Ole hyvä ja lataa pienempi tiedosto. The CSRF token is invalid. Please try to resubmit the form. CSRF tarkiste on virheellinen. Olen hyvä ja yritä lähettää lomake uudestaan. PK!0h?Symfony/Component/Form/Resources/translations/validators.es.xlfnu[ This form should not contain extra fields. Este formulario no debería contener campos adicionales. The uploaded file was too large. Please try to upload a smaller file. El archivo subido es demasiado grande. Por favor, suba un archivo más pequeño. The CSRF token is invalid. Please try to resubmit the form. El token CSRF no es válido. Por favor, pruebe de enviar nuevamente el formulario. PK!TI?Symfony/Component/Form/Resources/translations/validators.de.xlfnu[ This form should not contain extra fields. Dieses Formular sollte keine zusätzlichen Felder enthalten. The uploaded file was too large. Please try to upload a smaller file. Die hochgeladene Datei ist zu groß. Versuchen Sie bitte eine kleinere Datei hochzuladen. The CSRF token is invalid. Please try to resubmit the form. Der CSRF-Token ist ungültig. Versuchen Sie bitte das Formular erneut zu senden. PK!!aZ?Symfony/Component/Form/Resources/translations/validators.it.xlfnu[ This form should not contain extra fields. Questo form non dovrebbe contenere nessun campo extra. The uploaded file was too large. Please try to upload a smaller file. Il file caricato è troppo grande. Per favore caricare un file più piccolo. The CSRF token is invalid. Please try to resubmit the form. Il token CSRF non è valido. Provare a reinviare il form. PK! !?Symfony/Component/Form/Resources/translations/validators.ca.xlfnu[ This form should not contain extra fields. Aquest formulari no hauria de contenir camps addicionals. The uploaded file was too large. Please try to upload a smaller file. L'arxiu pujat és massa gran. Per favor, pugi un arxiu més petit. The CSRF token is invalid. Please try to resubmit the form. El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari. PK!?Symfony/Component/Form/Resources/translations/validators.mn.xlfnu[ This form should not contain extra fields. Форм нэмэлт талбар багтаах боломжгүй. The uploaded file was too large. Please try to upload a smaller file. Upload хийсэн файл хэтэрхий том байна. Бага хэмжээтэй файл оруулна уу. The CSRF token is invalid. Please try to resubmit the form. CSRF token буруу байна. Формоо дахин илгээнэ үү. PK!-?Symfony/Component/Form/Resources/translations/validators.ru.xlfnu[ This form should not contain extra fields. Эта форма не должна содержать дополнительных полей. The uploaded file was too large. Please try to upload a smaller file. Загруженный файл слишком большой. Пожалуйста, попробуйте загрузить файл меньшего размера. The CSRF token is invalid. Please try to resubmit the form. CSRF значение недопустимо. Пожалуйста, попробуйте повторить отправку формы. PK!3Ե^^?Symfony/Component/Form/Resources/translations/validators.bg.xlfnu[ This form should not contain extra fields. Тази форма не трябва да съдържа допълнителни полета. The uploaded file was too large. Please try to upload a smaller file. Каченият файл е твърде голям. Моля, опитайте да качите по-малък файл. The CSRF token is invalid. Please try to resubmit the form. Невалиден CSRF токен. Моля, опитайте да изпратите формата отново. PK!Ed?Symfony/Component/Form/Resources/translations/validators.ro.xlfnu[ This form should not contain extra fields. Aceast formular nu ar trebui să conțină câmpuri suplimentare. The uploaded file was too large. Please try to upload a smaller file. Fișierul încărcat a fost prea mare. Vă rugăm sa încărcați un fișier mai mic. The CSRF token is invalid. Please try to resubmit the form. Token-ul CSRF este invalid. Vă rugăm să trimiteți formularul incă o dată. PK!O?Symfony/Component/Form/Resources/translations/validators.nl.xlfnu[ This form should not contain extra fields. Dit formulier mag geen extra velden bevatten. The uploaded file was too large. Please try to upload a smaller file. Het geüploade bestand is te groot. Probeer een kleiner bestand te uploaden. The CSRF token is invalid. Please try to resubmit the form. De CSRF-token is ongeldig. Probeer het formulier opnieuw te versturen. PK!S*?Symfony/Component/Form/Resources/translations/validators.et.xlfnu[ This form should not contain extra fields. Väljade grupp ei tohiks sisalda lisaväljasid. The uploaded file was too large. Please try to upload a smaller file. Üleslaaditud fail oli liiga suur. Palun proovi uuesti väiksema failiga. The CSRF token is invalid. Please try to resubmit the form. CSRF-märgis on vigane. Palun proovi vormi uuesti esitada. PK!V5?Symfony/Component/Form/Resources/translations/validators.fa.xlfnu[ This form should not contain extra fields. این فرم نباید فیلد اضافی داشته باشد. The uploaded file was too large. Please try to upload a smaller file. فایل بارگذاری شده بسیار بزرگ است. لطفا فایل کوچکتری را بارگزاری کنید. The CSRF token is invalid. Please try to resubmit the form. مقدار CSRF نامعتبر است. لطفا فرم را مجددا ارسال فرمایید.. PK!q?Symfony/Component/Form/Resources/translations/validators.id.xlfnu[ This form should not contain extra fields. Gabungan kolom tidak boleh mengandung kolom tambahan. The uploaded file was too large. Please try to upload a smaller file. Berkas yang di unggah terlalu besar. Silahkan coba unggah berkas yang lebih kecil. The CSRF token is invalid. Please try to resubmit the form. CSRF-Token tidak sah. Silahkan coba kirim ulang formulir. PK! ?Symfony/Component/Form/Resources/translations/validators.cs.xlfnu[ This form should not contain extra fields. Tato skupina polí nesmí obsahovat další pole. The uploaded file was too large. Please try to upload a smaller file. Nahraný soubor je příliš velký. Nahrajte prosím menší soubor. The CSRF token is invalid. Please try to resubmit the form. CSRF token je neplatný. Zkuste prosím znovu odeslat formulář. PK!8,:BSymfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu[ This form should not contain extra fields. 该表单中不可有额外字段. The uploaded file was too large. Please try to upload a smaller file. 上传文件太大, 请重新尝试上传一个较小的文件. The CSRF token is invalid. Please try to resubmit the form. CSRF 验证符无效, 请重新提交. PK!Hq?Symfony/Component/Form/Resources/translations/validators.lt.xlfnu[ This form should not contain extra fields. Forma negali turėti papildomų laukų. The uploaded file was too large. Please try to upload a smaller file. Įkelta byla yra per didelė. bandykite įkelti mažesnę. The CSRF token is invalid. Please try to resubmit the form. CSRF kodas nepriimtinas. Bandykite siųsti formos užklausą dar kartą. PK!_8?Symfony/Component/Form/Resources/translations/validators.fr.xlfnu[ This form should not contain extra fields. Ce formulaire ne doit pas contenir des champs supplémentaires. The uploaded file was too large. Please try to upload a smaller file. Le fichier téléchargé est trop volumineux. Merci d'essayer d'envoyer un fichier plus petit. The CSRF token is invalid. Please try to resubmit the form. Le jeton CSRF est invalide. Veuillez renvoyer le formulaire. PK!A4?Symfony/Component/Form/Resources/translations/validators.gl.xlfnu[ This form should not contain extra fields. Este formulario non debería conter campos adicionais. The uploaded file was too large. Please try to upload a smaller file. O arquivo subido é demasiado grande. Por favor, suba un arquivo máis pequeno. The CSRF token is invalid. Please try to resubmit the form. O token CSRF non é válido. Por favor, probe a enviar novamente o formulario. PK! b8?Symfony/Component/Form/Resources/translations/validators.hr.xlfnu[ This form should not contain extra fields. Ovaj obrazac ne smije sadržavati dodatna polja. The uploaded file was too large. Please try to upload a smaller file. Prenesena datoteka je prevelika. Molim pokušajte prenijeti manju datoteku. The CSRF token is invalid. Please try to resubmit the form. CSRF vrijednost nije ispravna. Pokušajte ponovo poslati obrazac. PK!WgUugg?Symfony/Component/Form/Resources/translations/validators.nb.xlfnu[ This form should not contain extra fields. Feltgruppen må ikke inneholde ekstra felter. The uploaded file was too large. Please try to upload a smaller file. Den opplastede file var for stor. Vennligst last opp en mindre fil. The CSRF token is invalid. CSRF nøkkelen er ugyldig. PK!ٻ||?Symfony/Component/Form/Resources/translations/validators.eu.xlfnu[ This form should not contain extra fields. Formulario honek ez luke aparteko eremurik eduki behar. The uploaded file was too large. Please try to upload a smaller file. Igotako fitxategia handiegia da. Mesedez saiatu fitxategi txikiago bat igotzen. The CSRF token is invalid. CSFR tokena ez da egokia. PK!4@BSymfony/Component/Form/Resources/translations/validators.pt_BR.xlfnu[ This form should not contain extra fields. Este formulário não deve conter campos adicionais. The uploaded file was too large. Please try to upload a smaller file. O arquivo enviado é muito grande. Por favor, tente enviar um arquivo menor. The CSRF token is invalid. Please try to resubmit the form. O token CSRF é inválido. Por favor, tente reenviar o formulário. PK!5?Symfony/Component/Form/Resources/translations/validators.sl.xlfnu[ This form should not contain extra fields. Ta obrazec ne sme vsebovati dodatnih polj. The uploaded file was too large. Please try to upload a smaller file. Naložena datoteka je prevelika. Prosimo, poizkusite naložiti manjšo. The CSRF token is invalid. Please try to resubmit the form. CSRF vrednost je napačna. Prosimo, ponovno pošljite obrazec. PK!*{?Symfony/Component/Form/Resources/translations/validators.lb.xlfnu[ This form should not contain extra fields. Dës Feldergrupp sollt keng zousätzlech Felder enthalen. The uploaded file was too large. Please try to upload a smaller file. De geschécktene Fichier ass ze grouss. Versicht wann ech gelift ee méi klenge Fichier eropzelueden. The CSRF token is invalid. Please try to resubmit the form. Den CSRF-Token ass ongëlteg. Versicht wann ech gelift de Formulaire nach eng Kéier ze schécken. PK!be@?Symfony/Component/Form/Resources/translations/validators.hu.xlfnu[ This form should not contain extra fields. Ez a mezőcsoport nem tartalmazhat extra mezőket. The uploaded file was too large. Please try to upload a smaller file. A feltöltött fájl túl nagy. Kérem próbáljon egy kisebb fájlt feltölteni. The CSRF token is invalid. Please try to resubmit the form. Érvénytelen CSRF token. Kérem próbálja újra elküldeni az űrlapot. PK!_Π?Symfony/Component/Form/Resources/translations/validators.el.xlfnu[ This form should not contain extra fields. Αυτή η φόρμα δεν πρέπει να περιέχει επιπλέον πεδία. The uploaded file was too large. Please try to upload a smaller file. Το αρχείο είναι πολύ μεγάλο. Παρακαλούμε προσπαθήστε να ανεβάσετε ένα μικρότερο αρχείο. The CSRF token is invalid. Please try to resubmit the form. Το CSRF token δεν είναι έγκυρο. Παρακαλούμε δοκιμάστε να υποβάλετε τη φόρμα ξανά. PK!X?Symfony/Component/Form/Resources/translations/validators.da.xlfnu[ This form should not contain extra fields. Feltgruppen må ikke indeholde ekstra felter. The uploaded file was too large. Please try to upload a smaller file. Den oploadede fil var for stor. Opload venligst en mindre fil. The CSRF token is invalid. Please try to resubmit the form. CSRF nøglen er ugyldig. PK!?Symfony/Component/Form/Resources/translations/validators.ja.xlfnu[ This form should not contain extra fields. フィールドグループに追加のフィールドを含んではなりません。 The uploaded file was too large. Please try to upload a smaller file. アップロードされたファイルが大きすぎます。小さなファイルで再度アップロードしてください。 The CSRF token is invalid. CSRFトークンが無効です。 PK!s>ll?Symfony/Component/Form/Resources/translations/validators.sv.xlfnu[ This form should not contain extra fields. Formuläret kan inte innehålla extra fält. The uploaded file was too large. Please try to upload a smaller file. Den uppladdade filen var för stor. Försök ladda upp en mindre fil. The CSRF token is invalid. CSRF-symbolen är inte giltig. PK!y99?Symfony/Component/Form/Resources/translations/validators.hy.xlfnu[ This form should not contain extra fields. Այս ձևը չպետք է պարունակի լրացուցիչ տողեր. The uploaded file was too large. Please try to upload a smaller file. Վերբեռնված ֆայլը չափազանց մեծ է: Խնդրվում է վերբեռնել ավելի փոքր չափսի ֆայլ. The CSRF token is invalid. Please try to resubmit the form. CSRF արժեքը անթույլատրելի է: Փորձեք նորից ուղարկել ձևը. PK!|C?Symfony/Component/Form/Resources/translations/validators.ar.xlfnu[ This form should not contain extra fields. هذا النموذج يجب الا يحتوى على اى حقول اضافية. The uploaded file was too large. Please try to upload a smaller file. مساحة الملف المرسل كبيرة. من فضلك حاول ارسال ملف اصغر. The CSRF token is invalid. Please try to resubmit the form. قيمة رمز الموقع غير صحيحة. من فضلك اعد ارسال النموذج. PK!rDSymfony/Component/Form/Resources/translations/validators.sr_Latn.xlfnu[ This form should not contain extra fields. Ovaj formular ne treba da sadrži dodatna polja. The uploaded file was too large. Please try to upload a smaller file. Otpremljena datoteka je bila prevelika. Molim pokušajte otpremanje manje datoteke. The CSRF token is invalid. Please try to resubmit the form. CSRF vrednost je nevalidna. Pokušajte ponovo. PK!NP\?Symfony/Component/Form/Resources/translations/validators.he.xlfnu[ This form should not contain extra fields. הטופס לא צריך להכיל שדות נוספים. The uploaded file was too large. Please try to upload a smaller file. הקובץ שהועלה גדול מדי. נסה להעלות קובץ קטן יותר. The CSRF token is invalid. אסימון CSRF אינו חוקי. PK!xfh..6Symfony/Component/Form/Resources/config/validation.xmlnu[ PK!R}jj.Symfony/Component/Form/DataMapperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface DataMapperInterface { /** * Maps properties of some data to a list of forms. * * @param mixed $data Structured data. * @param FormInterface[] $forms A list of {@link FormInterface} instances. * * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. */ public function mapDataToForms($data, $forms); /** * Maps the data of a list of forms into the properties of some data. * * @param FormInterface[] $forms A list of {@link FormInterface} instances. * @param mixed $data Structured data. * * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. */ public function mapFormsToData($forms, &$data); } PK!s (Symfony/Component/Form/FormInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A form group bundling multiple forms in a hierarchical structure. * * @author Bernhard Schussek */ interface FormInterface extends \ArrayAccess, \Traversable, \Countable { /** * Sets the parent form. * * @param FormInterface|null $parent The parent form or null if it's the root. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException When trying to set a parent for a form with * an empty name. */ public function setParent(FormInterface $parent = null); /** * Returns the parent form. * * @return FormInterface|null The parent form or null if there is none. */ public function getParent(); /** * Adds or replaces a child to the form. * * @param FormInterface|string|integer $child The FormInterface instance or the name of the child. * @param string|null $type The child's type, if a name was passed. * @param array $options The child's options, if a name was passed. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException When trying to add a child to a non-compound form. * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type. */ public function add($child, $type = null, array $options = array()); /** * Returns the child with the given name. * * @param string $name The name of the child * * @return FormInterface The child form * * @throws \OutOfBoundsException If the named child does not exist. */ public function get($name); /** * Returns whether a child with the given name exists. * * @param string $name The name of the child * * @return Boolean */ public function has($name); /** * Removes a child from the form. * * @param string $name The name of the child to remove * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function remove($name); /** * Returns all children in this group. * * @return FormInterface[] An array of FormInterface instances */ public function all(); /** * Returns all errors. * * @return FormError[] An array of FormError instances that occurred during validation */ public function getErrors(); /** * Updates the form with default data. * * @param mixed $modelData The data formatted as expected for the underlying object * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException If listeners try to call setData in a cycle. Or if * the view data does not match the expected type * according to {@link FormConfigInterface::getDataClass}. */ public function setData($modelData); /** * Returns the data in the format needed for the underlying object. * * @return mixed */ public function getData(); /** * Returns the normalized data of the field. * * @return mixed When the field is not submitted, the default data is returned. * When the field is submitted, the normalized submitted data is * returned if the field is valid, null otherwise. */ public function getNormData(); /** * Returns the data transformed by the value transformer. * * @return mixed */ public function getViewData(); /** * Returns the extra data. * * @return array The submitted data which do not belong to a child */ public function getExtraData(); /** * Returns the form's configuration. * * @return FormConfigInterface The configuration. */ public function getConfig(); /** * Returns whether the form is submitted. * * @return Boolean true if the form is submitted, false otherwise */ public function isSubmitted(); /** * Returns the name by which the form is identified in forms. * * @return string The name of the form. */ public function getName(); /** * Returns the property path that the form is mapped to. * * @return \Symfony\Component\PropertyAccess\PropertyPathInterface The property path. */ public function getPropertyPath(); /** * Adds an error to this form. * * @param FormError $error * * @return FormInterface The form instance */ public function addError(FormError $error); /** * Returns whether the form and all children are valid. * * If the form is not submitted, this method always returns false. * * @return Boolean */ public function isValid(); /** * Returns whether the form is required to be filled out. * * If the form has a parent and the parent is not required, this method * will always return false. Otherwise the value set with setRequired() * is returned. * * @return Boolean */ public function isRequired(); /** * Returns whether this form is disabled. * * The content of a disabled form is displayed, but not allowed to be * modified. The validation of modified disabled forms should fail. * * Forms whose parents are disabled are considered disabled regardless of * their own state. * * @return Boolean */ public function isDisabled(); /** * Returns whether the form is empty. * * @return Boolean */ public function isEmpty(); /** * Returns whether the data in the different formats is synchronized. * * @return Boolean */ public function isSynchronized(); /** * Initializes the form tree. * * Should be called on the root form after constructing the tree. * * @return FormInterface The form instance. */ public function initialize(); /** * Inspects the given request and calls {@link submit()} if the form was * submitted. * * Internally, the request is forwarded to the configured * {@link RequestHandlerInterface} instance, which determines whether to * submit the form or not. * * @param mixed $request The request to handle. * * @return FormInterface The form instance. */ public function handleRequest($request = null); /** * Submits data to the form, transforms and validates it. * * @param null|string|array $submittedData The submitted data. * @param Boolean $clearMissing Whether to set fields to NULL * when they are missing in the * submitted data. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function submit($submittedData, $clearMissing = true); /** * Returns the root of the form tree. * * @return FormInterface The root of the tree */ public function getRoot(); /** * Returns whether the field is the root of the form tree. * * @return Boolean */ public function isRoot(); /** * Creates a view. * * @param FormView $parent The parent view * * @return FormView The view */ public function createView(FormView $parent = null); } PK!"$Symfony/Component/Form/FormEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\Event; /** * @author Bernhard Schussek */ class FormEvent extends Event { private $form; protected $data; /** * Constructs an event. * * @param FormInterface $form The associated form * @param mixed $data The data */ public function __construct(FormInterface $form, $data) { $this->form = $form; $this->data = $data; } /** * Returns the form at the source of the event. * * @return FormInterface */ public function getForm() { return $this->form; } /** * Returns the data associated with this event. * * @return mixed */ public function getData() { return $this->data; } /** * Allows updating with some filtered data. * * @param mixed $data */ public function setData($data) { $this->data = $data; } } PK!=MM5Symfony/Component/Form/FormTypeExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ interface FormTypeExtensionInterface { /** * Builds the form. * * This method is called after the extended type has built the form to * further modify it. * * @see FormTypeInterface::buildForm() * * @param FormBuilderInterface $builder The form builder * @param array $options The options */ public function buildForm(FormBuilderInterface $builder, array $options); /** * Builds the view. * * This method is called after the extended type has built the view to * further modify it. * * @see FormTypeInterface::buildView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes the view. * * This method is called after the extended type has finished the view to * further modify it. * * @see FormTypeInterface::finishView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options); /** * Overrides the default options from the extended type. * * @param OptionsResolverInterface $resolver The resolver for the options. */ public function setDefaultOptions(OptionsResolverInterface $resolver); /** * Returns the name of the type being extended. * * @return string The name of the type being extended */ public function getExtendedType(); } PK!}p  $Symfony/Component/Form/FormError.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Wraps errors in forms * * @author Bernhard Schussek */ class FormError { /** * @var string */ private $message; /** * The template for the error message * @var string */ protected $messageTemplate; /** * The parameters that should be substituted in the message template * @var array */ protected $messageParameters; /** * The value for error message pluralization * @var integer|null */ protected $messagePluralization; /** * Constructor * * Any array key in $messageParameters will be used as a placeholder in * $messageTemplate. * * @param string $message The translated error message * @param string|null $messageTemplate The template for the error message * @param array $messageParameters The parameters that should be * substituted in the message template. * @param integer|null $messagePluralization The value for error message pluralization * * @see \Symfony\Component\Translation\Translator */ public function __construct($message, $messageTemplate = null, array $messageParameters = array(), $messagePluralization = null) { $this->message = $message; $this->messageTemplate = $messageTemplate ?: $message; $this->messageParameters = $messageParameters; $this->messagePluralization = $messagePluralization; } /** * Returns the error message * * @return string */ public function getMessage() { return $this->message; } /** * Returns the error message template * * @return string */ public function getMessageTemplate() { return $this->messageTemplate; } /** * Returns the parameters to be inserted in the message template * * @return array */ public function getMessageParameters() { return $this->messageParameters; } /** * Returns the value for error message pluralization. * * @return integer|null */ public function getMessagePluralization() { return $this->messagePluralization; } } PK! /Symfony/Component/Form/NativeRequestHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * A request handler using PHP's super globals $_GET, $_POST and $_SERVER. * * @author Bernhard Schussek */ class NativeRequestHandler implements RequestHandlerInterface { /** * The allowed keys of the $_FILES array. * * @var array */ private static $fileKeys = array( 'error', 'name', 'size', 'tmp_name', 'type', ); /** * {@inheritdoc} */ public function handleRequest(FormInterface $form, $request = null) { if (null !== $request) { throw new UnexpectedTypeException($request, 'null'); } $name = $form->getName(); $method = $form->getConfig()->getMethod(); if ($method !== self::getRequestMethod()) { return; } if ('GET' === $method) { if ('' === $name) { $data = $_GET; } else { // Don't submit GET requests if the form's name does not exist // in the request if (!isset($_GET[$name])) { return; } $data = $_GET[$name]; } } else { $fixedFiles = array(); foreach ($_FILES as $name => $file) { $fixedFiles[$name] = self::stripEmptyFiles(self::fixPhpFilesArray($file)); } if ('' === $name) { $params = $_POST; $files = $fixedFiles; } elseif (array_key_exists($name, $_POST) || array_key_exists($name, $fixedFiles)) { $default = $form->getConfig()->getCompound() ? array() : null; $params = array_key_exists($name, $_POST) ? $_POST[$name] : $default; $files = array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default; } else { // Don't submit the form if it is not present in the request return; } if (is_array($params) && is_array($files)) { $data = array_replace_recursive($params, $files); } else { $data = $params ?: $files; } } // Don't auto-submit the form unless at least one field is present. if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { return; } $form->submit($data, 'PATCH' !== $method); } /** * Returns the method used to submit the request to the server. * * @return string The request method. */ private static function getRequestMethod() { $method = isset($_SERVER['REQUEST_METHOD']) ? strtoupper($_SERVER['REQUEST_METHOD']) : 'GET'; if ('POST' === $method && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { $method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); } return $method; } /** * Fixes a malformed PHP $_FILES array. * * PHP has a bug that the format of the $_FILES array differs, depending on * whether the uploaded file fields had normal field names or array-like * field names ("normal" vs. "parent[child]"). * * This method fixes the array to look like the "normal" $_FILES array. * * It's safe to pass an already converted array, in which case this method * just returns the original array unmodified. * * This method is identical to {@link Symfony\Component\HttpFoundation\FileBag::fixPhpFilesArray} * and should be kept as such in order to port fixes quickly and easily. * * @param array $data * * @return array */ private static function fixPhpFilesArray($data) { if (!is_array($data)) { return $data; } $keys = array_keys($data); sort($keys); if (self::$fileKeys !== $keys || !isset($data['name']) || !is_array($data['name'])) { return $data; } $files = $data; foreach (self::$fileKeys as $k) { unset($files[$k]); } foreach (array_keys($data['name']) as $key) { $files[$key] = self::fixPhpFilesArray(array( 'error' => $data['error'][$key], 'name' => $data['name'][$key], 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key] )); } return $files; } /** * Sets empty uploaded files to NULL in the given uploaded files array. * * @param mixed $data The file upload data. * * @return array|null Returns the stripped upload data. */ private static function stripEmptyFiles($data) { if (!is_array($data)) { return $data; } $keys = array_keys($data); sort($keys); if (self::$fileKeys === $keys) { if (UPLOAD_ERR_NO_FILE === $data['error']) { return null; } return $data; } foreach ($data as $key => $value) { $data[$key] = self::stripEmptyFiles($value); } return $data; } } PK!*OSymfony/Component/Form/Extension/Validator/EventListener/ValidationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface; use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Validator\Constraints\Form; /** * @author Bernhard Schussek */ class ValidationListener implements EventSubscriberInterface { private $validator; private $violationMapper; /** * {@inheritdoc} */ public static function getSubscribedEvents() { return array(FormEvents::POST_SUBMIT => 'validateForm'); } public function __construct(ValidatorInterface $validator, ViolationMapperInterface $violationMapper) { $this->validator = $validator; $this->violationMapper = $violationMapper; } /** * Validates the form and its domain object. * * @param FormEvent $event The event object */ public function validateForm(FormEvent $event) { $form = $event->getForm(); if ($form->isRoot()) { // Validate the form in group "Default" $violations = $this->validator->validate($form); foreach ($violations as $violation) { // Allow the "invalid" constraint to be put onto // non-synchronized forms $allowNonSynchronized = Form::ERR_INVALID === $violation->getCode(); $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); } } } } PK!Ck@Symfony/Component/Form/Extension/Validator/Util/ServerParams.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Util; /** * @author Bernhard Schussek */ class ServerParams { /** * Returns maximum post size in bytes. * * @return null|integer The maximum post size in bytes */ public function getPostMaxSize() { $iniMax = strtolower($this->getNormalizedIniPostMaxSize()); if ('' === $iniMax) { return null; } $max = ltrim($iniMax, '+'); if (0 === strpos($max, '0x')) { $max = intval($max, 16); } elseif (0 === strpos($max, '0')) { $max = intval($max, 8); } else { $max = intval($max); } switch (substr($iniMax, -1)) { case 't': $max *= 1024; case 'g': $max *= 1024; case 'm': $max *= 1024; case 'k': $max *= 1024; } return $max; } /** * Returns the normalized "post_max_size" ini setting. * * @return string */ public function getNormalizedIniPostMaxSize() { return strtoupper(trim(ini_get('post_max_size'))); } /** * Returns the content length of the request. * * @return mixed The request content length. */ public function getContentLength() { return isset($_SERVER['CONTENT_LENGTH']) ? (int) $_SERVER['CONTENT_LENGTH'] : null; } } PK!2=[<((ASymfony/Component/Form/Extension/Validator/ValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\Validator\Constraints\Valid; /** * Extension supporting the Symfony2 Validator component in forms. * * @author Bernhard Schussek */ class ValidatorExtension extends AbstractExtension { private $validator; public function __construct(ValidatorInterface $validator) { $this->validator = $validator; // Register the form constraints in the validator programmatically. // This functionality is required when using the Form component without // the DIC, where the XML file is loaded automatically. Thus the following // code must be kept synchronized with validation.xml /** @var \Symfony\Component\Validator\Mapping\ClassMetadata $metadata */ $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); $metadata->addConstraint(new Form()); $metadata->addPropertyConstraint('children', new Valid()); } public function loadTypeGuesser() { return new ValidatorTypeGuesser($this->validator->getMetadataFactory()); } protected function loadTypeExtensions() { return array( new Type\FormTypeValidatorExtension($this->validator), new Type\RepeatedTypeValidatorExtension(), new Type\SubmitTypeValidatorExtension(), ); } } PK!}>ُ?Symfony/Component/Form/Extension/Validator/Constraints/Form.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @author Bernhard Schussek */ class Form extends Constraint { /** * Violation code marking an invalid form. */ const ERR_INVALID = 1; /** * {@inheritdoc} */ public function getTargets() { return self::CLASS_CONSTRAINT; } } PK!-PHSymfony/Component/Form/Extension/Validator/Constraints/FormValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Constraints; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek */ class FormValidator extends ConstraintValidator { /** * @var ServerParams */ private $serverParams; /** * Creates a validator with the given server parameters. * * @param ServerParams $params The server parameters. Default * parameters are created if null. */ public function __construct(ServerParams $params = null) { $this->serverParams = $params ?: new ServerParams(); } /** * {@inheritdoc} */ public function validate($form, Constraint $constraint) { if (!$form instanceof FormInterface) { return; } /* @var FormInterface $form */ $config = $form->getConfig(); if ($form->isSynchronized()) { // Validate the form data only if transformation succeeded $groups = self::getValidationGroups($form); // Validate the data against its own constraints if (self::allowDataWalking($form)) { foreach ($groups as $group) { $this->context->validate($form->getData(), 'data', $group, true); } } // Validate the data against the constraints defined // in the form $constraints = $config->getOption('constraints'); foreach ($constraints as $constraint) { foreach ($groups as $group) { if (in_array($group, $constraint->groups)) { $this->context->validateValue($form->getData(), $constraint, 'data', $group); // Prevent duplicate validation continue 2; } } } } else { $childrenSynchronized = true; foreach ($form as $child) { if (!$child->isSynchronized()) { $childrenSynchronized = false; break; } } // Mark the form with an error if it is not synchronized BUT all // of its children are synchronized. If any child is not // synchronized, an error is displayed there already and showing // a second error in its parent form is pointless, or worse, may // lead to duplicate errors if error bubbling is enabled on the // child. // See also https://github.com/symfony/symfony/issues/4359 if ($childrenSynchronized) { $clientDataAsString = is_scalar($form->getViewData()) ? (string) $form->getViewData() : gettype($form->getViewData()); $this->context->addViolation( $config->getOption('invalid_message'), array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), $form->getViewData(), null, Form::ERR_INVALID ); } } // Mark the form with an error if it contains extra fields if (count($form->getExtraData()) > 0) { $this->context->addViolation( $config->getOption('extra_fields_message'), array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), $form->getExtraData() ); } // Mark the form with an error if the uploaded size was too large $length = $this->serverParams->getContentLength(); if ($form->isRoot() && null !== $length) { $max = $this->serverParams->getPostMaxSize(); if (!empty($max) && $length > $max) { $this->context->addViolation( $config->getOption('post_max_size_message'), array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), $length ); } } } /** * Returns whether the data of a form may be walked. * * @param FormInterface $form The form to test. * * @return Boolean Whether the graph walker may walk the data. */ private static function allowDataWalking(FormInterface $form) { $data = $form->getData(); // Scalar values cannot have mapped constraints if (!is_object($data) && !is_array($data)) { return false; } // Root forms are always validated if ($form->isRoot()) { return true; } // Non-root forms are validated if validation cascading // is enabled in all ancestor forms while (null !== ($form = $form->getParent())) { if (!$form->getConfig()->getOption('cascade_validation')) { return false; } } return true; } /** * Returns the validation groups of the given form. * * @param FormInterface $form The form. * * @return array The validation groups. */ private static function getValidationGroups(FormInterface $form) { // Determine the clicked button of the complete form tree $clickedButton = null; if (method_exists($form, 'getClickedButton')) { $clickedButton = $form->getClickedButton(); } if (null !== $clickedButton) { $groups = $clickedButton->getConfig()->getOption('validation_groups'); if (null !== $groups) { return self::resolveValidationGroups($groups, $form); } } do { $groups = $form->getConfig()->getOption('validation_groups'); if (null !== $groups) { return self::resolveValidationGroups($groups, $form); } $form = $form->getParent(); } while (null !== $form); return array(Constraint::DEFAULT_GROUP); } /** * Post-processes the validation groups option for a given form. * * @param array|callable $groups The validation groups. * @param FormInterface $form The validated form. * * @return array The validation groups. */ private static function resolveValidationGroups($groups, FormInterface $form) { if (!is_string($groups) && is_callable($groups)) { $groups = call_user_func($groups, $form); } return (array) $groups; } } PK!lCt*t*CSymfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; use Symfony\Component\Form\Guess\ValueGuess; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Constraint; class ValidatorTypeGuesser implements FormTypeGuesserInterface { private $metadataFactory; public function __construct(MetadataFactoryInterface $metadataFactory) { $this->metadataFactory = $metadataFactory; } /** * {@inheritDoc} */ public function guessType($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessTypeForConstraint($constraint); }); } /** * {@inheritDoc} */ public function guessRequired($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessRequiredForConstraint($constraint); // If we don't find any constraint telling otherwise, we can assume // that a field is not required (with LOW_CONFIDENCE) }, false); } /** * {@inheritDoc} */ public function guessMaxLength($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessMaxLengthForConstraint($constraint); }); } /** * {@inheritDoc} */ public function guessPattern($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessPatternForConstraint($constraint); }); } /** * Guesses a field class name for a given constraint * * @param Constraint $constraint The constraint to guess for * * @return TypeGuess|null The guessed field class and options */ public function guessTypeForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\Type': switch ($constraint->type) { case 'array': return new TypeGuess('collection', array(), Guess::MEDIUM_CONFIDENCE); case 'boolean': case 'bool': return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); case 'double': case 'float': case 'numeric': case 'real': return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE); case 'integer': case 'int': case 'long': return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE); case '\DateTime': return new TypeGuess('date', array(), Guess::MEDIUM_CONFIDENCE); case 'string': return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Country': return new TypeGuess('country', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Date': return new TypeGuess('date', array('input' => 'string'), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\DateTime': return new TypeGuess('datetime', array('input' => 'string'), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Email': return new TypeGuess('email', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\File': case 'Symfony\Component\Validator\Constraints\Image': return new TypeGuess('file', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Language': return new TypeGuess('language', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Locale': return new TypeGuess('locale', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Time': return new TypeGuess('time', array('input' => 'string'), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Url': return new TypeGuess('url', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Ip': return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Length': case 'Symfony\Component\Validator\Constraints\Regex': return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Range': return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Count': return new TypeGuess('collection', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\True': case 'Symfony\Component\Validator\Constraints\False': return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); } return null; } /** * Guesses whether a field is required based on the given constraint * * @param Constraint $constraint The constraint to guess for * * @return ValueGuess|null The guess whether the field is required */ public function guessRequiredForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\NotNull': case 'Symfony\Component\Validator\Constraints\NotBlank': case 'Symfony\Component\Validator\Constraints\True': return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } return null; } /** * Guesses a field's maximum length based on the given constraint * * @param Constraint $constraint The constraint to guess for * * @return ValueGuess|null The guess for the maximum length */ public function guessMaxLengthForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\Length': if (is_numeric($constraint->max)) { return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Type': if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Range': if (is_numeric($constraint->max)) { return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE); } break; } return null; } /** * Guesses a field's pattern based on the given constraint * * @param Constraint $constraint The constraint to guess for * * @return ValueGuess|null The guess for the pattern */ public function guessPatternForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\Length': if (is_numeric($constraint->min)) { return new ValueGuess(sprintf('.{%s,}', (string) $constraint->min), Guess::LOW_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Regex': $htmlPattern = $constraint->getHtmlPattern(); if (null !== $htmlPattern) { return new ValueGuess($htmlPattern, Guess::HIGH_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Range': if (is_numeric($constraint->min)) { return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->min)), Guess::LOW_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Type': if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } break; } return null; } /** * Iterates over the constraints of a property, executes a constraints on * them and returns the best guess * * @param string $class The class to read the constraints from * @param string $property The property for which to find constraints * @param \Closure $closure The closure that returns a guess * for a given constraint * @param mixed $defaultValue The default value assumed if no other value * can be guessed. * * @return Guess|null The guessed value with the highest confidence */ protected function guess($class, $property, \Closure $closure, $defaultValue = null) { $guesses = array(); $classMetadata = $this->metadataFactory->getMetadataFor($class); if ($classMetadata->hasMemberMetadatas($property)) { $memberMetadatas = $classMetadata->getMemberMetadatas($property); foreach ($memberMetadatas as $memberMetadata) { $constraints = $memberMetadata->getConstraints(); foreach ($constraints as $constraint) { if ($guess = $closure($constraint)) { $guesses[] = $guess; } } } if (null !== $defaultValue) { $guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE); } } return Guess::getBestGuess($guesses); } } PK!ɥSTSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\PropertyAccess\PropertyPathIterator; /** * @author Bernhard Schussek */ class ViolationPathIterator extends PropertyPathIterator { public function __construct(ViolationPath $violationPath) { parent::__construct($violationPath); } public function mapsForm() { return $this->path->mapsForm($this->key()); } } PK!\TKSymfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\PropertyAccess\PropertyPath; /** * @author Bernhard Schussek */ class RelativePath extends PropertyPath { /** * @var FormInterface */ private $root; /** * @param FormInterface $root * @param string $propertyPath */ public function __construct(FormInterface $root, $propertyPath) { parent::__construct($propertyPath); $this->root = $root; } /** * @return FormInterface */ public function getRoot() { return $this->root; } } PK!C_hU+U+NSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\PropertyAccess\PropertyPathIterator; use Symfony\Component\PropertyAccess\PropertyPathBuilder; use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface; use Symfony\Component\Form\FormError; use Symfony\Component\Validator\ConstraintViolation; /** * @author Bernhard Schussek */ class ViolationMapper implements ViolationMapperInterface { /** * @var Boolean */ private $allowNonSynchronized; /** * {@inheritdoc} */ public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false) { $this->allowNonSynchronized = $allowNonSynchronized; // The scope is the currently found most specific form that // an error should be mapped to. After setting the scope, the // mapper will try to continue to find more specific matches in // the children of scope. If it cannot, the error will be // mapped to this scope. $scope = null; $violationPath = null; $relativePath = null; $match = false; // Don't create a ViolationPath instance for empty property paths if (strlen($violation->getPropertyPath()) > 0) { $violationPath = new ViolationPath($violation->getPropertyPath()); $relativePath = $this->reconstructPath($violationPath, $form); } // This case happens if the violation path is empty and thus // the violation should be mapped to the root form if (null === $violationPath) { $scope = $form; } // In general, mapping happens from the root form to the leaf forms // First, the rules of the root form are applied to determine // the subsequent descendant. The rules of this descendant are then // applied to find the next and so on, until we have found the // most specific form that matches the violation. // If any of the forms found in this process is not synchronized, // mapping is aborted. Non-synchronized forms could not reverse // transform the value entered by the user, thus any further violations // caused by the (invalid) reverse transformed value should be // ignored. if (null !== $relativePath) { // Set the scope to the root of the relative path // This root will usually be $form. If the path contains // an unmapped form though, the last unmapped form found // will be the root of the path. $scope = $relativePath->getRoot(); $it = new PropertyPathIterator($relativePath); while ($this->acceptsErrors($scope) && null !== ($child = $this->matchChild($scope, $it))) { $scope = $child; $it->next(); $match = true; } } // This case happens if an error happened in the data under a // form inheriting its parent data that does not match any of the // children of that form. if (null !== $violationPath && !$match) { // If we could not map the error to anything more specific // than the root element, map it to the innermost directly // mapped form of the violation path // e.g. "children[foo].children[bar].data.baz" // Here the innermost directly mapped child is "bar" $scope = $form; $it = new ViolationPathIterator($violationPath); // Note: acceptsErrors() will always return true for forms inheriting // their parent data, because these forms can never be non-synchronized // (they don't do any data transformation on their own) while ($this->acceptsErrors($scope) && $it->valid() && $it->mapsForm()) { if (!$scope->has($it->current())) { // Break if we find a reference to a non-existing child break; } $scope = $scope->get($it->current()); $it->next(); } } // Follow dot rules until we have the final target $mapping = $scope->getConfig()->getOption('error_mapping'); while ($this->acceptsErrors($scope) && isset($mapping['.'])) { $dotRule = new MappingRule($scope, '.', $mapping['.']); $scope = $dotRule->getTarget(); $mapping = $scope->getConfig()->getOption('error_mapping'); } // Only add the error if the form is synchronized if ($this->acceptsErrors($scope)) { $scope->addError(new FormError( $violation->getMessage(), $violation->getMessageTemplate(), $violation->getMessageParameters(), $violation->getMessagePluralization() )); } } /** * Tries to match the beginning of the property path at the * current position against the children of the scope. * * If a matching child is found, it is returned. Otherwise * null is returned. * * @param FormInterface $form The form to search. * @param PropertyPathIteratorInterface $it The iterator at its current position. * * @return null|FormInterface The found match or null. */ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it) { // Remember at what property path underneath "data" // we are looking. Check if there is a child with that // path, otherwise increase path by one more piece $chunk = ''; $foundChild = null; $foundAtIndex = 0; // Construct mapping rules for the given form $rules = array(); foreach ($form->getConfig()->getOption('error_mapping') as $propertyPath => $targetPath) { // Dot rules are considered at the very end if ('.' !== $propertyPath) { $rules[] = new MappingRule($form, $propertyPath, $targetPath); } } // Skip forms inheriting their parent data when iterating the children $childIterator = new \RecursiveIteratorIterator( new InheritDataAwareIterator($form) ); // Make the path longer until we find a matching child while (true) { if (!$it->valid()) { return null; } if ($it->isIndex()) { $chunk .= '['.$it->current().']'; } else { $chunk .= ('' === $chunk ? '' : '.').$it->current(); } // Test mapping rules as long as we have any foreach ($rules as $key => $rule) { /* @var MappingRule $rule */ // Mapping rule matches completely, terminate. if (null !== ($form = $rule->match($chunk))) { return $form; } // Keep only rules that have $chunk as prefix if (!$rule->isPrefix($chunk)) { unset($rules[$key]); } } // Test children unless we already found one if (null === $foundChild) { foreach ($childIterator as $child) { /* @var FormInterface $child */ $childPath = (string) $child->getPropertyPath(); // Child found, mark as return value if ($chunk === $childPath) { $foundChild = $child; $foundAtIndex = $it->key(); } } } // Add element to the chunk $it->next(); // If we reached the end of the path or if there are no // more matching mapping rules, return the found child if (null !== $foundChild && (!$it->valid() || count($rules) === 0)) { // Reset index in case we tried to find mapping // rules further down the path $it->seek($foundAtIndex); return $foundChild; } } return null; } /** * Reconstructs a property path from a violation path and a form tree. * * @param ViolationPath $violationPath The violation path. * @param FormInterface $origin The root form of the tree. * * @return RelativePath The reconstructed path. */ private function reconstructPath(ViolationPath $violationPath, FormInterface $origin) { $propertyPathBuilder = new PropertyPathBuilder($violationPath); $it = $violationPath->getIterator(); $scope = $origin; // Remember the current index in the builder $i = 0; // Expand elements that map to a form (like "children[address]") for ($it->rewind(); $it->valid() && $it->mapsForm(); $it->next()) { if (!$scope->has($it->current())) { // Scope relates to a form that does not exist // Bail out break; } // Process child form $scope = $scope->get($it->current()); if ($scope->getConfig()->getInheritData()) { // Form inherits its parent data // Cut the piece out of the property path and proceed $propertyPathBuilder->remove($i); } elseif (!$scope->getConfig()->getMapped()) { // Form is not mapped // Set the form as new origin and strip everything // we have so far in the path $origin = $scope; $propertyPathBuilder->remove(0, $i + 1); $i = 0; } else { /* @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */ $propertyPath = $scope->getPropertyPath(); if (null === $propertyPath) { // Property path of a mapped form is null // Should not happen, bail out break; } $propertyPathBuilder->replace($i, 1, $propertyPath); $i += $propertyPath->getLength(); } } $finalPath = $propertyPathBuilder->getPropertyPath(); return null !== $finalPath ? new RelativePath($origin, $finalPath) : null; } /** * @param FormInterface $form * * @return Boolean */ private function acceptsErrors(FormInterface $form) { return $this->allowNonSynchronized || $form->isSynchronized(); } } PK!kt==WSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\Validator\ConstraintViolation; /** * @author Bernhard Schussek */ interface ViolationMapperInterface { /** * Maps a constraint violation to a form in the form tree under * the given form. * * @param ConstraintViolation $violation The violation to map. * @param FormInterface $form The root form of the tree * to map it to. * @param Boolean $allowNonSynchronized Whether to allow * mapping to non-synchronized forms. */ public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false); } PK!-!!LSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; /** * @author Bernhard Schussek */ class ViolationPath implements \IteratorAggregate, PropertyPathInterface { /** * @var array */ private $elements = array(); /** * @var array */ private $isIndex = array(); /** * @var array */ private $mapsForm = array(); /** * @var string */ private $pathAsString = ''; /** * @var integer */ private $length = 0; /** * Creates a new violation path from a string. * * @param string $violationPath The property path of a {@link ConstraintViolation} * object. */ public function __construct($violationPath) { $path = new PropertyPath($violationPath); $elements = $path->getElements(); $data = false; for ($i = 0, $l = count($elements); $i < $l; ++$i) { if (!$data) { // The element "data" has not yet been passed if ('children' === $elements[$i] && $path->isProperty($i)) { // Skip element "children" ++$i; // Next element must exist and must be an index // Otherwise consider this the end of the path if ($i >= $l || !$path->isIndex($i)) { break; } $this->elements[] = $elements[$i]; $this->isIndex[] = true; $this->mapsForm[] = true; } elseif ('data' === $elements[$i] && $path->isProperty($i)) { // Skip element "data" ++$i; // End of path if ($i >= $l) { break; } $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; $data = true; } else { // Neither "children" nor "data" property found // Consider this the end of the path break; } } else { // Already after the "data" element // Pick everything as is $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; } } $this->length = count($this->elements); $this->buildString(); } /** * {@inheritdoc} */ public function __toString() { return $this->pathAsString; } /** * {@inheritdoc} */ public function getLength() { return $this->length; } /** * {@inheritdoc} */ public function getParent() { if ($this->length <= 1) { return null; } $parent = clone $this; --$parent->length; array_pop($parent->elements); array_pop($parent->isIndex); array_pop($parent->mapsForm); $parent->buildString(); return $parent; } /** * {@inheritdoc} */ public function getElements() { return $this->elements; } /** * {@inheritdoc} */ public function getElement($index) { if (!isset($this->elements[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->elements[$index]; } /** * {@inheritdoc} */ public function isProperty($index) { if (!isset($this->isIndex[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return !$this->isIndex[$index]; } /** * {@inheritdoc} */ public function isIndex($index) { if (!isset($this->isIndex[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->isIndex[$index]; } /** * Returns whether an element maps directly to a form. * * Consider the following violation path: * * * children[address].children[office].data.street * * * In this example, "address" and "office" map to forms, while * "street does not. * * @param integer $index The element index. * * @return Boolean Whether the element maps to a form. * * @throws OutOfBoundsException If the offset is invalid. */ public function mapsForm($index) { if (!isset($this->mapsForm[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->mapsForm[$index]; } /** * Returns a new iterator for this path * * @return ViolationPathIterator */ public function getIterator() { return new ViolationPathIterator($this); } /** * Builds the string representation from the elements. */ private function buildString() { $this->pathAsString = ''; $data = false; foreach ($this->elements as $index => $element) { if ($this->mapsForm[$index]) { $this->pathAsString .= ".children[$element]"; } elseif (!$data) { $this->pathAsString .= '.data'.($this->isIndex[$index] ? "[$element]" : ".$element"); $data = true; } else { $this->pathAsString .= $this->isIndex[$index] ? "[$element]" : ".$element"; } } if ('' !== $this->pathAsString) { // remove leading dot $this->pathAsString = substr($this->pathAsString, 1); } } } PK!f JSymfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Exception\ErrorMappingException; /** * @author Bernhard Schussek */ class MappingRule { /** * @var FormInterface */ private $origin; /** * @var string */ private $propertyPath; /** * @var string */ private $targetPath; public function __construct(FormInterface $origin, $propertyPath, $targetPath) { $this->origin = $origin; $this->propertyPath = $propertyPath; $this->targetPath = $targetPath; } /** * @return FormInterface */ public function getOrigin() { return $this->origin; } /** * Matches a property path against the rule path. * * If the rule matches, the form mapped by the rule is returned. * Otherwise this method returns false. * * @param string $propertyPath The property path to match against the rule. * * @return null|FormInterface The mapped form or null. */ public function match($propertyPath) { if ($propertyPath === (string) $this->propertyPath) { return $this->getTarget(); } return null; } /** * Matches a property path against a prefix of the rule path. * * @param string $propertyPath The property path to match against the rule. * * @return Boolean Whether the property path is a prefix of the rule or not. */ public function isPrefix($propertyPath) { $length = strlen($propertyPath); $prefix = substr($this->propertyPath, 0, $length); $next = isset($this->propertyPath[$length]) ? $this->propertyPath[$length] : null; return $prefix === $propertyPath && ('[' === $next || '.' === $next); } /** * @return FormInterface * * @throws ErrorMappingException */ public function getTarget() { $childNames = explode('.', $this->targetPath); $target = $this->origin; foreach ($childNames as $childName) { if (!$target->has($childName)) { throw new ErrorMappingException(sprintf('The child "%s" of "%s" mapped by the rule "%s" in "%s" does not exist.', $childName, $target->getName(), $this->targetPath, $this->origin->getName())); } $target = $target->get($childName); } return $target; } } PK!JSymfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * Encapsulates common logic of {@link FormTypeValidatorExtension} and * {@link SubmitTypeValidatorExtension}. * * @author Bernhard Schussek */ abstract class BaseValidatorExtension extends AbstractTypeExtension { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { // Make sure that validation groups end up as null, closure or array $validationGroupsNormalizer = function (Options $options, $groups) { if (false === $groups) { return array(); } if (empty($groups)) { return null; } if (is_callable($groups)) { return $groups; } return (array) $groups; }; $resolver->setDefaults(array( 'validation_groups' => null, )); $resolver->setNormalizers(array( 'validation_groups' => $validationGroupsNormalizer, )); } } PK!eBR NSymfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ class FormTypeValidatorExtension extends BaseValidatorExtension { /** * @var ValidatorInterface */ private $validator; /** * @var ViolationMapper */ private $violationMapper; public function __construct(ValidatorInterface $validator) { $this->validator = $validator; $this->violationMapper = new ViolationMapper(); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber(new ValidationListener($this->validator, $this->violationMapper)); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); // Constraint should always be converted to an array $constraintsNormalizer = function (Options $options, $constraints) { return is_object($constraints) ? array($constraints) : (array) $constraints; }; $resolver->setDefaults(array( 'error_mapping' => array(), 'constraints' => array(), 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'extra_fields_message' => 'This form should not contain extra fields.', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', )); $resolver->setNormalizers(array( 'constraints' => $constraintsNormalizer, )); } /** * {@inheritdoc} */ public function getExtendedType() { return 'form'; } } PK!͚>@@RSymfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ class RepeatedTypeValidatorExtension extends AbstractTypeExtension { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { // Map errors to the first field $errorMapping = function (Options $options) { return array('.' => $options['first_name']); }; $resolver->setDefaults(array( 'error_mapping' => $errorMapping, )); } /** * {@inheritdoc} */ public function getExtendedType() { return 'repeated'; } } PK!1PSymfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; /** * @author Bernhard Schussek */ class SubmitTypeValidatorExtension extends BaseValidatorExtension { /** * {@inheritdoc} */ public function getExtendedType() { return 'submit'; } } PK!,QQCSymfony/Component/Form/Extension/Templating/TemplatingExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Templating; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Templating\PhpEngine; use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper; /** * Integrates the Templating component with the Form library. * * @author Bernhard Schussek */ class TemplatingExtension extends AbstractExtension { public function __construct(PhpEngine $engine, $csrfTokenManager = null, array $defaultThemes = array()) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $engine->addHelpers(array( new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfTokenManager)) )); } } PK!զYHSymfony/Component/Form/Extension/Templating/TemplatingRendererEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Templating; use Symfony\Component\Form\AbstractRendererEngine; use Symfony\Component\Form\FormView; use Symfony\Component\Templating\EngineInterface; /** * @author Bernhard Schussek */ class TemplatingRendererEngine extends AbstractRendererEngine { /** * @var EngineInterface */ private $engine; public function __construct(EngineInterface $engine, array $defaultThemes = array()) { parent::__construct($defaultThemes); $this->engine = $engine; } /** * {@inheritdoc} */ public function renderBlock(FormView $view, $resource, $blockName, array $variables = array()) { return trim($this->engine->render($resource, $variables)); } /** * Loads the cache with the resource for a given block name. * * This implementation tries to load as few blocks as possible, since each block * is represented by a template on the file system. * * @see getResourceForBlock() * * @param string $cacheKey The cache key of the form view. * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * * @return Boolean True if the resource could be loaded, false otherwise. */ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName) { // Recursively try to find the block in the themes assigned to $view, // then of its parent form, then of the parent form of the parent and so on. // When the root form is reached in this recursion, also the default // themes are taken into account. // Check each theme whether it contains the searched block if (isset($this->themes[$cacheKey])) { for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) { if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->themes[$cacheKey][$i])) { return true; } } } // Check the default themes once we reach the root form without success if (!$view->parent) { for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->defaultThemes[$i])) { return true; } } } // If we did not find anything in the themes of the current view, proceed // with the themes of the parent view if ($view->parent) { $parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR]; if (!isset($this->resources[$parentCacheKey][$blockName])) { $this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName); } // If a template exists in the parent themes, cache that template // for the current theme as well to speed up further accesses if ($this->resources[$parentCacheKey][$blockName]) { $this->resources[$cacheKey][$blockName] = $this->resources[$parentCacheKey][$blockName]; return true; } } // Cache that we didn't find anything to speed up further accesses $this->resources[$cacheKey][$blockName] = false; return false; } /** * Tries to load the resource for a block from a theme. * * @param string $cacheKey The cache key for storing the resource. * @param string $blockName The name of the block to load a resource for. * @param mixed $theme The theme to load the block from. * * @return Boolean True if the resource could be loaded, false otherwise. */ protected function loadResourceFromTheme($cacheKey, $blockName, $theme) { if ($this->engine->exists($templateName = $theme.':'.$blockName.'.html.php')) { $this->resources[$cacheKey][$blockName] = $templateName; return true; } return false; } } PK!䋧 USymfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; /** * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Pass the * Request instance to {@link Form::handleRequest()} instead. */ class BindRequestListener implements EventSubscriberInterface { public static function getSubscribedEvents() { // High priority in order to supersede other listeners return array(FormEvents::PRE_BIND => array('preBind', 128)); } public function preBind(FormEvent $event) { $form = $event->getForm(); /* @var Request $request */ $request = $event->getData(); // Only proceed if we actually deal with a Request if (!$request instanceof Request) { return; } // Uncomment this as soon as the deprecation note should be shown // trigger_error('Passing a Request instance to Form::submit() is deprecated since version 2.3 and will be disabled in 3.0. Call Form::process($request) instead.', E_USER_DEPRECATED); $name = $form->getConfig()->getName(); $default = $form->getConfig()->getCompound() ? array() : null; // Store the bound data in case of a post request switch ($request->getMethod()) { case 'POST': case 'PUT': case 'DELETE': case 'PATCH': if ('' === $name) { // Form bound without name $params = $request->request->all(); $files = $request->files->all(); } else { $params = $request->request->get($name, $default); $files = $request->files->get($name, $default); } if (is_array($params) && is_array($files)) { $data = array_replace_recursive($params, $files); } else { $data = $params ?: $files; } break; case 'GET': $data = '' === $name ? $request->query->all() : $request->query->get($name, $default); break; default: throw new LogicException(sprintf( 'The request method "%s" is not supported', $request->getMethod() )); } $event->setData($data); } } PK!j= = PSymfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\RequestHandlerInterface; use Symfony\Component\HttpFoundation\Request; /** * A request processor using the {@link Request} class of the HttpFoundation * component. * * @author Bernhard Schussek */ class HttpFoundationRequestHandler implements RequestHandlerInterface { /** * {@inheritdoc} */ public function handleRequest(FormInterface $form, $request = null) { if (!$request instanceof Request) { throw new UnexpectedTypeException($request, 'Symfony\Component\HttpFoundation\Request'); } $name = $form->getName(); $method = $form->getConfig()->getMethod(); if ($method !== $request->getMethod()) { return; } if ('GET' === $method) { if ('' === $name) { $data = $request->query->all(); } else { // Don't submit GET requests if the form's name does not exist // in the request if (!$request->query->has($name)) { return; } $data = $request->query->get($name); } } else { if ('' === $name) { $params = $request->request->all(); $files = $request->files->all(); } elseif ($request->request->has($name) || $request->files->has($name)) { $default = $form->getConfig()->getCompound() ? array() : null; $params = $request->request->get($name, $default); $files = $request->files->get($name, $default); } else { // Don't submit the form if it is not present in the request return; } if (is_array($params) && is_array($files)) { $data = array_replace_recursive($params, $files); } else { $data = $params ?: $files; } } // Don't auto-submit the form unless at least one field is present. if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { return; } $form->submit($data, 'PATCH' !== $method); } } PK!QKSymfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\AbstractExtension; /** * Integrates the HttpFoundation component with the Form library. * * @author Bernhard Schussek */ class HttpFoundationExtension extends AbstractExtension { protected function loadTypeExtensions() { return array( new Type\FormTypeHttpFoundationExtension(), ); } } PK!PffXSymfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormBuilderInterface; /** * @author Bernhard Schussek */ class FormTypeHttpFoundationExtension extends AbstractTypeExtension { /** * @var BindRequestListener */ private $listener; /** * @var HttpFoundationRequestHandler */ private $requestHandler; public function __construct() { $this->listener = new BindRequestListener(); $this->requestHandler = new HttpFoundationRequestHandler(); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber($this->listener); $builder->setRequestHandler($this->requestHandler); } /** * {@inheritdoc} */ public function getExtendedType() { return 'form'; } } PK!"q7Symfony/Component/Form/Extension/Csrf/CsrfExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** * This extension protects forms by using a CSRF token. * * @author Bernhard Schussek */ class CsrfExtension extends AbstractExtension { /** * @var CsrfTokenManagerInterface */ private $tokenManager; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * Constructor. * * @param CsrfTokenManagerInterface $tokenManager The CSRF token manager * @param TranslatorInterface $translator The translator for translating error messages * @param null|string $translationDomain The translation domain for translating */ public function __construct($tokenManager, TranslatorInterface $translator = null, $translationDomain = null) { if ($tokenManager instanceof CsrfProviderInterface) { $tokenManager = new CsrfProviderAdapter($tokenManager); } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $this->tokenManager = $tokenManager; $this->translator = $translator; $this->translationDomain = $translationDomain; } /** * {@inheritDoc} */ protected function loadTypeExtensions() { return array( new Type\FormTypeCsrfExtension($this->tokenManager, true, '_token', $this->translator, $this->translationDomain), ); } } PK!CJSymfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; /** * Default implementation of CsrfProviderInterface. * * This provider uses the session ID returned by session_id() as well as a * user-defined secret value to secure the CSRF token. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use * {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage} * instead. */ class DefaultCsrfProvider implements CsrfProviderInterface { /** * A secret value used for generating the CSRF token * @var string */ protected $secret; /** * Initializes the provider with a secret value * * A recommended value for the secret is a generated value with at least * 32 characters and mixed letters, digits and special characters. * * @param string $secret A secret value included in the CSRF token */ public function __construct($secret) { $this->secret = $secret; } /** * {@inheritDoc} */ public function generateCsrfToken($intention) { return sha1($this->secret.$intention.$this->getSessionId()); } /** * {@inheritDoc} */ public function isCsrfTokenValid($intention, $token) { return $token === $this->generateCsrfToken($intention); } /** * Returns the ID of the user session. * * Automatically starts the session if necessary. * * @return string The session ID */ protected function getSessionId() { if (version_compare(PHP_VERSION, '5.4', '>=')) { if (PHP_SESSION_NONE === session_status()) { session_start(); } } elseif (!session_id()) { session_start(); } return session_id(); } } PK![^JSymfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; use Symfony\Component\HttpFoundation\Session\Session; /** * This provider uses a Symfony2 Session object to retrieve the user's * session ID. * * @see DefaultCsrfProvider * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use * {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage} * instead. */ class SessionCsrfProvider extends DefaultCsrfProvider { /** * The user session from which the session ID is returned * @var Session */ protected $session; /** * Initializes the provider with a Session object and a secret value. * * A recommended value for the secret is a generated value with at least * 32 characters and mixed letters, digits and special characters. * * @param Session $session The user session * @param string $secret A secret value included in the CSRF token */ public function __construct(Session $session, $secret) { parent::__construct($secret); $this->session = $session; } /** * {@inheritdoc} */ protected function getSessionId() { $this->session->start(); return $this->session->getId(); } } PK!%GLSymfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; /** * Marks classes able to provide CSRF protection * * You can generate a CSRF token by using the method generateCsrfToken(). To * this method you should pass a value that is unique to the page that should * be secured against CSRF attacks. This value doesn't necessarily have to be * secret. Implementations of this interface are responsible for adding more * secret information. * * If you want to secure a form submission against CSRF attacks, you could * supply an "intention" string. This way you make sure that the form can only * be submitted to pages that are designed to handle the form, that is, that use * the same intention string to validate the CSRF token with isCsrfTokenValid(). * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use * {@link \Symfony\Component\Security\Csrf\CsrfTokenManagerInterface} * instead. */ interface CsrfProviderInterface { /** * Generates a CSRF token for a page of your application. * * @param string $intention Some value that identifies the action intention * (i.e. "authenticate"). Doesn't have to be a secret value. * * @return string The generated token */ public function generateCsrfToken($intention); /** * Validates a CSRF token. * * @param string $intention The intention used when generating the CSRF token * @param string $token The token supplied by the browser * * @return Boolean Whether the token supplied by the browser is correct */ public function isCsrfTokenValid($intention, $token); } PK!JSymfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Adapter for using old CSRF providers where the new {@link CsrfTokenManagerInterface} * is expected. * * @since 2.4 * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. */ class CsrfProviderAdapter implements CsrfTokenManagerInterface { /** * @var CsrfProviderInterface */ private $csrfProvider; public function __construct(CsrfProviderInterface $csrfProvider) { $this->csrfProvider = $csrfProvider; } public function getCsrfProvider() { return $this->csrfProvider; } /** * {@inheritdoc} */ public function getToken($tokenId) { return new CsrfToken($tokenId, $this->csrfProvider->generateCsrfToken($tokenId)); } /** * {@inheritdoc} */ public function refreshToken($tokenId) { throw new BadMethodCallException('Not supported'); } /** * {@inheritdoc} */ public function removeToken($tokenId) { throw new BadMethodCallException('Not supported'); } /** * {@inheritdoc} */ public function isTokenValid(CsrfToken $token) { return $this->csrfProvider->isCsrfTokenValid($token->getId(), $token->getValue()); } } PK!R'WTTNSymfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Adapter for using the new token generator with the old interface. * * @since 2.4 * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. */ class CsrfTokenManagerAdapter implements CsrfProviderInterface { /** * @var CsrfTokenManagerInterface */ private $tokenManager; public function __construct(CsrfTokenManagerInterface $tokenManager) { $this->tokenManager = $tokenManager; } public function getTokenManager() { return $this->tokenManager; } /** * {@inheritdoc} */ public function generateCsrfToken($intention) { return $this->tokenManager->getToken($intention)->getValue(); } /** * {@inheritdoc} */ public function isCsrfTokenValid($intention, $token) { return $this->tokenManager->isTokenValid(new CsrfToken($intention, $token)); } } PK!?ooNSymfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** * @author Bernhard Schussek */ class CsrfValidationListener implements EventSubscriberInterface { /** * The name of the CSRF field * @var string */ private $fieldName; /** * The generator for CSRF tokens * @var CsrfTokenManagerInterface */ private $tokenManager; /** * A text mentioning the tokenId of the CSRF token * * Validation of the token will only succeed if it was generated in the * same session and with the same tokenId. * * @var string */ private $tokenId; /** * The message displayed in case of an error. * @var string */ private $errorMessage; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; public static function getSubscribedEvents() { return array( FormEvents::PRE_SUBMIT => 'preSubmit', ); } public function __construct($fieldName, $tokenManager, $tokenId, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null) { if ($tokenManager instanceof CsrfProviderInterface) { $tokenManager = new CsrfProviderAdapter($tokenManager); } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $this->fieldName = $fieldName; $this->tokenManager = $tokenManager; $this->tokenId = $tokenId; $this->errorMessage = $errorMessage; $this->translator = $translator; $this->translationDomain = $translationDomain; } public function preSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if ($form->isRoot() && $form->getConfig()->getOption('compound')) { if (!isset($data[$this->fieldName]) || !$this->tokenManager->isTokenValid(new CsrfToken($this->tokenId, $data[$this->fieldName]))) { $errorMessage = $this->errorMessage; if (null !== $this->translator) { $errorMessage = $this->translator->trans($errorMessage, array(), $this->translationDomain); } $form->addError(new FormError($errorMessage)); } if (is_array($data)) { unset($data[$this->fieldName]); } } $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } } PK! fDSymfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfTokenManagerAdapter; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** * @author Bernhard Schussek */ class FormTypeCsrfExtension extends AbstractTypeExtension { /** * @var CsrfTokenManagerInterface */ private $defaultTokenManager; /** * @var Boolean */ private $defaultEnabled; /** * @var string */ private $defaultFieldName; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; public function __construct($defaultTokenManager, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null) { if ($defaultTokenManager instanceof CsrfProviderInterface) { $defaultTokenManager = new CsrfProviderAdapter($defaultTokenManager); } elseif (!$defaultTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($defaultTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $this->defaultTokenManager = $defaultTokenManager; $this->defaultEnabled = $defaultEnabled; $this->defaultFieldName = $defaultFieldName; $this->translator = $translator; $this->translationDomain = $translationDomain; } /** * Adds a CSRF field to the form when the CSRF protection is enabled. * * @param FormBuilderInterface $builder The form builder * @param array $options The options */ public function buildForm(FormBuilderInterface $builder, array $options) { if (!$options['csrf_protection']) { return; } $builder ->addEventSubscriber(new CsrfValidationListener( $options['csrf_field_name'], $options['csrf_token_manager'], $options['csrf_token_id'] ?: ($builder->getName() ?: get_class($builder->getType()->getInnerType())), $options['csrf_message'], $this->translator, $this->translationDomain )) ; } /** * Adds a CSRF field to the root form view. * * @param FormView $view The form view * @param FormInterface $form The form * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['csrf_protection'] && !$view->parent && $options['compound']) { $factory = $form->getConfig()->getFormFactory(); $tokenId = $options['csrf_token_id'] ?: ($form->getName() ?: get_class($form->getConfig()->getType()->getInnerType())); $data = (string) $options['csrf_token_manager']->getToken($tokenId); $csrfForm = $factory->createNamed($options['csrf_field_name'], 'hidden', $data, array( 'mapped' => false, )); $view->children[$options['csrf_field_name']] = $csrfForm->createView($view); } } /** * {@inheritDoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { // BC clause for the "intention" option $csrfTokenId = function (Options $options) { return $options['intention']; }; // BC clause for the "csrf_provider" option $csrfTokenManager = function (Options $options) { return $options['csrf_provider'] instanceof CsrfTokenManagerAdapter ? $options['csrf_provider']->getTokenManager() : new CsrfProviderAdapter($options['csrf_provider']); }; $resolver->setDefaults(array( 'csrf_protection' => $this->defaultEnabled, 'csrf_field_name' => $this->defaultFieldName, 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'csrf_token_manager' => $csrfTokenManager, 'csrf_token_id' => $csrfTokenId, 'csrf_provider' => new CsrfTokenManagerAdapter($this->defaultTokenManager), 'intention' => null, )); } /** * {@inheritDoc} */ public function getExtendedType() { return 'form'; } } PK!CW7Symfony/Component/Form/Extension/Core/CoreExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\PropertyAccess\PropertyAccess; /** * Represents the main form extension, which loads the core functionality. * * @author Bernhard Schussek */ class CoreExtension extends AbstractExtension { protected function loadTypes() { return array( new Type\FormType(PropertyAccess::createPropertyAccessor()), new Type\BirthdayType(), new Type\CheckboxType(), new Type\ChoiceType(), new Type\CollectionType(), new Type\CountryType(), new Type\DateType(), new Type\DateTimeType(), new Type\EmailType(), new Type\HiddenType(), new Type\IntegerType(), new Type\LanguageType(), new Type\LocaleType(), new Type\MoneyType(), new Type\NumberType(), new Type\PasswordType(), new Type\PercentType(), new Type\RadioType(), new Type\RepeatedType(), new Type\SearchType(), new Type\TextareaType(), new Type\TextType(), new Type\TimeType(), new Type\TimezoneType(), new Type\UrlType(), new Type\FileType(), new Type\ButtonType(), new Type\SubmitType(), new Type\ResetType(), new Type\CurrencyType(), ); } } PK!:AADSymfony/Component/Form/Extension/Core/EventListener/TrimListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Trims string data * * @author Bernhard Schussek */ class TrimListener implements EventSubscriberInterface { public function preSubmit(FormEvent $event) { $data = $event->getData(); if (!is_string($data)) { return; } if (null !== $result = @preg_replace('/^[\pZ\p{Cc}]+|[\pZ\p{Cc}]+$/u', '', $data)) { $event->setData($result); } else { $event->setData(trim($data)); } } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } PK!õeOSymfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class MergeCollectionListener implements EventSubscriberInterface { /** * Whether elements may be added to the collection * @var Boolean */ private $allowAdd; /** * Whether elements may be removed from the collection * @var Boolean */ private $allowDelete; /** * Creates a new listener. * * @param Boolean $allowAdd Whether values might be added to the * collection. * @param Boolean $allowDelete Whether values might be removed from the * collection. */ public function __construct($allowAdd = false, $allowDelete = false) { $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; } public static function getSubscribedEvents() { return array( FormEvents::SUBMIT => 'onSubmit', ); } public function onSubmit(FormEvent $event) { $dataToMergeInto = $event->getForm()->getNormData(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } if (null !== $dataToMergeInto && !is_array($dataToMergeInto) && !($dataToMergeInto instanceof \Traversable && $dataToMergeInto instanceof \ArrayAccess)) { throw new UnexpectedTypeException($dataToMergeInto, 'array or (\Traversable and \ArrayAccess)'); } // If we are not allowed to change anything, return immediately if ((!$this->allowAdd && !$this->allowDelete) || $data === $dataToMergeInto) { $event->setData($dataToMergeInto); return; } if (!$dataToMergeInto) { // No original data was set. Set it if allowed if ($this->allowAdd) { $dataToMergeInto = $data; } } else { // Calculate delta $itemsToAdd = is_object($data) ? clone $data : $data; $itemsToDelete = array(); foreach ($dataToMergeInto as $beforeKey => $beforeItem) { foreach ($data as $afterKey => $afterItem) { if ($afterItem === $beforeItem) { // Item found, next original item unset($itemsToAdd[$afterKey]); continue 2; } } // Item not found, remember for deletion $itemsToDelete[] = $beforeKey; } // Remove deleted items before adding to free keys that are to be // replaced if ($this->allowDelete) { foreach ($itemsToDelete as $key) { unset($dataToMergeInto[$key]); } } // Add remaining items if ($this->allowAdd) { foreach ($itemsToAdd as $key => $item) { if (!isset($dataToMergeInto[$key])) { $dataToMergeInto[$key] = $item; } else { $dataToMergeInto[] = $item; } } } } $event->setData($dataToMergeInto); } /** * Alias of {@link onSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link onSubmit()} instead. */ public function onBind(FormEvent $event) { $this->onSubmit($event); } } PK!>Q?NSymfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Adds a protocol to a URL if it doesn't already have one. * * @author Bernhard Schussek */ class FixUrlProtocolListener implements EventSubscriberInterface { private $defaultProtocol; public function __construct($defaultProtocol = 'http') { $this->defaultProtocol = $defaultProtocol; } public function onSubmit(FormEvent $event) { $data = $event->getData(); if ($this->defaultProtocol && $data && !preg_match('~^\w+://~', $data)) { $event->setData($this->defaultProtocol.'://'.$data); } } /** * Alias of {@link onSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link onSubmit()} instead. */ public function onBind(FormEvent $event) { $this->onSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::SUBMIT => 'onSubmit'); } } PK!b PSymfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * Takes care of converting the input from a list of checkboxes to a correctly * indexed array. * * @author Bernhard Schussek */ class FixCheckboxInputListener implements EventSubscriberInterface { private $choiceList; /** * Constructor. * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } public function preSubmit(FormEvent $event) { $data = $event->getData(); if (is_array($data)) { // Flip the submitted values for faster lookup // It's better to flip this array than $existingValues because // $submittedValues is generally smaller. $submittedValues = array_flip($data); // Since expanded choice fields are completely loaded anyway, we // can just as well get the values again without losing performance. $existingValues = $this->choiceList->getValues(); // Clear the data array and fill it with correct indices $data = array(); foreach ($existingValues as $index => $value) { if (isset($submittedValues[$value])) { // Value was submitted $data[$index] = $value; unset($submittedValues[$value]); } } if (count($submittedValues) > 0) { throw new TransformationFailedException(sprintf( 'The following choices were not found: "%s"', implode('", "', array_keys($submittedValues)) )); } } elseif ('' === $data || null === $data) { // Empty values are always accepted. $data = array(); } // Else leave the data unchanged to provoke an error during submission $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } PK!\//JSymfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Resize a collection form element based on the data sent from the client. * * @author Bernhard Schussek */ class ResizeFormListener implements EventSubscriberInterface { /** * @var string */ protected $type; /** * @var array */ protected $options; /** * Whether children could be added to the group * @var Boolean */ protected $allowAdd; /** * Whether children could be removed from the group * @var Boolean */ protected $allowDelete; public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false) { $this->type = $type; $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; $this->options = $options; } public static function getSubscribedEvents() { return array( FormEvents::PRE_SET_DATA => 'preSetData', FormEvents::PRE_SUBMIT => 'preSubmit', // (MergeCollectionListener, MergeDoctrineCollectionListener) FormEvents::SUBMIT => array('onSubmit', 50), ); } public function preSetData(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // First remove all rows foreach ($form as $name => $child) { $form->remove($name); } // Then add all rows again in the correct order foreach ($data as $name => $value) { $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } } public function preSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data || '' === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // Remove all empty rows if ($this->allowDelete) { foreach ($form as $name => $child) { if (!isset($data[$name])) { $form->remove($name); } } } // Add all additional rows if ($this->allowAdd) { foreach ($data as $name => $value) { if (!$form->has($name)) { $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } } } } public function onSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // The data mapper only adds, but does not remove items, so do this // here if ($this->allowDelete) { $toDelete = array(); foreach ($data as $name => $child) { if (!$form->has($name)) { $toDelete[] = $name; } } foreach ($toDelete as $name) { unset($data[$name]); } } $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } /** * Alias of {@link onSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link onSubmit()} instead. */ public function onBind(FormEvent $event) { $this->onSubmit($event); } } PK!?DMSymfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * Takes care of converting the input from a single radio button * to an array. * * @author Bernhard Schussek */ class FixRadioInputListener implements EventSubscriberInterface { private $choiceList; private $placeholderPresent; /** * Constructor. * * @param ChoiceListInterface $choiceList * @param Boolean $placeholderPresent */ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { $this->choiceList = $choiceList; $this->placeholderPresent = $placeholderPresent; } public function preSubmit(FormEvent $event) { $data = $event->getData(); // Since expanded choice fields are completely loaded anyway, we // can just as well get the values again without losing performance. $existingValues = $this->choiceList->getValues(); if (false !== ($index = array_search($data, $existingValues, true))) { $data = array($index => $data); } elseif ('' === $data || null === $data) { // Empty values are always accepted. $data = $this->placeholderPresent ? array('placeholder' => '') : array(); } // Else leave the data unchanged to provoke an error during submission $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } PK!jюESymfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; /** * A choice list for choices of type string or integer. * * Choices and their associated labels can be passed in a single array. Since * choices are passed as array keys, only strings or integer choices are * allowed. Choices may also be given as hierarchy of unlimited depth by * creating nested arrays. The title of the sub-hierarchy can be stored in the * array key pointing to the nested array. * * * $choiceList = new SimpleChoiceList(array( * 'creditcard' => 'Credit card payment', * 'cash' => 'Cash payment', * )); * * * @author Bernhard Schussek */ class SimpleChoiceList extends ChoiceList { /** * Creates a new simple choice list. * * @param array $choices The array of choices with the choices as keys and * the labels as values. Choices may also be given * as hierarchy of unlimited depth by creating nested * arrays. The title of the sub-hierarchy is stored * in the array key pointing to the nested array. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. */ public function __construct(array $choices, array $preferredChoices = array()) { // Flip preferred choices to speed up lookup parent::__construct($choices, $choices, array_flip($preferredChoices)); } /** * {@inheritdoc} */ public function getChoicesForValues(array $values) { $values = $this->fixValues($values); // The values are identical to the choices, so we can just return them // to improve performance a little bit return $this->fixChoices(array_intersect($values, $this->getValues())); } /** * {@inheritdoc} */ public function getValuesForChoices(array $choices) { $choices = $this->fixChoices($choices); // The choices are identical to the values, so we can just return them // to improve performance a little bit return $this->fixValues(array_intersect($choices, $this->getValues())); } /** * Recursively adds the given choices to the list. * * Takes care of splitting the single $choices array passed in the * constructor into choices and labels. * * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param array|\Traversable $choices The list of choices. * @param array $labels Ignored. * @param array $preferredChoices The preferred choices. */ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices) { // Add choices to the nested buckets foreach ($choices as $choice => $label) { if (is_array($label)) { // Don't do the work if the array is empty if (count($label) > 0) { $this->addChoiceGroup( $choice, $bucketForPreferred, $bucketForRemaining, $label, $label, $preferredChoices ); } } else { $this->addChoice( $bucketForPreferred, $bucketForRemaining, $choice, $label, $preferredChoices ); } } } /** * Returns whether the given choice should be preferred judging by the * given array of preferred choices. * * Optimized for performance by treating the preferred choices as array * where choices are stored in the keys. * * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * * @return Boolean Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { // Optimize performance over the default implementation return isset($preferredChoices[$choice]); } /** * Converts the choice to a valid PHP array key. * * @param mixed $choice The choice * * @return string|integer A valid PHP array key */ protected function fixChoice($choice) { return $this->fixIndex($choice); } /** * {@inheritdoc} */ protected function fixChoices(array $choices) { return $this->fixIndices($choices); } /** * {@inheritdoc} */ protected function createValue($choice) { // Choices are guaranteed to be unique and scalar, so we can simply // convert them to strings return (string) $choice; } } PK! ##ESymfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\Exception\StringCastException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; /** * A choice list for object choices. * * Supports generation of choice labels, choice groups and choice values * by calling getters of the object (or associated objects). * * * $choices = array($user1, $user2); * * // call getName() to determine the choice labels * $choiceList = new ObjectChoiceList($choices, 'name'); * * * @author Bernhard Schussek */ class ObjectChoiceList extends ChoiceList { /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * The property path used to obtain the choice label. * * @var PropertyPath */ private $labelPath; /** * The property path used for object grouping. * * @var PropertyPath */ private $groupPath; /** * The property path used to obtain the choice value. * * @var PropertyPath */ private $valuePath; /** * Creates a new object choice list. * * @param array|\Traversable $choices The array of choices. Choices may also be given * as hierarchy of unlimited depth by creating nested * arrays. The title of the sub-hierarchy can be * stored in the array key pointing to the nested * array. The topmost level of the hierarchy may also * be a \Traversable. * @param string $labelPath A property path pointing to the property used * for the choice labels. The value is obtained * by calling the getter on the object. If the * path is NULL, the object's __toString() method * is used instead. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. * @param string $groupPath A property path pointing to the property used * to group the choices. Only allowed if * the choices are given as flat array. * @param string $valuePath A property path pointing to the property used * for the choice values. If not given, integers * are generated instead. * @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths. */ public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); $this->labelPath = null !== $labelPath ? new PropertyPath($labelPath) : null; $this->groupPath = null !== $groupPath ? new PropertyPath($groupPath) : null; $this->valuePath = null !== $valuePath ? new PropertyPath($valuePath) : null; parent::__construct($choices, array(), $preferredChoices); } /** * Initializes the list with choices. * * Safe to be called multiple times. The list is cleared on every call. * * @param array|\Traversable $choices The choices to write into the list. * @param array $labels Ignored. * @param array $preferredChoices The choices to display with priority. * * @throws InvalidArgumentException When passing a hierarchy of choices and using * the "groupPath" option at the same time. */ protected function initialize($choices, array $labels, array $preferredChoices) { if (null !== $this->groupPath) { $groupedChoices = array(); foreach ($choices as $i => $choice) { if (is_array($choice)) { throw new InvalidArgumentException('You should pass a plain object array (without groups) when using the "groupPath" option.'); } try { $group = $this->propertyAccessor->getValue($choice, $this->groupPath); } catch (NoSuchPropertyException $e) { // Don't group items whose group property does not exist // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf $group = null; } if (null === $group) { $groupedChoices[$i] = $choice; } else { $groupName = (string) $group; if (!isset($groupedChoices[$groupName])) { $groupedChoices[$groupName] = array(); } $groupedChoices[$groupName][$i] = $choice; } } $choices = $groupedChoices; } $labels = array(); $this->extractLabels($choices, $labels); parent::initialize($choices, $labels, $preferredChoices); } /** * Creates a new unique value for this choice. * * If a property path for the value was given at object creation, * the getter behind that path is now called to obtain a new value. * Otherwise a new integer is generated. * * @param mixed $choice The choice to create a value for * * @return integer|string A unique value without character limitations. */ protected function createValue($choice) { if ($this->valuePath) { return (string) $this->propertyAccessor->getValue($choice, $this->valuePath); } return parent::createValue($choice); } private function extractLabels($choices, array &$labels) { foreach ($choices as $i => $choice) { if (is_array($choice)) { $labels[$i] = array(); $this->extractLabels($choice, $labels[$i]); } elseif ($this->labelPath) { $labels[$i] = $this->propertyAccessor->getValue($choice, $this->labelPath); } elseif (method_exists($choice, '__toString')) { $labels[$i] = (string) $choice; } else { throw new StringCastException(sprintf('A "__toString()" method was not found on the objects of type "%s" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.', get_class($choice))); } } } } PK!l_R(HSymfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; /** * Contains choices that can be selected in a form field. * * Each choice has three different properties: * * - Choice: The choice that should be returned to the application by the * choice field. Can be any scalar value or an object, but no * array. * - Label: A text representing the choice that is displayed to the user. * - Value: A uniquely identifying value that can contain arbitrary * characters, but no arrays or objects. This value is displayed * in the HTML "value" attribute. * * @author Bernhard Schussek */ interface ChoiceListInterface { /** * Returns the list of choices * * @return array The choices with their indices as keys */ public function getChoices(); /** * Returns the values for the choices * * @return array The values with the corresponding choice indices as keys */ public function getValues(); /** * Returns the choice views of the preferred choices as nested array with * the choice groups as top-level keys. * * Example: * * * array( * 'Group 1' => array( * 10 => ChoiceView object, * 20 => ChoiceView object, * ), * 'Group 2' => array( * 30 => ChoiceView object, * ), * ) * * * @return array A nested array containing the views with the corresponding * choice indices as keys on the lowest levels and the choice * group names in the keys of the higher levels */ public function getPreferredViews(); /** * Returns the choice views of the choices that are not preferred as nested * array with the choice groups as top-level keys. * * Example: * * * array( * 'Group 1' => array( * 10 => ChoiceView object, * 20 => ChoiceView object, * ), * 'Group 2' => array( * 30 => ChoiceView object, * ), * ) * * * @return array A nested array containing the views with the corresponding * choice indices as keys on the lowest levels and the choice * group names in the keys of the higher levels * * @see getPreferredValues */ public function getRemainingViews(); /** * Returns the choices corresponding to the given values. * * The choices can have any data type. * * The choices must be returned with the same keys and in the same order * as the corresponding values in the given array. * * @param array $values An array of choice values. Not existing values in * this array are ignored * * @return array An array of choices with ascending, 0-based numeric keys */ public function getChoicesForValues(array $values); /** * Returns the values corresponding to the given choices. * * The values must be strings. * * The values must be returned with the same keys and in the same order * as the corresponding choices in the given array. * * @param array $choices An array of choices. Not existing choices in this * array are ignored * * @return array An array of choice values with ascending, 0-based numeric * keys */ public function getValuesForChoices(array $choices); /** * Returns the indices corresponding to the given choices. * * The indices must be positive integers or strings accepted by * {@link FormConfigBuilder::validateName()}. * * The index "placeholder" is internally reserved. * * The indices must be returned with the same keys and in the same order * as the corresponding choices in the given array. * * @param array $choices An array of choices. Not existing choices in this * array are ignored * * @return array An array of indices with ascending, 0-based numeric keys * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices); /** * Returns the indices corresponding to the given values. * * The indices must be positive integers or strings accepted by * {@link FormConfigBuilder::validateName()}. * * The index "placeholder" is internally reserved. * * The indices must be returned with the same keys and in the same order * as the corresponding values in the given array. * * @param array $values An array of choice values. Not existing values in * this array are ignored * * @return array An array of indices with ascending, 0-based numeric keys * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values); } PK!В4 4 CSymfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * A choice list that is loaded lazily * * This list loads itself as soon as any of the getters is accessed for the * first time. You should implement loadChoiceList() in your child classes, * which should return a ChoiceListInterface instance. * * @author Bernhard Schussek */ abstract class LazyChoiceList implements ChoiceListInterface { /** * The loaded choice list * * @var ChoiceListInterface */ private $choiceList; /** * {@inheritdoc} */ public function getChoices() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getChoices(); } /** * {@inheritdoc} */ public function getValues() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getValues(); } /** * {@inheritdoc} */ public function getPreferredViews() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getPreferredViews(); } /** * {@inheritdoc} */ public function getRemainingViews() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getRemainingViews(); } /** * {@inheritdoc} */ public function getChoicesForValues(array $values) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getChoicesForValues($values); } /** * {@inheritdoc} */ public function getValuesForChoices(array $choices) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getValuesForChoices($choices); } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getIndicesForChoices($choices); } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getIndicesForValues($values); } /** * Loads the choice list * * Should be implemented by child classes. * * @return ChoiceListInterface The loaded choice list */ abstract protected function loadChoiceList(); private function load() { $choiceList = $this->loadChoiceList(); if (!$choiceList instanceof ChoiceListInterface) { throw new InvalidArgumentException(sprintf('loadChoiceList() should return a ChoiceListInterface instance. Got %s', gettype($choiceList))); } $this->choiceList = $choiceList; } } PK!'ç???Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Extension\Core\View\ChoiceView; /** * A choice list for choices of arbitrary data types. * * Choices and labels are passed in two arrays. The indices of the choices * and the labels should match. Choices may also be given as hierarchy of * unlimited depth by creating nested arrays. The title of the sub-hierarchy * can be stored in the array key pointing to the nested array. The topmost * level of the hierarchy may also be a \Traversable. * * * $choices = array(true, false); * $labels = array('Agree', 'Disagree'); * $choiceList = new ChoiceList($choices, $labels); * * * @author Bernhard Schussek */ class ChoiceList implements ChoiceListInterface { /** * The choices with their indices as keys. * * @var array */ private $choices = array(); /** * The choice values with the indices of the matching choices as keys. * * @var array */ private $values = array(); /** * The preferred view objects as hierarchy containing also the choice groups * with the indices of the matching choices as bottom-level keys. * * @var array */ private $preferredViews = array(); /** * The non-preferred view objects as hierarchy containing also the choice * groups with the indices of the matching choices as bottom-level keys. * * @var array */ private $remainingViews = array(); /** * Creates a new choice list. * * @param array|\Traversable $choices The array of choices. Choices may also be given * as hierarchy of unlimited depth. Hierarchies are * created by creating nested arrays. The title of * the sub-hierarchy can be stored in the array * key pointing to the nested array. The topmost * level of the hierarchy may also be a \Traversable. * @param array $labels The array of labels. The structure of this array * should match the structure of $choices. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. * * @throws UnexpectedTypeException If the choices are not an array or \Traversable. */ public function __construct($choices, array $labels, array $preferredChoices = array()) { if (!is_array($choices) && !$choices instanceof \Traversable) { throw new UnexpectedTypeException($choices, 'array or \Traversable'); } $this->initialize($choices, $labels, $preferredChoices); } /** * Initializes the list with choices. * * Safe to be called multiple times. The list is cleared on every call. * * @param array|\Traversable $choices The choices to write into the list. * @param array $labels The labels belonging to the choices. * @param array $preferredChoices The choices to display with priority. */ protected function initialize($choices, array $labels, array $preferredChoices) { $this->choices = array(); $this->values = array(); $this->preferredViews = array(); $this->remainingViews = array(); $this->addChoices( $this->preferredViews, $this->remainingViews, $choices, $labels, $preferredChoices ); } /** * {@inheritdoc} */ public function getChoices() { return $this->choices; } /** * {@inheritdoc} */ public function getValues() { return $this->values; } /** * {@inheritdoc} */ public function getPreferredViews() { return $this->preferredViews; } /** * {@inheritdoc} */ public function getRemainingViews() { return $this->remainingViews; } /** * {@inheritdoc} */ public function getChoicesForValues(array $values) { $values = $this->fixValues($values); $choices = array(); foreach ($values as $i => $givenValue) { foreach ($this->values as $j => $value) { if ($value === $givenValue) { $choices[$i] = $this->choices[$j]; unset($values[$i]); if (0 === count($values)) { break 2; } } } } return $choices; } /** * {@inheritdoc} */ public function getValuesForChoices(array $choices) { $choices = $this->fixChoices($choices); $values = array(); foreach ($choices as $i => $givenChoice) { foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { $values[$i] = $this->values[$j]; unset($choices[$i]); if (0 === count($choices)) { break 2; } } } } return $values; } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices) { $choices = $this->fixChoices($choices); $indices = array(); foreach ($choices as $i => $givenChoice) { foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { $indices[$i] = $j; unset($choices[$i]); if (0 === count($choices)) { break 2; } } } } return $indices; } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { $values = $this->fixValues($values); $indices = array(); foreach ($values as $i => $givenValue) { foreach ($this->values as $j => $value) { if ($value === $givenValue) { $indices[$i] = $j; unset($values[$i]); if (0 === count($values)) { break 2; } } } } return $indices; } /** * Recursively adds the given choices to the list. * * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param array|\Traversable $choices The list of choices. * @param array $labels The labels corresponding to the choices. * @param array $preferredChoices The preferred choices. * * @throws InvalidArgumentException If the structures of the choices and labels array do not match. * @throws InvalidConfigurationException If no valid value or index could be created for a choice. */ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices) { // Add choices to the nested buckets foreach ($choices as $group => $choice) { if (!array_key_exists($group, $labels)) { throw new InvalidArgumentException('The structures of the choices and labels array do not match.'); } if (is_array($choice)) { // Don't do the work if the array is empty if (count($choice) > 0) { $this->addChoiceGroup( $group, $bucketForPreferred, $bucketForRemaining, $choice, $labels[$group], $preferredChoices ); } } else { $this->addChoice( $bucketForPreferred, $bucketForRemaining, $choice, $labels[$group], $preferredChoices ); } } } /** * Recursively adds a choice group. * * @param string $group The name of the group. * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param array $choices The list of choices in the group. * @param array $labels The labels corresponding to the choices in the group. * @param array $preferredChoices The preferred choices. * * @throws InvalidConfigurationException If no valid value or index could be created for a choice. */ protected function addChoiceGroup($group, array &$bucketForPreferred, array &$bucketForRemaining, array $choices, array $labels, array $preferredChoices) { // If this is a choice group, create a new level in the choice // key hierarchy $bucketForPreferred[$group] = array(); $bucketForRemaining[$group] = array(); $this->addChoices( $bucketForPreferred[$group], $bucketForRemaining[$group], $choices, $labels, $preferredChoices ); // Remove child levels if empty if (empty($bucketForPreferred[$group])) { unset($bucketForPreferred[$group]); } if (empty($bucketForRemaining[$group])) { unset($bucketForRemaining[$group]); } } /** * Adds a new choice. * * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param mixed $choice The choice to add. * @param string $label The label for the choice. * @param array $preferredChoices The preferred choices. * * @throws InvalidConfigurationException If no valid value or index could be created. */ protected function addChoice(array &$bucketForPreferred, array &$bucketForRemaining, $choice, $label, array $preferredChoices) { $index = $this->createIndex($choice); if ('' === $index || null === $index || !FormConfigBuilder::isValidName((string) $index)) { throw new InvalidConfigurationException(sprintf('The index "%s" created by the choice list is invalid. It should be a valid, non-empty Form name.', $index)); } $value = $this->createValue($choice); if (!is_string($value)) { throw new InvalidConfigurationException(sprintf('The value created by the choice list is of type "%s", but should be a string.', gettype($value))); } $view = new ChoiceView($choice, $value, $label); $this->choices[$index] = $this->fixChoice($choice); $this->values[$index] = $value; if ($this->isPreferred($choice, $preferredChoices)) { $bucketForPreferred[$index] = $view; } else { $bucketForRemaining[$index] = $view; } } /** * Returns whether the given choice should be preferred judging by the * given array of preferred choices. * * Extension point to optimize performance by changing the structure of the * $preferredChoices array. * * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * * @return Boolean Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { return false !== array_search($choice, $preferredChoices, true); } /** * Creates a new unique index for this choice. * * Extension point to change the indexing strategy. * * @param mixed $choice The choice to create an index for * * @return integer|string A unique index containing only ASCII letters, * digits and underscores. */ protected function createIndex($choice) { return count($this->choices); } /** * Creates a new unique value for this choice. * * By default, an integer is generated since it cannot be guaranteed that * all values in the list are convertible to (unique) strings. Subclasses * can override this behaviour if they can guarantee this property. * * @param mixed $choice The choice to create a value for * * @return string A unique string. */ protected function createValue($choice) { return (string) count($this->values); } /** * Fixes the data type of the given choice value to avoid comparison * problems. * * @param mixed $value The choice value. * * @return string The value as string. */ protected function fixValue($value) { return (string) $value; } /** * Fixes the data types of the given choice values to avoid comparison * problems. * * @param array $values The choice values. * * @return array The values as strings. */ protected function fixValues(array $values) { foreach ($values as $i => $value) { $values[$i] = $this->fixValue($value); } return $values; } /** * Fixes the data type of the given choice index to avoid comparison * problems. * * @param mixed $index The choice index. * * @return integer|string The index as PHP array key. */ protected function fixIndex($index) { if (is_bool($index) || (string) (int) $index === (string) $index) { return (int) $index; } return (string) $index; } /** * Fixes the data types of the given choice indices to avoid comparison * problems. * * @param array $indices The choice indices. * * @return array The indices as strings. */ protected function fixIndices(array $indices) { foreach ($indices as $i => $index) { $indices[$i] = $this->fixIndex($index); } return $indices; } /** * Fixes the data type of the given choice to avoid comparison problems. * * Extension point. In this implementation, choices are guaranteed to * always maintain their type and thus can be typesafely compared. * * @param mixed $choice The choice * * @return mixed The fixed choice */ protected function fixChoice($choice) { return $choice; } /** * Fixes the data type of the given choices to avoid comparison problems. * * @param array $choices The choices. * * @return array The fixed choices. * * @see fixChoice */ protected function fixChoices(array $choices) { return $choices; } } PK!&PP9Symfony/Component/Form/Extension/Core/View/ChoiceView.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\View; /** * Represents a choice in templates. * * @author Bernhard Schussek */ class ChoiceView { /** * The original choice value. * * @var mixed */ public $data; /** * The view representation of the choice. * * @var string */ public $value; /** * The label displayed to humans. * * @var string */ public $label; /** * Creates a new ChoiceView. * * @param mixed $data The original choice. * @param string $value The view representation of the choice. * @param string $label The label displayed to humans. */ public function __construct($data, $value, $label) { $this->data = $data; $this->value = $value; $this->label = $label; } } PK!  GSymfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataMapper; use Symfony\Component\Form\DataMapperInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; /** * A data mapper using property paths to read/write data. * * @author Bernhard Schussek */ class PropertyPathMapper implements DataMapperInterface { /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * Creates a new property path mapper. * * @param PropertyAccessorInterface $propertyAccessor */ public function __construct(PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** * {@inheritdoc} */ public function mapDataToForms($data, $forms) { $empty = null === $data || array() === $data; if (!$empty && !is_array($data) && !is_object($data)) { throw new UnexpectedTypeException($data, 'object, array or empty'); } foreach ($forms as $form) { $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); if (!$empty && null !== $propertyPath && $config->getMapped()) { $form->setData($this->propertyAccessor->getValue($data, $propertyPath)); } else { $form->setData($form->getConfig()->getData()); } } } /** * {@inheritdoc} */ public function mapFormsToData($forms, &$data) { if (null === $data) { return; } if (!is_array($data) && !is_object($data)) { throw new UnexpectedTypeException($data, 'object, array or empty'); } foreach ($forms as $form) { $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); // Write-back is disabled if the form is not synchronized (transformation failed), // if the form was not submitted and if the form is disabled (modification not allowed) if (null !== $propertyPath && $config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled()) { // If the field is of type DateTime and the data is the same skip the update to // keep the original object hash if ($form->getData() instanceof \DateTime && $form->getData() == $this->propertyAccessor->getValue($data, $propertyPath)) { continue; } // If the data is identical to the value in $data, we are // dealing with a reference if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) { $this->propertyAccessor->setValue($data, $propertyPath, $form->getData()); } } } } } PK!O###\Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a number type and a localized number with grouping * (each thousand) and comma separators. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class NumberToLocalizedStringTransformer implements DataTransformerInterface { /** * Rounds a number towards positive infinity. * * Rounds 1.4 to 2 and -1.4 to -1. */ const ROUND_CEILING = \NumberFormatter::ROUND_CEILING; /** * Rounds a number towards negative infinity. * * Rounds 1.4 to 1 and -1.4 to -2. */ const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR; /** * Rounds a number away from zero. * * Rounds 1.4 to 2 and -1.4 to -2. */ const ROUND_UP = \NumberFormatter::ROUND_UP; /** * Rounds a number towards zero. * * Rounds 1.4 to 1 and -1.4 to -1. */ const ROUND_DOWN = \NumberFormatter::ROUND_DOWN; /** * Rounds to the nearest number and halves to the next even number. * * Rounds 2.5, 1.6 and 1.5 to 2 and 1.4 to 1. */ const ROUND_HALF_EVEN = \NumberFormatter::ROUND_HALFEVEN; /** * Rounds to the nearest number and halves away from zero. * * Rounds 2.5 to 3, 1.6 and 1.5 to 2 and 1.4 to 1. */ const ROUND_HALF_UP = \NumberFormatter::ROUND_HALFUP; /** * Rounds to the nearest number and halves towards zero. * * Rounds 2.5 and 1.6 to 2, 1.5 and 1.4 to 1. */ const ROUND_HALF_DOWN = \NumberFormatter::ROUND_HALFDOWN; /** * Alias for {@link self::ROUND_HALF_EVEN}. * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. */ const ROUND_HALFEVEN = self::ROUND_HALF_EVEN; /** * Alias for {@link self::ROUND_HALF_UP}. * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. */ const ROUND_HALFUP = self::ROUND_HALF_UP; /** * Alias for {@link self::ROUND_HALF_DOWN}. * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. */ const ROUND_HALFDOWN = self::ROUND_HALF_DOWN; protected $precision; protected $grouping; protected $roundingMode; public function __construct($precision = null, $grouping = false, $roundingMode = self::ROUND_HALF_UP) { if (null === $grouping) { $grouping = false; } if (null === $roundingMode) { $roundingMode = self::ROUND_HALF_UP; } $this->precision = $precision; $this->grouping = $grouping; $this->roundingMode = $roundingMode; } /** * Transforms a number type into localized number. * * @param integer|float $value Number value. * * @return string Localized value. * * @throws TransformationFailedException If the given value is not numeric * or if the value can not be transformed. */ public function transform($value) { if (null === $value) { return ''; } if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } $formatter = $this->getNumberFormatter(); $value = $formatter->format($value); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } // Convert fixed spaces to normal ones $value = str_replace("\xc2\xa0", ' ', $value); return $value; } /** * Transforms a localized number into an integer or float * * @param string $value The localized value * * @return integer|float The numeric value * * @throws TransformationFailedException If the given value is not a string * or if the value can not be transformed. */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return null; } if ('NaN' === $value) { throw new TransformationFailedException('"NaN" is not a valid number'); } $position = 0; $formatter = $this->getNumberFormatter(); $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); if ('.' !== $decSep && (!$this->grouping || '.' !== $groupSep)) { $value = str_replace('.', $decSep, $value); } if (',' !== $decSep && (!$this->grouping || ',' !== $groupSep)) { $value = str_replace(',', $decSep, $value); } $result = $formatter->parse($value, \NumberFormatter::TYPE_DOUBLE, $position); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } if ($result >= PHP_INT_MAX || $result <= -PHP_INT_MAX) { throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like'); } if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) { $strlen = function ($string) use ($encoding) { return mb_strlen($string, $encoding); }; $substr = function ($string, $offset, $length) use ($encoding) { return mb_substr($string, $offset, $length, $encoding); }; } else { $strlen = 'strlen'; $substr = 'substr'; } $length = $strlen($value); // After parsing, position holds the index of the character where the // parsing stopped if ($position < $length) { // Check if there are unrecognized characters at the end of the // number (excluding whitespace characters) $remainder = trim($substr($value, $position, $length), " \t\n\r\0\x0b\xc2\xa0"); if ('' !== $remainder) { throw new TransformationFailedException( sprintf('The number contains unrecognized characters: "%s"', $remainder) ); } } // NumberFormatter::parse() does not round return $this->round($result); } /** * Returns a preconfigured \NumberFormatter instance * * @return \NumberFormatter */ protected function getNumberFormatter() { $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL); if (null !== $this->precision) { $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision); $formatter->setAttribute(\NumberFormatter::ROUNDING_MODE, $this->roundingMode); } $formatter->setAttribute(\NumberFormatter::GROUPING_USED, $this->grouping); return $formatter; } /** * Rounds a number according to the configured precision and rounding mode. * * @param integer|float $number A number. * * @return integer|float The rounded number. */ private function round($number) { if (null !== $this->precision && null !== $this->roundingMode) { // shift number to maintain the correct precision during rounding $roundingCoef = pow(10, $this->precision); $number *= $roundingCoef; switch ($this->roundingMode) { case self::ROUND_CEILING: $number = ceil($number); break; case self::ROUND_FLOOR: $number = floor($number); break; case self::ROUND_UP: $number = $number > 0 ? ceil($number) : floor($number); break; case self::ROUND_DOWN: $number = $number > 0 ? floor($number) : ceil($number); break; case self::ROUND_HALF_EVEN: $number = round($number, 0, PHP_ROUND_HALF_EVEN); break; case self::ROUND_HALF_UP: $number = round($number, 0, PHP_ROUND_HALF_UP); break; case self::ROUND_HALF_DOWN: $number = round($number, 0, PHP_ROUND_HALF_DOWN); break; } $number /= $roundingCoef; } return $number; } } PK!)b""^Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a normalized time and a localized time string * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer { private $dateFormat; private $timeFormat; private $pattern; private $calendar; /** * Constructor. * * @see BaseDateTimeTransformer::formats for available format options * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * @param integer $dateFormat The date format * @param integer $timeFormat The time format * @param integer $calendar One of the \IntlDateFormatter calendar constants * @param string $pattern A pattern to pass to \IntlDateFormatter * * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, $dateFormat = null, $timeFormat = null, $calendar = \IntlDateFormatter::GREGORIAN, $pattern = null) { parent::__construct($inputTimezone, $outputTimezone); if (null === $dateFormat) { $dateFormat = \IntlDateFormatter::MEDIUM; } if (null === $timeFormat) { $timeFormat = \IntlDateFormatter::SHORT; } if (!in_array($dateFormat, self::$formats, true)) { throw new UnexpectedTypeException($dateFormat, implode('", "', self::$formats)); } if (!in_array($timeFormat, self::$formats, true)) { throw new UnexpectedTypeException($timeFormat, implode('", "', self::$formats)); } $this->dateFormat = $dateFormat; $this->timeFormat = $timeFormat; $this->calendar = $calendar; $this->pattern = $pattern; } /** * Transforms a normalized date into a localized date string/array. * * @param \DateTime $dateTime Normalized date. * * @return string|array Localized date string/array. * * @throws TransformationFailedException If the given value is not an instance * of \DateTime or if the date could not * be transformed. */ public function transform($dateTime) { if (null === $dateTime) { return ''; } if (!$dateTime instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } // convert time to UTC before passing it to the formatter $dateTime = clone $dateTime; if ('UTC' !== $this->inputTimezone) { $dateTime->setTimezone(new \DateTimeZone('UTC')); } $value = $this->getIntlDateFormatter()->format((int) $dateTime->format('U')); if (intl_get_error_code() != 0) { throw new TransformationFailedException(intl_get_error_message()); } return $value; } /** * Transforms a localized date string/array into a normalized date. * * @param string|array $value Localized date string/array * * @return \DateTime Normalized date * * @throws TransformationFailedException if the given value is not a string, * if the date could not be parsed or * if the input timezone is not supported */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return null; } $timestamp = $this->getIntlDateFormatter()->parse($value); if (intl_get_error_code() != 0) { throw new TransformationFailedException(intl_get_error_message()); } try { // read timestamp into DateTime object - the formatter delivers in UTC $dateTime = new \DateTime(sprintf('@%s UTC', $timestamp)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } if ('UTC' !== $this->inputTimezone) { try { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } } return $dateTime; } /** * Returns a preconfigured IntlDateFormatter instance * * @return \IntlDateFormatter */ protected function getIntlDateFormatter() { $dateFormat = $this->dateFormat; $timeFormat = $this->timeFormat; $timezone = $this->outputTimezone; $calendar = $this->calendar; $pattern = $this->pattern; $intlDateFormatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormat, $timeFormat, $timezone, $calendar, $pattern); $intlDateFormatter->setLenient(false); return $intlDateFormatter; } } PK!e^  VSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer { /** * {@inheritDoc} */ public function transform($dateTime) { if (null === $dateTime) { return ''; } if (!$dateTime instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } if ($this->inputTimezone !== $this->outputTimezone) { $dateTime = clone $dateTime; $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } return preg_replace('/\+00:00$/', 'Z', $dateTime->format('c')); } /** * {@inheritDoc} */ public function reverseTransform($rfc3339) { if (!is_string($rfc3339)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $rfc3339) { return null; } try { $dateTime = new \DateTime($rfc3339); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } if ($this->outputTimezone !== $dateTime->getTimezone()->getName()) { try { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } } if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $rfc3339, $matches)) { if (!checkdate($matches[2], $matches[3], $matches[1])) { throw new TransformationFailedException(sprintf( 'The date "%s-%s-%s" is not a valid date.', $matches[1], $matches[2], $matches[3] )); } } return $dateTime; } } PK!Þ XSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a timestamp and a DateTime object * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer { /** * Transforms a DateTime object into a timestamp in the configured timezone. * * @param \DateTime $value A \DateTime object * * @return integer A timestamp * * @throws TransformationFailedException If the given value is not an instance * of \DateTime or if the output * timezone is not supported. */ public function transform($value) { if (null === $value) { return null; } if (!$value instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } $value = clone $value; try { $value->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return (int) $value->format('U'); } /** * Transforms a timestamp in the configured timezone into a DateTime object * * @param string $value A timestamp * * @return \DateTime A \DateTime object * * @throws TransformationFailedException If the given value is not a timestamp * or if the given timestamp is invalid. */ public function reverseTransform($value) { if (null === $value) { return null; } if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } try { $dateTime = new \DateTime(); $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); $dateTime->setTimestamp($value); if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $dateTime; } } PK!c8V NSymfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Passes a value through multiple value transformers * * @author Bernhard Schussek */ class DataTransformerChain implements DataTransformerInterface { /** * The value transformers * @var DataTransformerInterface[] */ protected $transformers; /** * Uses the given value transformers to transform values * * @param array $transformers */ public function __construct(array $transformers) { $this->transformers = $transformers; } /** * Passes the value through the transform() method of all nested transformers * * The transformers receive the value in the same order as they were passed * to the constructor. Each transformer receives the result of the previous * transformer as input. The output of the last transformer is returned * by this method. * * @param mixed $value The original value * * @return mixed The transformed value * * @throws TransformationFailedException */ public function transform($value) { foreach ($this->transformers as $transformer) { $value = $transformer->transform($value); } return $value; } /** * Passes the value through the reverseTransform() method of all nested * transformers * * The transformers receive the value in the reverse order as they were passed * to the constructor. Each transformer receives the result of the previous * transformer as input. The output of the last transformer is returned * by this method. * * @param mixed $value The transformed value * * @return mixed The reverse-transformed value * * @throws TransformationFailedException */ public function reverseTransform($value) { for ($i = count($this->transformers) - 1; $i >= 0; --$i) { $value = $this->transformers[$i]->reverseTransform($value); } return $value; } } PK!;dd]Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a normalized format (integer or float) and a percentage value. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class PercentToLocalizedStringTransformer implements DataTransformerInterface { const FRACTIONAL = 'fractional'; const INTEGER = 'integer'; protected static $types = array( self::FRACTIONAL, self::INTEGER, ); private $type; private $precision; /** * Constructor. * * @see self::$types for a list of supported types * * @param integer $precision The precision * @param string $type One of the supported types * * @throws UnexpectedTypeException if the given value of type is unknown */ public function __construct($precision = null, $type = null) { if (null === $precision) { $precision = 0; } if (null === $type) { $type = self::FRACTIONAL; } if (!in_array($type, self::$types, true)) { throw new UnexpectedTypeException($type, implode('", "', self::$types)); } $this->type = $type; $this->precision = $precision; } /** * Transforms between a normalized format (integer or float) into a percentage value. * * @param number $value Normalized value * * @return number Percentage value * * @throws TransformationFailedException If the given value is not numeric or * if the value could not be transformed. */ public function transform($value) { if (null === $value) { return ''; } if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } if (self::FRACTIONAL == $this->type) { $value *= 100; } $formatter = $this->getNumberFormatter(); $value = $formatter->format($value); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } // replace the UTF-8 non break spaces return $value; } /** * Transforms between a percentage value into a normalized format (integer or float). * * @param number $value Percentage value. * * @return number Normalized value. * * @throws TransformationFailedException If the given value is not a string or * if the value could not be transformed. */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return null; } $formatter = $this->getNumberFormatter(); // replace normal spaces so that the formatter can read them $value = $formatter->parse(str_replace(' ', ' ', $value)); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } if (self::FRACTIONAL == $this->type) { $value /= 100; } return $value; } /** * Returns a preconfigured \NumberFormatter instance * * @return \NumberFormatter */ protected function getNumberFormatter() { $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL); $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision); return $formatter; } } PK!Ze  TSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a normalized time and a localized time string/array. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToArrayTransformer extends BaseDateTimeTransformer { private $pad; private $fields; /** * Constructor. * * @param string $inputTimezone The input timezone * @param string $outputTimezone The output timezone * @param array $fields The date fields * @param Boolean $pad Whether to use padding * * @throws UnexpectedTypeException if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, array $fields = null, $pad = false) { parent::__construct($inputTimezone, $outputTimezone); if (null === $fields) { $fields = array('year', 'month', 'day', 'hour', 'minute', 'second'); } $this->fields = $fields; $this->pad = (Boolean) $pad; } /** * Transforms a normalized date into a localized date. * * @param \DateTime $dateTime Normalized date. * * @return array Localized date. * * @throws TransformationFailedException If the given value is not an * instance of \DateTime or if the * output timezone is not supported. */ public function transform($dateTime) { if (null === $dateTime) { return array_intersect_key(array( 'year' => '', 'month' => '', 'day' => '', 'hour' => '', 'minute' => '', 'second' => '', ), array_flip($this->fields)); } if (!$dateTime instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } $dateTime = clone $dateTime; if ($this->inputTimezone !== $this->outputTimezone) { try { $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } } $result = array_intersect_key(array( 'year' => $dateTime->format('Y'), 'month' => $dateTime->format('m'), 'day' => $dateTime->format('d'), 'hour' => $dateTime->format('H'), 'minute' => $dateTime->format('i'), 'second' => $dateTime->format('s'), ), array_flip($this->fields)); if (!$this->pad) { foreach ($result as &$entry) { // remove leading zeros $entry = (string) (int) $entry; } } return $result; } /** * Transforms a localized date into a normalized date. * * @param array $value Localized date * * @return \DateTime Normalized date * * @throws TransformationFailedException If the given value is not an array, * if the value could not be transformed * or if the input timezone is not * supported. */ public function reverseTransform($value) { if (null === $value) { return null; } if (!is_array($value)) { throw new TransformationFailedException('Expected an array.'); } if ('' === implode('', $value)) { return null; } $emptyFields = array(); foreach ($this->fields as $field) { if (!isset($value[$field])) { $emptyFields[] = $field; } } if (count($emptyFields) > 0) { throw new TransformationFailedException( sprintf('The fields "%s" should not be empty', implode('", "', $emptyFields) )); } if (isset($value['month']) && !ctype_digit((string) $value['month'])) { throw new TransformationFailedException('This month is invalid'); } if (isset($value['day']) && !ctype_digit((string) $value['day'])) { throw new TransformationFailedException('This day is invalid'); } if (isset($value['year']) && !ctype_digit((string) $value['year'])) { throw new TransformationFailedException('This year is invalid'); } if (!empty($value['month']) && !empty($value['day']) && !empty($value['year']) && false === checkdate($value['month'], $value['day'], $value['year'])) { throw new TransformationFailedException('This is an invalid date'); } if (isset($value['hour']) && !ctype_digit((string) $value['hour'])) { throw new TransformationFailedException('This hour is invalid'); } if (isset($value['minute']) && !ctype_digit((string) $value['minute'])) { throw new TransformationFailedException('This minute is invalid'); } if (isset($value['second']) && !ctype_digit((string) $value['second'])) { throw new TransformationFailedException('This second is invalid'); } try { $dateTime = new \DateTime(sprintf( '%s-%s-%s %s:%s:%s %s', empty($value['year']) ? '1970' : $value['year'], empty($value['month']) ? '1' : $value['month'], empty($value['day']) ? '1' : $value['day'], empty($value['hour']) ? '0' : $value['hour'], empty($value['minute']) ? '0' : $value['minute'], empty($value['second']) ? '0' : $value['second'], $this->outputTimezone )); if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $dateTime; } } PK!Lpx&&YSymfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ChoiceToBooleanArrayTransformer implements DataTransformerInterface { private $choiceList; private $placeholderPresent; /** * Constructor. * * @param ChoiceListInterface $choiceList * @param Boolean $placeholderPresent */ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { $this->choiceList = $choiceList; $this->placeholderPresent = $placeholderPresent; } /** * Transforms a single choice to a format appropriate for the nested * checkboxes/radio buttons. * * The result is an array with the options as keys and true/false as values, * depending on whether a given option is selected. If this field is rendered * as select tag, the value is not modified. * * @param mixed $choice An array if "multiple" is set to true, a scalar * value otherwise. * * @return mixed An array * * @throws TransformationFailedException If the given value is not scalar or * if the choices can not be retrieved. */ public function transform($choice) { try { $values = $this->choiceList->getValues(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } $valueMap = array_flip($this->choiceList->getValuesForChoices(array($choice))); foreach ($values as $i => $value) { $values[$i] = isset($valueMap[$value]); } if ($this->placeholderPresent) { $values['placeholder'] = 0 === count($valueMap); } return $values; } /** * Transforms a checkbox/radio button array to a single choice. * * The input value is an array with the choices as keys and true/false as * values, depending on whether a given choice is selected. The output * is the selected choice. * * @param array $values An array of values * * @return mixed A scalar value * * @throws TransformationFailedException If the given value is not an array, * if the recuperation of the choices * fails or if some choice can't be * found. */ public function reverseTransform($values) { if (!is_array($values)) { throw new TransformationFailedException('Expected an array.'); } try { $choices = $this->choiceList->getChoices(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } foreach ($values as $i => $selected) { if ($selected) { if (isset($choices[$i])) { return $choices[$i] === '' ? null : $choices[$i]; } elseif ($this->placeholderPresent && 'placeholder' === $i) { return null; } else { throw new TransformationFailedException(sprintf('The choice "%s" does not exist', $i)); } } } return null; } } PK!  VSymfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ValueToDuplicatesTransformer implements DataTransformerInterface { private $keys; public function __construct(array $keys) { $this->keys = $keys; } /** * Duplicates the given value through the array. * * @param mixed $value The value * * @return array The array */ public function transform($value) { $result = array(); foreach ($this->keys as $key) { $result[$key] = $value; } return $result; } /** * Extracts the duplicated value from an array. * * @param array $array * * @return mixed The value * * @throws TransformationFailedException If the given value is not an array or * if the given array can not be transformed. */ public function reverseTransform($array) { if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } $result = current($array); $emptyKeys = array(); foreach ($this->keys as $key) { if (!empty($array[$key])) { if ($array[$key] !== $result) { throw new TransformationFailedException( 'All values in the array should be the same' ); } } else { $emptyKeys[] = $key; } } if (count($emptyKeys) > 0) { if (count($emptyKeys) == count($this->keys)) { // All keys empty return null; } throw new TransformationFailedException( sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys) )); } return $result; } } PK!'tqk55ZSymfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ChoicesToBooleanArrayTransformer implements DataTransformerInterface { private $choiceList; public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } /** * Transforms an array of choices to a format appropriate for the nested * checkboxes/radio buttons. * * The result is an array with the options as keys and true/false as values, * depending on whether a given option is selected. If this field is rendered * as select tag, the value is not modified. * * @param mixed $array An array * * @return mixed An array * * @throws TransformationFailedException If the given value is not an array * or if the choices can not be retrieved. */ public function transform($array) { if (null === $array) { return array(); } if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } try { $values = $this->choiceList->getValues(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } $valueMap = array_flip($this->choiceList->getValuesForChoices($array)); foreach ($values as $i => $value) { $values[$i] = isset($valueMap[$value]); } return $values; } /** * Transforms a checkbox/radio button array to an array of choices. * * The input value is an array with the choices as keys and true/false as * values, depending on whether a given choice is selected. The output * is an array with the selected choices. * * @param mixed $values An array * * @return mixed An array * * @throws TransformationFailedException If the given value is not an array, * if the recuperation of the choices * fails or if some choice can't be * found. */ public function reverseTransform($values) { if (!is_array($values)) { throw new TransformationFailedException('Expected an array.'); } try { $choices = $this->choiceList->getChoices(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } $result = array(); $unknown = array(); foreach ($values as $i => $selected) { if ($selected) { if (isset($choices[$i])) { $result[] = $choices[$i]; } else { $unknown[] = $i; } } } if (count($unknown) > 0) { throw new TransformationFailedException(sprintf('The choices "%s" were not found', implode('", "', $unknown))); } return $result; } } PK!ggTSymfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * @author Bernhard Schussek */ class ChoicesToValuesTransformer implements DataTransformerInterface { private $choiceList; /** * Constructor. * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } /** * @param array $array * * @return array * * @throws TransformationFailedException If the given value is not an array. */ public function transform($array) { if (null === $array) { return array(); } if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } return $this->choiceList->getValuesForChoices($array); } /** * @param array $array * * @return array * * @throws TransformationFailedException If the given value is not an array * or if no matching choice could be * found for some given value. */ public function reverseTransform($array) { if (null === $array) { return array(); } if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } $choices = $this->choiceList->getChoicesForValues($array); if (count($choices) !== count($array)) { throw new TransformationFailedException('Could not find all matching choices for the given values'); } return $choices; } } PK!Udq]Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; /** * Transforms between an integer and a localized number with grouping * (each thousand) and comma separators. * * @author Bernhard Schussek */ class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { /** * Constructs a transformer. * * @param integer $precision Unused. * @param Boolean $grouping Whether thousands should be grouped. * @param integer $roundingMode One of the ROUND_ constants in this class. */ public function __construct($precision = 0, $grouping = false, $roundingMode = self::ROUND_DOWN) { if (null === $roundingMode) { $roundingMode = self::ROUND_DOWN; } parent::__construct(0, $grouping, $roundingMode); } /** * {@inheritDoc} */ public function reverseTransform($value) { $result = parent::reverseTransform($value); return null !== $result ? (int) $result : null; } } PK!ΎgW USymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a date string and a DateTime object * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToStringTransformer extends BaseDateTimeTransformer { /** * Format used for generating strings * @var string */ private $generateFormat; /** * Format used for parsing strings * * Different than the {@link $generateFormat} because formats for parsing * support additional characters in PHP that are not supported for * generating strings. * * @var string */ private $parseFormat; /** * Whether to parse by appending a pipe "|" to the parse format. * * This only works as of PHP 5.3.7. * * @var Boolean */ private $parseUsingPipe; /** * Transforms a \DateTime instance to a string * * @see \DateTime::format() for supported formats * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * @param string $format The date format * @param Boolean $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format * * @throws UnexpectedTypeException if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = null) { parent::__construct($inputTimezone, $outputTimezone); $this->generateFormat = $this->parseFormat = $format; // The pipe in the parser pattern only works as of PHP 5.3.7 // See http://bugs.php.net/54316 $this->parseUsingPipe = null === $parseUsingPipe ? version_compare(phpversion(), '5.3.7', '>=') : $parseUsingPipe; // See http://php.net/manual/en/datetime.createfromformat.php // The character "|" in the format makes sure that the parts of a date // that are *not* specified in the format are reset to the corresponding // values from 1970-01-01 00:00:00 instead of the current time. // Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47", // where the time corresponds to the current server time. // With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00", // which is at least deterministic and thus used here. if ($this->parseUsingPipe && false === strpos($this->parseFormat, '|')) { $this->parseFormat .= '|'; } } /** * Transforms a DateTime object into a date string with the configured format * and timezone * * @param \DateTime $value A DateTime object * * @return string A value as produced by PHP's date() function * * @throws TransformationFailedException If the given value is not a \DateTime * instance or if the output timezone * is not supported. */ public function transform($value) { if (null === $value) { return ''; } if (!$value instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } $value = clone $value; try { $value->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $value->format($this->generateFormat); } /** * Transforms a date string in the configured timezone into a DateTime object. * * @param string $value A value as produced by PHP's date() function * * @return \DateTime An instance of \DateTime * * @throws TransformationFailedException If the given value is not a string, * if the date could not be parsed or * if the input timezone is not supported. */ public function reverseTransform($value) { if (empty($value)) { return null; } if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } try { $outputTz = new \DateTimeZone($this->outputTimezone); $dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz); $lastErrors = \DateTime::getLastErrors(); if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) { throw new TransformationFailedException( implode(', ', array_merge( array_values($lastErrors['warnings']), array_values($lastErrors['errors']) )) ); } // On PHP versions < 5.3.7 we need to emulate the pipe operator // and reset parts not given in the format to their equivalent // of the UNIX base timestamp. if (!$this->parseUsingPipe) { list($year, $month, $day, $hour, $minute, $second) = explode('-', $dateTime->format('Y-m-d-H-i-s')); // Check which of the date parts are present in the pattern preg_match( '/(' . '(?P[djDl])|' . '(?P[FMmn])|' . '(?P[Yy])|' . '(?P[ghGH])|' . '(?Pi)|' . '(?Ps)|' . '(?Pz)|' . '(?PU)|' . '[^djDlFMmnYyghGHiszU]' . ')*/', $this->parseFormat, $matches ); // preg_match() does not guarantee to set all indices, so // set them unless given $matches = array_merge(array( 'day' => false, 'month' => false, 'year' => false, 'hour' => false, 'minute' => false, 'second' => false, 'dayofyear' => false, 'timestamp' => false, ), $matches); // Reset all parts that don't exist in the format to the // corresponding part of the UNIX base timestamp if (!$matches['timestamp']) { if (!$matches['dayofyear']) { if (!$matches['day']) { $day = 1; } if (!$matches['month']) { $month = 1; } } if (!$matches['year']) { $year = 1970; } if (!$matches['hour']) { $hour = 0; } if (!$matches['minute']) { $minute = 0; } if (!$matches['second']) { $second = 0; } $dateTime->setDate($year, $month, $day); $dateTime->setTime($hour, $minute, $second); } } if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimeZone(new \DateTimeZone($this->inputTimezone)); } } catch (TransformationFailedException $e) { throw $e; } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $dateTime; } } PK!"hRSymfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * @author Bernhard Schussek */ class ChoiceToValueTransformer implements DataTransformerInterface { private $choiceList; /** * Constructor. * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } public function transform($choice) { return (string) current($this->choiceList->getValuesForChoices(array($choice))); } public function reverseTransform($value) { if (null !== $value && !is_scalar($value)) { throw new TransformationFailedException('Expected a scalar.'); } // These are now valid ChoiceList values, so we can return null // right away if ('' === $value || null === $value) { return null; } $choices = $this->choiceList->getChoicesForValues(array($value)); if (1 !== count($choices)) { throw new TransformationFailedException(sprintf('The choice "%s" does not exist or is not unique', $value)); } $choice = current($choices); return '' === $choice ? null : $choice; } } PK!H  QSymfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ArrayToPartsTransformer implements DataTransformerInterface { private $partMapping; public function __construct(array $partMapping) { $this->partMapping = $partMapping; } public function transform($array) { if (null === $array) { $array = array(); } if (!is_array($array) ) { throw new TransformationFailedException('Expected an array.'); } $result = array(); foreach ($this->partMapping as $partKey => $originalKeys) { if (empty($array)) { $result[$partKey] = null; } else { $result[$partKey] = array_intersect_key($array, array_flip($originalKeys)); } } return $result; } public function reverseTransform($array) { if (!is_array($array) ) { throw new TransformationFailedException('Expected an array.'); } $result = array(); $emptyKeys = array(); foreach ($this->partMapping as $partKey => $originalKeys) { if (!empty($array[$partKey])) { foreach ($originalKeys as $originalKey) { if (isset($array[$partKey][$originalKey])) { $result[$originalKey] = $array[$partKey][$originalKey]; } } } else { $emptyKeys[] = $partKey; } } if (count($emptyKeys) > 0) { if (count($emptyKeys) === count($this->partMapping)) { // All parts empty return null; } throw new TransformationFailedException( sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys) )); } return $result; } } PK!/CQSymfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; abstract class BaseDateTimeTransformer implements DataTransformerInterface { protected static $formats = array( \IntlDateFormatter::NONE, \IntlDateFormatter::FULL, \IntlDateFormatter::LONG, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, ); protected $inputTimezone; protected $outputTimezone; /** * Constructor. * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * * @throws UnexpectedTypeException if a timezone is not a string * @throws InvalidArgumentException if a timezone is not valid */ public function __construct($inputTimezone = null, $outputTimezone = null) { if (!is_string($inputTimezone) && null !== $inputTimezone) { throw new UnexpectedTypeException($inputTimezone, 'string'); } if (!is_string($outputTimezone) && null !== $outputTimezone) { throw new UnexpectedTypeException($outputTimezone, 'string'); } $this->inputTimezone = $inputTimezone ?: date_default_timezone_get(); $this->outputTimezone = $outputTimezone ?: date_default_timezone_get(); // Check if input and output timezones are valid try { new \DateTimeZone($this->inputTimezone); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Input timezone is invalid: %s.', $this->inputTimezone), $e->getCode(), $e); } try { new \DateTimeZone($this->outputTimezone); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Output timezone is invalid: %s.', $this->outputTimezone), $e->getCode(), $e); } } } PK!TTSymfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a Boolean and a string. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class BooleanToStringTransformer implements DataTransformerInterface { /** * The value emitted upon transform if the input is true * @var string */ private $trueValue; /** * Sets the value emitted upon transform if the input is true. * * @param string $trueValue */ public function __construct($trueValue) { $this->trueValue = $trueValue; } /** * Transforms a Boolean into a string. * * @param Boolean $value Boolean value. * * @return string String value. * * @throws TransformationFailedException If the given value is not a Boolean. */ public function transform($value) { if (null === $value) { return null; } if (!is_bool($value)) { throw new TransformationFailedException('Expected a Boolean.'); } return $value ? $this->trueValue : null; } /** * Transforms a string into a Boolean. * * @param string $value String value. * * @return Boolean Boolean value. * * @throws TransformationFailedException If the given value is not a string. */ public function reverseTransform($value) { if (null === $value) { return false; } if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } return true; } } PK!]yD D [Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a normalized format and a localized money string. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { private $divisor; public function __construct($precision = 2, $grouping = true, $roundingMode = self::ROUND_HALF_UP, $divisor = 1) { if (null === $grouping) { $grouping = true; } if (null === $precision) { $precision = 2; } parent::__construct($precision, $grouping, $roundingMode); if (null === $divisor) { $divisor = 1; } $this->divisor = $divisor; } /** * Transforms a normalized format into a localized money string. * * @param number $value Normalized number * * @return string Localized money string. * * @throws TransformationFailedException If the given value is not numeric or * if the value can not be transformed. */ public function transform($value) { if (null !== $value) { if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } $value /= $this->divisor; } return parent::transform($value); } /** * Transforms a localized money string into a normalized format. * * @param string $value Localized money string * * @return number Normalized number * * @throws TransformationFailedException If the given value is not a string * or if the value can not be transformed. */ public function reverseTransform($value) { $value = parent::reverseTransform($value); if (null !== $value) { $value *= $this->divisor; } return $value; } } PK!/++9Symfony/Component/Form/Extension/Core/Type/ChoiceType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; use Symfony\Component\Form\Extension\Core\EventListener\FixCheckboxInputListener; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToBooleanArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToBooleanArrayTransformer; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class ChoiceType extends AbstractType { /** * Caches created choice lists. * @var array */ private $choiceListCache = array(); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { if (!$options['choice_list'] && !is_array($options['choices']) && !$options['choices'] instanceof \Traversable) { throw new LogicException('Either the option "choices" or "choice_list" must be set.'); } if ($options['expanded']) { // Initialize all choices before doing the index check below. // This helps in cases where index checks are optimized for non // initialized choice lists. For example, when using an SQL driver, // the index check would read in one SQL query and the initialization // requires another SQL query. When the initialization is done first, // one SQL query is sufficient. $preferredViews = $options['choice_list']->getPreferredViews(); $remainingViews = $options['choice_list']->getRemainingViews(); // Check if the choices already contain the empty value // Only add the empty value option if this is not the case if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) { $placeholderView = new ChoiceView(null, '', $options['empty_value']); // "placeholder" is a reserved index // see also ChoiceListInterface::getIndicesForChoices() $this->addSubForms($builder, array('placeholder' => $placeholderView), $options); } $this->addSubForms($builder, $preferredViews, $options); $this->addSubForms($builder, $remainingViews, $options); if ($options['multiple']) { $builder->addViewTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list'])); $builder->addEventSubscriber(new FixCheckboxInputListener($options['choice_list']), 10); } else { $builder->addViewTransformer(new ChoiceToBooleanArrayTransformer($options['choice_list'], $builder->has('placeholder'))); $builder->addEventSubscriber(new FixRadioInputListener($options['choice_list'], $builder->has('placeholder')), 10); } } else { if ($options['multiple']) { $builder->addViewTransformer(new ChoicesToValuesTransformer($options['choice_list'])); } else { $builder->addViewTransformer(new ChoiceToValueTransformer($options['choice_list'])); } } if ($options['multiple'] && $options['by_reference']) { // Make sure the collection created during the client->norm // transformation is merged back into the original collection $builder->addEventSubscriber(new MergeCollectionListener(true, true)); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'multiple' => $options['multiple'], 'expanded' => $options['expanded'], 'preferred_choices' => $options['choice_list']->getPreferredViews(), 'choices' => $options['choice_list']->getRemainingViews(), 'separator' => '-------------------', 'empty_value' => null, )); // The decision, whether a choice is selected, is potentially done // thousand of times during the rendering of a template. Provide a // closure here that is optimized for the value of the form, to // avoid making the type check inside the closure. if ($options['multiple']) { $view->vars['is_selected'] = function ($choice, array $values) { return false !== array_search($choice, $values, true); }; } else { $view->vars['is_selected'] = function ($choice, $value) { return $choice === $value; }; } // Check if the choices already contain the empty value $view->vars['empty_value_in_choices'] = 0 !== count($options['choice_list']->getChoicesForValues(array(''))); // Only add the empty value option if this is not the case if (null !== $options['empty_value'] && !$view->vars['empty_value_in_choices']) { $view->vars['empty_value'] = $options['empty_value']; } if ($options['multiple'] && !$options['expanded']) { // Add "[]" to the name in case a select tag with multiple options is // displayed. Otherwise only one of the selected options is sent in the // POST request. $view->vars['full_name'] = $view->vars['full_name'].'[]'; } } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['expanded']) { // Radio buttons should have the same name as the parent $childName = $view->vars['full_name']; // Checkboxes should append "[]" to allow multiple selection if ($options['multiple']) { $childName .= '[]'; } foreach ($view as $childView) { $childView->vars['full_name'] = $childName; } } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $choiceListCache =& $this->choiceListCache; $choiceList = function (Options $options) use (&$choiceListCache) { // Harden against NULL values (like in EntityType and ModelType) $choices = null !== $options['choices'] ? $options['choices'] : array(); // Reuse existing choice lists in order to increase performance $hash = hash('sha256', json_encode(array($choices, $options['preferred_choices']))); if (!isset($choiceListCache[$hash])) { $choiceListCache[$hash] = new SimpleChoiceList($choices, $options['preferred_choices']); } return $choiceListCache[$hash]; }; $emptyData = function (Options $options) { if ($options['multiple'] || $options['expanded']) { return array(); } return ''; }; $emptyValue = function (Options $options) { return $options['required'] ? null : ''; }; $emptyValueNormalizer = function (Options $options, $emptyValue) { if ($options['multiple']) { // never use an empty value for this case return null; } elseif (false === $emptyValue) { // an empty value should be added but the user decided otherwise return null; } elseif ($options['expanded'] && '' === $emptyValue) { // never use an empty label for radio buttons return 'None'; } // empty value has been set explicitly return $emptyValue; }; $compound = function (Options $options) { return $options['expanded']; }; $resolver->setDefaults(array( 'multiple' => false, 'expanded' => false, 'choice_list' => $choiceList, 'choices' => array(), 'preferred_choices' => array(), 'empty_data' => $emptyData, 'empty_value' => $emptyValue, 'error_bubbling' => false, 'compound' => $compound, // The view data is always a string, even if the "data" option // is manually set to an object. // See https://github.com/symfony/symfony/pull/5582 'data_class' => null, )); $resolver->setNormalizers(array( 'empty_value' => $emptyValueNormalizer, )); $resolver->setAllowedTypes(array( 'choice_list' => array('null', 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface'), )); } /** * {@inheritdoc} */ public function getName() { return 'choice'; } /** * Adds the sub fields for an expanded choice field. * * @param FormBuilderInterface $builder The form builder. * @param array $choiceViews The choice view objects. * @param array $options The build options. */ private function addSubForms(FormBuilderInterface $builder, array $choiceViews, array $options) { foreach ($choiceViews as $i => $choiceView) { if (is_array($choiceView)) { // Flatten groups $this->addSubForms($builder, $choiceView, $options); } else { $choiceOpts = array( 'value' => $choiceView->value, 'label' => $choiceView->label, 'translation_domain' => $options['translation_domain'], ); if ($options['multiple']) { $choiceType = 'checkbox'; // The user can check 0 or more checkboxes. If required // is true, he is required to check all of them. $choiceOpts['required'] = false; } else { $choiceType = 'radio'; } $builder->add($i, $choiceType, $choiceOpts); } } } } PK!h9Symfony/Component/Form/Extension/Core/Type/ButtonType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\ButtonTypeInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * A form button. * * @author Bernhard Schussek */ class ButtonType extends BaseType implements ButtonTypeInterface { /** * {@inheritdoc} */ public function getParent() { return null; } /** * {@inheritdoc} */ public function getName() { return 'button'; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); $resolver->setDefaults(array( 'auto_initialize' => false, )); } } PK!DU9Symfony/Component/Form/Extension/Core/Type/SubmitType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\SubmitButtonTypeInterface; /** * A submit button. * * @author Bernhard Schussek */ class SubmitType extends AbstractType implements SubmitButtonTypeInterface { public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['clicked'] = $form->isClicked(); } /** * {@inheritdoc} */ public function getParent() { return 'button'; } /** * {@inheritdoc} */ public function getName() { return 'submit'; } } PK!񍢸;Symfony/Component/Form/Extension/Core/Type/CurrencyType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CurrencyType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getCurrencyBundle()->getCurrencyNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'currency'; } } PK!Ѝ'9Symfony/Component/Form/Extension/Core/Type/HiddenType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class HiddenType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // hidden fields cannot have a required attribute 'required' => false, // Pass errors to the parent 'error_bubbling' => true, 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'hidden'; } } PK!D9Symfony/Component/Form/Extension/Core/Type/LocaleType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class LocaleType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getLocaleBundle()->getLocaleNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'locale'; } } PK!uƵ``:Symfony/Component/Form/Extension/Core/Type/IntegerType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class IntegerType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer( new IntegerToLocalizedStringTransformer( $options['precision'], $options['grouping'], $options['rounding_mode'] )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // default precision is locale specific (usually around 3) 'precision' => null, 'grouping' => false, // Integer cast rounds towards 0, so do the same when displaying fractions 'rounding_mode' => IntegerToLocalizedStringTransformer::ROUND_DOWN, 'compound' => false, )); $resolver->setAllowedValues(array( 'rounding_mode' => array( IntegerToLocalizedStringTransformer::ROUND_FLOOR, IntegerToLocalizedStringTransformer::ROUND_DOWN, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN, IntegerToLocalizedStringTransformer::ROUND_HALF_UP, IntegerToLocalizedStringTransformer::ROUND_UP, IntegerToLocalizedStringTransformer::ROUND_CEILING, ), )); } /** * {@inheritdoc} */ public function getName() { return 'integer'; } } PK!a8Symfony/Component/Form/Extension/Core/Type/ResetType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\ButtonTypeInterface; /** * A reset button. * * @author Bernhard Schussek */ class ResetType extends AbstractType implements ButtonTypeInterface { /** * {@inheritdoc} */ public function getParent() { return 'button'; } /** * {@inheritdoc} */ public function getName() { return 'reset'; } } PK!옇;Symfony/Component/Form/Extension/Core/Type/PasswordType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class PasswordType extends AbstractType { /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { if ($options['always_empty'] || !$form->isSubmitted()) { $view->vars['value'] = ''; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'always_empty' => true, 'trim' => false, )); } /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'password'; } } PK!ٝGG7Symfony/Component/Form/Extension/Core/Type/BaseType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * Encapsulates common logic of {@link FormType} and {@link ButtonType}. * * This type does not appear in the form's type inheritance chain and as such * cannot be extended (via {@link FormTypeExtension}s) nor themed. * * @author Bernhard Schussek */ abstract class BaseType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setDisabled($options['disabled']); $builder->setAutoInitialize($options['auto_initialize']); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $name = $form->getName(); $blockName = $options['block_name'] ?: $form->getName(); $translationDomain = $options['translation_domain']; if ($view->parent) { if ('' !== ($parentFullName = $view->parent->vars['full_name'])) { $id = sprintf('%s_%s', $view->parent->vars['id'], $name); $fullName = sprintf('%s[%s]', $parentFullName, $name); $uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName); } else { $id = $name; $fullName = $name; $uniqueBlockPrefix = '_'.$blockName; } if (!$translationDomain) { $translationDomain = $view->parent->vars['translation_domain']; } } else { $id = $name; $fullName = $name; $uniqueBlockPrefix = '_'.$blockName; // Strip leading underscores and digits. These are allowed in // form names, but not in HTML4 ID attributes. // http://www.w3.org/TR/html401/struct/global.html#adef-id $id = ltrim($id, '_0123456789'); } $blockPrefixes = array(); for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) { array_unshift($blockPrefixes, $type->getName()); } $blockPrefixes[] = $uniqueBlockPrefix; if (!$translationDomain) { $translationDomain = 'messages'; } $view->vars = array_replace($view->vars, array( 'form' => $view, 'id' => $id, 'name' => $name, 'full_name' => $fullName, 'disabled' => $form->isDisabled(), 'label' => $options['label'], 'multipart' => false, 'attr' => $options['attr'], 'block_prefixes' => $blockPrefixes, 'unique_block_prefix' => $uniqueBlockPrefix, 'translation_domain' => $translationDomain, // Using the block name here speeds up performance in collection // forms, where each entry has the same full block name. // Including the type is important too, because if rows of a // collection form have different types (dynamically), they should // be rendered differently. // https://github.com/symfony/symfony/issues/5038 'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(), )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'block_name' => null, 'disabled' => false, 'label' => null, 'attr' => array(), 'translation_domain' => null, 'auto_initialize' => true, )); $resolver->setAllowedTypes(array( 'attr' => 'array', )); } } PK!Z^^:Symfony/Component/Form/Extension/Core/Type/PercentType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class PercentType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer(new PercentToLocalizedStringTransformer($options['precision'], $options['type'])); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'precision' => 0, 'type' => 'fractional', 'compound' => false, )); $resolver->setAllowedValues(array( 'type' => array( 'fractional', 'integer', ), )); } /** * {@inheritdoc} */ public function getName() { return 'percent'; } } PK!TT;Symfony/Component/Form/Extension/Core/Type/CheckboxType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CheckboxType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { // Unlike in other types, where the data is NULL by default, it // needs to be a Boolean here. setData(null) is not acceptable // for checkboxes and radio buttons (unless a custom model // transformer handles this case). // We cannot solve this case via overriding the "data" option, because // doing so also calls setDataLocked(true). $builder->setData(isset($options['data']) ? $options['data'] : false); $builder->addViewTransformer(new BooleanToStringTransformer($options['value'])); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'value' => $options['value'], 'checked' => null !== $form->getViewData(), )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $emptyData = function (FormInterface $form, $viewData) { return $viewData; }; $resolver->setDefaults(array( 'value' => '1', 'empty_data' => $emptyData, 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'checkbox'; } } PK!&ߏvv;Symfony/Component/Form/Extension/Core/Type/BirthdayType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class BirthdayType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'years' => range(date('Y') - 120, date('Y')), )); } /** * {@inheritdoc} */ public function getParent() { return 'date'; } /** * {@inheritdoc} */ public function getName() { return 'birthday'; } } PK!7pOLL8Symfony/Component/Form/Extension/Core/Type/RadioType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; class RadioType extends AbstractType { /** * {@inheritdoc} */ public function getParent() { return 'checkbox'; } /** * {@inheritdoc} */ public function getName() { return 'radio'; } } PK!Goo7Symfony/Component/Form/Extension/Core/Type/FileType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FileType extends AbstractType { /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'type' => 'file', 'value' => '', )); } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $view ->vars['multipart'] = true ; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'compound' => false, 'data_class' => 'Symfony\Component\HttpFoundation\File\File', 'empty_data' => null, )); } /** * {@inheritdoc} */ public function getName() { return 'file'; } } PK!8JJ9Symfony/Component/Form/Extension/Core/Type/SearchType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; class SearchType extends AbstractType { /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'search'; } } PK!_LL;Symfony/Component/Form/Extension/Core/Type/TimezoneType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TimezoneType extends AbstractType { /** * Stores the available timezone choices * @var array */ private static $timezones; /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => self::getTimezones(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'timezone'; } /** * Returns the timezone choices. * * The choices are generated from the ICU function * \DateTimeZone::listIdentifiers(). They are cached during a single request, * so multiple timezone fields on the same page don't lead to unnecessary * overhead. * * @return array The timezone choices */ public static function getTimezones() { if (null === static::$timezones) { static::$timezones = array(); foreach (\DateTimeZone::listIdentifiers() as $timezone) { $parts = explode('/', $timezone); if (count($parts) > 2) { $region = $parts[0]; $name = $parts[1].' - '.$parts[2]; } elseif (count($parts) > 1) { $region = $parts[0]; $name = $parts[1]; } else { $region = 'Other'; $name = $parts[0]; } static::$timezones[$region][$timezone] = str_replace('_', ' ', $name); } } return static::$timezones; } } PK!HH8Symfony/Component/Form/Extension/Core/Type/EmailType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; class EmailType extends AbstractType { /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'email'; } } PK![Gԃ =Symfony/Component/Form/Extension/Core/Type/CollectionType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CollectionType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { if ($options['allow_add'] && $options['prototype']) { $prototype = $builder->create($options['prototype_name'], $options['type'], array_replace(array( 'label' => $options['prototype_name'].'label__', ), $options['options'])); $builder->setAttribute('prototype', $prototype->getForm()); } $resizeListener = new ResizeFormListener( $options['type'], $options['options'], $options['allow_add'], $options['allow_delete'] ); $builder->addEventSubscriber($resizeListener); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'allow_add' => $options['allow_add'], 'allow_delete' => $options['allow_delete'], )); if ($form->getConfig()->hasAttribute('prototype')) { $view->vars['prototype'] = $form->getConfig()->getAttribute('prototype')->createView($view); } } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { if ($form->getConfig()->hasAttribute('prototype') && $view->vars['prototype']->vars['multipart']) { $view->vars['multipart'] = true; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $optionsNormalizer = function (Options $options, $value) { $value['block_name'] = 'entry'; return $value; }; $resolver->setDefaults(array( 'allow_add' => false, 'allow_delete' => false, 'prototype' => true, 'prototype_name' => '__name__', 'type' => 'text', 'options' => array(), )); $resolver->setNormalizers(array( 'options' => $optionsNormalizer, )); } /** * {@inheritdoc} */ public function getName() { return 'collection'; } } PK!tII;Symfony/Component/Form/Extension/Core/Type/TextareaType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; class TextareaType extends AbstractType { /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['pattern'] = null; } /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'textarea'; } } PK!;Symfony/Component/Form/Extension/Core/Type/LanguageType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class LanguageType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getLanguageBundle()->getLanguageNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'language'; } } PK!T;7Symfony/Component/Form/Extension/Core/Type/TextType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TextType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'text'; } } PK!H?!a7Symfony/Component/Form/Extension/Core/Type/TimeType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\ReversedTransformer; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TimeType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $parts = array('hour'); $format = 'H'; if ($options['with_seconds'] && !$options['with_minutes']) { throw new InvalidConfigurationException('You can not disable minutes if you have enabled seconds.'); } if ($options['with_minutes']) { $format .= ':i'; $parts[] = 'minute'; } if ($options['with_seconds']) { $format .= ':s'; $parts[] = 'second'; } if ('single_text' === $options['widget']) { $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format)); } else { $hourOptions = $minuteOptions = $secondOptions = array( 'error_bubbling' => true, ); if ('choice' === $options['widget']) { $hours = $minutes = array(); foreach ($options['hours'] as $hour) { $hours[$hour] = str_pad($hour, 2, '0', STR_PAD_LEFT); } // Only pass a subset of the options to children $hourOptions['choices'] = $hours; $hourOptions['empty_value'] = $options['empty_value']['hour']; if ($options['with_minutes']) { foreach ($options['minutes'] as $minute) { $minutes[$minute] = str_pad($minute, 2, '0', STR_PAD_LEFT); } $minuteOptions['choices'] = $minutes; $minuteOptions['empty_value'] = $options['empty_value']['minute']; } if ($options['with_seconds']) { $seconds = array(); foreach ($options['seconds'] as $second) { $seconds[$second] = str_pad($second, 2, '0', STR_PAD_LEFT); } $secondOptions['choices'] = $seconds; $secondOptions['empty_value'] = $options['empty_value']['second']; } // Append generic carry-along options foreach (array('required', 'translation_domain') as $passOpt) { $hourOptions[$passOpt] = $options[$passOpt]; if ($options['with_minutes']) { $minuteOptions[$passOpt] = $options[$passOpt]; } if ($options['with_seconds']) { $secondOptions[$passOpt] = $options[$passOpt]; } } } $builder->add('hour', $options['widget'], $hourOptions); if ($options['with_minutes']) { $builder->add('minute', $options['widget'], $minuteOptions); } if ($options['with_seconds']) { $builder->add('second', $options['widget'], $secondOptions); } $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget'])); } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'H:i:s') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) )); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'widget' => $options['widget'], 'with_minutes' => $options['with_minutes'], 'with_seconds' => $options['with_seconds'], )); if ('single_text' === $options['widget']) { $view->vars['type'] = 'time'; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['widget'] !== 'single_text'; }; $emptyValue = $emptyValueDefault = function (Options $options) { return $options['required'] ? null : ''; }; $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) { if (is_array($emptyValue)) { $default = $emptyValueDefault($options); return array_merge( array('hour' => $default, 'minute' => $default, 'second' => $default), $emptyValue ); } return array( 'hour' => $emptyValue, 'minute' => $emptyValue, 'second' => $emptyValue ); }; $resolver->setDefaults(array( 'hours' => range(0, 23), 'minutes' => range(0, 59), 'seconds' => range(0, 59), 'widget' => 'choice', 'input' => 'datetime', 'with_minutes' => true, 'with_seconds' => false, 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. 'data_class' => null, 'compound' => $compound, )); $resolver->setNormalizers(array( 'empty_value' => $emptyValueNormalizer, )); $resolver->setAllowedValues(array( 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), 'widget' => array( 'single_text', 'text', 'choice', ), )); } /** * {@inheritdoc} */ public function getName() { return 'time'; } } PK! &'';Symfony/Component/Form/Extension/Core/Type/DateTimeType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\ReversedTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class DateTimeType extends AbstractType { const DEFAULT_DATE_FORMAT = \IntlDateFormatter::MEDIUM; const DEFAULT_TIME_FORMAT = \IntlDateFormatter::MEDIUM; /** * This is not quite the HTML5 format yet, because ICU lacks the * capability of parsing and generating RFC 3339 dates, which * are like the below pattern but with a timezone suffix. The * timezone suffix is * * * "Z" for UTC * * "(-|+)HH:mm" for other timezones (note the colon!) * * For more information see: * * http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax * http://www.w3.org/TR/html-markup/input.datetime.html * http://tools.ietf.org/html/rfc3339 * * An ICU ticket was created: * http://icu-project.org/trac/ticket/9421 * * It was supposedly fixed, but is not available in all PHP installations * yet. To temporarily circumvent this issue, DateTimeToRfc3339Transformer * is used when the format matches this constant. */ const HTML5_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"; private static $acceptedFormats = array( \IntlDateFormatter::FULL, \IntlDateFormatter::LONG, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, ); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $parts = array('year', 'month', 'day', 'hour'); $dateParts = array('year', 'month', 'day'); $timeParts = array('hour'); if ($options['with_minutes']) { $parts[] = 'minute'; $timeParts[] = 'minute'; } if ($options['with_seconds']) { $parts[] = 'second'; $timeParts[] = 'second'; } $dateFormat = is_int($options['date_format']) ? $options['date_format'] : self::DEFAULT_DATE_FORMAT; $timeFormat = self::DEFAULT_TIME_FORMAT; $calendar = \IntlDateFormatter::GREGORIAN; $pattern = is_string($options['format']) ? $options['format'] : null; if (!in_array($dateFormat, self::$acceptedFormats, true)) { throw new InvalidOptionsException('The "date_format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.'); } if ('single_text' === $options['widget']) { if (self::HTML5_FORMAT === $pattern) { $builder->addViewTransformer(new DateTimeToRfc3339Transformer( $options['model_timezone'], $options['view_timezone'] )); } else { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( $options['model_timezone'], $options['view_timezone'], $dateFormat, $timeFormat, $calendar, $pattern )); } } else { // Only pass a subset of the options to children $dateOptions = array_intersect_key($options, array_flip(array( 'years', 'months', 'days', 'empty_value', 'required', 'translation_domain', ))); $timeOptions = array_intersect_key($options, array_flip(array( 'hours', 'minutes', 'seconds', 'with_minutes', 'with_seconds', 'empty_value', 'required', 'translation_domain', ))); if (null !== $options['date_widget']) { $dateOptions['widget'] = $options['date_widget']; } if (null !== $options['time_widget']) { $timeOptions['widget'] = $options['time_widget']; } if (null !== $options['date_format']) { $dateOptions['format'] = $options['date_format']; } $dateOptions['input'] = $timeOptions['input'] = 'array'; $dateOptions['error_bubbling'] = $timeOptions['error_bubbling'] = true; $builder ->addViewTransformer(new DataTransformerChain(array( new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts), new ArrayToPartsTransformer(array( 'date' => $dateParts, 'time' => $timeParts, )), ))) ->add('date', 'date', $dateOptions) ->add('time', 'time', $timeOptions) ; } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) )); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['widget'] = $options['widget']; // Change the input to a HTML5 date input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'datetime'; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['widget'] !== 'single_text'; }; // Defaults to the value of "widget" $dateWidget = function (Options $options) { return $options['widget']; }; // Defaults to the value of "widget" $timeWidget = function (Options $options) { return $options['widget']; }; $resolver->setDefaults(array( 'input' => 'datetime', 'model_timezone' => null, 'view_timezone' => null, 'format' => self::HTML5_FORMAT, 'date_format' => null, 'widget' => null, 'date_widget' => $dateWidget, 'time_widget' => $timeWidget, 'with_minutes' => true, 'with_seconds' => false, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. 'data_class' => null, 'compound' => $compound, )); // Don't add some defaults in order to preserve the defaults // set in DateType and TimeType $resolver->setOptional(array( 'empty_value', 'years', 'months', 'days', 'hours', 'minutes', 'seconds', )); $resolver->setAllowedValues(array( 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), 'date_widget' => array( null, // inherit default from DateType 'single_text', 'text', 'choice', ), 'time_widget' => array( null, // inherit default from TimeType 'single_text', 'text', 'choice', ), // This option will overwrite "date_widget" and "time_widget" options 'widget' => array( null, // default, don't overwrite options 'single_text', 'text', 'choice', ), )); } /** * {@inheritdoc} */ public function getName() { return 'datetime'; } } PK!q6Symfony/Component/Form/Extension/Core/Type/UrlType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class UrlType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber(new FixUrlProtocolListener($options['default_protocol'])); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'default_protocol' => 'http', )); } /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'url'; } } PK!9;Symfony/Component/Form/Extension/Core/Type/RepeatedType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class RepeatedType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { // Overwrite required option for child fields $options['first_options']['required'] = $options['required']; $options['second_options']['required'] = $options['required']; if (!isset($options['options']['error_bubbling'])) { $options['options']['error_bubbling'] = $options['error_bubbling']; } $builder ->addViewTransformer(new ValueToDuplicatesTransformer(array( $options['first_name'], $options['second_name'], ))) ->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options'])) ->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options'])) ; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'type' => 'text', 'options' => array(), 'first_options' => array(), 'second_options' => array(), 'first_name' => 'first', 'second_name' => 'second', 'error_bubbling' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'repeated'; } } PK!M2\3,3,7Symfony/Component/Form/Extension/Core/Type/DateType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\ReversedTransformer; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; class DateType extends AbstractType { const DEFAULT_FORMAT = \IntlDateFormatter::MEDIUM; const HTML5_FORMAT = 'yyyy-MM-dd'; private static $acceptedFormats = array( \IntlDateFormatter::FULL, \IntlDateFormatter::LONG, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, ); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $dateFormat = is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT; $timeFormat = \IntlDateFormatter::NONE; $calendar = \IntlDateFormatter::GREGORIAN; $pattern = is_string($options['format']) ? $options['format'] : null; if (!in_array($dateFormat, self::$acceptedFormats, true)) { throw new InvalidOptionsException('The "format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.'); } if (null !== $pattern && (false === strpos($pattern, 'y') || false === strpos($pattern, 'M') || false === strpos($pattern, 'd'))) { throw new InvalidOptionsException(sprintf('The "format" option should contain the letters "y", "M" and "d". Its current value is "%s".', $pattern)); } if ('single_text' === $options['widget']) { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( $options['model_timezone'], $options['view_timezone'], $dateFormat, $timeFormat, $calendar, $pattern )); } else { $yearOptions = $monthOptions = $dayOptions = array( 'error_bubbling' => true, ); $formatter = new \IntlDateFormatter( \Locale::getDefault(), $dateFormat, $timeFormat, 'UTC', $calendar, $pattern ); $formatter->setLenient(false); if ('choice' === $options['widget']) { // Only pass a subset of the options to children $yearOptions['choices'] = $this->formatTimestamps($formatter, '/y+/', $this->listYears($options['years'])); $yearOptions['empty_value'] = $options['empty_value']['year']; $monthOptions['choices'] = $this->formatTimestamps($formatter, '/[M|L]+/', $this->listMonths($options['months'])); $monthOptions['empty_value'] = $options['empty_value']['month']; $dayOptions['choices'] = $this->formatTimestamps($formatter, '/d+/', $this->listDays($options['days'])); $dayOptions['empty_value'] = $options['empty_value']['day']; } // Append generic carry-along options foreach (array('required', 'translation_domain') as $passOpt) { $yearOptions[$passOpt] = $monthOptions[$passOpt] = $dayOptions[$passOpt] = $options[$passOpt]; } $builder ->add('year', $options['widget'], $yearOptions) ->add('month', $options['widget'], $monthOptions) ->add('day', $options['widget'], $dayOptions) ->addViewTransformer(new DateTimeToArrayTransformer( $options['model_timezone'], $options['view_timezone'], array('year', 'month', 'day') )) ->setAttribute('formatter', $formatter) ; } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'Y-m-d') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], array('year', 'month', 'day')) )); } } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $view->vars['widget'] = $options['widget']; // Change the input to a HTML5 date input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'date'; } if ($form->getConfig()->hasAttribute('formatter')) { $pattern = $form->getConfig()->getAttribute('formatter')->getPattern(); // remove special characters unless the format was explicitly specified if (!is_string($options['format'])) { $pattern = preg_replace('/[^yMd]+/', '', $pattern); } // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy) // lookup various formats at http://userguide.icu-project.org/formatparse/datetime if (preg_match('/^([yMd]+)[^yMd]*([yMd]+)[^yMd]*([yMd]+)$/', $pattern)) { $pattern = preg_replace(array('/y+/', '/M+/', '/d+/'), array('{{ year }}', '{{ month }}', '{{ day }}'), $pattern); } else { // default fallback $pattern = '{{ year }}{{ month }}{{ day }}'; } $view->vars['date_pattern'] = $pattern; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['widget'] !== 'single_text'; }; $emptyValue = $emptyValueDefault = function (Options $options) { return $options['required'] ? null : ''; }; $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) { if (is_array($emptyValue)) { $default = $emptyValueDefault($options); return array_merge( array('year' => $default, 'month' => $default, 'day' => $default), $emptyValue ); } return array( 'year' => $emptyValue, 'month' => $emptyValue, 'day' => $emptyValue ); }; $format = function (Options $options) { return $options['widget'] === 'single_text' ? DateType::HTML5_FORMAT : DateType::DEFAULT_FORMAT; }; $resolver->setDefaults(array( 'years' => range(date('Y') - 5, date('Y') + 5), 'months' => range(1, 12), 'days' => range(1, 31), 'widget' => 'choice', 'input' => 'datetime', 'format' => $format, 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. 'data_class' => null, 'compound' => $compound, )); $resolver->setNormalizers(array( 'empty_value' => $emptyValueNormalizer, )); $resolver->setAllowedValues(array( 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), 'widget' => array( 'single_text', 'text', 'choice', ), )); $resolver->setAllowedTypes(array( 'format' => array('int', 'string'), )); } /** * {@inheritdoc} */ public function getName() { return 'date'; } private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $timestamps) { $pattern = $formatter->getPattern(); $timezone = $formatter->getTimezoneId(); if ($setTimeZone = method_exists($formatter, 'setTimeZone')) { $formatter->setTimeZone('UTC'); } else { $formatter->setTimeZoneId('UTC'); } if (preg_match($regex, $pattern, $matches)) { $formatter->setPattern($matches[0]); foreach ($timestamps as $key => $timestamp) { $timestamps[$key] = $formatter->format($timestamp); } // I'd like to clone the formatter above, but then we get a // segmentation fault, so let's restore the old state instead $formatter->setPattern($pattern); } if ($setTimeZone) { $formatter->setTimeZone($timezone); } else { $formatter->setTimeZoneId($timezone); } return $timestamps; } private function listYears(array $years) { $result = array(); foreach ($years as $year) { if (false !== $y = gmmktime(0, 0, 0, 6, 15, $year)) { $result[$year] = $y; } } return $result; } private function listMonths(array $months) { $result = array(); foreach ($months as $month) { $result[$month] = gmmktime(0, 0, 0, $month, 15); } return $result; } private function listDays(array $days) { $result = array(); foreach ($days as $day) { $result[$day] = gmmktime(0, 0, 0, 5, $day); } return $result; } } PK!aLŢ:Symfony/Component/Form/Extension/Core/Type/CountryType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CountryType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getRegionBundle()->getCountryNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'country'; } } PK!Ci9Symfony/Component/Form/Extension/Core/Type/NumberType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class NumberType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer(new NumberToLocalizedStringTransformer( $options['precision'], $options['grouping'], $options['rounding_mode'] )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // default precision is locale specific (usually around 3) 'precision' => null, 'grouping' => false, 'rounding_mode' => NumberToLocalizedStringTransformer::ROUND_HALF_UP, 'compound' => false, )); $resolver->setAllowedValues(array( 'rounding_mode' => array( NumberToLocalizedStringTransformer::ROUND_FLOOR, NumberToLocalizedStringTransformer::ROUND_DOWN, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN, NumberToLocalizedStringTransformer::ROUND_HALF_UP, NumberToLocalizedStringTransformer::ROUND_UP, NumberToLocalizedStringTransformer::ROUND_CEILING, ), )); } /** * {@inheritdoc} */ public function getName() { return 'number'; } } PK!:y  7Symfony/Component/Form/Extension/Core/Type/FormType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; class FormType extends BaseType { /** * @var PropertyAccessorInterface */ private $propertyAccessor; public function __construct(PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { parent::buildForm($builder, $options); $isDataOptionSet = array_key_exists('data', $options); $builder ->setRequired($options['required']) ->setErrorBubbling($options['error_bubbling']) ->setEmptyData($options['empty_data']) ->setPropertyPath($options['property_path']) ->setMapped($options['mapped']) ->setByReference($options['by_reference']) ->setInheritData($options['inherit_data']) ->setCompound($options['compound']) ->setData($isDataOptionSet ? $options['data'] : null) ->setDataLocked($isDataOptionSet) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ->setMethod($options['method']) ->setAction($options['action']) ; if ($options['trim']) { $builder->addEventSubscriber(new TrimListener()); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { parent::buildView($view, $form, $options); $name = $form->getName(); $readOnly = $options['read_only']; if ($view->parent) { if ('' === $name) { throw new LogicException('Form node with empty name can be used only as root form node.'); } // Complex fields are read-only if they themselves or their parents are. if (!$readOnly) { $readOnly = $view->parent->vars['read_only']; } } $view->vars = array_replace($view->vars, array( 'read_only' => $readOnly, 'errors' => $form->getErrors(), 'valid' => $form->isSubmitted() ? $form->isValid() : true, 'value' => $form->getViewData(), 'data' => $form->getNormData(), 'required' => $form->isRequired(), 'max_length' => $options['max_length'], 'pattern' => $options['pattern'], 'size' => null, 'label_attr' => $options['label_attr'], 'compound' => $form->getConfig()->getCompound(), 'method' => $form->getConfig()->getMethod(), 'action' => $form->getConfig()->getAction(), 'submitted' => $form->isSubmitted(), )); } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $multipart = false; foreach ($view->children as $child) { if ($child->vars['multipart']) { $multipart = true; break; } } $view->vars['multipart'] = $multipart; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); // Derive "data_class" option from passed "data" object $dataClass = function (Options $options) { return isset($options['data']) && is_object($options['data']) ? get_class($options['data']) : null; }; // Derive "empty_data" closure from "data_class" option $emptyData = function (Options $options) { $class = $options['data_class']; if (null !== $class) { return function (FormInterface $form) use ($class) { return $form->isEmpty() && !$form->isRequired() ? null : new $class(); }; } return function (FormInterface $form) { return $form->getConfig()->getCompound() ? array() : ''; }; }; // For any form that is not represented by a single HTML control, // errors should bubble up by default $errorBubbling = function (Options $options) { return $options['compound']; }; // BC with old "virtual" option $inheritData = function (Options $options) { if (null !== $options['virtual']) { // Uncomment this as soon as the deprecation note should be shown // trigger_error('The form option "virtual" is deprecated since version 2.3 and will be removed in 3.0. Use "inherit_data" instead.', E_USER_DEPRECATED); return $options['virtual']; } return false; }; // If data is given, the form is locked to that data // (independent of its value) $resolver->setOptional(array( 'data', )); $resolver->setDefaults(array( 'data_class' => $dataClass, 'empty_data' => $emptyData, 'trim' => true, 'required' => true, 'read_only' => false, 'max_length' => null, 'pattern' => null, 'property_path' => null, 'mapped' => true, 'by_reference' => true, 'error_bubbling' => $errorBubbling, 'label_attr' => array(), 'virtual' => null, 'inherit_data' => $inheritData, 'compound' => true, 'method' => 'POST', // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) // section 4.2., empty URIs are considered same-document references 'action' => '', )); $resolver->setAllowedTypes(array( 'label_attr' => 'array', )); } /** * {@inheritdoc} */ public function getParent() { return null; } /** * {@inheritdoc} */ public function getName() { return 'form'; } } PK!5S 8Symfony/Component/Form/Extension/Core/Type/MoneyType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class MoneyType extends AbstractType { protected static $patterns = array(); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->addViewTransformer(new MoneyToLocalizedStringTransformer( $options['precision'], $options['grouping'], null, $options['divisor'] )) ; } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['money_pattern'] = self::getPattern($options['currency']); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'precision' => 2, 'grouping' => false, 'divisor' => 1, 'currency' => 'EUR', 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'money'; } /** * Returns the pattern for this locale * * The pattern contains the placeholder "{{ widget }}" where the HTML tag should * be inserted */ protected static function getPattern($currency) { if (!$currency) { return '{{ widget }}'; } $locale = \Locale::getDefault(); if (!isset(self::$patterns[$locale])) { self::$patterns[$locale] = array(); } if (!isset(self::$patterns[$locale][$currency])) { $format = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); $pattern = $format->formatCurrency('123', $currency); // the spacings between currency symbol and number are ignored, because // a single space leads to better readability in combination with input // fields // the regex also considers non-break spaces (0xC2 or 0xA0 in UTF-8) preg_match('/^([^\s\xc2\xa0]*)[\s\xc2\xa0]*123(?:[,.]0+)?[\s\xc2\xa0]*([^\s\xc2\xa0]*)$/u', $pattern, $matches); if (!empty($matches[1])) { self::$patterns[$locale][$currency] = $matches[1].' {{ widget }}'; } elseif (!empty($matches[2])) { self::$patterns[$locale][$currency] = '{{ widget }} '.$matches[2]; } else { self::$patterns[$locale][$currency] = '{{ widget }}'; } } return self::$patterns[$locale][$currency]; } } PK!6sDSymfony/Component/Form/Extension/DataCollector/FormDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; /** * Data collector for {@link \Symfony\Component\Form\FormInterface} instances. * * @since 2.4 * @author Robert Schönthal * @author Bernhard Schussek */ class FormDataCollector extends DataCollector implements FormDataCollectorInterface { /** * @var FormDataExtractor */ private $dataExtractor; /** * Stores the collected data per {@link FormInterface} instance. * * Uses the hashes of the forms as keys. This is preferable over using * {@link \SplObjectStorage}, because in this way no references are kept * to the {@link FormInterface} instances. * * @var array */ private $dataByForm; /** * Stores the collected data per {@link FormView} instance. * * Uses the hashes of the views as keys. This is preferable over using * {@link \SplObjectStorage}, because in this way no references are kept * to the {@link FormView} instances. * * @var array */ private $dataByView; /** * Connects {@link FormView} with {@link FormInterface} instances. * * Uses the hashes of the views as keys and the hashes of the forms as * values. This is preferable over storing the objects directly, because * this way they can safely be discarded by the GC. * * @var array */ private $formsByView; public function __construct(FormDataExtractorInterface $dataExtractor) { $this->dataExtractor = $dataExtractor; $this->data = array( 'forms' => array(), 'nb_errors' => 0, ); } /** * Does nothing. The data is collected during the form event listeners. */ public function collect(Request $request, Response $response, \Exception $exception = null) { } /** * {@inheritdoc} */ public function associateFormWithView(FormInterface $form, FormView $view) { $this->formsByView[spl_object_hash($view)] = spl_object_hash($form); } /** * {@inheritdoc} */ public function collectConfiguration(FormInterface $form) { $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { $this->dataByForm[$hash] = array(); } $this->dataByForm[$hash] = array_replace( $this->dataByForm[$hash], $this->dataExtractor->extractConfiguration($form) ); foreach ($form as $child) { $this->collectConfiguration($child); } } /** * {@inheritdoc} */ public function collectDefaultData(FormInterface $form) { $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { $this->dataByForm[$hash] = array(); } $this->dataByForm[$hash] = array_replace( $this->dataByForm[$hash], $this->dataExtractor->extractDefaultData($form) ); foreach ($form as $child) { $this->collectDefaultData($child); } } /** * {@inheritdoc} */ public function collectSubmittedData(FormInterface $form) { $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { $this->dataByForm[$hash] = array(); } $this->dataByForm[$hash] = array_replace( $this->dataByForm[$hash], $this->dataExtractor->extractSubmittedData($form) ); // Count errors if (isset($this->dataByForm[$hash]['errors'])) { $this->data['nb_errors'] += count($this->dataByForm[$hash]['errors']); } foreach ($form as $child) { $this->collectSubmittedData($child); } } /** * {@inheritdoc} */ public function collectViewVariables(FormView $view) { $hash = spl_object_hash($view); if (!isset($this->dataByView[$hash])) { $this->dataByView[$hash] = array(); } $this->dataByView[$hash] = array_replace( $this->dataByView[$hash], $this->dataExtractor->extractViewVariables($view) ); foreach ($view->children as $child) { $this->collectViewVariables($child); } } /** * {@inheritdoc} */ public function buildPreliminaryFormTree(FormInterface $form) { $this->data['forms'][$form->getName()] = array(); $this->recursiveBuildPreliminaryFormTree($form, $this->data['forms'][$form->getName()]); } /** * {@inheritdoc} */ public function buildFinalFormTree(FormInterface $form, FormView $view) { $this->data['forms'][$form->getName()] = array(); $this->recursiveBuildFinalFormTree($form, $view, $this->data['forms'][$form->getName()]); } /** * {@inheritDoc} */ public function getName() { return 'form'; } /** * {@inheritdoc} */ public function getData() { return $this->data; } private function recursiveBuildPreliminaryFormTree(FormInterface $form, &$output = null) { $hash = spl_object_hash($form); $output = isset($this->dataByForm[$hash]) ? $this->dataByForm[$hash] : array(); $output['children'] = array(); foreach ($form as $name => $child) { $output['children'][$name] = array(); $this->recursiveBuildPreliminaryFormTree($child, $output['children'][$name]); } } private function recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, &$output = null) { $viewHash = spl_object_hash($view); $formHash = null; if (null !== $form) { $formHash = spl_object_hash($form); } elseif (isset($this->formsByView[$viewHash])) { // The FormInterface instance of the CSRF token is never contained in // the FormInterface tree of the form, so we need to get the // corresponding FormInterface instance for its view in a different way $formHash = $this->formsByView[$viewHash]; } $output = isset($this->dataByView[$viewHash]) ? $this->dataByView[$viewHash] : array(); if (null !== $formHash) { $output = array_replace( $output, isset($this->dataByForm[$formHash]) ? $this->dataByForm[$formHash] : array() ); } $output['children'] = array(); foreach ($view->children as $name => $childView) { // The CSRF token, for example, is never added to the form tree. // It is only present in the view. $childForm = null !== $form && $form->has($name) ? $form->get($name) : null; $output['children'][$name] = array(); $this->recursiveBuildFinalFormTree($childForm, $childView, $output['children'][$name]); } } } PK!I2  VSymfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; /** * Listener that invokes a data collector for the {@link FormEvents::POST_SET_DATA} * and {@link FormEvents::POST_SUBMIT} events. * * @since 2.4 * @author Bernhard Schussek */ class DataCollectorListener implements EventSubscriberInterface { /** * @var FormDataCollectorInterface */ private $dataCollector; public function __construct(FormDataCollectorInterface $dataCollector) { $this->dataCollector = $dataCollector; } /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array( // High priority in order to be called as soon as possible FormEvents::POST_SET_DATA => array('postSetData', 255), // Low priority in order to be called as late as possible FormEvents::POST_SUBMIT => array('postSubmit', -255), ); } /** * Listener for the {@link FormEvents::POST_SET_DATA} event. * * @param FormEvent $event The event object */ public function postSetData(FormEvent $event) { if ($event->getForm()->isRoot()) { // Collect basic information about each form $this->dataCollector->collectConfiguration($event->getForm()); // Collect the default data $this->dataCollector->collectDefaultData($event->getForm()); } } /** * Listener for the {@link FormEvents::POST_SUBMIT} event. * * @param FormEvent $event The event object */ public function postSubmit(FormEvent $event) { if ($event->getForm()->isRoot()) { // Collect the submitted data of each form $this->dataCollector->collectSubmittedData($event->getForm()); // Assemble a form tree // This is done again in collectViewVariables(), but that method // is not guaranteed to be called (i.e. when no view is created) $this->dataCollector->buildPreliminaryFormTree($event->getForm()); } } } PK!T MSymfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; /** * Collects and structures information about forms. * * @since 2.4 * @author Bernhard Schussek */ interface FormDataCollectorInterface extends DataCollectorInterface { /** * Stores configuration data of the given form and its children. * * @param FormInterface $form A root form */ public function collectConfiguration(FormInterface $form); /** * Stores the default data of the given form and its children. * * @param FormInterface $form A root form */ public function collectDefaultData(FormInterface $form); /** * Stores the submitted data of the given form and its children. * * @param FormInterface $form A root form */ public function collectSubmittedData(FormInterface $form); /** * Stores the view variables of the given form view and its children. * * @param FormView $view A root form view */ public function collectViewVariables(FormView $view); /** * Specifies that the given objects represent the same conceptual form. * * @param FormInterface $form A form object * @param FormView $view A view object */ public function associateFormWithView(FormInterface $form, FormView $view); /** * Assembles the data collected about the given form and its children as * a tree-like data structure. * * The result can be queried using {@link getData()}. * * @param FormInterface $form A root form */ public function buildPreliminaryFormTree(FormInterface $form); /** * Assembles the data collected about the given form and its children as * a tree-like data structure. * * The result can be queried using {@link getData()}. * * Contrary to {@link buildPreliminaryFormTree()}, a {@link FormView} * object has to be passed. The tree structure of this view object will be * used for structuring the resulting data. That means, if a child is * present in the view, but not in the form, it will be present in the final * data array anyway. * * When {@link FormView} instances are present in the view tree, for which * no corresponding {@link FormInterface} objects can be found in the form * tree, only the view data will be included in the result. If a * corresponding {@link FormInterface} exists otherwise, call * {@link associateFormWithView()} before calling this method. * * @param FormInterface $form A root form * @param FormView $view A root view */ public function buildFinalFormTree(FormInterface $form, FormView $view); /** * Returns all collected data. * * @return array */ public function getData(); } PK!MSymfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; /** * Extracts arrays of information out of forms. * * @since 2.4 * @author Bernhard Schussek */ interface FormDataExtractorInterface { /** * Extracts the configuration data of a form. * * @param FormInterface $form The form * * @return array Information about the form's configuration */ public function extractConfiguration(FormInterface $form); /** * Extracts the default data of a form. * * @param FormInterface $form The form * * @return array Information about the form's default data */ public function extractDefaultData(FormInterface $form); /** * Extracts the submitted data of a form. * * @param FormInterface $form The form * * @return array Information about the form's submitted data */ public function extractSubmittedData(FormInterface $form); /** * Extracts the view variables of a form. * * @param FormView $view The form view * * @return array Information about the view's variables */ public function extractViewVariables(FormView $view); } PK!| ]WSymfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\Proxy; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\ResolvedFormTypeInterface; /** * Proxy that invokes a data collector when creating a form and its view. * * @since 2.4 * @author Bernhard Schussek */ class ResolvedTypeDataCollectorProxy implements ResolvedFormTypeInterface { /** * @var ResolvedFormTypeInterface */ private $proxiedType; /** * @var FormDataCollectorInterface */ private $dataCollector; public function __construct(ResolvedFormTypeInterface $proxiedType, FormDataCollectorInterface $dataCollector) { $this->proxiedType = $proxiedType; $this->dataCollector = $dataCollector; } /** * {@inheritdoc} */ public function getName() { return $this->proxiedType->getName(); } /** * {@inheritdoc} */ public function getParent() { return $this->proxiedType->getParent(); } /** * {@inheritdoc} */ public function getInnerType() { return $this->proxiedType->getInnerType(); } /** * {@inheritdoc} */ public function getTypeExtensions() { return $this->proxiedType->getTypeExtensions(); } /** * {@inheritdoc} */ public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()) { $builder = $this->proxiedType->createBuilder($factory, $name, $options); $builder->setAttribute('data_collector/passed_options', $options); $builder->setType($this); return $builder; } /** * {@inheritdoc} */ public function createView(FormInterface $form, FormView $parent = null) { return $this->proxiedType->createView($form, $parent); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $this->proxiedType->buildForm($builder, $options); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $this->proxiedType->buildView($view, $form, $options); } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $this->proxiedType->finishView($view, $form, $options); // Remember which view belongs to which form instance, so that we can // get the collected data for a view when its form instance is not // available (e.g. CSRF token) $this->dataCollector->associateFormWithView($form, $view); // Since the CSRF token is only present in the FormView tree, we also // need to check the FormView tree instead of calling isRoot() on the // FormInterface tree if (null === $view->parent) { $this->dataCollector->collectViewVariables($view); // Re-assemble data, in case FormView instances were added, for // which no FormInterface instances were present (e.g. CSRF token). // Since finishView() is called after finishing the views of all // children, we can safely assume that information has been // collected about the complete form tree. $this->dataCollector->buildFinalFormTree($form, $view); } } /** * {@inheritdoc} */ public function getOptionsResolver() { return $this->proxiedType->getOptionsResolver(); } } PK!((^Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\Proxy; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\ResolvedFormTypeFactoryInterface; use Symfony\Component\Form\ResolvedFormTypeInterface; /** * Proxy that wraps resolved types into {@link ResolvedTypeDataCollectorProxy} * instances. * * @since 2.4 * @author Bernhard Schussek */ class ResolvedTypeFactoryDataCollectorProxy implements ResolvedFormTypeFactoryInterface { /** * @var ResolvedFormTypeFactoryInterface */ private $proxiedFactory; /** * @var FormDataCollectorInterface */ private $dataCollector; public function __construct(ResolvedFormTypeFactoryInterface $proxiedFactory, FormDataCollectorInterface $dataCollector) { $this->proxiedFactory = $proxiedFactory; $this->dataCollector = $dataCollector; } /** * {@inheritdoc} */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null) { return new ResolvedTypeDataCollectorProxy( $this->proxiedFactory->createResolvedType($type, $typeExtensions, $parent), $this->dataCollector ); } } PK!#11ISymfony/Component/Form/Extension/DataCollector/DataCollectorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\AbstractExtension; /** * Extension for collecting data of the forms on a page. * * @since 2.4 * @author Robert Schönthal * @author Bernhard Schussek */ class DataCollectorExtension extends AbstractExtension { /** * @var EventSubscriberInterface */ private $dataCollector; public function __construct(FormDataCollectorInterface $dataCollector) { $this->dataCollector = $dataCollector; } /** * {@inheritDoc} */ protected function loadTypeExtensions() { return array( new Type\DataCollectorTypeExtension($this->dataCollector) ); } } PK!%`DSymfony/Component/Form/Extension/DataCollector/FormDataExtractor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; /** * Default implementation of {@link FormDataExtractorInterface}. * * @since 2.4 * @author Bernhard Schussek */ class FormDataExtractor implements FormDataExtractorInterface { /** * @var ValueExporter */ private $valueExporter; /** * Constructs a new data extractor. */ public function __construct(ValueExporter $valueExporter = null) { $this->valueExporter = $valueExporter ?: new ValueExporter(); } /** * {@inheritdoc} */ public function extractConfiguration(FormInterface $form) { $data = array( 'id' => $this->buildId($form), 'type' => $form->getConfig()->getType()->getName(), 'type_class' => get_class($form->getConfig()->getType()->getInnerType()), 'synchronized' => $this->valueExporter->exportValue($form->isSynchronized()), 'passed_options' => array(), 'resolved_options' => array(), ); foreach ($form->getConfig()->getAttribute('data_collector/passed_options', array()) as $option => $value) { $data['passed_options'][$option] = $this->valueExporter->exportValue($value); } foreach ($form->getConfig()->getOptions() as $option => $value) { $data['resolved_options'][$option] = $this->valueExporter->exportValue($value); } ksort($data['passed_options']); ksort($data['resolved_options']); return $data; } /** * {@inheritdoc} */ public function extractDefaultData(FormInterface $form) { $data = array( 'default_data' => array( 'norm' => $this->valueExporter->exportValue($form->getNormData()), ), 'submitted_data' => array(), ); if ($form->getData() !== $form->getNormData()) { $data['default_data']['model'] = $this->valueExporter->exportValue($form->getData()); } if ($form->getViewData() !== $form->getNormData()) { $data['default_data']['view'] = $this->valueExporter->exportValue($form->getViewData()); } return $data; } /** * {@inheritdoc} */ public function extractSubmittedData(FormInterface $form) { $data = array( 'submitted_data' => array( 'norm' => $this->valueExporter->exportValue($form->getNormData()), ), 'errors' => array(), ); if ($form->getViewData() !== $form->getNormData()) { $data['submitted_data']['view'] = $this->valueExporter->exportValue($form->getViewData()); } if ($form->getData() !== $form->getNormData()) { $data['submitted_data']['model'] = $this->valueExporter->exportValue($form->getData()); } foreach ($form->getErrors() as $error) { $data['errors'][] = array( 'message' => $error->getMessage(), ); } $data['synchronized'] = $this->valueExporter->exportValue($form->isSynchronized()); return $data; } /** * {@inheritdoc} */ public function extractViewVariables(FormView $view) { $data = array(); // Set the ID in case no FormInterface object was collected for this // view if (isset($view->vars['id'])) { $data['id'] = $view->vars['id']; } foreach ($view->vars as $varName => $value) { $data['view_vars'][$varName] = $this->valueExporter->exportValue($value); } ksort($data['view_vars']); return $data; } /** * Recursively builds an HTML ID for a form. * * @param FormInterface $form The form * * @return string The HTML ID */ private function buildId(FormInterface $form) { $id = $form->getName(); if (null !== $form->getParent()) { $id = $this->buildId($form->getParent()).'_'.$id; } return $id; } } PK!1 uuRSymfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormBuilderInterface; /** * Type extension for collecting data of a form with this type. * * @since 2.4 * @author Robert Schönthal * @author Bernhard Schussek */ class DataCollectorTypeExtension extends AbstractTypeExtension { /** * @var \Symfony\Component\EventDispatcher\EventSubscriberInterface */ private $listener; public function __construct(FormDataCollectorInterface $dataCollector) { $this->listener = new DataCollectorListener($dataCollector); } /** * {@inheritDoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber($this->listener); } /** * {@inheritDoc} */ public function getExtendedType() { return 'form'; } } PK!uUSW W USymfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DependencyInjection; use Symfony\Component\Form\FormExtensionInterface; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\ContainerInterface; class DependencyInjectionExtension implements FormExtensionInterface { private $container; private $typeServiceIds; private $typeExtensionServiceIds; private $guesserServiceIds; private $guesser; private $guesserLoaded = false; public function __construct(ContainerInterface $container, array $typeServiceIds, array $typeExtensionServiceIds, array $guesserServiceIds) { $this->container = $container; $this->typeServiceIds = $typeServiceIds; $this->typeExtensionServiceIds = $typeExtensionServiceIds; $this->guesserServiceIds = $guesserServiceIds; } public function getType($name) { if (!isset($this->typeServiceIds[$name])) { throw new InvalidArgumentException(sprintf('The field type "%s" is not registered with the service container.', $name)); } $type = $this->container->get($this->typeServiceIds[$name]); if ($type->getName() !== $name) { throw new InvalidArgumentException( sprintf('The type name specified for the service "%s" does not match the actual name. Expected "%s", given "%s"', $this->typeServiceIds[$name], $name, $type->getName() )); } return $type; } public function hasType($name) { return isset($this->typeServiceIds[$name]); } public function getTypeExtensions($name) { $extensions = array(); if (isset($this->typeExtensionServiceIds[$name])) { foreach ($this->typeExtensionServiceIds[$name] as $serviceId) { $extensions[] = $this->container->get($serviceId); } } return $extensions; } public function hasTypeExtensions($name) { return isset($this->typeExtensionServiceIds[$name]); } public function getTypeGuesser() { if (!$this->guesserLoaded) { $this->guesserLoaded = true; $guessers = array(); foreach ($this->guesserServiceIds as $serviceId) { $guessers[] = $this->container->get($serviceId); } if (count($guessers) > 0) { $this->guesser = new FormTypeGuesserChain($guessers); } } return $this->guesser; } } PK!(s //-Symfony/Component/Form/ClickableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A clickable form element. * * @author Bernhard Schussek */ interface ClickableInterface { /** * Returns whether this element was clicked. * * @return Boolean Whether this element was clicked. */ public function isClicked(); } PK!H #Symfony/Component/Form/FormView.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; /** * @author Bernhard Schussek */ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable { /** * The variables assigned to this view. * @var array */ public $vars = array( 'value' => null, 'attr' => array(), ); /** * The parent view. * @var FormView */ public $parent; /** * The child views. * @var array */ public $children = array(); /** * Is the form attached to this renderer rendered? * * Rendering happens when either the widget or the row method was called. * Row implicitly includes widget, however certain rendering mechanisms * have to skip widget rendering when a row is rendered. * * @var Boolean */ private $rendered = false; public function __construct(FormView $parent = null) { $this->parent = $parent; } /** * Returns whether the view was already rendered. * * @return Boolean Whether this view's widget is rendered. */ public function isRendered() { $hasChildren = 0 < count($this->children); if (true === $this->rendered || !$hasChildren) { return $this->rendered; } if ($hasChildren) { foreach ($this->children as $child) { if (!$child->isRendered()) { return false; } } return $this->rendered = true; } return false; } /** * Marks the view as rendered. * * @return FormView The view object. */ public function setRendered() { $this->rendered = true; return $this; } /** * Returns a child by name (implements \ArrayAccess). * * @param string $name The child name * * @return FormView The child view */ public function offsetGet($name) { return $this->children[$name]; } /** * Returns whether the given child exists (implements \ArrayAccess). * * @param string $name The child name * * @return Boolean Whether the child view exists */ public function offsetExists($name) { return isset($this->children[$name]); } /** * Implements \ArrayAccess. * * @throws BadMethodCallException always as setting a child by name is not allowed */ public function offsetSet($name, $value) { throw new BadMethodCallException('Not supported'); } /** * Removes a child (implements \ArrayAccess). * * @param string $name The child name */ public function offsetUnset($name) { unset($this->children[$name]); } /** * Returns an iterator to iterate over children (implements \IteratorAggregate) * * @return \ArrayIterator The iterator */ public function getIterator() { return new \ArrayIterator($this->children); } /** * Implements \Countable. * * @return integer The number of children views */ public function count() { return count($this->children); } } PK! ͋   Symfony/Component/Form/Forms.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Extension\Core\CoreExtension; /** * Entry point of the Form component. * * Use this class to conveniently create new form factories: * * * use Symfony\Component\Form\Forms; * * $formFactory = Forms::createFormFactory(); * * $form = $formFactory->createBuilder() * ->add('firstName', 'text') * ->add('lastName', 'text') * ->add('age', 'integer') * ->add('gender', 'choice', array( * 'choices' => array('m' => 'Male', 'f' => 'Female'), * )) * ->getForm(); * * * You can also add custom extensions to the form factory: * * * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new AcmeExtension()) * ->getFormFactory(); * * * If you create custom form types or type extensions, it is * generally recommended to create your own extensions that lazily * load these types and type extensions. In projects where performance * does not matter that much, you can also pass them directly to the * form factory: * * * $formFactory = Forms::createFormFactoryBuilder() * ->addType(new PersonType()) * ->addType(new PhoneNumberType()) * ->addTypeExtension(new FormTypeHelpTextExtension()) * ->getFormFactory(); * * * Support for CSRF protection is provided by the CsrfExtension. * This extension needs a CSRF provider with a strong secret * (e.g. a 20 character long random string). The default * implementation for this is DefaultCsrfProvider: * * * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; * * $secret = 'V8a5Z97e...'; * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new CsrfExtension(new DefaultCsrfProvider($secret))) * ->getFormFactory(); * * * Support for the HttpFoundation is provided by the * HttpFoundationExtension. You are also advised to load the CSRF * extension with the driver for HttpFoundation's Session class: * * * use Symfony\Component\HttpFoundation\Session\Session; * use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; * * $session = new Session(); * $secret = 'V8a5Z97e...'; * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new HttpFoundationExtension()) * ->addExtension(new CsrfExtension(new SessionCsrfProvider($session, $secret))) * ->getFormFactory(); * * * Support for the Validator component is provided by ValidatorExtension. * This extension needs a validator object to function properly: * * * use Symfony\Component\Validator\Validation; * use Symfony\Component\Form\Extension\Validator\ValidatorExtension; * * $validator = Validation::createValidator(); * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new ValidatorExtension($validator)) * ->getFormFactory(); * * * Support for the Templating component is provided by TemplatingExtension. * This extension needs a PhpEngine object for rendering forms. As second * argument you should pass the names of the default themes. Here is an * example for using the default layout with "
" tags: * * * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; * * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new TemplatingExtension($engine, null, array( * 'FrameworkBundle:Form', * ))) * ->getFormFactory(); * * * The next example shows how to include the "" layout: * * * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; * * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new TemplatingExtension($engine, null, array( * 'FrameworkBundle:Form', * 'FrameworkBundle:FormTable', * ))) * ->getFormFactory(); * * * If you also loaded the CsrfExtension, you should pass the CSRF provider * to the extension so that you can render CSRF tokens in your templates * more easily: * * * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; * * * $secret = 'V8a5Z97e...'; * $csrfProvider = new DefaultCsrfProvider($secret); * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new CsrfExtension($csrfProvider)) * ->addExtension(new TemplatingExtension($engine, $csrfProvider, array( * 'FrameworkBundle:Form', * ))) * ->getFormFactory(); * * * @author Bernhard Schussek */ final class Forms { /** * Creates a form factory with the default configuration. * * @return FormFactoryInterface The form factory. */ public static function createFormFactory() { return self::createFormFactoryBuilder()->getFormFactory(); } /** * Creates a form factory builder with the default configuration. * * @return FormFactoryBuilderInterface The form factory builder. */ public static function createFormFactoryBuilder() { $builder = new FormFactoryBuilder(); $builder->addExtension(new CoreExtension()); return $builder; } /** * This class cannot be instantiated. */ private function __construct() { } } PK!\F1Symfony/Component/Security/Acl/Voter/AclVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Voter; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Acl\Exception\NoAceFoundException; use Symfony\Component\Security\Acl\Exception\AclNotFoundException; use Symfony\Component\Security\Acl\Model\AclProviderInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Permission\PermissionMapInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; /** * This voter can be used as a base class for implementing your own permissions. * * @author Johannes M. Schmitt */ class AclVoter implements VoterInterface { private $aclProvider; private $permissionMap; private $objectIdentityRetrievalStrategy; private $securityIdentityRetrievalStrategy; private $allowIfObjectIdentityUnavailable; private $logger; public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy, PermissionMapInterface $permissionMap, LoggerInterface $logger = null, $allowIfObjectIdentityUnavailable = true) { $this->aclProvider = $aclProvider; $this->permissionMap = $permissionMap; $this->objectIdentityRetrievalStrategy = $oidRetrievalStrategy; $this->securityIdentityRetrievalStrategy = $sidRetrievalStrategy; $this->logger = $logger; $this->allowIfObjectIdentityUnavailable = $allowIfObjectIdentityUnavailable; } public function supportsAttribute($attribute) { return $this->permissionMap->contains($attribute); } public function vote(TokenInterface $token, $object, array $attributes) { foreach ($attributes as $attribute) { if (null === $masks = $this->permissionMap->getMasks($attribute, $object)) { continue; } if (null === $object) { if (null !== $this->logger) { $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain')); } return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN; } elseif ($object instanceof FieldVote) { $field = $object->getField(); $object = $object->getDomainObject(); } else { $field = null; } if ($object instanceof ObjectIdentityInterface) { $oid = $object; } elseif (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) { if (null !== $this->logger) { $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain')); } return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN; } if (!$this->supportsClass($oid->getType())) { return self::ACCESS_ABSTAIN; } $sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token); try { $acl = $this->aclProvider->findAcl($oid, $sids); if (null === $field && $acl->isGranted($masks, $sids, false)) { if (null !== $this->logger) { $this->logger->debug('ACL found, permission granted. Voting to grant access'); } return self::ACCESS_GRANTED; } elseif (null !== $field && $acl->isFieldGranted($field, $masks, $sids, false)) { if (null !== $this->logger) { $this->logger->debug('ACL found, permission granted. Voting to grant access'); } return self::ACCESS_GRANTED; } if (null !== $this->logger) { $this->logger->debug('ACL found, insufficient permissions. Voting to deny access.'); } return self::ACCESS_DENIED; } catch (AclNotFoundException $noAcl) { if (null !== $this->logger) { $this->logger->debug('No ACL found for the object identity. Voting to deny access.'); } return self::ACCESS_DENIED; } catch (NoAceFoundException $noAce) { if (null !== $this->logger) { $this->logger->debug('ACL found, no ACE applicable. Voting to deny access.'); } return self::ACCESS_DENIED; } } // no attribute was supported return self::ACCESS_ABSTAIN; } /** * You can override this method when writing a voter for a specific domain * class. * * @param string $class The class name * * @return Boolean */ public function supportsClass($class) { return true; } } PK!\! HH2Symfony/Component/Security/Acl/Voter/FieldVote.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Voter; /** * This class is a lightweight wrapper around field vote requests which does * not violate any interface contracts. * * @author Johannes M. Schmitt */ class FieldVote { private $domainObject; private $field; public function __construct($domainObject, $field) { $this->domainObject = $domainObject; $this->field = $field; } public function getDomainObject() { return $this->domainObject; } public function getField() { return $this->field; } } PK!P͡ASymfony/Component/Security/Acl/Exception/AclNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when we cannot locate an ACL for a passed * ObjectIdentity implementation. * * @author Johannes M. Schmitt */ class AclNotFoundException extends Exception { } PK!kq6Symfony/Component/Security/Acl/Exception/Exception.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * Base ACL exception * * @author Johannes M. Schmitt */ class Exception extends \Exception { } PK!WLSymfony/Component/Security/Acl/Exception/ConcurrentModificationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown whenever you change shared properties of more than * one ACL of the same class type concurrently. * * @author Johannes M. Schmitt */ class ConcurrentModificationException extends Exception { } PK!OISymfony/Component/Security/Acl/Exception/InvalidDomainObjectException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when ObjectIdentity fails to construct an object * identity from the passed domain object. * * @author Johannes M. Schmitt */ class InvalidDomainObjectException extends Exception { } PK!]_""ESymfony/Component/Security/Acl/Exception/NotAllAclsFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when you have requested ACLs for multiple object * identities, but the AclProvider implementation failed to find ACLs for all * identities. * * This exception contains the partial result. * * @author Johannes M. Schmitt */ class NotAllAclsFoundException extends AclNotFoundException { private $partialResult; /** * Sets the partial result * * @param \SplObjectStorage $result */ public function setPartialResult(\SplObjectStorage $result) { $this->partialResult = $result; } /** * Returns the partial result * * @return \SplObjectStorage */ public function getPartialResult() { return $this->partialResult; } } PK!Bl@Symfony/Component/Security/Acl/Exception/NoAceFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when we cannot locate an ACE that matches the * combination of permission masks and security identities. * * @author Johannes M. Schmitt */ class NoAceFoundException extends Exception { public function __construct() { parent::__construct('No applicable ACE was found.'); } } PK![zBSymfony/Component/Security/Acl/Exception/SidNotLoadedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when ACEs for an SID are requested which has not * been loaded from the database. * * @author Johannes M. Schmitt */ class SidNotLoadedException extends Exception { } PK!5  FSymfony/Component/Security/Acl/Exception/AclAlreadyExistsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Exception; /** * This exception is thrown when someone tries to create an ACL for an object * identity that already has one. * * @author Johannes M. Schmitt */ class AclAlreadyExistsException extends Exception { } PK!tŐ:Symfony/Component/Security/Acl/Dbal/MutableAclProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Dbal; use Doctrine\Common\PropertyChangedListener; use Doctrine\DBAL\Driver\Connection; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException; use Symfony\Component\Security\Acl\Exception\ConcurrentModificationException; use Symfony\Component\Security\Acl\Model\AclCacheInterface; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; use Symfony\Component\Security\Acl\Model\MutableAclInterface; use Symfony\Component\Security\Acl\Model\MutableAclProviderInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * An implementation of the MutableAclProviderInterface using Doctrine DBAL. * * @author Johannes M. Schmitt */ class MutableAclProvider extends AclProvider implements MutableAclProviderInterface, PropertyChangedListener { private $propertyChanges; /** * {@inheritDoc} */ public function __construct(Connection $connection, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $options, AclCacheInterface $cache = null) { parent::__construct($connection, $permissionGrantingStrategy, $options, $cache); $this->propertyChanges = new \SplObjectStorage(); } /** * {@inheritDoc} */ public function createAcl(ObjectIdentityInterface $oid) { if (false !== $this->retrieveObjectIdentityPrimaryKey($oid)) { throw new AclAlreadyExistsException(sprintf('%s is already associated with an ACL.', $oid)); } $this->connection->beginTransaction(); try { $this->createObjectIdentity($oid); $pk = $this->retrieveObjectIdentityPrimaryKey($oid); $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $pk)); $this->connection->commit(); } catch (\Exception $failed) { $this->connection->rollBack(); throw $failed; } // re-read the ACL from the database to ensure proper caching, etc. return $this->findAcl($oid); } /** * {@inheritDoc} */ public function deleteAcl(ObjectIdentityInterface $oid) { $this->connection->beginTransaction(); try { foreach ($this->findChildren($oid, true) as $childOid) { $this->deleteAcl($childOid); } $oidPK = $this->retrieveObjectIdentityPrimaryKey($oid); $this->deleteAccessControlEntries($oidPK); $this->deleteObjectIdentityRelations($oidPK); $this->deleteObjectIdentity($oidPK); $this->connection->commit(); } catch (\Exception $failed) { $this->connection->rollBack(); throw $failed; } // evict the ACL from the in-memory identity map if (isset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()])) { $this->propertyChanges->offsetUnset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()]); unset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()]); } // evict the ACL from any caches if (null !== $this->cache) { $this->cache->evictFromCacheByIdentity($oid); } } /** * {@inheritDoc} */ public function findAcls(array $oids, array $sids = array()) { $result = parent::findAcls($oids, $sids); foreach ($result as $oid) { $acl = $result->offsetGet($oid); if (false === $this->propertyChanges->contains($acl) && $acl instanceof MutableAclInterface) { $acl->addPropertyChangedListener($this); $this->propertyChanges->attach($acl, array()); } $parentAcl = $acl->getParentAcl(); while (null !== $parentAcl) { if (false === $this->propertyChanges->contains($parentAcl) && $acl instanceof MutableAclInterface) { $parentAcl->addPropertyChangedListener($this); $this->propertyChanges->attach($parentAcl, array()); } $parentAcl = $parentAcl->getParentAcl(); } } return $result; } /** * Implementation of PropertyChangedListener * * This allows us to keep track of which values have been changed, so we don't * have to do a full introspection when ->updateAcl() is called. * * @param mixed $sender * @param string $propertyName * @param mixed $oldValue * @param mixed $newValue * * @throws \InvalidArgumentException */ public function propertyChanged($sender, $propertyName, $oldValue, $newValue) { if (!$sender instanceof MutableAclInterface && !$sender instanceof EntryInterface) { throw new \InvalidArgumentException('$sender must be an instance of MutableAclInterface, or EntryInterface.'); } if ($sender instanceof EntryInterface) { if (null === $sender->getId()) { return; } $ace = $sender; $sender = $ace->getAcl(); } else { $ace = null; } if (false === $this->propertyChanges->contains($sender)) { throw new \InvalidArgumentException('$sender is not being tracked by this provider.'); } $propertyChanges = $this->propertyChanges->offsetGet($sender); if (null === $ace) { if (isset($propertyChanges[$propertyName])) { $oldValue = $propertyChanges[$propertyName][0]; if ($oldValue === $newValue) { unset($propertyChanges[$propertyName]); } else { $propertyChanges[$propertyName] = array($oldValue, $newValue); } } else { $propertyChanges[$propertyName] = array($oldValue, $newValue); } } else { if (!isset($propertyChanges['aces'])) { $propertyChanges['aces'] = new \SplObjectStorage(); } $acePropertyChanges = $propertyChanges['aces']->contains($ace)? $propertyChanges['aces']->offsetGet($ace) : array(); if (isset($acePropertyChanges[$propertyName])) { $oldValue = $acePropertyChanges[$propertyName][0]; if ($oldValue === $newValue) { unset($acePropertyChanges[$propertyName]); } else { $acePropertyChanges[$propertyName] = array($oldValue, $newValue); } } else { $acePropertyChanges[$propertyName] = array($oldValue, $newValue); } if (count($acePropertyChanges) > 0) { $propertyChanges['aces']->offsetSet($ace, $acePropertyChanges); } else { $propertyChanges['aces']->offsetUnset($ace); if (0 === count($propertyChanges['aces'])) { unset($propertyChanges['aces']); } } } $this->propertyChanges->offsetSet($sender, $propertyChanges); } /** * {@inheritDoc} */ public function updateAcl(MutableAclInterface $acl) { if (!$this->propertyChanges->contains($acl)) { throw new \InvalidArgumentException('$acl is not tracked by this provider.'); } $propertyChanges = $this->propertyChanges->offsetGet($acl); // check if any changes were made to this ACL if (0 === count($propertyChanges)) { return; } $sets = $sharedPropertyChanges = array(); $this->connection->beginTransaction(); try { if (isset($propertyChanges['entriesInheriting'])) { $sets[] = 'entries_inheriting = '.$this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['entriesInheriting'][1]); } if (isset($propertyChanges['parentAcl'])) { if (null === $propertyChanges['parentAcl'][1]) { $sets[] = 'parent_object_identity_id = NULL'; } else { $sets[] = 'parent_object_identity_id = '.intval($propertyChanges['parentAcl'][1]->getId()); } $this->regenerateAncestorRelations($acl); $childAcls = $this->findAcls($this->findChildren($acl->getObjectIdentity(), false)); foreach ($childAcls as $childOid) { $this->regenerateAncestorRelations($childAcls[$childOid]); } } // check properties for deleted, and created ACEs, and perform deletions // we need to perfom deletions before updating existing ACEs, in order to // preserve uniqueness of the order field if (isset($propertyChanges['classAces'])) { $this->updateOldAceProperty('classAces', $propertyChanges['classAces']); } if (isset($propertyChanges['classFieldAces'])) { $this->updateOldFieldAceProperty('classFieldAces', $propertyChanges['classFieldAces']); } if (isset($propertyChanges['objectAces'])) { $this->updateOldAceProperty('objectAces', $propertyChanges['objectAces']); } if (isset($propertyChanges['objectFieldAces'])) { $this->updateOldFieldAceProperty('objectFieldAces', $propertyChanges['objectFieldAces']); } // this includes only updates of existing ACEs, but neither the creation, nor // the deletion of ACEs; these are tracked by changes to the ACL's respective // properties (classAces, classFieldAces, objectAces, objectFieldAces) if (isset($propertyChanges['aces'])) { $this->updateAces($propertyChanges['aces']); } // check properties for deleted, and created ACEs, and perform creations if (isset($propertyChanges['classAces'])) { $this->updateNewAceProperty('classAces', $propertyChanges['classAces']); $sharedPropertyChanges['classAces'] = $propertyChanges['classAces']; } if (isset($propertyChanges['classFieldAces'])) { $this->updateNewFieldAceProperty('classFieldAces', $propertyChanges['classFieldAces']); $sharedPropertyChanges['classFieldAces'] = $propertyChanges['classFieldAces']; } if (isset($propertyChanges['objectAces'])) { $this->updateNewAceProperty('objectAces', $propertyChanges['objectAces']); } if (isset($propertyChanges['objectFieldAces'])) { $this->updateNewFieldAceProperty('objectFieldAces', $propertyChanges['objectFieldAces']); } // if there have been changes to shared properties, we need to synchronize other // ACL instances for object identities of the same type that are already in-memory if (count($sharedPropertyChanges) > 0) { $classAcesProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Acl', 'classAces'); $classAcesProperty->setAccessible(true); $classFieldAcesProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Acl', 'classFieldAces'); $classFieldAcesProperty->setAccessible(true); foreach ($this->loadedAcls[$acl->getObjectIdentity()->getType()] as $sameTypeAcl) { if (isset($sharedPropertyChanges['classAces'])) { if ($acl !== $sameTypeAcl && $classAcesProperty->getValue($sameTypeAcl) !== $sharedPropertyChanges['classAces'][0]) { throw new ConcurrentModificationException('The "classAces" property has been modified concurrently.'); } $classAcesProperty->setValue($sameTypeAcl, $sharedPropertyChanges['classAces'][1]); } if (isset($sharedPropertyChanges['classFieldAces'])) { if ($acl !== $sameTypeAcl && $classFieldAcesProperty->getValue($sameTypeAcl) !== $sharedPropertyChanges['classFieldAces'][0]) { throw new ConcurrentModificationException('The "classFieldAces" property has been modified concurrently.'); } $classFieldAcesProperty->setValue($sameTypeAcl, $sharedPropertyChanges['classFieldAces'][1]); } } } // persist any changes to the acl_object_identities table if (count($sets) > 0) { $this->connection->executeQuery($this->getUpdateObjectIdentitySql($acl->getId(), $sets)); } $this->connection->commit(); } catch (\Exception $failed) { $this->connection->rollBack(); throw $failed; } $this->propertyChanges->offsetSet($acl, array()); if (null !== $this->cache) { if (count($sharedPropertyChanges) > 0) { // FIXME: Currently, there is no easy way to clear the cache for ACLs // of a certain type. The problem here is that we need to make // sure to clear the cache of all child ACLs as well, and these // child ACLs might be of a different class type. $this->cache->clearCache(); } else { // if there are no shared property changes, it's sufficient to just delete // the cache for this ACL $this->cache->evictFromCacheByIdentity($acl->getObjectIdentity()); foreach ($this->findChildren($acl->getObjectIdentity()) as $childOid) { $this->cache->evictFromCacheByIdentity($childOid); } } } } /** * Constructs the SQL for deleting access control entries. * * @param integer $oidPK * @return string */ protected function getDeleteAccessControlEntriesSql($oidPK) { return sprintf( 'DELETE FROM %s WHERE object_identity_id = %d', $this->options['entry_table_name'], $oidPK ); } /** * Constructs the SQL for deleting a specific ACE. * * @param integer $acePK * @return string */ protected function getDeleteAccessControlEntrySql($acePK) { return sprintf( 'DELETE FROM %s WHERE id = %d', $this->options['entry_table_name'], $acePK ); } /** * Constructs the SQL for deleting an object identity. * * @param integer $pk * @return string */ protected function getDeleteObjectIdentitySql($pk) { return sprintf( 'DELETE FROM %s WHERE id = %d', $this->options['oid_table_name'], $pk ); } /** * Constructs the SQL for deleting relation entries. * * @param integer $pk * @return string */ protected function getDeleteObjectIdentityRelationsSql($pk) { return sprintf( 'DELETE FROM %s WHERE object_identity_id = %d', $this->options['oid_ancestors_table_name'], $pk ); } /** * Constructs the SQL for inserting an ACE. * * @param integer $classId * @param integer|null $objectIdentityId * @param string|null $field * @param integer $aceOrder * @param integer $securityIdentityId * @param string $strategy * @param integer $mask * @param Boolean $granting * @param Boolean $auditSuccess * @param Boolean $auditFailure * @return string */ protected function getInsertAccessControlEntrySql($classId, $objectIdentityId, $field, $aceOrder, $securityIdentityId, $strategy, $mask, $granting, $auditSuccess, $auditFailure) { $query = <<options['entry_table_name'], $classId, null === $objectIdentityId? 'NULL' : intval($objectIdentityId), null === $field? 'NULL' : $this->connection->quote($field), $aceOrder, $securityIdentityId, $mask, $this->connection->getDatabasePlatform()->convertBooleans($granting), $this->connection->quote($strategy), $this->connection->getDatabasePlatform()->convertBooleans($auditSuccess), $this->connection->getDatabasePlatform()->convertBooleans($auditFailure) ); } /** * Constructs the SQL for inserting a new class type. * * @param string $classType * @return string */ protected function getInsertClassSql($classType) { return sprintf( 'INSERT INTO %s (class_type) VALUES (%s)', $this->options['class_table_name'], $this->connection->quote($classType) ); } /** * Constructs the SQL for inserting a relation entry. * * @param integer $objectIdentityId * @param integer $ancestorId * @return string */ protected function getInsertObjectIdentityRelationSql($objectIdentityId, $ancestorId) { return sprintf( 'INSERT INTO %s (object_identity_id, ancestor_id) VALUES (%d, %d)', $this->options['oid_ancestors_table_name'], $objectIdentityId, $ancestorId ); } /** * Constructs the SQL for inserting an object identity. * * @param string $identifier * @param integer $classId * @param Boolean $entriesInheriting * @return string */ protected function getInsertObjectIdentitySql($identifier, $classId, $entriesInheriting) { $query = <<options['oid_table_name'], $classId, $this->connection->quote($identifier), $this->connection->getDatabasePlatform()->convertBooleans($entriesInheriting) ); } /** * Constructs the SQL for inserting a security identity. * * @param SecurityIdentityInterface $sid * @throws \InvalidArgumentException * @return string */ protected function getInsertSecurityIdentitySql(SecurityIdentityInterface $sid) { if ($sid instanceof UserSecurityIdentity) { $identifier = $sid->getClass().'-'.$sid->getUsername(); $username = true; } elseif ($sid instanceof RoleSecurityIdentity) { $identifier = $sid->getRole(); $username = false; } else { throw new \InvalidArgumentException('$sid must either be an instance of UserSecurityIdentity, or RoleSecurityIdentity.'); } return sprintf( 'INSERT INTO %s (identifier, username) VALUES (%s, %s)', $this->options['sid_table_name'], $this->connection->quote($identifier), $this->connection->getDatabasePlatform()->convertBooleans($username) ); } /** * Constructs the SQL for selecting an ACE. * * @param integer $classId * @param integer $oid * @param string $field * @param integer $order * @return string */ protected function getSelectAccessControlEntryIdSql($classId, $oid, $field, $order) { return sprintf( 'SELECT id FROM %s WHERE class_id = %d AND %s AND %s AND ace_order = %d', $this->options['entry_table_name'], $classId, null === $oid ? $this->connection->getDatabasePlatform()->getIsNullExpression('object_identity_id') : 'object_identity_id = '.intval($oid), null === $field ? $this->connection->getDatabasePlatform()->getIsNullExpression('field_name') : 'field_name = '.$this->connection->quote($field), $order ); } /** * Constructs the SQL for selecting the primary key associated with * the passed class type. * * @param string $classType * @return string */ protected function getSelectClassIdSql($classType) { return sprintf( 'SELECT id FROM %s WHERE class_type = %s', $this->options['class_table_name'], $this->connection->quote($classType) ); } /** * Constructs the SQL for selecting the primary key of a security identity. * * @param SecurityIdentityInterface $sid * @throws \InvalidArgumentException * @return string */ protected function getSelectSecurityIdentityIdSql(SecurityIdentityInterface $sid) { if ($sid instanceof UserSecurityIdentity) { $identifier = $sid->getClass().'-'.$sid->getUsername(); $username = true; } elseif ($sid instanceof RoleSecurityIdentity) { $identifier = $sid->getRole(); $username = false; } else { throw new \InvalidArgumentException('$sid must either be an instance of UserSecurityIdentity, or RoleSecurityIdentity.'); } return sprintf( 'SELECT id FROM %s WHERE identifier = %s AND username = %s', $this->options['sid_table_name'], $this->connection->quote($identifier), $this->connection->getDatabasePlatform()->convertBooleans($username) ); } /** * Constructs the SQL for updating an object identity. * * @param integer $pk * @param array $changes * @throws \InvalidArgumentException * @return string */ protected function getUpdateObjectIdentitySql($pk, array $changes) { if (0 === count($changes)) { throw new \InvalidArgumentException('There are no changes.'); } return sprintf( 'UPDATE %s SET %s WHERE id = %d', $this->options['oid_table_name'], implode(', ', $changes), $pk ); } /** * Constructs the SQL for updating an ACE. * * @param integer $pk * @param array $sets * @throws \InvalidArgumentException * @return string */ protected function getUpdateAccessControlEntrySql($pk, array $sets) { if (0 === count($sets)) { throw new \InvalidArgumentException('There are no changes.'); } return sprintf( 'UPDATE %s SET %s WHERE id = %d', $this->options['entry_table_name'], implode(', ', $sets), $pk ); } /** * Creates the ACL for the passed object identity * * @param ObjectIdentityInterface $oid */ private function createObjectIdentity(ObjectIdentityInterface $oid) { $classId = $this->createOrRetrieveClassId($oid->getType()); $this->connection->executeQuery($this->getInsertObjectIdentitySql($oid->getIdentifier(), $classId, true)); } /** * Returns the primary key for the passed class type. * * If the type does not yet exist in the database, it will be created. * * @param string $classType * @return integer */ private function createOrRetrieveClassId($classType) { if (false !== $id = $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn()) { return $id; } $this->connection->executeQuery($this->getInsertClassSql($classType)); return $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn(); } /** * Returns the primary key for the passed security identity. * * If the security identity does not yet exist in the database, it will be * created. * * @param SecurityIdentityInterface $sid * @return integer */ private function createOrRetrieveSecurityIdentityId(SecurityIdentityInterface $sid) { if (false !== $id = $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn()) { return $id; } $this->connection->executeQuery($this->getInsertSecurityIdentitySql($sid)); return $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn(); } /** * Deletes all ACEs for the given object identity primary key. * * @param integer $oidPK */ private function deleteAccessControlEntries($oidPK) { $this->connection->executeQuery($this->getDeleteAccessControlEntriesSql($oidPK)); } /** * Deletes the object identity from the database. * * @param integer $pk */ private function deleteObjectIdentity($pk) { $this->connection->executeQuery($this->getDeleteObjectIdentitySql($pk)); } /** * Deletes all entries from the relations table from the database. * * @param integer $pk */ private function deleteObjectIdentityRelations($pk) { $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk)); } /** * This regenerates the ancestor table which is used for fast read access. * * @param AclInterface $acl */ private function regenerateAncestorRelations(AclInterface $acl) { $pk = $acl->getId(); $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk)); $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $pk)); $parentAcl = $acl->getParentAcl(); while (null !== $parentAcl) { $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $parentAcl->getId())); $parentAcl = $parentAcl->getParentAcl(); } } /** * This processes new entries changes on an ACE related property (classFieldAces, or objectFieldAces). * * @param string $name * @param array $changes */ private function updateNewFieldAceProperty($name, array $changes) { $sids = new \SplObjectStorage(); $classIds = new \SplObjectStorage(); $currentIds = array(); foreach ($changes[1] as $field => $new) { for ($i=0,$c=count($new); $i<$c; $i++) { $ace = $new[$i]; if (null === $ace->getId()) { if ($sids->contains($ace->getSecurityIdentity())) { $sid = $sids->offsetGet($ace->getSecurityIdentity()); } else { $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity()); } $oid = $ace->getAcl()->getObjectIdentity(); if ($classIds->contains($oid)) { $classId = $classIds->offsetGet($oid); } else { $classId = $this->createOrRetrieveClassId($oid->getType()); } $objectIdentityId = $name === 'classFieldAces' ? null : $ace->getAcl()->getId(); $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, $field, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure())); $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, $field, $i))->fetchColumn(); $this->loadedAces[$aceId] = $ace; $aceIdProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'id'); $aceIdProperty->setAccessible(true); $aceIdProperty->setValue($ace, intval($aceId)); } else { $currentIds[$ace->getId()] = true; } } } } /** * This process old entries changes on an ACE related property (classFieldAces, or objectFieldAces). * * @param string $name * @param array $changes */ private function updateOldFieldAceProperty($ane, array $changes) { $currentIds = array(); foreach ($changes[1] as $field => $new) { for ($i = 0, $c = count($new); $i < $c; $i++) { $ace = $new[$i]; if (null !== $ace->getId()) { $currentIds[$ace->getId()] = true; } } } foreach ($changes[0] as $old) { for ($i = 0, $c = count($old); $i < $c; $i++) { $ace = $old[$i]; if (!isset($currentIds[$ace->getId()])) { $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId())); unset($this->loadedAces[$ace->getId()]); } } } } /** * This processes new entries changes on an ACE related property (classAces, or objectAces). * * @param string $name * @param array $changes */ private function updateNewAceProperty($name, array $changes) { list($old, $new) = $changes; $sids = new \SplObjectStorage(); $classIds = new \SplObjectStorage(); $currentIds = array(); for ($i=0,$c=count($new); $i<$c; $i++) { $ace = $new[$i]; if (null === $ace->getId()) { if ($sids->contains($ace->getSecurityIdentity())) { $sid = $sids->offsetGet($ace->getSecurityIdentity()); } else { $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity()); } $oid = $ace->getAcl()->getObjectIdentity(); if ($classIds->contains($oid)) { $classId = $classIds->offsetGet($oid); } else { $classId = $this->createOrRetrieveClassId($oid->getType()); } $objectIdentityId = $name === 'classAces' ? null : $ace->getAcl()->getId(); $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, null, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure())); $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, null, $i))->fetchColumn(); $this->loadedAces[$aceId] = $ace; $aceIdProperty = new \ReflectionProperty($ace, 'id'); $aceIdProperty->setAccessible(true); $aceIdProperty->setValue($ace, intval($aceId)); } else { $currentIds[$ace->getId()] = true; } } } /** * This processes old entries changes on an ACE related property (classAces, or objectAces). * * @param string $name * @param array $changes */ private function updateOldAceProperty($name, array $changes) { list($old, $new) = $changes; $currentIds = array(); for ($i=0,$c=count($new); $i<$c; $i++) { $ace = $new[$i]; if (null !== $ace->getId()) { $currentIds[$ace->getId()] = true; } } for ($i = 0, $c = count($old); $i < $c; $i++) { $ace = $old[$i]; if (!isset($currentIds[$ace->getId()])) { $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId())); unset($this->loadedAces[$ace->getId()]); } } } /** * Persists the changes which were made to ACEs to the database. * * @param \SplObjectStorage $aces */ private function updateAces(\SplObjectStorage $aces) { foreach ($aces as $ace) { $this->updateAce($aces, $ace); } } private function updateAce(\SplObjectStorage $aces, $ace) { $propertyChanges = $aces->offsetGet($ace); $sets = array(); if (isset($propertyChanges['aceOrder']) && $propertyChanges['aceOrder'][1] > $propertyChanges['aceOrder'][0] && $propertyChanges == $aces->offsetGet($ace)) { $aces->next(); if ($aces->valid()) { $this->updateAce($aces, $aces->current()); } } if (isset($propertyChanges['mask'])) { $sets[] = sprintf('mask = %d', $propertyChanges['mask'][1]); } if (isset($propertyChanges['strategy'])) { $sets[] = sprintf('granting_strategy = %s', $this->connection->quote($propertyChanges['strategy'])); } if (isset($propertyChanges['aceOrder'])) { $sets[] = sprintf('ace_order = %d', $propertyChanges['aceOrder'][1]); } if (isset($propertyChanges['auditSuccess'])) { $sets[] = sprintf('audit_success = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditSuccess'][1])); } if (isset($propertyChanges['auditFailure'])) { $sets[] = sprintf('audit_failure = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditFailure'][1])); } $this->connection->executeQuery($this->getUpdateAccessControlEntrySql($ace->getId(), $sets)); } } PK!^+f+f3Symfony/Component/Security/Acl/Dbal/AclProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Dbal; use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\Statement; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Domain\Acl; use Symfony\Component\Security\Acl\Domain\Entry; use Symfony\Component\Security\Acl\Domain\FieldEntry; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Exception\AclNotFoundException; use Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException; use Symfony\Component\Security\Acl\Model\AclCacheInterface; use Symfony\Component\Security\Acl\Model\AclProviderInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; /** * An ACL provider implementation. * * This provider assumes that all ACLs share the same PermissionGrantingStrategy. * * @author Johannes M. Schmitt */ class AclProvider implements AclProviderInterface { const MAX_BATCH_SIZE = 30; protected $cache; protected $connection; protected $loadedAces = array(); protected $loadedAcls = array(); protected $options; private $permissionGrantingStrategy; /** * Constructor. * * @param Connection $connection * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy * @param array $options * @param AclCacheInterface $cache */ public function __construct(Connection $connection, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $options, AclCacheInterface $cache = null) { $this->cache = $cache; $this->connection = $connection; $this->options = $options; $this->permissionGrantingStrategy = $permissionGrantingStrategy; } /** * {@inheritDoc} */ public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false) { $sql = $this->getFindChildrenSql($parentOid, $directChildrenOnly); $children = array(); foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) { $children[] = new ObjectIdentity($data['object_identifier'], $data['class_type']); } return $children; } /** * {@inheritDoc} */ public function findAcl(ObjectIdentityInterface $oid, array $sids = array()) { return $this->findAcls(array($oid), $sids)->offsetGet($oid); } /** * {@inheritDoc} */ public function findAcls(array $oids, array $sids = array()) { $result = new \SplObjectStorage(); $currentBatch = array(); $oidLookup = array(); for ($i=0,$c=count($oids); $i<$c; $i++) { $oid = $oids[$i]; $oidLookupKey = $oid->getIdentifier().$oid->getType(); $oidLookup[$oidLookupKey] = $oid; $aclFound = false; // check if result already contains an ACL if ($result->contains($oid)) { $aclFound = true; } // check if this ACL has already been hydrated if (!$aclFound && isset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()])) { $acl = $this->loadedAcls[$oid->getType()][$oid->getIdentifier()]; if (!$acl->isSidLoaded($sids)) { // FIXME: we need to load ACEs for the missing SIDs. This is never // reached by the default implementation, since we do not // filter by SID throw new \RuntimeException('This is not supported by the default implementation.'); } else { $result->attach($oid, $acl); $aclFound = true; } } // check if we can locate the ACL in the cache if (!$aclFound && null !== $this->cache) { $acl = $this->cache->getFromCacheByIdentity($oid); if (null !== $acl) { if ($acl->isSidLoaded($sids)) { // check if any of the parents has been loaded since we need to // ensure that there is only ever one ACL per object identity $parentAcl = $acl->getParentAcl(); while (null !== $parentAcl) { $parentOid = $parentAcl->getObjectIdentity(); if (isset($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()])) { $acl->setParentAcl($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()]); break; } else { $this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()] = $parentAcl; $this->updateAceIdentityMap($parentAcl); } $parentAcl = $parentAcl->getParentAcl(); } $this->loadedAcls[$oid->getType()][$oid->getIdentifier()] = $acl; $this->updateAceIdentityMap($acl); $result->attach($oid, $acl); $aclFound = true; } else { $this->cache->evictFromCacheByIdentity($oid); foreach ($this->findChildren($oid) as $childOid) { $this->cache->evictFromCacheByIdentity($childOid); } } } } // looks like we have to load the ACL from the database if (!$aclFound) { $currentBatch[] = $oid; } // Is it time to load the current batch? if ((self::MAX_BATCH_SIZE === count($currentBatch) || ($i + 1) === $c) && count($currentBatch) > 0) { try { $loadedBatch = $this->lookupObjectIdentities($currentBatch, $sids, $oidLookup); } catch (AclNotFoundException $aclNotFoundexception) { if ($result->count()) { $partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.'); $partialResultException->setPartialResult($result); throw $partialResultException; } else { throw $aclNotFoundexception; } } foreach ($loadedBatch as $loadedOid) { $loadedAcl = $loadedBatch->offsetGet($loadedOid); if (null !== $this->cache) { $this->cache->putInCache($loadedAcl); } if (isset($oidLookup[$loadedOid->getIdentifier().$loadedOid->getType()])) { $result->attach($loadedOid, $loadedAcl); } } $currentBatch = array(); } } // check that we got ACLs for all the identities foreach ($oids as $oid) { if (!$result->contains($oid)) { if (1 === count($oids)) { throw new AclNotFoundException(sprintf('No ACL found for %s.', $oid)); } $partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.'); $partialResultException->setPartialResult($result); throw $partialResultException; } } return $result; } /** * Constructs the query used for looking up object identities and associated * ACEs, and security identities. * * @param array $ancestorIds * @return string */ protected function getLookupSql(array $ancestorIds) { // FIXME: add support for filtering by sids (right now we select all sids) $sql = <<options['oid_table_name']} o INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id LEFT JOIN {$this->options['entry_table_name']} e ON ( e.class_id = o.class_id AND (e.object_identity_id = o.id OR {$this->connection->getDatabasePlatform()->getIsNullExpression('e.object_identity_id')}) ) LEFT JOIN {$this->options['sid_table_name']} s ON ( s.id = e.security_identity_id ) WHERE (o.id = SELECTCLAUSE; $sql .= implode(' OR o.id = ', $ancestorIds).')'; return $sql; } protected function getAncestorLookupSql(array $batch) { $sql = <<options['oid_table_name']} o INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id INNER JOIN {$this->options['oid_ancestors_table_name']} a ON a.object_identity_id = o.id WHERE ( SELECTCLAUSE; $types = array(); $count = count($batch); for ($i = 0; $i < $count; $i++) { if (!isset($types[$batch[$i]->getType()])) { $types[$batch[$i]->getType()] = true; // if there is more than one type we can safely break out of the // loop, because it is the differentiator factor on whether to // query for only one or more class types if (count($types) > 1) { break; } } } if (1 === count($types)) { $ids = array(); for ($i = 0; $i < $count; $i++) { $ids[] = $this->connection->quote($batch[$i]->getIdentifier()); } $sql .= sprintf( '(o.object_identifier IN (%s) AND c.class_type = %s)', implode(',', $ids), $this->connection->quote($batch[0]->getType()) ); } else { $where = '(o.object_identifier = %s AND c.class_type = %s)'; for ($i = 0; $i < $count; $i++) { $sql .= sprintf( $where, $this->connection->quote($batch[$i]->getIdentifier()), $this->connection->quote($batch[$i]->getType()) ); if ($i+1 < $count) { $sql .= ' OR '; } } } $sql .= ')'; return $sql; } /** * Constructs the SQL for retrieving child object identities for the given * object identities. * * @param ObjectIdentityInterface $oid * @param Boolean $directChildrenOnly * @return string */ protected function getFindChildrenSql(ObjectIdentityInterface $oid, $directChildrenOnly) { if (false === $directChildrenOnly) { $query = <<options['oid_table_name']} as o INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id INNER JOIN {$this->options['oid_ancestors_table_name']} as a ON a.object_identity_id = o.id WHERE a.ancestor_id = %d AND a.object_identity_id != a.ancestor_id FINDCHILDREN; } else { $query = <<options['oid_table_name']} as o INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id WHERE o.parent_object_identity_id = %d FINDCHILDREN; } return sprintf($query, $this->retrieveObjectIdentityPrimaryKey($oid)); } /** * Constructs the SQL for retrieving the primary key of the given object * identity. * * @param ObjectIdentityInterface $oid * @return string */ protected function getSelectObjectIdentityIdSql(ObjectIdentityInterface $oid) { $query = <<options['oid_table_name'], $this->options['class_table_name'], $this->connection->quote($oid->getIdentifier()), $this->connection->quote($oid->getType()) ); } /** * Returns the primary key of the passed object identity. * * @param ObjectIdentityInterface $oid * @return integer */ final protected function retrieveObjectIdentityPrimaryKey(ObjectIdentityInterface $oid) { return $this->connection->executeQuery($this->getSelectObjectIdentityIdSql($oid))->fetchColumn(); } /** * This method is called when an ACL instance is retrieved from the cache. * * @param AclInterface $acl */ private function updateAceIdentityMap(AclInterface $acl) { foreach (array('classAces', 'classFieldAces', 'objectAces', 'objectFieldAces') as $property) { $reflection = new \ReflectionProperty($acl, $property); $reflection->setAccessible(true); $value = $reflection->getValue($acl); if ('classAces' === $property || 'objectAces' === $property) { $this->doUpdateAceIdentityMap($value); } else { foreach ($value as $field => $aces) { $this->doUpdateAceIdentityMap($value[$field]); } } $reflection->setValue($acl, $value); $reflection->setAccessible(false); } } /** * Retrieves all the ids which need to be queried from the database * including the ids of parent ACLs. * * @param array $batch * * @return array */ private function getAncestorIds(array $batch) { $sql = $this->getAncestorLookupSql($batch); $ancestorIds = array(); foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) { // FIXME: skip ancestors which are cached $ancestorIds[] = $data['ancestor_id']; } return $ancestorIds; } /** * Does either overwrite the passed ACE, or saves it in the global identity * map to ensure every ACE only gets instantiated once. * * @param array &$aces */ private function doUpdateAceIdentityMap(array &$aces) { foreach ($aces as $index => $ace) { if (isset($this->loadedAces[$ace->getId()])) { $aces[$index] = $this->loadedAces[$ace->getId()]; } else { $this->loadedAces[$ace->getId()] = $ace; } } } /** * This method is called for object identities which could not be retrieved * from the cache, and for which thus a database query is required. * * @param array $batch * @param array $sids * @param array $oidLookup * * @return \SplObjectStorage mapping object identities to ACL instances * * @throws AclNotFoundException */ private function lookupObjectIdentities(array $batch, array $sids, array $oidLookup) { $ancestorIds = $this->getAncestorIds($batch); if (!$ancestorIds) { throw new AclNotFoundException('There is no ACL for the given object identity.'); } $sql = $this->getLookupSql($ancestorIds); $stmt = $this->connection->executeQuery($sql); return $this->hydrateObjectIdentities($stmt, $oidLookup, $sids); } /** * This method is called to hydrate ACLs and ACEs. * * This method was designed for performance; thus, a lot of code has been * inlined at the cost of readability, and maintainability. * * Keep in mind that changes to this method might severely reduce the * performance of the entire ACL system. * * @param Statement $stmt * @param array $oidLookup * @param array $sids * @throws \RuntimeException * @return \SplObjectStorage */ private function hydrateObjectIdentities(Statement $stmt, array $oidLookup, array $sids) { $parentIdToFill = new \SplObjectStorage(); $acls = $aces = $emptyArray = array(); $oidCache = $oidLookup; $result = new \SplObjectStorage(); $loadedAces =& $this->loadedAces; $loadedAcls =& $this->loadedAcls; $permissionGrantingStrategy = $this->permissionGrantingStrategy; // we need these to set protected properties on hydrated objects $aclReflection = new \ReflectionClass('Symfony\Component\Security\Acl\Domain\Acl'); $aclClassAcesProperty = $aclReflection->getProperty('classAces'); $aclClassAcesProperty->setAccessible(true); $aclClassFieldAcesProperty = $aclReflection->getProperty('classFieldAces'); $aclClassFieldAcesProperty->setAccessible(true); $aclObjectAcesProperty = $aclReflection->getProperty('objectAces'); $aclObjectAcesProperty->setAccessible(true); $aclObjectFieldAcesProperty = $aclReflection->getProperty('objectFieldAces'); $aclObjectFieldAcesProperty->setAccessible(true); $aclParentAclProperty = $aclReflection->getProperty('parentAcl'); $aclParentAclProperty->setAccessible(true); // fetchAll() consumes more memory than consecutive calls to fetch(), // but it is faster foreach ($stmt->fetchAll(\PDO::FETCH_NUM) as $data) { list($aclId, $objectIdentifier, $parentObjectIdentityId, $entriesInheriting, $classType, $aceId, $objectIdentityId, $fieldName, $aceOrder, $mask, $granting, $grantingStrategy, $auditSuccess, $auditFailure, $username, $securityIdentifier) = $data; // has the ACL been hydrated during this hydration cycle? if (isset($acls[$aclId])) { $acl = $acls[$aclId]; // has the ACL been hydrated during any previous cycle, or was possibly loaded // from cache? } elseif (isset($loadedAcls[$classType][$objectIdentifier])) { $acl = $loadedAcls[$classType][$objectIdentifier]; // keep reference in local array (saves us some hash calculations) $acls[$aclId] = $acl; // attach ACL to the result set; even though we do not enforce that every // object identity has only one instance, we must make sure to maintain // referential equality with the oids passed to findAcls() if (!isset($oidCache[$objectIdentifier.$classType])) { $oidCache[$objectIdentifier.$classType] = $acl->getObjectIdentity(); } $result->attach($oidCache[$objectIdentifier.$classType], $acl); // so, this hasn't been hydrated yet } else { // create object identity if we haven't done so yet $oidLookupKey = $objectIdentifier.$classType; if (!isset($oidCache[$oidLookupKey])) { $oidCache[$oidLookupKey] = new ObjectIdentity($objectIdentifier, $classType); } $acl = new Acl((integer) $aclId, $oidCache[$oidLookupKey], $permissionGrantingStrategy, $emptyArray, !!$entriesInheriting); // keep a local, and global reference to this ACL $loadedAcls[$classType][$objectIdentifier] = $acl; $acls[$aclId] = $acl; // try to fill in parent ACL, or defer until all ACLs have been hydrated if (null !== $parentObjectIdentityId) { if (isset($acls[$parentObjectIdentityId])) { $aclParentAclProperty->setValue($acl, $acls[$parentObjectIdentityId]); } else { $parentIdToFill->attach($acl, $parentObjectIdentityId); } } $result->attach($oidCache[$oidLookupKey], $acl); } // check if this row contains an ACE record if (null !== $aceId) { // have we already hydrated ACEs for this ACL? if (!isset($aces[$aclId])) { $aces[$aclId] = array($emptyArray, $emptyArray, $emptyArray, $emptyArray); } // has this ACE already been hydrated during a previous cycle, or // possible been loaded from cache? // It is important to only ever have one ACE instance per actual row since // some ACEs are shared between ACL instances if (!isset($loadedAces[$aceId])) { if (!isset($sids[$key = ($username?'1':'0').$securityIdentifier])) { if ($username) { $sids[$key] = new UserSecurityIdentity( substr($securityIdentifier, 1 + $pos = strpos($securityIdentifier, '-')), substr($securityIdentifier, 0, $pos) ); } else { $sids[$key] = new RoleSecurityIdentity($securityIdentifier); } } if (null === $fieldName) { $loadedAces[$aceId] = new Entry((integer) $aceId, $acl, $sids[$key], $grantingStrategy, (integer) $mask, !!$granting, !!$auditFailure, !!$auditSuccess); } else { $loadedAces[$aceId] = new FieldEntry((integer) $aceId, $acl, $fieldName, $sids[$key], $grantingStrategy, (integer) $mask, !!$granting, !!$auditFailure, !!$auditSuccess); } } $ace = $loadedAces[$aceId]; // assign ACE to the correct property if (null === $objectIdentityId) { if (null === $fieldName) { $aces[$aclId][0][$aceOrder] = $ace; } else { $aces[$aclId][1][$fieldName][$aceOrder] = $ace; } } else { if (null === $fieldName) { $aces[$aclId][2][$aceOrder] = $ace; } else { $aces[$aclId][3][$fieldName][$aceOrder] = $ace; } } } } // We do not sort on database level since we only want certain subsets to be sorted, // and we are going to read the entire result set anyway. // Sorting on DB level increases query time by an order of magnitude while it is // almost negligible when we use PHPs array sort functions. foreach ($aces as $aclId => $aceData) { $acl = $acls[$aclId]; ksort($aceData[0]); $aclClassAcesProperty->setValue($acl, $aceData[0]); foreach (array_keys($aceData[1]) as $fieldName) { ksort($aceData[1][$fieldName]); } $aclClassFieldAcesProperty->setValue($acl, $aceData[1]); ksort($aceData[2]); $aclObjectAcesProperty->setValue($acl, $aceData[2]); foreach (array_keys($aceData[3]) as $fieldName) { ksort($aceData[3][$fieldName]); } $aclObjectFieldAcesProperty->setValue($acl, $aceData[3]); } // fill-in parent ACLs where this hasn't been done yet cause the parent ACL was not // yet available $processed = 0; foreach ($parentIdToFill as $acl) { $parentId = $parentIdToFill->offsetGet($acl); // let's see if we have already hydrated this if (isset($acls[$parentId])) { $aclParentAclProperty->setValue($acl, $acls[$parentId]); $processed += 1; continue; } } // reset reflection changes $aclClassAcesProperty->setAccessible(false); $aclClassFieldAcesProperty->setAccessible(false); $aclObjectAcesProperty->setAccessible(false); $aclObjectFieldAcesProperty->setAccessible(false); $aclParentAclProperty->setAccessible(false); // this should never be true if the database integrity hasn't been compromised if ($processed < count($parentIdToFill)) { throw new \RuntimeException('Not all parent ids were populated. This implies an integrity problem.'); } return $result; } } PK!K V.Symfony/Component/Security/Acl/Dbal/Schema.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Dbal; use Doctrine\DBAL\Schema\Schema as BaseSchema; use Doctrine\DBAL\Connection; /** * The schema used for the ACL system. * * @author Johannes M. Schmitt */ final class Schema extends BaseSchema { protected $options; /** * Constructor * * @param array $options the names for tables * @param Connection $connection */ public function __construct(array $options, Connection $connection = null) { $schemaConfig = null === $connection ? null : $connection->getSchemaManager()->createSchemaConfig(); parent::__construct(array(), array(), $schemaConfig); $this->options = $options; $this->addClassTable(); $this->addSecurityIdentitiesTable(); $this->addObjectIdentitiesTable(); $this->addObjectIdentityAncestorsTable(); $this->addEntryTable(); } /** * Merges ACL schema with the given schema. * * @param BaseSchema $schema */ public function addToSchema(BaseSchema $schema) { foreach ($this->getTables() as $table) { $schema->_addTable($table); } foreach ($this->getSequences() as $sequence) { $schema->_addSequence($sequence); } } /** * Adds the class table to the schema */ protected function addClassTable() { $table = $this->createTable($this->options['class_table_name']); $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto')); $table->addColumn('class_type', 'string', array('length' => 200)); $table->setPrimaryKey(array('id')); $table->addUniqueIndex(array('class_type')); } /** * Adds the entry table to the schema */ protected function addEntryTable() { $table = $this->createTable($this->options['entry_table_name']); $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto')); $table->addColumn('class_id', 'integer', array('unsigned' => true)); $table->addColumn('object_identity_id', 'integer', array('unsigned' => true, 'notnull' => false)); $table->addColumn('field_name', 'string', array('length' => 50, 'notnull' => false)); $table->addColumn('ace_order', 'smallint', array('unsigned' => true)); $table->addColumn('security_identity_id', 'integer', array('unsigned' => true)); $table->addColumn('mask', 'integer'); $table->addColumn('granting', 'boolean'); $table->addColumn('granting_strategy', 'string', array('length' => 30)); $table->addColumn('audit_success', 'boolean'); $table->addColumn('audit_failure', 'boolean'); $table->setPrimaryKey(array('id')); $table->addUniqueIndex(array('class_id', 'object_identity_id', 'field_name', 'ace_order')); $table->addIndex(array('class_id', 'object_identity_id', 'security_identity_id')); $table->addForeignKeyConstraint($this->getTable($this->options['class_table_name']), array('class_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); $table->addForeignKeyConstraint($this->getTable($this->options['oid_table_name']), array('object_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); $table->addForeignKeyConstraint($this->getTable($this->options['sid_table_name']), array('security_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); } /** * Adds the object identity table to the schema */ protected function addObjectIdentitiesTable() { $table = $this->createTable($this->options['oid_table_name']); $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto')); $table->addColumn('class_id', 'integer', array('unsigned' => true)); $table->addColumn('object_identifier', 'string', array('length' => 100)); $table->addColumn('parent_object_identity_id', 'integer', array('unsigned' => true, 'notnull' => false)); $table->addColumn('entries_inheriting', 'boolean'); $table->setPrimaryKey(array('id')); $table->addUniqueIndex(array('object_identifier', 'class_id')); $table->addIndex(array('parent_object_identity_id')); $table->addForeignKeyConstraint($table, array('parent_object_identity_id'), array('id')); } /** * Adds the object identity relation table to the schema */ protected function addObjectIdentityAncestorsTable() { $table = $this->createTable($this->options['oid_ancestors_table_name']); $table->addColumn('object_identity_id', 'integer', array('unsigned' => true)); $table->addColumn('ancestor_id', 'integer', array('unsigned' => true)); $table->setPrimaryKey(array('object_identity_id', 'ancestor_id')); $oidTable = $this->getTable($this->options['oid_table_name']); $table->addForeignKeyConstraint($oidTable, array('object_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); $table->addForeignKeyConstraint($oidTable, array('ancestor_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE')); } /** * Adds the security identity table to the schema */ protected function addSecurityIdentitiesTable() { $table = $this->createTable($this->options['sid_table_name']); $table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto')); $table->addColumn('identifier', 'string', array('length' => 200)); $table->addColumn('username', 'boolean'); $table->setPrimaryKey(array('id')); $table->addUniqueIndex(array('identifier', 'username')); } } PK!NTA]]5Symfony/Component/Security/Acl/Domain/AuditLogger.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\AuditableEntryInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; use Symfony\Component\Security\Acl\Model\AuditLoggerInterface; /** * Base audit logger implementation * * @author Johannes M. Schmitt */ abstract class AuditLogger implements AuditLoggerInterface { /** * Performs some checks if logging was requested * * @param Boolean $granted * @param EntryInterface $ace */ public function logIfNeeded($granted, EntryInterface $ace) { if (!$ace instanceof AuditableEntryInterface) { return; } if ($granted && $ace->isAuditSuccess()) { $this->doLog($granted, $ace); } elseif (!$granted && $ace->isAuditFailure()) { $this->doLog($granted, $ace); } } /** * This method is only called when logging is needed * * @param Boolean $granted * @param EntryInterface $ace */ abstract protected function doLog($granted, EntryInterface $ace); } PK!.* * >Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Util\ClassUtils; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * A SecurityIdentity implementation used for actual users * * @author Johannes M. Schmitt */ final class UserSecurityIdentity implements SecurityIdentityInterface { private $username; private $class; /** * Constructor * * @param string $username the username representation * @param string $class the user's fully qualified class name * * @throws \InvalidArgumentException */ public function __construct($username, $class) { if (empty($username)) { throw new \InvalidArgumentException('$username must not be empty.'); } if (empty($class)) { throw new \InvalidArgumentException('$class must not be empty.'); } $this->username = (string) $username; $this->class = $class; } /** * Creates a user security identity from a UserInterface * * @param UserInterface $user * @return UserSecurityIdentity */ public static function fromAccount(UserInterface $user) { return new self($user->getUsername(), ClassUtils::getRealClass($user)); } /** * Creates a user security identity from a TokenInterface * * @param TokenInterface $token * @return UserSecurityIdentity */ public static function fromToken(TokenInterface $token) { $user = $token->getUser(); if ($user instanceof UserInterface) { return self::fromAccount($user); } return new self((string) $user, is_object($user) ? ClassUtils::getRealClass($user) : ClassUtils::getRealClass($token)); } /** * Returns the username * * @return string */ public function getUsername() { return $this->username; } /** * Returns the user's class name * * @return string */ public function getClass() { return $this->class; } /** * {@inheritDoc} */ public function equals(SecurityIdentityInterface $sid) { if (!$sid instanceof UserSecurityIdentity) { return false; } return $this->username === $sid->getUsername() && $this->class === $sid->getClass(); } /** * A textual representation of this security identity. * * This is not used for equality comparison, but only for debugging. * * @return string */ public function __toString() { return sprintf('UserSecurityIdentity(%s, %s)', $this->username, $this->class); } } PK!C3:Symfony/Component/Security/Acl/Domain/DoctrineAclCache.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Doctrine\Common\Cache\Cache; use Symfony\Component\Security\Acl\Model\AclCacheInterface; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; /** * This class is a wrapper around the actual cache implementation. * * @author Johannes M. Schmitt */ class DoctrineAclCache implements AclCacheInterface { const PREFIX = 'sf2_acl_'; private $cache; private $prefix; private $permissionGrantingStrategy; /** * Constructor * * @param Cache $cache * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy * @param string $prefix * * @throws \InvalidArgumentException */ public function __construct(Cache $cache, PermissionGrantingStrategyInterface $permissionGrantingStrategy, $prefix = self::PREFIX) { if (0 === strlen($prefix)) { throw new \InvalidArgumentException('$prefix cannot be empty.'); } $this->cache = $cache; $this->permissionGrantingStrategy = $permissionGrantingStrategy; $this->prefix = $prefix; } /** * {@inheritDoc} */ public function clearCache() { $this->cache->deleteByPrefix($this->prefix); } /** * {@inheritDoc} */ public function evictFromCacheById($aclId) { $lookupKey = $this->getAliasKeyForIdentity($aclId); if (!$this->cache->contains($lookupKey)) { return; } $key = $this->cache->fetch($lookupKey); if ($this->cache->contains($key)) { $this->cache->delete($key); } $this->cache->delete($lookupKey); } /** * {@inheritDoc} */ public function evictFromCacheByIdentity(ObjectIdentityInterface $oid) { $key = $this->getDataKeyByIdentity($oid); if (!$this->cache->contains($key)) { return; } $this->cache->delete($key); } /** * {@inheritDoc} */ public function getFromCacheById($aclId) { $lookupKey = $this->getAliasKeyForIdentity($aclId); if (!$this->cache->contains($lookupKey)) { return null; } $key = $this->cache->fetch($lookupKey); if (!$this->cache->contains($key)) { $this->cache->delete($lookupKey); return null; } return $this->unserializeAcl($this->cache->fetch($key)); } /** * {@inheritDoc} */ public function getFromCacheByIdentity(ObjectIdentityInterface $oid) { $key = $this->getDataKeyByIdentity($oid); if (!$this->cache->contains($key)) { return null; } return $this->unserializeAcl($this->cache->fetch($key)); } /** * {@inheritDoc} */ public function putInCache(AclInterface $acl) { if (null === $acl->getId()) { throw new \InvalidArgumentException('Transient ACLs cannot be cached.'); } if (null !== $parentAcl = $acl->getParentAcl()) { $this->putInCache($parentAcl); } $key = $this->getDataKeyByIdentity($acl->getObjectIdentity()); $this->cache->save($key, serialize($acl)); $this->cache->save($this->getAliasKeyForIdentity($acl->getId()), $key); } /** * Unserializes the ACL. * * @param string $serialized * @return AclInterface */ private function unserializeAcl($serialized) { $acl = unserialize($serialized); if (null !== $parentId = $acl->getParentAcl()) { $parentAcl = $this->getFromCacheById($parentId); if (null === $parentAcl) { return null; } $acl->setParentAcl($parentAcl); } $reflectionProperty = new \ReflectionProperty($acl, 'permissionGrantingStrategy'); $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($acl, $this->permissionGrantingStrategy); $reflectionProperty->setAccessible(false); $aceAclProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'acl'); $aceAclProperty->setAccessible(true); foreach ($acl->getObjectAces() as $ace) { $aceAclProperty->setValue($ace, $acl); } foreach ($acl->getClassAces() as $ace) { $aceAclProperty->setValue($ace, $acl); } $aceClassFieldProperty = new \ReflectionProperty($acl, 'classFieldAces'); $aceClassFieldProperty->setAccessible(true); foreach ($aceClassFieldProperty->getValue($acl) as $aces) { foreach ($aces as $ace) { $aceAclProperty->setValue($ace, $acl); } } $aceClassFieldProperty->setAccessible(false); $aceObjectFieldProperty = new \ReflectionProperty($acl, 'objectFieldAces'); $aceObjectFieldProperty->setAccessible(true); foreach ($aceObjectFieldProperty->getValue($acl) as $aces) { foreach ($aces as $ace) { $aceAclProperty->setValue($ace, $acl); } } $aceObjectFieldProperty->setAccessible(false); $aceAclProperty->setAccessible(false); return $acl; } /** * Returns the key for the object identity * * @param ObjectIdentityInterface $oid * @return string */ private function getDataKeyByIdentity(ObjectIdentityInterface $oid) { return $this->prefix.md5($oid->getType()).sha1($oid->getType()) .'_'.md5($oid->getIdentifier()).sha1($oid->getIdentifier()); } /** * Returns the alias key for the object identity key * * @param string $aclId * @return string */ private function getAliasKeyForIdentity($aclId) { return $this->prefix.$aclId; } } PK!(]DSymfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Exception\NoAceFoundException; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\AuditLoggerInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * The permission granting strategy to apply to the access control list. * * @author Johannes M. Schmitt */ class PermissionGrantingStrategy implements PermissionGrantingStrategyInterface { const EQUAL = 'equal'; const ALL = 'all'; const ANY = 'any'; private $auditLogger; /** * Sets the audit logger * * @param AuditLoggerInterface $auditLogger */ public function setAuditLogger(AuditLoggerInterface $auditLogger) { $this->auditLogger = $auditLogger; } /** * {@inheritDoc} */ public function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false) { try { try { $aces = $acl->getObjectAces(); if (!$aces) { throw new NoAceFoundException(); } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } catch (NoAceFoundException $noObjectAce) { $aces = $acl->getClassAces(); if (!$aces) { throw $noObjectAce; } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } } catch (NoAceFoundException $noClassAce) { if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) { return $parentAcl->isGranted($masks, $sids, $administrativeMode); } throw $noClassAce; } } /** * {@inheritDoc} */ public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false) { try { try { $aces = $acl->getObjectFieldAces($field); if (!$aces) { throw new NoAceFoundException(); } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } catch (NoAceFoundException $noObjectAces) { $aces = $acl->getClassFieldAces($field); if (!$aces) { throw $noObjectAces; } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } } catch (NoAceFoundException $noClassAces) { if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) { return $parentAcl->isFieldGranted($field, $masks, $sids, $administrativeMode); } throw $noClassAces; } } /** * Makes an authorization decision. * * The order of ACEs, and SIDs is significant; the order of permission masks * not so much. It is important to note that the more specific security * identities should be at the beginning of the SIDs array in order for this * strategy to produce intuitive authorization decisions. * * First, we will iterate over permissions, then over security identities. * For each combination of permission, and identity we will test the * available ACEs until we find one which is applicable. * * The first applicable ACE will make the ultimate decision for the * permission/identity combination. If it is granting, this method will return * true, if it is denying, the method will continue to check the next * permission/identity combination. * * This process is repeated until either a granting ACE is found, or no * permission/identity combinations are left. Finally, we will either throw * an NoAceFoundException, or deny access. * * @param AclInterface $acl * @param EntryInterface[] $aces An array of ACE to check against * @param array $masks An array of permission masks * @param SecurityIdentityInterface[] $sids An array of SecurityIdentityInterface implementations * @param Boolean $administrativeMode True turns off audit logging * * @return Boolean true, or false; either granting, or denying access respectively. * * @throws NoAceFoundException */ private function hasSufficientPermissions(AclInterface $acl, array $aces, array $masks, array $sids, $administrativeMode) { $firstRejectedAce = null; foreach ($masks as $requiredMask) { foreach ($sids as $sid) { foreach ($aces as $ace) { if ($sid->equals($ace->getSecurityIdentity()) && $this->isAceApplicable($requiredMask, $ace)) { if ($ace->isGranting()) { if (!$administrativeMode && null !== $this->auditLogger) { $this->auditLogger->logIfNeeded(true, $ace); } return true; } if (null === $firstRejectedAce) { $firstRejectedAce = $ace; } break 2; } } } } if (null !== $firstRejectedAce) { if (!$administrativeMode && null !== $this->auditLogger) { $this->auditLogger->logIfNeeded(false, $firstRejectedAce); } return false; } throw new NoAceFoundException(); } /** * Determines whether the ACE is applicable to the given permission/security * identity combination. * * Per default, we support three different comparison strategies. * * Strategy ALL: * The ACE will be considered applicable when all the turned-on bits in the * required mask are also turned-on in the ACE mask. * * Strategy ANY: * The ACE will be considered applicable when any of the turned-on bits in * the required mask is also turned-on the in the ACE mask. * * Strategy EQUAL: * The ACE will be considered applicable when the bitmasks are equal. * * @param integer $requiredMask * @param EntryInterface $ace * * @return Boolean * * @throws \RuntimeException if the ACE strategy is not supported */ private function isAceApplicable($requiredMask, EntryInterface $ace) { $strategy = $ace->getStrategy(); if (self::ALL === $strategy) { return $requiredMask === ($ace->getMask() & $requiredMask); } elseif (self::ANY === $strategy) { return 0 !== ($ace->getMask() & $requiredMask); } elseif (self::EQUAL === $strategy) { return $requiredMask === $ace->getMask(); } throw new \RuntimeException(sprintf('The strategy "%s" is not supported.', $strategy)); } } PK!%}`M`M-Symfony/Component/Security/Acl/Domain/Acl.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Doctrine\Common\NotifyPropertyChanged; use Doctrine\Common\PropertyChangedListener; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\AuditableAclInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * An ACL implementation. * * Each object identity has exactly one associated ACL. Each ACL can have four * different types of ACEs (class ACEs, object ACEs, class field ACEs, object field * ACEs). * * You should not iterate over the ACEs yourself, but instead use isGranted(), * or isFieldGranted(). These will utilize an implementation of PermissionGrantingStrategy * internally. * * @author Johannes M. Schmitt */ class Acl implements AuditableAclInterface, NotifyPropertyChanged { private $parentAcl; private $permissionGrantingStrategy; private $objectIdentity; private $classAces = array(); private $classFieldAces = array(); private $objectAces = array(); private $objectFieldAces = array(); private $id; private $loadedSids; private $entriesInheriting; private $listeners = array(); /** * Constructor * * @param integer $id * @param ObjectIdentityInterface $objectIdentity * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy * @param array $loadedSids * @param Boolean $entriesInheriting */ public function __construct($id, ObjectIdentityInterface $objectIdentity, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $loadedSids = array(), $entriesInheriting) { $this->id = $id; $this->objectIdentity = $objectIdentity; $this->permissionGrantingStrategy = $permissionGrantingStrategy; $this->loadedSids = $loadedSids; $this->entriesInheriting = $entriesInheriting; } /** * Adds a property changed listener * * @param PropertyChangedListener $listener */ public function addPropertyChangedListener(PropertyChangedListener $listener) { $this->listeners[] = $listener; } /** * {@inheritDoc} */ public function deleteClassAce($index) { $this->deleteAce('classAces', $index); } /** * {@inheritDoc} */ public function deleteClassFieldAce($index, $field) { $this->deleteFieldAce('classFieldAces', $index, $field); } /** * {@inheritDoc} */ public function deleteObjectAce($index) { $this->deleteAce('objectAces', $index); } /** * {@inheritDoc} */ public function deleteObjectFieldAce($index, $field) { $this->deleteFieldAce('objectFieldAces', $index, $field); } /** * {@inheritDoc} */ public function getClassAces() { return $this->classAces; } /** * {@inheritDoc} */ public function getClassFieldAces($field) { return isset($this->classFieldAces[$field])? $this->classFieldAces[$field] : array(); } /** * {@inheritDoc} */ public function getObjectAces() { return $this->objectAces; } /** * {@inheritDoc} */ public function getObjectFieldAces($field) { return isset($this->objectFieldAces[$field]) ? $this->objectFieldAces[$field] : array(); } /** * {@inheritDoc} */ public function getId() { return $this->id; } /** * {@inheritDoc} */ public function getObjectIdentity() { return $this->objectIdentity; } /** * {@inheritDoc} */ public function getParentAcl() { return $this->parentAcl; } /** * {@inheritDoc} */ public function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null) { $this->insertAce('classAces', $index, $mask, $sid, $granting, $strategy); } /** * {@inheritDoc} */ public function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null) { $this->insertFieldAce('classFieldAces', $index, $field, $mask, $sid, $granting, $strategy); } /** * {@inheritDoc} */ public function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null) { $this->insertAce('objectAces', $index, $mask, $sid, $granting, $strategy); } /** * {@inheritDoc} */ public function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null) { $this->insertFieldAce('objectFieldAces', $index, $field, $mask, $sid, $granting, $strategy); } /** * {@inheritDoc} */ public function isEntriesInheriting() { return $this->entriesInheriting; } /** * {@inheritDoc} */ public function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false) { return $this->permissionGrantingStrategy->isFieldGranted($this, $field, $masks, $securityIdentities, $administrativeMode); } /** * {@inheritDoc} */ public function isGranted(array $masks, array $securityIdentities, $administrativeMode = false) { return $this->permissionGrantingStrategy->isGranted($this, $masks, $securityIdentities, $administrativeMode); } /** * {@inheritDoc} */ public function isSidLoaded($sids) { if (!$this->loadedSids) { return true; } if (!is_array($sids)) { $sids = array($sids); } foreach ($sids as $sid) { if (!$sid instanceof SecurityIdentityInterface) { throw new \InvalidArgumentException( '$sid must be an instance of SecurityIdentityInterface.'); } foreach ($this->loadedSids as $loadedSid) { if ($loadedSid->equals($sid)) { continue 2; } } return false; } return true; } /** * Implementation for the \Serializable interface * * @return string */ public function serialize() { return serialize(array( null === $this->parentAcl ? null : $this->parentAcl->getId(), $this->objectIdentity, $this->classAces, $this->classFieldAces, $this->objectAces, $this->objectFieldAces, $this->id, $this->loadedSids, $this->entriesInheriting, )); } /** * Implementation for the \Serializable interface * * @param string $serialized */ public function unserialize($serialized) { list($this->parentAcl, $this->objectIdentity, $this->classAces, $this->classFieldAces, $this->objectAces, $this->objectFieldAces, $this->id, $this->loadedSids, $this->entriesInheriting ) = unserialize($serialized); $this->listeners = array(); } /** * {@inheritDoc} */ public function setEntriesInheriting($boolean) { if ($this->entriesInheriting !== $boolean) { $this->onPropertyChanged('entriesInheriting', $this->entriesInheriting, $boolean); $this->entriesInheriting = $boolean; } } /** * {@inheritDoc} */ public function setParentAcl(AclInterface $acl = null) { if (null !== $acl && null === $acl->getId()) { throw new \InvalidArgumentException('$acl must have an ID.'); } if ($this->parentAcl !== $acl) { $this->onPropertyChanged('parentAcl', $this->parentAcl, $acl); $this->parentAcl = $acl; } } /** * {@inheritDoc} */ public function updateClassAce($index, $mask, $strategy = null) { $this->updateAce('classAces', $index, $mask, $strategy); } /** * {@inheritDoc} */ public function updateClassFieldAce($index, $field, $mask, $strategy = null) { $this->updateFieldAce('classFieldAces', $index, $field, $mask, $strategy); } /** * {@inheritDoc} */ public function updateObjectAce($index, $mask, $strategy = null) { $this->updateAce('objectAces', $index, $mask, $strategy); } /** * {@inheritDoc} */ public function updateObjectFieldAce($index, $field, $mask, $strategy = null) { $this->updateFieldAce('objectFieldAces', $index, $field, $mask, $strategy); } /** * {@inheritDoc} */ public function updateClassAuditing($index, $auditSuccess, $auditFailure) { $this->updateAuditing($this->classAces, $index, $auditSuccess, $auditFailure); } /** * {@inheritDoc} */ public function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure) { if (!isset($this->classFieldAces[$field])) { throw new \InvalidArgumentException(sprintf('There are no ACEs for field "%s".', $field)); } $this->updateAuditing($this->classFieldAces[$field], $index, $auditSuccess, $auditFailure); } /** * {@inheritDoc} */ public function updateObjectAuditing($index, $auditSuccess, $auditFailure) { $this->updateAuditing($this->objectAces, $index, $auditSuccess, $auditFailure); } /** * {@inheritDoc} */ public function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure) { if (!isset($this->objectFieldAces[$field])) { throw new \InvalidArgumentException(sprintf('There are no ACEs for field "%s".', $field)); } $this->updateAuditing($this->objectFieldAces[$field], $index, $auditSuccess, $auditFailure); } /** * Deletes an ACE * * @param string $property * @param integer $index * @throws \OutOfBoundsException */ private function deleteAce($property, $index) { $aces =& $this->$property; if (!isset($aces[$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } $oldValue = $this->$property; unset($aces[$index]); $this->$property = array_values($this->$property); $this->onPropertyChanged($property, $oldValue, $this->$property); for ($i=$index,$c=count($this->$property); $i<$c; $i++) { $this->onEntryPropertyChanged($aces[$i], 'aceOrder', $i+1, $i); } } /** * Deletes a field-based ACE * * @param string $property * @param integer $index * @param string $field * @throws \OutOfBoundsException */ private function deleteFieldAce($property, $index, $field) { $aces =& $this->$property; if (!isset($aces[$field][$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } $oldValue = $this->$property; unset($aces[$field][$index]); $aces[$field] = array_values($aces[$field]); $this->onPropertyChanged($property, $oldValue, $this->$property); for ($i=$index,$c=count($aces[$field]); $i<$c; $i++) { $this->onEntryPropertyChanged($aces[$field][$i], 'aceOrder', $i+1, $i); } } /** * Inserts an ACE * * @param string $property * @param integer $index * @param integer $mask * @param SecurityIdentityInterface $sid * @param Boolean $granting * @param string $strategy * @throws \OutOfBoundsException * @throws \InvalidArgumentException */ private function insertAce($property, $index, $mask, SecurityIdentityInterface $sid, $granting, $strategy = null) { if ($index < 0 || $index > count($this->$property)) { throw new \OutOfBoundsException(sprintf('The index must be in the interval [0, %d].', count($this->$property))); } if (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } if (null === $strategy) { if (true === $granting) { $strategy = PermissionGrantingStrategy::ALL; } else { $strategy = PermissionGrantingStrategy::ANY; } } $aces =& $this->$property; $oldValue = $this->$property; if (isset($aces[$index])) { $this->$property = array_merge( array_slice($this->$property, 0, $index), array(true), array_slice($this->$property, $index) ); for ($i=$index,$c=count($this->$property)-1; $i<$c; $i++) { $this->onEntryPropertyChanged($aces[$i+1], 'aceOrder', $i, $i+1); } } $aces[$index] = new Entry(null, $this, $sid, $strategy, $mask, $granting, false, false); $this->onPropertyChanged($property, $oldValue, $this->$property); } /** * Inserts a field-based ACE * * @param string $property * @param integer $index * @param string $field * @param integer $mask * @param SecurityIdentityInterface $sid * @param Boolean $granting * @param string $strategy * @throws \InvalidArgumentException * @throws \OutOfBoundsException */ private function insertFieldAce($property, $index, $field, $mask, SecurityIdentityInterface $sid, $granting, $strategy = null) { if (0 === strlen($field)) { throw new \InvalidArgumentException('$field cannot be empty.'); } if (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } if (null === $strategy) { if (true === $granting) { $strategy = PermissionGrantingStrategy::ALL; } else { $strategy = PermissionGrantingStrategy::ANY; } } $aces =& $this->$property; if (!isset($aces[$field])) { $aces[$field] = array(); } if ($index < 0 || $index > count($aces[$field])) { throw new \OutOfBoundsException(sprintf('The index must be in the interval [0, %d].', count($this->$property))); } $oldValue = $aces; if (isset($aces[$field][$index])) { $aces[$field] = array_merge( array_slice($aces[$field], 0, $index), array(true), array_slice($aces[$field], $index) ); for ($i=$index,$c=count($aces[$field])-1; $i<$c; $i++) { $this->onEntryPropertyChanged($aces[$field][$i+1], 'aceOrder', $i, $i+1); } } $aces[$field][$index] = new FieldEntry(null, $this, $field, $sid, $strategy, $mask, $granting, false, false); $this->onPropertyChanged($property, $oldValue, $this->$property); } /** * Updates an ACE * * @param string $property * @param integer $index * @param integer $mask * @param string $strategy * @throws \OutOfBoundsException */ private function updateAce($property, $index, $mask, $strategy = null) { $aces =& $this->$property; if (!isset($aces[$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } $ace = $aces[$index]; if ($mask !== $oldMask = $ace->getMask()) { $this->onEntryPropertyChanged($ace, 'mask', $oldMask, $mask); $ace->setMask($mask); } if (null !== $strategy && $strategy !== $oldStrategy = $ace->getStrategy()) { $this->onEntryPropertyChanged($ace, 'strategy', $oldStrategy, $strategy); $ace->setStrategy($strategy); } } /** * Updates auditing for an ACE * * @param array &$aces * @param integer $index * @param Boolean $auditSuccess * @param Boolean $auditFailure * @throws \OutOfBoundsException */ private function updateAuditing(array &$aces, $index, $auditSuccess, $auditFailure) { if (!isset($aces[$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } if ($auditSuccess !== $aces[$index]->isAuditSuccess()) { $this->onEntryPropertyChanged($aces[$index], 'auditSuccess', !$auditSuccess, $auditSuccess); $aces[$index]->setAuditSuccess($auditSuccess); } if ($auditFailure !== $aces[$index]->isAuditFailure()) { $this->onEntryPropertyChanged($aces[$index], 'auditFailure', !$auditFailure, $auditFailure); $aces[$index]->setAuditFailure($auditFailure); } } /** * Updates a field-based ACE * * @param string $property * @param integer $index * @param string $field * @param integer $mask * @param string $strategy * @throws \InvalidArgumentException * @throws \OutOfBoundsException */ private function updateFieldAce($property, $index, $field, $mask, $strategy = null) { if (0 === strlen($field)) { throw new \InvalidArgumentException('$field cannot be empty.'); } $aces =& $this->$property; if (!isset($aces[$field][$index])) { throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index)); } $ace = $aces[$field][$index]; if ($mask !== $oldMask = $ace->getMask()) { $this->onEntryPropertyChanged($ace, 'mask', $oldMask, $mask); $ace->setMask($mask); } if (null !== $strategy && $strategy !== $oldStrategy = $ace->getStrategy()) { $this->onEntryPropertyChanged($ace, 'strategy', $oldStrategy, $strategy); $ace->setStrategy($strategy); } } /** * Called when a property of the ACL changes * * @param string $name * @param mixed $oldValue * @param mixed $newValue */ private function onPropertyChanged($name, $oldValue, $newValue) { foreach ($this->listeners as $listener) { $listener->propertyChanged($this, $name, $oldValue, $newValue); } } /** * Called when a property of an ACE associated with this ACL changes * * @param EntryInterface $entry * @param string $name * @param mixed $oldValue * @param mixed $newValue */ private function onEntryPropertyChanged(EntryInterface $entry, $name, $oldValue, $newValue) { foreach ($this->listeners as $listener) { $listener->propertyChanged($entry, $name, $oldValue, $newValue); } } } PK! KSymfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter; /** * Strategy for retrieving security identities * * @author Johannes M. Schmitt */ class SecurityIdentityRetrievalStrategy implements SecurityIdentityRetrievalStrategyInterface { private $roleHierarchy; private $authenticationTrustResolver; /** * Constructor * * @param RoleHierarchyInterface $roleHierarchy * @param AuthenticationTrustResolver $authenticationTrustResolver */ public function __construct(RoleHierarchyInterface $roleHierarchy, AuthenticationTrustResolver $authenticationTrustResolver) { $this->roleHierarchy = $roleHierarchy; $this->authenticationTrustResolver = $authenticationTrustResolver; } /** * {@inheritDoc} */ public function getSecurityIdentities(TokenInterface $token) { $sids = array(); // add user security identity if (!$token instanceof AnonymousToken) { try { $sids[] = UserSecurityIdentity::fromToken($token); } catch (\InvalidArgumentException $invalid) { // ignore, user has no user security identity } } // add all reachable roles foreach ($this->roleHierarchy->getReachableRoles($token->getRoles()) as $role) { $sids[] = new RoleSecurityIdentity($role); } // add built-in special roles if ($this->authenticationTrustResolver->isFullFledged($token)) { $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_FULLY); $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_REMEMBERED); $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY); } elseif ($this->authenticationTrustResolver->isRememberMe($token)) { $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_REMEMBERED); $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY); } elseif ($this->authenticationTrustResolver->isAnonymous($token)) { $sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY); } return $sids; } } PK!X / / <Symfony/Component/Security/Acl/Domain/AclCollectionCache.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\AclProviderInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * This service caches ACLs for an entire collection of objects. * * @author Johannes M. Schmitt */ class AclCollectionCache { private $aclProvider; private $objectIdentityRetrievalStrategy; private $securityIdentityRetrievalStrategy; /** * Constructor. * * @param AclProviderInterface $aclProvider * @param ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy * @param SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy */ public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy) { $this->aclProvider = $aclProvider; $this->objectIdentityRetrievalStrategy = $oidRetrievalStrategy; $this->securityIdentityRetrievalStrategy = $sidRetrievalStrategy; } /** * Batch loads ACLs for an entire collection; thus, it reduces the number * of required queries considerably. * * @param mixed $collection anything that can be passed to foreach() * @param TokenInterface[] $tokens an array of TokenInterface implementations */ public function cache($collection, array $tokens = array()) { $sids = array(); foreach ($tokens as $token) { $sids = array_merge($sids, $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token)); } $oids = array(); foreach ($collection as $domainObject) { $oids[] = $this->objectIdentityRetrievalStrategy->getObjectIdentity($domainObject); } $this->aclProvider->findAcls($oids, $sids); } } PK!5D[/Symfony/Component/Security/Acl/Domain/Entry.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\AuditableEntryInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * Auditable ACE implementation * * @author Johannes M. Schmitt */ class Entry implements AuditableEntryInterface { private $acl; private $mask; private $id; private $securityIdentity; private $strategy; private $auditFailure; private $auditSuccess; private $granting; /** * Constructor * * @param integer $id * @param AclInterface $acl * @param SecurityIdentityInterface $sid * @param string $strategy * @param integer $mask * @param Boolean $granting * @param Boolean $auditFailure * @param Boolean $auditSuccess */ public function __construct($id, AclInterface $acl, SecurityIdentityInterface $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess) { $this->id = $id; $this->acl = $acl; $this->securityIdentity = $sid; $this->strategy = $strategy; $this->mask = $mask; $this->granting = $granting; $this->auditFailure = $auditFailure; $this->auditSuccess = $auditSuccess; } /** * {@inheritDoc} */ public function getAcl() { return $this->acl; } /** * {@inheritDoc} */ public function getMask() { return $this->mask; } /** * {@inheritDoc} */ public function getId() { return $this->id; } /** * {@inheritDoc} */ public function getSecurityIdentity() { return $this->securityIdentity; } /** * {@inheritDoc} */ public function getStrategy() { return $this->strategy; } /** * {@inheritDoc} */ public function isAuditFailure() { return $this->auditFailure; } /** * {@inheritDoc} */ public function isAuditSuccess() { return $this->auditSuccess; } /** * {@inheritDoc} */ public function isGranting() { return $this->granting; } /** * Turns on/off auditing on permissions denials. * * Do never call this method directly. Use the respective methods on the * AclInterface instead. * * @param Boolean $boolean */ public function setAuditFailure($boolean) { $this->auditFailure = $boolean; } /** * Turns on/off auditing on permission grants. * * Do never call this method directly. Use the respective methods on the * AclInterface instead. * * @param Boolean $boolean */ public function setAuditSuccess($boolean) { $this->auditSuccess = $boolean; } /** * Sets the permission mask * * Do never call this method directly. Use the respective methods on the * AclInterface instead. * * @param integer $mask */ public function setMask($mask) { $this->mask = $mask; } /** * Sets the mask comparison strategy * * Do never call this method directly. Use the respective methods on the * AclInterface instead. * * @param string $strategy */ public function setStrategy($strategy) { $this->strategy = $strategy; } /** * Implementation of \Serializable * * @return string */ public function serialize() { return serialize(array( $this->mask, $this->id, $this->securityIdentity, $this->strategy, $this->auditFailure, $this->auditSuccess, $this->granting, )); } /** * Implementation of \Serializable * * @param string $serialized */ public function unserialize($serialized) { list($this->mask, $this->id, $this->securityIdentity, $this->strategy, $this->auditFailure, $this->auditSuccess, $this->granting ) = unserialize($serialized); } } PK!pU4Symfony/Component/Security/Acl/Domain/FieldEntry.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\AclInterface; use Symfony\Component\Security\Acl\Model\FieldEntryInterface; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** * Field-aware ACE implementation which is auditable * * @author Johannes M. Schmitt */ class FieldEntry extends Entry implements FieldEntryInterface { private $field; /** * Constructor * * @param integer $id * @param AclInterface $acl * @param string $field * @param SecurityIdentityInterface $sid * @param string $strategy * @param integer $mask * @param Boolean $granting * @param Boolean $auditFailure * @param Boolean $auditSuccess */ public function __construct($id, AclInterface $acl, $field, SecurityIdentityInterface $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess) { parent::__construct($id, $acl, $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess); $this->field = $field; } /** * {@inheritDoc} */ public function getField() { return $this->field; } /** * {@inheritDoc} */ public function serialize() { return serialize(array( $this->field, parent::serialize(), )); } /** * {@inheritDoc} */ public function unserialize($serialized) { list($this->field, $parentStr) = unserialize($serialized); parent::unserialize($parentStr); } } PK!^@.Y Y 8Symfony/Component/Security/Acl/Domain/ObjectIdentity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Core\Util\ClassUtils; use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException; use Symfony\Component\Security\Acl\Model\DomainObjectInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; /** * ObjectIdentity implementation * * @author Johannes M. Schmitt */ final class ObjectIdentity implements ObjectIdentityInterface { private $identifier; private $type; /** * Constructor. * * @param string $identifier * @param string $type * * @throws \InvalidArgumentException */ public function __construct($identifier, $type) { if (empty($identifier)) { throw new \InvalidArgumentException('$identifier cannot be empty.'); } if (empty($type)) { throw new \InvalidArgumentException('$type cannot be empty.'); } $this->identifier = $identifier; $this->type = $type; } /** * Constructs an ObjectIdentity for the given domain object * * @param object $domainObject * @throws InvalidDomainObjectException * @return ObjectIdentity */ public static function fromDomainObject($domainObject) { if (!is_object($domainObject)) { throw new InvalidDomainObjectException('$domainObject must be an object.'); } try { if ($domainObject instanceof DomainObjectInterface) { return new self($domainObject->getObjectIdentifier(), ClassUtils::getRealClass($domainObject)); } elseif (method_exists($domainObject, 'getId')) { return new self($domainObject->getId(), ClassUtils::getRealClass($domainObject)); } } catch (\InvalidArgumentException $invalid) { throw new InvalidDomainObjectException($invalid->getMessage(), 0, $invalid); } throw new InvalidDomainObjectException('$domainObject must either implement the DomainObjectInterface, or have a method named "getId".'); } /** * {@inheritDoc} */ public function getIdentifier() { return $this->identifier; } /** * {@inheritDoc} */ public function getType() { return $this->type; } /** * {@inheritDoc} */ public function equals(ObjectIdentityInterface $identity) { // comparing the identifier with === might lead to problems, so we // waive this restriction return $this->identifier == $identity->getIdentifier() && $this->type === $identity->getType(); } /** * Returns a textual representation of this object identity * * @return string */ public function __toString() { return sprintf('ObjectIdentity(%s, %s)', $this->identifier, $this->type); } } PK!0FISymfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException; use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface; /** * Strategy to be used for retrieving object identities from domain objects * * @author Johannes M. Schmitt */ class ObjectIdentityRetrievalStrategy implements ObjectIdentityRetrievalStrategyInterface { /** * {@inheritDoc} */ public function getObjectIdentity($domainObject) { try { return ObjectIdentity::fromDomainObject($domainObject); } catch (InvalidDomainObjectException $failed) { return null; } } } PK!tA)==>Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; use Symfony\Component\Security\Core\Role\Role; /** * A SecurityIdentity implementation for roles * * @author Johannes M. Schmitt */ final class RoleSecurityIdentity implements SecurityIdentityInterface { private $role; /** * Constructor * * @param mixed $role a Role instance, or its string representation */ public function __construct($role) { if ($role instanceof Role) { $role = $role->getRole(); } $this->role = $role; } /** * Returns the role name * * @return string */ public function getRole() { return $this->role; } /** * {@inheritDoc} */ public function equals(SecurityIdentityInterface $sid) { if (!$sid instanceof RoleSecurityIdentity) { return false; } return $this->role === $sid->getRole(); } /** * Returns a textual representation of this security identity. * * This is solely used for debugging purposes, not to make an equality decision. * * @return string */ public function __toString() { return sprintf('RoleSecurityIdentity(%s)', $this->role); } } PK!#~~<Symfony/Component/Security/Acl/Resources/bin/generateSql.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ require_once __DIR__.'/../../../../ClassLoader/ClassLoader.php'; use Symfony\Component\ClassLoader\ClassLoader; use Symfony\Component\Finder\Finder; use Symfony\Component\Security\Acl\Dbal\Schema; $loader = new ClassLoader(); $loader->addPrefixes(array( 'Symfony' => __DIR__.'/../../../../../..', 'Doctrine\\Common' => __DIR__.'/../../../../../../../vendor/doctrine-common/lib', 'Doctrine\\DBAL\\Migrations' => __DIR__.'/../../../../../../../vendor/doctrine-migrations/lib', 'Doctrine\\DBAL' => __DIR__.'/../../../../../../../vendor/doctrine-dbal/lib', 'Doctrine' => __DIR__.'/../../../../../../../vendor/doctrine/lib', )); $loader->register(); $schema = new Schema(array( 'class_table_name' => 'acl_classes', 'entry_table_name' => 'acl_entries', 'oid_table_name' => 'acl_object_identities', 'oid_ancestors_table_name' => 'acl_object_identity_ancestors', 'sid_table_name' => 'acl_security_identities', )); $reflection = new ReflectionClass('Doctrine\\DBAL\\Platforms\\AbstractPlatform'); $finder = new Finder(); $finder->name('*Platform.php')->in(dirname($reflection->getFileName())); foreach ($finder as $file) { require_once $file->getPathName(); $className = 'Doctrine\\DBAL\\Platforms\\'.$file->getBasename('.php'); $reflection = new ReflectionClass($className); if ($reflection->isAbstract()) { continue; } $platform = $reflection->newInstance(); $targetFile = sprintf(__DIR__.'/../schema/%s.sql', $platform->name); file_put_contents($targetFile, implode("\n\n", $schema->toSql($platform))); } PK!j~ cF F 7Symfony/Component/Security/Acl/Resources/schema/db2.sqlnu[CREATE TABLE acl_classes (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) CREATE TABLE acl_security_identities (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, identifier VARCHAR(200) NOT NULL, username SMALLINT NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) CREATE TABLE acl_object_identities (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, parent_object_identity_id INTEGER DEFAULT NULL, class_id INTEGER NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting SMALLINT NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id INTEGER NOT NULL, ancestor_id INTEGER NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id)) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, class_id INTEGER NOT NULL, object_identity_id INTEGER DEFAULT NULL, security_identity_id INTEGER NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT NOT NULL, mask INTEGER NOT NULL, granting SMALLINT NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success SMALLINT NOT NULL, audit_failure SMALLINT NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK!Tsk k >Symfony/Component/Security/Acl/Resources/schema/postgresql.sqlnu[CREATE TABLE acl_classes (id SERIAL NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) CREATE TABLE acl_security_identities (id SERIAL NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) CREATE TABLE acl_object_identities (id SERIAL NOT NULL, parent_object_identity_id INT DEFAULT NULL, class_id INT NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id INT NOT NULL, ancestor_id INT NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id)) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id SERIAL NOT NULL, class_id INT NOT NULL, object_identity_id INT DEFAULT NULL, security_identity_id INT NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT NOT NULL, mask INT NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY(id)) CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATEPK!Jx.  9Symfony/Component/Security/Acl/Resources/schema/mssql.sqlnu[CREATE TABLE acl_classes (id INT UNSIGNED IDENTITY NOT NULL, class_type NVARCHAR(200) NOT NULL, PRIMARY KEY (id)) CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) WHERE class_type IS NOT NULL CREATE TABLE acl_security_identities (id INT UNSIGNED IDENTITY NOT NULL, identifier NVARCHAR(200) NOT NULL, username BIT NOT NULL, PRIMARY KEY (id)) CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) WHERE identifier IS NOT NULL AND username IS NOT NULL CREATE TABLE acl_object_identities (id INT UNSIGNED IDENTITY NOT NULL, parent_object_identity_id INT UNSIGNED DEFAULT NULL, class_id INT UNSIGNED NOT NULL, object_identifier NVARCHAR(100) NOT NULL, entries_inheriting BIT NOT NULL, PRIMARY KEY (id)) CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) WHERE object_identifier IS NOT NULL AND class_id IS NOT NULL CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id INT UNSIGNED NOT NULL, ancestor_id INT UNSIGNED NOT NULL, PRIMARY KEY (object_identity_id, ancestor_id)) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id INT UNSIGNED IDENTITY NOT NULL, class_id INT UNSIGNED NOT NULL, object_identity_id INT UNSIGNED DEFAULT NULL, security_identity_id INT UNSIGNED NOT NULL, field_name NVARCHAR(50) DEFAULT NULL, ace_order SMALLINT UNSIGNED NOT NULL, mask INT NOT NULL, granting BIT NOT NULL, granting_strategy NVARCHAR(30) NOT NULL, audit_success BIT NOT NULL, audit_failure BIT NOT NULL, PRIMARY KEY (id)) CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) WHERE class_id IS NOT NULL AND object_identity_id IS NOT NULL AND field_name IS NOT NULL AND ace_order IS NOT NULL CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK!fZ^ ^ 9Symfony/Component/Security/Acl/Resources/schema/mysql.sqlnu[CREATE TABLE acl_classes (id INT UNSIGNED AUTO_INCREMENT NOT NULL, class_type VARCHAR(200) NOT NULL, UNIQUE INDEX UNIQ_69DD750638A36066 (class_type), PRIMARY KEY(id)) ENGINE = InnoDB CREATE TABLE acl_security_identities (id INT UNSIGNED AUTO_INCREMENT NOT NULL, identifier VARCHAR(200) NOT NULL, username TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 (identifier, username), PRIMARY KEY(id)) ENGINE = InnoDB CREATE TABLE acl_object_identities (id INT UNSIGNED AUTO_INCREMENT NOT NULL, parent_object_identity_id INT UNSIGNED DEFAULT NULL, class_id INT UNSIGNED NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 (object_identifier, class_id), INDEX IDX_9407E54977FA751A (parent_object_identity_id), PRIMARY KEY(id)) ENGINE = InnoDB CREATE TABLE acl_object_identity_ancestors (object_identity_id INT UNSIGNED NOT NULL, ancestor_id INT UNSIGNED NOT NULL, INDEX IDX_825DE2993D9AB4A6 (object_identity_id), INDEX IDX_825DE299C671CEA1 (ancestor_id), PRIMARY KEY(object_identity_id, ancestor_id)) ENGINE = InnoDB CREATE TABLE acl_entries (id INT UNSIGNED AUTO_INCREMENT NOT NULL, class_id INT UNSIGNED NOT NULL, object_identity_id INT UNSIGNED DEFAULT NULL, security_identity_id INT UNSIGNED NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT UNSIGNED NOT NULL, mask INT NOT NULL, granting TINYINT(1) NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success TINYINT(1) NOT NULL, audit_failure TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 (class_id, object_identity_id, field_name, ace_order), INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 (class_id, object_identity_id, security_identity_id), INDEX IDX_46C8B806EA000B10 (class_id), INDEX IDX_46C8B8063D9AB4A6 (object_identity_id), INDEX IDX_46C8B806DF9183C9 (security_identity_id), PRIMARY KEY(id)) ENGINE = InnoDB ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK!c ;Symfony/Component/Security/Acl/Resources/schema/drizzle.sqlnu[CREATE TABLE acl_classes (id INT AUTO_INCREMENT NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_69DD750638A36066 (class_type)) CREATE TABLE acl_security_identities (id INT AUTO_INCREMENT NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 (identifier, username)) CREATE TABLE acl_object_identities (id INT AUTO_INCREMENT NOT NULL, parent_object_identity_id INT DEFAULT NULL, class_id INT NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 (object_identifier, class_id), INDEX IDX_9407E54977FA751A (parent_object_identity_id)) CREATE TABLE acl_object_identity_ancestors (object_identity_id INT NOT NULL, ancestor_id INT NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id), INDEX IDX_825DE2993D9AB4A6 (object_identity_id), INDEX IDX_825DE299C671CEA1 (ancestor_id)) CREATE TABLE acl_entries (id INT AUTO_INCREMENT NOT NULL, class_id INT NOT NULL, object_identity_id INT DEFAULT NULL, security_identity_id INT NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order INT NOT NULL, mask INT NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY(id), UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 (class_id, object_identity_id, field_name, ace_order), INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 (class_id, object_identity_id, security_identity_id), INDEX IDX_46C8B806EA000B10 (class_id), INDEX IDX_46C8B8063D9AB4A6 (object_identity_id), INDEX IDX_46C8B806DF9183C9 (security_identity_id)) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADEPK!C ;;:Symfony/Component/Security/Acl/Resources/schema/oracle.sqlnu[CREATE TABLE acl_classes (id NUMBER(10) NOT NULL, class_type VARCHAR2(200) NOT NULL, PRIMARY KEY(id)) DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_CLASSES' AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE ACL_CLASSES ADD CONSTRAINT ACL_CLASSES_AI_PK PRIMARY KEY (id)'; END IF; END; CREATE SEQUENCE ACL_CLASSES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 CREATE TRIGGER ACL_CLASSES_AI_PK BEFORE INSERT ON ACL_CLASSES FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ACL_CLASSES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; IF (:NEW.id IS NULL OR :NEW.id = 0) THEN SELECT ACL_CLASSES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = 'ACL_CLASSES_SEQ'; SELECT :NEW.id INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ACL_CLASSES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; END IF; END; CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) CREATE TABLE acl_security_identities (id NUMBER(10) NOT NULL, identifier VARCHAR2(200) NOT NULL, username NUMBER(1) NOT NULL, PRIMARY KEY(id)) DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_SECURITY_IDENTITIES' AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE ACL_SECURITY_IDENTITIES ADD CONSTRAINT ACL_SECURITY_IDENTITIES_AI_PK PRIMARY KEY (id)'; END IF; END; CREATE SEQUENCE ACL_SECURITY_IDENTITIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 CREATE TRIGGER ACL_SECURITY_IDENTITIES_AI_PK BEFORE INSERT ON ACL_SECURITY_IDENTITIES FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; IF (:NEW.id IS NULL OR :NEW.id = 0) THEN SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = 'ACL_SECURITY_IDENTITIES_SEQ'; SELECT :NEW.id INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; END IF; END; CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) CREATE TABLE acl_object_identities (id NUMBER(10) NOT NULL, parent_object_identity_id NUMBER(10) DEFAULT NULL, class_id NUMBER(10) NOT NULL, object_identifier VARCHAR2(100) NOT NULL, entries_inheriting NUMBER(1) NOT NULL, PRIMARY KEY(id)) DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_OBJECT_IDENTITIES' AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE ACL_OBJECT_IDENTITIES ADD CONSTRAINT ACL_OBJECT_IDENTITIES_AI_PK PRIMARY KEY (id)'; END IF; END; CREATE SEQUENCE ACL_OBJECT_IDENTITIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 CREATE TRIGGER ACL_OBJECT_IDENTITIES_AI_PK BEFORE INSERT ON ACL_OBJECT_IDENTITIES FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; IF (:NEW.id IS NULL OR :NEW.id = 0) THEN SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = 'ACL_OBJECT_IDENTITIES_SEQ'; SELECT :NEW.id INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; END IF; END; CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id NUMBER(10) NOT NULL, ancestor_id NUMBER(10) NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id)) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id NUMBER(10) NOT NULL, class_id NUMBER(10) NOT NULL, object_identity_id NUMBER(10) DEFAULT NULL, security_identity_id NUMBER(10) NOT NULL, field_name VARCHAR2(50) DEFAULT NULL, ace_order NUMBER(5) NOT NULL, mask NUMBER(10) NOT NULL, granting NUMBER(1) NOT NULL, granting_strategy VARCHAR2(30) NOT NULL, audit_success NUMBER(1) NOT NULL, audit_failure NUMBER(1) NOT NULL, PRIMARY KEY(id)) DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_ENTRIES' AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE ACL_ENTRIES ADD CONSTRAINT ACL_ENTRIES_AI_PK PRIMARY KEY (id)'; END IF; END; CREATE SEQUENCE ACL_ENTRIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 CREATE TRIGGER ACL_ENTRIES_AI_PK BEFORE INSERT ON ACL_ENTRIES FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; IF (:NEW.id IS NULL OR :NEW.id = 0) THEN SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO :NEW.id FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = 'ACL_ENTRIES_SEQ'; SELECT :NEW.id INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; END IF; END; CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id) ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON DELETE CASCADEPK!d:Symfony/Component/Security/Acl/Resources/schema/sqlite.sqlnu[CREATE TABLE acl_classes (id INTEGER NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY("id")) CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) CREATE TABLE acl_security_identities (id INTEGER NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY("id")) CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) CREATE TABLE acl_object_identities (id INTEGER NOT NULL, parent_object_identity_id INTEGER DEFAULT NULL, class_id INTEGER NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY("id")) CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id) CREATE TABLE acl_object_identity_ancestors (object_identity_id INTEGER NOT NULL, ancestor_id INTEGER NOT NULL, PRIMARY KEY("object_identity_id", "ancestor_id")) CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id) CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id) CREATE TABLE acl_entries (id INTEGER NOT NULL, class_id INTEGER NOT NULL, object_identity_id INTEGER DEFAULT NULL, security_identity_id INTEGER NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order INTEGER NOT NULL, mask INTEGER NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY("id")) CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id) CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id) CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id) CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)PK!wDSymfony/Component/Security/Acl/Permission/PermissionMapInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Permission; /** * This is the interface that must be implemented by permission maps. * * @author Johannes M. Schmitt */ interface PermissionMapInterface { /** * Returns an array of bitmasks. * * The security identity must have been granted access to at least one of * these bitmasks. * * @param string $permission * @param object $object * @return array may return null if permission/object combination is not supported */ public function getMasks($permission, $object); /** * Whether this map contains the given permission * * @param string $permission * @return Boolean */ public function contains($permission); } PK!epgg9Symfony/Component/Security/Acl/Permission/MaskBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Permission; /** * This class allows you to build cumulative permissions easily, or convert * masks to a human-readable format. * * * $builder = new MaskBuilder(); * $builder * ->add('view') * ->add('create') * ->add('edit') * ; * var_dump($builder->get()); // int(7) * var_dump($builder->getPattern()); // string(32) ".............................ECV" * * * We have defined some commonly used base permissions which you can use: * - VIEW: the SID is allowed to view the domain object / field * - CREATE: the SID is allowed to create new instances of the domain object / fields * - EDIT: the SID is allowed to edit existing instances of the domain object / field * - DELETE: the SID is allowed to delete domain objects * - UNDELETE: the SID is allowed to recover domain objects from trash * - OPERATOR: the SID is allowed to perform any action on the domain object * except for granting others permissions * - MASTER: the SID is allowed to perform any action on the domain object, * and is allowed to grant other SIDs any permission except for * MASTER and OWNER permissions * - OWNER: the SID is owning the domain object in question and can perform any * action on the domain object as well as grant any permission * * @author Johannes M. Schmitt */ class MaskBuilder { const MASK_VIEW = 1; // 1 << 0 const MASK_CREATE = 2; // 1 << 1 const MASK_EDIT = 4; // 1 << 2 const MASK_DELETE = 8; // 1 << 3 const MASK_UNDELETE = 16; // 1 << 4 const MASK_OPERATOR = 32; // 1 << 5 const MASK_MASTER = 64; // 1 << 6 const MASK_OWNER = 128; // 1 << 7 const MASK_IDDQD = 1073741823; // 1 << 0 | 1 << 1 | ... | 1 << 30 const CODE_VIEW = 'V'; const CODE_CREATE = 'C'; const CODE_EDIT = 'E'; const CODE_DELETE = 'D'; const CODE_UNDELETE = 'U'; const CODE_OPERATOR = 'O'; const CODE_MASTER = 'M'; const CODE_OWNER = 'N'; const ALL_OFF = '................................'; const OFF = '.'; const ON = '*'; private $mask; /** * Constructor * * @param integer $mask optional; defaults to 0 * * @throws \InvalidArgumentException */ public function __construct($mask = 0) { if (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } $this->mask = $mask; } /** * Adds a mask to the permission * * @param mixed $mask * * @return MaskBuilder * * @throws \InvalidArgumentException */ public function add($mask) { if (is_string($mask) && defined($name = 'static::MASK_'.strtoupper($mask))) { $mask = constant($name); } elseif (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } $this->mask |= $mask; return $this; } /** * Returns the mask of this permission * * @return integer */ public function get() { return $this->mask; } /** * Returns a human-readable representation of the permission * * @return string */ public function getPattern() { $pattern = self::ALL_OFF; $length = strlen($pattern); $bitmask = str_pad(decbin($this->mask), $length, '0', STR_PAD_LEFT); for ($i=$length-1; $i>=0; $i--) { if ('1' === $bitmask[$i]) { try { $pattern[$i] = self::getCode(1 << ($length - $i - 1)); } catch (\Exception $notPredefined) { $pattern[$i] = self::ON; } } } return $pattern; } /** * Removes a mask from the permission * * @param mixed $mask * * @return MaskBuilder * * @throws \InvalidArgumentException */ public function remove($mask) { if (is_string($mask) && defined($name = 'static::MASK_'.strtoupper($mask))) { $mask = constant($name); } elseif (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } $this->mask &= ~$mask; return $this; } /** * Resets the PermissionBuilder * * @return MaskBuilder */ public function reset() { $this->mask = 0; return $this; } /** * Returns the code for the passed mask * * @param integer $mask * @throws \InvalidArgumentException * @throws \RuntimeException * @return string */ public static function getCode($mask) { if (!is_int($mask)) { throw new \InvalidArgumentException('$mask must be an integer.'); } $reflection = new \ReflectionClass(get_called_class()); foreach ($reflection->getConstants() as $name => $cMask) { if (0 !== strpos($name, 'MASK_')) { continue; } if ($mask === $cMask) { if (!defined($cName = 'static::CODE_'.substr($name, 5))) { throw new \RuntimeException('There was no code defined for this mask.'); } return constant($cName); } } throw new \InvalidArgumentException(sprintf('The mask "%d" is not supported.', $mask)); } } PK! c0 @Symfony/Component/Security/Acl/Permission/BasicPermissionMap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Permission; /** * This is basic permission map complements the masks which have been defined * on the standard implementation of the MaskBuilder. * * @author Johannes M. Schmitt */ class BasicPermissionMap implements PermissionMapInterface { const PERMISSION_VIEW = 'VIEW'; const PERMISSION_EDIT = 'EDIT'; const PERMISSION_CREATE = 'CREATE'; const PERMISSION_DELETE = 'DELETE'; const PERMISSION_UNDELETE = 'UNDELETE'; const PERMISSION_OPERATOR = 'OPERATOR'; const PERMISSION_MASTER = 'MASTER'; const PERMISSION_OWNER = 'OWNER'; protected $map; public function __construct() { $this->map = array( self::PERMISSION_VIEW => array( MaskBuilder::MASK_VIEW, MaskBuilder::MASK_EDIT, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_EDIT => array( MaskBuilder::MASK_EDIT, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_CREATE => array( MaskBuilder::MASK_CREATE, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_DELETE => array( MaskBuilder::MASK_DELETE, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_UNDELETE => array( MaskBuilder::MASK_UNDELETE, MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_OPERATOR => array( MaskBuilder::MASK_OPERATOR, MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_MASTER => array( MaskBuilder::MASK_MASTER, MaskBuilder::MASK_OWNER, ), self::PERMISSION_OWNER => array( MaskBuilder::MASK_OWNER, ), ); } /** * {@inheritDoc} */ public function getMasks($permission, $object) { if (!isset($this->map[$permission])) { return null; } return $this->map[$permission]; } /** * {@inheritDoc} */ public function contains($permission) { return isset($this->map[$permission]); } } PK!6<Symfony/Component/Security/Acl/Model/MutableAclInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This interface adds mutators for the AclInterface. * * All changes to Access Control Entries must go through this interface. Access * Control Entries must never be modified directly. * * @author Johannes M. Schmitt */ interface MutableAclInterface extends AclInterface { /** * Deletes a class-based ACE * * @param integer $index */ public function deleteClassAce($index); /** * Deletes a class-field-based ACE * * @param integer $index * @param string $field */ public function deleteClassFieldAce($index, $field); /** * Deletes an object-based ACE * * @param integer $index */ public function deleteObjectAce($index); /** * Deletes an object-field-based ACE * * @param integer $index * @param string $field */ public function deleteObjectFieldAce($index, $field); /** * Returns the primary key of this ACL * * @return integer */ public function getId(); /** * Inserts a class-based ACE * * @param SecurityIdentityInterface $sid * @param integer $mask * @param integer $index * @param Boolean $granting * @param string $strategy */ public function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Inserts a class-field-based ACE * * @param string $field * @param SecurityIdentityInterface $sid * @param integer $mask * @param integer $index * @param Boolean $granting * @param string $strategy */ public function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Inserts an object-based ACE * * @param SecurityIdentityInterface $sid * @param integer $mask * @param integer $index * @param Boolean $granting * @param string $strategy */ public function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Inserts an object-field-based ACE * * @param string $field * @param SecurityIdentityInterface $sid * @param integer $mask * @param integer $index * @param Boolean $granting * @param string $strategy */ public function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null); /** * Sets whether entries are inherited * * @param Boolean $boolean */ public function setEntriesInheriting($boolean); /** * Sets the parent ACL * * @param AclInterface|null $acl */ public function setParentAcl(AclInterface $acl = null); /** * Updates a class-based ACE * * @param integer $index * @param integer $mask * @param string $strategy if null the strategy should not be changed */ public function updateClassAce($index, $mask, $strategy = null); /** * Updates a class-field-based ACE * * @param integer $index * @param string $field * @param integer $mask * @param string $strategy if null the strategy should not be changed */ public function updateClassFieldAce($index, $field, $mask, $strategy = null); /** * Updates an object-based ACE * * @param integer $index * @param integer $mask * @param string $strategy if null the strategy should not be changed */ public function updateObjectAce($index, $mask, $strategy = null); /** * Updates an object-field-based ACE * * @param integer $index * @param string $field * @param integer $mask * @param string $strategy if null the strategy should not be changed */ public function updateObjectFieldAce($index, $field, $mask, $strategy = null); } PK![Ob3SSymfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * Interface for retrieving security identities from tokens * * @author Johannes M. Schmitt */ interface SecurityIdentityRetrievalStrategyInterface { /** * Retrieves the available security identities for the given token * * The order in which the security identities are returned is significant. * Typically, security identities should be ordered from most specific to * least specific. * * @param TokenInterface $token * * @return SecurityIdentityInterface[] An array of SecurityIdentityInterface implementations */ public function getSecurityIdentities(TokenInterface $token); } PK!X >Symfony/Component/Security/Acl/Model/DomainObjectInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This method can be implemented by domain objects which you want to store * ACLs for if they do not have a getId() method, or getId() does not return * a unique identifier. * * @author Johannes M. Schmitt */ interface DomainObjectInterface { /** * Returns a unique identifier for this domain object. * * @return string */ public function getObjectIdentifier(); } PK!5Ayy@Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Represents the identity of an individual domain object instance. * * @author Johannes M. Schmitt */ interface ObjectIdentityInterface { /** * We specifically require this method so we can check for object equality * explicitly, and do not have to rely on referencial equality instead. * * Though in most cases, both checks should result in the same outcome. * * Referential Equality: $object1 === $object2 * Example for Object Equality: $object1->getId() === $object2->getId() * * @param ObjectIdentityInterface $identity * @return Boolean */ public function equals(ObjectIdentityInterface $identity); /** * Obtains a unique identifier for this object. The identifier must not be * re-used for other objects with the same type. * * @return string cannot return null */ public function getIdentifier(); /** * Returns a type for the domain object. Typically, this is the PHP class name. * * @return string cannot return null */ public function getType(); } PK!t @Symfony/Component/Security/Acl/Model/AuditableEntryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * ACEs can implement this interface if they support auditing capabilities. * * @author Johannes M. Schmitt */ interface AuditableEntryInterface extends EntryInterface { /** * Whether auditing for successful grants is turned on * * @return Boolean */ public function isAuditFailure(); /** * Whether auditing for successful denies is turned on * * @return Boolean */ public function isAuditSuccess(); } PK!-癥LSymfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Interface used by permission granting implementations. * * @author Johannes M. Schmitt */ interface PermissionGrantingStrategyInterface { /** * Determines whether access to a domain object is to be granted * * @param AclInterface $acl * @param array $masks * @param array $sids * @param Boolean $administrativeMode * @return Boolean */ public function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false); /** * Determines whether access to a domain object's field is to be granted * * @param AclInterface $acl * @param string $field * @param array $masks * @param array $sids * @param Boolean $administrativeMode * * @return Boolean */ public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false); } PK!=Symfony/Component/Security/Acl/Model/AclProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; use Symfony\Component\Security\Acl\Exception\AclNotFoundException; /** * Provides a common interface for retrieving ACLs. * * @author Johannes M. Schmitt */ interface AclProviderInterface { /** * Retrieves all child object identities from the database * * @param ObjectIdentityInterface $parentOid * @param Boolean $directChildrenOnly * * @return array returns an array of child 'ObjectIdentity's */ public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false); /** * Returns the ACL that belongs to the given object identity * * @param ObjectIdentityInterface $oid * @param SecurityIdentityInterface[] $sids * * @return AclInterface * * @throws AclNotFoundException when there is no ACL */ public function findAcl(ObjectIdentityInterface $oid, array $sids = array()); /** * Returns the ACLs that belong to the given object identities * * @param ObjectIdentityInterface[] $oids an array of ObjectIdentityInterface implementations * @param SecurityIdentityInterface[] $sids an array of SecurityIdentityInterface implementations * * @return \SplObjectStorage mapping the passed object identities to ACLs * * @throws AclNotFoundException when we cannot find an ACL for all identities */ public function findAcls(array $oids, array $sids = array()); } PK!#:Symfony/Component/Security/Acl/Model/AclCacheInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * AclCache Interface * * @author Johannes M. Schmitt */ interface AclCacheInterface { /** * Removes an ACL from the cache * * @param string $primaryKey a serialized primary key */ public function evictFromCacheById($primaryKey); /** * Removes an ACL from the cache * * The ACL which is returned, must reference the passed object identity. * * @param ObjectIdentityInterface $oid */ public function evictFromCacheByIdentity(ObjectIdentityInterface $oid); /** * Retrieves an ACL for the given object identity primary key from the cache * * @param integer $primaryKey * @return AclInterface */ public function getFromCacheById($primaryKey); /** * Retrieves an ACL for the given object identity from the cache * * @param ObjectIdentityInterface $oid * @return AclInterface */ public function getFromCacheByIdentity(ObjectIdentityInterface $oid); /** * Stores a new ACL in the cache * * @param AclInterface $acl */ public function putInCache(AclInterface $acl); /** * Removes all ACLs from the cache */ public function clearCache(); } PK!ӗ&1>Symfony/Component/Security/Acl/Model/AuditableAclInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This interface adds auditing capabilities to the ACL. * * @author Johannes M. Schmitt */ interface AuditableAclInterface extends MutableAclInterface { /** * Updates auditing for class-based ACE * * @param integer $index * @param Boolean $auditSuccess * @param Boolean $auditFailure */ public function updateClassAuditing($index, $auditSuccess, $auditFailure); /** * Updates auditing for class-field-based ACE * * @param integer $index * @param string $field * @param Boolean $auditSuccess * @param Boolean $auditFailure */ public function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure); /** * Updates auditing for object-based ACE * * @param integer $index * @param Boolean $auditSuccess * @param Boolean $auditFailure */ public function updateObjectAuditing($index, $auditSuccess, $auditFailure); /** * Updates auditing for object-field-based ACE * * @param integer $index * @param string $field * @param Boolean $auditSuccess * @param Boolean $auditFailure */ public function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure); } PK!ݤUU<Symfony/Component/Security/Acl/Model/FieldEntryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Interface for entries which are restricted to specific fields * * @author Johannes M. Schmitt */ interface FieldEntryInterface extends EntryInterface { /** * Returns the field used for this entry. * * @return string */ public function getField(); } PK! 8FF7Symfony/Component/Security/Acl/Model/EntryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This class represents an individual entry in the ACL list. * * Instances MUST be immutable, as they are returned by the ACL and should not * allow client modification. * * @author Johannes M. Schmitt */ interface EntryInterface extends \Serializable { /** * The ACL this ACE is associated with. * * @return AclInterface */ public function getAcl(); /** * The primary key of this ACE * * @return integer */ public function getId(); /** * The permission mask of this ACE * * @return integer */ public function getMask(); /** * The security identity associated with this ACE * * @return SecurityIdentityInterface */ public function getSecurityIdentity(); /** * The strategy for comparing masks * * @return string */ public function getStrategy(); /** * Returns whether this ACE is granting, or denying * * @return Boolean */ public function isGranting(); } PK!H * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Interface for audit loggers * * @author Johannes M. Schmitt */ interface AuditLoggerInterface { /** * This method is called whenever access is granted, or denied, and * administrative mode is turned off. * * @param Boolean $granted * @param EntryInterface $ace */ public function logIfNeeded($granted, EntryInterface $ace); } PK!77BSymfony/Component/Security/Acl/Model/SecurityIdentityInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * This interface provides an additional level of indirection, so that * we can work with abstracted versions of security objects and do * not have to save the entire objects. * * @author Johannes M. Schmitt */ interface SecurityIdentityInterface { /** * This method is used to compare two security identities in order to * not rely on referential equality. * * @param SecurityIdentityInterface $identity */ public function equals(SecurityIdentityInterface $identity); } PK!𕛼 5Symfony/Component/Security/Acl/Model/AclInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; use Symfony\Component\Security\Acl\Exception\NoAceFoundException; /** * This interface represents an access control list (ACL) for a domain object. * Each domain object can have exactly one associated ACL. * * An ACL contains all access control entries (ACE) for a given domain object. * In order to avoid needing references to the domain object itself, implementations * use ObjectIdentity implementations as an additional level of indirection. * * @author Johannes M. Schmitt */ interface AclInterface extends \Serializable { /** * Returns all class-based ACEs associated with this ACL * * @return array */ public function getClassAces(); /** * Returns all class-field-based ACEs associated with this ACL * * @param string $field * @return array */ public function getClassFieldAces($field); /** * Returns all object-based ACEs associated with this ACL * * @return array */ public function getObjectAces(); /** * Returns all object-field-based ACEs associated with this ACL * * @param string $field * @return array */ public function getObjectFieldAces($field); /** * Returns the object identity associated with this ACL * * @return ObjectIdentityInterface */ public function getObjectIdentity(); /** * Returns the parent ACL, or null if there is none. * * @return AclInterface|null */ public function getParentAcl(); /** * Whether this ACL is inheriting ACEs from a parent ACL. * * @return Boolean */ public function isEntriesInheriting(); /** * Determines whether field access is granted * * @param string $field * @param array $masks * @param array $securityIdentities * @param Boolean $administrativeMode * @return Boolean */ public function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false); /** * Determines whether access is granted * * @throws NoAceFoundException when no ACE was applicable for this request * @param array $masks * @param array $securityIdentities * @param Boolean $administrativeMode * @return Boolean */ public function isGranted(array $masks, array $securityIdentities, $administrativeMode = false); /** * Whether the ACL has loaded ACEs for all of the passed security identities * * @param mixed $securityIdentities an implementation of SecurityIdentityInterface, or an array thereof * @return Boolean */ public function isSidLoaded($securityIdentities); } PK!W}QSymfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Retrieves the object identity for a given domain object * * @author Johannes M. Schmitt */ interface ObjectIdentityRetrievalStrategyInterface { /** * Retrieves the object identity from a domain object * * @param object $domainObject * @return ObjectIdentityInterface */ public function getObjectIdentity($domainObject); } PK!jDSymfony/Component/Security/Acl/Model/MutableAclProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Model; /** * Provides support for creating and storing ACL instances. * * @author Johannes M. Schmitt */ interface MutableAclProviderInterface extends AclProviderInterface { /** * Creates a new ACL for the given object identity. * * @throws AclAlreadyExistsException when there already is an ACL for the given * object identity * @param ObjectIdentityInterface $oid * @return MutableAclInterface */ public function createAcl(ObjectIdentityInterface $oid); /** * Deletes the ACL for a given object identity. * * This will automatically trigger a delete for any child ACLs. If you don't * want child ACLs to be deleted, you will have to set their parent ACL to null. * * @param ObjectIdentityInterface $oid */ public function deleteAcl(ObjectIdentityInterface $oid); /** * Persists any changes which were made to the ACL, or any associated * access control entries. * * Changes to parent ACLs are not persisted. * * @param MutableAclInterface $acl */ public function updateAcl(MutableAclInterface $acl); } PK!W"RR)Symfony/Component/Security/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Firewall uses a FirewallMap to register security listeners for the given * request. * * It allows for different security strategies within the same application * (a Basic authentication for the /api, and a web based authentication for * everything else for instance). * * @author Fabien Potencier */ class Firewall implements EventSubscriberInterface { private $map; private $dispatcher; private $exceptionListeners; /** * Constructor. * * @param FirewallMapInterface $map A FirewallMapInterface instance * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance */ public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher) { $this->map = $map; $this->dispatcher = $dispatcher; $this->exceptionListeners = new \SplObjectStorage(); } /** * Handles security. * * @param GetResponseEvent $event An GetResponseEvent instance */ public function onKernelRequest(GetResponseEvent $event) { if (!$event->isMasterRequest()) { return; } // register listeners for this firewall list($listeners, $exceptionListener) = $this->map->getListeners($event->getRequest()); if (null !== $exceptionListener) { $this->exceptionListeners[$event->getRequest()] = $exceptionListener; $exceptionListener->register($this->dispatcher); } // initiate the listener chain foreach ($listeners as $listener) { $listener->handle($event); if ($event->hasResponse()) { break; } } } public function onKernelFinishRequest(FinishRequestEvent $event) { $request = $event->getRequest(); if (isset($this->exceptionListeners[$request])) { $this->exceptionListeners[$request]->unregister($this->dispatcher); unset($this->exceptionListeners[$request]); } } /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array('onKernelRequest', 8), KernelEvents::FINISH_REQUEST => 'onKernelFinishRequest', ); } } PK!"C/Symfony/Component/Security/Http/FirewallMap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpFoundation\RequestMatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\Firewall\ExceptionListener; /** * FirewallMap allows configuration of different firewalls for specific parts * of the website. * * @author Fabien Potencier */ class FirewallMap implements FirewallMapInterface { private $map = array(); /** * @param RequestMatcherInterface $requestMatcher * @param array $listeners * @param ExceptionListener $exceptionListener */ public function add(RequestMatcherInterface $requestMatcher = null, array $listeners = array(), ExceptionListener $exceptionListener = null) { $this->map[] = array($requestMatcher, $listeners, $exceptionListener); } /** * {@inheritDoc} */ public function getListeners(Request $request) { foreach ($this->map as $elements) { if (null === $elements[0] || $elements[0]->matches($request)) { return array($elements[1], $elements[2]); } } return array(array(), null); } } PK!יKSymfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * FormAuthenticationEntryPoint starts an authentication via a login form. * * @author Fabien Potencier */ class FormAuthenticationEntryPoint implements AuthenticationEntryPointInterface { private $loginPath; private $useForward; private $httpKernel; private $httpUtils; /** * Constructor. * * @param HttpKernelInterface $kernel * @param HttpUtils $httpUtils An HttpUtils instance * @param string $loginPath The path to the login form * @param Boolean $useForward Whether to forward or redirect to the login form */ public function __construct(HttpKernelInterface $kernel, HttpUtils $httpUtils, $loginPath, $useForward = false) { $this->httpKernel = $kernel; $this->httpUtils = $httpUtils; $this->loginPath = $loginPath; $this->useForward = (Boolean) $useForward; } /** * {@inheritdoc} */ public function start(Request $request, AuthenticationException $authException = null) { if ($this->useForward) { $subRequest = $this->httpUtils->createRequest($request, $this->loginPath); $response = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); if (200 === $response->getStatusCode()) { $response->headers->set('X-Status-Code', 401); } return $response; } return $this->httpUtils->createRedirectResponse($request, $this->loginPath); } } PK!<ݐppLSymfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; /** * BasicAuthenticationEntryPoint starts an HTTP Basic authentication. * * @author Fabien Potencier */ class BasicAuthenticationEntryPoint implements AuthenticationEntryPointInterface { private $realmName; public function __construct($realmName) { $this->realmName = $realmName; } /** * {@inheritdoc} */ public function start(Request $request, AuthenticationException $authException = null) { $response = new Response(); $response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName)); $response->setStatusCode(401); return $response; } } PK!)'_++PSymfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * AuthenticationEntryPointInterface is the interface used to start the * authentication scheme. * * @author Fabien Potencier */ interface AuthenticationEntryPointInterface { /** * Starts the authentication scheme. * * @param Request $request The request that resulted in an AuthenticationException * @param AuthenticationException $authException The exception that started the authentication process * * @return Response */ public function start(Request $request, AuthenticationException $authException = null); } PK!tZ)K K MSymfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\NonceExpiredException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Psr\Log\LoggerInterface; /** * DigestAuthenticationEntryPoint starts an HTTP Digest authentication. * * @author Fabien Potencier */ class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterface { private $key; private $realmName; private $nonceValiditySeconds; private $logger; public function __construct($realmName, $key, $nonceValiditySeconds = 300, LoggerInterface $logger = null) { $this->realmName = $realmName; $this->key = $key; $this->nonceValiditySeconds = $nonceValiditySeconds; $this->logger = $logger; } /** * {@inheritdoc} */ public function start(Request $request, AuthenticationException $authException = null) { $expiryTime = microtime(true) + $this->nonceValiditySeconds * 1000; $signatureValue = md5($expiryTime.':'.$this->key); $nonceValue = $expiryTime.':'.$signatureValue; $nonceValueBase64 = base64_encode($nonceValue); $authenticateHeader = sprintf('Digest realm="%s", qop="auth", nonce="%s"', $this->realmName, $nonceValueBase64); if ($authException instanceof NonceExpiredException) { $authenticateHeader = $authenticateHeader.', stale="true"'; } if (null !== $this->logger) { $this->logger->debug(sprintf('WWW-Authenticate header sent to user agent: "%s"', $authenticateHeader)); } $response = new Response(); $response->headers->set('WWW-Authenticate', $authenticateHeader); $response->setStatusCode(401); return $response; } /** * @return string */ public function getKey() { return $this->key; } /** * @return string */ public function getRealmName() { return $this->realmName; } } PK!LSymfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\EntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; /** * RetryAuthenticationEntryPoint redirects URL based on the configured scheme. * * This entry point is not intended to work with HTTP post requests. * * @author Fabien Potencier */ class RetryAuthenticationEntryPoint implements AuthenticationEntryPointInterface { private $httpPort; private $httpsPort; public function __construct($httpPort = 80, $httpsPort = 443) { $this->httpPort = $httpPort; $this->httpsPort = $httpsPort; } /** * {@inheritdoc} */ public function start(Request $request, AuthenticationException $authException = null) { $scheme = $request->isSecure() ? 'http' : 'https'; if ('http' === $scheme && 80 != $this->httpPort) { $port = ':'.$this->httpPort; } elseif ('https' === $scheme && 443 != $this->httpsPort) { $port = ':'.$this->httpsPort; } else { $port = ''; } $qs = $request->getQueryString(); if (null !== $qs) { $qs = '?'.$qs; } $url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$request->getPathInfo().$qs; return new RedirectResponse($url, 301); } } PK!`C-Symfony/Component/Security/Http/HttpUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; /** * Encapsulates the logic needed to create sub-requests, redirect the user, and match URLs. * * @author Fabien Potencier */ class HttpUtils { private $urlGenerator; private $urlMatcher; /** * Constructor. * * @param UrlGeneratorInterface $urlGenerator A UrlGeneratorInterface instance * @param UrlMatcherInterface|RequestMatcherInterface $urlMatcher The URL or Request matcher * * @throws \InvalidArgumentException */ public function __construct(UrlGeneratorInterface $urlGenerator = null, $urlMatcher = null) { $this->urlGenerator = $urlGenerator; if ($urlMatcher !== null && !$urlMatcher instanceof UrlMatcherInterface && !$urlMatcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } $this->urlMatcher = $urlMatcher; } /** * Creates a redirect Response. * * @param Request $request A Request instance * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo)) * @param integer $status The status code * * @return RedirectResponse A RedirectResponse instance */ public function createRedirectResponse(Request $request, $path, $status = 302) { return new RedirectResponse($this->generateUri($request, $path), $status); } /** * Creates a Request. * * @param Request $request The current Request instance * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo)) * * @return Request A Request instance */ public function createRequest(Request $request, $path) { $newRequest = Request::create($this->generateUri($request, $path), 'get', array(), $request->cookies->all(), array(), $request->server->all()); if ($request->hasSession()) { $newRequest->setSession($request->getSession()); } if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) { $newRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR)); } if ($request->attributes->has(SecurityContextInterface::ACCESS_DENIED_ERROR)) { $newRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $request->attributes->get(SecurityContextInterface::ACCESS_DENIED_ERROR)); } if ($request->attributes->has(SecurityContextInterface::LAST_USERNAME)) { $newRequest->attributes->set(SecurityContextInterface::LAST_USERNAME, $request->attributes->get(SecurityContextInterface::LAST_USERNAME)); } return $newRequest; } /** * Checks that a given path matches the Request. * * @param Request $request A Request instance * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo)) * * @return Boolean true if the path is the same as the one from the Request, false otherwise */ public function checkRequestPath(Request $request, $path) { if ('/' !== $path[0]) { try { // matching a request is more powerful than matching a URL path + context, so try that first if ($this->urlMatcher instanceof RequestMatcherInterface) { $parameters = $this->urlMatcher->matchRequest($request); } else { $parameters = $this->urlMatcher->match($request->getPathInfo()); } return $path === $parameters['_route']; } catch (MethodNotAllowedException $e) { return false; } catch (ResourceNotFoundException $e) { return false; } } return $path === rawurldecode($request->getPathInfo()); } /** * Generates a URI, based on the given path or absolute URL. * * @param Request $request A Request instance * @param string $path A path (an absolute path (/foo), an absolute URL (http://...), or a route name (foo)) * * @return string An absolute URL * * @throws \LogicException */ public function generateUri($request, $path) { if (0 === strpos($path, 'http') || !$path) { return $path; } if ('/' === $path[0]) { return $request->getUriForPath($path); } if (null === $this->urlGenerator) { throw new \LogicException('You must provide a UrlGeneratorInterface instance to be able to use routes.'); } $url = $this->urlGenerator->generate($path, $request->attributes->all(), UrlGeneratorInterface::ABSOLUTE_URL); // unnecessary query string parameters must be removed from URL // (ie. query parameters that are presents in $attributes) // fortunately, they all are, so we have to remove entire query string $position = strpos($url, '?'); if (false !== $position) { $url = substr($url, 0, $position); } return $url; } } PK!^VNSymfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authorization; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Exception\AccessDeniedException; /** * This is used by the ExceptionListener to translate an AccessDeniedException * to a Response object. * * @author Johannes M. Schmitt */ interface AccessDeniedHandlerInterface { /** * Handles an access denied failure. * * @param Request $request * @param AccessDeniedException $accessDeniedException * * @return Response may return null */ public function handle(Request $request, AccessDeniedException $accessDeniedException); } PK!̗WSymfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\HttpFoundation\Request; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * UsernamePasswordFormAuthenticationListener is the default implementation of * an authentication via a simple form composed of a username and a password. * * @author Fabien Potencier */ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationListener { private $csrfTokenManager; /** * {@inheritdoc} */ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new InvalidArgumentException('The CSRF token manager should be an instance of CsrfProviderInterface or CsrfTokenManagerInterface.'); } parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge(array( 'username_parameter' => '_username', 'password_parameter' => '_password', 'csrf_parameter' => '_csrf_token', 'intention' => 'authenticate', 'post_only' => true, ), $options), $logger, $dispatcher); $this->csrfTokenManager = $csrfTokenManager; } /** * {@inheritdoc} */ protected function requiresAuthentication(Request $request) { if ($this->options['post_only'] && !$request->isMethod('POST')) { return false; } return parent::requiresAuthentication($request); } /** * {@inheritdoc} */ protected function attemptAuthentication(Request $request) { if (null !== $this->csrfTokenManager) { $csrfToken = $request->get($this->options['csrf_parameter'], null, true); if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['intention'], $csrfToken))) { throw new InvalidCsrfTokenException('Invalid CSRF token.'); } } if ($this->options['post_only']) { $username = trim($request->request->get($this->options['username_parameter'], null, true)); $password = $request->request->get($this->options['password_parameter'], null, true); } else { $username = trim($request->get($this->options['username_parameter'], null, true)); $password = $request->get($this->options['password_parameter'], null, true); } $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username); return $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey)); } } PK!nz+S ?Symfony/Component/Security/Http/Firewall/RememberMeListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * RememberMeListener implements authentication capabilities via a cookie * * @author Johannes M. Schmitt */ class RememberMeListener implements ListenerInterface { private $securityContext; private $rememberMeServices; private $authenticationManager; private $logger; private $dispatcher; /** * Constructor. * * @param SecurityContextInterface $securityContext * @param RememberMeServicesInterface $rememberMeServices * @param AuthenticationManagerInterface $authenticationManager * @param LoggerInterface $logger * @param EventDispatcherInterface $dispatcher */ public function __construct(SecurityContextInterface $securityContext, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { $this->securityContext = $securityContext; $this->rememberMeServices = $rememberMeServices; $this->authenticationManager = $authenticationManager; $this->logger = $logger; $this->dispatcher = $dispatcher; } /** * Handles remember-me cookie based authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { if (null !== $this->securityContext->getToken()) { return; } $request = $event->getRequest(); if (null === $token = $this->rememberMeServices->autoLogin($request)) { return; } try { $token = $this->authenticationManager->authenticate($token); $this->securityContext->setToken($token); if (null !== $this->dispatcher) { $loginEvent = new InteractiveLoginEvent($request, $token); $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent); } if (null !== $this->logger) { $this->logger->debug('SecurityContext populated with remember-me token.'); } } catch (AuthenticationException $failed) { if (null !== $this->logger) { $this->logger->warning( 'SecurityContext not populated with remember-me token as the' .' AuthenticationManager rejected the AuthenticationToken returned' .' by the RememberMeServices: '.$failed->getMessage() ); } $this->rememberMeServices->loginFail($request); } } } PK!lٯLSymfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; /** * AnonymousAuthenticationListener automatically adds a Token if none is * already present. * * @author Fabien Potencier */ class AnonymousAuthenticationListener implements ListenerInterface { private $context; private $key; private $logger; public function __construct(SecurityContextInterface $context, $key, LoggerInterface $logger = null) { $this->context = $context; $this->key = $key; $this->logger = $logger; } /** * Handles anonymous authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { if (null !== $this->context->getToken()) { return; } $this->context->setToken(new AnonymousToken($this->key, 'anon.', array())); if (null !== $this->logger) { $this->logger->info('Populated SecurityContext with an anonymous Token'); } } } PK!>Symfony/Component/Security/Http/Firewall/ListenerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** * Interface that must be implemented by firewall listeners * * @author Johannes M. Schmitt */ interface ListenerInterface { /** * This interface must be implemented by firewall listeners. * * @param GetResponseEvent $event */ public function handle(GetResponseEvent $event); } PK!|L@**;Symfony/Component/Security/Http/Firewall/LogoutListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Exception\LogoutException; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface; use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface; /** * LogoutListener logout users. * * @author Fabien Potencier */ class LogoutListener implements ListenerInterface { private $securityContext; private $options; private $handlers; private $successHandler; private $httpUtils; private $csrfTokenManager; /** * Constructor. * * @param SecurityContextInterface $securityContext * @param HttpUtils $httpUtils An HttpUtilsInterface instance * @param LogoutSuccessHandlerInterface $successHandler A LogoutSuccessHandlerInterface instance * @param array $options An array of options to process a logout attempt * @param CsrfTokenManagerInterface $csrfTokenManager A CsrfTokenManagerInterface instance */ public function __construct(SecurityContextInterface $securityContext, HttpUtils $httpUtils, LogoutSuccessHandlerInterface $successHandler, array $options = array(), $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new InvalidArgumentException('The CSRF token manager should be an instance of CsrfProviderInterface or CsrfTokenManagerInterface.'); } $this->securityContext = $securityContext; $this->httpUtils = $httpUtils; $this->options = array_merge(array( 'csrf_parameter' => '_csrf_token', 'intention' => 'logout', 'logout_path' => '/logout', ), $options); $this->successHandler = $successHandler; $this->csrfTokenManager = $csrfTokenManager; $this->handlers = array(); } /** * Adds a logout handler * * @param LogoutHandlerInterface $handler */ public function addHandler(LogoutHandlerInterface $handler) { $this->handlers[] = $handler; } /** * Performs the logout if requested * * If a CsrfTokenManagerInterface instance is available, it will be used to * validate the request. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws LogoutException if the CSRF token is invalid * @throws \RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (!$this->requiresLogout($request)) { return; } if (null !== $this->csrfTokenManager) { $csrfToken = $request->get($this->options['csrf_parameter'], null, true); if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['intention'], $csrfToken))) { throw new LogoutException('Invalid CSRF token.'); } } $response = $this->successHandler->onLogoutSuccess($request); if (!$response instanceof Response) { throw new \RuntimeException('Logout Success Handler did not return a Response.'); } // handle multiple logout attempts gracefully if ($token = $this->securityContext->getToken()) { foreach ($this->handlers as $handler) { $handler->logout($request, $response, $token); } } $this->securityContext->setToken(null); $event->setResponse($response); } /** * Whether this request is asking for logout. * * The default implementation only processed requests to a specific path, * but a subclass could change this to logout requests where * certain parameters is present. * * @param Request $request * * @return Boolean */ protected function requiresLogout(Request $request) { return $this->httpUtils->checkRequestPath($request, $this->options['logout_path']); } } PK!B b  ?Symfony/Component/Security/Http/Firewall/SwitchUserListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Role\SwitchUserRole; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Http\Event\SwitchUserEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * SwitchUserListener allows a user to impersonate another one temporarily * (like the Unix su command). * * @author Fabien Potencier */ class SwitchUserListener implements ListenerInterface { private $securityContext; private $provider; private $userChecker; private $providerKey; private $accessDecisionManager; private $usernameParameter; private $role; private $logger; private $dispatcher; /** * Constructor. */ public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->provider = $provider; $this->userChecker = $userChecker; $this->providerKey = $providerKey; $this->accessDecisionManager = $accessDecisionManager; $this->usernameParameter = $usernameParameter; $this->role = $role; $this->logger = $logger; $this->dispatcher = $dispatcher; } /** * Handles the switch to another user. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws \LogicException if switching to a user failed */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (!$request->get($this->usernameParameter)) { return; } if ('_exit' === $request->get($this->usernameParameter)) { $this->securityContext->setToken($this->attemptExitUser($request)); } else { try { $this->securityContext->setToken($this->attemptSwitchUser($request)); } catch (AuthenticationException $e) { throw new \LogicException(sprintf('Switch User failed: "%s"', $e->getMessage())); } } $request->query->remove($this->usernameParameter); $request->server->set('QUERY_STRING', http_build_query($request->query->all())); $response = new RedirectResponse($request->getUri(), 302); $event->setResponse($response); } /** * Attempts to switch to another user. * * @param Request $request A Request instance * * @return TokenInterface|null The new TokenInterface if successfully switched, null otherwise * * @throws \LogicException * @throws AccessDeniedException */ private function attemptSwitchUser(Request $request) { $token = $this->securityContext->getToken(); $originalToken = $this->getOriginalToken($token); if (false !== $originalToken) { if ($token->getUsername() === $request->get($this->usernameParameter)) { return $token; } else { throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername())); } } if (false === $this->accessDecisionManager->decide($token, array($this->role))) { throw new AccessDeniedException(); } $username = $request->get($this->usernameParameter); if (null !== $this->logger) { $this->logger->info(sprintf('Attempt to switch to user "%s"', $username)); } $user = $this->provider->loadUserByUsername($username); $this->userChecker->checkPostAuth($user); $roles = $user->getRoles(); $roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->securityContext->getToken()); $token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles); if (null !== $this->dispatcher) { $switchEvent = new SwitchUserEvent($request, $token->getUser()); $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent); } return $token; } /** * Attempts to exit from an already switched user. * * @param Request $request A Request instance * * @return TokenInterface The original TokenInterface instance * * @throws AuthenticationCredentialsNotFoundException */ private function attemptExitUser(Request $request) { if (false === $original = $this->getOriginalToken($this->securityContext->getToken())) { throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.'); } if (null !== $this->dispatcher) { $switchEvent = new SwitchUserEvent($request, $original->getUser()); $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent); } return $original; } /** * Gets the original Token from a switched one. * * @param TokenInterface $token A switched TokenInterface instance * * @return TokenInterface|false The original TokenInterface instance, false if the current TokenInterface is not switched */ private function getOriginalToken(TokenInterface $token) { foreach ($token->getRoles() as $role) { if ($role instanceof SwitchUserRole) { return $role->getSource(); } } return false; } } PK!(T b!b!>Symfony/Component/Security/Http/Firewall/ExceptionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Core\Exception\AccountStatusException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException; use Symfony\Component\Security\Core\Exception\LogoutException; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\HttpFoundation\Request; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * ExceptionListener catches authentication exception and converts them to * Response instances. * * @author Fabien Potencier */ class ExceptionListener { private $context; private $providerKey; private $accessDeniedHandler; private $authenticationEntryPoint; private $authenticationTrustResolver; private $errorPage; private $logger; private $httpUtils; public function __construct(SecurityContextInterface $context, AuthenticationTrustResolverInterface $trustResolver, HttpUtils $httpUtils, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null, LoggerInterface $logger = null) { $this->context = $context; $this->accessDeniedHandler = $accessDeniedHandler; $this->httpUtils = $httpUtils; $this->providerKey = $providerKey; $this->authenticationEntryPoint = $authenticationEntryPoint; $this->authenticationTrustResolver = $trustResolver; $this->errorPage = $errorPage; $this->logger = $logger; } /** * Registers a onKernelException listener to take care of security exceptions. * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance */ public function register(EventDispatcherInterface $dispatcher) { $dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException')); } /** * Unregisters the dispatcher. * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance */ public function unregister(EventDispatcherInterface $dispatcher) { $dispatcher->removeListener(KernelEvents::EXCEPTION, array($this, 'onKernelException')); } /** * Handles security related exceptions. * * @param GetResponseForExceptionEvent $event An GetResponseForExceptionEvent instance */ public function onKernelException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); do { if ($exception instanceof AuthenticationException) { return $this->handleAuthenticationException($event, $exception); } elseif ($exception instanceof AccessDeniedException) { return $this->handleAccessDeniedException($event, $exception); } elseif ($exception instanceof LogoutException) { return $this->handleLogoutException($event, $exception); } } while (null !== $exception = $exception->getPrevious()); } private function handleAuthenticationException(GetResponseForExceptionEvent $event, AuthenticationException $exception) { if (null !== $this->logger) { $this->logger->info(sprintf('Authentication exception occurred; redirecting to authentication entry point (%s)', $exception->getMessage())); } try { $event->setResponse($this->startAuthentication($event->getRequest(), $exception)); } catch (\Exception $e) { $event->setException($e); } } private function handleAccessDeniedException(GetResponseForExceptionEvent $event, AccessDeniedException $exception) { $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception)); $token = $this->context->getToken(); if (!$this->authenticationTrustResolver->isFullFledged($token)) { if (null !== $this->logger) { $this->logger->debug(sprintf('Access is denied (user is not fully authenticated) by "%s" at line %s; redirecting to authentication entry point', $exception->getFile(), $exception->getLine())); } try { $insufficientAuthenticationException = new InsufficientAuthenticationException('Full authentication is required to access this resource.', 0, $exception); $insufficientAuthenticationException->setToken($token); $event->setResponse($this->startAuthentication($event->getRequest(), $insufficientAuthenticationException)); } catch (\Exception $e) { $event->setException($e); } return; } if (null !== $this->logger) { $this->logger->debug(sprintf('Access is denied (and user is neither anonymous, nor remember-me) by "%s" at line %s', $exception->getFile(), $exception->getLine())); } try { if (null !== $this->accessDeniedHandler) { $response = $this->accessDeniedHandler->handle($event->getRequest(), $exception); if ($response instanceof Response) { $event->setResponse($response); } } elseif (null !== $this->errorPage) { $subRequest = $this->httpUtils->createRequest($event->getRequest(), $this->errorPage); $subRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $exception); $event->setResponse($event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true)); } } catch (\Exception $e) { if (null !== $this->logger) { $this->logger->error(sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage())); } $event->setException(new \RuntimeException('Exception thrown when handling an exception.', 0, $e)); } } private function handleLogoutException(GetResponseForExceptionEvent $event, LogoutException $exception) { if (null !== $this->logger) { $this->logger->info(sprintf('Logout exception occurred; wrapping with AccessDeniedHttpException (%s)', $exception->getMessage())); } } /** * @param Request $request * @param AuthenticationException $authException * * @return Response * @throws AuthenticationException */ private function startAuthentication(Request $request, AuthenticationException $authException) { if (null === $this->authenticationEntryPoint) { throw $authException; } if (null !== $this->logger) { $this->logger->debug('Calling Authentication entry point'); } $this->setTargetPath($request); if ($authException instanceof AccountStatusException) { // remove the security token to prevent infinite redirect loops $this->context->setToken(null); } return $this->authenticationEntryPoint->start($request, $authException); } /** * @param Request $request */ protected function setTargetPath(Request $request) { // session isn't required when using HTTP basic authentication mechanism for example if ($request->hasSession() && $request->isMethodSafe()) { $request->getSession()->set('_security.'.$this->providerKey.'.target_path', $request->getUri()); } } } PK!׺=GSymfony/Component/Security/Http/Firewall/X509AuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * X509 authentication listener. * * @author Fabien Potencier */ class X509AuthenticationListener extends AbstractPreAuthenticatedListener { private $userKey; private $credentialKey; public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $userKey = 'SSL_CLIENT_S_DN_Email', $credentialKey = 'SSL_CLIENT_S_DN', LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { parent::__construct($securityContext, $authenticationManager, $providerKey, $logger, $dispatcher); $this->userKey = $userKey; $this->credentialKey = $credentialKey; } /** * {@inheritdoc} */ protected function getPreAuthenticatedData(Request $request) { if (!$request->server->has($this->userKey)) { throw new BadCredentialsException(sprintf('SSL key was not found: %s', $this->userKey)); } return array($request->server->get($this->userKey), $request->server->get($this->credentialKey, '')); } } PK!׿ͼ ISymfony/Component/Security/Http/Firewall/DigestAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\NonceExpiredException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\AuthenticationException; /** * DigestAuthenticationListener implements Digest HTTP authentication. * * @author Fabien Potencier */ class DigestAuthenticationListener implements ListenerInterface { private $securityContext; private $provider; private $providerKey; private $authenticationEntryPoint; private $logger; public function __construct(SecurityContextInterface $securityContext, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->provider = $provider; $this->providerKey = $providerKey; $this->authenticationEntryPoint = $authenticationEntryPoint; $this->logger = $logger; } /** * Handles digest authentication. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws AuthenticationServiceException */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (!$header = $request->server->get('PHP_AUTH_DIGEST')) { return; } $digestAuth = new DigestData($header); if (null !== $token = $this->securityContext->getToken()) { if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $digestAuth->getUsername()) { return; } } if (null !== $this->logger) { $this->logger->debug(sprintf('Digest Authorization header received from user agent: %s', $header)); } try { $digestAuth->validateAndDecode($this->authenticationEntryPoint->getKey(), $this->authenticationEntryPoint->getRealmName()); } catch (BadCredentialsException $e) { $this->fail($event, $request, $e); return; } try { $user = $this->provider->loadUserByUsername($digestAuth->getUsername()); if (null === $user) { throw new AuthenticationServiceException('AuthenticationDao returned null, which is an interface contract violation'); } $serverDigestMd5 = $digestAuth->calculateServerDigest($user->getPassword(), $request->getMethod()); } catch (UsernameNotFoundException $notFound) { $this->fail($event, $request, new BadCredentialsException(sprintf('Username %s not found.', $digestAuth->getUsername()))); return; } if ($serverDigestMd5 !== $digestAuth->getResponse()) { if (null !== $this->logger) { $this->logger->debug(sprintf("Expected response: '%s' but received: '%s'; is AuthenticationDao returning clear text passwords?", $serverDigestMd5, $digestAuth->getResponse())); } $this->fail($event, $request, new BadCredentialsException('Incorrect response')); return; } if ($digestAuth->isNonceExpired()) { $this->fail($event, $request, new NonceExpiredException('Nonce has expired/timed out.')); return; } if (null !== $this->logger) { $this->logger->info(sprintf('Authentication success for user "%s" with response "%s"', $digestAuth->getUsername(), $digestAuth->getResponse())); } $this->securityContext->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey)); } private function fail(GetResponseEvent $event, Request $request, AuthenticationException $authException) { $token = $this->securityContext->getToken(); if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) { $this->securityContext->setToken(null); } if (null !== $this->logger) { $this->logger->info($authException); } $event->setResponse($this->authenticationEntryPoint->start($request, $authException)); } } class DigestData { private $elements = array(); private $header; private $nonceExpiryTime; public function __construct($header) { $this->header = $header; preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER); foreach ($matches as $match) { if (isset($match[1]) && isset($match[3])) { $this->elements[$match[1]] = isset($match[4]) ? $match[4] : $match[3]; } } } public function getResponse() { return $this->elements['response']; } public function getUsername() { return strtr($this->elements['username'], array("\\\"" => "\"", "\\\\" => "\\")); } public function validateAndDecode($entryPointKey, $expectedRealm) { if ($keys = array_diff(array('username', 'realm', 'nonce', 'uri', 'response'), array_keys($this->elements))) { throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s" (%s)', $this->header, implode(', ', $keys))); } if ('auth' === $this->elements['qop']) { if (!isset($this->elements['nc']) || !isset($this->elements['cnonce'])) { throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s"', $this->header)); } } if ($expectedRealm !== $this->elements['realm']) { throw new BadCredentialsException(sprintf('Response realm name "%s" does not match system realm name of "%s".', $this->elements['realm'], $expectedRealm)); } if (false === $nonceAsPlainText = base64_decode($this->elements['nonce'])) { throw new BadCredentialsException(sprintf('Nonce is not encoded in Base64; received nonce "%s".', $this->elements['nonce'])); } $nonceTokens = explode(':', $nonceAsPlainText); if (2 !== count($nonceTokens)) { throw new BadCredentialsException(sprintf('Nonce should have yielded two tokens but was "%s".', $nonceAsPlainText)); } $this->nonceExpiryTime = $nonceTokens[0]; if (md5($this->nonceExpiryTime.':'.$entryPointKey) !== $nonceTokens[1]) { throw new BadCredentialsException(sprintf('Nonce token compromised "%s".', $nonceAsPlainText)); } } public function calculateServerDigest($password, $httpMethod) { $a2Md5 = md5(strtoupper($httpMethod).':'.$this->elements['uri']); $a1Md5 = md5($this->elements['username'].':'.$this->elements['realm'].':'.$password); $digest = $a1Md5.':'.$this->elements['nonce']; if (!isset($this->elements['qop'])) { } elseif ('auth' === $this->elements['qop']) { $digest .= ':'.$this->elements['nc'].':'.$this->elements['cnonce'].':'.$this->elements['qop']; } else { throw new \InvalidArgumentException('This method does not support a qop: "%s".', $this->elements['qop']); } $digest .= ':'.$a2Md5; return md5($digest); } public function isNonceExpired() { return $this->nonceExpiryTime < microtime(true); } } PK!~k<Symfony/Component/Security/Http/Firewall/ChannelListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Http\AccessMapInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** * ChannelListener switches the HTTP protocol based on the access control * configuration. * * @author Fabien Potencier */ class ChannelListener implements ListenerInterface { private $map; private $authenticationEntryPoint; private $logger; public function __construct(AccessMapInterface $map, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null) { $this->map = $map; $this->authenticationEntryPoint = $authenticationEntryPoint; $this->logger = $logger; } /** * Handles channel management. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); list($attributes, $channel) = $this->map->getPatterns($request); if ('https' === $channel && !$request->isSecure()) { if (null !== $this->logger) { $this->logger->info('Redirecting to HTTPS'); } $response = $this->authenticationEntryPoint->start($request); $event->setResponse($response); return; } if ('http' === $channel && $request->isSecure()) { if (null !== $this->logger) { $this->logger->info('Redirecting to HTTP'); } $response = $this->authenticationEntryPoint->start($request); $event->setResponse($response); } } } PK! 6'6'KSymfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\SessionUnavailableException; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\Security\Http\HttpUtils; /** * The AbstractAuthenticationListener is the preferred base class for all * browser-/HTTP-based authentication requests. * * Subclasses likely have to implement the following: * - an TokenInterface to hold authentication related data * - an AuthenticationProvider to perform the actual authentication of the * token, retrieve the UserInterface implementation from a database, and * perform the specific account checks using the UserChecker * * By default, this listener only is active for a specific path, e.g. * /login_check. If you want to change this behavior, you can overwrite the * requiresAuthentication() method. * * @author Fabien Potencier * @author Johannes M. Schmitt */ abstract class AbstractAuthenticationListener implements ListenerInterface { protected $options; protected $logger; protected $authenticationManager; protected $providerKey; protected $httpUtils; private $securityContext; private $sessionStrategy; private $dispatcher; private $successHandler; private $failureHandler; private $rememberMeServices; /** * Constructor. * * @param SecurityContextInterface $securityContext A SecurityContext instance * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance * @param SessionAuthenticationStrategyInterface $sessionStrategy * @param HttpUtils $httpUtils An HttpUtilsInterface instance * @param string $providerKey * @param AuthenticationSuccessHandlerInterface $successHandler * @param AuthenticationFailureHandlerInterface $failureHandler * @param array $options An array of options for the processing of a * successful, or failed authentication attempt * @param LoggerInterface $logger A LoggerInterface instance * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * * @throws \InvalidArgumentException */ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; $this->sessionStrategy = $sessionStrategy; $this->providerKey = $providerKey; $this->successHandler = $successHandler; $this->failureHandler = $failureHandler; $this->options = array_merge(array( 'check_path' => '/login_check', 'login_path' => '/login', 'always_use_default_target_path' => false, 'default_target_path' => '/', 'target_path_parameter' => '_target_path', 'use_referer' => false, 'failure_path' => null, 'failure_forward' => false, 'require_previous_session' => true, ), $options); $this->logger = $logger; $this->dispatcher = $dispatcher; $this->httpUtils = $httpUtils; } /** * Sets the RememberMeServices implementation to use * * @param RememberMeServicesInterface $rememberMeServices */ public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices) { $this->rememberMeServices = $rememberMeServices; } /** * Handles form based authentication. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws \RuntimeException * @throws SessionUnavailableException */ final public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (!$this->requiresAuthentication($request)) { return; } if (!$request->hasSession()) { throw new \RuntimeException('This authentication method requires a session.'); } try { if ($this->options['require_previous_session'] && !$request->hasPreviousSession()) { throw new SessionUnavailableException('Your session has timed out, or you have disabled cookies.'); } if (null === $returnValue = $this->attemptAuthentication($request)) { return; } if ($returnValue instanceof TokenInterface) { $this->sessionStrategy->onAuthentication($request, $returnValue); $response = $this->onSuccess($event, $request, $returnValue); } elseif ($returnValue instanceof Response) { $response = $returnValue; } else { throw new \RuntimeException('attemptAuthentication() must either return a Response, an implementation of TokenInterface, or null.'); } } catch (AuthenticationException $e) { $response = $this->onFailure($event, $request, $e); } $event->setResponse($response); } /** * Whether this request requires authentication. * * The default implementation only processes requests to a specific path, * but a subclass could change this to only authenticate requests where a * certain parameters is present. * * @param Request $request * * @return Boolean */ protected function requiresAuthentication(Request $request) { return $this->httpUtils->checkRequestPath($request, $this->options['check_path']); } /** * Performs authentication. * * @param Request $request A Request instance * * @return TokenInterface|Response|null The authenticated token, null if full authentication is not possible, or a Response * * @throws AuthenticationException if the authentication fails */ abstract protected function attemptAuthentication(Request $request); private function onFailure(GetResponseEvent $event, Request $request, AuthenticationException $failed) { if (null !== $this->logger) { $this->logger->info(sprintf('Authentication request failed: %s', $failed->getMessage())); } $token = $this->securityContext->getToken(); if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) { $this->securityContext->setToken(null); } $response = $this->failureHandler->onAuthenticationFailure($request, $failed); if (!$response instanceof Response) { throw new \RuntimeException('Authentication Failure Handler did not return a Response.'); } return $response; } private function onSuccess(GetResponseEvent $event, Request $request, TokenInterface $token) { if (null !== $this->logger) { $this->logger->info(sprintf('User "%s" has been authenticated successfully', $token->getUsername())); } $this->securityContext->setToken($token); $session = $request->getSession(); $session->remove(SecurityContextInterface::AUTHENTICATION_ERROR); $session->remove(SecurityContextInterface::LAST_USERNAME); if (null !== $this->dispatcher) { $loginEvent = new InteractiveLoginEvent($request, $token); $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent); } $response = $this->successHandler->onAuthenticationSuccess($request, $token); if (!$response instanceof Response) { throw new \RuntimeException('Authentication Success Handler did not return a Response.'); } if (null !== $this->rememberMeServices) { $this->rememberMeServices->loginSuccess($request, $response, $token); } return $response; } } PK!"?<Symfony/Component/Security/Http/Firewall/ContextListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * ContextListener manages the SecurityContext persistence through a session. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class ContextListener implements ListenerInterface { private $context; private $contextKey; private $logger; private $userProviders; private $dispatcher; private $registered; public function __construct(SecurityContextInterface $context, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { if (empty($contextKey)) { throw new \InvalidArgumentException('$contextKey must not be empty.'); } foreach ($userProviders as $userProvider) { if (!$userProvider instanceof UserProviderInterface) { throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "Symfony\Component\Security\Core\User\UserProviderInterface".', get_class($userProvider))); } } $this->context = $context; $this->userProviders = $userProviders; $this->contextKey = $contextKey; $this->logger = $logger; $this->dispatcher = $dispatcher; } /** * Reads the SecurityContext from the session. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { if (!$this->registered && null !== $this->dispatcher && $event->isMasterRequest()) { $this->dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse')); $this->registered = true; } $request = $event->getRequest(); $session = $request->hasPreviousSession() ? $request->getSession() : null; if (null === $session || null === $token = $session->get('_security_'.$this->contextKey)) { $this->context->setToken(null); return; } $token = unserialize($token); if (null !== $this->logger) { $this->logger->debug('Read SecurityContext from the session'); } if ($token instanceof TokenInterface) { $token = $this->refreshUser($token); } elseif (null !== $token) { if (null !== $this->logger) { $this->logger->warning(sprintf('Session includes a "%s" where a security token is expected', is_object($token) ? get_class($token) : gettype($token))); } $token = null; } $this->context->setToken($token); } /** * Writes the SecurityContext to the session. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest()) { return; } if (!$event->getRequest()->hasSession()) { return; } if (null !== $this->logger) { $this->logger->debug('Write SecurityContext in the session'); } $request = $event->getRequest(); $session = $request->getSession(); if (null === $session) { return; } if ((null === $token = $this->context->getToken()) || ($token instanceof AnonymousToken)) { if ($request->hasPreviousSession()) { $session->remove('_security_'.$this->contextKey); } } else { $session->set('_security_'.$this->contextKey, serialize($token)); } } /** * Refreshes the user by reloading it from the user provider * * @param TokenInterface $token * * @return TokenInterface|null * * @throws \RuntimeException */ private function refreshUser(TokenInterface $token) { $user = $token->getUser(); if (!$user instanceof UserInterface) { return $token; } if (null !== $this->logger) { $this->logger->debug(sprintf('Reloading user from user provider.')); } foreach ($this->userProviders as $provider) { try { $refreshedUser = $provider->refreshUser($user); $token->setUser($refreshedUser); if (null !== $this->logger) { $this->logger->debug(sprintf('Username "%s" was reloaded from user provider.', $refreshedUser->getUsername())); } return $token; } catch (UnsupportedUserException $unsupported) { // let's try the next user provider } catch (UsernameNotFoundException $notFound) { if (null !== $this->logger) { $this->logger->warning(sprintf('Username "%s" could not be found.', $notFound->getUsername())); } return null; } } throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user))); } } PK!MSymfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; use Psr\Log\LoggerInterface; /** * @author Jordi Boggiano */ class SimpleFormAuthenticationListener extends AbstractAuthenticationListener { private $simpleAuthenticator; private $csrfTokenManager; /** * Constructor. * * @param SecurityContextInterface $securityContext A SecurityContext instance * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance * @param SessionAuthenticationStrategyInterface $sessionStrategy * @param HttpUtils $httpUtils An HttpUtilsInterface instance * @param string $providerKey * @param AuthenticationSuccessHandlerInterface $successHandler * @param AuthenticationFailureHandlerInterface $failureHandler * @param array $options An array of options for the processing of a * successful, or failed authentication attempt * @param LoggerInterface $logger A LoggerInterface instance * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param SimpleFormAuthenticatorInterface $simpleAuthenticator A SimpleFormAuthenticatorInterface instance * @param CsrfTokenManagerInterface $csrfTokenManager A CsrfTokenManagerInterface instance */ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null, SimpleFormAuthenticatorInterface $simpleAuthenticator = null) { if (!$simpleAuthenticator) { throw new \InvalidArgumentException('Missing simple authenticator'); } if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new InvalidArgumentException('The CSRF token manager should be an instance of CsrfProviderInterface or CsrfTokenManagerInterface.'); } $this->simpleAuthenticator = $simpleAuthenticator; $this->csrfTokenManager = $csrfTokenManager; $options = array_merge(array( 'username_parameter' => '_username', 'password_parameter' => '_password', 'csrf_parameter' => '_csrf_token', 'intention' => 'authenticate', 'post_only' => true, ), $options); parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, $options, $logger, $dispatcher); } /** * {@inheritdoc} */ protected function requiresAuthentication(Request $request) { if ($this->options['post_only'] && !$request->isMethod('POST')) { return false; } return parent::requiresAuthentication($request); } /** * {@inheritdoc} */ protected function attemptAuthentication(Request $request) { if (null !== $this->csrfTokenManager) { $csrfToken = $request->get($this->options['csrf_parameter'], null, true); if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['intention'], $csrfToken))) { throw new InvalidCsrfTokenException('Invalid CSRF token.'); } } if ($this->options['post_only']) { $username = trim($request->request->get($this->options['username_parameter'], null, true)); $password = $request->request->get($this->options['password_parameter'], null, true); } else { $username = trim($request->get($this->options['username_parameter'], null, true)); $password = $request->get($this->options['password_parameter'], null, true); } $request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username); $token = $this->simpleAuthenticator->createToken($request, $username, $password, $this->providerKey); return $this->authenticationManager->authenticate($token); } } PK!+/Z Z ;Symfony/Component/Security/Http/Firewall/AccessListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Http\AccessMapInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; /** * AccessListener enforces access control rules. * * @author Fabien Potencier */ class AccessListener implements ListenerInterface { private $context; private $accessDecisionManager; private $map; private $authManager; public function __construct(SecurityContextInterface $context, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, AuthenticationManagerInterface $authManager) { $this->context = $context; $this->accessDecisionManager = $accessDecisionManager; $this->map = $map; $this->authManager = $authManager; } /** * Handles access authorization. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws AccessDeniedException * @throws AuthenticationCredentialsNotFoundException */ public function handle(GetResponseEvent $event) { if (null === $token = $this->context->getToken()) { throw new AuthenticationCredentialsNotFoundException('A Token was not found in the SecurityContext.'); } $request = $event->getRequest(); list($attributes, $channel) = $this->map->getPatterns($request); if (null === $attributes) { return; } if (!$token->isAuthenticated()) { $token = $this->authManager->authenticate($token); $this->context->setToken($token); } if (!$this->accessDecisionManager->decide($token, $attributes, $request)) { throw new AccessDeniedException(); } } } PK!ZMSymfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * AbstractPreAuthenticatedListener is the base class for all listener that * authenticates users based on a pre-authenticated request (like a certificate * for instance). * * @author Fabien Potencier */ abstract class AbstractPreAuthenticatedListener implements ListenerInterface { protected $logger; private $securityContext; private $authenticationManager; private $providerKey; private $dispatcher; public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; $this->providerKey = $providerKey; $this->logger = $logger; $this->dispatcher = $dispatcher; } /** * Handles pre-authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ final public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (null !== $this->logger) { $this->logger->debug(sprintf('Checking secure context token: %s', $this->securityContext->getToken())); } try { list($user, $credentials) = $this->getPreAuthenticatedData($request); } catch (BadCredentialsException $exception) { $this->clearToken($exception); return; } if (null !== $token = $this->securityContext->getToken()) { if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getProviderKey() && $token->isAuthenticated() && $token->getUsername() === $user) { return; } } if (null !== $this->logger) { $this->logger->debug(sprintf('Trying to pre-authenticate user "%s"', $user)); } try { $token = $this->authenticationManager->authenticate(new PreAuthenticatedToken($user, $credentials, $this->providerKey)); if (null !== $this->logger) { $this->logger->info(sprintf('Authentication success: %s', $token)); } $this->securityContext->setToken($token); if (null !== $this->dispatcher) { $loginEvent = new InteractiveLoginEvent($request, $token); $this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent); } } catch (AuthenticationException $failed) { $this->clearToken($failed); } } /** * Clears a PreAuthenticatedToken for this provider (if present) * * @param AuthenticationException $exception */ private function clearToken(AuthenticationException $exception) { $token = $this->securityContext->getToken(); if ($token instanceof PreAuthenticatedToken && $this->providerKey === $token->getProviderKey()) { $this->securityContext->setToken(null); if (null !== $this->logger) { $this->logger->info(sprintf("Cleared security context due to exception: %s", $exception->getMessage())); } } } /** * Gets the user and credentials from the Request. * * @param Request $request A Request instance * * @return array An array composed of the user and the credentials */ abstract protected function getPreAuthenticatedData(Request $request); } PK!nLSymfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; /** * SimplePreAuthenticationListener implements simple proxying to an authenticator. * * @author Jordi Boggiano */ class SimplePreAuthenticationListener implements ListenerInterface { private $securityContext; private $authenticationManager; private $providerKey; private $simpleAuthenticator; private $logger; /** * Constructor. * * @param SecurityContextInterface $securityContext A SecurityContext instance * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance * @param string $providerKey * @param SimplePreAuthenticatorInterface $simpleAuthenticator A SimplePreAuthenticatorInterface instance * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, SimplePreAuthenticatorInterface $simpleAuthenticator, LoggerInterface $logger = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; $this->providerKey = $providerKey; $this->simpleAuthenticator = $simpleAuthenticator; $this->logger = $logger; } /** * Handles basic authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (null !== $this->logger) { $this->logger->info(sprintf('Attempting simple pre-authorization %s', $this->providerKey)); } if (null !== $this->securityContext->getToken() && !$this->securityContext->getToken() instanceof AnonymousToken) { return; } try { $token = $this->simpleAuthenticator->createToken($request, $this->providerKey); $token = $this->authenticationManager->authenticate($token); $this->securityContext->setToken($token); } catch (AuthenticationException $e) { $this->securityContext->setToken(null); if (null !== $this->logger) { $this->logger->info(sprintf('Authentication request failed: %s', $e->getMessage())); } if ($this->simpleAuthenticator instanceof AuthenticationFailureHandlerInterface) { $response = $this->simpleAuthenticator->onAuthenticationFailure($request, $e); if ($response instanceof Response) { $event->setResponse($response); } elseif (null !== $response) { throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationFailure method must return null or a Response object', get_class($this->simpleAuthenticator))); } } return; } if ($this->simpleAuthenticator instanceof AuthenticationSuccessHandlerInterface) { $response = $this->simpleAuthenticator->onAuthenticationSuccess($request, $token); if ($response instanceof Response) { $event->setResponse($response); } elseif (null !== $response) { throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationSuccess method must return null or a Response object', get_class($this->simpleAuthenticator))); } } } } PK!&! HSymfony/Component/Security/Http/Firewall/BasicAuthenticationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; /** * BasicAuthenticationListener implements Basic HTTP authentication. * * @author Fabien Potencier */ class BasicAuthenticationListener implements ListenerInterface { private $securityContext; private $authenticationManager; private $providerKey; private $authenticationEntryPoint; private $logger; private $ignoreFailure; public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; $this->providerKey = $providerKey; $this->authenticationEntryPoint = $authenticationEntryPoint; $this->logger = $logger; $this->ignoreFailure = false; } /** * Handles basic authentication. * * @param GetResponseEvent $event A GetResponseEvent instance */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (false === $username = $request->headers->get('PHP_AUTH_USER', false)) { return; } if (null !== $token = $this->securityContext->getToken()) { if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $username) { return; } } if (null !== $this->logger) { $this->logger->info(sprintf('Basic Authentication Authorization header found for user "%s"', $username)); } try { $token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey)); $this->securityContext->setToken($token); } catch (AuthenticationException $failed) { $token = $this->securityContext->getToken(); if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) { $this->securityContext->setToken(null); } if (null !== $this->logger) { $this->logger->info(sprintf('Authentication request failed for user "%s": %s', $username, $failed->getMessage())); } if ($this->ignoreFailure) { return; } $event->setResponse($this->authenticationEntryPoint->start($request, $failed)); } } } PK!2j-Symfony/Component/Security/Http/AccessMap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpFoundation\RequestMatcherInterface; use Symfony\Component\HttpFoundation\Request; /** * AccessMap allows configuration of different access control rules for * specific parts of the website. * * @author Fabien Potencier */ class AccessMap implements AccessMapInterface { private $map = array(); /** * Constructor. * * @param RequestMatcherInterface $requestMatcher A RequestMatcherInterface instance * @param array $attributes An array of attributes to pass to the access decision manager (like roles) * @param string|null $channel The channel to enforce (http, https, or null) */ public function add(RequestMatcherInterface $requestMatcher, array $attributes = array(), $channel = null) { $this->map[] = array($requestMatcher, $attributes, $channel); } /** * {@inheritDoc} */ public function getPatterns(Request $request) { foreach ($this->map as $elements) { if (null === $elements[0] || $elements[0]->matches($request)) { return array($elements[1], $elements[2]); } } return array(null, null); } } PK!/``6Symfony/Component/Security/Http/AccessMapInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpFoundation\Request; /** * AccessMap allows configuration of different access control rules for * specific parts of the website. * * @author Fabien Potencier * @author Kris Wallsmith */ interface AccessMapInterface { /** * Returns security attributes and required channel for the supplied request. * * @param Request $request The current request * * @return array A tuple of security attributes and the required channel */ public function getPatterns(Request $request); } PK!\\8Symfony/Component/Security/Http/FirewallMapInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; use Symfony\Component\HttpFoundation\Request; /** * This interface must be implemented by firewall maps. * * @author Johannes M. Schmitt */ interface FirewallMapInterface { /** * Returns the authentication listeners, and the exception listener to use * for the given request. * * If there are no authentication listeners, the first inner array must be * empty. * * If there is no exception listener, the second element of the outer array * must be null. * * @param Request $request * * @return array of the format array(array(AuthenticationListener), ExceptionListener) */ public function getListeners(Request $request); } PK! z JSymfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Interface that needs to be implemented by classes which provide remember-me * capabilities. * * We provide two implementations out-of-the-box: * - TokenBasedRememberMeServices (does not require a TokenProvider) * - PersistentTokenBasedRememberMeServices (requires a TokenProvider) * * @author Johannes M. Schmitt */ interface RememberMeServicesInterface { /** * This attribute name can be used by the implementation if it needs to set * a cookie on the Request when there is no actual Response, yet. * * @var string */ const COOKIE_ATTR_NAME = '_security_remember_me_cookie'; /** * This method will be called whenever the SecurityContext does not contain * an TokenInterface object and the framework wishes to provide an implementation * with an opportunity to authenticate the request using remember-me capabilities. * * No attempt whatsoever is made to determine whether the browser has requested * remember-me services or presented a valid cookie. Any and all such determinations * are left to the implementation of this method. * * If a browser has presented an unauthorised cookie for whatever reason, * make sure to throw an AuthenticationException as this will consequentially * result in a call to loginFail() and therefore an invalidation of the cookie. * * @param Request $request * * @return TokenInterface */ public function autoLogin(Request $request); /** * Called whenever an interactive authentication attempt was made, but the * credentials supplied by the user were missing or otherwise invalid. * * This method needs to take care of invalidating the cookie. * * @param Request $request */ public function loginFail(Request $request); /** * Called whenever an interactive authentication attempt is successful * (e.g. a form login). * * An implementation may always set a remember-me cookie in the Response, * although this is not recommended. * * Instead, implementations should typically look for a request parameter * (such as a HTTP POST parameter) that indicates the browser has explicitly * requested for the authentication to be remembered. * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function loginSuccess(Request $request, Response $response, TokenInterface $token); } PK!Pڕ?Symfony/Component/Security/Http/RememberMe/ResponseListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\RememberMe; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Adds remember-me cookies to the Response. * * @author Johannes M. Schmitt */ class ResponseListener implements EventSubscriberInterface { /** * @param FilterResponseEvent $event */ public function onKernelResponse(FilterResponseEvent $event) { $request = $event->getRequest(); $response = $event->getResponse(); if ($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)) { $response->headers->setCookie($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)); } } /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array(KernelEvents::RESPONSE => 'onKernelResponse'); } } PK!s44USymfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\RememberMe; use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\CookieTheftException; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Util\SecureRandomInterface; use Psr\Log\LoggerInterface; /** * Concrete implementation of the RememberMeServicesInterface which needs * an implementation of TokenProviderInterface for providing remember-me * capabilities. * * @author Johannes M. Schmitt */ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices { private $tokenProvider; private $secureRandom; /** * Constructor. * * @param array $userProviders * @param string $key * @param string $providerKey * @param array $options * @param LoggerInterface $logger * @param SecureRandomInterface $secureRandom */ public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null, SecureRandomInterface $secureRandom) { parent::__construct($userProviders, $key, $providerKey, $options, $logger); $this->secureRandom = $secureRandom; } /** * Sets the token provider * * @param TokenProviderInterface $tokenProvider */ public function setTokenProvider(TokenProviderInterface $tokenProvider) { $this->tokenProvider = $tokenProvider; } /** * {@inheritDoc} */ protected function cancelCookie(Request $request) { // Delete cookie on the client parent::cancelCookie($request); // Delete cookie from the tokenProvider if (null !== ($cookie = $request->cookies->get($this->options['name'])) && count($parts = $this->decodeCookie($cookie)) === 2 ) { list($series, $tokenValue) = $parts; $this->tokenProvider->deleteTokenBySeries($series); } } /** * {@inheritDoc} */ protected function processAutoLoginCookie(array $cookieParts, Request $request) { if (count($cookieParts) !== 2) { throw new AuthenticationException('The cookie is invalid.'); } list($series, $tokenValue) = $cookieParts; $persistentToken = $this->tokenProvider->loadTokenBySeries($series); if ($persistentToken->getTokenValue() !== $tokenValue) { throw new CookieTheftException('This token was already used. The account is possibly compromised.'); } if ($persistentToken->getLastUsed()->getTimestamp() + $this->options['lifetime'] < time()) { throw new AuthenticationException('The cookie has expired.'); } $series = $persistentToken->getSeries(); $tokenValue = base64_encode($this->secureRandom->nextBytes(64)); $this->tokenProvider->updateToken($series, $tokenValue, new \DateTime()); $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie( $this->options['name'], $this->encodeCookie(array($series, $tokenValue)), time() + $this->options['lifetime'], $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly'] ) ); return $this->getUserProvider($persistentToken->getClass())->loadUserByUsername($persistentToken->getUsername()); } /** * {@inheritDoc} */ protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token) { $series = base64_encode($this->secureRandom->nextBytes(64)); $tokenValue = base64_encode($this->secureRandom->nextBytes(64)); $this->tokenProvider->createNewToken( new PersistentToken( get_class($user = $token->getUser()), $user->getUsername(), $series, $tokenValue, new \DateTime() ) ); $response->headers->setCookie( new Cookie( $this->options['name'], $this->encodeCookie(array($series, $tokenValue)), time() + $this->options['lifetime'], $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly'] ) ); } } PK!*b&&ISymfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\RememberMe; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\CookieTheftException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Cookie; use Psr\Log\LoggerInterface; /** * Base class implementing the RememberMeServicesInterface * * @author Johannes M. Schmitt */ abstract class AbstractRememberMeServices implements RememberMeServicesInterface, LogoutHandlerInterface { const COOKIE_DELIMITER = ':'; protected $logger; protected $options; private $providerKey; private $key; private $userProviders; /** * Constructor. * * @param array $userProviders * @param string $key * @param string $providerKey * @param array $options * @param LoggerInterface $logger * * @throws \InvalidArgumentException */ public function __construct(array $userProviders, $key, $providerKey, array $options = array(), LoggerInterface $logger = null) { if (empty($key)) { throw new \InvalidArgumentException('$key must not be empty.'); } if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } if (0 === count($userProviders)) { throw new \InvalidArgumentException('You must provide at least one user provider.'); } $this->userProviders = $userProviders; $this->key = $key; $this->providerKey = $providerKey; $this->options = $options; $this->logger = $logger; } /** * Returns the parameter that is used for checking whether remember-me * services have been requested. * * @return string */ public function getRememberMeParameter() { return $this->options['remember_me_parameter']; } /** * @return string */ public function getKey() { return $this->key; } /** * Implementation of RememberMeServicesInterface. Detects whether a remember-me * cookie was set, decodes it, and hands it to subclasses for further processing. * * @param Request $request * * @return TokenInterface|null * * @throws CookieTheftException * @throws \RuntimeException */ final public function autoLogin(Request $request) { if (null === $cookie = $request->cookies->get($this->options['name'])) { return; } if (null !== $this->logger) { $this->logger->debug('Remember-me cookie detected.'); } $cookieParts = $this->decodeCookie($cookie); try { $user = $this->processAutoLoginCookie($cookieParts, $request); if (!$user instanceof UserInterface) { throw new \RuntimeException('processAutoLoginCookie() must return a UserInterface implementation.'); } if (null !== $this->logger) { $this->logger->info('Remember-me cookie accepted.'); } return new RememberMeToken($user, $this->providerKey, $this->key); } catch (CookieTheftException $theft) { $this->cancelCookie($request); throw $theft; } catch (UsernameNotFoundException $notFound) { if (null !== $this->logger) { $this->logger->info('User for remember-me cookie not found.'); } } catch (UnsupportedUserException $unSupported) { if (null !== $this->logger) { $this->logger->warning('User class for remember-me cookie not supported.'); } } catch (AuthenticationException $invalid) { if (null !== $this->logger) { $this->logger->debug('Remember-Me authentication failed: '.$invalid->getMessage()); } } $this->cancelCookie($request); return null; } /** * Implementation for LogoutHandlerInterface. Deletes the cookie. * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function logout(Request $request, Response $response, TokenInterface $token) { $this->cancelCookie($request); } /** * Implementation for RememberMeServicesInterface. Deletes the cookie when * an attempted authentication fails. * * @param Request $request */ final public function loginFail(Request $request) { $this->cancelCookie($request); $this->onLoginFail($request); } /** * Implementation for RememberMeServicesInterface. This is called when an * authentication is successful. * * @param Request $request * @param Response $response * @param TokenInterface $token The token that resulted in a successful authentication */ final public function loginSuccess(Request $request, Response $response, TokenInterface $token) { // Make sure any old remember-me cookies are cancelled $this->cancelCookie($request); if (!$token->getUser() instanceof UserInterface) { if (null !== $this->logger) { $this->logger->debug('Remember-me ignores token since it does not contain a UserInterface implementation.'); } return; } if (!$this->isRememberMeRequested($request)) { if (null !== $this->logger) { $this->logger->debug('Remember-me was not requested.'); } return; } if (null !== $this->logger) { $this->logger->debug('Remember-me was requested; setting cookie.'); } // Remove attribute from request that sets a NULL cookie. // It was set by $this->cancelCookie() // (cancelCookie does other things too for some RememberMeServices // so we should still call it at the start of this method) $request->attributes->remove(self::COOKIE_ATTR_NAME); $this->onLoginSuccess($request, $response, $token); } /** * Subclasses should validate the cookie and do any additional processing * that is required. This is called from autoLogin(). * * @param array $cookieParts * @param Request $request * * @return TokenInterface */ abstract protected function processAutoLoginCookie(array $cookieParts, Request $request); /** * @param Request $request */ protected function onLoginFail(Request $request) { } /** * This is called after a user has been logged in successfully, and has * requested remember-me capabilities. The implementation usually sets a * cookie and possibly stores a persistent record of it. * * @param Request $request * @param Response $response * @param TokenInterface $token */ abstract protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token); final protected function getUserProvider($class) { foreach ($this->userProviders as $provider) { if ($provider->supportsClass($class)) { return $provider; } } throw new UnsupportedUserException(sprintf('There is no user provider that supports class "%s".', $class)); } /** * Decodes the raw cookie value * * @param string $rawCookie * * @return array */ protected function decodeCookie($rawCookie) { return explode(self::COOKIE_DELIMITER, base64_decode($rawCookie)); } /** * Encodes the cookie parts * * @param array $cookieParts * * @return string */ protected function encodeCookie(array $cookieParts) { return base64_encode(implode(self::COOKIE_DELIMITER, $cookieParts)); } /** * Deletes the remember-me cookie * * @param Request $request */ protected function cancelCookie(Request $request) { if (null !== $this->logger) { $this->logger->debug(sprintf('Clearing remember-me cookie "%s"', $this->options['name'])); } $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie($this->options['name'], null, 1, $this->options['path'], $this->options['domain'])); } /** * Checks whether remember-me capabilities were requested * * @param Request $request * * @return Boolean */ protected function isRememberMeRequested(Request $request) { if (true === $this->options['always_remember_me']) { return true; } $parameter = $request->get($this->options['remember_me_parameter'], null, true); if ($parameter === null && null !== $this->logger) { $this->logger->debug(sprintf('Did not send remember-me cookie (remember-me parameter "%s" was not sent).', $this->options['remember_me_parameter'])); } return $parameter === 'true' || $parameter === 'on' || $parameter === '1' || $parameter === 'yes'; } } PK!a$KSymfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\RememberMe; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\User\UserInterface; /** * Concrete implementation of the RememberMeServicesInterface providing * remember-me capabilities without requiring a TokenProvider. * * @author Johannes M. Schmitt */ class TokenBasedRememberMeServices extends AbstractRememberMeServices { /** * {@inheritDoc} */ protected function processAutoLoginCookie(array $cookieParts, Request $request) { if (count($cookieParts) !== 4) { throw new AuthenticationException('The cookie is invalid.'); } list($class, $username, $expires, $hash) = $cookieParts; if (false === $username = base64_decode($username, true)) { throw new AuthenticationException('$username contains a character from outside the base64 alphabet.'); } try { $user = $this->getUserProvider($class)->loadUserByUsername($username); } catch (\Exception $ex) { if (!$ex instanceof AuthenticationException) { $ex = new AuthenticationException($ex->getMessage(), $ex->getCode(), $ex); } throw $ex; } if (!$user instanceof UserInterface) { throw new \RuntimeException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".', get_class($user))); } if (true !== $this->compareHashes($hash, $this->generateCookieHash($class, $username, $expires, $user->getPassword()))) { throw new AuthenticationException('The cookie\'s hash is invalid.'); } if ($expires < time()) { throw new AuthenticationException('The cookie has expired.'); } return $user; } /** * Compares two hashes using a constant-time algorithm to avoid (remote) * timing attacks. * * This is the same implementation as used in the BasePasswordEncoder. * * @param string $hash1 The first hash * @param string $hash2 The second hash * * @return Boolean true if the two hashes are the same, false otherwise */ private function compareHashes($hash1, $hash2) { if (strlen($hash1) !== $c = strlen($hash2)) { return false; } $result = 0; for ($i = 0; $i < $c; $i++) { $result |= ord($hash1[$i]) ^ ord($hash2[$i]); } return 0 === $result; } /** * {@inheritDoc} */ protected function onLoginSuccess(Request $request, Response $response, TokenInterface $token) { $user = $token->getUser(); $expires = time() + $this->options['lifetime']; $value = $this->generateCookieValue(get_class($user), $user->getUsername(), $expires, $user->getPassword()); $response->headers->setCookie( new Cookie( $this->options['name'], $value, $expires, $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly'] ) ); } /** * Generates the cookie value. * * @param string $class * @param string $username The username * @param integer $expires The Unix timestamp when the cookie expires * @param string $password The encoded password * * @throws \RuntimeException if username contains invalid chars * * @return string */ protected function generateCookieValue($class, $username, $expires, $password) { return $this->encodeCookie(array( $class, base64_encode($username), $expires, $this->generateCookieHash($class, $username, $expires, $password) )); } /** * Generates a hash for the cookie to ensure it is not being tempered with * * @param string $class * @param string $username The username * @param integer $expires The Unix timestamp when the cookie expires * @param string $password The encoded password * * @throws \RuntimeException when the private key is empty * * @return string */ protected function generateCookieHash($class, $username, $expires, $password) { return hash_hmac('sha256', $class.$username.$expires.$password, $this->getKey()); } } PK!:&GGRSymfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Session; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Request; /** * SessionAuthenticationStrategyInterface * * Implementation are responsible for updating the session after an interactive * authentication attempt was successful. * * @author Johannes M. Schmitt */ interface SessionAuthenticationStrategyInterface { /** * This performs any necessary changes to the session. * * This method is called before the SecurityContext is populated with a * Token, and only by classes inheriting from AbstractAuthenticationListener. * * @param Request $request * @param TokenInterface $token */ public function onAuthentication(Request $request, TokenInterface $token); } PK!La[[ISymfony/Component/Security/Http/Session/SessionAuthenticationStrategy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Session; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Request; /** * The default session strategy implementation. * * Supports the following strategies: * NONE: the session is not changed * MIGRATE: the session id is updated, attributes are kept * INVALIDATE: the session id is updated, attributes are lost * * @author Johannes M. Schmitt */ class SessionAuthenticationStrategy implements SessionAuthenticationStrategyInterface { const NONE = 'none'; const MIGRATE = 'migrate'; const INVALIDATE = 'invalidate'; private $strategy; public function __construct($strategy) { $this->strategy = $strategy; } /** * {@inheritDoc} */ public function onAuthentication(Request $request, TokenInterface $token) { switch ($this->strategy) { case self::NONE: return; case self::MIGRATE: $request->getSession()->migrate(); return; case self::INVALIDATE: $request->getSession()->invalidate(); return; default: throw new \RuntimeException(sprintf('Invalid session authentication strategy "%s"', $this->strategy)); } } } PK!a7llFSymfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\HttpUtils; /** * Default logout success handler will redirect users to a configured path. * * @author Fabien Potencier * @author Alexander */ class DefaultLogoutSuccessHandler implements LogoutSuccessHandlerInterface { protected $httpUtils; protected $targetUrl; /** * @param HttpUtils $httpUtils * @param string $targetUrl */ public function __construct(HttpUtils $httpUtils, $targetUrl = '/') { $this->httpUtils = $httpUtils; $this->targetUrl = $targetUrl; } /** * {@inheritDoc} */ public function onLogoutSuccess(Request $request) { return $this->httpUtils->createRedirectResponse($request, $this->targetUrl); } } PK!1dHSymfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * LogoutSuccesshandlerInterface. * * In contrast to the LogoutHandlerInterface, this interface can return a response * which is then used instead of the default behavior. * * If you want to only perform some logout related clean-up task, use the * LogoutHandlerInterface instead. * * @author Johannes M. Schmitt */ interface LogoutSuccessHandlerInterface { /** * Creates a Response object to send upon a successful logout. * * @param Request $request * * @return Response never null */ public function onLogoutSuccess(Request $request); } PK!\ü?Symfony/Component/Security/Http/Logout/SessionLogoutHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; /** * Handler for clearing invalidating the current session. * * @author Johannes M. Schmitt */ class SessionLogoutHandler implements LogoutHandlerInterface { /** * Invalidate the current session * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function logout(Request $request, Response $response, TokenInterface $token) { $request->getSession()->invalidate(); } } PK!6OASymfony/Component/Security/Http/Logout/LogoutHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; /** * Interface that needs to be implemented by LogoutHandlers. * * @author Johannes M. Schmitt */ interface LogoutHandlerInterface { /** * This method is called by the LogoutListener when a user has requested * to be logged out. Usually, you would unset session variables, or remove * cookies, etc. * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function logout(Request $request, Response $response, TokenInterface $token); } PK!ddFSymfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Logout; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; /** * This handler clears the passed cookies when a user logs out. * * @author Johannes M. Schmitt */ class CookieClearingLogoutHandler implements LogoutHandlerInterface { private $cookies; /** * Constructor. * * @param array $cookies An array of cookie names to unset */ public function __construct(array $cookies) { $this->cookies = $cookies; } /** * Implementation for the LogoutHandlerInterface. Deletes all requested cookies. * * @param Request $request * @param Response $response * @param TokenInterface $token */ public function logout(Request $request, Response $response, TokenInterface $token) { foreach ($this->cookies as $cookieName => $cookieData) { $response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain']); } } } PK!/ sG2Symfony/Component/Security/Http/SecurityEvents.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http; final class SecurityEvents { /** * The INTERACTIVE_LOGIN event occurs after a user is logged in * interactively for authentication based on http, cookies or X509. * * The event listener method receives a * Symfony\Component\Security\Http\Event\InteractiveLoginEvent instance. * * @var string */ const INTERACTIVE_LOGIN = 'security.interactive_login'; /** * The SWITCH_USER event occurs before switch to another user and * before exit from an already switched user. * * The event listener method receives a * Symfony\Component\Security\Http\Event\SwitchUserEvent instance. * * @var string */ const SWITCH_USER = 'security.switch_user'; } PK!NAXSymfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Interface for a custom authentication success handler * * If you want to customize the success handling process, instead of * overwriting the respective listener globally, you can set a custom success * handler which implements this interface. * * @author Johannes M. Schmitt */ interface AuthenticationSuccessHandlerInterface { /** * This is called when an interactive authentication attempt succeeds. This * is called by authentication listeners inheriting from * AbstractAuthenticationListener. * * @param Request $request * @param TokenInterface $token * * @return Response never null */ public function onAuthenticationSuccess(Request $request, TokenInterface $token); } PK! VSymfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Http\HttpUtils; /** * Class with the default authentication failure handling logic. * * Can be optionally be extended from by the developer to alter the behaviour * while keeping the default behaviour. * * @author Fabien Potencier * @author Johannes M. Schmitt * @author Alexander */ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface { protected $httpKernel; protected $httpUtils; protected $logger; protected $options; /** * Constructor. * * @param HttpKernelInterface $httpKernel * @param HttpUtils $httpUtils * @param array $options Options for processing a failed authentication attempt. * @param LoggerInterface $logger Optional logger */ public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options, LoggerInterface $logger = null) { $this->httpKernel = $httpKernel; $this->httpUtils = $httpUtils; $this->logger = $logger; $this->options = array_merge(array( 'failure_path' => null, 'failure_forward' => false, 'login_path' => '/login', 'failure_path_parameter' => '_failure_path' ), $options); } /** * {@inheritDoc} */ public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { if ($failureUrl = $request->get($this->options['failure_path_parameter'], null, true)) { $this->options['failure_path'] = $failureUrl; } if (null === $this->options['failure_path']) { $this->options['failure_path'] = $this->options['login_path']; } if ($this->options['failure_forward']) { if (null !== $this->logger) { $this->logger->debug(sprintf('Forwarding to %s', $this->options['failure_path'])); } $subRequest = $this->httpUtils->createRequest($request, $this->options['failure_path']); $subRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception); return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); } if (null !== $this->logger) { $this->logger->debug(sprintf('Redirecting to %s', $this->options['failure_path'])); } $request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception); return $this->httpUtils->createRedirectResponse($request, $this->options['failure_path']); } } PK!H]  XSymfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Interface for custom authentication failure handlers. * * If you want to customize the failure handling process, instead of * overwriting the respective listener globally, you can set a custom failure * handler which implements this interface. * * @author Johannes M. Schmitt */ interface AuthenticationFailureHandlerInterface { /** * This is called when an interactive authentication attempt fails. This is * called by authentication listeners inheriting from * AbstractAuthenticationListener. * * @param Request $request * @param AuthenticationException $exception * * @return Response The response to return, never null */ public function onAuthenticationFailure(Request $request, AuthenticationException $exception); } PK!xGA A VSymfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\HttpUtils; /** * Class with the default authentication success handling logic. * * @author Fabien Potencier * @author Johannes M. Schmitt * @author Alexander */ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface { protected $httpUtils; protected $options; protected $providerKey; /** * Constructor. * * @param HttpUtils $httpUtils * @param array $options Options for processing a successful authentication attempt. */ public function __construct(HttpUtils $httpUtils, array $options) { $this->httpUtils = $httpUtils; $this->options = array_merge(array( 'always_use_default_target_path' => false, 'default_target_path' => '/', 'login_path' => '/login', 'target_path_parameter' => '_target_path', 'use_referer' => false, ), $options); } /** * {@inheritDoc} */ public function onAuthenticationSuccess(Request $request, TokenInterface $token) { return $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request)); } /** * Get the provider key. * * @return string */ public function getProviderKey() { return $this->providerKey; } /** * Set the provider key. * * @param string $providerKey */ public function setProviderKey($providerKey) { $this->providerKey = $providerKey; } /** * Builds the target URL according to the defined options. * * @param Request $request * * @return string */ protected function determineTargetUrl(Request $request) { if ($this->options['always_use_default_target_path']) { return $this->options['default_target_path']; } if ($targetUrl = $request->get($this->options['target_path_parameter'], null, true)) { return $targetUrl; } if (null !== $this->providerKey && $targetUrl = $request->getSession()->get('_security.'.$this->providerKey.'.target_path')) { $request->getSession()->remove('_security.'.$this->providerKey.'.target_path'); return $targetUrl; } if ($this->options['use_referer'] && ($targetUrl = $request->headers->get('Referer')) && $targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) { return $targetUrl; } return $this->options['default_target_path']; } } PK!AH\ݞNSymfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Authentication; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; /** * Class to proxy authentication success/failure handlers * * Events are sent to the SimpleAuthenticatorInterface if it implements * the right interface, otherwise (or if it fails to return a Response) * the default handlers are triggered. * * @author Jordi Boggiano */ class SimpleAuthenticationHandler implements AuthenticationFailureHandlerInterface, AuthenticationSuccessHandlerInterface { protected $successHandler; protected $failureHandler; protected $simpleAuthenticator; protected $logger; /** * Constructor. * * @param SimpleAuthenticatorInterface $authenticator SimpleAuthenticatorInterface instance * @param AuthenticationSuccessHandlerInterface $successHandler Default success handler * @param AuthenticationFailureHandlerInterface $failureHandler Default failure handler * @param LoggerInterface $logger Optional logger */ public function __construct(SimpleAuthenticatorInterface $authenticator, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, LoggerInterface $logger = null) { $this->simpleAuthenticator = $authenticator; $this->successHandler = $successHandler; $this->failureHandler = $failureHandler; $this->logger = $logger; } /** * {@inheritDoc} */ public function onAuthenticationSuccess(Request $request, TokenInterface $token) { if ($this->simpleAuthenticator instanceof AuthenticationSuccessHandlerInterface) { if ($this->logger) { $this->logger->debug(sprintf('Using the %s object as authentication success handler', get_class($this->simpleAuthenticator))); } $response = $this->simpleAuthenticator->onAuthenticationSuccess($request, $token); if ($response instanceof Response) { return $response; } if (null !== $response) { throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationSuccess method must return null to use the default success handler, or a Response object', get_class($this->simpleAuthenticator))); } } if ($this->logger) { $this->logger->debug('Fallback to the default authentication success handler'); } return $this->successHandler->onAuthenticationSuccess($request, $token); } /** * {@inheritDoc} */ public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { if ($this->simpleAuthenticator instanceof AuthenticationFailureHandlerInterface) { if ($this->logger) { $this->logger->debug(sprintf('Using the %s object as authentication failure handler', get_class($this->simpleAuthenticator))); } $response = $this->simpleAuthenticator->onAuthenticationFailure($request, $exception); if ($response instanceof Response) { return $response; } if (null !== $response) { throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationFailure method must return null to use the default failure handler, or a Response object', get_class($this->simpleAuthenticator))); } } if ($this->logger) { $this->logger->debug('Fallback to the default authentication failure handler'); } return $this->failureHandler->onAuthenticationFailure($request, $exception); } } PK!D9Symfony/Component/Security/Http/Event/SwitchUserEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\EventDispatcher\Event; /** * SwitchUserEvent * * @author Fabien Potencier */ class SwitchUserEvent extends Event { private $request; private $targetUser; public function __construct(Request $request, UserInterface $targetUser) { $this->request = $request; $this->targetUser = $targetUser; } /** * @return Request */ public function getRequest() { return $this->request; } /** * @return UserInterface */ public function getTargetUser() { return $this->targetUser; } } PK!Zv}?Symfony/Component/Security/Http/Event/InteractiveLoginEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * InteractiveLoginEvent * * @author Fabien Potencier */ class InteractiveLoginEvent extends Event { private $request; private $authenticationToken; /** * Constructor. * * @param Request $request A Request instance * @param TokenInterface $authenticationToken A TokenInterface instance */ public function __construct(Request $request, TokenInterface $authenticationToken) { $this->request = $request; $this->authenticationToken = $authenticationToken; } /** * Gets the request. * * @return Request A Request instance */ public function getRequest() { return $this->request; } /** * Gets the authentication token. * * @return TokenInterface A TokenInterface instance */ public function getAuthenticationToken() { return $this->authenticationToken; } } PK!VǴ=Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf; /** * Manages CSRF tokens. * * @since 2.4 * @author Bernhard Schussek */ interface CsrfTokenManagerInterface { /** * Returns a CSRF token for the given ID. * * If previously no token existed for the given ID, a new token is * generated. Otherwise the existing token is returned (with the same value, * not the same instance). * * @param string $tokenId The token ID. You may choose an arbitrary value * for the ID * * @return CsrfToken The CSRF token */ public function getToken($tokenId); /** * Generates a new token value for the given ID. * * This method will generate a new token for the given token ID, independent * of whether a token value previously existed or not. It can be used to * enforce once-only tokens in environments with high security needs. * * @param string $tokenId The token ID. You may choose an arbitrary value * for the ID * * @return CsrfToken The CSRF token */ public function refreshToken($tokenId); /** * Invalidates the CSRF token with the given ID, if one exists. * * @param string $tokenId The token ID * * @return string|null Returns the removed token value if one existed, NULL * otherwise */ public function removeToken($tokenId); /** * Returns whether the given CSRF token is valid. * * @param CsrfToken $token A CSRF token * * @return Boolean Returns true if the token is valid, false otherwise */ public function isTokenValid(CsrfToken $token); } PK!&%L L 4Symfony/Component/Security/Csrf/CsrfTokenManager.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf; use Symfony\Component\Security\Core\Util\StringUtils; use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator; use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface; use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage; use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface; /** * Default implementation of {@link CsrfTokenManagerInterface}. * * @author Bernhard Schussek */ class CsrfTokenManager implements CsrfTokenManagerInterface { /** * @var TokenGeneratorInterface */ private $generator; /** * @var TokenStorageInterface */ private $storage; /** * Creates a new CSRF provider using PHP's native session storage. * * @param TokenGeneratorInterface|null $generator The token generator * @param TokenStorageInterface|null $storage The storage for storing * generated CSRF tokens */ public function __construct(TokenGeneratorInterface $generator = null, TokenStorageInterface $storage = null) { $this->generator = $generator ?: new UriSafeTokenGenerator(); $this->storage = $storage ?: new NativeSessionTokenStorage(); } /** * {@inheritdoc} */ public function getToken($tokenId) { if ($this->storage->hasToken($tokenId)) { $value = $this->storage->getToken($tokenId); } else { $value = $this->generator->generateToken(); $this->storage->setToken($tokenId, $value); } return new CsrfToken($tokenId, $value); } /** * {@inheritdoc} */ public function refreshToken($tokenId) { $value = $this->generator->generateToken(); $this->storage->setToken($tokenId, $value); return new CsrfToken($tokenId, $value); } /** * {@inheritdoc} */ public function removeToken($tokenId) { return $this->storage->removeToken($tokenId); } /** * {@inheritdoc} */ public function isTokenValid(CsrfToken $token) { if (!$this->storage->hasToken($token->getId())) { return false; } return StringUtils::equals($this->storage->getToken($token->getId()), $token->getValue()); } } PK! JSymfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenStorage; use Symfony\Component\Security\Csrf\Exception\TokenNotFoundException; /** * Token storage that uses PHP's native session handling. * * @since 2.4 * @author Bernhard Schussek */ class NativeSessionTokenStorage implements TokenStorageInterface { /** * The namespace used to store values in the session. * @var string */ const SESSION_NAMESPACE = '_csrf'; /** * @var Boolean */ private $sessionStarted = false; /** * @var string */ private $namespace; /** * Initializes the storage with a session namespace. * * @param string $namespace The namespace under which the token is stored * in the session */ public function __construct($namespace = self::SESSION_NAMESPACE) { $this->namespace = $namespace; } /** * {@inheritdoc} */ public function getToken($tokenId) { if (!$this->sessionStarted) { $this->startSession(); } if (!isset($_SESSION[$this->namespace][$tokenId])) { throw new TokenNotFoundException('The CSRF token with ID '.$tokenId.' does not exist.'); } return (string) $_SESSION[$this->namespace][$tokenId]; } /** * {@inheritdoc} */ public function setToken($tokenId, $token) { if (!$this->sessionStarted) { $this->startSession(); } $_SESSION[$this->namespace][$tokenId] = (string) $token; } /** * {@inheritdoc} */ public function hasToken($tokenId) { if (!$this->sessionStarted) { $this->startSession(); } return isset($_SESSION[$this->namespace][$tokenId]); } /** * {@inheritdoc} */ public function removeToken($tokenId) { if (!$this->sessionStarted) { $this->startSession(); } $token = isset($_SESSION[$this->namespace][$tokenId]) ? (string) $_SESSION[$this->namespace][$tokenId] : null; unset($_SESSION[$this->namespace][$tokenId]); return $token; } private function startSession() { if (version_compare(PHP_VERSION, '5.4', '>=')) { if (PHP_SESSION_NONE === session_status()) { session_start(); } } elseif (!session_id()) { session_start(); } $this->sessionStarted = true; } } PK!FSymfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenStorage; /** * Stores CSRF tokens. * * @since 2.4 * @author Bernhard Schussek */ interface TokenStorageInterface { /** * Reads a stored CSRF token. * * @param string $tokenId The token ID * * @return string The stored token * * @throws \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException If the token ID does not exist */ public function getToken($tokenId); /** * Stores a CSRF token. * * @param string $tokenId The token ID * @param string $token The CSRF token */ public function setToken($tokenId, $token); /** * Removes a CSRF token. * * @param string $tokenId The token ID * * @return string|null Returns the removed token if one existed, NULL * otherwise */ public function removeToken($tokenId); /** * Checks whether a token with the given token ID exists. * * @param string $tokenId The token ID * * @return Boolean Whether a token exists with the given ID */ public function hasToken($tokenId); } PK!]N N DSymfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenStorage; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Security\Csrf\Exception\TokenNotFoundException; /** * Token storage that uses a Symfony2 Session object. * * @since 2.4 * @author Bernhard Schussek */ class SessionTokenStorage implements TokenStorageInterface { /** * The namespace used to store values in the session. * @var string */ const SESSION_NAMESPACE = '_csrf'; /** * The user session from which the session ID is returned * @var SessionInterface */ private $session; /** * @var string */ private $namespace; /** * Initializes the storage with a Session object and a session namespace. * * @param SessionInterface $session The user session * @param string $namespace The namespace under which the token * is stored in the session */ public function __construct(SessionInterface $session, $namespace = self::SESSION_NAMESPACE) { $this->session = $session; $this->namespace = $namespace; } /** * {@inheritdoc} */ public function getToken($tokenId) { if (!$this->session->isStarted()) { $this->session->start(); } if (!$this->session->has($this->namespace.'/'.$tokenId)) { throw new TokenNotFoundException('The CSRF token with ID '.$tokenId.' does not exist.'); } return (string) $this->session->get($this->namespace.'/'.$tokenId); } /** * {@inheritdoc} */ public function setToken($tokenId, $token) { if (!$this->session->isStarted()) { $this->session->start(); } $this->session->set($this->namespace.'/'.$tokenId, (string) $token); } /** * {@inheritdoc} */ public function hasToken($tokenId) { if (!$this->session->isStarted()) { $this->session->start(); } return $this->session->has($this->namespace.'/'.$tokenId); } /** * {@inheritdoc} */ public function removeToken($tokenId) { if (!$this->session->isStarted()) { $this->session->start(); } return $this->session->remove($this->namespace.'/'.$tokenId); } } PK!eIDSymfony/Component/Security/Csrf/Exception/TokenNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\Exception; use Symfony\Component\Security\Core\Exception\RuntimeException; /** * @author Bernhard Schussek */ class TokenNotFoundException extends RuntimeException { } PK! =HSymfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenGenerator; use Symfony\Component\Security\Core\Util\SecureRandomInterface; use Symfony\Component\Security\Core\Util\SecureRandom; /** * Generates CSRF tokens. * * @since 2.4 * @author Bernhard Schussek */ class UriSafeTokenGenerator implements TokenGeneratorInterface { /** * The generator for random values. * * @var SecureRandomInterface */ private $random; /** * The amount of entropy collected for each token (in bits). * * @var integer */ private $entropy; /** * Generates URI-safe CSRF tokens. * * @param SecureRandomInterface|null $random The random value generator used for * generating entropy * @param integer $entropy The amount of entropy collected for * each token (in bits) */ public function __construct(SecureRandomInterface $random = null, $entropy = 256) { $this->random = $random ?: new SecureRandom(); $this->entropy = $entropy; } /** * {@inheritdoc} */ public function generateToken() { // Generate an URI safe base64 encoded string that does not contain "+", // "/" or "=" which need to be URL encoded and make URLs unnecessarily // longer. $bytes = $this->random->nextBytes($this->entropy / 8); return rtrim(strtr(base64_encode($bytes), '+/', '-_'), '='); } } PK!J,pJSymfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\TokenGenerator; /** * Generates and validates CSRF tokens. * * You can generate a CSRF token by using the method {@link generateCsrfToken()}. * This method expects a unique token ID as argument. The token ID can later be * used to validate a token provided by the user. * * Token IDs do not necessarily have to be secret, but they should NEVER be * created from data provided by the client. A good practice is to hard-code the * token IDs for the various CSRF tokens used by your application. * * You should use the method {@link isCsrfTokenValid()} to check a CSRF token * submitted by the client. This method will return true if the CSRF token is * valid. * * @since 2.4 * @author Bernhard Schussek */ interface TokenGeneratorInterface { /** * Generates a CSRF token. * * @return string The generated CSRF token */ public function generateToken(); } PK!O-Symfony/Component/Security/Csrf/CsrfToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf; /** * A CSRF token. * * @author Bernhard Schussek */ class CsrfToken { /** * @var string */ private $id; /** * @var string */ private $value; /** * Constructor. * * @param string $id The token ID * @param string $value The actual token value */ public function __construct($id, $value) { $this->id = (string) $id; $this->value = (string) $value; } /** * Returns the ID of the CSRF token. * * @return string The token ID */ public function getId() { return $this->id; } /** * Returns the value of the CSRF token. * * @return string The token value */ public function getValue() { return $this->value; } /** * Returns the value of the CSRF token. * * @return string The token value */ public function __toString() { return $this->value; } } PK!S<Symfony/Component/Security/Core/SecurityContextInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * The SecurityContextInterface. * * @author Johannes M. Schmitt */ interface SecurityContextInterface { const ACCESS_DENIED_ERROR = '_security.403_error'; const AUTHENTICATION_ERROR = '_security.last_error'; const LAST_USERNAME = '_security.last_username'; /** * Returns the current security token. * * @return TokenInterface|null A TokenInterface instance or null if no authentication information is available */ public function getToken(); /** * Sets the authentication token. * * @param TokenInterface $token A TokenInterface token, or null if no further authentication information should be stored */ public function setToken(TokenInterface $token = null); /** * Checks if the attributes are granted against the current authentication token and optionally supplied object. * * @param mixed $attributes * @param mixed $object * * @return Boolean */ public function isGranted($attributes, $object = null); } PK!}ww?Symfony/Component/Security/Core/Role/RoleHierarchyInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; /** * RoleHierarchyInterface is the interface for a role hierarchy. * * @author Fabien Potencier */ interface RoleHierarchyInterface { /** * Returns an array of all reachable roles by the given ones. * * Reachable roles are the roles directly assigned but also all roles that * are transitively reachable from them in the role hierarchy. * * @param RoleInterface[] $roles An array of directly assigned roles * * @return RoleInterface[] An array of all reachable roles */ public function getReachableRoles(array $roles); } PK! w??6Symfony/Component/Security/Core/Role/RoleHierarchy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; /** * RoleHierarchy defines a role hierarchy. * * @author Fabien Potencier */ class RoleHierarchy implements RoleHierarchyInterface { private $hierarchy; private $map; /** * Constructor. * * @param array $hierarchy An array defining the hierarchy */ public function __construct(array $hierarchy) { $this->hierarchy = $hierarchy; $this->buildRoleMap(); } /** * {@inheritdoc} */ public function getReachableRoles(array $roles) { $reachableRoles = $roles; foreach ($roles as $role) { if (!isset($this->map[$role->getRole()])) { continue; } foreach ($this->map[$role->getRole()] as $r) { $reachableRoles[] = new Role($r); } } return $reachableRoles; } private function buildRoleMap() { $this->map = array(); foreach ($this->hierarchy as $main => $roles) { $this->map[$main] = $roles; $visited = array(); $additionalRoles = $roles; while ($role = array_shift($additionalRoles)) { if (!isset($this->hierarchy[$role])) { continue; } $visited[] = $role; $this->map[$main] = array_unique(array_merge($this->map[$main], $this->hierarchy[$role])); $additionalRoles = array_merge($additionalRoles, array_diff($this->hierarchy[$role], $visited)); } } } } PK!Ħ-Symfony/Component/Security/Core/Role/Role.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; /** * Role is a simple implementation of a RoleInterface where the role is a * string. * * @author Fabien Potencier */ class Role implements RoleInterface { private $role; /** * Constructor. * * @param string $role The role name */ public function __construct($role) { $this->role = (string) $role; } /** * {@inheritdoc} */ public function getRole() { return $this->role; } } PK!XS007Symfony/Component/Security/Core/Role/SwitchUserRole.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * SwitchUserRole is used when the current user temporarily impersonates * another one. * * @author Fabien Potencier */ class SwitchUserRole extends Role { private $source; /** * Constructor. * * @param string $role The role as a string * @param TokenInterface $source The original token */ public function __construct($role, TokenInterface $source) { parent::__construct($role); $this->source = $source; } /** * Returns the original Token. * * @return TokenInterface The original TokenInterface instance */ public function getSource() { return $this->source; } } PK!'c6Symfony/Component/Security/Core/Role/RoleInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Role; /** * RoleInterface represents a role granted to a user. * * A role must either have a string representation or it needs to be explicitly * supported by at least one AccessDecisionManager. * * @author Fabien Potencier */ interface RoleInterface { /** * Returns the role. * * This method returns a string representation whenever possible. * * When the role cannot be represented with sufficient precision by a * string, it should return null. * * @return string|null A string representation of the role, or null */ public function getRole(); } PK!E DSymfony/Component/Security/Core/Encoder/PasswordEncoderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; /** * PasswordEncoderInterface is the interface for all encoders. * * @author Fabien Potencier */ interface PasswordEncoderInterface { /** * Encodes the raw password. * * @param string $raw The password to encode * @param string $salt The salt * * @return string The encoded password */ public function encodePassword($raw, $salt); /** * Checks a raw password against an encoded password. * * @param string $encoded An encoded password * @param string $raw A raw password * @param string $salt The salt * * @return Boolean true if the password is valid, false otherwise */ public function isPasswordValid($encoded, $raw, $salt); } PK!Æ ASymfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * @author Elnur Abdurrakhimov * @author Terje Bråten */ class BCryptPasswordEncoder extends BasePasswordEncoder { /** * @var string */ private $cost; /** * Constructor. * * @param integer $cost The algorithmic cost that should be used * * @throws \RuntimeException When no BCrypt encoder is available * @throws \InvalidArgumentException if cost is out of range */ public function __construct($cost) { if (!function_exists('password_hash')) { throw new \RuntimeException('To use the BCrypt encoder, you need to upgrade to PHP 5.5 or install the "ircmaxell/password-compat" via Composer.'); } $cost = (int) $cost; if ($cost < 4 || $cost > 31) { throw new \InvalidArgumentException('Cost must be in the range of 4-31.'); } $this->cost = $cost; } /** * Encodes the raw password. * * It doesn't work with PHP versions lower than 5.3.7, since * the password compat library uses CRYPT_BLOWFISH hash type with * the "$2y$" salt prefix (which is not available in the early PHP versions). * @see https://github.com/ircmaxell/password_compat/issues/10#issuecomment-11203833 * * It is almost best to **not** pass a salt and let PHP generate one for you. * * @param string $raw The password to encode * @param string $salt The salt * * @return string The encoded password * * @link http://lxr.php.net/xref/PHP_5_5/ext/standard/password.c#111 */ public function encodePassword($raw, $salt) { if ($this->isPasswordTooLong($raw)) { throw new BadCredentialsException('Invalid password.'); } $options = array('cost' => $this->cost); if ($salt) { $options['salt'] = $salt; } return password_hash($raw, PASSWORD_BCRYPT, $options); } /** * {@inheritdoc} */ public function isPasswordValid($encoded, $raw, $salt) { return !$this->isPasswordTooLong($raw) && password_verify($raw, $encoded); } } PK!^HSymfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * MessageDigestPasswordEncoder uses a message digest algorithm. * * @author Fabien Potencier */ class MessageDigestPasswordEncoder extends BasePasswordEncoder { private $algorithm; private $encodeHashAsBase64; private $iterations; /** * Constructor. * * @param string $algorithm The digest algorithm to use * @param Boolean $encodeHashAsBase64 Whether to base64 encode the password hash * @param integer $iterations The number of iterations to use to stretch the password hash */ public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 5000) { $this->algorithm = $algorithm; $this->encodeHashAsBase64 = $encodeHashAsBase64; $this->iterations = $iterations; } /** * {@inheritdoc} */ public function encodePassword($raw, $salt) { if ($this->isPasswordTooLong($raw)) { throw new BadCredentialsException('Invalid password.'); } if (!in_array($this->algorithm, hash_algos(), true)) { throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm)); } $salted = $this->mergePasswordAndSalt($raw, $salt); $digest = hash($this->algorithm, $salted, true); // "stretch" hash for ($i = 1; $i < $this->iterations; $i++) { $digest = hash($this->algorithm, $digest.$salted, true); } return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest); } /** * {@inheritdoc} */ public function isPasswordValid($encoded, $raw, $salt) { return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt)); } } PK!,>"DSymfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * PlaintextPasswordEncoder does not do any encoding. * * @author Fabien Potencier */ class PlaintextPasswordEncoder extends BasePasswordEncoder { private $ignorePasswordCase; /** * Constructor. * * @param Boolean $ignorePasswordCase Compare password case-insensitive */ public function __construct($ignorePasswordCase = false) { $this->ignorePasswordCase = $ignorePasswordCase; } /** * {@inheritdoc} */ public function encodePassword($raw, $salt) { if ($this->isPasswordTooLong($raw)) { throw new BadCredentialsException('Invalid password.'); } return $this->mergePasswordAndSalt($raw, $salt); } /** * {@inheritdoc} */ public function isPasswordValid($encoded, $raw, $salt) { if ($this->isPasswordTooLong($raw)) { return false; } $pass2 = $this->mergePasswordAndSalt($raw, $salt); if (!$this->ignorePasswordCase) { return $this->comparePasswords($encoded, $pass2); } return $this->comparePasswords(strtolower($encoded), strtolower($pass2)); } } PK!;D:Symfony/Component/Security/Core/Encoder/EncoderFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; /** * A generic encoder factory implementation * * @author Johannes M. Schmitt */ class EncoderFactory implements EncoderFactoryInterface { private $encoders; public function __construct(array $encoders) { $this->encoders = $encoders; } /** * {@inheritDoc} */ public function getEncoder($user) { foreach ($this->encoders as $class => $encoder) { if ((is_object($user) && !$user instanceof $class) || (!is_object($user) && !is_subclass_of($user, $class) && $user != $class)) { continue; } if (!$encoder instanceof PasswordEncoderInterface) { return $this->encoders[$class] = $this->createEncoder($encoder); } return $this->encoders[$class]; } throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', is_object($user) ? get_class($user) : $user)); } /** * Creates the actual encoder instance * * @param array $config * * @return PasswordEncoderInterface * * @throws \InvalidArgumentException */ private function createEncoder(array $config) { if (!isset($config['class'])) { throw new \InvalidArgumentException(sprintf('"class" must be set in %s.', json_encode($config))); } if (!isset($config['arguments'])) { throw new \InvalidArgumentException(sprintf('"arguments" must be set in %s.', json_encode($config))); } $reflection = new \ReflectionClass($config['class']); return $reflection->newInstanceArgs($config['arguments']); } } PK!!@  ASymfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * Pbkdf2PasswordEncoder uses the PBKDF2 (Password-Based Key Derivation Function 2). * * Providing a high level of Cryptographic security, * PBKDF2 is recommended by the National Institute of Standards and Technology (NIST). * * But also warrants a warning, using PBKDF2 (with a high number of iterations) slows down the process. * PBKDF2 should be used with caution and care. * * @author Sebastiaan Stok * @author Andrew Johnson * @author Fabien Potencier */ class Pbkdf2PasswordEncoder extends BasePasswordEncoder { private $algorithm; private $encodeHashAsBase64; private $iterations; private $length; /** * Constructor. * * @param string $algorithm The digest algorithm to use * @param Boolean $encodeHashAsBase64 Whether to base64 encode the password hash * @param integer $iterations The number of iterations to use to stretch the password hash * @param integer $length Length of derived key to create */ public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 1000, $length = 40) { $this->algorithm = $algorithm; $this->encodeHashAsBase64 = $encodeHashAsBase64; $this->iterations = $iterations; $this->length = $length; } /** * {@inheritdoc} * * @throws \LogicException when the algorithm is not supported */ public function encodePassword($raw, $salt) { if ($this->isPasswordTooLong($raw)) { throw new BadCredentialsException('Invalid password.'); } if (!in_array($this->algorithm, hash_algos(), true)) { throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm)); } if (function_exists('hash_pbkdf2')) { $digest = hash_pbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length, true); } else { $digest = $this->hashPbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length); } return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest); } /** * {@inheritdoc} */ public function isPasswordValid($encoded, $raw, $salt) { return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt)); } private function hashPbkdf2($algorithm, $password, $salt, $iterations, $length = 0) { // Number of blocks needed to create the derived key $blocks = ceil($length / strlen(hash($algorithm, null, true))); $digest = ''; for ($i = 1; $i <= $blocks; $i++) { $ib = $block = hash_hmac($algorithm, $salt.pack('N', $i), $password, true); // Iterations for ($j = 1; $j < $iterations; $j++) { $ib ^= ($block = hash_hmac($algorithm, $block, $password, true)); } $digest .= $ib; } return substr($digest, 0, $this->length); } } PK!#MMqqCSymfony/Component/Security/Core/Encoder/EncoderFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\User\UserInterface; /** * EncoderFactoryInterface to support different encoders for different accounts. * * @author Johannes M. Schmitt */ interface EncoderFactoryInterface { /** * Returns the password encoder to use for the given account. * * @param UserInterface|string $user A UserInterface instance or a class name * * @return PasswordEncoderInterface * * @throws \RuntimeException when no password encoder could be found for the user */ public function getEncoder($user); } PK!7 ?Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Encoder; use Symfony\Component\Security\Core\Util\StringUtils; /** * BasePasswordEncoder is the base class for all password encoders. * * @author Fabien Potencier */ abstract class BasePasswordEncoder implements PasswordEncoderInterface { const MAX_PASSWORD_LENGTH = 4096; /** * Demerges a merge password and salt string. * * @param string $mergedPasswordSalt The merged password and salt string * * @return array An array where the first element is the password and the second the salt */ protected function demergePasswordAndSalt($mergedPasswordSalt) { if (empty($mergedPasswordSalt)) { return array('', ''); } $password = $mergedPasswordSalt; $salt = ''; $saltBegins = strrpos($mergedPasswordSalt, '{'); if (false !== $saltBegins && $saltBegins + 1 < strlen($mergedPasswordSalt)) { $salt = substr($mergedPasswordSalt, $saltBegins + 1, -1); $password = substr($mergedPasswordSalt, 0, $saltBegins); } return array($password, $salt); } /** * Merges a password and a salt. * * @param string $password the password to be used * @param string $salt the salt to be used * * @return string a merged password and salt * * @throws \InvalidArgumentException */ protected function mergePasswordAndSalt($password, $salt) { if (empty($salt)) { return $password; } if (false !== strrpos($salt, '{') || false !== strrpos($salt, '}')) { throw new \InvalidArgumentException('Cannot use { or } in salt.'); } return $password.'{'.$salt.'}'; } /** * Compares two passwords. * * This method implements a constant-time algorithm to compare passwords to * avoid (remote) timing attacks. * * @param string $password1 The first password * @param string $password2 The second password * * @return Boolean true if the two passwords are the same, false otherwise */ protected function comparePasswords($password1, $password2) { return StringUtils::equals($password1, $password2); } /** * Checks if the password is too long. * * @return Boolean true if the password is too long, false otherwise */ protected function isPasswordTooLong($password) { return strlen($password) > self::MAX_PASSWORD_LENGTH; } } PK! 77OSymfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Validator\Constraints; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; class UserPasswordValidator extends ConstraintValidator { private $securityContext; private $encoderFactory; public function __construct(SecurityContextInterface $securityContext, EncoderFactoryInterface $encoderFactory) { $this->securityContext = $securityContext; $this->encoderFactory = $encoderFactory; } /** * {@inheritdoc} */ public function validate($password, Constraint $constraint) { $user = $this->securityContext->getToken()->getUser(); if (!$user instanceof UserInterface) { throw new ConstraintDefinitionException('The User object must implement the UserInterface interface.'); } $encoder = $this->encoderFactory->getEncoder($user); if (!$encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) { $this->context->addViolation($constraint->message); } } } PK!iFSymfony/Component/Security/Core/Validator/Constraints/UserPassword.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation */ class UserPassword extends Constraint { public $message = 'This value should be the user current password.'; public $service = 'security.validator.user_password'; /** * {@inheritdoc} */ public function validatedBy() { return $this->service; } } PK!ΕESymfony/Component/Security/Core/Exception/BadCredentialsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * BadCredentialsException is thrown when the user credentials are invalid. * * @author Fabien Potencier * @author Alexander */ class BadCredentialsException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Invalid credentials.'; } } PK!zz=Symfony/Component/Security/Core/Exception/LockedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * LockedException is thrown if the user account is locked. * * @author Fabien Potencier * @author Alexander */ class LockedException extends AccountStatusException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Account is locked.'; } } PK!bM<<FSymfony/Component/Security/Core/Exception/UnsupportedUserException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * This exception is thrown when an account is reloaded from a provider which * doesn't support the passed implementation of UserInterface. * * @author Johannes M. Schmitt */ class UnsupportedUserException extends AuthenticationServiceException { } PK!z&ISymfony/Component/Security/Core/Exception/CredentialsExpiredException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * CredentialsExpiredException is thrown when the user account credentials have expired. * * @author Fabien Potencier * @author Alexander */ class CredentialsExpiredException extends AccountStatusException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Credentials have expired.'; } } PK!Xss=Symfony/Component/Security/Core/Exception/LogoutException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * LogoutException is thrown when the account cannot be logged out. * * @author Jeremy Mikola */ class LogoutException extends \RuntimeException { public function __construct($message = 'Logout Exception', \Exception $previous = null) { parent::__construct($message, 403, $previous); } } PK! 04}}GSymfony/Component/Security/Core/Exception/UsernameNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * UsernameNotFoundException is thrown if a User cannot be found by its username. * * @author Fabien Potencier * @author Alexander */ class UsernameNotFoundException extends AuthenticationException { private $username; /** * {@inheritDoc} */ public function getMessageKey() { return 'Username could not be found.'; } /** * Get the username. * * @return string */ public function getUsername() { return $this->username; } /** * Set the username. * * @param string $username */ public function setUsername($username) { $this->username = $username; } /** * {@inheritDoc} */ public function serialize() { return serialize(array( $this->username, parent::serialize(), )); } /** * {@inheritDoc} */ public function unserialize($str) { list($this->username, $parentData) = unserialize($str); parent::unserialize($parentData); } } PK!#q44QSymfony/Component/Security/Core/Exception/InsufficientAuthenticationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * InsufficientAuthenticationException is thrown if the user credentials are not sufficiently trusted. * * This is the case when a user is anonymous and the resource to be displayed has an access role. * * @author Fabien Potencier * @author Alexander */ class InsufficientAuthenticationException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Not privileged to request the resource.'; } } PK!5]ISymfony/Component/Security/Core/Exception/SessionUnavailableException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * This exception is thrown when no session is available. * * Possible reasons for this are: * * a) The session timed out because the user waited too long. * b) The user has disabled cookies, and a new session is started on each * request. * * @author Johannes M. Schmitt * @author Alexander */ class SessionUnavailableException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'No session available, it either timed out or cookies are not enabled.'; } } PK!D9DSymfony/Component/Security/Core/Exception/TokenNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * TokenNotFoundException is thrown if a Token cannot be found. * * @author Johannes M. Schmitt * @author Alexander */ class TokenNotFoundException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'No token could be found.'; } } PK!hcBSymfony/Component/Security/Core/Exception/CookieTheftException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * This exception is thrown when the RememberMeServices implementation * detects that a presented cookie has already been used by someone else. * * @author Johannes M. Schmitt * @author Alexander */ class CookieTheftException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Cookie has already been used by someone else.'; } } PK!A@Symfony/Component/Security/Core/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * Base ExceptionInterface for the Security component. * * @author Bernhard Schussek */ interface ExceptionInterface { } PK!qUSąCSymfony/Component/Security/Core/Exception/AccessDeniedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * AccessDeniedException is thrown when the account has not the required role. * * @author Fabien Potencier */ class AccessDeniedException extends \RuntimeException { public function __construct($message = 'Access Denied', \Exception $previous = null) { parent::__construct($message, 403, $previous); } } PK!'ESymfony/Component/Security/Core/Exception/AuthenticationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AuthenticationException is the base class for all authentication exceptions. * * @author Fabien Potencier * @author Alexander */ class AuthenticationException extends \RuntimeException implements \Serializable { private $token; /** * Get the token. * * @return TokenInterface */ public function getToken() { return $this->token; } /** * Set the token. * * @param TokenInterface $token */ public function setToken(TokenInterface $token) { $this->token = $token; } public function serialize() { return serialize(array( $this->token, $this->code, $this->message, $this->file, $this->line, )); } public function unserialize($str) { list( $this->token, $this->code, $this->message, $this->file, $this->line ) = unserialize($str); } /** * Message key to be used by the translation component. * * @return string */ public function getMessageKey() { return 'An authentication exception occurred.'; } /** * Message data to be used by the translation component. * * @return array */ public function getMessageData() { return array(); } } PK! >Symfony/Component/Security/Core/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * Base RuntimeException for the Security component. * * @author Bernhard Schussek */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK!@ GSymfony/Component/Security/Core/Exception/ProviderNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * ProviderNotFoundException is thrown when no AuthenticationProviderInterface instance * supports an authentication Token. * * @author Fabien Potencier * @author Alexander */ class ProviderNotFoundException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'No authentication provider found to support the authentication token.'; } } PK!ĸXSymfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * AuthenticationCredentialsNotFoundException is thrown when an authentication is rejected * because no Token is available. * * @author Fabien Potencier * @author Alexander */ class AuthenticationCredentialsNotFoundException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Authentication credentials could not be found.'; } } PK!:AADSymfony/Component/Security/Core/Exception/AccountStatusException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; use Symfony\Component\Security\Core\User\UserInterface; /** * AccountStatusException is the base class for authentication exceptions * caused by the user account status. * * @author Fabien Potencier * @author Alexander */ abstract class AccountStatusException extends AuthenticationException { private $user; /** * Get the user. * * @return UserInterface */ public function getUser() { return $this->user; } /** * Set the user. * * @param UserInterface $user */ public function setUser(UserInterface $user) { $this->user = $user; } /** * {@inheritDoc} */ public function serialize() { return serialize(array( $this->user, parent::serialize(), )); } /** * {@inheritDoc} */ public function unserialize($str) { list($this->user, $parentData) = unserialize($str); parent::unserialize($parentData); } } PK!7w-LSymfony/Component/Security/Core/Exception/AuthenticationServiceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * AuthenticationServiceException is thrown when an authentication request could not be processed due to a system problem. * * @author Fabien Potencier * @author Alexander */ class AuthenticationServiceException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Authentication request could not be processed due to a system problem.'; } } PK!xBESymfony/Component/Security/Core/Exception/AccountExpiredException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * AccountExpiredException is thrown when the user account has expired. * * @author Fabien Potencier * @author Alexander */ class AccountExpiredException extends AccountStatusException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Account has expired.'; } } PK!և?Symfony/Component/Security/Core/Exception/DisabledException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * DisabledException is thrown when the user account is disabled. * * @author Fabien Potencier * @author Alexander */ class DisabledException extends AccountStatusException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Account is disabled.'; } } PK!eCSymfony/Component/Security/Core/Exception/NonceExpiredException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * NonceExpiredException is thrown when an authentication is rejected because * the digest nonce has expired. * * @author Fabien Potencier * @author Alexander */ class NonceExpiredException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Digest nonce has expired.'; } } PK!ʝ9FSymfony/Component/Security/Core/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * Base InvalidArgumentException for the Security component. * * @author Bernhard Schussek */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK!OGSymfony/Component/Security/Core/Exception/InvalidCsrfTokenException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Exception; /** * This exception is thrown when the csrf token is invalid. * * @author Johannes M. Schmitt * @author Alexander */ class InvalidCsrfTokenException extends AuthenticationException { /** * {@inheritDoc} */ public function getMessageKey() { return 'Invalid CSRF token.'; } } PK!Õ  5Symfony/Component/Security/Core/Util/SecureRandom.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Util; use Psr\Log\LoggerInterface; /** * A secure random number generator implementation. * * @author Fabien Potencier * @author Johannes M. Schmitt */ final class SecureRandom implements SecureRandomInterface { private $logger; private $useOpenSsl; private $seed; private $seedUpdated; private $seedLastUpdatedAt; private $seedFile; /** * Constructor. * * Be aware that a guessable seed will severely compromise the PRNG * algorithm that is employed. * * @param string $seedFile * @param LoggerInterface $logger */ public function __construct($seedFile = null, LoggerInterface $logger = null) { $this->seedFile = $seedFile; $this->logger = $logger; // determine whether to use OpenSSL if (defined('PHP_WINDOWS_VERSION_BUILD') && version_compare(PHP_VERSION, '5.3.4', '<')) { $this->useOpenSsl = false; } elseif (!function_exists('openssl_random_pseudo_bytes')) { if (null !== $this->logger) { $this->logger->notice('It is recommended that you enable the "openssl" extension for random number generation.'); } $this->useOpenSsl = false; } else { $this->useOpenSsl = true; } } /** * {@inheritdoc} */ public function nextBytes($nbBytes) { // try OpenSSL if ($this->useOpenSsl) { $bytes = openssl_random_pseudo_bytes($nbBytes, $strong); if (false !== $bytes && true === $strong) { return $bytes; } if (null !== $this->logger) { $this->logger->info('OpenSSL did not produce a secure random number.'); } } // initialize seed if (null === $this->seed) { if (null === $this->seedFile) { throw new \RuntimeException('You need to specify a file path to store the seed.'); } if (is_file($this->seedFile)) { list($this->seed, $this->seedLastUpdatedAt) = $this->readSeed(); } else { $this->seed = uniqid(mt_rand(), true); $this->updateSeed(); } } $bytes = ''; while (strlen($bytes) < $nbBytes) { static $incr = 1; $bytes .= hash('sha512', $incr++.$this->seed.uniqid(mt_rand(), true).$nbBytes, true); $this->seed = base64_encode(hash('sha512', $this->seed.$bytes.$nbBytes, true)); $this->updateSeed(); } return substr($bytes, 0, $nbBytes); } private function readSeed() { return json_decode(file_get_contents($this->seedFile)); } private function updateSeed() { if (!$this->seedUpdated && $this->seedLastUpdatedAt < time() - mt_rand(1, 10)) { file_put_contents($this->seedFile, json_encode(array($this->seed, microtime(true)))); } $this->seedUpdated = true; } } PK!Ua4Symfony/Component/Security/Core/Util/StringUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Util; /** * String utility functions. * * @author Fabien Potencier */ class StringUtils { /** * This class should not be instantiated */ private function __construct() {} /** * Compares two strings. * * This method implements a constant-time algorithm to compare strings. * * @param string $knownString The string of known length to compare against * @param string $userInput The string that the user can control * * @return Boolean true if the two strings are the same, false otherwise */ public static function equals($knownString, $userInput) { // Prevent issues if string length is 0 $knownString .= chr(0); $userInput .= chr(0); $knownLen = strlen($knownString); $userLen = strlen($userInput); // Set the result to the difference between the lengths $result = $knownLen - $userLen; // Note that we ALWAYS iterate over the user-supplied length // This is to prevent leaking length information for ($i = 0; $i < $userLen; $i++) { // Using % here is a trick to prevent notices // It's safe, since if the lengths are different // $result is already non-0 $result |= (ord($knownString[$i % $knownLen]) ^ ord($userInput[$i])); } // They are only identical strings if $result is exactly 0... return 0 === $result; } } PK!T,,3Symfony/Component/Security/Core/Util/ClassUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Util; /** * Class related functionality for objects that * might or might not be proxy objects at the moment. * * @see Doctrine\Common\Util\ClassUtils * * @author Benjamin Eberlei * @author Johannes Schmitt */ class ClassUtils { /** * Marker for Proxy class names. * * @var string */ const MARKER = '__CG__'; /** * Length of the proxy marker * * @var int */ const MARKER_LENGTH = 6; /** * This class should not be instantiated */ private function __construct() {} /** * Gets the real class name of a class name that could be a proxy. * * @param string|object * @return string */ public static function getRealClass($object) { $class = is_object($object) ? get_class($object) : $object; if (false === $pos = strrpos($class, '\\'.self::MARKER.'\\')) { return $class; } return substr($class, $pos + self::MARKER_LENGTH + 2); } } PK! >Symfony/Component/Security/Core/Util/SecureRandomInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Util; /** * Interface that needs to be implemented by all secure random number generators. * * @author Fabien Potencier */ interface SecureRandomInterface { /** * Generates the specified number of secure random bytes. * * @param integer $nbBytes * * @return string */ public function nextBytes($nbBytes); } PK!m2GSymfony/Component/Security/Core/Authorization/AccessDecisionManager.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AccessDecisionManager is the base class for all access decision managers * that use decision voters. * * @author Fabien Potencier */ class AccessDecisionManager implements AccessDecisionManagerInterface { private $voters; private $strategy; private $allowIfAllAbstainDecisions; private $allowIfEqualGrantedDeniedDecisions; /** * Constructor. * * @param VoterInterface[] $voters An array of VoterInterface instances * @param string $strategy The vote strategy * @param Boolean $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not * @param Boolean $allowIfEqualGrantedDeniedDecisions Whether to grant access if result are equals * * @throws \InvalidArgumentException */ public function __construct(array $voters, $strategy = 'affirmative', $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true) { if (!$voters) { throw new \InvalidArgumentException('You must at least add one voter.'); } $strategyMethod = 'decide'.ucfirst($strategy); if (!is_callable(array($this, $strategyMethod))) { throw new \InvalidArgumentException(sprintf('The strategy "%s" is not supported.', $strategy)); } $this->voters = $voters; $this->strategy = $strategyMethod; $this->allowIfAllAbstainDecisions = (Boolean) $allowIfAllAbstainDecisions; $this->allowIfEqualGrantedDeniedDecisions = (Boolean) $allowIfEqualGrantedDeniedDecisions; } /** * {@inheritdoc} */ public function decide(TokenInterface $token, array $attributes, $object = null) { return $this->{$this->strategy}($token, $attributes, $object); } /** * {@inheritdoc} */ public function supportsAttribute($attribute) { foreach ($this->voters as $voter) { if ($voter->supportsAttribute($attribute)) { return true; } } return false; } /** * {@inheritdoc} */ public function supportsClass($class) { foreach ($this->voters as $voter) { if ($voter->supportsClass($class)) { return true; } } return false; } /** * Grants access if any voter returns an affirmative response. * * If all voters abstained from voting, the decision will be based on the * allowIfAllAbstainDecisions property value (defaults to false). */ private function decideAffirmative(TokenInterface $token, array $attributes, $object = null) { $deny = 0; foreach ($this->voters as $voter) { $result = $voter->vote($token, $object, $attributes); switch ($result) { case VoterInterface::ACCESS_GRANTED: return true; case VoterInterface::ACCESS_DENIED: ++$deny; break; default: break; } } if ($deny > 0) { return false; } return $this->allowIfAllAbstainDecisions; } /** * Grants access if there is consensus of granted against denied responses. * * Consensus means majority-rule (ignoring abstains) rather than unanimous * agreement (ignoring abstains). If you require unanimity, see * UnanimousBased. * * If there were an equal number of grant and deny votes, the decision will * be based on the allowIfEqualGrantedDeniedDecisions property value * (defaults to true). * * If all voters abstained from voting, the decision will be based on the * allowIfAllAbstainDecisions property value (defaults to false). */ private function decideConsensus(TokenInterface $token, array $attributes, $object = null) { $grant = 0; $deny = 0; $abstain = 0; foreach ($this->voters as $voter) { $result = $voter->vote($token, $object, $attributes); switch ($result) { case VoterInterface::ACCESS_GRANTED: ++$grant; break; case VoterInterface::ACCESS_DENIED: ++$deny; break; default: ++$abstain; break; } } if ($grant > $deny) { return true; } if ($deny > $grant) { return false; } if ($grant == $deny && $grant != 0) { return $this->allowIfEqualGrantedDeniedDecisions; } return $this->allowIfAllAbstainDecisions; } /** * Grants access if only grant (or abstain) votes were received. * * If all voters abstained from voting, the decision will be based on the * allowIfAllAbstainDecisions property value (defaults to false). */ private function decideUnanimous(TokenInterface $token, array $attributes, $object = null) { $grant = 0; foreach ($attributes as $attribute) { foreach ($this->voters as $voter) { $result = $voter->vote($token, $object, array($attribute)); switch ($result) { case VoterInterface::ACCESS_GRANTED: ++$grant; break; case VoterInterface::ACCESS_DENIED: return false; default: break; } } } // no deny votes if ($grant > 0) { return true; } return $this->allowIfAllAbstainDecisions; } } PK!З~ASymfony/Component/Security/Core/Authorization/Voter/RoleVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * RoleVoter votes if any attribute starts with a given prefix. * * @author Fabien Potencier */ class RoleVoter implements VoterInterface { private $prefix; /** * Constructor. * * @param string $prefix The role prefix */ public function __construct($prefix = 'ROLE_') { $this->prefix = $prefix; } /** * {@inheritdoc} */ public function supportsAttribute($attribute) { return 0 === strpos($attribute, $this->prefix); } /** * {@inheritdoc} */ public function supportsClass($class) { return true; } /** * {@inheritdoc} */ public function vote(TokenInterface $token, $object, array $attributes) { $result = VoterInterface::ACCESS_ABSTAIN; $roles = $this->extractRoles($token); foreach ($attributes as $attribute) { if (!$this->supportsAttribute($attribute)) { continue; } $result = VoterInterface::ACCESS_DENIED; foreach ($roles as $role) { if ($attribute === $role->getRole()) { return VoterInterface::ACCESS_GRANTED; } } } return $result; } protected function extractRoles(TokenInterface $token) { return $token->getRoles(); } } PK!~fJSymfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; /** * RoleHierarchyVoter uses a RoleHierarchy to determine the roles granted to * the user before voting. * * @author Fabien Potencier */ class RoleHierarchyVoter extends RoleVoter { private $roleHierarchy; public function __construct(RoleHierarchyInterface $roleHierarchy, $prefix = 'ROLE_') { $this->roleHierarchy = $roleHierarchy; parent::__construct($prefix); } /** * {@inheritdoc} */ protected function extractRoles(TokenInterface $token) { return $this->roleHierarchy->getReachableRoles($token->getRoles()); } } PK!`c GSymfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; use Symfony\Component\Security\Core\Authorization\ExpressionLanguage; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\HttpFoundation\Request; /** * ExpressionVoter votes based on the evaluation of an expression. * * @author Fabien Potencier */ class ExpressionVoter implements VoterInterface { private $expressionLanguage; private $trustResolver; private $roleHierarchy; /** * Constructor. * * @param ExpressionLanguage $expressionLanguage */ public function __construct(ExpressionLanguage $expressionLanguage, AuthenticationTrustResolverInterface $trustResolver, RoleHierarchyInterface $roleHierarchy = null) { $this->expressionLanguage = $expressionLanguage; $this->trustResolver = $trustResolver; $this->roleHierarchy = $roleHierarchy; } /** * {@inheritdoc} */ public function supportsAttribute($attribute) { return $attribute instanceof Expression; } /** * {@inheritdoc} */ public function supportsClass($class) { return true; } /** * {@inheritdoc} */ public function vote(TokenInterface $token, $object, array $attributes) { $result = VoterInterface::ACCESS_ABSTAIN; $variables = null; foreach ($attributes as $attribute) { if (!$this->supportsAttribute($attribute)) { continue; } if (null === $variables) { $variables = $this->getVariables($token, $object); } $result = VoterInterface::ACCESS_DENIED; if ($this->expressionLanguage->evaluate($attribute, $variables)) { return VoterInterface::ACCESS_GRANTED; } } return $result; } private function getVariables(TokenInterface $token, $object) { if (null !== $this->roleHierarchy) { $roles = $this->roleHierarchy->getReachableRoles($token->getRoles()); } else { $roles = $token->getRoles(); } $variables = array( 'token' => $token, 'user' => $token->getUser(), 'object' => $object, 'roles' => array_map(function ($role) { return $role->getRole(); }, $roles), 'trust_resolver' => $this->trustResolver, ); // this is mainly to propose a better experience when the expression is used // in an access control rule, as the developer does not know that it's going // to be handled by this voter if ($object instanceof Request) { $variables['request'] = $object; } return $variables; } } PK!X,m  JSymfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AuthenticatedVoter votes if an attribute like IS_AUTHENTICATED_FULLY, * IS_AUTHENTICATED_REMEMBERED, or IS_AUTHENTICATED_ANONYMOUSLY is present. * * This list is most restrictive to least restrictive checking. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class AuthenticatedVoter implements VoterInterface { const IS_AUTHENTICATED_FULLY = 'IS_AUTHENTICATED_FULLY'; const IS_AUTHENTICATED_REMEMBERED = 'IS_AUTHENTICATED_REMEMBERED'; const IS_AUTHENTICATED_ANONYMOUSLY = 'IS_AUTHENTICATED_ANONYMOUSLY'; private $authenticationTrustResolver; /** * Constructor. * * @param AuthenticationTrustResolverInterface $authenticationTrustResolver */ public function __construct(AuthenticationTrustResolverInterface $authenticationTrustResolver) { $this->authenticationTrustResolver = $authenticationTrustResolver; } /** * {@inheritdoc} */ public function supportsAttribute($attribute) { return null !== $attribute && (self::IS_AUTHENTICATED_FULLY === $attribute || self::IS_AUTHENTICATED_REMEMBERED === $attribute || self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute); } /** * {@inheritdoc} */ public function supportsClass($class) { return true; } /** * {@inheritdoc} */ public function vote(TokenInterface $token, $object, array $attributes) { $result = VoterInterface::ACCESS_ABSTAIN; foreach ($attributes as $attribute) { if (!$this->supportsAttribute($attribute)) { continue; } $result = VoterInterface::ACCESS_DENIED; if (self::IS_AUTHENTICATED_FULLY === $attribute && $this->authenticationTrustResolver->isFullFledged($token)) { return VoterInterface::ACCESS_GRANTED; } if (self::IS_AUTHENTICATED_REMEMBERED === $attribute && ($this->authenticationTrustResolver->isRememberMe($token) || $this->authenticationTrustResolver->isFullFledged($token))) { return VoterInterface::ACCESS_GRANTED; } if (self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute && ($this->authenticationTrustResolver->isAnonymous($token) || $this->authenticationTrustResolver->isRememberMe($token) || $this->authenticationTrustResolver->isFullFledged($token))) { return VoterInterface::ACCESS_GRANTED; } } return $result; } } PK!>FSymfony/Component/Security/Core/Authorization/Voter/VoterInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * VoterInterface is the interface implemented by all voters. * * @author Fabien Potencier */ interface VoterInterface { const ACCESS_GRANTED = 1; const ACCESS_ABSTAIN = 0; const ACCESS_DENIED = -1; /** * Checks if the voter supports the given attribute. * * @param string $attribute An attribute * * @return Boolean true if this Voter supports the attribute, false otherwise */ public function supportsAttribute($attribute); /** * Checks if the voter supports the given class. * * @param string $class A class name * * @return Boolean true if this Voter can process the class */ public function supportsClass($class); /** * Returns the vote for the given parameters. * * This method must return one of the following constants: * ACCESS_GRANTED, ACCESS_DENIED, or ACCESS_ABSTAIN. * * @param TokenInterface $token A TokenInterface instance * @param object $object The object to secure * @param array $attributes An array of attributes associated with the method being invoked * * @return integer either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED */ public function vote(TokenInterface $token, $object, array $attributes); } PK!:22PSymfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AccessDecisionManagerInterface makes authorization decisions. * * @author Fabien Potencier */ interface AccessDecisionManagerInterface { /** * Decides whether the access is possible or not. * * @param TokenInterface $token A TokenInterface instance * @param array $attributes An array of attributes associated with the method being invoked * @param object $object The object to secure * * @return Boolean true if the access is granted, false otherwise */ public function decide(TokenInterface $token, array $attributes, $object = null); /** * Checks if the access decision manager supports the given attribute. * * @param string $attribute An attribute * * @return Boolean true if this decision manager supports the attribute, false otherwise */ public function supportsAttribute($attribute); /** * Checks if the access decision manager supports the given class. * * @param string $class A class name * * @return true if this decision manager can process the class */ public function supportsClass($class); } PK!ѵ^DSymfony/Component/Security/Core/Authorization/ExpressionLanguage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authorization; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; /** * Adds some function to the default ExpressionLanguage. * * @author Fabien Potencier */ class ExpressionLanguage extends BaseExpressionLanguage { protected function registerFunctions() { parent::registerFunctions(); $this->register('is_anonymous', function () { return '$trust_resolver->isAnonymous($token)'; }, function (array $variables) { return $variables['trust_resolver']->isAnonymous($variables['token']); }); $this->register('is_authenticated', function () { return '$token && !$trust_resolver->isAnonymous($token)'; }, function (array $variables) { return $variables['token'] && !$variables['trust_resolver']->isAnonymous($variables['token']); }); $this->register('is_fully_authenticated', function () { return '$trust_resolver->isFullFledged($token)'; }, function (array $variables) { return $variables['trust_resolver']->isFullFledged($variables['token']); }); $this->register('is_remember_me', function () { return '$trust_resolver->isRememberMe($token)'; }, function (array $variables) { return $variables['trust_resolver']->isRememberMe($variables['token']); }); $this->register('has_role', function ($role) { return sprintf('in_array(%s, $roles)', $role); }, function (array $variables, $role) { return in_array($role, $variables['roles']); }); } } PK!=Symfony/Component/Security/Core/User/UserCheckerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; /** * UserCheckerInterface checks user account when authentication occurs. * * This should not be used to make authentication decisions. * * @author Fabien Potencier */ interface UserCheckerInterface { /** * Checks the user account before authentication. * * @param UserInterface $user a UserInterface instance */ public function checkPreAuth(UserInterface $user); /** * Checks the user account after authentication. * * @param UserInterface $user a UserInterface instance */ public function checkPostAuth(UserInterface $user); } PK!^ :Symfony/Component/Security/Core/User/ChainUserProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; /** * Chain User Provider. * * This provider calls several leaf providers in a chain until one is able to * handle the request. * * @author Johannes M. Schmitt */ class ChainUserProvider implements UserProviderInterface { private $providers; public function __construct(array $providers) { $this->providers = $providers; } /** * @return array */ public function getProviders() { return $this->providers; } /** * {@inheritDoc} */ public function loadUserByUsername($username) { foreach ($this->providers as $provider) { try { return $provider->loadUserByUsername($username); } catch (UsernameNotFoundException $notFound) { // try next one } } $ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $username)); $ex->setUsername($username); throw $ex; } /** * {@inheritDoc} */ public function refreshUser(UserInterface $user) { $supportedUserFound = false; foreach ($this->providers as $provider) { try { return $provider->refreshUser($user); } catch (UnsupportedUserException $unsupported) { // try next one } catch (UsernameNotFoundException $notFound) { $supportedUserFound = true; // try next one } } if ($supportedUserFound) { $ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $user->getUsername())); $ex->setUsername($user->getUsername()); throw $ex; } else { throw new UnsupportedUserException(sprintf('The account "%s" is not supported.', get_class($user))); } } /** * {@inheritDoc} */ public function supportsClass($class) { foreach ($this->providers as $provider) { if ($provider->supportsClass($class)) { return true; } } return false; } } PK!D$..4Symfony/Component/Security/Core/User/UserChecker.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\CredentialsExpiredException; use Symfony\Component\Security\Core\Exception\LockedException; use Symfony\Component\Security\Core\Exception\DisabledException; use Symfony\Component\Security\Core\Exception\AccountExpiredException; /** * UserChecker checks the user account flags. * * @author Fabien Potencier */ class UserChecker implements UserCheckerInterface { /** * {@inheritdoc} */ public function checkPreAuth(UserInterface $user) { if (!$user instanceof AdvancedUserInterface) { return; } if (!$user->isAccountNonLocked()) { $ex = new LockedException('User account is locked.'); $ex->setUser($user); throw $ex; } if (!$user->isEnabled()) { $ex = new DisabledException('User account is disabled.'); $ex->setUser($user); throw $ex; } if (!$user->isAccountNonExpired()) { $ex = new AccountExpiredException('User account has expired.'); $ex->setUser($user); throw $ex; } } /** * {@inheritdoc} */ public function checkPostAuth(UserInterface $user) { if (!$user instanceof AdvancedUserInterface) { return; } if (!$user->isCredentialsNonExpired()) { $ex = new CredentialsExpiredException('User credentials have expired.'); $ex->setUser($user); throw $ex; } } } PK!6bY Y >Symfony/Component/Security/Core/User/AdvancedUserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\AccountStatusException; use Symfony\Component\Security\Core\Exception\AccountExpiredException; use Symfony\Component\Security\Core\Exception\LockedException; use Symfony\Component\Security\Core\Exception\CredentialsExpiredException; use Symfony\Component\Security\Core\Exception\DisabledException; /** * Adds extra features to a user class related to account status flags. * * This interface can be implemented in place of UserInterface if you'd like * the authentication system to consider different account status flags * during authentication. If any of the methods in this interface return * false, authentication will fail. * * If you need to perform custom logic for any of these situations, then * you will need to register an exception listener and watch for the specific * exception instances thrown in each case. All exceptions are a subclass * of AccountStatusException * * @see UserInterface * @see AccountStatusException * * @author Fabien Potencier */ interface AdvancedUserInterface extends UserInterface { /** * Checks whether the user's account has expired. * * Internally, if this method returns false, the authentication system * will throw an AccountExpiredException and prevent login. * * @return Boolean true if the user's account is non expired, false otherwise * * @see AccountExpiredException */ public function isAccountNonExpired(); /** * Checks whether the user is locked. * * Internally, if this method returns false, the authentication system * will throw a LockedException and prevent login. * * @return Boolean true if the user is not locked, false otherwise * * @see LockedException */ public function isAccountNonLocked(); /** * Checks whether the user's credentials (password) has expired. * * Internally, if this method returns false, the authentication system * will throw a CredentialsExpiredException and prevent login. * * @return Boolean true if the user's credentials are non expired, false otherwise * * @see CredentialsExpiredException */ public function isCredentialsNonExpired(); /** * Checks whether the user is enabled. * * Internally, if this method returns false, the authentication system * will throw a DisabledException and prevent login. * * @return Boolean true if the user is enabled, false otherwise * * @see DisabledException */ public function isEnabled(); } PK! 6Symfony/Component/Security/Core/User/UserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Role\Role; /** * Represents the interface that all user classes must implement. * * This interface is useful because the authentication layer can deal with * the object through its lifecycle, using the object to get the encoded * password (for checking against a submitted password), assigning roles * and so on. * * Regardless of how your user are loaded or where they come from (a database, * configuration, web service, etc), you will have a class that implements * this interface. Objects that implement this interface are created and * loaded by different objects that implement UserProviderInterface * * @see UserProviderInterface * @see AdvancedUserInterface * * @author Fabien Potencier */ interface UserInterface { /** * Returns the roles granted to the user. * * * public function getRoles() * { * return array('ROLE_USER'); * } * * * Alternatively, the roles might be stored on a ``roles`` property, * and populated in any number of different ways when the user object * is created. * * @return Role[] The user roles */ public function getRoles(); /** * Returns the password used to authenticate the user. * * This should be the encoded password. On authentication, a plain-text * password will be salted, encoded, and then compared to this value. * * @return string The password */ public function getPassword(); /** * Returns the salt that was originally used to encode the password. * * This can return null if the password was not encoded using a salt. * * @return string|null The salt */ public function getSalt(); /** * Returns the username used to authenticate the user. * * @return string The username */ public function getUsername(); /** * Removes sensitive data from the user. * * This is important if, at any given point, sensitive information like * the plain-text password is stored on this object. */ public function eraseCredentials(); } PK!/!  =Symfony/Component/Security/Core/User/InMemoryUserProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; /** * InMemoryUserProvider is a simple non persistent user provider. * * Useful for testing, demonstration, prototyping, and for simple needs * (a backend with a unique admin for instance) * * @author Fabien Potencier */ class InMemoryUserProvider implements UserProviderInterface { private $users; /** * Constructor. * * The user array is a hash where the keys are usernames and the values are * an array of attributes: 'password', 'enabled', and 'roles'. * * @param array $users An array of users */ public function __construct(array $users = array()) { foreach ($users as $username => $attributes) { $password = isset($attributes['password']) ? $attributes['password'] : null; $enabled = isset($attributes['enabled']) ? $attributes['enabled'] : true; $roles = isset($attributes['roles']) ? $attributes['roles'] : array(); $user = new User($username, $password, $roles, $enabled, true, true, true); $this->createUser($user); } } /** * Adds a new User to the provider. * * @param UserInterface $user A UserInterface instance * * @throws \LogicException */ public function createUser(UserInterface $user) { if (isset($this->users[strtolower($user->getUsername())])) { throw new \LogicException('Another user with the same username already exists.'); } $this->users[strtolower($user->getUsername())] = $user; } /** * {@inheritdoc} */ public function loadUserByUsername($username) { if (!isset($this->users[strtolower($username)])) { $ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); $ex->setUsername($username); throw $ex; } $user = $this->users[strtolower($username)]; return new User($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled(), $user->isAccountNonExpired(), $user->isCredentialsNonExpired(), $user->isAccountNonLocked()); } /** * {@inheritDoc} */ public function refreshUser(UserInterface $user) { if (!$user instanceof User) { throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); } return $this->loadUserByUsername($user->getUsername()); } /** * {@inheritDoc} */ public function supportsClass($class) { return $class === 'Symfony\Component\Security\Core\User\User'; } } PK!//;Symfony/Component/Security/Core/User/EquatableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; /** * EquatableInterface used to test if two objects are equal in security * and re-authentication context. * * @author Dariusz Górecki */ interface EquatableInterface { /** * The equality comparison should neither be done by referential equality * nor by comparing identities (i.e. getId() === getId()). * * However, you do not need to compare every attribute, but only those that * are relevant for assessing whether re-authentication is required. * * Also implementation should consider that $user instance may implement * the extended user interface `AdvancedUserInterface`. * * @param UserInterface $user * * @return Boolean */ public function isEqualTo(UserInterface $user); } PK!svW W >Symfony/Component/Security/Core/User/UserProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; /** * Represents a class that loads UserInterface objects from some source for the authentication system. * * In a typical authentication configuration, a username (i.e. some unique * user identifier) credential enters the system (via form login, or any * method). The user provider that is configured with that authentication * method is asked to load the UserInterface object for the given username * (via loadUserByUsername) so that the rest of the process can continue. * * Internally, a user provider can load users from any source (databases, * configuration, web service). This is totally independent of how the authentication * information is submitted or what the UserInterface object looks like. * * @see UserInterface * * @author Fabien Potencier */ interface UserProviderInterface { /** * Loads the user for the given username. * * This method must throw UsernameNotFoundException if the user is not * found. * * @param string $username The username * * @return UserInterface * * @see UsernameNotFoundException * * @throws UsernameNotFoundException if the user is not found * */ public function loadUserByUsername($username); /** * Refreshes the user for the account interface. * * It is up to the implementation to decide if the user data should be * totally reloaded (e.g. from the database), or if the UserInterface * object can just be merged into some internal array of users / identity * map. * @param UserInterface $user * * @return UserInterface * * @throws UnsupportedUserException if the account is not supported */ public function refreshUser(UserInterface $user); /** * Whether this provider supports the given user class * * @param string $class * * @return Boolean */ public function supportsClass($class); } PK!1G G -Symfony/Component/Security/Core/User/User.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\User; /** * User is the user implementation used by the in-memory user provider. * * This should not be used for anything else. * * @author Fabien Potencier */ final class User implements AdvancedUserInterface { private $username; private $password; private $enabled; private $accountNonExpired; private $credentialsNonExpired; private $accountNonLocked; private $roles; public function __construct($username, $password, array $roles = array(), $enabled = true, $userNonExpired = true, $credentialsNonExpired = true, $userNonLocked = true) { if (empty($username)) { throw new \InvalidArgumentException('The username cannot be empty.'); } $this->username = $username; $this->password = $password; $this->enabled = $enabled; $this->accountNonExpired = $userNonExpired; $this->credentialsNonExpired = $credentialsNonExpired; $this->accountNonLocked = $userNonLocked; $this->roles = $roles; } /** * {@inheritdoc} */ public function getRoles() { return $this->roles; } /** * {@inheritdoc} */ public function getPassword() { return $this->password; } /** * {@inheritdoc} */ public function getSalt() { return null; } /** * {@inheritdoc} */ public function getUsername() { return $this->username; } /** * {@inheritdoc} */ public function isAccountNonExpired() { return $this->accountNonExpired; } /** * {@inheritdoc} */ public function isAccountNonLocked() { return $this->accountNonLocked; } /** * {@inheritdoc} */ public function isCredentialsNonExpired() { return $this->credentialsNonExpired; } /** * {@inheritdoc} */ public function isEnabled() { return $this->enabled; } /** * {@inheritdoc} */ public function eraseCredentials() { } } PK!'za! ! 3Symfony/Component/Security/Core/SecurityContext.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * SecurityContext is the main entry point of the Security component. * * It gives access to the token representing the current user authentication. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class SecurityContext implements SecurityContextInterface { private $token; private $accessDecisionManager; private $authenticationManager; private $alwaysAuthenticate; /** * Constructor. * * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManager instance * @param AccessDecisionManagerInterface|null $accessDecisionManager An AccessDecisionManager instance * @param Boolean $alwaysAuthenticate */ public function __construct(AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager, $alwaysAuthenticate = false) { $this->authenticationManager = $authenticationManager; $this->accessDecisionManager = $accessDecisionManager; $this->alwaysAuthenticate = $alwaysAuthenticate; } /** * {@inheritdoc} * * @throws AuthenticationCredentialsNotFoundException when the security context has no authentication token. */ final public function isGranted($attributes, $object = null) { if (null === $this->token) { throw new AuthenticationCredentialsNotFoundException('The security context contains no authentication token. One possible reason may be that there is no firewall configured for this URL.'); } if ($this->alwaysAuthenticate || !$this->token->isAuthenticated()) { $this->token = $this->authenticationManager->authenticate($this->token); } if (!is_array($attributes)) { $attributes = array($attributes); } return $this->accessDecisionManager->decide($this->token, $attributes, $object); } /** * {@inheritdoc} */ public function getToken() { return $this->token; } /** * {@inheritdoc} */ public function setToken(TokenInterface $token = null) { $this->token = $token; } } PK!l8Symfony/Component/Security/Core/AuthenticationEvents.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core; final class AuthenticationEvents { /** * The AUTHENTICATION_SUCCESS event occurs after a user is authenticated * by one provider. * * The event listener method receives a * Symfony\Component\Security\Core\Event\AuthenticationEvent instance. * * @var string */ const AUTHENTICATION_SUCCESS = 'security.authentication.success'; /** * The AUTHENTICATION_FAILURE event occurs after a user cannot be * authenticated by any of the providers. * * The event listener method receives a * Symfony\Component\Security\Core\Event\AuthenticationFailureEvent * instance. * * @var string */ const AUTHENTICATION_FAILURE = 'security.authentication.failure'; } PK!x$ccPSymfony/Component/Security/Core/Authentication/AuthenticationProviderManager.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent; use Symfony\Component\Security\Core\Event\AuthenticationEvent; use Symfony\Component\Security\Core\AuthenticationEvents; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Core\Exception\AccountStatusException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\ProviderNotFoundException; use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * AuthenticationProviderManager uses a list of AuthenticationProviderInterface * instances to authenticate a Token. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class AuthenticationProviderManager implements AuthenticationManagerInterface { private $providers; private $eraseCredentials; private $eventDispatcher; /** * Constructor. * * @param AuthenticationProviderInterface[] $providers An array of AuthenticationProviderInterface instances * @param Boolean $eraseCredentials Whether to erase credentials after authentication or not * * @throws \InvalidArgumentException */ public function __construct(array $providers, $eraseCredentials = true) { if (!$providers) { throw new \InvalidArgumentException('You must at least add one authentication provider.'); } $this->providers = $providers; $this->eraseCredentials = (Boolean) $eraseCredentials; } public function setEventDispatcher(EventDispatcherInterface $dispatcher) { $this->eventDispatcher = $dispatcher; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { $lastException = null; $result = null; foreach ($this->providers as $provider) { if (!$provider->supports($token)) { continue; } try { $result = $provider->authenticate($token); if (null !== $result) { break; } } catch (AccountStatusException $e) { $e->setToken($token); throw $e; } catch (AuthenticationException $e) { $lastException = $e; } } if (null !== $result) { if (true === $this->eraseCredentials) { $result->eraseCredentials(); } if (null !== $this->eventDispatcher) { $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_SUCCESS, new AuthenticationEvent($result)); } return $result; } if (null === $lastException) { $lastException = new ProviderNotFoundException(sprintf('No Authentication Provider found for token of class "%s".', get_class($token))); } if (null !== $this->eventDispatcher) { $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_FAILURE, new AuthenticationFailureEvent($token, $lastException)); } $lastException->setToken($token); throw $lastException; } } PK!¬> ##RSymfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\HttpFoundation\Request; /** * @author Jordi Boggiano */ interface SimplePreAuthenticatorInterface extends SimpleAuthenticatorInterface { public function createToken(Request $request, $providerKey); } PK!WOSymfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; /** * @author Jordi Boggiano */ interface SimpleAuthenticatorInterface { public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey); public function supportsToken(TokenInterface $token, $providerKey); } PK!>,vvXSymfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; /** * @author Jordi Boggiano */ class SimpleAuthenticationProvider implements AuthenticationProviderInterface { private $simpleAuthenticator; private $userProvider; private $providerKey; public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, UserProviderInterface $userProvider, $providerKey) { $this->simpleAuthenticator = $simpleAuthenticator; $this->userProvider = $userProvider; $this->providerKey = $providerKey; } public function authenticate(TokenInterface $token) { $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey); if ($authToken instanceof TokenInterface) { return $authToken; } throw new AuthenticationException('Simple authenticator failed to return an authenticated token.'); } public function supports(TokenInterface $token) { return $this->simpleAuthenticator->supportsToken($token, $this->providerKey); } } PK!USymfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; /** * DaoAuthenticationProvider uses a UserProviderInterface to retrieve the user * for a UsernamePasswordToken. * * @author Fabien Potencier */ class DaoAuthenticationProvider extends UserAuthenticationProvider { private $encoderFactory; private $userProvider; /** * Constructor. * * @param UserProviderInterface $userProvider An UserProviderInterface instance * @param UserCheckerInterface $userChecker An UserCheckerInterface instance * @param string $providerKey The provider key * @param EncoderFactoryInterface $encoderFactory An EncoderFactoryInterface instance * @param Boolean $hideUserNotFoundExceptions Whether to hide user not found exception or not */ public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, EncoderFactoryInterface $encoderFactory, $hideUserNotFoundExceptions = true) { parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions); $this->encoderFactory = $encoderFactory; $this->userProvider = $userProvider; } /** * {@inheritdoc} */ protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token) { $currentUser = $token->getUser(); if ($currentUser instanceof UserInterface) { if ($currentUser->getPassword() !== $user->getPassword()) { throw new BadCredentialsException('The credentials were changed from another session.'); } } else { if ("" === ($presentedPassword = $token->getCredentials())) { throw new BadCredentialsException('The presented password cannot be empty.'); } if (!$this->encoderFactory->getEncoder($user)->isPasswordValid($user->getPassword(), $presentedPassword, $user->getSalt())) { throw new BadCredentialsException('The presented password is invalid.'); } } } /** * {@inheritdoc} */ protected function retrieveUser($username, UsernamePasswordToken $token) { $user = $token->getUser(); if ($user instanceof UserInterface) { return $user; } try { $user = $this->userProvider->loadUserByUsername($username); if (!$user instanceof UserInterface) { throw new AuthenticationServiceException('The user provider must return a UserInterface object.'); } return $user; } catch (UsernameNotFoundException $notFound) { $notFound->setUsername($username); throw $notFound; } catch (\Exception $repositoryProblem) { $ex = new AuthenticationServiceException($repositoryProblem->getMessage(), 0, $repositoryProblem); $ex->setToken($token); throw $ex; } } } PK!byyVSymfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Role\SwitchUserRole; /** * UserProviderInterface retrieves users for UsernamePasswordToken tokens. * * @author Fabien Potencier */ abstract class UserAuthenticationProvider implements AuthenticationProviderInterface { private $hideUserNotFoundExceptions; private $userChecker; private $providerKey; /** * Constructor. * * @param UserCheckerInterface $userChecker An UserCheckerInterface interface * @param string $providerKey A provider key * @param Boolean $hideUserNotFoundExceptions Whether to hide user not found exception or not * * @throws \InvalidArgumentException */ public function __construct(UserCheckerInterface $userChecker, $providerKey, $hideUserNotFoundExceptions = true) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->userChecker = $userChecker; $this->providerKey = $providerKey; $this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { if (!$this->supports($token)) { return null; } $username = $token->getUsername(); if (empty($username)) { $username = 'NONE_PROVIDED'; } try { $user = $this->retrieveUser($username, $token); } catch (UsernameNotFoundException $notFound) { if ($this->hideUserNotFoundExceptions) { throw new BadCredentialsException('Bad credentials', 0, $notFound); } $notFound->setUsername($username); throw $notFound; } if (!$user instanceof UserInterface) { throw new AuthenticationServiceException('retrieveUser() must return a UserInterface.'); } try { $this->userChecker->checkPreAuth($user); $this->checkAuthentication($user, $token); $this->userChecker->checkPostAuth($user); } catch (BadCredentialsException $e) { if ($this->hideUserNotFoundExceptions) { throw new BadCredentialsException('Bad credentials', 0, $e); } throw $e; } $authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token)); $authenticatedToken->setAttributes($token->getAttributes()); return $authenticatedToken; } /** * {@inheritdoc} */ public function supports(TokenInterface $token) { return $token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey(); } /** * Retrieves roles from user and appends SwitchUserRole if original token contained one. * * @param UserInterface $user The user * @param TokenInterface $token The token * * @return Role[] The user roles */ private function getRoles(UserInterface $user, TokenInterface $token) { $roles = $user->getRoles(); foreach ($token->getRoles() as $role) { if ($role instanceof SwitchUserRole) { $roles[] = $role; break; } } return $roles; } /** * Retrieves the user from an implementation-specific location. * * @param string $username The username to retrieve * @param UsernamePasswordToken $token The Token * * @return UserInterface The user * * @throws AuthenticationException if the credentials could not be validated */ abstract protected function retrieveUser($username, UsernamePasswordToken $token); /** * Does additional checks on the user and token (like validating the * credentials). * * @param UserInterface $user The retrieved UserInterface instance * @param UsernamePasswordToken $token The UsernamePasswordToken token to be authenticated * * @throws AuthenticationException if the credentials could not be validated */ abstract protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token); } PK!JA\Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Core\Exception\BadCredentialsException; class RememberMeAuthenticationProvider implements AuthenticationProviderInterface { private $userChecker; private $key; private $providerKey; /** * Constructor. * * @param UserCheckerInterface $userChecker An UserCheckerInterface interface * @param string $key A key * @param string $providerKey A provider key */ public function __construct(UserCheckerInterface $userChecker, $key, $providerKey) { $this->userChecker = $userChecker; $this->key = $key; $this->providerKey = $providerKey; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { if (!$this->supports($token)) { return; } if ($this->key !== $token->getKey()) { throw new BadCredentialsException('The presented key does not match.'); } $user = $token->getUser(); $this->userChecker->checkPostAuth($user); $authenticatedToken = new RememberMeToken($user, $this->providerKey, $this->key); $authenticatedToken->setAttributes($token->getAttributes()); return $authenticatedToken; } /** * {@inheritdoc} */ public function supports(TokenInterface $token) { return $token instanceof RememberMeToken && $token->getProviderKey() === $this->providerKey; } } PK!X[Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; /** * AnonymousAuthenticationProvider validates AnonymousToken instances. * * @author Fabien Potencier */ class AnonymousAuthenticationProvider implements AuthenticationProviderInterface { private $key; /** * Constructor. * * @param string $key The key shared with the authentication token */ public function __construct($key) { $this->key = $key; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { if (!$this->supports($token)) { return null; } if ($this->key !== $token->getKey()) { throw new BadCredentialsException('The Token does not contain the expected key.'); } return $token; } /** * {@inheritdoc} */ public function supports(TokenInterface $token) { return $token instanceof AnonymousToken; } } PK!a""[Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; /** * AuthenticationProviderInterface is the interface for all authentication * providers. * * Concrete implementations processes specific Token instances. * * @author Fabien Potencier */ interface AuthenticationProviderInterface extends AuthenticationManagerInterface { /** * Checks whether this provider supports the given token. * * @param TokenInterface $token A TokenInterface instance * * @return Boolean true if the implementation supports the Token, false otherwise */ public function supports(TokenInterface $token); } PK!un\ bSymfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * Processes a pre-authenticated authentication request. * * This authentication provider will not perform any checks on authentication * requests, as they should already be pre-authenticated. However, the * UserProviderInterface implementation may still throw a * UsernameNotFoundException, for example. * * @author Fabien Potencier */ class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderInterface { private $userProvider; private $userChecker; private $providerKey; /** * Constructor. * * @param UserProviderInterface $userProvider An UserProviderInterface instance * @param UserCheckerInterface $userChecker An UserCheckerInterface instance * @param string $providerKey The provider key */ public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey) { $this->userProvider = $userProvider; $this->userChecker = $userChecker; $this->providerKey = $providerKey; } /** * {@inheritdoc} */ public function authenticate(TokenInterface $token) { if (!$this->supports($token)) { return null; } if (!$user = $token->getUser()) { throw new BadCredentialsException('No pre-authenticated principal found in request.'); } /* if (null === $token->getCredentials()) { throw new BadCredentialsException('No pre-authenticated credentials found in request.'); } */ $user = $this->userProvider->loadUserByUsername($user); $this->userChecker->checkPostAuth($user); $authenticatedToken = new PreAuthenticatedToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles()); $authenticatedToken->setAttributes($token->getAttributes()); return $authenticatedToken; } /** * {@inheritdoc} */ public function supports(TokenInterface $token) { return $token instanceof PreAuthenticatedToken && $this->providerKey === $token->getProviderKey(); } } PK!r3WWWSymfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * Interface for resolving the authentication status of a given token. * * @author Johannes M. Schmitt */ interface AuthenticationTrustResolverInterface { /** * Resolves whether the passed token implementation is authenticated * anonymously. * * If null is passed, the method must return false. * * @param TokenInterface $token * * @return Boolean */ public function isAnonymous(TokenInterface $token = null); /** * Resolves whether the passed token implementation is authenticated * using remember-me capabilities. * * @param TokenInterface $token * * @return Boolean */ public function isRememberMe(TokenInterface $token = null); /** * Resolves whether the passed token implementation is fully authenticated. * * @param TokenInterface $token * * @return Boolean */ public function isFullFledged(TokenInterface $token = null); } PK!ZvmSSymfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\RememberMe; use Symfony\Component\Security\Core\Exception\TokenNotFoundException; /** * This class is used for testing purposes, and is not really suited for production. * * @author Johannes M. Schmitt */ class InMemoryTokenProvider implements TokenProviderInterface { private $tokens = array(); /** * {@inheritdoc} */ public function loadTokenBySeries($series) { if (!isset($this->tokens[$series])) { throw new TokenNotFoundException('No token found.'); } return $this->tokens[$series]; } /** * {@inheritdoc} */ public function updateToken($series, $tokenValue, \DateTime $lastUsed) { if (!isset($this->tokens[$series])) { throw new TokenNotFoundException('No token found.'); } $token = new PersistentToken( $this->tokens[$series]->getClass(), $this->tokens[$series]->getUsername(), $series, $tokenValue, $lastUsed ); $this->tokens[$series] = $token; } /** * {@inheritdoc} */ public function deleteTokenBySeries($series) { unset($this->tokens[$series]); } /** * {@inheritdoc} */ public function createNewToken(PersistentTokenInterface $token) { $this->tokens[$token->getSeries()] = $token; } } PK!QZZVSymfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\RememberMe; /** * Interface to be implemented by persistent token classes (such as * Doctrine entities representing a remember-me token) * * @author Johannes M. Schmitt */ interface PersistentTokenInterface { /** * Returns the class of the user. * * @return string */ public function getClass(); /** * Returns the username. * * @return string */ public function getUsername(); /** * Returns the series. * * @return string */ public function getSeries(); /** * Returns the token value. * * @return string */ public function getTokenValue(); /** * Returns the time the token was last used. * * @return \DateTime */ public function getLastUsed(); } PK! TOMSymfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\RememberMe; /** * This class is only used by PersistentTokenRememberMeServices internally. * * @author Johannes M. Schmitt */ final class PersistentToken implements PersistentTokenInterface { private $class; private $username; private $series; private $tokenValue; private $lastUsed; /** * Constructor * * @param string $class * @param string $username * @param string $series * @param string $tokenValue * @param \DateTime $lastUsed * * @throws \InvalidArgumentException */ public function __construct($class, $username, $series, $tokenValue, \DateTime $lastUsed) { if (empty($class)) { throw new \InvalidArgumentException('$class must not be empty.'); } if (empty($username)) { throw new \InvalidArgumentException('$username must not be empty.'); } if (empty($series)) { throw new \InvalidArgumentException('$series must not be empty.'); } if (empty($tokenValue)) { throw new \InvalidArgumentException('$tokenValue must not be empty.'); } $this->class = $class; $this->username = $username; $this->series = $series; $this->tokenValue = $tokenValue; $this->lastUsed = $lastUsed; } /** * {@inheritdoc} */ public function getClass() { return $this->class; } /** * {@inheritdoc} */ public function getUsername() { return $this->username; } /** * {@inheritdoc} */ public function getSeries() { return $this->series; } /** * {@inheritdoc} */ public function getTokenValue() { return $this->tokenValue; } /** * {@inheritdoc} */ public function getLastUsed() { return $this->lastUsed; } } PK! CfTSymfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\RememberMe; use Symfony\Component\Security\Core\Exception\TokenNotFoundException; /** * Interface for TokenProviders * * @author Johannes M. Schmitt */ interface TokenProviderInterface { /** * Loads the active token for the given series. * * @param string $series * * @return PersistentTokenInterface * * @throws TokenNotFoundException if the token is not found */ public function loadTokenBySeries($series); /** * Deletes all tokens belonging to series. * * @param string $series */ public function deleteTokenBySeries($series); /** * Updates the token according to this data. * * @param string $series * @param string $tokenValue * @param \DateTime $lastUsed * @throws TokenNotFoundException if the token is not found */ public function updateToken($series, $tokenValue, \DateTime $lastUsed); /** * Creates a new token. * * @param PersistentTokenInterface $token */ public function createNewToken(PersistentTokenInterface $token); } PK!J-W;::SSymfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\HttpFoundation\Request; /** * @author Jordi Boggiano */ interface SimpleFormAuthenticatorInterface extends SimpleAuthenticatorInterface { public function createToken(Request $request, $username, $password, $providerKey); } PK!:6NSymfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * The default implementation of the authentication trust resolver. * * @author Johannes M. Schmitt */ class AuthenticationTrustResolver implements AuthenticationTrustResolverInterface { private $anonymousClass; private $rememberMeClass; /** * Constructor * * @param string $anonymousClass * @param string $rememberMeClass */ public function __construct($anonymousClass, $rememberMeClass) { $this->anonymousClass = $anonymousClass; $this->rememberMeClass = $rememberMeClass; } /** * {@inheritDoc} */ public function isAnonymous(TokenInterface $token = null) { if (null === $token) { return false; } return $token instanceof $this->anonymousClass; } /** * {@inheritDoc} */ public function isRememberMe(TokenInterface $token = null) { if (null === $token) { return false; } return $token instanceof $this->rememberMeClass; } /** * {@inheritDoc} */ public function isFullFledged(TokenInterface $token = null) { if (null === $token) { return false; } return !$this->isAnonymous($token) && !$this->isRememberMe($token); } } PK!f QSymfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; /** * AuthenticationManagerInterface is the interface for authentication managers, * which process Token authentication. * * @author Fabien Potencier */ interface AuthenticationManagerInterface { /** * Attempts to authenticate a TokenInterface object. * * @param TokenInterface $token The TokenInterface instance to authenticate * * @return TokenInterface An authenticated TokenInterface instance, never null * * @throws AuthenticationException if the authentication fails */ public function authenticate(TokenInterface $token); } PK!γ__NSymfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; /** * PreAuthenticatedToken implements a pre-authenticated token. * * @author Fabien Potencier */ class PreAuthenticatedToken extends AbstractToken { private $credentials; private $providerKey; /** * Constructor. */ public function __construct($user, $credentials, $providerKey, array $roles = array()) { parent::__construct($roles); if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->setUser($user); $this->credentials = $credentials; $this->providerKey = $providerKey; if ($roles) { $this->setAuthenticated(true); } } /** * Returns the provider key. * * @return string The provider key */ public function getProviderKey() { return $this->providerKey; } /** * {@inheritdoc} */ public function getCredentials() { return $this->credentials; } /** * {@inheritdoc} */ public function eraseCredentials() { parent::eraseCredentials(); $this->credentials = null; } /** * {@inheritdoc} */ public function serialize() { return serialize(array($this->credentials, $this->providerKey, parent::serialize())); } /** * {@inheritdoc} */ public function unserialize($str) { list($this->credentials, $this->providerKey, $parentStr) = unserialize($str); parent::unserialize($parentStr); } } PK!4FSymfony/Component/Security/Core/Authentication/Token/AbstractToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\Role\RoleInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\AdvancedUserInterface; use Symfony\Component\Security\Core\User\EquatableInterface; /** * Base class for Token instances. * * @author Fabien Potencier * @author Johannes M. Schmitt */ abstract class AbstractToken implements TokenInterface { private $user; private $roles = array(); private $authenticated = false; private $attributes = array(); /** * Constructor. * * @param RoleInterface[] $roles An array of roles * * @throws \InvalidArgumentException */ public function __construct(array $roles = array()) { foreach ($roles as $role) { if (is_string($role)) { $role = new Role($role); } elseif (!$role instanceof RoleInterface) { throw new \InvalidArgumentException(sprintf('$roles must be an array of strings, or RoleInterface instances, but got %s.', gettype($role))); } $this->roles[] = $role; } } /** * {@inheritdoc} */ public function getRoles() { return $this->roles; } /** * {@inheritdoc} */ public function getUsername() { if ($this->user instanceof UserInterface) { return $this->user->getUsername(); } return (string) $this->user; } /** * {@inheritdoc} */ public function getUser() { return $this->user; } /** * Sets the user in the token. * * The user can be a UserInterface instance, or an object implementing * a __toString method or the username as a regular string. * * @param mixed $user The user * @throws \InvalidArgumentException */ public function setUser($user) { if (!($user instanceof UserInterface || (is_object($user) && method_exists($user, '__toString')) || is_string($user))) { throw new \InvalidArgumentException('$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string.'); } if (null === $this->user) { $changed = false; } elseif ($this->user instanceof UserInterface) { if (!$user instanceof UserInterface) { $changed = true; } else { $changed = $this->hasUserChanged($user); } } elseif ($user instanceof UserInterface) { $changed = true; } else { $changed = (string) $this->user !== (string) $user; } if ($changed) { $this->setAuthenticated(false); } $this->user = $user; } /** * {@inheritdoc} */ public function isAuthenticated() { return $this->authenticated; } /** * {@inheritdoc} */ public function setAuthenticated($authenticated) { $this->authenticated = (Boolean) $authenticated; } /** * {@inheritdoc} */ public function eraseCredentials() { if ($this->getUser() instanceof UserInterface) { $this->getUser()->eraseCredentials(); } } /** * {@inheritdoc} */ public function serialize() { return serialize( array( is_object($this->user) ? clone $this->user : $this->user, $this->authenticated, $this->roles, $this->attributes ) ); } /** * {@inheritdoc} */ public function unserialize($serialized) { list($this->user, $this->authenticated, $this->roles, $this->attributes) = unserialize($serialized); } /** * Returns the token attributes. * * @return array The token attributes */ public function getAttributes() { return $this->attributes; } /** * Sets the token attributes. * * @param array $attributes The token attributes */ public function setAttributes(array $attributes) { $this->attributes = $attributes; } /** * Returns true if the attribute exists. * * @param string $name The attribute name * * @return Boolean true if the attribute exists, false otherwise */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * Returns an attribute value. * * @param string $name The attribute name * * @return mixed The attribute value * * @throws \InvalidArgumentException When attribute doesn't exist for this token */ public function getAttribute($name) { if (!array_key_exists($name, $this->attributes)) { throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name)); } return $this->attributes[$name]; } /** * Sets an attribute. * * @param string $name The attribute name * @param mixed $value The attribute value */ public function setAttribute($name, $value) { $this->attributes[$name] = $value; } /** * {@inheritDoc} */ public function __toString() { $class = get_class($this); $class = substr($class, strrpos($class, '\\')+1); $roles = array(); foreach ($this->roles as $role) { $roles[] = $role->getRole(); } return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUsername(), json_encode($this->authenticated), implode(', ', $roles)); } private function hasUserChanged(UserInterface $user) { if (!($this->user instanceof UserInterface)) { throw new \BadMethodCallException('Method "hasUserChanged" should be called when current user class is instance of "UserInterface".'); } if ($this->user instanceof EquatableInterface) { return ! (Boolean) $this->user->isEqualTo($user); } if ($this->user->getPassword() !== $user->getPassword()) { return true; } if ($this->user->getSalt() !== $user->getSalt()) { return true; } if ($this->user->getUsername() !== $user->getUsername()) { return true; } if ($this->user instanceof AdvancedUserInterface && $user instanceof AdvancedUserInterface) { if ($this->user->isAccountNonExpired() !== $user->isAccountNonExpired()) { return true; } if ($this->user->isAccountNonLocked() !== $user->isAccountNonLocked()) { return true; } if ($this->user->isCredentialsNonExpired() !== $user->isCredentialsNonExpired()) { return true; } if ($this->user->isEnabled() !== $user->isEnabled()) { return true; } } elseif ($this->user instanceof AdvancedUserInterface xor $user instanceof AdvancedUserInterface) { return true; } return false; } } PK!tC GSymfony/Component/Security/Core/Authentication/Token/TokenInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\Role\RoleInterface; /** * TokenInterface is the interface for the user authentication information. * * @author Fabien Potencier * @author Johannes M. Schmitt */ interface TokenInterface extends \Serializable { /** * Returns a string representation of the Token. * * This is only to be used for debugging purposes. * * @return string */ public function __toString(); /** * Returns the user roles. * * @return RoleInterface[] An array of RoleInterface instances. */ public function getRoles(); /** * Returns the user credentials. * * @return mixed The user credentials */ public function getCredentials(); /** * Returns a user representation. * * @return mixed either returns an object which implements __toString(), or * a primitive string is returned. */ public function getUser(); /** * Sets a user. * * @param mixed $user */ public function setUser($user); /** * Returns the username. * * @return string */ public function getUsername(); /** * Returns whether the user is authenticated or not. * * @return Boolean true if the token has been authenticated, false otherwise */ public function isAuthenticated(); /** * Sets the authenticated flag. * * @param Boolean $isAuthenticated The authenticated flag */ public function setAuthenticated($isAuthenticated); /** * Removes sensitive information from the token. */ public function eraseCredentials(); /** * Returns the token attributes. * * @return array The token attributes */ public function getAttributes(); /** * Sets the token attributes. * * @param array $attributes The token attributes */ public function setAttributes(array $attributes); /** * Returns true if the attribute exists. * * @param string $name The attribute name * * @return Boolean true if the attribute exists, false otherwise */ public function hasAttribute($name); /** * Returns an attribute value. * * @param string $name The attribute name * * @return mixed The attribute value * * @throws \InvalidArgumentException When attribute doesn't exist for this token */ public function getAttribute($name); /** * Sets an attribute. * * @param string $name The attribute name * @param mixed $value The attribute value */ public function setAttribute($name, $value); } PK!{Z--GSymfony/Component/Security/Core/Authentication/Token/AnonymousToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\Role\RoleInterface; /** * AnonymousToken represents an anonymous token. * * @author Fabien Potencier */ class AnonymousToken extends AbstractToken { private $key; /** * Constructor. * * @param string $key The key shared with the authentication provider * @param string $user The user * @param RoleInterface[] $roles An array of roles */ public function __construct($key, $user, array $roles = array()) { parent::__construct($roles); $this->key = $key; $this->setUser($user); $this->setAuthenticated(true); } /** * {@inheritdoc} */ public function getCredentials() { return ''; } /** * Returns the key. * * @return string The Key */ public function getKey() { return $this->key; } /** * {@inheritDoc} */ public function serialize() { return serialize(array($this->key, parent::serialize())); } /** * {@inheritDoc} */ public function unserialize($serialized) { list($this->key, $parentStr) = unserialize($serialized); parent::unserialize($parentStr); } } PK!6` ` NSymfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\Role\RoleInterface; /** * UsernamePasswordToken implements a username and password token. * * @author Fabien Potencier */ class UsernamePasswordToken extends AbstractToken { private $credentials; private $providerKey; /** * Constructor. * * @param string $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method. * @param string $credentials This usually is the password of the user * @param string $providerKey The provider key * @param RoleInterface[] $roles An array of roles * * @throws \InvalidArgumentException */ public function __construct($user, $credentials, $providerKey, array $roles = array()) { parent::__construct($roles); if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->setUser($user); $this->credentials = $credentials; $this->providerKey = $providerKey; parent::setAuthenticated(count($roles) > 0); } /** * {@inheritdoc} */ public function setAuthenticated($isAuthenticated) { if ($isAuthenticated) { throw new \LogicException('Cannot set this token to trusted after instantiation.'); } parent::setAuthenticated(false); } /** * {@inheritdoc} */ public function getCredentials() { return $this->credentials; } /** * Returns the provider key. * * @return string The provider key */ public function getProviderKey() { return $this->providerKey; } /** * {@inheritdoc} */ public function eraseCredentials() { parent::eraseCredentials(); $this->credentials = null; } /** * {@inheritdoc} */ public function serialize() { return serialize(array($this->credentials, $this->providerKey, parent::serialize())); } /** * {@inheritdoc} */ public function unserialize($serialized) { list($this->credentials, $this->providerKey, $parentStr) = unserialize($serialized); parent::unserialize($parentStr); } } PK!w HSymfony/Component/Security/Core/Authentication/Token/RememberMeToken.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Authentication\Token; use Symfony\Component\Security\Core\User\UserInterface; /** * Authentication Token for "Remember-Me". * * @author Johannes M. Schmitt */ class RememberMeToken extends AbstractToken { private $key; private $providerKey; /** * Constructor. * * @param UserInterface $user * @param string $providerKey * @param string $key * * @throws \InvalidArgumentException */ public function __construct(UserInterface $user, $providerKey, $key) { parent::__construct($user->getRoles()); if (empty($key)) { throw new \InvalidArgumentException('$key must not be empty.'); } if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->providerKey = $providerKey; $this->key = $key; $this->setUser($user); parent::setAuthenticated(true); } /** * {@inheritdoc} */ public function setAuthenticated($authenticated) { if ($authenticated) { throw new \LogicException('You cannot set this token to authenticated after creation.'); } parent::setAuthenticated(false); } /** * Returns the provider key. * * @return string The provider key */ public function getProviderKey() { return $this->providerKey; } /** * Returns the key. * * @return string The Key */ public function getKey() { return $this->key; } /** * {@inheritdoc} */ public function getCredentials() { return ''; } /** * {@inheritdoc} */ public function serialize() { return serialize(array( $this->key, $this->providerKey, parent::serialize(), )); } /** * {@inheritdoc} */ public function unserialize($serialized) { list($this->key, $this->providerKey, $parentStr) = unserialize($serialized); parent::unserialize($parentStr); } } PK!m|JJKSymfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlfnu[ An authentication exception occurred. Изузетак при аутентификацији. Authentication credentials could not be found. Аутентификациони подаци нису пронађени. Authentication request could not be processed due to a system problem. Захтев за аутентификацију не може бити обрађен због системских проблема. Invalid credentials. Невалидни подаци за аутентификацију. Cookie has already been used by someone else. Колачић је већ искоришћен од стране неког другог. Not privileged to request the resource. Немате права приступа овом ресурсу. Invalid CSRF token. Невалидан CSRF токен. Digest nonce has expired. Време криптографског кључа је истекло. No authentication provider found to support the authentication token. Аутентификациони провајдер за подршку токена није пронађен. No session available, it either timed out or cookies are not enabled. Сесија није доступна, истекла је или су колачићи искључени. No token could be found. Токен не може бити пронађен. Username could not be found. Корисничко име не може бити пронађено. Account has expired. Налог је истекао. Credentials have expired. Подаци за аутентификацију су истекли. Account is disabled. Налог је онемогућен. Account is locked. Налог је закључан. PK!&MЎ FSymfony/Component/Security/Core/Resources/translations/security.es.xlfnu[ An authentication exception occurred. Ocurrió un error de autenticación. Authentication credentials could not be found. No se encontraron las credenciales de autenticación. Authentication request could not be processed due to a system problem. La solicitud de autenticación no se pudo procesar debido a un problema del sistema. Invalid credentials. Credenciales no válidas. Cookie has already been used by someone else. La cookie ya ha sido usada por otra persona. Not privileged to request the resource. No tiene privilegios para solicitar el recurso. Invalid CSRF token. Token CSRF no válido. Digest nonce has expired. El vector de inicialización (digest nonce) ha expirado. No authentication provider found to support the authentication token. No se encontró un proveedor de autenticación que soporte el token de autenticación. No session available, it either timed out or cookies are not enabled. No hay ninguna sesión disponible, ha expirado o las cookies no están habilitados. No token could be found. No se encontró ningún token. Username could not be found. No se encontró el nombre de usuario. Account has expired. La cuenta ha expirado. Credentials have expired. Las credenciales han expirado. Account is disabled. La cuenta está deshabilitada. Account is locked. La cuenta está bloqueada. PK!M-@FSymfony/Component/Security/Core/Resources/translations/security.fa.xlfnu[ An authentication exception occurred. خطایی هنگام تعیین اعتبار اتفاق افتاد. Authentication credentials could not be found. شرایط تعیین اعتبار پیدا نشد. Authentication request could not be processed due to a system problem. درخواست تعیین اعتبار به دلیل مشکل سیستم قابل بررسی نیست. Invalid credentials. شرایط نامعتبر. Cookie has already been used by someone else. کوکی قبلا برای شخص دیگری استفاده شده است. Not privileged to request the resource. دسترسی لازم برای درخواست این منبع را ندارید. Invalid CSRF token. توکن CSRF معتبر نیست. Digest nonce has expired. Digest nonce منقضی شده است. No authentication provider found to support the authentication token. هیچ ارایه کننده تعیین اعتباری برای ساپورت توکن تعیین اعتبار پیدا نشد. No session available, it either timed out or cookies are not enabled. جلسه‌ای در دسترس نیست. این میتواند یا به دلیل پایان یافتن زمان باشد یا اینکه کوکی ها فعال نیستند. No token could be found. هیچ توکنی پیدا نشد. Username could not be found. نام ‌کاربری پیدا نشد. Account has expired. حساب کاربری منقضی شده است. Credentials have expired. پارامترهای تعیین اعتبار منقضی شده‌اند. Account is disabled. حساب کاربری غیرفعال است. Account is locked. حساب کاربری قفل شده است. PK!de FSymfony/Component/Security/Core/Resources/translations/security.fr.xlfnu[ An authentication exception occurred. Une exception d'authentification s'est produite. Authentication credentials could not be found. Les droits d'authentification n'ont pas pu être trouvés. Authentication request could not be processed due to a system problem. La requête d'authentification n'a pas pu être executée à cause d'un problème système. Invalid credentials. Droits invalides. Cookie has already been used by someone else. Le cookie a déjà été utilisé par quelqu'un d'autre. Not privileged to request the resource. Pas de privilèges pour accéder à la ressource. Invalid CSRF token. Jeton CSRF invalide. Digest nonce has expired. Le digest nonce a expiré. No authentication provider found to support the authentication token. Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification. No session available, it either timed out or cookies are not enabled. Pas de session disponible, celle-ci a expiré ou les cookies ne sont pas activés. No token could be found. Aucun jeton n'a pu être trouvé. Username could not be found. Le nom d'utilisateur ne peut pas être trouvé. Account has expired. Le compte a expiré. Credentials have expired. Les droits ont expirés. Account is disabled. Le compte est désactivé. Account is locked. Le compte est bloqué. PK!) FSymfony/Component/Security/Core/Resources/translations/security.ro.xlfnu[ An authentication exception occurred. A apărut o eroare de autentificare. Authentication credentials could not be found. Informațiile de autentificare nu au fost găsite. Authentication request could not be processed due to a system problem. Sistemul nu a putut procesa cererea de autentificare din cauza unei erori. Invalid credentials. Date de autentificare invalide. Cookie has already been used by someone else. Cookieul este folosit deja de altcineva. Not privileged to request the resource. Permisiuni insuficiente pentru resursa cerută. Invalid CSRF token. Tokenul CSRF este invalid. Digest nonce has expired. Tokenul temporar a expirat. No authentication provider found to support the authentication token. Nu a fost găsit nici un agent de autentificare pentru tokenul specificat. No session available, it either timed out or cookies are not enabled. Sesiunea nu mai este disponibilă, a expirat sau suportul pentru cookieuri nu este activat. No token could be found. Tokenul nu a putut fi găsit. Username could not be found. Numele de utilizator nu a fost găsit. Account has expired. Contul a expirat. Credentials have expired. Datele de autentificare au expirat. Account is disabled. Contul este dezactivat. Account is locked. Contul este blocat. PK!y FSymfony/Component/Security/Core/Resources/translations/security.gl.xlfnu[ An authentication exception occurred. Ocorreu un erro de autenticación. Authentication credentials could not be found. Non se atoparon as credenciais de autenticación. Authentication request could not be processed due to a system problem. A solicitude de autenticación no puido ser procesada debido a un problema do sistema. Invalid credentials. Credenciais non válidas. Cookie has already been used by someone else. A cookie xa foi empregado por outro usuario. Not privileged to request the resource. Non ten privilexios para solicitar o recurso. Invalid CSRF token. Token CSRF non válido. Digest nonce has expired. O vector de inicialización (digest nonce) expirou. No authentication provider found to support the authentication token. Non se atopou un provedor de autenticación que soporte o token de autenticación. No session available, it either timed out or cookies are not enabled. Non hai ningunha sesión dispoñible, expirou ou as cookies non están habilitadas. No token could be found. Non se atopou ningún token. Username could not be found. Non se atopou o nome de usuario. Account has expired. A conta expirou. Credentials have expired. As credenciais expiraron. Account is disabled. A conta está deshabilitada. Account is locked. A conta está bloqueada. PK!u^ ^ FSymfony/Component/Security/Core/Resources/translations/security.sv.xlfnu[ An authentication exception occurred. Ett autentiseringsfel har inträffat. Authentication credentials could not be found. Uppgifterna för autentisering kunde inte hittas. Authentication request could not be processed due to a system problem. Autentiseringen kunde inte genomföras på grund av systemfel. Invalid credentials. Felaktiga uppgifter. Cookie has already been used by someone else. Cookien har redan använts av någon annan. Not privileged to request the resource. Saknar rättigheter för resursen. Invalid CSRF token. Ogiltig CSRF-token. Digest nonce has expired. Förfallen digest nonce. No authentication provider found to support the authentication token. Ingen leverantör för autentisering hittades för angiven autentiseringstoken. No session available, it either timed out or cookies are not enabled. Ingen session finns tillgänglig, antingen har den förfallit eller är cookies inte aktiverat. No token could be found. Ingen token kunde hittas. Username could not be found. Användarnamnet kunde inte hittas. Account has expired. Kontot har förfallit. Credentials have expired. Uppgifterna har förfallit. Account is disabled. Kontot är inaktiverat. Account is locked. Kontot är låst. PK!ţ FSymfony/Component/Security/Core/Resources/translations/security.ca.xlfnu[ An authentication exception occurred. Ha succeït un error d'autenticació. Authentication credentials could not be found. No s'han trobat les credencials d'autenticació. Authentication request could not be processed due to a system problem. La solicitud d'autenticació no s'ha pogut processar per un problema del sistema. Invalid credentials. Credencials no vàlides. Cookie has already been used by someone else. La cookie ja ha estat utilitzada per una altra persona. Not privileged to request the resource. No té privilegis per solicitar el recurs. Invalid CSRF token. Token CSRF no vàlid. Digest nonce has expired. El vector d'inicialització (digest nonce) ha expirat. No authentication provider found to support the authentication token. No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació. No session available, it either timed out or cookies are not enabled. No hi ha sessió disponible, ha expirat o les cookies no estan habilitades. No token could be found. No s'ha trobat cap token. Username could not be found. No s'ha trobat el nom d'usuari. Account has expired. El compte ha expirat. Credentials have expired. Les credencials han expirat. Account is disabled. El compte està deshabilitat. Account is locked. El compte està bloquejat. PK!o'N FSymfony/Component/Security/Core/Resources/translations/security.de.xlfnu[ An authentication exception occurred. Es ist ein Fehler bei der Authentifikation aufgetreten. Authentication credentials could not be found. Es konnten keine Zugangsdaten gefunden werden. Authentication request could not be processed due to a system problem. Die Authentifikation konnte wegen eines Systemproblems nicht bearbeitet werden. Invalid credentials. Fehlerhafte Zugangsdaten. Cookie has already been used by someone else. Cookie wurde bereits von jemand anderem verwendet. Not privileged to request the resource. Keine Rechte, um die Ressource anzufragen. Invalid CSRF token. Ungültiges CSRF-Token. Digest nonce has expired. Digest nonce ist abgelaufen. No authentication provider found to support the authentication token. Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt. No session available, it either timed out or cookies are not enabled. Keine Session verfügbar, entweder ist diese abgelaufen oder Cookies sind nicht aktiviert. No token could be found. Es wurde kein Token gefunden. Username could not be found. Der Benutzername wurde nicht gefunden. Account has expired. Der Account ist abgelaufen. Credentials have expired. Die Zugangsdaten sind abgelaufen. Account is disabled. Der Account ist deaktiviert. Account is locked. Der Account ist gesperrt. PK!.W FSymfony/Component/Security/Core/Resources/translations/security.no.xlfnu[ An authentication exception occurred. En autentiserings feil har skjedd. Authentication credentials could not be found. Påloggingsinformasjonen kunne ikke bli funnet. Authentication request could not be processed due to a system problem. Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil. Invalid credentials. Ugyldig påloggingsinformasjonen. Cookie has already been used by someone else. Cookie har allerede blitt brukt av noen andre. Not privileged to request the resource. Ingen tilgang til å be om gitt kilde. Invalid CSRF token. Ugyldig CSRF token. Digest nonce has expired. Digest nonce er utløpt. No authentication provider found to support the authentication token. Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token. No session available, it either timed out or cookies are not enabled. Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på. No token could be found. Ingen token kunne bli funnet. Username could not be found. Brukernavn kunne ikke bli funnet. Account has expired. Brukerkonto har utgått. Credentials have expired. Påloggingsinformasjon har utløpt. Account is disabled. Brukerkonto er deaktivert. Account is locked. Brukerkonto er sperret. PK!ق FSymfony/Component/Security/Core/Resources/translations/security.sk.xlfnu[ An authentication exception occurred. Pri overovaní došlo k chybe. Authentication credentials could not be found. Overovacie údaje neboli nájdené. Authentication request could not be processed due to a system problem. Požiadavok na overenie nemohol byť spracovaný kvôli systémovej chybe. Invalid credentials. Neplatné prihlasovacie údaje. Cookie has already been used by someone else. Cookie už bolo použité niekým iným. Not privileged to request the resource. Nemáte oprávnenie pristupovať k prostriedku. Invalid CSRF token. Neplatný CSRF token. Digest nonce has expired. Platnosť inicializačného vektoru (digest nonce) skončila. No authentication provider found to support the authentication token. Poskytovateľ pre overovací token nebol nájdený. No session available, it either timed out or cookies are not enabled. Session nie je k dispozíci, vypršala jej platnosť, alebo sú zakázané cookies. No token could be found. Token nebol nájdený. Username could not be found. Prihlasovacie meno nebolo nájdené. Account has expired. Platnosť účtu skončila. Credentials have expired. Platnosť prihlasovacích údajov skončila. Account is disabled. Účet je zakázaný. Account is locked. Účet je zablokovaný. PK!w=FSymfony/Component/Security/Core/Resources/translations/security.ru.xlfnu[ An authentication exception occurred. Ошибка аутентификации. Authentication credentials could not be found. Аутентификационные данные не найдены. Authentication request could not be processed due to a system problem. Запрос аутентификации не может быть обработан в связи с проблемой в системе. Invalid credentials. Недействительные аутентификационные данные. Cookie has already been used by someone else. Cookie уже был использован кем-то другим. Not privileged to request the resource. Отсутствуют права на запрос этого ресурса. Invalid CSRF token. Недействительный токен CSRF. Digest nonce has expired. Время действия одноразового ключа дайджеста истекло. No authentication provider found to support the authentication token. Не найден провайдер аутентификации, поддерживающий токен аутентификации. No session available, it either timed out or cookies are not enabled. Сессия не найдена, ее время истекло, либо cookies не включены. No token could be found. Токен не найден. Username could not be found. Имя пользователя не найдено. Account has expired. Время действия учетной записи истекло. Credentials have expired. Время действия аутентификационных данных истекло. Account is disabled. Учетная запись отключена. Account is locked. Учетная запись заблокирована. PK!UɎd d FSymfony/Component/Security/Core/Resources/translations/security.sl.xlfnu[ An authentication exception occurred. Prišlo je do izjeme pri preverjanju avtentikacije. Authentication credentials could not be found. Poverilnic za avtentikacijo ni bilo mogoče najti. Authentication request could not be processed due to a system problem. Zahteve za avtentikacijo ni bilo mogoče izvesti zaradi sistemske težave. Invalid credentials. Neveljavne pravice. Cookie has already been used by someone else. Piškotek je uporabil že nekdo drug. Not privileged to request the resource. Nimate privilegijev za zahtevani vir. Invalid CSRF token. Neveljaven CSRF žeton. Digest nonce has expired. Začasni žeton je potekel. No authentication provider found to support the authentication token. Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti. No session available, it either timed out or cookies are not enabled. Seja ni na voljo, ali je potekla ali pa piškotki niso omogočeni. No token could be found. Žetona ni bilo mogoče najti. Username could not be found. Uporabniškega imena ni bilo mogoče najti. Account has expired. Račun je potekel. Credentials have expired. Poverilnice so potekle. Account is disabled. Račun je onemogočen. Account is locked. Račun je zaklenjen. PK! FSymfony/Component/Security/Core/Resources/translations/security.lb.xlfnu[ An authentication exception occurred. Bei der Authentifikatioun ass e Feeler opgetrueden. Authentication credentials could not be found. Et konnte keng Zouganksdate fonnt ginn. Authentication request could not be processed due to a system problem. D'Ufro fir eng Authentifikatioun konnt wéinst engem Problem vum System net beaarbecht ginn. Invalid credentials. Ongëlteg Zouganksdaten. Cookie has already been used by someone else. De Cookie gouf scho vun engem anere benotzt. Not privileged to request the resource. Keng Rechter fir d'Ressource unzefroen. Invalid CSRF token. Ongëltegen CSRF-Token. Digest nonce has expired. Den eemolege Schlëssel ass ofgelaf. No authentication provider found to support the authentication token. Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt. No session available, it either timed out or cookies are not enabled. Keng Sëtzung disponibel. Entweder ass se ofgelaf oder Cookies sinn net aktivéiert. No token could be found. Et konnt keen Token fonnt ginn. Username could not be found. De Benotzernumm konnt net fonnt ginn. Account has expired. Den Account ass ofgelaf. Credentials have expired. D'Zouganksdate sinn ofgelaf. Account is disabled. De Konto ass deaktivéiert. Account is locked. De Konto ass gespaart. PK!#@y y ISymfony/Component/Security/Core/Resources/translations/security.pt_PT.xlfnu[ An authentication exception occurred. Ocorreu um excepção durante a autenticação. Authentication credentials could not be found. As credenciais de autenticação não foram encontradas. Authentication request could not be processed due to a system problem. O pedido de autenticação não foi concluído devido a um problema no sistema. Invalid credentials. Credenciais inválidas. Cookie has already been used by someone else. Este cookie já esta em uso. Not privileged to request the resource. Não possui privilégios para aceder a este recurso. Invalid CSRF token. Token CSRF inválido. Digest nonce has expired. Digest nonce expirado. No authentication provider found to support the authentication token. Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação. No session available, it either timed out or cookies are not enabled. Não existe sessão disponível, esta expirou ou os cookies estão desativados. No token could be found. O token não foi encontrado. Username could not be found. Nome de utilizador não encontrado. Account has expired. A conta expirou. Credentials have expired. As credenciais expiraram. Account is disabled. Conta desativada. Account is locked. A conta esta trancada. PK!YWg g KSymfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlfnu[ An authentication exception occurred. Izuzetak pri autentifikaciji. Authentication credentials could not be found. Autentifikacioni podaci nisu pronađeni. Authentication request could not be processed due to a system problem. Zahtev za autentifikaciju ne može biti obrađen zbog sistemskih problema. Invalid credentials. Nevalidni podaci za autentifikaciju. Cookie has already been used by someone else. Kolačić je već iskorišćen od strane nekog drugog. Not privileged to request the resource. Nemate prava pristupa ovom resursu. Invalid CSRF token. Nevalidan CSRF token. Digest nonce has expired. Vreme kriptografskog ključa je isteklo. No authentication provider found to support the authentication token. Autentifikacioni provajder za podršku tokena nije pronađen. No session available, it either timed out or cookies are not enabled. Sesija nije dostupna, istekla je ili su kolačići isključeni. No token could be found. Token ne može biti pronađen. Username could not be found. Korisničko ime ne može biti pronađeno. Account has expired. Nalog je istekao. Credentials have expired. Podaci za autentifikaciju su istekli. Account is disabled. Nalog je onemogućen. Account is locked. Nalog je zaključan. PK!= ISymfony/Component/Security/Core/Resources/translations/security.pt_BR.xlfnu[ An authentication exception occurred. Uma exceção ocorreu durante a autenticação. Authentication credentials could not be found. As credenciais de autenticação não foram encontradas. Authentication request could not be processed due to a system problem. A autenticação não pôde ser concluída devido a um problema no sistema. Invalid credentials. Credenciais inválidas. Cookie has already been used by someone else. Este cookie já esta em uso. Not privileged to request the resource. Não possui privilégios o bastante para requisitar este recurso. Invalid CSRF token. Token CSRF inválido. Digest nonce has expired. Digest nonce expirado. No authentication provider found to support the authentication token. Nenhum provedor de autenticação encontrado para suportar o token de autenticação. No session available, it either timed out or cookies are not enabled. Nenhuma sessão disponível, ela expirou ou cookies estão desativados. No token could be found. Nenhum token foi encontrado. Username could not be found. Nome de usuário não encontrado. Account has expired. A conta esta expirada. Credentials have expired. As credenciais estão expiradas. Account is disabled. Conta desativada. Account is locked. A conta esta travada. PK! ( FSymfony/Component/Security/Core/Resources/translations/security.cs.xlfnu[ An authentication exception occurred. Při ověřování došlo k chybě. Authentication credentials could not be found. Ověřovací údaje nebyly nalezeny. Authentication request could not be processed due to a system problem. Požadavek na ověření nemohl být zpracován kvůli systémové chybě. Invalid credentials. Neplatné přihlašovací údaje. Cookie has already been used by someone else. Cookie již bylo použité někým jiným. Not privileged to request the resource. Nemáte oprávnění přistupovat k prostředku. Invalid CSRF token. Neplatný CSRF token. Digest nonce has expired. Platnost inicializačního vektoru (digest nonce) vypršela. No authentication provider found to support the authentication token. Poskytovatel pro ověřovací token nebyl nalezen. No session available, it either timed out or cookies are not enabled. Session není k dispozici, vypršela její platnost, nebo jsou zakázané cookies. No token could be found. Token nebyl nalezen. Username could not be found. Přihlašovací jméno nebylo nalezeno. Account has expired. Platnost účtu vypršela. Credentials have expired. Platnost přihlašovacích údajů vypršela. Account is disabled. Účet je zakázaný. Account is locked. Účet je zablokovaný. PK!O FSymfony/Component/Security/Core/Resources/translations/security.it.xlfnu[ An authentication exception occurred. Si è verificato un errore di autenticazione. Authentication credentials could not be found. Impossibile trovare le credenziali di autenticazione. Authentication request could not be processed due to a system problem. La richiesta di autenticazione non può essere processata a causa di un errore di sistema. Invalid credentials. Credenziali non valide. Cookie has already been used by someone else. Il cookie è già stato usato da qualcun altro. Not privileged to request the resource. Non hai i privilegi per richiedere questa risorsa. Invalid CSRF token. CSRF token non valido. Digest nonce has expired. Il numero di autenticazione è scaduto. No authentication provider found to support the authentication token. Non è stato trovato un valido fornitore di autenticazione per supportare il token. No session available, it either timed out or cookies are not enabled. Nessuna sessione disponibile, può essere scaduta o i cookie non sono abilitati. No token could be found. Nessun token trovato. Username could not be found. Username non trovato. Account has expired. Account scaduto. Credentials have expired. Credenziali scadute. Account is disabled. L'account è disabilitato. Account is locked. L'account è bloccato. PK!TkfFSymfony/Component/Security/Core/Resources/translations/security.ar.xlfnu[ An authentication exception occurred. حدث خطأ اثناء الدخول. Authentication credentials could not be found. لم استطع العثور على معلومات الدخول. Authentication request could not be processed due to a system problem. لم يكتمل طلب الدخول نتيجه عطل فى النظام. Invalid credentials. معلومات الدخول خاطئة. Cookie has already been used by someone else. ملفات تعريف الارتباط(cookies) تم استخدامها من قبل شخص اخر. Not privileged to request the resource. ليست لديك الصلاحيات الكافية لهذا الطلب. Invalid CSRF token. رمز الموقع غير صحيح. Digest nonce has expired. انتهت صلاحية(digest nonce). No authentication provider found to support the authentication token. لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول. No session available, it either timed out or cookies are not enabled. لا يوجد صلة بينك و بين الموقع اما انها انتهت او ان متصفحك لا يدعم خاصية ملفات تعريف الارتباط (cookies). No token could be found. لم استطع العثور على الرمز. Username could not be found. لم استطع العثور على اسم الدخول. Account has expired. انتهت صلاحية الحساب. Credentials have expired. انتهت صلاحية معلومات الدخول. Account is disabled. الحساب موقوف. Account is locked. الحساب مغلق. PK!|H FSymfony/Component/Security/Core/Resources/translations/security.hu.xlfnu[ An authentication exception occurred. Hitelesítési hiba lépett fel. Authentication credentials could not be found. Nem találhatók hitelesítési információk. Authentication request could not be processed due to a system problem. A hitelesítési kérést rendszerhiba miatt nem lehet feldolgozni. Invalid credentials. Érvénytelen hitelesítési információk. Cookie has already been used by someone else. Ezt a sütit valaki más már felhasználta. Not privileged to request the resource. Nem rendelkezik az erőforrás eléréséhez szükséges jogosultsággal. Invalid CSRF token. Érvénytelen CSRF token. Digest nonce has expired. A kivonat bélyege (nonce) lejárt. No authentication provider found to support the authentication token. Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás. No session available, it either timed out or cookies are not enabled. Munkamenet nem áll rendelkezésre, túllépte az időkeretet vagy a sütik le vannak tiltva. No token could be found. Nem található token. Username could not be found. A felhasználónév nem található. Account has expired. A fiók lejárt. Credentials have expired. A hitelesítési információk lejártak. Account is disabled. Felfüggesztett fiók. Account is locked. Zárolt fiók. PK!pU FSymfony/Component/Security/Core/Resources/translations/security.nl.xlfnu[ An authentication exception occurred. Er heeft zich een authenticatieprobleem voorgedaan. Authentication credentials could not be found. Authenticatiegegevens konden niet worden gevonden. Authentication request could not be processed due to a system problem. Authenticatieaanvraag kon niet worden verwerkt door een technisch probleem. Invalid credentials. Ongeldige inloggegevens. Cookie has already been used by someone else. Cookie is al door een ander persoon gebruikt. Not privileged to request the resource. Onvoldoende rechten om de aanvraag te verwerken. Invalid CSRF token. CSRF-code is ongeldig. Digest nonce has expired. Serverauthenticatiesleutel (digest nonce) is verlopen. No authentication provider found to support the authentication token. Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt. No session available, it either timed out or cookies are not enabled. Geen sessie beschikbaar, mogelijk is deze verlopen of cookies zijn uitgeschakeld. No token could be found. Er kon geen authenticatietoken worden gevonden. Username could not be found. Gebruikersnaam kon niet worden gevonden. Account has expired. Account is verlopen. Credentials have expired. Authenticatiegegevens zijn verlopen. Account is disabled. Account is gedeactiveerd. Account is locked. Account is geblokkeerd. PK!'{ { FSymfony/Component/Security/Core/Resources/translations/security.tr.xlfnu[ An authentication exception occurred. Bir yetkilendirme istisnası oluştu. Authentication credentials could not be found. Yetkilendirme girdileri bulunamadı. Authentication request could not be processed due to a system problem. Bir sistem hatası nedeniyle yetkilendirme isteği işleme alınamıyor. Invalid credentials. Geçersiz girdiler. Cookie has already been used by someone else. Çerez bir başkası tarafından zaten kullanılmıştı. Not privileged to request the resource. Kaynak talebi için imtiyaz bulunamadı. Invalid CSRF token. Geçersiz CSRF fişi. Digest nonce has expired. Derleme zaman aşımı gerçekleşti. No authentication provider found to support the authentication token. Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı. No session available, it either timed out or cookies are not enabled. Oturum bulunamadı, zaman aşımına uğradı veya çerezler etkin değil. No token could be found. Bilet bulunamadı. Username could not be found. Kullanıcı adı bulunamadı. Account has expired. Hesap zaman aşımına uğradı. Credentials have expired. Girdiler zaman aşımına uğradı. Account is disabled. Hesap devre dışı bırakılmış. Account is locked. Hesap kilitlenmiş. PK!UFSymfony/Component/Security/Core/Resources/translations/security.el.xlfnu[ An authentication exception occurred. Συνέβη ένα σφάλμα πιστοποίησης. Authentication credentials could not be found. Τα στοιχεία πιστοποίησης δε βρέθηκαν. Authentication request could not be processed due to a system problem. Το αίτημα πιστοποίησης δε μπορεί να επεξεργαστεί λόγω σφάλματος του συστήματος. Invalid credentials. Λανθασμένα στοιχεία σύνδεσης. Cookie has already been used by someone else. Το Cookie έχει ήδη χρησιμοποιηθεί από κάποιον άλλο. Not privileged to request the resource. Δεν είστε εξουσιοδοτημένος για πρόσβαση στο συγκεκριμένο περιεχόμενο. Invalid CSRF token. Μη έγκυρο CSRF token. Digest nonce has expired. Το digest nonce έχει λήξει. No authentication provider found to support the authentication token. Δε βρέθηκε κάποιος πάροχος πιστοποίησης που να υποστηρίζει το token πιστοποίησης. No session available, it either timed out or cookies are not enabled. Δεν υπάρχει ενεργή σύνοδος (session), είτε έχει λήξει ή τα cookies δεν είναι ενεργοποιημένα. No token could be found. Δεν ήταν δυνατόν να βρεθεί κάποιο token. Username could not be found. Το Username δε βρέθηκε. Account has expired. Ο λογαριασμός έχει λήξει. Credentials have expired. Τα στοιχεία σύνδεσης έχουν λήξει. Account is disabled. Ο λογαριασμός είναι απενεργοποιημένος. Account is locked. Ο λογαριασμός είναι κλειδωμένος. PK!.X: : FSymfony/Component/Security/Core/Resources/translations/security.en.xlfnu[ An authentication exception occurred. An authentication exception occurred. Authentication credentials could not be found. Authentication credentials could not be found. Authentication request could not be processed due to a system problem. Authentication request could not be processed due to a system problem. Invalid credentials. Invalid credentials. Cookie has already been used by someone else. Cookie has already been used by someone else. Not privileged to request the resource. Not privileged to request the resource. Invalid CSRF token. Invalid CSRF token. Digest nonce has expired. Digest nonce has expired. No authentication provider found to support the authentication token. No authentication provider found to support the authentication token. No session available, it either timed out or cookies are not enabled. No session available, it either timed out or cookies are not enabled. No token could be found. No token could be found. Username could not be found. Username could not be found. Account has expired. Account has expired. Credentials have expired. Credentials have expired. Account is disabled. Account is disabled. Account is locked. Account is locked. PK!d FSymfony/Component/Security/Core/Resources/translations/security.pl.xlfnu[ An authentication exception occurred. Wystąpił błąd uwierzytelniania. Authentication credentials could not be found. Dane uwierzytelniania nie zostały znalezione. Authentication request could not be processed due to a system problem. Żądanie uwierzytelniania nie mogło zostać pomyślnie zakończone z powodu problemu z systemem. Invalid credentials. Nieprawidłowe dane. Cookie has already been used by someone else. To ciasteczko jest używane przez kogoś innego. Not privileged to request the resource. Brak uprawnień dla żądania wskazanego zasobu. Invalid CSRF token. Nieprawidłowy token CSRF. Digest nonce has expired. Kod dostępu wygasł. No authentication provider found to support the authentication token. Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu. No session available, it either timed out or cookies are not enabled. Brak danych sesji, sesja wygasła lub ciasteczka nie są włączone. No token could be found. Nie znaleziono tokenu. Username could not be found. Użytkownik o podanej nazwie nie istnieje. Account has expired. Konto wygasło. Credentials have expired. Dane uwierzytelniania wygasły. Account is disabled. Konto jest wyłączone. Account is locked. Konto jest zablokowane. PK!5˙FSymfony/Component/Security/Core/Resources/translations/security.ua.xlfnu[ An authentication exception occurred. Помилка автентифікації. Authentication credentials could not be found. Автентифікаційні дані не знайдено. Authentication request could not be processed due to a system problem. Запит на автентифікацію не може бути опрацьовано у зв’язку з проблемою в системі. Invalid credentials. Невірні автентифікаційні дані. Cookie has already been used by someone else. Хтось інший вже використав цей сookie. Not privileged to request the resource. Відсутні права на запит цього ресурсу. Invalid CSRF token. Невірний токен CSRF. Digest nonce has expired. Закінчився термін дії одноразового ключа дайджесту. No authentication provider found to support the authentication token. Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії. No session available, it either timed out or cookies are not enabled. Сесія недоступна, її час вийшов, або cookies вимкнено. No token could be found. Токен не знайдено. Username could not be found. Ім’я користувача не знайдено. Account has expired. Термін дії облікового запису вичерпано. Credentials have expired. Термін дії автентифікаційних даних вичерпано. Account is disabled. Обліковий запис відключено. Account is locked. Обліковий запис заблоковано. PK!z J J FSymfony/Component/Security/Core/Resources/translations/security.da.xlfnu[ An authentication exception occurred. En fejl indtraf ved godkendelse. Authentication credentials could not be found. Loginoplysninger kan findes. Authentication request could not be processed due to a system problem. Godkendelsesanmodning kan ikke behandles på grund af et systemfejl. Invalid credentials. Ugyldige loginoplysninger. Cookie has already been used by someone else. Cookie er allerede brugt af en anden. Not privileged to request the resource. Ingen tilladselese at anvende kilden. Invalid CSRF token. Ugyldigt CSRF token. Digest nonce has expired. Digest nonce er udløbet. No authentication provider found to support the authentication token. Ingen godkendelsesudbyder er fundet til understøttelsen af godkendelsestoken. No session available, it either timed out or cookies are not enabled. Ingen session tilgængelig, sessionen er enten udløbet eller cookies er ikke aktiveret. No token could be found. Ingen token kan findes. Username could not be found. Brugernavn kan ikke findes. Account has expired. Brugerkonto er udløbet. Credentials have expired. Loginoplysninger er udløbet. Account is disabled. Brugerkonto er deaktiveret. Account is locked. Brugerkonto er låst. PK!EhDSymfony/Component/Security/Core/Event/AuthenticationFailureEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Event; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** * This event is dispatched on authentication failure. * * @author Johannes M. Schmitt */ class AuthenticationFailureEvent extends AuthenticationEvent { private $authenticationException; public function __construct(TokenInterface $token, AuthenticationException $ex) { parent::__construct($token); $this->authenticationException = $ex; } public function getAuthenticationException() { return $this->authenticationException; } } PK!+\ //=Symfony/Component/Security/Core/Event/AuthenticationEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Event; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\EventDispatcher\Event; /** * This is a general purpose authentication event. * * @author Johannes M. Schmitt */ class AuthenticationEvent extends Event { private $authenticationToken; public function __construct(TokenInterface $token) { $this->authenticationToken = $token; } public function getAuthenticationToken() { return $this->authenticationToken; } } PK!(SSASymfony/Component/Security/Resources/translations/security.bg.xlfnu[ An authentication exception occurred. Грешка при автентикация. Authentication credentials could not be found. Удостоверението за автентикация не е открито. Authentication request could not be processed due to a system problem. Заявката за автентикация не може да бъде обработената поради системна грешка. Invalid credentials. Невалидно удостоверение за автентикация. Cookie has already been used by someone else. Това cookie вече се ползва от някой друг. Not privileged to request the resource. Нямате права за достъп до този ресурс. Invalid CSRF token. Невалиден CSRF токен. Digest nonce has expired. Digest nonce е изтекъл. No authentication provider found to support the authentication token. Не е открит провайдър, който да поддържа този токен за автентикация. No session available, it either timed out or cookies are not enabled. Сесията не е достъпна, или времето за достъп е изтекло, или кукитата не са разрешени. No token could be found. Токена не е открит. Username could not be found. Потребителското име не е открито. Account has expired. Акаунта е изтекъл. Credentials have expired. Удостоверението за автентикация е изтекло. Account is disabled. Акаунта е деактивиран. Account is locked. Акаунта е заключен. PK!m|JJFSymfony/Component/Security/Resources/translations/security.sr_Cyrl.xlfnu[ An authentication exception occurred. Изузетак при аутентификацији. Authentication credentials could not be found. Аутентификациони подаци нису пронађени. Authentication request could not be processed due to a system problem. Захтев за аутентификацију не може бити обрађен због системских проблема. Invalid credentials. Невалидни подаци за аутентификацију. Cookie has already been used by someone else. Колачић је већ искоришћен од стране неког другог. Not privileged to request the resource. Немате права приступа овом ресурсу. Invalid CSRF token. Невалидан CSRF токен. Digest nonce has expired. Време криптографског кључа је истекло. No authentication provider found to support the authentication token. Аутентификациони провајдер за подршку токена није пронађен. No session available, it either timed out or cookies are not enabled. Сесија није доступна, истекла је или су колачићи искључени. No token could be found. Токен не може бити пронађен. Username could not be found. Корисничко име не може бити пронађено. Account has expired. Налог је истекао. Credentials have expired. Подаци за аутентификацију су истекли. Account is disabled. Налог је онемогућен. Account is locked. Налог је закључан. PK!&MЎ ASymfony/Component/Security/Resources/translations/security.es.xlfnu[ An authentication exception occurred. Ocurrió un error de autenticación. Authentication credentials could not be found. No se encontraron las credenciales de autenticación. Authentication request could not be processed due to a system problem. La solicitud de autenticación no se pudo procesar debido a un problema del sistema. Invalid credentials. Credenciales no válidas. Cookie has already been used by someone else. La cookie ya ha sido usada por otra persona. Not privileged to request the resource. No tiene privilegios para solicitar el recurso. Invalid CSRF token. Token CSRF no válido. Digest nonce has expired. El vector de inicialización (digest nonce) ha expirado. No authentication provider found to support the authentication token. No se encontró un proveedor de autenticación que soporte el token de autenticación. No session available, it either timed out or cookies are not enabled. No hay ninguna sesión disponible, ha expirado o las cookies no están habilitados. No token could be found. No se encontró ningún token. Username could not be found. No se encontró el nombre de usuario. Account has expired. La cuenta ha expirado. Credentials have expired. Las credenciales han expirado. Account is disabled. La cuenta está deshabilitada. Account is locked. La cuenta está bloqueada. PK!M-@ASymfony/Component/Security/Resources/translations/security.fa.xlfnu[ An authentication exception occurred. خطایی هنگام تعیین اعتبار اتفاق افتاد. Authentication credentials could not be found. شرایط تعیین اعتبار پیدا نشد. Authentication request could not be processed due to a system problem. درخواست تعیین اعتبار به دلیل مشکل سیستم قابل بررسی نیست. Invalid credentials. شرایط نامعتبر. Cookie has already been used by someone else. کوکی قبلا برای شخص دیگری استفاده شده است. Not privileged to request the resource. دسترسی لازم برای درخواست این منبع را ندارید. Invalid CSRF token. توکن CSRF معتبر نیست. Digest nonce has expired. Digest nonce منقضی شده است. No authentication provider found to support the authentication token. هیچ ارایه کننده تعیین اعتباری برای ساپورت توکن تعیین اعتبار پیدا نشد. No session available, it either timed out or cookies are not enabled. جلسه‌ای در دسترس نیست. این میتواند یا به دلیل پایان یافتن زمان باشد یا اینکه کوکی ها فعال نیستند. No token could be found. هیچ توکنی پیدا نشد. Username could not be found. نام ‌کاربری پیدا نشد. Account has expired. حساب کاربری منقضی شده است. Credentials have expired. پارامترهای تعیین اعتبار منقضی شده‌اند. Account is disabled. حساب کاربری غیرفعال است. Account is locked. حساب کاربری قفل شده است. PK!ASymfony/Component/Security/Resources/translations/security.vi.xlfnu[ An authentication exception occurred. Có lỗi trong quá trình xác thực. Authentication credentials could not be found. Thông tin dùng để xác thực không tìm thấy. Authentication request could not be processed due to a system problem. Yêu cầu xác thực không thể thực hiện do lỗi của hệ thống. Invalid credentials. Thông tin dùng để xác thực không hợp lệ. Cookie has already been used by someone else. Cookie đã được dùng bởi người dùng khác. Not privileged to request the resource. Không được phép yêu cầu tài nguyên. Invalid CSRF token. Mã CSRF không hợp lệ. Digest nonce has expired. Mã dùng một lần đã hết hạn. No authentication provider found to support the authentication token. Không tìm thấy nhà cung cấp dịch vụ xác thực nào cho mã xác thực mà bạn sử dụng. No session available, it either timed out or cookies are not enabled. Không tìm thấy phiên làm việc. Phiên làm việc hoặc cookie có thể bị tắt. No token could be found. Không tìm thấy mã token. Username could not be found. Không tìm thấy tên người dùng username. Account has expired. Tài khoản đã hết hạn. Credentials have expired. Thông tin xác thực đã hết hạn. Account is disabled. Tài khoản bị tạm ngừng. Account is locked. Tài khoản bị khóa. PK!de ASymfony/Component/Security/Resources/translations/security.fr.xlfnu[ An authentication exception occurred. Une exception d'authentification s'est produite. Authentication credentials could not be found. Les droits d'authentification n'ont pas pu être trouvés. Authentication request could not be processed due to a system problem. La requête d'authentification n'a pas pu être executée à cause d'un problème système. Invalid credentials. Droits invalides. Cookie has already been used by someone else. Le cookie a déjà été utilisé par quelqu'un d'autre. Not privileged to request the resource. Pas de privilèges pour accéder à la ressource. Invalid CSRF token. Jeton CSRF invalide. Digest nonce has expired. Le digest nonce a expiré. No authentication provider found to support the authentication token. Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification. No session available, it either timed out or cookies are not enabled. Pas de session disponible, celle-ci a expiré ou les cookies ne sont pas activés. No token could be found. Aucun jeton n'a pu être trouvé. Username could not be found. Le nom d'utilisateur ne peut pas être trouvé. Account has expired. Le compte a expiré. Credentials have expired. Les droits ont expirés. Account is disabled. Le compte est désactivé. Account is locked. Le compte est bloqué. PK!) ASymfony/Component/Security/Resources/translations/security.ro.xlfnu[ An authentication exception occurred. A apărut o eroare de autentificare. Authentication credentials could not be found. Informațiile de autentificare nu au fost găsite. Authentication request could not be processed due to a system problem. Sistemul nu a putut procesa cererea de autentificare din cauza unei erori. Invalid credentials. Date de autentificare invalide. Cookie has already been used by someone else. Cookieul este folosit deja de altcineva. Not privileged to request the resource. Permisiuni insuficiente pentru resursa cerută. Invalid CSRF token. Tokenul CSRF este invalid. Digest nonce has expired. Tokenul temporar a expirat. No authentication provider found to support the authentication token. Nu a fost găsit nici un agent de autentificare pentru tokenul specificat. No session available, it either timed out or cookies are not enabled. Sesiunea nu mai este disponibilă, a expirat sau suportul pentru cookieuri nu este activat. No token could be found. Tokenul nu a putut fi găsit. Username could not be found. Numele de utilizator nu a fost găsit. Account has expired. Contul a expirat. Credentials have expired. Datele de autentificare au expirat. Account is disabled. Contul este dezactivat. Account is locked. Contul este blocat. PK!y ASymfony/Component/Security/Resources/translations/security.gl.xlfnu[ An authentication exception occurred. Ocorreu un erro de autenticación. Authentication credentials could not be found. Non se atoparon as credenciais de autenticación. Authentication request could not be processed due to a system problem. A solicitude de autenticación no puido ser procesada debido a un problema do sistema. Invalid credentials. Credenciais non válidas. Cookie has already been used by someone else. A cookie xa foi empregado por outro usuario. Not privileged to request the resource. Non ten privilexios para solicitar o recurso. Invalid CSRF token. Token CSRF non válido. Digest nonce has expired. O vector de inicialización (digest nonce) expirou. No authentication provider found to support the authentication token. Non se atopou un provedor de autenticación que soporte o token de autenticación. No session available, it either timed out or cookies are not enabled. Non hai ningunha sesión dispoñible, expirou ou as cookies non están habilitadas. No token could be found. Non se atopou ningún token. Username could not be found. Non se atopou o nome de usuario. Account has expired. A conta expirou. Credentials have expired. As credenciais expiraron. Account is disabled. A conta está deshabilitada. Account is locked. A conta está bloqueada. PK!u^ ^ ASymfony/Component/Security/Resources/translations/security.sv.xlfnu[ An authentication exception occurred. Ett autentiseringsfel har inträffat. Authentication credentials could not be found. Uppgifterna för autentisering kunde inte hittas. Authentication request could not be processed due to a system problem. Autentiseringen kunde inte genomföras på grund av systemfel. Invalid credentials. Felaktiga uppgifter. Cookie has already been used by someone else. Cookien har redan använts av någon annan. Not privileged to request the resource. Saknar rättigheter för resursen. Invalid CSRF token. Ogiltig CSRF-token. Digest nonce has expired. Förfallen digest nonce. No authentication provider found to support the authentication token. Ingen leverantör för autentisering hittades för angiven autentiseringstoken. No session available, it either timed out or cookies are not enabled. Ingen session finns tillgänglig, antingen har den förfallit eller är cookies inte aktiverat. No token could be found. Ingen token kunde hittas. Username could not be found. Användarnamnet kunde inte hittas. Account has expired. Kontot har förfallit. Credentials have expired. Uppgifterna har förfallit. Account is disabled. Kontot är inaktiverat. Account is locked. Kontot är låst. PK!ţ ASymfony/Component/Security/Resources/translations/security.ca.xlfnu[ An authentication exception occurred. Ha succeït un error d'autenticació. Authentication credentials could not be found. No s'han trobat les credencials d'autenticació. Authentication request could not be processed due to a system problem. La solicitud d'autenticació no s'ha pogut processar per un problema del sistema. Invalid credentials. Credencials no vàlides. Cookie has already been used by someone else. La cookie ja ha estat utilitzada per una altra persona. Not privileged to request the resource. No té privilegis per solicitar el recurs. Invalid CSRF token. Token CSRF no vàlid. Digest nonce has expired. El vector d'inicialització (digest nonce) ha expirat. No authentication provider found to support the authentication token. No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació. No session available, it either timed out or cookies are not enabled. No hi ha sessió disponible, ha expirat o les cookies no estan habilitades. No token could be found. No s'ha trobat cap token. Username could not be found. No s'ha trobat el nom d'usuari. Account has expired. El compte ha expirat. Credentials have expired. Les credencials han expirat. Account is disabled. El compte està deshabilitat. Account is locked. El compte està bloquejat. PK!o'N ASymfony/Component/Security/Resources/translations/security.de.xlfnu[ An authentication exception occurred. Es ist ein Fehler bei der Authentifikation aufgetreten. Authentication credentials could not be found. Es konnten keine Zugangsdaten gefunden werden. Authentication request could not be processed due to a system problem. Die Authentifikation konnte wegen eines Systemproblems nicht bearbeitet werden. Invalid credentials. Fehlerhafte Zugangsdaten. Cookie has already been used by someone else. Cookie wurde bereits von jemand anderem verwendet. Not privileged to request the resource. Keine Rechte, um die Ressource anzufragen. Invalid CSRF token. Ungültiges CSRF-Token. Digest nonce has expired. Digest nonce ist abgelaufen. No authentication provider found to support the authentication token. Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt. No session available, it either timed out or cookies are not enabled. Keine Session verfügbar, entweder ist diese abgelaufen oder Cookies sind nicht aktiviert. No token could be found. Es wurde kein Token gefunden. Username could not be found. Der Benutzername wurde nicht gefunden. Account has expired. Der Account ist abgelaufen. Credentials have expired. Die Zugangsdaten sind abgelaufen. Account is disabled. Der Account ist deaktiviert. Account is locked. Der Account ist gesperrt. PK! ASymfony/Component/Security/Resources/translations/security.no.xlfnu[ An authentication exception occurred. En autentiserings feil har skjedd. Authentication credentials could not be found. Påloggingsinformasjonen kunne ikke bli funnet. Authentication request could not be processed due to a system problem. Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil. Invalid credentials. Ugyldig påloggingsinformasjonen. Cookie has already been used by someone else. Cookie har allerede blitt brukt av noen andre. Not privileged to request the resource. Ingen tilgang til å be om gitt kilde. Invalid CSRF token. Ugyldig CSRF token. Digest nonce has expired. Digest nonce er utløpt. No authentication provider found to support the authentication token. Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token. No session available, it either timed out or cookies are not enabled. Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på. No token could be found. Ingen token kunne bli funnet. Username could not be found. Brukernavn kunne ikke bli funnet. Account has expired. Brukerkonto har utgått. Credentials have expired. Påloggingsinformasjon har utløpt. Account is disabled. Brukerkonto er deaktivert. Account is locked. Brukerkonto er sperret. PK!RwD D ASymfony/Component/Security/Resources/translations/security.id.xlfnu[ An authentication exception occurred. Terjadi sebuah pengecualian otentikasi. Authentication credentials could not be found. Kredensial otentikasi tidak bisa ditemukan. Authentication request could not be processed due to a system problem. Permintaan otentikasi tidak bisa diproses karena masalah sistem. Invalid credentials. Kredensial salah. Cookie has already been used by someone else. Cookie sudah digunakan oleh orang lain. Not privileged to request the resource. Tidak berhak untuk meminta sumber daya. Invalid CSRF token. Token CSRF salah. Digest nonce has expired. Digest nonce telah berakhir. No authentication provider found to support the authentication token. Tidak ditemukan penyedia otentikasi untuk mendukung token otentikasi. No session available, it either timed out or cookies are not enabled. Tidak ada sesi yang tersedia, mungkin waktu sudah habis atau cookie tidak diaktifkan No token could be found. Tidak ada token yang bisa ditemukan. Username could not be found. Username tidak bisa ditemukan. Account has expired. Akun telah berakhir. Credentials have expired. Kredensial telah berakhir. Account is disabled. Akun dinonaktifkan. Account is locked. Akun terkunci. PK!ق ASymfony/Component/Security/Resources/translations/security.sk.xlfnu[ An authentication exception occurred. Pri overovaní došlo k chybe. Authentication credentials could not be found. Overovacie údaje neboli nájdené. Authentication request could not be processed due to a system problem. Požiadavok na overenie nemohol byť spracovaný kvôli systémovej chybe. Invalid credentials. Neplatné prihlasovacie údaje. Cookie has already been used by someone else. Cookie už bolo použité niekým iným. Not privileged to request the resource. Nemáte oprávnenie pristupovať k prostriedku. Invalid CSRF token. Neplatný CSRF token. Digest nonce has expired. Platnosť inicializačného vektoru (digest nonce) skončila. No authentication provider found to support the authentication token. Poskytovateľ pre overovací token nebol nájdený. No session available, it either timed out or cookies are not enabled. Session nie je k dispozíci, vypršala jej platnosť, alebo sú zakázané cookies. No token could be found. Token nebol nájdený. Username could not be found. Prihlasovacie meno nebolo nájdené. Account has expired. Platnosť účtu skončila. Credentials have expired. Platnosť prihlasovacích údajov skončila. Account is disabled. Účet je zakázaný. Account is locked. Účet je zablokovaný. PK!w=ASymfony/Component/Security/Resources/translations/security.ru.xlfnu[ An authentication exception occurred. Ошибка аутентификации. Authentication credentials could not be found. Аутентификационные данные не найдены. Authentication request could not be processed due to a system problem. Запрос аутентификации не может быть обработан в связи с проблемой в системе. Invalid credentials. Недействительные аутентификационные данные. Cookie has already been used by someone else. Cookie уже был использован кем-то другим. Not privileged to request the resource. Отсутствуют права на запрос этого ресурса. Invalid CSRF token. Недействительный токен CSRF. Digest nonce has expired. Время действия одноразового ключа дайджеста истекло. No authentication provider found to support the authentication token. Не найден провайдер аутентификации, поддерживающий токен аутентификации. No session available, it either timed out or cookies are not enabled. Сессия не найдена, ее время истекло, либо cookies не включены. No token could be found. Токен не найден. Username could not be found. Имя пользователя не найдено. Account has expired. Время действия учетной записи истекло. Credentials have expired. Время действия аутентификационных данных истекло. Account is disabled. Учетная запись отключена. Account is locked. Учетная запись заблокирована. PK!UɎd d ASymfony/Component/Security/Resources/translations/security.sl.xlfnu[ An authentication exception occurred. Prišlo je do izjeme pri preverjanju avtentikacije. Authentication credentials could not be found. Poverilnic za avtentikacijo ni bilo mogoče najti. Authentication request could not be processed due to a system problem. Zahteve za avtentikacijo ni bilo mogoče izvesti zaradi sistemske težave. Invalid credentials. Neveljavne pravice. Cookie has already been used by someone else. Piškotek je uporabil že nekdo drug. Not privileged to request the resource. Nimate privilegijev za zahtevani vir. Invalid CSRF token. Neveljaven CSRF žeton. Digest nonce has expired. Začasni žeton je potekel. No authentication provider found to support the authentication token. Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti. No session available, it either timed out or cookies are not enabled. Seja ni na voljo, ali je potekla ali pa piškotki niso omogočeni. No token could be found. Žetona ni bilo mogoče najti. Username could not be found. Uporabniškega imena ni bilo mogoče najti. Account has expired. Račun je potekel. Credentials have expired. Poverilnice so potekle. Account is disabled. Račun je onemogočen. Account is locked. Račun je zaklenjen. PK!]W W ASymfony/Component/Security/Resources/translations/security.hr.xlfnu[ An authentication exception occurred. Dogodila se autentifikacijske iznimka. Authentication credentials could not be found. Autentifikacijski podaci nisu pronađeni. Authentication request could not be processed due to a system problem. Autentifikacijski zahtjev nije moguće provesti uslijed sistemskog problema. Invalid credentials. Neispravni akreditacijski podaci. Cookie has already been used by someone else. Cookie je već netko drugi iskoristio. Not privileged to request the resource. Nemate privilegije zahtijevati resurs. Invalid CSRF token. Neispravan CSRF token. Digest nonce has expired. Digest nonce je isteko. No authentication provider found to support the authentication token. Nije pronađen autentifikacijski provider koji bi podržao autentifikacijski token. No session available, it either timed out or cookies are not enabled. Sesija nije dostupna, ili je istekla ili cookies nisu omogućeni. No token could be found. Token nije pronađen. Username could not be found. Korisničko ime nije pronađeno. Account has expired. Račun je isteko. Credentials have expired. Akreditacijski podaci su istekli. Account is disabled. Račun je onemogućen. Account is locked. Račun je zaključan. PK! ASymfony/Component/Security/Resources/translations/security.lb.xlfnu[ An authentication exception occurred. Bei der Authentifikatioun ass e Feeler opgetrueden. Authentication credentials could not be found. Et konnte keng Zouganksdate fonnt ginn. Authentication request could not be processed due to a system problem. D'Ufro fir eng Authentifikatioun konnt wéinst engem Problem vum System net beaarbecht ginn. Invalid credentials. Ongëlteg Zouganksdaten. Cookie has already been used by someone else. De Cookie gouf scho vun engem anere benotzt. Not privileged to request the resource. Keng Rechter fir d'Ressource unzefroen. Invalid CSRF token. Ongëltegen CSRF-Token. Digest nonce has expired. Den eemolege Schlëssel ass ofgelaf. No authentication provider found to support the authentication token. Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt. No session available, it either timed out or cookies are not enabled. Keng Sëtzung disponibel. Entweder ass se ofgelaf oder Cookies sinn net aktivéiert. No token could be found. Et konnt keen Token fonnt ginn. Username could not be found. De Benotzernumm konnt net fonnt ginn. Account has expired. Den Account ass ofgelaf. Credentials have expired. D'Zouganksdate sinn ofgelaf. Account is disabled. De Konto ass deaktivéiert. Account is locked. De Konto ass gespaart. PK!#@y y DSymfony/Component/Security/Resources/translations/security.pt_PT.xlfnu[ An authentication exception occurred. Ocorreu um excepção durante a autenticação. Authentication credentials could not be found. As credenciais de autenticação não foram encontradas. Authentication request could not be processed due to a system problem. O pedido de autenticação não foi concluído devido a um problema no sistema. Invalid credentials. Credenciais inválidas. Cookie has already been used by someone else. Este cookie já esta em uso. Not privileged to request the resource. Não possui privilégios para aceder a este recurso. Invalid CSRF token. Token CSRF inválido. Digest nonce has expired. Digest nonce expirado. No authentication provider found to support the authentication token. Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação. No session available, it either timed out or cookies are not enabled. Não existe sessão disponível, esta expirou ou os cookies estão desativados. No token could be found. O token não foi encontrado. Username could not be found. Nome de utilizador não encontrado. Account has expired. A conta expirou. Credentials have expired. As credenciais expiraram. Account is disabled. Conta desativada. Account is locked. A conta esta trancada. PK!YWg g FSymfony/Component/Security/Resources/translations/security.sr_Latn.xlfnu[ An authentication exception occurred. Izuzetak pri autentifikaciji. Authentication credentials could not be found. Autentifikacioni podaci nisu pronađeni. Authentication request could not be processed due to a system problem. Zahtev za autentifikaciju ne može biti obrađen zbog sistemskih problema. Invalid credentials. Nevalidni podaci za autentifikaciju. Cookie has already been used by someone else. Kolačić je već iskorišćen od strane nekog drugog. Not privileged to request the resource. Nemate prava pristupa ovom resursu. Invalid CSRF token. Nevalidan CSRF token. Digest nonce has expired. Vreme kriptografskog ključa je isteklo. No authentication provider found to support the authentication token. Autentifikacioni provajder za podršku tokena nije pronađen. No session available, it either timed out or cookies are not enabled. Sesija nije dostupna, istekla je ili su kolačići isključeni. No token could be found. Token ne može biti pronađen. Username could not be found. Korisničko ime ne može biti pronađeno. Account has expired. Nalog je istekao. Credentials have expired. Podaci za autentifikaciju su istekli. Account is disabled. Nalog je onemogućen. Account is locked. Nalog je zaključan. PK!Y DSymfony/Component/Security/Resources/translations/security.pt_BR.xlfnu[ An authentication exception occurred. Uma exceção ocorreu durante a autenticação. Authentication credentials could not be found. As credenciais de autenticação não foram encontradas. Authentication request could not be processed due to a system problem. A autenticação não pôde ser concluída devido a um problema no sistema. Invalid credentials. Credenciais inválidas. Cookie has already been used by someone else. Este cookie já está em uso. Not privileged to request the resource. Não possui privilégios o bastante para requisitar este recurso. Invalid CSRF token. Token CSRF inválido. Digest nonce has expired. Digest nonce expirado. No authentication provider found to support the authentication token. Nenhum provedor de autenticação encontrado para suportar o token de autenticação. No session available, it either timed out or cookies are not enabled. Nenhuma sessão disponível, ela expirou ou os cookies estão desativados. No token could be found. Nenhum token foi encontrado. Username could not be found. Nome de usuário não encontrado. Account has expired. A conta está expirada. Credentials have expired. As credenciais estão expiradas. Account is disabled. Conta desativada. Account is locked. A conta está travada. PK! ( ASymfony/Component/Security/Resources/translations/security.cs.xlfnu[ An authentication exception occurred. Při ověřování došlo k chybě. Authentication credentials could not be found. Ověřovací údaje nebyly nalezeny. Authentication request could not be processed due to a system problem. Požadavek na ověření nemohl být zpracován kvůli systémové chybě. Invalid credentials. Neplatné přihlašovací údaje. Cookie has already been used by someone else. Cookie již bylo použité někým jiným. Not privileged to request the resource. Nemáte oprávnění přistupovat k prostředku. Invalid CSRF token. Neplatný CSRF token. Digest nonce has expired. Platnost inicializačního vektoru (digest nonce) vypršela. No authentication provider found to support the authentication token. Poskytovatel pro ověřovací token nebyl nalezen. No session available, it either timed out or cookies are not enabled. Session není k dispozici, vypršela její platnost, nebo jsou zakázané cookies. No token could be found. Token nebyl nalezen. Username could not be found. Přihlašovací jméno nebylo nalezeno. Account has expired. Platnost účtu vypršela. Credentials have expired. Platnost přihlašovacích údajů vypršela. Account is disabled. Účet je zakázaný. Account is locked. Účet je zablokovaný. PK!O ASymfony/Component/Security/Resources/translations/security.it.xlfnu[ An authentication exception occurred. Si è verificato un errore di autenticazione. Authentication credentials could not be found. Impossibile trovare le credenziali di autenticazione. Authentication request could not be processed due to a system problem. La richiesta di autenticazione non può essere processata a causa di un errore di sistema. Invalid credentials. Credenziali non valide. Cookie has already been used by someone else. Il cookie è già stato usato da qualcun altro. Not privileged to request the resource. Non hai i privilegi per richiedere questa risorsa. Invalid CSRF token. CSRF token non valido. Digest nonce has expired. Il numero di autenticazione è scaduto. No authentication provider found to support the authentication token. Non è stato trovato un valido fornitore di autenticazione per supportare il token. No session available, it either timed out or cookies are not enabled. Nessuna sessione disponibile, può essere scaduta o i cookie non sono abilitati. No token could be found. Nessun token trovato. Username could not be found. Username non trovato. Account has expired. Account scaduto. Credentials have expired. Credenziali scadute. Account is disabled. L'account è disabilitato. Account is locked. L'account è bloccato. PK!TkfASymfony/Component/Security/Resources/translations/security.ar.xlfnu[ An authentication exception occurred. حدث خطأ اثناء الدخول. Authentication credentials could not be found. لم استطع العثور على معلومات الدخول. Authentication request could not be processed due to a system problem. لم يكتمل طلب الدخول نتيجه عطل فى النظام. Invalid credentials. معلومات الدخول خاطئة. Cookie has already been used by someone else. ملفات تعريف الارتباط(cookies) تم استخدامها من قبل شخص اخر. Not privileged to request the resource. ليست لديك الصلاحيات الكافية لهذا الطلب. Invalid CSRF token. رمز الموقع غير صحيح. Digest nonce has expired. انتهت صلاحية(digest nonce). No authentication provider found to support the authentication token. لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول. No session available, it either timed out or cookies are not enabled. لا يوجد صلة بينك و بين الموقع اما انها انتهت او ان متصفحك لا يدعم خاصية ملفات تعريف الارتباط (cookies). No token could be found. لم استطع العثور على الرمز. Username could not be found. لم استطع العثور على اسم الدخول. Account has expired. انتهت صلاحية الحساب. Credentials have expired. انتهت صلاحية معلومات الدخول. Account is disabled. الحساب موقوف. Account is locked. الحساب مغلق. PK!|H ASymfony/Component/Security/Resources/translations/security.hu.xlfnu[ An authentication exception occurred. Hitelesítési hiba lépett fel. Authentication credentials could not be found. Nem találhatók hitelesítési információk. Authentication request could not be processed due to a system problem. A hitelesítési kérést rendszerhiba miatt nem lehet feldolgozni. Invalid credentials. Érvénytelen hitelesítési információk. Cookie has already been used by someone else. Ezt a sütit valaki más már felhasználta. Not privileged to request the resource. Nem rendelkezik az erőforrás eléréséhez szükséges jogosultsággal. Invalid CSRF token. Érvénytelen CSRF token. Digest nonce has expired. A kivonat bélyege (nonce) lejárt. No authentication provider found to support the authentication token. Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás. No session available, it either timed out or cookies are not enabled. Munkamenet nem áll rendelkezésre, túllépte az időkeretet vagy a sütik le vannak tiltva. No token could be found. Nem található token. Username could not be found. A felhasználónév nem található. Account has expired. A fiók lejárt. Credentials have expired. A hitelesítési információk lejártak. Account is disabled. Felfüggesztett fiók. Account is locked. Zárolt fiók. PK!pU ASymfony/Component/Security/Resources/translations/security.nl.xlfnu[ An authentication exception occurred. Er heeft zich een authenticatieprobleem voorgedaan. Authentication credentials could not be found. Authenticatiegegevens konden niet worden gevonden. Authentication request could not be processed due to a system problem. Authenticatieaanvraag kon niet worden verwerkt door een technisch probleem. Invalid credentials. Ongeldige inloggegevens. Cookie has already been used by someone else. Cookie is al door een ander persoon gebruikt. Not privileged to request the resource. Onvoldoende rechten om de aanvraag te verwerken. Invalid CSRF token. CSRF-code is ongeldig. Digest nonce has expired. Serverauthenticatiesleutel (digest nonce) is verlopen. No authentication provider found to support the authentication token. Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt. No session available, it either timed out or cookies are not enabled. Geen sessie beschikbaar, mogelijk is deze verlopen of cookies zijn uitgeschakeld. No token could be found. Er kon geen authenticatietoken worden gevonden. Username could not be found. Gebruikersnaam kon niet worden gevonden. Account has expired. Account is verlopen. Credentials have expired. Authenticatiegegevens zijn verlopen. Account is disabled. Account is gedeactiveerd. Account is locked. Account is geblokkeerd. PK!'{ { ASymfony/Component/Security/Resources/translations/security.tr.xlfnu[ An authentication exception occurred. Bir yetkilendirme istisnası oluştu. Authentication credentials could not be found. Yetkilendirme girdileri bulunamadı. Authentication request could not be processed due to a system problem. Bir sistem hatası nedeniyle yetkilendirme isteği işleme alınamıyor. Invalid credentials. Geçersiz girdiler. Cookie has already been used by someone else. Çerez bir başkası tarafından zaten kullanılmıştı. Not privileged to request the resource. Kaynak talebi için imtiyaz bulunamadı. Invalid CSRF token. Geçersiz CSRF fişi. Digest nonce has expired. Derleme zaman aşımı gerçekleşti. No authentication provider found to support the authentication token. Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı. No session available, it either timed out or cookies are not enabled. Oturum bulunamadı, zaman aşımına uğradı veya çerezler etkin değil. No token could be found. Bilet bulunamadı. Username could not be found. Kullanıcı adı bulunamadı. Account has expired. Hesap zaman aşımına uğradı. Credentials have expired. Girdiler zaman aşımına uğradı. Account is disabled. Hesap devre dışı bırakılmış. Account is locked. Hesap kilitlenmiş. PK!UASymfony/Component/Security/Resources/translations/security.el.xlfnu[ An authentication exception occurred. Συνέβη ένα σφάλμα πιστοποίησης. Authentication credentials could not be found. Τα στοιχεία πιστοποίησης δε βρέθηκαν. Authentication request could not be processed due to a system problem. Το αίτημα πιστοποίησης δε μπορεί να επεξεργαστεί λόγω σφάλματος του συστήματος. Invalid credentials. Λανθασμένα στοιχεία σύνδεσης. Cookie has already been used by someone else. Το Cookie έχει ήδη χρησιμοποιηθεί από κάποιον άλλο. Not privileged to request the resource. Δεν είστε εξουσιοδοτημένος για πρόσβαση στο συγκεκριμένο περιεχόμενο. Invalid CSRF token. Μη έγκυρο CSRF token. Digest nonce has expired. Το digest nonce έχει λήξει. No authentication provider found to support the authentication token. Δε βρέθηκε κάποιος πάροχος πιστοποίησης που να υποστηρίζει το token πιστοποίησης. No session available, it either timed out or cookies are not enabled. Δεν υπάρχει ενεργή σύνοδος (session), είτε έχει λήξει ή τα cookies δεν είναι ενεργοποιημένα. No token could be found. Δεν ήταν δυνατόν να βρεθεί κάποιο token. Username could not be found. Το Username δε βρέθηκε. Account has expired. Ο λογαριασμός έχει λήξει. Credentials have expired. Τα στοιχεία σύνδεσης έχουν λήξει. Account is disabled. Ο λογαριασμός είναι απενεργοποιημένος. Account is locked. Ο λογαριασμός είναι κλειδωμένος. PK!Dt DSymfony/Component/Security/Resources/translations/security.zh_CN.xlfnu[ An authentication exception occurred. 身份验证发生异常。 Authentication credentials could not be found. 没有找到身份验证的凭证。 Authentication request could not be processed due to a system problem. 由于系统故障,身份验证的请求无法被处理。 Invalid credentials. 无效的凭证。 Cookie has already been used by someone else. Cookie 已经被其他人使用。 Not privileged to request the resource. 没有权限请求此资源。 Invalid CSRF token. 无效的 CSRF token 。 Digest nonce has expired. 摘要随机串(digest nonce)已过期。 No authentication provider found to support the authentication token. 没有找到支持此 token 的身份验证服务提供方。 No session available, it either timed out or cookies are not enabled. Session 不可用。会话超时或没有启用 cookies 。 No token could be found. 找不到 token 。 Username could not be found. 找不到用户名。 Account has expired. 帐号已过期。 Credentials have expired. 凭证已过期。 Account is disabled. 帐号已被禁用。 Account is locked. 帐号已被锁定。 PK!.X: : ASymfony/Component/Security/Resources/translations/security.en.xlfnu[ An authentication exception occurred. An authentication exception occurred. Authentication credentials could not be found. Authentication credentials could not be found. Authentication request could not be processed due to a system problem. Authentication request could not be processed due to a system problem. Invalid credentials. Invalid credentials. Cookie has already been used by someone else. Cookie has already been used by someone else. Not privileged to request the resource. Not privileged to request the resource. Invalid CSRF token. Invalid CSRF token. Digest nonce has expired. Digest nonce has expired. No authentication provider found to support the authentication token. No authentication provider found to support the authentication token. No session available, it either timed out or cookies are not enabled. No session available, it either timed out or cookies are not enabled. No token could be found. No token could be found. Username could not be found. Username could not be found. Account has expired. Account has expired. Credentials have expired. Credentials have expired. Account is disabled. Account is disabled. Account is locked. Account is locked. PK!d ASymfony/Component/Security/Resources/translations/security.pl.xlfnu[ An authentication exception occurred. Wystąpił błąd uwierzytelniania. Authentication credentials could not be found. Dane uwierzytelniania nie zostały znalezione. Authentication request could not be processed due to a system problem. Żądanie uwierzytelniania nie mogło zostać pomyślnie zakończone z powodu problemu z systemem. Invalid credentials. Nieprawidłowe dane. Cookie has already been used by someone else. To ciasteczko jest używane przez kogoś innego. Not privileged to request the resource. Brak uprawnień dla żądania wskazanego zasobu. Invalid CSRF token. Nieprawidłowy token CSRF. Digest nonce has expired. Kod dostępu wygasł. No authentication provider found to support the authentication token. Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu. No session available, it either timed out or cookies are not enabled. Brak danych sesji, sesja wygasła lub ciasteczka nie są włączone. No token could be found. Nie znaleziono tokenu. Username could not be found. Użytkownik o podanej nazwie nie istnieje. Account has expired. Konto wygasło. Credentials have expired. Dane uwierzytelniania wygasły. Account is disabled. Konto jest wyłączone. Account is locked. Konto jest zablokowane. PK!f488ASymfony/Component/Security/Resources/translations/security.ja.xlfnu[ An authentication exception occurred. 認証エラーが発生しました。 Authentication credentials could not be found. 認証資格がありません。 Authentication request could not be processed due to a system problem. システムの問題により認証要求を処理できませんでした。 Invalid credentials. 資格が無効です。 Cookie has already been used by someone else. Cookie が別のユーザーで使用されています。 Not privileged to request the resource. リソースをリクエストする権限がありません。 Invalid CSRF token. CSRF トークンが無効です。 Digest nonce has expired. Digest の nonce 値が期限切れです。 No authentication provider found to support the authentication token. 認証トークンをサポートする認証プロバイダーが見つかりません。 No session available, it either timed out or cookies are not enabled. 利用可能なセッションがありません。タイムアウトしたか、Cookie が無効になっています。 No token could be found. トークンが見つかりません。 Username could not be found. ユーザー名が見つかりません。 Account has expired. アカウントが有効期限切れです。 Credentials have expired. 資格が有効期限切れです。 Account is disabled. アカウントが無効です。 Account is locked. アカウントはロックされています。 PK!5˙ASymfony/Component/Security/Resources/translations/security.ua.xlfnu[ An authentication exception occurred. Помилка автентифікації. Authentication credentials could not be found. Автентифікаційні дані не знайдено. Authentication request could not be processed due to a system problem. Запит на автентифікацію не може бути опрацьовано у зв’язку з проблемою в системі. Invalid credentials. Невірні автентифікаційні дані. Cookie has already been used by someone else. Хтось інший вже використав цей сookie. Not privileged to request the resource. Відсутні права на запит цього ресурсу. Invalid CSRF token. Невірний токен CSRF. Digest nonce has expired. Закінчився термін дії одноразового ключа дайджесту. No authentication provider found to support the authentication token. Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії. No session available, it either timed out or cookies are not enabled. Сесія недоступна, її час вийшов, або cookies вимкнено. No token could be found. Токен не знайдено. Username could not be found. Ім’я користувача не знайдено. Account has expired. Термін дії облікового запису вичерпано. Credentials have expired. Термін дії автентифікаційних даних вичерпано. Account is disabled. Обліковий запис відключено. Account is locked. Обліковий запис заблоковано. PK!J J ASymfony/Component/Security/Resources/translations/security.da.xlfnu[ An authentication exception occurred. En fejl indtraf ved godkendelse. Authentication credentials could not be found. Loginoplysninger kan findes. Authentication request could not be processed due to a system problem. Godkendelsesanmodning kan ikke behandles på grund af et systemfejl. Invalid credentials. Ugyldige loginoplysninger. Cookie has already been used by someone else. Cookie er allerede brugt af en anden. Not privileged to request the resource. Ingen tilladselese at anvende kilden. Invalid CSRF token. Ugyldigt CSRF token. Digest nonce has expired. Digest nonce er udløbet. No authentication provider found to support the authentication token. Ingen godkendelsesudbyder er fundet til understøttelsen af godkendelsestoken. No session available, it either timed out or cookies are not enabled. Ingen session tilgængelig, sessionen er enten udløbet eller cookies er ikke aktiveret. No token could be found. Ingen token kan findes. Username could not be found. Brugernavn kan ikke findes. Account has expired. Brugerkonto er udløbet. Credentials have expired. Loginoplysninger er udløbet. Account is disabled. Brugerkonto er deaktiveret. Account is locked. Brugerkonto er låst. PK!@V@Symfony/Component/Validator/ConstraintViolationListInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A list of constraint violations. * * @author Bernhard Schussek * * @api */ interface ConstraintViolationListInterface extends \Traversable, \Countable, \ArrayAccess { /** * Adds a constraint violation to this list. * * @param ConstraintViolationInterface $violation The violation to add. * * @api */ public function add(ConstraintViolationInterface $violation); /** * Merges an existing violation list into this list. * * @param ConstraintViolationListInterface $otherList The list to merge. * * @api */ public function addAll(ConstraintViolationListInterface $otherList); /** * Returns the violation at a given offset. * * @param integer $offset The offset of the violation. * * @return ConstraintViolationInterface The violation. * * @throws \OutOfBoundsException If the offset does not exist. * * @api */ public function get($offset); /** * Returns whether the given offset exists. * * @param integer $offset The violation offset. * * @return Boolean Whether the offset exists. * * @api */ public function has($offset); /** * Sets a violation at a given offset. * * @param integer $offset The violation offset. * @param ConstraintViolationInterface $violation The violation. * * @api */ public function set($offset, ConstraintViolationInterface $violation); /** * Removes a violation at a given offset. * * @param integer $offset The offset to remove. * * @api */ public function remove($offset); } PK!z911:Symfony/Component/Validator/ObjectInitializerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Prepares an object for validation. * * Concrete implementations of this interface are used by {@link ValidationVisitorInterface} * to initialize objects just before validating them. * * @author Fabien Potencier * @author Bernhard Schussek * * @api */ interface ObjectInitializerInterface { /** * Initializes an object just before validation. * * @param object $object The object to validate * * @api */ public function initialize($object); } PK!,'<Symfony/Component/Validator/ConstraintValidatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * @author Bernhard Schussek * * @api */ interface ConstraintValidatorInterface { /** * Initializes the constraint validator. * * @param ExecutionContextInterface $context The current validation context */ public function initialize(ExecutionContextInterface $context); /** * Checks if the passed value is valid. * * @param mixed $value The value that should be validated * @param Constraint $constraint The constraint for the validation * * @api */ public function validate($value, Constraint $constraint); } PK!K}}1Symfony/Component/Validator/DefaultTranslator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Exception\BadMethodCallException; use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Translation\TranslatorInterface; /** * Simple translator implementation that simply replaces the parameters in * the message IDs. * * Example usage: * * $translator = new DefaultTranslator(); * * echo $translator->trans( * 'This is a {{ var }}.', * array('{{ var }}' => 'donkey') * ); * * // -> This is a donkey. * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 3, * array('{{ count }}' => 'three') * ); * * // -> These are three donkeys. * * This translator does not support message catalogs, translation domains or * locales. Instead, it implements a subset of the capabilities of * {@link \Symfony\Component\Translation\Translator} and can be used in places * where translation is not required by default but should be optional. * * @author Bernhard Schussek */ class DefaultTranslator implements TranslatorInterface { /** * Interpolates the given message. * * Parameters are replaced in the message in the same manner that * {@link strtr()} uses. * * Example usage: * * $translator = new DefaultTranslator(); * * echo $translator->trans( * 'This is a {{ var }}.', * array('{{ var }}' => 'donkey') * ); * * // -> This is a donkey. * * @param string $id The message id * @param array $parameters An array of parameters for the message * @param string $domain Ignored * @param string $locale Ignored * * @return string The interpolated string */ public function trans($id, array $parameters = array(), $domain = null, $locale = null) { return strtr($id, $parameters); } /** * Interpolates the given choice message by choosing a variant according to a number. * * The variants are passed in the message ID using the format * "|". "" is chosen if the passed $number is * exactly 1. "" is chosen otherwise. * * This format is consistent with the format supported by * {@link \Symfony\Component\Translation\Translator}, but it does not * have the same expressiveness. While Translator supports intervals in * message translations, which are needed for languages other than English, * this translator does not. You should use Translator or a custom * implementation of {@link TranslatorInterface} if you need this or similar * functionality. * * Example usage: * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 0, * array('{{ count }}' => 0) * ); * * // -> These are 0 donkeys. * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 1, * array('{{ count }}' => 1) * ); * * // -> This is 1 donkey. * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 3, * array('{{ count }}' => 3) * ); * * // -> These are 3 donkeys. * * @param string $id The message id * @param integer $number The number to use to find the index of the message * @param array $parameters An array of parameters for the message * @param string $domain Ignored * @param string $locale Ignored * * @return string The translated string * * @throws InvalidArgumentException If the message id does not have the format * "singular|plural". */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { $ids = explode('|', $id); if (1 == $number) { return strtr($ids[0], $parameters); } if (!isset($ids[1])) { throw new InvalidArgumentException(sprintf('The message "%s" cannot be pluralized, because it is missing a plural (e.g. "There is one apple|There are %%count%% apples").', $id)); } return strtr($ids[1], $parameters); } /** * Not supported. * * @param string $locale The locale * * @throws BadMethodCallException */ public function setLocale($locale) { throw new BadMethodCallException('Unsupported method.'); } /** * Returns the locale of the translator. * * @return string Always returns 'en' */ public function getLocale() { return 'en'; } } PK!3Symfony/Component/Validator/ConstraintViolation.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Default implementation of {@ConstraintViolationInterface}. * * @author Bernhard Schussek */ class ConstraintViolation implements ConstraintViolationInterface { /** * @var string */ private $message; /** * @var string */ private $messageTemplate; /** * @var array */ private $messageParameters; /** * @var integer|null */ private $messagePluralization; /** * @var mixed */ private $root; /** * @var string */ private $propertyPath; /** * @var mixed */ private $invalidValue; /** * @var mixed */ private $code; /** * Creates a new constraint violation. * * @param string $message The violation message. * @param string $messageTemplate The raw violation message. * @param array $messageParameters The parameters to substitute * in the raw message. * @param mixed $root The value originally passed * to the validator. * @param string $propertyPath The property path from the * root value to the invalid * value. * @param mixed $invalidValue The invalid value causing the * violation. * @param integer|null $messagePluralization The pluralization parameter. * @param mixed $code The error code of the * violation, if any. */ public function __construct($message, $messageTemplate, array $messageParameters, $root, $propertyPath, $invalidValue, $messagePluralization = null, $code = null) { $this->message = $message; $this->messageTemplate = $messageTemplate; $this->messageParameters = $messageParameters; $this->messagePluralization = $messagePluralization; $this->root = $root; $this->propertyPath = $propertyPath; $this->invalidValue = $invalidValue; $this->code = $code; } /** * Converts the violation into a string for debugging purposes. * * @return string The violation as string. */ public function __toString() { if (is_object($this->root)) { $class = get_class($this->root); } elseif (is_array($this->root)) { $class = "Array"; } else { $class = (string) $this->root; } $propertyPath = (string) $this->propertyPath; $code = $this->code; if ('' !== $propertyPath && '[' !== $propertyPath[0] && '' !== $class) { $class .= '.'; } if (!empty($code)) { $code = ' (code '.$code.')'; } return $class.$propertyPath.":\n ".$this->getMessage().$code; } /** * {@inheritDoc} */ public function getMessageTemplate() { return $this->messageTemplate; } /** * {@inheritDoc} */ public function getMessageParameters() { return $this->messageParameters; } /** * {@inheritDoc} */ public function getMessagePluralization() { return $this->messagePluralization; } /** * {@inheritDoc} */ public function getMessage() { return $this->message; } /** * {@inheritDoc} */ public function getRoot() { return $this->root; } /** * {@inheritDoc} */ public function getPropertyPath() { return $this->propertyPath; } /** * {@inheritDoc} */ public function getInvalidValue() { return $this->invalidValue; } /** * {@inheritDoc} */ public function getCode() { return $this->code; } } PK! Sb'b'0Symfony/Component/Validator/ValidatorBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Mapping\ClassMetadataFactory; use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Mapping\Loader\LoaderChain; use Symfony\Component\Validator\Mapping\Cache\CacheInterface; use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader; use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader; use Symfony\Component\Translation\TranslatorInterface; use Doctrine\Common\Annotations\Reader; use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\CachedReader; use Doctrine\Common\Cache\ArrayCache; /** * The default implementation of {@link ValidatorBuilderInterface}. * * @author Bernhard Schussek */ class ValidatorBuilder implements ValidatorBuilderInterface { /** * @var array */ private $initializers = array(); /** * @var array */ private $xmlMappings = array(); /** * @var array */ private $yamlMappings = array(); /** * @var array */ private $methodMappings = array(); /** * @var Reader */ private $annotationReader = null; /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ private $validatorFactory; /** * @var CacheInterface */ private $metadataCache; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * {@inheritdoc} */ public function addObjectInitializer(ObjectInitializerInterface $initializer) { $this->initializers[] = $initializer; return $this; } /** * {@inheritdoc} */ public function addObjectInitializers(array $initializers) { $this->initializers = array_merge($this->initializers, $initializers); return $this; } /** * {@inheritdoc} */ public function addXmlMapping($path) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->xmlMappings[] = $path; return $this; } /** * {@inheritdoc} */ public function addXmlMappings(array $paths) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->xmlMappings = array_merge($this->xmlMappings, $paths); return $this; } /** * {@inheritdoc} */ public function addYamlMapping($path) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->yamlMappings[] = $path; return $this; } /** * {@inheritdoc} */ public function addYamlMappings(array $paths) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->yamlMappings = array_merge($this->yamlMappings, $paths); return $this; } /** * {@inheritdoc} */ public function addMethodMapping($methodName) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->methodMappings[] = $methodName; return $this; } /** * {@inheritdoc} */ public function addMethodMappings(array $methodNames) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->methodMappings = array_merge($this->methodMappings, $methodNames); return $this; } /** * {@inheritdoc} */ public function enableAnnotationMapping(Reader $annotationReader = null) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot enable annotation mapping after setting a custom metadata factory. Configure your metadata factory instead.'); } if (null === $annotationReader) { if (!class_exists('Doctrine\Common\Annotations\AnnotationReader') || !class_exists('Doctrine\Common\Cache\ArrayCache')) { throw new \RuntimeException('Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.'); } $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache()); } $this->annotationReader = $annotationReader; return $this; } /** * {@inheritdoc} */ public function disableAnnotationMapping() { $this->annotationReader = null; return $this; } /** * {@inheritdoc} */ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory) { if (count($this->xmlMappings) > 0 || count($this->yamlMappings) > 0 || count($this->methodMappings) > 0 || null !== $this->annotationReader) { throw new ValidatorException('You cannot set a custom metadata factory after adding custom mappings. You should do either of both.'); } $this->metadataFactory = $metadataFactory; return $this; } /** * {@inheritdoc} */ public function setMetadataCache(CacheInterface $cache) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->metadataCache = $cache; return $this; } /** * {@inheritdoc} */ public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory) { if (null !== $this->propertyAccessor) { throw new ValidatorException('You cannot set a validator factory after setting a custom property accessor. Remove the call to setPropertyAccessor() if you want to call setConstraintValidatorFactory().'); } $this->validatorFactory = $validatorFactory; return $this; } /** * {@inheritdoc} */ public function setTranslator(TranslatorInterface $translator) { $this->translator = $translator; return $this; } /** * {@inheritdoc} */ public function setTranslationDomain($translationDomain) { $this->translationDomain = $translationDomain; return $this; } /** * {@inheritdoc} */ public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor) { if (null !== $this->validatorFactory) { throw new ValidatorException('You cannot set a property accessor after setting a custom validator factory. Configure your validator factory instead.'); } $this->propertyAccessor = $propertyAccessor; return $this; } /** * {@inheritdoc} */ public function getValidator() { $metadataFactory = $this->metadataFactory; if (!$metadataFactory) { $loaders = array(); if (count($this->xmlMappings) > 1) { $loaders[] = new XmlFilesLoader($this->xmlMappings); } elseif (1 === count($this->xmlMappings)) { $loaders[] = new XmlFileLoader($this->xmlMappings[0]); } if (count($this->yamlMappings) > 1) { $loaders[] = new YamlFilesLoader($this->yamlMappings); } elseif (1 === count($this->yamlMappings)) { $loaders[] = new YamlFileLoader($this->yamlMappings[0]); } foreach ($this->methodMappings as $methodName) { $loaders[] = new StaticMethodLoader($methodName); } if ($this->annotationReader) { $loaders[] = new AnnotationLoader($this->annotationReader); } $loader = null; if (count($loaders) > 1) { $loader = new LoaderChain($loaders); } elseif (1 === count($loaders)) { $loader = $loaders[0]; } $metadataFactory = new ClassMetadataFactory($loader, $this->metadataCache); } $propertyAccessor = $this->propertyAccessor ?: PropertyAccess::createPropertyAccessor(); $validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory($propertyAccessor); $translator = $this->translator ?: new DefaultTranslator(); return new Validator($metadataFactory, $validatorFactory, $translator, $this->translationDomain, $this->initializers); } } PK!SUU>Symfony/Component/Validator/GroupSequenceProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Defines the interface for a group sequence provider. */ interface GroupSequenceProviderInterface { /** * Returns which validation groups should be used for a certain state * of the object. * * @return array An array of validation groups */ public function getGroupSequence(); } PK!d)Symfony/Component/Validator/Validator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Translation\TranslatorInterface; /** * Default implementation of {@link ValidatorInterface}. * * @author Fabien Potencier * @author Bernhard Schussek */ class Validator implements ValidatorInterface { /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ private $validatorFactory; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var array */ private $objectInitializers; public function __construct( MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = 'validators', array $objectInitializers = array() ) { $this->metadataFactory = $metadataFactory; $this->validatorFactory = $validatorFactory; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->objectInitializers = $objectInitializers; } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->metadataFactory; } /** * {@inheritDoc} */ public function getMetadataFor($value) { return $this->metadataFactory->getMetadataFor($value); } /** * {@inheritDoc} */ public function validate($value, $groups = null, $traverse = false, $deep = false) { $visitor = $this->createVisitor($value); foreach ($this->resolveGroups($groups) as $group) { $visitor->validate($value, $group, '', $traverse, $deep); } return $visitor->getViolations(); } /** * {@inheritDoc} * * @throws ValidatorException If the metadata for the value does not support properties. */ public function validateProperty($containingValue, $property, $groups = null) { $visitor = $this->createVisitor($containingValue); $metadata = $this->metadataFactory->getMetadataFor($containingValue); if (!$metadata instanceof PropertyMetadataContainerInterface) { $valueAsString = is_scalar($containingValue) ? '"'.$containingValue.'"' : 'the value of type '.gettype($containingValue); throw new ValidatorException(sprintf('The metadata for %s does not support properties.', $valueAsString)); } foreach ($this->resolveGroups($groups) as $group) { if (!$metadata->hasPropertyMetadata($property)) { continue; } foreach ($metadata->getPropertyMetadata($property) as $propMeta) { $propMeta->accept($visitor, $propMeta->getPropertyValue($containingValue), $group, $property); } } return $visitor->getViolations(); } /** * {@inheritDoc} * * @throws ValidatorException If the metadata for the value does not support properties. */ public function validatePropertyValue($containingValue, $property, $value, $groups = null) { $visitor = $this->createVisitor($containingValue); $metadata = $this->metadataFactory->getMetadataFor($containingValue); if (!$metadata instanceof PropertyMetadataContainerInterface) { $valueAsString = is_scalar($containingValue) ? '"'.$containingValue.'"' : 'the value of type '.gettype($containingValue); throw new ValidatorException(sprintf('The metadata for '.$valueAsString.' does not support properties.')); } foreach ($this->resolveGroups($groups) as $group) { if (!$metadata->hasPropertyMetadata($property)) { continue; } foreach ($metadata->getPropertyMetadata($property) as $propMeta) { $propMeta->accept($visitor, $value, $group, $property); } } return $visitor->getViolations(); } /** * {@inheritDoc} */ public function validateValue($value, $constraints, $groups = null) { $context = new ExecutionContext($this->createVisitor($value), $this->translator, $this->translationDomain); $constraints = is_array($constraints) ? $constraints : array($constraints); foreach ($constraints as $constraint) { if ($constraint instanceof Valid) { // Why can't the Valid constraint be executed directly? // // It cannot be executed like regular other constraints, because regular // constraints are only executed *if they belong to the validated group*. // The Valid constraint, on the other hand, is always executed and propagates // the group to the cascaded object. The propagated group depends on // // * Whether a group sequence is currently being executed. Then the default // group is propagated. // // * Otherwise the validated group is propagated. throw new ValidatorException( sprintf( 'The constraint %s cannot be validated. Use the method validate() instead.', get_class($constraint) ) ); } $context->validateValue($value, $constraint, '', $groups); } return $context->getViolations(); } /** * @param mixed $root * * @return ValidationVisitor */ private function createVisitor($root) { return new ValidationVisitor( $root, $this->metadataFactory, $this->validatorFactory, $this->translator, $this->translationDomain, $this->objectInitializers ); } /** * @param null|string|string[] $groups * * @return string[] */ private function resolveGroups($groups) { return $groups ? (array) $groups : array(Constraint::DEFAULT_GROUP); } } PK!&{{9Symfony/Component/Validator/ValidatorBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Mapping\Cache\CacheInterface; use Symfony\Component\Translation\TranslatorInterface; use Doctrine\Common\Annotations\Reader; /** * A configurable builder for ValidatorInterface objects. * * @author Bernhard Schussek */ interface ValidatorBuilderInterface { /** * Adds an object initializer to the validator. * * @param ObjectInitializerInterface $initializer The initializer. * * @return ValidatorBuilderInterface The builder object. */ public function addObjectInitializer(ObjectInitializerInterface $initializer); /** * Adds a list of object initializers to the validator. * * @param array $initializers The initializer. * * @return ValidatorBuilderInterface The builder object. */ public function addObjectInitializers(array $initializers); /** * Adds an XML constraint mapping file to the validator. * * @param string $path The path to the mapping file. * * @return ValidatorBuilderInterface The builder object. */ public function addXmlMapping($path); /** * Adds a list of XML constraint mapping files to the validator. * * @param array $paths The paths to the mapping files. * * @return ValidatorBuilderInterface The builder object. */ public function addXmlMappings(array $paths); /** * Adds a YAML constraint mapping file to the validator. * * @param string $path The path to the mapping file. * * @return ValidatorBuilderInterface The builder object. */ public function addYamlMapping($path); /** * Adds a list of YAML constraint mappings file to the validator. * * @param array $paths The paths to the mapping files. * * @return ValidatorBuilderInterface The builder object. */ public function addYamlMappings(array $paths); /** * Enables constraint mapping using the given static method. * * @param string $methodName The name of the method. * * @return ValidatorBuilderInterface The builder object. */ public function addMethodMapping($methodName); /** * Enables constraint mapping using the given static methods. * * @param array $methodNames The names of the methods. * * @return ValidatorBuilderInterface The builder object. */ public function addMethodMappings(array $methodNames); /** * Enables annotation based constraint mapping. * * @param Reader $annotationReader The annotation reader to be used. * * @return ValidatorBuilderInterface The builder object. */ public function enableAnnotationMapping(Reader $annotationReader = null); /** * Disables annotation based constraint mapping. * * @return ValidatorBuilderInterface The builder object. */ public function disableAnnotationMapping(); /** * Sets the class metadata factory used by the validator. * * @param MetadataFactoryInterface $metadataFactory The metadata factory. * * @return ValidatorBuilderInterface The builder object. */ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory); /** * Sets the cache for caching class metadata. * * @param CacheInterface $cache The cache instance. * * @return ValidatorBuilderInterface The builder object. */ public function setMetadataCache(CacheInterface $cache); /** * Sets the constraint validator factory used by the validator. * * @param ConstraintValidatorFactoryInterface $validatorFactory The validator factory. * * @return ValidatorBuilderInterface The builder object. */ public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory); /** * Sets the translator used for translating violation messages. * * @param TranslatorInterface $translator The translator instance. * * @return ValidatorBuilderInterface The builder object. */ public function setTranslator(TranslatorInterface $translator); /** * Sets the default translation domain of violation messages. * * The same message can have different translations in different domains. * Pass the domain that is used for violation messages by default to this * method. * * @param string $translationDomain The translation domain of the violation messages. * * @return ValidatorBuilderInterface The builder object. */ public function setTranslationDomain($translationDomain); /** * Sets the property accessor for resolving property paths. * * @param PropertyAccessorInterface $propertyAccessor The property accessor. * * @return ValidatorBuilderInterface The builder object. */ public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor); /** * Builds and returns a new validator object. * * @return ValidatorInterface The built validator. */ public function getValidator(); } PK!oSS*Symfony/Component/Validator/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Stores the validator's state during validation. * * For example, let's validate the following object graph: * *
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 * 
* * We validate the Person instance, which becomes the "root" of the * validation run (see {@link getRoot}). The state of the context after the * first step will be like this: * *
 * (Person)---($firstName: string)
 *    ^ \
 *   ($address: Address)---($street: string)
 * 
* * The validator is stopped at the Person node, both the root and the * value (see {@link getValue}) of the context point to the Person * instance. The property path is empty at this point (see {@link getPropertyPath}). * The metadata of the context is the metadata of the Person node * (see {@link getMetadata}). * * After advancing to the property $firstName of the Person * instance, the state of the context looks like this: * *
 * (Person)---($firstName: string)
 *      \              ^
 *   ($address: Address)---($street: string)
 * 
* * The validator is stopped at the property $firstName. The root still * points to the Person instance, because this is where the validation * started. The property path is now "firstName" and the current value is the * value of that property. * * After advancing to the $address property and then to the * $street property of the Address instance, the context state * looks like this: * *
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 *                               ^
 * 
* * The validator is stopped at the property $street. The root still * points to the Person instance, but the property path is now * "address.street" and the validated value is the value of that property. * * Apart from the root, the property path and the currently validated value, * the execution context also knows the metadata of the current node (see * {@link getMetadata}) which for example returns a {@link Mapping\PropertyMetadata} * or a {@link Mapping\ClassMetadata} object. he context also contains the * validation group that is currently being validated (see {@link getGroup}) and * the violations that happened up until now (see {@link getViolations}). * * Apart from reading the execution context, you can also use * {@link addViolation} or {@link addViolationAt} to add new violations and * {@link validate} or {@link validateValue} to validate values that the * validator otherwise would not reach. * * @author Bernhard Schussek * * @api */ interface ExecutionContextInterface { /** * Adds a violation at the current node of the validation graph. * * @param string $message The error message. * @param array $params The parameters substituted in the error message. * @param mixed $invalidValue The invalid, validated value. * @param integer|null $pluralization The number to use to pluralize of the message. * @param integer|null $code The violation code. * * @api */ public function addViolation($message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null); /** * Adds a violation at the validation graph node with the given property * path relative to the current property path. * * @param string $subPath The relative property path for the violation. * @param string $message The error message. * @param array $params The parameters substituted in the error message. * @param mixed $invalidValue The invalid, validated value. * @param integer|null $pluralization The number to use to pluralize of the message. * @param integer|null $code The violation code. * * @api */ public function addViolationAt($subPath, $message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null); /** * Validates the given value within the scope of the current validation. * * The value may be any value recognized by the used metadata factory * (see {@link MetadataFactoryInterface::getMetadata}), or an array or a * traversable object of such values. * * Usually you validate a value that is not the current node of the * execution context. For this case, you can pass the {@link $subPath} * argument which is appended to the current property path when a violation * is created. For example, take the following object graph: * *
     * (Person)---($address: Address)---($phoneNumber: PhoneNumber)
     *                     ^
     * 
* * When the execution context stops at the Person instance, the * property path is "address". When you validate the PhoneNumber * instance now, pass "phoneNumber" as sub path to correct the property path * to "address.phoneNumber": * *
     * $context->validate($address->phoneNumber, 'phoneNumber');
     * 
* * Any violations generated during the validation will be added to the * violation list that you can access with {@link getViolations}. * * @param mixed $value The value to validate. * @param string $subPath The path to append to the context's property path. * @param null|string|string[] $groups The groups to validate in. If you don't pass any * groups here, the current group of the context * will be used. * @param Boolean $traverse Whether to traverse the value if it is an array * or an instance of \Traversable. * @param Boolean $deep Whether to traverse the value recursively if * it is a collection of collections. */ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false); /** * Validates a value against a constraint. * * Use the parameter $subPath to adapt the property path for the * validated value. For example, take the following object graph: * *
     * (Person)---($address: Address)---($street: string)
     *                     ^
     * 
* * When the validator validates the Address instance, the * property path stored in the execution context is "address". When you * manually validate the property $street now, pass the sub path * "street" to adapt the full property path to "address.street": * *
     * $context->validate($address->street, new NotNull(), 'street');
     * 
* * @param mixed $value The value to validate. * @param Constraint|Constraint[] $constraints The constraint(s) to validate against. * @param string $subPath The path to append to the context's property path. * @param null|string|string[] $groups The groups to validate in. If you don't pass any * groups here, the current group of the context * will be used. */ public function validateValue($value, $constraints, $subPath = '', $groups = null); /** * Returns the violations generated by the validator so far. * * @return ConstraintViolationListInterface The constraint violation list. * * @api */ public function getViolations(); /** * Returns the value at which validation was started in the object graph. * * The validator, when given an object, traverses the properties and * related objects and their properties. The root of the validation is the * object from which the traversal started. * * The current value is returned by {@link getValue}. * * @return mixed The root value of the validation. */ public function getRoot(); /** * Returns the value that the validator is currently validating. * * If you want to retrieve the object that was originally passed to the * validator, use {@link getRoot}. * * @return mixed The currently validated value. */ public function getValue(); /** * Returns the metadata for the currently validated value. * * With the core implementation, this method returns a * {@link Mapping\ClassMetadata} instance if the current value is an object, * a {@link Mapping\PropertyMetadata} instance if the current value is * the value of a property and a {@link Mapping\GetterMetadata} instance if * the validated value is the result of a getter method. * * If the validated value is neither of these, for example if the validator * has been called with a plain value and constraint, this method returns * null. * * @return MetadataInterface|null The metadata of the currently validated * value. */ public function getMetadata(); /** * Returns the used metadata factory. * * @return MetadataFactoryInterface The metadata factory. */ public function getMetadataFactory(); /** * Returns the validation group that is currently being validated. * * @return string The current validation group. */ public function getGroup(); /** * Returns the class name of the current node. * * If the metadata of the current node does not implement * {@link ClassBasedInterface} or if no metadata is available for the * current node, this method returns null. * * @return string|null The class name or null, if no class name could be found. */ public function getClassName(); /** * Returns the property name of the current node. * * If the metadata of the current node does not implement * {@link PropertyMetadataInterface} or if no metadata is available for the * current node, this method returns null. * * @return string|null The property name or null, if no property name could be found. */ public function getPropertyName(); /** * Returns the property path to the value that the validator is currently * validating. * * For example, take the following object graph: * *
     * (Person)---($address: Address)---($street: string)
     * 
* * When the Person instance is passed to the validator, the * property path is initially empty. When the $address property * of that person is validated, the property path is "address". When * the $street property of the related Address instance * is validated, the property path is "address.street". * * Properties of objects are prefixed with a dot in the property path. * Indices of arrays or objects implementing the {@link \ArrayAccess} * interface are enclosed in brackets. For example, if the property in * the previous example is $addresses and contains an array * of Address instance, the property path generated for the * $street property of one of these addresses is for example * "addresses[0].street". * * @param string $subPath Optional. The suffix appended to the current * property path. * * @return string The current property path. The result may be an empty * string if the validator is currently validating the * root value of the validation graph. */ public function getPropertyPath($subPath = ''); } PK!}`9Symfony/Component/Validator/PropertyMetadataInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A container for validation metadata of a property. * * What exactly you define as "property" is up to you. The validator expects * implementations of {@link MetadataInterface} that contain constraints and * optionally a list of named properties that also have constraints (and may * have further sub properties). Such properties are mapped by implementations * of this interface. * * @author Bernhard Schussek * * @see MetadataInterface */ interface PropertyMetadataInterface extends MetadataInterface { /** * Returns the name of the property. * * @return string The property name. */ public function getPropertyName(); /** * Extracts the value of the property from the given container. * * @param mixed $containingValue The container to extract the property value from. * * @return mixed The value of the property. */ public function getPropertyValue($containingValue); } PK!޽/!/!0Symfony/Component/Validator/ExecutionContext.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Translation\TranslatorInterface; /** * Default implementation of {@link ExecutionContextInterface}. * * This class is immutable by design. * * @author Fabien Potencier * @author Bernhard Schussek */ class ExecutionContext implements ExecutionContextInterface { /** * @var GlobalExecutionContextInterface */ private $globalContext; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var MetadataInterface */ private $metadata; /** * @var mixed */ private $value; /** * @var string */ private $group; /** * @var string */ private $propertyPath; /** * Creates a new execution context. * * @param GlobalExecutionContextInterface $globalContext The global context storing node-independent state. * @param TranslatorInterface $translator The translator for translating violation messages. * @param null|string $translationDomain The domain of the validation messages. * @param MetadataInterface $metadata The metadata of the validated node. * @param mixed $value The value of the validated node. * @param string $group The current validation group. * @param string $propertyPath The property path to the current node. */ public function __construct(GlobalExecutionContextInterface $globalContext, TranslatorInterface $translator, $translationDomain = null, MetadataInterface $metadata = null, $value = null, $group = null, $propertyPath = '') { if (null === $group) { $group = Constraint::DEFAULT_GROUP; } $this->globalContext = $globalContext; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->metadata = $metadata; $this->value = $value; $this->propertyPath = $propertyPath; $this->group = $group; } /** * {@inheritdoc} */ public function addViolation($message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null) { if (null === $pluralization) { $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain); } else { try { $translatedMessage = $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain); } catch (\InvalidArgumentException $e) { $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain); } } $this->globalContext->getViolations()->add(new ConstraintViolation( $translatedMessage, $message, $params, $this->globalContext->getRoot(), $this->propertyPath, // check using func_num_args() to allow passing null values func_num_args() >= 3 ? $invalidValue : $this->value, $pluralization, $code )); } /** * {@inheritdoc} */ public function addViolationAt($subPath, $message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null) { $this->globalContext->getViolations()->add(new ConstraintViolation( null === $pluralization ? $this->translator->trans($message, $params, $this->translationDomain) : $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain), $message, $params, $this->globalContext->getRoot(), $this->getPropertyPath($subPath), // check using func_num_args() to allow passing null values func_num_args() >= 4 ? $invalidValue : $this->value, $pluralization, $code )); } /** * {@inheritdoc} */ public function getViolations() { return $this->globalContext->getViolations(); } /** * {@inheritdoc} */ public function getRoot() { return $this->globalContext->getRoot(); } /** * {@inheritdoc} */ public function getPropertyPath($subPath = '') { if ('' != $subPath && '' !== $this->propertyPath && '[' !== $subPath[0]) { return $this->propertyPath.'.'.$subPath; } return $this->propertyPath.$subPath; } /** * {@inheritdoc} */ public function getClassName() { if ($this->metadata instanceof ClassBasedInterface) { return $this->metadata->getClassName(); } return null; } /** * {@inheritdoc} */ public function getPropertyName() { if ($this->metadata instanceof PropertyMetadataInterface) { return $this->metadata->getPropertyName(); } return null; } /** * {@inheritdoc} */ public function getValue() { return $this->value; } /** * {@inheritdoc} */ public function getGroup() { return $this->group; } /** * {@inheritdoc} */ public function getMetadata() { return $this->metadata; } /** * {@inheritdoc} */ public function getMetadataFor($value) { return $this->globalContext->getMetadataFactory()->getMetadataFor($value); } /** * {@inheritdoc} */ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false) { $propertyPath = $this->getPropertyPath($subPath); foreach ($this->resolveGroups($groups) as $group) { $this->globalContext->getVisitor()->validate($value, $group, $propertyPath, $traverse, $deep); } } /** * {@inheritdoc} */ public function validateValue($value, $constraints, $subPath = '', $groups = null) { $constraints = is_array($constraints) ? $constraints : array($constraints); if (null === $groups && '' === $subPath) { $context = clone $this; $context->value = $value; $context->executeConstraintValidators($value, $constraints); return; } $propertyPath = $this->getPropertyPath($subPath); foreach ($this->resolveGroups($groups) as $group) { $context = clone $this; $context->value = $value; $context->group = $group; $context->propertyPath = $propertyPath; $context->executeConstraintValidators($value, $constraints); } } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->globalContext->getMetadataFactory(); } /** * Executes the validators of the given constraints for the given value. * * @param mixed $value The value to validate. * @param Constraint[] $constraints The constraints to match against. */ private function executeConstraintValidators($value, array $constraints) { foreach ($constraints as $constraint) { $validator = $this->globalContext->getValidatorFactory()->getInstance($constraint); $validator->initialize($this); $validator->validate($value, $constraint); } } /** * Returns an array of group names. * * @param null|string|string[] $groups The groups to resolve. If a single string is * passed, it is converted to an array. If null * is passed, an array containing the current * group of the context is returned. * * @return array An array of validation groups. */ private function resolveGroups($groups) { return $groups ? (array) $groups : (array) $this->group; } } PK!+s:Symfony/Component/Validator/ConstraintValidatorFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Constraints\ExpressionValidator; /** * Default implementation of the ConstraintValidatorFactoryInterface. * * This enforces the convention that the validatedBy() method on any * Constraint will return the class name of the ConstraintValidator that * should validate the Constraint. * * @author Bernhard Schussek */ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface { protected $validators = array(); /** * @var PropertyAccessorInterface */ private $propertyAccessor; public function __construct(PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** * {@inheritDoc} */ public function getInstance(Constraint $constraint) { $className = $constraint->validatedBy(); // The second condition is a hack that is needed when CollectionValidator // calls itself recursively (Collection constraints can be nested). // Since the context of the validator is overwritten when initialize() // is called for the nested constraint, the outer validator is // acting on the wrong context when the nested validation terminates. // // A better solution - which should be approached in Symfony 3.0 - is to // remove the initialize() method and pass the context as last argument // to validate() instead. if (!isset($this->validators[$className]) || 'Symfony\Component\Validator\Constraints\CollectionValidator' === $className) { $this->validators[$className] = 'validator.expression' === $className ? new ExpressionValidator($this->propertyAccessor) : new $className(); } return $this->validators[$className]; } } PK!SqK K 1Symfony/Component/Validator/MetadataInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A container for validation metadata. * * The container contains constraints that may belong to different validation * groups. Constraints for a specific group can be fetched by calling * {@link findConstraints}. * * Implement this interface to add validation metadata to your own metadata * layer. Each metadata may have named properties. Each property can be * represented by one or more {@link PropertyMetadataInterface} instances that * are returned by {@link getPropertyMetadata}. Since * PropertyMetadataInterface inherits from MetadataInterface, * each property may be divided into further properties. * * The {@link accept} method of each metadata implements the Visitor pattern. * The method should forward the call to the visitor's * {@link ValidationVisitorInterface::visit} method and additionally call * accept() on all structurally related metadata instances. * * For example, to store constraints for PHP classes and their properties, * create a class ClassMetadata (implementing MetadataInterface) * and a class PropertyMetadata (implementing PropertyMetadataInterface). * ClassMetadata::getPropertyMetadata($property) returns all * PropertyMetadata instances for a property of that class. Its * accept()-method simply forwards to ValidationVisitorInterface::visit() * and calls accept() on all contained PropertyMetadata * instances, which themselves call ValidationVisitorInterface::visit() * again. * * @author Bernhard Schussek */ interface MetadataInterface { /** * Implementation of the Visitor design pattern. * * Calls {@link ValidationVisitorInterface::visit} and then forwards the * accept()-call to all property metadata instances. * * @param ValidationVisitorInterface $visitor The visitor implementing the validation logic. * @param mixed $value The value to validate. * @param string|string[] $group The validation group to validate in. * @param string $propertyPath The current property path in the validation graph. */ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath); /** * Returns all constraints for a given validation group. * * @param string $group The validation group. * * @return Constraint[] A list of constraint instances. */ public function findConstraints($group); } PK!R'<Symfony/Component/Validator/ConstraintViolationInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A violation of a constraint that happened during validation. * * For each constraint that fails during validation one or more violations are * created. The violations store the violation message, the path to the failing * element in the validation graph and the root element that was originally * passed to the validator. For example, take the following graph: * *
 * (Person)---(firstName: string)
 *      \
 *   (address: Address)---(street: string)
 * 
* * If the Person object is validated and validation fails for the * "firstName" property, the generated violation has the Person * instance as root and the property path "firstName". If validation fails * for the "street" property of the related Address instance, the root * element is still the person, but the property path is "address.street". * * @author Bernhard Schussek * * @api */ interface ConstraintViolationInterface { /** * Returns the violation message. * * @return string The violation message. * * @api */ public function getMessage(); /** * Returns the raw violation message. * * The raw violation message contains placeholders for the parameters * returned by {@link getMessageParameters}. Typically you'll pass the * message template and parameters to a translation engine. * * @return string The raw violation message. * * @api */ public function getMessageTemplate(); /** * Returns the parameters to be inserted into the raw violation message. * * @return array A possibly empty list of parameters indexed by the names * that appear in the message template. * * @see getMessageTemplate * * @api */ public function getMessageParameters(); /** * Returns a number for pluralizing the violation message. * * For example, the message template could have different translation based * on a parameter "choices": * *
    *
  • Please select exactly one entry. (choices=1)
  • *
  • Please select two entries. (choices=2)
  • *
* * This method returns the value of the parameter for choosing the right * pluralization form (in this case "choices"). * * @return integer|null The number to use to pluralize of the message. */ public function getMessagePluralization(); /** * Returns the root element of the validation. * * @return mixed The value that was passed originally to the validator when * the validation was started. Because the validator traverses * the object graph, the value at which the violation occurs * is not necessarily the value that was originally validated. * * @api */ public function getRoot(); /** * Returns the property path from the root element to the violation. * * @return string The property path indicates how the validator reached * the invalid value from the root element. If the root * element is a Person instance with a property * "address" that contains an Address instance * with an invalid property "street", the generated property * path is "address.street". Property access is denoted by * dots, while array access is denoted by square brackets, * for example "addresses[1].street". * * @api */ public function getPropertyPath(); /** * Returns the value that caused the violation. * * @return mixed The invalid value that caused the validated constraint to * fail. * * @api */ public function getInvalidValue(); /** * Returns a machine-digestible error code for the violation. * * @return mixed The error code. */ public function getCode(); } PK!ƭW*Symfony/Component/Validator/Constraint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Exception\InvalidOptionsException; use Symfony\Component\Validator\Exception\MissingOptionsException; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Contains the properties of a constraint definition. * * A constraint can be defined on a class, an option or a getter method. * The Constraint class encapsulates all the configuration required for * validating this class, option or getter result successfully. * * Constraint instances are immutable and serializable. * * @author Bernhard Schussek * * @api */ abstract class Constraint { /** * The name of the group given to all constraints with no explicit group * @var string */ const DEFAULT_GROUP = 'Default'; /** * Marks a constraint that can be put onto classes * @var string */ const CLASS_CONSTRAINT = 'class'; /** * Marks a constraint that can be put onto properties * @var string */ const PROPERTY_CONSTRAINT = 'property'; /** * @var array */ public $groups = array(self::DEFAULT_GROUP); /** * Initializes the constraint with options. * * You should pass an associative array. The keys should be the names of * existing properties in this class. The values should be the value for these * properties. * * Alternatively you can override the method getDefaultOption() to return the * name of an existing property. If no associative array is passed, this * property is set instead. * * You can force that certain options are set by overriding * getRequiredOptions() to return the names of these options. If any * option is not set here, an exception is thrown. * * @param mixed $options The options (as associative array) * or the value for the default * option (any other type) * * @throws InvalidOptionsException When you pass the names of non-existing * options * @throws MissingOptionsException When you don't pass any of the options * returned by getRequiredOptions() * @throws ConstraintDefinitionException When you don't pass an associative * array, but getDefaultOption() returns * null * * @api */ public function __construct($options = null) { $invalidOptions = array(); $missingOptions = array_flip((array) $this->getRequiredOptions()); if (is_array($options) && count($options) >= 1 && isset($options['value']) && !property_exists($this, 'value')) { $options[$this->getDefaultOption()] = $options['value']; unset($options['value']); } if (is_array($options) && count($options) > 0 && is_string(key($options))) { foreach ($options as $option => $value) { if (property_exists($this, $option)) { $this->$option = $value; unset($missingOptions[$option]); } else { $invalidOptions[] = $option; } } } elseif (null !== $options && ! (is_array($options) && count($options) === 0)) { $option = $this->getDefaultOption(); if (null === $option) { throw new ConstraintDefinitionException( sprintf('No default option is configured for constraint %s', get_class($this)) ); } if (property_exists($this, $option)) { $this->$option = $options; unset($missingOptions[$option]); } else { $invalidOptions[] = $option; } } if (count($invalidOptions) > 0) { throw new InvalidOptionsException( sprintf('The options "%s" do not exist in constraint %s', implode('", "', $invalidOptions), get_class($this)), $invalidOptions ); } if (count($missingOptions) > 0) { throw new MissingOptionsException( sprintf('The options "%s" must be set for constraint %s', implode('", "', array_keys($missingOptions)), get_class($this)), array_keys($missingOptions) ); } $this->groups = (array) $this->groups; } /** * Unsupported operation. */ public function __set($option, $value) { throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, get_class($this)), array($option)); } /** * Adds the given group if this constraint is in the Default group * * @param string $group * * @api */ public function addImplicitGroupName($group) { if (in_array(Constraint::DEFAULT_GROUP, $this->groups) && !in_array($group, $this->groups)) { $this->groups[] = $group; } } /** * Returns the name of the default option * * Override this method to define a default option. * * @return string * @see __construct() * * @api */ public function getDefaultOption() { return null; } /** * Returns the name of the required options * * Override this method if you want to define required options. * * @return array * @see __construct() * * @api */ public function getRequiredOptions() { return array(); } /** * Returns the name of the class that validates this constraint * * By default, this is the fully qualified name of the constraint class * suffixed with "Validator". You can override this method to change that * behaviour. * * @return string * * @api */ public function validatedBy() { return get_class($this).'Validator'; } /** * Returns whether the constraint can be put onto classes, properties or * both * * This method should return one or more of the constants * Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT. * * @return string|array One or more constant values * * @api */ public function getTargets() { return self::PROPERTY_CONSTRAINT; } } PK!|6Symfony/Component/Validator/Mapping/GetterMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Exception\ValidatorException; class GetterMetadata extends MemberMetadata { /** * Constructor. * * @param string $class The class the getter is defined on * @param string $property The property which the getter returns * * @throws ValidatorException */ public function __construct($class, $property) { $getMethod = 'get'.ucfirst($property); $isMethod = 'is'.ucfirst($property); if (method_exists($class, $getMethod)) { $method = $getMethod; } elseif (method_exists($class, $isMethod)) { $method = $isMethod; } else { throw new ValidatorException(sprintf('Neither method %s nor %s exists in class %s', $getMethod, $isMethod, $class)); } parent::__construct($class, $method, $property); } /** * {@inheritDoc} */ public function getPropertyValue($object) { return $this->newReflectionMember($object)->invoke($object); } /** * {@inheritDoc} */ protected function newReflectionMember($objectOrClassName) { return new \ReflectionMethod($objectOrClassName, $this->getName()); } } PK! r 8Symfony/Component/Validator/Mapping/PropertyMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Exception\ValidatorException; class PropertyMetadata extends MemberMetadata { /** * Constructor. * * @param string $class The class this property is defined on * @param string $name The name of this property * * @throws ValidatorException */ public function __construct($class, $name) { if (!property_exists($class, $name)) { throw new ValidatorException(sprintf('Property %s does not exist in class %s', $name, $class)); } parent::__construct($class, $name, $name); } /** * {@inheritDoc} */ public function getPropertyValue($object) { return $this->getReflectionMember($object)->getValue($object); } /** * {@inheritDoc} */ protected function newReflectionMember($objectOrClassName) { $class = new \ReflectionClass($objectOrClassName); while (!$class->hasProperty($this->getName())) { $class = $class->getParentClass(); } $member = new \ReflectionProperty($class->getName(), $this->getName()); $member->setAccessible(true); return $member; } } PK!t././5Symfony/Component/Validator/Mapping/ClassMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\ValidationVisitorInterface; use Symfony\Component\Validator\PropertyMetadataContainerInterface; use Symfony\Component\Validator\ClassBasedInterface; use Symfony\Component\Validator\MetadataInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\GroupDefinitionException; /** * Represents all the configured constraints on a given class. * * @author Bernhard Schussek * @author Fabien Potencier */ class ClassMetadata extends ElementMetadata implements MetadataInterface, ClassBasedInterface, PropertyMetadataContainerInterface { /** * @var string */ public $name; /** * @var string */ public $defaultGroup; /** * @var MemberMetadata[] */ public $members = array(); /** * @var PropertyMetadata[] */ public $properties = array(); /** * @var GetterMetadata[] */ public $getters = array(); /** * @var array */ public $groupSequence = array(); /** * @var Boolean */ public $groupSequenceProvider = false; /** * @var \ReflectionClass */ private $reflClass; /** * Constructs a metadata for the given class * * @param string $class */ public function __construct($class) { $this->name = $class; // class name without namespace if (false !== $nsSep = strrpos($class, '\\')) { $this->defaultGroup = substr($class, $nsSep + 1); } else { $this->defaultGroup = $class; } } public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null) { if (null === $propagatedGroup && Constraint::DEFAULT_GROUP === $group && ($this->hasGroupSequence() || $this->isGroupSequenceProvider())) { if ($this->hasGroupSequence()) { $groups = $this->getGroupSequence(); } else { $groups = $value->getGroupSequence(); } foreach ($groups as $group) { $this->accept($visitor, $value, $group, $propertyPath, Constraint::DEFAULT_GROUP); if (count($visitor->getViolations()) > 0) { break; } } return; } $visitor->visit($this, $value, $group, $propertyPath); if (null !== $value) { $pathPrefix = empty($propertyPath) ? '' : $propertyPath.'.'; foreach ($this->getConstrainedProperties() as $property) { foreach ($this->getMemberMetadatas($property) as $member) { $member->accept($visitor, $member->getPropertyValue($value), $group, $pathPrefix.$property, $propagatedGroup); } } } } /** * Returns the properties to be serialized * * @return array */ public function __sleep() { return array_merge(parent::__sleep(), array( 'getters', 'groupSequence', 'groupSequenceProvider', 'members', 'name', 'properties', 'defaultGroup' )); } /** * Returns the fully qualified name of the class * * @return string The fully qualified class name */ public function getClassName() { return $this->name; } /** * Returns the name of the default group for this class * * For each class, the group "Default" is an alias for the group * "", where is the non-namespaced name of the * class. All constraints implicitly or explicitly assigned to group * "Default" belong to both of these groups, unless the class defines * a group sequence. * * If a class defines a group sequence, validating the class in "Default" * will validate the group sequence. The constraints assigned to "Default" * can still be validated by validating the class in "". * * @return string The name of the default group */ public function getDefaultGroup() { return $this->defaultGroup; } /** * {@inheritDoc} */ public function addConstraint(Constraint $constraint) { if (!in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets())) { throw new ConstraintDefinitionException(sprintf( 'The constraint %s cannot be put on classes', get_class($constraint) )); } $constraint->addImplicitGroupName($this->getDefaultGroup()); parent::addConstraint($constraint); } /** * Adds a constraint to the given property. * * @param string $property The name of the property * @param Constraint $constraint The constraint * * @return ClassMetadata This object */ public function addPropertyConstraint($property, Constraint $constraint) { if (!isset($this->properties[$property])) { $this->properties[$property] = new PropertyMetadata($this->getClassName(), $property); $this->addMemberMetadata($this->properties[$property]); } $constraint->addImplicitGroupName($this->getDefaultGroup()); $this->properties[$property]->addConstraint($constraint); return $this; } /** * Adds a constraint to the getter of the given property. * * The name of the getter is assumed to be the name of the property with an * uppercased first letter and either the prefix "get" or "is". * * @param string $property The name of the property * @param Constraint $constraint The constraint * * @return ClassMetadata This object */ public function addGetterConstraint($property, Constraint $constraint) { if (!isset($this->getters[$property])) { $this->getters[$property] = new GetterMetadata($this->getClassName(), $property); $this->addMemberMetadata($this->getters[$property]); } $constraint->addImplicitGroupName($this->getDefaultGroup()); $this->getters[$property]->addConstraint($constraint); return $this; } /** * Merges the constraints of the given metadata into this object. * * @param ClassMetadata $source The source metadata */ public function mergeConstraints(ClassMetadata $source) { foreach ($source->getConstraints() as $constraint) { $this->addConstraint(clone $constraint); } foreach ($source->getConstrainedProperties() as $property) { foreach ($source->getMemberMetadatas($property) as $member) { $member = clone $member; foreach ($member->getConstraints() as $constraint) { $constraint->addImplicitGroupName($this->getDefaultGroup()); } $this->addMemberMetadata($member); if (!$member->isPrivate($this->name)) { $property = $member->getPropertyName(); if ($member instanceof PropertyMetadata && !isset($this->properties[$property])) { $this->properties[$property] = $member; } elseif ($member instanceof GetterMetadata && !isset($this->getters[$property])) { $this->getters[$property] = $member; } } } } } /** * Adds a member metadata. * * @param MemberMetadata $metadata */ protected function addMemberMetadata(MemberMetadata $metadata) { $property = $metadata->getPropertyName(); $this->members[$property][] = $metadata; } /** * Returns true if metadatas of members is present for the given property. * * @param string $property The name of the property * * @return Boolean */ public function hasMemberMetadatas($property) { return array_key_exists($property, $this->members); } /** * Returns all metadatas of members describing the given property. * * @param string $property The name of the property * * @return MemberMetadata[] An array of MemberMetadata */ public function getMemberMetadatas($property) { return $this->members[$property]; } /** * {@inheritdoc} */ public function hasPropertyMetadata($property) { return array_key_exists($property, $this->members); } /** * {@inheritdoc} */ public function getPropertyMetadata($property) { return $this->members[$property]; } /** * Returns all properties for which constraints are defined. * * @return array An array of property names */ public function getConstrainedProperties() { return array_keys($this->members); } /** * Sets the default group sequence for this class. * * @param array $groups An array of group names * * @return ClassMetadata * * @throws GroupDefinitionException */ public function setGroupSequence(array $groups) { if ($this->isGroupSequenceProvider()) { throw new GroupDefinitionException('Defining a static group sequence is not allowed with a group sequence provider'); } if (in_array(Constraint::DEFAULT_GROUP, $groups, true)) { throw new GroupDefinitionException(sprintf('The group "%s" is not allowed in group sequences', Constraint::DEFAULT_GROUP)); } if (!in_array($this->getDefaultGroup(), $groups, true)) { throw new GroupDefinitionException(sprintf('The group "%s" is missing in the group sequence', $this->getDefaultGroup())); } $this->groupSequence = $groups; return $this; } /** * Returns whether this class has an overridden default group sequence. * * @return Boolean */ public function hasGroupSequence() { return count($this->groupSequence) > 0; } /** * Returns the default group sequence for this class. * * @return array An array of group names */ public function getGroupSequence() { return $this->groupSequence; } /** * Returns a ReflectionClass instance for this class. * * @return \ReflectionClass */ public function getReflectionClass() { if (!$this->reflClass) { $this->reflClass = new \ReflectionClass($this->getClassName()); } return $this->reflClass; } /** * Sets whether a group sequence provider should be used. * * @param Boolean $active * * @throws GroupDefinitionException */ public function setGroupSequenceProvider($active) { if ($this->hasGroupSequence()) { throw new GroupDefinitionException('Defining a group sequence provider is not allowed with a static group sequence'); } if (!$this->getReflectionClass()->implementsInterface('Symfony\Component\Validator\GroupSequenceProviderInterface')) { throw new GroupDefinitionException(sprintf('Class "%s" must implement GroupSequenceProviderInterface', $this->name)); } $this->groupSequenceProvider = $active; } /** * Returns whether the class is a group sequence provider. * * @return Boolean */ public function isGroupSequenceProvider() { return $this->groupSequenceProvider; } } PK!!" " 7Symfony/Component/Validator/Mapping/ElementMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Constraint; abstract class ElementMetadata { /** * @var Constraint[] */ public $constraints = array(); /** * @var array */ public $constraintsByGroup = array(); /** * Returns the names of the properties that should be serialized. * * @return array */ public function __sleep() { return array( 'constraints', 'constraintsByGroup', ); } /** * Clones this object. */ public function __clone() { $constraints = $this->constraints; $this->constraints = array(); $this->constraintsByGroup = array(); foreach ($constraints as $constraint) { $this->addConstraint(clone $constraint); } } /** * Adds a constraint to this element. * * @param Constraint $constraint * * @return ElementMetadata */ public function addConstraint(Constraint $constraint) { $this->constraints[] = $constraint; foreach ($constraint->groups as $group) { $this->constraintsByGroup[$group][] = $constraint; } return $this; } /** * Returns all constraints of this element. * * @return Constraint[] An array of Constraint instances */ public function getConstraints() { return $this->constraints; } /** * Returns whether this element has any constraints. * * @return Boolean */ public function hasConstraints() { return count($this->constraints) > 0; } /** * Returns the constraints of the given group and global ones (* group). * * @param string $group The group name * * @return array An array with all Constraint instances belonging to the group */ public function findConstraints($group) { return isset($this->constraintsByGroup[$group]) ? $this->constraintsByGroup[$group] : array(); } } PK!/;aa6Symfony/Component/Validator/Mapping/MemberMetadata.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\ValidationVisitorInterface; use Symfony\Component\Validator\ClassBasedInterface; use Symfony\Component\Validator\PropertyMetadataInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; abstract class MemberMetadata extends ElementMetadata implements PropertyMetadataInterface, ClassBasedInterface { public $class; public $name; public $property; public $cascaded = false; public $collectionCascaded = false; public $collectionCascadedDeeply = false; private $reflMember = array(); /** * Constructor. * * @param string $class The name of the class this member is defined on * @param string $name The name of the member * @param string $property The property the member belongs to */ public function __construct($class, $name, $property) { $this->class = $class; $this->name = $name; $this->property = $property; } public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null) { $visitor->visit($this, $value, $group, $propertyPath); if ($this->isCascaded()) { $visitor->validate($value, $propagatedGroup ?: $group, $propertyPath, $this->isCollectionCascaded(), $this->isCollectionCascadedDeeply()); } } /** * {@inheritDoc} */ public function addConstraint(Constraint $constraint) { if (!in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets())) { throw new ConstraintDefinitionException(sprintf( 'The constraint %s cannot be put on properties or getters', get_class($constraint) )); } if ($constraint instanceof Valid) { $this->cascaded = true; /* @var Valid $constraint */ $this->collectionCascaded = $constraint->traverse; $this->collectionCascadedDeeply = $constraint->deep; } else { parent::addConstraint($constraint); } return $this; } /** * Returns the names of the properties that should be serialized * * @return array */ public function __sleep() { return array_merge(parent::__sleep(), array( 'class', 'name', 'property', 'cascaded', 'collectionCascaded', 'collectionCascadedDeeply', )); } /** * Returns the name of the member * * @return string */ public function getName() { return $this->name; } /** * Returns the class this member is defined on * * @return string */ public function getClassName() { return $this->class; } /** * Returns the name of the property this member belongs to * * @return string The property name */ public function getPropertyName() { return $this->property; } /** * Returns whether this member is public * * @param object|string $objectOrClassName The object or the class name * * @return Boolean */ public function isPublic($objectOrClassName) { return $this->getReflectionMember($objectOrClassName)->isPublic(); } /** * Returns whether this member is protected * * @param object|string $objectOrClassName The object or the class name * * @return Boolean */ public function isProtected($objectOrClassName) { return $this->getReflectionMember($objectOrClassName)->isProtected(); } /** * Returns whether this member is private * * @param object|string $objectOrClassName The object or the class name * * @return Boolean */ public function isPrivate($objectOrClassName) { return $this->getReflectionMember($objectOrClassName)->isPrivate(); } /** * Returns whether objects stored in this member should be validated * * @return Boolean */ public function isCascaded() { return $this->cascaded; } /** * Returns whether arrays or traversable objects stored in this member * should be traversed and validated in each entry * * @return Boolean */ public function isCollectionCascaded() { return $this->collectionCascaded; } /** * Returns whether arrays or traversable objects stored in this member * should be traversed recursively for inner arrays/traversable objects * * @return Boolean */ public function isCollectionCascadedDeeply() { return $this->collectionCascadedDeeply; } /** * Returns the Reflection instance of the member * * @param object|string $objectOrClassName The object or the class name * * @return object */ public function getReflectionMember($objectOrClassName) { $className = is_string($objectOrClassName) ? $objectOrClassName : get_class($objectOrClassName); if (!isset($this->reflMember[$className])) { $this->reflMember[$className] = $this->newReflectionMember($objectOrClassName); } return $this->reflMember[$className]; } /** * Creates a new Reflection instance for the member * * @param object|string $objectOrClassName The object or the class name * * @return mixed Reflection class */ abstract protected function newReflectionMember($objectOrClassName); } PK!+d%%<Symfony/Component/Validator/Mapping/Cache/CacheInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Cache; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Persists ClassMetadata instances in a cache * * @author Bernhard Schussek */ interface CacheInterface { /** * Returns whether metadata for the given class exists in the cache * * @param string $class */ public function has($class); /** * Returns the metadata for the given class from the cache * * @param string $class Class Name * * @return ClassMetadata|false A ClassMetadata instance or false on miss */ public function read($class); /** * Stores a class metadata in the cache * * @param ClassMetadata $metadata A Class Metadata */ public function write(ClassMetadata $metadata); } PK!6Symfony/Component/Validator/Mapping/Cache/ApcCache.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Cache; use Symfony\Component\Validator\Mapping\ClassMetadata; class ApcCache implements CacheInterface { private $prefix; public function __construct($prefix) { if (!extension_loaded('apc')) { throw new \RuntimeException('Unable to use ApcCache to cache validator mappings as APC is not enabled.'); } $this->prefix = $prefix; } public function has($class) { if (!function_exists('apc_exists')) { $exists = false; apc_fetch($this->prefix.$class, $exists); return $exists; } return apc_exists($this->prefix.$class); } public function read($class) { return apc_fetch($this->prefix.$class); } public function write(ClassMetadata $metadata) { apc_store($this->prefix.$metadata->getClassName(), $metadata); } } PK!d#[N <Symfony/Component/Validator/Mapping/ClassMetadataFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Exception\NoSuchMetadataException; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; use Symfony\Component\Validator\Mapping\Cache\CacheInterface; /** * A factory for creating metadata for PHP classes. * * @author Bernhard Schussek */ class ClassMetadataFactory implements MetadataFactoryInterface { /** * The loader for loading the class metadata * @var LoaderInterface */ protected $loader; /** * The cache for caching class metadata * @var CacheInterface */ protected $cache; protected $loadedClasses = array(); public function __construct(LoaderInterface $loader = null, CacheInterface $cache = null) { $this->loader = $loader; $this->cache = $cache; } /** * {@inheritdoc} */ public function getMetadataFor($value) { if (!is_object($value) && !is_string($value)) { throw new NoSuchMetadataException(sprintf('Cannot create metadata for non-objects. Got: %s', gettype($value))); } $class = ltrim(is_object($value) ? get_class($value) : $value, '\\'); if (isset($this->loadedClasses[$class])) { return $this->loadedClasses[$class]; } if (null !== $this->cache && false !== ($this->loadedClasses[$class] = $this->cache->read($class))) { return $this->loadedClasses[$class]; } if (!class_exists($class) && !interface_exists($class)) { throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class)); } $metadata = new ClassMetadata($class); // Include constraints from the parent class if ($parent = $metadata->getReflectionClass()->getParentClass()) { $metadata->mergeConstraints($this->getMetadataFor($parent->name)); } // Include constraints from all implemented interfaces foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) { if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) { continue; } $metadata->mergeConstraints($this->getMetadataFor($interface->name)); } if (null !== $this->loader) { $this->loader->loadClassMetadata($metadata); } if (null !== $this->cache) { $this->cache->write($metadata); } return $this->loadedClasses[$class] = $metadata; } /** * {@inheritdoc} */ public function hasMetadataFor($value) { if (!is_object($value) && !is_string($value)) { return false; } $class = ltrim(is_object($value) ? get_class($value) : $value, '\\'); if (class_exists($class) || interface_exists($class)) { return true; } return false; } } PK!ʚ9Symfony/Component/Validator/Mapping/Loader/FileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; abstract class FileLoader extends AbstractLoader { protected $file; /** * Constructor. * * @param string $file The mapping file to load * * @throws MappingException if the mapping file does not exist * @throws MappingException if the mapping file is not readable */ public function __construct($file) { if (!is_file($file)) { throw new MappingException(sprintf('The mapping file %s does not exist', $file)); } if (!is_readable($file)) { throw new MappingException(sprintf('The mapping file %s is not readable', $file)); } $this->file = $file; } } PK!kG+=Symfony/Component/Validator/Mapping/Loader/AbstractLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Constraint; abstract class AbstractLoader implements LoaderInterface { /** * Contains all known namespaces indexed by their prefix * @var array */ protected $namespaces = array(); /** * Adds a namespace alias. * * @param string $alias The alias * @param string $namespace The PHP namespace */ protected function addNamespaceAlias($alias, $namespace) { $this->namespaces[$alias] = $namespace; } /** * Creates a new constraint instance for the given constraint name. * * @param string $name The constraint name. Either a constraint relative * to the default constraint namespace, or a fully * qualified class name * @param mixed $options The constraint options * * @return Constraint * * @throws MappingException If the namespace prefix is undefined */ protected function newConstraint($name, $options) { if (strpos($name, '\\') !== false && class_exists($name)) { $className = (string) $name; } elseif (strpos($name, ':') !== false) { list($prefix, $className) = explode(':', $name, 2); if (!isset($this->namespaces[$prefix])) { throw new MappingException(sprintf('Undefined namespace prefix "%s"', $prefix)); } $className = $this->namespaces[$prefix].$className; } else { $className = 'Symfony\\Component\\Validator\\Constraints\\'.$name; } return new $className($options); } } PK!Rᠯ=Symfony/Component/Validator/Mapping/Loader/XmlFilesLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; /** * Loads multiple xml mapping files * * @author Bulat Shakirzyanov * * @see Symfony\Component\Validator\Mapping\Loader\FilesLoader */ class XmlFilesLoader extends FilesLoader { /** * {@inheritDoc} */ public function getFileLoaderInstance($file) { return new XmlFileLoader($file); } } PK!?>Symfony/Component/Validator/Mapping/Loader/YamlFilesLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; /** * Loads multiple yaml mapping files * * @author Bulat Shakirzyanov * * @see Symfony\Component\Validator\Mapping\Loader\FilesLoader */ class YamlFilesLoader extends FilesLoader { /** * {@inheritDoc} */ public function getFileLoaderInstance($file) { return new YamlFileLoader($file); } } PK!:Symfony/Component/Validator/Mapping/Loader/LoaderChain.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Calls multiple LoaderInterface instances in a chain * * This class accepts multiple instances of LoaderInterface to be passed to the * constructor. When loadClassMetadata() is called, the same method is called * in all of these loaders, regardless of whether any of them was * successful or not. * * @author Bernhard Schussek */ class LoaderChain implements LoaderInterface { protected $loaders; /** * Accepts a list of LoaderInterface instances * * @param LoaderInterface[] $loaders An array of LoaderInterface instances * * @throws MappingException If any of the loaders does not implement LoaderInterface */ public function __construct(array $loaders) { foreach ($loaders as $loader) { if (!$loader instanceof LoaderInterface) { throw new MappingException(sprintf('Class %s is expected to implement LoaderInterface', get_class($loader))); } } $this->loaders = $loaders; } /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { $success = false; foreach ($this->loaders as $loader) { $success = $loader->loadClassMetadata($metadata) || $success; } return $success; } } PK!TbASymfony/Component/Validator/Mapping/Loader/StaticMethodLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; class StaticMethodLoader implements LoaderInterface { protected $methodName; public function __construct($methodName = 'loadValidatorMetadata') { $this->methodName = $methodName; } /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { /** @var \ReflectionClass $reflClass */ $reflClass = $metadata->getReflectionClass(); if (!$reflClass->isInterface() && $reflClass->hasMethod($this->methodName)) { $reflMethod = $reflClass->getMethod($this->methodName); if ($reflMethod->isAbstract()) { return false; } if (!$reflMethod->isStatic()) { throw new MappingException(sprintf('The method %s::%s should be static', $reflClass->name, $this->methodName)); } if ($reflMethod->getDeclaringClass()->name != $reflClass->name) { return false; } $reflMethod->invoke(null, $metadata); return true; } return false; } } PK!>??>Symfony/Component/Validator/Mapping/Loader/LoaderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Mapping\ClassMetadata; interface LoaderInterface { /** * Load a Class Metadata. * * @param ClassMetadata $metadata A metadata * * @return Boolean */ public function loadClassMetadata(ClassMetadata $metadata); } PK!*:Symfony/Component/Validator/Mapping/Loader/FilesLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; /** * Creates mapping loaders for array of files. * * Abstract class, used by * * @author Bulat Shakirzyanov * * @see Symfony\Component\Validator\Mapping\Loader\YamlFileLoader * @see Symfony\Component\Validator\Mapping\Loader\XmlFileLoader */ abstract class FilesLoader extends LoaderChain { /** * Array of mapping files. * * @param array $paths Array of file paths */ public function __construct(array $paths) { parent::__construct($this->getFileLoaders($paths)); } /** * Array of mapping files. * * @param array $paths Array of file paths * * @return LoaderInterface[] Array of metadata loaders */ protected function getFileLoaders($paths) { $loaders = array(); foreach ($paths as $path) { $loaders[] = $this->getFileLoaderInstance($path); } return $loaders; } /** * Takes mapping file path. * * @param string $file * * @return LoaderInterface */ abstract protected function getFileLoaderInstance($file); } PK!TO--cSymfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsdnu[ PK!;QF11<Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Config\Util\XmlUtils; class XmlFileLoader extends FileLoader { /** * An array of SimpleXMLElement instances. * * @var \SimpleXMLElement[] */ protected $classes = null; /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { if (null === $this->classes) { $this->classes = array(); $xml = $this->parseFile($this->file); foreach ($xml->namespace as $namespace) { $this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace)); } foreach ($xml->class as $class) { $this->classes[(string) $class['name']] = $class; } } if (isset($this->classes[$metadata->getClassName()])) { $xml = $this->classes[$metadata->getClassName()]; foreach ($xml->{'group-sequence-provider'} as $provider) { $metadata->setGroupSequenceProvider(true); } foreach ($xml->{'group-sequence'} as $groupSequence) { if (count($groupSequence->value) > 0) { $metadata->setGroupSequence($this->parseValues($groupSequence[0]->value)); } } foreach ($this->parseConstraints($xml->constraint) as $constraint) { $metadata->addConstraint($constraint); } foreach ($xml->property as $property) { foreach ($this->parseConstraints($property->constraint) as $constraint) { $metadata->addPropertyConstraint((string) $property['name'], $constraint); } } foreach ($xml->getter as $getter) { foreach ($this->parseConstraints($getter->constraint) as $constraint) { $metadata->addGetterConstraint((string) $getter['property'], $constraint); } } return true; } return false; } /** * Parses a collection of "constraint" XML nodes. * * @param \SimpleXMLElement $nodes The XML nodes * * @return array The Constraint instances */ protected function parseConstraints(\SimpleXMLElement $nodes) { $constraints = array(); foreach ($nodes as $node) { if (count($node) > 0) { if (count($node->value) > 0) { $options = $this->parseValues($node->value); } elseif (count($node->constraint) > 0) { $options = $this->parseConstraints($node->constraint); } elseif (count($node->option) > 0) { $options = $this->parseOptions($node->option); } else { $options = array(); } } elseif (strlen((string) $node) > 0) { $options = trim($node); } else { $options = null; } $constraints[] = $this->newConstraint((string) $node['name'], $options); } return $constraints; } /** * Parses a collection of "value" XML nodes. * * @param \SimpleXMLElement $nodes The XML nodes * * @return array The values */ protected function parseValues(\SimpleXMLElement $nodes) { $values = array(); foreach ($nodes as $node) { if (count($node) > 0) { if (count($node->value) > 0) { $value = $this->parseValues($node->value); } elseif (count($node->constraint) > 0) { $value = $this->parseConstraints($node->constraint); } else { $value = array(); } } else { $value = trim($node); } if (isset($node['key'])) { $values[(string) $node['key']] = $value; } else { $values[] = $value; } } return $values; } /** * Parses a collection of "option" XML nodes. * * @param \SimpleXMLElement $nodes The XML nodes * * @return array The options */ protected function parseOptions(\SimpleXMLElement $nodes) { $options = array(); foreach ($nodes as $node) { if (count($node) > 0) { if (count($node->value) > 0) { $value = $this->parseValues($node->value); } elseif (count($node->constraint) > 0) { $value = $this->parseConstraints($node->constraint); } else { $value = array(); } } else { $value = XmlUtils::phpize($node); if (is_string($value)) { $value = trim($value); } } $options[(string) $node['name']] = $value; } return $options; } /** * Parse a XML File. * * @param string $file Path of file * * @return \SimpleXMLElement * * @throws MappingException */ protected function parseFile($file) { try { $dom = XmlUtils::loadFile($file, __DIR__.'/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd'); } catch (\Exception $e) { throw new MappingException($e->getMessage(), $e->getCode(), $e); } return simplexml_import_dom($dom); } } PK! lw#Q Q ?Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Doctrine\Common\Annotations\Reader; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\GroupSequenceProvider; use Symfony\Component\Validator\Constraint; class AnnotationLoader implements LoaderInterface { protected $reader; public function __construct(Reader $reader) { $this->reader = $reader; } /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { $reflClass = $metadata->getReflectionClass(); $className = $reflClass->name; $loaded = false; foreach ($this->reader->getClassAnnotations($reflClass) as $constraint) { if ($constraint instanceof GroupSequence) { $metadata->setGroupSequence($constraint->groups); } elseif ($constraint instanceof GroupSequenceProvider) { $metadata->setGroupSequenceProvider(true); } elseif ($constraint instanceof Constraint) { $metadata->addConstraint($constraint); } $loaded = true; } foreach ($reflClass->getProperties() as $property) { if ($property->getDeclaringClass()->name == $className) { foreach ($this->reader->getPropertyAnnotations($property) as $constraint) { if ($constraint instanceof Constraint) { $metadata->addPropertyConstraint($property->name, $constraint); } $loaded = true; } } } foreach ($reflClass->getMethods() as $method) { if ($method->getDeclaringClass()->name == $className) { foreach ($this->reader->getMethodAnnotations($method) as $constraint) { if ($constraint instanceof Callback) { $constraint->callback = $method->getName(); $constraint->methods = null; $metadata->addConstraint($constraint); } elseif ($constraint instanceof Constraint) { if (preg_match('/^(get|is)(.+)$/i', $method->name, $matches)) { $metadata->addGetterConstraint(lcfirst($matches[2]), $constraint); } else { throw new MappingException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get" or "is".', $className, $method->name)); } } $loaded = true; } } } return $loaded; } } PK!'pkk=Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Yaml\Parser as YamlParser; class YamlFileLoader extends FileLoader { private $yamlParser; /** * An array of YAML class descriptions * * @var array */ protected $classes = null; /** * {@inheritDoc} */ public function loadClassMetadata(ClassMetadata $metadata) { if (null === $this->classes) { if (!stream_is_local($this->file)) { throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $this->file)); } if (!file_exists($this->file)) { throw new \InvalidArgumentException(sprintf('File "%s" not found.', $this->file)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } $this->classes = $this->yamlParser->parse(file_get_contents($this->file)); // empty file if (null === $this->classes) { return false; } // not an array if (!is_array($this->classes)) { throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $this->file)); } if (isset($this->classes['namespaces'])) { foreach ($this->classes['namespaces'] as $alias => $namespace) { $this->addNamespaceAlias($alias, $namespace); } unset($this->classes['namespaces']); } } // TODO validation if (isset($this->classes[$metadata->getClassName()])) { $yaml = $this->classes[$metadata->getClassName()]; if (isset($yaml['group_sequence_provider'])) { $metadata->setGroupSequenceProvider((bool) $yaml['group_sequence_provider']); } if (isset($yaml['group_sequence'])) { $metadata->setGroupSequence($yaml['group_sequence']); } if (isset($yaml['constraints']) && is_array($yaml['constraints'])) { foreach ($this->parseNodes($yaml['constraints']) as $constraint) { $metadata->addConstraint($constraint); } } if (isset($yaml['properties']) && is_array($yaml['properties'])) { foreach ($yaml['properties'] as $property => $constraints) { if (null !== $constraints) { foreach ($this->parseNodes($constraints) as $constraint) { $metadata->addPropertyConstraint($property, $constraint); } } } } if (isset($yaml['getters']) && is_array($yaml['getters'])) { foreach ($yaml['getters'] as $getter => $constraints) { if (null !== $constraints) { foreach ($this->parseNodes($constraints) as $constraint) { $metadata->addGetterConstraint($getter, $constraint); } } } } return true; } return false; } /** * Parses a collection of YAML nodes * * @param array $nodes The YAML nodes * * @return array An array of values or Constraint instances */ protected function parseNodes(array $nodes) { $values = array(); foreach ($nodes as $name => $childNodes) { if (is_numeric($name) && is_array($childNodes) && count($childNodes) == 1) { $options = current($childNodes); if (is_array($options)) { $options = $this->parseNodes($options); } $values[] = $this->newConstraint(key($childNodes), $options); } else { if (is_array($childNodes)) { $childNodes = $this->parseNodes($childNodes); } $values[$name] = $childNodes; } } return $values; } } PK!۔@Symfony/Component/Validator/Mapping/BlackholeMetadataFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\MetadataFactoryInterface; /** * Simple implementation of MetadataFactoryInterface that can be used when using ValidatorInterface::validateValue(). * * @author Fabien Potencier */ class BlackholeMetadataFactory implements MetadataFactoryInterface { /** * @inheritdoc */ public function getMetadataFor($value) { throw new \LogicException('BlackholeClassMetadataFactory only works with ValidatorInterface::validateValue().'); } /** * @inheritdoc */ public function hasMetadataFor($value) { return false; } } PK!L8 :Symfony/Component/Validator/ValidationVisitorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Validates values against constraints defined in {@link MetadataInterface} * instances. * * This interface is an implementation of the Visitor design pattern. A value * is validated by first passing it to the {@link validate} method. That method * will determine the matching {@link MetadataInterface} for validating the * value. It then calls the {@link MetadataInterface::accept} method of that * metadata. accept() does two things: * *
    *
  1. It calls {@link visit} to validate the value against the constraints of * the metadata.
  2. *
  3. It calls accept() on all nested metadata instances with the * corresponding values extracted from the current value. For example, if the * current metadata represents a class and the current value is an object of * that class, the metadata contains nested instances for each property of that * class. It forwards the call to these nested metadata with the values of the * corresponding properties in the original object.
  4. *
* * @author Bernhard Schussek */ interface ValidationVisitorInterface { /** * Validates a value. * * If the value is an array or a traversable object, you can set the * parameter $traverse to true in order to run through * the collection and validate each element. If these elements can be * collections again and you want to traverse them recursively, set the * parameter $deep to true as well. * * If you set $traversable to true, the visitor will * nevertheless try to find metadata for the collection and validate its * constraints. If no such metadata is found, the visitor ignores that and * only iterates the collection. * * If you don't set $traversable to true and the visitor * does not find metadata for the given value, it will fail with an * exception. * * @param mixed $value The value to validate. * @param string $group The validation group to validate. * @param string $propertyPath The current property path in the validation graph. * @param Boolean $traverse Whether to traverse the value if it is traversable. * @param Boolean $deep Whether to traverse nested traversable values recursively. * * @throws Exception\NoSuchMetadataException If no metadata can be found for * the given value. */ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false); /** * Validates a value against the constraints defined in some metadata. * * This method implements the Visitor design pattern. See also * {@link ValidationVisitorInterface}. * * @param MetadataInterface $metadata The metadata holding the constraints. * @param mixed $value The value to validate. * @param string $group The validation group to validate. * @param string $propertyPath The current property path in the validation graph. */ public function visit(MetadataInterface $metadata, $value, $group, $propertyPath); } PK!QVV:Symfony/Component/Validator/Exception/MappingException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class MappingException extends ValidatorException { } PK!y@Symfony/Component/Validator/Exception/BadMethodCallException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base BadMethodCallException for the Validator component. * * @author Bernhard Schussek */ class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface { } PK!LЉRRASymfony/Component/Validator/Exception/InvalidOptionsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class InvalidOptionsException extends ValidatorException { private $options; public function __construct($message, array $options) { parent::__construct($message); $this->options = $options; } public function getOptions() { return $this->options; } } PK!k1+WW<Symfony/Component/Validator/Exception/ValidatorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class ValidatorException extends \RuntimeException { } PK!b<<ASymfony/Component/Validator/Exception/UnexpectedTypeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class UnexpectedTypeException extends ValidatorException { public function __construct($value, $expectedType) { parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value))); } } PK!1"ccGSymfony/Component/Validator/Exception/ConstraintDefinitionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class ConstraintDefinitionException extends ValidatorException { } PK!T<Symfony/Component/Validator/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base ExceptionInterface for the Validator component. * * @author Bernhard Schussek */ interface ExceptionInterface { } PK!z:Symfony/Component/Validator/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base RuntimeException for the Validator component. * * @author Bernhard Schussek */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK!xASymfony/Component/Validator/Exception/NoSuchMetadataException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * @author Bernhard Schussek */ class NoSuchMetadataException extends ValidatorException { } PK!uRRASymfony/Component/Validator/Exception/MissingOptionsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class MissingOptionsException extends ValidatorException { private $options; public function __construct($message, array $options) { parent::__construct($message); $this->options = $options; } public function getOptions() { return $this->options; } } PK!M#^^BSymfony/Component/Validator/Exception/GroupDefinitionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class GroupDefinitionException extends ValidatorException { } PK!\BSymfony/Component/Validator/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base InvalidArgumentException for the Validator component. * * @author Bernhard Schussek */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK!U<<3Symfony/Component/Validator/ClassBasedInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * An object backed by a PHP class. * * @author Bernhard Schussek */ interface ClassBasedInterface { /** * Returns the name of the backing PHP class. * * @return string The name of the backing class. */ public function getClassName(); } PK!;5t 7Symfony/Component/Validator/ConstraintViolationList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Default implementation of {@ConstraintViolationListInterface}. * * @author Bernhard Schussek */ class ConstraintViolationList implements \IteratorAggregate, ConstraintViolationListInterface { /** * @var ConstraintViolationInterface[] */ private $violations = array(); /** * Creates a new constraint violation list. * * @param ConstraintViolationInterface[] $violations The constraint violations to add to the list */ public function __construct(array $violations = array()) { foreach ($violations as $violation) { $this->add($violation); } } /** * Converts the violation into a string for debugging purposes. * * @return string The violation as string. */ public function __toString() { $string = ''; foreach ($this->violations as $violation) { $string .= $violation."\n"; } return $string; } /** * {@inheritDoc} */ public function add(ConstraintViolationInterface $violation) { $this->violations[] = $violation; } /** * {@inheritDoc} */ public function addAll(ConstraintViolationListInterface $otherList) { foreach ($otherList as $violation) { $this->violations[] = $violation; } } /** * {@inheritDoc} */ public function get($offset) { if (!isset($this->violations[$offset])) { throw new \OutOfBoundsException(sprintf('The offset "%s" does not exist.', $offset)); } return $this->violations[$offset]; } /** * {@inheritDoc} */ public function has($offset) { return isset($this->violations[$offset]); } /** * {@inheritDoc} */ public function set($offset, ConstraintViolationInterface $violation) { $this->violations[$offset] = $violation; } /** * {@inheritDoc} */ public function remove($offset) { unset($this->violations[$offset]); } /** * {@inheritDoc} */ public function getIterator() { return new \ArrayIterator($this->violations); } /** * {@inheritDoc} */ public function count() { return count($this->violations); } /** * {@inheritDoc} */ public function offsetExists($offset) { return $this->has($offset); } /** * {@inheritDoc} */ public function offsetGet($offset) { return $this->get($offset); } /** * {@inheritDoc} */ public function offsetSet($offset, $violation) { if (null === $offset) { $this->add($violation); } else { $this->set($offset, $violation); } } /** * {@inheritDoc} */ public function offsetUnset($offset) { $this->remove($offset); } } PK!AbI̲1Symfony/Component/Validator/ValidationVisitor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Exception\NoSuchMetadataException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Translation\TranslatorInterface; /** * Default implementation of {@link ValidationVisitorInterface} and * {@link GlobalExecutionContextInterface}. * * @author Bernhard Schussek */ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionContextInterface { /** * @var mixed */ private $root; /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ private $validatorFactory; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var array */ private $objectInitializers; /** * @var ConstraintViolationList */ private $violations; /** * @var array */ private $validatedObjects = array(); /** * Creates a new validation visitor. * * @param mixed $root The value passed to the validator. * @param MetadataFactoryInterface $metadataFactory The factory for obtaining metadata instances. * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating constraint validators. * @param TranslatorInterface $translator The translator for translating violation messages. * @param string|null $translationDomain The domain of the translation messages. * @param ObjectInitializerInterface[] $objectInitializers The initializers for preparing objects before validation. * * @throws UnexpectedTypeException If any of the object initializers is not an instance of ObjectInitializerInterface */ public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = null, array $objectInitializers = array()) { foreach ($objectInitializers as $initializer) { if (!$initializer instanceof ObjectInitializerInterface) { throw new UnexpectedTypeException($initializer, 'Symfony\Component\Validator\ObjectInitializerInterface'); } } $this->root = $root; $this->metadataFactory = $metadataFactory; $this->validatorFactory = $validatorFactory; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->objectInitializers = $objectInitializers; $this->violations = new ConstraintViolationList(); } /** * {@inheritdoc} */ public function visit(MetadataInterface $metadata, $value, $group, $propertyPath) { $context = new ExecutionContext( $this, $this->translator, $this->translationDomain, $metadata, $value, $group, $propertyPath ); $context->validateValue($value, $metadata->findConstraints($group)); } /** * {@inheritdoc} */ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false) { if (null === $value) { return; } if (is_object($value)) { $hash = spl_object_hash($value); // Exit, if the object is already validated for the current group if (isset($this->validatedObjects[$hash][$group])) { return; } // Remember validating this object before starting and possibly // traversing the object graph $this->validatedObjects[$hash][$group] = true; foreach ($this->objectInitializers as $initializer) { if (!$initializer instanceof ObjectInitializerInterface) { throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.'); } $initializer->initialize($value); } } // Validate arrays recursively by default, otherwise every driver needs // to implement special handling for arrays. // https://github.com/symfony/symfony/issues/6246 if (is_array($value) || ($traverse && $value instanceof \Traversable)) { foreach ($value as $key => $element) { // Ignore any scalar values in the collection if (is_object($element) || is_array($element)) { // Only repeat the traversal if $deep is set $this->validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep); } } try { $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath); } catch (NoSuchMetadataException $e) { // Metadata doesn't necessarily have to exist for // traversable objects, because we know how to validate // them anyway. Optionally, additional metadata is supported. } } else { $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath); } } /** * {@inheritdoc} */ public function getViolations() { return $this->violations; } /** * {@inheritdoc} */ public function getRoot() { return $this->root; } /** * {@inheritdoc} */ public function getVisitor() { return $this; } /** * {@inheritdoc} */ public function getValidatorFactory() { return $this->validatorFactory; } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->metadataFactory; } } PK!bhBSymfony/Component/Validator/PropertyMetadataContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A container for {@link PropertyMetadataInterface} instances. * * @author Bernhard Schussek */ interface PropertyMetadataContainerInterface { /** * Check if there's any metadata attached to the given named property. * * @param string $property The property name. * * @return Boolean */ public function hasPropertyMetadata($property); /** * Returns all metadata instances for the given named property. * * If your implementation does not support properties, simply throw an * exception in this method (for example a BadMethodCallException). * * @param string $property The property name. * * @return PropertyMetadataInterface[] A list of metadata instances. Empty if * no metadata exists for the property. */ public function getPropertyMetadata($property); } PK!Y8Symfony/Component/Validator/MetadataFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Returns {@link MetadataInterface} instances for values. * * @author Bernhard Schussek */ interface MetadataFactoryInterface { /** * Returns the metadata for the given value. * * @param mixed $value Some value. * * @return MetadataInterface The metadata for the value. * * @throws Exception\NoSuchMetadataException If no metadata exists for the value. */ public function getMetadataFor($value); /** * Returns whether metadata exists for the given value. * * @param mixed $value Some value. * * @return Boolean Whether metadata exists for the value. */ public function hasMetadataFor($value); } PK!D#??DSymfony/Component/Validator/Resources/translations/validators.en.xlfnu[ This value should be false. This value should be false. This value should be true. This value should be true. This value should be of type {{ type }}. This value should be of type {{ type }}. This value should be blank. This value should be blank. The value you selected is not a valid choice. The value you selected is not a valid choice. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. One or more of the given values is invalid. One or more of the given values is invalid. The fields {{ fields }} were not expected. The fields {{ fields }} were not expected. The fields {{ fields }} are missing. The fields {{ fields }} are missing. This value is not a valid date. This value is not a valid date. This value is not a valid datetime. This value is not a valid datetime. This value is not a valid email address. This value is not a valid email address. The file could not be found. The file could not be found. The file is not readable. The file is not readable. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. This value should be {{ limit }} or less. This value should be {{ limit }} or less. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. This value should be {{ limit }} or more. This value should be {{ limit }} or more. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. This value should not be blank. This value should not be blank. This value should not be null. This value should not be null. This value should be null. This value should be null. This value is not valid. This value is not valid. This value is not a valid time. This value is not a valid time. This value is not a valid URL. This value is not a valid URL. The two values should be equal. The two values should be equal. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. The file is too large. The file is too large. The file could not be uploaded. The file could not be uploaded. This value should be a valid number. This value should be a valid number. This file is not a valid image. This file is not a valid image. This is not a valid IP address. This is not a valid IP address. This value is not a valid language. This value is not a valid language. This value is not a valid locale. This value is not a valid locale. This value is not a valid country. This value is not a valid country. This value is already used. This value is already used. The size of the image could not be detected. The size of the image could not be detected. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. This value should be the user current password. This value should be the user current password. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. The file was only partially uploaded. The file was only partially uploaded. No file was uploaded. No file was uploaded. No temporary folder was configured in php.ini. No temporary folder was configured in php.ini. Cannot write temporary file to disk. Cannot write temporary file to disk. A PHP extension caused the upload to fail. A PHP extension caused the upload to fail. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Invalid card number. Invalid card number. Unsupported card type or invalid card number. Unsupported card type or invalid card number. This is not a valid International Bank Account Number (IBAN). This is not a valid International Bank Account Number (IBAN). This value is not a valid ISBN-10. This value is not a valid ISBN-10. This value is not a valid ISBN-13. This value is not a valid ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. This value is not a valid ISSN. This value is not a valid ISSN. This value is not a valid currency. This value is not a valid currency. This value should be equal to {{ compared_value }}. This value should be equal to {{ compared_value }}. This value should be greater than {{ compared_value }}. This value should be greater than {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. This value should be less than {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. This value should not be equal to {{ compared_value }}. This value should not be equal to {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. PK!-uCuCDSymfony/Component/Validator/Resources/translations/validators.sk.xlfnu[ This value should be false. Táto hodnota by mala byť nastavená na false. This value should be true. Táto hodnota by mala byť nastavená na true. This value should be of type {{ type }}. Táto hodnota by mala byť typu {{ type }}. This value should be blank. Táto hodnota by mala byť prázdna. The value you selected is not a valid choice. Táto hodnota by mala byť jednou z poskytnutých možností. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Mali by ste vybrať minimálne {{ limit }} možnosť.|Mali by ste vybrať minimálne {{ limit }} možnosti.|Mali by ste vybrať minimálne {{ limit }} možností. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Mali by ste vybrať najviac {{ limit }} možnosť.|Mali by ste vybrať najviac {{ limit }} možnosti.|Mali by ste vybrať najviac {{ limit }} možností. One or more of the given values is invalid. Niektoré z uvedených hodnôt sú neplatné. The fields {{ fields }} were not expected. Polia {{ fields }} neboli očakávané. The fields {{ fields }} are missing. Chýbajú polia {{ fields }} . This value is not a valid date. Tato hodnota nemá platný formát dátumu. This value is not a valid datetime. Táto hodnota nemá platný formát dátumu a času. This value is not a valid email address. Táto hodnota nie je platná emailová adresa. The file could not be found. Súbor sa nenašiel. The file is not readable. Súbor nie je čitateľný. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Súbor je príliš veľký ({{ size }} {{ suffix }}). Maximálna povolená veľkosť je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Súbor typu ({{ type }}) nie je podporovaný. Podporované typy sú {{ types }}. This value should be {{ limit }} or less. Táto hodnota by mala byť {{ limit }} alebo menej. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znak.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znaky.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znakov. This value should be {{ limit }} or more. Táto hodnota by mala byť viac ako {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znak.|Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znaky.|Táto hodnota je príliš krátka. Minimálny počet znakov je {{ limit }}. This value should not be blank. Táto hodnota by mala byť vyplnená. This value should not be null. Táto hodnota by nemala byť null. This value should be null. Táto hodnota by mala byť null. This value is not valid. Táto hodnota nie je platná. This value is not a valid time. Tato hodnota nemá správny formát času. This value is not a valid URL. Táto hodnota nie je platnou URL adresou. The two values should be equal. Tieto dve hodnoty by mali byť rovnaké. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Súbor je príliš veľký. Maximálna povolená veľkosť je {{ limit }} {{ suffix }}. The file is too large. Súbor je príliš veľký. The file could not be uploaded. Súbor sa nepodarilo nahrať. This value should be a valid number. Táto hodnota by mala byť číslo. This file is not a valid image. Tento súbor nie je obrázok. This is not a valid IP address. Toto nie je platná IP adresa. This value is not a valid language. Tento jazyk neexistuje. This value is not a valid locale. Táto lokalizácia neexistuje. This value is not a valid country. Táto krajina neexistuje. This value is already used. Táto hodnota sa už používa. The size of the image could not be detected. Nepodarilo sa zistiť rozmery obrázku. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Obrázok je príliš široký ({{ width }}px). Maximálna povolená šírka obrázku je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Obrázok je príliš úzky ({{ width }}px). Minimálna šírka obrázku by mala byť {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. >Obrázok je príliš vysoký ({{ height }}px). Maximálna povolená výška obrázku je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Obrázok je príliš nízky ({{ height }}px). Minimálna výška obrázku by mala byť {{ min_height }}px. This value should be the user current password. Táto hodnota by mala byť aktuálne heslo používateľa. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Táto hodnota by mala mať presne {{ limit }} znak.|Táto hodnota by mala mať presne {{ limit }} znaky.|Táto hodnota by mala mať presne {{ limit }} znakov. The file was only partially uploaded. Bola nahraná len časť súboru. No file was uploaded. Žiadny súbor nebol nahraný. No temporary folder was configured in php.ini. V php.ini nie je nastavená cesta k adresáru pre dočasné súbory. Cannot write temporary file to disk. Dočasný súbor sa nepodarilo zapísať na disk. A PHP extension caused the upload to fail. Rozšírenie PHP zabránilo nahraniu súboru. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Táto kolekcia by mala obsahovať aspoň {{ limit }} prvok alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvky alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvkov alebo viac. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Táto kolekcia by mala maximálne {{ limit }} prvok.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvky.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvkov. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Táto kolekcia by mala obsahovať presne {{ limit }} prvok.|Táto kolekcia by mala obsahovať presne {{ limit }} prvky.|Táto kolekcia by mala obsahovať presne {{ limit }} prvkov. Invalid card number. Neplatné číslo karty. Unsupported card type or invalid card number. Nepodporovaný typ karty alebo neplatné číslo karty. This is not a valid International Bank Account Number (IBAN). Toto je neplatný IBAN. This value is not a valid ISBN-10. Táto hodnota je neplatné ISBN-10. This value is not a valid ISBN-13. Táto hodnota je neplatné ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Táto hodnota nie je platné ISBN-10 ani ISBN-13. This value is not a valid ISSN. Táto hodnota nie je platné ISSN. This value is not a valid currency. Táto hodnota nie je platná mena. This value should be equal to {{ compared_value }}. Táto hodnota by mala byť rovná {{ compared_value }}. This value should be greater than {{ compared_value }}. Táto hodnota by mala byť väčšia ako {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Táto hodnota by mala byť väčšia alebo rovná {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Táto hodnota by mala byť typu {{ compared_value_type }} a zároveň by mala byť rovná {{ compared_value }}. This value should be less than {{ compared_value }}. Táto hodnota by mala byť menšia ako {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Táto hodnota by mala byť menšia alebo rovná {{ compared_value }}. This value should not be equal to {{ compared_value }}. Táto hodnota by nemala byť rovná {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Táto hodnota by nemala byť typu {{ compared_value_type }} a zároveň by nemala byť rovná {{ compared_value }}. PK!τ}K}KDSymfony/Component/Validator/Resources/translations/validators.uk.xlfnu[ This value should be false. Значення повинно бути Ні. This value should be true. Значення повинно бути Так. This value should be of type {{ type }}. Тип значення повинен бути {{ type }}. This value should be blank. Значення повинно бути пустим. The value you selected is not a valid choice. Обране вами значення недопустиме. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Ви повинні обрати хоча б {{ limit }} варіант.|Ви повинні обрати хоча б {{ limit }} варіанти.|Ви повинні обрати хоча б {{ limit }} варіантів. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Ви повинні обрати не більше ніж {{ limit }} варіантів. One or more of the given values is invalid. Одне або кілька заданих значень є недопустимі. The fields {{ fields }} were not expected. Поля {{ fields }} не очікувалися. The fields {{ fields }} are missing. Поля {{ fields }} відсутні. This value is not a valid date. Дане значення не є вірною датою. This value is not a valid datetime. Дане значення дати та часу недопустиме. This value is not a valid email address. Значення адреси электронної пошти недопустиме. The file could not be found. Файл не знайдено. The file is not readable. Файл не читається. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файл занадто великий ({{ size }} {{ suffix }}). Дозволений максимальний розмір {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. MIME-тип файлу недопустимий ({{ type }}). Допустимі MIME-типи файлів {{ types }}. This value should be {{ limit }} or less. Значення повинно бути {{ limit }} або менше. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Значення занадто довге. Повинно бути рівне {{ limit }} символу або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше. This value should be {{ limit }} or more. Значення повинно бути {{ limit }} або більше. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Значення занадто коротке. Повинно бути рівне {{ limit }} символу або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше. This value should not be blank. Значення не повинно бути пустим. This value should not be null. Значення не повинно бути null. This value should be null. Значення повинно бути null. This value is not valid. Значення недопустиме. This value is not a valid time. Значення часу недопустиме. This value is not a valid URL. Значення URL недопустиме. The two values should be equal. Обидва занчення повинні бути одинаковими. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файл занадто великий. Максимальний допустимий розмір {{ limit }} {{ suffix }}. The file is too large. Файл занадто великий. The file could not be uploaded. Файл не можливо завантажити. This value should be a valid number. Значення має бути допустимим числом. This file is not a valid image. Цей файл не є допустимим форматом зображення. This is not a valid IP address. Це некоректна IP адреса. This value is not a valid language. Це некоректна мова. This value is not a valid locale. Це некоректна локалізація. This value is not a valid country. Це некоректна країна. This value is already used. Це значення вже використовується. The size of the image could not be detected. Не вдалося визначити розмір зображення. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Ширина зображення занадто велика ({{ width }}px). Максимально допустима ширина {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Ширина зображення занадто мала ({{ width }}px). Мінімально допустима ширина {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Висота зображення занадто велика ({{ height }}px). Максимально допустима висота {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Висота зображення занадто мала ({{ height }}px). Мінімально допустима висота {{ min_height }}px. This value should be the user current password. Значення має бути поточним паролем користувача. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Значення повиино бути рівним {{ limit }} символу.|Значення повиино бути рівним {{ limit }} символам.|Значення повиино бути рівним {{ limit }} символам. The file was only partially uploaded. Файл був завантажений лише частково. No file was uploaded. Файл не був завантажений. No temporary folder was configured in php.ini. Не налаштована тимчасова директорія в php.ini. Cannot write temporary file to disk. Неможливо записати тимчасовий файл на диск. A PHP extension caused the upload to fail. Розширення PHP викликало помилку при завантаженні. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ця колекція повинна містити {{ limit }} елемент чи більше.|Ця колекція повинна містити {{ limit }} елемента чи більше.|Ця колекція повинна містити {{ limit }} елементів чи більше. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ця колекція повинна містити {{ limit }} елемент чи менше.|Ця колекція повинна містити {{ limit }} елемента чи менше.|Ця колекція повинна містити {{ limit }} елементов чи менше. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ця колекція повинна містити рівно {{ limit }} елемент.|Ця колекція повинна містити рівно {{ limit }} елемента.|Ця колекція повинна містити рівно {{ limit }} елементів. Invalid card number. Невірний номер карти. Unsupported card type or invalid card number. Непідтримуваний тип карти або невірний номер карти. This is not a valid International Bank Account Number (IBAN). Це не дійсний міжнародний номер банківського рахунку (IBAN). This value is not a valid ISBN-10. Значення не у форматі ISBN-10. This value is not a valid ISBN-13. Значення не у форматі ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Значення не відповідає форматам ISBN-10 та ISBN-13. This value is not a valid ISSN. Значення має невірний формат ISSN. This value is not a valid currency. Значення має невірний формат валюти. This value should be equal to {{ compared_value }}. Значення повинно дорівнювати {{ compared_value }}. This value should be greater than {{ compared_value }}. Значення має бути більше ніж {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Значення має бути більше або дорівнювати {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Значення має бути ідентичним {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Значення повинно бути менше ніж {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Значення повинно бути менше або дорівнювати {{ compared_value }}. This value should not be equal to {{ compared_value }}. Значення не повинно дорівнювати {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Значення не повинно бути ідентичним {{ compared_value_type }} {{ compared_value }}. PK!-11DSymfony/Component/Validator/Resources/translations/validators.cy.xlfnu[ This value should be false. Dylid bod y gwerth hwn yn ffug. This value should be true. Dylid bod y gwerth hwn yn wir. This value should be of type {{ type }}. Dylid bod y gwerth hwn bod o fath {{ type }}. This value should be blank. Dylid bod y gwerth hwn yn wag. The value you selected is not a valid choice. Nid yw'r gwerth â ddewiswyd yn ddilys. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Rhaid dewis o leiaf {{ limit }} opsiwn. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Rhaid dewis dim mwy na {{ limit }} opsiwn. One or more of the given values is invalid. Mae un neu fwy o'r gwerthoedd a roddwyd yn annilys. The fields {{ fields }} were not expected. Roedd y maesydd {{ fields }} yn anisgwyl. The fields {{ fields }} are missing. Roedd y maesydd {{ fields }} ar goll. This value is not a valid date. Nid yw'r gwerth yn ddyddiad dilys. This value is not a valid datetime. Nid yw'r gwerth yn datetime dilys. This value is not a valid email address. Nid yw'r gwerth yn gyfeiriad ebost dilys. The file could not be found. Ni ddarganfyddwyd y ffeil. The file is not readable. Ni ellir darllen y ffeil. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Mae'r ffeil yn rhy fawr ({{ size }} {{ suffix }}). Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Nid yw math mime y ffeil yn ddilys ({{ type }}). Dyma'r mathau â ganiateir {{ types }}. This value should be {{ limit }} or less. Dylai'r gwerth hwn fod yn {{ limit }} neu lai. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Mae'r gwerth hwn rhy hir. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu lai. This value should be {{ limit }} or more. Dylai'r gwerth hwn fod yn {{ limit }} neu fwy. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Mae'r gwerth hwn yn rhy fyr. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu fwy. This value should not be blank. Ni ddylai'r gwerth hwn fod yn wag. This value should not be null. Ni ddylai'r gwerth hwn fod yn null. This value should be null. Dylai'r gwerth fod yn null. This value is not valid. Nid yw'r gwerth hwn yn ddilys. This value is not a valid time. Nid yw'r gwerth hwn yn amser dilys. This value is not a valid URL. Nid yw'r gwerth hwn yn URL dilys. The two values should be equal. Rhaid i'r ddau werth fod yn gyfystyr a'u gilydd. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Mae'r ffeil yn rhy fawr. Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}. The file is too large. Mae'r ffeil yn rhy fawr. The file could not be uploaded. Methwyd ag uwchlwytho'r ffeil. This value should be a valid number. Dylai'r gwerth hwn fod yn rif dilys. This file is not a valid image. Nid yw'r ffeil hon yn ddelwedd dilys. This is not a valid IP address. Nid yw hwn yn gyfeiriad IP dilys. This value is not a valid language. Nid yw'r gwerth hwn yn iaith ddilys. This value is not a valid locale. Nid yw'r gwerth hwn yn locale dilys. This value is not a valid country. Nid yw'r gwerth hwn yn wlad dilys. This value is already used. Mae'r gwerth hwn eisoes yn cael ei ddefnyddio. The size of the image could not be detected. Methwyd â darganfod maint y ddelwedd. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Mae lled y ddelwedd yn rhy fawr ({{ width }}px). Y lled mwyaf â ganiateir yw {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Mae lled y ddelwedd yn rhy fach ({{ width }}px). Y lled lleiaf â ganiateir yw {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Mae uchder y ddelwedd yn rhy fawr ({{ width }}px). Yr uchder mwyaf â ganiateir yw {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Mae uchder y ddelwedd yn rhy fach ({{ width }}px). Yr uchder lleiaf â ganiateir yw {{ min_height }}px. This value should be the user current password. Dylaid bod y gwerth hwn yn gyfrinair presenol y defnyddiwr. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Dylai'r gwerth hwn fod yn union {{ limit }} nodyn cyfrifiadurol o hyd. The file was only partially uploaded. Dim ond rhan o'r ffeil ag uwchlwythwyd. No file was uploaded. Ni uwchlwythwyd unrhyw ffeil. No temporary folder was configured in php.ini. Nid oes ffolder dros-dro wedi'i gosod yn php.ini. Cannot write temporary file to disk. Methwyd ag ysgrifennu'r ffeil dros-dro ar ddisg. A PHP extension caused the upload to fail. Methwyd ag uwchlwytho oherwydd ategyn PHP. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu fwy. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu lai. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Dylai'r casgliad hwn gynnwys union {{ limit }} elfen. Invalid card number. Nid oedd rhif y cerdyn yn ddilys. Unsupported card type or invalid card number. Unai ni dderbynir y math yna o gerdyn, neu nid yw rhif y cerdyn yn ddilys. PK!mwBBDSymfony/Component/Validator/Resources/translations/validators.pl.xlfnu[ This value should be false. Ta wartość powinna być fałszem. This value should be true. Ta wartość powinna być prawdą. This value should be of type {{ type }}. Ta wartość powinna być typu {{ type }}. This value should be blank. Ta wartość powinna być pusta. The value you selected is not a valid choice. Ta wartość powinna być jedną z podanych opcji. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Powinieneś wybrać co najmniej {{ limit }} opcję.|Powinieneś wybrać co najmniej {{ limit }} opcje.|Powinieneś wybrać co najmniej {{ limit }} opcji. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Powinieneś wybrać maksymalnie {{ limit }} opcję.|Powinieneś wybrać maksymalnie {{ limit }} opcje.|Powinieneś wybrać maksymalnie {{ limit }} opcji. One or more of the given values is invalid. Jedna lub więcej z podanych wartości jest nieprawidłowa. The fields {{ fields }} were not expected. Pola {{ fields }} nie były oczekiwane. The fields {{ fields }} are missing. Brakuje pól {{ fields }}. This value is not a valid date. Ta wartość nie jest prawidłową datą. This value is not a valid datetime. Ta wartość nie jest prawidłową datą i czasem. This value is not a valid email address. Ta wartość nie jest prawidłowym adresem email. The file could not be found. Plik nie mógł zostać odnaleziony. The file is not readable. Nie można odczytać pliku. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Plik jest za duży ({{ size }} {{ suffix }}). Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Nieprawidłowy typ mime pliku ({{ type }}). Dozwolone typy mime to {{ types }}. This value should be {{ limit }} or less. Ta wartość powinna wynosić {{ limit }} lub mniej. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków. This value should be {{ limit }} or more. Ta wartość powinna wynosić {{ limit }} lub więcej. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków. This value should not be blank. Ta wartość nie powinna być pusta. This value should not be null. Ta wartość nie powinna być nullem. This value should be null. Ta wartość powinna być nullem. This value is not valid. Ta wartość jest nieprawidłowa. This value is not a valid time. Ta wartość nie jest prawidłowym czasem. This value is not a valid URL. Ta wartość nie jest prawidłowym adresem URL. The two values should be equal. Obie wartości powinny być równe. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Plik jest za duży. Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}. The file is too large. Plik jest za duży. The file could not be uploaded. Plik nie mógł być wgrany. This value should be a valid number. Ta wartość powinna być prawidłową liczbą. This file is not a valid image. Ten plik nie jest obrazem. This is not a valid IP address. To nie jest prawidłowy adres IP. This value is not a valid language. Ta wartość nie jest prawidłowym językiem. This value is not a valid locale. Ta wartość nie jest prawidłową lokalizacją. This value is not a valid country. Ta wartość nie jest prawidłową nazwą kraju. This value is already used. Ta wartość jest już wykorzystywana. The size of the image could not be detected. Nie można wykryć rozmiaru obrazka. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Szerokość obrazka jest zbyt duża ({{ width }}px). Maksymalna dopuszczalna szerokość to {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Szerokość obrazka jest zbyt mała ({{ width }}px). Oczekiwana minimalna szerokość to {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Wysokość obrazka jest zbyt duża ({{ height }}px). Maksymalna dopuszczalna wysokość to {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Wysokość obrazka jest zbyt mała ({{ height }}px). Oczekiwana minimalna wysokość to {{ min_height }}px. This value should be the user current password. Ta wartość powinna być aktualnym hasłem użytkownika. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ta wartość powinna mieć dokładnie {{ limit }} znak.|Ta wartość powinna mieć dokładnie {{ limit }} znaki.|Ta wartość powinna mieć dokładnie {{ limit }} znaków. The file was only partially uploaded. Plik został wgrany tylko częściowo. No file was uploaded. Żaden plik nie został wgrany. No temporary folder was configured in php.ini. Nie skonfigurowano folderu tymczasowego w php.ini. Cannot write temporary file to disk. Nie można zapisać pliku tymczasowego na dysku. A PHP extension caused the upload to fail. Rozszerzenie PHP spowodowało błąd podczas wgrywania. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ten zbiór powinien zawierać {{ limit }} lub więcej elementów. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ten zbiór powinien zawierać {{ limit }} lub mniej elementów. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ten zbiór powinien zawierać dokładnie {{ limit }} element.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementy.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementów. Invalid card number. Nieprawidłowy numer karty. Unsupported card type or invalid card number. Nieobsługiwany rodzaj karty lub nieprawidłowy numer karty. This is not a valid International Bank Account Number (IBAN). Nieprawidłowy międzynarodowy numer rachunku bankowego (IBAN). This value is not a valid ISBN-10. Ta wartość nie jest prawidłowym numerem ISBN-10. This value is not a valid ISBN-13. Ta wartość nie jest prawidłowym numerem ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ta wartość nie jest prawidłowym numerem ISBN-10 ani ISBN-13. This value is not a valid ISSN. Ta wartość nie jest prawidłowym numerem ISSN. This value is not a valid currency. Ta wartość nie jest prawidłową walutą. This value should be equal to {{ compared_value }}. Ta wartość powinna być równa {{ compared_value }}. This value should be greater than {{ compared_value }}. Ta wartość powinna być większa niż {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ta wartość powinna być większa bądź równa {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ta wartość powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}. This value should be less than {{ compared_value }}. Ta wartość powinna być mniejsza niż {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ta wartość powinna być mniejsza bądź równa {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ta wartość nie powinna być równa {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ta wartość nie powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}. PK!@T\44DSymfony/Component/Validator/Resources/translations/validators.af.xlfnu[ This value should be false. Hierdie waarde moet vals wees. This value should be true. Hierdie waarde moet waar wees. This value should be of type {{ type }}. Hierdie waarde moet van die soort {{type}} wees. This value should be blank. Hierdie waarde moet leeg wees. The value you selected is not a valid choice. Die waarde wat jy gekies het is nie 'n geldige keuse nie. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Jy moet ten minste {{ limit }} kies.|Jy moet ten minste {{ limit }} keuses kies. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Jy moet by die meeste {{ limit }} keuse kies.|Jy moet by die meeste {{ limit }} keuses kies. One or more of the given values is invalid. Een of meer van die gegewe waardes is ongeldig. The fields {{ fields }} were not expected. Die velde {{ fields }} is nie verwag nie. The fields {{ fields }} are missing. Die velde {{ fields }} ontbreek. This value is not a valid date. Hierdie waarde is nie 'n geldige datum nie. This value is not a valid datetime. Hierdie waarde is nie 'n geldige datum en tyd nie. This value is not a valid email address. Hierdie waarde is nie 'n geldige e-pos adres nie. The file could not be found. Die lêer kon nie gevind word nie. The file is not readable. Die lêer kan nie gelees word nie. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Die lêer is te groot ({{ size }} {{ suffix }}). Toegelaat maksimum grootte is {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Die MIME-tipe van die lêer is ongeldig ({{ type }}). Toegelaat MIME-tipes is {{ types }}. This value should be {{ limit }} or less. Hierdie waarde moet {{ limit }} of minder wees. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Hierdie waarde is te lank. Dit moet {{ limit }} karakter of minder wees.|Hierdie waarde is te lank. Dit moet {{ limit }} karakters of minder wees. This value should be {{ limit }} or more. Hierdie waarde moet {{ limit }} of meer wees. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Hierdie waarde is te kort. Dit moet {{ limit }} karakter of meer wees.|Hierdie waarde is te kort. Dit moet {{ limit }} karakters of meer wees. This value should not be blank. Hierdie waarde moet nie leeg wees nie. This value should not be null. Hierdie waarde moet nie nul wees nie. This value should be null. Hierdie waarde moet nul wees. This value is not valid. Hierdie waarde is nie geldig nie. This value is not a valid time. Hierdie waarde is nie 'n geldige tyd nie. This value is not a valid URL. Hierdie waarde is nie 'n geldige URL nie. The two values should be equal. Die twee waardes moet gelyk wees. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Die lêer is te groot. Toegelaat maksimum grootte is {{ limit }} {{ suffix }}. The file is too large. Die lêer is te groot. The file could not be uploaded. Die lêer kan nie opgelaai word nie. This value should be a valid number. Hierdie waarde moet 'n geldige nommer wees. This file is not a valid image. Hierdie lêer is nie 'n geldige beeld nie. This is not a valid IP address. Hierdie is nie 'n geldige IP-adres nie. This value is not a valid language. Hierdie waarde is nie 'n geldige taal nie. This value is not a valid locale. Hierdie waarde is nie 'n geldige land instelling nie. This value is not a valid country. Hierdie waarde is nie 'n geldige land nie. This value is already used. Hierdie waarde word reeds gebruik. The size of the image could not be detected. Die grootte van die beeld kon nie opgespoor word nie. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Die beeld breedte is te groot ({{ width }}px). Toegelaat maksimum breedte is {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Die beeld breedte is te klein ({{ width }}px). Minimum breedte verwag is {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Die beeld hoogte is te groot ({{ height }}px). Toegelaat maksimum hoogte is {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Die beeld hoogte is te klein ({{ height }}px). Minimum hoogte verwag is {{ min_height }}px. This value should be the user current password. Hierdie waarde moet die huidige wagwoord van die gebruiker wees. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Hierdie waarde moet presies {{ limit }} karakter wees.|Hierdie waarde moet presies {{ limit }} karakters wees. The file was only partially uploaded. Die lêer is slegs gedeeltelik opgelaai. No file was uploaded. Geen lêer is opgelaai nie. No temporary folder was configured in php.ini. Geen tydelike lêer is ingestel in php.ini nie. Cannot write temporary file to disk. Kan nie tydelike lêer skryf op skyf nie. A PHP extension caused the upload to fail. 'n PHP-uitbreiding veroorsaak die oplaai van die lêer om te misluk. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Hierdie versameling moet {{ limit }} element of meer bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Hierdie versameling moet {{ limit }} element of minder bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Hierdie versameling moet presies {{ limit }} element bevat.|Hierdie versameling moet presies {{ limit }} elemente bevat. Invalid card number. Ongeldige kredietkaart nommer. Unsupported card type or invalid card number. Nie-ondersteunde tipe kaart of ongeldige kredietkaart nommer. PK!b@@DSymfony/Component/Validator/Resources/translations/validators.pt.xlfnu[ This value should be false. Este valor deveria ser falso. This value should be true. Este valor deveria ser verdadeiro. This value should be of type {{ type }}. Este valor deveria ser do tipo {{ type }}. This value should be blank. Este valor deveria ser vazio. The value you selected is not a valid choice. O valor selecionado não é uma opção válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Você deveria selecionar {{ limit }} opção no mínimo.|Você deveria selecionar {{ limit }} opções no mínimo. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Você deve selecionar, no máximo {{ limit }} opção.|Você deve selecionar, no máximo {{ limit }} opções. One or more of the given values is invalid. Um ou mais dos valores introduzidos não são válidos. The fields {{ fields }} were not expected. Os campos {{ fields }} não eram esperados. The fields {{ fields }} are missing. Os campos {{ fields }} estão ausentes. This value is not a valid date. Este valor não é uma data válida. This value is not a valid datetime. Este valor não é uma data-hora válida. This value is not a valid email address. Este valor não é um endereço de e-mail válido. The file could not be found. O arquivo não pôde ser encontrado. The file is not readable. O arquivo não pôde ser lido. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é de {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}. This value should be {{ limit }} or less. Este valor deveria ser {{ limit }} ou menor. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. O valor é muito longo. Deveria ter {{ limit }} caracteres ou menos. This value should be {{ limit }} or more. Este valor deveria ser {{ limit }} ou mais. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. O valor é muito curto. Deveria de ter {{ limit }} caractere ou mais.|O valor é muito curto. Deveria de ter {{ limit }} caracteres ou mais. This value should not be blank. Este valor não deveria ser branco/vazio. This value should not be null. Este valor não deveria ser nulo. This value should be null. Este valor deveria ser nulo. This value is not valid. Este valor não é válido. This value is not a valid time. Este valor não é uma hora válida. This value is not a valid URL. Este valor não é um URL válido. The two values should be equal. Os dois valores deveriam ser iguais. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}. The file is too large. O ficheiro é muito grande. The file could not be uploaded. Não foi possível carregar o ficheiro. This value should be a valid number. Este valor deveria de ser um número válido. This file is not a valid image. Este ficheiro não é uma imagem. This is not a valid IP address. Este endereço de IP não é válido. This value is not a valid language. Este valor não é uma linguagem válida. This value is not a valid locale. Este valor não é um 'locale' válido. This value is not a valid country. Este valor não é um País válido. This value is already used. Este valor já está a ser usado. The size of the image could not be detected. O tamanho da imagem não foi detetado. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A largura da imagem ({{ width }}px) é muito grande. A largura máxima da imagem é: {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A largura da imagem ({{ width }}px) é muito pequena. A largura miníma da imagem é de: {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A altura da imagem ({{ height }}px) é muito grande. A altura máxima da imagem é de: {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A altura da imagem ({{ height }}px) é muito pequena. A altura miníma da imagem é de: {{ min_height }}px. This value should be the user current password. Este valor deveria de ser a password atual do utilizador. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor tem de ter exatamente {{ limit }} carateres. The file was only partially uploaded. Só foi enviado parte do ficheiro. No file was uploaded. Nenhum ficheiro foi enviado. No temporary folder was configured in php.ini. Não existe nenhum directório temporária configurado no ficheiro php.ini. Cannot write temporary file to disk. Não foi possível escrever ficheiros temporários no disco. A PHP extension caused the upload to fail. Uma extensão PHP causou a falha no envio. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos. Invalid card number. Número de cartão inválido. Unsupported card type or invalid card number. Tipo de cartão não suportado ou número de cartão inválido. This is not a valid International Bank Account Number (IBAN). Este não é um Número Internacional de Conta Bancária (IBAN) válido. This value is not a valid ISBN-10. Este valor não é um ISBN-10 válido. This value is not a valid ISBN-13. Este valor não é um ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor não é um ISBN-10 ou ISBN-13 válido. This value is not a valid ISSN. Este valor não é um ISSN válido. This value is not a valid currency. Este não é um valor monetário válido. This value should be equal to {{ compared_value }}. Este valor deve ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor deve ser superior a {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor deve ser igual ou superior a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor deve ser inferior a {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor deve ser igual ou inferior a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor não deve ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. PK!e]߭AAISymfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlfnu[ This value should be false. Вредност треба да буде нетачна. This value should be true. Вредност треба да буде тачна. This value should be of type {{ type }}. Вредност треба да буде типа {{ type }}. This value should be blank. Вредност треба да буде празна. The value you selected is not a valid choice. Вредност треба да буде једна од понуђених. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Изаберите бар {{ limit }} могућност.|Изаберите бар {{ limit }} могућности.|Изаберите бар {{ limit }} могућности. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Изаберите највише {{ limit }} могућност.|Изаберите највише {{ limit }} могућности.|Изаберите највише {{ limit }} могућности. One or more of the given values is invalid. Једна или више вредности је невалидна. The fields {{ fields }} were not expected. Поља {{ fields }} нису била очекивана. The fields {{ fields }} are missing. Поља {{ fields }} недостају. This value is not a valid date. Вредност није валидан датум. This value is not a valid datetime. Вредност није валидан датум-време. This value is not a valid email address. Вредност није валидна адреса електронске поште. The file could not be found. Датотека не може бити пронађена. The file is not readable. Датотека није читљива. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Датотека је превелика ({{ size }} {{ suffix }}). Највећа дозвољена величина је {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Миме тип датотеке није валидан ({{ type }}). Дозвољени миме типови су {{ types }}. This value should be {{ limit }} or less. Вредност треба да буде {{ limit }} или мање. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Вредност је предугачка. Треба да има {{ limit }} карактер или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање. This value should be {{ limit }} or more. Вредност треба да буде {{ limit }} или више. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Вредност је прекратка. Треба да има {{ limit }} карактер или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више. This value should not be blank. Вредност не треба да буде празна. This value should not be null. Вредност не треба да буде null. This value should be null. Вредност треба да буде null. This value is not valid. Вредност је невалидна. This value is not a valid time. Вредност није валидно време. This value is not a valid URL. Вредност није валидан URL. The two values should be equal. Обе вредности треба да буду једнаке. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Датотека је превелика. Највећа дозвољена величина је {{ limit }} {{ suffix }}. The file is too large. Датотека је превелика. The file could not be uploaded. Датотека не може бити отпремљена. This value should be a valid number. Вредност треба да буде валидан број. This file is not a valid image. Ова датотека није валидна слика. This is not a valid IP address. Ово није валидна ИП адреса. This value is not a valid language. Вредност није валидан језик. This value is not a valid locale. Вредност није валидан локал. This value is not a valid country. Вредност није валидна земља. This value is already used. Вредност је већ искоришћена. The size of the image could not be detected. Величина слике не може бити одређена. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Ширина слике је превелика ({{ width }}px). Најећа дозвољена ширина је {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Ширина слике је премала ({{ width }}px). Најмања дозвољена ширина је {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Висина слике је превелика ({{ height }}px). Најећа дозвољена висина је {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Висина слике је премала ({{ height }}px). Најмања дозвољена висина је {{ min_height }}px. This value should be the user current password. Вредност треба да буде тренутна корисничка лозинка. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Вредност треба да има тачно {{ limit }} карактер.|Вредност треба да има тачно {{ limit }} карактера.|Вредност треба да има тачно {{ limit }} карактера. The file was only partially uploaded. Датотека је само парцијално отпремљена. No file was uploaded. Датотека није отпремљена. No temporary folder was configured in php.ini. Привремени директоријум није конфигурисан у php.ini. Cannot write temporary file to disk. Немогуће писање привремене датотеке на диск. A PHP extension caused the upload to fail. PHP екстензија је проузроковала неуспех отпремања датотеке. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ова колекција треба да садржи тачно {{ limit }} елемент.|Ова колекција треба да садржи тачно {{ limit }} елемента.|Ова колекција треба да садржи тачно {{ limit }} елемената. Invalid card number. Невалидан број картице. Unsupported card type or invalid card number. Невалидан број картице или тип картице није подржан. This is not a valid International Bank Account Number (IBAN). Ово није валидан међународни број банковног рачуна (IBAN). This value is not a valid ISBN-10. Ово није валидан ISBN-10. This value is not a valid ISBN-13. Ово није валидан ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ово није валидан ISBN-10 или ISBN-13. This value is not a valid ISSN. Ово није валидан ISSN. PK!a22DSymfony/Component/Validator/Resources/translations/validators.fi.xlfnu[ This value should be false. Arvon tulee olla epätosi. This value should be true. Arvon tulee olla tosi. This value should be of type {{ type }}. Arvon tulee olla tyyppiä {{ type }}. This value should be blank. Arvon tulee olla tyhjä. The value you selected is not a valid choice. Arvon tulee olla yksi annetuista vaihtoehdoista. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Sinun tulee valita vähintään {{ limit }} vaihtoehtoa. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Sinun tulee valitan enintään {{ limit }} vaihtoehtoa. One or more of the given values is invalid. Yksi tai useampi annetuista arvoista on virheellinen. The fields {{ fields }} were not expected. Odottamattomia kenttiä {{ fields }}. The fields {{ fields }} are missing. Kentät {{ fields }} puuttuvat. This value is not a valid date. Annettu arvo ei ole kelvollinen päivämäärä. This value is not a valid datetime. Annettu arvo ei ole kelvollinen päivämäärä ja kellonaika. This value is not a valid email address. Annettu arvo ei ole kelvollinen sähköpostiosoite. The file could not be found. Tiedostoa ei löydy. The file is not readable. Tiedostoa ei voida lukea. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Tiedostonkoko ({{ size }} {{ suffix }}) on liian iso. Suurin sallittu tiedostonkoko on {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Tiedostotyyppi ({{ type }}) on virheellinen. Sallittuja tiedostotyyppejä ovat {{ types }}. This value should be {{ limit }} or less. Arvon tulee olla {{ limit }} tai vähemmän. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Liian pitkä syöte. Syöte saa olla enintään {{ limit }} merkkiä. This value should be {{ limit }} or more. Arvon tulee olla {{ limit }} tai enemmän. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Liian lyhyt syöte. Syötteen tulee olla vähintään {{ limit }} merkkiä. This value should not be blank. Kenttä ei voi olla tyhjä. This value should not be null. Syöte ei voi olla null. This value should be null. Syötteen tulee olla null. This value is not valid. Virheellinen arvo. This value is not a valid time. Annettu arvo ei ole kelvollinen kellonaika. This value is not a valid URL. Annettu arvo ei ole kelvollinen URL-osoite. The two values should be equal. Kahden annetun arvon tulee olla samat. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Annettu tiedosto on liian iso. Suurin sallittu tiedostokoko on {{ limit }} {{ suffix }}. The file is too large. Tiedosto on liian iso. The file could not be uploaded. Tiedoston siirto epäonnistui. This value should be a valid number. Tämän arvon tulee olla numero. This file is not a valid image. Tämä tiedosto ei ole kelvollinen kuva. This is not a valid IP address. Tämä ei ole kelvollinen IP-osoite. This value is not a valid language. Tämä arvo ei ole kelvollinen kieli. This value is not a valid locale. Tämä arvo ei ole kelvollinen kieli- ja alueasetus (locale). This value is not a valid country. Tämä arvo ei ole kelvollinen maa. This value is already used. Tämä arvo on jo käytetty. The size of the image could not be detected. Kuvan kokoa ei voitu tunnistaa. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Kuva on liian leveä ({{ width }}px). Sallittu maksimileveys on {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Kuva on liian kapea ({{ width }}px). Leveyden tulisi olla vähintään {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Kuva on liian korkea ({{ width }}px). Sallittu maksimikorkeus on {{ max_width }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Kuva on liian matala ({{ height }}px). Korkeuden tulisi olla vähintään {{ min_height }}px. This value should be the user current password. Tämän arvon tulisi olla käyttäjän tämänhetkinen salasana. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Tämän arvon tulisi olla tasan yhden merkin pituinen.|Tämän arvon tulisi olla tasan {{ limit }} merkkiä pitkä. The file was only partially uploaded. Tiedosto ladattiin vain osittain. No file was uploaded. Tiedostoa ei ladattu. No temporary folder was configured in php.ini. Väliaikaishakemistoa ei ole asetettu php.ini -tiedostoon. Cannot write temporary file to disk. Väliaikaistiedostoa ei voitu kirjoittaa levylle. A PHP extension caused the upload to fail. PHP-laajennoksen vuoksi tiedoston lataus epäonnistui. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Tässä ryhmässä tulisi olla yksi tai useampi elementti.|Tässä ryhmässä tulisi olla vähintään {{ limit }} elementtiä. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Tässä ryhmässä tulisi olla enintään yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Tässä ryhmässä tulisi olla tasan yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä. Invalid card number. Virheellinen korttinumero. Unsupported card type or invalid card number. Tätä korttityyppiä ei tueta tai korttinumero on virheellinen. PK!"}2A2ADSymfony/Component/Validator/Resources/translations/validators.es.xlfnu[ This value should be false. Este valor debería ser falso. This value should be true. Este valor debería ser verdadero. This value should be of type {{ type }}. Este valor debería ser de tipo {{ type }}. This value should be blank. Este valor debería estar vacío. The value you selected is not a valid choice. El valor seleccionado no es una opción válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Debe seleccionar al menos {{ limit }} opción.|Debe seleccionar al menos {{ limit }} opciones. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opciones. One or more of the given values is invalid. Uno o más de los valores indicados no son válidos. The fields {{ fields }} were not expected. No se esperaban los campos {{ fields }}. The fields {{ fields }} are missing. Faltan los campos {{ fields }}. This value is not a valid date. Este valor no es una fecha válida. This value is not a valid datetime. Este valor no es una fecha y hora válidas. This value is not a valid email address. Este valor no es una dirección de email válida. The file could not be found. No se pudo encontrar el archivo. The file is not readable. No se puede leer el archivo. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. El archivo es demasiado grande ({{ size }} {{ suffix }}). El tamaño máximo permitido es {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. El tipo mime del archivo no es válido ({{ type }}). Los tipos mime válidos son {{ types }}. This value should be {{ limit }} or less. Este valor debería ser {{ limit }} o menos. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Este valor es demasiado largo. Debería tener {{ limit }} carácter o menos.|Este valor es demasiado largo. Debería tener {{ limit }} caracteres o menos. This value should be {{ limit }} or more. Este valor debería ser {{ limit }} o más. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Este valor es demasiado corto. Debería tener {{ limit }} carácter o más.|Este valor es demasiado corto. Debería tener {{ limit }} caracteres o más. This value should not be blank. Este valor no debería estar vacío. This value should not be null. Este valor no debería ser nulo. This value should be null. Este valor debería ser nulo. This value is not valid. Este valor no es válido. This value is not a valid time. Este valor no es una hora válida. This value is not a valid URL. Este valor no es una URL válida. The two values should be equal. Los dos valores deberían ser iguales. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. El archivo es demasiado grande. El tamaño máximo permitido es {{ limit }} {{ suffix }}. The file is too large. El archivo es demasiado grande. The file could not be uploaded. No se pudo subir el archivo. This value should be a valid number. Este valor debería ser un número válido. This file is not a valid image. El archivo no es una imagen válida. This is not a valid IP address. Esto no es una dirección IP válida. This value is not a valid language. Este valor no es un idioma válido. This value is not a valid locale. Este valor no es una localización válida. This value is not a valid country. Este valor no es un país válido. This value is already used. Este valor ya se ha utilizado. The size of the image could not be detected. No se pudo determinar el tamaño de la imagen. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. La anchura de la imagen es demasiado grande ({{ width }}px). La anchura máxima permitida son {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. La anchura de la imagen es demasiado pequeña ({{ width }}px). La anchura mínima requerida son {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. La altura de la imagen es demasiado grande ({{ height }}px). La altura máxima permitida son {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. La altura de la imagen es demasiado pequeña ({{ height }}px). La altura mínima requerida son {{ min_height }}px. This value should be the user current password. Este valor debería ser la contraseña actual del usuario. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor debería tener exactamente {{ limit }} carácter.|Este valor debería tener exactamente {{ limit }} caracteres. The file was only partially uploaded. El archivo fue sólo subido parcialmente. No file was uploaded. Ningún archivo fue subido. No temporary folder was configured in php.ini. Ninguna carpeta temporal fue configurada en php.ini. Cannot write temporary file to disk. No se pudo escribir el archivo temporal en el disco. A PHP extension caused the upload to fail. Una extensión de PHP hizo que la subida fallara. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta colección debe contener {{ limit }} elemento o más.|Esta colección debe contener {{ limit }} elementos o más. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta colección debe contener {{ limit }} elemento o menos.|Esta colección debe contener {{ limit }} elementos o menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta colección debe contener exactamente {{ limit }} elemento.|Esta colección debe contener exactamente {{ limit }} elementos. Invalid card number. Número de tarjeta inválido. Unsupported card type or invalid card number. Tipo de tarjeta no soportado o número de tarjeta inválido. This is not a valid International Bank Account Number (IBAN). Esto no es un International Bank Account Number (IBAN) válido. This value is not a valid ISBN-10. Este valor no es un ISBN-10 válido. This value is not a valid ISBN-13. Este valor no es un ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor no es ni un ISBN-10 válido ni un ISBN-13 válido. This value is not a valid ISSN. Este valor no es un ISSN válido. This value is not a valid currency. Este valor no es una divisa válida. This value should be equal to {{ compared_value }}. Este valor debería ser igual que {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor debería ser mayor que {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor debería ser mayor o igual que {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor debería ser idéntico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor debería ser menor que {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor debería ser menor o igual que {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor debería ser distinto de {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor no debería ser idéntico a {{ compared_value_type }} {{ compared_value }}. PK!sE#AADSymfony/Component/Validator/Resources/translations/validators.de.xlfnu[ This value should be false. Dieser Wert sollte false sein. This value should be true. Dieser Wert sollte true sein. This value should be of type {{ type }}. Dieser Wert sollte vom Typ {{ type }} sein. This value should be blank. Dieser Wert sollte leer sein. The value you selected is not a valid choice. Sie haben einen ungültigen Wert ausgewählt. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Sie dürfen höchstens {{ limit }} Möglichkeit wählen.|Sie dürfen höchstens {{ limit }} Möglichkeiten wählen. One or more of the given values is invalid. Einer oder mehrere der angegebenen Werte sind ungültig. The fields {{ fields }} were not expected. Die Felder {{ fields }} wurden nicht erwartet. The fields {{ fields }} are missing. Die erwarteten Felder {{ fields }} fehlen. This value is not a valid date. Dieser Wert entspricht keiner gültigen Datumsangabe. This value is not a valid datetime. Dieser Wert entspricht keiner gültigen Datums- und Zeitangabe. This value is not a valid email address. Dieser Wert ist keine gültige E-Mail-Adresse. The file could not be found. Die Datei wurde nicht gefunden. The file is not readable. Die Datei ist nicht lesbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Die Datei ist zu groß ({{ size }} {{ suffix }}). Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Der Dateityp ist ungültig ({{ type }}). Erlaubte Dateitypen sind {{ types }}. This value should be {{ limit }} or less. Dieser Wert sollte kleiner oder gleich {{ limit }} sein. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben. This value should be {{ limit }} or more. Dieser Wert sollte größer oder gleich {{ limit }} sein. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben. This value should not be blank. Dieser Wert sollte nicht leer sein. This value should not be null. Dieser Wert sollte nicht null sein. This value should be null. Dieser Wert sollte null sein. This value is not valid. Dieser Wert ist nicht gültig. This value is not a valid time. Dieser Wert entspricht keiner gültigen Zeitangabe. This value is not a valid URL. Dieser Wert ist keine gültige URL. The two values should be equal. Die beiden Werte sollten identisch sein. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Die Datei ist zu groß. Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}. The file is too large. Die Datei ist zu groß. The file could not be uploaded. Die Datei konnte nicht hochgeladen werden. This value should be a valid number. Dieser Wert sollte eine gültige Zahl sein. This file is not a valid image. Diese Datei ist kein gültiges Bild. This is not a valid IP address. Dies ist keine gültige IP-Adresse. This value is not a valid language. Dieser Wert entspricht keiner gültigen Sprache. This value is not a valid locale. Dieser Wert entspricht keinem gültigen Gebietsschema. This value is not a valid country. Dieser Wert entspricht keinem gültigen Land. This value is already used. Dieser Wert wird bereits verwendet. The size of the image could not be detected. Die Größe des Bildes konnte nicht ermittelt werden. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Die Bildbreite ist zu groß ({{ width }}px). Die maximal zulässige Breite beträgt {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Die Bildbreite ist zu gering ({{ width }}px). Die erwartete Mindestbreite beträgt {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Die Bildhöhe ist zu groß ({{ height }}px). Die maximal zulässige Höhe beträgt {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Die Bildhöhe ist zu gering ({{ height }}px). Die erwartete Mindesthöhe beträgt {{ min_height }}px. This value should be the user current password. Dieser Wert sollte dem aktuellen Benutzerpasswort entsprechen. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Dieser Wert sollte genau {{ limit }} Zeichen lang sein.|Dieser Wert sollte genau {{ limit }} Zeichen lang sein. The file was only partially uploaded. Die Datei wurde nur teilweise hochgeladen. No file was uploaded. Es wurde keine Datei hochgeladen. No temporary folder was configured in php.ini. Es wurde kein temporärer Ordner in der php.ini konfiguriert. Cannot write temporary file to disk. Kann die temporäre Datei nicht speichern. A PHP extension caused the upload to fail. Eine PHP-Erweiterung verhinderte den Upload. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Diese Sammlung sollte genau {{ limit }} Element beinhalten.|Diese Sammlung sollte genau {{ limit }} Elemente beinhalten. Invalid card number. Ungültige Kartennummer. Unsupported card type or invalid card number. Nicht unterstützer Kartentyp oder ungültige Kartennummer. This is not a valid International Bank Account Number (IBAN). Dieser Wert ist keine gültige IBAN-Kontonummer. This value is not a valid ISBN-10. Dieser Wert entspricht keiner gültigen ISBN-10. This value is not a valid ISBN-13. Dieser Wert entspricht keiner gültigen ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Dieser Wert ist weder eine gültige ISBN-10 noch eine gültige ISBN-13. This value is not a valid ISSN. Dieser Wert ist keine gültige ISSN. This value is not a valid currency. Dieser Wert ist keine gültige Währung. This value should be equal to {{ compared_value }}. Dieser Wert sollte gleich {{ compared_value }} sein. This value should be greater than {{ compared_value }}. Dieser Wert sollte größer als {{ compared_value }} sein. This value should be greater than or equal to {{ compared_value }}. Dieser Wert sollte größer oder gleich {{ compared_value }} sein. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Dieser Wert sollte identisch sein mit {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Dieser Wert sollte kleiner als {{ compared_value }} sein. This value should be less than or equal to {{ compared_value }}. Dieser Wert sollte kleiner oder gleich {{ compared_value }} sein. This value should not be equal to {{ compared_value }}. Dieser Wert sollte nicht {{ compared_value }} sein. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Dieser Wert sollte nicht identisch sein mit {{ compared_value_type }} {{ compared_value }}. PK!=^::DSymfony/Component/Validator/Resources/translations/validators.it.xlfnu[ This value should be false. Questo valore dovrebbe essere falso. This value should be true. Questo valore dovrebbe essere vero. This value should be of type {{ type }}. Questo valore dovrebbe essere di tipo {{ type }}. This value should be blank. Questo valore dovrebbe essere vuoto. The value you selected is not a valid choice. Questo valore dovrebbe essere una delle opzioni disponibili. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Si dovrebbe selezionare almeno {{ limit }} opzione.|Si dovrebbero selezionare almeno {{ limit }} opzioni. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Si dovrebbe selezionare al massimo {{ limit }} opzione.|Si dovrebbero selezionare al massimo {{ limit }} opzioni. One or more of the given values is invalid. Uno o più valori inseriti non sono validi. The fields {{ fields }} were not expected. I campi {{ fields }} non sono validi. The fields {{ fields }} are missing. I campi {{ fields }} sono mancanti. This value is not a valid date. Questo valore non è una data valida. This value is not a valid datetime. Questo valore non è una data e ora valida. This value is not a valid email address. Questo valore non è un indirizzo email valido. The file could not be found. Non è stato possibile trovare il file. The file is not readable. Il file non è leggibile. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Il file è troppo grande ({{ size }} {{ suffix }}). La dimensione massima consentita è {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Il mime type del file non è valido ({{ type }}). I tipi permessi sono {{ types }}. This value should be {{ limit }} or less. Questo valore dovrebbe essere {{ limit }} o inferiore. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} carattere.|Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} caratteri. This value should be {{ limit }} or more. Questo valore dovrebbe essere {{ limit }} o superiore. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} carattere.|Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} caratteri. This value should not be blank. Questo valore non dovrebbe essere vuoto. This value should not be null. Questo valore non dovrebbe essere nullo. This value should be null. Questo valore dovrebbe essere nullo. This value is not valid. Questo valore non è valido. This value is not a valid time. Questo valore non è un'ora valida. This value is not a valid URL. Questo valore non è un URL valido. The two values should be equal. I due valori dovrebbero essere uguali. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Il file è troppo grande. La dimensione massima è {{ limit }} {{ suffix }}. The file is too large. Il file è troppo grande. The file could not be uploaded. Il file non può essere caricato. This value should be a valid number. Questo valore dovrebbe essere un numero. This file is not a valid image. Questo file non è una immagine valida. This is not a valid IP address. Questo valore non è un indirizzo IP valido. This value is not a valid language. Questo valore non è una lingua valida. This value is not a valid locale. Questo valore non è una impostazione regionale valida. This value is not a valid country. Questo valore non è una nazione valida. This value is already used. Questo valore è già stato utilizzato. The size of the image could not be detected. La dimensione dell'immagine non può essere determinata. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. La larghezza dell'immagine è troppo grande ({{ width }}px). La larghezza massima è di {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. La larghezza dell'immagine è troppo piccola ({{ width }}px). La larghezza minima è di {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. L'altezza dell'immagine è troppo grande ({{ height }}px). L'altezza massima è di {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. L'altezza dell'immagine è troppo piccola ({{ height }}px). L'altezza minima è di {{ min_height }}px. This value should be the user current password. Questo valore dovrebbe essere la password attuale dell'utente. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Questo valore dovrebbe contenere esattamente {{ limit }} carattere.|Questo valore dovrebbe contenere esattamente {{ limit }} caratteri. The file was only partially uploaded. Il file è stato caricato solo parzialmente. No file was uploaded. Nessun file è stato caricato. No temporary folder was configured in php.ini. Nessuna cartella temporanea è stata configurata nel php.ini. Cannot write temporary file to disk. Impossibile scrivere il file temporaneo sul disco. A PHP extension caused the upload to fail. Un'estensione PHP ha causato il fallimento del caricamento. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Questa collezione dovrebbe contenere almeno {{ limit }} elemento.|Questa collezione dovrebbe contenere almeno {{ limit }} elementi. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Questa collezione dovrebbe contenere massimo {{ limit }} elemento.|Questa collezione dovrebbe contenere massimo {{ limit }} elementi. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Questa collezione dovrebbe contenere esattamente {{ limit }} elemento.|Questa collezione dovrebbe contenere esattamente {{ limit }} elementi. Invalid card number. Numero di carta non valido. Unsupported card type or invalid card number. Tipo di carta non supportato o numero non valido. This is not a valid International Bank Account Number (IBAN). Questo valore non è un IBAN (International Bank Account Number) valido. This value is not a valid ISBN-10. Questo valore non è un codice ISBN-10 valido. This value is not a valid ISBN-13. Questo valore non è un codice ISBN-13 valido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Questo valore non è un codice ISBN-10 o ISBN-13 valido. This value is not a valid ISSN. Questo valore non è un codice ISSN valido. This value is not a valid currency. Questo valore non è una valuta valida. PK! AADSymfony/Component/Validator/Resources/translations/validators.ca.xlfnu[ This value should be false. Aquest valor hauria de ser fals. This value should be true. Aquest valor hauria de ser cert. This value should be of type {{ type }}. Aquest valor hauria de ser del tipus {{ type }}. This value should be blank. Aquest valor hauria d'estar buit. The value you selected is not a valid choice. El valor seleccionat no és una opció vàlida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Ha de seleccionar almenys {{ limit }} opció.|Ha de seleccionar almenys {{ limit }} opcions. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Ha de seleccionar com a màxim {{ limit }} opció.|Ha de seleccionar com a màxim {{ limit }} opcions. One or more of the given values is invalid. Un o més dels valors facilitats són incorrectes. The fields {{ fields }} were not expected. No s'esperaven els camps {{ fields }}. The fields {{ fields }} are missing. Falten els camps {{ fields }}. This value is not a valid date. Aquest valor no és una data vàlida. This value is not a valid datetime. Aquest valor no és una data i hora vàlida. This value is not a valid email address. Aquest valor no és una adreça d'email vàlida. The file could not be found. No s'ha pogut trobar l'arxiu. The file is not readable. No es pot llegir l'arxiu. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. L'arxiu és massa gran ({{ size }} {{ suffix }}). La grandària màxima permesa és {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. El tipus mime de l'arxiu no és vàlid ({{ type }}). Els tipus mime vàlids són {{ types }}. This value should be {{ limit }} or less. Aquest valor hauria de ser {{ limit }} o menys. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcter o menys.|Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcters o menys. This value should be {{ limit }} or more. Aquest valor hauria de ser {{ limit }} o més. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Aquest valor és massa curt. Hauria de tenir {{ limit }} caràcters o més. This value should not be blank. Aquest valor no hauria d'estar buit. This value should not be null. Aquest valor no hauria de ser null. This value should be null. Aquest valor hauria de ser null. This value is not valid. Aquest valor no és vàlid. This value is not a valid time. Aquest valor no és una hora vàlida. This value is not a valid URL. Aquest valor no és una URL vàlida. The two values should be equal. Els dos valors haurien de ser iguals. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. L'arxiu és massa gran. El tamany màxim permés és {{ limit }} {{ suffix }}. The file is too large. L'arxiu és massa gran. The file could not be uploaded. No es pot pujar l'arxiu. This value should be a valid number. Aquest valor hauria de ser un nombre vàlid. This file is not a valid image. L'arxiu no és una imatge vàlida. This is not a valid IP address. Això no és una adreça IP vàlida. This value is not a valid language. Aquest valor no és un idioma vàlid. This value is not a valid locale. Aquest valor no és una localització vàlida. This value is not a valid country. Aquest valor no és un país vàlid. This value is already used. Aquest valor ja s'ha utilitzat. The size of the image could not be detected. No s'ha pogut determinar la grandària de la imatge. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. L'amplària de la imatge és massa gran ({{ width }}px). L'amplària màxima permesa són {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. L'amplària de la imatge és massa petita ({{ width }}px). L'amplària mínima requerida són {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. L'altura de la imatge és massa gran ({{ height }}px). L'altura màxima permesa són {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. L'altura de la imatge és massa petita ({{ height }}px). L'altura mínima requerida són {{ min_height }}px. This value should be the user current password. Aquest valor hauria de ser la contrasenya actual de l'usuari. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Aquest valor hauria de tenir exactament {{ limit }} caràcter.|Aquest valor hauria de tenir exactament {{ limit }} caràcters. The file was only partially uploaded. L'arxiu va ser només pujat parcialment. No file was uploaded. Cap arxiu va ser pujat. No temporary folder was configured in php.ini. Cap carpeta temporal va ser configurada en php.ini. Cannot write temporary file to disk. No es va poder escriure l'arxiu temporal en el disc. A PHP extension caused the upload to fail. Una extensió de PHP va fer que la pujada fallara. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Aquesta col·lecció ha de contenir {{ limit }} element o més.|Aquesta col·lecció ha de contenir {{ limit }} elements o més. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Aquesta col·lecció ha de contenir {{ limit }} element o menys.|Aquesta col·lecció ha de contenir {{ limit }} elements o menys. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Aquesta col·lecció ha de contenir exactament {{ limit }} element.|Aquesta col·lecció ha de contenir exactament {{ limit }} elements. Invalid card number. Número de targeta invàlid. Unsupported card type or invalid card number. Tipus de targeta no suportada o número de targeta invàlid. This is not a valid International Bank Account Number (IBAN). Això no és un nombre de compte bancari internacional (IBAN) vàlid. This value is not a valid ISBN-10. Aquest valor no és un ISBN-10 vàlid. This value is not a valid ISBN-13. Aquest valor no és un ISBN-13 vàlid. This value is neither a valid ISBN-10 nor a valid ISBN-13. Aquest valor no és ni un ISBN-10 vàlid ni un ISBN-13 vàlid. This value is not a valid ISSN. Aquest valor no és un ISSN vàlid. This value is not a valid currency. Aquest valor no és una divisa vàlida. This value should be equal to {{ compared_value }}. Aquest valor hauria de ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Aquest valor hauria de ser més gran a {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Aquest valor hauria de ser major o igual a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Aquest valor hauria de ser idèntic a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Aquest valor hauria de ser menor a {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Aquest valor hauria de ser menor o igual a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Aquest valor no hauria de ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Aquest valor no hauria de idèntic a {{ compared_value_type }} {{ compared_value }}. PK!D#"#"DSymfony/Component/Validator/Resources/translations/validators.mn.xlfnu[ This value should be false. Энэ утга буруу байх ёстой. This value should be true. Энэ утга үнэн байх ёстой. This value should be of type {{ type }}. Энэ утга {{ type }} -н төрөл байх ёстой. This value should be blank. Энэ утга хоосон байх ёстой. The value you selected is not a valid choice. Сонгосон утга буруу байна. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Хамгийн багадаа {{ limit }} утга сонгогдсон байх ёстой. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Хамгийн ихдээ {{ limit }} утга сонгогдох боломжтой. One or more of the given values is invalid. Өгөгдсөн нэг эсвэл нэгээс олон утга буруу байна. Талбарууд {{ fields }} зөвшөөрөгдөөгүй байна. {{ fields }}. The fields {{ fields }} are missing. {{ fields }} талбарууд дутуу байна. This value is not a valid date. Энэ утга буруу date төрөл байна . This value is not a valid datetime. Энэ утга буруу цаг төрөл байна. This value is not a valid email address. И-майл хаяг буруу байна. The file could not be found. Файл олдсонгүй. The file is not readable. Файл уншигдахуйц биш байна. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файл хэтэрхий том байна ({{ size }} {{ suffix }}). Зөвшөөрөгдөх дээд хэмжээ {{ limit }} {{ suffix }} байна. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Файлын MIME-төрөл нь буруу байна ({{ type }}). Зөвшөөрөгдөх MIME-төрлүүд {{ types }}. This value should be {{ limit }} or less. Энэ утга {{ limit }} юмуу эсвэл бага байна. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Энэ утга хэтэрхий урт байна. {{ limit }} тэмдэгтийн урттай юмуу эсвэл бага байна. This value should be {{ limit }} or more. Энэ утга {{ limit }} юмуу эсвэл их байна. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Энэ утга хэтэрхий богино байна. {{ limit }} тэмдэгт эсвэл их байна. This value should not be blank. Энэ утга хоосон байж болохгүй. This value should not be null. Энэ утга null байж болохгүй. This value should be null. Энэ утга null байна. This value is not valid. Энэ утга буруу байна. This value is not a valid time. Энэ утга буруу цаг төрөл байна. This value is not a valid URL. Энэ утга буруу URL байна . The two values should be equal. Хоёр утгууд ижил байх ёстой. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файл хэтэрхий том байна. Зөвшөөрөгдөх дээд хэмжээ нь {{ limit }} {{ suffix }} байна. The file is too large. Файл хэтэрхий том байна. The file could not be uploaded. Файл upload хийгдсэнгүй. This value should be a valid number. Энэ утга зөвхөн тоо байна. This value is not a valid country. Энэ утга үнэн бодит улс биш байна. This file is not a valid image. Файл зураг биш байна. This is not a valid IP address. IP хаяг зөв биш байна. This value is not a valid language. Энэ утга үнэн зөв хэл биш байна . PK!-tZMZMDSymfony/Component/Validator/Resources/translations/validators.ru.xlfnu[ This value should be false. Значение должно быть ложным. This value should be true. Значение должно быть истинным. This value should be of type {{ type }}. Тип значения должен быть {{ type }}. This value should be blank. Значение должно быть пустым. The value you selected is not a valid choice. Выбранное Вами значение недопустимо. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Вы должны выбрать хотя бы {{ limit }} вариант.|Вы должны выбрать хотя бы {{ limit }} варианта.|Вы должны выбрать хотя бы {{ limit }} вариантов. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Вы должны выбрать не более чем {{ limit }} вариант.|Вы должны выбрать не более чем {{ limit }} варианта.|Вы должны выбрать не более чем {{ limit }} вариантов. One or more of the given values is invalid. Одно или несколько заданных значений недопустимо. The fields {{ fields }} were not expected. Поля {{ fields }} не ожидались. The fields {{ fields }} are missing. Поля {{ fields }} отсутствуют. This value is not a valid date. Значение не является правильной датой. This value is not a valid datetime. Значение даты и времени недопустимо. This value is not a valid email address. Значение адреса электронной почты недопустимо. The file could not be found. Файл не может быть найден. The file is not readable. Файл не может быть прочитан. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файл слишком большой ({{ size }} {{ suffix }}). Максимально допустимый размер {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. MIME-тип файла недопустим ({{ type }}). Допустимы MIME-типы файлов {{ types }}. This value should be {{ limit }} or less. Значение должно быть {{ limit }} или меньше. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Значение слишком длинное. Должно быть равно {{ limit }} символу или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше. This value should be {{ limit }} or more. Значение должно быть {{ limit }} или больше. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Значение слишком короткое. Должно быть равно {{ limit }} символу или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше. This value should not be blank. Значение не должно быть пустым. This value should not be null. Значение не должно быть null. This value should be null. Значение должно быть null. This value is not valid. Значение недопустимо. This value is not a valid time. Значение времени недопустимо. This value is not a valid URL. Значение не является допустимым URL. The two values should be equal. Оба значения должны быть одинаковыми. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файл слишком большой. Максимально допустимый размер {{ limit }} {{ suffix }}. The file is too large. Файл слишком большой. The file could not be uploaded. Файл не может быть загружен. This value should be a valid number. Значение должно быть числом. This value is not a valid country. Значение не является допустимой страной. This file is not a valid image. Файл не является допустимым форматом изображения. This is not a valid IP address. Значение не является допустимым IP адресом. This value is not a valid language. Значение не является допустимым языком. This value is not a valid locale. Значение не является допустимой локалью. This value is already used. Это значение уже используется. The size of the image could not be detected. Не удалось определить размер изображения. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Ширина изображения слишком велика ({{ width }}px). Максимально допустимая ширина {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Ширина изображения слишком мала ({{ width }}px). Минимально допустимая ширина {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Высота изображения слишком велика ({{ height }}px). Максимально допустимая высота {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Высота изображения слишком мала ({{ height }}px). Минимально допустимая высота {{ min_height }}px. This value should be the user current password. Значение должно быть текущим паролем пользователя. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Значение должно быть равно {{ limit }} символу.|Значение должно быть равно {{ limit }} символам.|Значение должно быть равно {{ limit }} символам. The file was only partially uploaded. Файл был загружен только частично. No file was uploaded. Файл не был загружен. No temporary folder was configured in php.ini. Не настроена временная директория в php.ini. Cannot write temporary file to disk. Невозможно записать временный файл на диск. A PHP extension caused the upload to fail. Расширение PHP вызвало ошибку при загрузке. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Эта коллекция должна содержать {{ limit }} элемент или больше.|Эта коллекция должна содержать {{ limit }} элемента или больше.|Эта коллекция должна содержать {{ limit }} элементов или больше. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Эта коллекция должна содержать {{ limit }} элемент или меньше.|Эта коллекция должна содержать {{ limit }} элемента или меньше.|Эта коллекция должна содержать {{ limit }} элементов или меньше. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Эта коллекция должна содержать ровно {{ limit }} элемент.|Эта коллекция должна содержать ровно {{ limit }} элемента.|Эта коллекция должна содержать ровно {{ limit }} элементов. Invalid card number. Неверный номер карты. Unsupported card type or invalid card number. Неподдерживаемый тип или неверный номер карты. This is not a valid International Bank Account Number (IBAN). Значение не является допустимым международным номером банковского счета (IBAN). This value is not a valid ISBN-10. Значение имеет неверный формат ISBN-10. This value is not a valid ISBN-13. Значение имеет неверный формат ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Значение не соответствует форматам ISBN-10 и ISBN-13. This value is not a valid ISSN. Значение не соответствует формату ISSN. This value is not a valid currency. Некорректный формат валюты. This value should be equal to {{ compared_value }}. Значение должно быть равно {{ compared_value }}. This value should be greater than {{ compared_value }}. Значение должно быть больше чем {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Значение должно быть больше или равно {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Значение должно быть идентичным {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Значение должно быть меньше чем {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Значение должно быть меньше или равно {{ compared_value }}. This value should not be equal to {{ compared_value }}. Значение не должно быть равно {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Значение не должно быть идентичным {{ compared_value_type }} {{ compared_value }}. PK! This value should be false. Стойността трябва да бъде лъжа (false). This value should be true. Стойността трябва да бъде истина (true). This value should be of type {{ type }}. Стойността трябва да бъде от тип {{ type }}. This value should be blank. Стойността трябва да бъде празна. The value you selected is not a valid choice. Избраната стойност е невалидна. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Трябва да изберете поне {{ limit }} опция.|Трябва да изберете поне {{ limit }} опции. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Трябва да изберете най-много {{ limit }} опция.|Трябва да изберете най-много {{ limit }} опции. One or more of the given values is invalid. Една или повече от зададените стойности е невалидна. The fields {{ fields }} were not expected. Полетата {{ fields }} не бяха очаквани. The fields {{ fields }} are missing. Полетата {{ fields }} липсват. This value is not a valid date. Стойността не е валидна дата (date). This value is not a valid datetime. Стойността не е валидна дата (datetime). This value is not a valid email address. Стойността не е валиден email адрес. The file could not be found. Файлът не беше открит. The file is not readable. Файлът не може да бъде прочетен. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файлът е твърде голям ({{ size }} {{ suffix }}). Максималният размер е {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Майм типа на файла е невалиден ({{ type }}). Разрешени майм типове са {{ types }}. This value should be {{ limit }} or less. Стойността трябва да бъде {{ limit }} или по-малко. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символ.|Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символа. This value should be {{ limit }} or more. Стойността трябва да бъде {{ limit }} или повече. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символ.|Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символа. This value should not be blank. Стойността не трябва да бъде празна. This value should not be null. Стойността не трябва да бъде null. This value should be null. Стойността трябва да бъде null. This value is not valid. Стойността не е валидна. This value is not a valid time. Стойността не е валидно време (time). This value is not a valid URL. Стойността не е валиден URL. The two values should be equal. Двете стойности трябва да бъдат равни. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файлът е твърде голям. Разрешеният максимален размер е {{ limit }} {{ suffix }}. The file is too large. Файлът е твърде голям. The file could not be uploaded. Файлът не може да бъде качен. This value should be a valid number. Стойността трябва да бъде валиден номер. This file is not a valid image. Файлът не е валидно изображение. This is not a valid IP address. Това не е валиден IP адрес. This value is not a valid language. Стойността не е валиден език. This value is not a valid locale. Стойността не е валидна локализация. This value is not a valid country. Стойността не е валидна държава. This value is already used. Стойността вече е в употреба. The size of the image could not be detected. Размера на изображението не може да бъде определен. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Изображението е твърде широко ({{ width }}px). Широчината трябва да бъде максимум {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Изображението е с твърде малка широчина ({{ width }}px). Широчината трябва да бъде минимум {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Изображението е с твърде голяма височина ({{ height }}px). Височината трябва да бъде максимум {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Изображението е с твърде малка височина ({{ height }}px). Височина трябва да бъде минимум {{ min_height }}px. This value should be the user current password. Стойността трябва да бъде текущата потребителска парола. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Стойността трябва да бъде точно {{ limit }} символ.|Стойността трябва да бъде точно {{ limit }} символа. The file was only partially uploaded. Файлът е качен частично. No file was uploaded. Файлът не беше качен. No temporary folder was configured in php.ini. Не е посочена директория за временни файлове в php.ini. Cannot write temporary file to disk. Не може да запише временен файл на диска. A PHP extension caused the upload to fail. PHP разширение предизвика прекъсване на качването. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Колекцията трябва да съдържа поне {{ limit }} елемент.|Колекцията трябва да съдържа поне {{ limit }} елемента. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Колекцията трябва да съдържа най-много {{ limit }} елемент.|Колекцията трябва да съдържа най-много {{ limit }} елемента. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Колекцията трябва да съдържа точно {{ limit }} елемент.|Колекцията трябва да съдържа точно {{ limit }} елемента. Invalid card number. Невалиден номер на картата. Unsupported card type or invalid card number. Неподдържан тип карта или невалиден номер на картата. This is not a valid International Bank Account Number (IBAN). Невалиден Международен номер на банкова сметка (IBAN). This value is not a valid ISBN-10. Невалиден ISBN-10. This value is not a valid ISBN-13. Невалиден ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Невалидна стойност както за ISBN-10, така и за ISBN-13 . This value is not a valid ISSN. Невалиден Международен стандартен сериен номер (ISSN). This value is not a valid currency. Невалидна валута. This value should be equal to {{ compared_value }}. Стойността трябва да бъде равна на {{ compared_value }}. This value should be greater than {{ compared_value }}. Стойността трябва да бъде по-голяма от {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Стойността трябва да бъде по-голяма или равна на {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Стойността трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Стойността трябва да бъде по-малка {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Стойността трябва да бъде по-малка или равна на {{ compared_value }}. This value should not be equal to {{ compared_value }}. Стойността не трябва да бъде равна на {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Стойността не трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}. PK!AADSymfony/Component/Validator/Resources/translations/validators.ro.xlfnu[ This value should be false. Această valoare ar trebui să fie falsă (false). This value should be true. Această valoare ar trebui să fie adevărată (true). This value should be of type {{ type }}. Această valoare ar trebui să fie de tipul {{ type }}. This value should be blank. Această valoare ar trebui sa fie goală. The value you selected is not a valid choice. Valoarea selectată nu este o opțiune validă. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Trebuie să selectați cel puțin {{ limit }} opțiuni. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Trebuie să selectați cel mult {{ limit }} opțiuni. One or more of the given values is invalid. Una sau mai multe dintre valorile furnizate sunt invalide. The fields {{ fields }} were not expected. Câmpurile {{ fields }} nu erau așteptate. The fields {{ fields }} are missing. Câmpurile {{ fields }} lipsesc. This value is not a valid date. Această valoare nu reprezintă o dată validă. This value is not a valid datetime. Această valoare nu reprezintă o dată și oră validă. This value is not a valid email address. Această valoare nu reprezintă o adresă de e-mail validă. The file could not be found. Fișierul nu a putut fi găsit. The file is not readable. Fișierul nu poate fi citit. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fișierul este prea mare ({{ size }} {{ suffix }}). Dimensiunea maximă permisă este {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Tipul fișierului este invalid ({{ type }}). Tipurile permise de fișiere sunt ({{ types }}). This value should be {{ limit }} or less. Această valoare ar trebui să fie cel mult {{ limit }}. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caracter.|Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caractere. This value should be {{ limit }} or more. Această valoare ar trebui să fie cel puțin {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caracter.|Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caractere. This value should not be blank. Această valoare nu ar trebui să fie goală. This value should not be null. Această valoare nu ar trebui să fie nulă (null). This value should be null. Această valoare ar trebui să fie nulă (null). This value is not valid. Această valoare nu este validă. This value is not a valid time. Această valoare nu reprezintă o oră validă. This value is not a valid URL. Această valoare nu reprezintă un URL (link) valid. The two values should be equal. Cele două valori ar trebui să fie egale. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fișierul este prea mare. Mărimea maximă permisă este {{ limit }} {{ suffix }}. The file is too large. Fișierul este prea mare. The file could not be uploaded. Fișierul nu a putut fi încărcat. This value should be a valid number. Această valoare nu reprezintă un număr valid. This file is not a valid image. Acest fișier nu este o imagine validă. This is not a valid IP address. Această valoare nu este o adresă IP validă. This value is not a valid language. Această valoare nu reprezintă o limbă corectă. This value is not a valid locale. Această valoare nu reprezintă un dialect (o limbă) corect. This value is not a valid country. Această valoare nu este o țară validă. This value is already used. Această valoare este folosită deja. The size of the image could not be detected. Mărimea imaginii nu a putut fi detectată. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Lățimea imaginii este prea mare ({{ width }}px). Lățimea maximă permisă este de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Lățimea imaginii este prea mică ({{ width }}px). Lățimea minimă permisă este de {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Înălțimea imaginii este prea mare ({{ height }}px). Înălțimea maximă permisă este de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Înălțimea imaginii este prea mică ({{ height }}px). Înălțimea minimă permisă este de {{ min_height }}px. This value should be the user current password. Această valoare trebuie să fie parola curentă a utilizatorului. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Această valoare trebuie să conțină exact {{ limit }} caracter.|Această valoare trebuie să conțină exact {{ limit }} caractere. The file was only partially uploaded. Fișierul a fost încărcat parțial. No file was uploaded. Nu a fost încărcat nici un fișier. No temporary folder was configured in php.ini. Nu este configurat nici un director temporar in php.ini. Cannot write temporary file to disk. Nu a fost posibilă scrierea fișierului temporar pe disk. A PHP extension caused the upload to fail. O extensie PHP a prevenit încărcarea cu succes a fișierului. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Această colecție trebuie să conțină cel puțin {{ limit }} elemente. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Această colecție trebuie să conțină cel mult {{ limit }} elemente. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Această colecție trebuie să conțină {{ limit }} elemente. Invalid card number. Numărul card invalid. Unsupported card type or invalid card number. Tipul sau numărul cardului nu sunt valide. This is not a valid International Bank Account Number (IBAN). Acesta nu este un cod IBAN (International Bank Account Number) valid. This value is not a valid ISBN-10. Această valoare nu este un cod ISBN-10 valid. This value is not a valid ISBN-13. Această valoare nu este un cod ISBN-13 valid. This value is neither a valid ISBN-10 nor a valid ISBN-13. Această valoare nu este un cod ISBN-10 sau ISBN-13 valid. This value is not a valid ISSN. Această valoare nu este un cod ISSN valid. This value is not a valid currency. Această valoare nu este o monedă validă. This value should be equal to {{ compared_value }}. Această valoare trebuie să fie egală cu {{ compared_value }}. This value should be greater than {{ compared_value }}. Această valoare trebuie să fie mai mare de {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Această valoare trebuie să fie mai mare sau egală cu {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Această valoare trebuie identică cu {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Această valoare trebuie să fie mai mică de {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Această valoare trebuie să fie mai mică sau egală cu {{ compared_value }}. This value should not be equal to {{ compared_value }}. Această valoare nu trebuie să fie egală cu {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Această valoare nu trebuie să fie identică cu {{ compared_value_type }} {{ compared_value }}. PK!ժN@@DSymfony/Component/Validator/Resources/translations/validators.nl.xlfnu[ This value should be false. Deze waarde mag niet waar zijn. This value should be true. Deze waarde moet waar zijn. This value should be of type {{ type }}. Deze waarde moet van het type {{ type }} zijn. This value should be blank. Deze waarde moet leeg zijn. The value you selected is not a valid choice. De geselecteerde waarde is geen geldige optie. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Selecteer ten minste {{ limit }} optie.|Selecteer ten minste {{ limit }} opties. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Selecteer maximaal {{ limit }} optie.|Selecteer maximaal {{ limit }} opties. One or more of the given values is invalid. Eén of meer van de ingegeven waarden zijn ongeldig. The fields {{ fields }} were not expected. De velden {{ fields }} werden niet verwacht. The fields {{ fields }} are missing. De velden {{ fields }} ontbreken. This value is not a valid date. Deze waarde is geen geldige datum. This value is not a valid datetime. Deze waarde is geen geldige datum en tijd. This value is not a valid email address. Deze waarde is geen geldig e-mailadres. The file could not be found. Het bestand is niet gevonden. The file is not readable. Het bestand is niet leesbaar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Het bestand is te groot ({{ size }} {{ suffix }}). Toegestane maximum grootte is {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Het mime type van het bestand is ongeldig ({{ type }}). Toegestane mime types zijn {{ types }}. This value should be {{ limit }} or less. Deze waarde moet {{ limit }} of minder zijn. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Deze waarde is te lang. Hij mag maximaal {{ limit }} teken bevatten.|Deze waarde is te lang. Hij mag maximaal {{ limit }} tekens bevatten. This value should be {{ limit }} or more. Deze waarde moet {{ limit }} of meer zijn. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Deze waarde is te kort. Hij moet tenminste {{ limit }} teken bevatten.|Deze waarde is te kort. Hij moet tenminste {{ limit }} tekens bevatten. This value should not be blank. Deze waarde mag niet leeg zijn. This value should not be null. Deze waarde mag niet null zijn. This value should be null. Deze waarde moet null zijn. This value is not valid. Deze waarde is ongeldig. This value is not a valid time. Deze waarde is geen geldige tijd. This value is not a valid URL. Deze waarde is geen geldige URL. The two values should be equal. De twee waarden moeten gelijk zijn. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Het bestand is te groot. Toegestane maximum grootte is {{ limit }} {{ suffix }}. The file is too large. Het bestand is te groot. The file could not be uploaded. Het bestand kon niet geüpload worden. This value should be a valid number. Deze waarde moet een geldig getal zijn. This file is not a valid image. Dit bestand is geen geldige afbeelding. This is not a valid IP address. Dit is geen geldig IP-adres. This value is not a valid language. Deze waarde representeert geen geldige taal. This value is not a valid locale. Deze waarde representeert geen geldige lokalisering. This value is not a valid country. Deze waarde representeert geen geldig land. This value is already used. Deze waarde wordt al gebruikt. The size of the image could not be detected. De grootte van de afbeelding kon niet bepaald worden. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. De afbeelding is te breed ({{ width }}px). De maximaal toegestane breedte is {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. De afbeelding is niet breed genoeg ({{ width }}px). De minimaal verwachte breedte is {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. De afbeelding is te hoog ({{ height }}px). De maximaal toegestane hoogte is {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. De afbeelding is niet hoog genoeg ({{ height }}px). De minimaal verwachte hoogte is {{ min_height }}px. This value should be the user current password. Deze waarde moet het huidige wachtwoord van de gebruiker zijn. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Deze waarde moet exact {{ limit }} tekens lang zijn. The file was only partially uploaded. Het bestand is niet geheel geüpload. No file was uploaded. Er is geen bestand geüpload. No temporary folder was configured in php.ini. Er is geen tijdelijke map geconfigureerd in php.ini. Cannot write temporary file to disk. Kan het tijdelijke bestand niet wegschrijven op disk. A PHP extension caused the upload to fail. De upload is mislukt vanwege een PHP-extensie. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Deze collectie moet {{ limit }} element of meer bevatten.|Deze collectie moet {{ limit }} elementen of meer bevatten. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Deze collectie moet {{ limit }} element of minder bevatten.|Deze collectie moet {{ limit }} elementen of minder bevatten. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Deze collectie moet exact {{ limit }} element bevatten.|Deze collectie moet exact {{ limit }} elementen bevatten. Invalid card number. Ongeldig creditcardnummer. Unsupported card type or invalid card number. Niet-ondersteund type creditcard of ongeldig nummer. This is not a valid International Bank Account Number (IBAN). Dit is geen geldig internationaal bankrekeningnummer (IBAN). This value is not a valid ISBN-10. Deze waarde is geen geldige ISBN-10. This value is not a valid ISBN-13. Deze waarde is geen geldige ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Deze waarde is geen geldige ISBN-10 of ISBN-13 waarde. This value is not a valid ISSN. Deze waarde is geen geldige ISSN waarde. This value is not a valid currency. Deze waarde is geen geldige valuta. This value should be equal to {{ compared_value }}. Deze waarde moet gelijk zijn aan {{ compared_value }}. This value should be greater than {{ compared_value }}. Deze waarde moet groter zijn dan {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Deze waarde moet groter dan of gelijk aan {{ compared_value }} zijn. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Deze waarde moet identiek zijn aan {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Deze waarde moet minder zijn dan {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Deze waarde moet minder dan of gelijk aan {{ compared_value }} zijn. This value should not be equal to {{ compared_value }}. Deze waarde mag niet gelijk zijn aan {{ compared_value }}. This value should not be identical to {{ compared_value }}. Deze waarde mag niet identiek zijn aan {{ compared_value }}. PK!%N==DSymfony/Component/Validator/Resources/translations/validators.et.xlfnu[ This value should be false. Väärtus peaks olema väär. This value should be true. Väärtus peaks oleme tõene. This value should be of type {{ type }}. Väärtus peaks olema {{ type }}-tüüpi. This value should be blank. Väärtus peaks olema tühi. The value you selected is not a valid choice. Väärtus peaks olema üks etteantud valikutest. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Valima peaks vähemalt {{ limit }} valikut. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Valima peaks mitte rohkem kui {{ limit }} valikut. One or more of the given values is invalid. One or more of the given values is invalid. The fields {{ fields }} were not expected. Väljad {{ fields }} olid ootamatud. The fields {{ fields }} are missing. Väljad {{ fields }} on puudu. This value is not a valid date. Väärtus pole korrektne kuupäev. This value is not a valid datetime. Väärtus pole korrektne kuupäev ja kellaeg. This value is not a valid email address. Väärtus pole korrektne e-maili aadress. The file could not be found. Faili ei leita. The file is not readable. Fail ei ole loetav. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fail on liiga suur ({{ size }} {{ suffix }}). Suurim lubatud suurus on {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Faili sisutüüp on vigane ({{ type }}). Lubatud sisutüübid on {{ types }}. This value should be {{ limit }} or less. Väärtus peaks olema {{ limit }} või vähem. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Väärtus on liiga pikk. Pikkus peaks olema {{ limit }} tähemärki või vähem. This value should be {{ limit }} or more. Väärtus peaks olema {{ limit }} või rohkem. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Väärtus on liiga lühike. Pikkus peaks olema {{ limit }} tähemärki või rohkem. This value should not be blank. Väärtus ei tohiks olla tühi. This value should not be null. Väärtus ei tohiks olla 'null'. This value should be null. Väärtus peaks olema 'null'. This value is not valid. Väärtus on vigane. This value is not a valid time. Väärtus pole korrektne aeg. This value is not a valid URL. Väärtus pole korrektne URL. The two values should be equal. Väärtused peaksid olema võrdsed. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fail on liiga suur. Maksimaalne lubatud suurus on {{ limit }} {{ suffix }}. The file is too large. Fail on liiga suur. The file could not be uploaded. Faili ei saa üles laadida. This value should be a valid number. Väärtus peaks olema korrektne number. This file is not a valid image. Fail ei ole korrektne pilt. This is not a valid IP address. IP aadress pole korrektne. This value is not a valid language. Väärtus pole korrektne keel. This value is not a valid locale. Väärtus pole korrektne asukohakeel. This value is not a valid country. Väärtus pole olemasolev riik. This value is already used. Väärtust on juba kasutatud. The size of the image could not be detected. Pildi suurust polnud võimalik tuvastada. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Pilt on liiga lai ({{ width }}px). Suurim lubatud laius on {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Pilt on liiga kitsas ({{ width }}px). Vähim lubatud laius on {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Pilt on liiga pikk ({{ height }}px). Lubatud suurim pikkus on {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Pilt pole piisavalt pikk ({{ height }}px). Lubatud vähim pikkus on {{ min_height }}px. This value should be the user current password. Väärtus peaks olema kasutaja kehtiv salasõna. This value should have exactly {{ limit }} characters. Väärtus peaks olema täpselt {{ limit }} tähemärk pikk.|Väärtus peaks olema täpselt {{ limit }} tähemärki pikk. The file was only partially uploaded. Fail ei laetud täielikult üles. No file was uploaded. Ühtegi faili ei laetud üles. No temporary folder was configured in php.ini. Ühtegi ajutist kausta polnud php.ini-s seadistatud. Cannot write temporary file to disk. Ajutist faili ei saa kettale kirjutada. A PHP extension caused the upload to fail. PHP laiendi tõttu ebaõnnestus faili üleslaadimine. This collection should contain {{ limit }} elements or more. Kogumikus peaks olema vähemalt {{ limit }} element.|Kogumikus peaks olema vähemalt {{ limit }} elementi. This collection should contain {{ limit }} elements or less. Kogumikus peaks olema ülimalt {{ limit }} element.|Kogumikus peaks olema ülimalt {{ limit }} elementi. This collection should contain exactly {{ limit }} elements. Kogumikus peaks olema täpselt {{ limit }} element.|Kogumikus peaks olema täpselt {{ limit }}|elementi. Invalid card number. Vigane kaardi number. Unsupported card type or invalid card number. Kaardi tüüpi ei toetata või kaardi number on vigane. This is not a valid International Bank Account Number (IBAN). Väärtus pole korrektne IBAN-number. This value is not a valid ISBN-10. Väärtus pole korrektne ISBN-10. This value is not a valid ISBN-13. Väärtus pole korrektne ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Väärtus pole korrektne ISBN-10 ega ISBN-13. This value is not a valid ISSN. Väärtus pole korrektne ISSN. This value is not a valid currency. Väärtus pole korrektne valuuta. This value should be equal to {{ compared_value }}. Väärtus peaks olema võrdne {{ compared_value }}-ga. This value should be greater than {{ compared_value }}. Väärtus peaks olema suurem kui {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Väärtus peaks olema suurem kui või võrduma {{ compared_value }}-ga. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Väärtus peaks olema identne väärtusega {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Väärtus peaks olema väiksem kui {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Väärtus peaks olema väiksem kui või võrduma {{ compared_value }}-ga. This value should not be equal to {{ compared_value }}. Väärtus ei tohiks võrduda {{ compared_value }}-ga. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Väärtus ei tohiks olla identne väärtusega {{ compared_value_type }} {{ compared_value }}. PK! GGDSymfony/Component/Validator/Resources/translations/validators.fa.xlfnu[ This value should be false. این مقدار باید نادرست(False) باشد. This value should be true. این مقدار باید درست(True) باشد. This value should be of type {{ type }}. این مقدار باید از نوع {{ type }} باشد. This value should be blank. این فیلد باید خالی باشد. The value you selected is not a valid choice. گزینه انتخابی معتبر نیست. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. باید حداقل {{ limit }} گزینه انتخاب کنید.|باید حداقل {{ limit }} گزینه انتخاب کنید. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. حداکثر {{ limit }} گزینه می توانید انتخاب کنید.|حداکثر {{ limit }} گزینه می توانید انتخاب کنید. One or more of the given values is invalid. یک یا چند مقدار نامعتبر وجود دارد. The fields {{ fields }} were not expected. فیلدهای {{ fields }} اضافی هستند. The fields {{ fields }} are missing. فیلدهای {{ fields }} کم هستند. This value is not a valid date. این مقدار یک تاریخ معتبر نیست. This value is not a valid datetime. این مقدار یک تاریخ و زمان معتبر نیست. This value is not a valid email address. این یک رایانامه معتبر نیست. The file could not be found. فایل پیدا نشد. The file is not readable. فایل قابلیت خواندن ندارد. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. فایل بیش از اندازه بزرگ است({{ size }} {{ suffix }}). حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. این نوع فایل مجاز نیست({{ type }}). نوع های مجاز {{ types }} هستند. This value should be {{ limit }} or less. این مقدار باید کوچکتر یا مساوی {{ limit }} باشد. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.|بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است. This value should be {{ limit }} or more. این مقدار باید برابر و یا بیشتر از {{ limit }} باشد. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.|بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد. This value should not be blank. این مقدار نباید تهی باشد. This value should not be null. باید مقداری داشته باشد.. This value should be null. نباید مقداری داشته باشد. This value is not valid. این مقدار معتبر نیست. This value is not a valid time. این مقدار یک زمان صحیح نیست. This value is not a valid URL. این یک URL معتبر نیست. The two values should be equal. دو مقدار باید برابر باشند. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. فایل بیش از اندازه بزرگ است. حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است. The file is too large. فایل بیش از اندازه بزرگ است. The file could not be uploaded. بارگذاری فایل با شکست مواجه شد. This value should be a valid number. این مقدار باید یک عدد معتبر باشد. This file is not a valid image. این فایل یک تصویر نیست. This is not a valid IP address. این مقدار یک IP معتبر نیست. This value is not a valid language. این مقدار یک زبان صحیح نیست. This value is not a valid locale. این مقدار یک محل صحیح نیست. This value is not a valid country. این مقدار یک کشور صحیح نیست. This value is already used. این مقدار قبلا مورد استفاده قرار گرفته است. The size of the image could not be detected. اندازه تصویر قابل شناسایی نیست. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. طول تصویر بسیار بزرگ است ({{ width }}px). بشینه طول مجاز {{ max_width }}px است. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. طول تصویر بسیار کوچک است ({{ width }}px). کمینه طول موردنظر {{ min_width }}px است. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. ارتفاع تصویر بسیار بزرگ است ({{ height }}px). بشینه ارتفاع مجاز {{ max_height }}px است. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. ارتفاع تصویر بسیار کوچک است ({{ height }}px). کمینه ارتفاع موردنظر {{ min_height }}px است. This value should be the user current password. این مقدار می بایست کلمه عبور کنونی کاربر باشد. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. این مقدار می بایست دقیفا {{ limit }} کاراکتر داشته باشد.|این مقدرا می بایشت دقیقا {{ limit }} کاراکتر داشته باشد. The file was only partially uploaded. فایل به صورت جزیی بارگذاری شده است. No file was uploaded. هیچ فایلی بارگذاری نشد. No temporary folder was configured in php.ini. فولدر موقت در php.ini پیکربندی نشده است. Cannot write temporary file to disk. فایل موقت را نمی توان در دیسک نوشت. A PHP extension caused the upload to fail. اکستنشن PHP موجب شد که بارگذاری فایل با شکست مواجه شود. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. این مجموعه می بایست دارای حداقل {{ limit }} عنصر یا کمتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا کمتر باشد. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. این مجموعه می بایست به طور دقیق دارا {{ limit }} عنصر باشد.|این مجموعه می بایست به طور دقیق دارای {{ limit }} قلم باشد. Invalid card number. شماره کارت نامعتبر است. Unsupported card type or invalid card number. نوع کارت پشتیبانی نمی شود یا شماره کارت نامعتبر است. This is not a valid International Bank Account Number (IBAN). این یک شماره حساب بین المللی بانک (IBAN) درست نیست. This value is not a valid ISBN-10. این مقدار یک ISBN-10 درست نیست. This value is not a valid ISBN-13. این مقدار یک ISBN-13 درست نیست. This value is neither a valid ISBN-10 nor a valid ISBN-13. این مقدار یک ISBN-10 درست یا ISBN-13 درست نیست. This value is not a valid ISSN. این مقدار یک ISSN درست نیست. This value is not a valid currency. این مقدار یک یکای پول درست نیست. This value should be equal to {{ compared_value }}. این مقدار باید برابر با {{ compared_value }} باشد. This value should be greater than {{ compared_value }}. این مقدار باید از {{ compared_value }} بیشتر باشد. This value should be greater than or equal to {{ compared_value }}. این مقدار باید بزرگتر یا مساوی با {{ compared_value }} باشد. This value should be identical to {{ compared_value_type }} {{ compared_value }}. این مقدار باید با {{ compared_value_type }} {{ compared_value }} یکی باشد. This value should be less than {{ compared_value }}. این مقدار باید کمتر از {{ compared_value }} باشد. This value should be less than or equal to {{ compared_value }}. این مقدار باید کمتر یا مساوی با {{ compared_value }} باشد. This value should not be equal to {{ compared_value }}. این مقدار نباید با {{ compared_value }} برابر باشد. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. این مقدار نباید {{ compared_value_type }} {{ compared_value }} یکی باشد. PK!-L>L>DSymfony/Component/Validator/Resources/translations/validators.id.xlfnu[ This value should be false. Nilai ini harus bernilai salah. This value should be true. Nilai ini harus bernilai benar. This value should be of type {{ type }}. Nilai ini harus bertipe {{ type }}. This value should be blank. Nilai ini harus kosong. The value you selected is not a valid choice. Nilai yang dipilih tidak tepat. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Anda harus memilih paling tidak {{ limit }} pilihan. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Anda harus memilih paling banyak {{ limit }} pilihan. One or more of the given values is invalid. Satu atau lebih nilai yang diberikan tidak sah. The fields {{ fields }} were not expected. Kolom {{ fields }} tidak seperti yang diharapkan. The fields {{ fields }} are missing. Kolom {{ fields }} hilang. This value is not a valid date. Nilai ini bukan merupakan tanggal yang sah. This value is not a valid datetime. Nilai ini bukan merupakan tanggal dan waktu yang sah. This value is not a valid email address. Nilai ini bukan alamat email yang sah. The file could not be found. Berkas tidak ditemukan. The file is not readable. Berkas tidak bisa dibaca. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Ukuran berkas terlalu besar ({{ size }} {{ suffix }}). Ukuran maksimum yang diizinkan adalah {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Jenis berkas ({{ type }}) tidak sah. Jenis berkas yang diijinkan adalah {{ types }}. This value should be {{ limit }} or less. Nilai ini harus {{ limit }} atau kurang. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Nilai ini terlalu panjang. Seharusnya {{ limit }} karakter atau kurang. This value should be {{ limit }} or more. Nilai ini harus {{ limit }} atau lebih. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Nilai ini terlalu pendek. Seharusnya {{ limit }} karakter atau lebih. This value should not be blank. Nilai ini tidak boleh kosong. This value should not be null. Nilai ini tidak boleh 'null'. This value should be null. Nilai ini harus 'null'. This value is not valid. Nilai ini tidak sah. This value is not a valid time. Nilai ini bukan merupakan waktu yang sah. This value is not a valid URL. Nilai ini bukan URL yang sah. The two values should be equal. Isi keduanya harus sama. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ukuran berkas terlalu besar. Ukuran maksimum yang diijinkan adalah {{ limit }} {{ suffix }}. The file is too large. Ukuran berkas terlalu besar. The file could not be uploaded. Berkas tidak dapat diunggah. This value should be a valid number. Nilai ini harus angka yang sah. This file is not a valid image. Berkas ini tidak termasuk gambar. This is not a valid IP address. Ini bukan alamat IP yang sah. This value is not a valid language. Nilai ini bukan bahasa yang sah. This value is not a valid locale. Nilai ini bukan lokal yang sah. This value is not a valid country. Nilai ini bukan negara yang sah. This value is already used. Nilai ini sudah digunakan. The size of the image could not be detected. Ukuran dari gambar tidak bisa dideteksi. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Lebar gambar terlalu besar ({{ width }}px). Ukuran lebar maksimum adalah {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Lebar gambar terlalu kecil ({{ width}}px). Ukuran lebar minimum yang diharapkan adalah {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Tinggi gambar terlalu besar ({{ height }}px). Ukuran tinggi maksimum adalah {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Tinggi gambar terlalu kecil ({{ height }}px). Ukuran tinggi minimum yang diharapkan adalah {{ min_height }}px. This value should be the user current password. Nilai ini harus kata sandi pengguna saat ini. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Nilai ini harus memiliki tepat {{ limit }} karakter. The file was only partially uploaded. Berkas hanya terunggah sebagian. No file was uploaded. Tidak ada berkas terunggah. No temporary folder was configured in php.ini. Direktori sementara tidak dikonfiguasi pada php.ini. Cannot write temporary file to disk. Tidak dapat menuliskan berkas sementara ke dalam media penyimpanan. A PHP extension caused the upload to fail. Sebuah ekstensi PHP menyebabkan kegagalan unggah. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Kumpulan ini harus memiliki {{ limit }} elemen atau lebih. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Kumpulan ini harus memiliki kurang dari {{ limit }} elemen. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Kumpulan ini harus memiliki tepat {{ limit }} elemen. Invalid card number. Nomor kartu tidak sah. Unsupported card type or invalid card number. Jenis kartu tidak didukung atau nomor kartu tidak sah. This is not a valid International Bank Account Number (IBAN). Ini bukan Nomor Rekening Bank Internasional (IBAN) yang sah. This value is not a valid ISBN-10. Nilai ini bukan ISBN-10 yang sah. This value is not a valid ISBN-13. Nilai ini bukan ISBN-13 yang sah. This value is neither a valid ISBN-10 nor a valid ISBN-13. Nilai ini bukan ISBN-10 maupun ISBN-13 yang sah. This value is not a valid ISSN. Nilai ini bukan ISSN yang sah. This value is not a valid currency. Nilai ini bukan mata uang yang sah. This value should be equal to {{ compared_value }}. Nilai ini seharusnya sama dengan {{ compared_value }}. This value should be greater than {{ compared_value }}. Nilai ini seharusnya lebih dari {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Nilai ini seharusnya lebih dari atau sama dengan {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Nilai ini seharusnya identik dengan {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Nilai ini seharusnya kurang dari {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Nilai ini seharusnya kurang dari atau sama dengan {{ compared_value }}. This value should not be equal to {{ compared_value }}. Nilai ini seharusnya tidak sama dengan {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Nilai ini seharusnya tidak identik dengan {{ compared_value_type }} {{ compared_value }}. PK!˺Q1Q1DSymfony/Component/Validator/Resources/translations/validators.tr.xlfnu[ This value should be false. Bu değer olumsuz olmalıdır. This value should be true. Bu değer olumlu olmalıdır. This value should be of type {{ type }}. Bu değerin tipi {{ type }} olmalıdır. This value should be blank. Bu değer boş olmalıdır. The value you selected is not a valid choice. Seçtiğiniz değer geçerli bir seçenek değil. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. En az {{ limit }} seçenek belirtmelisiniz. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. En çok {{ limit }} seçenek belirtmelisiniz. One or more of the given values is invalid. Verilen değerlerden bir veya daha fazlası geçersiz. The fields {{ fields }} were not expected. {{ fields }} alanları kabul edilmedi. The fields {{ fields }} are missing. {{ fields }} alanları eksik. This value is not a valid date. Bu değer doğru bir tarih biçimi değildir. This value is not a valid datetime. Bu değer doğru bir tarihsaat biçimi değildir. This value is not a valid email address. Bu değer doğru bir e-mail adresi değildir. The file could not be found. Dosya bulunamadı. The file is not readable. Dosya okunabilir değil. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Dosya çok büyük ({{ size }} {{ suffix }}). İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Dosyanın mime tipi geçersiz ({{ type }}). İzin verilen mime tipleri {{ types }}. This value should be {{ limit }} or less. Bu değer {{ limit }} ve altında olmalıdır. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Bu değer çok uzun. {{ limit }} karakter veya daha az olmalıdır. This value should be {{ limit }} or more. Bu değer {{ limit }} veya daha fazla olmalıdır. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Bu değer çok kısa. {{ limit }} karakter veya daha fazla olmaldır. This value should not be blank. Bu değer boşluk olamaz. This value should not be null. Bu değer boş bırakılmamalıdır. This value should be null. Bu değer boş bırakılmalıdır. This value is not valid. Bu değer geçerli değil. This value is not a valid time. Bu değer doğru bir saat değil. This value is not a valid URL. Bu değer doğru bir URL değil. The two values should be equal. İki değer eşit olmalıdır. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Dosya çok büyük. İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}. The file is too large. Dosya çok büyük. The file could not be uploaded. Dosya yüklenemiyor. This value should be a valid number. Bu değer geçerli bir rakam olmalıdır. This file is not a valid image. Bu dosya geçerli bir resim değildir. This is not a valid IP address. Bu geçerli bir IP adresi değildir. This value is not a valid language. Bu değer geçerli bir lisan değil. This value is not a valid locale. Bu değer geçerli bir yer değildir. This value is not a valid country. Bu değer geçerli bir ülke değildir. This value is already used. Bu değer şu anda kullanımda. The size of the image could not be detected. Resmin boyutu saptanamıyor. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Resmin genişliği çok büyük ({{ width }}px). İzin verilen en büyük genişlik {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Resmin genişliği çok küçük ({{ width }}px). En az {{ min_width }}px olmalıdır. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Resmin yüksekliği çok büyük ({{ height }}px). İzin verilen en büyük yükseklik {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Resmin yüksekliği çok küçük ({{ height }}px). En az {{ min_height }}px olmalıdır. This value should be the user current password. Bu değer kullanıcının şu anki şifresi olmalıdır. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Bu değer tam olarak {{ limit }} karakter olmaldır. The file was only partially uploaded. Dosya sadece kısmen yüklendi. No file was uploaded. Hiçbir dosya yüklenmedi. No temporary folder was configured in php.ini. php.ini içerisinde geçici dizin tanımlanmadı. Cannot write temporary file to disk. Geçici dosya diske yazılamıyor. A PHP extension caused the upload to fail. Bir PHP eklentisi dosyanın yüklemesini başarısız kıldı. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Bu derlem {{ limit }} veya daha çok eleman içermelidir. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Bu derlem {{ limit }} veya daha az eleman içermelidir. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Bu derlem {{ limit }} eleman içermelidir. Invalid card number. Geçersiz kart numarası. Unsupported card type or invalid card number. Desteklenmeyen kart tipi veya geçersiz kart numarası. PK! )BBDSymfony/Component/Validator/Resources/translations/validators.cs.xlfnu[ This value should be false. Tato hodnota musí být nepravdivá (false). This value should be true. Tato hodnota musí být pravdivá (true). This value should be of type {{ type }}. Tato hodnota musí být typu {{ type }}. This value should be blank. Tato hodnota musí být prázdná. The value you selected is not a valid choice. Vybraná hodnota není platnou možností. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Musí být vybrána nejméně {{ limit }} možnost.|Musí být vybrány nejméně {{ limit }} možnosti.|Musí být vybráno nejméně {{ limit }} možností. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Musí být vybrána maximálně {{ limit }} možnost.|Musí být vybrány maximálně {{ limit }} možnosti.|Musí být vybráno maximálně {{ limit }} možností. One or more of the given values is invalid. Některé z uvedených hodnot jsou neplatné. The fields {{ fields }} were not expected. Neočekávaná pole {{ fields }}. The fields {{ fields }} are missing. Chybí následující pole {{ fields }}. This value is not a valid date. Tato hodnota není platné datum. This value is not a valid datetime. Tato hodnota není platné datum s časovým údajem. This value is not a valid email address. Tato hodnota není platná e-mailová adresa. The file could not be found. Soubor nebyl nalezen. The file is not readable. Soubor je nečitelný. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Soubor je příliš velký ({{ size }} {{ suffix }}). Maximální povolená velikost souboru je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Neplatný mime typ souboru ({{ type }}). Povolené mime typy souborů jsou {{ types }}. This value should be {{ limit }} or less. Tato hodnota musí být {{ limit }} nebo méně. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znak.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaky.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaků. This value should be {{ limit }} or more. Tato hodnota musí být {{ limit }} nebo více. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znak.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaky.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaků. This value should not be blank. Tato hodnota nesmí být prázdná. This value should not be null. Tato hodnota nesmí být prázdná. This value should be null. Tato hodnota musí být prázdná. This value is not valid. Tato hodnota není platná. This value is not a valid time. Tato hodnota není platný časový údaj. This value is not a valid URL. Tato hodnota není platná URL adresa. The two values should be equal. Tyto dvě hodnoty musí být stejné. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Soubor je příliš velký. Maximální povolená velikost souboru je {{ limit }} {{ suffix }}. The file is too large. Soubor je příliš velký. The file could not be uploaded. Soubor se nepodařilo nahrát. This value should be a valid number. Tato hodnota musí být číslo. This file is not a valid image. Tento soubor není obrázek. This is not a valid IP address. Toto není platná IP adresa. This value is not a valid language. Tento jazyk neexistuje. This value is not a valid locale. Tato lokalizace neexistuje. This value is not a valid country. Tato země neexistuje. This value is already used. Tato hodnota je již používána. The size of the image could not be detected. Nepodařily se zjistit rozměry obrázku. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Obrázek je příliš široký ({{ width }}px). Maximální povolená šířka obrázku je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Obrázek je příliš úzký ({{ width }}px). Minimální šířka musí být {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Obrázek je příliš vysoký ({{ height }}px). Maximální povolená výška obrázku je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Obrázek je příliš nízký ({{ height }}px). Minimální výška obrázku musí být {{ min_height }}px. This value should be the user current password. Tato hodnota musí být aktuální heslo uživatele. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Tato hodnota musí mít přesně {{ limit }} znak.|Tato hodnota musí mít přesně {{ limit }} znaky.|Tato hodnota musí mít přesně {{ limit }} znaků. The file was only partially uploaded. Byla nahrána jen část souboru. No file was uploaded. Žádný soubor nebyl nahrán. No temporary folder was configured in php.ini. V php.ini není nastavena cesta k adresáři pro dočasné soubory. Cannot write temporary file to disk. Dočasný soubor se nepodařilo zapsat na disk. A PHP extension caused the upload to fail. Rozšíření PHP zabránilo nahrání souboru. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Tato kolekce musí obsahovat minimálně {{ limit }} prvek.|Tato kolekce musí obsahovat minimálně {{ limit }} prvky.|Tato kolekce musí obsahovat minimálně {{ limit }} prvků. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Tato kolekce musí obsahovat maximálně {{ limit }} prvek.|Tato kolekce musí obsahovat maximálně {{ limit }} prvky.|Tato kolekce musí obsahovat maximálně {{ limit }} prvků. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Tato kolekce musí obsahovat přesně {{ limit }} prvek.|Tato kolekce musí obsahovat přesně {{ limit }} prvky.|Tato kolekce musí obsahovat přesně {{ limit }} prvků. Invalid card number. Neplatné číslo karty. Unsupported card type or invalid card number. Nepodporovaný typ karty nebo neplatné číslo karty. This is not a valid International Bank Account Number (IBAN). Toto je neplatný IBAN. This value is not a valid ISBN-10. Tato hodnota není platné ISBN-10. This value is not a valid ISBN-13. Tato hodnota není platné ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Tato hodnota není platné ISBN-10 ani ISBN-13. This value is not a valid ISSN. Tato hodnota není platné ISSN. This value is not a valid currency. Tato měna neexistuje. This value should be equal to {{ compared_value }}. Tato hodnota musí být rovna {{ compared_value }}. This value should be greater than {{ compared_value }}. Tato hodnota musí být větší než {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Tato hodnota musí být větší nebo rovna {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Tato hodnota musí být typu {{ compared_value_type }} a zároveň musí být rovna {{ compared_value }}. This value should be less than {{ compared_value }}. Tato hodnota musí být menší než {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Tato hodnota musí být menší nebo rovna {{ compared_value }}. This value should not be equal to {{ compared_value }}. Tato hodnota nesmí být rovna {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Tato hodnota nesmí být typu {{ compared_value_type }} a zároveň nesmí být rovna {{ compared_value }}. PK!6%=%=GSymfony/Component/Validator/Resources/translations/validators.zh_CN.xlfnu[ This value should be false. 该变量的值应为 false 。 This value should be true. 该变量的值应为 true 。 This value should be of type {{ type }}. 该变量的类型应为 {{ type }} 。 This value should be blank. 该变量值应为空。 The value you selected is not a valid choice. 选定变量的值不是有效的选项。 You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. 您至少要选择 {{ limit }} 个选项。 You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. 您最多能选择 {{ limit }} 个选项。 One or more of the given values is invalid. 一个或者多个给定的值无效。 The fields {{ fields }} were not expected. 非预期字段 {{ fields }} 。 The fields {{ fields }} are missing. 遗漏字段 {{ fields }} 。 This value is not a valid date. 该值不是一个有效的日期(date)。 This value is not a valid datetime. 该值不是一个有效的日期时间(datetime)。 This value is not a valid email address. 该值不是一个有效的邮件地址。 The file could not be found. 文件未找到。 The file is not readable. 文件不可读。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. 文件太大 ({{ size }} {{ suffix }})。文件大小不可以超过 {{ limit }} {{ suffix }} 。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. 无效的文件类型 ({{ type }}) 。允许的文件类型有 {{ types }} 。 This value should be {{ limit }} or less. 这个变量的值应该小于或等于 {{ limit }}。 This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. 字符串太长,长度不可超过 {{ limit }} 个字符。 This value should be {{ limit }} or more. 该变量的值应该大于或等于 {{ limit }}。 This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. 字符串太短,长度不可少于 {{ limit }} 个字符。 This value should not be blank. 该变量不应为空。 This value should not be null. 该变量不应为 null 。 This value should be null. 该变量应为空 null 。 This value is not valid. 该变量值无效 。 This value is not a valid time. 该值不是一个有效的时间。 This value is not a valid URL. 该值不是一个有效的 URL 。 The two values should be equal. 这两个变量的值应该相等。 The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. 文件太大,文件大小不可以超过 {{ limit }} {{ suffix }}。 The file is too large. 文件太大。 The file could not be uploaded. 无法上传此文件。 This value should be a valid number. 该值应该为有效的数字。 This value is not a valid country. 该值不是有效的国家名。 This file is not a valid image. 该文件不是有效的图片。 This is not a valid IP address. 该值不是有效的IP地址。 This value is not a valid language. 该值不是有效的语言名。 This value is not a valid locale. 该值不是有效的区域值(locale)。 This value is already used. 该值已经被使用。 The size of the image could not be detected. 不能解析图片大小。 The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. 图片太宽 ({{ width }}px),最大宽度为 {{ max_width }}px 。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. 图片宽度不够 ({{ width }}px),最小宽度为 {{ min_width }}px 。 The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. 图片太高 ({{ height }}px),最大高度为 {{ max_height }}px 。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. 图片高度不够 ({{ height }}px),最小高度为 {{ min_height }}px 。 This value should be the user current password. 该变量的值应为用户当前的密码。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. 该变量应为 {{ limit }} 个字符。 The file was only partially uploaded. 该文件的上传不完整。 No file was uploaded. 没有上传任何文件。 No temporary folder was configured in php.ini. php.ini 里没有配置临时文件目录。 Cannot write temporary file to disk. 临时文件写入磁盘失败。 A PHP extension caused the upload to fail. 某个 PHP 扩展造成上传失败。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. 该集合最少应包含 {{ limit }} 个元素。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. 该集合最多包含 {{ limit }} 个元素。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. 该集合应包含 {{ limit }} 个元素 element 。 Invalid card number. 无效的信用卡号。 Unsupported card type or invalid card number. 不支持的信用卡类型或无效的信用卡号。 This is not a valid International Bank Account Number (IBAN). 该值不是有效的国际银行帐号(IBAN)。 This value is not a valid ISBN-10. 该值不是有效的10位国际标准书号(ISBN-10)。 This value is not a valid ISBN-13. 该值不是有效的13位国际标准书号(ISBN-13)。 This value is neither a valid ISBN-10 nor a valid ISBN-13. 该值不是有效的国际标准书号(ISBN-10 或 ISBN-13)。 This value is not a valid ISSN. 该值不是有效的国际标准期刊号(ISSN)。 This value is not a valid currency. 该值不是有效的货币名(currency)。 This value should be equal to {{ compared_value }}. 该值应等于 {{ compared_value }} 。 This value should be greater than {{ compared_value }}. 该值应大于 {{ compared_value }} 。 This value should be greater than or equal to {{ compared_value }}. 该值应大于或等于 {{ compared_value }} 。 This value should be identical to {{ compared_value_type }} {{ compared_value }}. 该值应与 {{ compared_value_type }} {{ compared_value }} 相同。 This value should be less than {{ compared_value }}. 该值应小于 {{ compared_value }} 。 This value should be less than or equal to {{ compared_value }}. 该值应小于或等于 {{ compared_value }} 。 This value should not be equal to {{ compared_value }}. 该值不应先等于 {{ compared_value }} 。 This value should not be identical to {{ compared_value_type }} {{ compared_value }}. 该值不应与 {{ compared_value_type }} {{ compared_value }} 相同。 PK!PhBhBDSymfony/Component/Validator/Resources/translations/validators.lt.xlfnu[ This value should be false. Reikšmė turi būti neigiama. This value should be true. Reikšmė turi būti teigiama. This value should be of type {{ type }}. Šios reikšmės tipas turi būti {{ type }}. This value should be blank. Ši reikšmė turi būti tuščia. The value you selected is not a valid choice. Neteisingas pasirinkimas. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Turite pasirinkti bent {{ limit }} variantą.|Turite pasirinkti bent {{ limit }} variantus.|Turite pasirinkti bent {{ limit }} variantų. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Turite pasirinkti ne daugiau kaip {{ limit }} variantą.|Turite pasirinkti ne daugiau kaip {{ limit }} variantus.|Turite pasirinkti ne daugiau kaip {{ limit }} variantų. One or more of the given values is invalid. Viena ar daugiau įvestų reikšmių yra netinkamos. The fields {{ fields }} were not expected. Laukai {{ fields }} yra nenumatyti. The fields {{ fields }} are missing. Trūkstami laukai {{ fields }}. This value is not a valid date. Ši reikšmė nėra data. This value is not a valid datetime. Ši reikšmė nera data ir laikas. This value is not a valid email address. Ši reikšmė nėra tinkamas el. pašto adresas. The file could not be found. Byla nerasta. The file is not readable. Negalima nuskaityti bylos. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Byla yra per didelė ({{ size }} {{ suffix }}). Maksimalus dydis {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Netinkamas bylos tipas (mime type) ({{ type }}). Galimi bylų tipai {{ types }}. This value should be {{ limit }} or less. Reikšmė turi būti {{ limit }} arba mažiau. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių. This value should be {{ limit }} or more. Reikšmė turi būti {{ limit }} arba daugiau. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių. This value should not be blank. Ši reikšmė negali būti tuščia. This value should not be null. Ši reikšmė negali būti null. This value should be null. Ši reikšmė turi būti null. This value is not valid. Netinkama reikšmė. This value is not a valid time. Ši reikšmė nėra laikas. This value is not a valid URL. Ši reikšmė nėra tinkamas interneto adresas. The two values should be equal. Abi reikšmės turi būti identiškos. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Byla yra per didelė. Maksimalus dydis yra {{ limit }} {{ suffix }}. The file is too large. Byla per didelė. The file could not be uploaded. Byla negali būti įkelta. This value should be a valid number. Ši reikšmė turi būti skaičius. This value is not a valid country. Ši reikšmė nėra tinkama šalis. This file is not a valid image. Byla nėra paveikslėlis. This is not a valid IP address. Ši reikšmė nėra tinkamas IP adresas. This value is not a valid language. Ši reikšmė nėra tinkama kalba. This value is not a valid locale. Ši reikšmė nėra tinkama lokalė. This value is already used. Ši reikšmė jau yra naudojama. The size of the image could not be detected. Nepavyko nustatyti nuotraukos dydžio. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Nuotraukos plotis per didelis ({{ width }}px). Maksimalus leidžiamas plotis yra {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Nuotraukos plotis per mažas ({{ width }}px). Minimalus leidžiamas plotis yra {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Nuotraukos aukštis per didelis ({{ height }}px). Maksimalus leidžiamas aukštis yra {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Nuotraukos aukštis per mažas ({{ height }}px). Minimalus leidžiamas aukštis yra {{ min_height }}px. This value should be the user current password. Ši reikšmė turi sutapti su dabartiniu naudotojo slaptažodžiu. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ši reikšmė turi turėti lygiai {{ limit }} simbolį.|Ši reikšmė turi turėti lygiai {{ limit }} simbolius.|Ši reikšmė turi turėti lygiai {{ limit }} simbolių. The file was only partially uploaded. Failas buvo tik dalinai įkeltas. No file was uploaded. Nebuvo įkelta jokių failų. No temporary folder was configured in php.ini. Nėra sukonfiguruoto jokio laikino katalogo php.ini faile. Cannot write temporary file to disk. Nepavyko išsaugoti laikino failo. A PHP extension caused the upload to fail. PHP plėtinys sutrukdė failo įkėlimą ir jis nepavyko. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Sąraše turi būti lygiai {{ limit }} įrašas.|Sąraše turi būti lygiai {{ limit }} įrašai.|Sąraše turi būti lygiai {{ limit }} įrašų. Invalid card number. Klaidingas kortelės numeris. Unsupported card type or invalid card number. Kortelės tipas nepalaikomas arba klaidingas kortelės numeris. This is not a valid International Bank Account Number (IBAN). Ši reišmė neatitinka tarptautinio banko sąskaitos numerio formato (IBAN). This value is not a valid ISBN-10. Ši reikšmė neatitinka ISBN-10 formato. This value is not a valid ISBN-13. Ši reikšmė neatitinka ISBN-13 formato. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ši reikšmė neatitinka nei ISBN-10, nei ISBN-13 formato. This value is not a valid ISSN. Ši reišmė neatitinka ISSN formato. This value is not a valid currency. Netinkamas valiutos formatas. This value should be equal to {{ compared_value }}. Ši reikšmė turi būti lygi {{ compared_value }}. This value should be greater than {{ compared_value }}. Ši reikšmė turi būti didesnė už {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ši reikšmė turi būti didesnė už arba lygi {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ši reikšmė turi būti identiška {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ši reikšmė turi būti mažesnė už {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ši reikšmė turi būti mažesnė už arba lygi {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ši reikšmė neturi būti lygi {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ši reikšmė neturi būti identiška {{ compared_value_type }} {{ compared_value }}. PK!+ B BDSymfony/Component/Validator/Resources/translations/validators.fr.xlfnu[ This value should be false. Cette valeur doit être fausse. This value should be true. Cette valeur doit être vraie. This value should be of type {{ type }}. Cette valeur doit être de type {{ type }}. This value should be blank. Cette valeur doit être vide. The value you selected is not a valid choice. Cette valeur doit être l'un des choix proposés. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Vous devez sélectionner au moins {{ limit }} choix.|Vous devez sélectionner au moins {{ limit }} choix. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Vous devez sélectionner au maximum {{ limit }} choix.|Vous devez sélectionner au maximum {{ limit }} choix. One or more of the given values is invalid. Une ou plusieurs des valeurs soumises sont invalides. The fields {{ fields }} were not expected. Les champs {{ fields }} n'ont pas été prévus. The fields {{ fields }} are missing. Les champs {{ fields }} sont manquants. This value is not a valid date. Cette valeur n'est pas une date valide. This value is not a valid datetime. Cette valeur n'est pas une date valide. This value is not a valid email address. Cette valeur n'est pas une adresse email valide. The file could not be found. Le fichier n'a pas été trouvé. The file is not readable. Le fichier n'est pas lisible. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Le fichier est trop volumineux ({{ size }} {{ suffix }}). Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Le type du fichier est invalide ({{ type }}). Les types autorisés sont {{ types }}. This value should be {{ limit }} or less. Cette valeur doit être inférieure ou égale à {{ limit }}. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères. This value should be {{ limit }} or more. Cette valeur doit être supérieure ou égale à {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères. This value should not be blank. Cette valeur ne doit pas être vide. This value should not be null. Cette valeur ne doit pas être nulle. This value should be null. Cette valeur doit être nulle. This value is not valid. Cette valeur n'est pas valide. This value is not a valid time. Cette valeur n'est pas une heure valide. This value is not a valid URL. Cette valeur n'est pas une URL valide. The two values should be equal. Les deux valeurs doivent être identiques. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Le fichier est trop volumineux. Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}. The file is too large. Le fichier est trop volumineux. The file could not be uploaded. Le téléchargement de ce fichier est impossible. This value should be a valid number. Cette valeur doit être un nombre. This file is not a valid image. Ce fichier n'est pas une image valide. This is not a valid IP address. Cette adresse IP n'est pas valide. This value is not a valid language. Cette langue n'est pas valide. This value is not a valid locale. Ce paramètre régional n'est pas valide. This value is not a valid country. Ce pays n'est pas valide. This value is already used. Cette valeur est déjà utilisée. The size of the image could not be detected. La taille de l'image n'a pas pu être détectée. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. La largeur de l'image est trop grande ({{ width }}px). La largeur maximale autorisée est de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. La largeur de l'image est trop petite ({{ width }}px). La largeur minimale attendue est de {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. La hauteur de l'image est trop grande ({{ height }}px). La hauteur maximale autorisée est de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. La hauteur de l'image est trop petite ({{ height }}px). La hauteur minimale attendue est de {{ min_height }}px. This value should be the user current password. Cette valeur doit être le mot de passe actuel de l'utilisateur. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Cette chaine doit avoir exactement {{ limit }} caractère.|Cette chaine doit avoir exactement {{ limit }} caractères. The file was only partially uploaded. Le fichier a été partiellement transféré. No file was uploaded. Aucun fichier n'a été transféré. No temporary folder was configured in php.ini. Aucun répertoire temporaire n'a été configuré dans le php.ini. Cannot write temporary file to disk. Impossible d'écrire le fichier temporaire sur le disque. A PHP extension caused the upload to fail. Une extension PHP a empêché le transfert du fichier. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Cette collection doit contenir {{ limit }} élément ou plus.|Cette collection doit contenir {{ limit }} éléments ou plus. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Cette collection doit contenir {{ limit }} élément ou moins.|Cette collection doit contenir {{ limit }} éléments ou moins. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Cette collection doit contenir exactement {{ limit }} élément.|Cette collection doit contenir exactement {{ limit }} éléments. Invalid card number. Numéro de carte invalide. Unsupported card type or invalid card number. Type de carte non supporté ou numéro invalide. This is not a valid International Bank Account Number (IBAN). Le numéro IBAN (International Bank Account Number) saisi n'est pas valide. This value is not a valid ISBN-10. Cette valeur n'est pas un code ISBN-10 valide. This value is not a valid ISBN-13. Cette valeur n'est pas un code ISBN-13 valide. This value is neither a valid ISBN-10 nor a valid ISBN-13. Cette valeur n'est ni un code ISBN-10, ni un code ISBN-13 valide. This value is not a valid ISSN. Cette valeur n'est pas un code ISSN valide. This value is not a valid currency. Cette valeur n'est pas une devise valide. This value should be equal to {{ compared_value }}. Cette valeur doit être égale à {{ compared_value }}. This value should be greater than {{ compared_value }}. Cette valeur doit être supérieure à {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Cette valeur doit être supérieure ou égale à {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Cette valeur doit être identique à {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Cette valeur doit être inférieure à {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Cette valeur doit être inférieure ou égale à {{ compared_value }}. This value should not be equal to {{ compared_value }}. Cette valeur ne doit pas être égale à {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Cette valeur ne doit pas être identique à {{ compared_value_type }} {{ compared_value }}. PK!(=A=ADSymfony/Component/Validator/Resources/translations/validators.gl.xlfnu[ This value should be false. Este valor debería ser falso. This value should be true. Este valor debería ser verdadeiro. This value should be of type {{ type }}. Este valor debería ser de tipo {{ type }}. This value should be blank. Este valor debería estar baleiro. The value you selected is not a valid choice. O valor seleccionado non é unha opción válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Debe seleccionar polo menos {{ limit }} opción.|Debe seleccionar polo menos {{ limit }} opcions. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opcions. One or more of the given values is invalid. Un ou máis dos valores indicados non son válidos. The fields {{ fields }} were not expected. Non se esperaban os campos {{ fields }}. The fields {{ fields }} are missing. Faltan os campos {{ fields }}. This value is not a valid date. Este valor non é unha data válida. This value is not a valid datetime. Este valor non é unha data e hora válidas. This value is not a valid email address. Este valor non é unha dirección de correo electrónico válida. The file could not be found. Non se puido atopar o arquivo. The file is not readable. O arquivo non se pode ler. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é demasiado grande ({{ size }} {{ suffix }}). O tamaño máximo permitido é {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. O tipo mime do arquivo non é válido ({{ type }}). Os tipos mime válidos son {{ types }}. This value should be {{ limit }} or less. Este valor debería ser {{ limit }} ou menos. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Este valor é demasiado longo. Debería ter {{ limit }} carácter ou menos.|Este valor é demasiado longo. Debería ter {{ limit }} caracteres ou menos. This value should be {{ limit }} or more. Este valor debería ser {{ limit }} ou máis. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Este valor é demasiado curto. Debería ter {{ limit }} carácter ou máis.|Este valor é demasiado corto. Debería ter {{ limit }} caracteres ou máis. This value should not be blank. Este valor non debería estar baleiro. This value should not be null. Este valor non debería ser null. This value should be null. Este valor debería ser null. This value is not valid. Este valor non é válido. This value is not a valid time. Este valor non é unha hora válida. This value is not a valid URL. Este valor non é unha URL válida. The two values should be equal. Os dous valores deberían ser iguais. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é demasiado grande. O tamaño máximo permitido é {{ limit }} {{ suffix }}. The file is too large. O arquivo é demasiado grande. The file could not be uploaded. No se puido cargar o arquivo. This value should be a valid number. Este valor debería ser un número válido. This file is not a valid image. O arquivo non é unha imaxe válida. This is not a valid IP address. Isto non é unha dirección IP válida. This value is not a valid language. Este valor non é un idioma válido. This value is not a valid locale. Este valor non é unha localización válida. This value is not a valid country. Este valor non é un país válido. This value is already used. Este valor xa está a ser empregado. The size of the image could not be detected. Non se puido determinar o tamaño da imaxe. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A largura da imaxe é demasiado grande ({{ width }}px). A largura máxima permitida son {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A largura da imaxe é demasiado pequena ({{ width }}px). A largura mínima requerida son {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A altura da imaxe é demasiado grande ({{ height }}px). A altura máxima permitida son {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A altura da imaxe é demasiado pequena ({{ height }}px). A altura mínima requerida son {{ min_height }}px. This value should be the user current password. Este valor debería ser a contrasinal actual do usuario. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor debería ter exactamente {{ limit }} carácter.|Este valor debería ter exactamente {{ limit }} caracteres. The file was only partially uploaded. O arquivo foi só subido parcialmente. No file was uploaded. Non se subiu ningún arquivo. No temporary folder was configured in php.ini. Ningunha carpeta temporal foi configurada en php.ini. Cannot write temporary file to disk. Non se puido escribir o arquivo temporal no disco. A PHP extension caused the upload to fail. Unha extensión de PHP provocou que a subida fallara. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta colección debe conter {{ limit }} elemento ou máis.|Esta colección debe conter {{ limit }} elementos ou máis. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta colección debe conter {{ limit }} elemento ou menos.|Esta colección debe conter {{ limit }} elementos ou menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta colección debe conter exactamente {{ limit }} elemento.|Esta colección debe conter exactamente {{ limit }} elementos. Invalid card number. Número de tarxeta non válido. Unsupported card type or invalid card number. Tipo de tarxeta non soportado ou número de tarxeta non válido. This is not a valid International Bank Account Number (IBAN). Este valor non é un International Bank Account Number (IBAN) válido. This value is not a valid ISBN-10. Este valor non é un ISBN-10 válido. This value is not a valid ISBN-13. Este valor non é un ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor non é nin un ISBN-10 válido nin un ISBN-13 válido. This value is not a valid ISSN. Este valor non é un ISSN válido. This value is not a valid currency. Este valor non é unha moeda válida. This value should be equal to {{ compared_value }}. Este valor debería ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor debería ser maior que {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor debería ser maior ou igual que {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor debería ser identico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor debería ser menor que {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor debería ser menor ou igual que {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor non debería ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor non debería ser identico a {{ compared_value_type }} {{ compared_value }}. PK!wX@X@DSymfony/Component/Validator/Resources/translations/validators.hr.xlfnu[ This value should be false. Ova vrijednost treba biti netočna (false). This value should be true. Ova vrijednost treba biti točna (true). This value should be of type {{ type }}. Ova vrijednost treba biti tipa {{ type }}. This value should be blank. Ova vrijednost treba biti prazna. The value you selected is not a valid choice. Ova vrijednost treba biti jedna od ponuđenih. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Izaberite barem {{ limit }} mogućnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Izaberite najviše {{ limit }} mogućnosti. One or more of the given values is invalid. Jedna ili više danih vrijednosti nije ispravna. The fields {{ fields }} were not expected. Polja {{ fields }} nisu bila očekivana. The fields {{ fields }} are missing. Polja {{ fields }} nedostaju. This value is not a valid date. Ova vrijednost nije ispravan datum. This value is not a valid datetime. Ova vrijednost nije ispravan datum-vrijeme. This value is not a valid email address. Ova vrijednost nije ispravna e-mail adresa. The file could not be found. Datoteka ne može biti pronađena. The file is not readable. Datoteka nije čitljiva. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime tip datoteke nije ispravan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}. This value should be {{ limit }} or less. Ova vrijednost treba biti {{ limit }} ili manje. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ova vrijednost je predugačka. Treba imati {{ limit }} znakova ili manje. This value should be {{ limit }} or more. Ova vrijednost treba biti {{ limit }} ili više. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ova vrijednost je prekratka. Treba imati {{ limit }} znakova ili više. This value should not be blank. Ova vrijednost ne smije biti prazna. This value should not be null. Ova vrijednost ne smije biti null. This value should be null. Ova vrijednost treba biti null. This value is not valid. Ova vrijednost nije ispravna. This value is not a valid time. Ova vrijednost nije ispravno vrijeme. This value is not a valid URL. Ova vrijednost nije ispravan URL. The two values should be equal. Obje vrijednosti trebaju biti jednake. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ova datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The file is too large. Ova datoteka je prevelika. The file could not be uploaded. Ova datoteka ne može biti prenesena. This value should be a valid number. Ova vrijednost treba biti ispravan broj. This file is not a valid image. Ova datoteka nije ispravna slika. This is not a valid IP address. Ovo nije ispravna IP adresa. This value is not a valid language. Ova vrijednost nije ispravan jezik. This value is not a valid locale. Ova vrijednost nije ispravana regionalna oznaka. This value is not a valid country. Ova vrijednost nije ispravna zemlja. This value is already used. Ova vrijednost je već iskorištena. The size of the image could not be detected. Veličina slike se ne može odrediti. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Širina slike je prevelika ({{ width }}px). Najveća dozvoljena širina je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Visina slike je prevelika ({{ height }}px). Najveća dozvoljena visina je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px. This value should be the user current password. Ova vrijednost treba biti trenutna korisnička lozinka. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ova vrijednost treba imati točno {{ limit }} znakova. The file was only partially uploaded. Datoteka je samo djelomično prenesena. No file was uploaded. Niti jedna datoteka nije prenesena. No temporary folder was configured in php.ini. U php.ini datoteci nije konfiguriran privremeni folder. Cannot write temporary file to disk. Ne mogu zapisati privremenu datoteku na disk. A PHP extension caused the upload to fail. Prijenos datoteke nije uspio zbog PHP ekstenzije. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ova kolekcija treba sadržavati točno {{ limit }} element.|Ova kolekcija treba sadržavati točno {{ limit }} elementa.|Ova kolekcija treba sadržavati točno {{ limit }} elemenata. Invalid card number. Neispravan broj kartice. Unsupported card type or invalid card number. Neispravan broj kartice ili tip kartice nije podržan. This is not a valid International Bank Account Number (IBAN). Ova vrijednost nije ispravan međunarodni broj bankovnog računa (IBAN). This value is not a valid ISBN-10. Ova vrijednost nije ispravan ISBN-10. This value is not a valid ISBN-13. Ova vrijednost nije ispravan ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ova vrijednost nije ispravan ISBN-10 niti ISBN-13. This value is not a valid ISSN. Ova vrijednost nije ispravan ISSN. This value is not a valid currency. Ova vrijednost nije ispravna valuta. This value should be equal to {{ compared_value }}. Ova vrijednost bi trebala biti jednaka {{ compared_value }}. This value should be greater than {{ compared_value }}. Ova vrijednost bi trebala biti veća od {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ova vrijednost bi trebala biti veća ili jednaka od {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ova vrijednost bi trebala biti {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ova vrijednost bi trebala biti manja od {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ova vrijednost bi trebala biti manja ili jednaka {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ova vrijednost ne bi trebala biti {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ova vrijednost ne bi trebala biti {{ compared_value_type }} {{ compared_value }}. PK!Y.355DSymfony/Component/Validator/Resources/translations/validators.sq.xlfnu[ This value should be false. Kjo vlerë duhet të jetë e pavërtetë (false). This value should be true. Kjo vlerë duhet të jetë e vërtetë (true). This value should be of type {{ type }}. Kjo vlerë duhet të jetë e llojit {{ type }}. This value should be blank. Kjo vlerë duhet të jetë e zbrazët. The value you selected is not a valid choice. Vlera që keni zgjedhur nuk është alternativë e vlefshme. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Duhet të zgjedhni së paku {{ limit }} alternativa.|Duhet të zgjedhni së paku {{ limit }} alternativa. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Duhet të zgjedhni më së shumti {{ limit }} alternativa.|Duhet të zgjedhni më së shumti {{ limit }} alternativa. One or more of the given values is invalid. Një apo më shumë nga vlerat e dhëna nuk janë të sakta. The fields {{ fields }} were not expected. Fushat {{ fields }} nuk ishin të pritura. The fields {{ fields }} are missing. Fushat {{ fields }} mungojnë. This value is not a valid date. Kjo vlerë nuk është datë e vlefshme. This value is not a valid datetime. Kjo vlerë nuk është datë-kohë e vlefshme. This value is not a valid email address. Kjo vlerë nuk është e-mail adresë e vlefshme. The file could not be found. File nuk mund të gjindej. The file is not readable. File nuk është i lexueshëm. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. File është shumë i madh ({{ size }} {{ suffix }}). Madhësia më e madhe e lejuar është {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Lloji mime i files nuk është i vlefshëm ({{ type }}). Llojet mime të lejuara janë {{ types }}. This value should be {{ limit }} or less. Kjo vlerë duhet të jetë {{ limit }} ose më pak. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.|Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere. This value should be {{ limit }} or more. Kjo vlerë duhet të jetë {{ limit }} ose më shumë. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.|Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere. This value should not be blank. Kjo vlerë nuk duhet të jetë e zbrazët. This value should not be null. Kjo vlerë nuk duhet të jetë null. This value should be null. Kjo vlerë duhet të jetë null. This value is not valid. Kjo vlerë nuk është e vlefshme. This value is not a valid time. Kjo vlerë nuk është kohë e vlefshme. This value is not a valid URL. Kjo vlerë nuk është URL e vlefshme. The two values should be equal. Këto dy vlera duhet të jenë të barabarta. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ky file është shumë i madh. Madhësia maksimale e lejuar është {{ limit }} {{ suffix }}. The file is too large. Ky file është shumë i madh. The file could not be uploaded. Ky file nuk mund të ngarkohet. This value should be a valid number. Kjo vlerë duhet të jetë numër i vlefshëm. This file is not a valid image. Ky file nuk është imazh i vlefshëm. This is not a valid IP address. Kjo vlerë nuk është IP adresë e vlefshme. This value is not a valid language. Kjo vlerë nuk është gjuhë e vlefshme. This value is not a valid locale. Kjo vlerë nuk është përcaktim rajonal i vlefshëm. This value is not a valid country. Kjo vlerë nuk është shtet i vlefshëm. This value is already used. Kjo vlerë është tashmë në përdorim. The size of the image could not be detected. Madhësia e këtij imazhi nuk mund të zbulohet. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Gjerësia e imazhit është shumë e madhe ({{ width }}px). Gjerësia maksimale e lejuar është {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Gjerësia e imazhit është shumë e vogël ({{ width }}px). Gjerësia minimale e pritur është {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Gjatësia e imazhit është shumë e madhe ({{ height }}px). Gjatësia maksimale e lejuar është {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Gjatësia e imazhit është shumë e vogël ({{ height }}px). Gjatësia minimale e pritur është {{ min_height }}px. This value should be the user current password. Kjo vlerë duhet të jetë fjalëkalimi aktual i përdoruesit. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.|Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere. The file was only partially uploaded. Ky file është ngarkuar pjesërisht. No file was uploaded. Nuk është ngarkuar ndonjë file. No temporary folder was configured in php.ini. Asnjë folder i përkohshëm nuk është konfiguruar në php.ini. Cannot write temporary file to disk. Nuk mund të shkruhet file i përkohshëm në disk. A PHP extension caused the upload to fail. Një ekstenzion i PHP-së bëri të dështojë ngarkimi i files. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.|Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente. Invalid card number. Numër kartele i pavlefshëm. Unsupported card type or invalid card number. Lloj kartele i pambështetur ose numër kartele i pavlefshëm. PK!(eeDSymfony/Component/Validator/Resources/translations/validators.nb.xlfnu[ This value should be false. Verdien skal være falsk. This value should be true. Verdien skal være sann. This value should be of type {{ type }}. Verdien skal være av typen {{ type }}. This value should be blank. Verdien skal være blank. The value you selected is not a valid choice. Verdien skal være en av de gitte valg. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du skal velge minst {{ limit }} valg. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan maks velge {{ limit }} valg. One or more of the given values is invalid. En eller flere av de oppgitte verdier er ugyldige. The fields {{ fields }} were not expected. Feltene {{ fields }} var ikke forventet. The fields {{ fields }} are missing. Feltene {{ fields }} mangler. This value is not a valid date. Verdien er ikke en gyldig dato. This value is not a valid datetime. Verdien er ikke en gyldig dato og tid. This value is not a valid email address. Verdien er ikke en gyldig e-mail adresse. The file could not be found. Filen kunne ikke finnes. The file is not readable. Filen kan ikke leses. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}. This value should be {{ limit }} or less. Verdien skal være {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Verdien er for lang. Den skal ha {{ limit }} bokstaver eller mindre. This value should be {{ limit }} or more. Verdien skal være {{ limit }} eller mer. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Verdien er for kort. Den skal ha {{ limit }} tegn eller flere. This value should not be blank. Verdien må ikke være blank. This value should not be null. Verdien må ikke være tom (null). This value should be null. Verdien skal være tom (null). This value is not valid. Verdien er ikke gyldig. This value is not a valid time. Verdien er ikke en gyldig tid. This value is not a valid URL. Verdien er ikke en gyldig URL. The two values should be equal. De to verdier skal være ens. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}. The file is too large. Filen er for stor. The file could not be uploaded. Filen kunne ikke lastes opp. This value should be a valid number. Denne verdi skal være et gyldig tall. This file is not a valid image. Denne filen er ikke et gyldig bilde. This is not a valid IP address. Dette er ikke en gyldig IP adresse. This value is not a valid language. Denne verdi er ikke et gyldig språk. This value is not a valid locale. Denne verdi er ikke en gyldig lokalitet. This value is not a valid country. Denne verdi er ikke et gyldig land. PK!tAADSymfony/Component/Validator/Resources/translations/validators.eu.xlfnu[ This value should be false. Balio hau faltsua izan beharko litzateke. This value should be true. Balio hau egia izan beharko litzateke. This value should be of type {{ type }}. Balio hau {{ type }} motakoa izan beharko litzateke. This value should be blank. Balio hau hutsik egon beharko litzateke. The value you selected is not a valid choice. Hautatu duzun balioa ez da aukera egoki bat. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Gutxienez aukera {{ limit }} hautatu behar duzu.|Gutxienez {{ limit }} aukera hautatu behar dituzu. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Gehienez aukera {{ limit }} hautatu behar duzu.|Gehienez {{ limit }} aukera hautatu behar dituzu. One or more of the given values is invalid. Emandako balioetatik gutxienez bat ez da egokia. The fields {{ fields }} were not expected. {{ fields }} eremuak ez ziren espero. The fields {{ fields }} are missing. {{ fields }} eremuak falta dira. This value is not a valid date. Balio hau ez da data egoki bat. This value is not a valid datetime. Balio hau ez da data-ordu egoki bat. This value is not a valid email address. Balio hau ez da posta elektroniko egoki bat. The file could not be found. Ezin izan da fitxategia aurkitu. The file is not readable. Fitxategia ez da irakurgarria. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fitxategia handiegia da ({{ size }} {{ suffix }}). Baimendutako tamaina handiena {{ limit }} {{ suffix }} da. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Fitxategiaren mime mota ez da egokia ({{ type }}). Hauek dira baimendutako mime motak: {{ types }}. This value should be {{ limit }} or less. Balio hau gehienez {{ limit }} izan beharko litzateke. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Balio hau luzeegia da. Gehienez karaktere {{ limit }} eduki beharko luke.|Balio hau luzeegia da. Gehienez {{ limit }} karaktere eduki beharko lituzke. This value should be {{ limit }} or more. Balio hau gutxienez {{ limit }} izan beharko litzateke. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Balio hau motzegia da. Karaktere {{ limit }} gutxienez eduki beharko luke.|Balio hau motzegia da. Gutxienez {{ limit }} karaktere eduki beharko lituzke. This value should not be blank. Balio hau ez litzateke hutsik egon behar. This value should not be null. Balio hau ez litzateke nulua izan behar. This value should be null. Balio hau nulua izan beharko litzateke. This value is not valid. Balio hau ez da egokia. This value is not a valid time. Balio hau ez da ordu egoki bat. This value is not a valid URL. Balio hau ez da baliabideen kokatzaile uniforme (URL) egoki bat. The two values should be equal. Bi balioak berdinak izan beharko lirateke. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fitxategia handiegia da. Baimendutako tamaina handiena {{ limit }} {{ suffix }} da. The file is too large. Fitxategia handiegia da. The file could not be uploaded. Ezin izan da fitxategia igo. This value should be a valid number. Balio hau zenbaki egoki bat izan beharko litzateke. This file is not a valid image. Fitxategi hau ez da irudi egoki bat. This is not a valid IP address. Honako hau ez da IP helbide egoki bat. This value is not a valid language. Balio hau ez da hizkuntza egoki bat. This value is not a valid locale. Balio hau ez da kokapen egoki bat. This value is not a valid country. Balio hau ez da herrialde egoki bat. This value is already used. Balio hau jadanik erabilia izan da. The size of the image could not be detected. Ezin izan da irudiaren tamaina detektatu. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Irudiaren zabalera handiegia da ({{ width }}px). Onartutako gehienezko zabalera {{ max_width }}px dira. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Irudiaren zabalera txikiegia da ({{ width }}px). Onartutako gutxieneko zabalera {{ min_width }}px dira. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Irudiaren altuera handiegia da ({{ height }}px). Onartutako gehienezko altuera {{ max_height }}px dira. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Irudiaren altuera txikiegia da ({{ height }}px). Onartutako gutxieneko altuera {{ min_height }}px dira. This value should be the user current password. Balio hau uneko erabiltzailearen pasahitza izan beharko litzateke. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Balio honek zehazki karaktere {{ limit }} izan beharko luke.|Balio honek zehazki {{ limit }} karaktere izan beharko lituzke. The file was only partially uploaded. Fitxategiaren zati bat bakarrik igo da. No file was uploaded. Ez da fitxategirik igo. No temporary folder was configured in php.ini. Ez da aldi baterako karpetarik konfiguratu php.ini fitxategian. Cannot write temporary file to disk. Ezin izan da aldi baterako fitxategia diskoan idatzi. A PHP extension caused the upload to fail. PHP luzapen batek igoeraren hutsa eragin du. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Bilduma honek gutxienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gutxienez {{ limit }} elementu eduki beharko lituzke. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Bilduma honek gehienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gehienez {{ limit }} elementu eduki beharko lituzke. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Bilduma honek zehazki elementu {{ limit }} eduki beharko luke.|Bilduma honek zehazki {{ limit }} elementu eduki beharko lituzke. Invalid card number. Txartel zenbaki baliogabea. Unsupported card type or invalid card number. Txartel mota onartezina edo txartel zenbaki baliogabea. This is not a valid International Bank Account Number (IBAN). Hau ez da baliozko banku internazionaleko kontu zenbaki (IBAN) bat. This value is not a valid ISBN-10. Balio hau ez da onartutako ISBN-10 bat. This value is not a valid ISBN-13. Balio hau ez da onartutako ISBN-13 bat. This value is neither a valid ISBN-10 nor a valid ISBN-13. Balio hau ez da onartutako ISBN-10 edo ISBN-13 bat. This value is not a valid ISSN. Balio hau ez da onartutako ISSN bat. This value is not a valid currency. Balio hau ez da baliozko moneta bat. This value should be equal to {{ compared_value }}. Balio hau {{ compared_value }}-(r)en berbera izan beharko litzateke. This value should be greater than {{ compared_value }}. Balio hau {{ compared_value }} baino handiagoa izan beharko litzateke. This value should be greater than or equal to {{ compared_value }}. Balio hau {{ compared_value }}-(r)en berdina edota handiagoa izan beharko litzateke. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Balio hau {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan beharko litzateke. This value should be less than {{ compared_value }}. Balio hau {{ compared_value }} baino txikiagoa izan beharko litzateke. This value should be less than or equal to {{ compared_value }}. Balio hau {{ compared_value }}-(r)en berdina edota txikiagoa izan beharko litzateke. This value should not be equal to {{ compared_value }}. Balio hau ez litzateke {{ compared_value }}-(r)en berdina izan behar. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Balio hau ez litzateke {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan behar. PK!1ar==GSymfony/Component/Validator/Resources/translations/validators.zh_TW.xlfnu[ This value should be false. 該變數的值應為 false 。 This value should be true. 該變數的值應為 true 。 This value should be of type {{ type }}. 該變數的類型應為 {{ type }} 。 This value should be blank. 該變數應為空。 The value you selected is not a valid choice. 選定變數的值不是有效的選項。 You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. 您至少要選擇 {{ limit }} 個選項。 You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. 您最多能選擇 {{ limit }} 個選項。 One or more of the given values is invalid. 一個或者多個給定的值無效。 The fields {{ fields }} were not expected. 非預期的欄位 {{ fields }} 。 The fields {{ fields }} are missing. 缺少的欄位 {{ fields }} 。 This value is not a valid date. 該值不是一個有效的日期(date)。 This value is not a valid datetime. 該值不是一個有效的日期時間(datetime)。 This value is not a valid email address. 該值不是一個有效的郵件地址。 The file could not be found. 找不到檔案。 The file is not readable. 無法讀取檔案。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. 檔案太大 ({{ size }} {{ suffix }})。檔案大小不可以超過 {{ limit }} {{ suffix }} 。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. 無效的檔案類型 ({{ type }}) 。允許的檔案類型有 {{ types }} 。 This value should be {{ limit }} or less. 這個變數的值應該小於或等於 {{ limit }}。 This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. 字串太長,長度不可超過 {{ limit }} 個字元。 This value should be {{ limit }} or more. 該變數的值應該大於或等於 {{ limit }}。 This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. 字串太短,長度不可少於 {{ limit }} 個字元。 This value should not be blank. 該變數不應為空白。 This value should not be null. 該值不應為 null 。 This value should be null. 該值應為 null 。 This value is not valid. 無效的數值 。 This value is not a valid time. 該值不是一個有效的時間。 This value is not a valid URL. 該值不是一個有效的 URL 。 The two values should be equal. 這兩個變數的值應該相等。 The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. 檔案太大,檔案大小不可以超過 {{ limit }} {{ suffix }}。 The file is too large. 檔案太大。 The file could not be uploaded. 無法上傳此檔案。 This value should be a valid number. 該值應該為有效的數字。 This value is not a valid country. 該值不是有效的國家名。 This file is not a valid image. 該檔案不是有效的圖片。 This is not a valid IP address. 該值不是有效的IP地址。 This value is not a valid language. 該值不是有效的語言名。 This value is not a valid locale. 該值不是有效的區域值(locale)。 This value is already used. 該值已經被使用。 The size of the image could not be detected. 不能解析圖片大小。 The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. 圖片太寬 ({{ width }}px),最大寬度為 {{ max_width }}px 。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. 圖片寬度不夠 ({{ width }}px),最小寬度為 {{ min_width }}px 。 The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. 圖片太高 ({{ height }}px),最大高度為 {{ max_height }}px 。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. 圖片高度不夠 ({{ height }}px),最小高度為 {{ min_height }}px 。 This value should be the user current password. 該變數的值應為用戶目前的密碼。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. 該變數應為 {{ limit }} 個字元。 The file was only partially uploaded. 該檔案的上傳不完整。 No file was uploaded. 沒有上傳任何檔案。 No temporary folder was configured in php.ini. php.ini 裡沒有配置臨時目錄。 Cannot write temporary file to disk. 暫存檔寫入磁碟失敗。 A PHP extension caused the upload to fail. 某個 PHP 擴展造成上傳失敗。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. 該集合最少應包含 {{ limit }} 個元素。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. 該集合最多包含 {{ limit }} 個元素。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. 該集合應包含 {{ limit }} 個元素 element 。 Invalid card number. 無效的信用卡號。 Unsupported card type or invalid card number. 不支援的信用卡類型或無效的信用卡號。 This is not a valid International Bank Account Number (IBAN). 該值不是有效的國際銀行帳號(IBAN)。 This value is not a valid ISBN-10. 該值不是有效的10位國際標準書號(ISBN-10)。 This value is not a valid ISBN-13. 該值不是有效的13位國際標準書號(ISBN-13)。 This value is neither a valid ISBN-10 nor a valid ISBN-13. 該值不是有效的國際標準書號(ISBN-10 或 ISBN-13)。 This value is not a valid ISSN. 該值不是有效的國際標準期刊號(ISSN)。 This value is not a valid currency. 該值不是有效的貨幣名(currency)。 This value should be equal to {{ compared_value }}. 該值應等於 {{ compared_value }} 。 This value should be greater than {{ compared_value }}. 該值應大於 {{ compared_value }} 。 This value should be greater than or equal to {{ compared_value }}. 該值應大於或等於 {{ compared_value }} 。 This value should be identical to {{ compared_value_type }} {{ compared_value }}. 該值應與 {{ compared_value_type }} {{ compared_value }} 相同。 This value should be less than {{ compared_value }}. 該值應小於 {{ compared_value }} 。 This value should be less than or equal to {{ compared_value }}. 該值應小於或等於 {{ compared_value }} 。 This value should not be equal to {{ compared_value }}. 該值應不等於 {{ compared_value }} 。 This value should not be identical to {{ compared_value_type }} {{ compared_value }}. 該值不應與 {{ compared_value_type }} {{ compared_value }} 相同。 PK!Tл@@GSymfony/Component/Validator/Resources/translations/validators.pt_BR.xlfnu[ This value should be false. Este valor deve ser falso. This value should be true. Este valor deve ser verdadeiro. This value should be of type {{ type }}. Este valor deve ser do tipo {{ type }}. This value should be blank. Este valor deve ser vazio. The value you selected is not a valid choice. O valor selecionado não é uma opção válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Você deve selecionar, no mínimo, {{ limit }} opção.|Você deve selecionar, no mínimo, {{ limit }} opções. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Você deve selecionar, no máximo, {{ limit }} opção.|Você deve selecionar, no máximo, {{ limit }} opções. One or more of the given values is invalid. Um ou mais valores informados são inválidos. The fields {{ fields }} were not expected. Os campos {{ fields }} não são esperados. The fields {{ fields }} are missing. Os campos {{ fields }} estão ausentes. This value is not a valid date. Este valor não é uma data válida. This value is not a valid datetime. Este valor não é uma data e hora válida. This value is not a valid email address. Este valor não é um endereço de e-mail válido. The file could not be found. O arquivo não foi encontrado. The file is not readable. O arquivo não pode ser lido. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}. This value should be {{ limit }} or less. Este valor deve ser {{ limit }} ou menos. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Este valor é muito longo. Deve ter {{ limit }} caractere ou menos.|Este valor é muito longo. Deve ter {{ limit }} caracteres ou menos. This value should be {{ limit }} or more. Este valor deve ser {{ limit }} ou mais. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Este valor é muito curto. Deve ter {{ limit }} caractere ou mais.|Este valor é muito curto. Deve ter {{ limit }} caracteres ou mais. This value should not be blank. Este valor não deve ser vazio. This value should not be null. Este valor não deve ser nulo. This value should be null. Este valor deve ser nulo. This value is not valid. Este valor não é válido. This value is not a valid time. Este valor não é uma hora válida. This value is not a valid URL. Este valor não é uma URL válida. The two values should be equal. Os dois valores devem ser iguais. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}. The file is too large. O arquivo é muito grande. The file could not be uploaded. O arquivo não pode ser enviado. This value should be a valid number. Este valor deve ser um número válido. This file is not a valid image. Este arquivo não é uma imagem válida. This is not a valid IP address. Este não é um endereço de IP válido. This value is not a valid language. Este valor não é um idioma válido. This value is not a valid locale. Este valor não é uma localidade válida. This value is not a valid country. Este valor não é um país válido. This value is already used. Este valor já está sendo usado. The size of the image could not be detected. O tamanho da imagem não pode ser detectado. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A largura da imagem é muito grande ({{ width }}px). A largura máxima permitida é de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A largura da imagem é muito pequena ({{ width }}px). A largura mínima esperada é de {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A altura da imagem é muito grande ({{ height }}px). A altura máxima permitida é de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A altura da imagem é muito pequena ({{ height }}px). A altura mínima esperada é de {{ min_height }}px. This value should be the user current password. Este valor deve ser a senha atual do usuário. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor deve ter exatamente {{ limit }} caractere.|Este valor deve ter exatamente {{ limit }} caracteres. The file was only partially uploaded. O arquivo foi enviado apenas parcialmente. No file was uploaded. Nenhum arquivo foi enviado. No temporary folder was configured in php.ini. Nenhum diretório temporário foi configurado no php.ini. Cannot write temporary file to disk. Não foi possível escrever o arquivo temporário no disco. A PHP extension caused the upload to fail. Uma extensão PHP fez com que o envio falhasse. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos. Invalid card number. Número de cartão inválido. Unsupported card type or invalid card number. Tipo de cartão não suportado ou número de cartão inválido. This is not a valid International Bank Account Number (IBAN). Este não é um Número Internacional de Conta Bancária (IBAN) válido. This value is not a valid ISBN-10. Este valor não é um ISBN-10 válido. This value is not a valid ISBN-13. Este valor não é um ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor não é um ISBN-10 e nem um ISBN-13 válido. This value is not a valid ISSN. Este valor não é um ISSN válido. This value is not a valid currency. Este não é um valor monetário válido. This value should be equal to {{ compared_value }}. Este valor deve ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor deve ser maior que {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor deve ser maior ou igual a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor deve ser menor que {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor deve ser menor ou igual a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor não deve ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. PK!11DSymfony/Component/Validator/Resources/translations/validators.no.xlfnu[ This value should be false. Verdien skulle ha vore tom/nei. This value should be true. Verdien skulla ha vore satt/ja. This value should be of type {{ type }}. Verdien må vere av typen {{ type }}. This value should be blank. Verdien skal vere blank. The value you selected is not a valid choice. Verdien du valgte er ikkje gyldig. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du må velge minst {{ limit }} valg. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan maksimalt gjere {{ limit }} valg. One or more of the given values is invalid. Ein eller fleire av dei opplyste verdiane er ugyldige. The fields {{ fields }} were not expected. Felta {{ fields }} var ikkje forventa. The fields {{ fields }} are missing. Felta {{ fields }} manglar. This value is not a valid date. Verdien er ikkje ein gyldig dato. This value is not a valid datetime. Verdien er ikkje ein gyldig dato og tid. This value is not a valid email address. Verdien er ikkje ei gyldig e-postadresse. The file could not be found. Fila kunne ikkje finnes. The file is not readable. Fila kan ikkje lesast. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fila er for stor ({{ size }} {{ suffix }}). Tillatt maksimal størrelse er {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime-typen av fila er ugyldig ({{ type }}). Tillatte mime-typar er {{ types }}. This value should be {{ limit }} or less. Verdien må vere {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre. This value should be {{ limit }} or more. Verdien må vere {{ limit }} eller meir. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Verdien er for kort. Den må ha {{ limit }} teikn eller fleire. This value should not be blank. Verdien må ikkje vere blank. This value should not be null. Verdien må ikkje vere tom (null). This value should be null. Verdien må vere tom (null). This value is not valid. Verdien er ikkje gyldig. This value is not a valid time. Verdien er ikkje gyldig tidseining. This value is not a valid URL. Verdien er ikkje ein gyldig URL. The two values should be equal. Dei to verdiane må vere like. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fila er for stor. Den maksimale storleik er {{ limit }} {{ suffix }}. The file is too large. Fila er for stor. The file could not be uploaded. Fila kunne ikkje bli lasta opp. This value should be a valid number. Verdien må vere eit gyldig tal. This file is not a valid image. Fila er ikkje eit gyldig bilete. This is not a valid IP address. Dette er ikkje ei gyldig IP-adresse. This value is not a valid language. Verdien er ikkje eit gyldig språk. This value is not a valid locale. Verdien er ikkje ein gyldig lokalitet (språk/region). This value is not a valid country. Verdien er ikkje eit gyldig land. This value is already used. Verdien er allereie i bruk. The size of the image could not be detected. Storleiken på biletet kunne ikkje oppdagast. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Biletbreidda er for stor, ({{ width }} pikslar). Tillatt maksimumsbreidde er {{ max_width }} pikslar. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Bilethøgda er for stor, ({{ height }} pikslar). Tillatt maksimumshøgde er {{ max_height }} pikslar. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar. This value should be the user current password. Verdien må vere brukaren sitt noverande passord. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Verdien må vere nøyaktig {{ limit }} teikn. The file was only partially uploaded. Fila vart kun delvis opplasta. No file was uploaded. Inga fil vart lasta opp. No temporary folder was configured in php.ini. Førebels mappe (tmp) er ikkje konfigurert i php.ini. Cannot write temporary file to disk. Kan ikkje skrive førebels fil til disk. A PHP extension caused the upload to fail. Ei PHP-udviding forårsaka feil under opplasting. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element. Invalid card number. Ugyldig kortnummer. Unsupported card type or invalid card number. Korttypen er ikkje støtta eller ugyldig kortnummer. PK!nCCDSymfony/Component/Validator/Resources/translations/validators.sl.xlfnu[ This value should be false. Vrednost bi morala biti nepravilna (false). This value should be true. Vrednost bi morala biti pravilna (true). This value should be of type {{ type }}. Vrednost mora biti naslednjega tipa {{ type }}. This value should be blank. Vrednost mora biti prazna. The value you selected is not a valid choice. Vrednost, ki ste jo izbrali, ni veljavna možnost. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Izbrati morate vsaj {{ limit }} možnost.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Izberete lahko največ {{ limit }} možnost.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti. One or more of the given values is invalid. Ena ali več podanih vrednosti ni veljavnih. The fields {{ fields }} were not expected. Polja {{ fields }} niso bila pričakovana. The fields {{ fields }} are missing. Polja {{ fields }} manjkajo. This value is not a valid date. Ta vrednost ni veljaven datum. This value is not a valid datetime. Ta vrednost ni veljaven datum in čas. This value is not a valid email address. Ta vrednost ni veljaven e-poštni naslov. The file could not be found. Datoteke ni mogoče najti. The file is not readable. Datoteke ni mogoče prebrati. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika ({{ size }} {{ suffix }}). Največja dovoljena velikost je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime tip datoteke je neveljaven ({{ type }}). Dovoljeni mime tipi so {{ types }}. This value should be {{ limit }} or less. Ta vrednost bi morala biti {{ limit }} ali manj. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ta vrednost je predolga. Morala bi imeti {{ limit }} znak ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znaka ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znake ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znakov ali manj. This value should be {{ limit }} or more. Ta vrednost bi morala biti {{ limit }} ali več. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ta vrednost je prekratka. Morala bi imeti {{ limit }} znak ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znaka ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znake ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znakov ali več. This value should not be blank. Ta vrednost ne bi smela biti prazna. This value should not be null. Ta vrednost ne bi smela biti nedefinirana (null). This value should be null. Ta vrednost bi morala biti nedefinirana (null). This value is not valid. Ta vrednost ni veljavna. This value is not a valid time. Ta vrednost ni veljaven čas. This value is not a valid URL. Ta vrednost ni veljaven URL. The two values should be equal. Ti dve vrednosti bi morali biti enaki. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika. Največja dovoljena velikost je {{ limit }} {{ suffix }}. The file is too large. Datoteka je prevelika. The file could not be uploaded. Datoteke ni bilo mogoče naložiti. This value should be a valid number. Ta vrednost bi morala biti veljavna številka. This file is not a valid image. Ta datoteka ni veljavna slika. This is not a valid IP address. To ni veljaven IP naslov. This value is not a valid language. Ta vrednost ni veljaven jezik. This value is not a valid locale. Ta vrednost ni veljavna lokalnost. This value is not a valid country. Ta vrednost ni veljavna država. This value is already used. Ta vrednost je že uporabljena. The size of the image could not be detected. Velikosti slike ni bilo mogoče zaznati. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Širina slike je preširoka ({{ width }}px). Največja dovoljena širina je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Širina slike je premajhna ({{ width }}px). Najmanjša predvidena širina je {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Višina slike je prevelika ({{ height }}px). Največja dovoljena višina je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Višina slike je premajhna ({{ height }}px). Najmanjša predvidena višina je {{ min_height }}px. This value should be the user current password. Ta vrednost bi morala biti trenutno uporabnikovo geslo. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ta vrednost bi morala imeti točno {{ limit }} znak.|Ta vrednost bi morala imeti točno {{ limit }} znaka.|Ta vrednost bi morala imeti točno {{ limit }} znake.|Ta vrednost bi morala imeti točno {{ limit }} znakov. The file was only partially uploaded. Datoteka je bila le delno naložena. No file was uploaded. Nobena datoteka ni bila naložena. No temporary folder was configured in php.ini. Začasna mapa ni nastavljena v php.ini. Cannot write temporary file to disk. Začasne datoteke ni bilo mogoče zapisati na disk. A PHP extension caused the upload to fail. PHP razširitev je vzrok, da nalaganje ni uspelo. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ta zbirka bi morala vsebovati {{ limit }} element ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali več.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali več. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ta zbirka bi morala vsebovati {{ limit }} element ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali manj. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ta zbirka bi morala vsebovati točno {{ limit }} element.|Ta zbirka bi morala vsebovati točno {{ limit }} elementa.|Ta zbirka bi morala vsebovati točno {{ limit }} elemente.|Ta zbirka bi morala vsebovati točno {{ limit }} elementov. Invalid card number. Neveljavna številka kartice. Unsupported card type or invalid card number. Nepodprti tip kartice ali neveljavna številka kartice. This is not a valid International Bank Account Number (IBAN). To ni veljavna mednarodna številka bančnega računa (IBAN). This value is not a valid ISBN-10. Neveljavna vrednost po ISBN-10. This value is not a valid ISBN-13. Neveljavna vrednost po ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Neveljavna vrednost po ISBN-10 ali po ISBN-13. This value is not a valid ISSN. Neveljavna vrednost ISSN. This value is not a valid currency. Ta vrednost ni veljavna valuta. This value should be equal to {{ compared_value }}. Ta vrednost bi morala biti enaka {{ compared_value }}. This value should be greater than {{ compared_value }}. Ta vrednost bi morala biti večja od {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ta vrednost bi morala biti večja ali enaka {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ta vrednost bi morala biti identična {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ta vrednost bi morala biti manjša od {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ta vrednost bi morala biti manjša ali enaka {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ta vrednost ne bi smela biti enaka {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ta vrednost ne bi smela biti identična {{ compared_value_type }} {{ compared_value }}. PK!qb??DSymfony/Component/Validator/Resources/translations/validators.lb.xlfnu[ This value should be false. Dëse Wäert sollt falsch sinn. This value should be true. Dëse Wäert sollt wouer sinn. This value should be of type {{ type }}. Dëse Wäert sollt vum Typ {{ type }} sinn. This value should be blank. Dëse Wäert sollt eidel sinn. The value you selected is not a valid choice. Dëse Wäert sollt enger vun de Wielméiglechkeeten entspriechen. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Dir sollt mindestens {{ limit }} Méiglechkeete wielen. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Dir sollt héchstens {{ limit }} Méiglechkeete wielen. One or more of the given values is invalid. Een oder méi vun de Wäerter ass ongëlteg. The fields {{ fields }} were not expected. D'Felder {{ fields }} goufen net erwaart. The fields {{ fields }} are missing. D'Felder {{ fields }} feelen. This value is not a valid date. Dëse Wäert entsprécht kenger gëlteger Datumsangab. This value is not a valid datetime. Dëse Wäert entsprécht kenger gëlteger Datums- an Zäitangab. This value is not a valid email address. Dëse Wäert ass keng gëlteg Email-Adress. The file could not be found. De Fichier gouf net fonnt. The file is not readable. De Fichier ass net liesbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. De Fichier ass ze grouss ({{ size }} {{ suffix }}). Déi zougeloosse Maximalgréisst bedréit {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Den Typ vum Fichier ass ongëlteg ({{ type }}). Erlaabten Type sinn {{ types }}. This value should be {{ limit }} or less. Dëse Wäert soll méi kleng oder gläich {{ limit }} sinn. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Dës Zeecheketten ass ze laang. Se sollt héchstens {{ limit }} Zeechen hunn. This value should be {{ limit }} or more. Dëse Wäert sollt méi grouss oder gläich {{ limit }} sinn. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Dës Zeecheketten ass ze kuerz. Se sollt mindestens {{ limit }} Zeechen hunn. This value should not be blank. Dëse Wäert sollt net eidel sinn. This value should not be null. Dëst sollt keen Null-Wäert sinn. This value should be null. Dëst sollt keen Null-Wäert sinn. This value is not valid. Dëse Wäert ass net gëlteg. This value is not a valid time. Dëse Wäert entsprécht kenger gëlteger Zäitangab. This value is not a valid URL. Dëse Wäert ass keng gëlteg URL. The two values should be equal. Béid Wäerter sollten identesch sinn. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. De fichier ass ze grouss. Déi maximal Gréisst dierf {{ limit }} {{ suffix }} net depasséieren. The file is too large. De Fichier ass ze grouss. The file could not be uploaded. De Fichier konnt net eropgeluede ginn. This value should be a valid number. Dëse Wäert sollt eng gëlteg Zuel sinn. This file is not a valid image. Dëse Fichier ass kee gëltegt Bild. This is not a valid IP address. Dëst ass keng gëlteg IP-Adress. This value is not a valid language. Dëse Wäert aentsprécht kenger gëlteger Sprooch. This value is not a valid locale. Dëse Wäert entsprécht kengem gëltege Gebittsschema. This value is not a valid country. Dëse Wäert entsprécht kengem gëltege Land. This value is already used. Dëse Wäert gëtt scho benotzt. The size of the image could not be detected. D'Gréisst vum Bild konnt net detektéiert ginn. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. D'Breet vum Bild ass ze grouss ({{ width }}px). Déi erlaabte maximal Breet ass {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. D'Breet vum Bild ass ze kleng ({{ width }}px). Déi minimal Breet ass {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. D'Héicht vum Bild ass ze grouss ({{ height }}px). Déi erlaabte maximal Héicht ass {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. D'Héicht vum Bild ass ze kleng ({{ height }}px). Déi minimal Héicht ass {{ min_height }}px. This value should be the user current password. Dëse Wäert sollt dem aktuelle Benotzerpasswuert entspriechen. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Dëse Wäert sollt exactly {{ limit }} Buschtaf hunn.|Dëse Wäert sollt exakt {{ limit }} Buschtawen hunn. The file was only partially uploaded. De Fichier gouf just deelweis eropgelueden. No file was uploaded. Et gouf kee Fichier eropgelueden. No temporary folder was configured in php.ini. Et gouf keen temporären Dossier an der php.ini konfiguréiert. Cannot write temporary file to disk. Den temporäre Fichier kann net gespäichert ginn. A PHP extension caused the upload to fail. Eng PHP-Erweiderung huet den Upload verhënnert. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Dës Sammlung sollt {{ limit }} oder méi Elementer hunn. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Dës Sammlung sollt {{ limit }} oder manner Elementer hunn. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Dës Sammlung sollt exakt {{ limit }} Element hunn.|Dës Sammlung sollt exakt {{ limit }} Elementer hunn. Invalid card number. Ongëlteg Kaartennummer. Unsupported card type or invalid card number. Net ënnerstëtzte Kaartentyp oder ongëlteg Kaartennummer. This is not a valid International Bank Account Number (IBAN). Dëst ass keng gëlteg IBAN-Kontonummer. This value is not a valid ISBN-10. Dëse Wäert ass keng gëlteg ISBN-10. This value is not a valid ISBN-13. Dëse Wäert ass keng gëlteg ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Dëse Wäert ass weder eng gëlteg ISBN-10 nach eng gëlteg ISBN-13. This value is not a valid ISSN. Dëse Wäert ass keng gëlteg ISSN. This value is not a valid currency. Dëse Wäert ass keng gëlteg Währung. This value should be equal to {{ compared_value }}. Dëse Wäert sollt {{ compared_value }} sinn. This value should be greater than {{ compared_value }}. Dëse Wäert sollt méi grouss wéi {{ compared_value }} sinn. This value should be greater than or equal to {{ compared_value }}. Dëse Wäert sollt méi grouss wéi oder gläich {{ compared_value }} sinn. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Dëse Wäert sollt identesch si mat {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Dëse Wäert sollt méi kleng wéi {{ compared_value }} sinn. This value should be less than or equal to {{ compared_value }}. Dëse Wäert sollt méi kleng wéi oder gläich {{ compared_value }} sinn. This value should not be equal to {{ compared_value }}. Dëse Wäert sollt net {{ compared_value }} sinn. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Dëse Wäert sollt net identesch si mat {{ compared_value_type }} {{ compared_value }}. PK!93XaoAoADSymfony/Component/Validator/Resources/translations/validators.hu.xlfnu[ This value should be false. Ennek az értéknek hamisnak kell lennie. This value should be true. Ennek az értéknek igaznak kell lennie. This value should be of type {{ type }}. Ennek az értéknek {{ type }} típusúnak kell lennie. This value should be blank. Ennek az értéknek üresnek kell lennie. The value you selected is not a valid choice. A választott érték érvénytelen. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Legalább {{ limit }} értéket kell kiválasztani.|Legalább {{ limit }} értéket kell kiválasztani. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Legfeljebb {{ limit }} értéket lehet kiválasztani.|Legfeljebb {{ limit }} értéket lehet kiválasztani. One or more of the given values is invalid. A megadott értékek közül legalább egy érvénytelen. The fields {{ fields }} were not expected. Váratlan mezők: {{ fields }}. The fields {{ fields }} are missing. A következő mezők hiányoznak: {{ fields }}. This value is not a valid date. Ez az érték nem egy érvényes dátum. This value is not a valid datetime. Ez az érték nem egy érvényes időpont. This value is not a valid email address. Ez az érték nem egy érvényes e-mail cím. The file could not be found. A fájl nem található. The file is not readable. A fájl nem olvasható. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. A fájl túl nagy ({{ size }} {{ suffix }}). A legnagyobb megengedett méret {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. A fájl mime típusa érvénytelen ({{ type }}). Az engedélyezett mime típusok: {{ types }}. This value should be {{ limit }} or less. Ez az érték legfeljebb {{ limit }} lehet. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat.|Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat. This value should be {{ limit }} or more. Ez az érték legalább {{ limit }} kell legyen. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia.|Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia. This value should not be blank. Ez az érték nem lehet üres. This value should not be null. Ez az érték nem lehet null. This value should be null. Ennek az értéknek nullnak kell lennie. This value is not valid. Ez az érték nem érvényes. This value is not a valid time. Ez az érték nem egy érvényes időpont. This value is not a valid URL. Ez az érték nem egy érvényes URL. The two values should be equal. A két értéknek azonosnak kell lennie. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. A fájl túl nagy. A megengedett maximális méret: {{ limit }} {{ suffix }}. The file is too large. A fájl túl nagy. The file could not be uploaded. A fájl nem tölthető fel. This value should be a valid number. Ennek az értéknek érvényes számnak kell lennie. This file is not a valid image. Ez a fájl nem egy érvényes kép. This is not a valid IP address. Ez az érték nem egy érvényes IP cím. This value is not a valid language. Ez az érték nem egy érvényes nyelv. This value is not a valid locale. Ez az érték nem egy érvényes területi beállítás. This value is not a valid country. Ez az érték nem egy érvényes ország. This value is already used. Ez az érték már használatban van. The size of the image could not be detected. A kép méretét nem lehet megállapítani. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A kép szélessége túl nagy ({{ width }}px). A megengedett legnagyobb szélesség {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A kép szélessége túl kicsi ({{ width }}px). Az elvárt legkisebb szélesség {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A kép magassága túl nagy ({{ height }}px). A megengedett legnagyobb magasság {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A kép magassága túl kicsi ({{ height }}px). Az elvárt legkisebb magasság {{ min_height }}px. This value should be the user current password. Ez az érték a felhasználó jelenlegi jelszavával kell megegyezzen. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia.|Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia. The file was only partially uploaded. A fájl csak részben lett feltöltve. No file was uploaded. Nem lett fájl feltöltve. No temporary folder was configured in php.ini. Nincs ideiglenes könyvtár beállítva a php.ini-ben. Cannot write temporary file to disk. Az ideiglenes fájl nem írható a lemezre. A PHP extension caused the upload to fail. Egy PHP bővítmény miatt a feltöltés nem sikerült. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat.|Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia. Invalid card number. Érvénytelen kártyaszám. Unsupported card type or invalid card number. Nem támogatott kártyatípus vagy érvénytelen kártyaszám. This is not a valid International Bank Account Number (IBAN). Érvénytelen nemzetközi bankszámlaszám (IBAN). This value is not a valid ISBN-10. Ez az érték nem egy érvényes ISBN-10. This value is not a valid ISBN-13. Ez az érték nem egy érvényes ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ez az érték nem egy érvényes ISBN-10 vagy ISBN-13. This value is not a valid ISSN. Ez az érték nem egy érvényes ISSN. This value is not a valid currency. Ez az érték nem egy érvényes pénznem. This value should be equal to {{ compared_value }}. Ez az érték legyen {{ compared_value }}. This value should be greater than {{ compared_value }}. Ez az érték nagyobb legyen mint {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ez az érték nagyobb vagy egyenlő legyen mint {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ez az érték ugyanolyan legyen mint {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ez az érték kisebb legyen mint {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ez az érték kisebb vagy egyenlő legyen mint {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ez az érték ne legyen {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ez az érték ne legyen ugyanolyan mint {{ compared_value_type }} {{ compared_value }}. PK!MMDSymfony/Component/Validator/Resources/translations/validators.el.xlfnu[ This value should be false. Αυτή η τιμή πρέπει να είναι ψευδής. This value should be true. Αυτή η τιμή πρέπει να είναι αληθής. This value should be of type {{ type }}. Αυτή η τιμή πρέπει να είναι τύπου {{ type }}. This value should be blank. Αυτή η τιμή πρέπει να είναι κενή. The value you selected is not a valid choice. Η τιμή που επιλέχθηκε δεν αντιστοιχεί σε έγκυρη επιλογή. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογή.|Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογές. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογή.|Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογές. One or more of the given values is invalid. Μια ή περισσότερες τιμές δεν είναι έγκυρες. The fields {{ fields }} were not expected. Τα πεδία {{ fields }} δεν ήταν αναμενόμενα. The fields {{ fields }} are missing. Τα πεδία {{ fields }} απουσιάζουν. This value is not a valid date. Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία. This value is not a valid datetime. Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία και ώρα. This value is not a valid email address. Η τιμή δεν αντιστοιχεί σε έγκυρο email. The file could not be found. Το αρχείο δε μπορεί να βρεθεί. The file is not readable. Το αρχείο δεν είναι αναγνώσιμο. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Το αρχείο είναι πολύ μεγάλο ({{ size }} {{ suffix }}). Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Ο τύπος mime του αρχείου δεν είναι έγκυρος ({{ type }}). Οι έγκρυοι τύποι mime είναι {{ types }}. This value should be {{ limit }} or less. Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή λιγότερο. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή λιγότερο.|Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή λιγότερο. This value should be {{ limit }} or more. Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή περισσότερο. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή περισσότερο.|Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή περισσότερο. This value should not be blank. Αυτή η τιμή δεν πρέπει να είναι κενή. This value should not be null. Αυτή η τιμή δεν πρέπει να είναι μηδενική. This value should be null. Αυτή η τιμή πρέπει να είναι μηδενική. This value is not valid. Αυτή η τιμή δεν είναι έκγυρη. This value is not a valid time. Αυτή η τιμή δεν αντιστοιχεί σε έγκυρη ώρα. This value is not a valid URL. Αυτή η τιμή δεν αντιστοιχεί σε έγκυρο URL. The two values should be equal. Οι δύο τιμές θα πρέπει να είναι ίδιες. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Το αρχείο είναι πολύ μεγάλο. Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}. The file is too large. Το αρχείο είναι πολύ μεγάλο. The file could not be uploaded. Το αρχείο δε μπορεί να ανέβει. This value should be a valid number. Αυτή η τιμή θα πρέπει να είναι ένας έγκυρος αριθμός. This file is not a valid image. Το αρχείο δεν αποτελεί έγκυρη εικόνα. This is not a valid IP address. Αυτό δεν είναι μια έκγυρη διεύθυνση IP. This value is not a valid language. Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη γλώσσα. This value is not a valid locale. Αυτή η τιμή δεν αντιστοιχεί σε έκγυρο κωδικό τοποθεσίας. This value is not a valid country. Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη χώρα. This value is already used. Αυτή η τιμή χρησιμοποιείται ήδη. The size of the image could not be detected. Το μέγεθος της εικόνας δεν ήταν δυνατό να ανιχνευθεί. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Το πλάτος της εικόνας είναι πολύ μεγάλο ({{ width }}px). Το μέγιστο επιτρεπτό πλάτος είναι {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Το πλάτος της εικόνας είναι πολύ μικρό ({{ width }}px). Το ελάχιστο επιτρεπτό πλάτος είναι {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Το ύψος της εικόνας είναι πολύ μεγάλο ({{ height }}px). Το μέγιστο επιτρεπτό ύψος είναι {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Το ύψος της εικόνας είναι πολύ μικρό ({{ height }}px). Το ελάχιστο επιτρεπτό ύψος είναι {{ min_height }}px. This value should be the user current password. Αυτή η τιμή θα έπρεπε να είναι ο τρέχων κωδικός. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρα.|Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρες. The file was only partially uploaded. Το αρχείο δεν ανέβηκε ολόκληρο. No file was uploaded. Δεν ανέβηκε κανένα αρχείο. No temporary folder was configured in php.ini. Κανένας προσωρινός φάκελος δεν έχει ρυθμιστεί στο php.ini. Cannot write temporary file to disk. Αδυναμία εγγραφής προσωρινού αρχείου στο δίσκο. A PHP extension caused the upload to fail. Μια επέκταση PHP προκάλεσε αδυναμία ανεβάσματος. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείο ή περισσότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή περισσότερα. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείo ή λιγότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή λιγότερα. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχείo.|Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχεία. Invalid card number. Μη έγκυρος αριθμός κάρτας. Unsupported card type or invalid card number. Μη υποστηριζόμενος τύπος κάρτας ή μη έγκυρος αριθμός κάρτας. This is not a valid International Bank Account Number (IBAN). Αυτό δεν αντιστοιχεί σε έκγυρο διεθνή αριθμό τραπεζικού λογαριασμού (IBAN). This value is not a valid ISBN-10. Αυτό δεν είναι έγκυρος κωδικός ISBN-10. This value is not a valid ISBN-13. Αυτό δεν είναι έγκυρος κωδικός ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Αυτό δεν είναι ούτε έγκυρος κωδικός ISBN-10 ούτε έγκυρος κωδικός ISBN-13. This value is not a valid ISSN. Αυτό δεν είναι έγκυρος κωδικός ISSN. This value is not a valid currency. Αυτό δεν αντιστοιχεί σε έγκυρο νόμισμα. This value should be equal to {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι ίση με {{ compared_value }}. This value should be greater than {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη από {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη ή ίση με {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μικρότερη από {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μικρότερη ή ίση με {{ compared_value }}. This value should not be equal to {{ compared_value }}. Αυτή η τιμή δεν θα πρέπει να είναι ίση με {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Αυτή η τιμή δεν πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}. PK!9>55DSymfony/Component/Validator/Resources/translations/validators.da.xlfnu[ This value should be false. Værdien skal være falsk. This value should be true. Værdien skal være sand. This value should be of type {{ type }}. Værdien skal være af typen {{ type }}. This value should be blank. Værdien skal være blank. The value you selected is not a valid choice. Værdien skal være en af de givne muligheder. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du skal vælge mindst {{ limit }} muligheder. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan højest vælge {{ limit }} muligheder. One or more of the given values is invalid. En eller flere af de oplyste værdier er ugyldige. The fields {{ fields }} were not expected. Felterne {{ fields }} var ikke forventet. The fields {{ fields }} are missing. Felterne {{ fields }} mangler. This value is not a valid date. Værdien er ikke en gyldig dato. This value is not a valid datetime. Værdien er ikke en gyldig dato og tid. This value is not a valid email address. Værdien er ikke en gyldig e-mail adresse. The file could not be found. Filen kunne ikke findes. The file is not readable. Filen kan ikke læses. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor ({{ size }} {{ suffix }}). Tilladte maksimale størrelse {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mimetypen af filen er ugyldig ({{ type }}). Tilladte mimetyper er {{ types }}. This value should be {{ limit }} or less. Værdien skal være {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Værdien er for lang. Den skal have {{ limit }} bogstaver eller mindre. This value should be {{ limit }} or more. Værdien skal være {{ limit }} eller mere. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Værdien er for kort. Den skal have {{ limit }} tegn eller flere. This value should not be blank. Værdien må ikke være blank. This value should not be null. Værdien må ikke være tom (null). This value should be null. Værdien skal være tom (null). This value is not valid. Værdien er ikke gyldig. This value is not a valid time. Værdien er ikke en gyldig tid. This value is not a valid URL. Værdien er ikke en gyldig URL. The two values should be equal. De to værdier skal være ens. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}. The file is too large. Filen er for stor. The file could not be uploaded. Filen kunne ikke blive uploadet. This value should be a valid number. Værdien skal være et gyldigt tal. This file is not a valid image. Filen er ikke gyldigt billede. This is not a valid IP address. Dette er ikke en gyldig IP adresse. This value is not a valid language. Værdien er ikke et gyldigt sprog. This value is not a valid locale. Værdien er ikke en gyldig lokalitet. This value is not a valid country. Værdien er ikke et gyldigt land. This value is already used. Værdien er allerede i brug. The size of the image could not be detected. Størrelsen på billedet kunne ikke detekteres. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Billedbredden er for stor ({{ width }}px). Tilladt maksimumsbredde er {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Billedebredden er for lille ({{ width }}px). Forventet minimumshøjde er {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Billedhøjden er for stor ({{ height }}px). Tilladt maksimumshøjde er {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Billedhøjden er for lille ({{ height }}px). Forventet minimumshøjde er {{ min_height }}px. This value should be the user current password. Værdien skal være brugerens nuværende password. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Værdien skal have præcis {{ limit }} tegn. The file was only partially uploaded. Filen var kun delvis uploadet. No file was uploaded. Ingen fil blev uploadet. No temporary folder was configured in php.ini. Ingen midlertidig mappe er konfigureret i php.ini. Cannot write temporary file to disk. Kan ikke skrive midlertidig fil til disk. A PHP extension caused the upload to fail. En PHP udvidelse forårsagede fejl i upload. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Denne samling skal indeholde {{ limit }} element eller flere.|Denne samling skal indeholde {{ limit }} elementer eller flere. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Denne samling skal indeholde {{ limit }} element eller mindre.|Denne samling skal indeholde {{ limit }} elementer eller mindre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Denne samling skal indeholde præcis {{ limit }} element.|Denne samling skal indeholde præcis {{ limit }} elementer. Invalid card number. Ugyldigt kortnummer. Unsupported card type or invalid card number. Ikke-understøttet korttype eller ugyldigt kortnummer. This is not a valid International Bank Account Number (IBAN). Det er ikke en gyldig International Bank Account Number (IBAN). This value is not a valid ISBN-10. Værdien er ikke en gyldig ISBN-10. This value is not a valid ISBN-13. Værdien er ikke en gyldig ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Værdien er hverken en gyldig ISBN-10 eller en gyldig ISBN-13. This value is not a valid ISSN. Værdien er ikke en gyldig ISSN. PK!AADSymfony/Component/Validator/Resources/translations/validators.ja.xlfnu[ This value should be false. falseでなければなりません。 This value should be true. trueでなければなりません。 This value should be of type {{ type }}. 型は{{ type }}でなければなりません。 This value should be blank. 空でなければなりません。 The value you selected is not a valid choice. 有効な選択肢ではありません。 You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. {{ limit }}個以上選択してください。 You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. {{ limit }}個以内で選択してください。 One or more of the given values is invalid. 無効な選択肢が含まれています。 The fields {{ fields }} were not expected. フィールド{{ fields }}は無効です。 The fields {{ fields }} are missing. フィールド{{ fields }}は必須です。 This value is not a valid date. 有効な日付ではありません。 This value is not a valid datetime. 有効な日時ではありません。 This value is not a valid email address. 有効なメールアドレスではありません。 The file could not be found. ファイルが見つかりません。 The file is not readable. ファイルを読み込めません。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. ファイルのサイズが大きすぎます({{ size }} {{ suffix }})。有効な最大サイズは{{ limit }} {{ suffix }}です。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. ファイルのMIMEタイプが無効です({{ type }})。有効なMIMEタイプは{{ types }}です。 This value should be {{ limit }} or less. {{ limit }}以下でなければなりません。 This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. 値が長すぎます。{{ limit }}文字以内でなければなりません。 This value should be {{ limit }} or more. {{ limit }}以上でなければなりません。 This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. 値が短すぎます。{{ limit }}文字以上でなければなりません。 This value should not be blank. 空であってはなりません。 This value should not be null. nullであってはなりません。 This value should be null. nullでなければなりません。 This value is not valid. 有効な値ではありません。 This value is not a valid time. 有効な時刻ではありません。 This value is not a valid URL. 有効なURLではありません。 The two values should be equal. 2つの値が同じでなければなりません。 The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. ファイルのサイズが大きすぎます。有効な最大サイズは{{ limit }} {{ suffix }}です。 The file is too large. ファイルのサイズが大きすぎます。 The file could not be uploaded. ファイルをアップロードできませんでした。 This value should be a valid number. 有効な数字ではありません。 This file is not a valid image. ファイルが画像ではありません。 This is not a valid IP address. 有効なIPアドレスではありません。 This value is not a valid language. 有効な言語名ではありません。 This value is not a valid locale. 有効なロケールではありません。 This value is not a valid country. 有効な国名ではありません。 This value is already used. 既に使用されています。 The size of the image could not be detected. 画像のサイズが検出できません。 The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. 画像の幅が大きすぎます({{ width }}ピクセル)。{{ max_width }}ピクセルまでにしてください。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. 画像の幅が小さすぎます({{ width }}ピクセル)。{{ min_width }}ピクセル以上にしてください。 The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. 画像の高さが大きすぎます({{ height }}ピクセル)。{{ max_height }}ピクセルまでにしてください。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. 画像の高さが小さすぎます({{ height }}ピクセル)。{{ min_height }}ピクセル以上にしてください。 This value should be the user current password. ユーザーの現在のパスワードでなければなりません。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. ちょうど{{ limit }}文字でなければなりません。 The file was only partially uploaded. ファイルのアップロードは完全ではありません。 No file was uploaded. ファイルがアップロードされていません。 No temporary folder was configured in php.ini. php.iniで一時フォルダが設定されていません。 Cannot write temporary file to disk. 一時ファイルをディスクに書き込むことができません。 A PHP extension caused the upload to fail. PHP拡張によってアップロードに失敗しました。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. {{ limit }}個以上の要素を含んでなければいけません。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. 要素は{{ limit }}個までです。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. 要素はちょうど{{ limit }}個でなければなりません。 Invalid card number. 無効なカード番号です。 Unsupported card type or invalid card number. 未対応のカード種類又は無効なカード番号です。 This is not a valid International Bank Account Number (IBAN). 有効なIBANコードではありません。 This value is not a valid ISBN-10. 有効なISBN-10コードではありません。 This value is not a valid ISBN-13. 有効なISBN-13コードではありません。 This value is neither a valid ISBN-10 nor a valid ISBN-13. 有効なISBN-10コード又はISBN-13コードではありません。 This value is not a valid ISSN. 有効なISSNコードではありません。 This value is not a valid currency. 有効な貨幣ではありません。 This value should be equal to {{ compared_value }}. {{ compared_value }}と等しくなければなりません。 This value should be greater than {{ compared_value }}. {{ compared_value }}より大きくなければなりません。 This value should be greater than or equal to {{ compared_value }}. {{ compared_value }}以上でなければなりません。 This value should be identical to {{ compared_value_type }} {{ compared_value }}. {{ compared_value_type }}としての{{ compared_value }}と等しくなければなりません。 This value should be less than {{ compared_value }}. {{ compared_value }}未満でなければなりません。 This value should be less than or equal to {{ compared_value }}. {{ compared_value }}以下でなければなりません。 This value should not be equal to {{ compared_value }}. {{ compared_value }}と等しくてはいけません。 This value should not be identical to {{ compared_value_type }} {{ compared_value }}. {{ compared_value_type }}としての{{ compared_value }}と等しくてはいけません。 PK!Q>??DSymfony/Component/Validator/Resources/translations/validators.sv.xlfnu[ This value should be false. Värdet ska vara falskt. This value should be true. Värdet ska vara sant. This value should be of type {{ type }}. Värdet ska vara av typen {{ type }}. This value should be blank. Värdet ska vara tomt. The value you selected is not a valid choice. Värdet ska vara ett av de givna valen. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du måste välja minst {{ limit }} val.|Du måste välja minst {{ limit }} val. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan som mest välja {{ limit }} val.|Du kan som mest välja {{ limit }} val. One or more of the given values is invalid. Ett eller fler av de angivna värdena är ogiltigt. The fields {{ fields }} were not expected. Fälten {{ fields }} var oväntade. The fields {{ fields }} are missing. Fälten {{ fields }} saknas. This value is not a valid date. Värdet är inte ett giltigt datum. This value is not a valid datetime. Värdet är inte ett giltigt datum med tid. This value is not a valid email address. Värdet är inte en giltig epost-adress. The file could not be found. Filen kunde inte hittas. The file is not readable. Filen är inte läsbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Filen är för stor ({{ size }} {{ suffix }}). Största tillåtna storlek är {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Filens MIME-typ ({{ type }}) är ogiltig. De tillåtna typerna är {{ types }}. This value should be {{ limit }} or less. Värdet ska vara {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Värdet är för långt. Det ska ha {{ limit }} tecken eller färre.|Värdet är för långt. Det ska ha {{ limit }} tecken eller färre. This value should be {{ limit }} or more. Värdet ska vara {{ limit }} eller mer. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Värdet är för kort. Det ska ha {{ limit }} tecken eller mer.|Värdet är för kort. Det ska ha {{ limit }} tecken eller mer. This value should not be blank. Värdet kan inte vara tomt. This value should not be null. Värdet kan inte vara null. This value should be null. Värdet ska vara null. This value is not valid. Värdet är inte giltigt. This value is not a valid time. Värdet är inte en giltig tid. This value is not a valid URL. Värdet är inte en giltig URL. The two values should be equal. De två värdena måste vara lika. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Filen är för stor. Tillåten maximal storlek är {{ limit }} {{ suffix }}. The file is too large. Filen är för stor. The file could not be uploaded. Filen kunde inte laddas upp. This value should be a valid number. Värdet ska vara ett giltigt nummer. This file is not a valid image. Filen är ingen giltig bild. This is not a valid IP address. Det här är inte en giltig IP-adress. This value is not a valid language. Värdet är inte ett giltigt språk. This value is not a valid locale. Värdet är inte en giltig plats. This value is not a valid country. Värdet är inte ett giltigt land. This value is already used. Värdet används redan. The size of the image could not be detected. Det gick inte att fastställa storleken på bilden. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Bildens bredd är för stor ({{ width }}px). Tillåten maximal bredd är {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Bildens bredd är för liten ({{ width }}px). Minsta förväntade bredd är {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Bildens höjd är för stor ({{ height }}px). Tillåten maximal bredd är {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Bildens höjd är för liten ({{ height }}px). Minsta förväntade höjd är {{ min_height }}px. This value should be the user current password. Värdet ska vara användarens nuvarande lösenord. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Värdet ska ha exakt {{ limit }} tecken.|Värdet ska ha exakt {{ limit }} tecken. The file was only partially uploaded. Filen laddades bara upp delvis. No file was uploaded. Ingen fil laddades upp. No temporary folder was configured in php.ini. Det finns ingen temporär mapp konfigurerad i php.ini. Cannot write temporary file to disk. Kan inte skriva temporär fil till disken. A PHP extension caused the upload to fail. En PHP extension gjorde att uppladdningen misslyckades. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Den här samlingen ska innehålla {{ limit }} element eller mer.|Den här samlingen ska innehålla {{ limit }} element eller mer. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Den här samlingen ska innehålla {{ limit }} element eller mindre.|Den här samlingen ska innehålla {{ limit }} element eller mindre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Den här samlingen ska innehålla exakt {{ limit }} element.|Den här samlingen ska innehålla exakt {{ limit }} element. Invalid card number. Ogiltigt kortnummer. Unsupported card type or invalid card number. Okänd korttyp eller ogiltigt kortnummer. This is not a valid International Bank Account Number (IBAN). Det här är inte en giltig International Bank Account Number (IBANK). This value is not a valid ISBN-10. Värdet är inte en giltig ISBN-10. This value is not a valid ISBN-13. Värdet är inte en giltig ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Värdet är varken en giltig ISBN-10 eller en giltig ISBN-13. This value is not a valid ISSN. Värdet är inte en giltig ISSN. This value is not a valid currency. Värdet är inte en giltig valuta. This value should be equal to {{ compared_value }}. Värdet ska vara detsamma som {{ compared_value }}. This value should be greater than {{ compared_value }}. Värdet ska vara större än {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Värdet ska bara större än eller detsamma som {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Värdet ska vara identiskt till {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Värdet ska vara mindre än {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Värdet ska vara mindre än eller detsamma som {{ compared_value }}. This value should not be equal to {{ compared_value }}. Värdet ska inte vara detsamma som {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Värdet ska inte vara identiskt med {{ compared_value_type }} {{ compared_value }}. PK!v_w,w,DSymfony/Component/Validator/Resources/translations/validators.hy.xlfnu[ This value should be false. Արժեքը պետք է լինի կեղծ. This value should be true. Արժեքը պետք է լինի ճշմարիտ. This value should be of type {{ type }}. Արժեքը պետք է լինի {{ type }} տեսակի. This value should be blank. Արժեքը պետք է լինի դատարկ. The value you selected is not a valid choice. Ձեր ընտրած արժեքը անթույլատրելի է. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Դուք պետք է ընտրեք ամենաքիչը {{ limit }} տարբերակներ. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Դուք պետք է ընտրեք ոչ ավելի քան {{ limit }} տարբերակներ. One or more of the given values is invalid. Մեկ կամ ավելի տրված արժեքները անթույլատրելի են. The fields {{ fields }} were not expected. {{ fields }} տողերը չէին սպասվում. The fields {{ fields }} are missing. {{ fields }} տողերը բացակայում են. This value is not a valid date. Արժեքը սխալ ամսաթիվ է. This value is not a valid datetime. Ամսաթվի և ժամանակի արժեքը անթույլատրելի է. This value is not a valid email address. Էլ-փոստի արժեքը անթույլատրելի է. The file could not be found. Ֆայլը չի գտնվել. The file is not readable. Ֆայլը անընթեռնելի է. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Ֆայլը չափազանց մեծ է ({{ size }} {{ suffix }}): Մաքսիմալ թույլատրելի չափսը՝ {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. MIME-տեսակը անթույլատրելի է({{ type }}): Ֆայլերի թույլատրելի MIME-տեսակներն են: {{ types }}. This value should be {{ limit }} or less. Արժեքը պետք է լինի {{ limit }} կամ փոքր. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Արժեքը չափազանց երկար է: Պետք է լինի {{ limit }} կամ ավել սիմվոլներ. This value should be {{ limit }} or more. Արժեքը պետ է լինի {{ limit }} կամ շատ. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Արժեքը չափազանց կարճ է: Պետք է լինի {{ limit }} կամ ավելի սիմվոլներ. This value should not be blank. Արժեքը չպետք է դատարկ լինի. This value should not be null. Արժեքը չպետք է լինի null. This value should be null. Արժեքը պետք է լինի null. This value is not valid. Անթույլատրելի արժեք. This value is not a valid time. Ժամանակի արժեքը անթույլատրելի է. This value is not a valid URL. Արժեքը URL չէ. The two values should be equal. Երկու արժեքները պետք է նույնը լինեն. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ֆայլը չափազանց մեծ է: Մաքսիմալ թույլատրելի չափսը {{ limit }} {{ suffix }} է. The file is too large. Ֆայլը չափազանց մեծ է. The file could not be uploaded. Ֆայլը չի կարող բեռնվել. This value should be a valid number. Արժեքը պետք է լինի թիվ. This value is not a valid country. Արժեքը պետք է լինի երկիր. This file is not a valid image. Ֆայլը նկարի թույլատրելի ֆորմատ չէ. This is not a valid IP address. Արժեքը թույլատրելի IP հասցե չէ. This value is not a valid language. Արժեքը թույլատրելի լեզու չէ. This value is not a valid locale. Արժեքը չի հանդիսանում թույլատրելի տեղայնացում. This value is already used. Այդ արժեքը արդեն օգտագործվում է. The size of the image could not be detected. Նկարի չափսերը չստացվեց որոշել. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Նկարի լայնությունը չափազանց մեծ է({{ width }}px). Մաքսիմալ չափն է {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Նկարի լայնությունը չափազանց փոքր է ({{ width }}px). Մինիմալ չափն է {{ min_ width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Նկարի բարձրությունը չափազանց մեծ է ({{ height }}px). Մաքսիմալ չափն է {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Նկարի բարձրությունը չափազանց փոքր է ({{ height }}px). Մինիմալ չափն է {{ min_height }}px. This value should be the user current password. Այս արժեքը պետք է լինի օգտագործողի ներկա ծածկագիրը. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Այս արժեքը պետք է ունենա ճիշտ {{ limit }} սիմվոլներ. PK!OODSymfony/Component/Validator/Resources/translations/validators.ar.xlfnu[ This value should be false. هذه القيمة يجب أن تكون خاطئة. This value should be true. هذه القيمة يجب أن تكون حقيقية. This value should be of type {{ type }}. هذه القيمة يجب ان تكون من نوع {{ type }}. This value should be blank. هذه القيمة يجب ان تكون فارغة. The value you selected is not a valid choice. القيمة المختارة ليست خيارا صحيحا. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيارات على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيارات على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر. One or more of the given values is invalid. واحد أو أكثر من القيم المعطاه خاطئ. The fields {{ fields }} were not expected. القيم {{ fields }} لم تكن متوقعة. The fields {{ fields }} are missing. القيم {{ fields }} مفقودة. This value is not a valid date. هذه القيمة ليست تاريخا صالحا. This value is not a valid datetime. هذه القيمة ليست تاريخا و وقتا صالحا. This value is not a valid email address. هذه القيمة ليست عنوان بريد إلكتروني صحيح. The file could not be found. لا يمكن العثور على الملف. The file is not readable. الملف غير قابل للقراءة. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. الملف كبير جدا ({{ size }} {{ suffix }}).اقصى مساحه مسموح بها ({{ limit }} {{ suffix }}). The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. نوع الملف غير صحيح ({{ type }}). الانواع المسموح بها هى {{ types }}. This value should be {{ limit }} or less. هذه القيمة يجب ان تكون {{ limit }} او اقل. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حروف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل. This value should be {{ limit }} or more. هذه القيمة يجب ان تكون {{ limit }} او اكثر. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حروف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر. This value should not be blank. هذه القيمة يجب الا تكون فارغة. This value should not be null. هذه القيمة يجب الا تكون فارغة. This value should be null. هذه القيمة يجب ان تكون فارغة. This value is not valid. هذه القيمة غير صحيحة. This value is not a valid time. هذه القيمة ليست وقت صحيح. This value is not a valid URL. هذه القيمة ليست رابط الكترونى صحيح. The two values should be equal. القيمتان يجب ان تكونا متساويتان. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. الملف كبير جدا. اقصى مساحه مسموح بها {{ limit }} {{ suffix }}. The file is too large. الملف كبير جدا. The file could not be uploaded. لم استطع استقبال الملف. This value should be a valid number. هذه القيمة يجب ان تكون رقم. This file is not a valid image. هذا الملف ليس صورة صحيحة. This is not a valid IP address. هذه القيمة ليست عنوان رقمى صحيح. This value is not a valid language. هذه القيمة ليست لغة صحيحة. This value is not a valid locale. هذه القيمة ليست موقع صحيح. This value is not a valid country. هذه القيمة ليست بلدا صالحا. This value is already used. هذه القيمة مستخدمة بالفعل. The size of the image could not be detected. لم استطع معرفة حجم الصورة. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. عرض الصورة كبير جدا ({{ width }}px). اقصى عرض مسموح به هو{{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. عرض الصورة صغير جدا ({{ width }}px). اقل عرض مسموح به هو{{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. طول الصورة كبير جدا ({{ height }}px). اقصى طول مسموح به هو{{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. طول الصورة صغير جدا ({{ height }}px). اقل طول مسموح به هو{{ min_height }}px. This value should be the user current password. هذه القيمة يجب ان تكون كلمة سر المستخدم الحالية. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حروف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط. The file was only partially uploaded. تم استقبال جزء من الملف فقط. No file was uploaded. لم يتم ارسال اى ملف. No temporary folder was configured in php.ini. لم يتم تهيئة حافظة مؤقتة فى ملف php.ini. Cannot write temporary file to disk. لم استطع كتابة الملف المؤقت. A PHP extension caused the upload to fail. احد اضافات PHP تسببت فى فشل استقبال الملف. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط. Invalid card number. رقم البطاقه غير صحيح. Unsupported card type or invalid card number. نوع البطاقه غير مدعوم او الرقم غير صحيح. This is not a valid International Bank Account Number (IBAN). الرقم IBAN (رقم الحساب المصرفي الدولي) الذي تم إدخاله غير صالح. This value is not a valid ISBN-10. هذه القيمة ليست ISBN-10 صالحة. This value is not a valid ISBN-13. هذه القيمة ليست ISBN-13 صالحة. This value is neither a valid ISBN-10 nor a valid ISBN-13. هذه القيمة ليست ISBN-10 صالحة ولا ISBN-13 صالحة. This value is not a valid ISSN. هذه القيمة ليست ISSN صالحة. This value is not a valid currency. العُملة غير صحيحة. This value should be equal to {{ compared_value }}. القيمة يجب ان تساوي {{ compared_value }}. This value should be greater than {{ compared_value }}. القيمة يجب ان تكون اعلي من {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. القيمة يجب ان تكون مساوية او اعلي من {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. القيمة يجب ان تطابق {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. القيمة يجب ان تكون اقل من {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. القيمة يجب ان تساوي او تقل عن {{ compared_value }}. This value should not be equal to {{ compared_value }}. القيمة يجب ان لا تساوي {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. القيمة يجب ان لا تطابق {{ compared_value_type }} {{ compared_value }}. PK!1^44ISymfony/Component/Validator/Resources/translations/validators.sr_Latn.xlfnu[ This value should be false. Vrednost treba da bude netačna. This value should be true. Vrednost treba da bude tačna. This value should be of type {{ type }}. Vrednost treba da bude tipa {{ type }}. This value should be blank. Vrednost treba da bude prazna. The value you selected is not a valid choice. Vrednost treba da bude jedna od ponuđenih. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Izaberite bar {{ limit }} mogućnost.|Izaberite bar {{ limit }} mogućnosti.|Izaberite bar {{ limit }} mogućnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Izaberite najviše {{ limit }} mogućnost.|Izaberite najviše {{ limit }} mogućnosti.|Izaberite najviše {{ limit }} mogućnosti. One or more of the given values is invalid. Jedna ili više vrednosti je nevalidna. The fields {{ fields }} were not expected. Polja {{ fields }} nisu bila očekivana. The fields {{ fields }} are missing. Polja {{ fields }} nedostaju. This value is not a valid date. Vrednost nije validan datum. This value is not a valid datetime. Vrednost nije validan datum-vreme. This value is not a valid email address. Vrednost nije validna adresa elektronske pošte. The file could not be found. Datoteka ne može biti pronađena. The file is not readable. Datoteka nije čitljiva. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime tip datoteke nije validan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}. This value should be {{ limit }} or less. Vrednost treba da bude {{ limit }} ili manje. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Vrednost je predugačka. Treba da ima {{ limit }} karakter ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje. This value should be {{ limit }} or more. Vrednost treba da bude {{ limit }} ili više. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Vrednost je prekratka. Treba da ima {{ limit }} karakter ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više. This value should not be blank. Vrednost ne treba da bude prazna. This value should not be null. Vrednost ne treba da bude null. This value should be null. Vrednost treba da bude null. This value is not valid. Vrednost je nevalidna. This value is not a valid time. Vrednost nije validno vreme. This value is not a valid URL. Vrednost nije validan URL. The two values should be equal. Obe vrednosti treba da budu jednake. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The file is too large. Datoteka je prevelika. The file could not be uploaded. Datoteka ne može biti otpremljena. This value should be a valid number. Vrednost treba da bude validan broj. This file is not a valid image. Ova datoteka nije validna slika. This is not a valid IP address. Ovo nije validna IP adresa. This value is not a valid language. Vrednost nije validan jezik. This value is not a valid locale. Vrednost nije validan lokal. This value is not a valid country. Vrednost nije validna zemlja. This value is already used. Vrednost je već iskorišćena. The size of the image could not be detected. Veličina slike ne može biti određena. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Širina slike je prevelika ({{ width }}px). Najeća dozvoljena širina je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Visina slike je prevelika ({{ height }}px). Najeća dozvoljena visina je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px. This value should be the user current password. Vrednost treba da bude trenutna korisnička lozinka. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Vrednost treba da ima tačno {{ limit }} karakter.|Vrednost treba da ima tačno {{ limit }} karaktera.|Vrednost treba da ima tačno {{ limit }} karaktera. The file was only partially uploaded. Datoteka je samo parcijalno otpremljena. No file was uploaded. Datoteka nije otpremljena. No temporary folder was configured in php.ini. Privremeni direktorijum nije konfigurisan u php.ini. Cannot write temporary file to disk. Nemoguće pisanje privremene datoteke na disk. A PHP extension caused the upload to fail. PHP ekstenzija je prouzrokovala neuspeh otpremanja datoteke. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ova kolekcija treba da sadrži tačno {{ limit }} element.|Ova kolekcija treba da sadrži tačno {{ limit }} elementa.|Ova kolekcija treba da sadrži tačno {{ limit }} elemenata. Invalid card number. Nevalidan broj kartice. Unsupported card type or invalid card number. Nevalidan broj kartice ili tip kartice nije podržan. PK!@T'%BBDSymfony/Component/Validator/Resources/translations/validators.vi.xlfnu[ This value should be false. Giá trị này phải là sai. This value should be true. Giá trị này phải là đúng. This value should be of type {{ type }}. Giá trị này phải là kiểu {{ type }}. This value should be blank. Giá trị này phải rỗng. The value you selected is not a valid choice. Giá trị bạn vừa chọn không hợp lệ. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Bạn phải chọn ít nhất {{ limit }} lựa chọn.|Bạn phải chọn ít nhất {{ limit }} lựa chọn. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Bạn phải chọn nhiều nhất {{ limit }} lựa chọn.|Bạn phải chọn nhiều nhất {{ limit }} lựa chọn. One or more of the given values is invalid. Một hoặc nhiều giá trị được chọn không hợp lệ. The fields {{ fields }} were not expected. Trường có tên {{ fields }} không được chấp nhận. The fields {{ fields }} are missing. Trường có tên {{ fields }} không tìm thấy. This value is not a valid date. Giá trị không phải là ngày hợp lệ. This value is not a valid datetime. Giá trị không phải là ngày tháng hợp lệ. This value is not a valid email address. Giá trị này không phải là email hợp lệ. The file could not be found. Tập tin không tìm thấy. The file is not readable. Tập tin không thể đọc được. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Tập tin quá lớn ({{ size }} {{ suffix }}). Kích thước tối đa cho phép {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Kiểu mime của tập tin không hợp lệ ({{ type }}). Kiểu hợp lệ là {{ types }}. This value should be {{ limit }} or less. Giá trị phải bằng hoặc nhỏ hơn {{ limit }}. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự.|Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự. This value should be {{ limit }} or more. Giá trị phải lớn hơn hoặc bằng {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự.|Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự. This value should not be blank. Giá trị không được phép để trống. This value should not be null. Giá trị không được phép rỗng. This value should be null. Giá trị phải rỗng. This value is not valid. Giá trị không hợp lệ. This value is not a valid time. Giá trị không phải là thời gian hợp lệ. This value is not a valid URL. Giá trị không phải là địa chỉ URL hợp lệ. The two values should be equal. Hai giá trị phải bằng nhau. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Tập tin quá lớn. Kích thước tối đa cho phép là {{ limit }} {{ suffix }}. The file is too large. Tập tin quá lớn. The file could not be uploaded. Tập tin không thể tải lên. This value should be a valid number. Giá trị phải là con số. This file is not a valid image. Tập tin không phải là hình ảnh. This is not a valid IP address. Địa chỉ IP không hợp lệ. This value is not a valid language. Giá trị không phải là ngôn ngữ hợp lệ. This value is not a valid locale. Giá trị không phải là một bản địa địa phương hợp lệ. This value is not a valid country. Giá trị không phải là nước hợp lệ. This value is already used. Giá trị đã được sử dụng. The size of the image could not be detected. Kích thước của hình ảnh không thể xác định. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Chiều rộng của hình quá lớn ({{ width }}px). Chiều rộng tối đa phải là {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Chiều rộng của hình quá thấp ({{ width }}px). Chiều rộng tối thiểu phải là {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Chiều cao của hình quá cao ({{ height }}px). Chiều cao tối đa phải là {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Chiều cao của hình quá thấp ({{ height }}px). Chiều cao tối thiểu phải là {{ min_height }}px. This value should be the user current password. Giá trị này phải là mật khẩu hiện tại của người dùng. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Giá trị phải có chính xác {{ limit }} kí tự.|Giá trị phải có chính xác {{ limit }} kí tự. The file was only partially uploaded. Tập tin chỉ được tải lên một phần. No file was uploaded. Tập tin không được tải lên. No temporary folder was configured in php.ini. Thư mục tạm không được định nghĩa trong php.ini. Cannot write temporary file to disk. Không thể ghi tập tin tạm ra đĩa. A PHP extension caused the upload to fail. Một PHP extension đã phá hỏng quá trình tải lên của tập tin. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Danh sách phải chứa chính xác {{ limit }} thành phần.|Danh sách phải chứa chính xác {{ limit }} thành phần. Invalid card number. Số thẻ không hợp lệ. Unsupported card type or invalid card number. Thẻ không được hỗ trợ hoặc số thẻ không hợp lệ. This is not a valid International Bank Account Number (IBAN). Giá trị không phải là International Bank Account Number (IBAN) hợp lệ. This value is not a valid ISBN-10. Giá trị không phải là ISBN-10 hợp lệ. This value is not a valid ISBN-13. Giá trị không phải là ISBN-13 hợp lệ. This value is neither a valid ISBN-10 nor a valid ISBN-13. Giá trị không phải là ISBN-10 hoặc ISBN-13 hợp lệ. This value is not a valid ISSN. Giá trị không là ISSN hợp lệ. This value is not a valid currency. Giá trị không phải là đơn vi tiền tệ hợp lệ. This value should be equal to {{ compared_value }}. Giá trị phải bằng {{ compared_value }}. This value should be greater than {{ compared_value }}. Giá trị phải lớn hơn {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Giá trị phải lớn hơn hoặc bằng {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Giá trị phải giống {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Giá trị phải bé hơn {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Giá trị không được phép nhỏ hơn hoặc bằng {{ compared_value }}. This value should not be equal to {{ compared_value }}. Giá trị không được phép bằng {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Giá trị không được phép giống như {{ compared_value_type }} {{ compared_value }}. PK!tý55DSymfony/Component/Validator/Resources/translations/validators.he.xlfnu[ This value should be false. הערך צריך להיות שקר. This value should be true. הערך צריך להיות אמת. This value should be of type {{ type }}. הערך צריך להיות מסוג {{ type }}. This value should be blank. הערך צריך להיות ריק. The value you selected is not a valid choice. הערך שבחרת אינו חוקי. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. אתה צריך לבחור לפחות {{ limit }} אפשרויות.|אתה צריך לבחור לפחות {{ limit }} אפשרויות. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. אתה צריך לבחור לכל היותר {{ limit }} אפשרויות.|אתה צריך לבחור לכל היותר {{ limit }} אפשרויות. One or more of the given values is invalid. אחד או יותר מהערכים אינו חוקי. The fields {{ fields }} were not expected. השדות {{ fields }} לא היו צפויים. The fields {{ fields }} are missing. השדות {{ fields }} חסרים. This value is not a valid date. הערך אינו תאריך חוקי. This value is not a valid datetime. הערך אינו תאריך ושעה חוקיים. This value is not a valid email address. כתובת המייל אינה תקינה. The file could not be found. הקובץ לא נמצא. The file is not readable. לא ניתן לקרוא את הקובץ. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. הקובץ גדול מדי ({{ size }} {{ suffix }}). הגודל המרבי המותר הוא {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. סוג MIME של הקובץ אינו חוקי ({{ type }}). מותרים סוגי MIME {{ types }}. This value should be {{ limit }} or less. הערך צריל להכיל {{ limit }} תווים לכל היותר. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר.|הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר. This value should be {{ limit }} or more. הערך צריך להכיל {{ limit }} תווים לפחות. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות.|הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות. This value should not be blank. הערך לא אמור להיות ריק. This value should not be null. הערך לא אמור להיות ריק. This value should be null. הערך צריך להיות ריק. This value is not valid. הערך אינו חוקי. This value is not a valid time. הערך אינו זמן תקין. This value is not a valid URL. זאת אינה כתובת אתר תקינה. The two values should be equal. שני הערכים צריכים להיות שווים. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. הקובץ גדול מדי. הגודל המרבי המותר הוא {{ limit }} {{ suffix }}. The file is too large. הקובץ גדול מדי. The file could not be uploaded. לא ניתן לעלות את הקובץ. This value should be a valid number. הערך צריך להיות מספר חוקי. This file is not a valid image. הקובץ הזה אינו תמונה תקינה. This is not a valid IP address. זו אינה כתובת IP חוקית. This value is not a valid language. הערך אינו שפה חוקית. This value is not a valid locale. הערך אינו אזור תקף. This value is not a valid country. הערך אינו ארץ חוקית. This value is already used. הערך כבר בשימוש. The size of the image could not be detected. לא ניתן לקבוע את גודל התמונה. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. רוחב התמונה גדול מדי ({{ width }}px). הרוחב המקסימלי הוא {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. רוחב התמונה קטן מדי ({{ width }}px). הרוחב המינימלי הוא {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. גובה התמונה גדול מדי ({{ height }}px). הגובה המקסימלי הוא {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. גובה התמונה קטן מדי ({{ height }}px). הגובה המינימלי הוא {{ min_height }}px. This value should be the user current password. הערך צריך להיות סיסמת המשתמש הנוכחי. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. הערך צריך להיות בדיוק {{ limit }} תווים.|הערך צריך להיות בדיוק {{ limit }} תווים. The file was only partially uploaded. הקובץ הועלה באופן חלקי. No file was uploaded. הקובץ לא הועלה. No temporary folder was configured in php.ini. לא הוגדרה תיקייה זמנית ב php.ini. Cannot write temporary file to disk. לא ניתן לכתוב קובץ זמני לדיסק. A PHP extension caused the upload to fail. סיומת PHP גרם להעלאה להיכשל. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. האוסף אמור להכיל {{ limit }} אלמנטים או יותר.|האוסף אמור להכיל {{ limit }} אלמנטים או יותר. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. האוסף אמור להכיל {{ limit }} אלמנטים או פחות.|האוסף אמור להכיל {{ limit }} אלמנטים או פחות. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. האוסף צריך להכיל בדיוק {{ limit }} אלמנטים.|האוסף צריך להכיל בדיוק {{ limit }} אלמנטים. Invalid card number. מספר הכרטיס אינו חוקי. Unsupported card type or invalid card number. סוג הכרטיס אינו נתמך או לא חוקי. PK!D<Symfony/Component/Validator/Constraints/NotNullValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class NotNullValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { $this->context->addViolation($constraint->message); } } } PK!D~SS2Symfony/Component/Validator/Constraints/Choice.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Choice extends Constraint { public $choices; public $callback; public $multiple = false; public $strict = false; public $min = null; public $max = null; public $message = 'The value you selected is not a valid choice.'; public $multipleMessage = 'One or more of the given values is invalid.'; public $minMessage = 'You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.'; public $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.'; /** * {@inheritDoc} */ public function getDefaultOption() { return 'choices'; } } PK!~%ɋ1Symfony/Component/Validator/Constraints/Valid.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Valid extends Constraint { public $traverse = true; public $deep = false; public function __construct($options = null) { if (is_array($options) && array_key_exists('groups', $options)) { throw new ConstraintDefinitionException(sprintf('The option "groups" is not supported by the constraint %s', __CLASS__)); } parent::__construct($options); } } PK!+ 6Symfony/Component/Validator/Constraints/NotEqualTo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class NotEqualTo extends AbstractComparison { public $message = 'This value should not be equal to {{ compared_value }}.'; } PK!mԼ\\CSymfony/Component/Validator/Constraints/NotIdenticalToValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values aren't identical (!==). * * @author Daniel Holmes */ class NotIdenticalToValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 !== $value2; } } PK!Ŀ:KK6Symfony/Component/Validator/Constraints/Expression.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Fabien Potencier * @author Bernhard Schussek */ class Expression extends Constraint { public $message = 'This value is not valid.'; public $expression; /** * {@inheritDoc} */ public function getDefaultOption() { return 'expression'; } /** * {@inheritDoc} */ public function getRequiredOptions() { return array('expression'); } /** * {@inheritDoc} */ public function getTargets() { return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT); } /** * {@inheritDoc} */ public function validatedBy() { return 'validator.expression'; } } PK!خ zz?Symfony/Component/Validator/Constraints/Collection/Optional.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Optional as BaseOptional; /** * @Annotation * * @author Bernhard Schussek * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Validator\Constraints\Optional} instead. */ class Optional extends BaseOptional { } PK!\,yzz?Symfony/Component/Validator/Constraints/Collection/Required.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Required as BaseRequired; /** * @Annotation * * @author Bernhard Schussek * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Validator\Constraints\Required} instead. */ class Required extends BaseRequired { } PK! n?Symfony/Component/Validator/Constraints/CollectionValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class CollectionValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!is_array($value) && !($value instanceof \Traversable && $value instanceof \ArrayAccess)) { throw new UnexpectedTypeException($value, 'array or Traversable and ArrayAccess'); } $group = $this->context->getGroup(); foreach ($constraint->fields as $field => $fieldConstraint) { if ( // bug fix issue #2779 (is_array($value) && array_key_exists($field, $value)) || ($value instanceof \ArrayAccess && $value->offsetExists($field)) ) { foreach ($fieldConstraint->constraints as $constr) { $this->context->validateValue($value[$field], $constr, '['.$field.']', $group); } } elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) { $this->context->addViolationAt('['.$field.']', $constraint->missingFieldsMessage, array( '{{ field }}' => $field ), null); } } if (!$constraint->allowExtraFields) { foreach ($value as $field => $fieldValue) { if (!isset($constraint->fields[$field])) { $this->context->addViolationAt('['.$field.']', $constraint->extraFieldsMessage, array( '{{ field }}' => $field ), $fieldValue); } } } } } PK! y:Symfony/Component/Validator/Constraints/BlankValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class BlankValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if ('' !== $value && null !== $value) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!+0Symfony/Component/Validator/Constraints/Iban.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation */ class Iban extends Constraint { public $message = 'This is not a valid International Bank Account Number (IBAN).'; } PK! =Symfony/Component/Validator/Constraints/CallbackValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Validator for Callback constraint * * @author Bernhard Schussek * * @api */ class CallbackValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($object, Constraint $constraint) { if (null === $object) { return; } if (null !== $constraint->callback && null !== $constraint->methods) { throw new ConstraintDefinitionException( 'The Callback constraint supports either the option "callback" ' . 'or "methods", but not both at the same time.' ); } // has to be an array so that we can differentiate between callables // and method names if (null !== $constraint->methods && !is_array($constraint->methods)) { throw new UnexpectedTypeException($constraint->methods, 'array'); } $methods = $constraint->methods ?: array($constraint->callback); foreach ($methods as $method) { if (is_array($method) || $method instanceof \Closure) { if (!is_callable($method)) { throw new ConstraintDefinitionException(sprintf('"%s::%s" targeted by Callback constraint is not a valid callable', $method[0], $method[1])); } call_user_func($method, $object, $this->context); } else { if (!method_exists($object, $method)) { throw new ConstraintDefinitionException(sprintf('Method "%s" targeted by Callback constraint does not exist', $method)); } $reflMethod = new \ReflectionMethod($object, $method); if ($reflMethod->isStatic()) { $reflMethod->invoke(null, $object, $this->context); } else { $reflMethod->invoke($object, $this->context); } } } } } PK!}&&2Symfony/Component/Validator/Constraints/Length.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Length extends Constraint { public $maxMessage = 'This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.'; public $minMessage = 'This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.'; public $exactMessage = 'This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.'; public $max; public $min; public $charset = 'UTF-8'; public function __construct($options = null) { if (null !== $options && !is_array($options)) { $options = array( 'min' => $options, 'max' => $options, ); } parent::__construct($options); if (null === $this->min && null === $this->max) { throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max')); } } } PK!b=n n 9Symfony/Component/Validator/Constraints/IsbnValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether the value is a valid ISBN-10 or ISBN-13. * * @author The Whole Life To Learn * * @see https://en.wikipedia.org/wiki/Isbn */ class IsbnValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } if (!is_numeric($value)) { $value = str_replace('-', '', $value); } $validation = 0; $value = strtoupper($value); $valueLength = strlen($value); if (10 === $valueLength && null !== $constraint->isbn10) { for ($i = 0; $i < 10; $i++) { if ($value[$i] == 'X') { $validation += 10 * intval(10 - $i); } else { $validation += intval($value[$i]) * intval(10 - $i); } } if ($validation % 11 != 0) { if (null !== $constraint->isbn13) { $this->context->addViolation($constraint->bothIsbnMessage); } else { $this->context->addViolation($constraint->isbn10Message); } } } elseif (13 === $valueLength && null !== $constraint->isbn13) { for ($i = 0; $i < 13; $i += 2) { $validation += intval($value[$i]); } for ($i = 1; $i < 12; $i += 2) { $validation += intval($value[$i]) * 3; } if ($validation % 10 != 0) { if (null !== $constraint->isbn10) { $this->context->addViolation($constraint->bothIsbnMessage); } else { $this->context->addViolation($constraint->isbn13Message); } } } else { if (null !== $constraint->isbn10 && null !== $constraint->isbn13) { $this->context->addViolation($constraint->bothIsbnMessage); } elseif (null !== $constraint->isbn10) { $this->context->addViolation($constraint->isbn10Message); } else { $this->context->addViolation($constraint->isbn13Message); } } } } PK! * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value match or not given regexp pattern * * @author Bernhard Schussek * @author Joseph Bielawski * * @api */ class RegexValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if ($constraint->match xor preg_match($constraint->pattern, $value)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!^r  4Symfony/Component/Validator/Constraints/Language.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Language extends Constraint { public $message = 'This value is not a valid language.'; } PK!,,0Symfony/Component/Validator/Constraints/Isbn.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * * @author The Whole Life To Learn */ class Isbn extends Constraint { public $isbn10Message = 'This value is not a valid ISBN-10.'; public $isbn13Message = 'This value is not a valid ISBN-13.'; public $bothIsbnMessage = 'This value is neither a valid ISBN-10 nor a valid ISBN-13.'; public $isbn10; public $isbn13; public function __construct($options = null) { if (null !== $options && !is_array($options)) { $options = array( 'isbn10' => $options, 'isbn13' => $options, ); } parent::__construct($options); if (null === $this->isbn10 && null === $this->isbn13) { throw new MissingOptionsException(sprintf('Either option "isbn10" or "isbn13" must be given for constraint "%s".', __CLASS__), array('isbn10', 'isbn13')); } } } PK!EW^<Symfony/Component/Validator/Constraints/CountryValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid country code * * @author Bernhard Schussek * * @api */ class CountryValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $countries = Intl::getRegionBundle()->getCountryNames(); if (!isset($countries[$value])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!zet ?Symfony/Component/Validator/Constraints/ExpressionValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Validator\Exception\RuntimeException; /** * @author Fabien Potencier * @author Bernhard Schussek */ class ExpressionValidator extends ConstraintValidator { /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * @var ExpressionLanguage */ private $expressionLanguage; public function __construct(PropertyAccessorInterface $propertyAccessor) { $this->propertyAccessor = $propertyAccessor; } /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } $variables = array(); if (null === $this->context->getPropertyName()) { $variables['this'] = $value; } else { // Extract the object that the property belongs to from the object // graph $path = new PropertyPath($this->context->getPropertyPath()); $parentPath = $path->getParent(); $root = $this->context->getRoot(); $variables['value'] = $value; $variables['this'] = $parentPath ? $this->propertyAccessor->getValue($root, $parentPath) : $root; } if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) { $this->context->addViolation($constraint->message); } } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK! 00/Symfony/Component/Validator/Constraints/Url.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Url extends Constraint { public $message = 'This value is not a valid URL.'; public $protocols = array('http', 'https'); } PK!V`9Symfony/Component/Validator/Constraints/IbanValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Manuel Reinhard * @author Michael Schummel * @link http://www.michael-schummel.de/2007/10/05/iban-prufung-mit-php/ */ class IbanValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } // An IBAN without a country code is not an IBAN. if (0 === preg_match('/[A-Z]/', $value)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); return; } $teststring = preg_replace('/\s+/', '', $value); if (strlen($teststring) < 4) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); return; } $teststring = substr($teststring, 4) .strval(ord($teststring{0}) - 55) .strval(ord($teststring{1}) - 55) .substr($teststring, 2, 2); $teststring = preg_replace_callback('/[A-Z]/', function ($letter) { return intval(ord(strtolower($letter[0])) - 87); }, $teststring); $rest = 0; $strlen = strlen($teststring); for ($pos = 0; $pos < $strlen; $pos += 7) { $part = strval($rest).substr($teststring, $pos, 7); $rest = intval($part) % 97; } if ($rest != 1) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); return; } } } PK!vbb@Symfony/Component/Validator/Constraints/GreaterThanValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are greater than the previous (>). * * @author Daniel Holmes */ class GreaterThanValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 > $value2; } } PK!S탟0Symfony/Component/Validator/Constraints/Date.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Date extends Constraint { public $message = 'This value is not a valid date.'; } PK!|4XX8Symfony/Component/Validator/Constraints/UrlValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class UrlValidator extends ConstraintValidator { const PATTERN = '~^ (%s):// # protocol ( ([\pL\pN\pS-]+\.)+([\pL]|xn\-\-[\pL\pN-]+)+ # a domain name | # or \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # a IP address | # or \[ (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::)))) \] # a IPv6 address ) (:[0-9]+)? # a port (optional) (/?|/\S+) # a /, nothing or a / with something $~ixu'; /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $pattern = sprintf(static::PATTERN, implode('|', $constraint->protocols)); if (!preg_match($pattern, $value)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!w3Symfony/Component/Validator/Constraints/NotNull.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class NotNull extends Constraint { public $message = 'This value should not be null.'; } PK!Sn0Symfony/Component/Validator/Constraints/Null.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Null extends Constraint { public $message = 'This value should be null.'; } PK!oo:Symfony/Component/Validator/Constraints/RangeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek */ class RangeValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!is_numeric($value)) { $this->context->addViolation($constraint->invalidMessage, array( '{{ value }}' => $value, )); return; } if (null !== $constraint->max && $value > $constraint->max) { $this->context->addViolation($constraint->maxMessage, array( '{{ value }}' => $value, '{{ limit }}' => $constraint->max, )); return; } if (null !== $constraint->min && $value < $constraint->min) { $this->context->addViolation($constraint->minMessage, array( '{{ value }}' => $value, '{{ limit }}' => $constraint->min, )); } } } PK!  4Symfony/Component/Validator/Constraints/Currency.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Miha Vrhovnik * * @api */ class Currency extends Constraint { public $message = 'This value is not a valid currency.'; } PK!rs+4Symfony/Component/Validator/Constraints/Optional.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Bernhard Schussek */ class Optional extends Existence { } PK!449Symfony/Component/Validator/Constraints/IssnValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether the value is a valid ISSN. * * @author Antonio J. García Lagar * * @see https://en.wikipedia.org/wiki/Issn */ class IssnValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } // Compose regex pattern $digitsPattern = $constraint->requireHyphen ? '\d{4}-\d{3}' : '\d{4}-?\d{3}'; $checksumPattern = $constraint->caseSensitive ? '[\d|X]' : '[\d|X|x]'; $pattern = "/^".$digitsPattern.$checksumPattern."$/"; if (!preg_match($pattern, $value)) { $this->context->addViolation($constraint->message); } else { $digits = str_split(strtoupper(str_replace('-', '', $value))); $sum = 0; for ($i = 8; $i > 1; $i--) { $sum += $i * (int) array_shift($digits); } $checksum = 'X' == reset($digits) ? 10 : (int) reset($digits); if (0 != ($sum + $checksum) % 11) { $this->context->addViolation($constraint->message); } } } } PK!qp""0Symfony/Component/Validator/Constraints/File.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class File extends Constraint { public $maxSize = null; public $mimeTypes = array(); public $notFoundMessage = 'The file could not be found.'; public $notReadableMessage = 'The file is not readable.'; public $maxSizeMessage = 'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.'; public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.'; public $uploadIniSizeErrorMessage = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.'; public $uploadFormSizeErrorMessage = 'The file is too large.'; public $uploadPartialErrorMessage = 'The file was only partially uploaded.'; public $uploadNoFileErrorMessage = 'No file was uploaded.'; public $uploadNoTmpDirErrorMessage = 'No temporary folder was configured in php.ini.'; public $uploadCantWriteErrorMessage = 'Cannot write temporary file to disk.'; public $uploadExtensionErrorMessage = 'A PHP extension caused the upload to fail.'; public $uploadErrorMessage = 'The file could not be uploaded.'; } PK!5ʟ9Symfony/Component/Validator/Constraints/DateValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class DateValidator extends ConstraintValidator { const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/'; /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value || $value instanceof \DateTime) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if (!preg_match(static::PATTERN, $value, $matches) || !checkdate($matches[2], $matches[3], $matches[1])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!0@9Symfony/Component/Validator/Constraints/NullValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class NullValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null !== $value) { if (is_object($value)) { $value = get_class($value); } elseif (is_array($value)) { $value = 'Array'; } $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!> i//5Symfony/Component/Validator/Constraints/Existence.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @author Bernhard Schussek */ abstract class Existence extends Constraint { public $constraints = array(); public function getDefaultOption() { return 'constraints'; } } PK!tUה4Symfony/Component/Validator/Constraints/Required.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Bernhard Schussek */ class Required extends Existence { } PK!m\\>Symfony/Component/Validator/Constraints/AbstractComparison.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Used for the comparison of values. * * @author Daniel Holmes */ abstract class AbstractComparison extends Constraint { public $message; public $value; /** * {@inheritDoc} */ public function __construct($options = null) { if (is_array($options) && !isset($options['value'])) { throw new ConstraintDefinitionException(sprintf( 'The %s constraint requires the "value" option to be set.', get_class($this) )); } parent::__construct($options); } /** * {@inheritDoc} */ public function getDefaultOption() { return 'value'; } } PK!cy  4Symfony/Component/Validator/Constraints/DateTime.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class DateTime extends Constraint { public $message = 'This value is not a valid datetime.'; } PK!l˘ 7Symfony/Component/Validator/Constraints/IpValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid IP address * * @author Bernhard Schussek * @author Joseph Bielawski * * @api */ class IpValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; switch ($constraint->version) { case Ip::V4: $flag = FILTER_FLAG_IPV4; break; case Ip::V6: $flag = FILTER_FLAG_IPV6; break; case Ip::V4_NO_PRIV: $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE; break; case Ip::V6_NO_PRIV: $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE; break; case Ip::ALL_NO_PRIV: $flag = FILTER_FLAG_NO_PRIV_RANGE; break; case Ip::V4_NO_RES: $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE; break; case Ip::V6_NO_RES: $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE; break; case Ip::ALL_NO_RES: $flag = FILTER_FLAG_NO_RES_RANGE; break; case Ip::V4_ONLY_PUBLIC: $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; break; case Ip::V6_ONLY_PUBLIC: $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; break; case Ip::ALL_ONLY_PUBLIC: $flag = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; break; default: $flag = null; break; } if (!filter_var($value, FILTER_VALIDATE_IP, $flag)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!\\=Symfony/Component/Validator/Constraints/LessThanValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are less than the previous (<). * * @author Daniel Holmes */ class LessThanValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 < $value2; } } PK!U4Symfony/Component/Validator/Constraints/NotBlank.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class NotBlank extends Constraint { public $message = 'This value should not be blank.'; } PK!<8S:Symfony/Component/Validator/Constraints/ImageValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Validates whether a value is a valid image file and is valid * against minWidth, maxWidth, minHeight and maxHeight constraints * * @author Benjamin Dulau */ class ImageValidator extends FileValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { $violations = count($this->context->getViolations()); parent::validate($value, $constraint); $failed = count($this->context->getViolations()) !== $violations; if ($failed || null === $value || '' === $value) { return; } if (null === $constraint->minWidth && null === $constraint->maxWidth && null === $constraint->minHeight && null === $constraint->maxHeight && null === $constraint->minRatio && null === $constraint->maxRatio && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait) { return; } $size = @getimagesize($value); if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) { $this->context->addViolation($constraint->sizeNotDetectedMessage); return; } $width = $size[0]; $height = $size[1]; if ($constraint->minWidth) { if (!ctype_digit((string) $constraint->minWidth)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width', $constraint->minWidth)); } if ($width < $constraint->minWidth) { $this->context->addViolation($constraint->minWidthMessage, array( '{{ width }}' => $width, '{{ min_width }}' => $constraint->minWidth )); return; } } if ($constraint->maxWidth) { if (!ctype_digit((string) $constraint->maxWidth)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width', $constraint->maxWidth)); } if ($width > $constraint->maxWidth) { $this->context->addViolation($constraint->maxWidthMessage, array( '{{ width }}' => $width, '{{ max_width }}' => $constraint->maxWidth )); return; } } if ($constraint->minHeight) { if (!ctype_digit((string) $constraint->minHeight)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum height', $constraint->minHeight)); } if ($height < $constraint->minHeight) { $this->context->addViolation($constraint->minHeightMessage, array( '{{ height }}' => $height, '{{ min_height }}' => $constraint->minHeight )); return; } } if ($constraint->maxHeight) { if (!ctype_digit((string) $constraint->maxHeight)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum height', $constraint->maxHeight)); } if ($height > $constraint->maxHeight) { $this->context->addViolation($constraint->maxHeightMessage, array( '{{ height }}' => $height, '{{ max_height }}' => $constraint->maxHeight )); } } $ratio = $width / $height; if (null !== $constraint->minRatio) { if (!is_numeric((string) $constraint->minRatio)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio)); } if ($ratio < $constraint->minRatio) { $this->context->addViolation($constraint->minRatioMessage, array( '{{ ratio }}' => $ratio, '{{ min_ratio }}' => $constraint->minRatio )); } } if (null !== $constraint->maxRatio) { if (!is_numeric((string) $constraint->maxRatio)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio)); } if ($ratio > $constraint->maxRatio) { $this->context->addViolation($constraint->maxRatioMessage, array( '{{ ratio }}' => $ratio, '{{ max_ratio }}' => $constraint->maxRatio )); } } if (!$constraint->allowSquare && $width == $height) { $this->context->addViolation($constraint->allowSquareMessage, array( '{{ width }}' => $width, '{{ height }}' => $height )); } if (!$constraint->allowLandscape && $width > $height) { $this->context->addViolation($constraint->allowLandscapeMessage, array( '{{ width }}' => $width, '{{ height }}' => $height )); } if (!$constraint->allowPortrait && $width < $height) { $this->context->addViolation($constraint->allowPortraitMessage, array( '{{ width }}' => $width, '{{ height }}' => $height )); } } } PK!Lֻ6Symfony/Component/Validator/Constraints/CardScheme.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * Metadata for the CardSchemeValidator. * * @Annotation */ class CardScheme extends Constraint { public $message = 'Unsupported card type or invalid card number.'; public $schemes; public function getDefaultOption() { return 'schemes'; } public function getRequiredOptions() { return array('schemes'); } } PK!"?Symfony/Component/Validator/Constraints/CardSchemeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * Validates that a card number belongs to a specified scheme. * * @see http://en.wikipedia.org/wiki/Bank_card_number * @see http://www.regular-expressions.info/creditcard.html * @author Tim Nagel */ class CardSchemeValidator extends ConstraintValidator { protected $schemes = array( /** * American Express card numbers start with 34 or 37 and have 15 digits. */ 'AMEX' => array( '/^3[47][0-9]{13}$/' ), /** * China UnionPay cards start with 62 and have between 16 and 19 digits. * Please note that these cards do not follow Luhn Algorithm as a checksum. */ 'CHINA_UNIONPAY' => array( '/^62[0-9]{14,17}$/' ), /** * Diners Club card numbers begin with 300 through 305, 36 or 38. All have 14 digits. * There are Diners Club cards that begin with 5 and have 16 digits. * These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard. */ 'DINERS' => array( '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/', ), /** * Discover card numbers begin with 6011, 622126 through 622925, 644 through 649 or 65. * All have 16 digits */ 'DISCOVER' => array( '/^6011[0-9]{12}$/', '/^64[4-9][0-9]{13}$/', '/^65[0-9]{14}$/', '/^622(12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|91[0-9]|92[0-5])[0-9]{10}$/' ), /** * InstaPayment cards begin with 637 through 639 and have 16 digits */ 'INSTAPAYMENT' => array( '/^63[7-9][0-9]{13}$/' ), /** * JCB cards beginning with 2131 or 1800 have 15 digits. * JCB cards beginning with 35 have 16 digits. */ 'JCB' => array( '/^(?:2131|1800|35[0-9]{3})[0-9]{11}$/' ), /** * Laser cards begin with either 6304, 6706, 6709 or 6771 and have between 16 and 19 digits */ 'LASER' => array( '/^(6304|670[69]|6771)[0-9]{12,15}$/' ), /** * Maestro cards begin with either 5018, 5020, 5038, 5893, 6304, 6759, 6761, 6762, 6763 or 0604 * They have between 12 and 19 digits */ 'MAESTRO' => array( '/^(5018|5020|5038|6304|6759|6761|676[23]|0604)[0-9]{8,15}$/' ), /** * All MasterCard numbers start with the numbers 51 through 55. All have 16 digits. */ 'MASTERCARD' => array( '/^5[1-5][0-9]{14}$/' ), /** * All Visa card numbers start with a 4. New cards have 16 digits. Old cards have 13. */ 'VISA' => array( '/^4([0-9]{12}|[0-9]{15})$/' ), ); /** * Validates a creditcard belongs to a specified scheme. * * @param mixed $value * @param Constraint $constraint */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_numeric($value)) { $this->context->addViolation($constraint->message); return; } $schemes = array_flip((array) $constraint->schemes); $schemeRegexes = array_intersect_key($this->schemes, $schemes); foreach ($schemeRegexes as $regexes) { foreach ($regexes as $regex) { if (preg_match($regex, $value)) { return; } } } $this->context->addViolation($constraint->message); } } PK!N30Symfony/Component/Validator/Constraints/Type.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Type extends Constraint { public $message = 'This value should be of type {{ type }}.'; public $type; /** * {@inheritDoc} */ public function getDefaultOption() { return 'type'; } /** * {@inheritDoc} */ public function getRequiredOptions() { return array('type'); } } PK!@vqq9Symfony/Component/Validator/Constraints/FileValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\HttpFoundation\File\File as FileObject; use Symfony\Component\HttpFoundation\File\UploadedFile; /** * @author Bernhard Schussek * * @api */ class FileValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if ($value instanceof UploadedFile && !$value->isValid()) { switch ($value->getError()) { case UPLOAD_ERR_INI_SIZE: if ($constraint->maxSize) { if (ctype_digit((string) $constraint->maxSize)) { $maxSize = (int) $constraint->maxSize; } elseif (preg_match('/^\d++k$/', $constraint->maxSize)) { $maxSize = $constraint->maxSize * 1024; } elseif (preg_match('/^\d++M$/', $constraint->maxSize)) { $maxSize = $constraint->maxSize * 1048576; } else { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize)); } $maxSize = min(UploadedFile::getMaxFilesize(), $maxSize); } else { $maxSize = UploadedFile::getMaxFilesize(); } $this->context->addViolation($constraint->uploadIniSizeErrorMessage, array( '{{ limit }}' => $maxSize, '{{ suffix }}' => 'bytes', )); return; case UPLOAD_ERR_FORM_SIZE: $this->context->addViolation($constraint->uploadFormSizeErrorMessage); return; case UPLOAD_ERR_PARTIAL: $this->context->addViolation($constraint->uploadPartialErrorMessage); return; case UPLOAD_ERR_NO_FILE: $this->context->addViolation($constraint->uploadNoFileErrorMessage); return; case UPLOAD_ERR_NO_TMP_DIR: $this->context->addViolation($constraint->uploadNoTmpDirErrorMessage); return; case UPLOAD_ERR_CANT_WRITE: $this->context->addViolation($constraint->uploadCantWriteErrorMessage); return; case UPLOAD_ERR_EXTENSION: $this->context->addViolation($constraint->uploadExtensionErrorMessage); return; default: $this->context->addViolation($constraint->uploadErrorMessage); return; } } if (!is_scalar($value) && !$value instanceof FileObject && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $path = $value instanceof FileObject ? $value->getPathname() : (string) $value; if (!is_file($path)) { $this->context->addViolation($constraint->notFoundMessage, array('{{ file }}' => $path)); return; } if (!is_readable($path)) { $this->context->addViolation($constraint->notReadableMessage, array('{{ file }}' => $path)); return; } if ($constraint->maxSize) { if (ctype_digit((string) $constraint->maxSize)) { $size = filesize($path); $limit = (int) $constraint->maxSize; $suffix = 'bytes'; } elseif (preg_match('/^\d++k$/', $constraint->maxSize)) { $size = round(filesize($path) / 1000, 2); $limit = (int) $constraint->maxSize; $suffix = 'kB'; } elseif (preg_match('/^\d++M$/', $constraint->maxSize)) { $size = round(filesize($path) / 1000000, 2); $limit = (int) $constraint->maxSize; $suffix = 'MB'; } else { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize)); } if ($size > $limit) { $this->context->addViolation($constraint->maxSizeMessage, array( '{{ size }}' => $size, '{{ limit }}' => $limit, '{{ suffix }}' => $suffix, '{{ file }}' => $path, )); return; } } if ($constraint->mimeTypes) { if (!$value instanceof FileObject) { $value = new FileObject($value); } $mimeTypes = (array) $constraint->mimeTypes; $mime = $value->getMimeType(); $valid = false; foreach ($mimeTypes as $mimeType) { if ($mimeType === $mime) { $valid = true; break; } if ($discrete = strstr($mimeType, '/*', true)) { if (strstr($mime, '/', true) === $discrete) { $valid = true; break; } } } if (false === $valid) { $this->context->addViolation($constraint->mimeTypesMessage, array( '{{ type }}' => '"'.$mime.'"', '{{ types }}' => '"'.implode('", "', $mimeTypes) .'"', '{{ file }}' => $path, )); } } } } PK!'1Symfony/Component/Validator/Constraints/Count.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Count extends Constraint { public $minMessage = 'This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.'; public $maxMessage = 'This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.'; public $exactMessage = 'This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.'; public $min; public $max; public function __construct($options = null) { if (null !== $options && !is_array($options)) { $options = array( 'min' => $options, 'max' => $options, ); } parent::__construct($options); if (null === $this->min && null === $this->max) { throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max')); } } } PK!̢VV@Symfony/Component/Validator/Constraints/IdenticalToValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are identical (===). * * @author Daniel Holmes */ class IdenticalToValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 === $value2; } } PK!dXBB0Symfony/Component/Validator/Constraints/Issn.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Antonio J. García Lagar */ class Issn extends Constraint { public $message = 'This value is not a valid ISSN.'; public $caseSensitive = false; public $requireHyphen = false; } PK!ଏASymfony/Component/Validator/Constraints/GroupSequenceProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Annotation to define a group sequence provider * * @Annotation */ class GroupSequenceProvider { } PK!}a7Symfony/Component/Validator/Constraints/GreaterThan.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class GreaterThan extends AbstractComparison { public $message = 'This value should be greater than {{ compared_value }}.'; } PK!Ǧ3Symfony/Component/Validator/Constraints/EqualTo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class EqualTo extends AbstractComparison { public $message = 'This value should be equal to {{ compared_value }}.'; } PK!b+9Symfony/Component/Validator/Constraints/LuhnValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates a PAN using the LUHN Algorithm * * For a list of example card numbers that are used to test this * class, please see the LuhnValidatorTest class. * * @see http://en.wikipedia.org/wiki/Luhn_algorithm * @author Tim Nagel * @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/ */ class LuhnValidator extends ConstraintValidator { /** * Validates a creditcard number with the Luhn algorithm. * * @param mixed $value * @param Constraint $constraint */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } /** * need to work with strings only because long numbers are treated as floats and don't work with strlen */ if (!is_string($value)) { throw new UnexpectedTypeException($value, 'string'); } if (!is_numeric($value)) { $this->context->addViolation($constraint->message); return; } $length = strlen($value); $oddLength = $length % 2; for ($sum = 0, $i = $length - 1; $i >= 0; $i--) { $digit = (int) $value[$i]; $sum += (($i % 2) === $oddLength) ? array_sum(str_split($digit * 2)) : $digit; } if ($sum === 0 || ($sum % 10) !== 0) { $this->context->addViolation($constraint->message); } } } PK!ٜ?0Symfony/Component/Validator/Constraints/True.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class True extends Constraint { public $message = 'This value should be true.'; } PK!?GSymfony/Component/Validator/Constraints/AbstractComparisonValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * Provides a base class for the validation of property comparisons. * * @author Daniel Holmes */ abstract class AbstractComparisonValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!$this->compareValues($value, $constraint->value)) { $this->context->addViolation($constraint->message, array( '{{ value }}' => $this->valueToString($constraint->value), '{{ compared_value }}' => $this->valueToString($constraint->value), '{{ compared_value_type }}' => $this->valueToType($constraint->value) )); } } /** * Returns a string representation of the type of the value. * * @param mixed $value * * @return string */ private function valueToType($value) { return is_object($value) ? get_class($value) : gettype($value); } /** * Returns a string representation of the value. * * @param mixed $value * * @return string */ private function valueToString($value) { if (is_object($value) && method_exists($value, '__toString')) { return (string) $value; } if ($value instanceof \DateTime) { return $value->format('Y-m-d H:i:s'); } return var_export($value, true); } /** * Compares the two given values to find if their relationship is valid * * @param mixed $value1 The first value to compare * @param mixed $value2 The second value to compare * * @return Boolean true if the relationship is valid, false otherwise */ abstract protected function compareValues($value1, $value2); } PK!̋ 1Symfony/Component/Validator/Constraints/Regex.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Regex extends Constraint { public $message = 'This value is not valid.'; public $pattern; public $htmlPattern = null; public $match = true; /** * {@inheritDoc} */ public function getDefaultOption() { return 'pattern'; } /** * {@inheritDoc} */ public function getRequiredOptions() { return array('pattern'); } /** * Returns htmlPattern if exists or pattern is convertible. * * @return string|null */ public function getHtmlPattern() { // If htmlPattern is specified, use it if (null !== $this->htmlPattern) { return empty($this->htmlPattern) ? null : $this->htmlPattern; } return $this->getNonDelimitedPattern(); } /** * Converts the htmlPattern to a suitable format for HTML5 pattern. * Example: /^[a-z]+$/ would be converted to [a-z]+ * However, if options are specified, it cannot be converted * * Pattern is also ignored if match=false since the pattern should * then be reversed before application. * * @todo reverse pattern in case match=false as per issue #5307 * * @link http://dev.w3.org/html5/spec/single-page.html#the-pattern-attribute * * @return string|null */ private function getNonDelimitedPattern() { // If match = false, pattern should not be added to HTML5 validation if (!$this->match) { return null; } if (preg_match('/^(.)(\^?)(.*?)(\$?)\1$/', $this->pattern, $matches)) { $delimiter = $matches[1]; $start = empty($matches[2]) ? '.*' : ''; $pattern = $matches[3]; $end = empty($matches[4]) ? '.*' : ''; // Unescape the delimiter in pattern $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern); return $start.$pattern.$end; } return null; } } PK!BB1Symfony/Component/Validator/Constraints/Range.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Range extends Constraint { public $minMessage = 'This value should be {{ limit }} or more.'; public $maxMessage = 'This value should be {{ limit }} or less.'; public $invalidMessage = 'This value should be a valid number.'; public $min; public $max; public function __construct($options = null) { parent::__construct($options); if (null === $this->min && null === $this->max) { throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max')); } } } PK![A;Symfony/Component/Validator/Constraints/LessThanOrEqual.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class LessThanOrEqual extends AbstractComparison { public $message = 'This value should be less than or equal to {{ compared_value }}.'; } PK!q;O3Symfony/Component/Validator/Constraints/Country.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Country extends Constraint { public $message = 'This value is not a valid country.'; } PK!5:Symfony/Component/Validator/Constraints/EmailValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class EmailValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $valid = filter_var($value, FILTER_VALIDATE_EMAIL); if ($valid) { $host = substr($value, strpos($value, '@') + 1); // Check for host DNS resource records if ($valid && $constraint->checkMX) { $valid = $this->checkMX($host); } elseif ($valid && $constraint->checkHost) { $valid = $this->checkHost($host); } } if (!$valid) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } /** * Check DNS Records for MX type. * * @param string $host Host * * @return Boolean */ private function checkMX($host) { return checkdnsrr($host, 'MX'); } /** * Check if one of MX, A or AAAA DNS RR exists. * * @param string $host Host * * @return Boolean */ private function checkHost($host) { return $this->checkMX($host) || (checkdnsrr($host, "A") || checkdnsrr($host, "AAAA")); } } PK!`v;Symfony/Component/Validator/Constraints/LocaleValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid locale code * * @author Bernhard Schussek * * @api */ class LocaleValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $locales = Intl::getLocaleBundle()->getLocaleNames(); if (!isset($locales[$value])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!'㔘  7Symfony/Component/Validator/Constraints/IdenticalTo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class IdenticalTo extends AbstractComparison { public $message = 'This value should be identical to {{ compared_value_type }} {{ compared_value }}.'; } PK!/Symfony/Component/Validator/Constraints/All.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class All extends Constraint { public $constraints = array(); /** * {@inheritDoc} */ public function __construct($options = null) { parent::__construct($options); if (!is_array($this->constraints)) { $this->constraints = array($this->constraints); } foreach ($this->constraints as $constraint) { if (!$constraint instanceof Constraint) { throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, __CLASS__)); } if ($constraint instanceof Valid) { throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', __CLASS__)); } } } public function getDefaultOption() { return 'constraints'; } public function getRequiredOptions() { return array('constraints'); } } PK!{UU?Symfony/Component/Validator/Constraints/NotEqualToValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are all unequal (!=). * * @author Daniel Holmes */ class NotEqualToValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 != $value2; } } PK!ɑ559Symfony/Component/Validator/Constraints/TrueValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class TrueValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (true !== $value && 1 !== $value && '1' !== $value) { $this->context->addViolation($constraint->message); } } } PK!(.wwGSymfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are greater than or equal to the previous (>=). * * @author Daniel Holmes */ class GreaterThanOrEqualValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 >= $value2; } } PK!(9Symfony/Component/Validator/Constraints/TimeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class TimeValidator extends ConstraintValidator { const PATTERN = '/^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/'; /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value || $value instanceof \DateTime) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if (!preg_match(static::PATTERN, $value)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!Fn8Symfony/Component/Validator/Constraints/AllValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class AllValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!is_array($value) && !$value instanceof \Traversable) { throw new UnexpectedTypeException($value, 'array or Traversable'); } $group = $this->context->getGroup(); foreach ($value as $key => $element) { foreach ($constraint->constraints as $constr) { $this->context->validateValue($element, $constr, '['.$key.']', $group); } } } } PK!c.Symfony/Component/Validator/Constraints/Ip.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Constraint; /** * Validates that a value is a valid IP address * * @Annotation * * @author Bernhard Schussek * @author Joseph Bielawski * * @api */ class Ip extends Constraint { const V4 = '4'; const V6 = '6'; const ALL = 'all'; // adds FILTER_FLAG_NO_PRIV_RANGE flag (skip private ranges) const V4_NO_PRIV = '4_no_priv'; const V6_NO_PRIV = '6_no_priv'; const ALL_NO_PRIV = 'all_no_priv'; // adds FILTER_FLAG_NO_RES_RANGE flag (skip reserved ranges) const V4_NO_RES = '4_no_res'; const V6_NO_RES = '6_no_res'; const ALL_NO_RES = 'all_no_res'; // adds FILTER_FLAG_NO_PRIV_RANGE and FILTER_FLAG_NO_RES_RANGE flags (skip both) const V4_ONLY_PUBLIC = '4_public'; const V6_ONLY_PUBLIC = '6_public'; const ALL_ONLY_PUBLIC = 'all_public'; protected static $versions = array( self::V4, self::V6, self::ALL, self::V4_NO_PRIV, self::V6_NO_PRIV, self::ALL_NO_PRIV, self::V4_NO_RES, self::V6_NO_RES, self::ALL_NO_RES, self::V4_ONLY_PUBLIC, self::V6_ONLY_PUBLIC, self::ALL_ONLY_PUBLIC, ); public $version = self::V4; public $message = 'This is not a valid IP address.'; /** * {@inheritDoc} */ public function __construct($options = null) { parent::__construct($options); if (!in_array($this->version, self::$versions)) { throw new ConstraintDefinitionException(sprintf('The option "version" must be one of "%s"', implode('", "', self::$versions))); } } } PK!Hð2Symfony/Component/Validator/Constraints/Locale.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Locale extends Constraint { public $message = 'This value is not a valid locale.'; } PK!Q=Symfony/Component/Validator/Constraints/LanguageValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid language code * * @author Bernhard Schussek * * @api */ class LanguageValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $languages = Intl::getLanguageBundle()->getLanguageNames(); if (!isset($languages[$value])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!aHβ  ;Symfony/Component/Validator/Constraints/ChoiceValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * ChoiceValidator validates that the value is one of the expected values. * * @author Fabien Potencier * @author Florian Eckerstorfer * @author Bernhard Schussek * * @api */ class ChoiceValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (!$constraint->choices && !$constraint->callback) { throw new ConstraintDefinitionException('Either "choices" or "callback" must be specified on constraint Choice'); } if (null === $value) { return; } if ($constraint->multiple && !is_array($value)) { throw new UnexpectedTypeException($value, 'array'); } if ($constraint->callback) { if (is_callable(array($this->context->getClassName(), $constraint->callback))) { $choices = call_user_func(array($this->context->getClassName(), $constraint->callback)); } elseif (is_callable($constraint->callback)) { $choices = call_user_func($constraint->callback); } else { throw new ConstraintDefinitionException('The Choice constraint expects a valid callback'); } } else { $choices = $constraint->choices; } if ($constraint->multiple) { foreach ($value as $_value) { if (!in_array($_value, $choices, $constraint->strict)) { $this->context->addViolation($constraint->multipleMessage, array('{{ value }}' => $_value)); } } $count = count($value); if ($constraint->min !== null && $count < $constraint->min) { $this->context->addViolation($constraint->minMessage, array('{{ limit }}' => $constraint->min), null, (int) $constraint->min); return; } if ($constraint->max !== null && $count > $constraint->max) { $this->context->addViolation($constraint->maxMessage, array('{{ limit }}' => $constraint->max), null, (int) $constraint->max); return; } } elseif (!in_array($value, $choices, $constraint->strict)) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!{HH1Symfony/Component/Validator/Constraints/Email.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Email extends Constraint { public $message = 'This value is not a valid email address.'; public $checkMX = false; public $checkHost = false; } PK!x.`ss4Symfony/Component/Validator/Constraints/Callback.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Callback extends Constraint { /** * @var string|callable * * @since 2.4 */ public $callback; /** * @var array * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. */ public $methods; /** * {@inheritdoc} */ public function __construct($options = null) { // Invocation through annotations with an array parameter only if (is_array($options) && 1 === count($options) && isset($options['value'])) { $options = $options['value']; } if (is_array($options) && !isset($options['callback']) && !isset($options['methods']) && !isset($options['groups'])) { if (is_callable($options)) { $options = array('callback' => $options); } else { // BC with Symfony < 2.4 $options = array('methods' => $options); } } parent::__construct($options); } /** * {@inheritdoc} */ public function getDefaultOption() { return 'callback'; } /** * {@inheritdoc} */ public function getTargets() { return self::CLASS_CONSTRAINT; } } PK!=Symfony/Component/Validator/Constraints/DateTimeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @author Bernhard Schussek * * @api */ class DateTimeValidator extends DateValidator { const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/'; } PK!&0Symfony/Component/Validator/Constraints/Luhn.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * Metadata for the LuhnValidator. * * @Annotation */ class Luhn extends Constraint { public $message = 'Invalid card number.'; } PK!F9Symfony/Component/Validator/Constraints/TypeValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class TypeValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } $type = strtolower($constraint->type); $type = $type == 'boolean' ? 'bool' : $constraint->type; $isFunction = 'is_'.$type; $ctypeFunction = 'ctype_'.$type; if (function_exists($isFunction) && call_user_func($isFunction, $value)) { return; } elseif (function_exists($ctypeFunction) && call_user_func($ctypeFunction, $value)) { return; } elseif ($value instanceof $constraint->type) { return; } $this->context->addViolation($constraint->message, array( '{{ value }}' => is_object($value) ? get_class($value) : (is_array($value) ? 'Array' : (string) $value), '{{ type }}' => $constraint->type, )); } } PK!&=Symfony/Component/Validator/Constraints/NotBlankValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class NotBlankValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (false === $value || (empty($value) && '0' != $value)) { $this->context->addViolation($constraint->message); } } } PK!e8B 6Symfony/Component/Validator/Constraints/Collection.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Collection extends Constraint { public $fields = array(); public $allowExtraFields = false; public $allowMissingFields = false; public $extraFieldsMessage = 'This field was not expected.'; public $missingFieldsMessage = 'This field is missing.'; /** * {@inheritDoc} */ public function __construct($options = null) { // no known options set? $options is the fields array if (is_array($options) && !array_intersect(array_keys($options), array('groups', 'fields', 'allowExtraFields', 'allowMissingFields', 'extraFieldsMessage', 'missingFieldsMessage'))) { $options = array('fields' => $options); } parent::__construct($options); if (!is_array($this->fields)) { throw new ConstraintDefinitionException(sprintf('The option "fields" is expected to be an array in constraint %s', __CLASS__)); } foreach ($this->fields as $fieldName => $field) { // the XmlFileLoader and YamlFileLoader pass the field Optional // and Required constraint as an array with exactly one element if (is_array($field) && count($field) == 1) { $this->fields[$fieldName] = $field = $field[0]; } if (!$field instanceof Optional && !$field instanceof Required) { $this->fields[$fieldName] = $field = new Required($field); } if (!is_array($field->constraints)) { $field->constraints = array($field->constraints); } foreach ($field->constraints as $constraint) { if (!$constraint instanceof Constraint) { throw new ConstraintDefinitionException(sprintf('The value %s of the field %s is not an instance of Constraint in constraint %s', $constraint, $fieldName, __CLASS__)); } if ($constraint instanceof Valid) { throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', __CLASS__)); } } } } public function getRequiredOptions() { return array('fields'); } } PK!I7U1Symfony/Component/Validator/Constraints/False.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class False extends Constraint { public $message = 'This value should be false.'; } PK!Q>Symfony/Component/Validator/Constraints/GreaterThanOrEqual.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class GreaterThanOrEqual extends AbstractComparison { public $message = 'This value should be greater than or equal to {{ compared_value }}.'; } PK!l1Symfony/Component/Validator/Constraints/Blank.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Blank extends Constraint { public $message = 'This value should be blank.'; } PK!CG^LL<Symfony/Component/Validator/Constraints/EqualToValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are equal (==). * * @author Daniel Holmes */ class EqualToValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 == $value2; } } PK!^T :Symfony/Component/Validator/Constraints/FalseValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek * * @api */ class FalseValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || false === $value || 0 === $value || '0' === $value) { return; } $this->context->addViolation($constraint->message); } } PK!OqqDSymfony/Component/Validator/Constraints/LessThanOrEqualValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are less than or equal to the previous (<=). * * @author Daniel Holmes */ class LessThanOrEqualValidator extends AbstractComparisonValidator { /** * @inheritDoc */ protected function compareValues($value1, $value2) { return $value1 <= $value2; } } PK!vv9Symfony/Component/Validator/Constraints/GroupSequence.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Annotation for group sequences * * @Annotation * * @author Bernhard Schussek * * @api */ class GroupSequence { /** * The members of the sequence * @var array */ public $groups; public function __construct(array $groups) { $this->groups = $groups['value']; } } PK!_1Symfony/Component/Validator/Constraints/Image.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @api */ class Image extends File { public $mimeTypes = 'image/*'; public $minWidth = null; public $maxWidth = null; public $maxHeight = null; public $minHeight = null; public $maxRatio = null; public $minRatio = null; public $allowSquare = true; public $allowLandscape = true; public $allowPortrait = true; public $mimeTypesMessage = 'This file is not a valid image.'; public $sizeNotDetectedMessage = 'The size of the image could not be detected.'; public $maxWidthMessage = 'The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.'; public $minWidthMessage = 'The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.'; public $maxHeightMessage = 'The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.'; public $minHeightMessage = 'The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.'; public $maxRatioMessage = 'The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.'; public $minRatioMessage = 'The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.'; public $allowSquareMessage = 'The image is square ({{ width }}x{{ height }}px). Square images are not allowed.'; public $allowLandscapeMessage = 'The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.'; public $allowPortraitMessage = 'The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.'; } PK!F;;Symfony/Component/Validator/Constraints/LengthValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class LengthValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $stringValue = (string) $value; if (function_exists('grapheme_strlen') && 'UTF-8' === $constraint->charset) { $length = grapheme_strlen($stringValue); } elseif (function_exists('mb_strlen')) { $length = mb_strlen($stringValue, $constraint->charset); } else { $length = strlen($stringValue); } if ($constraint->min == $constraint->max && $length != $constraint->min) { $this->context->addViolation($constraint->exactMessage, array( '{{ value }}' => $stringValue, '{{ limit }}' => $constraint->min, ), $value, (int) $constraint->min); return; } if (null !== $constraint->max && $length > $constraint->max) { $this->context->addViolation($constraint->maxMessage, array( '{{ value }}' => $stringValue, '{{ limit }}' => $constraint->max, ), $value, (int) $constraint->max); return; } if (null !== $constraint->min && $length < $constraint->min) { $this->context->addViolation($constraint->minMessage, array( '{{ value }}' => $stringValue, '{{ limit }}' => $constraint->min, ), $value, (int) $constraint->min); } } } PK!!xHH:Symfony/Component/Validator/Constraints/CountValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class CountValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!is_array($value) && !$value instanceof \Countable) { throw new UnexpectedTypeException($value, 'array or \Countable'); } $count = count($value); if ($constraint->min == $constraint->max && $count != $constraint->min) { $this->context->addViolation($constraint->exactMessage, array( '{{ count }}' => $count, '{{ limit }}' => $constraint->min, ), $value, (int) $constraint->min); return; } if (null !== $constraint->max && $count > $constraint->max) { $this->context->addViolation($constraint->maxMessage, array( '{{ count }}' => $count, '{{ limit }}' => $constraint->max, ), $value, (int) $constraint->max); return; } if (null !== $constraint->min && $count < $constraint->min) { $this->context->addViolation($constraint->minMessage, array( '{{ count }}' => $count, '{{ limit }}' => $constraint->min, ), $value, (int) $constraint->min); } } } PK!70Symfony/Component/Validator/Constraints/Time.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Bernhard Schussek * * @api */ class Time extends Constraint { public $message = 'This value is not a valid time.'; } PK!NH4Symfony/Component/Validator/Constraints/LessThan.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class LessThan extends AbstractComparison { public $message = 'This value should be less than {{ compared_value }}.'; } PK!e:Symfony/Component/Validator/Constraints/NotIdenticalTo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * * @author Daniel Holmes */ class NotIdenticalTo extends AbstractComparison { public $message = 'This value should not be identical to {{ compared_value_type }} {{ compared_value }}.'; } PK!Z=Symfony/Component/Validator/Constraints/CurrencyValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid currency * * @author Miha Vrhovnik * * @api */ class CurrencyValidator extends ConstraintValidator { /** * {@inheritDoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $currencies = Intl::getCurrencyBundle()->getCurrencyNames(); if (!isset($currencies[$value])) { $this->context->addViolation($constraint->message, array('{{ value }}' => $value)); } } } PK!Gk 3Symfony/Component/Validator/ConstraintValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Base class for constraint validators * * @author Bernhard Schussek * * @api */ abstract class ConstraintValidator implements ConstraintValidatorInterface { /** * @var ExecutionContextInterface */ protected $context; /** * {@inheritDoc} */ public function initialize(ExecutionContextInterface $context) { $this->context = $context; } } PK!KOCSymfony/Component/Validator/ConstraintValidatorFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Specifies an object able to return the correct ConstraintValidatorInterface * instance given a Constraint object. */ interface ConstraintValidatorFactoryInterface { /** * Given a Constraint, this returns the ConstraintValidatorInterface * object that should be used to verify its validity. * * @param Constraint $constraint The source constraint * * @return ConstraintValidatorInterface */ public function getInstance(Constraint $constraint); } PK!8Wc?Symfony/Component/Validator/GlobalExecutionContextInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Stores the node-independent state of a validation run. * * When the validator validates a graph of objects, it uses two classes to * store the state during the validation: * *
    *
  • For each node in the validation graph (objects, properties, getters) the * validator creates an instance of {@link ExecutionContextInterface} that * stores the information about that node.
  • *
  • One single GlobalExecutionContextInterface stores the state * that is independent of the current node.
  • *
* * @author Bernhard Schussek */ interface GlobalExecutionContextInterface { /** * Returns the violations generated by the validator so far. * * @return ConstraintViolationListInterface A list of constraint violations. */ public function getViolations(); /** * Returns the value at which validation was started in the object graph. * * @return mixed The root value. * * @see ExecutionContextInterface::getRoot */ public function getRoot(); /** * Returns the visitor instance used to validate the object graph nodes. * * @return ValidationVisitorInterface The validation visitor. */ public function getVisitor(); /** * Returns the factory for constraint validators. * * @return ConstraintValidatorFactoryInterface The constraint validator factory. */ public function getValidatorFactory(); /** * Returns the factory for validation metadata objects. * * @return MetadataFactoryInterface The metadata factory. */ public function getMetadataFactory(); } PK!xfJJ*Symfony/Component/Validator/Validation.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Entry point for the Validator component. * * @author Bernhard Schussek */ final class Validation { /** * Creates a new validator. * * If you want to configure the validator, use * {@link createValidatorBuilder()} instead. * * @return ValidatorInterface The new validator. */ public static function createValidator() { return self::createValidatorBuilder()->getValidator(); } /** * Creates a configurable builder for validator objects. * * @return ValidatorBuilderInterface The new builder. */ public static function createValidatorBuilder() { return new ValidatorBuilder(); } /** * This class cannot be instantiated. */ private function __construct() { } } PK!n r 2Symfony/Component/Validator/ValidatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Validates values and graphs of objects and arrays. * * @author Bernhard Schussek * * @api */ interface ValidatorInterface { /** * Validates a value. * * The accepted values depend on the {@link MetadataFactoryInterface} * implementation. * * @param mixed $value The value to validate * @param array|null $groups The validation groups to validate. * @param Boolean $traverse Whether to traverse the value if it is traversable. * @param Boolean $deep Whether to traverse nested traversable values recursively. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validate($value, $groups = null, $traverse = false, $deep = false); /** * Validates a property of a value against its current value. * * The accepted values depend on the {@link MetadataFactoryInterface} * implementation. * * @param mixed $containingValue The value containing the property. * @param string $property The name of the property to validate. * @param array|null $groups The validation groups to validate. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validateProperty($containingValue, $property, $groups = null); /** * Validate a property of a value against a potential value. * * The accepted values depend on the {@link MetadataFactoryInterface} * implementation. * * @param string $containingValue The value containing the property. * @param string $property The name of the property to validate * @param string $value The value to validate against the * constraints of the property. * @param array|null $groups The validation groups to validate. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validatePropertyValue($containingValue, $property, $value, $groups = null); /** * Validates a value against a constraint or a list of constraints. * * @param mixed $value The value to validate. * @param Constraint|Constraint[] $constraints The constraint(s) to validate against. * @param array|null $groups The validation groups to validate. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validateValue($value, $constraints, $groups = null); /** * Returns the factory for metadata instances. * * @return MetadataFactoryInterface The metadata factory. * * @api */ public function getMetadataFactory(); } PK!C9Symfony/Component/Templating/StreamingEngineInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * StreamingEngineInterface provides a method that knows how to stream a template. * * @author Fabien Potencier */ interface StreamingEngineInterface { /** * Streams a template. * * The implementation should output the content directly to the client. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * @param array $parameters An array of parameters to pass to the template * * @throws \RuntimeException if the template cannot be rendered * @throws \LogicException if the template cannot be streamed */ public function stream($name, array $parameters = array()); } PK!<,}}2Symfony/Component/Templating/TemplateReference.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * Internal representation of a template. * * @author Victor Berchet * * @api */ class TemplateReference implements TemplateReferenceInterface { protected $parameters; public function __construct($name = null, $engine = null) { $this->parameters = array( 'name' => $name, 'engine' => $engine, ); } /** * {@inheritdoc} */ public function __toString() { return $this->getLogicalName(); } /** * {@inheritdoc} * * @api */ public function set($name, $value) { if (array_key_exists($name, $this->parameters)) { $this->parameters[$name] = $value; } else { throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.', $name)); } return $this; } /** * {@inheritdoc} * * @api */ public function get($name) { if (array_key_exists($name, $this->parameters)) { return $this->parameters[$name]; } throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.', $name)); } /** * {@inheritdoc} * * @api */ public function all() { return $this->parameters; } /** * {@inheritdoc} * * @api */ public function getPath() { return $this->parameters['name']; } /** * {@inheritdoc} * * @api */ public function getLogicalName() { return $this->parameters['name']; } } PK!mtTT+Symfony/Component/Templating/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * Interface to be implemented by all templates. * * @author Victor Berchet * * @api */ interface TemplateReferenceInterface { /** * Gets the template parameters. * * @return array An array of parameters * * @api */ public function all(); /** * Sets a template parameter. * * @param string $name The parameter name * @param string $value The parameter value * * @return TemplateReferenceInterface The TemplateReferenceInterface instance * * @throws \InvalidArgumentException if the parameter name is not supported * * @api */ public function set($name, $value); /** * Gets a template parameter. * * @param string $name The parameter name * * @return string The parameter value * * @throws \InvalidArgumentException if the parameter name is not supported * * @api */ public function get($name); /** * Returns the path to the template. * * By default, it just returns the template name. * * @return string A path to the template or a resource * * @api */ public function getPath(); /** * Returns the "logical" template name. * * The template name acts as a unique identifier for the template. * * @return string The template name * * @api */ public function getLogicalName(); /** * Returns the string representation as shortcut for getLogicalName(). * * Alias of getLogicalName(). * * @return string The template name * * @api */ public function __toString(); } PK!J 2Symfony/Component/Templating/DebuggerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * DebuggerInterface is the interface you need to implement * to debug template loader instances. * * @author Fabien Potencier * * @deprecated Deprecated in 2.4, to be removed in 3.0. Use Psr\Log\LoggerInterface instead. */ interface DebuggerInterface { /** * Logs a message. * * @param string $message A message to log */ public function log($message); } PK!DZ_++<Symfony/Component/Templating/TemplateNameParserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * TemplateNameParserInterface converts template names to TemplateReferenceInterface * instances. * * @author Fabien Potencier * * @api */ interface TemplateNameParserInterface { /** * Convert a template name to a TemplateReferenceInterface instance. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return TemplateReferenceInterface A template * * @api */ public function parse($name); } PK!3Symfony/Component/Templating/TemplateNameParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * TemplateNameParser is the default implementation of TemplateNameParserInterface. * * This implementation takes everything as the template name * and the extension for the engine. * * @author Fabien Potencier * * @api */ class TemplateNameParser implements TemplateNameParserInterface { /** * {@inheritdoc} * * @api */ public function parse($name) { if ($name instanceof TemplateReferenceInterface) { return $name; } $engine = null; if (false !== $pos = strrpos($name, '.')) { $engine = substr($name, $pos + 1); } return new TemplateReference($name, $engine); } } PK!0Symfony/Component/Templating/EngineInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * EngineInterface is the interface each engine must implement. * * All methods relies on a template name. A template name is a * "logical" name for the template, and as such it does not refer to * a path on the filesystem (in fact, the template can be stored * anywhere, like in a database). * * The methods should accept any name. If the name is not an instance of * TemplateReferenceInterface, a TemplateNameParserInterface should be used to * convert the name to a TemplateReferenceInterface instance. * * Each template loader uses the logical template name to look for * the template. * * @author Fabien Potencier * * @api */ interface EngineInterface { /** * Renders a template. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * @param array $parameters An array of parameters to pass to the template * * @return string The evaluated template as a string * * @throws \RuntimeException if the template cannot be rendered * * @api */ public function render($name, array $parameters = array()); /** * Returns true if the template exists. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return Boolean true if the template exists, false otherwise * * @throws \RuntimeException if the engine cannot handle the template name * * @api */ public function exists($name); /** * Returns true if this class is able to render the given template. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return Boolean true if this class supports the given template, false otherwise * * @api */ public function supports($name); } PK!bNN2Symfony/Component/Templating/Asset/PathPackage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Asset; /** * The path packages adds a version and a base path to asset URLs. * * @author Kris Wallsmith */ class PathPackage extends Package { private $basePath; /** * Constructor. * * @param string $basePath The base path to be prepended to relative paths * @param string $version The package version * @param string $format The format used to apply the version */ public function __construct($basePath = null, $version = null, $format = null) { parent::__construct($version, $format); if (!$basePath) { $this->basePath = '/'; } else { if ('/' != $basePath[0]) { $basePath = '/'.$basePath; } $this->basePath = rtrim($basePath, '/').'/'; } } public function getUrl($path) { if (false !== strpos($path, '://') || 0 === strpos($path, '//')) { return $path; } $url = $this->applyVersion($path); // apply the base path if ('/' !== substr($url, 0, 1)) { $url = $this->basePath.$url; } return $url; } /** * Returns the base path. * * @return string The base path */ public function getBasePath() { return $this->basePath; } } PK!TT1Symfony/Component/Templating/Asset/UrlPackage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Asset; /** * The URL packages adds a version and a base URL to asset URLs. * * @author Kris Wallsmith */ class UrlPackage extends Package { private $baseUrls; /** * Constructor. * * @param string|array $baseUrls Base asset URLs * @param string $version The package version * @param string $format The format used to apply the version */ public function __construct($baseUrls = array(), $version = null, $format = null) { parent::__construct($version, $format); if (!is_array($baseUrls)) { $baseUrls = (array) $baseUrls; } $this->baseUrls = array(); foreach ($baseUrls as $baseUrl) { $this->baseUrls[] = rtrim($baseUrl, '/'); } } public function getUrl($path) { if (false !== strpos($path, '://') || 0 === strpos($path, '//')) { return $path; } $url = $this->applyVersion($path); if ($url && '/' != $url[0]) { $url = '/'.$url; } return $this->getBaseUrl($path).$url; } /** * Returns the base URL for a path. * * @param string $path * * @return string The base URL */ public function getBaseUrl($path) { switch ($count = count($this->baseUrls)) { case 0: return ''; case 1: return $this->baseUrls[0]; default: return $this->baseUrls[fmod(hexdec(substr(hash('sha256', $path), 0, 10)), $count)]; } } } PK!o##.Symfony/Component/Templating/Asset/Package.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Asset; /** * The basic package will add a version to asset URLs. * * @author Kris Wallsmith */ class Package implements PackageInterface { private $version; private $format; /** * Constructor. * * @param string $version The package version * @param string $format The format used to apply the version */ public function __construct($version = null, $format = '') { $this->version = $version; $this->format = $format ?: '%s?%s'; } public function getVersion() { return $this->version; } public function getUrl($path) { if (false !== strpos($path, '://') || 0 === strpos($path, '//')) { return $path; } return $this->applyVersion($path); } /** * Applies version to the supplied path. * * @param string $path A path * * @return string The versionized path */ protected function applyVersion($path) { if (null === $this->version) { return $path; } $versionized = sprintf($this->format, ltrim($path, '/'), $this->version); if ($path && '/' == $path[0]) { $versionized = '/'.$versionized; } return $versionized; } } PK!pvj7Symfony/Component/Templating/Asset/PackageInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Asset; /** * Asset package interface. * * @author Kris Wallsmith */ interface PackageInterface { /** * Returns the asset package version. * * @return string The version string */ public function getVersion(); /** * Returns an absolute or root-relative public path. * * @param string $path A path * * @return string The public path */ public function getUrl($path); } PK!'4Symfony/Component/Templating/Storage/FileStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Storage; /** * FileStorage represents a template stored on the filesystem. * * @author Fabien Potencier * * @api */ class FileStorage extends Storage { /** * Returns the content of the template. * * @return string The template content * * @api */ public function getContent() { return file_get_contents($this->template); } } PK!("w6Symfony/Component/Templating/Storage/StringStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Storage; /** * StringStorage represents a template stored in a string. * * @author Fabien Potencier * * @api */ class StringStorage extends Storage { /** * Returns the content of the template. * * @return string The template content * * @api */ public function getContent() { return $this->template; } } PK!π\0Symfony/Component/Templating/Storage/Storage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Storage; /** * Storage is the base class for all storage classes. * * @author Fabien Potencier * * @api */ abstract class Storage { protected $template; /** * Constructor. * * @param string $template The template name * * @api */ public function __construct($template) { $this->template = $template; } /** * Returns the object string representation. * * @return string The template name */ public function __toString() { return (string) $this->template; } /** * Returns the content of the template. * * @return string The template content * * @api */ abstract public function getContent(); } PK!>3Symfony/Component/Templating/Loader/ChainLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\TemplateReferenceInterface; /** * ChainLoader is a loader that calls other loaders to load templates. * * @author Fabien Potencier */ class ChainLoader extends Loader { protected $loaders = array(); /** * Constructor. * * @param LoaderInterface[] $loaders An array of loader instances */ public function __construct(array $loaders = array()) { foreach ($loaders as $loader) { $this->addLoader($loader); } } /** * Adds a loader instance. * * @param LoaderInterface $loader A Loader instance */ public function addLoader(LoaderInterface $loader) { $this->loaders[] = $loader; } /** * Loads a template. * * @param TemplateReferenceInterface $template A template * * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise */ public function load(TemplateReferenceInterface $template) { foreach ($this->loaders as $loader) { if (false !== $storage = $loader->load($template)) { return $storage; } } return false; } /** * Returns true if the template is still fresh. * * @param TemplateReferenceInterface $template A template * @param integer $time The last modification time of the cached template (timestamp) * * @return Boolean */ public function isFresh(TemplateReferenceInterface $template, $time) { foreach ($this->loaders as $loader) { return $loader->isFresh($template, $time); } return false; } } PK!b8Symfony/Component/Templating/Loader/FilesystemLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\Storage\FileStorage; use Symfony\Component\Templating\TemplateReferenceInterface; /** * FilesystemLoader is a loader that read templates from the filesystem. * * @author Fabien Potencier * * @api */ class FilesystemLoader extends Loader { protected $templatePathPatterns; /** * Constructor. * * @param array $templatePathPatterns An array of path patterns to look for templates * * @api */ public function __construct($templatePathPatterns) { $this->templatePathPatterns = (array) $templatePathPatterns; } /** * Loads a template. * * @param TemplateReferenceInterface $template A template * * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise * * @api */ public function load(TemplateReferenceInterface $template) { $file = $template->get('name'); if (self::isAbsolutePath($file) && is_file($file)) { return new FileStorage($file); } $replacements = array(); foreach ($template->all() as $key => $value) { $replacements['%'.$key.'%'] = $value; } $logs = array(); foreach ($this->templatePathPatterns as $templatePathPattern) { if (is_file($file = strtr($templatePathPattern, $replacements)) && is_readable($file)) { if (null !== $this->logger) { $this->logger->debug(sprintf('Loaded template file "%s"', $file)); } elseif (null !== $this->debugger) { // just for BC, to be removed in 3.0 $this->debugger->log(sprintf('Loaded template file "%s"', $file)); } return new FileStorage($file); } if (null !== $this->logger || null !== $this->debugger) { $logs[] = sprintf('Failed loading template file "%s"', $file); } } foreach ($logs as $log) { if (null !== $this->logger) { $this->logger->debug($log); } elseif (null !== $this->debugger) { $this->debugger->log($log); } } return false; } /** * Returns true if the template is still fresh. * * @param TemplateReferenceInterface $template A template * @param integer $time The last modification time of the cached template (timestamp) * * @return Boolean true if the template is still fresh, false otherwise * * @api */ public function isFresh(TemplateReferenceInterface $template, $time) { if (false === $storage = $this->load($template)) { return false; } return filemtime((string) $storage) < $time; } /** * Returns true if the file is an existing absolute path. * * @param string $file A path * * @return Boolean true if the path exists and is absolute, false otherwise */ protected static function isAbsolutePath($file) { if ($file[0] == '/' || $file[0] == '\\' || (strlen($file) > 3 && ctype_alpha($file[0]) && $file[1] == ':' && ($file[2] == '\\' || $file[2] == '/') ) || null !== parse_url($file, PHP_URL_SCHEME) ) { return true; } return false; } } PK!g((.Symfony/Component/Templating/Loader/Loader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Psr\Log\LoggerInterface; use Symfony\Component\Templating\DebuggerInterface; /** * Loader is the base class for all template loader classes. * * @author Fabien Potencier */ abstract class Loader implements LoaderInterface { /** * @var LoggerInterface|null */ protected $logger; /** * @deprecated Deprecated in 2.4, to be removed in 3.0. Use $this->logger instead. */ protected $debugger; /** * Sets the debug logger to use for this loader. * * @param LoggerInterface $logger A logger instance */ public function setLogger(LoggerInterface $logger) { $this->logger = $logger; } /** * Sets the debugger to use for this loader. * * @param DebuggerInterface $debugger A debugger instance * * @deprecated Deprecated in 2.4, to be removed in 3.0. Use $this->setLogger() instead. */ public function setDebugger(DebuggerInterface $debugger) { $this->debugger = $debugger; } } PK!yAn n 3Symfony/Component/Templating/Loader/CacheLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\Storage\FileStorage; use Symfony\Component\Templating\TemplateReferenceInterface; /** * CacheLoader is a loader that caches other loaders responses * on the filesystem. * * This cache only caches on disk to allow PHP accelerators to cache the opcodes. * All other mechanism would imply the use of `eval()`. * * @author Fabien Potencier */ class CacheLoader extends Loader { protected $loader; protected $dir; /** * Constructor. * * @param LoaderInterface $loader A Loader instance * @param string $dir The directory where to store the cache files */ public function __construct(LoaderInterface $loader, $dir) { $this->loader = $loader; $this->dir = $dir; } /** * Loads a template. * * @param TemplateReferenceInterface $template A template * * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise */ public function load(TemplateReferenceInterface $template) { $key = hash('sha256', $template->getLogicalName()); $dir = $this->dir.DIRECTORY_SEPARATOR.substr($key, 0, 2); $file = substr($key, 2).'.tpl'; $path = $dir.DIRECTORY_SEPARATOR.$file; if (is_file($path)) { if (null !== $this->logger) { $this->logger->debug(sprintf('Fetching template "%s" from cache', $template->get('name'))); } elseif (null !== $this->debugger) { // just for BC, to be removed in 3.0 $this->debugger->log(sprintf('Fetching template "%s" from cache', $template->get('name'))); } return new FileStorage($path); } if (false === $storage = $this->loader->load($template)) { return false; } $content = $storage->getContent(); if (!is_dir($dir)) { mkdir($dir, 0777, true); } file_put_contents($path, $content); if (null !== $this->logger) { $this->logger->debug(sprintf('Storing template "%s" in cache', $template->get('name'))); } elseif (null !== $this->debugger) { // just for BC, to be removed in 3.0 $this->debugger->log(sprintf('Storing template "%s" in cache', $template->get('name'))); } return new FileStorage($path); } /** * Returns true if the template is still fresh. * * @param TemplateReferenceInterface $template A template * @param integer $time The last modification time of the cached template (timestamp) * * @return Boolean */ public function isFresh(TemplateReferenceInterface $template, $time) { return $this->loader->isFresh($template, $time); } } PK!I * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Loader; use Symfony\Component\Templating\TemplateReferenceInterface; use Symfony\Component\Templating\Storage\Storage; /** * LoaderInterface is the interface all loaders must implement. * * @author Fabien Potencier * * @api */ interface LoaderInterface { /** * Loads a template. * * @param TemplateReferenceInterface $template A template * * @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise * * @api */ public function load(TemplateReferenceInterface $template); /** * Returns true if the template is still fresh. * * @param TemplateReferenceInterface $template A template * @param integer $time The last modification time of the cached template (timestamp) * * @return Boolean * * @api */ public function isFresh(TemplateReferenceInterface $template, $time); } PK!+rm m 3Symfony/Component/Templating/Helper/SlotsHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; /** * SlotsHelper manages template slots. * * @author Fabien Potencier * * @api */ class SlotsHelper extends Helper { protected $slots = array(); protected $openSlots = array(); /** * Starts a new slot. * * This method starts an output buffer that will be * closed when the stop() method is called. * * @param string $name The slot name * * @throws \InvalidArgumentException if a slot with the same name is already started * * @api */ public function start($name) { if (in_array($name, $this->openSlots)) { throw new \InvalidArgumentException(sprintf('A slot named "%s" is already started.', $name)); } $this->openSlots[] = $name; $this->slots[$name] = ''; ob_start(); ob_implicit_flush(0); } /** * Stops a slot. * * @throws \LogicException if no slot has been started * * @api */ public function stop() { if (!$this->openSlots) { throw new \LogicException('No slot started.'); } $name = array_pop($this->openSlots); $this->slots[$name] = ob_get_clean(); } /** * Returns true if the slot exists. * * @param string $name The slot name * * @return Boolean * * @api */ public function has($name) { return isset($this->slots[$name]); } /** * Gets the slot value. * * @param string $name The slot name * @param Boolean|string $default The default slot content * * @return string The slot content * * @api */ public function get($name, $default = false) { return isset($this->slots[$name]) ? $this->slots[$name] : $default; } /** * Sets a slot value. * * @param string $name The slot name * @param string $content The slot content * * @api */ public function set($name, $content) { $this->slots[$name] = $content; } /** * Outputs a slot. * * @param string $name The slot name * @param Boolean|string $default The default slot content * * @return Boolean true if the slot is defined or if a default content has been provided, false otherwise * * @api */ public function output($name, $default = false) { if (!isset($this->slots[$name])) { if (false !== $default) { echo $default; return true; } return false; } echo $this->slots[$name]; return true; } /** * Returns the canonical name of this helper. * * @return string The canonical name * * @api */ public function getName() { return 'slots'; } } PK!V¤՟4Symfony/Component/Templating/Helper/AssetsHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; use Symfony\Component\Templating\Asset\PathPackage; use Symfony\Component\Templating\Asset\UrlPackage; /** * AssetsHelper helps manage asset URLs. * * Usage: * * * * * * @author Fabien Potencier * @author Kris Wallsmith */ class AssetsHelper extends CoreAssetsHelper { /** * Constructor. * * @param string $basePath The base path * @param string|array $baseUrls Base asset URLs * @param string $version The asset version * @param string $format The version format * @param array $namedPackages Additional packages */ public function __construct($basePath = null, $baseUrls = array(), $version = null, $format = null, $namedPackages = array()) { if ($baseUrls) { $defaultPackage = new UrlPackage($baseUrls, $version, $format); } else { $defaultPackage = new PathPackage($basePath, $version, $format); } parent::__construct($defaultPackage, $namedPackages); } } PK!Է7Symfony/Component/Templating/Helper/HelperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; /** * HelperInterface is the interface all helpers must implement. * * @author Fabien Potencier * * @api */ interface HelperInterface { /** * Returns the canonical name of this helper. * * @return string The canonical name * * @api */ public function getName(); /** * Sets the default charset. * * @param string $charset The charset * * @api */ public function setCharset($charset); /** * Gets the default charset. * * @return string The default charset * * @api */ public function getCharset(); } PK! 8Symfony/Component/Templating/Helper/CoreAssetsHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; use Symfony\Component\Templating\Asset\PackageInterface; /** * CoreAssetsHelper helps manage asset URLs. * * Usage: * * * * * * @author Fabien Potencier * @author Kris Wallsmith */ class CoreAssetsHelper extends Helper implements PackageInterface { protected $defaultPackage; protected $namedPackages = array(); /** * Constructor. * * @param PackageInterface $defaultPackage The default package * @param array $namedPackages Additional packages indexed by name */ public function __construct(PackageInterface $defaultPackage, array $namedPackages = array()) { $this->defaultPackage = $defaultPackage; foreach ($namedPackages as $name => $package) { $this->addPackage($name, $package); } } /** * Sets the default package. * * @param PackageInterface $defaultPackage The default package */ public function setDefaultPackage(PackageInterface $defaultPackage) { $this->defaultPackage = $defaultPackage; } /** * Adds an asset package to the helper. * * @param string $name The package name * @param PackageInterface $package The package */ public function addPackage($name, PackageInterface $package) { $this->namedPackages[$name] = $package; } /** * Returns an asset package. * * @param string $name The name of the package or null for the default package * * @return PackageInterface An asset package * * @throws \InvalidArgumentException If there is no package by that name */ public function getPackage($name = null) { if (null === $name) { return $this->defaultPackage; } if (!isset($this->namedPackages[$name])) { throw new \InvalidArgumentException(sprintf('There is no "%s" asset package.', $name)); } return $this->namedPackages[$name]; } /** * Gets the version to add to public URL. * * @param string $packageName A package name * * @return string The current version */ public function getVersion($packageName = null) { return $this->getPackage($packageName)->getVersion(); } /** * Returns the public path. * * Absolute paths (i.e. http://...) are returned unmodified. * * @param string $path A public path * @param string $packageName The name of the asset package to use * * @return string A public path which takes into account the base path and URL path */ public function getUrl($path, $packageName = null) { return $this->getPackage($packageName)->getUrl($path); } /** * Returns the canonical name of this helper. * * @return string The canonical name */ public function getName() { return 'assets'; } } PK!NO.Symfony/Component/Templating/Helper/Helper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Helper; /** * Helper is the base class for all helper classes. * * Most of the time, a Helper is an adapter around an existing * class that exposes a read-only interface for templates. * * @author Fabien Potencier * * @api */ abstract class Helper implements HelperInterface { protected $charset = 'UTF-8'; /** * Sets the default charset. * * @param string $charset The charset * * @api */ public function setCharset($charset) { $this->charset = $charset; } /** * Gets the default charset. * * @return string The default charset * * @api */ public function getCharset() { return $this->charset; } } PK!_6H  1Symfony/Component/Templating/DelegatingEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; /** * DelegatingEngine selects an engine for a given template. * * @author Fabien Potencier * * @api */ class DelegatingEngine implements EngineInterface, StreamingEngineInterface { /** * @var EngineInterface[] */ protected $engines = array(); /** * Constructor. * * @param EngineInterface[] $engines An array of EngineInterface instances to add * * @api */ public function __construct(array $engines = array()) { foreach ($engines as $engine) { $this->addEngine($engine); } } /** * {@inheritdoc} * * @api */ public function render($name, array $parameters = array()) { return $this->getEngine($name)->render($name, $parameters); } /** * {@inheritdoc} * * @api */ public function stream($name, array $parameters = array()) { $engine = $this->getEngine($name); if (!$engine instanceof StreamingEngineInterface) { throw new \LogicException(sprintf('Template "%s" cannot be streamed as the engine supporting it does not implement StreamingEngineInterface.', $name)); } $engine->stream($name, $parameters); } /** * {@inheritdoc} * * @api */ public function exists($name) { return $this->getEngine($name)->exists($name); } /** * Adds an engine. * * @param EngineInterface $engine An EngineInterface instance * * @api */ public function addEngine(EngineInterface $engine) { $this->engines[] = $engine; } /** * {@inheritdoc} * * @api */ public function supports($name) { try { $this->getEngine($name); } catch (\RuntimeException $e) { return false; } return true; } /** * Get an engine able to render the given template. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return EngineInterface The engine * * @throws \RuntimeException if no engine able to work with the template is found * * @api */ public function getEngine($name) { foreach ($this->engines as $engine) { if ($engine->supports($name)) { return $engine; } } throw new \RuntimeException(sprintf('No engine is able to work with the template "%s".', $name)); } } PK!?w y=y=*Symfony/Component/Templating/PhpEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\Storage\FileStorage; use Symfony\Component\Templating\Storage\StringStorage; use Symfony\Component\Templating\Helper\HelperInterface; use Symfony\Component\Templating\Loader\LoaderInterface; if (!defined('ENT_SUBSTITUTE')) { define('ENT_SUBSTITUTE', 8); } /** * PhpEngine is an engine able to render PHP templates. * * @author Fabien Potencier * * @api */ class PhpEngine implements EngineInterface, \ArrayAccess { protected $loader; protected $current; protected $helpers = array(); protected $parents = array(); protected $stack = array(); protected $charset = 'UTF-8'; protected $cache = array(); protected $escapers = array(); protected static $escaperCache = array(); protected $globals = array(); protected $parser; private $evalTemplate; private $evalParameters; /** * Constructor. * * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance * @param LoaderInterface $loader A loader instance * @param HelperInterface[] $helpers An array of helper instances */ public function __construct(TemplateNameParserInterface $parser, LoaderInterface $loader, array $helpers = array()) { $this->parser = $parser; $this->loader = $loader; $this->addHelpers($helpers); $this->initializeEscapers(); foreach ($this->escapers as $context => $escaper) { $this->setEscaper($context, $escaper); } } /** * {@inheritdoc} * * @throws \InvalidArgumentException if the template does not exist * * @api */ public function render($name, array $parameters = array()) { $storage = $this->load($name); $key = hash('sha256', serialize($storage)); $this->current = $key; $this->parents[$key] = null; // attach the global variables $parameters = array_replace($this->getGlobals(), $parameters); // render if (false === $content = $this->evaluate($storage, $parameters)) { throw new \RuntimeException(sprintf('The template "%s" cannot be rendered.', $this->parser->parse($name))); } // decorator if ($this->parents[$key]) { $slots = $this->get('slots'); $this->stack[] = $slots->get('_content'); $slots->set('_content', $content); $content = $this->render($this->parents[$key], $parameters); $slots->set('_content', array_pop($this->stack)); } return $content; } /** * {@inheritdoc} * * @api */ public function exists($name) { try { $this->load($name); } catch (\InvalidArgumentException $e) { return false; } return true; } /** * {@inheritdoc} * * @api */ public function supports($name) { $template = $this->parser->parse($name); return 'php' === $template->get('engine'); } /** * Evaluates a template. * * @param Storage $template The template to render * @param array $parameters An array of parameters to pass to the template * * @return string|false The evaluated template, or false if the engine is unable to render the template * * @throws \InvalidArgumentException */ protected function evaluate(Storage $template, array $parameters = array()) { $this->evalTemplate = $template; $this->evalParameters = $parameters; unset($template, $parameters); if (isset($this->evalParameters['this'])) { throw new \InvalidArgumentException('Invalid parameter (this)'); } if (isset($this->evalParameters['view'])) { throw new \InvalidArgumentException('Invalid parameter (view)'); } $view = $this; if ($this->evalTemplate instanceof FileStorage) { extract($this->evalParameters, EXTR_SKIP); $this->evalParameters = null; ob_start(); require $this->evalTemplate; $this->evalTemplate = null; return ob_get_clean(); } elseif ($this->evalTemplate instanceof StringStorage) { extract($this->evalParameters, EXTR_SKIP); $this->evalParameters = null; ob_start(); eval('; ?>'.$this->evalTemplate.'evalTemplate = null; return ob_get_clean(); } return false; } /** * Gets a helper value. * * @param string $name The helper name * * @return HelperInterface The helper value * * @throws \InvalidArgumentException if the helper is not defined * * @api */ public function offsetGet($name) { return $this->get($name); } /** * Returns true if the helper is defined. * * @param string $name The helper name * * @return Boolean true if the helper is defined, false otherwise * * @api */ public function offsetExists($name) { return isset($this->helpers[$name]); } /** * Sets a helper. * * @param HelperInterface $name The helper instance * @param string $value An alias * * @api */ public function offsetSet($name, $value) { $this->set($name, $value); } /** * Removes a helper. * * @param string $name The helper name * * @throws \LogicException * * @api */ public function offsetUnset($name) { throw new \LogicException(sprintf('You can\'t unset a helper (%s).', $name)); } /** * Adds some helpers. * * @param HelperInterface[] $helpers An array of helper * * @api */ public function addHelpers(array $helpers) { foreach ($helpers as $alias => $helper) { $this->set($helper, is_int($alias) ? null : $alias); } } /** * Sets the helpers. * * @param HelperInterface[] $helpers An array of helper * * @api */ public function setHelpers(array $helpers) { $this->helpers = array(); $this->addHelpers($helpers); } /** * Sets a helper. * * @param HelperInterface $helper The helper instance * @param string $alias An alias * * @api */ public function set(HelperInterface $helper, $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { $this->helpers[$alias] = $helper; } $helper->setCharset($this->charset); } /** * Returns true if the helper if defined. * * @param string $name The helper name * * @return Boolean true if the helper is defined, false otherwise * * @api */ public function has($name) { return isset($this->helpers[$name]); } /** * Gets a helper value. * * @param string $name The helper name * * @return HelperInterface The helper instance * * @throws \InvalidArgumentException if the helper is not defined * * @api */ public function get($name) { if (!isset($this->helpers[$name])) { throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); } return $this->helpers[$name]; } /** * Decorates the current template with another one. * * @param string $template The decorator logical name * * @api */ public function extend($template) { $this->parents[$this->current] = $template; } /** * Escapes a string by using the current charset. * * @param mixed $value A variable to escape * @param string $context The context name * * @return string The escaped value * * @api */ public function escape($value, $context = 'html') { if (is_numeric($value)) { return $value; } // If we deal with a scalar value, we can cache the result to increase // the performance when the same value is escaped multiple times (e.g. loops) if (is_scalar($value)) { if (!isset(self::$escaperCache[$context][$value])) { self::$escaperCache[$context][$value] = call_user_func($this->getEscaper($context), $value); } return self::$escaperCache[$context][$value]; } return call_user_func($this->getEscaper($context), $value); } /** * Sets the charset to use. * * @param string $charset The charset * * @api */ public function setCharset($charset) { $this->charset = $charset; } /** * Gets the current charset. * * @return string The current charset * * @api */ public function getCharset() { return $this->charset; } /** * Adds an escaper for the given context. * * @param string $context The escaper context (html, js, ...) * @param mixed $escaper A PHP callable * * @api */ public function setEscaper($context, $escaper) { $this->escapers[$context] = $escaper; self::$escaperCache[$context] = array(); } /** * Gets an escaper for a given context. * * @param string $context The context name * * @return mixed $escaper A PHP callable * * @throws \InvalidArgumentException * * @api */ public function getEscaper($context) { if (!isset($this->escapers[$context])) { throw new \InvalidArgumentException(sprintf('No registered escaper for context "%s".', $context)); } return $this->escapers[$context]; } /** * @param string $name * @param mixed $value * * @api */ public function addGlobal($name, $value) { $this->globals[$name] = $value; } /** * Returns the assigned globals. * * @return array * * @api */ public function getGlobals() { return $this->globals; } /** * Initializes the built-in escapers. * * Each function specifies a way for applying a transformation to a string * passed to it. The purpose is for the string to be "escaped" so it is * suitable for the format it is being displayed in. * * For example, the string: "It's required that you enter a username & password.\n" * If this were to be displayed as HTML it would be sensible to turn the * ampersand into '&' and the apostrophe into '&aps;'. However if it were * going to be used as a string in JavaScript to be displayed in an alert box * it would be right to leave the string as-is, but c-escape the apostrophe and * the new line. * * For each function there is a define to avoid problems with strings being * incorrectly specified. */ protected function initializeEscapers() { $that = $this; $this->escapers = array( 'html' => /** * Runs the PHP function htmlspecialchars on the value passed. * * @param string $value the value to escape * * @return string the escaped value */ function ($value) use ($that) { // Numbers and Boolean values get turned into strings which can cause problems // with type comparisons (e.g. === or is_int() etc). return is_string($value) ? htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, $that->getCharset(), false) : $value; }, 'js' => /** * A function that escape all non-alphanumeric characters * into their \xHH or \uHHHH representations * * @param string $value the value to escape * @return string the escaped value */ function ($value) use ($that) { if ('UTF-8' != $that->getCharset()) { $value = $that->convertEncoding($value, 'UTF-8', $that->getCharset()); } $callback = function ($matches) use ($that) { $char = $matches[0]; // \xHH if (!isset($char[1])) { return '\\x'.substr('00'.bin2hex($char), -2); } // \uHHHH $char = $that->convertEncoding($char, 'UTF-16BE', 'UTF-8'); return '\\u'.substr('0000'.bin2hex($char), -4); }; if (null === $value = preg_replace_callback('#[^\p{L}\p{N} ]#u', $callback, $value)) { throw new \InvalidArgumentException('The string to escape is not a valid UTF-8 string.'); } if ('UTF-8' != $that->getCharset()) { $value = $that->convertEncoding($value, $that->getCharset(), 'UTF-8'); } return $value; }, ); self::$escaperCache = array(); } /** * Convert a string from one encoding to another. * * @param string $string The string to convert * @param string $to The input encoding * @param string $from The output encoding * * @return string The string with the new encoding * * @throws \RuntimeException if no suitable encoding function is found (iconv or mbstring) */ public function convertEncoding($string, $to, $from) { if (function_exists('mb_convert_encoding')) { return mb_convert_encoding($string, $to, $from); } elseif (function_exists('iconv')) { return iconv($from, $to, $string); } throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); } /** * Gets the loader associated with this engine. * * @return LoaderInterface A LoaderInterface instance */ public function getLoader() { return $this->loader; } /** * Loads the given template. * * @param string|TemplateReferenceInterface $name A template name or a TemplateReferenceInterface instance * * @return Storage A Storage instance * * @throws \InvalidArgumentException if the template cannot be found */ protected function load($name) { $template = $this->parser->parse($name); $key = $template->getLogicalName(); if (isset($this->cache[$key])) { return $this->cache[$key]; } $storage = $this->loader->load($template); if (false === $storage) { throw new \InvalidArgumentException(sprintf('The template "%s" does not exist.', $template)); } return $this->cache[$key] = $storage; } } PK!6H $Symfony/Component/Yaml/Unescaper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; /** * Unescaper encapsulates unescaping rules for single and double-quoted * YAML strings. * * @author Matthew Lewinski */ class Unescaper { // Parser and Inline assume UTF-8 encoding, so escaped Unicode characters // must be converted to that encoding. const ENCODING = 'UTF-8'; // Regex fragment that matches an escaped character in a double quoted // string. const REGEX_ESCAPED_CHARACTER = "\\\\([0abt\tnvfre \\\"\\/\\\\N_LP]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})"; /** * Unescapes a single quoted string. * * @param string $value A single quoted string. * * @return string The unescaped string. */ public function unescapeSingleQuotedString($value) { return str_replace('\'\'', '\'', $value); } /** * Unescapes a double quoted string. * * @param string $value A double quoted string. * * @return string The unescaped string. */ public function unescapeDoubleQuotedString($value) { $self = $this; $callback = function ($match) use ($self) { return $self->unescapeCharacter($match[0]); }; // evaluate the string return preg_replace_callback('/'.self::REGEX_ESCAPED_CHARACTER.'/u', $callback, $value); } /** * Unescapes a character that was found in a double-quoted string * * @param string $value An escaped character * * @return string The unescaped character */ public function unescapeCharacter($value) { switch ($value{1}) { case '0': return "\x0"; case 'a': return "\x7"; case 'b': return "\x8"; case 't': return "\t"; case "\t": return "\t"; case 'n': return "\n"; case 'v': return "\xb"; case 'f': return "\xc"; case 'r': return "\xd"; case 'e': return "\x1b"; case ' ': return ' '; case '"': return '"'; case '/': return '/'; case '\\': return '\\'; case 'N': // U+0085 NEXT LINE return $this->convertEncoding("\x00\x85", self::ENCODING, 'UCS-2BE'); case '_': // U+00A0 NO-BREAK SPACE return $this->convertEncoding("\x00\xA0", self::ENCODING, 'UCS-2BE'); case 'L': // U+2028 LINE SEPARATOR return $this->convertEncoding("\x20\x28", self::ENCODING, 'UCS-2BE'); case 'P': // U+2029 PARAGRAPH SEPARATOR return $this->convertEncoding("\x20\x29", self::ENCODING, 'UCS-2BE'); case 'x': $char = pack('n', hexdec(substr($value, 2, 2))); return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE'); case 'u': $char = pack('n', hexdec(substr($value, 2, 4))); return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE'); case 'U': $char = pack('N', hexdec(substr($value, 2, 8))); return $this->convertEncoding($char, self::ENCODING, 'UCS-4BE'); } } /** * Convert a string from one encoding to another. * * @param string $value The string to convert * @param string $to The input encoding * @param string $from The output encoding * * @return string The string with the new encoding * * @throws \RuntimeException if no suitable encoding function is found (iconv or mbstring) */ private function convertEncoding($value, $to, $from) { if (function_exists('mb_convert_encoding')) { return mb_convert_encoding($value, $to, $from); } elseif (function_exists('iconv')) { return iconv($from, $to, $value); } throw new \RuntimeException('No suitable convert encoding function (install the iconv or mbstring extension).'); } } PK!8n !Symfony/Component/Yaml/Dumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; /** * Dumper dumps PHP variables to YAML strings. * * @author Fabien Potencier */ class Dumper { /** * The amount of spaces to use for indentation of nested nodes. * * @var integer */ protected $indentation = 4; /** * Sets the indentation. * * @param integer $num The amount of spaces to use for indentation of nested nodes. */ public function setIndentation($num) { $this->indentation = (int) $num; } /** * Dumps a PHP value to YAML. * * @param mixed $input The PHP value * @param integer $inline The level where you switch to inline YAML * @param integer $indent The level of indentation (used internally) * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return string The YAML representation of the PHP value */ public function dump($input, $inline = 0, $indent = 0, $exceptionOnInvalidType = false, $objectSupport = false) { $output = ''; $prefix = $indent ? str_repeat(' ', $indent) : ''; if ($inline <= 0 || !is_array($input) || empty($input)) { $output .= $prefix.Inline::dump($input, $exceptionOnInvalidType, $objectSupport); } else { $isAHash = array_keys($input) !== range(0, count($input) - 1); foreach ($input as $key => $value) { $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value); $output .= sprintf('%s%s%s%s', $prefix, $isAHash ? Inline::dump($key, $exceptionOnInvalidType, $objectSupport).':' : '-', $willBeInlined ? ' ' : "\n", $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $exceptionOnInvalidType, $objectSupport) ).($willBeInlined ? "\n" : ''); } } return $output; } } PK!bNN%Symfony/Component/Yaml/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; use Symfony\Component\Yaml\Exception\ParseException; /** * Parser parses YAML strings to convert them to PHP arrays. * * @author Fabien Potencier */ class Parser { const FOLDED_SCALAR_PATTERN = '(?P\||>)(?P\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P +#.*)?'; private $offset = 0; private $lines = array(); private $currentLineNb = -1; private $currentLine = ''; private $refs = array(); /** * Constructor * * @param integer $offset The offset of YAML document (used for line numbers in error messages) */ public function __construct($offset = 0) { $this->offset = $offset; } /** * Parses a YAML string to a PHP value. * * @param string $value A YAML string * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return mixed A PHP value * * @throws ParseException If the YAML is not valid */ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = false) { $this->currentLineNb = -1; $this->currentLine = ''; $this->lines = explode("\n", $this->cleanup($value)); if (function_exists('mb_detect_encoding') && false === mb_detect_encoding($value, 'UTF-8', true)) { throw new ParseException('The YAML value does not appear to be valid UTF-8.'); } if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { $mbEncoding = mb_internal_encoding(); mb_internal_encoding('UTF-8'); } $data = array(); $context = null; while ($this->moveToNextLine()) { if ($this->isCurrentLineEmpty()) { continue; } // tab? if ("\t" === $this->currentLine[0]) { throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } $isRef = $isInPlace = $isProcessed = false; if (preg_match('#^\-((?P\s+)(?P.+?))?\s*$#u', $this->currentLine, $values)) { if ($context && 'mapping' == $context) { throw new ParseException('You cannot define a sequence item when in a mapping'); } $context = 'sequence'; if (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; $values['value'] = $matches['value']; } // array if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { $c = $this->getRealCurrentLineNb() + 1; $parser = new Parser($c); $parser->refs =& $this->refs; $data[] = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport); } else { if (isset($values['leadspaces']) && ' ' == $values['leadspaces'] && preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P.+?))?\s*$#u', $values['value'], $matches) ) { // this is a compact notation element, add to next block and parse $c = $this->getRealCurrentLineNb(); $parser = new Parser($c); $parser->refs =& $this->refs; $block = $values['value']; if ($this->isNextLineIndented()) { $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2); } $data[] = $parser->parse($block, $exceptionOnInvalidType, $objectSupport); } else { $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport); } } } elseif (preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P.+?))?\s*$#u', $this->currentLine, $values) && false === strpos($values['key'],' #')) { if ($context && 'sequence' == $context) { throw new ParseException('You cannot define a mapping item when in a sequence'); } $context = 'mapping'; // force correct settings Inline::parse(null, $exceptionOnInvalidType, $objectSupport); try { $key = Inline::parseScalar($values['key']); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); throw $e; } if ('<<' === $key) { if (isset($values['value']) && 0 === strpos($values['value'], '*')) { $isInPlace = substr($values['value'], 1); if (!array_key_exists($isInPlace, $this->refs)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $isInPlace), $this->getRealCurrentLineNb() + 1, $this->currentLine); } } else { if (isset($values['value']) && $values['value'] !== '') { $value = $values['value']; } else { $value = $this->getNextEmbedBlock(); } $c = $this->getRealCurrentLineNb() + 1; $parser = new Parser($c); $parser->refs =& $this->refs; $parsed = $parser->parse($value, $exceptionOnInvalidType, $objectSupport); $merged = array(); if (!is_array($parsed)) { throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } elseif (isset($parsed[0])) { // Numeric array, merge individual elements foreach (array_reverse($parsed) as $parsedItem) { if (!is_array($parsedItem)) { throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem); } $merged = array_merge($parsedItem, $merged); } } else { // Associative array, merge $merged = array_merge($merged, $parsed); } $isProcessed = $merged; } } elseif (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; $values['value'] = $matches['value']; } if ($isProcessed) { // Merge keys $data = $isProcessed; // hash } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { // if next line is less indented or equal, then it means that the current value is null if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { $data[$key] = null; } else { $c = $this->getRealCurrentLineNb() + 1; $parser = new Parser($c); $parser->refs =& $this->refs; $data[$key] = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport); } } else { if ($isInPlace) { $data = $this->refs[$isInPlace]; } else { $data[$key] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport); } } } else { // 1-liner optionally followed by newline $lineCount = count($this->lines); if (1 === $lineCount || (2 === $lineCount && empty($this->lines[1]))) { try { $value = Inline::parse($this->lines[0], $exceptionOnInvalidType, $objectSupport); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); throw $e; } if (is_array($value)) { $first = reset($value); if (is_string($first) && 0 === strpos($first, '*')) { $data = array(); foreach ($value as $alias) { $data[] = $this->refs[substr($alias, 1)]; } $value = $data; } } if (isset($mbEncoding)) { mb_internal_encoding($mbEncoding); } return $value; } switch (preg_last_error()) { case PREG_INTERNAL_ERROR: $error = 'Internal PCRE error.'; break; case PREG_BACKTRACK_LIMIT_ERROR: $error = 'pcre.backtrack_limit reached.'; break; case PREG_RECURSION_LIMIT_ERROR: $error = 'pcre.recursion_limit reached.'; break; case PREG_BAD_UTF8_ERROR: $error = 'Malformed UTF-8 data.'; break; case PREG_BAD_UTF8_OFFSET_ERROR: $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.'; break; default: $error = 'Unable to parse.'; } throw new ParseException($error, $this->getRealCurrentLineNb() + 1, $this->currentLine); } if ($isRef) { $this->refs[$isRef] = end($data); } } if (isset($mbEncoding)) { mb_internal_encoding($mbEncoding); } return empty($data) ? null : $data; } /** * Returns the current line number (takes the offset into account). * * @return integer The current line number */ private function getRealCurrentLineNb() { return $this->currentLineNb + $this->offset; } /** * Returns the current line indentation. * * @return integer The current line indentation */ private function getCurrentLineIndentation() { return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' ')); } /** * Returns the next embed block of YAML. * * @param integer $indentation The indent level at which the block is to be read, or null for default * * @return string A YAML string * * @throws ParseException When indentation problem are detected */ private function getNextEmbedBlock($indentation = null) { $this->moveToNextLine(); if (null === $indentation) { $newIndent = $this->getCurrentLineIndentation(); $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem($this->currentLine); if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) { throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } } else { $newIndent = $indentation; } $data = array(substr($this->currentLine, $newIndent)); $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine); // Comments must not be removed inside a string block (ie. after a line ending with "|") $removeCommentsPattern = '~'.self::FOLDED_SCALAR_PATTERN.'$~'; $removeComments = !preg_match($removeCommentsPattern, $this->currentLine); while ($this->moveToNextLine()) { $indent = $this->getCurrentLineIndentation(); if ($indent === $newIndent) { $removeComments = !preg_match($removeCommentsPattern, $this->currentLine); } if ($isItUnindentedCollection && !$this->isStringUnIndentedCollectionItem($this->currentLine)) { $this->moveToPreviousLine(); break; } if ($this->isCurrentLineBlank()) { $data[] = substr($this->currentLine, $newIndent); continue; } if ($removeComments && $this->isCurrentLineComment()) { continue; } if ($indent >= $newIndent) { $data[] = substr($this->currentLine, $newIndent); } elseif (0 == $indent) { $this->moveToPreviousLine(); break; } else { throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } } return implode("\n", $data); } /** * Moves the parser to the next line. * * @return Boolean */ private function moveToNextLine() { if ($this->currentLineNb >= count($this->lines) - 1) { return false; } $this->currentLine = $this->lines[++$this->currentLineNb]; return true; } /** * Moves the parser to the previous line. */ private function moveToPreviousLine() { $this->currentLine = $this->lines[--$this->currentLineNb]; } /** * Parses a YAML value. * * @param string $value A YAML value * @param Boolean $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise * @param Boolean $objectSupport True if object support is enabled, false otherwise * * @return mixed A PHP value * * @throws ParseException When reference does not exist */ private function parseValue($value, $exceptionOnInvalidType, $objectSupport) { if (0 === strpos($value, '*')) { if (false !== $pos = strpos($value, '#')) { $value = substr($value, 1, $pos - 2); } else { $value = substr($value, 1); } if (!array_key_exists($value, $this->refs)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLine); } return $this->refs[$value]; } if (preg_match('/^'.self::FOLDED_SCALAR_PATTERN.'$/', $value, $matches)) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers))); } try { return Inline::parse($value, $exceptionOnInvalidType, $objectSupport); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); throw $e; } } /** * Parses a folded scalar. * * @param string $separator The separator that was used to begin this folded scalar (| or >) * @param string $indicator The indicator that was used to begin this folded scalar (+ or -) * @param integer $indentation The indentation that was used to begin this folded scalar * * @return string The text value */ private function parseFoldedScalar($separator, $indicator = '', $indentation = 0) { $notEOF = $this->moveToNextLine(); if (!$notEOF) { return ''; } $isCurrentLineBlank = $this->isCurrentLineBlank(); $text = ''; // leading blank lines are consumed before determining indentation while ($notEOF && $isCurrentLineBlank) { // newline only if not EOF if ($notEOF = $this->moveToNextLine()) { $text .= "\n"; $isCurrentLineBlank = $this->isCurrentLineBlank(); } } // determine indentation if not specified if (0 === $indentation) { if (preg_match('/^ +/', $this->currentLine, $matches)) { $indentation = strlen($matches[0]); } } if ($indentation > 0) { $pattern = sprintf('/^ {%d}(.*)$/', $indentation); while ( $notEOF && ( $isCurrentLineBlank || preg_match($pattern, $this->currentLine, $matches) ) ) { if ($isCurrentLineBlank) { $text .= substr($this->currentLine, $indentation); } else { $text .= $matches[1]; } // newline only if not EOF if ($notEOF = $this->moveToNextLine()) { $text .= "\n"; $isCurrentLineBlank = $this->isCurrentLineBlank(); } } } elseif ($notEOF) { $text .= "\n"; } if ($notEOF) { $this->moveToPreviousLine(); } // replace all non-trailing single newlines with spaces in folded blocks if ('>' === $separator) { preg_match('/(\n*)$/', $text, $matches); $text = preg_replace('/(?getCurrentLineIndentation(); $EOF = !$this->moveToNextLine(); while (!$EOF && $this->isCurrentLineEmpty()) { $EOF = !$this->moveToNextLine(); } if ($EOF) { return false; } $ret = false; if ($this->getCurrentLineIndentation() > $currentIndentation) { $ret = true; } $this->moveToPreviousLine(); return $ret; } /** * Returns true if the current line is blank or if it is a comment line. * * @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise */ private function isCurrentLineEmpty() { return $this->isCurrentLineBlank() || $this->isCurrentLineComment(); } /** * Returns true if the current line is blank. * * @return Boolean Returns true if the current line is blank, false otherwise */ private function isCurrentLineBlank() { return '' == trim($this->currentLine, ' '); } /** * Returns true if the current line is a comment line. * * @return Boolean Returns true if the current line is a comment line, false otherwise */ private function isCurrentLineComment() { //checking explicitly the first char of the trim is faster than loops or strpos $ltrimmedLine = ltrim($this->currentLine, ' '); return $ltrimmedLine[0] === '#'; } /** * Cleanups a YAML string to be parsed. * * @param string $value The input YAML string * * @return string A cleaned up YAML string */ private function cleanup($value) { $value = str_replace(array("\r\n", "\r"), "\n", $value); // strip YAML header $count = 0; $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#su', '', $value, -1, $count); $this->offset += $count; // remove leading comments $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count); if ($count == 1) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; } // remove start of the document marker (---) $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count); if ($count == 1) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; // remove end of the document marker (...) $value = preg_replace('#\.\.\.\s*$#s', '', $value); } return $value; } /** * Returns true if the next line starts unindented collection * * @return Boolean Returns true if the next line starts unindented collection, false otherwise */ private function isNextLineUnIndentedCollection() { $currentIndentation = $this->getCurrentLineIndentation(); $notEOF = $this->moveToNextLine(); while ($notEOF && $this->isCurrentLineEmpty()) { $notEOF = $this->moveToNextLine(); } if (false === $notEOF) { return false; } $ret = false; if ( $this->getCurrentLineIndentation() == $currentIndentation && $this->isStringUnIndentedCollectionItem($this->currentLine) ) { $ret = true; } $this->moveToPreviousLine(); return $ret; } /** * Returns true if the string is un-indented collection item * * @return Boolean Returns true if the string is un-indented collection item, false otherwise */ private function isStringUnIndentedCollectionItem() { return (0 === strpos($this->currentLine, '- ')); } } PK!7MӺ  Symfony/Component/Yaml/Yaml.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; use Symfony\Component\Yaml\Exception\ParseException; /** * Yaml offers convenience methods to load and dump YAML. * * @author Fabien Potencier * * @api */ class Yaml { /** * Parses YAML into a PHP array. * * The parse method, when supplied with a YAML stream (string or file), * will do its best to convert YAML in a file into a PHP array. * * Usage: * * $array = Yaml::parse('config.yml'); * print_r($array); * * * As this method accepts both plain strings and file names as an input, * you must validate the input before calling this method. Passing a file * as an input is a deprecated feature and will be removed in 3.0. * * @param string $input Path to a YAML file or a string containing YAML * @param Boolean $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise * @param Boolean $objectSupport True if object support is enabled, false otherwise * * @return array The YAML converted to a PHP array * * @throws ParseException If the YAML is not valid * * @api */ public static function parse($input, $exceptionOnInvalidType = false, $objectSupport = false) { // if input is a file, process it $file = ''; if (strpos($input, "\n") === false && is_file($input)) { if (false === is_readable($input)) { throw new ParseException(sprintf('Unable to parse "%s" as the file is not readable.', $input)); } $file = $input; $input = file_get_contents($file); } $yaml = new Parser(); try { return $yaml->parse($input, $exceptionOnInvalidType, $objectSupport); } catch (ParseException $e) { if ($file) { $e->setParsedFile($file); } throw $e; } } /** * Dumps a PHP array to a YAML string. * * The dump method, when supplied with an array, will do its best * to convert the array into friendly YAML. * * @param array $array PHP array * @param integer $inline The level where you switch to inline YAML * @param integer $indent The amount of spaces to use for indentation of nested nodes. * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return string A YAML string representing the original PHP array * * @api */ public static function dump($array, $inline = 2, $indent = 4, $exceptionOnInvalidType = false, $objectSupport = false) { $yaml = new Dumper(); $yaml->setIndentation($indent); return $yaml->dump($array, $inline, 0, $exceptionOnInvalidType, $objectSupport); } } PK!+l7Symfony/Component/Yaml/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Fabien Potencier * * @api */ interface ExceptionInterface { } PK!|-5Symfony/Component/Yaml/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception class thrown when an error occurs during parsing. * * @author Romain Neutron * * @api */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK! 3Symfony/Component/Yaml/Exception/ParseException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; if (!defined('JSON_UNESCAPED_UNICODE')) { define('JSON_UNESCAPED_SLASHES', 64); define('JSON_UNESCAPED_UNICODE', 256); } /** * Exception class thrown when an error occurs during parsing. * * @author Fabien Potencier * * @api */ class ParseException extends RuntimeException { private $parsedFile; private $parsedLine; private $snippet; private $rawMessage; /** * Constructor. * * @param string $message The error message * @param integer $parsedLine The line where the error occurred * @param integer $snippet The snippet of code near the problem * @param string $parsedFile The file name where the error occurred * @param \Exception $previous The previous exception */ public function __construct($message, $parsedLine = -1, $snippet = null, $parsedFile = null, \Exception $previous = null) { $this->parsedFile = $parsedFile; $this->parsedLine = $parsedLine; $this->snippet = $snippet; $this->rawMessage = $message; $this->updateRepr(); parent::__construct($this->message, 0, $previous); } /** * Gets the snippet of code near the error. * * @return string The snippet of code */ public function getSnippet() { return $this->snippet; } /** * Sets the snippet of code near the error. * * @param string $snippet The code snippet */ public function setSnippet($snippet) { $this->snippet = $snippet; $this->updateRepr(); } /** * Gets the filename where the error occurred. * * This method returns null if a string is parsed. * * @return string The filename */ public function getParsedFile() { return $this->parsedFile; } /** * Sets the filename where the error occurred. * * @param string $parsedFile The filename */ public function setParsedFile($parsedFile) { $this->parsedFile = $parsedFile; $this->updateRepr(); } /** * Gets the line where the error occurred. * * @return integer The file line */ public function getParsedLine() { return $this->parsedLine; } /** * Sets the line where the error occurred. * * @param integer $parsedLine The file line */ public function setParsedLine($parsedLine) { $this->parsedLine = $parsedLine; $this->updateRepr(); } private function updateRepr() { $this->message = $this->rawMessage; $dot = false; if ('.' === substr($this->message, -1)) { $this->message = substr($this->message, 0, -1); $dot = true; } if (null !== $this->parsedFile) { $this->message .= sprintf(' in %s', json_encode($this->parsedFile, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); } if ($this->parsedLine >= 0) { $this->message .= sprintf(' at line %d', $this->parsedLine); } if ($this->snippet) { $this->message .= sprintf(' (near "%s")', $this->snippet); } if ($dot) { $this->message .= '.'; } } } PK!ؙ՚2Symfony/Component/Yaml/Exception/DumpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception class thrown when an error occurs during dumping. * * @author Fabien Potencier * * @api */ class DumpException extends RuntimeException { } PK!)%,m m "Symfony/Component/Yaml/Escaper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; /** * Escaper encapsulates escaping rules for single and double-quoted * YAML strings. * * @author Matthew Lewinski */ class Escaper { // Characters that would cause a dumped string to require double quoting. const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9"; // Mapping arrays for escaping a double quoted string. The backslash is // first to ensure proper escaping because str_replace operates iteratively // on the input arrays. This ordering of the characters avoids the use of strtr, // which performs more slowly. private static $escapees = array('\\\\', '\\"', '"', "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f", "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9"); private static $escaped = array('\\"', '\\\\', '\\"', "\\0", "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\a", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "\\x0e", "\\x0f", "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17", "\\x18", "\\x19", "\\x1a", "\\e", "\\x1c", "\\x1d", "\\x1e", "\\x1f", "\\N", "\\_", "\\L", "\\P"); /** * Determines if a PHP value would require double quoting in YAML. * * @param string $value A PHP value * * @return Boolean True if the value would require double quotes. */ public static function requiresDoubleQuoting($value) { return preg_match('/'.self::REGEX_CHARACTER_TO_ESCAPE.'/u', $value); } /** * Escapes and surrounds a PHP value with double quotes. * * @param string $value A PHP value * * @return string The quoted, escaped string */ public static function escapeWithDoubleQuotes($value) { return sprintf('"%s"', str_replace(self::$escapees, self::$escaped, $value)); } /** * Determines if a PHP value would require single quoting in YAML. * * @param string $value A PHP value * * @return Boolean True if the value would require single quotes. */ public static function requiresSingleQuoting($value) { return preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ \- ? | < > = ! % @ ` ]/x', $value); } /** * Escapes and surrounds a PHP value with single quotes. * * @param string $value A PHP value * * @return string The quoted, escaped string */ public static function escapeWithSingleQuotes($value) { return sprintf("'%s'", str_replace('\'', '\'\'', $value)); } } PK!q+3??!Symfony/Component/Yaml/Inline.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Exception\DumpException; /** * Inline implements a YAML parser/dumper for the YAML inline syntax. * * @author Fabien Potencier */ class Inline { const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')'; private static $exceptionOnInvalidType = false; private static $objectSupport = false; /** * Converts a YAML string to a PHP array. * * @param string $value A YAML string * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return array A PHP array representing the YAML string * * @throws ParseException */ public static function parse($value, $exceptionOnInvalidType = false, $objectSupport = false) { self::$exceptionOnInvalidType = $exceptionOnInvalidType; self::$objectSupport = $objectSupport; $value = trim($value); if (0 == strlen($value)) { return ''; } if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { $mbEncoding = mb_internal_encoding(); mb_internal_encoding('ASCII'); } $i = 0; switch ($value[0]) { case '[': $result = self::parseSequence($value, $i); ++$i; break; case '{': $result = self::parseMapping($value, $i); ++$i; break; default: $result = self::parseScalar($value, null, array('"', "'"), $i); } // some comments are allowed at the end if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) { throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i))); } if (isset($mbEncoding)) { mb_internal_encoding($mbEncoding); } return $result; } /** * Dumps a given PHP variable to a YAML string. * * @param mixed $value The PHP variable to convert * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return string The YAML string representing the PHP array * * @throws DumpException When trying to dump PHP resource */ public static function dump($value, $exceptionOnInvalidType = false, $objectSupport = false) { switch (true) { case is_resource($value): if ($exceptionOnInvalidType) { throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value))); } return 'null'; case is_object($value): if ($objectSupport) { return '!!php/object:'.serialize($value); } if ($exceptionOnInvalidType) { throw new DumpException('Object support when dumping a YAML file has been disabled.'); } return 'null'; case is_array($value): return self::dumpArray($value, $exceptionOnInvalidType, $objectSupport); case null === $value: return 'null'; case true === $value: return 'true'; case false === $value: return 'false'; case ctype_digit($value): return is_string($value) ? "'$value'" : (int) $value; case is_numeric($value): $locale = setlocale(LC_NUMERIC, 0); if (false !== $locale) { setlocale(LC_NUMERIC, 'C'); } $repr = is_string($value) ? "'$value'" : (is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : strval($value)); if (false !== $locale) { setlocale(LC_NUMERIC, $locale); } return $repr; case Escaper::requiresDoubleQuoting($value): return Escaper::escapeWithDoubleQuotes($value); case Escaper::requiresSingleQuoting($value): return Escaper::escapeWithSingleQuotes($value); case '' == $value: return "''"; case preg_match(self::getTimestampRegex(), $value): case in_array(strtolower($value), array('null', '~', 'true', 'false')): return "'$value'"; default: return $value; } } /** * Dumps a PHP array to a YAML string. * * @param array $value The PHP array to dump * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param Boolean $objectSupport true if object support is enabled, false otherwise * * @return string The YAML string representing the PHP array */ private static function dumpArray($value, $exceptionOnInvalidType, $objectSupport) { // array $keys = array_keys($value); if ((1 == count($keys) && '0' == $keys[0]) || (count($keys) > 1 && array_reduce($keys, function ($v, $w) { return (integer) $v + $w; }, 0) == count($keys) * (count($keys) - 1) / 2) ) { $output = array(); foreach ($value as $val) { $output[] = self::dump($val, $exceptionOnInvalidType, $objectSupport); } return sprintf('[%s]', implode(', ', $output)); } // mapping $output = array(); foreach ($value as $key => $val) { $output[] = sprintf('%s: %s', self::dump($key, $exceptionOnInvalidType, $objectSupport), self::dump($val, $exceptionOnInvalidType, $objectSupport)); } return sprintf('{ %s }', implode(', ', $output)); } /** * Parses a scalar to a YAML string. * * @param scalar $scalar * @param string $delimiters * @param array $stringDelimiters * @param integer &$i * @param Boolean $evaluate * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ public static function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true) { if (in_array($scalar[$i], $stringDelimiters)) { // quoted scalar $output = self::parseQuotedScalar($scalar, $i); if (null !== $delimiters) { $tmp = ltrim(substr($scalar, $i), ' '); if (!in_array($tmp[0], $delimiters)) { throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i))); } } } else { // "normal" string if (!$delimiters) { $output = substr($scalar, $i); $i += strlen($output); // remove comments if (false !== $strpos = strpos($output, ' #')) { $output = rtrim(substr($output, 0, $strpos)); } } elseif (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { $output = $match[1]; $i += strlen($output); } else { throw new ParseException(sprintf('Malformed inline YAML string (%s).', $scalar)); } if ($evaluate) { $output = self::evaluateScalar($output); } } return $output; } /** * Parses a quoted scalar to YAML. * * @param string $scalar * @param integer &$i * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ private static function parseQuotedScalar($scalar, &$i) { if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { throw new ParseException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i))); } $output = substr($match[0], 1, strlen($match[0]) - 2); $unescaper = new Unescaper(); if ('"' == $scalar[$i]) { $output = $unescaper->unescapeDoubleQuotedString($output); } else { $output = $unescaper->unescapeSingleQuotedString($output); } $i += strlen($match[0]); return $output; } /** * Parses a sequence to a YAML string. * * @param string $sequence * @param integer &$i * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ private static function parseSequence($sequence, &$i = 0) { $output = array(); $len = strlen($sequence); $i += 1; // [foo, bar, ...] while ($i < $len) { switch ($sequence[$i]) { case '[': // nested sequence $output[] = self::parseSequence($sequence, $i); break; case '{': // nested mapping $output[] = self::parseMapping($sequence, $i); break; case ']': return $output; case ',': case ' ': break; default: $isQuoted = in_array($sequence[$i], array('"', "'")); $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i); if (!$isQuoted && false !== strpos($value, ': ')) { // embedded mapping? try { $value = self::parseMapping('{'.$value.'}'); } catch (\InvalidArgumentException $e) { // no, it's not } } $output[] = $value; --$i; } ++$i; } throw new ParseException(sprintf('Malformed inline YAML string %s', $sequence)); } /** * Parses a mapping to a YAML string. * * @param string $mapping * @param integer &$i * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ private static function parseMapping($mapping, &$i = 0) { $output = array(); $len = strlen($mapping); $i += 1; // {foo: bar, bar:foo, ...} while ($i < $len) { switch ($mapping[$i]) { case ' ': case ',': ++$i; continue 2; case '}': return $output; } // key $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false); // value $done = false; while ($i < $len) { switch ($mapping[$i]) { case '[': // nested sequence $output[$key] = self::parseSequence($mapping, $i); $done = true; break; case '{': // nested mapping $output[$key] = self::parseMapping($mapping, $i); $done = true; break; case ':': case ' ': break; default: $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i); $done = true; --$i; } ++$i; if ($done) { continue 2; } } } throw new ParseException(sprintf('Malformed inline YAML string %s', $mapping)); } /** * Evaluates scalars and replaces magic values. * * @param string $scalar * * @return string A YAML string */ private static function evaluateScalar($scalar) { $scalar = trim($scalar); $scalarLower = strtolower($scalar); switch (true) { case 'null' === $scalarLower: case '' === $scalar: case '~' === $scalar: return null; case 'true' === $scalarLower: return true; case 'false' === $scalarLower: return false; // Optimise for returning strings. case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || $scalar[0] === '!' || is_numeric($scalar[0]): switch (true) { case 0 === strpos($scalar, '!str'): return (string) substr($scalar, 5); case 0 === strpos($scalar, '! '): return intval(self::parseScalar(substr($scalar, 2))); case 0 === strpos($scalar, '!!php/object:'): if (self::$objectSupport) { return unserialize(substr($scalar, 13)); } if (self::$exceptionOnInvalidType) { throw new ParseException('Object support when parsing a YAML file has been disabled.'); } return null; case ctype_digit($scalar): $raw = $scalar; $cast = intval($scalar); return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)): $raw = $scalar; $cast = intval($scalar); return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); case is_numeric($scalar): return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar); case '.inf' === $scalarLower: case '.nan' === $scalarLower: return -log(0); case '-.inf' === $scalarLower: return log(0); case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar): return floatval(str_replace(',', '', $scalar)); case preg_match(self::getTimestampRegex(), $scalar): return strtotime($scalar); } default: return (string) $scalar; } } /** * Gets a regex that matches a YAML date. * * @return string The regular expression * * @see http://www.yaml.org/spec/1.2/spec.html#id2761573 */ private static function getTimestampRegex() { return <<[0-9][0-9][0-9][0-9]) -(?P[0-9][0-9]?) -(?P[0-9][0-9]?) (?:(?:[Tt]|[ \t]+) (?P[0-9][0-9]?) :(?P[0-9][0-9]) :(?P[0-9][0-9]) (?:\.(?P[0-9]*))? (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) (?::(?P[0-9][0-9]))?))?)? $~x EOF; } } PK!ݣ""6Symfony/Component/HttpFoundation/ResponseHeaderBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * ResponseHeaderBag is a container for Response HTTP headers. * * @author Fabien Potencier * * @api */ class ResponseHeaderBag extends HeaderBag { const COOKIES_FLAT = 'flat'; const COOKIES_ARRAY = 'array'; const DISPOSITION_ATTACHMENT = 'attachment'; const DISPOSITION_INLINE = 'inline'; /** * @var array */ protected $computedCacheControl = array(); /** * @var array */ protected $cookies = array(); /** * @var array */ protected $headerNames = array(); /** * Constructor. * * @param array $headers An array of HTTP headers * * @api */ public function __construct(array $headers = array()) { parent::__construct($headers); if (!isset($this->headers['cache-control'])) { $this->set('Cache-Control', ''); } } /** * {@inheritdoc} */ public function __toString() { $cookies = ''; foreach ($this->getCookies() as $cookie) { $cookies .= 'Set-Cookie: '.$cookie."\r\n"; } ksort($this->headerNames); return parent::__toString().$cookies; } /** * Returns the headers, with original capitalizations. * * @return array An array of headers */ public function allPreserveCase() { return array_combine($this->headerNames, $this->headers); } /** * {@inheritdoc} * * @api */ public function replace(array $headers = array()) { $this->headerNames = array(); parent::replace($headers); if (!isset($this->headers['cache-control'])) { $this->set('Cache-Control', ''); } } /** * {@inheritdoc} * * @api */ public function set($key, $values, $replace = true) { parent::set($key, $values, $replace); $uniqueKey = strtr(strtolower($key), '_', '-'); $this->headerNames[$uniqueKey] = $key; // ensure the cache-control header has sensible defaults if (in_array($uniqueKey, array('cache-control', 'etag', 'last-modified', 'expires'))) { $computed = $this->computeCacheControlValue(); $this->headers['cache-control'] = array($computed); $this->headerNames['cache-control'] = 'Cache-Control'; $this->computedCacheControl = $this->parseCacheControl($computed); } } /** * {@inheritdoc} * * @api */ public function remove($key) { parent::remove($key); $uniqueKey = strtr(strtolower($key), '_', '-'); unset($this->headerNames[$uniqueKey]); if ('cache-control' === $uniqueKey) { $this->computedCacheControl = array(); } } /** * {@inheritdoc} */ public function hasCacheControlDirective($key) { return array_key_exists($key, $this->computedCacheControl); } /** * {@inheritdoc} */ public function getCacheControlDirective($key) { return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null; } /** * Sets a cookie. * * @param Cookie $cookie * * @api */ public function setCookie(Cookie $cookie) { $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; } /** * Removes a cookie from the array, but does not unset it in the browser * * @param string $name * @param string $path * @param string $domain * * @api */ public function removeCookie($name, $path = '/', $domain = null) { if (null === $path) { $path = '/'; } unset($this->cookies[$domain][$path][$name]); if (empty($this->cookies[$domain][$path])) { unset($this->cookies[$domain][$path]); if (empty($this->cookies[$domain])) { unset($this->cookies[$domain]); } } } /** * Returns an array with all cookies * * @param string $format * * @throws \InvalidArgumentException When the $format is invalid * * @return array * * @api */ public function getCookies($format = self::COOKIES_FLAT) { if (!in_array($format, array(self::COOKIES_FLAT, self::COOKIES_ARRAY))) { throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', array(self::COOKIES_FLAT, self::COOKIES_ARRAY)))); } if (self::COOKIES_ARRAY === $format) { return $this->cookies; } $flattenedCookies = array(); foreach ($this->cookies as $path) { foreach ($path as $cookies) { foreach ($cookies as $cookie) { $flattenedCookies[] = $cookie; } } } return $flattenedCookies; } /** * Clears a cookie in the browser * * @param string $name * @param string $path * @param string $domain * * @api */ public function clearCookie($name, $path = '/', $domain = null) { $this->setCookie(new Cookie($name, null, 1, $path, $domain)); } /** * Generates a HTTP Content-Disposition field-value. * * @param string $disposition One of "inline" or "attachment" * @param string $filename A unicode string * @param string $filenameFallback A string containing only ASCII characters that * is semantically equivalent to $filename. If the filename is already ASCII, * it can be omitted, or just copied from $filename * * @return string A string suitable for use as a Content-Disposition field-value. * * @throws \InvalidArgumentException * @see RFC 6266 */ public function makeDisposition($disposition, $filename, $filenameFallback = '') { if (!in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) { throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); } if ('' == $filenameFallback) { $filenameFallback = $filename; } // filenameFallback is not ASCII. if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); } // percent characters aren't safe in fallback. if (false !== strpos($filenameFallback, '%')) { throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); } // path separators aren't allowed in either. if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) { throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); } $output = sprintf('%s; filename="%s"', $disposition, str_replace('"', '\\"', $filenameFallback)); if ($filename !== $filenameFallback) { $output .= sprintf("; filename*=utf-8''%s", rawurlencode($filename)); } return $output; } /** * Returns the calculated value of the cache-control header. * * This considers several other headers and calculates or modifies the * cache-control header to a sensible, conservative value. * * @return string */ protected function computeCacheControlValue() { if (!$this->cacheControl && !$this->has('ETag') && !$this->has('Last-Modified') && !$this->has('Expires')) { return 'no-cache'; } if (!$this->cacheControl) { // conservative by default return 'private, must-revalidate'; } $header = $this->getCacheControlHeader(); if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) { return $header; } // public if s-maxage is defined, private otherwise if (!isset($this->cacheControl['s-maxage'])) { return $header.', private'; } return $header; } } PK!}xx.Symfony/Component/HttpFoundation/ServerBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * ServerBag is a container for HTTP headers from the $_SERVER variable. * * @author Fabien Potencier * @author Bulat Shakirzyanov * @author Robert Kiss */ class ServerBag extends ParameterBag { /** * Gets the HTTP headers. * * @return array */ public function getHeaders() { $headers = array(); $contentHeaders = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true); foreach ($this->parameters as $key => $value) { if (0 === strpos($key, 'HTTP_')) { $headers[substr($key, 5)] = $value; } // CONTENT_* are not prefixed with HTTP_ elseif (isset($contentHeaders[$key])) { $headers[$key] = $value; } } if (isset($this->parameters['PHP_AUTH_USER'])) { $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER']; $headers['PHP_AUTH_PW'] = isset($this->parameters['PHP_AUTH_PW']) ? $this->parameters['PHP_AUTH_PW'] : ''; } else { /* * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default * For this workaround to work, add these lines to your .htaccess file: * RewriteCond %{HTTP:Authorization} ^(.+)$ * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] * * A sample .htaccess file: * RewriteEngine On * RewriteCond %{HTTP:Authorization} ^(.+)$ * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] * RewriteCond %{REQUEST_FILENAME} !-f * RewriteRule ^(.*)$ app.php [QSA,L] */ $authorizationHeader = null; if (isset($this->parameters['HTTP_AUTHORIZATION'])) { $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION']; } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) { $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; } if (null !== $authorizationHeader) { if (0 === stripos($authorizationHeader, 'basic')) { // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic $exploded = explode(':', base64_decode(substr($authorizationHeader, 6))); if (count($exploded) == 2) { list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded; } } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest'))) { // In some circumstances PHP_AUTH_DIGEST needs to be set $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; } } } // PHP_AUTH_USER/PHP_AUTH_PW if (isset($headers['PHP_AUTH_USER'])) { $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']); } elseif (isset($headers['PHP_AUTH_DIGEST'])) { $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST']; } return $headers; } } PK!_DK 5Symfony/Component/HttpFoundation/RedirectResponse.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * RedirectResponse represents an HTTP response doing a redirect. * * @author Fabien Potencier * * @api */ class RedirectResponse extends Response { protected $targetUrl; /** * Creates a redirect response so that it conforms to the rules defined for a redirect status code. * * @param string $url The URL to redirect to * @param integer $status The status code (302 by default) * @param array $headers The headers (Location is always set to the given URL) * * @throws \InvalidArgumentException * * @see http://tools.ietf.org/html/rfc2616#section-10.3 * * @api */ public function __construct($url, $status = 302, $headers = array()) { if (empty($url)) { throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); } parent::__construct('', $status, $headers); $this->setTargetUrl($url); if (!$this->isRedirect()) { throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); } } /** * {@inheritDoc} */ public static function create($url = '', $status = 302, $headers = array()) { return new static($url, $status, $headers); } /** * Returns the target URL. * * @return string target URL */ public function getTargetUrl() { return $this->targetUrl; } /** * Sets the redirect target of this response. * * @param string $url The URL to redirect to * * @return RedirectResponse The current response. * * @throws \InvalidArgumentException */ public function setTargetUrl($url) { if (empty($url)) { throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); } $this->targetUrl = $url; $this->setContent( sprintf(' Redirecting to %1$s Redirecting to %1$s. ', htmlspecialchars($url, ENT_QUOTES, 'UTF-8'))); $this->headers->set('Location', $url); return $this; } } PK!s 5Symfony/Component/HttpFoundation/StreamedResponse.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * StreamedResponse represents a streamed HTTP response. * * A StreamedResponse uses a callback for its content. * * The callback should use the standard PHP functions like echo * to stream the response back to the client. The flush() method * can also be used if needed. * * @see flush() * * @author Fabien Potencier * * @api */ class StreamedResponse extends Response { protected $callback; protected $streamed; /** * Constructor. * * @param callable|null $callback A valid PHP callback or null to set it later * @param integer $status The response status code * @param array $headers An array of response headers * * @api */ public function __construct($callback = null, $status = 200, $headers = array()) { parent::__construct(null, $status, $headers); if (null !== $callback) { $this->setCallback($callback); } $this->streamed = false; } /** * Factory method for chainability * * @param callable|null $callback A valid PHP callback or null to set it later * @param integer $status The response status code * @param array $headers An array of response headers * * @return StreamedResponse */ public static function create($callback = null, $status = 200, $headers = array()) { return new static($callback, $status, $headers); } /** * Sets the PHP callback associated with this Response. * * @param callable $callback A valid PHP callback * * @throws \LogicException */ public function setCallback($callback) { if (!is_callable($callback)) { throw new \LogicException('The Response callback must be a valid PHP callable.'); } $this->callback = $callback; } /** * {@inheritdoc} */ public function prepare(Request $request) { $this->headers->set('Cache-Control', 'no-cache'); return parent::prepare($request); } /** * {@inheritdoc} * * This method only sends the content once. */ public function sendContent() { if ($this->streamed) { return; } $this->streamed = true; if (null === $this->callback) { throw new \LogicException('The Response callback must not be null.'); } call_user_func($this->callback); } /** * {@inheritdoc} * * @throws \LogicException when the content is not null */ public function setContent($content) { if (null !== $content) { throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); } } /** * {@inheritdoc} * * @return false */ public function getContent() { return false; } } PK!F+Symfony/Component/HttpFoundation/Cookie.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Represents a cookie * * @author Johannes M. Schmitt * * @api */ class Cookie { protected $name; protected $value; protected $domain; protected $expire; protected $path; protected $secure; protected $httpOnly; /** * Constructor. * * @param string $name The name of the cookie * @param string $value The value of the cookie * @param integer|string|\DateTime $expire The time the cookie expires * @param string $path The path on the server in which the cookie will be available on * @param string $domain The domain that the cookie is available to * @param Boolean $secure Whether the cookie should only be transmitted over a secure HTTPS connection from the client * @param Boolean $httpOnly Whether the cookie will be made accessible only through the HTTP protocol * * @throws \InvalidArgumentException * * @api */ public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true) { // from PHP source code if (preg_match("/[=,; \t\r\n\013\014]/", $name)) { throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); } if (empty($name)) { throw new \InvalidArgumentException('The cookie name cannot be empty.'); } // convert expiration time to a Unix timestamp if ($expire instanceof \DateTime) { $expire = $expire->format('U'); } elseif (!is_numeric($expire)) { $expire = strtotime($expire); if (false === $expire || -1 === $expire) { throw new \InvalidArgumentException('The cookie expiration time is not valid.'); } } $this->name = $name; $this->value = $value; $this->domain = $domain; $this->expire = $expire; $this->path = empty($path) ? '/' : $path; $this->secure = (Boolean) $secure; $this->httpOnly = (Boolean) $httpOnly; } /** * Returns the cookie as a string. * * @return string The cookie */ public function __toString() { $str = urlencode($this->getName()).'='; if ('' === (string) $this->getValue()) { $str .= 'deleted; expires='.gmdate("D, d-M-Y H:i:s T", time() - 31536001); } else { $str .= urlencode($this->getValue()); if ($this->getExpiresTime() !== 0) { $str .= '; expires='.gmdate("D, d-M-Y H:i:s T", $this->getExpiresTime()); } } if ($this->path) { $str .= '; path='.$this->path; } if ($this->getDomain()) { $str .= '; domain='.$this->getDomain(); } if (true === $this->isSecure()) { $str .= '; secure'; } if (true === $this->isHttpOnly()) { $str .= '; httponly'; } return $str; } /** * Gets the name of the cookie. * * @return string * * @api */ public function getName() { return $this->name; } /** * Gets the value of the cookie. * * @return string * * @api */ public function getValue() { return $this->value; } /** * Gets the domain that the cookie is available to. * * @return string * * @api */ public function getDomain() { return $this->domain; } /** * Gets the time the cookie expires. * * @return integer * * @api */ public function getExpiresTime() { return $this->expire; } /** * Gets the path on the server in which the cookie will be available on. * * @return string * * @api */ public function getPath() { return $this->path; } /** * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client. * * @return Boolean * * @api */ public function isSecure() { return $this->secure; } /** * Checks whether the cookie will be made accessible only through the HTTP protocol. * * @return Boolean * * @api */ public function isHttpOnly() { return $this->httpOnly; } /** * Whether this cookie is about to be cleared * * @return Boolean * * @api */ public function isCleared() { return $this->expire < time(); } } PK!6= ,Symfony/Component/HttpFoundation/IpUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Http utility functions. * * @author Fabien Potencier */ class IpUtils { /** * This class should not be instantiated */ private function __construct() {} /** * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets * * @param string $requestIp IP to check * @param string|array $ips List of IPs or subnets (can be a string if only a single one) * * @return boolean Whether the IP is valid */ public static function checkIp($requestIp, $ips) { if (!is_array($ips)) { $ips = array($ips); } $method = false !== strpos($requestIp, ':') ? 'checkIp6': 'checkIp4'; foreach ($ips as $ip) { if (self::$method($requestIp, $ip)) { return true; } } return false; } /** * Compares two IPv4 addresses. * In case a subnet is given, it checks if it contains the request IP. * * @param string $requestIp IPv4 address to check * @param string $ip IPv4 address or subnet in CIDR notation * * @return boolean Whether the IP is valid */ public static function checkIp4($requestIp, $ip) { if (false !== strpos($ip, '/')) { list($address, $netmask) = explode('/', $ip, 2); if ($netmask < 1 || $netmask > 32) { return false; } } else { $address = $ip; $netmask = 32; } return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); } /** * Compares two IPv6 addresses. * In case a subnet is given, it checks if it contains the request IP. * * @author David Soria Parra * @see https://github.com/dsp/v6tools * * @param string $requestIp IPv6 address to check * @param string $ip IPv6 address or subnet in CIDR notation * * @return boolean Whether the IP is valid * * @throws \RuntimeException When IPV6 support is not enabled */ public static function checkIp6($requestIp, $ip) { if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) { throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); } if (false !== strpos($ip, '/')) { list($address, $netmask) = explode('/', $ip, 2); if ($netmask < 1 || $netmask > 128) { return false; } } else { $address = $ip; $netmask = 128; } $bytesAddr = unpack("n*", inet_pton($address)); $bytesTest = unpack("n*", inet_pton($requestIp)); for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; $i++) { $left = $netmask - 16 * ($i-1); $left = ($left <= 16) ? $left : 16; $mask = ~(0xffff >> $left) & 0xffff; if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { return false; } } return true; } } PK!Pi,Symfony/Component/HttpFoundation/FileBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\File\UploadedFile; /** * FileBag is a container for uploaded files. * * @author Fabien Potencier * @author Bulat Shakirzyanov * * @api */ class FileBag extends ParameterBag { private static $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); /** * Constructor. * * @param array $parameters An array of HTTP files * * @api */ public function __construct(array $parameters = array()) { $this->replace($parameters); } /** * {@inheritdoc} * * @api */ public function replace(array $files = array()) { $this->parameters = array(); $this->add($files); } /** * {@inheritdoc} * * @api */ public function set($key, $value) { if (!is_array($value) && !$value instanceof UploadedFile) { throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); } parent::set($key, $this->convertFileInformation($value)); } /** * {@inheritdoc} * * @api */ public function add(array $files = array()) { foreach ($files as $key => $file) { $this->set($key, $file); } } /** * Converts uploaded files to UploadedFile instances. * * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information * * @return array A (multi-dimensional) array of UploadedFile instances */ protected function convertFileInformation($file) { if ($file instanceof UploadedFile) { return $file; } $file = $this->fixPhpFilesArray($file); if (is_array($file)) { $keys = array_keys($file); sort($keys); if ($keys == self::$fileKeys) { if (UPLOAD_ERR_NO_FILE == $file['error']) { $file = null; } else { $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']); } } else { $file = array_map(array($this, 'convertFileInformation'), $file); } } return $file; } /** * Fixes a malformed PHP $_FILES array. * * PHP has a bug that the format of the $_FILES array differs, depending on * whether the uploaded file fields had normal field names or array-like * field names ("normal" vs. "parent[child]"). * * This method fixes the array to look like the "normal" $_FILES array. * * It's safe to pass an already converted array, in which case this method * just returns the original array unmodified. * * @param array $data * * @return array */ protected function fixPhpFilesArray($data) { if (!is_array($data)) { return $data; } $keys = array_keys($data); sort($keys); if (self::$fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) { return $data; } $files = $data; foreach (self::$fileKeys as $k) { unset($files[$k]); } foreach (array_keys($data['name']) as $key) { $files[$key] = $this->fixPhpFilesArray(array( 'error' => $data['error'][$key], 'name' => $data['name'][$key], 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key] )); } return $files; } } PK!1y<Symfony/Component/HttpFoundation/RequestMatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * RequestMatcherInterface is an interface for strategies to match a Request. * * @author Fabien Potencier * * @api */ interface RequestMatcherInterface { /** * Decides whether the rule(s) implemented by the strategy matches the supplied request. * * @param Request $request The request to check for a match * * @return Boolean true if the request matches, false otherwise * * @api */ public function matches(Request $request); } PK!PE XX/Symfony/Component/HttpFoundation/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * RequestMatcher compares a pre-defined set of checks against a Request instance. * * @author Fabien Potencier * * @api */ class RequestMatcher implements RequestMatcherInterface { /** * @var string */ private $path; /** * @var string */ private $host; /** * @var array */ private $methods = array(); /** * @var string */ private $ips = array(); /** * @var array */ private $attributes = array(); /** * @param string|null $path * @param string|null $host * @param string|string[]|null $methods * @param string|string[]|null $ips * @param array $attributes */ public function __construct($path = null, $host = null, $methods = null, $ips = null, array $attributes = array()) { $this->matchPath($path); $this->matchHost($host); $this->matchMethod($methods); $this->matchIps($ips); foreach ($attributes as $k => $v) { $this->matchAttribute($k, $v); } } /** * Adds a check for the URL host name. * * @param string $regexp A Regexp */ public function matchHost($regexp) { $this->host = $regexp; } /** * Adds a check for the URL path info. * * @param string $regexp A Regexp */ public function matchPath($regexp) { $this->path = $regexp; } /** * Adds a check for the client IP. * * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 */ public function matchIp($ip) { $this->matchIps($ip); } /** * Adds a check for the client IP. * * @param string|string[] $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 */ public function matchIps($ips) { $this->ips = (array) $ips; } /** * Adds a check for the HTTP method. * * @param string|string[]|null $method An HTTP method or an array of HTTP methods */ public function matchMethod($method) { $this->methods = array_map('strtoupper', (array) $method); } /** * Adds a check for request attribute. * * @param string $key The request attribute name * @param string $regexp A Regexp */ public function matchAttribute($key, $regexp) { $this->attributes[$key] = $regexp; } /** * {@inheritdoc} * * @api */ public function matches(Request $request) { if ($this->methods && !in_array($request->getMethod(), $this->methods)) { return false; } foreach ($this->attributes as $key => $pattern) { if (!preg_match('{'.$pattern.'}', $request->attributes->get($key))) { return false; } } if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) { return false; } if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) { return false; } if (IpUtils::checkIp($request->getClientIp(), $this->ips)) { return true; } // Note to future implementors: add additional checks above the // foreach above or else your check might not be run! return count($this->ips) === 0; } } PK!͢|1Symfony/Component/HttpFoundation/JsonResponse.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Response represents an HTTP response in JSON format. * * Note that this class does not force the returned JSON content to be an * object. It is however recommended that you do return an object as it * protects yourself against XSSI and JSON-JavaScript Hijacking. * * @see https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside * * @author Igor Wiedler */ class JsonResponse extends Response { protected $data; protected $callback; /** * Constructor. * * @param mixed $data The response data * @param integer $status The response status code * @param array $headers An array of response headers */ public function __construct($data = null, $status = 200, $headers = array()) { parent::__construct('', $status, $headers); if (null === $data) { $data = new \ArrayObject(); } $this->setData($data); } /** * {@inheritDoc} */ public static function create($data = null, $status = 200, $headers = array()) { return new static($data, $status, $headers); } /** * Sets the JSONP callback. * * @param string|null $callback The JSONP callback or null to use none * * @return JsonResponse * * @throws \InvalidArgumentException When the callback name is not valid */ public function setCallback($callback = null) { if (null !== $callback) { // taken from http://www.geekality.net/2011/08/03/valid-javascript-identifier/ $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u'; $parts = explode('.', $callback); foreach ($parts as $part) { if (!preg_match($pattern, $part)) { throw new \InvalidArgumentException('The callback name is not valid.'); } } } $this->callback = $callback; return $this->update(); } /** * Sets the data to be sent as json. * * @param mixed $data * * @return JsonResponse * * @throws \InvalidArgumentException */ public function setData($data = array()) { // Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be embedded into HTML. $this->data = json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT); if (JSON_ERROR_NONE !== json_last_error()) { throw new \InvalidArgumentException($this->transformJsonError()); } return $this->update(); } /** * Updates the content and headers according to the json data and callback. * * @return JsonResponse */ protected function update() { if (null !== $this->callback) { // Not using application/javascript for compatibility reasons with older browsers. $this->headers->set('Content-Type', 'text/javascript'); return $this->setContent(sprintf('%s(%s);', $this->callback, $this->data)); } // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback) // in order to not overwrite a custom definition. if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) { $this->headers->set('Content-Type', 'application/json'); } return $this->setContent($this->data); } private function transformJsonError() { if (function_exists('json_last_error_msg')) { return json_last_error_msg(); } switch (json_last_error()) { case JSON_ERROR_DEPTH: return 'Maximum stack depth exceeded.'; case JSON_ERROR_STATE_MISMATCH: return 'Underflow or the modes mismatch.'; case JSON_ERROR_CTRL_CHAR: return 'Unexpected control character found.'; case JSON_ERROR_SYNTAX: return 'Syntax error, malformed JSON.'; case JSON_ERROR_UTF8: return 'Malformed UTF-8 characters, possibly incorrectly encoded.'; default: return 'Unknown error.'; } } } PK!Vkb335Symfony/Component/HttpFoundation/AcceptHeaderItem.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Represents an Accept-* header item. * * @author Jean-François Simon */ class AcceptHeaderItem { /** * @var string */ private $value; /** * @var float */ private $quality = 1.0; /** * @var int */ private $index = 0; /** * @var array */ private $attributes = array(); /** * Constructor. * * @param string $value * @param array $attributes */ public function __construct($value, array $attributes = array()) { $this->value = $value; foreach ($attributes as $name => $value) { $this->setAttribute($name, $value); } } /** * Builds an AcceptHeaderInstance instance from a string. * * @param string $itemValue * * @return AcceptHeaderItem */ public static function fromString($itemValue) { $bits = preg_split('/\s*(?:;*("[^"]+");*|;*(\'[^\']+\');*|;+)\s*/', $itemValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); $value = array_shift($bits); $attributes = array(); $lastNullAttribute = null; foreach ($bits as $bit) { if (($start = substr($bit, 0, 1)) === ($end = substr($bit, -1)) && ($start === '"' || $start === '\'')) { $attributes[$lastNullAttribute] = substr($bit, 1, -1); } elseif ('=' === $end) { $lastNullAttribute = $bit = substr($bit, 0, -1); $attributes[$bit] = null; } else { $parts = explode('=', $bit); $attributes[$parts[0]] = isset($parts[1]) && strlen($parts[1]) > 0 ? $parts[1] : ''; } } return new self(($start = substr($value, 0, 1)) === ($end = substr($value, -1)) && ($start === '"' || $start === '\'') ? substr($value, 1, -1) : $value, $attributes); } /** * Returns header value's string representation. * * @return string */ public function __toString() { $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); if (count($this->attributes) > 0) { $string .= ';'.implode(';', array_map(function ($name, $value) { return sprintf(preg_match('/[,;=]/', $value) ? '%s="%s"' : '%s=%s', $name, $value); }, array_keys($this->attributes), $this->attributes)); } return $string; } /** * Set the item value. * * @param string $value * * @return AcceptHeaderItem */ public function setValue($value) { $this->value = $value; return $this; } /** * Returns the item value. * * @return string */ public function getValue() { return $this->value; } /** * Set the item quality. * * @param float $quality * * @return AcceptHeaderItem */ public function setQuality($quality) { $this->quality = $quality; return $this; } /** * Returns the item quality. * * @return float */ public function getQuality() { return $this->quality; } /** * Set the item index. * * @param int $index * * @return AcceptHeaderItem */ public function setIndex($index) { $this->index = $index; return $this; } /** * Returns the item index. * * @return int */ public function getIndex() { return $this->index; } /** * Tests if an attribute exists. * * @param string $name * * @return Boolean */ public function hasAttribute($name) { return isset($this->attributes[$name]); } /** * Returns an attribute by its name. * * @param string $name * @param mixed $default * * @return mixed */ public function getAttribute($name, $default = null) { return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; } /** * Returns all attributes. * * @return array */ public function getAttributes() { return $this->attributes; } /** * Set an attribute. * * @param string $name * @param string $value * * @return AcceptHeaderItem */ public function setAttribute($name, $value) { if ('q' === $name) { $this->quality = (float) $value; } else { $this->attributes[$name] = (string) $value; } return $this; } } PK!nOO=Symfony/Component/HttpFoundation/ExpressionRequestMatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; /** * ExpressionRequestMatcher uses an expression to match a Request. * * @author Fabien Potencier */ class ExpressionRequestMatcher extends RequestMatcher { private $language; private $expression; public function setExpression(ExpressionLanguage $language, $expression) { $this->language = $language; $this->expression = $expression; } public function matches(Request $request) { if (!$this->language) { throw new \LogicException('Unable to match the request as the expression language is not available.'); } return $this->language->evaluate($this->expression, array( 'request' => $request, 'method' => $request->getMethod(), 'path' => rawurldecode($request->getPathInfo()), 'host' => $request->getHost(), 'ip' => $request->getClientIp(), 'attributes' => $request->attributes->all(), )) && parent::matches($request); } } PK!a.1Symfony/Component/HttpFoundation/AcceptHeader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Represents an Accept-* header. * * An accept header is compound with a list of items, * sorted by descending quality. * * @author Jean-François Simon */ class AcceptHeader { /** * @var AcceptHeaderItem[] */ private $items = array(); /** * @var bool */ private $sorted = true; /** * Constructor. * * @param AcceptHeaderItem[] $items */ public function __construct(array $items) { foreach ($items as $item) { $this->add($item); } } /** * Builds an AcceptHeader instance from a string. * * @param string $headerValue * * @return AcceptHeader */ public static function fromString($headerValue) { $index = 0; return new self(array_map(function ($itemValue) use (&$index) { $item = AcceptHeaderItem::fromString($itemValue); $item->setIndex($index++); return $item; }, preg_split('/\s*(?:,*("[^"]+"),*|,*(\'[^\']+\'),*|,+)\s*/', $headerValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE))); } /** * Returns header value's string representation. * * @return string */ public function __toString() { return implode(',', $this->items); } /** * Tests if header has given value. * * @param string $value * * @return Boolean */ public function has($value) { return isset($this->items[$value]); } /** * Returns given value's item, if exists. * * @param string $value * * @return AcceptHeaderItem|null */ public function get($value) { return isset($this->items[$value]) ? $this->items[$value] : null; } /** * Adds an item. * * @param AcceptHeaderItem $item * * @return AcceptHeader */ public function add(AcceptHeaderItem $item) { $this->items[$item->getValue()] = $item; $this->sorted = false; return $this; } /** * Returns all items. * * @return AcceptHeaderItem[] */ public function all() { $this->sort(); return $this->items; } /** * Filters items on their value using given regex. * * @param string $pattern * * @return AcceptHeader */ public function filter($pattern) { return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) { return preg_match($pattern, $item->getValue()); })); } /** * Returns first item. * * @return AcceptHeaderItem|null */ public function first() { $this->sort(); return !empty($this->items) ? reset($this->items) : null; } /** * Sorts items by descending quality */ private function sort() { if (!$this->sorted) { uasort($this->items, function ($a, $b) { $qA = $a->getQuality(); $qB = $b->getQuality(); if ($qA === $qB) { return $a->getIndex() > $b->getIndex() ? 1 : -1; } return $qA > $qB ? -1 : 1; }); $this->sorted = true; } } } PK!\81Symfony/Component/HttpFoundation/ParameterBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * ParameterBag is a container for key/value pairs. * * @author Fabien Potencier * * @api */ class ParameterBag implements \IteratorAggregate, \Countable { /** * Parameter storage. * * @var array */ protected $parameters; /** * Constructor. * * @param array $parameters An array of parameters * * @api */ public function __construct(array $parameters = array()) { $this->parameters = $parameters; } /** * Returns the parameters. * * @return array An array of parameters * * @api */ public function all() { return $this->parameters; } /** * Returns the parameter keys. * * @return array An array of parameter keys * * @api */ public function keys() { return array_keys($this->parameters); } /** * Replaces the current parameters by a new set. * * @param array $parameters An array of parameters * * @api */ public function replace(array $parameters = array()) { $this->parameters = $parameters; } /** * Adds parameters. * * @param array $parameters An array of parameters * * @api */ public function add(array $parameters = array()) { $this->parameters = array_replace($this->parameters, $parameters); } /** * Returns a parameter by name. * * @param string $path The key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return mixed * * @throws \InvalidArgumentException * * @api */ public function get($path, $default = null, $deep = false) { if (!$deep || false === $pos = strpos($path, '[')) { return array_key_exists($path, $this->parameters) ? $this->parameters[$path] : $default; } $root = substr($path, 0, $pos); if (!array_key_exists($root, $this->parameters)) { return $default; } $value = $this->parameters[$root]; $currentKey = null; for ($i = $pos, $c = strlen($path); $i < $c; $i++) { $char = $path[$i]; if ('[' === $char) { if (null !== $currentKey) { throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "[" at position %d.', $i)); } $currentKey = ''; } elseif (']' === $char) { if (null === $currentKey) { throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "]" at position %d.', $i)); } if (!is_array($value) || !array_key_exists($currentKey, $value)) { return $default; } $value = $value[$currentKey]; $currentKey = null; } else { if (null === $currentKey) { throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "%s" at position %d.', $char, $i)); } $currentKey .= $char; } } if (null !== $currentKey) { throw new \InvalidArgumentException(sprintf('Malformed path. Path must end with "]".')); } return $value; } /** * Sets a parameter by name. * * @param string $key The key * @param mixed $value The value * * @api */ public function set($key, $value) { $this->parameters[$key] = $value; } /** * Returns true if the parameter is defined. * * @param string $key The key * * @return Boolean true if the parameter exists, false otherwise * * @api */ public function has($key) { return array_key_exists($key, $this->parameters); } /** * Removes a parameter. * * @param string $key The key * * @api */ public function remove($key) { unset($this->parameters[$key]); } /** * Returns the alphabetic characters of the parameter value. * * @param string $key The parameter key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return string The filtered value * * @api */ public function getAlpha($key, $default = '', $deep = false) { return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default, $deep)); } /** * Returns the alphabetic characters and digits of the parameter value. * * @param string $key The parameter key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return string The filtered value * * @api */ public function getAlnum($key, $default = '', $deep = false) { return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default, $deep)); } /** * Returns the digits of the parameter value. * * @param string $key The parameter key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return string The filtered value * * @api */ public function getDigits($key, $default = '', $deep = false) { // we need to remove - and + because they're allowed in the filter return str_replace(array('-', '+'), '', $this->filter($key, $default, $deep, FILTER_SANITIZE_NUMBER_INT)); } /** * Returns the parameter value converted to integer. * * @param string $key The parameter key * @param mixed $default The default value if the parameter key does not exist * @param boolean $deep If true, a path like foo[bar] will find deeper items * * @return integer The filtered value * * @api */ public function getInt($key, $default = 0, $deep = false) { return (int) $this->get($key, $default, $deep); } /** * Filter key. * * @param string $key Key. * @param mixed $default Default = null. * @param boolean $deep Default = false. * @param integer $filter FILTER_* constant. * @param mixed $options Filter options. * * @see http://php.net/manual/en/function.filter-var.php * * @return mixed */ public function filter($key, $default = null, $deep = false, $filter = FILTER_DEFAULT, $options = array()) { $value = $this->get($key, $default, $deep); // Always turn $options into an array - this allows filter_var option shortcuts. if (!is_array($options) && $options) { $options = array('flags' => $options); } // Add a convenience check for arrays. if (is_array($value) && !isset($options['flags'])) { $options['flags'] = FILTER_REQUIRE_ARRAY; } return filter_var($value, $filter, $options); } /** * Returns an iterator for parameters. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->parameters); } /** * Returns the number of parameters. * * @return int The number of parameters */ public function count() { return count($this->parameters); } } PK!6BSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; /** * A singleton mime type guesser. * * By default, all mime type guessers provided by the framework are installed * (if available on the current OS/PHP setup). * * You can register custom guessers by calling the register() method on the * singleton instance. Custom guessers are always called before any default ones. * * $guesser = MimeTypeGuesser::getInstance(); * $guesser->register(new MyCustomMimeTypeGuesser()); * * If you want to change the order of the default guessers, just re-register your * preferred one as a custom one. The last registered guesser is preferred over * previously registered ones. * * Re-registering a built-in guesser also allows you to configure it: * * $guesser = MimeTypeGuesser::getInstance(); * $guesser->register(new FileinfoMimeTypeGuesser('/path/to/magic/file')); * * @author Bernhard Schussek */ class MimeTypeGuesser implements MimeTypeGuesserInterface { /** * The singleton instance * * @var MimeTypeGuesser */ private static $instance = null; /** * All registered MimeTypeGuesserInterface instances * * @var array */ protected $guessers = array(); /** * Returns the singleton instance * * @return MimeTypeGuesser */ public static function getInstance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } /** * Registers all natively provided mime type guessers */ private function __construct() { if (FileBinaryMimeTypeGuesser::isSupported()) { $this->register(new FileBinaryMimeTypeGuesser()); } if (FileinfoMimeTypeGuesser::isSupported()) { $this->register(new FileinfoMimeTypeGuesser()); } } /** * Registers a new mime type guesser * * When guessing, this guesser is preferred over previously registered ones. * * @param MimeTypeGuesserInterface $guesser */ public function register(MimeTypeGuesserInterface $guesser) { array_unshift($this->guessers, $guesser); } /** * Tries to guess the mime type of the given file * * The file is passed to each registered mime type guesser in reverse order * of their registration (last registered is queried first). Once a guesser * returns a value that is not NULL, this method terminates and returns the * value. * * @param string $path The path to the file * * @return string The mime type or NULL, if none could be guessed * * @throws \LogicException * @throws FileNotFoundException * @throws AccessDeniedException */ public function guess($path) { if (!is_file($path)) { throw new FileNotFoundException($path); } if (!is_readable($path)) { throw new AccessDeniedException($path); } if (!$this->guessers) { throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)'); } foreach ($this->guessers as $guesser) { if (null !== $mimeType = $guesser->guess($path)) { return $mimeType; } } } } PK!5p1JSymfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; /** * Guesses the mime type using the PECL extension FileInfo. * * @author Bernhard Schussek */ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface { private $magicFile; /** * Constructor. * * @param string $magicFile A magic file to use with the finfo instance * * @link http://www.php.net/manual/en/function.finfo-open.php */ public function __construct($magicFile = null) { $this->magicFile = $magicFile; } /** * Returns whether this guesser is supported on the current OS/PHP setup * * @return Boolean */ public static function isSupported() { return function_exists('finfo_open'); } /** * {@inheritdoc} */ public function guess($path) { if (!is_file($path)) { throw new FileNotFoundException($path); } if (!is_readable($path)) { throw new AccessDeniedException($path); } if (!self::isSupported()) { return null; } if (!$finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) { return null; } return $finfo->file($path); } } PK!q xLSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; /** * Guesses the file extension corresponding to a given mime type */ interface ExtensionGuesserInterface { /** * Makes a best guess for a file extension, given a mime type * * @param string $mimeType The mime type * @return string The guessed extension or NULL, if none could be guessed */ public function guess($mimeType); } PK!JLSymfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; /** * Guesses the mime type with the binary "file" (only available on *nix) * * @author Bernhard Schussek */ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface { private $cmd; /** * Constructor. * * The $cmd pattern must contain a "%s" string that will be replaced * with the file name to guess. * * The command output must start with the mime type of the file. * * @param string $cmd The command to run to get the mime type of a file */ public function __construct($cmd = 'file -b --mime %s 2>/dev/null') { $this->cmd = $cmd; } /** * Returns whether this guesser is supported on the current OS * * @return Boolean */ public static function isSupported() { return !defined('PHP_WINDOWS_VERSION_BUILD') && function_exists('passthru') && function_exists('escapeshellarg'); } /** * {@inheritdoc} */ public function guess($path) { if (!is_file($path)) { throw new FileNotFoundException($path); } if (!is_readable($path)) { throw new AccessDeniedException($path); } if (!self::isSupported()) { return null; } ob_start(); // need to use --mime instead of -i. see #6641 passthru(sprintf($this->cmd, escapeshellarg($path)), $return); if ($return > 0) { ob_end_clean(); return null; } $type = trim(ob_get_clean()); if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) { // it's not a type, but an error message return null; } return $match[1]; } } PK!2 k CSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; /** * A singleton mime type to file extension guesser. * * A default guesser is provided. * You can register custom guessers by calling the register() * method on the singleton instance: * * $guesser = ExtensionGuesser::getInstance(); * $guesser->register(new MyCustomExtensionGuesser()); * * The last registered guesser is preferred over previously registered ones. */ class ExtensionGuesser implements ExtensionGuesserInterface { /** * The singleton instance * * @var ExtensionGuesser */ private static $instance = null; /** * All registered ExtensionGuesserInterface instances * * @var array */ protected $guessers = array(); /** * Returns the singleton instance * * @return ExtensionGuesser */ public static function getInstance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } /** * Registers all natively provided extension guessers */ private function __construct() { $this->register(new MimeTypeExtensionGuesser()); } /** * Registers a new extension guesser * * When guessing, this guesser is preferred over previously registered ones. * * @param ExtensionGuesserInterface $guesser */ public function register(ExtensionGuesserInterface $guesser) { array_unshift($this->guessers, $guesser); } /** * Tries to guess the extension * * The mime type is passed to each registered mime type guesser in reverse order * of their registration (last registered is queried first). Once a guesser * returns a value that is not NULL, this method terminates and returns the * value. * * @param string $mimeType The mime type * * @return string The guessed extension or NULL, if none could be guessed */ public function guess($mimeType) { foreach ($this->guessers as $guesser) { if (null !== $extension = $guesser->guess($mimeType)) { return $extension; } } } } PK!wnMMKSymfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; /** * Provides a best-guess mapping of mime type to file extension. */ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface { /** * A map of mime types and their default extensions. * * This list has been placed under the public domain by the Apache HTTPD project. * This list has been updated from upstream on 2013-04-23. * * @see http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types * * @var array */ protected $defaultExtensions = array( 'application/andrew-inset' => 'ez', 'application/applixware' => 'aw', 'application/atom+xml' => 'atom', 'application/atomcat+xml' => 'atomcat', 'application/atomsvc+xml' => 'atomsvc', 'application/ccxml+xml' => 'ccxml', 'application/cdmi-capability' => 'cdmia', 'application/cdmi-container' => 'cdmic', 'application/cdmi-domain' => 'cdmid', 'application/cdmi-object' => 'cdmio', 'application/cdmi-queue' => 'cdmiq', 'application/cu-seeme' => 'cu', 'application/davmount+xml' => 'davmount', 'application/docbook+xml' => 'dbk', 'application/dssc+der' => 'dssc', 'application/dssc+xml' => 'xdssc', 'application/ecmascript' => 'ecma', 'application/emma+xml' => 'emma', 'application/epub+zip' => 'epub', 'application/exi' => 'exi', 'application/font-tdpfr' => 'pfr', 'application/gml+xml' => 'gml', 'application/gpx+xml' => 'gpx', 'application/gxf' => 'gxf', 'application/hyperstudio' => 'stk', 'application/inkml+xml' => 'ink', 'application/ipfix' => 'ipfix', 'application/java-archive' => 'jar', 'application/java-serialized-object' => 'ser', 'application/java-vm' => 'class', 'application/javascript' => 'js', 'application/json' => 'json', 'application/jsonml+json' => 'jsonml', 'application/lost+xml' => 'lostxml', 'application/mac-binhex40' => 'hqx', 'application/mac-compactpro' => 'cpt', 'application/mads+xml' => 'mads', 'application/marc' => 'mrc', 'application/marcxml+xml' => 'mrcx', 'application/mathematica' => 'ma', 'application/mathml+xml' => 'mathml', 'application/mbox' => 'mbox', 'application/mediaservercontrol+xml' => 'mscml', 'application/metalink+xml' => 'metalink', 'application/metalink4+xml' => 'meta4', 'application/mets+xml' => 'mets', 'application/mods+xml' => 'mods', 'application/mp21' => 'm21', 'application/mp4' => 'mp4s', 'application/msword' => 'doc', 'application/mxf' => 'mxf', 'application/octet-stream' => 'bin', 'application/oda' => 'oda', 'application/oebps-package+xml' => 'opf', 'application/ogg' => 'ogx', 'application/omdoc+xml' => 'omdoc', 'application/onenote' => 'onetoc', 'application/oxps' => 'oxps', 'application/patch-ops-error+xml' => 'xer', 'application/pdf' => 'pdf', 'application/pgp-encrypted' => 'pgp', 'application/pgp-signature' => 'asc', 'application/pics-rules' => 'prf', 'application/pkcs10' => 'p10', 'application/pkcs7-mime' => 'p7m', 'application/pkcs7-signature' => 'p7s', 'application/pkcs8' => 'p8', 'application/pkix-attr-cert' => 'ac', 'application/pkix-cert' => 'cer', 'application/pkix-crl' => 'crl', 'application/pkix-pkipath' => 'pkipath', 'application/pkixcmp' => 'pki', 'application/pls+xml' => 'pls', 'application/postscript' => 'ai', 'application/prs.cww' => 'cww', 'application/pskc+xml' => 'pskcxml', 'application/rdf+xml' => 'rdf', 'application/reginfo+xml' => 'rif', 'application/relax-ng-compact-syntax' => 'rnc', 'application/resource-lists+xml' => 'rl', 'application/resource-lists-diff+xml' => 'rld', 'application/rls-services+xml' => 'rs', 'application/rpki-ghostbusters' => 'gbr', 'application/rpki-manifest' => 'mft', 'application/rpki-roa' => 'roa', 'application/rsd+xml' => 'rsd', 'application/rss+xml' => 'rss', 'application/rtf' => 'rtf', 'application/sbml+xml' => 'sbml', 'application/scvp-cv-request' => 'scq', 'application/scvp-cv-response' => 'scs', 'application/scvp-vp-request' => 'spq', 'application/scvp-vp-response' => 'spp', 'application/sdp' => 'sdp', 'application/set-payment-initiation' => 'setpay', 'application/set-registration-initiation' => 'setreg', 'application/shf+xml' => 'shf', 'application/smil+xml' => 'smi', 'application/sparql-query' => 'rq', 'application/sparql-results+xml' => 'srx', 'application/srgs' => 'gram', 'application/srgs+xml' => 'grxml', 'application/sru+xml' => 'sru', 'application/ssdl+xml' => 'ssdl', 'application/ssml+xml' => 'ssml', 'application/tei+xml' => 'tei', 'application/thraud+xml' => 'tfi', 'application/timestamped-data' => 'tsd', 'application/vnd.3gpp.pic-bw-large' => 'plb', 'application/vnd.3gpp.pic-bw-small' => 'psb', 'application/vnd.3gpp.pic-bw-var' => 'pvb', 'application/vnd.3gpp2.tcap' => 'tcap', 'application/vnd.3m.post-it-notes' => 'pwn', 'application/vnd.accpac.simply.aso' => 'aso', 'application/vnd.accpac.simply.imp' => 'imp', 'application/vnd.acucobol' => 'acu', 'application/vnd.acucorp' => 'atc', 'application/vnd.adobe.air-application-installer-package+zip' => 'air', 'application/vnd.adobe.formscentral.fcdt' => 'fcdt', 'application/vnd.adobe.fxp' => 'fxp', 'application/vnd.adobe.xdp+xml' => 'xdp', 'application/vnd.adobe.xfdf' => 'xfdf', 'application/vnd.ahead.space' => 'ahead', 'application/vnd.airzip.filesecure.azf' => 'azf', 'application/vnd.airzip.filesecure.azs' => 'azs', 'application/vnd.amazon.ebook' => 'azw', 'application/vnd.americandynamics.acc' => 'acc', 'application/vnd.amiga.ami' => 'ami', 'application/vnd.android.package-archive' => 'apk', 'application/vnd.anser-web-certificate-issue-initiation' => 'cii', 'application/vnd.anser-web-funds-transfer-initiation' => 'fti', 'application/vnd.antix.game-component' => 'atx', 'application/vnd.apple.installer+xml' => 'mpkg', 'application/vnd.apple.mpegurl' => 'm3u8', 'application/vnd.aristanetworks.swi' => 'swi', 'application/vnd.astraea-software.iota' => 'iota', 'application/vnd.audiograph' => 'aep', 'application/vnd.blueice.multipass' => 'mpm', 'application/vnd.bmi' => 'bmi', 'application/vnd.businessobjects' => 'rep', 'application/vnd.chemdraw+xml' => 'cdxml', 'application/vnd.chipnuts.karaoke-mmd' => 'mmd', 'application/vnd.cinderella' => 'cdy', 'application/vnd.claymore' => 'cla', 'application/vnd.cloanto.rp9' => 'rp9', 'application/vnd.clonk.c4group' => 'c4g', 'application/vnd.cluetrust.cartomobile-config' => 'c11amc', 'application/vnd.cluetrust.cartomobile-config-pkg' => 'c11amz', 'application/vnd.commonspace' => 'csp', 'application/vnd.contact.cmsg' => 'cdbcmsg', 'application/vnd.cosmocaller' => 'cmc', 'application/vnd.crick.clicker' => 'clkx', 'application/vnd.crick.clicker.keyboard' => 'clkk', 'application/vnd.crick.clicker.palette' => 'clkp', 'application/vnd.crick.clicker.template' => 'clkt', 'application/vnd.crick.clicker.wordbank' => 'clkw', 'application/vnd.criticaltools.wbs+xml' => 'wbs', 'application/vnd.ctc-posml' => 'pml', 'application/vnd.cups-ppd' => 'ppd', 'application/vnd.curl.car' => 'car', 'application/vnd.curl.pcurl' => 'pcurl', 'application/vnd.dart' => 'dart', 'application/vnd.data-vision.rdz' => 'rdz', 'application/vnd.dece.data' => 'uvf', 'application/vnd.dece.ttml+xml' => 'uvt', 'application/vnd.dece.unspecified' => 'uvx', 'application/vnd.dece.zip' => 'uvz', 'application/vnd.denovo.fcselayout-link' => 'fe_launch', 'application/vnd.dna' => 'dna', 'application/vnd.dolby.mlp' => 'mlp', 'application/vnd.dpgraph' => 'dpg', 'application/vnd.dreamfactory' => 'dfac', 'application/vnd.ds-keypoint' => 'kpxx', 'application/vnd.dvb.ait' => 'ait', 'application/vnd.dvb.service' => 'svc', 'application/vnd.dynageo' => 'geo', 'application/vnd.ecowin.chart' => 'mag', 'application/vnd.enliven' => 'nml', 'application/vnd.epson.esf' => 'esf', 'application/vnd.epson.msf' => 'msf', 'application/vnd.epson.quickanime' => 'qam', 'application/vnd.epson.salt' => 'slt', 'application/vnd.epson.ssf' => 'ssf', 'application/vnd.eszigno3+xml' => 'es3', 'application/vnd.ezpix-album' => 'ez2', 'application/vnd.ezpix-package' => 'ez3', 'application/vnd.fdf' => 'fdf', 'application/vnd.fdsn.mseed' => 'mseed', 'application/vnd.fdsn.seed' => 'seed', 'application/vnd.flographit' => 'gph', 'application/vnd.fluxtime.clip' => 'ftc', 'application/vnd.framemaker' => 'fm', 'application/vnd.frogans.fnc' => 'fnc', 'application/vnd.frogans.ltf' => 'ltf', 'application/vnd.fsc.weblaunch' => 'fsc', 'application/vnd.fujitsu.oasys' => 'oas', 'application/vnd.fujitsu.oasys2' => 'oa2', 'application/vnd.fujitsu.oasys3' => 'oa3', 'application/vnd.fujitsu.oasysgp' => 'fg5', 'application/vnd.fujitsu.oasysprs' => 'bh2', 'application/vnd.fujixerox.ddd' => 'ddd', 'application/vnd.fujixerox.docuworks' => 'xdw', 'application/vnd.fujixerox.docuworks.binder' => 'xbd', 'application/vnd.fuzzysheet' => 'fzs', 'application/vnd.genomatix.tuxedo' => 'txd', 'application/vnd.geogebra.file' => 'ggb', 'application/vnd.geogebra.tool' => 'ggt', 'application/vnd.geometry-explorer' => 'gex', 'application/vnd.geonext' => 'gxt', 'application/vnd.geoplan' => 'g2w', 'application/vnd.geospace' => 'g3w', 'application/vnd.gmx' => 'gmx', 'application/vnd.google-earth.kml+xml' => 'kml', 'application/vnd.google-earth.kmz' => 'kmz', 'application/vnd.grafeq' => 'gqf', 'application/vnd.groove-account' => 'gac', 'application/vnd.groove-help' => 'ghf', 'application/vnd.groove-identity-message' => 'gim', 'application/vnd.groove-injector' => 'grv', 'application/vnd.groove-tool-message' => 'gtm', 'application/vnd.groove-tool-template' => 'tpl', 'application/vnd.groove-vcard' => 'vcg', 'application/vnd.hal+xml' => 'hal', 'application/vnd.handheld-entertainment+xml' => 'zmm', 'application/vnd.hbci' => 'hbci', 'application/vnd.hhe.lesson-player' => 'les', 'application/vnd.hp-hpgl' => 'hpgl', 'application/vnd.hp-hpid' => 'hpid', 'application/vnd.hp-hps' => 'hps', 'application/vnd.hp-jlyt' => 'jlt', 'application/vnd.hp-pcl' => 'pcl', 'application/vnd.hp-pclxl' => 'pclxl', 'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx', 'application/vnd.ibm.minipay' => 'mpy', 'application/vnd.ibm.modcap' => 'afp', 'application/vnd.ibm.rights-management' => 'irm', 'application/vnd.ibm.secure-container' => 'sc', 'application/vnd.iccprofile' => 'icc', 'application/vnd.igloader' => 'igl', 'application/vnd.immervision-ivp' => 'ivp', 'application/vnd.immervision-ivu' => 'ivu', 'application/vnd.insors.igm' => 'igm', 'application/vnd.intercon.formnet' => 'xpw', 'application/vnd.intergeo' => 'i2g', 'application/vnd.intu.qbo' => 'qbo', 'application/vnd.intu.qfx' => 'qfx', 'application/vnd.ipunplugged.rcprofile' => 'rcprofile', 'application/vnd.irepository.package+xml' => 'irp', 'application/vnd.is-xpr' => 'xpr', 'application/vnd.isac.fcs' => 'fcs', 'application/vnd.jam' => 'jam', 'application/vnd.jcp.javame.midlet-rms' => 'rms', 'application/vnd.jisp' => 'jisp', 'application/vnd.joost.joda-archive' => 'joda', 'application/vnd.kahootz' => 'ktz', 'application/vnd.kde.karbon' => 'karbon', 'application/vnd.kde.kchart' => 'chrt', 'application/vnd.kde.kformula' => 'kfo', 'application/vnd.kde.kivio' => 'flw', 'application/vnd.kde.kontour' => 'kon', 'application/vnd.kde.kpresenter' => 'kpr', 'application/vnd.kde.kspread' => 'ksp', 'application/vnd.kde.kword' => 'kwd', 'application/vnd.kenameaapp' => 'htke', 'application/vnd.kidspiration' => 'kia', 'application/vnd.kinar' => 'kne', 'application/vnd.koan' => 'skp', 'application/vnd.kodak-descriptor' => 'sse', 'application/vnd.las.las+xml' => 'lasxml', 'application/vnd.llamagraphics.life-balance.desktop' => 'lbd', 'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe', 'application/vnd.lotus-1-2-3' => '123', 'application/vnd.lotus-approach' => 'apr', 'application/vnd.lotus-freelance' => 'pre', 'application/vnd.lotus-notes' => 'nsf', 'application/vnd.lotus-organizer' => 'org', 'application/vnd.lotus-screencam' => 'scm', 'application/vnd.lotus-wordpro' => 'lwp', 'application/vnd.macports.portpkg' => 'portpkg', 'application/vnd.mcd' => 'mcd', 'application/vnd.medcalcdata' => 'mc1', 'application/vnd.mediastation.cdkey' => 'cdkey', 'application/vnd.mfer' => 'mwf', 'application/vnd.mfmp' => 'mfm', 'application/vnd.micrografx.flo' => 'flo', 'application/vnd.micrografx.igx' => 'igx', 'application/vnd.mif' => 'mif', 'application/vnd.mobius.daf' => 'daf', 'application/vnd.mobius.dis' => 'dis', 'application/vnd.mobius.mbk' => 'mbk', 'application/vnd.mobius.mqy' => 'mqy', 'application/vnd.mobius.msl' => 'msl', 'application/vnd.mobius.plc' => 'plc', 'application/vnd.mobius.txf' => 'txf', 'application/vnd.mophun.application' => 'mpn', 'application/vnd.mophun.certificate' => 'mpc', 'application/vnd.mozilla.xul+xml' => 'xul', 'application/vnd.ms-artgalry' => 'cil', 'application/vnd.ms-cab-compressed' => 'cab', 'application/vnd.ms-excel' => 'xls', 'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam', 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb', 'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm', 'application/vnd.ms-excel.template.macroenabled.12' => 'xltm', 'application/vnd.ms-fontobject' => 'eot', 'application/vnd.ms-htmlhelp' => 'chm', 'application/vnd.ms-ims' => 'ims', 'application/vnd.ms-lrm' => 'lrm', 'application/vnd.ms-officetheme' => 'thmx', 'application/vnd.ms-pki.seccat' => 'cat', 'application/vnd.ms-pki.stl' => 'stl', 'application/vnd.ms-powerpoint' => 'ppt', 'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam', 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm', 'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm', 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm', 'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm', 'application/vnd.ms-project' => 'mpp', 'application/vnd.ms-word.document.macroenabled.12' => 'docm', 'application/vnd.ms-word.template.macroenabled.12' => 'dotm', 'application/vnd.ms-works' => 'wps', 'application/vnd.ms-wpl' => 'wpl', 'application/vnd.ms-xpsdocument' => 'xps', 'application/vnd.mseq' => 'mseq', 'application/vnd.musician' => 'mus', 'application/vnd.muvee.style' => 'msty', 'application/vnd.mynfc' => 'taglet', 'application/vnd.neurolanguage.nlu' => 'nlu', 'application/vnd.nitf' => 'ntf', 'application/vnd.noblenet-directory' => 'nnd', 'application/vnd.noblenet-sealer' => 'nns', 'application/vnd.noblenet-web' => 'nnw', 'application/vnd.nokia.n-gage.data' => 'ngdat', 'application/vnd.nokia.n-gage.symbian.install' => 'n-gage', 'application/vnd.nokia.radio-preset' => 'rpst', 'application/vnd.nokia.radio-presets' => 'rpss', 'application/vnd.novadigm.edm' => 'edm', 'application/vnd.novadigm.edx' => 'edx', 'application/vnd.novadigm.ext' => 'ext', 'application/vnd.oasis.opendocument.chart' => 'odc', 'application/vnd.oasis.opendocument.chart-template' => 'otc', 'application/vnd.oasis.opendocument.database' => 'odb', 'application/vnd.oasis.opendocument.formula' => 'odf', 'application/vnd.oasis.opendocument.formula-template' => 'odft', 'application/vnd.oasis.opendocument.graphics' => 'odg', 'application/vnd.oasis.opendocument.graphics-template' => 'otg', 'application/vnd.oasis.opendocument.image' => 'odi', 'application/vnd.oasis.opendocument.image-template' => 'oti', 'application/vnd.oasis.opendocument.presentation' => 'odp', 'application/vnd.oasis.opendocument.presentation-template' => 'otp', 'application/vnd.oasis.opendocument.spreadsheet' => 'ods', 'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots', 'application/vnd.oasis.opendocument.text' => 'odt', 'application/vnd.oasis.opendocument.text-master' => 'odm', 'application/vnd.oasis.opendocument.text-template' => 'ott', 'application/vnd.oasis.opendocument.text-web' => 'oth', 'application/vnd.olpc-sugar' => 'xo', 'application/vnd.oma.dd2+xml' => 'dd2', 'application/vnd.openofficeorg.extension' => 'oxt', 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx', 'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx', 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx', 'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx', 'application/vnd.osgeo.mapguide.package' => 'mgp', 'application/vnd.osgi.dp' => 'dp', 'application/vnd.osgi.subsystem' => 'esa', 'application/vnd.palm' => 'pdb', 'application/vnd.pawaafile' => 'paw', 'application/vnd.pg.format' => 'str', 'application/vnd.pg.osasli' => 'ei6', 'application/vnd.picsel' => 'efif', 'application/vnd.pmi.widget' => 'wg', 'application/vnd.pocketlearn' => 'plf', 'application/vnd.powerbuilder6' => 'pbd', 'application/vnd.previewsystems.box' => 'box', 'application/vnd.proteus.magazine' => 'mgz', 'application/vnd.publishare-delta-tree' => 'qps', 'application/vnd.pvi.ptid1' => 'ptid', 'application/vnd.quark.quarkxpress' => 'qxd', 'application/vnd.realvnc.bed' => 'bed', 'application/vnd.recordare.musicxml' => 'mxl', 'application/vnd.recordare.musicxml+xml' => 'musicxml', 'application/vnd.rig.cryptonote' => 'cryptonote', 'application/vnd.rim.cod' => 'cod', 'application/vnd.rn-realmedia' => 'rm', 'application/vnd.rn-realmedia-vbr' => 'rmvb', 'application/vnd.route66.link66+xml' => 'link66', 'application/vnd.sailingtracker.track' => 'st', 'application/vnd.seemail' => 'see', 'application/vnd.sema' => 'sema', 'application/vnd.semd' => 'semd', 'application/vnd.semf' => 'semf', 'application/vnd.shana.informed.formdata' => 'ifm', 'application/vnd.shana.informed.formtemplate' => 'itp', 'application/vnd.shana.informed.interchange' => 'iif', 'application/vnd.shana.informed.package' => 'ipk', 'application/vnd.simtech-mindmapper' => 'twd', 'application/vnd.smaf' => 'mmf', 'application/vnd.smart.teacher' => 'teacher', 'application/vnd.solent.sdkm+xml' => 'sdkm', 'application/vnd.spotfire.dxp' => 'dxp', 'application/vnd.spotfire.sfs' => 'sfs', 'application/vnd.stardivision.calc' => 'sdc', 'application/vnd.stardivision.draw' => 'sda', 'application/vnd.stardivision.impress' => 'sdd', 'application/vnd.stardivision.math' => 'smf', 'application/vnd.stardivision.writer' => 'sdw', 'application/vnd.stardivision.writer-global' => 'sgl', 'application/vnd.stepmania.package' => 'smzip', 'application/vnd.stepmania.stepchart' => 'sm', 'application/vnd.sun.xml.calc' => 'sxc', 'application/vnd.sun.xml.calc.template' => 'stc', 'application/vnd.sun.xml.draw' => 'sxd', 'application/vnd.sun.xml.draw.template' => 'std', 'application/vnd.sun.xml.impress' => 'sxi', 'application/vnd.sun.xml.impress.template' => 'sti', 'application/vnd.sun.xml.math' => 'sxm', 'application/vnd.sun.xml.writer' => 'sxw', 'application/vnd.sun.xml.writer.global' => 'sxg', 'application/vnd.sun.xml.writer.template' => 'stw', 'application/vnd.sus-calendar' => 'sus', 'application/vnd.svd' => 'svd', 'application/vnd.symbian.install' => 'sis', 'application/vnd.syncml+xml' => 'xsm', 'application/vnd.syncml.dm+wbxml' => 'bdm', 'application/vnd.syncml.dm+xml' => 'xdm', 'application/vnd.tao.intent-module-archive' => 'tao', 'application/vnd.tcpdump.pcap' => 'pcap', 'application/vnd.tmobile-livetv' => 'tmo', 'application/vnd.trid.tpt' => 'tpt', 'application/vnd.triscape.mxs' => 'mxs', 'application/vnd.trueapp' => 'tra', 'application/vnd.ufdl' => 'ufd', 'application/vnd.uiq.theme' => 'utz', 'application/vnd.umajin' => 'umj', 'application/vnd.unity' => 'unityweb', 'application/vnd.uoml+xml' => 'uoml', 'application/vnd.vcx' => 'vcx', 'application/vnd.visio' => 'vsd', 'application/vnd.visionary' => 'vis', 'application/vnd.vsf' => 'vsf', 'application/vnd.wap.wbxml' => 'wbxml', 'application/vnd.wap.wmlc' => 'wmlc', 'application/vnd.wap.wmlscriptc' => 'wmlsc', 'application/vnd.webturbo' => 'wtb', 'application/vnd.wolfram.player' => 'nbp', 'application/vnd.wordperfect' => 'wpd', 'application/vnd.wqd' => 'wqd', 'application/vnd.wt.stf' => 'stf', 'application/vnd.xara' => 'xar', 'application/vnd.xfdl' => 'xfdl', 'application/vnd.yamaha.hv-dic' => 'hvd', 'application/vnd.yamaha.hv-script' => 'hvs', 'application/vnd.yamaha.hv-voice' => 'hvp', 'application/vnd.yamaha.openscoreformat' => 'osf', 'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg', 'application/vnd.yamaha.smaf-audio' => 'saf', 'application/vnd.yamaha.smaf-phrase' => 'spf', 'application/vnd.yellowriver-custom-menu' => 'cmp', 'application/vnd.zul' => 'zir', 'application/vnd.zzazz.deck+xml' => 'zaz', 'application/voicexml+xml' => 'vxml', 'application/widget' => 'wgt', 'application/winhlp' => 'hlp', 'application/wsdl+xml' => 'wsdl', 'application/wspolicy+xml' => 'wspolicy', 'application/x-7z-compressed' => '7z', 'application/x-abiword' => 'abw', 'application/x-ace-compressed' => 'ace', 'application/x-apple-diskimage' => 'dmg', 'application/x-authorware-bin' => 'aab', 'application/x-authorware-map' => 'aam', 'application/x-authorware-seg' => 'aas', 'application/x-bcpio' => 'bcpio', 'application/x-bittorrent' => 'torrent', 'application/x-blorb' => 'blb', 'application/x-bzip' => 'bz', 'application/x-bzip2' => 'bz2', 'application/x-cbr' => 'cbr', 'application/x-cdlink' => 'vcd', 'application/x-cfs-compressed' => 'cfs', 'application/x-chat' => 'chat', 'application/x-chess-pgn' => 'pgn', 'application/x-conference' => 'nsc', 'application/x-cpio' => 'cpio', 'application/x-csh' => 'csh', 'application/x-debian-package' => 'deb', 'application/x-dgc-compressed' => 'dgc', 'application/x-director' => 'dir', 'application/x-doom' => 'wad', 'application/x-dtbncx+xml' => 'ncx', 'application/x-dtbook+xml' => 'dtb', 'application/x-dtbresource+xml' => 'res', 'application/x-dvi' => 'dvi', 'application/x-envoy' => 'evy', 'application/x-eva' => 'eva', 'application/x-font-bdf' => 'bdf', 'application/x-font-ghostscript' => 'gsf', 'application/x-font-linux-psf' => 'psf', 'application/x-font-otf' => 'otf', 'application/x-font-pcf' => 'pcf', 'application/x-font-snf' => 'snf', 'application/x-font-ttf' => 'ttf', 'application/x-font-type1' => 'pfa', 'application/x-font-woff' => 'woff', 'application/x-freearc' => 'arc', 'application/x-futuresplash' => 'spl', 'application/x-gca-compressed' => 'gca', 'application/x-glulx' => 'ulx', 'application/x-gnumeric' => 'gnumeric', 'application/x-gramps-xml' => 'gramps', 'application/x-gtar' => 'gtar', 'application/x-hdf' => 'hdf', 'application/x-install-instructions' => 'install', 'application/x-iso9660-image' => 'iso', 'application/x-java-jnlp-file' => 'jnlp', 'application/x-latex' => 'latex', 'application/x-lzh-compressed' => 'lzh', 'application/x-mie' => 'mie', 'application/x-mobipocket-ebook' => 'prc', 'application/x-ms-application' => 'application', 'application/x-ms-shortcut' => 'lnk', 'application/x-ms-wmd' => 'wmd', 'application/x-ms-wmz' => 'wmz', 'application/x-ms-xbap' => 'xbap', 'application/x-msaccess' => 'mdb', 'application/x-msbinder' => 'obd', 'application/x-mscardfile' => 'crd', 'application/x-msclip' => 'clp', 'application/x-msdownload' => 'exe', 'application/x-msmediaview' => 'mvb', 'application/x-msmetafile' => 'wmf', 'application/x-msmoney' => 'mny', 'application/x-mspublisher' => 'pub', 'application/x-msschedule' => 'scd', 'application/x-msterminal' => 'trm', 'application/x-mswrite' => 'wri', 'application/x-netcdf' => 'nc', 'application/x-nzb' => 'nzb', 'application/x-pkcs12' => 'p12', 'application/x-pkcs7-certificates' => 'p7b', 'application/x-pkcs7-certreqresp' => 'p7r', 'application/x-rar-compressed' => 'rar', 'application/x-rar' => 'rar', 'application/x-research-info-systems' => 'ris', 'application/x-sh' => 'sh', 'application/x-shar' => 'shar', 'application/x-shockwave-flash' => 'swf', 'application/x-silverlight-app' => 'xap', 'application/x-sql' => 'sql', 'application/x-stuffit' => 'sit', 'application/x-stuffitx' => 'sitx', 'application/x-subrip' => 'srt', 'application/x-sv4cpio' => 'sv4cpio', 'application/x-sv4crc' => 'sv4crc', 'application/x-t3vm-image' => 't3', 'application/x-tads' => 'gam', 'application/x-tar' => 'tar', 'application/x-tcl' => 'tcl', 'application/x-tex' => 'tex', 'application/x-tex-tfm' => 'tfm', 'application/x-texinfo' => 'texinfo', 'application/x-tgif' => 'obj', 'application/x-ustar' => 'ustar', 'application/x-wais-source' => 'src', 'application/x-x509-ca-cert' => 'der', 'application/x-xfig' => 'fig', 'application/x-xliff+xml' => 'xlf', 'application/x-xpinstall' => 'xpi', 'application/x-xz' => 'xz', 'application/x-zmachine' => 'z1', 'application/xaml+xml' => 'xaml', 'application/xcap-diff+xml' => 'xdf', 'application/xenc+xml' => 'xenc', 'application/xhtml+xml' => 'xhtml', 'application/xml' => 'xml', 'application/xml-dtd' => 'dtd', 'application/xop+xml' => 'xop', 'application/xproc+xml' => 'xpl', 'application/xslt+xml' => 'xslt', 'application/xspf+xml' => 'xspf', 'application/xv+xml' => 'mxml', 'application/yang' => 'yang', 'application/yin+xml' => 'yin', 'application/zip' => 'zip', 'audio/adpcm' => 'adp', 'audio/basic' => 'au', 'audio/midi' => 'mid', 'audio/mp4' => 'mp4a', 'audio/mpeg' => 'mpga', 'audio/ogg' => 'oga', 'audio/s3m' => 's3m', 'audio/silk' => 'sil', 'audio/vnd.dece.audio' => 'uva', 'audio/vnd.digital-winds' => 'eol', 'audio/vnd.dra' => 'dra', 'audio/vnd.dts' => 'dts', 'audio/vnd.dts.hd' => 'dtshd', 'audio/vnd.lucent.voice' => 'lvp', 'audio/vnd.ms-playready.media.pya' => 'pya', 'audio/vnd.nuera.ecelp4800' => 'ecelp4800', 'audio/vnd.nuera.ecelp7470' => 'ecelp7470', 'audio/vnd.nuera.ecelp9600' => 'ecelp9600', 'audio/vnd.rip' => 'rip', 'audio/webm' => 'weba', 'audio/x-aac' => 'aac', 'audio/x-aiff' => 'aif', 'audio/x-caf' => 'caf', 'audio/x-flac' => 'flac', 'audio/x-matroska' => 'mka', 'audio/x-mpegurl' => 'm3u', 'audio/x-ms-wax' => 'wax', 'audio/x-ms-wma' => 'wma', 'audio/x-pn-realaudio' => 'ram', 'audio/x-pn-realaudio-plugin' => 'rmp', 'audio/x-wav' => 'wav', 'audio/xm' => 'xm', 'chemical/x-cdx' => 'cdx', 'chemical/x-cif' => 'cif', 'chemical/x-cmdf' => 'cmdf', 'chemical/x-cml' => 'cml', 'chemical/x-csml' => 'csml', 'chemical/x-xyz' => 'xyz', 'image/bmp' => 'bmp', 'image/cgm' => 'cgm', 'image/g3fax' => 'g3', 'image/gif' => 'gif', 'image/ief' => 'ief', 'image/jpeg' => 'jpeg', 'image/ktx' => 'ktx', 'image/png' => 'png', 'image/prs.btif' => 'btif', 'image/sgi' => 'sgi', 'image/svg+xml' => 'svg', 'image/tiff' => 'tiff', 'image/vnd.adobe.photoshop' => 'psd', 'image/vnd.dece.graphic' => 'uvi', 'image/vnd.dvb.subtitle' => 'sub', 'image/vnd.djvu' => 'djvu', 'image/vnd.dwg' => 'dwg', 'image/vnd.dxf' => 'dxf', 'image/vnd.fastbidsheet' => 'fbs', 'image/vnd.fpx' => 'fpx', 'image/vnd.fst' => 'fst', 'image/vnd.fujixerox.edmics-mmr' => 'mmr', 'image/vnd.fujixerox.edmics-rlc' => 'rlc', 'image/vnd.ms-modi' => 'mdi', 'image/vnd.ms-photo' => 'wdp', 'image/vnd.net-fpx' => 'npx', 'image/vnd.wap.wbmp' => 'wbmp', 'image/vnd.xiff' => 'xif', 'image/webp' => 'webp', 'image/x-3ds' => '3ds', 'image/x-cmu-raster' => 'ras', 'image/x-cmx' => 'cmx', 'image/x-freehand' => 'fh', 'image/x-icon' => 'ico', 'image/x-mrsid-image' => 'sid', 'image/x-pcx' => 'pcx', 'image/x-pict' => 'pic', 'image/x-portable-anymap' => 'pnm', 'image/x-portable-bitmap' => 'pbm', 'image/x-portable-graymap' => 'pgm', 'image/x-portable-pixmap' => 'ppm', 'image/x-rgb' => 'rgb', 'image/x-tga' => 'tga', 'image/x-xbitmap' => 'xbm', 'image/x-xpixmap' => 'xpm', 'image/x-xwindowdump' => 'xwd', 'message/rfc822' => 'eml', 'model/iges' => 'igs', 'model/mesh' => 'msh', 'model/vnd.collada+xml' => 'dae', 'model/vnd.dwf' => 'dwf', 'model/vnd.gdl' => 'gdl', 'model/vnd.gtw' => 'gtw', 'model/vnd.mts' => 'mts', 'model/vnd.vtu' => 'vtu', 'model/vrml' => 'wrl', 'model/x3d+binary' => 'x3db', 'model/x3d+vrml' => 'x3dv', 'model/x3d+xml' => 'x3d', 'text/cache-manifest' => 'appcache', 'text/calendar' => 'ics', 'text/css' => 'css', 'text/csv' => 'csv', 'text/html' => 'html', 'text/n3' => 'n3', 'text/plain' => 'txt', 'text/prs.lines.tag' => 'dsc', 'text/richtext' => 'rtx', 'text/sgml' => 'sgml', 'text/tab-separated-values' => 'tsv', 'text/troff' => 't', 'text/turtle' => 'ttl', 'text/uri-list' => 'uri', 'text/vcard' => 'vcard', 'text/vnd.curl' => 'curl', 'text/vnd.curl.dcurl' => 'dcurl', 'text/vnd.curl.scurl' => 'scurl', 'text/vnd.curl.mcurl' => 'mcurl', 'text/vnd.dvb.subtitle' => 'sub', 'text/vnd.fly' => 'fly', 'text/vnd.fmi.flexstor' => 'flx', 'text/vnd.graphviz' => 'gv', 'text/vnd.in3d.3dml' => '3dml', 'text/vnd.in3d.spot' => 'spot', 'text/vnd.sun.j2me.app-descriptor' => 'jad', 'text/vnd.wap.wml' => 'wml', 'text/vnd.wap.wmlscript' => 'wmls', 'text/x-asm' => 's', 'text/x-c' => 'c', 'text/x-fortran' => 'f', 'text/x-pascal' => 'p', 'text/x-java-source' => 'java', 'text/x-opml' => 'opml', 'text/x-nfo' => 'nfo', 'text/x-setext' => 'etx', 'text/x-sfv' => 'sfv', 'text/x-uuencode' => 'uu', 'text/x-vcalendar' => 'vcs', 'text/x-vcard' => 'vcf', 'video/3gpp' => '3gp', 'video/3gpp2' => '3g2', 'video/h261' => 'h261', 'video/h263' => 'h263', 'video/h264' => 'h264', 'video/jpeg' => 'jpgv', 'video/jpm' => 'jpm', 'video/mj2' => 'mj2', 'video/mp4' => 'mp4', 'video/mpeg' => 'mpeg', 'video/ogg' => 'ogv', 'video/quicktime' => 'qt', 'video/vnd.dece.hd' => 'uvh', 'video/vnd.dece.mobile' => 'uvm', 'video/vnd.dece.pd' => 'uvp', 'video/vnd.dece.sd' => 'uvs', 'video/vnd.dece.video' => 'uvv', 'video/vnd.dvb.file' => 'dvb', 'video/vnd.fvt' => 'fvt', 'video/vnd.mpegurl' => 'mxu', 'video/vnd.ms-playready.media.pyv' => 'pyv', 'video/vnd.uvvu.mp4' => 'uvu', 'video/vnd.vivo' => 'viv', 'video/webm' => 'webm', 'video/x-f4v' => 'f4v', 'video/x-fli' => 'fli', 'video/x-flv' => 'flv', 'video/x-m4v' => 'm4v', 'video/x-matroska' => 'mkv', 'video/x-mng' => 'mng', 'video/x-ms-asf' => 'asf', 'video/x-ms-vob' => 'vob', 'video/x-ms-wm' => 'wm', 'video/x-ms-wmv' => 'wmv', 'video/x-ms-wmx' => 'wmx', 'video/x-ms-wvx' => 'wvx', 'video/x-msvideo' => 'avi', 'video/x-sgi-movie' => 'movie', 'video/x-smv' => 'smv', 'x-conference/x-cooltalk' => 'ice', ); /** * {@inheritdoc} */ public function guess($mimeType) { return isset($this->defaultExtensions[$mimeType]) ? $this->defaultExtensions[$mimeType] : null; } } PK! LKSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\MimeType; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; /** * Guesses the mime type of a file * * @author Bernhard Schussek */ interface MimeTypeGuesserInterface { /** * Guesses the mime type of the file with the given path. * * @param string $path The path to the file * * @return string The mime type or NULL, if none could be guessed * * @throws FileNotFoundException If the file does not exist * @throws AccessDeniedException If the file could not be read */ public function guess($path); } PK!).Symfony/Component/HttpFoundation/File/File.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser; /** * A file in the file system. * * @author Bernhard Schussek * * @api */ class File extends \SplFileInfo { /** * Constructs a new file from the given path. * * @param string $path The path to the file * @param Boolean $checkPath Whether to check the path or not * * @throws FileNotFoundException If the given path is not a file * * @api */ public function __construct($path, $checkPath = true) { if ($checkPath && !is_file($path)) { throw new FileNotFoundException($path); } parent::__construct($path); } /** * Returns the extension based on the mime type. * * If the mime type is unknown, returns null. * * This method uses the mime type as guessed by getMimeType() * to guess the file extension. * * @return string|null The guessed extension or null if it cannot be guessed * * @api * * @see ExtensionGuesser * @see getMimeType() */ public function guessExtension() { $type = $this->getMimeType(); $guesser = ExtensionGuesser::getInstance(); return $guesser->guess($type); } /** * Returns the mime type of the file. * * The mime type is guessed using a MimeTypeGuesser instance, which uses finfo(), * mime_content_type() and the system binary "file" (in this order), depending on * which of those are available. * * @return string|null The guessed mime type (i.e. "application/pdf") * * @see MimeTypeGuesser * * @api */ public function getMimeType() { $guesser = MimeTypeGuesser::getInstance(); return $guesser->guess($this->getPathname()); } /** * Returns the extension of the file. * * \SplFileInfo::getExtension() is not available before PHP 5.3.6 * * @return string The extension * * @api */ public function getExtension() { return pathinfo($this->getBasename(), PATHINFO_EXTENSION); } /** * Moves the file to a new location. * * @param string $directory The destination folder * @param string $name The new file name * * @return File A File object representing the new file * * @throws FileException if the target file could not be created * * @api */ public function move($directory, $name = null) { $target = $this->getTargetFile($directory, $name); if (!@rename($this->getPathname(), $target)) { $error = error_get_last(); throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message']))); } @chmod($target, 0666 & ~umask()); return $target; } protected function getTargetFile($directory, $name = null) { if (!is_dir($directory)) { if (false === @mkdir($directory, 0777, true)) { throw new FileException(sprintf('Unable to create the "%s" directory', $directory)); } } elseif (!is_writable($directory)) { throw new FileException(sprintf('Unable to write in the "%s" directory', $directory)); } $target = rtrim($directory, '/\\').DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); return new File($target, false); } /** * Returns locale independent base name of the given path. * * @param string $name The new file name * * @return string containing */ protected function getName($name) { $originalName = str_replace('\\', '/', $name); $pos = strrpos($originalName, '/'); $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1); return $originalName; } } PK!s-ISymfony/Component/HttpFoundation/File/Exception/FileNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when a file was not found * * @author Bernhard Schussek */ class FileNotFoundException extends FileException { /** * Constructor. * * @param string $path The path to the file that was not found */ public function __construct($path) { parent::__construct(sprintf('The file "%s" does not exist', $path)); } } PK!S==KSymfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; class UnexpectedTypeException extends FileException { public function __construct($value, $expectedType) { parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, is_object($value) ? get_class($value) : gettype($value))); } } PK!1eISymfony/Component/HttpFoundation/File/Exception/AccessDeniedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when the access on a file was denied. * * @author Bernhard Schussek */ class AccessDeniedException extends FileException { /** * Constructor. * * @param string $path The path to the accessed file */ public function __construct($path) { parent::__construct(sprintf('The file %s could not be accessed', $path)); } } PK!grCSymfony/Component/HttpFoundation/File/Exception/UploadException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an error occurred during file upload * * @author Bernhard Schussek */ class UploadException extends FileException { } PK!oASymfony/Component/HttpFoundation/File/Exception/FileException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an error occurred in the component File * * @author Bernhard Schussek */ class FileException extends \RuntimeException { } PK!ގ##6Symfony/Component/HttpFoundation/File/UploadedFile.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser; /** * A file uploaded through a form. * * @author Bernhard Schussek * @author Florian Eckerstorfer * @author Fabien Potencier * * @api */ class UploadedFile extends File { /** * Whether the test mode is activated. * * Local files are used in test mode hence the code should not enforce HTTP uploads. * * @var Boolean */ private $test = false; /** * The original name of the uploaded file. * * @var string */ private $originalName; /** * The mime type provided by the uploader. * * @var string */ private $mimeType; /** * The file size provided by the uploader. * * @var string */ private $size; /** * The UPLOAD_ERR_XXX constant provided by the uploader. * * @var integer */ private $error; /** * Accepts the information of the uploaded file as provided by the PHP global $_FILES. * * The file object is only created when the uploaded file is valid (i.e. when the * isValid() method returns true). Otherwise the only methods that could be called * on an UploadedFile instance are: * * * getClientOriginalName, * * getClientMimeType, * * isValid, * * getError. * * Calling any other method on an non-valid instance will cause an unpredictable result. * * @param string $path The full temporary path to the file * @param string $originalName The original file name * @param string $mimeType The type of the file as provided by PHP * @param integer $size The file size * @param integer $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants) * @param Boolean $test Whether the test mode is active * * @throws FileException If file_uploads is disabled * @throws FileNotFoundException If the file does not exist * * @api */ public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null, $test = false) { $this->originalName = $this->getName($originalName); $this->mimeType = $mimeType ?: 'application/octet-stream'; $this->size = $size; $this->error = $error ?: UPLOAD_ERR_OK; $this->test = (Boolean) $test; parent::__construct($path, UPLOAD_ERR_OK === $this->error); } /** * Returns the original file name. * * It is extracted from the request from which the file has been uploaded. * Then it should not be considered as a safe value. * * @return string|null The original name * * @api */ public function getClientOriginalName() { return $this->originalName; } /** * Returns the original file extension * * It is extracted from the original file name that was uploaded. * Then it should not be considered as a safe value. * * @return string The extension */ public function getClientOriginalExtension() { return pathinfo($this->originalName, PATHINFO_EXTENSION); } /** * Returns the file mime type. * * The client mime type is extracted from the request from which the file * was uploaded, so it should not be considered as a safe value. * * For a trusted mime type, use getMimeType() instead (which guesses the mime * type based on the file content). * * @return string|null The mime type * * @see getMimeType * * @api */ public function getClientMimeType() { return $this->mimeType; } /** * Returns the extension based on the client mime type. * * If the mime type is unknown, returns null. * * This method uses the mime type as guessed by getClientMimeType() * to guess the file extension. As such, the extension returned * by this method cannot be trusted. * * For a trusted extension, use guessExtension() instead (which guesses * the extension based on the guessed mime type for the file). * * @return string|null The guessed extension or null if it cannot be guessed * * @see guessExtension() * @see getClientMimeType() */ public function guessClientExtension() { $type = $this->getClientMimeType(); $guesser = ExtensionGuesser::getInstance(); return $guesser->guess($type); } /** * Returns the file size. * * It is extracted from the request from which the file has been uploaded. * Then it should not be considered as a safe value. * * @return integer|null The file size * * @api */ public function getClientSize() { return $this->size; } /** * Returns the upload error. * * If the upload was successful, the constant UPLOAD_ERR_OK is returned. * Otherwise one of the other UPLOAD_ERR_XXX constants is returned. * * @return integer The upload error * * @api */ public function getError() { return $this->error; } /** * Returns whether the file was uploaded successfully. * * @return Boolean True if the file has been uploaded with HTTP and no error occurred. * * @api */ public function isValid() { $isOk = $this->error === UPLOAD_ERR_OK; return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()); } /** * Moves the file to a new location. * * @param string $directory The destination folder * @param string $name The new file name * * @return File A File object representing the new file * * @throws FileException if, for any reason, the file could not have been moved * * @api */ public function move($directory, $name = null) { if ($this->isValid()) { if ($this->test) { return parent::move($directory, $name); } $target = $this->getTargetFile($directory, $name); if (!@move_uploaded_file($this->getPathname(), $target)) { $error = error_get_last(); throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message']))); } @chmod($target, 0666 & ~umask()); return $target; } throw new FileException($this->getErrorMessage()); } /** * Returns the maximum size of an uploaded file as configured in php.ini * * @return int The maximum size of an uploaded file in bytes */ public static function getMaxFilesize() { $iniMax = strtolower(ini_get('upload_max_filesize')); if ('' === $iniMax) { return PHP_INT_MAX; } $max = ltrim($iniMax, '+'); if (0 === strpos($max, '0x')) { $max = intval($max, 16); } elseif (0 === strpos($max, '0')) { $max = intval($max, 8); } else { $max = intval($max); } switch (substr($iniMax, -1)) { case 't': $max *= 1024; case 'g': $max *= 1024; case 'm': $max *= 1024; case 'k': $max *= 1024; } return $max; } /** * Returns an informative upload error message. * * @return string The error message regarding the specified error code */ public function getErrorMessage() { static $errors = array( UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d kb).', UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', UPLOAD_ERR_NO_FILE => 'No file was uploaded.', UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', ); $errorCode = $this->error; $maxFilesize = $errorCode === UPLOAD_ERR_INI_SIZE ? self::getMaxFilesize() / 1024 : 0; $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.'; return sprintf($message, $this->getClientOriginalName(), $maxFilesize); } } PK!7 E E 1Symfony/Component/HttpFoundation/RequestStack.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Request stack that controls the lifecycle of requests. * * @author Benjamin Eberlei */ class RequestStack { /** * @var Request[] */ private $requests = array(); /** * Pushes a Request on the stack. * * This method should generally not be called directly as the stack * management should be taken care of by the application itself. */ public function push(Request $request) { $this->requests[] = $request; } /** * Pops the current request from the stack. * * This operation lets the current request go out of scope. * * This method should generally not be called directly as the stack * management should be taken care of by the application itself. * * @return Request|null */ public function pop() { if (!$this->requests) { return null; } return array_pop($this->requests); } /** * @return Request|null */ public function getCurrentRequest() { return end($this->requests) ?: null; } /** * Gets the master Request. * * Be warned that making your code aware of the master request * might make it un-compatible with other features of your framework * like ESI support. * * @return Request|null */ public function getMasterRequest() { if (!$this->requests) { return null; } return $this->requests[0]; } /** * Returns the parent request of the current. * * Be warned that making your code aware of the parent request * might make it un-compatible with other features of your framework * like ESI support. * * If current Request is the master request, it returns null. * * @return Request|null */ public function getParentRequest() { $pos = count($this->requests) - 2; if (!isset($this->requests[$pos])) { return null; } return $this->requests[$pos]; } } PK!W ;Symfony/Component/HttpFoundation/Session/Flash/FlashBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Flash; /** * FlashBag flash message container. * * \IteratorAggregate implementation is deprecated and will be removed in 3.0. * * @author Drak */ class FlashBag implements FlashBagInterface, \IteratorAggregate { private $name = 'flashes'; /** * Flash messages. * * @var array */ private $flashes = array(); /** * The storage key for flashes in the session * * @var string */ private $storageKey; /** * Constructor. * * @param string $storageKey The key used to store flashes in the session. */ public function __construct($storageKey = '_sf2_flashes') { $this->storageKey = $storageKey; } /** * {@inheritdoc} */ public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } /** * {@inheritdoc} */ public function initialize(array &$flashes) { $this->flashes = &$flashes; } /** * {@inheritdoc} */ public function add($type, $message) { $this->flashes[$type][] = $message; } /** * {@inheritdoc} */ public function peek($type, array $default = array()) { return $this->has($type) ? $this->flashes[$type] : $default; } /** * {@inheritdoc} */ public function peekAll() { return $this->flashes; } /** * {@inheritdoc} */ public function get($type, array $default = array()) { if (!$this->has($type)) { return $default; } $return = $this->flashes[$type]; unset($this->flashes[$type]); return $return; } /** * {@inheritdoc} */ public function all() { $return = $this->peekAll(); $this->flashes = array(); return $return; } /** * {@inheritdoc} */ public function set($type, $messages) { $this->flashes[$type] = (array) $messages; } /** * {@inheritdoc} */ public function setAll(array $messages) { $this->flashes = $messages; } /** * {@inheritdoc} */ public function has($type) { return array_key_exists($type, $this->flashes) && $this->flashes[$type]; } /** * {@inheritdoc} */ public function keys() { return array_keys($this->flashes); } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * {@inheritdoc} */ public function clear() { return $this->all(); } /** * Returns an iterator for flashes. * * @deprecated Will be removed in 3.0. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->all()); } } PK!@WWESymfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Flash; /** * AutoExpireFlashBag flash message container. * * @author Drak */ class AutoExpireFlashBag implements FlashBagInterface { private $name = 'flashes'; /** * Flash messages. * * @var array */ private $flashes = array('display' => array(), 'new' => array()); /** * The storage key for flashes in the session * * @var string */ private $storageKey; /** * Constructor. * * @param string $storageKey The key used to store flashes in the session. */ public function __construct($storageKey = '_sf2_flashes') { $this->storageKey = $storageKey; } /** * {@inheritdoc} */ public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } /** * {@inheritdoc} */ public function initialize(array &$flashes) { $this->flashes = &$flashes; // The logic: messages from the last request will be stored in new, so we move them to previous // This request we will show what is in 'display'. What is placed into 'new' this time round will // be moved to display next time round. $this->flashes['display'] = array_key_exists('new', $this->flashes) ? $this->flashes['new'] : array(); $this->flashes['new'] = array(); } /** * {@inheritdoc} */ public function add($type, $message) { $this->flashes['new'][$type][] = $message; } /** * {@inheritdoc} */ public function peek($type, array $default = array()) { return $this->has($type) ? $this->flashes['display'][$type] : $default; } /** * {@inheritdoc} */ public function peekAll() { return array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : array(); } /** * {@inheritdoc} */ public function get($type, array $default = array()) { $return = $default; if (!$this->has($type)) { return $return; } if (isset($this->flashes['display'][$type])) { $return = $this->flashes['display'][$type]; unset($this->flashes['display'][$type]); } return $return; } /** * {@inheritdoc} */ public function all() { $return = $this->flashes['display']; $this->flashes = array('new' => array(), 'display' => array()); return $return; } /** * {@inheritdoc} */ public function setAll(array $messages) { $this->flashes['new'] = $messages; } /** * {@inheritdoc} */ public function set($type, $messages) { $this->flashes['new'][$type] = (array) $messages; } /** * {@inheritdoc} */ public function has($type) { return array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; } /** * {@inheritdoc} */ public function keys() { return array_keys($this->flashes['display']); } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * {@inheritdoc} */ public function clear() { return $this->all(); } } PK!aDSymfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Flash; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * FlashBagInterface. * * @author Drak */ interface FlashBagInterface extends SessionBagInterface { /** * Adds a flash message for type. * * @param string $type * @param string $message */ public function add($type, $message); /** * Registers a message for a given type. * * @param string $type * @param string|array $message */ public function set($type, $message); /** * Gets flash messages for a given type. * * @param string $type Message category type. * @param array $default Default value if $type does not exist. * * @return array */ public function peek($type, array $default = array()); /** * Gets all flash messages. * * @return array */ public function peekAll(); /** * Gets and clears flash from the stack. * * @param string $type * @param array $default Default value if $type does not exist. * * @return array */ public function get($type, array $default = array()); /** * Gets and clears flashes from the stack. * * @return array */ public function all(); /** * Sets all flash messages. */ public function setAll(array $messages); /** * Has flash messages for a given type? * * @param string $type * * @return boolean */ public function has($type); /** * Returns a list of all defined types. * * @return array */ public function keys(); } PK!=\\=Symfony/Component/HttpFoundation/Session/SessionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; /** * Interface for the session. * * @author Drak */ interface SessionInterface { /** * Starts the session storage. * * @return Boolean True if session started. * * @throws \RuntimeException If session fails to start. * * @api */ public function start(); /** * Returns the session ID. * * @return string The session ID. * * @api */ public function getId(); /** * Sets the session ID * * @param string $id * * @api */ public function setId($id); /** * Returns the session name. * * @return mixed The session name. * * @api */ public function getName(); /** * Sets the session name. * * @param string $name * * @api */ public function setName($name); /** * Invalidates the current session. * * Clears all session attributes and flashes and regenerates the * session and deletes the old session from persistence. * * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. * * @return Boolean True if session invalidated, false if error. * * @api */ public function invalidate($lifetime = null); /** * Migrates the current session to a new session id while maintaining all * session attributes. * * @param Boolean $destroy Whether to delete the old session or leave it to garbage collection. * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. * * @return Boolean True if session migrated, false if error. * * @api */ public function migrate($destroy = false, $lifetime = null); /** * Force the session to be saved and closed. * * This method is generally not required for real sessions as * the session will be automatically saved at the end of * code execution. */ public function save(); /** * Checks if an attribute is defined. * * @param string $name The attribute name * * @return Boolean true if the attribute is defined, false otherwise * * @api */ public function has($name); /** * Returns an attribute. * * @param string $name The attribute name * @param mixed $default The default value if not found. * * @return mixed * * @api */ public function get($name, $default = null); /** * Sets an attribute. * * @param string $name * @param mixed $value * * @api */ public function set($name, $value); /** * Returns attributes. * * @return array Attributes * * @api */ public function all(); /** * Sets attributes. * * @param array $attributes Attributes */ public function replace(array $attributes); /** * Removes an attribute. * * @param string $name * * @return mixed The removed value or null when it does not exist * * @api */ public function remove($name); /** * Clears all attributes. * * @api */ public function clear(); /** * Checks if the session was started. * * @return Boolean */ public function isStarted(); /** * Registers a SessionBagInterface with the session. * * @param SessionBagInterface $bag */ public function registerBag(SessionBagInterface $bag); /** * Gets a bag instance by name. * * @param string $name * * @return SessionBagInterface */ public function getBag($name); /** * Gets session meta. * * @return MetadataBag */ public function getMetadataBag(); } PK!:au774Symfony/Component/HttpFoundation/Session/Session.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; /** * Session. * * @author Fabien Potencier * @author Drak * * @api */ class Session implements SessionInterface, \IteratorAggregate, \Countable { /** * Storage driver. * * @var SessionStorageInterface */ protected $storage; /** * @var string */ private $flashName; /** * @var string */ private $attributeName; /** * Constructor. * * @param SessionStorageInterface $storage A SessionStorageInterface instance. * @param AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag) * @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag) */ public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null) { $this->storage = $storage ?: new NativeSessionStorage(); $attributes = $attributes ?: new AttributeBag(); $this->attributeName = $attributes->getName(); $this->registerBag($attributes); $flashes = $flashes ?: new FlashBag(); $this->flashName = $flashes->getName(); $this->registerBag($flashes); } /** * {@inheritdoc} */ public function start() { return $this->storage->start(); } /** * {@inheritdoc} */ public function has($name) { return $this->storage->getBag($this->attributeName)->has($name); } /** * {@inheritdoc} */ public function get($name, $default = null) { return $this->storage->getBag($this->attributeName)->get($name, $default); } /** * {@inheritdoc} */ public function set($name, $value) { $this->storage->getBag($this->attributeName)->set($name, $value); } /** * {@inheritdoc} */ public function all() { return $this->storage->getBag($this->attributeName)->all(); } /** * {@inheritdoc} */ public function replace(array $attributes) { $this->storage->getBag($this->attributeName)->replace($attributes); } /** * {@inheritdoc} */ public function remove($name) { return $this->storage->getBag($this->attributeName)->remove($name); } /** * {@inheritdoc} */ public function clear() { $this->storage->getBag($this->attributeName)->clear(); } /** * {@inheritdoc} */ public function isStarted() { return $this->storage->isStarted(); } /** * Returns an iterator for attributes. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->storage->getBag($this->attributeName)->all()); } /** * Returns the number of attributes. * * @return int The number of attributes */ public function count() { return count($this->storage->getBag($this->attributeName)->all()); } /** * {@inheritdoc} */ public function invalidate($lifetime = null) { $this->storage->clear(); return $this->migrate(true, $lifetime); } /** * {@inheritdoc} */ public function migrate($destroy = false, $lifetime = null) { return $this->storage->regenerate($destroy, $lifetime); } /** * {@inheritdoc} */ public function save() { $this->storage->save(); } /** * {@inheritdoc} */ public function getId() { return $this->storage->getId(); } /** * {@inheritdoc} */ public function setId($id) { $this->storage->setId($id); } /** * {@inheritdoc} */ public function getName() { return $this->storage->getName(); } /** * {@inheritdoc} */ public function setName($name) { $this->storage->setName($name); } /** * {@inheritdoc} */ public function getMetadataBag() { return $this->storage->getMetadataBag(); } /** * {@inheritdoc} */ public function registerBag(SessionBagInterface $bag) { $this->storage->registerBag($bag); } /** * {@inheritdoc} */ public function getBag($name) { return $this->storage->getBag($name); } /** * Gets the flashbag interface. * * @return FlashBagInterface */ public function getFlashBag() { return $this->getBag($this->flashName); } } PK!M&zrr@Symfony/Component/HttpFoundation/Session/SessionBagInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; /** * Session Bag store. * * @author Drak */ interface SessionBagInterface { /** * Gets this bag's name * * @return string */ public function getName(); /** * Initializes the Bag * * @param array $array */ public function initialize(array &$array); /** * Gets the storage key for this bag. * * @return string */ public function getStorageKey(); /** * Clears out data from bag. * * @return mixed Whatever data was contained. */ public function clear(); } PK!e  LSymfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Attribute; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * Attributes store. * * @author Drak */ interface AttributeBagInterface extends SessionBagInterface { /** * Checks if an attribute is defined. * * @param string $name The attribute name * * @return Boolean true if the attribute is defined, false otherwise */ public function has($name); /** * Returns an attribute. * * @param string $name The attribute name * @param mixed $default The default value if not found * * @return mixed */ public function get($name, $default = null); /** * Sets an attribute. * * @param string $name * @param mixed $value */ public function set($name, $value); /** * Returns attributes. * * @return array Attributes */ public function all(); /** * Sets attributes. * * @param array $attributes Attributes */ public function replace(array $attributes); /** * Removes an attribute. * * @param string $name * * @return mixed The removed value or null when it does not exist */ public function remove($name); } PK!( CSymfony/Component/HttpFoundation/Session/Attribute/AttributeBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Attribute; /** * This class relates to session attribute storage */ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable { private $name = 'attributes'; /** * @var string */ private $storageKey; /** * @var array */ protected $attributes = array(); /** * Constructor. * * @param string $storageKey The key used to store attributes in the session */ public function __construct($storageKey = '_sf2_attributes') { $this->storageKey = $storageKey; } /** * {@inheritdoc} */ public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } /** * {@inheritdoc} */ public function initialize(array &$attributes) { $this->attributes = &$attributes; } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * {@inheritdoc} */ public function has($name) { return array_key_exists($name, $this->attributes); } /** * {@inheritdoc} */ public function get($name, $default = null) { return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** * {@inheritdoc} */ public function set($name, $value) { $this->attributes[$name] = $value; } /** * {@inheritdoc} */ public function all() { return $this->attributes; } /** * {@inheritdoc} */ public function replace(array $attributes) { $this->attributes = array(); foreach ($attributes as $key => $value) { $this->set($key, $value); } } /** * {@inheritdoc} */ public function remove($name) { $retval = null; if (array_key_exists($name, $this->attributes)) { $retval = $this->attributes[$name]; unset($this->attributes[$name]); } return $retval; } /** * {@inheritdoc} */ public function clear() { $return = $this->attributes; $this->attributes = array(); return $return; } /** * Returns an iterator for attributes. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->attributes); } /** * Returns the number of attributes. * * @return integer The number of attributes */ public function count() { return count($this->attributes); } } PK!0H66MSymfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Attribute; /** * This class provides structured storage of session attributes using * a name spacing character in the key. * * @author Drak */ class NamespacedAttributeBag extends AttributeBag { /** * Namespace character. * * @var string */ private $namespaceCharacter; /** * Constructor. * * @param string $storageKey Session storage key. * @param string $namespaceCharacter Namespace character to use in keys. */ public function __construct($storageKey = '_sf2_attributes', $namespaceCharacter = '/') { $this->namespaceCharacter = $namespaceCharacter; parent::__construct($storageKey); } /** * {@inheritdoc} */ public function has($name) { $attributes = $this->resolveAttributePath($name); $name = $this->resolveKey($name); if (null === $attributes) { return false; } return array_key_exists($name, $attributes); } /** * {@inheritdoc} */ public function get($name, $default = null) { $attributes = $this->resolveAttributePath($name); $name = $this->resolveKey($name); if (null === $attributes) { return $default; } return array_key_exists($name, $attributes) ? $attributes[$name] : $default; } /** * {@inheritdoc} */ public function set($name, $value) { $attributes = & $this->resolveAttributePath($name, true); $name = $this->resolveKey($name); $attributes[$name] = $value; } /** * {@inheritdoc} */ public function remove($name) { $retval = null; $attributes = & $this->resolveAttributePath($name); $name = $this->resolveKey($name); if (null !== $attributes && array_key_exists($name, $attributes)) { $retval = $attributes[$name]; unset($attributes[$name]); } return $retval; } /** * Resolves a path in attributes property and returns it as a reference. * * This method allows structured namespacing of session attributes. * * @param string $name Key name * @param boolean $writeContext Write context, default false * * @return array */ protected function &resolveAttributePath($name, $writeContext = false) { $array = & $this->attributes; $name = (strpos($name, $this->namespaceCharacter) === 0) ? substr($name, 1) : $name; // Check if there is anything to do, else return if (!$name) { return $array; } $parts = explode($this->namespaceCharacter, $name); if (count($parts) < 2) { if (!$writeContext) { return $array; } $array[$parts[0]] = array(); return $array; } unset($parts[count($parts)-1]); foreach ($parts as $part) { if (null !== $array && !array_key_exists($part, $array)) { $array[$part] = $writeContext ? array() : null; } $array = & $array[$part]; } return $array; } /** * Resolves the key from the name. * * This is the last part in a dot separated string. * * @param string $name * * @return string */ protected function resolveKey($name) { if (false !== $pos = strrpos($name, $this->namespaceCharacter)) { $name = substr($name, $pos+1); } return $name; } } PK!t33ISymfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; /** * This provides a base class for session attribute storage. * * @author Drak */ class NativeSessionStorage implements SessionStorageInterface { /** * Array of SessionBagInterface * * @var SessionBagInterface[] */ protected $bags; /** * @var Boolean */ protected $started = false; /** * @var Boolean */ protected $closed = false; /** * @var AbstractProxy */ protected $saveHandler; /** * @var MetadataBag */ protected $metadataBag; /** * Constructor. * * Depending on how you want the storage driver to behave you probably * want to override this constructor entirely. * * List of options for $options array with their defaults. * @see http://php.net/session.configuration for options * but we omit 'session.' from the beginning of the keys for convenience. * * ("auto_start", is not supported as it tells PHP to start a session before * PHP starts to execute user-land code. Setting during runtime has no effect). * * cache_limiter, "nocache" (use "0" to prevent headers from being sent entirely). * cookie_domain, "" * cookie_httponly, "" * cookie_lifetime, "0" * cookie_path, "/" * cookie_secure, "" * entropy_file, "" * entropy_length, "0" * gc_divisor, "100" * gc_maxlifetime, "1440" * gc_probability, "1" * hash_bits_per_character, "4" * hash_function, "0" * name, "PHPSESSID" * referer_check, "" * serialize_handler, "php" * use_cookies, "1" * use_only_cookies, "1" * use_trans_sid, "0" * upload_progress.enabled, "1" * upload_progress.cleanup, "1" * upload_progress.prefix, "upload_progress_" * upload_progress.name, "PHP_SESSION_UPLOAD_PROGRESS" * upload_progress.freq, "1%" * upload_progress.min-freq, "1" * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset=" * * @param array $options Session configuration options. * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler * @param MetadataBag $metaBag MetadataBag. */ public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) { session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used) ini_set('session.use_cookies', 1); if (version_compare(phpversion(), '5.4.0', '>=')) { session_register_shutdown(); } else { register_shutdown_function('session_write_close'); } $this->setMetadataBag($metaBag); $this->setOptions($options); $this->setSaveHandler($handler); } /** * Gets the save handler instance. * * @return AbstractProxy */ public function getSaveHandler() { return $this->saveHandler; } /** * {@inheritdoc} */ public function start() { if ($this->started && !$this->closed) { return true; } if (version_compare(phpversion(), '5.4.0', '>=') && \PHP_SESSION_ACTIVE === session_status()) { throw new \RuntimeException('Failed to start the session: already started by PHP.'); } if (version_compare(phpversion(), '5.4.0', '<') && isset($_SESSION) && session_id()) { // not 100% fool-proof, but is the most reliable way to determine if a session is active in PHP 5.3 throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).'); } if (ini_get('session.use_cookies') && headers_sent($file, $line)) { throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); } // ok to try and start the session if (!session_start()) { throw new \RuntimeException('Failed to start the session'); } $this->loadSession(); if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { // This condition matches only PHP 5.3 with internal save handlers $this->saveHandler->setActive(true); } return true; } /** * {@inheritdoc} */ public function getId() { if (!$this->started && !$this->closed) { return ''; // returning empty is consistent with session_id() behaviour } return $this->saveHandler->getId(); } /** * {@inheritdoc} */ public function setId($id) { $this->saveHandler->setId($id); } /** * {@inheritdoc} */ public function getName() { return $this->saveHandler->getName(); } /** * {@inheritdoc} */ public function setName($name) { $this->saveHandler->setName($name); } /** * {@inheritdoc} */ public function regenerate($destroy = false, $lifetime = null) { if (null !== $lifetime) { ini_set('session.cookie_lifetime', $lifetime); } if ($destroy) { $this->metadataBag->stampNew(); } $ret = session_regenerate_id($destroy); // workaround for https://bugs.php.net/bug.php?id=61470 as suggested by David Grudl if ('files' === $this->getSaveHandler()->getSaveHandlerName()) { session_write_close(); if (isset($_SESSION)) { $backup = $_SESSION; session_start(); $_SESSION = $backup; } else { session_start(); } $this->loadSession(); } return $ret; } /** * {@inheritdoc} */ public function save() { session_write_close(); if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { // This condition matches only PHP 5.3 with internal save handlers $this->saveHandler->setActive(false); } $this->closed = true; $this->started = false; } /** * {@inheritdoc} */ public function clear() { // clear out the bags foreach ($this->bags as $bag) { $bag->clear(); } // clear out the session $_SESSION = array(); // reconnect the bags to the session $this->loadSession(); } /** * {@inheritdoc} */ public function registerBag(SessionBagInterface $bag) { $this->bags[$bag->getName()] = $bag; } /** * {@inheritdoc} */ public function getBag($name) { if (!isset($this->bags[$name])) { throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); } if ($this->saveHandler->isActive() && !$this->started) { $this->loadSession(); } elseif (!$this->started) { $this->start(); } return $this->bags[$name]; } /** * Sets the MetadataBag. * * @param MetadataBag $metaBag */ public function setMetadataBag(MetadataBag $metaBag = null) { if (null === $metaBag) { $metaBag = new MetadataBag(); } $this->metadataBag = $metaBag; } /** * Gets the MetadataBag. * * @return MetadataBag */ public function getMetadataBag() { return $this->metadataBag; } /** * {@inheritdoc} */ public function isStarted() { return $this->started; } /** * Sets session.* ini variables. * * For convenience we omit 'session.' from the beginning of the keys. * Explicitly ignores other ini keys. * * @param array $options Session ini directives array(key => value). * * @see http://php.net/session.configuration */ public function setOptions(array $options) { $validOptions = array_flip(array( 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'entropy_file', 'entropy_length', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', 'hash_function', 'name', 'referer_check', 'serialize_handler', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', )); foreach ($options as $key => $value) { if (isset($validOptions[$key])) { ini_set('session.'.$key, $value); } } } /** * Registers session save handler as a PHP session handler. * * To use internal PHP session save handlers, override this method using ini_set with * session.save_handler and session.save_path e.g. * * ini_set('session.save_handler', 'files'); * ini_set('session.save_path', /tmp'); * * or pass in a NativeSessionHandler instance which configures session.save_handler in the * constructor, for a template see NativeFileSessionHandler or use handlers in * composer package drak/native-session * * @see http://php.net/session-set-save-handler * @see http://php.net/sessionhandlerinterface * @see http://php.net/sessionhandler * @see http://github.com/drak/NativeSession * * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $saveHandler * * @throws \InvalidArgumentException */ public function setSaveHandler($saveHandler = null) { if (!$saveHandler instanceof AbstractProxy && !$saveHandler instanceof NativeSessionHandler && !$saveHandler instanceof \SessionHandlerInterface && null !== $saveHandler) { throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.'); } // Wrap $saveHandler in proxy and prevent double wrapping of proxy if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler); } elseif (!$saveHandler instanceof AbstractProxy) { $saveHandler = version_compare(phpversion(), '5.4.0', '>=') ? new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy(); } $this->saveHandler = $saveHandler; if ($this->saveHandler instanceof \SessionHandlerInterface) { if (version_compare(phpversion(), '5.4.0', '>=')) { session_set_save_handler($this->saveHandler, false); } else { session_set_save_handler( array($this->saveHandler, 'open'), array($this->saveHandler, 'close'), array($this->saveHandler, 'read'), array($this->saveHandler, 'write'), array($this->saveHandler, 'destroy'), array($this->saveHandler, 'gc') ); } } } /** * Load the session with attributes. * * After starting the session, PHP retrieves the session from whatever handlers * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). * PHP takes the return value from the read() handler, unserializes it * and populates $_SESSION with the result automatically. * * @param array|null $session */ protected function loadSession(array &$session = null) { if (null === $session) { $session = &$_SESSION; } $bags = array_merge($this->bags, array($this->metadataBag)); foreach ($bags as $bag) { $key = $bag->getStorageKey(); $session[$key] = isset($session[$key]) ? $session[$key] : array(); $bag->initialize($session[$key]); } $this->started = true; $this->closed = false; } } PK!ގ!LSymfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * MockArraySessionStorage mocks the session for unit tests. * * No PHP session is actually started since a session can be initialized * and shutdown only once per PHP execution cycle. * * When doing functional testing, you should use MockFileSessionStorage instead. * * @author Fabien Potencier * @author Bulat Shakirzyanov * @author Drak */ class MockArraySessionStorage implements SessionStorageInterface { /** * @var string */ protected $id = ''; /** * @var string */ protected $name; /** * @var boolean */ protected $started = false; /** * @var boolean */ protected $closed = false; /** * @var array */ protected $data = array(); /** * @var MetadataBag */ protected $metadataBag; /** * @var array */ protected $bags; /** * Constructor. * * @param string $name Session name * @param MetadataBag $metaBag MetadataBag instance. */ public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null) { $this->name = $name; $this->setMetadataBag($metaBag); } /** * Sets the session data. * * @param array $array */ public function setSessionData(array $array) { $this->data = $array; } /** * {@inheritdoc} */ public function start() { if ($this->started && !$this->closed) { return true; } if (empty($this->id)) { $this->id = $this->generateId(); } $this->loadSession(); return true; } /** * {@inheritdoc} */ public function regenerate($destroy = false, $lifetime = null) { if (!$this->started) { $this->start(); } $this->metadataBag->stampNew($lifetime); $this->id = $this->generateId(); return true; } /** * {@inheritdoc} */ public function getId() { return $this->id; } /** * {@inheritdoc} */ public function setId($id) { if ($this->started) { throw new \LogicException('Cannot set session ID after the session has started.'); } $this->id = $id; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * {@inheritdoc} */ public function setName($name) { $this->name = $name; } /** * {@inheritdoc} */ public function save() { if (!$this->started || $this->closed) { throw new \RuntimeException("Trying to save a session that was not started yet or was already closed"); } // nothing to do since we don't persist the session data $this->closed = false; $this->started = false; } /** * {@inheritdoc} */ public function clear() { // clear out the bags foreach ($this->bags as $bag) { $bag->clear(); } // clear out the session $this->data = array(); // reconnect the bags to the session $this->loadSession(); } /** * {@inheritdoc} */ public function registerBag(SessionBagInterface $bag) { $this->bags[$bag->getName()] = $bag; } /** * {@inheritdoc} */ public function getBag($name) { if (!isset($this->bags[$name])) { throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); } if (!$this->started) { $this->start(); } return $this->bags[$name]; } /** * {@inheritdoc} */ public function isStarted() { return $this->started; } /** * Sets the MetadataBag. * * @param MetadataBag $bag */ public function setMetadataBag(MetadataBag $bag = null) { if (null === $bag) { $bag = new MetadataBag(); } $this->metadataBag = $bag; } /** * Gets the MetadataBag. * * @return MetadataBag */ public function getMetadataBag() { return $this->metadataBag; } /** * Generates a session ID. * * This doesn't need to be particularly cryptographically secure since this is just * a mock. * * @return string */ protected function generateId() { return hash('sha256', uniqid(mt_rand())); } protected function loadSession() { $bags = array_merge($this->bags, array($this->metadataBag)); foreach ($bags as $bag) { $key = $bag->getStorageKey(); $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array(); $bag->initialize($this->data[$key]); } $this->started = true; $this->closed = false; } } PK!$  KSymfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; /** * MockFileSessionStorage is used to mock sessions for * functional testing when done in a single PHP process. * * No PHP session is actually started since a session can be initialized * and shutdown only once per PHP execution cycle and this class does * not pollute any session related globals, including session_*() functions * or session.* PHP ini directives. * * @author Drak */ class MockFileSessionStorage extends MockArraySessionStorage { /** * @var string */ private $savePath; /** * Constructor. * * @param string $savePath Path of directory to save session files. * @param string $name Session name. * @param MetadataBag $metaBag MetadataBag instance. */ public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null) { if (null === $savePath) { $savePath = sys_get_temp_dir(); } if (!is_dir($savePath)) { mkdir($savePath, 0777, true); } $this->savePath = $savePath; parent::__construct($name, $metaBag); } /** * {@inheritdoc} */ public function start() { if ($this->started) { return true; } if (!$this->id) { $this->id = $this->generateId(); } $this->read(); $this->started = true; return true; } /** * {@inheritdoc} */ public function regenerate($destroy = false, $lifetime = null) { if (!$this->started) { $this->start(); } if ($destroy) { $this->destroy(); } return parent::regenerate($destroy, $lifetime); } /** * {@inheritdoc} */ public function save() { if (!$this->started) { throw new \RuntimeException("Trying to save a session that was not started yet or was already closed"); } file_put_contents($this->getFilePath(), serialize($this->data)); // this is needed for Silex, where the session object is re-used across requests // in functional tests. In Symfony, the container is rebooted, so we don't have // this issue $this->started = false; } /** * Deletes a session from persistent storage. * Deliberately leaves session data in memory intact. */ private function destroy() { if (is_file($this->getFilePath())) { unlink($this->getFilePath()); } } /** * Calculate path to file. * * @return string File path */ private function getFilePath() { return $this->savePath.'/'.$this->id.'.mocksess'; } /** * Reads session from storage and loads session. */ private function read() { $filePath = $this->getFilePath(); $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array(); $this->loadSession(); } } PK!33QSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Adds SessionHandler functionality if available. * * @see http://php.net/sessionhandler */ if (version_compare(phpversion(), '5.4.0', '>=')) { class NativeSessionHandler extends \SessionHandler {} } else { class NativeSessionHandler {} } PK!>qOSymfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * NullSessionHandler. * * Can be used in unit testing or in a situations where persisted sessions are not desired. * * @author Drak * * @api */ class NullSessionHandler implements \SessionHandlerInterface { /** * {@inheritdoc} */ public function open($savePath, $sessionName) { return true; } /** * {@inheritdoc} */ public function close() { return true; } /** * {@inheritdoc} */ public function read($sessionId) { return ''; } /** * {@inheritdoc} */ public function write($sessionId, $data) { return true; } /** * {@inheritdoc} */ public function destroy($sessionId) { return true; } /** * {@inheritdoc} */ public function gc($lifetime) { return true; } } PK!iRSymfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * MongoDB session handler * * @author Markus Bachmann */ class MongoDbSessionHandler implements \SessionHandlerInterface { /** * @var \Mongo */ private $mongo; /** * @var \MongoCollection */ private $collection; /** * @var array */ private $options; /** * Constructor. * * List of available options: * * database: The name of the database [required] * * collection: The name of the collection [required] * * id_field: The field name for storing the session id [default: _id] * * data_field: The field name for storing the session data [default: data] * * time_field: The field name for storing the timestamp [default: time] * * @param \Mongo|\MongoClient $mongo A MongoClient or Mongo instance * @param array $options An associative array of field options * * @throws \InvalidArgumentException When MongoClient or Mongo instance not provided * @throws \InvalidArgumentException When "database" or "collection" not provided */ public function __construct($mongo, array $options) { if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo)) { throw new \InvalidArgumentException('MongoClient or Mongo instance required'); } if (!isset($options['database']) || !isset($options['collection'])) { throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler'); } $this->mongo = $mongo; $this->options = array_merge(array( 'id_field' => '_id', 'data_field' => 'data', 'time_field' => 'time', ), $options); } /** * {@inheritDoc} */ public function open($savePath, $sessionName) { return true; } /** * {@inheritDoc} */ public function close() { return true; } /** * {@inheritDoc} */ public function destroy($sessionId) { $this->getCollection()->remove(array( $this->options['id_field'] => $sessionId )); return true; } /** * {@inheritDoc} */ public function gc($lifetime) { /* Note: MongoDB 2.2+ supports TTL collections, which may be used in * place of this method by indexing the "time_field" field with an * "expireAfterSeconds" option. Regardless of whether TTL collections * are used, consider indexing this field to make the remove query more * efficient. * * See: http://docs.mongodb.org/manual/tutorial/expire-data/ */ $time = new \MongoDate(time() - $lifetime); $this->getCollection()->remove(array( $this->options['time_field'] => array('$lt' => $time), )); return true; } /** * {@inheritDoc] */ public function write($sessionId, $data) { $this->getCollection()->update( array($this->options['id_field'] => $sessionId), array('$set' => array( $this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY), $this->options['time_field'] => new \MongoDate(), )), array('upsert' => true, 'multiple' => false) ); return true; } /** * {@inheritDoc} */ public function read($sessionId) { $dbData = $this->getCollection()->findOne(array( $this->options['id_field'] => $sessionId, )); return null === $dbData ? '' : $dbData[$this->options['data_field']]->bin; } /** * Return a "MongoCollection" instance * * @return \MongoCollection */ private function getCollection() { if (null === $this->collection) { $this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']); } return $this->collection; } /** * Return a Mongo instance * * @return \Mongo */ protected function getMongo() { return $this->mongo; } } PK!OZP""NSymfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * PdoSessionHandler. * * @author Fabien Potencier * @author Michael Williams */ class PdoSessionHandler implements \SessionHandlerInterface { /** * @var \PDO PDO instance. */ private $pdo; /** * @var array Database options. */ private $dbOptions; /** * Constructor. * * List of available options: * * db_table: The name of the table [required] * * db_id_col: The column where to store the session id [default: sess_id] * * db_data_col: The column where to store the session data [default: sess_data] * * db_time_col: The column where to store the timestamp [default: sess_time] * * @param \PDO $pdo A \PDO instance * @param array $dbOptions An associative array of DB options * * @throws \InvalidArgumentException When "db_table" option is not provided */ public function __construct(\PDO $pdo, array $dbOptions = array()) { if (!array_key_exists('db_table', $dbOptions)) { throw new \InvalidArgumentException('You must provide the "db_table" option for a PdoSessionStorage.'); } if (\PDO::ERRMODE_EXCEPTION !== $pdo->getAttribute(\PDO::ATTR_ERRMODE)) { throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__)); } $this->pdo = $pdo; $this->dbOptions = array_merge(array( 'db_id_col' => 'sess_id', 'db_data_col' => 'sess_data', 'db_time_col' => 'sess_time', ), $dbOptions); } /** * {@inheritDoc} */ public function open($path, $name) { return true; } /** * {@inheritDoc} */ public function close() { return true; } /** * {@inheritDoc} */ public function destroy($id) { // get table/column $dbTable = $this->dbOptions['db_table']; $dbIdCol = $this->dbOptions['db_id_col']; // delete the record associated with this id $sql = "DELETE FROM $dbTable WHERE $dbIdCol = :id"; try { $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->execute(); } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e); } return true; } /** * {@inheritDoc} */ public function gc($lifetime) { // get table/column $dbTable = $this->dbOptions['db_table']; $dbTimeCol = $this->dbOptions['db_time_col']; // delete the session records that have expired $sql = "DELETE FROM $dbTable WHERE $dbTimeCol < :time"; try { $stmt = $this->pdo->prepare($sql); $stmt->bindValue(':time', time() - $lifetime, \PDO::PARAM_INT); $stmt->execute(); } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e); } return true; } /** * {@inheritDoc} */ public function read($id) { // get table/columns $dbTable = $this->dbOptions['db_table']; $dbDataCol = $this->dbOptions['db_data_col']; $dbIdCol = $this->dbOptions['db_id_col']; try { $sql = "SELECT $dbDataCol FROM $dbTable WHERE $dbIdCol = :id"; $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->execute(); // it is recommended to use fetchAll so that PDO can close the DB cursor // we anyway expect either no rows, or one row with one column. fetchColumn, seems to be buggy #4777 $sessionRows = $stmt->fetchAll(\PDO::FETCH_NUM); if (count($sessionRows) == 1) { return base64_decode($sessionRows[0][0]); } // session does not exist, create it $this->createNewSession($id); return ''; } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to read the session data: %s', $e->getMessage()), 0, $e); } } /** * {@inheritDoc} */ public function write($id, $data) { // get table/column $dbTable = $this->dbOptions['db_table']; $dbDataCol = $this->dbOptions['db_data_col']; $dbIdCol = $this->dbOptions['db_id_col']; $dbTimeCol = $this->dbOptions['db_time_col']; //session data can contain non binary safe characters so we need to encode it $encoded = base64_encode($data); try { $driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); if ('mysql' === $driver) { // MySQL would report $stmt->rowCount() = 0 on UPDATE when the data is left unchanged // it could result in calling createNewSession() whereas the session already exists in // the DB which would fail as the id is unique $stmt = $this->pdo->prepare( "INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time) " . "ON DUPLICATE KEY UPDATE $dbDataCol = VALUES($dbDataCol), $dbTimeCol = VALUES($dbTimeCol)" ); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->execute(); } elseif ('oci' === $driver) { $stmt = $this->pdo->prepare("MERGE INTO $dbTable USING DUAL ON($dbIdCol = :id) ". "WHEN NOT MATCHED THEN INSERT ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, sysdate) " . "WHEN MATCHED THEN UPDATE SET $dbDataCol = :data WHERE $dbIdCol = :id"); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->execute(); } else { $stmt = $this->pdo->prepare("UPDATE $dbTable SET $dbDataCol = :data, $dbTimeCol = :time WHERE $dbIdCol = :id"); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->execute(); if (!$stmt->rowCount()) { // No session exists in the database to update. This happens when we have called // session_regenerate_id() $this->createNewSession($id, $data); } } } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e); } return true; } /** * Creates a new session with the given $id and $data * * @param string $id * @param string $data * * @return boolean True. */ private function createNewSession($id, $data = '') { // get table/column $dbTable = $this->dbOptions['db_table']; $dbDataCol = $this->dbOptions['db_data_col']; $dbIdCol = $this->dbOptions['db_id_col']; $dbTimeCol = $this->dbOptions['db_time_col']; $sql = "INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time)"; //session data can contain non binary safe characters so we need to encode it $encoded = base64_encode($data); $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $id, \PDO::PARAM_STR); $stmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->execute(); return true; } /** * Return a PDO instance * * @return \PDO */ protected function getConnection() { return $this->pdo; } } PK!k4{ { TSymfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * MemcachedSessionHandler. * * Memcached based session storage handler based on the Memcached class * provided by the PHP memcached extension. * * @see http://php.net/memcached * * @author Drak */ class MemcachedSessionHandler implements \SessionHandlerInterface { /** * @var \Memcached Memcached driver. */ private $memcached; /** * @var integer Time to live in seconds */ private $ttl; /** * @var string Key prefix for shared environments. */ private $prefix; /** * Constructor. * * List of available options: * * prefix: The prefix to use for the memcached keys in order to avoid collision * * expiretime: The time to live in seconds * * @param \Memcached $memcached A \Memcached instance * @param array $options An associative array of Memcached options * * @throws \InvalidArgumentException When unsupported options are passed */ public function __construct(\Memcached $memcached, array $options = array()) { $this->memcached = $memcached; if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) { throw new \InvalidArgumentException(sprintf( 'The following options are not supported "%s"', implode(', ', $diff) )); } $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; } /** * {@inheritDoc} */ public function open($savePath, $sessionName) { return true; } /** * {@inheritDoc} */ public function close() { return true; } /** * {@inheritDoc} */ public function read($sessionId) { return $this->memcached->get($this->prefix.$sessionId) ?: ''; } /** * {@inheritDoc} */ public function write($sessionId, $data) { return $this->memcached->set($this->prefix.$sessionId, $data, time() + $this->ttl); } /** * {@inheritDoc} */ public function destroy($sessionId) { return $this->memcached->delete($this->prefix.$sessionId); } /** * {@inheritDoc} */ public function gc($lifetime) { // not required here because memcached will auto expire the records anyhow. return true; } /** * Return a Memcached instance * * @return \Memcached */ protected function getMemcached() { return $this->memcached; } } PK!uY0USymfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * NativeFileSessionHandler. * * Native session handler using PHP's built in file storage. * * @author Drak */ class NativeFileSessionHandler extends NativeSessionHandler { /** * Constructor. * * @param string $savePath Path of directory to save session files. * Default null will leave setting as defined by PHP. * '/path', 'N;/path', or 'N;octal-mode;/path * * @see http://php.net/session.configuration.php#ini.session.save-path for further details. * * @throws \InvalidArgumentException On invalid $savePath */ public function __construct($savePath = null) { if (null === $savePath) { $savePath = ini_get('session.save_path'); } $baseDir = $savePath; if ($count = substr_count($savePath, ';')) { if ($count > 2) { throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath)); } // characters after last ';' are the path $baseDir = ltrim(strrchr($savePath, ';'), ';'); } if ($baseDir && !is_dir($baseDir)) { mkdir($baseDir, 0777, true); } ini_set('session.save_path', $savePath); ini_set('session.save_handler', 'files'); } } PK!ڏ۹ SSymfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * MemcacheSessionHandler. * * @author Drak */ class MemcacheSessionHandler implements \SessionHandlerInterface { /** * @var \Memcache Memcache driver. */ private $memcache; /** * @var integer Time to live in seconds */ private $ttl; /** * @var string Key prefix for shared environments. */ private $prefix; /** * Constructor. * * List of available options: * * prefix: The prefix to use for the memcache keys in order to avoid collision * * expiretime: The time to live in seconds * * @param \Memcache $memcache A \Memcache instance * @param array $options An associative array of Memcache options * * @throws \InvalidArgumentException When unsupported options are passed */ public function __construct(\Memcache $memcache, array $options = array()) { if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) { throw new \InvalidArgumentException(sprintf( 'The following options are not supported "%s"', implode(', ', $diff) )); } $this->memcache = $memcache; $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; } /** * {@inheritDoc} */ public function open($savePath, $sessionName) { return true; } /** * {@inheritDoc} */ public function close() { return $this->memcache->close(); } /** * {@inheritDoc} */ public function read($sessionId) { return $this->memcache->get($this->prefix.$sessionId) ?: ''; } /** * {@inheritDoc} */ public function write($sessionId, $data) { return $this->memcache->set($this->prefix.$sessionId, $data, 0, time() + $this->ttl); } /** * {@inheritDoc} */ public function destroy($sessionId) { return $this->memcache->delete($this->prefix.$sessionId); } /** * {@inheritDoc} */ public function gc($lifetime) { // not required here because memcache will auto expire the records anyhow. return true; } /** * Return a Memcache instance * * @return \Memcache */ protected function getMemcache() { return $this->memcache; } } PK!USymfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Wraps another SessionHandlerInterface to only write the session when it has been modified. * * @author Adrien Brault */ class WriteCheckSessionHandler implements \SessionHandlerInterface { /** * @var \SessionHandlerInterface */ private $wrappedSessionHandler; /** * @var array sessionId => session */ private $readSessions; public function __construct(\SessionHandlerInterface $wrappedSessionHandler) { $this->wrappedSessionHandler = $wrappedSessionHandler; } /** * {@inheritdoc} */ public function close() { return $this->wrappedSessionHandler->close(); } /** * {@inheritdoc} */ public function destroy($sessionId) { return $this->wrappedSessionHandler->destroy($sessionId); } /** * {@inheritdoc} */ public function gc($maxLifetime) { return $this->wrappedSessionHandler->gc($maxLifetime); } /** * {@inheritdoc} */ public function open($savePath, $sessionId) { return $this->wrappedSessionHandler->open($savePath, $sessionId); } /** * {@inheritdoc} */ public function read($sessionId) { $session = $this->wrappedSessionHandler->read($sessionId); $this->readSessions[$sessionId] = $session; return $session; } /** * {@inheritdoc} */ public function write($sessionId, $sessionData) { if (isset($this->readSessions[$sessionId]) && $sessionData === $this->readSessions[$sessionId]) { return true; } return $this->wrappedSessionHandler->write($sessionId, $sessionData); } } PK!zu00LSymfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; /** * Allows session to be started by PHP and managed by Symfony2 * * @author Drak */ class PhpBridgeSessionStorage extends NativeSessionStorage { /** * Constructor. * * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler * @param MetadataBag $metaBag MetadataBag */ public function __construct($handler = null, MetadataBag $metaBag = null) { $this->setMetadataBag($metaBag); $this->setSaveHandler($handler); } /** * {@inheritdoc} */ public function start() { if ($this->started && !$this->closed) { return true; } $this->loadSession(); if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { // This condition matches only PHP 5.3 + internal save handlers $this->saveHandler->setActive(true); } return true; } /** * {@inheritdoc} */ public function clear() { // clear out the bags and nothing else that may be set // since the purpose of this driver is to share a handler foreach ($this->bags as $bag) { $bag->clear(); } // reconnect the bags to the session $this->loadSession(); } } PK!mwȡNSymfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** * SessionHandler proxy. * * @author Drak */ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface { /** * @var \SessionHandlerInterface */ protected $handler; /** * Constructor. * * @param \SessionHandlerInterface $handler */ public function __construct(\SessionHandlerInterface $handler) { $this->handler = $handler; $this->wrapper = ($handler instanceof \SessionHandler); $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; } // \SessionHandlerInterface /** * {@inheritdoc} */ public function open($savePath, $sessionName) { $return = (bool) $this->handler->open($savePath, $sessionName); if (true === $return) { $this->active = true; } return $return; } /** * {@inheritdoc} */ public function close() { $this->active = false; return (bool) $this->handler->close(); } /** * {@inheritdoc} */ public function read($id) { return (string) $this->handler->read($id); } /** * {@inheritdoc} */ public function write($id, $data) { return (bool) $this->handler->write($id, $data); } /** * {@inheritdoc} */ public function destroy($id) { return (bool) $this->handler->destroy($id); } /** * {@inheritdoc} */ public function gc($maxlifetime) { return (bool) $this->handler->gc($maxlifetime); } } PK!2] HSymfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** * AbstractProxy. * * @author Drak */ abstract class AbstractProxy { /** * Flag if handler wraps an internal PHP session handler (using \SessionHandler). * * @var boolean */ protected $wrapper = false; /** * @var boolean */ protected $active = false; /** * @var string */ protected $saveHandlerName; /** * Gets the session.save_handler name. * * @return string */ public function getSaveHandlerName() { return $this->saveHandlerName; } /** * Is this proxy handler and instance of \SessionHandlerInterface. * * @return boolean */ public function isSessionHandlerInterface() { return ($this instanceof \SessionHandlerInterface); } /** * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. * * @return Boolean */ public function isWrapper() { return $this->wrapper; } /** * Has a session started? * * @return Boolean */ public function isActive() { if (version_compare(phpversion(), '5.4.0', '>=')) { return $this->active = \PHP_SESSION_ACTIVE === session_status(); } return $this->active; } /** * Sets the active flag. * * Has no effect under PHP 5.4+ as status is detected * automatically in isActive() * * @internal * * @param Boolean $flag * * @throws \LogicException */ public function setActive($flag) { if (version_compare(phpversion(), '5.4.0', '>=')) { throw new \LogicException('This method is disabled in PHP 5.4.0+'); } $this->active = (bool) $flag; } /** * Gets the session ID. * * @return string */ public function getId() { return session_id(); } /** * Sets the session ID. * * @param string $id * * @throws \LogicException */ public function setId($id) { if ($this->isActive()) { throw new \LogicException('Cannot change the ID of an active session'); } session_id($id); } /** * Gets the session name. * * @return string */ public function getName() { return session_name(); } /** * Sets the session name. * * @param string $name * * @throws \LogicException */ public function setName($name) { if ($this->isActive()) { throw new \LogicException('Cannot change the name of an active session'); } session_name($name); } } PK!AFSymfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** * NativeProxy. * * This proxy is built-in session handlers in PHP 5.3.x * * @author Drak */ class NativeProxy extends AbstractProxy { /** * Constructor. */ public function __construct() { // this makes an educated guess as to what the handler is since it should already be set. $this->saveHandlerName = ini_get('session.save_handler'); } /** * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. * * @return Boolean False. */ public function isWrapper() { return false; } } PK!g_@Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * Metadata container. * * Adds metadata to the session. * * @author Drak */ class MetadataBag implements SessionBagInterface { const CREATED = 'c'; const UPDATED = 'u'; const LIFETIME = 'l'; /** * @var string */ private $name = '__metadata'; /** * @var string */ private $storageKey; /** * @var array */ protected $meta = array(self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0); /** * Unix timestamp. * * @var integer */ private $lastUsed; /** * @var integer */ private $updateThreshold; /** * Constructor. * * @param string $storageKey The key used to store bag in the session. * @param integer $updateThreshold The time to wait between two UPDATED updates */ public function __construct($storageKey = '_sf2_meta', $updateThreshold = 0) { $this->storageKey = $storageKey; $this->updateThreshold = $updateThreshold; } /** * {@inheritdoc} */ public function initialize(array &$array) { $this->meta = &$array; if (isset($array[self::CREATED])) { $this->lastUsed = $this->meta[self::UPDATED]; $timeStamp = time(); if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) { $this->meta[self::UPDATED] = $timeStamp; } } else { $this->stampCreated(); } } /** * Gets the lifetime that the session cookie was set with. * * @return integer */ public function getLifetime() { return $this->meta[self::LIFETIME]; } /** * Stamps a new session's metadata. * * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. */ public function stampNew($lifetime = null) { $this->stampCreated($lifetime); } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * Gets the created timestamp metadata. * * @return integer Unix timestamp */ public function getCreated() { return $this->meta[self::CREATED]; } /** * Gets the last used metadata. * * @return integer Unix timestamp */ public function getLastUsed() { return $this->lastUsed; } /** * {@inheritdoc} */ public function clear() { // nothing to do } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * Sets name. * * @param string $name */ public function setName($name) { $this->name = $name; } private function stampCreated($lifetime = null) { $timeStamp = time(); $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; $this->meta[self::LIFETIME] = (null === $lifetime) ? ini_get('session.cookie_lifetime') : $lifetime; } } PK!?yyLSymfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * StorageInterface. * * @author Fabien Potencier * @author Drak * * @api */ interface SessionStorageInterface { /** * Starts the session. * * @throws \RuntimeException If something goes wrong starting the session. * * @return boolean True if started. * * @api */ public function start(); /** * Checks if the session is started. * * @return boolean True if started, false otherwise. */ public function isStarted(); /** * Returns the session ID * * @return string The session ID or empty. * * @api */ public function getId(); /** * Sets the session ID * * @param string $id * * @api */ public function setId($id); /** * Returns the session name * * @return mixed The session name. * * @api */ public function getName(); /** * Sets the session name * * @param string $name * * @api */ public function setName($name); /** * Regenerates id that represents this storage. * * This method must invoke session_regenerate_id($destroy) unless * this interface is used for a storage object designed for unit * or functional testing where a real PHP session would interfere * with testing. * * Note regenerate+destroy should not clear the session data in memory * only delete the session data from persistent storage. * * @param Boolean $destroy Destroy session when regenerating? * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. * * @return Boolean True if session regenerated, false if error * * @throws \RuntimeException If an error occurs while regenerating this storage * * @api */ public function regenerate($destroy = false, $lifetime = null); /** * Force the session to be saved and closed. * * This method must invoke session_write_close() unless this interface is * used for a storage object design for unit or functional testing where * a real PHP session would interfere with testing, in which case it * it should actually persist the session data if required. * * @throws \RuntimeException If the session is saved without being started, or if the session * is already closed. */ public function save(); /** * Clear all session data in memory. */ public function clear(); /** * Gets a SessionBagInterface by name. * * @param string $name * * @return SessionBagInterface * * @throws \InvalidArgumentException If the bag does not exist */ public function getBag($name); /** * Registers a SessionBagInterface for use. * * @param SessionBagInterface $bag */ public function registerBag(SessionBagInterface $bag); /** * @return MetadataBag */ public function getMetadataBag(); } PK!K>2Symfony/Component/HttpFoundation/ApacheRequest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Request represents an HTTP request from an Apache server. * * @author Fabien Potencier */ class ApacheRequest extends Request { /** * {@inheritdoc} */ protected function prepareRequestUri() { return $this->server->get('REQUEST_URI'); } /** * {@inheritdoc} */ protected function prepareBaseUrl() { $baseUrl = $this->server->get('SCRIPT_NAME'); if (false === strpos($this->server->get('REQUEST_URI'), $baseUrl)) { // assume mod_rewrite return rtrim(dirname($baseUrl), '/\\'); } return $baseUrl; } } PK!qugdd,Symfony/Component/HttpFoundation/Request.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Request represents an HTTP request. * * The methods dealing with URL accept / return a raw path (% encoded): * * getBasePath * * getBaseUrl * * getPathInfo * * getRequestUri * * getUri * * getUriForPath * * @author Fabien Potencier * * @api */ class Request { const HEADER_CLIENT_IP = 'client_ip'; const HEADER_CLIENT_HOST = 'client_host'; const HEADER_CLIENT_PROTO = 'client_proto'; const HEADER_CLIENT_PORT = 'client_port'; protected static $trustedProxies = array(); /** * @var string[] */ protected static $trustedHostPatterns = array(); /** * @var string[] */ protected static $trustedHosts = array(); /** * Names for headers that can be trusted when * using trusted proxies. * * The default names are non-standard, but widely used * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). */ protected static $trustedHeaders = array( self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', ); protected static $httpMethodParameterOverride = false; /** * Custom parameters * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $attributes; /** * Request body parameters ($_POST) * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $request; /** * Query string parameters ($_GET) * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $query; /** * Server and execution environment parameters ($_SERVER) * * @var \Symfony\Component\HttpFoundation\ServerBag * * @api */ public $server; /** * Uploaded files ($_FILES) * * @var \Symfony\Component\HttpFoundation\FileBag * * @api */ public $files; /** * Cookies ($_COOKIE) * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $cookies; /** * Headers (taken from the $_SERVER) * * @var \Symfony\Component\HttpFoundation\HeaderBag * * @api */ public $headers; /** * @var string */ protected $content; /** * @var array */ protected $languages; /** * @var array */ protected $charsets; /** * @var array */ protected $encodings; /** * @var array */ protected $acceptableContentTypes; /** * @var string */ protected $pathInfo; /** * @var string */ protected $requestUri; /** * @var string */ protected $baseUrl; /** * @var string */ protected $basePath; /** * @var string */ protected $method; /** * @var string */ protected $format; /** * @var \Symfony\Component\HttpFoundation\Session\SessionInterface */ protected $session; /** * @var string */ protected $locale; /** * @var string */ protected $defaultLocale = 'en'; /** * @var array */ protected static $formats; protected static $requestFactory; /** * Constructor. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * @param string $content The raw body data * * @api */ public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); } /** * Sets the parameters for this request. * * This method also re-initializes all properties. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * @param string $content The raw body data * * @api */ public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { $this->request = new ParameterBag($request); $this->query = new ParameterBag($query); $this->attributes = new ParameterBag($attributes); $this->cookies = new ParameterBag($cookies); $this->files = new FileBag($files); $this->server = new ServerBag($server); $this->headers = new HeaderBag($this->server->getHeaders()); $this->content = $content; $this->languages = null; $this->charsets = null; $this->encodings = null; $this->acceptableContentTypes = null; $this->pathInfo = null; $this->requestUri = null; $this->baseUrl = null; $this->basePath = null; $this->method = null; $this->format = null; } /** * Creates a new request with values from PHP's super globals. * * @return Request A new request * * @api */ public static function createFromGlobals() { $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER); if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH')) ) { parse_str($request->getContent(), $data); $request->request = new ParameterBag($data); } return $request; } /** * Creates a Request based on a given URI and configuration. * * The information contained in the URI always take precedence * over the other information (server and parameters). * * @param string $uri The URI * @param string $method The HTTP method * @param array $parameters The query (GET) or request (POST) parameters * @param array $cookies The request cookies ($_COOKIE) * @param array $files The request files ($_FILES) * @param array $server The server parameters ($_SERVER) * @param string $content The raw body data * * @return Request A Request instance * * @api */ public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null) { $server = array_replace(array( 'SERVER_NAME' => 'localhost', 'SERVER_PORT' => 80, 'HTTP_HOST' => 'localhost', 'HTTP_USER_AGENT' => 'Symfony/2.X', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'REMOTE_ADDR' => '127.0.0.1', 'SCRIPT_NAME' => '', 'SCRIPT_FILENAME' => '', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_TIME' => time(), ), $server); $server['PATH_INFO'] = ''; $server['REQUEST_METHOD'] = strtoupper($method); $components = parse_url($uri); if (isset($components['host'])) { $server['SERVER_NAME'] = $components['host']; $server['HTTP_HOST'] = $components['host']; } if (isset($components['scheme'])) { if ('https' === $components['scheme']) { $server['HTTPS'] = 'on'; $server['SERVER_PORT'] = 443; } else { unset($server['HTTPS']); $server['SERVER_PORT'] = 80; } } if (isset($components['port'])) { $server['SERVER_PORT'] = $components['port']; $server['HTTP_HOST'] = $server['HTTP_HOST'].':'.$components['port']; } if (isset($components['user'])) { $server['PHP_AUTH_USER'] = $components['user']; } if (isset($components['pass'])) { $server['PHP_AUTH_PW'] = $components['pass']; } if (!isset($components['path'])) { $components['path'] = '/'; } switch (strtoupper($method)) { case 'POST': case 'PUT': case 'DELETE': if (!isset($server['CONTENT_TYPE'])) { $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; } case 'PATCH': $request = $parameters; $query = array(); break; default: $request = array(); $query = $parameters; break; } $queryString = ''; if (isset($components['query'])) { parse_str(html_entity_decode($components['query']), $qs); if ($query) { $query = array_replace($qs, $query); $queryString = http_build_query($query, '', '&'); } else { $query = $qs; $queryString = $components['query']; } } elseif ($query) { $queryString = http_build_query($query, '', '&'); } $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); $server['QUERY_STRING'] = $queryString; return self::createRequestFromFactory($query, $request, array(), $cookies, $files, $server, $content); } /** * Sets a callable able to create a Request instance. * * This is mainly useful when you need to override the Request class * to keep BC with an existing system. It should not be used for any * other purpose. * * @param callable|null $callable A PHP callable */ public static function setFactory($callable) { self::$requestFactory = $callable; } /** * Clones a request and overrides some of its parameters. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * * @return Request The duplicated request * * @api */ public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) { $dup = clone $this; if ($query !== null) { $dup->query = new ParameterBag($query); } if ($request !== null) { $dup->request = new ParameterBag($request); } if ($attributes !== null) { $dup->attributes = new ParameterBag($attributes); } if ($cookies !== null) { $dup->cookies = new ParameterBag($cookies); } if ($files !== null) { $dup->files = new FileBag($files); } if ($server !== null) { $dup->server = new ServerBag($server); $dup->headers = new HeaderBag($dup->server->getHeaders()); } $dup->languages = null; $dup->charsets = null; $dup->encodings = null; $dup->acceptableContentTypes = null; $dup->pathInfo = null; $dup->requestUri = null; $dup->baseUrl = null; $dup->basePath = null; $dup->method = null; $dup->format = null; if (!$dup->get('_format') && $this->get('_format')) { $dup->attributes->set('_format', $this->get('_format')); } if (!$dup->getRequestFormat(null)) { $dup->setRequestFormat($format = $this->getRequestFormat(null)); } return $dup; } /** * Clones the current request. * * Note that the session is not cloned as duplicated requests * are most of the time sub-requests of the main one. */ public function __clone() { $this->query = clone $this->query; $this->request = clone $this->request; $this->attributes = clone $this->attributes; $this->cookies = clone $this->cookies; $this->files = clone $this->files; $this->server = clone $this->server; $this->headers = clone $this->headers; } /** * Returns the request as a string. * * @return string The request */ public function __toString() { return sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". $this->headers."\r\n". $this->getContent(); } /** * Overrides the PHP global variables according to this request instance. * * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. * $_FILES is never override, see rfc1867 * * @api */ public function overrideGlobals() { $_GET = $this->query->all(); $_POST = $this->request->all(); $_SERVER = $this->server->all(); $_COOKIE = $this->cookies->all(); foreach ($this->headers->all() as $key => $value) { $key = strtoupper(str_replace('-', '_', $key)); if (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) { $_SERVER[$key] = implode(', ', $value); } else { $_SERVER['HTTP_'.$key] = implode(', ', $value); } } $request = array('g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE); $requestOrder = ini_get('request_order') ?: ini_get('variables_order'); $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; $_REQUEST = array(); foreach (str_split($requestOrder) as $order) { $_REQUEST = array_merge($_REQUEST, $request[$order]); } } /** * Sets a list of trusted proxies. * * You should only list the reverse proxies that you manage directly. * * @param array $proxies A list of trusted proxies * * @api */ public static function setTrustedProxies(array $proxies) { self::$trustedProxies = $proxies; } /** * Gets the list of trusted proxies. * * @return array An array of trusted proxies. */ public static function getTrustedProxies() { return self::$trustedProxies; } /** * Sets a list of trusted host patterns. * * You should only list the hosts you manage using regexs. * * @param array $hostPatterns A list of trusted host patterns */ public static function setTrustedHosts(array $hostPatterns) { self::$trustedHostPatterns = array_map(function ($hostPattern) { return sprintf('{%s}i', str_replace('}', '\\}', $hostPattern)); }, $hostPatterns); // we need to reset trusted hosts on trusted host patterns change self::$trustedHosts = array(); } /** * Gets the list of trusted host patterns. * * @return array An array of trusted host patterns. */ public static function getTrustedHosts() { return self::$trustedHostPatterns; } /** * Sets the name for trusted headers. * * The following header keys are supported: * * * Request::HEADER_CLIENT_IP: defaults to X-Forwarded-For (see getClientIp()) * * Request::HEADER_CLIENT_HOST: defaults to X-Forwarded-Host (see getClientHost()) * * Request::HEADER_CLIENT_PORT: defaults to X-Forwarded-Port (see getClientPort()) * * Request::HEADER_CLIENT_PROTO: defaults to X-Forwarded-Proto (see getScheme() and isSecure()) * * Setting an empty value allows to disable the trusted header for the given key. * * @param string $key The header key * @param string $value The header name * * @throws \InvalidArgumentException */ public static function setTrustedHeaderName($key, $value) { if (!array_key_exists($key, self::$trustedHeaders)) { throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); } self::$trustedHeaders[$key] = $value; } /** * Gets the trusted proxy header name. * * @param string $key The header key * * @return string The header name * * @throws \InvalidArgumentException */ public static function getTrustedHeaderName($key) { if (!array_key_exists($key, self::$trustedHeaders)) { throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key)); } return self::$trustedHeaders[$key]; } /** * Normalizes a query string. * * It builds a normalized query string, where keys/value pairs are alphabetized, * have consistent escaping and unneeded delimiters are removed. * * @param string $qs Query string * * @return string A normalized query string for the Request */ public static function normalizeQueryString($qs) { if ('' == $qs) { return ''; } $parts = array(); $order = array(); foreach (explode('&', $qs) as $param) { if ('' === $param || '=' === $param[0]) { // Ignore useless delimiters, e.g. "x=y&". // Also ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway. // PHP also does not include them when building _GET. continue; } $keyValuePair = explode('=', $param, 2); // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded). // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str. This is why we use urldecode and then normalize to // RFC 3986 with rawurlencode. $parts[] = isset($keyValuePair[1]) ? rawurlencode(urldecode($keyValuePair[0])).'='.rawurlencode(urldecode($keyValuePair[1])) : rawurlencode(urldecode($keyValuePair[0])); $order[] = urldecode($keyValuePair[0]); } array_multisort($order, SORT_ASC, $parts); return implode('&', $parts); } /** * Enables support for the _method request parameter to determine the intended HTTP method. * * Be warned that enabling this feature might lead to CSRF issues in your code. * Check that you are using CSRF tokens when required. * * The HTTP method can only be overridden when the real HTTP method is POST. */ public static function enableHttpMethodParameterOverride() { self::$httpMethodParameterOverride = true; } /** * Checks whether support for the _method request parameter is enabled. * * @return Boolean True when the _method request parameter is enabled, false otherwise */ public static function getHttpMethodParameterOverride() { return self::$httpMethodParameterOverride; } /** * Gets a "parameter" value. * * This method is mainly useful for libraries that want to provide some flexibility. * * Order of precedence: GET, PATH, POST * * Avoid using this method in controllers: * * * slow * * prefer to get from a "named" source * * It is better to explicitly get request parameters from the appropriate * public property instead (query, attributes, request). * * @param string $key the key * @param mixed $default the default value * @param Boolean $deep is parameter deep in multidimensional array * * @return mixed */ public function get($key, $default = null, $deep = false) { return $this->query->get($key, $this->attributes->get($key, $this->request->get($key, $default, $deep), $deep), $deep); } /** * Gets the Session. * * @return SessionInterface|null The session * * @api */ public function getSession() { return $this->session; } /** * Whether the request contains a Session which was started in one of the * previous requests. * * @return Boolean * * @api */ public function hasPreviousSession() { // the check for $this->session avoids malicious users trying to fake a session cookie with proper name return $this->hasSession() && $this->cookies->has($this->session->getName()); } /** * Whether the request contains a Session object. * * This method does not give any information about the state of the session object, * like whether the session is started or not. It is just a way to check if this Request * is associated with a Session instance. * * @return Boolean true when the Request contains a Session object, false otherwise * * @api */ public function hasSession() { return null !== $this->session; } /** * Sets the Session. * * @param SessionInterface $session The Session * * @api */ public function setSession(SessionInterface $session) { $this->session = $session; } /** * Returns the client IP addresses. * * In the returned array the most trusted IP address is first, and the * least trusted one last. The "real" client IP address is the last one, * but this is also the least trusted one. Trusted proxies are stripped. * * Use this method carefully; you should use getClientIp() instead. * * @return array The client IP addresses * * @see getClientIp() */ public function getClientIps() { $ip = $this->server->get('REMOTE_ADDR'); if (!self::$trustedProxies) { return array($ip); } if (!self::$trustedHeaders[self::HEADER_CLIENT_IP] || !$this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) { return array($ip); } $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP]))); $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from $ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies // Eliminate all IPs from the forwarded IP chain which are trusted proxies foreach ($clientIps as $key => $clientIp) { if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { unset($clientIps[$key]); } } // Now the IP chain contains only untrusted proxies and the client IP return $clientIps ? array_reverse($clientIps) : array($ip); } /** * Returns the client IP address. * * This method can read the client IP address from the "X-Forwarded-For" header * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For" * header value is a comma+space separated list of IP addresses, the left-most * being the original client, and each successive proxy that passed the request * adding the IP address where it received the request from. * * If your reverse proxy uses a different header name than "X-Forwarded-For", * ("Client-Ip" for instance), configure it via "setTrustedHeaderName()" with * the "client-ip" key. * * @return string The client IP address * * @see getClientIps() * @see http://en.wikipedia.org/wiki/X-Forwarded-For * * @api */ public function getClientIp() { $ipAddresses = $this->getClientIps(); return $ipAddresses[0]; } /** * Returns current script name. * * @return string * * @api */ public function getScriptName() { return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', '')); } /** * Returns the path being requested relative to the executed script. * * The path info always starts with a /. * * Suppose this request is instantiated from /mysite on localhost: * * * http://localhost/mysite returns an empty string * * http://localhost/mysite/about returns '/about' * * http://localhost/mysite/enco%20ded returns '/enco%20ded' * * http://localhost/mysite/about?var=1 returns '/about' * * @return string The raw path (i.e. not urldecoded) * * @api */ public function getPathInfo() { if (null === $this->pathInfo) { $this->pathInfo = $this->preparePathInfo(); } return $this->pathInfo; } /** * Returns the root path from which this request is executed. * * Suppose that an index.php file instantiates this request object: * * * http://localhost/index.php returns an empty string * * http://localhost/index.php/page returns an empty string * * http://localhost/web/index.php returns '/web' * * http://localhost/we%20b/index.php returns '/we%20b' * * @return string The raw path (i.e. not urldecoded) * * @api */ public function getBasePath() { if (null === $this->basePath) { $this->basePath = $this->prepareBasePath(); } return $this->basePath; } /** * Returns the root URL from which this request is executed. * * The base URL never ends with a /. * * This is similar to getBasePath(), except that it also includes the * script filename (e.g. index.php) if one exists. * * @return string The raw URL (i.e. not urldecoded) * * @api */ public function getBaseUrl() { if (null === $this->baseUrl) { $this->baseUrl = $this->prepareBaseUrl(); } return $this->baseUrl; } /** * Gets the request's scheme. * * @return string * * @api */ public function getScheme() { return $this->isSecure() ? 'https' : 'http'; } /** * Returns the port on which the request is made. * * This method can read the client port from the "X-Forwarded-Port" header * when trusted proxies were set via "setTrustedProxies()". * * The "X-Forwarded-Port" header must contain the client port. * * If your reverse proxy uses a different header name than "X-Forwarded-Port", * configure it via "setTrustedHeaderName()" with the "client-port" key. * * @return string * * @api */ public function getPort() { if (self::$trustedProxies) { if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) { return $port; } if (self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && 'https' === $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO], 'http')) { return 443; } } if ($host = $this->headers->get('HOST')) { if (false !== $pos = strrpos($host, ':')) { return intval(substr($host, $pos + 1)); } return 'https' === $this->getScheme() ? 443 : 80; } return $this->server->get('SERVER_PORT'); } /** * Returns the user. * * @return string|null */ public function getUser() { return $this->server->get('PHP_AUTH_USER'); } /** * Returns the password. * * @return string|null */ public function getPassword() { return $this->server->get('PHP_AUTH_PW'); } /** * Gets the user info. * * @return string A user name and, optionally, scheme-specific information about how to gain authorization to access the server */ public function getUserInfo() { $userinfo = $this->getUser(); $pass = $this->getPassword(); if ('' != $pass) { $userinfo .= ":$pass"; } return $userinfo; } /** * Returns the HTTP host being requested. * * The port name will be appended to the host if it's non-standard. * * @return string * * @api */ public function getHttpHost() { $scheme = $this->getScheme(); $port = $this->getPort(); if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) { return $this->getHost(); } return $this->getHost().':'.$port; } /** * Returns the requested URI. * * @return string The raw URI (i.e. not urldecoded) * * @api */ public function getRequestUri() { if (null === $this->requestUri) { $this->requestUri = $this->prepareRequestUri(); } return $this->requestUri; } /** * Gets the scheme and HTTP host. * * If the URL was called with basic authentication, the user * and the password are not added to the generated string. * * @return string The scheme and HTTP host */ public function getSchemeAndHttpHost() { return $this->getScheme().'://'.$this->getHttpHost(); } /** * Generates a normalized URI for the Request. * * @return string A normalized URI for the Request * * @see getQueryString() * * @api */ public function getUri() { if (null !== $qs = $this->getQueryString()) { $qs = '?'.$qs; } return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs; } /** * Generates a normalized URI for the given path. * * @param string $path A path to use instead of the current one * * @return string The normalized URI for the path * * @api */ public function getUriForPath($path) { return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path; } /** * Generates the normalized query string for the Request. * * It builds a normalized query string, where keys/value pairs are alphabetized * and have consistent escaping. * * @return string|null A normalized query string for the Request * * @api */ public function getQueryString() { $qs = static::normalizeQueryString($this->server->get('QUERY_STRING')); return '' === $qs ? null : $qs; } /** * Checks whether the request is secure or not. * * This method can read the client port from the "X-Forwarded-Proto" header * when trusted proxies were set via "setTrustedProxies()". * * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". * * If your reverse proxy uses a different header name than "X-Forwarded-Proto" * ("SSL_HTTPS" for instance), configure it via "setTrustedHeaderName()" with * the "client-proto" key. * * @return Boolean * * @api */ public function isSecure() { if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) { return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1')); } return 'on' == strtolower($this->server->get('HTTPS')) || 1 == $this->server->get('HTTPS'); } /** * Returns the host name. * * This method can read the client port from the "X-Forwarded-Host" header * when trusted proxies were set via "setTrustedProxies()". * * The "X-Forwarded-Host" header must contain the client host name. * * If your reverse proxy uses a different header name than "X-Forwarded-Host", * configure it via "setTrustedHeaderName()" with the "client-host" key. * * @return string * * @throws \UnexpectedValueException when the host name is invalid * * @api */ public function getHost() { if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) { $elements = explode(',', $host); $host = $elements[count($elements) - 1]; } elseif (!$host = $this->headers->get('HOST')) { if (!$host = $this->server->get('SERVER_NAME')) { $host = $this->server->get('SERVER_ADDR', ''); } } // trim and remove port number from host // host is lowercase as per RFC 952/2181 $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) if ($host && !preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host)) { throw new \UnexpectedValueException(sprintf('Invalid Host "%s"', $host)); } if (count(self::$trustedHostPatterns) > 0) { // to avoid host header injection attacks, you should provide a list of trusted host patterns if (in_array($host, self::$trustedHosts)) { return $host; } foreach (self::$trustedHostPatterns as $pattern) { if (preg_match($pattern, $host)) { self::$trustedHosts[] = $host; return $host; } } throw new \UnexpectedValueException(sprintf('Untrusted Host "%s"', $host)); } return $host; } /** * Sets the request method. * * @param string $method * * @api */ public function setMethod($method) { $this->method = null; $this->server->set('REQUEST_METHOD', $method); } /** * Gets the request "intended" method. * * If the X-HTTP-Method-Override header is set, and if the method is a POST, * then it is used to determine the "real" intended HTTP method. * * The _method request parameter can also be used to determine the HTTP method, * but only if enableHttpMethodParameterOverride() has been called. * * The method is always an uppercased string. * * @return string The request method * * @api * * @see getRealMethod */ public function getMethod() { if (null === $this->method) { $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); if ('POST' === $this->method) { if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) { $this->method = strtoupper($method); } elseif (self::$httpMethodParameterOverride) { $this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST'))); } } } return $this->method; } /** * Gets the "real" request method. * * @return string The request method * * @see getMethod */ public function getRealMethod() { return strtoupper($this->server->get('REQUEST_METHOD', 'GET')); } /** * Gets the mime type associated with the format. * * @param string $format The format * * @return string The associated mime type (null if not found) * * @api */ public function getMimeType($format) { if (null === static::$formats) { static::initializeFormats(); } return isset(static::$formats[$format]) ? static::$formats[$format][0] : null; } /** * Gets the format associated with the mime type. * * @param string $mimeType The associated mime type * * @return string|null The format (null if not found) * * @api */ public function getFormat($mimeType) { if (false !== $pos = strpos($mimeType, ';')) { $mimeType = substr($mimeType, 0, $pos); } if (null === static::$formats) { static::initializeFormats(); } foreach (static::$formats as $format => $mimeTypes) { if (in_array($mimeType, (array) $mimeTypes)) { return $format; } } return null; } /** * Associates a format with mime types. * * @param string $format The format * @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type) * * @api */ public function setFormat($format, $mimeTypes) { if (null === static::$formats) { static::initializeFormats(); } static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes); } /** * Gets the request format. * * Here is the process to determine the format: * * * format defined by the user (with setRequestFormat()) * * _format request parameter * * $default * * @param string $default The default format * * @return string The request format * * @api */ public function getRequestFormat($default = 'html') { if (null === $this->format) { $this->format = $this->get('_format', $default); } return $this->format; } /** * Sets the request format. * * @param string $format The request format. * * @api */ public function setRequestFormat($format) { $this->format = $format; } /** * Gets the format associated with the request. * * @return string|null The format (null if no content type is present) * * @api */ public function getContentType() { return $this->getFormat($this->headers->get('CONTENT_TYPE')); } /** * Sets the default locale. * * @param string $locale * * @api */ public function setDefaultLocale($locale) { $this->defaultLocale = $locale; if (null === $this->locale) { $this->setPhpDefaultLocale($locale); } } /** * Sets the locale. * * @param string $locale * * @api */ public function setLocale($locale) { $this->setPhpDefaultLocale($this->locale = $locale); } /** * Get the locale. * * @return string */ public function getLocale() { return null === $this->locale ? $this->defaultLocale : $this->locale; } /** * Checks if the request method is of specified type. * * @param string $method Uppercase request method (GET, POST etc). * * @return Boolean */ public function isMethod($method) { return $this->getMethod() === strtoupper($method); } /** * Checks whether the method is safe or not. * * @return Boolean * * @api */ public function isMethodSafe() { return in_array($this->getMethod(), array('GET', 'HEAD')); } /** * Returns the request body content. * * @param Boolean $asResource If true, a resource will be returned * * @return string|resource The request body content or a resource to read the body stream. * * @throws \LogicException */ public function getContent($asResource = false) { if (false === $this->content || (true === $asResource && null !== $this->content)) { throw new \LogicException('getContent() can only be called once when using the resource return type.'); } if (true === $asResource) { $this->content = false; return fopen('php://input', 'rb'); } if (null === $this->content) { $this->content = file_get_contents('php://input'); } return $this->content; } /** * Gets the Etags. * * @return array The entity tags */ public function getETags() { return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY); } /** * @return Boolean */ public function isNoCache() { return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); } /** * Returns the preferred language. * * @param array $locales An array of ordered available locales * * @return string|null The preferred locale * * @api */ public function getPreferredLanguage(array $locales = null) { $preferredLanguages = $this->getLanguages(); if (empty($locales)) { return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null; } if (!$preferredLanguages) { return $locales[0]; } $extendedPreferredLanguages = array(); foreach ($preferredLanguages as $language) { $extendedPreferredLanguages[] = $language; if (false !== $position = strpos($language, '_')) { $superLanguage = substr($language, 0, $position); if (!in_array($superLanguage, $preferredLanguages)) { $extendedPreferredLanguages[] = $superLanguage; } } } $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales)); return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0]; } /** * Gets a list of languages acceptable by the client browser. * * @return array Languages ordered in the user browser preferences * * @api */ public function getLanguages() { if (null !== $this->languages) { return $this->languages; } $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); $this->languages = array(); foreach (array_keys($languages) as $lang) { if (strstr($lang, '-')) { $codes = explode('-', $lang); if ($codes[0] == 'i') { // Language not listed in ISO 639 that are not variants // of any listed language, which can be registered with the // i-prefix, such as i-cherokee if (count($codes) > 1) { $lang = $codes[1]; } } else { for ($i = 0, $max = count($codes); $i < $max; $i++) { if ($i == 0) { $lang = strtolower($codes[0]); } else { $lang .= '_'.strtoupper($codes[$i]); } } } } $this->languages[] = $lang; } return $this->languages; } /** * Gets a list of charsets acceptable by the client browser. * * @return array List of charsets in preferable order * * @api */ public function getCharsets() { if (null !== $this->charsets) { return $this->charsets; } return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all()); } /** * Gets a list of encodings acceptable by the client browser. * * @return array List of encodings in preferable order */ public function getEncodings() { if (null !== $this->encodings) { return $this->encodings; } return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all()); } /** * Gets a list of content types acceptable by the client browser * * @return array List of content types in preferable order * * @api */ public function getAcceptableContentTypes() { if (null !== $this->acceptableContentTypes) { return $this->acceptableContentTypes; } return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all()); } /** * Returns true if the request is a XMLHttpRequest. * * It works if your JavaScript library set an X-Requested-With HTTP header. * It is known to work with common JavaScript frameworks: * @link http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript * * @return Boolean true if the request is an XMLHttpRequest, false otherwise * * @api */ public function isXmlHttpRequest() { return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); } /* * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) * * Code 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) */ protected function prepareRequestUri() { $requestUri = ''; if ($this->headers->has('X_ORIGINAL_URL')) { // IIS with Microsoft Rewrite Module $requestUri = $this->headers->get('X_ORIGINAL_URL'); $this->headers->remove('X_ORIGINAL_URL'); $this->server->remove('HTTP_X_ORIGINAL_URL'); $this->server->remove('UNENCODED_URL'); $this->server->remove('IIS_WasUrlRewritten'); } elseif ($this->headers->has('X_REWRITE_URL')) { // IIS with ISAPI_Rewrite $requestUri = $this->headers->get('X_REWRITE_URL'); $this->headers->remove('X_REWRITE_URL'); } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') { // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) $requestUri = $this->server->get('UNENCODED_URL'); $this->server->remove('UNENCODED_URL'); $this->server->remove('IIS_WasUrlRewritten'); } elseif ($this->server->has('REQUEST_URI')) { $requestUri = $this->server->get('REQUEST_URI'); // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path $schemeAndHttpHost = $this->getSchemeAndHttpHost(); if (strpos($requestUri, $schemeAndHttpHost) === 0) { $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); } } elseif ($this->server->has('ORIG_PATH_INFO')) { // IIS 5.0, PHP as CGI $requestUri = $this->server->get('ORIG_PATH_INFO'); if ('' != $this->server->get('QUERY_STRING')) { $requestUri .= '?'.$this->server->get('QUERY_STRING'); } $this->server->remove('ORIG_PATH_INFO'); } // normalize the request URI to ease creating sub-requests from this request $this->server->set('REQUEST_URI', $requestUri); return $requestUri; } /** * Prepares the base URL. * * @return string */ protected function prepareBaseUrl() { $filename = basename($this->server->get('SCRIPT_FILENAME')); if (basename($this->server->get('SCRIPT_NAME')) === $filename) { $baseUrl = $this->server->get('SCRIPT_NAME'); } elseif (basename($this->server->get('PHP_SELF')) === $filename) { $baseUrl = $this->server->get('PHP_SELF'); } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) { $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility } else { // Backtrack up the script_filename to find the portion matching // php_self $path = $this->server->get('PHP_SELF', ''); $file = $this->server->get('SCRIPT_FILENAME', ''); $segs = explode('/', trim($file, '/')); $segs = array_reverse($segs); $index = 0; $last = count($segs); $baseUrl = ''; do { $seg = $segs[$index]; $baseUrl = '/'.$seg.$baseUrl; ++$index; } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); } // Does the baseUrl have anything in common with the request_uri? $requestUri = $this->getRequestUri(); if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { // full $baseUrl matches return $prefix; } if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl))) { // directory portion of $baseUrl matches return rtrim($prefix, '/'); } $truncatedRequestUri = $requestUri; if (false !== $pos = strpos($requestUri, '?')) { $truncatedRequestUri = substr($requestUri, 0, $pos); } $basename = basename($baseUrl); if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { // no match whatsoever; set it blank return ''; } // If using mod_rewrite or ISAPI_Rewrite strip the script filename // out of baseUrl. $pos !== 0 makes sure it is not matching a value // from PATH_INFO or QUERY_STRING if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && $pos !== 0) { $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); } return rtrim($baseUrl, '/'); } /** * Prepares the base path. * * @return string base path */ protected function prepareBasePath() { $filename = basename($this->server->get('SCRIPT_FILENAME')); $baseUrl = $this->getBaseUrl(); if (empty($baseUrl)) { return ''; } if (basename($baseUrl) === $filename) { $basePath = dirname($baseUrl); } else { $basePath = $baseUrl; } if ('\\' === DIRECTORY_SEPARATOR) { $basePath = str_replace('\\', '/', $basePath); } return rtrim($basePath, '/'); } /** * Prepares the path info. * * @return string path info */ protected function preparePathInfo() { $baseUrl = $this->getBaseUrl(); if (null === ($requestUri = $this->getRequestUri())) { return '/'; } $pathInfo = '/'; // Remove the query string from REQUEST_URI if ($pos = strpos($requestUri, '?')) { $requestUri = substr($requestUri, 0, $pos); } if (null !== $baseUrl && false === $pathInfo = substr($requestUri, strlen($baseUrl))) { // If substr() returns false then PATH_INFO is set to an empty string return '/'; } elseif (null === $baseUrl) { return $requestUri; } return (string) $pathInfo; } /** * Initializes HTTP request formats. */ protected static function initializeFormats() { static::$formats = array( 'html' => array('text/html', 'application/xhtml+xml'), 'txt' => array('text/plain'), 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), 'css' => array('text/css'), 'json' => array('application/json', 'application/x-json'), 'xml' => array('text/xml', 'application/xml', 'application/x-xml'), 'rdf' => array('application/rdf+xml'), 'atom' => array('application/atom+xml'), 'rss' => array('application/rss+xml'), ); } /** * Sets the default PHP locale. * * @param string $locale */ private function setPhpDefaultLocale($locale) { // if either the class Locale doesn't exist, or an exception is thrown when // setting the default locale, the intl module is not installed, and // the call can be ignored: try { if (class_exists('Locale', false)) { \Locale::setDefault($locale); } } catch (\Exception $e) { } } /* * Returns the prefix as encoded in the string when the string starts with * the given prefix, false otherwise. * * @param string $string The urlencoded string * @param string $prefix The prefix not encoded * * @return string|false The prefix as it is encoded in $string, or false */ private function getUrlencodedPrefix($string, $prefix) { if (0 !== strpos(rawurldecode($string), $prefix)) { return false; } $len = strlen($prefix); if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) { return $match[0]; } return false; } private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { if (self::$requestFactory) { $request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content); if (!$request instanceof Request) { throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.'); } return $request; } return new static($query, $request, $attributes, $cookies, $files, $server, $content); } } PK!d}޷%%7Symfony/Component/HttpFoundation/BinaryFileResponse.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; /** * BinaryFileResponse represents an HTTP response delivering a file. * * @author Niklas Fiekas * @author stealth35 * @author Igor Wiedler * @author Jordan Alliot * @author Sergey Linnik */ class BinaryFileResponse extends Response { protected static $trustXSendfileTypeHeader = false; protected $file; protected $offset; protected $maxlen; /** * Constructor. * * @param \SplFileInfo|string $file The file to stream * @param integer $status The response status code * @param array $headers An array of response headers * @param boolean $public Files are public by default * @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename * @param boolean $autoEtag Whether the ETag header should be automatically set * @param boolean $autoLastModified Whether the Last-Modified header should be automatically set */ public function __construct($file, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) { parent::__construct(null, $status, $headers); $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified); if ($public) { $this->setPublic(); } } /** * @param \SplFileInfo|string $file The file to stream * @param integer $status The response status code * @param array $headers An array of response headers * @param boolean $public Files are public by default * @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename * @param boolean $autoEtag Whether the ETag header should be automatically set * @param boolean $autoLastModified Whether the Last-Modified header should be automatically set */ public static function create($file = null, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) { return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); } /** * Sets the file to stream. * * @param \SplFileInfo|string $file The file to stream * @param string $contentDisposition * @param Boolean $autoEtag * @param Boolean $autoLastModified * * @return BinaryFileResponse * * @throws FileException */ public function setFile($file, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) { $file = new File((string) $file); if (!$file->isReadable()) { throw new FileException('File must be readable.'); } $this->file = $file; if ($autoEtag) { $this->setAutoEtag(); } if ($autoLastModified) { $this->setAutoLastModified(); } if ($contentDisposition) { $this->setContentDisposition($contentDisposition); } return $this; } /** * Gets the file. * * @return File The file to stream */ public function getFile() { return $this->file; } /** * Automatically sets the Last-Modified header according the file modification date. */ public function setAutoLastModified() { $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime())); return $this; } /** * Automatically sets the ETag header according to the checksum of the file. */ public function setAutoEtag() { $this->setEtag(sha1_file($this->file->getPathname())); return $this; } /** * Sets the Content-Disposition header with the given filename. * * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT * @param string $filename Optionally use this filename instead of the real name of the file * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename * * @return BinaryFileResponse */ public function setContentDisposition($disposition, $filename = '', $filenameFallback = '') { if ($filename === '') { $filename = $this->file->getFilename(); } $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback); $this->headers->set('Content-Disposition', $dispositionHeader); return $this; } /** * {@inheritdoc} */ public function prepare(Request $request) { $this->headers->set('Content-Length', $this->file->getSize()); $this->headers->set('Accept-Ranges', 'bytes'); $this->headers->set('Content-Transfer-Encoding', 'binary'); if (!$this->headers->has('Content-Type')) { $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); } if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { $this->setProtocolVersion('1.1'); } $this->ensureIEOverSSLCompatibility($request); $this->offset = 0; $this->maxlen = -1; if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) { // Use X-Sendfile, do not send any content. $type = $request->headers->get('X-Sendfile-Type'); $path = $this->file->getRealPath(); if (strtolower($type) == 'x-accel-redirect') { // Do X-Accel-Mapping substitutions. foreach (explode(',', $request->headers->get('X-Accel-Mapping', '')) as $mapping) { $mapping = explode('=', $mapping, 2); if (2 == count($mapping)) { $location = trim($mapping[0]); $pathPrefix = trim($mapping[1]); if (substr($path, 0, strlen($pathPrefix)) == $pathPrefix) { $path = $location.substr($path, strlen($pathPrefix)); break; } } } } $this->headers->set($type, $path); $this->maxlen = 0; } elseif ($request->headers->has('Range')) { // Process the range headers. if (!$request->headers->has('If-Range') || $this->getEtag() == $request->headers->get('If-Range')) { $range = $request->headers->get('Range'); $fileSize = $this->file->getSize(); list($start, $end) = explode('-', substr($range, 6), 2) + array(0); $end = ('' === $end) ? $fileSize - 1 : (int) $end; if ('' === $start) { $start = $fileSize - $end; $end = $fileSize - 1; } else { $start = (int) $start; } if ($start <= $end) { if ($start < 0 || $end > $fileSize - 1) { $this->setStatusCode(416); } elseif ($start !== 0 || $end !== $fileSize - 1) { $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; $this->offset = $start; $this->setStatusCode(206); $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize)); $this->headers->set('Content-Length', $end - $start + 1); } } } } return $this; } /** * Sends the file. */ public function sendContent() { if (!$this->isSuccessful()) { parent::sendContent(); return; } if (0 === $this->maxlen) { return; } $out = fopen('php://output', 'wb'); $file = fopen($this->file->getPathname(), 'rb'); stream_copy_to_stream($file, $out, $this->maxlen, $this->offset); fclose($out); fclose($file); } /** * {@inheritdoc} * * @throws \LogicException when the content is not null */ public function setContent($content) { if (null !== $content) { throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); } } /** * {@inheritdoc} * * @return false */ public function getContent() { return false; } /** * Trust X-Sendfile-Type header. */ public static function trustXSendfileTypeHeader() { self::$trustXSendfileTypeHeader = true; } } PK!pߋߋ-Symfony/Component/HttpFoundation/Response.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Response represents an HTTP response. * * @author Fabien Potencier * * @api */ class Response { const HTTP_CONTINUE = 100; const HTTP_SWITCHING_PROTOCOLS = 101; const HTTP_PROCESSING = 102; // RFC2518 const HTTP_OK = 200; const HTTP_CREATED = 201; const HTTP_ACCEPTED = 202; const HTTP_NON_AUTHORITATIVE_INFORMATION = 203; const HTTP_NO_CONTENT = 204; const HTTP_RESET_CONTENT = 205; const HTTP_PARTIAL_CONTENT = 206; const HTTP_MULTI_STATUS = 207; // RFC4918 const HTTP_ALREADY_REPORTED = 208; // RFC5842 const HTTP_IM_USED = 226; // RFC3229 const HTTP_MULTIPLE_CHOICES = 300; const HTTP_MOVED_PERMANENTLY = 301; const HTTP_FOUND = 302; const HTTP_SEE_OTHER = 303; const HTTP_NOT_MODIFIED = 304; const HTTP_USE_PROXY = 305; const HTTP_RESERVED = 306; const HTTP_TEMPORARY_REDIRECT = 307; const HTTP_PERMANENTLY_REDIRECT = 308; // RFC-reschke-http-status-308-07 const HTTP_BAD_REQUEST = 400; const HTTP_UNAUTHORIZED = 401; const HTTP_PAYMENT_REQUIRED = 402; const HTTP_FORBIDDEN = 403; const HTTP_NOT_FOUND = 404; const HTTP_METHOD_NOT_ALLOWED = 405; const HTTP_NOT_ACCEPTABLE = 406; const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; const HTTP_REQUEST_TIMEOUT = 408; const HTTP_CONFLICT = 409; const HTTP_GONE = 410; const HTTP_LENGTH_REQUIRED = 411; const HTTP_PRECONDITION_FAILED = 412; const HTTP_REQUEST_ENTITY_TOO_LARGE = 413; const HTTP_REQUEST_URI_TOO_LONG = 414; const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; const HTTP_EXPECTATION_FAILED = 417; const HTTP_I_AM_A_TEAPOT = 418; // RFC2324 const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 const HTTP_LOCKED = 423; // RFC4918 const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425; // RFC2817 const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 const HTTP_INTERNAL_SERVER_ERROR = 500; const HTTP_NOT_IMPLEMENTED = 501; const HTTP_BAD_GATEWAY = 502; const HTTP_SERVICE_UNAVAILABLE = 503; const HTTP_GATEWAY_TIMEOUT = 504; const HTTP_VERSION_NOT_SUPPORTED = 505; const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295 const HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918 const HTTP_LOOP_DETECTED = 508; // RFC5842 const HTTP_NOT_EXTENDED = 510; // RFC2774 const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585 /** * @var \Symfony\Component\HttpFoundation\ResponseHeaderBag */ public $headers; /** * @var string */ protected $content; /** * @var string */ protected $version; /** * @var integer */ protected $statusCode; /** * @var string */ protected $statusText; /** * @var string */ protected $charset; /** * Status codes translation table. * * The list of codes is complete according to the * {@link http://www.iana.org/assignments/http-status-codes/ Hypertext Transfer Protocol (HTTP) Status Code Registry} * (last updated 2012-02-13). * * Unless otherwise noted, the status code is defined in RFC2616. * * @var array */ public static $statusTexts = array( 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', // RFC2518 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', // RFC4918 208 => 'Already Reported', // RFC5842 226 => 'IM Used', // RFC3229 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Reserved', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', // RFC-reschke-http-status-308-07 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', // RFC2324 422 => 'Unprocessable Entity', // RFC4918 423 => 'Locked', // RFC4918 424 => 'Failed Dependency', // RFC4918 425 => 'Reserved for WebDAV advanced collections expired proposal', // RFC2817 426 => 'Upgrade Required', // RFC2817 428 => 'Precondition Required', // RFC6585 429 => 'Too Many Requests', // RFC6585 431 => 'Request Header Fields Too Large', // RFC6585 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates (Experimental)', // RFC2295 507 => 'Insufficient Storage', // RFC4918 508 => 'Loop Detected', // RFC5842 510 => 'Not Extended', // RFC2774 511 => 'Network Authentication Required', // RFC6585 ); /** * Constructor. * * @param mixed $content The response content, see setContent() * @param integer $status The response status code * @param array $headers An array of response headers * * @throws \InvalidArgumentException When the HTTP status code is not valid * * @api */ public function __construct($content = '', $status = 200, $headers = array()) { $this->headers = new ResponseHeaderBag($headers); $this->setContent($content); $this->setStatusCode($status); $this->setProtocolVersion('1.0'); if (!$this->headers->has('Date')) { $this->setDate(new \DateTime(null, new \DateTimeZone('UTC'))); } } /** * Factory method for chainability * * Example: * * return Response::create($body, 200) * ->setSharedMaxAge(300); * * @param mixed $content The response content, see setContent() * @param integer $status The response status code * @param array $headers An array of response headers * * @return Response */ public static function create($content = '', $status = 200, $headers = array()) { return new static($content, $status, $headers); } /** * Returns the Response as an HTTP string. * * The string representation of the Response is the same as the * one that will be sent to the client only if the prepare() method * has been called before. * * @return string The Response as an HTTP string * * @see prepare() */ public function __toString() { return sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". $this->headers."\r\n". $this->getContent(); } /** * Clones the current Response instance. */ public function __clone() { $this->headers = clone $this->headers; } /** * Prepares the Response before it is sent to the client. * * This method tweaks the Response to ensure that it is * compliant with RFC 2616. Most of the changes are based on * the Request that is "associated" with this Response. * * @param Request $request A Request instance * * @return Response The current response. */ public function prepare(Request $request) { $headers = $this->headers; if ($this->isInformational() || in_array($this->statusCode, array(204, 304))) { $this->setContent(null); } // Content-type based on the Request if (!$headers->has('Content-Type')) { $format = $request->getRequestFormat(); if (null !== $format && $mimeType = $request->getMimeType($format)) { $headers->set('Content-Type', $mimeType); } } // Fix Content-Type $charset = $this->charset ?: 'UTF-8'; if (!$headers->has('Content-Type')) { $headers->set('Content-Type', 'text/html; charset='.$charset); } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) { // add the charset $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); } // Fix Content-Length if ($headers->has('Transfer-Encoding')) { $headers->remove('Content-Length'); } if ($request->isMethod('HEAD')) { // cf. RFC2616 14.13 $length = $headers->get('Content-Length'); $this->setContent(null); if ($length) { $headers->set('Content-Length', $length); } } // Fix protocol if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { $this->setProtocolVersion('1.1'); } // Check if we need to send extra expire info headers if ('1.0' == $this->getProtocolVersion() && 'no-cache' == $this->headers->get('Cache-Control')) { $this->headers->set('pragma', 'no-cache'); $this->headers->set('expires', -1); } $this->ensureIEOverSSLCompatibility($request); return $this; } /** * Sends HTTP headers. * * @return Response */ public function sendHeaders() { // headers have already been sent by the developer if (headers_sent()) { return $this; } // status header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); // headers foreach ($this->headers->allPreserveCase() as $name => $values) { foreach ($values as $value) { header($name.': '.$value, false, $this->statusCode); } } // cookies foreach ($this->headers->getCookies() as $cookie) { setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); } return $this; } /** * Sends content for the current web response. * * @return Response */ public function sendContent() { echo $this->content; return $this; } /** * Sends HTTP headers and content. * * @return Response * * @api */ public function send() { $this->sendHeaders(); $this->sendContent(); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } elseif ('cli' !== PHP_SAPI) { // ob_get_level() never returns 0 on some Windows configurations, so if // the level is the same two times in a row, the loop should be stopped. $previous = null; $obStatus = ob_get_status(1); while (($level = ob_get_level()) > 0 && $level !== $previous) { $previous = $level; if ($obStatus[$level - 1]) { if (version_compare(PHP_VERSION, '5.4', '>=')) { if (isset($obStatus[$level - 1]['flags']) && ($obStatus[$level - 1]['flags'] & PHP_OUTPUT_HANDLER_REMOVABLE)) { ob_end_flush(); } } else { if (isset($obStatus[$level - 1]['del']) && $obStatus[$level - 1]['del']) { ob_end_flush(); } } } } flush(); } return $this; } /** * Sets the response content. * * Valid types are strings, numbers, null, and objects that implement a __toString() method. * * @param mixed $content Content that can be cast to string * * @return Response * * @throws \UnexpectedValueException * * @api */ public function setContent($content) { if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable(array($content, '__toString'))) { throw new \UnexpectedValueException(sprintf('The Response content must be a string or object implementing __toString(), "%s" given.', gettype($content))); } $this->content = (string) $content; return $this; } /** * Gets the current response content. * * @return string Content * * @api */ public function getContent() { return $this->content; } /** * Sets the HTTP protocol version (1.0 or 1.1). * * @param string $version The HTTP protocol version * * @return Response * * @api */ public function setProtocolVersion($version) { $this->version = $version; return $this; } /** * Gets the HTTP protocol version. * * @return string The HTTP protocol version * * @api */ public function getProtocolVersion() { return $this->version; } /** * Sets the response status code. * * @param integer $code HTTP status code * @param mixed $text HTTP status text * * If the status text is null it will be automatically populated for the known * status codes and left empty otherwise. * * @return Response * * @throws \InvalidArgumentException When the HTTP status code is not valid * * @api */ public function setStatusCode($code, $text = null) { $this->statusCode = $code = (int) $code; if ($this->isInvalid()) { throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code)); } if (null === $text) { $this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : ''; return $this; } if (false === $text) { $this->statusText = ''; return $this; } $this->statusText = $text; return $this; } /** * Retrieves the status code for the current web response. * * @return integer Status code * * @api */ public function getStatusCode() { return $this->statusCode; } /** * Sets the response charset. * * @param string $charset Character set * * @return Response * * @api */ public function setCharset($charset) { $this->charset = $charset; return $this; } /** * Retrieves the response charset. * * @return string Character set * * @api */ public function getCharset() { return $this->charset; } /** * Returns true if the response is worth caching under any circumstance. * * Responses marked "private" with an explicit Cache-Control directive are * considered uncacheable. * * Responses with neither a freshness lifetime (Expires, max-age) nor cache * validator (Last-Modified, ETag) are considered uncacheable. * * @return Boolean true if the response is worth caching, false otherwise * * @api */ public function isCacheable() { if (!in_array($this->statusCode, array(200, 203, 300, 301, 302, 404, 410))) { return false; } if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) { return false; } return $this->isValidateable() || $this->isFresh(); } /** * Returns true if the response is "fresh". * * Fresh responses may be served from cache without any interaction with the * origin. A response is considered fresh when it includes a Cache-Control/max-age * indicator or Expires header and the calculated age is less than the freshness lifetime. * * @return Boolean true if the response is fresh, false otherwise * * @api */ public function isFresh() { return $this->getTtl() > 0; } /** * Returns true if the response includes headers that can be used to validate * the response with the origin server using a conditional GET request. * * @return Boolean true if the response is validateable, false otherwise * * @api */ public function isValidateable() { return $this->headers->has('Last-Modified') || $this->headers->has('ETag'); } /** * Marks the response as "private". * * It makes the response ineligible for serving other clients. * * @return Response * * @api */ public function setPrivate() { $this->headers->removeCacheControlDirective('public'); $this->headers->addCacheControlDirective('private'); return $this; } /** * Marks the response as "public". * * It makes the response eligible for serving other clients. * * @return Response * * @api */ public function setPublic() { $this->headers->addCacheControlDirective('public'); $this->headers->removeCacheControlDirective('private'); return $this; } /** * Returns true if the response must be revalidated by caches. * * This method indicates that the response must not be served stale by a * cache in any circumstance without first revalidating with the origin. * When present, the TTL of the response should not be overridden to be * greater than the value provided by the origin. * * @return Boolean true if the response must be revalidated by a cache, false otherwise * * @api */ public function mustRevalidate() { return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->has('proxy-revalidate'); } /** * Returns the Date header as a DateTime instance. * * @return \DateTime A \DateTime instance * * @throws \RuntimeException When the header is not parseable * * @api */ public function getDate() { return $this->headers->getDate('Date', new \DateTime()); } /** * Sets the Date header. * * @param \DateTime $date A \DateTime instance * * @return Response * * @api */ public function setDate(\DateTime $date) { $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); return $this; } /** * Returns the age of the response. * * @return integer The age of the response in seconds */ public function getAge() { if (null !== $age = $this->headers->get('Age')) { return (int) $age; } return max(time() - $this->getDate()->format('U'), 0); } /** * Marks the response stale by setting the Age header to be equal to the maximum age of the response. * * @return Response * * @api */ public function expire() { if ($this->isFresh()) { $this->headers->set('Age', $this->getMaxAge()); } return $this; } /** * Returns the value of the Expires header as a DateTime instance. * * @return \DateTime|null A DateTime instance or null if the header does not exist * * @api */ public function getExpires() { try { return $this->headers->getDate('Expires'); } catch (\RuntimeException $e) { // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past return \DateTime::createFromFormat(DATE_RFC2822, 'Sat, 01 Jan 00 00:00:00 +0000'); } } /** * Sets the Expires HTTP header with a DateTime instance. * * Passing null as value will remove the header. * * @param \DateTime|null $date A \DateTime instance or null to remove the header * * @return Response * * @api */ public function setExpires(\DateTime $date = null) { if (null === $date) { $this->headers->remove('Expires'); } else { $date = clone $date; $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); } return $this; } /** * Returns the number of seconds after the time specified in the response's Date * header when the response should no longer be considered fresh. * * First, it checks for a s-maxage directive, then a max-age directive, and then it falls * back on an expires header. It returns null when no maximum age can be established. * * @return integer|null Number of seconds * * @api */ public function getMaxAge() { if ($this->headers->hasCacheControlDirective('s-maxage')) { return (int) $this->headers->getCacheControlDirective('s-maxage'); } if ($this->headers->hasCacheControlDirective('max-age')) { return (int) $this->headers->getCacheControlDirective('max-age'); } if (null !== $this->getExpires()) { return $this->getExpires()->format('U') - $this->getDate()->format('U'); } return null; } /** * Sets the number of seconds after which the response should no longer be considered fresh. * * This methods sets the Cache-Control max-age directive. * * @param integer $value Number of seconds * * @return Response * * @api */ public function setMaxAge($value) { $this->headers->addCacheControlDirective('max-age', $value); return $this; } /** * Sets the number of seconds after which the response should no longer be considered fresh by shared caches. * * This methods sets the Cache-Control s-maxage directive. * * @param integer $value Number of seconds * * @return Response * * @api */ public function setSharedMaxAge($value) { $this->setPublic(); $this->headers->addCacheControlDirective('s-maxage', $value); return $this; } /** * Returns the response's time-to-live in seconds. * * It returns null when no freshness information is present in the response. * * When the responses TTL is <= 0, the response may not be served from cache without first * revalidating with the origin. * * @return integer|null The TTL in seconds * * @api */ public function getTtl() { if (null !== $maxAge = $this->getMaxAge()) { return $maxAge - $this->getAge(); } return null; } /** * Sets the response's time-to-live for shared caches. * * This method adjusts the Cache-Control/s-maxage directive. * * @param integer $seconds Number of seconds * * @return Response * * @api */ public function setTtl($seconds) { $this->setSharedMaxAge($this->getAge() + $seconds); return $this; } /** * Sets the response's time-to-live for private/client caches. * * This method adjusts the Cache-Control/max-age directive. * * @param integer $seconds Number of seconds * * @return Response * * @api */ public function setClientTtl($seconds) { $this->setMaxAge($this->getAge() + $seconds); return $this; } /** * Returns the Last-Modified HTTP header as a DateTime instance. * * @return \DateTime|null A DateTime instance or null if the header does not exist * * @throws \RuntimeException When the HTTP header is not parseable * * @api */ public function getLastModified() { return $this->headers->getDate('Last-Modified'); } /** * Sets the Last-Modified HTTP header with a DateTime instance. * * Passing null as value will remove the header. * * @param \DateTime|null $date A \DateTime instance or null to remove the header * * @return Response * * @api */ public function setLastModified(\DateTime $date = null) { if (null === $date) { $this->headers->remove('Last-Modified'); } else { $date = clone $date; $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); } return $this; } /** * Returns the literal value of the ETag HTTP header. * * @return string|null The ETag HTTP header or null if it does not exist * * @api */ public function getEtag() { return $this->headers->get('ETag'); } /** * Sets the ETag value. * * @param string|null $etag The ETag unique identifier or null to remove the header * @param Boolean $weak Whether you want a weak ETag or not * * @return Response * * @api */ public function setEtag($etag = null, $weak = false) { if (null === $etag) { $this->headers->remove('Etag'); } else { if (0 !== strpos($etag, '"')) { $etag = '"'.$etag.'"'; } $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag); } return $this; } /** * Sets the response's cache headers (validation and/or expiration). * * Available options are: etag, last_modified, max_age, s_maxage, private, and public. * * @param array $options An array of cache options * * @return Response * * @throws \InvalidArgumentException * * @api */ public function setCache(array $options) { if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public'))) { throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_values($diff)))); } if (isset($options['etag'])) { $this->setEtag($options['etag']); } if (isset($options['last_modified'])) { $this->setLastModified($options['last_modified']); } if (isset($options['max_age'])) { $this->setMaxAge($options['max_age']); } if (isset($options['s_maxage'])) { $this->setSharedMaxAge($options['s_maxage']); } if (isset($options['public'])) { if ($options['public']) { $this->setPublic(); } else { $this->setPrivate(); } } if (isset($options['private'])) { if ($options['private']) { $this->setPrivate(); } else { $this->setPublic(); } } return $this; } /** * Modifies the response so that it conforms to the rules defined for a 304 status code. * * This sets the status, removes the body, and discards any headers * that MUST NOT be included in 304 responses. * * @return Response * * @see http://tools.ietf.org/html/rfc2616#section-10.3.5 * * @api */ public function setNotModified() { $this->setStatusCode(304); $this->setContent(null); // remove headers that MUST NOT be included with 304 Not Modified responses foreach (array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified') as $header) { $this->headers->remove($header); } return $this; } /** * Returns true if the response includes a Vary header. * * @return Boolean true if the response includes a Vary header, false otherwise * * @api */ public function hasVary() { return null !== $this->headers->get('Vary'); } /** * Returns an array of header names given in the Vary header. * * @return array An array of Vary names * * @api */ public function getVary() { if (!$vary = $this->headers->get('Vary', null, false)) { return array(); } $ret = array(); foreach ($vary as $item) { $ret = array_merge($ret, preg_split('/[\s,]+/', $item)); } return $ret; } /** * Sets the Vary header. * * @param string|array $headers * @param Boolean $replace Whether to replace the actual value of not (true by default) * * @return Response * * @api */ public function setVary($headers, $replace = true) { $this->headers->set('Vary', $headers, $replace); return $this; } /** * Determines if the Response validators (ETag, Last-Modified) match * a conditional value specified in the Request. * * If the Response is not modified, it sets the status code to 304 and * removes the actual content by calling the setNotModified() method. * * @param Request $request A Request instance * * @return Boolean true if the Response validators match the Request, false otherwise * * @api */ public function isNotModified(Request $request) { if (!$request->isMethodSafe()) { return false; } $lastModified = $request->headers->get('If-Modified-Since'); $notModified = false; if ($etags = $request->getEtags()) { $notModified = (in_array($this->getEtag(), $etags) || in_array('*', $etags)) && (!$lastModified || $this->headers->get('Last-Modified') == $lastModified); } elseif ($lastModified) { $notModified = $lastModified == $this->headers->get('Last-Modified'); } if ($notModified) { $this->setNotModified(); } return $notModified; } // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html /** * Is response invalid? * * @return Boolean * * @api */ public function isInvalid() { return $this->statusCode < 100 || $this->statusCode >= 600; } /** * Is response informative? * * @return Boolean * * @api */ public function isInformational() { return $this->statusCode >= 100 && $this->statusCode < 200; } /** * Is response successful? * * @return Boolean * * @api */ public function isSuccessful() { return $this->statusCode >= 200 && $this->statusCode < 300; } /** * Is the response a redirect? * * @return Boolean * * @api */ public function isRedirection() { return $this->statusCode >= 300 && $this->statusCode < 400; } /** * Is there a client error? * * @return Boolean * * @api */ public function isClientError() { return $this->statusCode >= 400 && $this->statusCode < 500; } /** * Was there a server side error? * * @return Boolean * * @api */ public function isServerError() { return $this->statusCode >= 500 && $this->statusCode < 600; } /** * Is the response OK? * * @return Boolean * * @api */ public function isOk() { return 200 === $this->statusCode; } /** * Is the response forbidden? * * @return Boolean * * @api */ public function isForbidden() { return 403 === $this->statusCode; } /** * Is the response a not found error? * * @return Boolean * * @api */ public function isNotFound() { return 404 === $this->statusCode; } /** * Is the response a redirect of some form? * * @param string $location * * @return Boolean * * @api */ public function isRedirect($location = null) { return in_array($this->statusCode, array(201, 301, 302, 303, 307, 308)) && (null === $location ?: $location == $this->headers->get('Location')); } /** * Is the response empty? * * @return Boolean * * @api */ public function isEmpty() { return in_array($this->statusCode, array(201, 204, 304)); } /** * Check if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9 * * @link http://support.microsoft.com/kb/323308 */ protected function ensureIEOverSSLCompatibility(Request $request) { if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) { if (intval(preg_replace("/(MSIE )(.*?);/", "$2", $match[0])) < 9) { $this->headers->remove('Cache-Control'); } } } } PK!?` y y LSymfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * SessionHandlerInterface * * Provides forward compatibility with PHP 5.4 * * Extensive documentation can be found at php.net, see links: * * @see http://php.net/sessionhandlerinterface * @see http://php.net/session.customhandler * @see http://php.net/session-set-save-handler * * @author Drak */ interface SessionHandlerInterface { /** * Open session. * * @see http://php.net/sessionhandlerinterface.open * * @param string $savePath Save path. * @param string $sessionName Session Name. * * @throws \RuntimeException If something goes wrong starting the session. * * @return boolean */ public function open($savePath, $sessionName); /** * Close session. * * @see http://php.net/sessionhandlerinterface.close * * @return boolean */ public function close(); /** * Read session. * * @param string $sessionId * * @see http://php.net/sessionhandlerinterface.read * * @throws \RuntimeException On fatal error but not "record not found". * * @return string String as stored in persistent storage or empty string in all other cases. */ public function read($sessionId); /** * Commit session to storage. * * @see http://php.net/sessionhandlerinterface.write * * @param string $sessionId Session ID. * @param string $data Session serialized data to save. * * @return boolean */ public function write($sessionId, $data); /** * Destroys this session. * * @see http://php.net/sessionhandlerinterface.destroy * * @param string $sessionId Session ID. * * @throws \RuntimeException On fatal error. * * @return boolean */ public function destroy($sessionId); /** * Garbage collection for storage. * * @see http://php.net/sessionhandlerinterface.gc * * @param integer $lifetime Max lifetime in seconds to keep sessions stored. * * @throws \RuntimeException On fatal error. * * @return boolean */ public function gc($lifetime); } PK!EY.Symfony/Component/HttpFoundation/HeaderBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * HeaderBag is a container for HTTP headers. * * @author Fabien Potencier * * @api */ class HeaderBag implements \IteratorAggregate, \Countable { protected $headers = array(); protected $cacheControl = array(); /** * Constructor. * * @param array $headers An array of HTTP headers * * @api */ public function __construct(array $headers = array()) { foreach ($headers as $key => $values) { $this->set($key, $values); } } /** * Returns the headers as a string. * * @return string The headers */ public function __toString() { if (!$this->headers) { return ''; } $max = max(array_map('strlen', array_keys($this->headers))) + 1; $content = ''; ksort($this->headers); foreach ($this->headers as $name => $values) { $name = implode('-', array_map('ucfirst', explode('-', $name))); foreach ($values as $value) { $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); } } return $content; } /** * Returns the headers. * * @return array An array of headers * * @api */ public function all() { return $this->headers; } /** * Returns the parameter keys. * * @return array An array of parameter keys * * @api */ public function keys() { return array_keys($this->headers); } /** * Replaces the current HTTP headers by a new set. * * @param array $headers An array of HTTP headers * * @api */ public function replace(array $headers = array()) { $this->headers = array(); $this->add($headers); } /** * Adds new headers the current HTTP headers set. * * @param array $headers An array of HTTP headers * * @api */ public function add(array $headers) { foreach ($headers as $key => $values) { $this->set($key, $values); } } /** * Returns a header value by name. * * @param string $key The header name * @param mixed $default The default value * @param Boolean $first Whether to return the first value or all header values * * @return string|array The first header value if $first is true, an array of values otherwise * * @api */ public function get($key, $default = null, $first = true) { $key = strtr(strtolower($key), '_', '-'); if (!array_key_exists($key, $this->headers)) { if (null === $default) { return $first ? null : array(); } return $first ? $default : array($default); } if ($first) { return count($this->headers[$key]) ? $this->headers[$key][0] : $default; } return $this->headers[$key]; } /** * Sets a header by name. * * @param string $key The key * @param string|array $values The value or an array of values * @param Boolean $replace Whether to replace the actual value or not (true by default) * * @api */ public function set($key, $values, $replace = true) { $key = strtr(strtolower($key), '_', '-'); $values = array_values((array) $values); if (true === $replace || !isset($this->headers[$key])) { $this->headers[$key] = $values; } else { $this->headers[$key] = array_merge($this->headers[$key], $values); } if ('cache-control' === $key) { $this->cacheControl = $this->parseCacheControl($values[0]); } } /** * Returns true if the HTTP header is defined. * * @param string $key The HTTP header * * @return Boolean true if the parameter exists, false otherwise * * @api */ public function has($key) { return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers); } /** * Returns true if the given HTTP header contains the given value. * * @param string $key The HTTP header name * @param string $value The HTTP value * * @return Boolean true if the value is contained in the header, false otherwise * * @api */ public function contains($key, $value) { return in_array($value, $this->get($key, null, false)); } /** * Removes a header. * * @param string $key The HTTP header name * * @api */ public function remove($key) { $key = strtr(strtolower($key), '_', '-'); unset($this->headers[$key]); if ('cache-control' === $key) { $this->cacheControl = array(); } } /** * Returns the HTTP header value converted to a date. * * @param string $key The parameter key * @param \DateTime $default The default value * * @return null|\DateTime The parsed DateTime or the default value if the header does not exist * * @throws \RuntimeException When the HTTP header is not parseable * * @api */ public function getDate($key, \DateTime $default = null) { if (null === $value = $this->get($key)) { return $default; } if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) { throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value)); } return $date; } public function addCacheControlDirective($key, $value = true) { $this->cacheControl[$key] = $value; $this->set('Cache-Control', $this->getCacheControlHeader()); } public function hasCacheControlDirective($key) { return array_key_exists($key, $this->cacheControl); } public function getCacheControlDirective($key) { return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null; } public function removeCacheControlDirective($key) { unset($this->cacheControl[$key]); $this->set('Cache-Control', $this->getCacheControlHeader()); } /** * Returns an iterator for headers. * * @return \ArrayIterator An \ArrayIterator instance */ public function getIterator() { return new \ArrayIterator($this->headers); } /** * Returns the number of headers. * * @return int The number of headers */ public function count() { return count($this->headers); } protected function getCacheControlHeader() { $parts = array(); ksort($this->cacheControl); foreach ($this->cacheControl as $key => $value) { if (true === $value) { $parts[] = $key; } else { if (preg_match('#[^a-zA-Z0-9._-]#', $value)) { $value = '"'.$value.'"'; } $parts[] = "$key=$value"; } } return implode(', ', $parts); } /** * Parses a Cache-Control HTTP header. * * @param string $header The value of the Cache-Control HTTP header * * @return array An array representing the attribute values */ protected function parseCacheControl($header) { $cacheControl = array(); preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER); foreach ($matches as $match) { $cacheControl[strtolower($match[1])] = isset($match[3]) ? $match[3] : (isset($match[2]) ? $match[2] : true); } return $cacheControl; } } PK!9;""'Symfony/Component/BrowserKit/Cookie.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * Cookie represents an HTTP cookie. * * @author Fabien Potencier * * @api */ class Cookie { /** * Handles dates as defined by RFC 2616 section 3.3.1, and also some other * non-standard, but common formats. * * @var array */ private static $dateFormats = array( 'D, d M Y H:i:s T', 'D, d-M-y H:i:s T', 'D, d-M-Y H:i:s T', 'D, d-m-y H:i:s T', 'D, d-m-Y H:i:s T', 'D M j G:i:s Y', 'D M d H:i:s Y T', ); protected $name; protected $value; protected $expires; protected $path; protected $domain; protected $secure; protected $httponly; protected $rawValue; /** * Sets a cookie. * * @param string $name The cookie name * @param string $value The value of the cookie * @param string $expires The time the cookie expires * @param string $path The path on the server in which the cookie will be available on * @param string $domain The domain that the cookie is available * @param Boolean $secure Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client * @param Boolean $httponly The cookie httponly flag * @param Boolean $encodedValue Whether the value is encoded or not * * @api */ public function __construct($name, $value, $expires = null, $path = null, $domain = '', $secure = false, $httponly = true, $encodedValue = false) { if ($encodedValue) { $this->value = urldecode($value); $this->rawValue = $value; } else { $this->value = $value; $this->rawValue = urlencode($value); } $this->name = $name; $this->expires = null === $expires ? null : (integer) $expires; $this->path = empty($path) ? '/' : $path; $this->domain = $domain; $this->secure = (Boolean) $secure; $this->httponly = (Boolean) $httponly; } /** * Returns the HTTP representation of the Cookie. * * @return string The HTTP representation of the Cookie * * @throws \UnexpectedValueException * * @api */ public function __toString() { $cookie = sprintf('%s=%s', $this->name, $this->rawValue); if (null !== $this->expires) { $dateTime = \DateTime::createFromFormat('U', $this->expires, new \DateTimeZone('GMT')); if ($dateTime === false) { throw new \UnexpectedValueException(sprintf('The cookie expiration time "%s" is not valid.'), $this->expires); } $cookie .= '; expires='.str_replace('+0000', '', $dateTime->format(self::$dateFormats[0])); } if ('' !== $this->domain) { $cookie .= '; domain='.$this->domain; } if ($this->path) { $cookie .= '; path='.$this->path; } if ($this->secure) { $cookie .= '; secure'; } if ($this->httponly) { $cookie .= '; httponly'; } return $cookie; } /** * Creates a Cookie instance from a Set-Cookie header value. * * @param string $cookie A Set-Cookie header value * @param string $url The base URL * * @return Cookie A Cookie instance * * @throws \InvalidArgumentException * * @api */ public static function fromString($cookie, $url = null) { $parts = explode(';', $cookie); if (false === strpos($parts[0], '=')) { throw new \InvalidArgumentException(sprintf('The cookie string "%s" is not valid.', $parts[0])); } list($name, $value) = explode('=', array_shift($parts), 2); $values = array( 'name' => trim($name), 'value' => trim($value), 'expires' => null, 'path' => '/', 'domain' => '', 'secure' => false, 'httponly' => false, 'passedRawValue' => true, ); if (null !== $url) { if ((false === $urlParts = parse_url($url)) || !isset($urlParts['host']) || !isset($urlParts['path'])) { throw new \InvalidArgumentException(sprintf('The URL "%s" is not valid.', $url)); } $values['domain'] = $urlParts['host']; $values['path'] = substr($urlParts['path'], 0, strrpos($urlParts['path'], '/')); } foreach ($parts as $part) { $part = trim($part); if ('secure' === strtolower($part)) { // Ignore the secure flag if the original URI is not given or is not HTTPS if (!$url || !isset($urlParts['scheme']) || 'https' != $urlParts['scheme']) { continue; } $values['secure'] = true; continue; } if ('httponly' === strtolower($part)) { $values['httponly'] = true; continue; } if (2 === count($elements = explode('=', $part, 2))) { if ('expires' === strtolower($elements[0])) { $elements[1] = self::parseDate($elements[1]); } $values[strtolower($elements[0])] = $elements[1]; } } return new static( $values['name'], $values['value'], $values['expires'], $values['path'], $values['domain'], $values['secure'], $values['httponly'], $values['passedRawValue'] ); } private static function parseDate($dateValue) { // trim single quotes around date if present if (($length = strlen($dateValue)) > 1 && "'" === $dateValue[0] && "'" === $dateValue[$length-1]) { $dateValue = substr($dateValue, 1, -1); } foreach (self::$dateFormats as $dateFormat) { if (false !== $date = \DateTime::createFromFormat($dateFormat, $dateValue, new \DateTimeZone('GMT'))) { return $date->getTimestamp(); } } // attempt a fallback for unusual formatting if (false !== $date = date_create($dateValue, new \DateTimeZone('GMT'))) { return $date->getTimestamp(); } throw new \InvalidArgumentException(sprintf('Could not parse date "%s".', $dateValue)); } /** * Gets the name of the cookie. * * @return string The cookie name * * @api */ public function getName() { return $this->name; } /** * Gets the value of the cookie. * * @return string The cookie value * * @api */ public function getValue() { return $this->value; } /** * Gets the raw value of the cookie. * * @return string The cookie value * * @api */ public function getRawValue() { return $this->rawValue; } /** * Gets the expires time of the cookie. * * @return string The cookie expires time * * @api */ public function getExpiresTime() { return $this->expires; } /** * Gets the path of the cookie. * * @return string The cookie path * * @api */ public function getPath() { return $this->path; } /** * Gets the domain of the cookie. * * @return string The cookie domain * * @api */ public function getDomain() { return $this->domain; } /** * Returns the secure flag of the cookie. * * @return Boolean The cookie secure flag * * @api */ public function isSecure() { return $this->secure; } /** * Returns the httponly flag of the cookie. * * @return Boolean The cookie httponly flag * * @api */ public function isHttpOnly() { return $this->httponly; } /** * Returns true if the cookie has expired. * * @return Boolean true if the cookie has expired, false otherwise * * @api */ public function isExpired() { return null !== $this->expires && 0 !== $this->expires && $this->expires < time(); } } PK!.TT+Symfony/Component/BrowserKit/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * CookieJar. * * @author Fabien Potencier * * @api */ class CookieJar { protected $cookieJar = array(); /** * Sets a cookie. * * @param Cookie $cookie A Cookie instance * * @api */ public function set(Cookie $cookie) { $this->cookieJar[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; } /** * Gets a cookie by name. * * You should never use an empty domain, but if you do so, * this method returns the first cookie for the given name/path * (this behavior ensures a BC behavior with previous versions of * Symfony). * * @param string $name The cookie name * @param string $path The cookie path * @param string $domain The cookie domain * * @return Cookie|null A Cookie instance or null if the cookie does not exist * * @api */ public function get($name, $path = '/', $domain = null) { $this->flushExpiredCookies(); if (!empty($domain)) { foreach ($this->cookieJar as $cookieDomain => $pathCookies) { if ($cookieDomain) { $cookieDomain = '.'.ltrim($cookieDomain, '.'); if ($cookieDomain != substr('.'.$domain, -strlen($cookieDomain))) { continue; } } foreach ($pathCookies as $cookiePath => $namedCookies) { if ($cookiePath != substr($path, 0, strlen($cookiePath))) { continue; } if (isset($namedCookies[$name])) { return $namedCookies[$name]; } } } return null; } // avoid relying on this behavior that is mainly here for BC reasons foreach ($this->cookieJar as $cookies) { if (isset($cookies[$path][$name])) { return $cookies[$path][$name]; } } return null; } /** * Removes a cookie by name. * * You should never use an empty domain, but if you do so, * all cookies for the given name/path expire (this behavior * ensures a BC behavior with previous versions of Symfony). * * @param string $name The cookie name * @param string $path The cookie path * @param string $domain The cookie domain * * @api */ public function expire($name, $path = '/', $domain = null) { if (null === $path) { $path = '/'; } if (empty($domain)) { // an empty domain means any domain // this should never happen but it allows for a better BC $domains = array_keys($this->cookieJar); } else { $domains = array($domain); } foreach ($domains as $domain) { unset($this->cookieJar[$domain][$path][$name]); if (empty($this->cookieJar[$domain][$path])) { unset($this->cookieJar[$domain][$path]); if (empty($this->cookieJar[$domain])) { unset($this->cookieJar[$domain]); } } } } /** * Removes all the cookies from the jar. * * @api */ public function clear() { $this->cookieJar = array(); } /** * Updates the cookie jar from a response Set-Cookie headers. * * @param array $setCookies Set-Cookie headers from an HTTP response * @param string $uri The base URL */ public function updateFromSetCookie(array $setCookies, $uri = null) { $cookies = array(); foreach ($setCookies as $cookie) { foreach (explode(',', $cookie) as $i => $part) { if (0 === $i || preg_match('/^(?P\s*[0-9A-Za-z!#\$%\&\'\*\+\-\.^_`\|~]+)=/', $part)) { $cookies[] = ltrim($part); } else { $cookies[count($cookies) - 1] .= ','.$part; } } } foreach ($cookies as $cookie) { try { $this->set(Cookie::fromString($cookie, $uri)); } catch (\InvalidArgumentException $e) { // invalid cookies are just ignored } } } /** * Updates the cookie jar from a Response object. * * @param Response $response A Response object * @param string $uri The base URL */ public function updateFromResponse(Response $response, $uri = null) { $this->updateFromSetCookie($response->getHeader('Set-Cookie', false), $uri); } /** * Returns not yet expired cookies. * * @return Cookie[] An array of cookies */ public function all() { $this->flushExpiredCookies(); $flattenedCookies = array(); foreach ($this->cookieJar as $path) { foreach ($path as $cookies) { foreach ($cookies as $cookie) { $flattenedCookies[] = $cookie; } } } return $flattenedCookies; } /** * Returns not yet expired cookie values for the given URI. * * @param string $uri A URI * @param Boolean $returnsRawValue Returns raw value or urldecoded value * * @return array An array of cookie values */ public function allValues($uri, $returnsRawValue = false) { $this->flushExpiredCookies(); $parts = array_replace(array('path' => '/'), parse_url($uri)); $cookies = array(); foreach ($this->cookieJar as $domain => $pathCookies) { if ($domain) { $domain = '.'.ltrim($domain, '.'); if ($domain != substr('.'.$parts['host'], -strlen($domain))) { continue; } } foreach ($pathCookies as $path => $namedCookies) { if ($path != substr($parts['path'], 0, strlen($path))) { continue; } foreach ($namedCookies as $cookie) { if ($cookie->isSecure() && 'https' != $parts['scheme']) { continue; } $cookies[$cookie->getName()] = $returnsRawValue ? $cookie->getRawValue() : $cookie->getValue(); } } } return $cookies; } /** * Returns not yet expired raw cookie values for the given URI. * * @param string $uri A URI * * @return array An array of cookie values */ public function allRawValues($uri) { return $this->allValues($uri, true); } /** * Removes all expired cookies. */ public function flushExpiredCookies() { foreach ($this->cookieJar as $domain => $pathCookies) { foreach ($pathCookies as $path => $namedCookies) { foreach ($namedCookies as $name => $cookie) { if ($cookie->isExpired()) { unset($this->cookieJar[$domain][$path][$name]); } } } } } } PK! (Symfony/Component/BrowserKit/Request.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * Request object. * * @author Fabien Potencier * * @api */ class Request { protected $uri; protected $method; protected $parameters; protected $files; protected $cookies; protected $server; protected $content; /** * Constructor. * * @param string $uri The request URI * @param string $method The HTTP method request * @param array $parameters The request parameters * @param array $files An array of uploaded files * @param array $cookies An array of cookies * @param array $server An array of server parameters * @param string $content The raw body data * * @api */ public function __construct($uri, $method, array $parameters = array(), array $files = array(), array $cookies = array(), array $server = array(), $content = null) { $this->uri = $uri; $this->method = $method; $this->parameters = $parameters; $this->files = $files; $this->cookies = $cookies; $this->server = $server; $this->content = $content; } /** * Gets the request URI. * * @return string The request URI * * @api */ public function getUri() { return $this->uri; } /** * Gets the request HTTP method. * * @return string The request HTTP method * * @api */ public function getMethod() { return $this->method; } /** * Gets the request parameters. * * @return array The request parameters * * @api */ public function getParameters() { return $this->parameters; } /** * Gets the request server files. * * @return array The request files * * @api */ public function getFiles() { return $this->files; } /** * Gets the request cookies. * * @return array The request cookies * * @api */ public function getCookies() { return $this->cookies; } /** * Gets the request server parameters. * * @return array The request server parameters * * @api */ public function getServer() { return $this->server; } /** * Gets the request raw body data. * * @return string The request raw body data. * * @api */ public function getContent() { return $this->content; } } PK!l- - )Symfony/Component/BrowserKit/Response.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * Response object. * * @author Fabien Potencier * * @api */ class Response { protected $content; protected $status; protected $headers; /** * Constructor. * * The headers array is a set of key/value pairs. If a header is present multiple times * then the value is an array of all the values. * * @param string $content The content of the response * @param integer $status The response status code * @param array $headers An array of headers * * @api */ public function __construct($content = '', $status = 200, array $headers = array()) { $this->content = $content; $this->status = $status; $this->headers = $headers; } /** * Converts the response object to string containing all headers and the response content. * * @return string The response with headers and content */ public function __toString() { $headers = ''; foreach ($this->headers as $name => $value) { if (is_string($value)) { $headers .= $this->buildHeader($name, $value); } else { foreach ($value as $headerValue) { $headers .= $this->buildHeader($name, $headerValue); } } } return $headers."\n".$this->content; } /** * Returns the build header line. * * @param string $name The header name * @param string $value The header value * * @return string The built header line */ protected function buildHeader($name, $value) { return sprintf("%s: %s\n", $name, $value); } /** * Gets the response content. * * @return string The response content * * @api */ public function getContent() { return $this->content; } /** * Gets the response status code. * * @return integer The response status code * * @api */ public function getStatus() { return $this->status; } /** * Gets the response headers. * * @return array The response headers * * @api */ public function getHeaders() { return $this->headers; } /** * Gets a response header. * * @param string $header The header name * @param Boolean $first Whether to return the first value or all header values * * @return string|array The first header value if $first is true, an array of values otherwise */ public function getHeader($header, $first = true) { foreach ($this->headers as $key => $value) { if (str_replace('-', '_', strtolower($key)) == str_replace('-', '_', strtolower($header))) { if ($first) { return is_array($value) ? (count($value) ? $value[0] : '') : $value; } return is_array($value) ? $value : array($value); } } return $first ? null : array(); } } PK!㩑eCC'Symfony/Component/BrowserKit/Client.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\DomCrawler\Link; use Symfony\Component\DomCrawler\Form; use Symfony\Component\Process\PhpProcess; /** * Client simulates a browser. * * To make the actual request, you need to implement the doRequest() method. * * If you want to be able to run requests in their own process (insulated flag), * you need to also implement the getScript() method. * * @author Fabien Potencier * * @api */ abstract class Client { protected $history; protected $cookieJar; protected $server = array(); protected $internalRequest; protected $request; protected $internalResponse; protected $response; protected $crawler; protected $insulated = false; protected $redirect; protected $followRedirects = true; private $maxRedirects = -1; private $redirectCount = 0; private $isMainRequest = true; /** * Constructor. * * @param array $server The server parameters (equivalent of $_SERVER) * @param History $history A History instance to store the browser history * @param CookieJar $cookieJar A CookieJar instance to store the cookies * * @api */ public function __construct(array $server = array(), History $history = null, CookieJar $cookieJar = null) { $this->setServerParameters($server); $this->history = $history ?: new History(); $this->cookieJar = $cookieJar ?: new CookieJar(); } /** * Sets whether to automatically follow redirects or not. * * @param Boolean $followRedirect Whether to follow redirects * * @api */ public function followRedirects($followRedirect = true) { $this->followRedirects = (Boolean) $followRedirect; } /** * Sets the maximum number of requests that crawler can follow. * * @param integer $maxRedirects */ public function setMaxRedirects($maxRedirects) { $this->maxRedirects = $maxRedirects < 0 ? -1 : $maxRedirects; $this->followRedirects = -1 != $this->maxRedirects; } /** * Sets the insulated flag. * * @param Boolean $insulated Whether to insulate the requests or not * * @throws \RuntimeException When Symfony Process Component is not installed * * @api */ public function insulate($insulated = true) { if ($insulated && !class_exists('Symfony\\Component\\Process\\Process')) { // @codeCoverageIgnoreStart throw new \RuntimeException('Unable to isolate requests as the Symfony Process Component is not installed.'); // @codeCoverageIgnoreEnd } $this->insulated = (Boolean) $insulated; } /** * Sets server parameters. * * @param array $server An array of server parameters * * @api */ public function setServerParameters(array $server) { $this->server = array_merge(array( 'HTTP_HOST' => 'localhost', 'HTTP_USER_AGENT' => 'Symfony2 BrowserKit', ), $server); } /** * Sets single server parameter. * * @param string $key A key of the parameter * @param string $value A value of the parameter */ public function setServerParameter($key, $value) { $this->server[$key] = $value; } /** * Gets single server parameter for specified key. * * @param string $key A key of the parameter to get * @param string $default A default value when key is undefined * * @return string A value of the parameter */ public function getServerParameter($key, $default = '') { return (isset($this->server[$key])) ? $this->server[$key] : $default; } /** * Returns the History instance. * * @return History A History instance * * @api */ public function getHistory() { return $this->history; } /** * Returns the CookieJar instance. * * @return CookieJar A CookieJar instance * * @api */ public function getCookieJar() { return $this->cookieJar; } /** * Returns the current Crawler instance. * * @return Crawler|null A Crawler instance * * @api */ public function getCrawler() { return $this->crawler; } /** * Returns the current BrowserKit Response instance. * * @return Response|null A BrowserKit Response instance * * @api */ public function getInternalResponse() { return $this->internalResponse; } /** * Returns the current origin response instance. * * The origin response is the response instance that is returned * by the code that handles requests. * * @return object|null A response instance * * @see doRequest * * @api */ public function getResponse() { return $this->response; } /** * Returns the current BrowserKit Request instance. * * @return Request|null A BrowserKit Request instance * * @api */ public function getInternalRequest() { return $this->internalRequest; } /** * Returns the current origin Request instance. * * The origin request is the request instance that is sent * to the code that handles requests. * * @return object|null A Request instance * * @see doRequest * * @api */ public function getRequest() { return $this->request; } /** * Clicks on a given link. * * @param Link $link A Link instance * * @return Crawler * * @api */ public function click(Link $link) { if ($link instanceof Form) { return $this->submit($link); } return $this->request($link->getMethod(), $link->getUri()); } /** * Submits a form. * * @param Form $form A Form instance * @param array $values An array of form field values * * @return Crawler * * @api */ public function submit(Form $form, array $values = array()) { $form->setValues($values); return $this->request($form->getMethod(), $form->getUri(), $form->getPhpValues(), $form->getPhpFiles()); } /** * Calls a URI. * * @param string $method The request method * @param string $uri The URI to fetch * @param array $parameters The Request parameters * @param array $files The files * @param array $server The server parameters (HTTP headers are referenced with a HTTP_ prefix as PHP does) * @param string $content The raw body data * @param Boolean $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload()) * * @return Crawler * * @api */ public function request($method, $uri, array $parameters = array(), array $files = array(), array $server = array(), $content = null, $changeHistory = true) { if ($this->isMainRequest) { $this->redirectCount = 0; } else { ++$this->redirectCount; } $uri = $this->getAbsoluteUri($uri); if (isset($server['HTTP_HOST'])) { $uri = preg_replace('{^(https?\://)'.parse_url($uri, PHP_URL_HOST).'}', '\\1'.$server['HTTP_HOST'], $uri); } if (isset($server['HTTPS'])) { $uri = preg_replace('{^'.parse_url($uri, PHP_URL_SCHEME).'}', $server['HTTPS'] ? 'https' : 'http', $uri); } $server = array_merge($this->server, $server); if (!$this->history->isEmpty()) { $server['HTTP_REFERER'] = $this->history->current()->getUri(); } $server['HTTP_HOST'] = parse_url($uri, PHP_URL_HOST); if ($port = parse_url($uri, PHP_URL_PORT)) { $server['HTTP_HOST'] .= ':'.$port; } $server['HTTPS'] = 'https' == parse_url($uri, PHP_URL_SCHEME); $this->internalRequest = new Request($uri, $method, $parameters, $files, $this->cookieJar->allValues($uri), $server, $content); $this->request = $this->filterRequest($this->internalRequest); if (true === $changeHistory) { $this->history->add($this->internalRequest); } if ($this->insulated) { $this->response = $this->doRequestInProcess($this->request); } else { $this->response = $this->doRequest($this->request); } $this->internalResponse = $this->filterResponse($this->response); $this->cookieJar->updateFromResponse($this->internalResponse, $uri); $status = $this->internalResponse->getStatus(); if ($status >= 300 && $status < 400) { $this->redirect = $this->internalResponse->getHeader('Location'); } else { $this->redirect = null; } if ($this->followRedirects && $this->redirect) { return $this->crawler = $this->followRedirect(); } return $this->crawler = $this->createCrawlerFromContent($this->internalRequest->getUri(), $this->internalResponse->getContent(), $this->internalResponse->getHeader('Content-Type')); } /** * Makes a request in another process. * * @param object $request An origin request instance * * @return object An origin response instance * * @throws \RuntimeException When processing returns exit code */ protected function doRequestInProcess($request) { // We set the TMPDIR (for Macs) and TEMP (for Windows), because on these platforms the temp directory changes based on the user. $process = new PhpProcess($this->getScript($request), null, array('TMPDIR' => sys_get_temp_dir(), 'TEMP' => sys_get_temp_dir())); $process->run(); if (!$process->isSuccessful() || !preg_match('/^O\:\d+\:/', $process->getOutput())) { throw new \RuntimeException(sprintf('OUTPUT: %s ERROR OUTPUT: %s', $process->getOutput(), $process->getErrorOutput())); } return unserialize($process->getOutput()); } /** * Makes a request. * * @param object $request An origin request instance * * @return object An origin response instance */ abstract protected function doRequest($request); /** * Returns the script to execute when the request must be insulated. * * @param object $request An origin request instance * * @throws \LogicException When this abstract class is not implemented */ protected function getScript($request) { // @codeCoverageIgnoreStart throw new \LogicException('To insulate requests, you need to override the getScript() method.'); // @codeCoverageIgnoreEnd } /** * Filters the BrowserKit request to the origin one. * * @param Request $request The BrowserKit Request to filter * * @return object An origin request instance */ protected function filterRequest(Request $request) { return $request; } /** * Filters the origin response to the BrowserKit one. * * @param object $response The origin response to filter * * @return Response An BrowserKit Response instance */ protected function filterResponse($response) { return $response; } /** * Creates a crawler. * * This method returns null if the DomCrawler component is not available. * * @param string $uri A URI * @param string $content Content for the crawler to use * @param string $type Content type * * @return Crawler|null */ protected function createCrawlerFromContent($uri, $content, $type) { if (!class_exists('Symfony\Component\DomCrawler\Crawler')) { return null; } $crawler = new Crawler(null, $uri); $crawler->addContent($content, $type); return $crawler; } /** * Goes back in the browser history. * * @return Crawler * * @api */ public function back() { return $this->requestFromRequest($this->history->back(), false); } /** * Goes forward in the browser history. * * @return Crawler * * @api */ public function forward() { return $this->requestFromRequest($this->history->forward(), false); } /** * Reloads the current browser. * * @return Crawler * * @api */ public function reload() { return $this->requestFromRequest($this->history->current(), false); } /** * Follow redirects? * * @return Crawler * * @throws \LogicException If request was not a redirect * * @api */ public function followRedirect() { if (empty($this->redirect)) { throw new \LogicException('The request was not redirected.'); } if (-1 !== $this->maxRedirects) { if ($this->redirectCount > $this->maxRedirects) { throw new \LogicException(sprintf('The maximum number (%d) of redirections was reached.', $this->maxRedirects)); } } $request = $this->internalRequest; if (in_array($this->internalResponse->getStatus(), array(302, 303))) { $method = 'get'; $files = array(); $content = null; } else { $method = $request->getMethod(); $files = $request->getFiles(); $content = $request->getContent(); } if ('get' === strtolower($method)) { // Don't forward parameters for GET request as it should reach the redirection URI $parameters = array(); } else { $parameters = $request->getParameters(); } $server = $request->getServer(); $server = $this->updateServerFromUri($server, $this->redirect); $this->isMainRequest = false; $response = $this->request($method, $this->redirect, $parameters, $files, $server, $content); $this->isMainRequest = true; return $response; } /** * Restarts the client. * * It flushes history and all cookies. * * @api */ public function restart() { $this->cookieJar->clear(); $this->history->clear(); } /** * Takes a URI and converts it to absolute if it is not already absolute. * * @param string $uri A URI * * @return string An absolute URI */ protected function getAbsoluteUri($uri) { // already absolute? if (0 === strpos($uri, 'http')) { return $uri; } if (!$this->history->isEmpty()) { $currentUri = $this->history->current()->getUri(); } else { $currentUri = sprintf('http%s://%s/', isset($this->server['HTTPS']) ? 's' : '', isset($this->server['HTTP_HOST']) ? $this->server['HTTP_HOST'] : 'localhost' ); } // protocol relative URL if (0 === strpos($uri, '//')) { return parse_url($currentUri, PHP_URL_SCHEME).':'.$uri; } // anchor? if (!$uri || '#' == $uri[0]) { return preg_replace('/#.*?$/', '', $currentUri).$uri; } if ('/' !== $uri[0]) { $path = parse_url($currentUri, PHP_URL_PATH); if ('/' !== substr($path, -1)) { $path = substr($path, 0, strrpos($path, '/') + 1); } $uri = $path.$uri; } return preg_replace('#^(.*?//[^/]+)\/.*$#', '$1', $currentUri).$uri; } /** * Makes a request from a Request object directly. * * @param Request $request A Request instance * @param Boolean $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload()) * * @return Crawler */ protected function requestFromRequest(Request $request, $changeHistory = true) { return $this->request($request->getMethod(), $request->getUri(), $request->getParameters(), $request->getFiles(), $request->getServer(), $request->getContent(), $changeHistory); } private function updateServerFromUri($server, $uri) { $server['HTTP_HOST'] = parse_url($uri, PHP_URL_HOST); $scheme = parse_url($uri, PHP_URL_SCHEME); $server['HTTPS'] = null === $scheme ? $server['HTTPS'] : 'https' == $scheme; unset($server['HTTP_IF_NONE_MATCH'], $server['HTTP_IF_MODIFIED_SINCE']); return $server; } } PK!/  (Symfony/Component/BrowserKit/History.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; /** * History. * * @author Fabien Potencier */ class History { protected $stack = array(); protected $position = -1; /** * Clears the history. */ public function clear() { $this->stack = array(); $this->position = -1; } /** * Adds a Request to the history. * * @param Request $request A Request instance */ public function add(Request $request) { $this->stack = array_slice($this->stack, 0, $this->position + 1); $this->stack[] = clone $request; $this->position = count($this->stack) - 1; } /** * Returns true if the history is empty. * * @return Boolean true if the history is empty, false otherwise */ public function isEmpty() { return count($this->stack) == 0; } /** * Goes back in the history. * * @return Request A Request instance * * @throws \LogicException if the stack is already on the first page */ public function back() { if ($this->position < 1) { throw new \LogicException('You are already on the first page.'); } return clone $this->stack[--$this->position]; } /** * Goes forward in the history. * * @return Request A Request instance * * @throws \LogicException if the stack is already on the last page */ public function forward() { if ($this->position > count($this->stack) - 2) { throw new \LogicException('You are already on the last page.'); } return clone $this->stack[++$this->position]; } /** * Returns the current element in the history. * * @return Request A Request instance * * @throws \LogicException if the stack is empty */ public function current() { if (-1 == $this->position) { throw new \LogicException('The page history is empty.'); } return clone $this->stack[$this->position]; } } PK!V * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler; use Symfony\Component\DomCrawler\Field\FormField; /** * This is an internal class that must not be used directly. */ class FormFieldRegistry { private $fields = array(); private $base; /** * Adds a field to the registry. * * @param FormField $field The field * * @throws \InvalidArgumentException when the name is malformed */ public function add(FormField $field) { $segments = $this->getSegments($field->getName()); $target =& $this->fields; while ($segments) { if (!is_array($target)) { $target = array(); } $path = array_shift($segments); if ('' === $path) { $target =& $target[]; } else { $target =& $target[$path]; } } $target = $field; } /** * Removes a field and its children from the registry. * * @param string $name The fully qualified name of the base field * * @throws \InvalidArgumentException when the name is malformed */ public function remove($name) { $segments = $this->getSegments($name); $target =& $this->fields; while (count($segments) > 1) { $path = array_shift($segments); if (!array_key_exists($path, $target)) { return; } $target =& $target[$path]; } unset($target[array_shift($segments)]); } /** * Returns the value of the field and its children. * * @param string $name The fully qualified name of the field * * @return mixed The value of the field * * @throws \InvalidArgumentException when the name is malformed * @throws \InvalidArgumentException if the field does not exist */ public function &get($name) { $segments = $this->getSegments($name); $target =& $this->fields; while ($segments) { $path = array_shift($segments); if (!array_key_exists($path, $target)) { throw new \InvalidArgumentException(sprintf('Unreachable field "%s"', $path)); } $target =& $target[$path]; } return $target; } /** * Tests whether the form has the given field. * * @param string $name The fully qualified name of the field * * @return Boolean Whether the form has the given field */ public function has($name) { try { $this->get($name); return true; } catch (\InvalidArgumentException $e) { return false; } } /** * Set the value of a field and its children. * * @param string $name The fully qualified name of the field * @param mixed $value The value * * @throws \InvalidArgumentException when the name is malformed * @throws \InvalidArgumentException if the field does not exist */ public function set($name, $value) { $target =& $this->get($name); if (!is_array($value) || $target instanceof Field\ChoiceFormField) { $target->setValue($value); } else { $fields = self::create($name, $value); foreach ($fields->all() as $k => $v) { $this->set($k, $v); } } } /** * Returns the list of field with their value. * * @return array The list of fields as array((string) Fully qualified name => (mixed) value) */ public function all() { return $this->walk($this->fields, $this->base); } /** * Creates an instance of the class. * * This function is made private because it allows overriding the $base and * the $values properties without any type checking. * * @param string $base The fully qualified name of the base field * @param array $values The values of the fields * * @return FormFieldRegistry */ private static function create($base, array $values) { $registry = new static(); $registry->base = $base; $registry->fields = $values; return $registry; } /** * Transforms a PHP array in a list of fully qualified name / value. * * @param array $array The PHP array * @param string $base The name of the base field * @param array $output The initial values * * @return array The list of fields as array((string) Fully qualified name => (mixed) value) */ private function walk(array $array, $base = '', array &$output = array()) { foreach ($array as $k => $v) { $path = empty($base) ? $k : sprintf("%s[%s]", $base, $k); if (is_array($v)) { $this->walk($v, $path, $output); } else { $output[$path] = $v; } } return $output; } /** * Splits a field name into segments as a web browser would do. * * * getSegments('base[foo][3][]') = array('base', 'foo, '3', ''); * * * @param string $name The name of the field * * @return array The list of segments * * @throws \InvalidArgumentException when the name is malformed */ private function getSegments($name) { if (preg_match('/^(?P[^[]+)(?P(\[.*)|$)/', $name, $m)) { $segments = array($m['base']); while (!empty($m['extra'])) { if (preg_match('/^\[(?P.*?)\](?P.*)$/', $m['extra'], $m)) { $segments[] = $m['segment']; } else { throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name)); } } return $segments; } throw new \InvalidArgumentException(sprintf('Malformed field path "%s"', $name)); } } PK!LoTT+Symfony/Component/DomCrawler/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler; /** * Link represents an HTML link (an HTML a or area tag). * * @author Fabien Potencier * * @api */ class Link { /** * @var \DOMNode A \DOMNode instance */ protected $node; /** * @var string The method to use for the link */ protected $method; /** * @var string The URI of the page where the link is embedded (or the base href) */ protected $currentUri; /** * Constructor. * * @param \DOMNode $node A \DOMNode instance * @param string $currentUri The URI of the page where the link is embedded (or the base href) * @param string $method The method to use for the link (get by default) * * @throws \InvalidArgumentException if the node is not a link * * @api */ public function __construct(\DOMNode $node, $currentUri, $method = 'GET') { if (!in_array(strtolower(substr($currentUri, 0, 4)), array('http', 'file'))) { throw new \InvalidArgumentException(sprintf('Current URI must be an absolute URL ("%s").', $currentUri)); } $this->setNode($node); $this->method = $method ? strtoupper($method) : null; $this->currentUri = $currentUri; } /** * Gets the node associated with this link. * * @return \DOMNode A \DOMNode instance */ public function getNode() { return $this->node; } /** * Gets the method associated with this link. * * @return string The method * * @api */ public function getMethod() { return $this->method; } /** * Gets the URI associated with this link. * * @return string The URI * * @api */ public function getUri() { $uri = trim($this->getRawUri()); // absolute URL? if (null !== parse_url($uri, PHP_URL_SCHEME)) { return $uri; } // empty URI if (!$uri) { return $this->currentUri; } // only an anchor if ('#' === $uri[0]) { $baseUri = $this->currentUri; if (false !== $pos = strpos($baseUri, '#')) { $baseUri = substr($baseUri, 0, $pos); } return $baseUri.$uri; } // only a query string if ('?' === $uri[0]) { $baseUri = $this->currentUri; // remove the query string from the current URI if (false !== $pos = strpos($baseUri, '?')) { $baseUri = substr($baseUri, 0, $pos); } return $baseUri.$uri; } // absolute URL with relative schema if (0 === strpos($uri, '//')) { return preg_replace('#^([^/]*)//.*$#', '$1', $this->currentUri).$uri; } $baseUri = preg_replace('#^(.*?//[^/]*)(?:\/.*)?$#', '$1', $this->currentUri); // absolute path if ('/' === $uri[0]) { return $baseUri.$uri; } // relative path $path = parse_url(substr($this->currentUri, strlen($baseUri)), PHP_URL_PATH); $path = $this->canonicalizePath(substr($path, 0, strrpos($path, '/')).'/'.$uri); return $baseUri.('' === $path || '/' !== $path[0] ? '/' : '').$path; } /** * Returns raw URI data. * * @return string */ protected function getRawUri() { return $this->node->getAttribute('href'); } /** * Returns the canonicalized URI path (see RFC 3986, section 5.2.4) * * @param string $path URI path * * @return string */ protected function canonicalizePath($path) { if ('' === $path || '/' === $path) { return $path; } if ('.' === substr($path, -1)) { $path = $path.'/'; } $output = array(); foreach (explode('/', $path) as $segment) { if ('..' === $segment) { array_pop($output); } elseif ('.' !== $segment) { array_push($output, $segment); } } return implode('/', $output); } /** * Sets current \DOMNode instance. * * @param \DOMNode $node A \DOMNode instance * * @throws \LogicException If given node is not an anchor */ protected function setNode(\DOMNode $node) { if ('a' != $node->nodeName && 'area' != $node->nodeName) { throw new \LogicException(sprintf('Unable to click on a "%s" tag.', $node->nodeName)); } $this->node = $node; } } PK!\Ud 0Symfony/Component/DomCrawler/Field/FormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * FormField is the abstract class for all form fields. * * @author Fabien Potencier */ abstract class FormField { /** * @var \DOMNode */ protected $node; /** * @var string */ protected $name; /** * @var string */ protected $value; /** * @var \DOMDocument */ protected $document; /** * @var \DOMXPath */ protected $xpath; /** * @var Boolean */ protected $disabled; /** * Constructor. * * @param \DOMNode $node The node associated with this field */ public function __construct(\DOMNode $node) { $this->node = $node; $this->name = $node->getAttribute('name'); $this->document = new \DOMDocument('1.0', 'UTF-8'); $this->node = $this->document->importNode($this->node, true); $root = $this->document->appendChild($this->document->createElement('_root')); $root->appendChild($this->node); $this->xpath = new \DOMXPath($this->document); $this->initialize(); } /** * Returns the name of the field. * * @return string The name of the field */ public function getName() { return $this->name; } /** * Gets the value of the field. * * @return string|array The value of the field */ public function getValue() { return $this->value; } /** * Sets the value of the field. * * @param string $value The value of the field * * @api */ public function setValue($value) { $this->value = (string) $value; } /** * Returns true if the field should be included in the submitted values. * * @return Boolean true if the field should be included in the submitted values, false otherwise */ public function hasValue() { return true; } /** * Check if the current field is disabled * * @return Boolean */ public function isDisabled() { return $this->node->hasAttribute('disabled'); } /** * Initializes the form field. */ abstract protected function initialize(); } PK!bڋvB B 4Symfony/Component/DomCrawler/Field/FileFormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * FileFormField represents a file form field (an HTML file input tag). * * @author Fabien Potencier * * @api */ class FileFormField extends FormField { /** * Sets the PHP error code associated with the field. * * @param integer $error The error code (one of UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, or UPLOAD_ERR_EXTENSION) * * @throws \InvalidArgumentException When error code doesn't exist */ public function setErrorCode($error) { $codes = array(UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_EXTENSION); if (!in_array($error, $codes)) { throw new \InvalidArgumentException(sprintf('The error code %s is not valid.', $error)); } $this->value = array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => $error, 'size' => 0); } /** * Sets the value of the field. * * @param string $value The value of the field * * @api */ public function upload($value) { $this->setValue($value); } /** * Sets the value of the field. * * @param string $value The value of the field */ public function setValue($value) { if (null !== $value && is_readable($value)) { $error = UPLOAD_ERR_OK; $size = filesize($value); $info = pathinfo($value); $name = $info['basename']; // copy to a tmp location $tmp = sys_get_temp_dir().'/'.sha1(uniqid(mt_rand(), true)); if (array_key_exists('extension', $info)) { $tmp .= '.'.$info['extension']; } if (is_file($tmp)) { unlink($tmp); } copy($value, $tmp); $value = $tmp; } else { $error = UPLOAD_ERR_NO_FILE; $size = 0; $name = ''; $value = ''; } $this->value = array('name' => $name, 'type' => '', 'tmp_name' => $value, 'error' => $error, 'size' => $size); } /** * Sets path to the file as string for simulating HTTP request * * @param string $path The path to the file */ public function setFilePath($path) { parent::setValue($path); } /** * Initializes the form field. * * @throws \LogicException When node type is incorrect */ protected function initialize() { if ('input' != $this->node->nodeName) { throw new \LogicException(sprintf('A FileFormField can only be created from an input tag (%s given).', $this->node->nodeName)); } if ('file' != $this->node->getAttribute('type')) { throw new \LogicException(sprintf('A FileFormField can only be created from an input tag with a type of file (given type is %s).', $this->node->getAttribute('type'))); } $this->setValue(null); } } PK! Y[$[$6Symfony/Component/DomCrawler/Field/ChoiceFormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * ChoiceFormField represents a choice form field. * * It is constructed from a HTML select tag, or a HTML checkbox, or radio inputs. * * @author Fabien Potencier * * @api */ class ChoiceFormField extends FormField { /** * @var string */ private $type; /** * @var Boolean */ private $multiple; /** * @var array */ private $options; /** * @var boolean */ private $validationDisabled = false; /** * Returns true if the field should be included in the submitted values. * * @return Boolean true if the field should be included in the submitted values, false otherwise */ public function hasValue() { // don't send a value for unchecked checkboxes if (in_array($this->type, array('checkbox', 'radio')) && null === $this->value) { return false; } return true; } /** * Check if the current selected option is disabled * * @return Boolean */ public function isDisabled() { foreach ($this->options as $option) { if ($option['value'] == $this->value && $option['disabled']) { return true; } } return false; } /** * Sets the value of the field. * * @param string $value The value of the field * * @api */ public function select($value) { $this->setValue($value); } /** * Ticks a checkbox. * * @throws \LogicException When the type provided is not correct * * @api */ public function tick() { if ('checkbox' !== $this->type) { throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type)); } $this->setValue(true); } /** * Ticks a checkbox. * * @throws \LogicException When the type provided is not correct * * @api */ public function untick() { if ('checkbox' !== $this->type) { throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type)); } $this->setValue(false); } /** * Sets the value of the field. * * @param string $value The value of the field * * @throws \InvalidArgumentException When value type provided is not correct */ public function setValue($value) { if ('checkbox' == $this->type && false === $value) { // uncheck $this->value = null; } elseif ('checkbox' == $this->type && true === $value) { // check $this->value = $this->options[0]['value']; } else { if (is_array($value)) { if (!$this->multiple) { throw new \InvalidArgumentException(sprintf('The value for "%s" cannot be an array.', $this->name)); } foreach ($value as $v) { if (!$this->containsOption($v, $this->options)) { throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $v, implode(', ', $this->availableOptionValues()))); } } } elseif (!$this->containsOption($value, $this->options)) { throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $value, implode(', ', $this->availableOptionValues()))); } if ($this->multiple) { $value = (array) $value; } if (is_array($value)) { $this->value = $value; } else { parent::setValue($value); } } } /** * Adds a choice to the current ones. * * This method should only be used internally. * * @param \DOMNode $node A \DOMNode * * @throws \LogicException When choice provided is not multiple nor radio */ public function addChoice(\DOMNode $node) { if (!$this->multiple && 'radio' != $this->type) { throw new \LogicException(sprintf('Unable to add a choice for "%s" as it is not multiple or is not a radio button.', $this->name)); } $option = $this->buildOptionValue($node); $this->options[] = $option; if ($node->getAttribute('checked')) { $this->value = $option['value']; } } /** * Returns the type of the choice field (radio, select, or checkbox). * * @return string The type */ public function getType() { return $this->type; } /** * Returns true if the field accepts multiple values. * * @return Boolean true if the field accepts multiple values, false otherwise */ public function isMultiple() { return $this->multiple; } /** * Initializes the form field. * * @throws \LogicException When node type is incorrect */ protected function initialize() { if ('input' != $this->node->nodeName && 'select' != $this->node->nodeName) { throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input or select tag (%s given).', $this->node->nodeName)); } if ('input' == $this->node->nodeName && 'checkbox' != $this->node->getAttribute('type') && 'radio' != $this->node->getAttribute('type')) { throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input tag with a type of checkbox or radio (given type is %s).', $this->node->getAttribute('type'))); } $this->value = null; $this->options = array(); $this->multiple = false; if ('input' == $this->node->nodeName) { $this->type = $this->node->getAttribute('type'); $optionValue = $this->buildOptionValue($this->node); $this->options[] = $optionValue; if ($this->node->getAttribute('checked')) { $this->value = $optionValue['value']; } } else { $this->type = 'select'; if ($this->node->hasAttribute('multiple')) { $this->multiple = true; $this->value = array(); $this->name = str_replace('[]', '', $this->name); } $found = false; foreach ($this->xpath->query('descendant::option', $this->node) as $option) { $this->options[] = $this->buildOptionValue($option); if ($option->getAttribute('selected')) { $found = true; if ($this->multiple) { $this->value[] = $option->getAttribute('value'); } else { $this->value = $option->getAttribute('value'); } } } // if no option is selected and if it is a simple select box, take the first option as the value $option = $this->xpath->query('descendant::option', $this->node)->item(0); if (!$found && !$this->multiple && $option instanceof \DOMElement) { $this->value = $option->getAttribute('value'); } } } /** * Returns option value with associated disabled flag * * @param \DOMNode $node * * @return array */ private function buildOptionValue($node) { $option = array(); $defaultValue = (isset($node->nodeValue) && !empty($node->nodeValue)) ? $node->nodeValue : '1'; $option['value'] = $node->hasAttribute('value') ? $node->getAttribute('value') : $defaultValue; $option['disabled'] = ($node->hasAttribute('disabled') && $node->getAttribute('disabled') == 'disabled'); return $option; } /** * Checks whether given vale is in the existing options * * @param string $optionValue * @param array $options * * @return bool */ public function containsOption($optionValue, $options) { if ($this->validationDisabled) { return true; } foreach ($options as $option) { if ($option['value'] == $optionValue) { return true; } } return false; } /** * Returns list of available field options * * @return array */ public function availableOptionValues() { $values = array(); foreach ($this->options as $option) { $values[] = $option['value']; } return $values; } /** * Disables the internal validation of the field. * * @return self */ public function disableValidation() { $this->validationDisabled = true; return $this; } } PK! ʀ8Symfony/Component/DomCrawler/Field/TextareaFormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * TextareaFormField represents a textarea form field (an HTML textarea tag). * * @author Fabien Potencier * * @api */ class TextareaFormField extends FormField { /** * Initializes the form field. * * @throws \LogicException When node type is incorrect */ protected function initialize() { if ('textarea' != $this->node->nodeName) { throw new \LogicException(sprintf('A TextareaFormField can only be created from a textarea tag (%s given).', $this->node->nodeName)); } $this->value = null; foreach ($this->node->childNodes as $node) { $this->value .= $node->wholeText; } } } PK!5Symfony/Component/DomCrawler/Field/InputFormField.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Field; /** * InputFormField represents an input form field (an HTML input tag). * * For inputs with type of file, checkbox, or radio, there are other more * specialized classes (cf. FileFormField and ChoiceFormField). * * @author Fabien Potencier * * @api */ class InputFormField extends FormField { /** * Initializes the form field. * * @throws \LogicException When node type is incorrect */ protected function initialize() { if ('input' != $this->node->nodeName && 'button' != $this->node->nodeName) { throw new \LogicException(sprintf('An InputFormField can only be created from an input or button tag (%s given).', $this->node->nodeName)); } if ('checkbox' == $this->node->getAttribute('type')) { throw new \LogicException('Checkboxes should be instances of ChoiceFormField.'); } if ('file' == $this->node->getAttribute('type')) { throw new \LogicException('File inputs should be instances of FileFormField.'); } $this->value = $this->node->getAttribute('value'); } } PK!<4{bb(Symfony/Component/DomCrawler/Crawler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler; use Symfony\Component\CssSelector\CssSelector; /** * Crawler eases navigation of a list of \DOMNode objects. * * @author Fabien Potencier * * @api */ class Crawler extends \SplObjectStorage { /** * @var string The current URI or the base href value */ protected $uri; /** * @var string The default namespace prefix to be used with XPath and CSS expressions */ private $defaultNamespacePrefix = 'default'; /** * @var array A map of manually registered namespaces */ private $namespaces = array(); /** * Constructor. * * @param mixed $node A Node to use as the base for the crawling * @param string $uri The current URI or the base href value * * @api */ public function __construct($node = null, $uri = null) { $this->uri = $uri; $this->add($node); } /** * Removes all the nodes. * * @api */ public function clear() { $this->removeAll($this); } /** * Adds a node to the current list of nodes. * * This method uses the appropriate specialized add*() method based * on the type of the argument. * * @param \DOMNodeList|\DOMNode|array|string|null $node A node * * @throws \InvalidArgumentException When node is not the expected type. * * @api */ public function add($node) { if ($node instanceof \DOMNodeList) { $this->addNodeList($node); } elseif ($node instanceof \DOMNode) { $this->addNode($node); } elseif (is_array($node)) { $this->addNodes($node); } elseif (is_string($node)) { $this->addContent($node); } elseif (null !== $node) { throw new \InvalidArgumentException(sprintf('Expecting a DOMNodeList or DOMNode instance, an array, a string, or null, but got "%s".', is_object($node) ? get_class($node) : gettype($node))); } } /** * Adds HTML/XML content. * * If the charset is not set via the content type, it is assumed * to be ISO-8859-1, which is the default charset defined by the * HTTP 1.1 specification. * * @param string $content A string to parse as HTML/XML * @param null|string $type The content type of the string */ public function addContent($content, $type = null) { if (empty($type)) { $type = 0 === strpos($content, ']+charset *= *["\']?([a-zA-Z\-0-9]+)/i', $content, $matches)) { $charset = $matches[1]; } if (null === $charset) { $charset = 'ISO-8859-1'; } if ('x' === $xmlMatches[1]) { $this->addXmlContent($content, $charset); } else { $this->addHtmlContent($content, $charset); } } /** * Adds an HTML content to the list of nodes. * * The libxml errors are disabled when the content is parsed. * * If you want to get parsing errors, be sure to enable * internal errors via libxml_use_internal_errors(true) * and then, get the errors via libxml_get_errors(). Be * sure to clear errors with libxml_clear_errors() afterward. * * @param string $content The HTML content * @param string $charset The charset * * @api */ public function addHtmlContent($content, $charset = 'UTF-8') { $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); $dom = new \DOMDocument('1.0', $charset); $dom->validateOnParse = true; if (function_exists('mb_convert_encoding')) { $hasError = false; set_error_handler(function () use (&$hasError) { $hasError = true; }); $tmpContent = @mb_convert_encoding($content, 'HTML-ENTITIES', $charset); restore_error_handler(); if (!$hasError) { $content = $tmpContent; } } if ('' !== trim($content)) { @$dom->loadHTML($content); } libxml_use_internal_errors($internalErrors); libxml_disable_entity_loader($disableEntities); $this->addDocument($dom); $base = $this->filterXPath('descendant-or-self::base')->extract(array('href')); $baseHref = current($base); if (count($base) && !empty($baseHref)) { if ($this->uri) { $linkNode = $dom->createElement('a'); $linkNode->setAttribute('href', $baseHref); $link = new Link($linkNode, $this->uri); $this->uri = $link->getUri(); } else { $this->uri = $baseHref; } } } /** * Adds an XML content to the list of nodes. * * The libxml errors are disabled when the content is parsed. * * If you want to get parsing errors, be sure to enable * internal errors via libxml_use_internal_errors(true) * and then, get the errors via libxml_get_errors(). Be * sure to clear errors with libxml_clear_errors() afterward. * * @param string $content The XML content * @param string $charset The charset * * @api */ public function addXmlContent($content, $charset = 'UTF-8') { // remove the default namespace if it's the only namespace to make XPath expressions simpler if (!preg_match('/xmlns:/', $content)) { $content = str_replace('xmlns', 'ns', $content); } $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); $dom = new \DOMDocument('1.0', $charset); $dom->validateOnParse = true; if ('' !== trim($content)) { @$dom->loadXML($content, LIBXML_NONET); } libxml_use_internal_errors($internalErrors); libxml_disable_entity_loader($disableEntities); $this->addDocument($dom); } /** * Adds a \DOMDocument to the list of nodes. * * @param \DOMDocument $dom A \DOMDocument instance * * @api */ public function addDocument(\DOMDocument $dom) { if ($dom->documentElement) { $this->addNode($dom->documentElement); } } /** * Adds a \DOMNodeList to the list of nodes. * * @param \DOMNodeList $nodes A \DOMNodeList instance * * @api */ public function addNodeList(\DOMNodeList $nodes) { foreach ($nodes as $node) { $this->addNode($node); } } /** * Adds an array of \DOMNode instances to the list of nodes. * * @param \DOMNode[] $nodes An array of \DOMNode instances * * @api */ public function addNodes(array $nodes) { foreach ($nodes as $node) { $this->add($node); } } /** * Adds a \DOMNode instance to the list of nodes. * * @param \DOMNode $node A \DOMNode instance * * @api */ public function addNode(\DOMNode $node) { if ($node instanceof \DOMDocument) { $this->attach($node->documentElement); } else { $this->attach($node); } } /** * Returns a node given its position in the node list. * * @param integer $position The position * * @return Crawler A new instance of the Crawler with the selected node, or an empty Crawler if it does not exist. * * @api */ public function eq($position) { foreach ($this as $i => $node) { if ($i == $position) { return new static($node, $this->uri); } } return new static(null, $this->uri); } /** * Calls an anonymous function on each node of the list. * * The anonymous function receives the position and the node wrapped * in a Crawler instance as arguments. * * Example: * * $crawler->filter('h1')->each(function ($node, $i) { * return $node->text(); * }); * * @param \Closure $closure An anonymous function * * @return array An array of values returned by the anonymous function * * @api */ public function each(\Closure $closure) { $data = array(); foreach ($this as $i => $node) { $data[] = $closure(new static($node, $this->uri), $i); } return $data; } /** * Reduces the list of nodes by calling an anonymous function. * * To remove a node from the list, the anonymous function must return false. * * @param \Closure $closure An anonymous function * * @return Crawler A Crawler instance with the selected nodes. * * @api */ public function reduce(\Closure $closure) { $nodes = array(); foreach ($this as $i => $node) { if (false !== $closure(new static($node, $this->uri), $i)) { $nodes[] = $node; } } return new static($nodes, $this->uri); } /** * Returns the first node of the current selection * * @return Crawler A Crawler instance with the first selected node * * @api */ public function first() { return $this->eq(0); } /** * Returns the last node of the current selection * * @return Crawler A Crawler instance with the last selected node * * @api */ public function last() { return $this->eq(count($this) - 1); } /** * Returns the siblings nodes of the current selection * * @return Crawler A Crawler instance with the sibling nodes * * @throws \InvalidArgumentException When current node is empty * * @api */ public function siblings() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } return new static($this->sibling($this->getNode(0)->parentNode->firstChild), $this->uri); } /** * Returns the next siblings nodes of the current selection * * @return Crawler A Crawler instance with the next sibling nodes * * @throws \InvalidArgumentException When current node is empty * * @api */ public function nextAll() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } return new static($this->sibling($this->getNode(0)), $this->uri); } /** * Returns the previous sibling nodes of the current selection * * @return Crawler A Crawler instance with the previous sibling nodes * * @throws \InvalidArgumentException * * @api */ public function previousAll() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } return new static($this->sibling($this->getNode(0), 'previousSibling'), $this->uri); } /** * Returns the parents nodes of the current selection * * @return Crawler A Crawler instance with the parents nodes of the current selection * * @throws \InvalidArgumentException When current node is empty * * @api */ public function parents() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $node = $this->getNode(0); $nodes = array(); while ($node = $node->parentNode) { if (1 === $node->nodeType && '_root' !== $node->nodeName) { $nodes[] = $node; } } return new static($nodes, $this->uri); } /** * Returns the children nodes of the current selection * * @return Crawler A Crawler instance with the children nodes * * @throws \InvalidArgumentException When current node is empty * * @api */ public function children() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $node = $this->getNode(0)->firstChild; return new static($node ? $this->sibling($node) : array(), $this->uri); } /** * Returns the attribute value of the first node of the list. * * @param string $attribute The attribute name * * @return string|null The attribute value or null if the attribute does not exist * * @throws \InvalidArgumentException When current node is empty * * @api */ public function attr($attribute) { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $node = $this->getNode(0); return $node->hasAttribute($attribute) ? $node->getAttribute($attribute) : null; } /** * Returns the node value of the first node of the list. * * @return string The node value * * @throws \InvalidArgumentException When current node is empty * * @api */ public function text() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } return $this->getNode(0)->nodeValue; } /** * Returns the first node of the list as HTML. * * @return string The node html * * @throws \InvalidArgumentException When current node is empty */ public function html() { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $html = ''; foreach ($this->getNode(0)->childNodes as $child) { if (version_compare(PHP_VERSION, '5.3.6', '>=')) { // node parameter was added to the saveHTML() method in PHP 5.3.6 // @see http://php.net/manual/en/domdocument.savehtml.php $html .= $child->ownerDocument->saveHTML($child); } else { $document = new \DOMDocument('1.0', 'UTF-8'); $document->appendChild($document->importNode($child, true)); $html .= rtrim($document->saveHTML()); } } return $html; } /** * Extracts information from the list of nodes. * * You can extract attributes or/and the node value (_text). * * Example: * * $crawler->filter('h1 a')->extract(array('_text', 'href')); * * @param array $attributes An array of attributes * * @return array An array of extracted values * * @api */ public function extract($attributes) { $attributes = (array) $attributes; $count = count($attributes); $data = array(); foreach ($this as $node) { $elements = array(); foreach ($attributes as $attribute) { if ('_text' === $attribute) { $elements[] = $node->nodeValue; } else { $elements[] = $node->getAttribute($attribute); } } $data[] = $count > 1 ? $elements : $elements[0]; } return $data; } /** * Filters the list of nodes with an XPath expression. * * @param string $xpath An XPath expression * * @return Crawler A new instance of Crawler with the filtered list of nodes * * @api */ public function filterXPath($xpath) { $document = new \DOMDocument('1.0', 'UTF-8'); $root = $document->appendChild($document->createElement('_root')); foreach ($this as $node) { $root->appendChild($document->importNode($node, true)); } $prefixes = $this->findNamespacePrefixes($xpath); $domxpath = $this->createDOMXPath($document, $prefixes); return new static($domxpath->query($xpath), $this->uri); } /** * Filters the list of nodes with a CSS selector. * * This method only works if you have installed the CssSelector Symfony Component. * * @param string $selector A CSS selector * * @return Crawler A new instance of Crawler with the filtered list of nodes * * @throws \RuntimeException if the CssSelector Component is not available * * @api */ public function filter($selector) { if (!class_exists('Symfony\\Component\\CssSelector\\CssSelector')) { // @codeCoverageIgnoreStart throw new \RuntimeException('Unable to filter with a CSS selector as the Symfony CssSelector is not installed (you can use filterXPath instead).'); // @codeCoverageIgnoreEnd } return $this->filterXPath(CssSelector::toXPath($selector)); } /** * Selects links by name or alt value for clickable images. * * @param string $value The link text * * @return Crawler A new instance of Crawler with the filtered list of nodes * * @api */ public function selectLink($value) { $xpath = sprintf('//a[contains(concat(\' \', normalize-space(string(.)), \' \'), %s)] ', static::xpathLiteral(' '.$value.' ')). sprintf('| //a/img[contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)]/ancestor::a', static::xpathLiteral(' '.$value.' ')); return $this->filterXPath($xpath); } /** * Selects a button by name or alt value for images. * * @param string $value The button text * * @return Crawler A new instance of Crawler with the filtered list of nodes * * @api */ public function selectButton($value) { $xpath = sprintf('//input[((@type="submit" or @type="button") and contains(concat(\' \', normalize-space(string(@value)), \' \'), %s)) ', static::xpathLiteral(' '.$value.' ')). sprintf('or (@type="image" and contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)) or @id="%s" or @name="%s"] ', static::xpathLiteral(' '.$value.' '), $value, $value). sprintf('| //button[contains(concat(\' \', normalize-space(string(.)), \' \'), %s) or @id="%s" or @name="%s"]', static::xpathLiteral(' '.$value.' '), $value, $value); return $this->filterXPath($xpath); } /** * Returns a Link object for the first node in the list. * * @param string $method The method for the link (get by default) * * @return Link A Link instance * * @throws \InvalidArgumentException If the current node list is empty * * @api */ public function link($method = 'get') { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $node = $this->getNode(0); return new Link($node, $this->uri, $method); } /** * Returns an array of Link objects for the nodes in the list. * * @return Link[] An array of Link instances * * @api */ public function links() { $links = array(); foreach ($this as $node) { $links[] = new Link($node, $this->uri, 'get'); } return $links; } /** * Returns a Form object for the first node in the list. * * @param array $values An array of values for the form fields * @param string $method The method for the form * * @return Form A Form instance * * @throws \InvalidArgumentException If the current node list is empty * * @api */ public function form(array $values = null, $method = null) { if (!count($this)) { throw new \InvalidArgumentException('The current node list is empty.'); } $form = new Form($this->getNode(0), $this->uri, $method); if (null !== $values) { $form->setValues($values); } return $form; } /** * Overloads a default namespace prefix to be used with XPath and CSS expressions. * * @param string $prefix */ public function setDefaultNamespacePrefix($prefix) { $this->defaultNamespacePrefix = $prefix; } /** * @param string $prefix * @param string $namespace */ public function registerNamespace($prefix, $namespace) { $this->namespaces[$prefix] = $namespace; } /** * Converts string for XPath expressions. * * Escaped characters are: quotes (") and apostrophe ('). * * Examples: * * echo Crawler::xpathLiteral('foo " bar'); * //prints 'foo " bar' * * echo Crawler::xpathLiteral("foo ' bar"); * //prints "foo ' bar" * * echo Crawler::xpathLiteral('a\'b"c'); * //prints concat('a', "'", 'b"c') * * * @param string $s String to be escaped * * @return string Converted string */ public static function xpathLiteral($s) { if (false === strpos($s, "'")) { return sprintf("'%s'", $s); } if (false === strpos($s, '"')) { return sprintf('"%s"', $s); } $string = $s; $parts = array(); while (true) { if (false !== $pos = strpos($string, "'")) { $parts[] = sprintf("'%s'", substr($string, 0, $pos)); $parts[] = "\"'\""; $string = substr($string, $pos + 1); } else { $parts[] = "'$string'"; break; } } return sprintf("concat(%s)", implode($parts, ', ')); } /** * @param integer $position * * @return \DOMElement|null */ public function getNode($position) { foreach ($this as $i => $node) { if ($i == $position) { return $node; } // @codeCoverageIgnoreStart } return null; // @codeCoverageIgnoreEnd } /** * @param \DOMElement $node * @param string $siblingDir * * @return array */ protected function sibling($node, $siblingDir = 'nextSibling') { $nodes = array(); do { if ($node !== $this->getNode(0) && $node->nodeType === 1) { $nodes[] = $node; } } while ($node = $node->$siblingDir); return $nodes; } /** * @param \DOMDocument $document * @param array $prefixes * * @return \DOMXPath * * @throws \InvalidArgumentException */ private function createDOMXPath(\DOMDocument $document, array $prefixes = array()) { $domxpath = new \DOMXPath($document); foreach ($prefixes as $prefix) { $namespace = $this->discoverNamespace($domxpath, $prefix); if (null !== $namespace) { $domxpath->registerNamespace($prefix, $namespace); } } return $domxpath; } /** * @param \DOMXPath $domxpath * @param string $prefix * * @return string * * @throws \InvalidArgumentException */ private function discoverNamespace(\DOMXPath $domxpath, $prefix) { if (isset($this->namespaces[$prefix])) { return $this->namespaces[$prefix]; } // ask for one namespace, otherwise we'd get a collection with an item for each node $namespaces = $domxpath->query(sprintf('(//namespace::*[name()="%s"])[last()]', $this->defaultNamespacePrefix === $prefix ? '' : $prefix)); if ($node = $namespaces->item(0)) { return $node->nodeValue; } } /** * @param $xpath * * @return array */ private function findNamespacePrefixes($xpath) { if (preg_match_all('/(?P[a-z_][a-z_0-9\-\.]*):[^"\/]/i', $xpath, $matches)) { return array_unique($matches['prefix']); } return array(); } } PK! H7H7%Symfony/Component/DomCrawler/Form.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler; use Symfony\Component\DomCrawler\Field\FormField; /** * Form represents an HTML form. * * @author Fabien Potencier * * @api */ class Form extends Link implements \ArrayAccess { /** * @var \DOMNode */ private $button; /** * @var Field\FormField[] */ private $fields; /** * Constructor. * * @param \DOMNode $node A \DOMNode instance * @param string $currentUri The URI of the page where the form is embedded * @param string $method The method to use for the link (if null, it defaults to the method defined by the form) * * @throws \LogicException if the node is not a button inside a form tag * * @api */ public function __construct(\DOMNode $node, $currentUri, $method = null) { parent::__construct($node, $currentUri, $method); $this->initialize(); } /** * Gets the form node associated with this form. * * @return \DOMNode A \DOMNode instance */ public function getFormNode() { return $this->node; } /** * Sets the value of the fields. * * @param array $values An array of field values * * @return Form * * @api */ public function setValues(array $values) { foreach ($values as $name => $value) { $this->fields->set($name, $value); } return $this; } /** * Gets the field values. * * The returned array does not include file fields (@see getFiles). * * @return array An array of field values. * * @api */ public function getValues() { $values = array(); foreach ($this->fields->all() as $name => $field) { if ($field->isDisabled()) { continue; } if (!$field instanceof Field\FileFormField && $field->hasValue()) { $values[$name] = $field->getValue(); } } return $values; } /** * Gets the file field values. * * @return array An array of file field values. * * @api */ public function getFiles() { if (!in_array($this->getMethod(), array('POST', 'PUT', 'DELETE', 'PATCH'))) { return array(); } $files = array(); foreach ($this->fields->all() as $name => $field) { if ($field->isDisabled()) { continue; } if ($field instanceof Field\FileFormField) { $files[$name] = $field->getValue(); } } return $files; } /** * Gets the field values as PHP. * * This method converts fields with the array notation * (like foo[bar] to arrays) like PHP does. * * @return array An array of field values. * * @api */ public function getPhpValues() { $values = array(); foreach ($this->getValues() as $name => $value) { $qs = http_build_query(array($name => $value), '', '&'); parse_str($qs, $expandedValue); $varName = substr($name, 0, strlen(key($expandedValue))); $values = array_replace_recursive($values, array($varName => current($expandedValue))); } return $values; } /** * Gets the file field values as PHP. * * This method converts fields with the array notation * (like foo[bar] to arrays) like PHP does. * * @return array An array of field values. * * @api */ public function getPhpFiles() { $values = array(); foreach ($this->getFiles() as $name => $value) { $qs = http_build_query(array($name => $value), '', '&'); parse_str($qs, $expandedValue); $varName = substr($name, 0, strlen(key($expandedValue))); $values = array_replace_recursive($values, array($varName => current($expandedValue))); } return $values; } /** * Gets the URI of the form. * * The returned URI is not the same as the form "action" attribute. * This method merges the value if the method is GET to mimics * browser behavior. * * @return string The URI * * @api */ public function getUri() { $uri = parent::getUri(); if (!in_array($this->getMethod(), array('POST', 'PUT', 'DELETE', 'PATCH')) && $queryString = http_build_query($this->getValues(), null, '&')) { $sep = false === strpos($uri, '?') ? '?' : '&'; $uri .= $sep.$queryString; } return $uri; } protected function getRawUri() { return $this->node->getAttribute('action'); } /** * Gets the form method. * * If no method is defined in the form, GET is returned. * * @return string The method * * @api */ public function getMethod() { if (null !== $this->method) { return $this->method; } return $this->node->getAttribute('method') ? strtoupper($this->node->getAttribute('method')) : 'GET'; } /** * Returns true if the named field exists. * * @param string $name The field name * * @return Boolean true if the field exists, false otherwise * * @api */ public function has($name) { return $this->fields->has($name); } /** * Removes a field from the form. * * @param string $name The field name * * @throws \InvalidArgumentException when the name is malformed * * @api */ public function remove($name) { $this->fields->remove($name); } /** * Gets a named field. * * @param string $name The field name * * @return FormField The field instance * * @throws \InvalidArgumentException When field is not present in this form * * @api */ public function get($name) { return $this->fields->get($name); } /** * Sets a named field. * * @param FormField $field The field * * @api */ public function set(FormField $field) { $this->fields->add($field); } /** * Gets all fields. * * @return FormField[] An array of fields * * @api */ public function all() { return $this->fields->all(); } /** * Returns true if the named field exists. * * @param string $name The field name * * @return Boolean true if the field exists, false otherwise */ public function offsetExists($name) { return $this->has($name); } /** * Gets the value of a field. * * @param string $name The field name * * @return FormField The associated Field instance * * @throws \InvalidArgumentException if the field does not exist */ public function offsetGet($name) { return $this->fields->get($name); } /** * Sets the value of a field. * * @param string $name The field name * @param string|array $value The value of the field * * @throws \InvalidArgumentException if the field does not exist */ public function offsetSet($name, $value) { $this->fields->set($name, $value); } /** * Removes a field from the form. * * @param string $name The field name */ public function offsetUnset($name) { $this->fields->remove($name); } /** * Disables validation * * @return self */ public function disableValidation() { foreach ($this->fields->all() as $field) { if ($field instanceof Field\ChoiceFormField) { $field->disableValidation(); } } return $this; } /** * Sets the node for the form. * * Expects a 'submit' button \DOMNode and finds the corresponding form element. * * @param \DOMNode $node A \DOMNode instance * * @throws \LogicException If given node is not a button or input or does not have a form ancestor */ protected function setNode(\DOMNode $node) { $this->button = $node; if ('button' == $node->nodeName || ('input' == $node->nodeName && in_array($node->getAttribute('type'), array('submit', 'button', 'image')))) { if ($node->hasAttribute('form')) { // if the node has the HTML5-compliant 'form' attribute, use it $formId = $node->getAttribute('form'); $form = $node->ownerDocument->getElementById($formId); if (null === $form) { throw new \LogicException(sprintf('The selected node has an invalid form attribute (%s).', $formId)); } $this->node = $form; return; } // we loop until we find a form ancestor do { if (null === $node = $node->parentNode) { throw new \LogicException('The selected node does not have a form ancestor.'); } } while ('form' != $node->nodeName); } elseif ('form' != $node->nodeName) { throw new \LogicException(sprintf('Unable to submit on a "%s" tag.', $node->nodeName)); } $this->node = $node; } /** * Adds form elements related to this form. * * Creates an internal copy of the submitted 'button' element and * the form node or the entire document depending on whether we need * to find non-descendant elements through HTML5 'form' attribute. */ private function initialize() { $this->fields = new FormFieldRegistry(); $document = new \DOMDocument('1.0', 'UTF-8'); $xpath = new \DOMXPath($document); $root = $document->appendChild($document->createElement('_root')); // add submitted button if it has a valid name if ('form' !== $this->button->nodeName && $this->button->hasAttribute('name') && $this->button->getAttribute('name')) { if ('input' == $this->button->nodeName && 'image' == $this->button->getAttribute('type')) { $name = $this->button->getAttribute('name'); $this->button->setAttribute('value', '0'); // temporarily change the name of the input node for the x coordinate $this->button->setAttribute('name', $name.'.x'); $this->set(new Field\InputFormField($document->importNode($this->button, true))); // temporarily change the name of the input node for the y coordinate $this->button->setAttribute('name', $name.'.y'); $this->set(new Field\InputFormField($document->importNode($this->button, true))); // restore the original name of the input node $this->button->setAttribute('name', $name); } else { $this->set(new Field\InputFormField($document->importNode($this->button, true))); } } // find form elements corresponding to the current form if ($this->node->hasAttribute('id')) { // traverse through the whole document $node = $document->importNode($this->node->ownerDocument->documentElement, true); $root->appendChild($node); // corresponding elements are either descendants or have a matching HTML5 form attribute $formId = Crawler::xpathLiteral($this->node->getAttribute('id')); $fieldNodes = $xpath->query(sprintf('descendant::input[@form=%s] | descendant::button[@form=%s] | descendant::textarea[@form=%s] | descendant::select[@form=%s] | //form[@id=%s]//input[not(@form)] | //form[@id=%s]//button[not(@form)] | //form[@id=%s]//textarea[not(@form)] | //form[@id=%s]//select[not(@form)]', $formId, $formId, $formId, $formId, $formId, $formId, $formId, $formId), $root); foreach ($fieldNodes as $node) { $this->addField($node); } } else { // parent form has no id, add descendant elements only $node = $document->importNode($this->node, true); $root->appendChild($node); // descendant elements with form attribute are not part of this form $fieldNodes = $xpath->query('descendant::input[not(@form)] | descendant::button[not(@form)] | descendant::textarea[not(@form)] | descendant::select[not(@form)]', $root); foreach ($fieldNodes as $node) { $this->addField($node); } } } private function addField(\DOMNode $node) { if (!$node->hasAttribute('name') || !$node->getAttribute('name')) { return; } $nodeName = $node->nodeName; if ('select' == $nodeName || 'input' == $nodeName && 'checkbox' == $node->getAttribute('type')) { $this->set(new Field\ChoiceFormField($node)); } elseif ('input' == $nodeName && 'radio' == $node->getAttribute('type')) { if ($this->has($node->getAttribute('name'))) { $this->get($node->getAttribute('name'))->addChoice($node); } else { $this->set(new Field\ChoiceFormField($node)); } } elseif ('input' == $nodeName && 'file' == $node->getAttribute('type')) { $this->set(new Field\FileFormField($node)); } elseif ('input' == $nodeName && !in_array($node->getAttribute('type'), array('submit', 'button', 'image'))) { $this->set(new Field\InputFormField($node)); } elseif ('textarea' == $nodeName) { $this->set(new Field\TextareaFormField($node)); } } } PK!!!2Symfony/Component/CssSelector/XPath/Translator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\Node\NodeInterface; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\Parser; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * XPath expression translator interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Translator implements TranslatorInterface { /** * @var ParserInterface */ private $mainParser; /** * @var ParserInterface[] */ private $shortcutParsers = array(); /** * @var Extension\ExtensionInterface */ private $extensions = array(); /** * @var array */ private $nodeTranslators = array(); /** * @var array */ private $combinationTranslators = array(); /** * @var array */ private $functionTranslators = array(); /** * @var array */ private $pseudoClassTranslators = array(); /** * @var array */ private $attributeMatchingTranslators = array(); /** * Constructor. */ public function __construct(ParserInterface $parser = null) { $this->mainParser = $parser ?: new Parser(); $this ->registerExtension(new Extension\NodeExtension($this)) ->registerExtension(new Extension\CombinationExtension()) ->registerExtension(new Extension\FunctionExtension()) ->registerExtension(new Extension\PseudoClassExtension()) ->registerExtension(new Extension\AttributeMatchingExtension()) ; } /** * @param string $element * * @return string */ public static function getXpathLiteral($element) { if (false === strpos($element, "'")) { return "'".$element."'"; } if (false === strpos($element, '"')) { return '"'.$element.'"'; } $string = $element; $parts = array(); while (true) { if (false !== $pos = strpos($string, "'")) { $parts[] = sprintf("'%s'", substr($string, 0, $pos)); $parts[] = "\"'\""; $string = substr($string, $pos + 1); } else { $parts[] = "'$string'"; break; } } return sprintf('concat(%s)', implode($parts, ', ')); } /** * {@inheritdoc} */ public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::') { $selectors = $this->parseSelectors($cssExpr); /** @var SelectorNode $selector */ foreach ($selectors as $selector) { if (null !== $selector->getPseudoElement()) { throw new ExpressionErrorException('Pseudo-elements are not supported.'); } } $translator = $this; return implode(' | ', array_map(function (SelectorNode $selector) use ($translator, $prefix) { return $translator->selectorToXPath($selector, $prefix); }, $selectors)); } /** * {@inheritdoc} */ public function selectorToXPath(SelectorNode $selector, $prefix = 'descendant-or-self::') { return ($prefix ?: '').$this->nodeToXPath($selector); } /** * Registers an extension. * * @param Extension\ExtensionInterface $extension * * @return Translator */ public function registerExtension(Extension\ExtensionInterface $extension) { $this->extensions[$extension->getName()] = $extension; $this->nodeTranslators = array_merge($this->nodeTranslators, $extension->getNodeTranslators()); $this->combinationTranslators = array_merge($this->combinationTranslators, $extension->getCombinationTranslators()); $this->functionTranslators = array_merge($this->functionTranslators, $extension->getFunctionTranslators()); $this->pseudoClassTranslators = array_merge($this->pseudoClassTranslators, $extension->getPseudoClassTranslators()); $this->attributeMatchingTranslators = array_merge($this->attributeMatchingTranslators, $extension->getAttributeMatchingTranslators()); return $this; } /** * @param string $name * * @return Extension\ExtensionInterface * * @throws ExpressionErrorException */ public function getExtension($name) { if (!isset($this->extensions[$name])) { throw new ExpressionErrorException(sprintf('Extension "%s" not registered.', $name)); } return $this->extensions[$name]; } /** * Registers a shortcut parser. * * @param ParserInterface $shortcut * * @return Translator */ public function registerParserShortcut(ParserInterface $shortcut) { $this->shortcutParsers[] = $shortcut; return $this; } /** * @param NodeInterface $node * * @return XPathExpr * * @throws ExpressionErrorException */ public function nodeToXPath(NodeInterface $node) { if (!isset($this->nodeTranslators[$node->getNodeName()])) { throw new ExpressionErrorException(sprintf('Node "%s" not supported.', $node->getNodeName())); } return call_user_func($this->nodeTranslators[$node->getNodeName()], $node); } /** * @param string $combiner * @param NodeInterface $xpath * @param NodeInterface $combinedXpath * * @return XPathExpr * * @throws ExpressionErrorException */ public function addCombination($combiner, NodeInterface $xpath, NodeInterface $combinedXpath) { if (!isset($this->combinationTranslators[$combiner])) { throw new ExpressionErrorException(sprintf('Combiner "%s" not supported.', $combiner)); } return call_user_func($this->combinationTranslators[$combiner], $this->nodeToXPath($xpath), $this->nodeToXPath($combinedXpath)); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function addFunction(XPathExpr $xpath, FunctionNode $function) { if (!isset($this->functionTranslators[$function->getName()])) { throw new ExpressionErrorException(sprintf('Function "%s" not supported.', $function->getName())); } return call_user_func($this->functionTranslators[$function->getName()], $xpath, $function); } /** * @param XPathExpr $xpath * @param string $pseudoClass * * @return XPathExpr * * @throws ExpressionErrorException */ public function addPseudoClass(XPathExpr $xpath, $pseudoClass) { if (!isset($this->pseudoClassTranslators[$pseudoClass])) { throw new ExpressionErrorException(sprintf('Pseudo-class "%s" not supported.', $pseudoClass)); } return call_user_func($this->pseudoClassTranslators[$pseudoClass], $xpath); } /** * @param XPathExpr $xpath * @param string $operator * @param string $attribute * @param string $value * * @throws ExpressionErrorException * * @return XPathExpr */ public function addAttributeMatching(XPathExpr $xpath, $operator, $attribute, $value) { if (!isset($this->attributeMatchingTranslators[$operator])) { throw new ExpressionErrorException(sprintf('Attribute matcher operator "%s" not supported.', $operator)); } return call_user_func($this->attributeMatchingTranslators[$operator], $xpath, $attribute, $value); } /** * @param string $css * * @return SelectorNode[] */ private function parseSelectors($css) { foreach ($this->shortcutParsers as $shortcut) { $tokens = $shortcut->parse($css); if (!empty($tokens)) { return $tokens; } } return $this->mainParser->parse($css); } } PK!r7 7 1Symfony/Component/CssSelector/XPath/XPathExpr.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; /** * XPath expression translator interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class XPathExpr { /** * @var string */ private $path; /** * @var string */ private $element; /** * @var string */ private $condition; /** * @param string $path * @param string $element * @param string $condition * @param boolean $starPrefix */ public function __construct($path = '', $element = '*', $condition = '', $starPrefix = false) { $this->path = $path; $this->element = $element; $this->condition = $condition; if ($starPrefix) { $this->addStarPrefix(); } } /** * @return string */ public function getElement() { return $this->element; } /** * @param $condition * * @return XPathExpr */ public function addCondition($condition) { $this->condition = $this->condition ? sprintf('%s and (%s)', $this->condition, $condition) : $condition; return $this; } /** * @return string */ public function getCondition() { return $this->condition; } /** * @return XPathExpr */ public function addNameTest() { if ('*' !== $this->element) { $this->addCondition('name() = '.Translator::getXpathLiteral($this->element)); $this->element = '*'; } return $this; } /** * @return XPathExpr */ public function addStarPrefix() { $this->path .= '*/'; return $this; } /** * Joins another XPathExpr with a combiner. * * @param string $combiner * @param XPathExpr $expr * * @return XPathExpr */ public function join($combiner, XPathExpr $expr) { $path = $this->__toString().$combiner; if ('*/' !== $expr->path) { $path .= $expr->path; } $this->path = $path; $this->element = $expr->element; $this->condition = $expr->condition; return $this; } /** * @return string */ public function __toString() { $path = $this->path.$this->element; $condition = null === $this->condition || '' === $this->condition ? '' : '['.$this->condition.']'; return $path.$condition; } } PK! ;Symfony/Component/CssSelector/XPath/TranslatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; use Symfony\Component\CssSelector\Node\SelectorNode; /** * XPath expression translator interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface TranslatorInterface { /** * Translates a CSS selector to an XPath expression. * * @param string $cssExpr * @param string $prefix * * @return XPathExpr */ public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::'); /** * Translates a parsed selector node to an XPath expression * * @param SelectorNode $selector * @param string $prefix * * @return XPathExpr */ public function selectorToXPath(SelectorNode $selector, $prefix = 'descendant-or-self::'); } PK!uCSymfony/Component/CssSelector/XPath/Extension/FunctionExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\Parser\Parser; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator function extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class FunctionExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getFunctionTranslators() { return array( 'nth-child' => array($this, 'translateNthChild'), 'nth-last-child' => array($this, 'translateNthLastChild'), 'nth-of-type' => array($this, 'translateNthOfType'), 'nth-last-of-type' => array($this, 'translateNthLastOfType'), 'contains' => array($this, 'translateContains'), 'lang' => array($this, 'translateLang'), ); } /** * @param XPathExpr $xpath * @param FunctionNode $function * @param boolean $last * @param boolean $addNameTest * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateNthChild(XPathExpr $xpath, FunctionNode $function, $last = false, $addNameTest = true) { try { list($a, $b) = Parser::parseSeries($function->getArguments()); } catch (SyntaxErrorException $e) { throw new ExpressionErrorException(sprintf('Invalid series: %s', implode(', ', $function->getArguments())), 0, $e); } $xpath->addStarPrefix(); if ($addNameTest) { $xpath->addNameTest(); } if (0 === $a) { return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b)); } if ($a < 0) { if ($b < 1) { return $xpath->addCondition('false()'); } $sign = '<='; } else { $sign = '>='; } $expr = 'position()'; if ($last) { $expr = 'last() - '.$expr; $b--; } if (0 !== $b) { $expr .= ' - '.$b; } $conditions = array(sprintf('%s %s 0', $expr, $sign)); if (1 !== $a && -1 !== $a) { $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a); } return $xpath->addCondition(implode(' and ', $conditions)); // todo: handle an+b, odd, even // an+b means every-a, plus b, e.g., 2n+1 means odd // 0n+b means b // n+0 means a=1, i.e., all elements // an means every a elements, i.e., 2n means even // -n means -1n // -1n+6 means elements 6 and previous } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr */ public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function) { return $this->translateNthChild($xpath, $function, true); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr */ public function translateNthOfType(XPathExpr $xpath, FunctionNode $function) { return $this->translateNthChild($xpath, $function, false, false); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function) { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.'); } return $this->translateNthChild($xpath, $function, true, false); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateContains(XPathExpr $xpath, FunctionNode $function) { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException( 'Expected a single string or identifier for :contains(), got ' .implode(', ', $arguments) ); } } return $xpath->addCondition(sprintf( 'contains(string(.), %s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function) { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException( 'Expected a single string or identifier for :lang(), got ' .implode(', ', $arguments) ); } } return $xpath->addCondition(sprintf( 'lang(%s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } /** * {@inheritdoc} */ public function getName() { return 'function'; } } PK!܍LSymfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator attribute extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class AttributeMatchingExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getAttributeMatchingTranslators() { return array( 'exists' => array($this, 'translateExists'), '=' => array($this, 'translateEquals'), '~=' => array($this, 'translateIncludes'), '|=' => array($this, 'translateDashMatch'), '^=' => array($this, 'translatePrefixMatch'), '$=' => array($this, 'translateSuffixMatch'), '*=' => array($this, 'translateSubstringMatch'), '!=' => array($this, 'translateDifferent'), ); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateExists(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($attribute); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateEquals(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition(sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value))); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateIncludes(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($value ? sprintf( '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)', $attribute, Translator::getXpathLiteral(' '.$value.' ') ) : '0'); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateDashMatch(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition(sprintf( '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))', $attribute, Translator::getXpathLiteral($value), Translator::getXpathLiteral($value.'-') )); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translatePrefixMatch(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($value ? sprintf( '%1$s and starts-with(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateSuffixMatch(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($value ? sprintf( '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s', $attribute, strlen($value) - 1, Translator::getXpathLiteral($value) ) : '0'); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateSubstringMatch(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition($value ? sprintf( '%1$s and contains(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } /** * @param XPathExpr $xpath * @param string $attribute * @param string $value * * @return XPathExpr */ public function translateDifferent(XPathExpr $xpath, $attribute, $value) { return $xpath->addCondition(sprintf( $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s', $attribute, Translator::getXpathLiteral($value) )); } /** * {@inheritdoc} */ public function getName() { return 'attribute-matching'; } } PK!Ѽ`PP?Symfony/Component/CssSelector/XPath/Extension/NodeExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator node extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class NodeExtension extends AbstractExtension { const ELEMENT_NAME_IN_LOWER_CASE = 1; const ATTRIBUTE_NAME_IN_LOWER_CASE = 2; const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4; /** * @var Translator */ private $translator; /** * @var int */ private $flags; /** * Constructor. * * @param Translator $translator * @param int $flags */ public function __construct(Translator $translator, $flags = 0) { $this->translator = $translator; $this->flags = $flags; } /** * @param int $flag * @param boolean $on * * @return NodeExtension */ public function setFlag($flag, $on) { if ($on && !$this->hasFlag($flag)) { $this->flags += $flag; } if (!$on && $this->hasFlag($flag)) { $this->flags -= $flag; } return $this; } /** * @param int $flag * * @return boolean */ public function hasFlag($flag) { return $this->flags & $flag; } /** * {@inheritdoc} */ public function getNodeTranslators() { return array( 'Selector' => array($this, 'translateSelector'), 'CombinedSelector' => array($this, 'translateCombinedSelector'), 'Negation' => array($this, 'translateNegation'), 'Function' => array($this, 'translateFunction'), 'Pseudo' => array($this, 'translatePseudo'), 'Attribute' => array($this, 'translateAttribute'), 'Class' => array($this, 'translateClass'), 'Hash' => array($this, 'translateHash'), 'Element' => array($this, 'translateElement'), ); } /** * @param Node\SelectorNode $node * * @return XPathExpr */ public function translateSelector(Node\SelectorNode $node) { return $this->translator->nodeToXPath($node->getTree()); } /** * @param Node\CombinedSelectorNode $node * * @return XPathExpr */ public function translateCombinedSelector(Node\CombinedSelectorNode $node) { return $this->translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector()); } /** * @param Node\NegationNode $node * * @return XPathExpr */ public function translateNegation(Node\NegationNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); $subXpath = $this->translator->nodeToXPath($node->getSubSelector()); $subXpath->addNameTest(); if ($subXpath->getCondition()) { return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition())); } return $xpath->addCondition('0'); } /** * @param Node\FunctionNode $node * * @return XPathExpr */ public function translateFunction(Node\FunctionNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); return $this->translator->addFunction($xpath, $node); } /** * @param Node\PseudoNode $node * * @return XPathExpr */ public function translatePseudo(Node\PseudoNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); return $this->translator->addPseudoClass($xpath, $node->getIdentifier()); } /** * @param Node\AttributeNode $node * * @return XPathExpr */ public function translateAttribute(Node\AttributeNode $node) { $name = $node->getAttribute(); $safe = $this->isSafeName($name); if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) { $name = strtolower($name); } if ($node->getNamespace()) { $name = sprintf('%s:%s', $node->getNamespace(), $name); $safe = $safe && $this->isSafeName($node->getNamespace()); } $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name)); $value = $node->getValue(); $xpath = $this->translator->nodeToXPath($node->getSelector()); if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) { $value = strtolower($value); } return $this->translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value); } /** * @param Node\ClassNode $node * * @return XPathExpr */ public function translateClass(Node\ClassNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); return $this->translator->addAttributeMatching($xpath, '~=', '@class', $node->getName()); } /** * @param Node\HashNode $node * * @return XPathExpr */ public function translateHash(Node\HashNode $node) { $xpath = $this->translator->nodeToXPath($node->getSelector()); return $this->translator->addAttributeMatching($xpath, '=', '@id', $node->getId()); } /** * @param Node\ElementNode $node * * @return XPathExpr */ public function translateElement(Node\ElementNode $node) { $element = $node->getElement(); if ($this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) { $element = strtolower($element); } if ($element) { $safe = $this->isSafeName($element); } else { $element = '*'; $safe = true; } if ($node->getNamespace()) { $element = sprintf('%s:%s', $node->getNamespace(), $element); $safe = $safe && $this->isSafeName($node->getNamespace()); } $xpath = new XPathExpr('', $element); if (!$safe) { $xpath->addNameTest(); } return $xpath; } /** * {@inheritdoc} */ public function getName() { return 'node'; } /** * Tests if given name is safe. * * @param string $name * * @return boolean */ private function isSafeName($name) { return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name); } } PK!$pBB?Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator HTML extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class HtmlExtension extends AbstractExtension { /** * Constructor. * * @param Translator $translator */ public function __construct(Translator $translator) { $translator ->getExtension('node') ->setFlag(NodeExtension::ELEMENT_NAME_IN_LOWER_CASE, true) ->setFlag(NodeExtension::ATTRIBUTE_NAME_IN_LOWER_CASE, true); } /** * {@inheritdoc} */ public function getPseudoClassTranslators() { return array( 'checked' => array($this, 'translateChecked'), 'link' => array($this, 'translateLink'), 'disabled' => array($this, 'translateDisabled'), 'enabled' => array($this, 'translateEnabled'), 'selected' => array($this, 'translateSelected'), 'invalid' => array($this, 'translateInvalid'), 'hover' => array($this, 'translateHover'), 'visited' => array($this, 'translateVisited'), ); } /** * {@inheritdoc} */ public function getFunctionTranslators() { return array( 'lang' => array($this, 'translateLang'), ); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateChecked(XPathExpr $xpath) { return $xpath->addCondition( '(@checked ' ."and (name(.) = 'input' or name(.) = 'command')" ."and (@type = 'checkbox' or @type = 'radio'))" ); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateLink(XPathExpr $xpath) { return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')"); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateDisabled(XPathExpr $xpath) { return $xpath->addCondition( "(" ."@disabled and" ."(" ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" ." or name(.) = 'option'" .")" .") or (" ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" .")" ." and ancestor::fieldset[@disabled]" ); // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any." } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateEnabled(XPathExpr $xpath) { return $xpath->addCondition( '(' .'@href and (' ."name(.) = 'a'" ." or name(.) = 'link'" ." or name(.) = 'area'" .')' .') or (' .'(' ."name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" .')' .' and not(@disabled)' .') or (' .'(' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'keygen'" .')' ." and not (@disabled or ancestor::fieldset[@disabled])" .') or (' ."name(.) = 'option' and not(" ."@disabled or ancestor::optgroup[@disabled]" .')' .')' ); } /** * @param XPathExpr $xpath * @param FunctionNode $function * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function) { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException( 'Expected a single string or identifier for :lang(), got ' .implode(', ', $arguments) ); } } return $xpath->addCondition(sprintf( 'ancestor-or-self::*[@lang][1][starts-with(concat(' ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')" .', %s)]', 'lang', Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-') )); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateSelected(XPathExpr $xpath) { return $xpath->addCondition("(@selected and name(.) = 'option')"); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateInvalid(XPathExpr $xpath) { return $xpath->addCondition('0'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateHover(XPathExpr $xpath) { return $xpath->addCondition('0'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateVisited(XPathExpr $xpath) { return $xpath->addCondition('0'); } /** * {@inheritdoc} */ public function getName() { return 'html'; } } PK!c-CSymfony/Component/CssSelector/XPath/Extension/AbstractExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; /** * XPath expression translator abstract extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ abstract class AbstractExtension implements ExtensionInterface { /** * {@inheritdoc} */ public function getNodeTranslators() { return array(); } /** * {@inheritdoc} */ public function getCombinationTranslators() { return array(); } /** * {@inheritdoc} */ public function getFunctionTranslators() { return array(); } /** * {@inheritdoc} */ public function getPseudoClassTranslators() { return array(); } /** * {@inheritdoc} */ public function getAttributeMatchingTranslators() { return array(); } } PK!x= = FSymfony/Component/CssSelector/XPath/Extension/CombinationExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator combination extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class CombinationExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getCombinationTranslators() { return array( ' ' => array($this, 'translateDescendant'), '>' => array($this, 'translateChild'), '+' => array($this, 'translateDirectAdjacent'), '~' => array($this, 'translateIndirectAdjacent'), ); } /** * @param XPathExpr $xpath * @param XPathExpr $combinedXpath * * @return XPathExpr */ public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath) { return $xpath->join('/descendant-or-self::*/', $combinedXpath); } /** * @param XPathExpr $xpath * @param XPathExpr $combinedXpath * * @return XPathExpr */ public function translateChild(XPathExpr $xpath, XPathExpr $combinedXpath) { return $xpath->join('/', $combinedXpath); } /** * @param XPathExpr $xpath * @param XPathExpr $combinedXpath * * @return XPathExpr */ public function translateDirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath) { return $xpath ->join('/following-sibling::', $combinedXpath) ->addNameTest() ->addCondition('position() = 1'); } /** * @param XPathExpr $xpath * @param XPathExpr $combinedXpath * * @return XPathExpr */ public function translateIndirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath) { return $xpath->join('/following-sibling::', $combinedXpath); } /** * {@inheritdoc} */ public function getName() { return 'combination'; } } PK! FSymfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator pseudo-class extension. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class PseudoClassExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getPseudoClassTranslators() { return array( 'root' => array($this, 'translateRoot'), 'first-child' => array($this, 'translateFirstChild'), 'last-child' => array($this, 'translateLastChild'), 'first-of-type' => array($this, 'translateFirstOfType'), 'last-of-type' => array($this, 'translateLastOfType'), 'only-child' => array($this, 'translateOnlyChild'), 'only-of-type' => array($this, 'translateOnlyOfType'), 'empty' => array($this, 'translateEmpty'), ); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateRoot(XPathExpr $xpath) { return $xpath->addCondition('not(parent::*)'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateFirstChild(XPathExpr $xpath) { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = 1'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateLastChild(XPathExpr $xpath) { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = last()'); } /** * @param XPathExpr $xpath * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateFirstOfType(XPathExpr $xpath) { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:first-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = 1'); } /** * @param XPathExpr $xpath * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateLastOfType(XPathExpr $xpath) { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:last-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = last()'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateOnlyChild(XPathExpr $xpath) { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('last() = 1'); } /** * @param XPathExpr $xpath * * @return XPathExpr * * @throws ExpressionErrorException */ public function translateOnlyOfType(XPathExpr $xpath) { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:only-of-type" is not implemented.'); } return $xpath->addCondition('last() = 1'); } /** * @param XPathExpr $xpath * * @return XPathExpr */ public function translateEmpty(XPathExpr $xpath) { return $xpath->addCondition('not(*) and not(string-length())'); } /** * {@inheritdoc} */ public function getName() { return 'pseudo-class'; } } PK!||DSymfony/Component/CssSelector/XPath/Extension/ExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; /** * XPath expression translator extension interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface ExtensionInterface { /** * Returns node translators. * * @return callable[] */ public function getNodeTranslators(); /** * Returns combination translators. * * @return callable[] */ public function getCombinationTranslators(); /** * Returns function translators. * * @return callable[] */ public function getFunctionTranslators(); /** * Returns pseudo-class translators. * * @return callable[] */ public function getPseudoClassTranslators(); /** * Returns attribute operation translators. * * @return callable[] */ public function getAttributeMatchingTranslators(); /** * Returns extension name. * * @return string */ public function getName(); } PK!uUU,Symfony/Component/CssSelector/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a combined node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class CombinedSelectorNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $combinator; /** * @var NodeInterface */ private $subSelector; /** * @param NodeInterface $selector * @param string $combinator * @param NodeInterface $subSelector */ public function __construct(NodeInterface $selector, $combinator, NodeInterface $subSelector) { $this->selector = $selector; $this->combinator = $combinator; $this->subSelector = $subSelector; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getCombinator() { return $this->combinator; } /** * @return NodeInterface */ public function getSubSelector() { return $this->subSelector; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); } /** * {@inheritdoc} */ public function __toString() { $combinator = ' ' === $this->combinator ? '' : $this->combinator; return sprintf('%s[%s %s %s]', $this->getNodeName(), $this->selector, $combinator, $this->subSelector); } } PK!rI4Symfony/Component/CssSelector/Node/NodeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Interface for nodes. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface NodeInterface { /** * Returns node's name. * * @return string */ public function getNodeName(); /** * Returns node's specificity. * * @return Specificity */ public function getSpecificity(); /** * Returns node's string representation. * * @return string */ public function __toString(); } PK!3Symfony/Component/CssSelector/Node/SelectorNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "(::|:)" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class SelectorNode extends AbstractNode { /** * @var NodeInterface */ private $tree; /** * @var null|string */ private $pseudoElement; /** * @param NodeInterface $tree * @param null|string $pseudoElement */ public function __construct(NodeInterface $tree, $pseudoElement = null) { $this->tree = $tree; $this->pseudoElement = $pseudoElement ? strtolower($pseudoElement) : null; } /** * @return NodeInterface */ public function getTree() { return $this->tree; } /** * @return null|string */ public function getPseudoElement() { return $this->pseudoElement; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->tree->getSpecificity()->plus(new Specificity(0, 0, $this->pseudoElement ? 1 : 0)); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s%s]', $this->getNodeName(), $this->tree, $this->pseudoElement ? '::'.$this->pseudoElement : ''); } } PK!pM23Symfony/Component/CssSelector/Node/AbstractNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Abstract base node class. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ abstract class AbstractNode implements NodeInterface { /** * @var string */ private $nodeName; /** * @return string */ public function getNodeName() { if (null === $this->nodeName) { $this->nodeName = preg_replace('~.*\\\\([^\\\\]+)Node$~', '$1', get_called_class()); } return $this->nodeName; } } PK!Г^FF2Symfony/Component/CssSelector/Node/ElementNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "|" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ElementNode extends AbstractNode { /** * @var string|null */ private $namespace; /** * @var string|null */ private $element; /** * @param string|null $namespace * @param string|null $element */ public function __construct($namespace = null, $element = null) { $this->namespace = $namespace; $this->element = $element; } /** * @return null|string */ public function getNamespace() { return $this->namespace; } /** * @return null|string */ public function getElement() { return $this->element; } /** * {@inheritdoc} */ public function getSpecificity() { return new Specificity(0, 0, $this->element ? 1 : 0); } /** * {@inheritdoc} */ public function __toString() { $element = $this->element ?: '*'; return sprintf('%s[%s]', $this->getNodeName(), $this->namespace ? $this->namespace.'|'.$element : $element); } } PK!.221Symfony/Component/CssSelector/Node/PseudoNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a ":" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class PseudoNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $identifier; /** * @param NodeInterface $selector * @param string $identifier */ public function __construct(NodeInterface $selector, $identifier) { $this->selector = $selector; $this->identifier = strtolower($identifier); } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getIdentifier() { return $this->identifier; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s:%s]', $this->getNodeName(), $this->selector, $this->identifier); } } PK! i0Symfony/Component/CssSelector/Node/ClassNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "." node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ClassNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $name; /** * @param NodeInterface $selector * @param string $name */ public function __construct(NodeInterface $selector, $name) { $this->selector = $selector; $this->name = $name; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getName() { return $this->name; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s.%s]', $this->getNodeName(), $this->selector, $this->name); } } PK!bb3Symfony/Component/CssSelector/Node/NegationNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a ":not()" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class NegationNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var NodeInterface */ private $subSelector; /** * @param NodeInterface $selector * @param NodeInterface $subSelector */ public function __construct(NodeInterface $selector, NodeInterface $subSelector) { $this->selector = $selector; $this->subSelector = $subSelector; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return NodeInterface */ public function getSubSelector() { return $this->subSelector; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s:not(%s)]', $this->getNodeName(), $this->selector, $this->subSelector); } } PK!x2Symfony/Component/CssSelector/Node/Specificity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a node specificity. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @see http://www.w3.org/TR/selectors/#specificity * * @author Jean-François Simon */ class Specificity { const A_FACTOR = 100; const B_FACTOR = 10; const C_FACTOR = 1; /** * @var int */ private $a; /** * @var int */ private $b; /** * @var int */ private $c; /** * Constructor. * * @param int $a * @param int $b * @param int $c */ public function __construct($a, $b, $c) { $this->a = $a; $this->b = $b; $this->c = $c; } /** * @param Specificity $specificity * * @return Specificity */ public function plus(Specificity $specificity) { return new self($this->a + $specificity->a, $this->b + $specificity->b, $this->c + $specificity->c); } /** * Returns global specificity value. * * @return int */ public function getValue() { return $this->a * self::A_FACTOR + $this->b * self::B_FACTOR + $this->c * self::C_FACTOR; } } PK!#^[/Symfony/Component/CssSelector/Node/HashNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "#" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class HashNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $id; /** * @param NodeInterface $selector * @param string $id */ public function __construct(NodeInterface $selector, $id) { $this->selector = $selector; $this->id = $id; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getId() { return $this->id; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(1, 0, 0)); } /** * {@inheritdoc} */ public function __toString() { return sprintf('%s[%s#%s]', $this->getNodeName(), $this->selector, $this->id); } } PK!FK K 4Symfony/Component/CssSelector/Node/AttributeNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "[| ]" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class AttributeNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $namespace; /** * @var string */ private $attribute; /** * @var string */ private $operator; /** * @var string */ private $value; /** * @param NodeInterface $selector * @param string $namespace * @param string $attribute * @param string $operator * @param string $value */ public function __construct(NodeInterface $selector, $namespace, $attribute, $operator, $value) { $this->selector = $selector; $this->namespace = $namespace; $this->attribute = $attribute; $this->operator = $operator; $this->value = $value; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getNamespace() { return $this->namespace; } /** * @return string */ public function getAttribute() { return $this->attribute; } /** * @return string */ public function getOperator() { return $this->operator; } /** * @return string */ public function getValue() { return $this->value; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } /** * {@inheritdoc} */ public function __toString() { $attribute = $this->namespace ? $this->namespace.'|'.$this->attribute : $this->attribute; return 'exists' === $this->operator ? sprintf('%s[%s[%s]]', $this->getNodeName(), $this->selector, $attribute) : sprintf("%s[%s[%s %s '%s']]", $this->getNodeName(), $this->selector, $attribute, $this->operator, $this->value); } } PK!x3Symfony/Component/CssSelector/Node/FunctionNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\Parser\Token; /** * Represents a ":()" node. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class FunctionNode extends AbstractNode { /** * @var NodeInterface */ private $selector; /** * @var string */ private $name; /** * @var Token[] */ private $arguments; /** * @param NodeInterface $selector * @param string $name * @param Token[] $arguments */ public function __construct(NodeInterface $selector, $name, array $arguments = array()) { $this->selector = $selector; $this->name = strtolower($name); $this->arguments = $arguments; } /** * @return NodeInterface */ public function getSelector() { return $this->selector; } /** * @return string */ public function getName() { return $this->name; } /** * @return Token[] */ public function getArguments() { return $this->arguments; } /** * {@inheritdoc} */ public function getSpecificity() { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } /** * {@inheritdoc} */ public function __toString() { $arguments = implode(', ', array_map(function (Token $token) { return "'".$token->getValue()."'"; }, $this->arguments)); return sprintf('%s[%s:%s(%s)]', $this->getNodeName(), $this->selector, $this->name, $arguments ? '['.$arguments.']' : ''); } } PK!mcBSymfony/Component/CssSelector/Exception/InternalErrorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class InternalErrorException extends ParseException implements ExceptionInterface { } PK!מ@Symfony/Component/CssSelector/Exception/SyntaxErrorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; use Symfony\Component\CssSelector\Parser\Token; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class SyntaxErrorException extends ParseException implements ExceptionInterface { /** * @param string $expectedValue * @param Token $foundToken * * @return SyntaxErrorException */ public static function unexpectedToken($expectedValue, Token $foundToken) { return new self(sprintf('Expected %s, but %s found.', $expectedValue, $foundToken)); } /** * @param string $pseudoElement * @param string $unexpectedLocation * * @return SyntaxErrorException */ public static function pseudoElementFound($pseudoElement, $unexpectedLocation) { return new self(sprintf('Unexpected pseudo-element "::%s" found %s.', $pseudoElement, $unexpectedLocation)); } /** * @param int $position * * @return SyntaxErrorException */ public static function unclosedString($position) { return new self(sprintf('Unclosed/invalid string at %s.', $position)); } /** * @return SyntaxErrorException */ public static function nestedNot() { return new self('Got nested ::not().'); } /** * @return SyntaxErrorException */ public static function stringAsFunctionArgument() { return new self('String not allowed as function argument.'); } } PK!/pTСDSymfony/Component/CssSelector/Exception/ExpressionErrorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ExpressionErrorException extends ParseException implements ExceptionInterface { } PK!gfGBB>Symfony/Component/CssSelector/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * Interface for exceptions. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface ExceptionInterface { } PK!'[|ɀ:Symfony/Component/CssSelector/Exception/ParseException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Fabien Potencier */ class ParseException extends \Exception implements ExceptionInterface { } PK!^}  -Symfony/Component/CssSelector/CssSelector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector; use Symfony\Component\CssSelector\Parser\Shortcut\ClassParser; use Symfony\Component\CssSelector\Parser\Shortcut\ElementParser; use Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser; use Symfony\Component\CssSelector\Parser\Shortcut\HashParser; use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension; use Symfony\Component\CssSelector\XPath\Translator; /** * CssSelector is the main entry point of the component and can convert CSS * selectors to XPath expressions. * * $xpath = CssSelector::toXpath('h1.foo'); * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Fabien Potencier * * @api */ class CssSelector { private static $html = true; /** * Translates a CSS expression to its XPath equivalent. * Optionally, a prefix can be added to the resulting XPath * expression with the $prefix parameter. * * @param mixed $cssExpr The CSS expression. * @param string $prefix An optional prefix for the XPath expression. * * @return string * * @api */ public static function toXPath($cssExpr, $prefix = 'descendant-or-self::') { $translator = new Translator(); if (self::$html) { $translator->registerExtension(new HtmlExtension($translator)); } $translator ->registerParserShortcut(new EmptyStringParser()) ->registerParserShortcut(new ElementParser()) ->registerParserShortcut(new ClassParser()) ->registerParserShortcut(new HashParser()) ; return $translator->cssToXPath($cssExpr, $prefix); } /** * Enables the HTML extension. */ public static function enableHtmlExtension() { self::$html = true; } /** * Disables the HTML extension. */ public static function disableHtmlExtension() { self::$html = false; } } PK!5# HH<Symfony/Component/CssSelector/Parser/Shortcut/HashParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\HashNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector hash parser shortcut. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class HashParser implements ParserInterface { /** * {@inheritdoc} */ public function parse($source) { // Matches an optional namespace, optional element, and required id // $source = 'test|input#ab6bd_field'; // $matches = array (size=5) // 0 => string 'test:input#ab6bd_field' (length=22) // 1 => string 'test:' (length=5) // 2 => string 'test' (length=4) // 3 => string 'input' (length=5) // 4 => string 'ab6bd_field' (length=11) if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)?#([\w-]+)$/i', trim($source), $matches)) { return array( new SelectorNode(new HashNode(new ElementNode($matches[2] ?: null, $matches[3] ?: null), $matches[4])) ); } return array(); } } PK!ҵܗCSymfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector class parser shortcut. * * This shortcut ensure compatibility with previous version. * - The parser fails to parse an empty string. * - In the previous version, an empty string matches each tags. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class EmptyStringParser implements ParserInterface { /** * {@inheritdoc} */ public function parse($source) { // Matches an empty string if ($source == '') { return array(new SelectorNode(new ElementNode(null, '*'))); } return array(); } } PK!TR#[PP=Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ClassNode; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector class parser shortcut. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ClassParser implements ParserInterface { /** * {@inheritdoc} */ public function parse($source) { // Matches an optional namespace, optional element, and required class // $source = 'test|input.ab6bd_field'; // $matches = array (size=5) // 0 => string 'test:input.ab6bd_field' (length=22) // 1 => string 'test:' (length=5) // 2 => string 'test' (length=4) // 3 => string 'input' (length=5) // 4 => string 'ab6bd_field' (length=11) if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)?\.([\w-]+)$/i', trim($source), $matches)) { return array( new SelectorNode(new ClassNode(new ElementNode($matches[2] ?: null, $matches[3] ?: null), $matches[4])) ); } return array(); } } PK!Z>?Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector element parser shortcut. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ElementParser implements ParserInterface { /** * {@inheritdoc} */ public function parse($source) { // Matches an optional namespace, required element or `*` // $source = 'testns|testel'; // $matches = array (size=4) // 0 => string 'testns:testel' (length=13) // 1 => string 'testns:' (length=7) // 2 => string 'testns' (length=6) // 3 => string 'testel' (length=6) if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)$/i', trim($source), $matches)) { return array(new SelectorNode(new ElementNode($matches[2] ?: null, $matches[3]))); } return array(); } } PK!QQ4Symfony/Component/CssSelector/Parser/TokenStream.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; use Symfony\Component\CssSelector\Exception\InternalErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; /** * CSS selector token stream. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class TokenStream { /** * @var Token[] */ private $tokens = array(); /** * @var boolean */ private $frozen = false; /** * @var Token[] */ private $used = array(); /** * @var int */ private $cursor = 0; /** * @var Token|null */ private $peeked = null; /** * @var boolean */ private $peeking = false; /** * Pushes a token. * * @param Token $token * * @return TokenStream */ public function push(Token $token) { $this->tokens[] = $token; return $this; } /** * Freezes stream. * * @return TokenStream */ public function freeze() { $this->frozen = true; return $this; } /** * Returns next token. * * @throws InternalErrorException If there is no more token * * @return Token */ public function getNext() { if ($this->peeking) { $this->peeking = false; $this->used[] = $this->peeked; return $this->peeked; } if (!isset($this->tokens[$this->cursor])) { throw new InternalErrorException('Unexpected token stream end.'); } return $this->tokens[$this->cursor ++]; } /** * Returns peeked token. * * @return Token */ public function getPeek() { if (!$this->peeking) { $this->peeked = $this->getNext(); $this->peeking = true; } return $this->peeked; } /** * Returns used tokens. * * @return Token[] */ public function getUsed() { return $this->used; } /** * Returns nex identifier token. * * @throws SyntaxErrorException If next token is not an identifier * * @return string The identifier token value */ public function getNextIdentifier() { $next = $this->getNext(); if (!$next->isIdentifier()) { throw SyntaxErrorException::unexpectedToken('identifier', $next); } return $next->getValue(); } /** * Returns nex identifier or star delimiter token. * * @throws SyntaxErrorException If next token is not an identifier or a star delimiter * * @return null|string The identifier token value or null if star found */ public function getNextIdentifierOrStar() { $next = $this->getNext(); if ($next->isIdentifier()) { return $next->getValue(); } if ($next->isDelimiter(array('*'))) { return null; } throw SyntaxErrorException::unexpectedToken('identifier or "*"', $next); } /** * Skips next whitespace if any. */ public function skipWhitespace() { $peek = $this->getPeek(); if ($peek->isWhitespace()) { $this->getNext(); } } } PK!6\5 5 >Symfony/Component/CssSelector/Parser/Handler/StringHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Exception\InternalErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class StringHandler implements HandlerInterface { /** * @var TokenizerPatterns */ private $patterns; /** * @var TokenizerEscaping */ private $escaping; /** * @param TokenizerPatterns $patterns * @param TokenizerEscaping $escaping */ public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) { $this->patterns = $patterns; $this->escaping = $escaping; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $quote = $reader->getSubstring(1); if (!in_array($quote, array("'", '"'))) { return false; } $reader->moveForward(1); $match = $reader->findPattern($this->patterns->getQuotedStringPattern($quote)); if (!$match) { throw new InternalErrorException(sprintf('Should have found at least an empty match at %s.', $reader->getPosition())); } // check unclosed strings if (strlen($match[0]) === $reader->getRemainingLength()) { throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); } // check quotes pairs validity if ($quote !== $reader->getSubstring(1, strlen($match[0]))) { throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); } $string = $this->escaping->escapeUnicodeAndNewLine($match[0]); $stream->push(new Token(Token::TYPE_STRING, $string, $reader->getPosition())); $reader->moveForward(strlen($match[0]) + 1); return true; } } PK!8D^^?Symfony/Component/CssSelector/Parser/Handler/CommentHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class CommentHandler implements HandlerInterface { /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { if ('/*' !== $reader->getSubstring(2)) { return false; } $offset = $reader->getOffset('*/'); if (false === $offset) { $reader->moveToEnd(); } else { $reader->moveForward($offset + 2); } return true; } } PK!X{<Symfony/Component/CssSelector/Parser/Handler/HashHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class HashHandler implements HandlerInterface { /** * @var TokenizerPatterns */ private $patterns; /** * @var TokenizerEscaping */ private $escaping; /** * @param TokenizerPatterns $patterns * @param TokenizerEscaping $escaping */ public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) { $this->patterns = $patterns; $this->escaping = $escaping; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $match = $reader->findPattern($this->patterns->getHashPattern()); if (!$match) { return false; } $value = $this->escaping->escapeUnicode($match[1]); $stream->push(new Token(Token::TYPE_HASH, $value, $reader->getPosition())); $reader->moveForward(strlen($match[0])); return true; } } PK!hffASymfony/Component/CssSelector/Parser/Handler/HandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector handler interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface HandlerInterface { /** * @param Reader $reader * @param TokenStream $stream * * @return boolean */ public function handle(Reader $reader, TokenStream $stream); } PK!e'n>Symfony/Component/CssSelector/Parser/Handler/NumberHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class NumberHandler implements HandlerInterface { /** * @var TokenizerPatterns */ private $patterns; /** * @param TokenizerPatterns $patterns */ public function __construct(TokenizerPatterns $patterns) { $this->patterns = $patterns; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $match = $reader->findPattern($this->patterns->getNumberPattern()); if (!$match) { return false; } $stream->push(new Token(Token::TYPE_NUMBER, $match[0], $reader->getPosition())); $reader->moveForward(strlen($match[0])); return true; } } PK!#BSymfony/Component/CssSelector/Parser/Handler/IdentifierHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; /** * CSS selector comment handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class IdentifierHandler implements HandlerInterface { /** * @var TokenizerPatterns */ private $patterns; /** * @var TokenizerEscaping */ private $escaping; /** * @param TokenizerPatterns $patterns * @param TokenizerEscaping $escaping */ public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) { $this->patterns = $patterns; $this->escaping = $escaping; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $match = $reader->findPattern($this->patterns->getIdentifierPattern()); if (!$match) { return false; } $value = $this->escaping->escapeUnicode($match[0]); $stream->push(new Token(Token::TYPE_IDENTIFIER, $value, $reader->getPosition())); $reader->moveForward(strlen($match[0])); return true; } } PK!BSymfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector whitespace handler. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class WhitespaceHandler implements HandlerInterface { /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream) { $match = $reader->findPattern('~^[ \t\r\n\f]+~'); if (false === $match) { return false; } $stream->push(new Token(Token::TYPE_WHITESPACE, $match[0], $reader->getPosition())); $reader->moveForward(strlen($match[0])); return true; } } PK!6ND1D1/Symfony/Component/CssSelector/Parser/Parser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\Parser\Tokenizer\Tokenizer; /** * CSS selector parser. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Parser implements ParserInterface { /** * @var Tokenizer */ private $tokenizer; /** * Constructor. * * @param null|Tokenizer $tokenizer */ public function __construct(Tokenizer $tokenizer = null) { $this->tokenizer = $tokenizer ?: new Tokenizer(); } /** * {@inheritdoc} */ public function parse($source) { $reader = new Reader($source); $stream = $this->tokenizer->tokenize($reader); return $this->parseSelectorList($stream); } /** * Parses the arguments for ":nth-child()" and friends. * * @param Token[] $tokens * * @throws SyntaxErrorException * * @return array */ public static function parseSeries(array $tokens) { foreach ($tokens as $token) { if ($token->isString()) { throw SyntaxErrorException::stringAsFunctionArgument(); } } $joined = trim(implode('', array_map(function (Token $token) { return $token->getValue(); }, $tokens))); $int = function ($string) { if (!is_numeric($string)) { throw SyntaxErrorException::stringAsFunctionArgument(); } return (int) $string; }; switch (true) { case 'odd' === $joined: return array(2, 1); case 'even' === $joined: return array(2, 0); case 'n' === $joined: return array(1, 0); case false === strpos($joined, 'n'): return array(0, $int($joined)); } $split = explode('n', $joined); $first = isset($split[0]) ? $split[0] : null; return array( $first ? ('-' === $first || '+' === $first ? $int($first.'1') : $int($first)) : 1, isset($split[1]) && $split[1] ? $int($split[1]) : 0 ); } /** * Parses selector nodes. * * @param TokenStream $stream * * @return array */ private function parseSelectorList(TokenStream $stream) { $stream->skipWhitespace(); $selectors = array(); while (true) { $selectors[] = $this->parserSelectorNode($stream); if ($stream->getPeek()->isDelimiter(array(','))) { $stream->getNext(); $stream->skipWhitespace(); } else { break; } } return $selectors; } /** * Parses next selector or combined node. * * @param TokenStream $stream * * @throws SyntaxErrorException * * @return Node\SelectorNode */ private function parserSelectorNode(TokenStream $stream) { list($result, $pseudoElement) = $this->parseSimpleSelector($stream); while (true) { $stream->skipWhitespace(); $peek = $stream->getPeek(); if ($peek->isFileEnd() || $peek->isDelimiter(array(','))) { break; } if (null !== $pseudoElement) { throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); } if ($peek->isDelimiter(array('+', '>', '~'))) { $combinator = $stream->getNext()->getValue(); $stream->skipWhitespace(); } else { $combinator = ' '; } list($nextSelector, $pseudoElement) = $this->parseSimpleSelector($stream); $result = new Node\CombinedSelectorNode($result, $combinator, $nextSelector); } return new Node\SelectorNode($result, $pseudoElement); } /** * Parses next simple node (hash, class, pseudo, negation). * * @param TokenStream $stream * @param boolean $insideNegation * * @throws SyntaxErrorException * * @return array */ private function parseSimpleSelector(TokenStream $stream, $insideNegation = false) { $stream->skipWhitespace(); $selectorStart = count($stream->getUsed()); $result = $this->parseElementNode($stream); $pseudoElement = null; while (true) { $peek = $stream->getPeek(); if ($peek->isWhitespace() || $peek->isFileEnd() || $peek->isDelimiter(array(',', '+', '>', '~')) || ($insideNegation && $peek->isDelimiter(array(')'))) ) { break; } if (null !== $pseudoElement) { throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); } if ($peek->isHash()) { $result = new Node\HashNode($result, $stream->getNext()->getValue()); } elseif ($peek->isDelimiter(array('.'))) { $stream->getNext(); $result = new Node\ClassNode($result, $stream->getNextIdentifier()); } elseif ($peek->isDelimiter(array('['))) { $stream->getNext(); $result = $this->parseAttributeNode($result, $stream); } elseif ($peek->isDelimiter(array(':'))) { $stream->getNext(); if ($stream->getPeek()->isDelimiter(array(':'))) { $stream->getNext(); $pseudoElement = $stream->getNextIdentifier(); continue; } $identifier = $stream->getNextIdentifier(); if (in_array(strtolower($identifier), array('first-line', 'first-letter', 'before', 'after'))) { // Special case: CSS 2.1 pseudo-elements can have a single ':'. // Any new pseudo-element must have two. $pseudoElement = $identifier; continue; } if (!$stream->getPeek()->isDelimiter(array('('))) { $result = new Node\PseudoNode($result, $identifier); continue; } $stream->getNext(); $stream->skipWhitespace(); if ('not' === strtolower($identifier)) { if ($insideNegation) { throw SyntaxErrorException::nestedNot(); } list($argument, $argumentPseudoElement) = $this->parseSimpleSelector($stream, true); $next = $stream->getNext(); if (null !== $argumentPseudoElement) { throw SyntaxErrorException::pseudoElementFound($argumentPseudoElement, 'inside ::not()'); } if (!$next->isDelimiter(array(')'))) { throw SyntaxErrorException::unexpectedToken('")"', $next); } $result = new Node\NegationNode($result, $argument); } else { $arguments = array(); $next = null; while (true) { $stream->skipWhitespace(); $next = $stream->getNext(); if ($next->isIdentifier() || $next->isString() || $next->isNumber() || $next->isDelimiter(array('+', '-')) ) { $arguments[] = $next; } elseif ($next->isDelimiter(array(')'))) { break; } else { throw SyntaxErrorException::unexpectedToken('an argument', $next); } } if (empty($arguments)) { throw SyntaxErrorException::unexpectedToken('at least one argument', $next); } $result = new Node\FunctionNode($result, $identifier, $arguments); } } else { throw SyntaxErrorException::unexpectedToken('selector', $peek); } } if (count($stream->getUsed()) === $selectorStart) { throw SyntaxErrorException::unexpectedToken('selector', $stream->getPeek()); } return array($result, $pseudoElement); } /** * Parses next element node. * * @param TokenStream $stream * * @return Node\ElementNode */ private function parseElementNode(TokenStream $stream) { $peek = $stream->getPeek(); if ($peek->isIdentifier() || $peek->isDelimiter(array('*'))) { if ($peek->isIdentifier()) { $namespace = $stream->getNext()->getValue(); } else { $stream->getNext(); $namespace = null; } if ($stream->getPeek()->isDelimiter(array('|'))) { $stream->getNext(); $element = $stream->getNextIdentifierOrStar(); } else { $element = $namespace; $namespace = null; } } else { $element = $namespace = null; } return new Node\ElementNode($namespace, $element); } /** * Parses next attribute node. * * @param Node\NodeInterface $selector * @param TokenStream $stream * * @throws SyntaxErrorException * * @return Node\AttributeNode */ private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream) { $stream->skipWhitespace(); $attribute = $stream->getNextIdentifierOrStar(); if (null === $attribute && !$stream->getPeek()->isDelimiter(array('|'))) { throw SyntaxErrorException::unexpectedToken('"|"', $stream->getPeek()); } if ($stream->getPeek()->isDelimiter(array('|'))) { $stream->getNext(); if ($stream->getPeek()->isDelimiter(array('='))) { $namespace = null; $stream->getNext(); $operator = '|='; } else { $namespace = $attribute; $attribute = $stream->getNextIdentifier(); $operator = null; } } else { $namespace = $operator = null; } if (null === $operator) { $stream->skipWhitespace(); $next = $stream->getNext(); if ($next->isDelimiter(array(']'))) { return new Node\AttributeNode($selector, $namespace, $attribute, 'exists', null); } elseif ($next->isDelimiter(array('='))) { $operator = '='; } elseif ($next->isDelimiter(array('^', '$', '*', '~', '|', '!')) && $stream->getPeek()->isDelimiter(array('=')) ) { $operator = $next->getValue().'='; $stream->getNext(); } else { throw SyntaxErrorException::unexpectedToken('operator', $next); } } $stream->skipWhitespace(); $value = $stream->getNext(); if ($value->isNumber()) { // if the value is a number, it's casted into a string $value = new Token(Token::TYPE_STRING, (string) $value->getValue(), $value->getPosition()); } if (!($value->isIdentifier() || $value->isString())) { throw SyntaxErrorException::unexpectedToken('string or identifier', $value); } $stream->skipWhitespace(); $next = $stream->getNext(); if (!$next->isDelimiter(array(']'))) { throw SyntaxErrorException::unexpectedToken('"]"', $next); } return new Node\AttributeNode($selector, $namespace, $attribute, $operator, $value->getValue()); } } PK!;  /Symfony/Component/CssSelector/Parser/Reader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; /** * CSS selector reader. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Reader { /** * @var string */ private $source; /** * @var int */ private $length; /** * @var int */ private $position = 0; /** * @param string $source */ public function __construct($source) { $this->source = $source; $this->length = strlen($source); } /** * @return bool */ public function isEOF() { return $this->position >= $this->length; } /** * @return int */ public function getPosition() { return $this->position; } /** * @return int */ public function getRemainingLength() { return $this->length - $this->position; } /** * @param int $length * @param int $offset * * @return string */ public function getSubstring($length, $offset = 0) { return substr($this->source, $this->position + $offset, $length); } /** * @param string $string * * @return int */ public function getOffset($string) { $position = strpos($this->source, $string, $this->position); return false === $position ? false : $position - $this->position; } /** * @param string $pattern * * @return bool */ public function findPattern($pattern) { $source = substr($this->source, $this->position); if (preg_match($pattern, $source, $matches)) { return $matches; } return false; } /** * @param int $length */ public function moveForward($length) { $this->position += $length; } /** */ public function moveToEnd() { $this->position = $this->length; } } PK!AEo118Symfony/Component/CssSelector/Parser/ParserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; use Symfony\Component\CssSelector\Node\SelectorNode; /** * CSS selector parser interface. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface ParserInterface { /** * Parses given selector source into an array of tokens. * * @param string $source * * @return SelectorNode[] */ public function parse($source); } PK!zZ< .Symfony/Component/CssSelector/Parser/Token.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; /** * CSS selector token. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Token { const TYPE_FILE_END = 'eof'; const TYPE_DELIMITER = 'delimiter'; const TYPE_WHITESPACE = 'whitespace'; const TYPE_IDENTIFIER = 'identifier'; const TYPE_HASH = 'hash'; const TYPE_NUMBER = 'number'; const TYPE_STRING = 'string'; /** * @var int */ private $type; /** * @var string */ private $value; /** * @var int */ private $position; /** * @param int $type * @param string $value * @param int $position */ public function __construct($type, $value, $position) { $this->type = $type; $this->value = $value; $this->position = $position; } /** * @return int */ public function getType() { return $this->type; } /** * @return string */ public function getValue() { return $this->value; } /** * @return int */ public function getPosition() { return $this->position; } /** * @return boolean */ public function isFileEnd() { return self::TYPE_FILE_END === $this->type; } /** * @param array $values * * @return boolean */ public function isDelimiter(array $values = array()) { if (self::TYPE_DELIMITER !== $this->type) { return false; } if (empty($values)) { return true; } return in_array($this->value, $values); } /** * @return boolean */ public function isWhitespace() { return self::TYPE_WHITESPACE === $this->type; } /** * @return boolean */ public function isIdentifier() { return self::TYPE_IDENTIFIER === $this->type; } /** * @return boolean */ public function isHash() { return self::TYPE_HASH === $this->type; } /** * @return boolean */ public function isNumber() { return self::TYPE_NUMBER === $this->type; } /** * @return boolean */ public function isString() { return self::TYPE_STRING === $this->type; } /** * @return string */ public function __toString() { if ($this->value) { return sprintf('<%s "%s" at %s>', $this->type, $this->value, $this->position); } return sprintf('<%s at %s>', $this->type, $this->position); } } PK!>< DSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Tokenizer; /** * CSS selector tokenizer patterns builder. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class TokenizerPatterns { /** * @var string */ private $unicodeEscapePattern; /** * @var string */ private $simpleEscapePattern; /** * @var string */ private $newLineEscapePattern; /** * @var string */ private $escapePattern; /** * @var string */ private $stringEscapePattern; /** * @var string */ private $nonAsciiPattern; /** * @var string */ private $nmCharPattern; /** * @var string */ private $nmStartPattern; /** * @var string */ private $identifierPattern; /** * @var string */ private $hashPattern; /** * @var string */ private $numberPattern; /** * @var string */ private $quotedStringPattern; /** * Constructor. */ public function __construct() { $this->unicodeEscapePattern = '\\\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?'; $this->simpleEscapePattern = '\\\\(.)'; $this->newLineEscapePattern = '\\\\(?:\n|\r\n|\r|\f)'; $this->escapePattern = $this->unicodeEscapePattern.'|\\\\[^\n\r\f0-9a-f]'; $this->stringEscapePattern = $this->newLineEscapePattern.'|'.$this->escapePattern; $this->nonAsciiPattern = '[^\x00-\x7F]'; $this->nmCharPattern = '[_a-z0-9-]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; $this->nmStartPattern = '[_a-z]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; $this->identifierPattern = '(?:'.$this->nmStartPattern.')(?:'.$this->nmCharPattern.')*'; $this->hashPattern = '#((?:'.$this->nmCharPattern.')+)'; $this->numberPattern = '[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)'; $this->quotedStringPattern = '([^\n\r\f%s]|'.$this->stringEscapePattern.')*'; } /** * @return string */ public function getNewLineEscapePattern() { return '~^'.$this->newLineEscapePattern.'~'; } /** * @return string */ public function getSimpleEscapePattern() { return '~^'.$this->simpleEscapePattern.'~'; } /** * @return string */ public function getUnicodeEscapePattern() { return '~^'.$this->unicodeEscapePattern.'~i'; } /** * @return string */ public function getIdentifierPattern() { return '~^'.$this->identifierPattern.'~i'; } /** * @return string */ public function getHashPattern() { return '~^'.$this->hashPattern.'~i'; } /** * @return string */ public function getNumberPattern() { return '~^'.$this->numberPattern.'~'; } /** * @param string $quote * * @return string */ public function getQuotedStringPattern($quote) { return '~^'.sprintf($this->quotedStringPattern, $quote).'~i'; } } PK!SkFF<Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Tokenizer; use Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector tokenizer. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class Tokenizer { /** * @var Handler\HandlerInterface[] */ private $handlers; /** * Constructor. */ public function __construct() { $patterns = new TokenizerPatterns(); $escaping = new TokenizerEscaping($patterns); $this->handlers = array( new Handler\WhitespaceHandler(), new Handler\IdentifierHandler($patterns, $escaping), new Handler\HashHandler($patterns, $escaping), new Handler\StringHandler($patterns, $escaping), new Handler\NumberHandler($patterns), new Handler\CommentHandler(), ); } /** * Tokenize selector source code. * * @param Reader $reader * * @return TokenStream */ public function tokenize(Reader $reader) { $stream = new TokenStream(); while (!$reader->isEOF()) { foreach ($this->handlers as $handler) { if ($handler->handle($reader, $stream)) { continue 2; } } $stream->push(new Token(Token::TYPE_DELIMITER, $reader->getSubstring(1), $reader->getPosition())); $reader->moveForward(1); } return $stream ->push(new Token(Token::TYPE_FILE_END, null, $reader->getPosition())) ->freeze(); } } PK! W55DSymfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Tokenizer; /** * CSS selector tokenizer escaping applier. * * This component is a port of the Python cssselector library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class TokenizerEscaping { /** * @var TokenizerPatterns */ private $patterns; /** * @param TokenizerPatterns $patterns */ public function __construct(TokenizerPatterns $patterns) { $this->patterns = $patterns; } /** * @param string $value * * @return string */ public function escapeUnicode($value) { $value = $this->replaceUnicodeSequences($value); return preg_replace($this->patterns->getSimpleEscapePattern(), '$1', $value); } /** * @param string $value * * @return string */ public function escapeUnicodeAndNewLine($value) { $value = preg_replace($this->patterns->getNewLineEscapePattern(), '', $value); return $this->escapeUnicode($value); } /** * @param string $value * * @return string */ private function replaceUnicodeSequences($value) { return preg_replace_callback($this->patterns->getUnicodeEscapePattern(), function (array $match) { $code = $match[1]; if (bin2hex($code) > 0xFFFD) { $code = '\\FFFD'; } return mb_convert_encoding(pack('H*', $code), 'UTF-8', 'UCS-2BE'); }, $value); } } PK!bk +Symfony/Component/EventDispatcher/Event.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * Event is the base class for classes containing event data. * * This class contains no event data. It is used by events that do not pass * state information to an event handler when an event is raised. * * You can call the method stopPropagation() to abort the execution of * further listeners in your event listener. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * * @api */ class Event { /** * @var Boolean Whether no further event listeners should be triggered */ private $propagationStopped = false; /** * @var EventDispatcher Dispatcher that dispatched this event */ private $dispatcher; /** * @var string This event's name */ private $name; /** * Returns whether further event listeners should be triggered. * * @see Event::stopPropagation * @return Boolean Whether propagation was already stopped for this event. * * @api */ public function isPropagationStopped() { return $this->propagationStopped; } /** * Stops the propagation of the event to further event listeners. * * If multiple event listeners are connected to the same event, no * further event listener will be triggered once any trigger calls * stopPropagation(). * * @api */ public function stopPropagation() { $this->propagationStopped = true; } /** * Stores the EventDispatcher that dispatches this Event * * @param EventDispatcherInterface $dispatcher * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. * * @api */ public function setDispatcher(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * Returns the EventDispatcher that dispatches this Event * * @return EventDispatcherInterface * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. * * @api */ public function getDispatcher() { return $this->dispatcher; } /** * Gets the event's name. * * @return string * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call. * * @api */ public function getName() { return $this->name; } /** * Sets the event's name property. * * @param string $name The event name. * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call. * * @api */ public function setName($name) { $this->name = $name; } } PK! YY0Symfony/Component/EventDispatcher/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\Debug; /** * @author Fabien Potencier */ interface TraceableEventDispatcherInterface { /** * Gets the called listeners. * * @return array An array of called listeners */ public function getCalledListeners(); /** * Gets the not called listeners. * * @return array An array of not called listeners */ public function getNotCalledListeners(); } PK!,DD2Symfony/Component/EventDispatcher/GenericEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * Event encapsulation class. * * Encapsulates events thus decoupling the observer from the subject they encapsulate. * * @author Drak */ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate { /** * Event subject. * * @var mixed usually object or callable */ protected $subject; /** * Array of arguments. * * @var array */ protected $arguments; /** * Encapsulate an event with $subject and $args. * * @param mixed $subject The subject of the event, usually an object. * @param array $arguments Arguments to store in the event. */ public function __construct($subject = null, array $arguments = array()) { $this->subject = $subject; $this->arguments = $arguments; } /** * Getter for subject property. * * @return mixed $subject The observer subject. */ public function getSubject() { return $this->subject; } /** * Get argument by key. * * @param string $key Key. * * @throws \InvalidArgumentException If key is not found. * * @return mixed Contents of array key. */ public function getArgument($key) { if ($this->hasArgument($key)) { return $this->arguments[$key]; } throw new \InvalidArgumentException(sprintf('%s not found in %s', $key, $this->getName())); } /** * Add argument to event. * * @param string $key Argument name. * @param mixed $value Value. * * @return GenericEvent */ public function setArgument($key, $value) { $this->arguments[$key] = $value; return $this; } /** * Getter for all arguments. * * @return array */ public function getArguments() { return $this->arguments; } /** * Set args property. * * @param array $args Arguments. * * @return GenericEvent */ public function setArguments(array $args = array()) { $this->arguments = $args; return $this; } /** * Has argument. * * @param string $key Key of arguments array. * * @return boolean */ public function hasArgument($key) { return array_key_exists($key, $this->arguments); } /** * ArrayAccess for argument getter. * * @param string $key Array key. * * @throws \InvalidArgumentException If key does not exist in $this->args. * * @return mixed */ public function offsetGet($key) { return $this->getArgument($key); } /** * ArrayAccess for argument setter. * * @param string $key Array key to set. * @param mixed $value Value. */ public function offsetSet($key, $value) { $this->setArgument($key, $value); } /** * ArrayAccess for unset argument. * * @param string $key Array key. */ public function offsetUnset($key) { if ($this->hasArgument($key)) { unset($this->arguments[$key]); } } /** * ArrayAccess has argument. * * @param string $key Array key. * * @return boolean */ public function offsetExists($key) { return $this->hasArgument($key); } /** * IteratorAggregate for iterating over the object like an array * * @return \ArrayIterator */ public function getIterator() { return new \ArrayIterator($this->arguments); } } PK!cG11>Symfony/Component/EventDispatcher/EventSubscriberInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * An EventSubscriber knows himself what events he is interested in. * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes * {@link getSubscribedEvents} and registers the subscriber as a listener for all * returned events. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * * @api */ interface EventSubscriberInterface { /** * Returns an array of event names this subscriber wants to listen to. * * The array keys are event names and the value can be: * * * The method name to call (priority defaults to 0) * * An array composed of the method name to call and the priority * * An array of arrays composed of the method names to call and respective * priorities, or 0 if unset * * For instance: * * * array('eventName' => 'methodName') * * array('eventName' => array('methodName', $priority)) * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) * * @return array The event names to listen to * * @api */ public static function getSubscribedEvents(); } PK!s >Symfony/Component/EventDispatcher/ImmutableEventDispatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * A read-only proxy for an event dispatcher. * * @author Bernhard Schussek */ class ImmutableEventDispatcher implements EventDispatcherInterface { /** * The proxied dispatcher. * @var EventDispatcherInterface */ private $dispatcher; /** * Creates an unmodifiable proxy for an event dispatcher. * * @param EventDispatcherInterface $dispatcher The proxied event dispatcher. */ public function __construct(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * {@inheritdoc} */ public function dispatch($eventName, Event $event = null) { return $this->dispatcher->dispatch($eventName, $event); } /** * {@inheritdoc} */ public function addListener($eventName, $listener, $priority = 0) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function removeListener($eventName, $listener) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function getListeners($eventName = null) { return $this->dispatcher->getListeners($eventName); } /** * {@inheritdoc} */ public function hasListeners($eventName = null) { return $this->dispatcher->hasListeners($eventName); } } PK!U >Symfony/Component/EventDispatcher/EventDispatcherInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * Listeners are registered on the manager and events are dispatched through the * manager. * * @author Bernhard Schussek * * @api */ interface EventDispatcherInterface { /** * Dispatches an event to all registered listeners. * * @param string $eventName The name of the event to dispatch. The name of * the event is the name of the method that is * invoked on listeners. * @param Event $event The event to pass to the event handlers/listeners. * If not supplied, an empty Event instance is created. * * @return Event * * @api */ public function dispatch($eventName, Event $event = null); /** * Adds an event listener that listens on the specified events. * * @param string $eventName The event to listen on * @param callable $listener The listener * @param integer $priority The higher this value, the earlier an event * listener will be triggered in the chain (defaults to 0) * * @api */ public function addListener($eventName, $listener, $priority = 0); /** * Adds an event subscriber. * * The subscriber is asked for all the events he is * interested in and added as a listener for these events. * * @param EventSubscriberInterface $subscriber The subscriber. * * @api */ public function addSubscriber(EventSubscriberInterface $subscriber); /** * Removes an event listener from the specified events. * * @param string|array $eventName The event(s) to remove a listener from * @param callable $listener The listener to remove */ public function removeListener($eventName, $listener); /** * Removes an event subscriber. * * @param EventSubscriberInterface $subscriber The subscriber */ public function removeSubscriber(EventSubscriberInterface $subscriber); /** * Gets the listeners of a specific event or all listeners. * * @param string $eventName The name of the event * * @return array The event listeners for the specified event, or all event listeners by event name */ public function getListeners($eventName = null); /** * Checks whether an event has any registered listeners. * * @param string $eventName The name of the event * * @return Boolean true if the specified event has any listeners, false otherwise */ public function hasListeners($eventName = null); } PK!NmCSymfony/Component/EventDispatcher/ContainerAwareEventDispatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Lazily loads listeners and subscribers from the dependency injection * container * * @author Fabien Potencier * @author Bernhard Schussek * @author Jordan Alliot */ class ContainerAwareEventDispatcher extends EventDispatcher { /** * The container from where services are loaded * @var ContainerInterface */ private $container; /** * The service IDs of the event listeners and subscribers * @var array */ private $listenerIds = array(); /** * The services registered as listeners * @var array */ private $listeners = array(); /** * Constructor. * * @param ContainerInterface $container A ContainerInterface instance */ public function __construct(ContainerInterface $container) { $this->container = $container; } /** * Adds a service as event listener * * @param string $eventName Event for which the listener is added * @param array $callback The service ID of the listener service & the method * name that has to be called * @param integer $priority The higher this value, the earlier an event listener * will be triggered in the chain. * Defaults to 0. * * @throws \InvalidArgumentException */ public function addListenerService($eventName, $callback, $priority = 0) { if (!is_array($callback) || 2 !== count($callback)) { throw new \InvalidArgumentException('Expected an array("service", "method") argument'); } $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority); } public function removeListener($eventName, $listener) { $this->lazyLoad($eventName); if (isset($this->listeners[$eventName])) { foreach ($this->listeners[$eventName] as $key => $l) { foreach ($this->listenerIds[$eventName] as $i => $args) { list($serviceId, $method, $priority) = $args; if ($key === $serviceId.'.'.$method) { if ($listener === array($l, $method)) { unset($this->listeners[$eventName][$key]); if (empty($this->listeners[$eventName])) { unset($this->listeners[$eventName]); } unset($this->listenerIds[$eventName][$i]); if (empty($this->listenerIds[$eventName])) { unset($this->listenerIds[$eventName]); } } } } } } parent::removeListener($eventName, $listener); } /** * @see EventDispatcherInterface::hasListeners */ public function hasListeners($eventName = null) { if (null === $eventName) { return (Boolean) count($this->listenerIds) || (Boolean) count($this->listeners); } if (isset($this->listenerIds[$eventName])) { return true; } return parent::hasListeners($eventName); } /** * @see EventDispatcherInterface::getListeners */ public function getListeners($eventName = null) { if (null === $eventName) { foreach (array_keys($this->listenerIds) as $serviceEventName) { $this->lazyLoad($serviceEventName); } } else { $this->lazyLoad($eventName); } return parent::getListeners($eventName); } /** * Adds a service as event subscriber * * @param string $serviceId The service ID of the subscriber service * @param string $class The service's class name (which must implement EventSubscriberInterface) */ public function addSubscriberService($serviceId, $class) { foreach ($class::getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { $this->listenerIds[$eventName][] = array($serviceId, $params, 0); } elseif (is_string($params[0])) { $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0); } } } } /** * {@inheritDoc} * * Lazily loads listeners for this event from the dependency injection * container. * * @throws \InvalidArgumentException if the service is not defined */ public function dispatch($eventName, Event $event = null) { $this->lazyLoad($eventName); return parent::dispatch($eventName, $event); } public function getContainer() { return $this->container; } /** * Lazily loads listeners for this event from the dependency injection * container. * * @param string $eventName The name of the event to dispatch. The name of * the event is the name of the method that is * invoked on listeners. */ protected function lazyLoad($eventName) { if (isset($this->listenerIds[$eventName])) { foreach ($this->listenerIds[$eventName] as $args) { list($serviceId, $method, $priority) = $args; $listener = $this->container->get($serviceId); $key = $serviceId.'.'.$method; if (!isset($this->listeners[$eventName][$key])) { $this->addListener($eventName, array($listener, $method), $priority); } elseif ($listener !== $this->listeners[$eventName][$key]) { parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); $this->addListener($eventName, array($listener, $method), $priority); } $this->listeners[$eventName][$key] = $listener; } } } } PK!Y"5Symfony/Component/EventDispatcher/EventDispatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * * Listeners are registered on the manager and events are dispatched through the * manager. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * @author Fabien Potencier * @author Jordi Boggiano * @author Jordan Alliot * * @api */ class EventDispatcher implements EventDispatcherInterface { private $listeners = array(); private $sorted = array(); /** * @see EventDispatcherInterface::dispatch * * @api */ public function dispatch($eventName, Event $event = null) { if (null === $event) { $event = new Event(); } $event->setDispatcher($this); $event->setName($eventName); if (!isset($this->listeners[$eventName])) { return $event; } $this->doDispatch($this->getListeners($eventName), $eventName, $event); return $event; } /** * @see EventDispatcherInterface::getListeners */ public function getListeners($eventName = null) { if (null !== $eventName) { if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } return $this->sorted[$eventName]; } foreach (array_keys($this->listeners) as $eventName) { if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } } return $this->sorted; } /** * @see EventDispatcherInterface::hasListeners */ public function hasListeners($eventName = null) { return (Boolean) count($this->getListeners($eventName)); } /** * @see EventDispatcherInterface::addListener * * @api */ public function addListener($eventName, $listener, $priority = 0) { $this->listeners[$eventName][$priority][] = $listener; unset($this->sorted[$eventName]); } /** * @see EventDispatcherInterface::removeListener */ public function removeListener($eventName, $listener) { if (!isset($this->listeners[$eventName])) { return; } foreach ($this->listeners[$eventName] as $priority => $listeners) { if (false !== ($key = array_search($listener, $listeners, true))) { unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]); } } } /** * @see EventDispatcherInterface::addSubscriber * * @api */ public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { $this->addListener($eventName, array($subscriber, $params)); } elseif (is_string($params[0])) { $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); } } } } /** * @see EventDispatcherInterface::removeSubscriber */ public function removeSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_array($params) && is_array($params[0])) { foreach ($params as $listener) { $this->removeListener($eventName, array($subscriber, $listener[0])); } } else { $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0])); } } } /** * Triggers the listeners of an event. * * This method can be overridden to add functionality that is executed * for each listener. * * @param callable[] $listeners The event listeners. * @param string $eventName The name of the event to dispatch. * @param Event $event The event object to pass to the event handlers/listeners. */ protected function doDispatch($listeners, $eventName, Event $event) { foreach ($listeners as $listener) { call_user_func($listener, $event, $eventName, $this); if ($event->isPropagationStopped()) { break; } } } /** * Sorts the internal list of listeners for the given event by priority. * * @param string $eventName The name of the event. */ private function sortListeners($eventName) { $this->sorted[$eventName] = array(); if (isset($this->listeners[$eventName])) { krsort($this->listeners[$eventName]); $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); } } } PK! x 1Symfony/Component/Console/Command/ListCommand.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Helper\DescriptorHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputDefinition; /** * ListCommand displays the list of all available commands for the application. * * @author Fabien Potencier */ class ListCommand extends Command { /** * {@inheritdoc} */ protected function configure() { $this ->setName('list') ->setDefinition($this->createDefinition()) ->setDescription('Lists commands') ->setHelp(<<%command.name% command lists all commands: php %command.full_name% You can also display the commands for a specific namespace: php %command.full_name% test You can also output the information in other formats by using the --format option: php %command.full_name% --format=xml It's also possible to get raw list of commands (useful for embedding command runner): php %command.full_name% --raw EOF ) ; } /** * {@inheritdoc} */ public function getNativeDefinition() { return $this->createDefinition(); } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { if ($input->getOption('xml')) { $input->setOption('format', 'xml'); } $helper = new DescriptorHelper(); $helper->describe($output, $this->getApplication(), array( 'format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'namespace' => $input->getArgument('namespace'), )); } /** * {@inheritdoc} */ private function createDefinition() { return new InputDefinition(array( new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats', 'txt'), )); } } PK!Ƙ7@7@-Symfony/Component/Console/Command/Command.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Application; use Symfony\Component\Console\Helper\HelperSet; /** * Base class for all commands. * * @author Fabien Potencier * * @api */ class Command { private $application; private $name; private $aliases = array(); private $definition; private $help; private $description; private $ignoreValidationErrors = false; private $applicationDefinitionMerged = false; private $applicationDefinitionMergedWithArgs = false; private $code; private $synopsis; private $helperSet; /** * Constructor. * * @param string|null $name The name of the command; passing null means it must be set in configure() * * @throws \LogicException When the command name is empty * * @api */ public function __construct($name = null) { $this->definition = new InputDefinition(); if (null !== $name) { $this->setName($name); } $this->configure(); if (!$this->name) { throw new \LogicException('The command name cannot be empty.'); } } /** * Ignores validation errors. * * This is mainly useful for the help command. */ public function ignoreValidationErrors() { $this->ignoreValidationErrors = true; } /** * Sets the application instance for this command. * * @param Application $application An Application instance * * @api */ public function setApplication(Application $application = null) { $this->application = $application; if ($application) { $this->setHelperSet($application->getHelperSet()); } else { $this->helperSet = null; } } /** * Sets the helper set. * * @param HelperSet $helperSet A HelperSet instance */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; } /** * Gets the helper set. * * @return HelperSet A HelperSet instance */ public function getHelperSet() { return $this->helperSet; } /** * Gets the application instance for this command. * * @return Application An Application instance * * @api */ public function getApplication() { return $this->application; } /** * Checks whether the command is enabled or not in the current environment * * Override this to check for x or y and return false if the command can not * run properly under the current conditions. * * @return Boolean */ public function isEnabled() { return true; } /** * Configures the current command. */ protected function configure() { } /** * Executes the current command. * * This method is not abstract because you can use this class * as a concrete class. In this case, instead of defining the * execute() method, you set the code to execute by passing * a Closure to the setCode() method. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * * @return null|integer null or 0 if everything went fine, or an error code * * @throws \LogicException When this abstract method is not implemented * @see setCode() */ protected function execute(InputInterface $input, OutputInterface $output) { throw new \LogicException('You must override the execute() method in the concrete command class.'); } /** * Interacts with the user. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ protected function interact(InputInterface $input, OutputInterface $output) { } /** * Initializes the command just after the input has been validated. * * This is mainly useful when a lot of commands extends one main command * where some things need to be initialized based on the input arguments and options. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ protected function initialize(InputInterface $input, OutputInterface $output) { } /** * Runs the command. * * The code to execute is either defined directly with the * setCode() method or by overriding the execute() method * in a sub-class. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * * @return integer The command exit code * * @throws \Exception * * @see setCode() * @see execute() * * @api */ public function run(InputInterface $input, OutputInterface $output) { // force the creation of the synopsis before the merge with the app definition $this->getSynopsis(); // add the application arguments and options $this->mergeApplicationDefinition(); // bind the input against the command specific arguments/options try { $input->bind($this->definition); } catch (\Exception $e) { if (!$this->ignoreValidationErrors) { throw $e; } } $this->initialize($input, $output); if ($input->isInteractive()) { $this->interact($input, $output); } $input->validate(); if ($this->code) { $statusCode = call_user_func($this->code, $input, $output); } else { $statusCode = $this->execute($input, $output); } return is_numeric($statusCode) ? (int) $statusCode : 0; } /** * Sets the code to execute when running this command. * * If this method is used, it overrides the code defined * in the execute() method. * * @param callable $code A callable(InputInterface $input, OutputInterface $output) * * @return Command The current instance * * @throws \InvalidArgumentException * * @see execute() * * @api */ public function setCode($code) { if (!is_callable($code)) { throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.'); } $this->code = $code; return $this; } /** * Merges the application definition with the command definition. * * This method is not part of public API and should not be used directly. * * @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments */ public function mergeApplicationDefinition($mergeArgs = true) { if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { return; } if ($mergeArgs) { $currentArguments = $this->definition->getArguments(); $this->definition->setArguments($this->application->getDefinition()->getArguments()); $this->definition->addArguments($currentArguments); } $this->definition->addOptions($this->application->getDefinition()->getOptions()); $this->applicationDefinitionMerged = true; if ($mergeArgs) { $this->applicationDefinitionMergedWithArgs = true; } } /** * Sets an array of argument and option instances. * * @param array|InputDefinition $definition An array of argument and option instances or a definition instance * * @return Command The current instance * * @api */ public function setDefinition($definition) { if ($definition instanceof InputDefinition) { $this->definition = $definition; } else { $this->definition->setDefinition($definition); } $this->applicationDefinitionMerged = false; return $this; } /** * Gets the InputDefinition attached to this Command. * * @return InputDefinition An InputDefinition instance * * @api */ public function getDefinition() { return $this->definition; } /** * Gets the InputDefinition to be used to create XML and Text representations of this Command. * * Can be overridden to provide the original command representation when it would otherwise * be changed by merging with the application InputDefinition. * * This method is not part of public API and should not be used directly. * * @return InputDefinition An InputDefinition instance */ public function getNativeDefinition() { return $this->getDefinition(); } /** * Adds an argument. * * @param string $name The argument name * @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL * @param string $description A description text * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) * * @return Command The current instance * * @api */ public function addArgument($name, $mode = null, $description = '', $default = null) { $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); return $this; } /** * Adds an option. * * @param string $name The option name * @param string $shortcut The shortcut (can be null) * @param integer $mode The option mode: One of the InputOption::VALUE_* constants * @param string $description A description text * @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE) * * @return Command The current instance * * @api */ public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null) { $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); return $this; } /** * Sets the name of the command. * * This method can set both the namespace and the name if * you separate them by a colon (:) * * $command->setName('foo:bar'); * * @param string $name The command name * * @return Command The current instance * * @throws \InvalidArgumentException When the name is invalid * * @api */ public function setName($name) { $this->validateName($name); $this->name = $name; return $this; } /** * Returns the command name. * * @return string The command name * * @api */ public function getName() { return $this->name; } /** * Sets the description for the command. * * @param string $description The description for the command * * @return Command The current instance * * @api */ public function setDescription($description) { $this->description = $description; return $this; } /** * Returns the description for the command. * * @return string The description for the command * * @api */ public function getDescription() { return $this->description; } /** * Sets the help for the command. * * @param string $help The help for the command * * @return Command The current instance * * @api */ public function setHelp($help) { $this->help = $help; return $this; } /** * Returns the help for the command. * * @return string The help for the command * * @api */ public function getHelp() { return $this->help; } /** * Returns the processed help for the command replacing the %command.name% and * %command.full_name% patterns with the real values dynamically. * * @return string The processed help for the command */ public function getProcessedHelp() { $name = $this->name; $placeholders = array( '%command.name%', '%command.full_name%' ); $replacements = array( $name, $_SERVER['PHP_SELF'].' '.$name ); return str_replace($placeholders, $replacements, $this->getHelp()); } /** * Sets the aliases for the command. * * @param array $aliases An array of aliases for the command * * @return Command The current instance * * @throws \InvalidArgumentException When an alias is invalid * * @api */ public function setAliases($aliases) { foreach ($aliases as $alias) { $this->validateName($alias); } $this->aliases = $aliases; return $this; } /** * Returns the aliases for the command. * * @return array An array of aliases for the command * * @api */ public function getAliases() { return $this->aliases; } /** * Returns the synopsis for the command. * * @return string The synopsis */ public function getSynopsis() { if (null === $this->synopsis) { $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis())); } return $this->synopsis; } /** * Gets a helper instance by name. * * @param string $name The helper name * * @return mixed The helper value * * @throws \InvalidArgumentException if the helper is not defined * * @api */ public function getHelper($name) { return $this->helperSet->get($name); } /** * Returns a text representation of the command. * * @return string A string representing the command * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asText() { $descriptor = new TextDescriptor(); $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); $descriptor->describe($output, $this, array('raw_output' => true)); return $output->fetch(); } /** * Returns an XML representation of the command. * * @param Boolean $asDom Whether to return a DOM or an XML string * * @return string|\DOMDocument An XML string representing the command * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asXml($asDom = false) { $descriptor = new XmlDescriptor(); if ($asDom) { return $descriptor->getCommandDocument($this); } $output = new BufferedOutput(); $descriptor->describe($output, $this); return $output->fetch(); } /** * Validates a command name. * * It must be non-empty and parts can optionally be separated by ":". * * @param string $name * * @throws \InvalidArgumentException When the name is invalid */ private function validateName($name) { if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); } } } PK!m_ _ 1Symfony/Component/Console/Command/HelpCommand.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Helper\DescriptorHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * HelpCommand displays the help for a given command. * * @author Fabien Potencier */ class HelpCommand extends Command { private $command; /** * {@inheritdoc} */ protected function configure() { $this->ignoreValidationErrors(); $this ->setName('help') ->setDefinition(array( new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats', 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), )) ->setDescription('Displays help for a command') ->setHelp(<<%command.name% command displays help for a given command: php %command.full_name% list You can also output the help in other formats by using the --format option: php %command.full_name% --format=xml list To display the list of available commands, please use the list command. EOF ) ; } /** * Sets the command * * @param Command $command The command to set */ public function setCommand(Command $command) { $this->command = $command; } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { if (null === $this->command) { $this->command = $this->getApplication()->find($input->getArgument('command_name')); } if ($input->getOption('xml')) { $input->setOption('format', 'xml'); } $helper = new DescriptorHelper(); $helper->describe($output, $this->command, array( 'format' => $input->getOption('format'), 'raw' => $input->getOption('raw'), )); $this->command = null; } } PK!\0E+Symfony/Component/Console/ConsoleEvents.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console; /** * Contains all events dispatched by an Application. * * @author Francesco Levorato */ final class ConsoleEvents { /** * The COMMAND event allows you to attach listeners before any command is * executed by the console. It also allows you to modify the command, input and output * before they are handled to the command. * * The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent * instance. * * @var string */ const COMMAND = 'console.command'; /** * The TERMINATE event allows you to attach listeners after a command is * executed by the console. * * The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent * instance. * * @var string */ const TERMINATE = 'console.terminate'; /** * The EXCEPTION event occurs when an uncaught exception appears. * * This event allows you to deal with the exception or * to modify the thrown exception. The event listener method receives * a Symfony\Component\Console\Event\ConsoleExceptionEvent * instance. * * @var string */ const EXCEPTION = 'console.exception'; } PK!2V#Symfony/Component/Console/Shell.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Process\ProcessBuilder; use Symfony\Component\Process\PhpExecutableFinder; /** * A Shell wraps an Application to add shell capabilities to it. * * Support for history and completion only works with a PHP compiled * with readline support (either --with-readline or --with-libedit) * * @author Fabien Potencier * @author Martin Hasoň */ class Shell { private $application; private $history; private $output; private $hasReadline; private $processIsolation = false; /** * Constructor. * * If there is no readline support for the current PHP executable * a \RuntimeException exception is thrown. * * @param Application $application An application instance */ public function __construct(Application $application) { $this->hasReadline = function_exists('readline'); $this->application = $application; $this->history = getenv('HOME').'/.history_'.$application->getName(); $this->output = new ConsoleOutput(); } /** * Runs the shell. */ public function run() { $this->application->setAutoExit(false); $this->application->setCatchExceptions(true); if ($this->hasReadline) { readline_read_history($this->history); readline_completion_function(array($this, 'autocompleter')); } $this->output->writeln($this->getHeader()); $php = null; if ($this->processIsolation) { $finder = new PhpExecutableFinder(); $php = $finder->find(); $this->output->writeln(<<Running with process isolation, you should consider this: * each command is executed as separate process, * commands don't support interactivity, all params must be passed explicitly, * commands output is not colorized. EOF ); } while (true) { $command = $this->readline(); if (false === $command) { $this->output->writeln("\n"); break; } if ($this->hasReadline) { readline_add_history($command); readline_write_history($this->history); } if ($this->processIsolation) { $pb = new ProcessBuilder(); $process = $pb ->add($php) ->add($_SERVER['argv'][0]) ->add($command) ->inheritEnvironmentVariables(true) ->getProcess() ; $output = $this->output; $process->run(function ($type, $data) use ($output) { $output->writeln($data); }); $ret = $process->getExitCode(); } else { $ret = $this->application->run(new StringInput($command), $this->output); } if (0 !== $ret) { $this->output->writeln(sprintf('The command terminated with an error status (%s)', $ret)); } } } /** * Returns the shell header. * * @return string The header string */ protected function getHeader() { return <<{$this->application->getName()} shell ({$this->application->getVersion()}). At the prompt, type help for some help, or list to get a list of available commands. To exit the shell, type ^D. EOF; } /** * Renders a prompt. * * @return string The prompt */ protected function getPrompt() { // using the formatter here is required when using readline return $this->output->getFormatter()->format($this->application->getName().' > '); } protected function getOutput() { return $this->output; } protected function getApplication() { return $this->application; } /** * Tries to return autocompletion for the current entered text. * * @param string $text The last segment of the entered text * * @return Boolean|array A list of guessed strings or true */ private function autocompleter($text) { $info = readline_info(); $text = substr($info['line_buffer'], 0, $info['end']); if ($info['point'] !== $info['end']) { return true; } // task name? if (false === strpos($text, ' ') || !$text) { return array_keys($this->application->all()); } // options and arguments? try { $command = $this->application->find(substr($text, 0, strpos($text, ' '))); } catch (\Exception $e) { return true; } $list = array('--help'); foreach ($command->getDefinition()->getOptions() as $option) { $list[] = '--'.$option->getName(); } return $list; } /** * Reads a single line from standard input. * * @return string The single line from standard input */ private function readline() { if ($this->hasReadline) { $line = readline($this->getPrompt()); } else { $this->output->write($this->getPrompt()); $line = fgets(STDIN, 1024); $line = (!$line && strlen($line) == 0) ? false : rtrim($line); } return $line; } public function getProcessIsolation() { return $this->processIsolation; } public function setProcessIsolation($processIsolation) { $this->processIsolation = (Boolean) $processIsolation; if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) { throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.'); } } } PK!.QQ(Symfony/Component/Console/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tester; use Symfony\Component\Console\Application; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\StreamOutput; /** * Eases the testing of console applications. * * When testing an application, don't forget to disable the auto exit flag: * * $application = new Application(); * $application->setAutoExit(false); * * @author Fabien Potencier */ class ApplicationTester { private $application; private $input; private $output; private $statusCode; /** * Constructor. * * @param Application $application An Application instance to test. */ public function __construct(Application $application) { $this->application = $application; } /** * Executes the application. * * Available options: * * * interactive: Sets the input interactive flag * * decorated: Sets the output decorated flag * * verbosity: Sets the output verbosity flag * * @param array $input An array of arguments and options * @param array $options An array of options * * @return integer The command exit code */ public function run(array $input, $options = array()) { $this->input = new ArrayInput($input); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } $this->output = new StreamOutput(fopen('php://memory', 'w', false)); if (isset($options['decorated'])) { $this->output->setDecorated($options['decorated']); } if (isset($options['verbosity'])) { $this->output->setVerbosity($options['verbosity']); } return $this->statusCode = $this->application->run($this->input, $this->output); } /** * Gets the display returned by the last execution of the application. * * @param Boolean $normalize Whether to normalize end of lines to \n or not * * @return string The display */ public function getDisplay($normalize = false) { rewind($this->output->getStream()); $display = stream_get_contents($this->output->getStream()); if ($normalize) { $display = str_replace(PHP_EOL, "\n", $display); } return $display; } /** * Gets the input instance used by the last execution of the application. * * @return InputInterface The current input instance */ public function getInput() { return $this->input; } /** * Gets the output instance used by the last execution of the application. * * @return OutputInterface The current output instance */ public function getOutput() { return $this->output; } /** * Gets the status code returned by the last execution of the application. * * @return integer The status code */ public function getStatusCode() { return $this->statusCode; } } PK!~H(R2Symfony/Component/Console/Tester/CommandTester.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tester; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Eases the testing of console commands. * * @author Fabien Potencier */ class CommandTester { private $command; private $input; private $output; private $statusCode; /** * Constructor. * * @param Command $command A Command instance to test. */ public function __construct(Command $command) { $this->command = $command; } /** * Executes the command. * * Available options: * * * interactive: Sets the input interactive flag * * decorated: Sets the output decorated flag * * verbosity: Sets the output verbosity flag * * @param array $input An array of arguments and options * @param array $options An array of options * * @return integer The command exit code */ public function execute(array $input, array $options = array()) { // set the command name automatically if the application requires // this argument and no command name was passed if (!isset($input['command']) && (null !== $application = $this->command->getApplication()) && $application->getDefinition()->hasArgument('command') ) { $input['command'] = $this->command->getName(); } $this->input = new ArrayInput($input); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } $this->output = new StreamOutput(fopen('php://memory', 'w', false)); if (isset($options['decorated'])) { $this->output->setDecorated($options['decorated']); } if (isset($options['verbosity'])) { $this->output->setVerbosity($options['verbosity']); } return $this->statusCode = $this->command->run($this->input, $this->output); } /** * Gets the display returned by the last execution of the command. * * @param Boolean $normalize Whether to normalize end of lines to \n or not * * @return string The display */ public function getDisplay($normalize = false) { rewind($this->output->getStream()); $display = stream_get_contents($this->output->getStream()); if ($normalize) { $display = str_replace(PHP_EOL, "\n", $display); } return $display; } /** * Gets the input instance used by the last execution of the command. * * @return InputInterface The current input instance */ public function getInput() { return $this->input; } /** * Gets the output instance used by the last execution of the command. * * @return OutputInterface The current output instance */ public function getOutput() { return $this->output; } /** * Gets the status code returned by the last execution of the application. * * @return integer The status code */ public function getStatusCode() { return $this->statusCode; } } PK!Q))-Symfony/Component/Console/Input/ArgvInput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * ArgvInput represents an input coming from the CLI arguments. * * Usage: * * $input = new ArgvInput(); * * By default, the `$_SERVER['argv']` array is used for the input values. * * This can be overridden by explicitly passing the input values in the constructor: * * $input = new ArgvInput($_SERVER['argv']); * * If you pass it yourself, don't forget that the first element of the array * is the name of the running application. * * When passing an argument to the constructor, be sure that it respects * the same rules as the argv one. It's almost always better to use the * `StringInput` when you want to provide your own input. * * @author Fabien Potencier * * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 * * @api */ class ArgvInput extends Input { private $tokens; private $parsed; /** * Constructor. * * @param array $argv An array of parameters from the CLI (in the argv format) * @param InputDefinition $definition A InputDefinition instance * * @api */ public function __construct(array $argv = null, InputDefinition $definition = null) { if (null === $argv) { $argv = $_SERVER['argv']; } // strip the application name array_shift($argv); $this->tokens = $argv; parent::__construct($definition); } protected function setTokens(array $tokens) { $this->tokens = $tokens; } /** * Processes command line arguments. */ protected function parse() { $parseOptions = true; $this->parsed = $this->tokens; while (null !== $token = array_shift($this->parsed)) { if ($parseOptions && '' == $token) { $this->parseArgument($token); } elseif ($parseOptions && '--' == $token) { $parseOptions = false; } elseif ($parseOptions && 0 === strpos($token, '--')) { $this->parseLongOption($token); } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { $this->parseShortOption($token); } else { $this->parseArgument($token); } } } /** * Parses a short option. * * @param string $token The current token. */ private function parseShortOption($token) { $name = substr($token, 1); if (strlen($name) > 1) { if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { // an option with a value (with no space) $this->addShortOption($name[0], substr($name, 1)); } else { $this->parseShortOptionSet($name); } } else { $this->addShortOption($name, null); } } /** * Parses a short option set. * * @param string $name The current token * * @throws \RuntimeException When option given doesn't exist */ private function parseShortOptionSet($name) { $len = strlen($name); for ($i = 0; $i < $len; $i++) { if (!$this->definition->hasShortcut($name[$i])) { throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i])); } $option = $this->definition->getOptionForShortcut($name[$i]); if ($option->acceptValue()) { $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); break; } else { $this->addLongOption($option->getName(), null); } } } /** * Parses a long option. * * @param string $token The current token */ private function parseLongOption($token) { $name = substr($token, 2); if (false !== $pos = strpos($name, '=')) { $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); } else { $this->addLongOption($name, null); } } /** * Parses an argument. * * @param string $token The current token * * @throws \RuntimeException When too many arguments are given */ private function parseArgument($token) { $c = count($this->arguments); // if input is expecting another argument, add it if ($this->definition->hasArgument($c)) { $arg = $this->definition->getArgument($c); $this->arguments[$arg->getName()] = $arg->isArray()? array($token) : $token; // if last argument isArray(), append token to last argument } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { $arg = $this->definition->getArgument($c - 1); $this->arguments[$arg->getName()][] = $token; // unexpected argument } else { throw new \RuntimeException('Too many arguments.'); } } /** * Adds a short option value. * * @param string $shortcut The short option key * @param mixed $value The value for the option * * @throws \RuntimeException When option given doesn't exist */ private function addShortOption($shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); } /** * Adds a long option value. * * @param string $name The long option key * @param mixed $value The value for the option * * @throws \RuntimeException When option given doesn't exist */ private function addLongOption($name, $value) { if (!$this->definition->hasOption($name)) { throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name)); } $option = $this->definition->getOption($name); // Convert false values (from a previous call to substr()) to null if (false === $value) { $value = null; } if (null !== $value && !$option->acceptValue()) { throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name, $value)); } if (null === $value && $option->acceptValue() && count($this->parsed)) { // if option accepts an optional or mandatory argument // let's see if there is one provided $next = array_shift($this->parsed); if (isset($next[0]) && '-' !== $next[0]) { $value = $next; } elseif (empty($next)) { $value = ''; } else { array_unshift($this->parsed, $next); } } if (null === $value) { if ($option->isValueRequired()) { throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); } if (!$option->isArray()) { $value = $option->isValueOptional() ? $option->getDefault() : true; } } if ($option->isArray()) { $this->options[$name][] = $value; } else { $this->options[$name] = $value; } } /** * Returns the first argument from the raw parameters (not parsed). * * @return string The value of the first argument or null otherwise */ public function getFirstArgument() { foreach ($this->tokens as $token) { if ($token && '-' === $token[0]) { continue; } return $token; } } /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * * @return Boolean true if the value is contained in the raw parameters */ public function hasParameterOption($values) { $values = (array) $values; foreach ($this->tokens as $token) { foreach ($values as $value) { if ($token === $value || 0 === strpos($token, $value.'=')) { return true; } } } return false; } /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * * @return mixed The option value */ public function getParameterOption($values, $default = false) { $values = (array) $values; $tokens = $this->tokens; while ($token = array_shift($tokens)) { foreach ($values as $value) { if ($token === $value || 0 === strpos($token, $value.'=')) { if (false !== $pos = strpos($token, '=')) { return substr($token, $pos + 1); } return array_shift($tokens); } } } return $default; } /** * Returns a stringified representation of the args passed to the command * * @return string */ public function __toString() { $self = $this; $tokens = array_map(function ($token) use ($self) { if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { return $match[1] . $self->escapeToken($match[2]); } if ($token && $token[0] !== '-') { return $self->escapeToken($token); } return $token; }, $this->tokens); return implode(' ', $tokens); } } PK!' 1Symfony/Component/Console/Input/InputArgument.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * Represents a command line argument. * * @author Fabien Potencier * * @api */ class InputArgument { const REQUIRED = 1; const OPTIONAL = 2; const IS_ARRAY = 4; private $name; private $mode; private $default; private $description; /** * Constructor. * * @param string $name The argument name * @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param string $description A description text * @param mixed $default The default value (for self::OPTIONAL mode only) * * @throws \InvalidArgumentException When argument mode is not valid * * @api */ public function __construct($name, $mode = null, $description = '', $default = null) { if (null === $mode) { $mode = self::OPTIONAL; } elseif (!is_int($mode) || $mode > 7 || $mode < 1) { throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); } $this->name = $name; $this->mode = $mode; $this->description = $description; $this->setDefault($default); } /** * Returns the argument name. * * @return string The argument name */ public function getName() { return $this->name; } /** * Returns true if the argument is required. * * @return Boolean true if parameter mode is self::REQUIRED, false otherwise */ public function isRequired() { return self::REQUIRED === (self::REQUIRED & $this->mode); } /** * Returns true if the argument can take multiple values. * * @return Boolean true if mode is self::IS_ARRAY, false otherwise */ public function isArray() { return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); } /** * Sets the default value. * * @param mixed $default The default value * * @throws \LogicException When incorrect default value is given */ public function setDefault($default = null) { if (self::REQUIRED === $this->mode && null !== $default) { throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.'); } if ($this->isArray()) { if (null === $default) { $default = array(); } elseif (!is_array($default)) { throw new \LogicException('A default value for an array argument must be an array.'); } } $this->default = $default; } /** * Returns the default value. * * @return mixed The default value */ public function getDefault() { return $this->default; } /** * Returns the description text. * * @return string The description text */ public function getDescription() { return $this->description; } } PK!AM662Symfony/Component/Console/Input/InputInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * InputInterface is the interface implemented by all input classes. * * @author Fabien Potencier */ interface InputInterface { /** * Returns the first argument from the raw parameters (not parsed). * * @return string The value of the first argument or null otherwise */ public function getFirstArgument(); /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The values to look for in the raw parameters (can be an array) * * @return Boolean true if the value is contained in the raw parameters */ public function hasParameterOption($values); /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * * @return mixed The option value */ public function getParameterOption($values, $default = false); /** * Binds the current Input instance with the given arguments and options. * * @param InputDefinition $definition A InputDefinition instance */ public function bind(InputDefinition $definition); /** * Validates if arguments given are correct. * * Throws an exception when not enough arguments are given. * * @throws \RuntimeException */ public function validate(); /** * Returns all the given arguments merged with the default values. * * @return array */ public function getArguments(); /** * Gets argument by name. * * @param string $name The name of the argument * * @return mixed */ public function getArgument($name); /** * Sets an argument value by name. * * @param string $name The argument name * @param string $value The argument value * * @throws \InvalidArgumentException When argument given doesn't exist */ public function setArgument($name, $value); /** * Returns true if an InputArgument object exists by name or position. * * @param string|integer $name The InputArgument name or position * * @return Boolean true if the InputArgument object exists, false otherwise */ public function hasArgument($name); /** * Returns all the given options merged with the default values. * * @return array */ public function getOptions(); /** * Gets an option by name. * * @param string $name The name of the option * * @return mixed */ public function getOption($name); /** * Sets an option value by name. * * @param string $name The option name * @param string|boolean $value The option value * * @throws \InvalidArgumentException When option given doesn't exist */ public function setOption($name, $value); /** * Returns true if an InputOption object exists by name. * * @param string $name The InputOption name * * @return Boolean true if the InputOption object exists, false otherwise */ public function hasOption($name); /** * Is this input means interactive? * * @return Boolean */ public function isInteractive(); /** * Sets the input interactivity. * * @param Boolean $interactive If the input should be interactive */ public function setInteractive($interactive); } PK!OVV/Symfony/Component/Console/Input/InputOption.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * Represents a command line option. * * @author Fabien Potencier * * @api */ class InputOption { const VALUE_NONE = 1; const VALUE_REQUIRED = 2; const VALUE_OPTIONAL = 4; const VALUE_IS_ARRAY = 8; private $name; private $shortcut; private $mode; private $default; private $description; /** * Constructor. * * @param string $name The option name * @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts * @param integer $mode The option mode: One of the VALUE_* constants * @param string $description A description text * @param mixed $default The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE) * * @throws \InvalidArgumentException If option mode is invalid or incompatible * * @api */ public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) { if (0 === strpos($name, '--')) { $name = substr($name, 2); } if (empty($name)) { throw new \InvalidArgumentException('An option name cannot be empty.'); } if (empty($shortcut)) { $shortcut = null; } if (null !== $shortcut) { if (is_array($shortcut)) { $shortcut = implode('|', $shortcut); } $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); $shortcuts = array_filter($shortcuts); $shortcut = implode('|', $shortcuts); if (empty($shortcut)) { throw new \InvalidArgumentException('An option shortcut cannot be empty.'); } } if (null === $mode) { $mode = self::VALUE_NONE; } elseif (!is_int($mode) || $mode > 15 || $mode < 1) { throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); } $this->name = $name; $this->shortcut = $shortcut; $this->mode = $mode; $this->description = $description; if ($this->isArray() && !$this->acceptValue()) { throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); } $this->setDefault($default); } /** * Returns the option shortcut. * * @return string The shortcut */ public function getShortcut() { return $this->shortcut; } /** * Returns the option name. * * @return string The name */ public function getName() { return $this->name; } /** * Returns true if the option accepts a value. * * @return Boolean true if value mode is not self::VALUE_NONE, false otherwise */ public function acceptValue() { return $this->isValueRequired() || $this->isValueOptional(); } /** * Returns true if the option requires a value. * * @return Boolean true if value mode is self::VALUE_REQUIRED, false otherwise */ public function isValueRequired() { return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); } /** * Returns true if the option takes an optional value. * * @return Boolean true if value mode is self::VALUE_OPTIONAL, false otherwise */ public function isValueOptional() { return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); } /** * Returns true if the option can take multiple values. * * @return Boolean true if mode is self::VALUE_IS_ARRAY, false otherwise */ public function isArray() { return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); } /** * Sets the default value. * * @param mixed $default The default value * * @throws \LogicException When incorrect default value is given */ public function setDefault($default = null) { if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); } if ($this->isArray()) { if (null === $default) { $default = array(); } elseif (!is_array($default)) { throw new \LogicException('A default value for an array option must be an array.'); } } $this->default = $this->acceptValue() ? $default : false; } /** * Returns the default value. * * @return mixed The default value */ public function getDefault() { return $this->default; } /** * Returns the description text. * * @return string The description text */ public function getDescription() { return $this->description; } /** * Checks whether the given option equals this one * * @param InputOption $option option to compare * @return Boolean */ public function equals(InputOption $option) { return $option->getName() === $this->getName() && $option->getShortcut() === $this->getShortcut() && $option->getDefault() === $this->getDefault() && $option->isArray() === $this->isArray() && $option->isValueRequired() === $this->isValueRequired() && $option->isValueOptional() === $this->isValueOptional() ; } } PK!1E(0(03Symfony/Component/Console/Input/InputDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; if (!defined('JSON_UNESCAPED_UNICODE')) { define('JSON_UNESCAPED_SLASHES', 64); define('JSON_UNESCAPED_UNICODE', 256); } use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Output\BufferedOutput; /** * A InputDefinition represents a set of valid command line arguments and options. * * Usage: * * $definition = new InputDefinition(array( * new InputArgument('name', InputArgument::REQUIRED), * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), * )); * * @author Fabien Potencier * * @api */ class InputDefinition { private $arguments; private $requiredCount; private $hasAnArrayArgument = false; private $hasOptional; private $options; private $shortcuts; /** * Constructor. * * @param array $definition An array of InputArgument and InputOption instance * * @api */ public function __construct(array $definition = array()) { $this->setDefinition($definition); } /** * Sets the definition of the input. * * @param array $definition The definition array * * @api */ public function setDefinition(array $definition) { $arguments = array(); $options = array(); foreach ($definition as $item) { if ($item instanceof InputOption) { $options[] = $item; } else { $arguments[] = $item; } } $this->setArguments($arguments); $this->setOptions($options); } /** * Sets the InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects * * @api */ public function setArguments($arguments = array()) { $this->arguments = array(); $this->requiredCount = 0; $this->hasOptional = false; $this->hasAnArrayArgument = false; $this->addArguments($arguments); } /** * Adds an array of InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects * * @api */ public function addArguments($arguments = array()) { if (null !== $arguments) { foreach ($arguments as $argument) { $this->addArgument($argument); } } } /** * Adds an InputArgument object. * * @param InputArgument $argument An InputArgument object * * @throws \LogicException When incorrect argument is given * * @api */ public function addArgument(InputArgument $argument) { if (isset($this->arguments[$argument->getName()])) { throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName())); } if ($this->hasAnArrayArgument) { throw new \LogicException('Cannot add an argument after an array argument.'); } if ($argument->isRequired() && $this->hasOptional) { throw new \LogicException('Cannot add a required argument after an optional one.'); } if ($argument->isArray()) { $this->hasAnArrayArgument = true; } if ($argument->isRequired()) { ++$this->requiredCount; } else { $this->hasOptional = true; } $this->arguments[$argument->getName()] = $argument; } /** * Returns an InputArgument by name or by position. * * @param string|integer $name The InputArgument name or position * * @return InputArgument An InputArgument object * * @throws \InvalidArgumentException When argument given doesn't exist * * @api */ public function getArgument($name) { if (!$this->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; return $arguments[$name]; } /** * Returns true if an InputArgument object exists by name or position. * * @param string|integer $name The InputArgument name or position * * @return Boolean true if the InputArgument object exists, false otherwise * * @api */ public function hasArgument($name) { $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; return isset($arguments[$name]); } /** * Gets the array of InputArgument objects. * * @return InputArgument[] An array of InputArgument objects * * @api */ public function getArguments() { return $this->arguments; } /** * Returns the number of InputArguments. * * @return integer The number of InputArguments */ public function getArgumentCount() { return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments); } /** * Returns the number of required InputArguments. * * @return integer The number of required InputArguments */ public function getArgumentRequiredCount() { return $this->requiredCount; } /** * Gets the default values. * * @return array An array of default values */ public function getArgumentDefaults() { $values = array(); foreach ($this->arguments as $argument) { $values[$argument->getName()] = $argument->getDefault(); } return $values; } /** * Sets the InputOption objects. * * @param InputOption[] $options An array of InputOption objects * * @api */ public function setOptions($options = array()) { $this->options = array(); $this->shortcuts = array(); $this->addOptions($options); } /** * Adds an array of InputOption objects. * * @param InputOption[] $options An array of InputOption objects * * @api */ public function addOptions($options = array()) { foreach ($options as $option) { $this->addOption($option); } } /** * Adds an InputOption object. * * @param InputOption $option An InputOption object * * @throws \LogicException When option given already exist * * @api */ public function addOption(InputOption $option) { if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName())); } if ($option->getShortcut()) { foreach (explode('|', $option->getShortcut()) as $shortcut) { if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); } } } $this->options[$option->getName()] = $option; if ($option->getShortcut()) { foreach (explode('|', $option->getShortcut()) as $shortcut) { $this->shortcuts[$shortcut] = $option->getName(); } } } /** * Returns an InputOption by name. * * @param string $name The InputOption name * * @return InputOption A InputOption object * * @throws \InvalidArgumentException When option given doesn't exist * * @api */ public function getOption($name) { if (!$this->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); } return $this->options[$name]; } /** * Returns true if an InputOption object exists by name. * * @param string $name The InputOption name * * @return Boolean true if the InputOption object exists, false otherwise * * @api */ public function hasOption($name) { return isset($this->options[$name]); } /** * Gets the array of InputOption objects. * * @return InputOption[] An array of InputOption objects * * @api */ public function getOptions() { return $this->options; } /** * Returns true if an InputOption object exists by shortcut. * * @param string $name The InputOption shortcut * * @return Boolean true if the InputOption object exists, false otherwise */ public function hasShortcut($name) { return isset($this->shortcuts[$name]); } /** * Gets an InputOption by shortcut. * * @param string $shortcut the Shortcut name * * @return InputOption An InputOption object */ public function getOptionForShortcut($shortcut) { return $this->getOption($this->shortcutToName($shortcut)); } /** * Gets an array of default values. * * @return array An array of all default values */ public function getOptionDefaults() { $values = array(); foreach ($this->options as $option) { $values[$option->getName()] = $option->getDefault(); } return $values; } /** * Returns the InputOption name given a shortcut. * * @param string $shortcut The shortcut * * @return string The InputOption name * * @throws \InvalidArgumentException When option given does not exist */ private function shortcutToName($shortcut) { if (!isset($this->shortcuts[$shortcut])) { throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); } return $this->shortcuts[$shortcut]; } /** * Gets the synopsis. * * @return string The synopsis */ public function getSynopsis() { $elements = array(); foreach ($this->getOptions() as $option) { $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName()); } foreach ($this->getArguments() as $argument) { $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : '')); if ($argument->isArray()) { $elements[] = sprintf('... [%sN]', $argument->getName()); } } return implode(' ', $elements); } /** * Returns a textual representation of the InputDefinition. * * @return string A string representing the InputDefinition * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asText() { $descriptor = new TextDescriptor(); $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); $descriptor->describe($output, $this, array('raw_output' => true)); return $output->fetch(); } /** * Returns an XML representation of the InputDefinition. * * @param Boolean $asDom Whether to return a DOM or an XML string * * @return string|\DOMDocument An XML string representing the InputDefinition * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asXml($asDom = false) { $descriptor = new XmlDescriptor(); if ($asDom) { return $descriptor->getInputDefinitionDocument($this); } $output = new BufferedOutput(); $descriptor->describe($output, $this); return $output->fetch(); } } PK!΂= /Symfony/Component/Console/Input/StringInput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * StringInput represents an input provided as a string. * * Usage: * * $input = new StringInput('foo --bar="foobar"'); * * @author Fabien Potencier * * @api */ class StringInput extends ArgvInput { const REGEX_STRING = '([^\s]+?)(?:\s|(?setTokens($this->tokenize($input)); if (null !== $definition) { $this->bind($definition); } } /** * Tokenizes a string. * * @param string $input The input to tokenize * * @return array An array of tokens * * @throws \InvalidArgumentException When unable to parse input (should never happen) */ private function tokenize($input) { $tokens = array(); $length = strlen($input); $cursor = 0; while ($cursor < $length) { if (preg_match('/\s+/A', $input, $match, null, $cursor)) { } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2))); } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) { $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) { $tokens[] = stripcslashes($match[1]); } else { // should never happen // @codeCoverageIgnoreStart throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); // @codeCoverageIgnoreEnd } $cursor += strlen($match[0]); } return $tokens; } } PK!gm()Symfony/Component/Console/Input/Input.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * Input is the base class for all concrete Input classes. * * Three concrete classes are provided by default: * * * `ArgvInput`: The input comes from the CLI arguments (argv) * * `StringInput`: The input is provided as a string * * `ArrayInput`: The input is provided as an array * * @author Fabien Potencier */ abstract class Input implements InputInterface { /** * @var InputDefinition */ protected $definition; protected $options = array(); protected $arguments = array(); protected $interactive = true; /** * Constructor. * * @param InputDefinition $definition A InputDefinition instance */ public function __construct(InputDefinition $definition = null) { if (null === $definition) { $this->definition = new InputDefinition(); } else { $this->bind($definition); $this->validate(); } } /** * Binds the current Input instance with the given arguments and options. * * @param InputDefinition $definition A InputDefinition instance */ public function bind(InputDefinition $definition) { $this->arguments = array(); $this->options = array(); $this->definition = $definition; $this->parse(); } /** * Processes command line arguments. */ abstract protected function parse(); /** * Validates the input. * * @throws \RuntimeException When not enough arguments are given */ public function validate() { if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) { throw new \RuntimeException('Not enough arguments.'); } } /** * Checks if the input is interactive. * * @return Boolean Returns true if the input is interactive */ public function isInteractive() { return $this->interactive; } /** * Sets the input interactivity. * * @param Boolean $interactive If the input should be interactive */ public function setInteractive($interactive) { $this->interactive = (Boolean) $interactive; } /** * Returns the argument values. * * @return array An array of argument values */ public function getArguments() { return array_merge($this->definition->getArgumentDefaults(), $this->arguments); } /** * Returns the argument value for a given argument name. * * @param string $name The argument name * * @return mixed The argument value * * @throws \InvalidArgumentException When argument given doesn't exist */ public function getArgument($name) { if (!$this->definition->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); } /** * Sets an argument value by name. * * @param string $name The argument name * @param string $value The argument value * * @throws \InvalidArgumentException When argument given doesn't exist */ public function setArgument($name, $value) { if (!$this->definition->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; } /** * Returns true if an InputArgument object exists by name or position. * * @param string|integer $name The InputArgument name or position * * @return Boolean true if the InputArgument object exists, false otherwise */ public function hasArgument($name) { return $this->definition->hasArgument($name); } /** * Returns the options values. * * @return array An array of option values */ public function getOptions() { return array_merge($this->definition->getOptionDefaults(), $this->options); } /** * Returns the option value for a given option name. * * @param string $name The option name * * @return mixed The option value * * @throws \InvalidArgumentException When option given doesn't exist */ public function getOption($name) { if (!$this->definition->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); } /** * Sets an option value by name. * * @param string $name The option name * @param string|boolean $value The option value * * @throws \InvalidArgumentException When option given doesn't exist */ public function setOption($name, $value) { if (!$this->definition->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } $this->options[$name] = $value; } /** * Returns true if an InputOption object exists by name. * * @param string $name The InputOption name * * @return Boolean true if the InputOption object exists, false otherwise */ public function hasOption($name) { return $this->definition->hasOption($name); } /** * Escapes a token through escapeshellarg if it contains unsafe chars * * @param string $token * * @return string */ public function escapeToken($token) { return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); } } PK!p%%.Symfony/Component/Console/Input/ArrayInput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * ArrayInput represents an input provided as an array. * * Usage: * * $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar')); * * @author Fabien Potencier * * @api */ class ArrayInput extends Input { private $parameters; /** * Constructor. * * @param array $parameters An array of parameters * @param InputDefinition $definition A InputDefinition instance * * @api */ public function __construct(array $parameters, InputDefinition $definition = null) { $this->parameters = $parameters; parent::__construct($definition); } /** * Returns the first argument from the raw parameters (not parsed). * * @return string The value of the first argument or null otherwise */ public function getFirstArgument() { foreach ($this->parameters as $key => $value) { if ($key && '-' === $key[0]) { continue; } return $value; } } /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The values to look for in the raw parameters (can be an array) * * @return Boolean true if the value is contained in the raw parameters */ public function hasParameterOption($values) { $values = (array) $values; foreach ($this->parameters as $k => $v) { if (!is_int($k)) { $v = $k; } if (in_array($v, $values)) { return true; } } return false; } /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * * @return mixed The option value */ public function getParameterOption($values, $default = false) { $values = (array) $values; foreach ($this->parameters as $k => $v) { if (is_int($k) && in_array($v, $values)) { return true; } elseif (in_array($k, $values)) { return $v; } } return $default; } /** * Returns a stringified representation of the args passed to the command * * @return string */ public function __toString() { $params = array(); foreach ($this->parameters as $param => $val) { if ($param && '-' === $param[0]) { $params[] = $param . ('' != $val ? '='.$this->escapeToken($val) : ''); } else { $params[] = $this->escapeToken($val); } } return implode(' ', $params); } /** * Processes command line arguments. */ protected function parse() { foreach ($this->parameters as $key => $value) { if (0 === strpos($key, '--')) { $this->addLongOption(substr($key, 2), $value); } elseif ('-' === $key[0]) { $this->addShortOption(substr($key, 1), $value); } else { $this->addArgument($key, $value); } } } /** * Adds a short option value. * * @param string $shortcut The short option key * @param mixed $value The value for the option * * @throws \InvalidArgumentException When option given doesn't exist */ private function addShortOption($shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); } /** * Adds a long option value. * * @param string $name The long option key * @param mixed $value The value for the option * * @throws \InvalidArgumentException When option given doesn't exist * @throws \InvalidArgumentException When a required value is missing */ private function addLongOption($name, $value) { if (!$this->definition->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); } $option = $this->definition->getOption($name); if (null === $value) { if ($option->isValueRequired()) { throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name)); } $value = $option->isValueOptional() ? $option->getDefault() : true; } $this->options[$name] = $value; } /** * Adds an argument value. * * @param string $name The argument name * @param mixed $value The value for the argument * * @throws \InvalidArgumentException When argument given doesn't exist */ private function addArgument($name, $value) { if (!$this->definition->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; } } PK!9Kh^^7Symfony/Component/Console/Input/InputAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * InputAwareInterface should be implemented by classes that depends on the * Console Input. * * @author Wouter J */ interface InputAwareInterface { /** * Sets the Console Input. * * @param InputInterface */ public function setInput(InputInterface $input); } PK!onj&&<Symfony/Component/Console/Formatter/OutputFormatterStyle.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter style class for defining styles. * * @author Konstantin Kudryashov * * @api */ class OutputFormatterStyle implements OutputFormatterStyleInterface { private static $availableForegroundColors = array( 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37 ); private static $availableBackgroundColors = array( 'black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47 ); private static $availableOptions = array( 'bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8 ); private $foreground; private $background; private $options = array(); /** * Initializes output formatter style. * * @param string|null $foreground The style foreground color name * @param string|null $background The style background color name * @param array $options The style options * * @api */ public function __construct($foreground = null, $background = null, array $options = array()) { if (null !== $foreground) { $this->setForeground($foreground); } if (null !== $background) { $this->setBackground($background); } if (count($options)) { $this->setOptions($options); } } /** * Sets style foreground color. * * @param string|null $color The color name * * @throws \InvalidArgumentException When the color name isn't defined * * @api */ public function setForeground($color = null) { if (null === $color) { $this->foreground = null; return; } if (!isset(static::$availableForegroundColors[$color])) { throw new \InvalidArgumentException(sprintf( 'Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors)) )); } $this->foreground = static::$availableForegroundColors[$color]; } /** * Sets style background color. * * @param string|null $color The color name * * @throws \InvalidArgumentException When the color name isn't defined * * @api */ public function setBackground($color = null) { if (null === $color) { $this->background = null; return; } if (!isset(static::$availableBackgroundColors[$color])) { throw new \InvalidArgumentException(sprintf( 'Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors)) )); } $this->background = static::$availableBackgroundColors[$color]; } /** * Sets some specific style option. * * @param string $option The option name * * @throws \InvalidArgumentException When the option name isn't defined * * @api */ public function setOption($option) { if (!isset(static::$availableOptions[$option])) { throw new \InvalidArgumentException(sprintf( 'Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)) )); } if (false === array_search(static::$availableOptions[$option], $this->options)) { $this->options[] = static::$availableOptions[$option]; } } /** * Unsets some specific style option. * * @param string $option The option name * * @throws \InvalidArgumentException When the option name isn't defined * */ public function unsetOption($option) { if (!isset(static::$availableOptions[$option])) { throw new \InvalidArgumentException(sprintf( 'Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)) )); } $pos = array_search(static::$availableOptions[$option], $this->options); if (false !== $pos) { unset($this->options[$pos]); } } /** * Sets multiple style options at once. * * @param array $options */ public function setOptions(array $options) { $this->options = array(); foreach ($options as $option) { $this->setOption($option); } } /** * Applies the style to a given text. * * @param string $text The text to style * * @return string */ public function apply($text) { $codes = array(); if (null !== $this->foreground) { $codes[] = $this->foreground; } if (null !== $this->background) { $codes[] = $this->background; } if (count($this->options)) { $codes = array_merge($codes, $this->options); } if (0 === count($codes)) { return $text; } return sprintf("\033[%sm%s\033[0m", implode(';', $codes), $text); } } PK!l7Symfony/Component/Console/Formatter/OutputFormatter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter class for console output. * * @author Konstantin Kudryashov * * @api */ class OutputFormatter implements OutputFormatterInterface { private $decorated; private $styles = array(); private $styleStack; /** * Escapes "<" special char in given text. * * @param string $text Text to escape * * @return string Escaped text */ public static function escape($text) { return preg_replace('/([^\\\\]?) FormatterStyle" instances * * @api */ public function __construct($decorated = false, array $styles = array()) { $this->decorated = (Boolean) $decorated; $this->setStyle('error', new OutputFormatterStyle('white', 'red')); $this->setStyle('info', new OutputFormatterStyle('green')); $this->setStyle('comment', new OutputFormatterStyle('yellow')); $this->setStyle('question', new OutputFormatterStyle('black', 'cyan')); foreach ($styles as $name => $style) { $this->setStyle($name, $style); } $this->styleStack = new OutputFormatterStyleStack(); } /** * Sets the decorated flag. * * @param Boolean $decorated Whether to decorate the messages or not * * @api */ public function setDecorated($decorated) { $this->decorated = (Boolean) $decorated; } /** * Gets the decorated flag. * * @return Boolean true if the output will decorate messages, false otherwise * * @api */ public function isDecorated() { return $this->decorated; } /** * Sets a new style. * * @param string $name The style name * @param OutputFormatterStyleInterface $style The style instance * * @api */ public function setStyle($name, OutputFormatterStyleInterface $style) { $this->styles[strtolower($name)] = $style; } /** * Checks if output formatter has style with specified name. * * @param string $name * * @return Boolean * * @api */ public function hasStyle($name) { return isset($this->styles[strtolower($name)]); } /** * Gets style options from style with specified name. * * @param string $name * * @return OutputFormatterStyleInterface * * @throws \InvalidArgumentException When style isn't defined * * @api */ public function getStyle($name) { if (!$this->hasStyle($name)) { throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name)); } return $this->styles[strtolower($name)]; } /** * Formats a message according to the given styles. * * @param string $message The message to style * * @return string The styled message * * @api */ public function format($message) { $offset = 0; $output = ''; $tagRegex = '[a-z][a-z0-9_=;-]*'; preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#isx", $message, $matches, PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; $text = $match[0]; // add the text up to the next tag $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset)); $offset = $pos + strlen($text); // opening tag? if ($open = '/' != $text[1]) { $tag = $matches[1][$i][0]; } else { $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : ''; } if (!$open && !$tag) { // $this->styleStack->pop(); } elseif ($pos && '\\' == $message[$pos - 1]) { // escaped tag $output .= $this->applyCurrentStyle($text); } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) { $output .= $this->applyCurrentStyle($text); } elseif ($open) { $this->styleStack->push($style); } else { $this->styleStack->pop($style); } } $output .= $this->applyCurrentStyle(substr($message, $offset)); return str_replace('\\<', '<', $output); } /** * @return OutputFormatterStyleStack */ public function getStyleStack() { return $this->styleStack; } /** * Tries to create new style instance from string. * * @param string $string * * @return OutputFormatterStyle|Boolean false if string is not format string */ private function createStyleFromString($string) { if (isset($this->styles[$string])) { return $this->styles[$string]; } if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) { return false; } $style = new OutputFormatterStyle(); foreach ($matches as $match) { array_shift($match); if ('fg' == $match[0]) { $style->setForeground($match[1]); } elseif ('bg' == $match[0]) { $style->setBackground($match[1]); } else { $style->setOption($match[1]); } } return $style; } /** * Applies current style from stack to text, if must be applied. * * @param string $text Input text * * @return string Styled text */ private function applyCurrentStyle($text) { return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text; } } PK!5ESymfony/Component/Console/Formatter/OutputFormatterStyleInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter style interface for defining styles. * * @author Konstantin Kudryashov * * @api */ interface OutputFormatterStyleInterface { /** * Sets style foreground color. * * @param string $color The color name * * @api */ public function setForeground($color = null); /** * Sets style background color. * * @param string $color The color name * * @api */ public function setBackground($color = null); /** * Sets some specific style option. * * @param string $option The option name * * @api */ public function setOption($option); /** * Unsets some specific style option. * * @param string $option The option name */ public function unsetOption($option); /** * Sets multiple style options at once. * * @param array $options */ public function setOptions(array $options); /** * Applies the style to a given text. * * @param string $text The text to style * * @return string */ public function apply($text); } PK!v ASymfony/Component/Console/Formatter/OutputFormatterStyleStack.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * @author Jean-François Simon */ class OutputFormatterStyleStack { /** * @var OutputFormatterStyleInterface[] */ private $styles; /** * @var OutputFormatterStyleInterface */ private $emptyStyle; /** * Constructor. * * @param OutputFormatterStyleInterface|null $emptyStyle */ public function __construct(OutputFormatterStyleInterface $emptyStyle = null) { $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); $this->reset(); } /** * Resets stack (ie. empty internal arrays). */ public function reset() { $this->styles = array(); } /** * Pushes a style in the stack. * * @param OutputFormatterStyleInterface $style */ public function push(OutputFormatterStyleInterface $style) { $this->styles[] = $style; } /** * Pops a style from the stack. * * @param OutputFormatterStyleInterface|null $style * * @return OutputFormatterStyleInterface * * @throws \InvalidArgumentException When style tags incorrectly nested */ public function pop(OutputFormatterStyleInterface $style = null) { if (empty($this->styles)) { return $this->emptyStyle; } if (null === $style) { return array_pop($this->styles); } foreach (array_reverse($this->styles, true) as $index => $stackedStyle) { if ($style->apply('') === $stackedStyle->apply('')) { $this->styles = array_slice($this->styles, 0, $index); return $stackedStyle; } } throw new \InvalidArgumentException('Incorrectly nested style tag found.'); } /** * Computes current style with stacks top codes. * * @return OutputFormatterStyle */ public function getCurrent() { if (empty($this->styles)) { return $this->emptyStyle; } return $this->styles[count($this->styles)-1]; } /** * @param OutputFormatterStyleInterface $emptyStyle * * @return OutputFormatterStyleStack */ public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) { $this->emptyStyle = $emptyStyle; return $this; } /** * @return OutputFormatterStyleInterface */ public function getEmptyStyle() { return $this->emptyStyle; } } PK!Jp@Symfony/Component/Console/Formatter/OutputFormatterInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter interface for console output. * * @author Konstantin Kudryashov * * @api */ interface OutputFormatterInterface { /** * Sets the decorated flag. * * @param Boolean $decorated Whether to decorate the messages or not * * @api */ public function setDecorated($decorated); /** * Gets the decorated flag. * * @return Boolean true if the output will decorate messages, false otherwise * * @api */ public function isDecorated(); /** * Sets a new style. * * @param string $name The style name * @param OutputFormatterStyleInterface $style The style instance * * @api */ public function setStyle($name, OutputFormatterStyleInterface $style); /** * Checks if output formatter has style with specified name. * * @param string $name * * @return Boolean * * @api */ public function hasStyle($name); /** * Gets style options from style with specified name. * * @param string $name * * @return OutputFormatterStyleInterface * * @api */ public function getStyle($name); /** * Formats a message according to the given styles. * * @param string $message The message to style * * @return string The styled message * * @api */ public function format($message); } PK!0KK;Symfony/Component/Console/Output/ConsoleOutputInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; /** * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. * This adds information about stderr output stream. * * @author Dariusz Górecki */ interface ConsoleOutputInterface extends OutputInterface { /** * Gets the OutputInterface for errors. * * @return OutputInterface */ public function getErrorOutput(); /** * Sets the OutputInterface used for errors. * * @param OutputInterface $error */ public function setErrorOutput(OutputInterface $error); } PK!ϱ} } 2Symfony/Component/Console/Output/ConsoleOutput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * ConsoleOutput is the default class for all CLI output. It uses STDOUT. * * This class is a convenient wrapper around `StreamOutput`. * * $output = new ConsoleOutput(); * * This is equivalent to: * * $output = new StreamOutput(fopen('php://stdout', 'w')); * * @author Fabien Potencier * * @api */ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface { private $stderr; /** * Constructor. * * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param Boolean|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @api */ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) { $outputStream = 'php://stdout'; if (!$this->hasStdoutSupport()) { $outputStream = 'php://output'; } parent::__construct(fopen($outputStream, 'w'), $verbosity, $decorated, $formatter); $this->stderr = new StreamOutput(fopen('php://stderr', 'w'), $verbosity, $decorated, $formatter); } /** * {@inheritdoc} */ public function setDecorated($decorated) { parent::setDecorated($decorated); $this->stderr->setDecorated($decorated); } /** * {@inheritdoc} */ public function setFormatter(OutputFormatterInterface $formatter) { parent::setFormatter($formatter); $this->stderr->setFormatter($formatter); } /** * {@inheritdoc} */ public function setVerbosity($level) { parent::setVerbosity($level); $this->stderr->setVerbosity($level); } /** * {@inheritdoc} */ public function getErrorOutput() { return $this->stderr; } /** * {@inheritdoc} */ public function setErrorOutput(OutputInterface $error) { $this->stderr = $error; } /** * Returns true if current environment supports writing console output to * STDOUT. * * IBM iSeries (OS400) exhibits character-encoding issues when writing to * STDOUT and doesn't properly convert ASCII to EBCDIC, resulting in garbage * output. * * @return boolean */ protected function hasStdoutSupport() { return ('OS400' != php_uname('s')); } } PK!zM M 4Symfony/Component/Console/Output/OutputInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * OutputInterface is the interface implemented by all Output classes. * * @author Fabien Potencier * * @api */ interface OutputInterface { const VERBOSITY_QUIET = 0; const VERBOSITY_NORMAL = 1; const VERBOSITY_VERBOSE = 2; const VERBOSITY_VERY_VERBOSE = 3; const VERBOSITY_DEBUG = 4; const OUTPUT_NORMAL = 0; const OUTPUT_RAW = 1; const OUTPUT_PLAIN = 2; /** * Writes a message to the output. * * @param string|array $messages The message as an array of lines or a single string * @param Boolean $newline Whether to add a newline * @param integer $type The type of output (one of the OUTPUT constants) * * @throws \InvalidArgumentException When unknown output type is given * * @api */ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL); /** * Writes a message to the output and adds a newline at the end. * * @param string|array $messages The message as an array of lines of a single string * @param integer $type The type of output (one of the OUTPUT constants) * * @throws \InvalidArgumentException When unknown output type is given * * @api */ public function writeln($messages, $type = self::OUTPUT_NORMAL); /** * Sets the verbosity of the output. * * @param integer $level The level of verbosity (one of the VERBOSITY constants) * * @api */ public function setVerbosity($level); /** * Gets the current verbosity of the output. * * @return integer The current level of verbosity (one of the VERBOSITY constants) * * @api */ public function getVerbosity(); /** * Sets the decorated flag. * * @param Boolean $decorated Whether to decorate the messages * * @api */ public function setDecorated($decorated); /** * Gets the decorated flag. * * @return Boolean true if the output will decorate messages, false otherwise * * @api */ public function isDecorated(); /** * Sets output formatter. * * @param OutputFormatterInterface $formatter * * @api */ public function setFormatter(OutputFormatterInterface $formatter); /** * Returns current output formatter instance. * * @return OutputFormatterInterface * * @api */ public function getFormatter(); } PK!F$_/Symfony/Component/Console/Output/NullOutput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * NullOutput suppresses all output. * * $output = new NullOutput(); * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class NullOutput implements OutputInterface { /** * {@inheritdoc} */ public function setFormatter(OutputFormatterInterface $formatter) { // do nothing } /** * {@inheritdoc} */ public function getFormatter() { // to comply with the interface we must return a OutputFormatterInterface return new OutputFormatter(); } /** * {@inheritdoc} */ public function setDecorated($decorated) { // do nothing } /** * {@inheritdoc} */ public function isDecorated() { return false; } /** * {@inheritdoc} */ public function setVerbosity($level) { // do nothing } /** * {@inheritdoc} */ public function getVerbosity() { return self::VERBOSITY_QUIET; } /** * {@inheritdoc} */ public function writeln($messages, $type = self::OUTPUT_NORMAL) { // do nothing } /** * {@inheritdoc} */ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) { // do nothing } } PK!sQ;;+Symfony/Component/Console/Output/Output.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Formatter\OutputFormatter; /** * Base class for output classes. * * There are five levels of verbosity: * * * normal: no option passed (normal output) * * verbose: -v (more output) * * very verbose: -vv (highly extended output) * * debug: -vvv (all debug output) * * quiet: -q (no output) * * @author Fabien Potencier * * @api */ abstract class Output implements OutputInterface { private $verbosity; private $formatter; /** * Constructor. * * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param Boolean $decorated Whether to decorate messages * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @api */ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null) { $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; $this->formatter = $formatter ?: new OutputFormatter(); $this->formatter->setDecorated($decorated); } /** * {@inheritdoc} */ public function setFormatter(OutputFormatterInterface $formatter) { $this->formatter = $formatter; } /** * {@inheritdoc} */ public function getFormatter() { return $this->formatter; } /** * {@inheritdoc} */ public function setDecorated($decorated) { $this->formatter->setDecorated($decorated); } /** * {@inheritdoc} */ public function isDecorated() { return $this->formatter->isDecorated(); } /** * {@inheritdoc} */ public function setVerbosity($level) { $this->verbosity = (int) $level; } /** * {@inheritdoc} */ public function getVerbosity() { return $this->verbosity; } public function isQuiet() { return self::VERBOSITY_QUIET === $this->verbosity; } public function isVerbose() { return self::VERBOSITY_VERBOSE <= $this->verbosity; } public function isVeryVerbose() { return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; } public function isDebug() { return self::VERBOSITY_DEBUG <= $this->verbosity; } /** * {@inheritdoc} */ public function writeln($messages, $type = self::OUTPUT_NORMAL) { $this->write($messages, true, $type); } /** * {@inheritdoc} */ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) { if (self::VERBOSITY_QUIET === $this->verbosity) { return; } $messages = (array) $messages; foreach ($messages as $message) { switch ($type) { case OutputInterface::OUTPUT_NORMAL: $message = $this->formatter->format($message); break; case OutputInterface::OUTPUT_RAW: break; case OutputInterface::OUTPUT_PLAIN: $message = strip_tags($this->formatter->format($message)); break; default: throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type)); } $this->doWrite($message, $newline); } } /** * Writes a message to the output. * * @param string $message A message to write to the output * @param Boolean $newline Whether to add a newline or not */ abstract protected function doWrite($message, $newline); } PK!,QM M 1Symfony/Component/Console/Output/StreamOutput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * StreamOutput writes the output to a given stream. * * Usage: * * $output = new StreamOutput(fopen('php://stdout', 'w')); * * As `StreamOutput` can use any stream, you can also use a file: * * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); * * @author Fabien Potencier * * @api */ class StreamOutput extends Output { private $stream; /** * Constructor. * * @param mixed $stream A stream resource * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param Boolean|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @throws \InvalidArgumentException When first argument is not a real stream * * @api */ public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) { if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) { throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); } $this->stream = $stream; if (null === $decorated) { $decorated = $this->hasColorSupport(); } parent::__construct($verbosity, $decorated, $formatter); } /** * Gets the stream attached to this StreamOutput instance. * * @return resource A stream resource */ public function getStream() { return $this->stream; } /** * {@inheritdoc} */ protected function doWrite($message, $newline) { if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) { // @codeCoverageIgnoreStart // should never happen throw new \RuntimeException('Unable to write output.'); // @codeCoverageIgnoreEnd } fflush($this->stream); } /** * Returns true if the stream supports colorization. * * Colorization is disabled if not supported by the stream: * * - Windows without Ansicon and ConEmu * - non tty consoles * * @return Boolean true if the stream supports colorization, false otherwise */ protected function hasColorSupport() { // @codeCoverageIgnoreStart if (DIRECTORY_SEPARATOR == '\\') { return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI'); } return function_exists('posix_isatty') && @posix_isatty($this->stream); // @codeCoverageIgnoreEnd } } PK!t|X4hh3Symfony/Component/Console/Output/BufferedOutput.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; /** * @author Jean-François Simon */ class BufferedOutput extends Output { /** * @var string */ private $buffer = ''; /** * Empties buffer and returns its content. * * @return string */ public function fetch() { $content = $this->buffer; $this->buffer = ''; return $content; } /** * {@inheritdoc} */ protected function doWrite($message, $newline) { $this->buffer .= $message; if ($newline) { $this->buffer .= "\n"; } } } PK!LUҊҊ)Symfony/Component/Console/Application.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputAwareInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\HelpCommand; use Symfony\Component\Console\Command\ListCommand; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\FormatterHelper; use Symfony\Component\Console\Helper\DialogHelper; use Symfony\Component\Console\Helper\ProgressHelper; use Symfony\Component\Console\Helper\TableHelper; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * An Application is the container for a collection of commands. * * It is the main entry point of a Console application. * * This class is optimized for a standard CLI environment. * * Usage: * * $app = new Application('myapp', '1.0 (stable)'); * $app->add(new SimpleCommand()); * $app->run(); * * @author Fabien Potencier * * @api */ class Application { private $commands = array(); private $wantHelps = false; private $runningCommand; private $name; private $version; private $catchExceptions = true; private $autoExit = true; private $definition; private $helperSet; private $dispatcher; private $terminalDimensions; /** * Constructor. * * @param string $name The name of the application * @param string $version The version of the application * * @api */ public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') { $this->name = $name; $this->version = $version; $this->helperSet = $this->getDefaultHelperSet(); $this->definition = $this->getDefaultInputDefinition(); foreach ($this->getDefaultCommands() as $command) { $this->add($command); } } public function setDispatcher(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * Runs the current application. * * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return integer 0 if everything went fine, or an error code * * @throws \Exception When doRun returns Exception * * @api */ public function run(InputInterface $input = null, OutputInterface $output = null) { if (null === $input) { $input = new ArgvInput(); } if (null === $output) { $output = new ConsoleOutput(); } $this->configureIO($input, $output); try { $exitCode = $this->doRun($input, $output); } catch (\Exception $e) { if (!$this->catchExceptions) { throw $e; } if ($output instanceof ConsoleOutputInterface) { $this->renderException($e, $output->getErrorOutput()); } else { $this->renderException($e, $output); } $exitCode = $e->getCode(); if (is_numeric($exitCode)) { $exitCode = (int) $exitCode; if (0 === $exitCode) { $exitCode = 1; } } else { $exitCode = 1; } } if ($this->autoExit) { if ($exitCode > 255) { $exitCode = 255; } // @codeCoverageIgnoreStart exit($exitCode); // @codeCoverageIgnoreEnd } return $exitCode; } /** * Runs the current application. * * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return integer 0 if everything went fine, or an error code */ public function doRun(InputInterface $input, OutputInterface $output) { if (true === $input->hasParameterOption(array('--version', '-V'))) { $output->writeln($this->getLongVersion()); return 0; } $name = $this->getCommandName($input); if (true === $input->hasParameterOption(array('--help', '-h'))) { if (!$name) { $name = 'help'; $input = new ArrayInput(array('command' => 'help')); } else { $this->wantHelps = true; } } if (!$name) { $name = 'list'; $input = new ArrayInput(array('command' => 'list')); } // the command name MUST be the first element of the input $command = $this->find($name); $this->runningCommand = $command; $exitCode = $this->doRunCommand($command, $input, $output); $this->runningCommand = null; return $exitCode; } /** * Set a helper set to be used with the command. * * @param HelperSet $helperSet The helper set * * @api */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; } /** * Get the helper set associated with the command. * * @return HelperSet The HelperSet instance associated with this command * * @api */ public function getHelperSet() { return $this->helperSet; } /** * Set an input definition set to be used with this application * * @param InputDefinition $definition The input definition * * @api */ public function setDefinition(InputDefinition $definition) { $this->definition = $definition; } /** * Gets the InputDefinition related to this Application. * * @return InputDefinition The InputDefinition instance */ public function getDefinition() { return $this->definition; } /** * Gets the help message. * * @return string A help message. */ public function getHelp() { $messages = array( $this->getLongVersion(), '', 'Usage:', ' [options] command [arguments]', '', 'Options:', ); foreach ($this->getDefinition()->getOptions() as $option) { $messages[] = sprintf(' %-29s %s %s', '--'.$option->getName().'', $option->getShortcut() ? '-'.$option->getShortcut().'' : ' ', $option->getDescription() ); } return implode(PHP_EOL, $messages); } /** * Sets whether to catch exceptions or not during commands execution. * * @param Boolean $boolean Whether to catch exceptions or not during commands execution * * @api */ public function setCatchExceptions($boolean) { $this->catchExceptions = (Boolean) $boolean; } /** * Sets whether to automatically exit after a command execution or not. * * @param Boolean $boolean Whether to automatically exit after a command execution or not * * @api */ public function setAutoExit($boolean) { $this->autoExit = (Boolean) $boolean; } /** * Gets the name of the application. * * @return string The application name * * @api */ public function getName() { return $this->name; } /** * Sets the application name. * * @param string $name The application name * * @api */ public function setName($name) { $this->name = $name; } /** * Gets the application version. * * @return string The application version * * @api */ public function getVersion() { return $this->version; } /** * Sets the application version. * * @param string $version The application version * * @api */ public function setVersion($version) { $this->version = $version; } /** * Returns the long version of the application. * * @return string The long application version * * @api */ public function getLongVersion() { if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) { return sprintf('%s version %s', $this->getName(), $this->getVersion()); } return 'Console Tool'; } /** * Registers a new command. * * @param string $name The command name * * @return Command The newly created command * * @api */ public function register($name) { return $this->add(new Command($name)); } /** * Adds an array of command objects. * * @param Command[] $commands An array of commands * * @api */ public function addCommands(array $commands) { foreach ($commands as $command) { $this->add($command); } } /** * Adds a command object. * * If a command with the same name already exists, it will be overridden. * * @param Command $command A Command object * * @return Command The registered command * * @api */ public function add(Command $command) { $command->setApplication($this); if (!$command->isEnabled()) { $command->setApplication(null); return; } if (null === $command->getDefinition()) { throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command))); } $this->commands[$command->getName()] = $command; foreach ($command->getAliases() as $alias) { $this->commands[$alias] = $command; } return $command; } /** * Returns a registered command by name or alias. * * @param string $name The command name or alias * * @return Command A Command object * * @throws \InvalidArgumentException When command name given does not exist * * @api */ public function get($name) { if (!isset($this->commands[$name])) { throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name)); } $command = $this->commands[$name]; if ($this->wantHelps) { $this->wantHelps = false; $helpCommand = $this->get('help'); $helpCommand->setCommand($command); return $helpCommand; } return $command; } /** * Returns true if the command exists, false otherwise. * * @param string $name The command name or alias * * @return Boolean true if the command exists, false otherwise * * @api */ public function has($name) { return isset($this->commands[$name]); } /** * Returns an array of all unique namespaces used by currently registered commands. * * It does not returns the global namespace which always exists. * * @return array An array of namespaces */ public function getNamespaces() { $namespaces = array(); foreach ($this->commands as $command) { $namespaces[] = $this->extractNamespace($command->getName()); foreach ($command->getAliases() as $alias) { $namespaces[] = $this->extractNamespace($alias); } } return array_values(array_unique(array_filter($namespaces))); } /** * Finds a registered namespace by a name or an abbreviation. * * @param string $namespace A namespace or abbreviation to search for * * @return string A registered namespace * * @throws \InvalidArgumentException When namespace is incorrect or ambiguous */ public function findNamespace($namespace) { $allNamespaces = $this->getNamespaces(); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace); $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); if (empty($namespaces)) { $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); if ($alternatives = $this->findAlternatives($namespace, $allNamespaces, array())) { if (1 == count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { $message .= "\n\nDid you mean one of these?\n "; } $message .= implode("\n ", $alternatives); } throw new \InvalidArgumentException($message); } $exact = in_array($namespace, $namespaces, true); if (count($namespaces) > 1 && !$exact) { throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces)))); } return $exact ? $namespace : reset($namespaces); } /** * Finds a command by name or alias. * * Contrary to get, this command tries to find the best * match if you give it an abbreviation of a name or alias. * * @param string $name A command name or a command alias * * @return Command A Command instance * * @throws \InvalidArgumentException When command name is incorrect or ambiguous * * @api */ public function find($name) { $allCommands = array_keys($this->commands); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); $commands = preg_grep('{^'.$expr.'}', $allCommands); if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) { if (false !== $pos = strrpos($name, ':')) { // check if a namespace exists and contains commands $this->findNamespace(substr($name, 0, $pos)); } $message = sprintf('Command "%s" is not defined.', $name); if ($alternatives = $this->findAlternatives($name, $allCommands, array())) { if (1 == count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { $message .= "\n\nDid you mean one of these?\n "; } $message .= implode("\n ", $alternatives); } throw new \InvalidArgumentException($message); } // filter out aliases for commands which are already on the list if (count($commands) > 1) { $commandList = $this->commands; $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) { $commandName = $commandList[$nameOrAlias]->getName(); return $commandName === $nameOrAlias || !in_array($commandName, $commands); }); } $exact = in_array($name, $commands, true); if (count($commands) > 1 && !$exact) { $suggestions = $this->getAbbreviationSuggestions(array_values($commands)); throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions)); } return $this->get($exact ? $name : reset($commands)); } /** * Gets the commands (registered in the given namespace if provided). * * The array keys are the full names and the values the command instances. * * @param string $namespace A namespace name * * @return Command[] An array of Command instances * * @api */ public function all($namespace = null) { if (null === $namespace) { return $this->commands; } $commands = array(); foreach ($this->commands as $name => $command) { if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { $commands[$name] = $command; } } return $commands; } /** * Returns an array of possible abbreviations given a set of names. * * @param array $names An array of names * * @return array An array of abbreviations */ public static function getAbbreviations($names) { $abbrevs = array(); foreach ($names as $name) { for ($len = strlen($name); $len > 0; --$len) { $abbrev = substr($name, 0, $len); $abbrevs[$abbrev][] = $name; } } return $abbrevs; } /** * Returns a text representation of the Application. * * @param string $namespace An optional namespace name * @param boolean $raw Whether to return raw command list * * @return string A string representing the Application * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asText($namespace = null, $raw = false) { $descriptor = new TextDescriptor(); $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw); $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true)); return $output->fetch(); } /** * Returns an XML representation of the Application. * * @param string $namespace An optional namespace name * @param Boolean $asDom Whether to return a DOM or an XML string * * @return string|\DOMDocument An XML string representing the Application * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asXml($namespace = null, $asDom = false) { $descriptor = new XmlDescriptor(); if ($asDom) { return $descriptor->getApplicationDocument($this, $namespace); } $output = new BufferedOutput(); $descriptor->describe($output, $this, array('namespace' => $namespace)); return $output->fetch(); } /** * Renders a caught exception. * * @param \Exception $e An exception instance * @param OutputInterface $output An OutputInterface instance */ public function renderException($e, $output) { $strlen = function ($string) { if (!function_exists('mb_strlen')) { return strlen($string); } if (false === $encoding = mb_detect_encoding($string)) { return strlen($string); } return mb_strlen($string, $encoding); }; do { $title = sprintf(' [%s] ', get_class($e)); $len = $strlen($title); // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : (defined('HHVM_VERSION') ? 1 << 31 : PHP_INT_MAX); $formatter = $output->getFormatter(); $lines = array(); foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { foreach (str_split($line, $width - 4) as $line) { // pre-format lines to get the right string length $lineLength = $strlen(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4; $lines[] = array($line, $lineLength); $len = max($lineLength, $len); } } $messages = array('', ''); $messages[] = $emptyLine = $formatter->format(sprintf('%s', str_repeat(' ', $len))); $messages[] = $formatter->format(sprintf('%s%s', $title, str_repeat(' ', max(0, $len - $strlen($title))))); foreach ($lines as $line) { $messages[] = $formatter->format(sprintf(' %s %s', $line[0], str_repeat(' ', $len - $line[1]))); } $messages[] = $emptyLine; $messages[] = ''; $messages[] = ''; $output->writeln($messages, OutputInterface::OUTPUT_RAW); if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $output->writeln('Exception trace:'); // exception related properties $trace = $e->getTrace(); array_unshift($trace, array( 'function' => '', 'file' => $e->getFile() != null ? $e->getFile() : 'n/a', 'line' => $e->getLine() != null ? $e->getLine() : 'n/a', 'args' => array(), )); for ($i = 0, $count = count($trace); $i < $count; $i++) { $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; $function = $trace[$i]['function']; $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line)); } $output->writeln(""); $output->writeln(""); } } while ($e = $e->getPrevious()); if (null !== $this->runningCommand) { $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName()))); $output->writeln(""); $output->writeln(""); } } /** * Tries to figure out the terminal width in which this application runs * * @return int|null */ protected function getTerminalWidth() { $dimensions = $this->getTerminalDimensions(); return $dimensions[0]; } /** * Tries to figure out the terminal height in which this application runs * * @return int|null */ protected function getTerminalHeight() { $dimensions = $this->getTerminalDimensions(); return $dimensions[1]; } /** * Tries to figure out the terminal dimensions based on the current environment * * @return array Array containing width and height */ public function getTerminalDimensions() { if ($this->terminalDimensions) { return $this->terminalDimensions; } if (defined('PHP_WINDOWS_VERSION_BUILD')) { // extract [w, H] from "wxh (WxH)" if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) { return array((int) $matches[1], (int) $matches[2]); } // extract [w, h] from "wxh" if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) { return array((int) $matches[1], (int) $matches[2]); } } if ($sttyString = $this->getSttyColumns()) { // extract [w, h] from "rows h; columns w;" if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { return array((int) $matches[2], (int) $matches[1]); } // extract [w, h] from "; h rows; w columns" if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { return array((int) $matches[2], (int) $matches[1]); } } return array(null, null); } /** * Sets terminal dimensions. * * Can be useful to force terminal dimensions for functional tests. * * @param integer $width The width * @param integer $height The height * * @return Application The current application */ public function setTerminalDimensions($width, $height) { $this->terminalDimensions = array($width, $height); return $this; } /** * Configures the input and output instances based on the user arguments and options. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ protected function configureIO(InputInterface $input, OutputInterface $output) { if (true === $input->hasParameterOption(array('--ansi'))) { $output->setDecorated(true); } elseif (true === $input->hasParameterOption(array('--no-ansi'))) { $output->setDecorated(false); } if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) { $input->setInteractive(false); } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) { $inputStream = $this->getHelperSet()->get('dialog')->getInputStream(); if (!@posix_isatty($inputStream)) { $input->setInteractive(false); } } if (true === $input->hasParameterOption(array('--quiet', '-q'))) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); } else { if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) { $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) { $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); } } } /** * Runs the current command. * * If an event dispatcher has been attached to the application, * events are also dispatched during the life-cycle of the command. * * @param Command $command A Command instance * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return integer 0 if everything went fine, or an error code */ protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) { foreach ($command->getHelperSet() as $helper) { if ($helper instanceof InputAwareInterface) { $helper->setInput($input); } } if (null === $this->dispatcher) { return $command->run($input, $output); } $event = new ConsoleCommandEvent($command, $input, $output); $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); try { $exitCode = $command->run($input, $output); } catch (\Exception $e) { $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode()); $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode()); $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); throw $event->getException(); } $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); return $event->getExitCode(); } /** * Gets the name of the command based on input. * * @param InputInterface $input The input interface * * @return string The command name */ protected function getCommandName(InputInterface $input) { return $input->getFirstArgument(); } /** * Gets the default input definition. * * @return InputDefinition An InputDefinition instance */ protected function getDefaultInputDefinition() { return new InputDefinition(array( new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message.'), new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message.'), new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version.'), new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output.'), new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output.'), new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'), )); } /** * Gets the default commands that should always be available. * * @return Command[] An array of default Command instances */ protected function getDefaultCommands() { return array(new HelpCommand(), new ListCommand()); } /** * Gets the default helper set with the helpers that should always be available. * * @return HelperSet A HelperSet instance */ protected function getDefaultHelperSet() { return new HelperSet(array( new FormatterHelper(), new DialogHelper(), new ProgressHelper(), new TableHelper(), )); } /** * Runs and parses stty -a if it's available, suppressing any error output * * @return string */ private function getSttyColumns() { if (!function_exists('proc_open')) { return; } $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); if (is_resource($process)) { $info = stream_get_contents($pipes[1]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); return $info; } } /** * Runs and parses mode CON if it's available, suppressing any error output * * @return string x or null if it could not be parsed */ private function getConsoleMode() { if (!function_exists('proc_open')) { return; } $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); if (is_resource($process)) { $info = stream_get_contents($pipes[1]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { return $matches[2].'x'.$matches[1]; } } } /** * Returns abbreviated suggestions in string format. * * @param array $abbrevs Abbreviated suggestions to convert * * @return string A formatted string of abbreviated suggestions */ private function getAbbreviationSuggestions($abbrevs) { return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''); } /** * Returns the namespace part of the command name. * * This method is not part of public API and should not be used directly. * * @param string $name The full name of the command * @param string $limit The maximum number of parts of the namespace * * @return string The namespace of the command */ public function extractNamespace($name, $limit = null) { $parts = explode(':', $name); array_pop($parts); return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit)); } /** * Finds alternative of $name among $collection, * if nothing is found in $collection, try in $abbrevs * * @param string $name The string * @param array|\Traversable $collection The collection * * @return array A sorted array of similar string */ private function findAlternatives($name, $collection) { $threshold = 1e3; $alternatives = array(); $collectionParts = array(); foreach ($collection as $item) { $collectionParts[$item] = explode(':', $item); } foreach (explode(':', $name) as $i => $subname) { foreach ($collectionParts as $collectionName => $parts) { $exists = isset($alternatives[$collectionName]); if (!isset($parts[$i]) && $exists) { $alternatives[$collectionName] += $threshold; continue; } elseif (!isset($parts[$i])) { continue; } $lev = levenshtein($subname, $parts[$i]); if ($lev <= strlen($subname) / 3 || false !== strpos($parts[$i], $subname)) { $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; } elseif ($exists) { $alternatives[$collectionName] += $threshold; } } } foreach ($collection as $item) { $lev = levenshtein($name, $item); if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; } } $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2*$threshold; }); asort($alternatives); return array_keys($alternatives); } } PK! .Symfony/Component/Console/Helper/HelperSet.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Command\Command; /** * HelperSet represents a set of helpers to be used with a command. * * @author Fabien Potencier */ class HelperSet implements \IteratorAggregate { private $helpers = array(); private $command; /** * Constructor. * * @param Helper[] $helpers An array of helper. */ public function __construct(array $helpers = array()) { foreach ($helpers as $alias => $helper) { $this->set($helper, is_int($alias) ? null : $alias); } } /** * Sets a helper. * * @param HelperInterface $helper The helper instance * @param string $alias An alias */ public function set(HelperInterface $helper, $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { $this->helpers[$alias] = $helper; } $helper->setHelperSet($this); } /** * Returns true if the helper if defined. * * @param string $name The helper name * * @return Boolean true if the helper is defined, false otherwise */ public function has($name) { return isset($this->helpers[$name]); } /** * Gets a helper value. * * @param string $name The helper name * * @return HelperInterface The helper instance * * @throws \InvalidArgumentException if the helper is not defined */ public function get($name) { if (!$this->has($name)) { throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); } return $this->helpers[$name]; } /** * Sets the command associated with this helper set. * * @param Command $command A Command instance */ public function setCommand(Command $command = null) { $this->command = $command; } /** * Gets the command associated with this helper set. * * @return Command A Command instance */ public function getCommand() { return $this->command; } public function getIterator() { return new \ArrayIterator($this->helpers); } } PK!z4Symfony/Component/Console/Helper/HelperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * HelperInterface is the interface all helpers must implement. * * @author Fabien Potencier * * @api */ interface HelperInterface { /** * Sets the helper set associated with this helper. * * @param HelperSet $helperSet A HelperSet instance * * @api */ public function setHelperSet(HelperSet $helperSet = null); /** * Gets the helper set associated with this helper. * * @return HelperSet A HelperSet instance * * @api */ public function getHelperSet(); /** * Returns the canonical name of this helper. * * @return string The canonical name * * @api */ public function getName(); } PK!Z\+Symfony/Component/Console/Helper/Helper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * Helper is the base class for all helper classes. * * @author Fabien Potencier */ abstract class Helper implements HelperInterface { protected $helperSet = null; /** * Sets the helper set associated with this helper. * * @param HelperSet $helperSet A HelperSet instance */ public function setHelperSet(HelperSet $helperSet = null) { $this->helperSet = $helperSet; } /** * Gets the helper set associated with this helper. * * @return HelperSet A HelperSet instance */ public function getHelperSet() { return $this->helperSet; } /** * Returns the length of a string, using mb_strlen if it is available. * * @param string $string The string to check its length * * @return integer The length of the string */ protected function strlen($string) { if (!function_exists('mb_strlen')) { return strlen($string); } if (false === $encoding = mb_detect_encoding($string)) { return strlen($string); } return mb_strlen($string, $encoding); } } PK!gse4Symfony/Component/Console/Helper/FormatterHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Formatter\OutputFormatter; /** * The Formatter class provides helpers to format messages. * * @author Fabien Potencier */ class FormatterHelper extends Helper { /** * Formats a message within a section. * * @param string $section The section name * @param string $message The message * @param string $style The style to apply to the section * * @return string The format section */ public function formatSection($section, $message, $style = 'info') { return sprintf('<%s>[%s] %s', $style, $section, $style, $message); } /** * Formats a message as a block of text. * * @param string|array $messages The message to write in the block * @param string $style The style to apply to the whole block * @param Boolean $large Whether to return a large block * * @return string The formatter message */ public function formatBlock($messages, $style, $large = false) { $messages = (array) $messages; $len = 0; $lines = array(); foreach ($messages as $message) { $message = OutputFormatter::escape($message); $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); $len = max($this->strlen($message) + ($large ? 4 : 2), $len); } $messages = $large ? array(str_repeat(' ', $len)) : array(); foreach ($lines as $line) { $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); } if ($large) { $messages[] = str_repeat(' ', $len); } foreach ($messages as &$message) { $message = sprintf('<%s>%s', $style, $message, $style); } return implode("\n", $messages); } /** * {@inheritDoc} */ public function getName() { return 'formatter'; } } PK!220Symfony/Component/Console/Helper/TableHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use InvalidArgumentException; /** * Provides helpers to display table output. * * @author Саша Стаменковић */ class TableHelper extends Helper { const LAYOUT_DEFAULT = 0; const LAYOUT_BORDERLESS = 1; const LAYOUT_COMPACT = 2; /** * Table headers. * * @var array */ private $headers = array(); /** * Table rows. * * @var array */ private $rows = array(); // Rendering options private $paddingChar; private $horizontalBorderChar; private $verticalBorderChar; private $crossingChar; private $cellHeaderFormat; private $cellRowFormat; private $cellRowContentFormat; private $borderFormat; private $padType; /** * Column widths cache. * * @var array */ private $columnWidths = array(); /** * Number of columns cache. * * @var array */ private $numberOfColumns; /** * @var OutputInterface */ private $output; public function __construct() { $this->setLayout(self::LAYOUT_DEFAULT); } /** * Sets table layout type. * * @param int $layout self::LAYOUT_* * * @return TableHelper */ public function setLayout($layout) { switch ($layout) { case self::LAYOUT_BORDERLESS: $this ->setPaddingChar(' ') ->setHorizontalBorderChar('=') ->setVerticalBorderChar(' ') ->setCrossingChar(' ') ->setCellHeaderFormat('%s') ->setCellRowFormat('%s') ->setCellRowContentFormat(' %s ') ->setBorderFormat('%s') ->setPadType(STR_PAD_RIGHT) ; break; case self::LAYOUT_COMPACT: $this ->setPaddingChar(' ') ->setHorizontalBorderChar('') ->setVerticalBorderChar(' ') ->setCrossingChar('') ->setCellHeaderFormat('%s') ->setCellRowFormat('%s') ->setCellRowContentFormat('%s') ->setBorderFormat('%s') ->setPadType(STR_PAD_RIGHT) ; break; case self::LAYOUT_DEFAULT: $this ->setPaddingChar(' ') ->setHorizontalBorderChar('-') ->setVerticalBorderChar('|') ->setCrossingChar('+') ->setCellHeaderFormat('%s') ->setCellRowFormat('%s') ->setCellRowContentFormat(' %s ') ->setBorderFormat('%s') ->setPadType(STR_PAD_RIGHT) ; break; default: throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout)); break; }; return $this; } public function setHeaders(array $headers) { $this->headers = array_values($headers); return $this; } public function setRows(array $rows) { $this->rows = array(); return $this->addRows($rows); } public function addRows(array $rows) { foreach ($rows as $row) { $this->addRow($row); } return $this; } public function addRow(array $row) { $this->rows[] = array_values($row); $keys = array_keys($this->rows); $rowKey = array_pop($keys); foreach ($row as $key => $cellValue) { if (!strstr($cellValue, "\n")) { continue; } $lines = explode("\n", $cellValue); $this->rows[$rowKey][$key] = $lines[0]; unset($lines[0]); foreach ($lines as $lineKey => $line) { $nextRowKey = $rowKey + $lineKey + 1; if (isset($this->rows[$nextRowKey])) { $this->rows[$nextRowKey][$key] = $line; } else { $this->rows[$nextRowKey] = array($key => $line); } } } return $this; } public function setRow($column, array $row) { $this->rows[$column] = $row; return $this; } /** * Sets padding character, used for cell padding. * * @param string $paddingChar * * @return TableHelper */ public function setPaddingChar($paddingChar) { if (!$paddingChar) { throw new \LogicException('The padding char must not be empty'); } $this->paddingChar = $paddingChar; return $this; } /** * Sets horizontal border character. * * @param string $horizontalBorderChar * * @return TableHelper */ public function setHorizontalBorderChar($horizontalBorderChar) { $this->horizontalBorderChar = $horizontalBorderChar; return $this; } /** * Sets vertical border character. * * @param string $verticalBorderChar * * @return TableHelper */ public function setVerticalBorderChar($verticalBorderChar) { $this->verticalBorderChar = $verticalBorderChar; return $this; } /** * Sets crossing character. * * @param string $crossingChar * * @return TableHelper */ public function setCrossingChar($crossingChar) { $this->crossingChar = $crossingChar; return $this; } /** * Sets header cell format. * * @param string $cellHeaderFormat * * @return TableHelper */ public function setCellHeaderFormat($cellHeaderFormat) { $this->cellHeaderFormat = $cellHeaderFormat; return $this; } /** * Sets row cell format. * * @param string $cellRowFormat * * @return TableHelper */ public function setCellRowFormat($cellRowFormat) { $this->cellRowFormat = $cellRowFormat; return $this; } /** * Sets row cell content format. * * @param string $cellRowContentFormat * * @return TableHelper */ public function setCellRowContentFormat($cellRowContentFormat) { $this->cellRowContentFormat = $cellRowContentFormat; return $this; } /** * Sets table border format. * * @param string $borderFormat * * @return TableHelper */ public function setBorderFormat($borderFormat) { $this->borderFormat = $borderFormat; return $this; } /** * Sets cell padding type. * * @param integer $padType STR_PAD_* * * @return TableHelper */ public function setPadType($padType) { $this->padType = $padType; return $this; } /** * Renders table to output. * * Example: * +---------------+-----------------------+------------------+ * | ISBN | Title | Author | * +---------------+-----------------------+------------------+ * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ * * @param OutputInterface $output */ public function render(OutputInterface $output) { $this->output = $output; $this->renderRowSeparator(); $this->renderRow($this->headers, $this->cellHeaderFormat); if (!empty($this->headers)) { $this->renderRowSeparator(); } foreach ($this->rows as $row) { $this->renderRow($row, $this->cellRowFormat); } if (!empty($this->rows)) { $this->renderRowSeparator(); } $this->cleanup(); } /** * Renders horizontal header separator. * * Example: +-----+-----------+-------+ */ private function renderRowSeparator() { if (0 === $count = $this->getNumberOfColumns()) { return; } if (!$this->horizontalBorderChar && !$this->crossingChar) { return; } $markup = $this->crossingChar; for ($column = 0; $column < $count; $column++) { $markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column)).$this->crossingChar; } $this->output->writeln(sprintf($this->borderFormat, $markup)); } /** * Renders vertical column separator. */ private function renderColumnSeparator() { $this->output->write(sprintf($this->borderFormat, $this->verticalBorderChar)); } /** * Renders table row. * * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * * @param array $row * @param string $cellFormat */ private function renderRow(array $row, $cellFormat) { if (empty($row)) { return; } $this->renderColumnSeparator(); for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) { $this->renderCell($row, $column, $cellFormat); $this->renderColumnSeparator(); } $this->output->writeln(''); } /** * Renders table cell with padding. * * @param array $row * @param integer $column * @param string $cellFormat */ private function renderCell(array $row, $column, $cellFormat) { $cell = isset($row[$column]) ? $row[$column] : ''; $width = $this->getColumnWidth($column); // str_pad won't work properly with multi-byte strings, we need to fix the padding if (function_exists('mb_strlen') && false !== $encoding = mb_detect_encoding($cell)) { $width += strlen($cell) - mb_strlen($cell, $encoding); } $width += $this->strlen($cell) - $this->computeLengthWithoutDecoration($cell); $content = sprintf($this->cellRowContentFormat, $cell); $this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->paddingChar, $this->padType))); } /** * Gets number of columns for this table. * * @return int */ private function getNumberOfColumns() { if (null !== $this->numberOfColumns) { return $this->numberOfColumns; } $columns = array(0); $columns[] = count($this->headers); foreach ($this->rows as $row) { $columns[] = count($row); } return $this->numberOfColumns = max($columns); } /** * Gets column width. * * @param integer $column * * @return int */ private function getColumnWidth($column) { if (isset($this->columnWidths[$column])) { return $this->columnWidths[$column]; } $lengths = array(0); $lengths[] = $this->getCellWidth($this->headers, $column); foreach ($this->rows as $row) { $lengths[] = $this->getCellWidth($row, $column); } return $this->columnWidths[$column] = max($lengths) + strlen($this->cellRowContentFormat) - 2; } /** * Gets cell width. * * @param array $row * @param integer $column * * @return int */ private function getCellWidth(array $row, $column) { return isset($row[$column]) ? $this->computeLengthWithoutDecoration($row[$column]) : 0; } /** * Called after rendering to cleanup cache data. */ private function cleanup() { $this->columnWidths = array(); $this->numberOfColumns = null; } private function computeLengthWithoutDecoration($string) { $formatter = $this->output->getFormatter(); $isDecorated = $formatter->isDecorated(); $formatter->setDecorated(false); $string = $formatter->format($string); $formatter->setDecorated($isDecorated); return $this->strlen($string); } /** * {@inheritDoc} */ public function getName() { return 'table'; } } PK!"U1  5Symfony/Component/Console/Helper/DescriptorHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Descriptor\DescriptorInterface; use Symfony\Component\Console\Descriptor\JsonDescriptor; use Symfony\Component\Console\Descriptor\MarkdownDescriptor; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Output\OutputInterface; /** * This class adds helper method to describe objects in various formats. * * @author Jean-François Simon */ class DescriptorHelper extends Helper { /** * @var DescriptorInterface[] */ private $descriptors = array(); /** * Constructor. */ public function __construct() { $this ->register('txt', new TextDescriptor()) ->register('xml', new XmlDescriptor()) ->register('json', new JsonDescriptor()) ->register('md', new MarkdownDescriptor()) ; } /** * Describes an object if supported. * * Available options are: * * format: string, the output format name * * raw_text: boolean, sets output type as raw * * @param OutputInterface $output * @param object $object * @param array $options * * @throws \InvalidArgumentException */ public function describe(OutputInterface $output, $object, array $options = array()) { $options = array_merge(array( 'raw_text' => false, 'format' => 'txt', ), $options); if (!isset($this->descriptors[$options['format']])) { throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); } $descriptor = $this->descriptors[$options['format']]; $descriptor->describe($output, $object, $options); } /** * Registers a descriptor. * * @param string $format * @param DescriptorInterface $descriptor * * @return DescriptorHelper */ public function register($format, DescriptorInterface $descriptor) { $this->descriptors[$format] = $descriptor; return $this; } /** * {@inheritdoc} */ public function getName() { return 'descriptor'; } } PK!s H5Symfony/Component/Console/Helper/InputAwareHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputAwareInterface; /** * An implementation of InputAwareInterface for Helpers. * * @author Wouter J */ abstract class InputAwareHelper extends Helper implements InputAwareInterface { protected $input; /** * {@inheritDoc} */ public function setInput(InputInterface $input) { $this->input = $input; } } PK!|po.o.3Symfony/Component/Console/Helper/ProgressHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; /** * The Progress class provides helpers to display progress output. * * @author Chris Jones * @author Fabien Potencier */ class ProgressHelper extends Helper { const FORMAT_QUIET = ' %percent%%'; const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%'; const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%'; const FORMAT_QUIET_NOMAX = ' %current%'; const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]'; const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%'; // options private $barWidth = 28; private $barChar = '='; private $emptyBarChar = '-'; private $progressChar = '>'; private $format = null; private $redrawFreq = 1; private $lastMessagesLength; private $barCharOriginal; /** * @var OutputInterface */ private $output; /** * Current step * * @var integer */ private $current; /** * Maximum number of steps * * @var integer */ private $max; /** * Start time of the progress bar * * @var integer */ private $startTime; /** * List of formatting variables * * @var array */ private $defaultFormatVars = array( 'current', 'max', 'bar', 'percent', 'elapsed', ); /** * Available formatting variables * * @var array */ private $formatVars; /** * Stored format part widths (used for padding) * * @var array */ private $widths = array( 'current' => 4, 'max' => 4, 'percent' => 3, 'elapsed' => 6, ); /** * Various time formats * * @var array */ private $timeFormats = array( array(0, '???'), array(2, '1 sec'), array(59, 'secs', 1), array(60, '1 min'), array(3600, 'mins', 60), array(5400, '1 hr'), array(86400, 'hrs', 3600), array(129600, '1 day'), array(604800, 'days', 86400), ); /** * Sets the progress bar width. * * @param int $size The progress bar size */ public function setBarWidth($size) { $this->barWidth = (int) $size; } /** * Sets the bar character. * * @param string $char A character */ public function setBarCharacter($char) { $this->barChar = $char; } /** * Sets the empty bar character. * * @param string $char A character */ public function setEmptyBarCharacter($char) { $this->emptyBarChar = $char; } /** * Sets the progress bar character. * * @param string $char A character */ public function setProgressCharacter($char) { $this->progressChar = $char; } /** * Sets the progress bar format. * * @param string $format The format */ public function setFormat($format) { $this->format = $format; } /** * Sets the redraw frequency. * * @param int $freq The frequency in steps */ public function setRedrawFrequency($freq) { $this->redrawFreq = (int) $freq; } /** * Starts the progress output. * * @param OutputInterface $output An Output instance * @param integer|null $max Maximum steps */ public function start(OutputInterface $output, $max = null) { $this->startTime = time(); $this->current = 0; $this->max = (int) $max; $this->output = $output; $this->lastMessagesLength = 0; $this->barCharOriginal = ''; if (null === $this->format) { switch ($output->getVerbosity()) { case OutputInterface::VERBOSITY_QUIET: $this->format = self::FORMAT_QUIET_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_QUIET; } break; case OutputInterface::VERBOSITY_VERBOSE: case OutputInterface::VERBOSITY_VERY_VERBOSE: case OutputInterface::VERBOSITY_DEBUG: $this->format = self::FORMAT_VERBOSE_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_VERBOSE; } break; default: $this->format = self::FORMAT_NORMAL_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_NORMAL; } break; } } $this->initialize(); } /** * Advances the progress output X steps. * * @param integer $step Number of steps to advance * @param Boolean $redraw Whether to redraw or not * * @throws \LogicException */ public function advance($step = 1, $redraw = false) { $this->setCurrent($this->current + $step, $redraw); } /** * Sets the current progress. * * @param integer $current The current progress * @param Boolean $redraw Whether to redraw or not * * @throws \LogicException */ public function setCurrent($current, $redraw = false) { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling setCurrent().'); } $current = (int) $current; if ($current < $this->current) { throw new \LogicException('You can\'t regress the progress bar'); } if (0 === $this->current) { $redraw = true; } $prevPeriod = intval($this->current / $this->redrawFreq); $this->current = $current; $currPeriod = intval($this->current / $this->redrawFreq); if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) { $this->display(); } } /** * Outputs the current progress string. * * @param Boolean $finish Forces the end result * * @throws \LogicException */ public function display($finish = false) { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling display().'); } $message = $this->format; foreach ($this->generate($finish) as $name => $value) { $message = str_replace("%{$name}%", $value, $message); } $this->overwrite($this->output, $message); } /** * Removes the progress bar from the current line. * * This is useful if you wish to write some output * while a progress bar is running. * Call display() to show the progress bar again. */ public function clear() { $this->overwrite($this->output, ''); } /** * Finishes the progress output. */ public function finish() { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling finish().'); } if (null !== $this->startTime) { if (!$this->max) { $this->barChar = $this->barCharOriginal; $this->display(true); } $this->startTime = null; $this->output->writeln(''); $this->output = null; } } /** * Initializes the progress helper. */ private function initialize() { $this->formatVars = array(); foreach ($this->defaultFormatVars as $var) { if (false !== strpos($this->format, "%{$var}%")) { $this->formatVars[$var] = true; } } if ($this->max > 0) { $this->widths['max'] = $this->strlen($this->max); $this->widths['current'] = $this->widths['max']; } else { $this->barCharOriginal = $this->barChar; $this->barChar = $this->emptyBarChar; } } /** * Generates the array map of format variables to values. * * @param Boolean $finish Forces the end result * * @return array Array of format vars and values */ private function generate($finish = false) { $vars = array(); $percent = 0; if ($this->max > 0) { $percent = (float) $this->current / $this->max; } if (isset($this->formatVars['bar'])) { $completeBars = 0; if ($this->max > 0) { $completeBars = floor($percent * $this->barWidth); } else { if (!$finish) { $completeBars = floor($this->current % $this->barWidth); } else { $completeBars = $this->barWidth; } } $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar); $bar = str_repeat($this->barChar, $completeBars); if ($completeBars < $this->barWidth) { $bar .= $this->progressChar; $bar .= str_repeat($this->emptyBarChar, $emptyBars); } $vars['bar'] = $bar; } if (isset($this->formatVars['elapsed'])) { $elapsed = time() - $this->startTime; $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT); } if (isset($this->formatVars['current'])) { $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT); } if (isset($this->formatVars['max'])) { $vars['max'] = $this->max; } if (isset($this->formatVars['percent'])) { $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT); } return $vars; } /** * Converts seconds into human-readable format. * * @param integer $secs Number of seconds * * @return string Time in readable format */ private function humaneTime($secs) { $text = ''; foreach ($this->timeFormats as $format) { if ($secs < $format[0]) { if (count($format) == 2) { $text = $format[1]; break; } else { $text = ceil($secs / $format[2]).' '.$format[1]; break; } } } return $text; } /** * Overwrites a previous message to the output. * * @param OutputInterface $output An Output instance * @param string $message The message */ private function overwrite(OutputInterface $output, $message) { $length = $this->strlen($message); // append whitespace to match the last line's length if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) { $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); } // carriage return $output->write("\x0D"); $output->write($message); $this->lastMessagesLength = $this->strlen($message); } /** * {@inheritDoc} */ public function getName() { return 'progress'; } } PK!&>@>@1Symfony/Component/Console/Helper/DialogHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; /** * The Dialog class provides helpers to interact with the user. * * @author Fabien Potencier */ class DialogHelper extends InputAwareHelper { private $inputStream; private static $shell; private static $stty; /** * Asks the user to select a value. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param array $choices List of choices to pick from * @param Boolean|string $default The default answer if the user enters nothing * @param Boolean|integer $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param string $errorMessage Message which will be shown if invalid value from choice list would be picked * @param Boolean $multiselect Select more than one value separated by comma * * @return integer|string|array The selected value or values (the key of the choices array) * * @throws \InvalidArgumentException */ public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false) { $width = max(array_map('strlen', array_keys($choices))); $messages = (array) $question; foreach ($choices as $key => $value) { $messages[] = sprintf(" [%-${width}s] %s", $key, $value); } $output->writeln($messages); $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) { // Collapse all spaces. $selectedChoices = str_replace(" ", "", $picked); if ($multiselect) { // Check for a separated comma values if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) { throw new \InvalidArgumentException(sprintf($errorMessage, $picked)); } $selectedChoices = explode(",", $selectedChoices); } else { $selectedChoices = array($picked); } $multiselectChoices = array(); foreach ($selectedChoices as $value) { if (empty($choices[$value])) { throw new \InvalidArgumentException(sprintf($errorMessage, $value)); } array_push($multiselectChoices, $value); } if ($multiselect) { return $multiselectChoices; } return $picked; }, $attempts, $default); return $result; } /** * Asks a question to the user. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param string $default The default answer if none is given by the user * @param array $autocomplete List of values to autocomplete * * @return string The user answer * * @throws \RuntimeException If there is no data to read in the input stream */ public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null) { if ($this->input && !$this->input->isInteractive()) { return $default; } $output->write($question); $inputStream = $this->inputStream ?: STDIN; if (null === $autocomplete || !$this->hasSttyAvailable()) { $ret = fgets($inputStream, 4096); if (false === $ret) { throw new \RuntimeException('Aborted'); } $ret = trim($ret); } else { $ret = ''; $i = 0; $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); $sttyMode = shell_exec('stty -g'); // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) shell_exec('stty -icanon -echo'); // Add highlighted text style $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); // Read a keypress while (!feof($inputStream)) { $c = fread($inputStream, 1); // Backspace Character if ("\177" === $c) { if (0 === $numMatches && 0 !== $i) { $i--; // Move cursor backwards $output->write("\033[1D"); } if ($i === 0) { $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); } else { $numMatches = 0; } // Pop the last character off the end of our string $ret = substr($ret, 0, $i); } elseif ("\033" === $c) { // Did we read an escape sequence? $c .= fread($inputStream, 2); // A = Up Arrow. B = Down Arrow if ('A' === $c[2] || 'B' === $c[2]) { if ('A' === $c[2] && -1 === $ofs) { $ofs = 0; } if (0 === $numMatches) { continue; } $ofs += ('A' === $c[2]) ? -1 : 1; $ofs = ($numMatches + $ofs) % $numMatches; } } elseif (ord($c) < 32) { if ("\t" === $c || "\n" === $c) { if ($numMatches > 0 && -1 !== $ofs) { $ret = $matches[$ofs]; // Echo out remaining chars for current match $output->write(substr($ret, $i)); $i = strlen($ret); } if ("\n" === $c) { $output->write($c); break; } $numMatches = 0; } continue; } else { $output->write($c); $ret .= $c; $i++; $numMatches = 0; $ofs = 0; foreach ($autocomplete as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) if (0 === strpos($value, $ret) && $i !== strlen($value)) { $matches[$numMatches++] = $value; } } } // Erase characters from cursor to end of line $output->write("\033[K"); if ($numMatches > 0 && -1 !== $ofs) { // Save cursor position $output->write("\0337"); // Write highlighted text $output->write(''.substr($matches[$ofs], $i).''); // Restore cursor position $output->write("\0338"); } } // Reset stty so it behaves normally again shell_exec(sprintf('stty %s', $sttyMode)); } return strlen($ret) > 0 ? $ret : $default; } /** * Asks a confirmation to the user. * * The question will be asked until the user answers by nothing, yes, or no. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param Boolean $default The default answer if the user enters nothing * * @return Boolean true if the user has confirmed, false otherwise */ public function askConfirmation(OutputInterface $output, $question, $default = true) { $answer = 'z'; while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) { $answer = $this->ask($output, $question); } if (false === $default) { return $answer && 'y' == strtolower($answer[0]); } return !$answer || 'y' == strtolower($answer[0]); } /** * Asks a question to the user, the response is hidden * * @param OutputInterface $output An Output instance * @param string|array $question The question * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not * * @return string The answer * * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden */ public function askHiddenResponse(OutputInterface $output, $question, $fallback = true) { if (defined('PHP_WINDOWS_VERSION_BUILD')) { $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; // handle code running from a phar if ('phar:' === substr(__FILE__, 0, 5)) { $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; copy($exe, $tmpExe); $exe = $tmpExe; } $output->write($question); $value = rtrim(shell_exec($exe)); $output->writeln(''); if (isset($tmpExe)) { unlink($tmpExe); } return $value; } if ($this->hasSttyAvailable()) { $output->write($question); $sttyMode = shell_exec('stty -g'); shell_exec('stty -echo'); $value = fgets($this->inputStream ?: STDIN, 4096); shell_exec(sprintf('stty %s', $sttyMode)); if (false === $value) { throw new \RuntimeException('Aborted'); } $value = trim($value); $output->writeln(''); return $value; } if (false !== $shell = $this->getShell()) { $output->write($question); $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); $value = rtrim(shell_exec($command)); $output->writeln(''); return $value; } if ($fallback) { return $this->ask($output, $question); } throw new \RuntimeException('Unable to hide the response'); } /** * Asks for a value and validates the response. * * The validator receives the data to validate. It must return the * validated data when the data is valid and throw an exception * otherwise. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param callable $validator A PHP callback * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param string $default The default answer if none is given by the user * @param array $autocomplete List of values to autocomplete * * @return mixed * * @throws \Exception When any of the validators return an error */ public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null) { $that = $this; $interviewer = function () use ($output, $question, $default, $autocomplete, $that) { return $that->ask($output, $question, $default, $autocomplete); }; return $this->validateAttempts($interviewer, $output, $validator, $attempts); } /** * Asks for a value, hide and validates the response. * * The validator receives the data to validate. It must return the * validated data when the data is valid and throw an exception * otherwise. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param callable $validator A PHP callback * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not * * @return string The response * * @throws \Exception When any of the validators return an error * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden * */ public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true) { $that = $this; $interviewer = function () use ($output, $question, $fallback, $that) { return $that->askHiddenResponse($output, $question, $fallback); }; return $this->validateAttempts($interviewer, $output, $validator, $attempts); } /** * Sets the input stream to read from when interacting with the user. * * This is mainly useful for testing purpose. * * @param resource $stream The input stream */ public function setInputStream($stream) { $this->inputStream = $stream; } /** * Returns the helper's input stream * * @return string */ public function getInputStream() { return $this->inputStream; } /** * {@inheritDoc} */ public function getName() { return 'dialog'; } /** * Return a valid Unix shell * * @return string|Boolean The valid shell name, false in case no valid shell is found */ private function getShell() { if (null !== self::$shell) { return self::$shell; } self::$shell = false; if (file_exists('/usr/bin/env')) { // handle other OSs with bash/zsh/ksh/csh if available to hide the answer $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) { if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { self::$shell = $sh; break; } } } return self::$shell; } private function hasSttyAvailable() { if (null !== self::$stty) { return self::$stty; } exec('stty 2>&1', $output, $exitcode); return self::$stty = $exitcode === 0; } /** * Validate an attempt * * @param callable $interviewer A callable that will ask for a question and return the result * @param OutputInterface $output An Output instance * @param callable $validator A PHP callback * @param integer $attempts Max number of times to ask before giving up ; false will ask infinitely * * @return string The validated response * * @throws \Exception In case the max number of attempts has been reached and no valid response has been given */ private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts) { $error = null; while (false === $attempts || $attempts--) { if (null !== $error) { $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error')); } try { return call_user_func($validator, $interviewer()); } catch (\Exception $error) { } } throw $error; } } PK!Duu7Symfony/Component/Console/Descriptor/JsonDescriptor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * JSON descriptor. * * @author Jean-François Simon */ class JsonDescriptor extends Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->writeData($this->getInputArgumentData($argument), $options); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { $this->writeData($this->getInputOptionData($option), $options); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { $this->writeData($this->getInputDefinitionData($definition), $options); } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $this->writeData($this->getCommandData($command), $options); } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); $commands = array(); foreach ($description->getCommands() as $command) { $commands[] = $this->getCommandData($command); } $data = $describedNamespace ? array('commands' => $commands, 'namespace' => $describedNamespace) : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces())); $this->writeData($data, $options); } /** * Writes data as json. * * @param array $data * @param array $options * * @return array|string */ private function writeData(array $data, array $options) { $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0)); } /** * @param InputArgument $argument * * @return array */ private function getInputArgumentData(InputArgument $argument) { return array( 'name' => $argument->getName(), 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => $argument->getDescription(), 'default' => $argument->getDefault(), ); } /** * @param InputOption $option * * @return array */ private function getInputOptionData(InputOption $option) { return array( 'name' => '--'.$option->getName(), 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '', 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => $option->getDescription(), 'default' => $option->getDefault(), ); } /** * @param InputDefinition $definition * * @return array */ private function getInputDefinitionData(InputDefinition $definition) { $inputArguments = array(); foreach ($definition->getArguments() as $name => $argument) { $inputArguments[$name] = $this->getInputArgumentData($argument); } $inputOptions = array(); foreach ($definition->getOptions() as $name => $option) { $inputOptions[$name] = $this->getInputOptionData($option); } return array('arguments' => $inputArguments, 'options' => $inputOptions); } /** * @param Command $command * * @return array */ private function getCommandData(Command $command) { $command->getSynopsis(); $command->mergeApplicationDefinition(false); return array( 'name' => $command->getName(), 'usage' => $command->getSynopsis(), 'description' => $command->getDescription(), 'help' => $command->getProcessedHelp(), 'aliases' => $command->getAliases(), 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), ); } } PK!m 3Symfony/Component/Console/Descriptor/Descriptor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * @author Jean-François Simon */ abstract class Descriptor implements DescriptorInterface { /** * @var OutputInterface */ private $output; /** * {@inheritdoc} */ public function describe(OutputInterface $output, $object, array $options = array()) { $this->output = $output; switch (true) { case $object instanceof InputArgument: $this->describeInputArgument($object, $options); break; case $object instanceof InputOption: $this->describeInputOption($object, $options); break; case $object instanceof InputDefinition: $this->describeInputDefinition($object, $options); break; case $object instanceof Command: $this->describeCommand($object, $options); break; case $object instanceof Application: $this->describeApplication($object, $options); break; default: throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object))); } } /** * Writes content to output. * * @param string $content * @param boolean $decorated */ protected function write($content, $decorated = false) { $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); } /** * Describes an InputArgument instance. * * @param InputArgument $argument * @param array $options * * @return string|mixed */ abstract protected function describeInputArgument(InputArgument $argument, array $options = array()); /** * Describes an InputOption instance. * * @param InputOption $option * @param array $options * * @return string|mixed */ abstract protected function describeInputOption(InputOption $option, array $options = array()); /** * Describes an InputDefinition instance. * * @param InputDefinition $definition * @param array $options * * @return string|mixed */ abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array()); /** * Describes a Command instance. * * @param Command $command * @param array $options * * @return string|mixed */ abstract protected function describeCommand(Command $command, array $options = array()); /** * Describes an Application instance. * * @param Application $application * @param array $options * * @return string|mixed */ abstract protected function describeApplication(Application $application, array $options = array()); } PK!lP..;Symfony/Component/Console/Descriptor/MarkdownDescriptor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * Markdown descriptor. * * @author Jean-François Simon */ class MarkdownDescriptor extends Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->write( '**'.$argument->getName().':**'."\n\n" .'* Name: '.($argument->getName() ?: '')."\n" .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" .'* Description: '.($argument->getDescription() ?: '')."\n" .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' ); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { $this->write( '**'.$option->getName().':**'."\n\n" .'* Name: `--'.$option->getName().'`'."\n" .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '')."\n" .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" .'* Description: '.($option->getDescription() ?: '')."\n" .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' ); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { if ($showArguments = count($definition->getArguments()) > 0) { $this->write('### Arguments:'); foreach ($definition->getArguments() as $argument) { $this->write("\n\n"); $this->write($this->describeInputArgument($argument)); } } if (count($definition->getOptions()) > 0) { if ($showArguments) { $this->write("\n\n"); } $this->write('### Options:'); foreach ($definition->getOptions() as $option) { $this->write("\n\n"); $this->write($this->describeInputOption($option)); } } } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $command->getSynopsis(); $command->mergeApplicationDefinition(false); $this->write( $command->getName()."\n" .str_repeat('-', strlen($command->getName()))."\n\n" .'* Description: '.($command->getDescription() ?: '')."\n" .'* Usage: `'.$command->getSynopsis().'`'."\n" .'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '') ); if ($help = $command->getProcessedHelp()) { $this->write("\n\n"); $this->write($help); } if ($definition = $command->getNativeDefinition()) { $this->write("\n\n"); $this->describeInputDefinition($command->getNativeDefinition()); } } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); $this->write($application->getName()."\n".str_repeat('=', strlen($application->getName()))); foreach ($description->getNamespaces() as $namespace) { if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { $this->write("\n\n"); $this->write('**'.$namespace['id'].':**'); } $this->write("\n\n"); $this->write(implode("\n", array_map(function ($commandName) { return '* '.$commandName; } , $namespace['commands']))); } foreach ($description->getCommands() as $command) { $this->write("\n\n"); $this->write($this->describeCommand($command)); } } } PK!sX ?Symfony/Component/Console/Descriptor/ApplicationDescription.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; /** * @author Jean-François Simon */ class ApplicationDescription { const GLOBAL_NAMESPACE = '_global'; /** * @var Application */ private $application; /** * @var null|string */ private $namespace; /** * @var array */ private $namespaces; /** * @var Command[] */ private $commands; /** * @var Command[] */ private $aliases; /** * Constructor. * * @param Application $application * @param string|null $namespace */ public function __construct(Application $application, $namespace = null) { $this->application = $application; $this->namespace = $namespace; } /** * @return array */ public function getNamespaces() { if (null === $this->namespaces) { $this->inspectApplication(); } return $this->namespaces; } /** * @return Command[] */ public function getCommands() { if (null === $this->commands) { $this->inspectApplication(); } return $this->commands; } /** * @param string $name * * @return Command * * @throws \InvalidArgumentException */ public function getCommand($name) { if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name)); } return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; } private function inspectApplication() { $this->commands = array(); $this->namespaces = array(); $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); foreach ($this->sortCommands($all) as $namespace => $commands) { $names = array(); /** @var Command $command */ foreach ($commands as $name => $command) { if (!$command->getName()) { continue; } if ($command->getName() === $name) { $this->commands[$name] = $command; } else { $this->aliases[$name] = $command; } $names[] = $name; } $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names); } } /** * @param array $commands * * @return array */ private function sortCommands(array $commands) { $namespacedCommands = array(); foreach ($commands as $name => $command) { $key = $this->application->extractNamespace($name, 1); if (!$key) { $key = '_global'; } $namespacedCommands[$key][$name] = $command; } ksort($namespacedCommands); foreach ($namespacedCommands as &$commands) { ksort($commands); } return $namespacedCommands; } } PK!ﶲ%%6Symfony/Component/Console/Descriptor/XmlDescriptor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * XML descriptor. * * @author Jean-François Simon */ class XmlDescriptor extends Descriptor { /** * @param InputDefinition $definition * * @return \DOMDocument */ public function getInputDefinitionDocument(InputDefinition $definition) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($definitionXML = $dom->createElement('definition')); $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); foreach ($definition->getArguments() as $argument) { $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); } $definitionXML->appendChild($optionsXML = $dom->createElement('options')); foreach ($definition->getOptions() as $option) { $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); } return $dom; } /** * @param Command $command * * @return \DOMDocument */ public function getCommandDocument(Command $command) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($commandXML = $dom->createElement('command')); $command->getSynopsis(); $command->mergeApplicationDefinition(false); $commandXML->setAttribute('id', $command->getName()); $commandXML->setAttribute('name', $command->getName()); $commandXML->appendChild($usageXML = $dom->createElement('usage')); $usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), ''))); $commandXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); $commandXML->appendChild($helpXML = $dom->createElement('help')); $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); $commandXML->appendChild($aliasesXML = $dom->createElement('aliases')); foreach ($command->getAliases() as $alias) { $aliasesXML->appendChild($aliasXML = $dom->createElement('alias')); $aliasXML->appendChild($dom->createTextNode($alias)); } $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition()); $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); return $dom; } /** * @param Application $application * @param string|null $namespace * * @return \DOMDocument */ public function getApplicationDocument(Application $application, $namespace = null) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($rootXml = $dom->createElement('symfony')); if ($application->getName() !== 'UNKNOWN') { $rootXml->setAttribute('name', $application->getName()); if ($application->getVersion() !== 'UNKNOWN') { $rootXml->setAttribute('version', $application->getVersion()); } } $rootXml->appendChild($commandsXML = $dom->createElement('commands')); $description = new ApplicationDescription($application, $namespace); if ($namespace) { $commandsXML->setAttribute('namespace', $namespace); } foreach ($description->getCommands() as $command) { $this->appendDocument($commandsXML, $this->getCommandDocument($command)); } if (!$namespace) { $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); foreach ($description->getNamespaces() as $namespaceDescription) { $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); foreach ($namespaceDescription['commands'] as $name) { $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); $commandXML->appendChild($dom->createTextNode($name)); } } } return $dom; } /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->writeDocument($this->getInputArgumentDocument($argument)); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { $this->writeDocument($this->getInputOptionDocument($option)); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { $this->writeDocument($this->getInputDefinitionDocument($definition)); } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $this->writeDocument($this->getCommandDocument($command)); } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); } /** * Appends document children to parent node. * * @param \DOMNode $parentNode * @param \DOMNode $importedParent */ private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) { foreach ($importedParent->childNodes as $childNode) { $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); } } /** * Writes DOM document. * * @param \DOMDocument $dom * * @return \DOMDocument|string */ private function writeDocument(\DOMDocument $dom) { $dom->formatOutput = true; $this->write($dom->saveXML()); } /** * @param InputArgument $argument * * @return \DOMDocument */ private function getInputArgumentDocument(InputArgument $argument) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($objectXML = $dom->createElement('argument')); $objectXML->setAttribute('name', $argument->getName()); $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); $objectXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array())); foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); } return $dom; } /** * @param InputOption $option * * @return \DOMDocument */ private function getInputOptionDocument(InputOption $option) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($objectXML = $dom->createElement('option')); $objectXML->setAttribute('name', '--'.$option->getName()); $pos = strpos($option->getShortcut(), '|'); if (false !== $pos) { $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut()))); } else { $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); } $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); $objectXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); if ($option->acceptValue()) { $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array())); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); if (!empty($defaults)) { foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); } } } return $dom; } } PK!7Symfony/Component/Console/Descriptor/TextDescriptor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * Text descriptor. * * @author Jean-François Simon */ class TextDescriptor extends Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) { $default = sprintf(' (default: %s)', $this->formatDefaultValue($argument->getDefault())); } else { $default = ''; } $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName()); $this->writeText(sprintf(" %-${nameWidth}s %s%s", $argument->getName(), str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()), $default ), $options); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) { $default = sprintf(' (default: %s)', $this->formatDefaultValue($option->getDefault())); } else { $default = ''; } $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName()); $nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2; $this->writeText(sprintf(" %s %-${nameWithShortcutWidth}s%s%s%s", '--'.$option->getName(), $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()), $default, $option->isArray() ? ' (multiple values allowed)' : '' ), $options); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { $nameWidth = 0; foreach ($definition->getOptions() as $option) { $nameLength = strlen($option->getName()) + 2; if ($option->getShortcut()) { $nameLength += strlen($option->getShortcut()) + 3; } $nameWidth = max($nameWidth, $nameLength); } foreach ($definition->getArguments() as $argument) { $nameWidth = max($nameWidth, strlen($argument->getName())); } ++$nameWidth; if ($definition->getArguments()) { $this->writeText('Arguments:', $options); $this->writeText("\n"); foreach ($definition->getArguments() as $argument) { $this->describeInputArgument($argument, array_merge($options, array('name_width' => $nameWidth))); $this->writeText("\n"); } } if ($definition->getArguments() && $definition->getOptions()) { $this->writeText("\n"); } if ($definition->getOptions()) { $this->writeText('Options:', $options); $this->writeText("\n"); foreach ($definition->getOptions() as $option) { $this->describeInputOption($option, array_merge($options, array('name_width' => $nameWidth))); $this->writeText("\n"); } } } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $command->getSynopsis(); $command->mergeApplicationDefinition(false); $this->writeText('Usage:', $options); $this->writeText("\n"); $this->writeText(' '.$command->getSynopsis(), $options); $this->writeText("\n"); if (count($command->getAliases()) > 0) { $this->writeText("\n"); $this->writeText('Aliases: '.implode(', ', $command->getAliases()).'', $options); } if ($definition = $command->getNativeDefinition()) { $this->writeText("\n"); $this->describeInputDefinition($definition, $options); } $this->writeText("\n"); if ($help = $command->getProcessedHelp()) { $this->writeText('Help:', $options); $this->writeText("\n"); $this->writeText(' '.str_replace("\n", "\n ", $help), $options); $this->writeText("\n"); } } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); if (isset($options['raw_text']) && $options['raw_text']) { $width = $this->getColumnWidth($description->getCommands()); foreach ($description->getCommands() as $command) { $this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options); $this->writeText("\n"); } } else { $width = $this->getColumnWidth($description->getCommands()); $this->writeText($application->getHelp(), $options); $this->writeText("\n\n"); if ($describedNamespace) { $this->writeText(sprintf("Available commands for the \"%s\" namespace:", $describedNamespace), $options); } else { $this->writeText('Available commands:', $options); } // add commands by namespace foreach ($description->getNamespaces() as $namespace) { if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { $this->writeText("\n"); $this->writeText(''.$namespace['id'].'', $options); } foreach ($namespace['commands'] as $name) { $this->writeText("\n"); $this->writeText(sprintf(" %-${width}s %s", $name, $description->getCommand($name)->getDescription()), $options); } } $this->writeText("\n"); } } /** * {@inheritdoc} */ private function writeText($content, array $options = array()) { $this->write( isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : true ); } /** * Formats input option/argument default value. * * @param mixed $default * * @return string */ private function formatDefaultValue($default) { if (version_compare(PHP_VERSION, '5.4', '<')) { return str_replace('\/', '/', json_encode($default)); } return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } /** * @param Command[] $commands * * @return int */ private function getColumnWidth(array $commands) { $width = 0; foreach ($commands as $command) { $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width; } return $width + 2; } } PK!JZ0<<Symfony/Component/Console/Descriptor/DescriptorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Output\OutputInterface; /** * Descriptor interface. * * @author Jean-François Simon */ interface DescriptorInterface { /** * Describes an InputArgument instance. * * @param OutputInterface $output * @param object $object * @param array $options */ public function describe(OutputInterface $output, $object, array $options = array()); } PK!v$$7Symfony/Component/Console/Resources/bin/hiddeninput.exenu[MZ@ !L!This program cannot be run in DOS mode. $,;B;B;B2מ:B2-B2ƞ9B2ў?Ba98B;CB2Ȟ:B2֞:B2Ӟ:BRich;BPELMoO  8 @`?@"P@ Pp!8!@ .text   `.rdata @@.data0@.rsrc @@@.relocP"@Bj$@xj @eEPV @EЃPV @MX @eEP5H @L @YY5\ @EP5` @D @YYP @MMT @3H; 0@uh@l3@$40@5h3@40@h$0@h(0@h 0@ @00@}jYjh"@3ۉ]dp]俀3@SVW0 @;t;u3Fuh4 @3F|3@;u j\Y;|3@u,5|3@h @h @YYtE5<0@|3@;uh @h @lYY|3@9]uSW8 @93@th3@Yt SjS3@$0@ @5$0@5(0@5 0@ 80@9,0@u7P @E MPQYYËeE80@39,0@uPh @9<0@u @E80@øMZf9@t3M<@@8PEuH t uՃv39xtv39j,0@p @jl @YY3@3@ @ t3@ @ p3@ @x3@V=0@u h@ @Yg=0@u j @Y3{U(H1@ D1@@1@<1@581@=41@f`1@f T1@f01@f,1@f%(1@f-$1@X1@EL1@EP1@E\1@0@P1@L0@@0@ D0@0@0@ @0@j?Yj @h!@$ @=0@ujYh ( @P, @ËUE8csmu*xu$@= t=!t="t=@u3]hH@ @3% @jh("@b53@5 @YEu u @YgjYe53@։E53@YYEEPEPu5l @YPUEu֣3@uփ3@E EjYËUuNYH]ËV!@!@W;stЃ;r_^ËV"@"@W;stЃ;r_^% @̋UMMZf9t3]ËA<8PEu3ҹ f9H‹]̋UEH<ASVq3WDv} H ;r X;r B(;r3_^[]̋UjhH"@he@dPSVW0@1E3PEdeEh@*tUE-@Ph@Pt;@$ЃEMd Y_^[]ËE3=‹ËeE3Md Y_^[]% @% @he@d5D$l$l$+SVW0@1E3PeuEEEEdËMd Y__^[]QËUuuu uh@h0@]ËVhh3V t VVVVV^3ËU0@eeSWN@;t t У0@`VEP< @u3u @3 @3 @3EP @E3E3;uO@ u 50@։50@^_[%t @%x @%| @% @% @% @% @% @% @Pd5D$ +d$ SVW(0@3PEuEEdËMd Y__^[]QËM3M%T @T$B J3J3l"@s###)r)b)H)4))(((((()#$%%&d&&$('''''(((6('H(Z(t(('''''l'^'R'F'>'>(0'')@W@@MoOl!@0@0@bad allocationH0@!@RSDSьJ!LZc:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdbe@@:@@@@"d"@"# $#&D H#(h ###)r)b)H)4))(((((()#$%%&d&&$('''''(((6('H(Z(t(('''''l'^'R'F'>'>(0'')GetConsoleModeSetConsoleMode;GetStdHandleKERNEL32.dll??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@AJ?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ{??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@ZMSVCP90.dll_amsg_exit__getmainargs,_cexit|_exitf_XcptFilterexit__initenv_initterm_initterm_e<_configthreadlocale__setusermatherr _adjust_fdiv__p__commode__p__fmodej_encode_pointer__set_app_typeK_crt_debugger_hookC?terminate@@YAXXZMSVCR90.dll_unlock__dllonexitv_lock_onexit`_decode_pointers_except_handler4_common _invoke_watson?_controlfp_sInterlockedExchange!SleepInterlockedCompareExchange-TerminateProcessGetCurrentProcess>UnhandledExceptionFilterSetUnhandledExceptionFilterIsDebuggerPresentTQueryPerformanceCounterfGetTickCountGetCurrentThreadIdGetCurrentProcessIdOGetSystemTimeAsFileTimes__CxxFrameHandler3N@D$!@ 8Ph  @(CV(4VS_VERSION_INFOStringFileInfob040904b0QFileDescriptionReads from stdin without leaking info to the terminal and outputs back to stdout6 FileVersion1, 0, 0, 08 InternalNamehiddeninputPLegalCopyrightJordi Boggiano - 2012HOriginalFilenamehiddeninput.exe: ProductNameHidden Input: ProductVersion1, 0, 0, 0DVarFileInfo$Translation  PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING@00!0/080F0L0T0^0d0n0{000000000000001#1-1@1J1O1T1v1{1111111111111112"2*23292A2M2_2j2p222222222222 333%303N3T3Z3`3f3l3s3z333333333333333334444%4;4B444444444445!5^5c5555H6M6_6}66677 7*7w7|777778 88=8E8P8V8\8b8h8n8t8z88889 $0001 1t1x12 2@2\2`2h2t20 0PK!||-&7Symfony/Component/Console/Event/ConsoleCommandEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; /** * Allows to do things before the command is executed. * * @author Fabien Potencier */ class ConsoleCommandEvent extends ConsoleEvent { } PK!Z&&9Symfony/Component/Console/Event/ConsoleTerminateEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Allows to manipulate the exit code of a command after its execution. * * @author Francesco Levorato */ class ConsoleTerminateEvent extends ConsoleEvent { /** * The exit code of the command. * * @var integer */ private $exitCode; public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode) { parent::__construct($command, $input, $output); $this->setExitCode($exitCode); } /** * Sets the exit code. * * @param integer $exitCode The command exit code */ public function setExitCode($exitCode) { $this->exitCode = (int) $exitCode; } /** * Gets the exit code. * * @return integer The command exit code */ public function getExitCode() { return $this->exitCode; } } PK!sKAA9Symfony/Component/Console/Event/ConsoleExceptionEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Allows to handle exception thrown in a command. * * @author Fabien Potencier */ class ConsoleExceptionEvent extends ConsoleEvent { private $exception; private $exitCode; public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode) { parent::__construct($command, $input, $output); $this->setException($exception); $this->exitCode = (int) $exitCode; } /** * Returns the thrown exception. * * @return \Exception The thrown exception */ public function getException() { return $this->exception; } /** * Replaces the thrown exception. * * This exception will be thrown if no response is set in the event. * * @param \Exception $exception The thrown exception */ public function setException(\Exception $exception) { $this->exception = $exception; } /** * Gets the exit code. * * @return integer The command exit code */ public function getExitCode() { return $this->exitCode; } } PK! 0Symfony/Component/Console/Event/ConsoleEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\EventDispatcher\Event; /** * Allows to inspect input and output of a command. * * @author Francesco Levorato */ class ConsoleEvent extends Event { protected $command; private $input; private $output; public function __construct(Command $command, InputInterface $input, OutputInterface $output) { $this->command = $command; $this->input = $input; $this->output = $output; } /** * Gets the command that is executed. * * @return Command A Command instance */ public function getCommand() { return $this->command; } /** * Gets the input instance. * * @return InputInterface An InputInterface instance */ public function getInput() { return $this->input; } /** * Gets the output instance. * * @return OutputInterface An OutputInterface instance */ public function getOutput() { return $this->output; } } PK!]='YY0Symfony/Component/OptionsResolver/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Exception; /** * Exception thrown when an invalid option is passed. * * @author Bernhard Schussek */ class InvalidOptionsException extends \InvalidArgumentException implements ExceptionInterface { } PK!yPHISymfony/Component/OptionsResolver/Exception/OptionDefinitionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Exception; /** * Thrown when an option definition is invalid. * * @author Bernhard Schussek */ class OptionDefinitionException extends \RuntimeException implements ExceptionInterface { } PK!E@^BSymfony/Component/OptionsResolver/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Exception; /** * Marker interface for the Options component. * * @author Bernhard Schussek */ interface ExceptionInterface { } PK! pGSymfony/Component/OptionsResolver/Exception/MissingOptionsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Exception; /** * Exception thrown when a required option is missing. * * @author Bernhard Schussek */ class MissingOptionsException extends \InvalidArgumentException implements ExceptionInterface { } PK!G>Symfony/Component/OptionsResolver/OptionsResolverInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver; /** * @author Bernhard Schussek */ interface OptionsResolverInterface { /** * Sets default option values. * * The options can either be values of any types or closures that * evaluate the option value lazily. These closures must have one * of the following signatures: * * * function (Options $options) * function (Options $options, $value) * * * The second parameter passed to the closure is the previously * set default value, in case you are overwriting an existing * default value. * * The closures should return the lazily created option value. * * @param array $defaultValues A list of option names as keys and default * values or closures as values. * * @return OptionsResolverInterface The resolver instance. */ public function setDefaults(array $defaultValues); /** * Replaces default option values. * * Old defaults are erased, which means that closures passed here cannot * access the previous default value. This may be useful to improve * performance if the previous default value is calculated by an expensive * closure. * * @param array $defaultValues A list of option names as keys and default * values or closures as values. * * @return OptionsResolverInterface The resolver instance. */ public function replaceDefaults(array $defaultValues); /** * Sets optional options. * * This method declares valid option names without setting default values for them. * If these options are not passed to {@link resolve()} and no default has been set * for them, they will be missing in the final options array. This can be helpful * if you want to determine whether an option has been set or not because otherwise * {@link resolve()} would trigger an exception for unknown options. * * @param array $optionNames A list of option names. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\OptionDefinitionException When trying to pass default values. */ public function setOptional(array $optionNames); /** * Sets required options. * * If these options are not passed to {@link resolve()} and no default has been set for * them, an exception will be thrown. * * @param array $optionNames A list of option names. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\OptionDefinitionException When trying to pass default values. */ public function setRequired(array $optionNames); /** * Sets allowed values for a list of options. * * @param array $allowedValues A list of option names as keys and arrays * with values acceptable for that option as * values. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\InvalidOptionsException If an option has not been defined * (see {@link isKnown()}) for which * an allowed value is set. */ public function setAllowedValues(array $allowedValues); /** * Adds allowed values for a list of options. * * The values are merged with the allowed values defined previously. * * @param array $allowedValues A list of option names as keys and arrays * with values acceptable for that option as * values. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\InvalidOptionsException If an option has not been defined * (see {@link isKnown()}) for which * an allowed value is set. */ public function addAllowedValues(array $allowedValues); /** * Sets allowed types for a list of options. * * @param array $allowedTypes A list of option names as keys and type * names passed as string or array as values. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\InvalidOptionsException If an option has not been defined for * which an allowed type is set. */ public function setAllowedTypes(array $allowedTypes); /** * Adds allowed types for a list of options. * * The types are merged with the allowed types defined previously. * * @param array $allowedTypes A list of option names as keys and type * names passed as string or array as values. * * @return OptionsResolverInterface The resolver instance. * * @throws Exception\InvalidOptionsException If an option has not been defined for * which an allowed type is set. */ public function addAllowedTypes(array $allowedTypes); /** * Sets normalizers that are applied on resolved options. * * The normalizers should be closures with the following signature: * * * function (Options $options, $value) * * * The second parameter passed to the closure is the value of * the option. * * The closure should return the normalized value. * * @param array $normalizers An array of closures. * * @return OptionsResolverInterface The resolver instance. */ public function setNormalizers(array $normalizers); /** * Returns whether an option is known. * * An option is known if it has been passed to either {@link setDefaults()}, * {@link setRequired()} or {@link setOptional()} before. * * @param string $option The name of the option. * * @return Boolean Whether the option is known. */ public function isKnown($option); /** * Returns whether an option is required. * * An option is required if it has been passed to {@link setRequired()}, * but not to {@link setDefaults()}. That is, the option has been declared * as required and no default value has been set. * * @param string $option The name of the option. * * @return Boolean Whether the option is required. */ public function isRequired($option); /** * Returns the combination of the default and the passed options. * * @param array $options The custom option values. * * @return array A list of options and their values. * * @throws Exception\InvalidOptionsException If any of the passed options has not * been defined or does not contain an * allowed value. * @throws Exception\MissingOptionsException If a required option is missing. * @throws Exception\OptionDefinitionException If a cyclic dependency is detected * between two lazy options. */ public function resolve(array $options = array()); } PK!^R<<-Symfony/Component/OptionsResolver/Options.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver; use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException; /** * Container for resolving inter-dependent options. * * @author Bernhard Schussek */ class Options implements \ArrayAccess, \Iterator, \Countable { /** * A list of option values. * @var array */ private $options = array(); /** * A list of normalizer closures. * @var array */ private $normalizers = array(); /** * A list of closures for evaluating lazy options. * @var array */ private $lazy = array(); /** * A list containing the currently locked options. * @var array */ private $lock = array(); /** * Whether at least one option has already been read. * * Once read, the options cannot be changed anymore. This is * necessary in order to avoid inconsistencies during the resolving * process. If any option is changed after being read, all evaluated * lazy options that depend on this option would become invalid. * * @var Boolean */ private $reading = false; /** * Sets the value of a given option. * * You can set lazy options by passing a closure with the following * signature: * * * function (Options $options) * * * This closure will be evaluated once the option is read using * {@link get()}. The closure has access to the resolved values of * other options through the passed {@link Options} instance. * * @param string $option The name of the option. * @param mixed $value The value of the option. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function set($option, $value) { // Setting is not possible once an option is read, because then lazy // options could manipulate the state of the object, leading to // inconsistent results. if ($this->reading) { throw new OptionDefinitionException('Options cannot be set anymore once options have been read.'); } // Setting is equivalent to overloading while discarding the previous // option value unset($this->options[$option]); unset($this->lazy[$option]); $this->overload($option, $value); } /** * Sets the normalizer for a given option. * * Normalizers should be closures with the following signature: * * * function (Options $options, $value) * * * This closure will be evaluated once the option is read using * {@link get()}. The closure has access to the resolved values of * other options through the passed {@link Options} instance. * * @param string $option The name of the option. * @param \Closure $normalizer The normalizer. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function setNormalizer($option, \Closure $normalizer) { if ($this->reading) { throw new OptionDefinitionException('Normalizers cannot be added anymore once options have been read.'); } $this->normalizers[$option] = $normalizer; } /** * Replaces the contents of the container with the given options. * * This method is a shortcut for {@link clear()} with subsequent * calls to {@link set()}. * * @param array $options The options to set. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function replace(array $options) { if ($this->reading) { throw new OptionDefinitionException('Options cannot be replaced anymore once options have been read.'); } $this->options = array(); $this->lazy = array(); $this->normalizers = array(); foreach ($options as $option => $value) { $this->overload($option, $value); } } /** * Overloads the value of a given option. * * Contrary to {@link set()}, this method keeps the previous default * value of the option so that you can access it if you pass a closure. * Passed closures should have the following signature: * * * function (Options $options, $value) * * * The second parameter passed to the closure is the current default * value of the option. * * @param string $option The option name. * @param mixed $value The option value. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function overload($option, $value) { if ($this->reading) { throw new OptionDefinitionException('Options cannot be overloaded anymore once options have been read.'); } // If an option is a closure that should be evaluated lazily, store it // in the "lazy" property. if ($value instanceof \Closure) { $reflClosure = new \ReflectionFunction($value); $params = $reflClosure->getParameters(); if (isset($params[0]) && null !== ($class = $params[0]->getClass()) && __CLASS__ === $class->name) { // Initialize the option if no previous value exists if (!isset($this->options[$option])) { $this->options[$option] = null; } // Ignore previous lazy options if the closure has no second parameter if (!isset($this->lazy[$option]) || !isset($params[1])) { $this->lazy[$option] = array(); } // Store closure for later evaluation $this->lazy[$option][] = $value; return; } } // Remove lazy options by default unset($this->lazy[$option]); $this->options[$option] = $value; } /** * Returns the value of the given option. * * If the option was a lazy option, it is evaluated now. * * @param string $option The option name. * * @return mixed The option value. * * @throws \OutOfBoundsException If the option does not exist. * @throws OptionDefinitionException If a cyclic dependency is detected * between two lazy options. */ public function get($option) { $this->reading = true; if (!array_key_exists($option, $this->options)) { throw new \OutOfBoundsException(sprintf('The option "%s" does not exist.', $option)); } if (isset($this->lazy[$option])) { $this->resolve($option); } if (isset($this->normalizers[$option])) { $this->normalize($option); } return $this->options[$option]; } /** * Returns whether the given option exists. * * @param string $option The option name. * * @return Boolean Whether the option exists. */ public function has($option) { return array_key_exists($option, $this->options); } /** * Removes the option with the given name. * * @param string $option The option name. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function remove($option) { if ($this->reading) { throw new OptionDefinitionException('Options cannot be removed anymore once options have been read.'); } unset($this->options[$option]); unset($this->lazy[$option]); unset($this->normalizers[$option]); } /** * Removes all options. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. */ public function clear() { if ($this->reading) { throw new OptionDefinitionException('Options cannot be cleared anymore once options have been read.'); } $this->options = array(); $this->lazy = array(); $this->normalizers = array(); } /** * Returns the values of all options. * * Lazy options are evaluated at this point. * * @return array The option values. */ public function all() { $this->reading = true; // Performance-wise this is slightly better than // while (null !== $option = key($this->lazy)) foreach ($this->lazy as $option => $closures) { // Double check, in case the option has already been resolved // by cascade in the previous cycles if (isset($this->lazy[$option])) { $this->resolve($option); } } foreach ($this->normalizers as $option => $normalizer) { if (isset($this->normalizers[$option])) { $this->normalize($option); } } return $this->options; } /** * Equivalent to {@link has()}. * * @param string $option The option name. * * @return Boolean Whether the option exists. * * @see \ArrayAccess::offsetExists() */ public function offsetExists($option) { return $this->has($option); } /** * Equivalent to {@link get()}. * * @param string $option The option name. * * @return mixed The option value. * * @throws \OutOfBoundsException If the option does not exist. * @throws OptionDefinitionException If a cyclic dependency is detected * between two lazy options. * * @see \ArrayAccess::offsetGet() */ public function offsetGet($option) { return $this->get($option); } /** * Equivalent to {@link set()}. * * @param string $option The name of the option. * @param mixed $value The value of the option. May be a closure with a * signature as defined in DefaultOptions::add(). * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. * * @see \ArrayAccess::offsetSet() */ public function offsetSet($option, $value) { $this->set($option, $value); } /** * Equivalent to {@link remove()}. * * @param string $option The option name. * * @throws OptionDefinitionException If options have already been read. * Once options are read, the container * becomes immutable. * * @see \ArrayAccess::offsetUnset() */ public function offsetUnset($option) { $this->remove($option); } /** * {@inheritdoc} */ public function current() { return $this->get($this->key()); } /** * {@inheritdoc} */ public function next() { next($this->options); } /** * {@inheritdoc} */ public function key() { return key($this->options); } /** * {@inheritdoc} */ public function valid() { return null !== $this->key(); } /** * {@inheritdoc} */ public function rewind() { reset($this->options); } /** * {@inheritdoc} */ public function count() { return count($this->options); } /** * Evaluates the given lazy option. * * The evaluated value is written into the options array. The closure for * evaluating the option is discarded afterwards. * * @param string $option The option to evaluate. * * @throws OptionDefinitionException If the option has a cyclic dependency * on another option. */ private function resolve($option) { // The code duplication with normalize() exists for performance // reasons, in order to save a method call. // Remember that this method is potentially called a couple of thousand // times and needs to be as efficient as possible. if (isset($this->lock[$option])) { $conflicts = array(); foreach ($this->lock as $option => $locked) { if ($locked) { $conflicts[] = $option; } } throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', implode('", "', $conflicts))); } $this->lock[$option] = true; foreach ($this->lazy[$option] as $closure) { $this->options[$option] = $closure($this, $this->options[$option]); } unset($this->lock[$option]); // The option now isn't lazy anymore unset($this->lazy[$option]); } /** * Normalizes the given option. * * The evaluated value is written into the options array. * * @param string $option The option to normalizer. * * @throws OptionDefinitionException If the option has a cyclic dependency * on another option. */ private function normalize($option) { // The code duplication with resolve() exists for performance // reasons, in order to save a method call. // Remember that this method is potentially called a couple of thousand // times and needs to be as efficient as possible. if (isset($this->lock[$option])) { $conflicts = array(); foreach ($this->lock as $option => $locked) { if ($locked) { $conflicts[] = $option; } } throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', implode('", "', $conflicts))); } /** @var \Closure $normalizer */ $normalizer = $this->normalizers[$option]; $this->lock[$option] = true; $this->options[$option] = $normalizer($this, array_key_exists($option, $this->options) ? $this->options[$option] : null); unset($this->lock[$option]); // The option is now normalized unset($this->normalizers[$option]); } } PK!}8%8%5Symfony/Component/OptionsResolver/OptionsResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver; use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; use Symfony\Component\OptionsResolver\Exception\MissingOptionsException; /** * Helper for merging default and concrete option values. * * @author Bernhard Schussek * @author Tobias Schultze */ class OptionsResolver implements OptionsResolverInterface { /** * The default option values. * @var Options */ private $defaultOptions; /** * The options known by the resolver. * @var array */ private $knownOptions = array(); /** * The options without defaults that are required to be passed to resolve(). * @var array */ private $requiredOptions = array(); /** * A list of accepted values for each option. * @var array */ private $allowedValues = array(); /** * A list of accepted types for each option. * @var array */ private $allowedTypes = array(); /** * Creates a new instance. */ public function __construct() { $this->defaultOptions = new Options(); } /** * Clones the resolver. */ public function __clone() { $this->defaultOptions = clone $this->defaultOptions; } /** * {@inheritdoc} */ public function setDefaults(array $defaultValues) { foreach ($defaultValues as $option => $value) { $this->defaultOptions->overload($option, $value); $this->knownOptions[$option] = true; unset($this->requiredOptions[$option]); } return $this; } /** * {@inheritdoc} */ public function replaceDefaults(array $defaultValues) { foreach ($defaultValues as $option => $value) { $this->defaultOptions->set($option, $value); $this->knownOptions[$option] = true; unset($this->requiredOptions[$option]); } return $this; } /** * {@inheritdoc} */ public function setOptional(array $optionNames) { foreach ($optionNames as $key => $option) { if (!is_int($key)) { throw new OptionDefinitionException('You should not pass default values to setOptional()'); } $this->knownOptions[$option] = true; } return $this; } /** * {@inheritdoc} */ public function setRequired(array $optionNames) { foreach ($optionNames as $key => $option) { if (!is_int($key)) { throw new OptionDefinitionException('You should not pass default values to setRequired()'); } $this->knownOptions[$option] = true; // set as required if no default has been set already if (!isset($this->defaultOptions[$option])) { $this->requiredOptions[$option] = true; } } return $this; } /** * {@inheritdoc} */ public function setAllowedValues(array $allowedValues) { $this->validateOptionsExistence($allowedValues); $this->allowedValues = array_replace($this->allowedValues, $allowedValues); return $this; } /** * {@inheritdoc} */ public function addAllowedValues(array $allowedValues) { $this->validateOptionsExistence($allowedValues); $this->allowedValues = array_merge_recursive($this->allowedValues, $allowedValues); return $this; } /** * {@inheritdoc} */ public function setAllowedTypes(array $allowedTypes) { $this->validateOptionsExistence($allowedTypes); $this->allowedTypes = array_replace($this->allowedTypes, $allowedTypes); return $this; } /** * {@inheritdoc} */ public function addAllowedTypes(array $allowedTypes) { $this->validateOptionsExistence($allowedTypes); $this->allowedTypes = array_merge_recursive($this->allowedTypes, $allowedTypes); return $this; } /** * {@inheritdoc} */ public function setNormalizers(array $normalizers) { $this->validateOptionsExistence($normalizers); foreach ($normalizers as $option => $normalizer) { $this->defaultOptions->setNormalizer($option, $normalizer); } return $this; } /** * {@inheritdoc} */ public function isKnown($option) { return isset($this->knownOptions[$option]); } /** * {@inheritdoc} */ public function isRequired($option) { return isset($this->requiredOptions[$option]); } /** * {@inheritdoc} */ public function resolve(array $options = array()) { $this->validateOptionsExistence($options); $this->validateOptionsCompleteness($options); // Make sure this method can be called multiple times $combinedOptions = clone $this->defaultOptions; // Override options set by the user foreach ($options as $option => $value) { $combinedOptions->set($option, $value); } // Resolve options $resolvedOptions = $combinedOptions->all(); $this->validateOptionValues($resolvedOptions); $this->validateOptionTypes($resolvedOptions); return $resolvedOptions; } /** * Validates that the given option names exist and throws an exception * otherwise. * * @param array $options An list of option names as keys. * * @throws InvalidOptionsException If any of the options has not been defined. */ private function validateOptionsExistence(array $options) { $diff = array_diff_key($options, $this->knownOptions); if (count($diff) > 0) { ksort($this->knownOptions); ksort($diff); throw new InvalidOptionsException(sprintf( (count($diff) > 1 ? 'The options "%s" do not exist.' : 'The option "%s" does not exist.').' Known options are: "%s"', implode('", "', array_keys($diff)), implode('", "', array_keys($this->knownOptions)) )); } } /** * Validates that all required options are given and throws an exception * otherwise. * * @param array $options An list of option names as keys. * * @throws MissingOptionsException If a required option is missing. */ private function validateOptionsCompleteness(array $options) { $diff = array_diff_key($this->requiredOptions, $options); if (count($diff) > 0) { ksort($diff); throw new MissingOptionsException(sprintf( count($diff) > 1 ? 'The required options "%s" are missing.' : 'The required option "%s" is missing.', implode('", "', array_keys($diff)) )); } } /** * Validates that the given option values match the allowed values and * throws an exception otherwise. * * @param array $options A list of option values. * * @throws InvalidOptionsException If any of the values does not match the * allowed values of the option. */ private function validateOptionValues(array $options) { foreach ($this->allowedValues as $option => $allowedValues) { if (isset($options[$option]) && !in_array($options[$option], $allowedValues, true)) { throw new InvalidOptionsException(sprintf('The option "%s" has the value "%s", but is expected to be one of "%s"', $option, $options[$option], implode('", "', $allowedValues))); } } } /** * Validates that the given options match the allowed types and * throws an exception otherwise. * * @param array $options A list of options. * * @throws InvalidOptionsException If any of the types does not match the * allowed types of the option. */ private function validateOptionTypes(array $options) { foreach ($this->allowedTypes as $option => $allowedTypes) { if (!array_key_exists($option, $options)) { continue; } $value = $options[$option]; $allowedTypes = (array) $allowedTypes; foreach ($allowedTypes as $type) { $isFunction = 'is_'.$type; if (function_exists($isFunction) && $isFunction($value)) { continue 2; } elseif ($value instanceof $type) { continue 2; } } $printableValue = is_object($value) ? get_class($value) : (is_array($value) ? 'Array' : (string) $value); throw new InvalidOptionsException(sprintf( 'The option "%s" with value "%s" is expected to be of type "%s"', $option, $printableValue, implode('", "', $allowedTypes) )); } } } PK!fJ5Symfony/Component/Config/Definition/NodeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * Common Interface among all nodes. * * In most cases, it is better to inherit from BaseNode instead of implementing * this interface yourself. * * @author Johannes M. Schmitt */ interface NodeInterface { /** * Returns the name of the node. * * @return string The name of the node */ public function getName(); /** * Returns the path of the node. * * @return string The node path */ public function getPath(); /** * Returns true when the node is required. * * @return Boolean If the node is required */ public function isRequired(); /** * Returns true when the node has a default value. * * @return Boolean If the node has a default value */ public function hasDefaultValue(); /** * Returns the default value of the node. * * @return mixed The default value * @throws \RuntimeException if the node has no default value */ public function getDefaultValue(); /** * Normalizes the supplied value. * * @param mixed $value The value to normalize * * @return mixed The normalized value */ public function normalize($value); /** * Merges two values together. * * @param mixed $leftSide * @param mixed $rightSide * * @return mixed The merged values */ public function merge($leftSide, $rightSide); /** * Finalizes a value. * * @param mixed $value The value to finalize * * @return mixed The finalized value */ public function finalize($value); } PK!jkk3Symfony/Component/Config/Definition/IntegerNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents an integer value in the config tree. * * @author Jeanmonod David */ class IntegerNode extends NumericNode { /** * {@inheritDoc} */ protected function validateType($value) { if (!is_int($value)) { $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected int, but got %s.', $this->getPath(), gettype($value))); $ex->setPath($this->getPath()); throw $ex; } } } PK!aVp  0Symfony/Component/Config/Definition/EnumNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * Node which only allows a finite set of values. * * @author Johannes M. Schmitt */ class EnumNode extends ScalarNode { private $values; public function __construct($name, NodeInterface $parent = null, array $values = array()) { $values = array_unique($values); if (count($values) <= 1) { throw new \InvalidArgumentException('$values must contain at least two distinct elements.'); } parent::__construct($name, $parent); $this->values = $values; } public function getValues() { return $this->values; } protected function finalizeValue($value) { $value = parent::finalizeValue($value); if (!in_array($value, $this->values, true)) { $ex = new InvalidConfigurationException(sprintf( 'The value %s is not allowed for path "%s". Permissible values: %s', json_encode($value), $this->getPath(), implode(', ', array_map('json_encode', $this->values)))); $ex->setPath($this->getPath()); throw $ex; } return $value; } } PK!Un=#'#';Symfony/Component/Config/Definition/PrototypedArrayNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Exception\DuplicateKeyException; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; use Symfony\Component\Config\Definition\Exception\Exception; /** * Represents a prototyped Array node in the config tree. * * @author Johannes M. Schmitt */ class PrototypedArrayNode extends ArrayNode { protected $prototype; protected $keyAttribute; protected $removeKeyAttribute = false; protected $minNumberOfElements = 0; protected $defaultValue = array(); protected $defaultChildren; /** * Sets the minimum number of elements that a prototype based node must * contain. By default this is zero, meaning no elements. * * @param integer $number */ public function setMinNumberOfElements($number) { $this->minNumberOfElements = $number; } /** * Sets the attribute which value is to be used as key. * * This is useful when you have an indexed array that should be an * associative array. You can select an item from within the array * to be the key of the particular item. For example, if "id" is the * "key", then: * * array( * array('id' => 'my_name', 'foo' => 'bar'), * ); * * becomes * * array( * 'my_name' => array('foo' => 'bar'), * ); * * If you'd like "'id' => 'my_name'" to still be present in the resulting * array, then you can set the second argument of this method to false. * * @param string $attribute The name of the attribute which value is to be used as a key * @param Boolean $remove Whether or not to remove the key */ public function setKeyAttribute($attribute, $remove = true) { $this->keyAttribute = $attribute; $this->removeKeyAttribute = $remove; } /** * Retrieves the name of the attribute which value should be used as key. * * @return string The name of the attribute */ public function getKeyAttribute() { return $this->keyAttribute; } /** * Sets the default value of this node. * * @param string $value * * @throws \InvalidArgumentException if the default value is not an array */ public function setDefaultValue($value) { if (!is_array($value)) { throw new \InvalidArgumentException($this->getPath().': the default value of an array node has to be an array.'); } $this->defaultValue = $value; } /** * Checks if the node has a default value. * * @return Boolean */ public function hasDefaultValue() { return true; } /** * Adds default children when none are set. * * @param integer|string|array|null $children The number of children|The child name|The children names to be added */ public function setAddChildrenIfNoneSet($children = array('defaults')) { if (null === $children) { $this->defaultChildren = array('defaults'); } else { $this->defaultChildren = is_integer($children) && $children > 0 ? range(1, $children) : (array) $children; } } /** * Retrieves the default value. * * The default value could be either explicited or derived from the prototype * default value. * * @return array The default value */ public function getDefaultValue() { if (null !== $this->defaultChildren) { $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : array(); $defaults = array(); foreach (array_values($this->defaultChildren) as $i => $name) { $defaults[null === $this->keyAttribute ? $i : $name] = $default; } return $defaults; } return $this->defaultValue; } /** * Sets the node prototype. * * @param PrototypeNodeInterface $node */ public function setPrototype(PrototypeNodeInterface $node) { $this->prototype = $node; } /** * Retrieves the prototype * * @return PrototypeNodeInterface The prototype */ public function getPrototype() { return $this->prototype; } /** * Disable adding concrete children for prototyped nodes. * * @param NodeInterface $node The child node to add * * @throws Exception */ public function addChild(NodeInterface $node) { throw new Exception('A prototyped array node can not have concrete children.'); } /** * Finalizes the value of this node. * * @param mixed $value * * @return mixed The finalized value * * @throws UnsetKeyException * @throws InvalidConfigurationException if the node doesn't have enough children */ protected function finalizeValue($value) { if (false === $value) { $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value)); throw new UnsetKeyException($msg); } foreach ($value as $k => $v) { $this->prototype->setName($k); try { $value[$k] = $this->prototype->finalize($v); } catch (UnsetKeyException $unset) { unset($value[$k]); } } if (count($value) < $this->minNumberOfElements) { $msg = sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } return $value; } /** * Normalizes the value. * * @param mixed $value The value to normalize * * @return mixed The normalized value * * @throws InvalidConfigurationException * @throws DuplicateKeyException */ protected function normalizeValue($value) { if (false === $value) { return $value; } $value = $this->remapXml($value); $isAssoc = array_keys($value) !== range(0, count($value) -1); $normalized = array(); foreach ($value as $k => $v) { if (null !== $this->keyAttribute && is_array($v)) { if (!isset($v[$this->keyAttribute]) && is_int($k) && !$isAssoc) { $msg = sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } elseif (isset($v[$this->keyAttribute])) { $k = $v[$this->keyAttribute]; // remove the key attribute when required if ($this->removeKeyAttribute) { unset($v[$this->keyAttribute]); } // if only "value" is left if (1 == count($v) && isset($v['value'])) { $v = $v['value']; } } if (array_key_exists($k, $normalized)) { $msg = sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath()); $ex = new DuplicateKeyException($msg); $ex->setPath($this->getPath()); throw $ex; } } $this->prototype->setName($k); if (null !== $this->keyAttribute || $isAssoc) { $normalized[$k] = $this->prototype->normalize($v); } else { $normalized[] = $this->prototype->normalize($v); } } return $normalized; } /** * Merges values together. * * @param mixed $leftSide The left side to merge. * @param mixed $rightSide The right side to merge. * * @return mixed The merged values * * @throws InvalidConfigurationException * @throws \RuntimeException */ protected function mergeValues($leftSide, $rightSide) { if (false === $rightSide) { // if this is still false after the last config has been merged the // finalization pass will take care of removing this key entirely return false; } if (false === $leftSide || !$this->performDeepMerging) { return $rightSide; } foreach ($rightSide as $k => $v) { // prototype, and key is irrelevant, so simply append the element if (null === $this->keyAttribute) { $leftSide[] = $v; continue; } // no conflict if (!array_key_exists($k, $leftSide)) { if (!$this->allowNewKeys) { $ex = new InvalidConfigurationException(sprintf( 'You are not allowed to define new elements for path "%s". ' . 'Please define all elements for this path in one config file.', $this->getPath() )); $ex->setPath($this->getPath()); throw $ex; } $leftSide[$k] = $v; continue; } $this->prototype->setName($k); $leftSide[$k] = $this->prototype->merge($leftSide[$k], $v); } return $leftSide; } } PK!U' ' 1Symfony/Component/Config/Definition/Processor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * This class is the entry point for config normalization/merging/finalization. * * @author Johannes M. Schmitt */ class Processor { /** * Processes an array of configurations. * * @param NodeInterface $configTree The node tree describing the configuration * @param array $configs An array of configuration items to process * * @return array The processed configuration */ public function process(NodeInterface $configTree, array $configs) { $currentConfig = array(); foreach ($configs as $config) { $config = $configTree->normalize($config); $currentConfig = $configTree->merge($currentConfig, $config); } return $configTree->finalize($currentConfig); } /** * Processes an array of configurations. * * @param ConfigurationInterface $configuration The configuration class * @param array $configs An array of configuration items to process * * @return array The processed configuration */ public function processConfiguration(ConfigurationInterface $configuration, array $configs) { return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs); } /** * Normalizes a configuration entry. * * This method returns a normalize configuration array for a given key * to remove the differences due to the original format (YAML and XML mainly). * * Here is an example. * * The configuration in XML: * * twig.extension.foo * twig.extension.bar * * And the same configuration in YAML: * * extensions: ['twig.extension.foo', 'twig.extension.bar'] * * @param array $config A config array * @param string $key The key to normalize * @param string $plural The plural form of the key if it is irregular * * @return array */ public static function normalizeConfig($config, $key, $plural = null) { if (null === $plural) { $plural = $key.'s'; } if (isset($config[$plural])) { return $config[$plural]; } if (isset($config[$key])) { if (is_string($config[$key]) || !is_int(key($config[$key]))) { // only one return array($config[$key]); } return $config[$key]; } return array(); } } PK!C;Symfony/Component/Config/Definition/Exception/Exception.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * Base exception for all configuration exceptions * * @author Johannes M. Schmitt */ class Exception extends \RuntimeException { } PK!5-OSymfony/Component/Config/Definition/Exception/InvalidConfigurationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * A very general exception which can be thrown whenever non of the more specific * exceptions is suitable. * * @author Johannes M. Schmitt */ class InvalidConfigurationException extends Exception { private $path; public function setPath($path) { $this->path = $path; } public function getPath() { return $this->path; } } PK!CSymfony/Component/Config/Definition/Exception/UnsetKeyException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is usually not encountered by the end-user, but only used * internally to signal the parent scope to unset a key. * * @author Johannes M. Schmitt */ class UnsetKeyException extends Exception { } PK!@FSymfony/Component/Config/Definition/Exception/InvalidTypeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is thrown if an invalid type is encountered. * * @author Johannes M. Schmitt */ class InvalidTypeException extends InvalidConfigurationException { } PK!]F4LSymfony/Component/Config/Definition/Exception/InvalidDefinitionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * Thrown when an error is detected in a node Definition. * * @author Victor Berchet */ class InvalidDefinitionException extends Exception { } PK!|EEGSymfony/Component/Config/Definition/Exception/DuplicateKeyException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is thrown whenever the key of an array is not unique. This can * only be the case if the configuration is coming from an XML file. * * @author Johannes M. Schmitt */ class DuplicateKeyException extends InvalidConfigurationException { } PK!:2&QQMSymfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is thrown when a configuration path is overwritten from a * subsequent configuration file, but the entry node specifically forbids this. * * @author Johannes M. Schmitt */ class ForbiddenOverwriteException extends InvalidConfigurationException { } PK!# ֕44DSymfony/Component/Config/Definition/Builder/NormalizationBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class builds normalization conditions. * * @author Johannes M. Schmitt */ class NormalizationBuilder { protected $node; public $before = array(); public $remappings = array(); /** * Constructor * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Registers a key to remap to its plural form. * * @param string $key The key to remap * @param string $plural The plural of the key in case of irregular plural * * @return NormalizationBuilder */ public function remap($key, $plural = null) { $this->remappings[] = array($key, null === $plural ? $key.'s' : $plural); return $this; } /** * Registers a closure to run before the normalization or an expression builder to build it if null is provided. * * @param \Closure $closure * * @return ExprBuilder|NormalizationBuilder */ public function before(\Closure $closure = null) { if (null !== $closure) { $this->before[] = $closure; return $this; } return $this->before[] = new ExprBuilder($this->node); } } PK!VhU;Symfony/Component/Config/Definition/Builder/TreeBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\NodeInterface; /** * This is the entry class for building a config tree. * * @author Johannes M. Schmitt */ class TreeBuilder implements NodeParentInterface { protected $tree; protected $root; protected $builder; /** * Creates the root node. * * @param string $name The name of the root node * @param string $type The type of the root node * @param NodeBuilder $builder A custom node builder instance * * @return ArrayNodeDefinition|NodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array') * * @throws \RuntimeException When the node type is not supported */ public function root($name, $type = 'array', NodeBuilder $builder = null) { $builder = $builder ?: new NodeBuilder(); return $this->root = $builder->node($name, $type)->setParent($this); } /** * Builds the tree. * * @return NodeInterface * * @throws \RuntimeException */ public function buildTree() { if (null === $this->root) { throw new \RuntimeException('The configuration tree has no root node.'); } if (null !== $this->tree) { return $this->tree; } return $this->tree = $this->root->getNode(true); } } PK!ʍBSymfony/Component/Config/Definition/Builder/EnumNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\EnumNode; /** * Enum Node Definition. * * @author Johannes M. Schmitt */ class EnumNodeDefinition extends ScalarNodeDefinition { private $values; public function values(array $values) { $values = array_unique($values); if (count($values) <= 1) { throw new \InvalidArgumentException('->values() must be called with at least two distinct values.'); } $this->values = $values; return $this; } /** * Instantiate a Node * * @return EnumNode The node * * @throws \RuntimeException */ protected function instantiateNode() { if (null === $this->values) { throw new \RuntimeException('You must call ->values() on enum nodes.'); } return new EnumNode($this->name, $this->parent, $this->values); } } PK!{{<Symfony/Component/Config/Definition/Builder/MergeBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class builds merge conditions. * * @author Johannes M. Schmitt */ class MergeBuilder { protected $node; public $allowFalse = false; public $allowOverwrite = true; /** * Constructor * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Sets whether the node can be unset. * * @param Boolean $allow * * @return MergeBuilder */ public function allowUnset($allow = true) { $this->allowFalse = $allow; return $this; } /** * Sets whether the node can be overwritten. * * @param Boolean $deny Whether the overwriting is forbidden or not * * @return MergeBuilder */ public function denyOverwrite($deny = true) { $this->allowOverwrite = !$deny; return $this; } /** * Returns the related node. * * @return NodeDefinition */ public function end() { return $this->node; } } PK!,l[[ASymfony/Component/Config/Definition/Builder/ValidationBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class builds validation conditions. * * @author Christophe Coevoet */ class ValidationBuilder { protected $node; public $rules = array(); /** * Constructor * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Registers a closure to run as normalization or an expression builder to build it if null is provided. * * @param \Closure $closure * * @return ExprBuilder|ValidationBuilder */ public function rule(\Closure $closure = null) { if (null !== $closure) { $this->rules[] = $closure; return $this; } return $this->rules[] = new ExprBuilder($this->node); } } PK!PESymfony/Component/Config/Definition/Builder/BooleanNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\BooleanNode; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ class BooleanNodeDefinition extends ScalarNodeDefinition { /** * {@inheritDoc} */ public function __construct($name, NodeParentInterface $parent = null) { parent::__construct($name, $parent); $this->nullEquivalent = true; } /** * Instantiate a Node * * @return BooleanNode The node */ protected function instantiateNode() { return new BooleanNode($this->name, $this->parent); } } PK!e@FSymfony/Component/Config/Definition/Builder/VariableNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\VariableNode; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ class VariableNodeDefinition extends NodeDefinition { /** * Instantiate a Node * * @return VariableNode The node */ protected function instantiateNode() { return new VariableNode($this->name, $this->parent); } /** * {@inheritDoc} */ protected function createNode() { $node = $this->instantiateNode(); if (null !== $this->normalization) { $node->setNormalizationClosures($this->normalization->before); } if (null !== $this->merge) { $node->setAllowOverwrite($this->merge->allowOverwrite); } if (true === $this->default) { $node->setDefaultValue($this->defaultValue); } $node->setAllowEmptyValue($this->allowEmptyValue); $node->addEquivalentValue(null, $this->nullEquivalent); $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setRequired($this->required); if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); } return $node; } } PK!88CSymfony/Component/Config/Definition/Builder/ArrayNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; /** * This class provides a fluent interface for defining an array node. * * @author Johannes M. Schmitt */ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface { protected $performDeepMerging = true; protected $ignoreExtraKeys = false; protected $children = array(); protected $prototype; protected $atLeastOne = false; protected $allowNewKeys = true; protected $key; protected $removeKeyItem; protected $addDefaults = false; protected $addDefaultChildren = false; protected $nodeBuilder; protected $normalizeKeys = true; /** * {@inheritDoc} */ public function __construct($name, NodeParentInterface $parent = null) { parent::__construct($name, $parent); $this->nullEquivalent = array(); $this->trueEquivalent = array(); } /** * Sets a custom children builder. * * @param NodeBuilder $builder A custom NodeBuilder */ public function setBuilder(NodeBuilder $builder) { $this->nodeBuilder = $builder; } /** * Returns a builder to add children nodes. * * @return NodeBuilder */ public function children() { return $this->getNodeBuilder(); } /** * Sets a prototype for child nodes. * * @param string $type the type of node * * @return NodeDefinition */ public function prototype($type) { return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this); } /** * Adds the default value if the node is not set in the configuration. * * This method is applicable to concrete nodes only (not to prototype nodes). * If this function has been called and the node is not set during the finalization * phase, it's default value will be derived from its children default values. * * @return ArrayNodeDefinition */ public function addDefaultsIfNotSet() { $this->addDefaults = true; return $this; } /** * Adds children with a default value when none are defined. * * @param integer|string|array|null $children The number of children|The child name|The children names to be added * * This method is applicable to prototype nodes only. * * @return ArrayNodeDefinition */ public function addDefaultChildrenIfNoneSet($children = null) { $this->addDefaultChildren = $children; return $this; } /** * Requires the node to have at least one element. * * This method is applicable to prototype nodes only. * * @return ArrayNodeDefinition */ public function requiresAtLeastOneElement() { $this->atLeastOne = true; return $this; } /** * Disallows adding news keys in a subsequent configuration. * * If used all keys have to be defined in the same configuration file. * * @return ArrayNodeDefinition */ public function disallowNewKeysInSubsequentConfigs() { $this->allowNewKeys = false; return $this; } /** * Sets a normalization rule for XML configurations. * * @param string $singular The key to remap * @param string $plural The plural of the key for irregular plurals * * @return ArrayNodeDefinition */ public function fixXmlConfig($singular, $plural = null) { $this->normalization()->remap($singular, $plural); return $this; } /** * Sets the attribute which value is to be used as key. * * This is useful when you have an indexed array that should be an * associative array. You can select an item from within the array * to be the key of the particular item. For example, if "id" is the * "key", then: * * array( * array('id' => 'my_name', 'foo' => 'bar'), * ); * * becomes * * array( * 'my_name' => array('foo' => 'bar'), * ); * * If you'd like "'id' => 'my_name'" to still be present in the resulting * array, then you can set the second argument of this method to false. * * This method is applicable to prototype nodes only. * * @param string $name The name of the key * @param Boolean $removeKeyItem Whether or not the key item should be removed. * * @return ArrayNodeDefinition */ public function useAttributeAsKey($name, $removeKeyItem = true) { $this->key = $name; $this->removeKeyItem = $removeKeyItem; return $this; } /** * Sets whether the node can be unset. * * @param Boolean $allow * * @return ArrayNodeDefinition */ public function canBeUnset($allow = true) { $this->merge()->allowUnset($allow); return $this; } /** * Adds an "enabled" boolean to enable the current section. * * By default, the section is disabled. If any configuration is specified then * the node will be automatically enabled: * * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden * enableableArrayNode: ~ # The config is enabled & use the default values * enableableArrayNode: true # The config is enabled & use the default values * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden * enableableArrayNode: {enabled: false, ...} # The config is disabled * enableableArrayNode: false # The config is disabled * * @return ArrayNodeDefinition */ public function canBeEnabled() { $this ->addDefaultsIfNotSet() ->treatFalseLike(array('enabled' => false)) ->treatTrueLike(array('enabled' => true)) ->treatNullLike(array('enabled' => true)) ->beforeNormalization() ->ifArray() ->then(function ($v) { $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true; return $v; }) ->end() ->children() ->booleanNode('enabled') ->defaultFalse() ; return $this; } /** * Adds an "enabled" boolean to enable the current section. * * By default, the section is enabled. * * @return ArrayNodeDefinition */ public function canBeDisabled() { $this ->addDefaultsIfNotSet() ->treatFalseLike(array('enabled' => false)) ->treatTrueLike(array('enabled' => true)) ->treatNullLike(array('enabled' => true)) ->children() ->booleanNode('enabled') ->defaultTrue() ; return $this; } /** * Disables the deep merging of the node. * * @return ArrayNodeDefinition */ public function performNoDeepMerging() { $this->performDeepMerging = false; return $this; } /** * Allows extra config keys to be specified under an array without * throwing an exception. * * Those config values are simply ignored. This should be used only * in special cases where you want to send an entire configuration * array through a special tree that processes only part of the array. * * @return ArrayNodeDefinition */ public function ignoreExtraKeys() { $this->ignoreExtraKeys = true; return $this; } /** * Sets key normalization. * * @param Boolean $bool Whether to enable key normalization * * @return ArrayNodeDefinition */ public function normalizeKeys($bool) { $this->normalizeKeys = (Boolean) $bool; return $this; } /** * Appends a node definition. * * $node = new ArrayNodeDefinition() * ->children() * ->scalarNode('foo')->end() * ->scalarNode('baz')->end() * ->end() * ->append($this->getBarNodeDefinition()) * ; * * @param NodeDefinition $node A NodeDefinition instance * * @return ArrayNodeDefinition This node */ public function append(NodeDefinition $node) { $this->children[$node->name] = $node->setParent($this); return $this; } /** * Returns a node builder to be used to add children and prototype * * @return NodeBuilder The node builder */ protected function getNodeBuilder() { if (null === $this->nodeBuilder) { $this->nodeBuilder = new NodeBuilder(); } return $this->nodeBuilder->setParent($this); } /** * {@inheritDoc} */ protected function createNode() { if (null === $this->prototype) { $node = new ArrayNode($this->name, $this->parent); $this->validateConcreteNode($node); $node->setAddIfNotSet($this->addDefaults); foreach ($this->children as $child) { $child->parent = $node; $node->addChild($child->getNode()); } } else { $node = new PrototypedArrayNode($this->name, $this->parent); $this->validatePrototypeNode($node); if (null !== $this->key) { $node->setKeyAttribute($this->key, $this->removeKeyItem); } if (true === $this->atLeastOne) { $node->setMinNumberOfElements(1); } if ($this->default) { $node->setDefaultValue($this->defaultValue); } if (false !== $this->addDefaultChildren) { $node->setAddChildrenIfNoneSet($this->addDefaultChildren); if ($this->prototype instanceof static && null === $this->prototype->prototype) { $this->prototype->addDefaultsIfNotSet(); } } $this->prototype->parent = $node; $node->setPrototype($this->prototype->getNode()); } $node->setAllowNewKeys($this->allowNewKeys); $node->addEquivalentValue(null, $this->nullEquivalent); $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setPerformDeepMerging($this->performDeepMerging); $node->setRequired($this->required); $node->setIgnoreExtraKeys($this->ignoreExtraKeys); $node->setNormalizeKeys($this->normalizeKeys); if (null !== $this->normalization) { $node->setNormalizationClosures($this->normalization->before); $node->setXmlRemappings($this->normalization->remappings); } if (null !== $this->merge) { $node->setAllowOverwrite($this->merge->allowOverwrite); $node->setAllowFalse($this->merge->allowFalse); } if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); } return $node; } /** * Validate the configuration of a concrete node. * * @param ArrayNode $node The related node * * @throws InvalidDefinitionException */ protected function validateConcreteNode(ArrayNode $node) { $path = $node->getPath(); if (null !== $this->key) { throw new InvalidDefinitionException( sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path) ); } if (true === $this->atLeastOne) { throw new InvalidDefinitionException( sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path) ); } if ($this->default) { throw new InvalidDefinitionException( sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path) ); } if (false !== $this->addDefaultChildren) { throw new InvalidDefinitionException( sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path) ); } } /** * Validate the configuration of a prototype node. * * @param PrototypedArrayNode $node The related node * * @throws InvalidDefinitionException */ protected function validatePrototypeNode(PrototypedArrayNode $node) { $path = $node->getPath(); if ($this->addDefaults) { throw new InvalidDefinitionException( sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path) ); } if (false !== $this->addDefaultChildren) { if ($this->default) { throw new InvalidDefinitionException( sprintf('A default value and default children might not be used together at path "%s"', $path) ); } if (null !== $this->key && (null === $this->addDefaultChildren || is_integer($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { throw new InvalidDefinitionException( sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path) ); } if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) { throw new InvalidDefinitionException( sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path) ); } } } } PK! "$$;Symfony/Component/Config/Definition/Builder/ExprBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; /** * This class builds an if expression. * * @author Johannes M. Schmitt * @author Christophe Coevoet */ class ExprBuilder { protected $node; public $ifPart; public $thenPart; /** * Constructor * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Marks the expression as being always used. * * @param \Closure $then * * @return ExprBuilder */ public function always(\Closure $then = null) { $this->ifPart = function ($v) { return true; }; if (null !== $then) { $this->thenPart = $then; } return $this; } /** * Sets a closure to use as tests. * * The default one tests if the value is true. * * @param \Closure $closure * * @return ExprBuilder */ public function ifTrue(\Closure $closure = null) { if (null === $closure) { $closure = function ($v) { return true === $v; }; } $this->ifPart = $closure; return $this; } /** * Tests if the value is a string. * * @return ExprBuilder */ public function ifString() { $this->ifPart = function ($v) { return is_string($v); }; return $this; } /** * Tests if the value is null. * * @return ExprBuilder */ public function ifNull() { $this->ifPart = function ($v) { return null === $v; }; return $this; } /** * Tests if the value is an array. * * @return ExprBuilder */ public function ifArray() { $this->ifPart = function ($v) { return is_array($v); }; return $this; } /** * Tests if the value is in an array. * * @param array $array * * @return ExprBuilder */ public function ifInArray(array $array) { $this->ifPart = function ($v) use ($array) { return in_array($v, $array, true); }; return $this; } /** * Tests if the value is not in an array. * * @param array $array * * @return ExprBuilder */ public function ifNotInArray(array $array) { $this->ifPart = function ($v) use ($array) { return !in_array($v, $array, true); }; return $this; } /** * Sets the closure to run if the test pass. * * @param \Closure $closure * * @return ExprBuilder */ public function then(\Closure $closure) { $this->thenPart = $closure; return $this; } /** * Sets a closure returning an empty array. * * @return ExprBuilder */ public function thenEmptyArray() { $this->thenPart = function ($v) { return array(); }; return $this; } /** * Sets a closure marking the value as invalid at validation time. * * if you want to add the value of the node in your message just use a %s placeholder. * * @param string $message * * @return ExprBuilder * * @throws \InvalidArgumentException */ public function thenInvalid($message) { $this->thenPart = function ($v) use ($message) {throw new \InvalidArgumentException(sprintf($message, json_encode($v))); }; return $this; } /** * Sets a closure unsetting this key of the array at validation time. * * @return ExprBuilder * * @throws UnsetKeyException */ public function thenUnset() { $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key'); }; return $this; } /** * Returns the related node * * @return NodeDefinition * * @throws \RuntimeException */ public function end() { if (null === $this->ifPart) { throw new \RuntimeException('You must specify an if part.'); } if (null === $this->thenPart) { throw new \RuntimeException('You must specify a then part.'); } return $this->node; } /** * Builds the expressions. * * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build * * @return array */ public static function buildExpressions(array $expressions) { foreach ($expressions as $k => $expr) { if ($expr instanceof ExprBuilder) { $expressions[$k] = function ($v) use ($expr) { return call_user_func($expr->ifPart, $v) ? call_user_func($expr->thenPart, $v) : $v; }; } } return $expressions; } } PK!3d__MSymfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * An interface that must be implemented by nodes which can have children * * @author Victor Berchet */ interface ParentNodeDefinitionInterface { public function children(); public function append(NodeDefinition $node); public function setBuilder(NodeBuilder $builder); } PK!mcDSymfony/Component/Config/Definition/Builder/ScalarNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\ScalarNode; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ class ScalarNodeDefinition extends VariableNodeDefinition { /** * Instantiate a Node * * @return ScalarNode The node */ protected function instantiateNode() { return new ScalarNode($this->name, $this->parent); } } PK!'nڭESymfony/Component/Config/Definition/Builder/IntegerNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\IntegerNode; /** * This class provides a fluent interface for defining an integer node. * * @author Jeanmonod David */ class IntegerNodeDefinition extends NumericNodeDefinition { /** * Instantiates a Node. * * @return IntegerNode The node */ protected function instantiateNode() { return new IntegerNode($this->name, $this->parent, $this->min, $this->max); } } PK!tpCSymfony/Component/Config/Definition/Builder/FloatNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\FloatNode; /** * This class provides a fluent interface for defining a float node. * * @author Jeanmonod David */ class FloatNodeDefinition extends NumericNodeDefinition { /** * Instantiates a Node. * * @return FloatNode The node */ protected function instantiateNode() { return new FloatNode($this->name, $this->parent, $this->min, $this->max); } } PK!U=CSymfony/Component/Config/Definition/Builder/NodeParentInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * An interface that must be implemented by all node parents * * @author Victor Berchet */ interface NodeParentInterface { } PK! };Symfony/Component/Config/Definition/Builder/NodeBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class provides a fluent interface for building a node. * * @author Johannes M. Schmitt */ class NodeBuilder implements NodeParentInterface { protected $parent; protected $nodeMapping; /** * Constructor * */ public function __construct() { $this->nodeMapping = array( 'variable' => __NAMESPACE__.'\\VariableNodeDefinition', 'scalar' => __NAMESPACE__.'\\ScalarNodeDefinition', 'boolean' => __NAMESPACE__.'\\BooleanNodeDefinition', 'integer' => __NAMESPACE__.'\\IntegerNodeDefinition', 'float' => __NAMESPACE__.'\\FloatNodeDefinition', 'array' => __NAMESPACE__.'\\ArrayNodeDefinition', 'enum' => __NAMESPACE__.'\\EnumNodeDefinition', ); } /** * Set the parent node. * * @param ParentNodeDefinitionInterface $parent The parent node * * @return NodeBuilder This node builder */ public function setParent(ParentNodeDefinitionInterface $parent = null) { $this->parent = $parent; return $this; } /** * Creates a child array node. * * @param string $name The name of the node * * @return ArrayNodeDefinition The child node */ public function arrayNode($name) { return $this->node($name, 'array'); } /** * Creates a child scalar node. * * @param string $name the name of the node * * @return ScalarNodeDefinition The child node */ public function scalarNode($name) { return $this->node($name, 'scalar'); } /** * Creates a child Boolean node. * * @param string $name The name of the node * * @return BooleanNodeDefinition The child node */ public function booleanNode($name) { return $this->node($name, 'boolean'); } /** * Creates a child integer node. * * @param string $name the name of the node * * @return IntegerNodeDefinition The child node */ public function integerNode($name) { return $this->node($name, 'integer'); } /** * Creates a child float node. * * @param string $name the name of the node * * @return FloatNodeDefinition The child node */ public function floatNode($name) { return $this->node($name, 'float'); } /** * Creates a child EnumNode. * * @param string $name * * @return EnumNodeDefinition */ public function enumNode($name) { return $this->node($name, 'enum'); } /** * Creates a child variable node. * * @param string $name The name of the node * * @return VariableNodeDefinition The builder of the child node */ public function variableNode($name) { return $this->node($name, 'variable'); } /** * Returns the parent node. * * @return ParentNodeDefinitionInterface The parent node */ public function end() { return $this->parent; } /** * Creates a child node. * * @param string $name The name of the node * @param string $type The type of the node * * @return NodeDefinition The child node * * @throws \RuntimeException When the node type is not registered * @throws \RuntimeException When the node class is not found */ public function node($name, $type) { $class = $this->getNodeClass($type); $node = new $class($name); $this->append($node); return $node; } /** * Appends a node definition. * * Usage: * * $node = new ArrayNodeDefinition('name') * ->children() * ->scalarNode('foo')->end() * ->scalarNode('baz')->end() * ->append($this->getBarNodeDefinition()) * ->end() * ; * * @param NodeDefinition $node * * @return NodeBuilder This node builder */ public function append(NodeDefinition $node) { if ($node instanceof ParentNodeDefinitionInterface) { $builder = clone $this; $builder->setParent(null); $node->setBuilder($builder); } if (null !== $this->parent) { $this->parent->append($node); // Make this builder the node parent to allow for a fluid interface $node->setParent($this); } return $this; } /** * Adds or overrides a node Type. * * @param string $type The name of the type * @param string $class The fully qualified name the node definition class * * @return NodeBuilder This node builder */ public function setNodeClass($type, $class) { $this->nodeMapping[strtolower($type)] = $class; return $this; } /** * Returns the class name of the node definition. * * @param string $type The node type * * @return string The node definition class name * * @throws \RuntimeException When the node type is not registered * @throws \RuntimeException When the node class is not found */ protected function getNodeClass($type) { $type = strtolower($type); if (!isset($this->nodeMapping[$type])) { throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type)); } $class = $this->nodeMapping[$type]; if (!class_exists($class)) { throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class)); } return $class; } } PK!~GXXESymfony/Component/Config/Definition/Builder/NumericNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * Abstract class that contain common code of integer and float node definition. * * @author David Jeanmonod */ abstract class NumericNodeDefinition extends ScalarNodeDefinition { protected $min; protected $max; /** * Ensures that the value is smaller than the given reference. * * @param mixed $max * * @return NumericNodeDefinition * * @throws \InvalidArgumentException when the constraint is inconsistent */ public function max($max) { if (isset($this->min) && $this->min > $max) { throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s)', $max, $this->min)); } $this->max = $max; return $this; } /** * Ensures that the value is bigger than the given reference. * * @param mixed $min * * @return NumericNodeDefinition * * @throws \InvalidArgumentException when the constraint is inconsistent */ public function min($min) { if (isset($this->max) && $this->max < $min) { throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s)', $min, $this->max)); } $this->min = $min; return $this; } } PK!K>Symfony/Component/Config/Definition/Builder/NodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ abstract class NodeDefinition implements NodeParentInterface { protected $name; protected $normalization; protected $validation; protected $defaultValue; protected $default = false; protected $required = false; protected $merge; protected $allowEmptyValue = true; protected $nullEquivalent; protected $trueEquivalent = true; protected $falseEquivalent = false; /** * @var NodeParentInterface|null */ protected $parent; protected $attributes = array(); /** * Constructor * * @param string $name The name of the node * @param NodeParentInterface|null $parent The parent */ public function __construct($name, NodeParentInterface $parent = null) { $this->parent = $parent; $this->name = $name; } /** * Sets the parent node. * * @param NodeParentInterface $parent The parent * * @return NodeDefinition */ public function setParent(NodeParentInterface $parent) { $this->parent = $parent; return $this; } /** * Sets info message. * * @param string $info The info text * * @return NodeDefinition */ public function info($info) { return $this->attribute('info', $info); } /** * Sets example configuration. * * @param string|array $example * * @return NodeDefinition */ public function example($example) { return $this->attribute('example', $example); } /** * Sets an attribute on the node. * * @param string $key * @param mixed $value * * @return NodeDefinition */ public function attribute($key, $value) { $this->attributes[$key] = $value; return $this; } /** * Returns the parent node. * * @return NodeParentInterface|null The builder of the parent node */ public function end() { return $this->parent; } /** * Creates the node. * * @param Boolean $forceRootNode Whether to force this node as the root node * * @return NodeInterface */ public function getNode($forceRootNode = false) { if ($forceRootNode) { $this->parent = null; } if (null !== $this->normalization) { $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before); } if (null !== $this->validation) { $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules); } $node = $this->createNode(); $node->setAttributes($this->attributes); return $node; } /** * Sets the default value. * * @param mixed $value The default value * * @return NodeDefinition */ public function defaultValue($value) { $this->default = true; $this->defaultValue = $value; return $this; } /** * Sets the node as required. * * @return NodeDefinition */ public function isRequired() { $this->required = true; return $this; } /** * Sets the equivalent value used when the node contains null. * * @param mixed $value * * @return NodeDefinition */ public function treatNullLike($value) { $this->nullEquivalent = $value; return $this; } /** * Sets the equivalent value used when the node contains true. * * @param mixed $value * * @return NodeDefinition */ public function treatTrueLike($value) { $this->trueEquivalent = $value; return $this; } /** * Sets the equivalent value used when the node contains false. * * @param mixed $value * * @return NodeDefinition */ public function treatFalseLike($value) { $this->falseEquivalent = $value; return $this; } /** * Sets null as the default value. * * @return NodeDefinition */ public function defaultNull() { return $this->defaultValue(null); } /** * Sets true as the default value. * * @return NodeDefinition */ public function defaultTrue() { return $this->defaultValue(true); } /** * Sets false as the default value. * * @return NodeDefinition */ public function defaultFalse() { return $this->defaultValue(false); } /** * Sets an expression to run before the normalization. * * @return ExprBuilder */ public function beforeNormalization() { return $this->normalization()->before(); } /** * Denies the node value being empty. * * @return NodeDefinition */ public function cannotBeEmpty() { $this->allowEmptyValue = false; return $this; } /** * Sets an expression to run for the validation. * * The expression receives the value of the node and must return it. It can * modify it. * An exception should be thrown when the node is not valid. * * @return ExprBuilder */ public function validate() { return $this->validation()->rule(); } /** * Sets whether the node can be overwritten. * * @param Boolean $deny Whether the overwriting is forbidden or not * * @return NodeDefinition */ public function cannotBeOverwritten($deny = true) { $this->merge()->denyOverwrite($deny); return $this; } /** * Gets the builder for validation rules. * * @return ValidationBuilder */ protected function validation() { if (null === $this->validation) { $this->validation = new ValidationBuilder($this); } return $this->validation; } /** * Gets the builder for merging rules. * * @return MergeBuilder */ protected function merge() { if (null === $this->merge) { $this->merge = new MergeBuilder($this); } return $this->merge; } /** * Gets the builder for normalization rules. * * @return NormalizationBuilder */ protected function normalization() { if (null === $this->normalization) { $this->normalization = new NormalizationBuilder($this); } return $this->normalization; } /** * Instantiate and configure the node according to this definition * * @return NodeInterface $node The node instance * * @throws InvalidDefinitionException When the definition is invalid */ abstract protected function createNode(); } PK!3Symfony/Component/Config/Definition/BooleanNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents a Boolean value in the config tree. * * @author Johannes M. Schmitt */ class BooleanNode extends ScalarNode { /** * {@inheritDoc} */ protected function validateType($value) { if (!is_bool($value)) { $ex = new InvalidTypeException(sprintf( 'Invalid type for path "%s". Expected boolean, but got %s.', $this->getPath(), gettype($value) )); $ex->setPath($this->getPath()); throw $ex; } } } PK!+;;2Symfony/Component/Config/Definition/ScalarNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents a scalar value in the config tree. * * The following values are considered scalars: * * booleans * * strings * * null * * integers * * floats * * @author Johannes M. Schmitt */ class ScalarNode extends VariableNode { /** * {@inheritDoc} */ protected function validateType($value) { if (!is_scalar($value) && null !== $value) { $ex = new InvalidTypeException(sprintf( 'Invalid type for path "%s". Expected scalar, but got %s.', $this->getPath(), gettype($value) )); $ex->setPath($this->getPath()); throw $ex; } } } PK!m+1Symfony/Component/Config/Definition/FloatNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents a float value in the config tree. * * @author Jeanmonod David */ class FloatNode extends NumericNode { /** * {@inheritDoc} */ protected function validateType($value) { // Integers are also accepted, we just cast them if (is_int($value)) { $value = (float) $value; } if (!is_float($value)) { $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected float, but got %s.', $this->getPath(), gettype($value))); $ex->setPath($this->getPath()); throw $ex; } } } PK!i >>BSymfony/Component/Config/Definition/Dumper/YamlReferenceDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Dumper; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\ScalarNode; use Symfony\Component\Config\Definition\EnumNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; use Symfony\Component\Yaml\Inline; /** * Dumps a Yaml reference configuration for the given configuration/node instance. * * @author Kevin Bond */ class YamlReferenceDumper { private $reference; public function dump(ConfigurationInterface $configuration) { return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree()); } public function dumpNode(NodeInterface $node) { $this->reference = ''; $this->writeNode($node); $ref = $this->reference; $this->reference = null; return $ref; } /** * @param NodeInterface $node * @param integer $depth */ private function writeNode(NodeInterface $node, $depth = 0) { $comments = array(); $default = ''; $defaultArray = null; $children = null; $example = $node->getExample(); // defaults if ($node instanceof ArrayNode) { $children = $node->getChildren(); if ($node instanceof PrototypedArrayNode) { $prototype = $node->getPrototype(); if ($prototype instanceof ArrayNode) { $children = $prototype->getChildren(); } // check for attribute as key if ($key = $node->getKeyAttribute()) { $keyNodeClass = 'Symfony\Component\Config\Definition\\'.($prototype instanceof ArrayNode ? 'ArrayNode' : 'ScalarNode'); $keyNode = new $keyNodeClass($key, $node); $keyNode->setInfo('Prototype'); // add children foreach ($children as $childNode) { $keyNode->addChild($childNode); } $children = array($key => $keyNode); } } if (!$children) { if ($node->hasDefaultValue() && count($defaultArray = $node->getDefaultValue())) { $default = ''; } elseif (!is_array($example)) { $default = '[]'; } } } elseif ($node instanceof EnumNode) { $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues())); $default = '~'; } else { $default = '~'; if ($node->hasDefaultValue()) { $default = $node->getDefaultValue(); if (is_array($default)) { if (count($defaultArray = $node->getDefaultValue())) { $default = ''; } elseif (!is_array($example)) { $default = '[]'; } } else { $default = Inline::dump($default); } } } // required? if ($node->isRequired()) { $comments[] = 'Required'; } // example if ($example && !is_array($example)) { $comments[] = 'Example: '.$example; } $default = (string) $default != '' ? ' '.$default : ''; $comments = count($comments) ? '# '.implode(', ', $comments) : ''; $text = rtrim(sprintf('%-20s %s %s', $node->getName().':', $default, $comments), ' '); if ($info = $node->getInfo()) { $this->writeLine(''); // indenting multi-line info $info = str_replace("\n", sprintf("\n%".$depth * 4 . "s# ", ' '), $info); $this->writeLine('# '.$info, $depth * 4); } $this->writeLine($text, $depth * 4); // output defaults if ($defaultArray) { $this->writeLine(''); $message = count($defaultArray) > 1 ? 'Defaults' : 'Default'; $this->writeLine('# '.$message.':', $depth * 4 + 4); $this->writeArray($defaultArray, $depth + 1); } if (is_array($example)) { $this->writeLine(''); $message = count($example) > 1 ? 'Examples' : 'Example'; $this->writeLine('# '.$message.':', $depth * 4 + 4); $this->writeArray($example, $depth + 1); } if ($children) { foreach ($children as $childNode) { $this->writeNode($childNode, $depth + 1); } } } /** * Outputs a single config reference line * * @param string $text * @param int $indent */ private function writeLine($text, $indent = 0) { $indent = strlen($text) + $indent; $format = '%'.$indent.'s'; $this->reference .= sprintf($format, $text)."\n"; } private function writeArray(array $array, $depth) { $isIndexed = array_values($array) === $array; foreach ($array as $key => $value) { if (is_array($value)) { $val = ''; } else { $val = $value; } if ($isIndexed) { $this->writeLine('- '.$val, $depth * 4); } else { $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4); } if (is_array($value)) { $this->writeArray($value, $depth + 1); } } } } PK!2&&ASymfony/Component/Config/Definition/Dumper/XmlReferenceDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Dumper; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\EnumNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; /** * Dumps a XML reference configuration for the given configuration/node instance. * * @author Wouter J */ class XmlReferenceDumper { private $reference; public function dump(ConfigurationInterface $configuration, $namespace = null) { return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace); } public function dumpNode(NodeInterface $node, $namespace = null) { $this->reference = ''; $this->writeNode($node, 0, true, $namespace); $ref = $this->reference; $this->reference = null; return $ref; } /** * @param NodeInterface $node * @param integer $depth * @param Boolean $root If the node is the root node * @param string $namespace The namespace of the node */ private function writeNode(NodeInterface $node, $depth = 0, $root = false, $namespace = null) { $rootName = ($root ? 'config' : $node->getName()); $rootNamespace = ($namespace ?: ($root ? 'http://example.org/schema/dic/'.$node->getName() : null)); // xml remapping if ($node->getParent()) { $remapping = array_filter($node->getParent()->getXmlRemappings(), function ($mapping) use ($rootName) { return $rootName === $mapping[1]; }); if (count($remapping)) { list($singular, $plural) = current($remapping); $rootName = $singular; } } $rootName = str_replace('_', '-', $rootName); $rootAttributes = array(); $rootAttributeComments = array(); $rootChildren = array(); $rootComments = array(); if ($node instanceof ArrayNode) { $children = $node->getChildren(); // comments about the root node if ($rootInfo = $node->getInfo()) { $rootComments[] = $rootInfo; } if ($rootNamespace) { $rootComments[] = 'Namespace: '.$rootNamespace; } // render prototyped nodes if ($node instanceof PrototypedArrayNode) { array_unshift($rootComments, 'prototype'); if ($key = $node->getKeyAttribute()) { $rootAttributes[$key] = str_replace('-', ' ', $rootName).' '.$key; } $prototype = $node->getPrototype(); if ($prototype instanceof ArrayNode) { $children = $prototype->getChildren(); } else { if ($prototype->hasDefaultValue()) { $prototypeValue = $prototype->getDefaultValue(); } else { switch (get_class($prototype)) { case 'Symfony\Component\Config\Definition\ScalarNode': $prototypeValue = 'scalar value'; break; case 'Symfony\Component\Config\Definition\FloatNode': case 'Symfony\Component\Config\Definition\IntegerNode': $prototypeValue = 'numeric value'; break; case 'Symfony\Component\Config\Definition\BooleanNode': $prototypeValue = 'true|false'; break; case 'Symfony\Component\Config\Definition\EnumNode': $prototypeValue = implode('|', array_map('json_encode', $prototype->getValues())); break; default: $prototypeValue = 'value'; } } } } // get attributes and elements foreach ($children as $child) { if (!$child instanceof ArrayNode) { // get attributes // metadata $name = str_replace('_', '-', $child->getName()); $value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world // comments $comments = array(); if ($info = $child->getInfo()) { $comments[] = $info; } if ($example = $child->getExample()) { $comments[] = 'Example: '.$example; } if ($child->isRequired()) { $comments[] = 'Required'; } if ($child instanceof EnumNode) { $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues())); } if (count($comments)) { $rootAttributeComments[$name] = implode(";\n", $comments); } // default values if ($child->hasDefaultValue()) { $value = $child->getDefaultValue(); } // append attribute $rootAttributes[$name] = $value; } else { // get elements $rootChildren[] = $child; } } } // render comments // root node comment if (count($rootComments)) { foreach ($rootComments as $comment) { $this->writeLine('', $depth); } } // attribute comments if (count($rootAttributeComments)) { foreach ($rootAttributeComments as $attrName => $comment) { $commentDepth = $depth + 4 + strlen($attrName) + 2; $commentLines = explode("\n", $comment); $multiline = (count($commentLines) > 1); $comment = implode(PHP_EOL.str_repeat(' ', $commentDepth), $commentLines); if ($multiline) { $this->writeLine('', $depth); } else { $this->writeLine('', $depth); } } } // render start tag + attributes $rootIsVariablePrototype = isset($prototypeValue); $rootIsEmptyTag = (0 === count($rootChildren) && !$rootIsVariablePrototype); $rootOpenTag = '<'.$rootName; if (1 >= ($attributesCount = count($rootAttributes))) { if (1 === $attributesCount) { $rootOpenTag .= sprintf(' %s="%s"', current(array_keys($rootAttributes)), $this->writeValue(current($rootAttributes))); } $rootOpenTag .= $rootIsEmptyTag ? ' />' : '>'; if ($rootIsVariablePrototype) { $rootOpenTag .= $prototypeValue.''; } $this->writeLine($rootOpenTag, $depth); } else { $this->writeLine($rootOpenTag, $depth); $i = 1; foreach ($rootAttributes as $attrName => $attrValue) { $attr = sprintf('%s="%s"', $attrName, $this->writeValue($attrValue)); $this->writeLine($attr, $depth + 4); if ($attributesCount === $i++) { $this->writeLine($rootIsEmptyTag ? '/>' : '>', $depth); if ($rootIsVariablePrototype) { $rootOpenTag .= $prototypeValue.''; } } } } // render children tags foreach ($rootChildren as $child) { $this->writeLine(''); $this->writeNode($child, $depth + 4); } // render end tag if (!$rootIsEmptyTag && !$rootIsVariablePrototype) { $this->writeLine(''); $rootEndTag = ''; $this->writeLine($rootEndTag, $depth); } } /** * Outputs a single config reference line * * @param string $text * @param int $indent */ private function writeLine($text, $indent = 0) { $indent = strlen($text) + $indent; $format = '%'.$indent.'s'; $this->reference .= sprintf($format, $text)."\n"; } /** * Renders the string conversion of the value. * * @param mixed $value * * @return string */ private function writeValue($value) { if ('%%%%not_defined%%%%' === $value) { return ''; } if (is_string($value) || is_numeric($value)) { return $value; } if (false === $value) { return 'false'; } if (true === $value) { return 'true'; } if (null === $value) { return 'null'; } if (empty($value)) { return ''; } if (is_array($value)) { return implode(',', $value); } } } PK!$¸ 4Symfony/Component/Config/Definition/VariableNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * This node represents a value of variable type in the config tree. * * This node is intended for values of arbitrary type. * Any PHP type is accepted as a value. * * @author Jeremy Mikola */ class VariableNode extends BaseNode implements PrototypeNodeInterface { protected $defaultValueSet = false; protected $defaultValue; protected $allowEmptyValue = true; /** * {@inheritDoc} */ public function setDefaultValue($value) { $this->defaultValueSet = true; $this->defaultValue = $value; } /** * {@inheritDoc} */ public function hasDefaultValue() { return $this->defaultValueSet; } /** * {@inheritDoc} */ public function getDefaultValue() { return $this->defaultValue instanceof \Closure ? call_user_func($this->defaultValue) : $this->defaultValue; } /** * Sets if this node is allowed to have an empty value. * * @param Boolean $boolean True if this entity will accept empty values. */ public function setAllowEmptyValue($boolean) { $this->allowEmptyValue = (Boolean) $boolean; } /** * {@inheritDoc} */ public function setName($name) { $this->name = $name; } /** * {@inheritDoc} */ protected function validateType($value) { } /** * {@inheritDoc} */ protected function finalizeValue($value) { if (!$this->allowEmptyValue && empty($value)) { $ex = new InvalidConfigurationException(sprintf( 'The path "%s" cannot contain an empty value, but got %s.', $this->getPath(), json_encode($value) )); $ex->setPath($this->getPath()); throw $ex; } return $value; } /** * {@inheritDoc} */ protected function normalizeValue($value) { return $value; } /** * {@inheritDoc} */ protected function mergeValues($leftSide, $rightSide) { return $rightSide; } } PK!G4**1Symfony/Component/Config/Definition/ArrayNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; /** * Represents an Array node in the config tree. * * @author Johannes M. Schmitt */ class ArrayNode extends BaseNode implements PrototypeNodeInterface { protected $xmlRemappings = array(); protected $children = array(); protected $allowFalse = false; protected $allowNewKeys = true; protected $addIfNotSet = false; protected $performDeepMerging = true; protected $ignoreExtraKeys = false; protected $normalizeKeys = true; public function setNormalizeKeys($normalizeKeys) { $this->normalizeKeys = (Boolean) $normalizeKeys; } /** * Normalizes keys between the different configuration formats. * * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML. * After running this method, all keys are normalized to foo_bar. * * If you have a mixed key like foo-bar_moo, it will not be altered. * The key will also not be altered if the target key already exists. * * @param mixed $value * * @return array The value with normalized keys */ protected function preNormalize($value) { if (!$this->normalizeKeys || !is_array($value)) { return $value; } foreach ($value as $k => $v) { if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) { $value[$normalizedKey] = $v; unset($value[$k]); } } return $value; } /** * Retrieves the children of this node. * * @return array The children */ public function getChildren() { return $this->children; } /** * Sets the xml remappings that should be performed. * * @param array $remappings an array of the form array(array(string, string)) */ public function setXmlRemappings(array $remappings) { $this->xmlRemappings = $remappings; } /** * Gets the xml remappings that should be performed. * * @return array $remappings an array of the form array(array(string, string)) */ public function getXmlRemappings() { return $this->xmlRemappings; } /** * Sets whether to add default values for this array if it has not been * defined in any of the configuration files. * * @param Boolean $boolean */ public function setAddIfNotSet($boolean) { $this->addIfNotSet = (Boolean) $boolean; } /** * Sets whether false is allowed as value indicating that the array should be unset. * * @param Boolean $allow */ public function setAllowFalse($allow) { $this->allowFalse = (Boolean) $allow; } /** * Sets whether new keys can be defined in subsequent configurations. * * @param Boolean $allow */ public function setAllowNewKeys($allow) { $this->allowNewKeys = (Boolean) $allow; } /** * Sets if deep merging should occur. * * @param Boolean $boolean */ public function setPerformDeepMerging($boolean) { $this->performDeepMerging = (Boolean) $boolean; } /** * Whether extra keys should just be ignore without an exception. * * @param Boolean $boolean To allow extra keys */ public function setIgnoreExtraKeys($boolean) { $this->ignoreExtraKeys = (Boolean) $boolean; } /** * Sets the node Name. * * @param string $name The node's name */ public function setName($name) { $this->name = $name; } /** * Checks if the node has a default value. * * @return Boolean */ public function hasDefaultValue() { return $this->addIfNotSet; } /** * Retrieves the default value. * * @return array The default value * * @throws \RuntimeException if the node has no default value */ public function getDefaultValue() { if (!$this->hasDefaultValue()) { throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath())); } $defaults = array(); foreach ($this->children as $name => $child) { if ($child->hasDefaultValue()) { $defaults[$name] = $child->getDefaultValue(); } } return $defaults; } /** * Adds a child node. * * @param NodeInterface $node The child node to add * * @throws \InvalidArgumentException when the child node has no name * @throws \InvalidArgumentException when the child node's name is not unique */ public function addChild(NodeInterface $node) { $name = $node->getName(); if (!strlen($name)) { throw new \InvalidArgumentException('Child nodes must be named.'); } if (isset($this->children[$name])) { throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name)); } $this->children[$name] = $node; } /** * Finalizes the value of this node. * * @param mixed $value * * @return mixed The finalised value * * @throws UnsetKeyException * @throws InvalidConfigurationException if the node doesn't have enough children */ protected function finalizeValue($value) { if (false === $value) { $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value)); throw new UnsetKeyException($msg); } foreach ($this->children as $name => $child) { if (!array_key_exists($name, $value)) { if ($child->isRequired()) { $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } if ($child->hasDefaultValue()) { $value[$name] = $child->getDefaultValue(); } continue; } try { $value[$name] = $child->finalize($value[$name]); } catch (UnsetKeyException $unset) { unset($value[$name]); } } return $value; } /** * Validates the type of the value. * * @param mixed $value * * @throws InvalidTypeException */ protected function validateType($value) { if (!is_array($value) && (!$this->allowFalse || false !== $value)) { $ex = new InvalidTypeException(sprintf( 'Invalid type for path "%s". Expected array, but got %s', $this->getPath(), gettype($value) )); $ex->setPath($this->getPath()); throw $ex; } } /** * Normalizes the value. * * @param mixed $value The value to normalize * * @return mixed The normalized value * * @throws InvalidConfigurationException */ protected function normalizeValue($value) { if (false === $value) { return $value; } $value = $this->remapXml($value); $normalized = array(); foreach ($value as $name => $val) { if (isset($this->children[$name])) { $normalized[$name] = $this->children[$name]->normalize($val); unset($value[$name]); } } // if extra fields are present, throw exception if (count($value) && !$this->ignoreExtraKeys) { $msg = sprintf('Unrecognized options "%s" under "%s"', implode(', ', array_keys($value)), $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } return $normalized; } /** * Remaps multiple singular values to a single plural value. * * @param array $value The source values * * @return array The remapped values */ protected function remapXml($value) { foreach ($this->xmlRemappings as $transformation) { list($singular, $plural) = $transformation; if (!isset($value[$singular])) { continue; } $value[$plural] = Processor::normalizeConfig($value, $singular, $plural); unset($value[$singular]); } return $value; } /** * Merges values together. * * @param mixed $leftSide The left side to merge. * @param mixed $rightSide The right side to merge. * * @return mixed The merged values * * @throws InvalidConfigurationException * @throws \RuntimeException */ protected function mergeValues($leftSide, $rightSide) { if (false === $rightSide) { // if this is still false after the last config has been merged the // finalization pass will take care of removing this key entirely return false; } if (false === $leftSide || !$this->performDeepMerging) { return $rightSide; } foreach ($rightSide as $k => $v) { // no conflict if (!array_key_exists($k, $leftSide)) { if (!$this->allowNewKeys) { $ex = new InvalidConfigurationException(sprintf( 'You are not allowed to define new elements for path "%s". ' .'Please define all elements for this path in one config file. ' .'If you are trying to overwrite an element, make sure you redefine it ' .'with the same name.', $this->getPath() )); $ex->setPath($this->getPath()); throw $ex; } $leftSide[$k] = $v; continue; } if (!isset($this->children[$k])) { throw new \RuntimeException('merge() expects a normalized config array.'); } $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v); } return $leftSide; } } PK!*dd>Symfony/Component/Config/Definition/ConfigurationInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * Configuration interface * * @author Victor Berchet */ interface ConfigurationInterface { /** * Generates the configuration tree builder. * * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder */ public function getConfigTreeBuilder(); } PK!eww>Symfony/Component/Config/Definition/PrototypeNodeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * This interface must be implemented by nodes which can be used as prototypes. * * @author Johannes M. Schmitt */ interface PrototypeNodeInterface extends NodeInterface { /** * Sets the name of the node. * * @param string $name The name of the node */ public function setName($name); } PK!-*ҹ--3Symfony/Component/Config/Definition/NumericNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * This node represents a numeric value in the config tree * * @author David Jeanmonod */ class NumericNode extends ScalarNode { protected $min; protected $max; public function __construct($name, NodeInterface $parent = null, $min = null, $max = null) { parent::__construct($name, $parent); $this->min = $min; $this->max = $max; } /** * {@inheritDoc} */ protected function finalizeValue($value) { $value = parent::finalizeValue($value); $errorMsg = null; if (isset($this->min) && $value < $this->min) { $errorMsg = sprintf('The value %s is too small for path "%s". Should be greater than or equal to %s', $value, $this->getPath(), $this->min); } if (isset($this->max) && $value > $this->max) { $errorMsg = sprintf('The value %s is too big for path "%s". Should be less than or equal to %s', $value, $this->getPath(), $this->max); } if (isset($errorMsg)) { $ex = new InvalidConfigurationException($errorMsg); $ex->setPath($this->getPath()); throw $ex; } return $value; } } PK!B""0Symfony/Component/Config/Definition/BaseNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\Exception; use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * The base node class * * @author Johannes M. Schmitt */ abstract class BaseNode implements NodeInterface { protected $name; protected $parent; protected $normalizationClosures = array(); protected $finalValidationClosures = array(); protected $allowOverwrite = true; protected $required = false; protected $equivalentValues = array(); protected $attributes = array(); /** * Constructor. * * @param string $name The name of the node * @param NodeInterface $parent The parent of this node * * @throws \InvalidArgumentException if the name contains a period. */ public function __construct($name, NodeInterface $parent = null) { if (false !== strpos($name, '.')) { throw new \InvalidArgumentException('The name must not contain ".".'); } $this->name = $name; $this->parent = $parent; } public function setAttribute($key, $value) { $this->attributes[$key] = $value; } public function getAttribute($key, $default = null) { return isset($this->attributes[$key]) ? $this->attributes[$key] : $default; } public function hasAttribute($key) { return isset($this->attributes[$key]); } public function getAttributes() { return $this->attributes; } public function setAttributes(array $attributes) { $this->attributes = $attributes; } public function removeAttribute($key) { unset($this->attributes[$key]); } /** * Sets an info message. * * @param string $info */ public function setInfo($info) { $this->setAttribute('info', $info); } /** * Returns info message. * * @return string The info text */ public function getInfo() { return $this->getAttribute('info'); } /** * Sets the example configuration for this node. * * @param string|array $example */ public function setExample($example) { $this->setAttribute('example', $example); } /** * Retrieves the example configuration for this node. * * @return string|array The example */ public function getExample() { return $this->getAttribute('example'); } /** * Adds an equivalent value. * * @param mixed $originalValue * @param mixed $equivalentValue */ public function addEquivalentValue($originalValue, $equivalentValue) { $this->equivalentValues[] = array($originalValue, $equivalentValue); } /** * Set this node as required. * * @param Boolean $boolean Required node */ public function setRequired($boolean) { $this->required = (Boolean) $boolean; } /** * Sets if this node can be overridden. * * @param Boolean $allow */ public function setAllowOverwrite($allow) { $this->allowOverwrite = (Boolean) $allow; } /** * Sets the closures used for normalization. * * @param \Closure[] $closures An array of Closures used for normalization */ public function setNormalizationClosures(array $closures) { $this->normalizationClosures = $closures; } /** * Sets the closures used for final validation. * * @param \Closure[] $closures An array of Closures used for final validation */ public function setFinalValidationClosures(array $closures) { $this->finalValidationClosures = $closures; } /** * Checks if this node is required. * * @return Boolean */ public function isRequired() { return $this->required; } /** * Returns the name of this node * * @return string The Node's name. */ public function getName() { return $this->name; } /** * Retrieves the path of this node. * * @return string The Node's path */ public function getPath() { $path = $this->name; if (null !== $this->parent) { $path = $this->parent->getPath().'.'.$path; } return $path; } /** * Merges two values together. * * @param mixed $leftSide * @param mixed $rightSide * * @return mixed The merged value * * @throws ForbiddenOverwriteException */ final public function merge($leftSide, $rightSide) { if (!$this->allowOverwrite) { throw new ForbiddenOverwriteException(sprintf( 'Configuration path "%s" cannot be overwritten. You have to ' .'define all options for this path, and any of its sub-paths in ' .'one configuration section.', $this->getPath() )); } $this->validateType($leftSide); $this->validateType($rightSide); return $this->mergeValues($leftSide, $rightSide); } /** * Normalizes a value, applying all normalization closures. * * @param mixed $value Value to normalize. * * @return mixed The normalized value. */ final public function normalize($value) { $value = $this->preNormalize($value); // run custom normalization closures foreach ($this->normalizationClosures as $closure) { $value = $closure($value); } // replace value with their equivalent foreach ($this->equivalentValues as $data) { if ($data[0] === $value) { $value = $data[1]; } } // validate type $this->validateType($value); // normalize value return $this->normalizeValue($value); } /** * Normalizes the value before any other normalization is applied. * * @param $value * * @return $value The normalized array value */ protected function preNormalize($value) { return $value; } /** * Returns parent node for this node. * * @return NodeInterface|null */ public function getParent() { return $this->parent; } /** * Finalizes a value, applying all finalization closures. * * @param mixed $value The value to finalize * * @return mixed The finalized value * * @throws InvalidConfigurationException */ final public function finalize($value) { $this->validateType($value); $value = $this->finalizeValue($value); // Perform validation on the final value if a closure has been set. // The closure is also allowed to return another value. foreach ($this->finalValidationClosures as $closure) { try { $value = $closure($value); } catch (Exception $correctEx) { throw $correctEx; } catch (\Exception $invalid) { throw new InvalidConfigurationException(sprintf( 'Invalid configuration for path "%s": %s', $this->getPath(), $invalid->getMessage() ), $invalid->getCode(), $invalid); } } return $value; } /** * Validates the type of a Node. * * @param mixed $value The value to validate * * @throws InvalidTypeException when the value is invalid */ abstract protected function validateType($value); /** * Normalizes the value. * * @param mixed $value The value to normalize. * * @return mixed The normalized value */ abstract protected function normalizeValue($value); /** * Merges two values together. * * @param mixed $leftSide * @param mixed $rightSide * * @return mixed The merged value */ abstract protected function mergeValues($leftSide, $rightSide); /** * Finalizes a value. * * @param mixed $value The value to finalize * * @return mixed The finalized value */ abstract protected function finalizeValue($value); } PK!0007Symfony/Component/Config/Definition/ReferenceDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper; /** * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper instead. */ class ReferenceDumper extends YamlReferenceDumper { } PK!`PP'Symfony/Component/Config/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Resource; /** * ResourceInterface is the interface that must be implemented by all Resource classes. * * @author Fabien Potencier */ interface ResourceInterface { /** * Returns a string representation of the Resource. * * @return string A string representation of the Resource */ public function __toString(); /** * Returns true if the resource has not been updated since the given timestamp. * * @param integer $timestamp The last time the resource was loaded * * @return Boolean true if the resource has not been updated, false otherwise */ public function isFresh($timestamp); /** * Returns the resource tied to this Resource. * * @return mixed The resource */ public function getResource(); } PK!T!!2Symfony/Component/Config/Resource/FileResource.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Resource; /** * FileResource represents a resource stored on the filesystem. * * The resource can be a file or a directory. * * @author Fabien Potencier */ class FileResource implements ResourceInterface, \Serializable { private $resource; /** * Constructor. * * @param string $resource The file path to the resource */ public function __construct($resource) { $this->resource = realpath($resource); } /** * Returns a string representation of the Resource. * * @return string A string representation of the Resource */ public function __toString() { return (string) $this->resource; } /** * Returns the resource tied to this Resource. * * @return mixed The resource */ public function getResource() { return $this->resource; } /** * Returns true if the resource has not been updated since the given timestamp. * * @param integer $timestamp The last time the resource was loaded * * @return Boolean true if the resource has not been updated, false otherwise */ public function isFresh($timestamp) { if (!file_exists($this->resource)) { return false; } return filemtime($this->resource) < $timestamp; } public function serialize() { return serialize($this->resource); } public function unserialize($serialized) { $this->resource = unserialize($serialized); } } PK! # 7Symfony/Component/Config/Resource/DirectoryResource.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Resource; /** * DirectoryResource represents a resources stored in a subdirectory tree. * * @author Fabien Potencier */ class DirectoryResource implements ResourceInterface, \Serializable { private $resource; private $pattern; /** * Constructor. * * @param string $resource The file path to the resource * @param string $pattern A pattern to restrict monitored files */ public function __construct($resource, $pattern = null) { $this->resource = $resource; $this->pattern = $pattern; } /** * Returns a string representation of the Resource. * * @return string A string representation of the Resource */ public function __toString() { return (string) $this->resource; } /** * Returns the resource tied to this Resource. * * @return mixed The resource */ public function getResource() { return $this->resource; } public function getPattern() { return $this->pattern; } /** * Returns true if the resource has not been updated since the given timestamp. * * @param integer $timestamp The last time the resource was loaded * * @return Boolean true if the resource has not been updated, false otherwise */ public function isFresh($timestamp) { if (!is_dir($this->resource)) { return false; } $newestMTime = filemtime($this->resource); foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) { // if regex filtering is enabled only check matching files if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) { continue; } // always monitor directories for changes, except the .. entries // (otherwise deleted files wouldn't get detected) if ($file->isDir() && '/..' === substr($file, -3)) { continue; } $newestMTime = max($file->getMTime(), $newestMTime); } return $newestMTime < $timestamp; } public function serialize() { return serialize(array($this->resource, $this->pattern)); } public function unserialize($serialized) { list($this->resource, $this->pattern) = unserialize($serialized); } } PK!C3kll1Symfony/Component/Config/FileLocatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config; /** * @author Fabien Potencier */ interface FileLocatorInterface { /** * Returns a full path for a given file name. * * @param mixed $name The file name to locate * @param string $currentPath The current path * @param Boolean $first Whether to return the first occurrence or an array of filenames * * @return string|array The full path to the file|An array of file paths * * @throws \InvalidArgumentException When file is not found */ public function locate($name, $currentPath = null, $first = true); } PK!7 TTQSymfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Exception; /** * Exception class for when a circular reference is detected when importing resources. * * @author Fabien Potencier */ class FileLoaderImportCircularReferenceException extends FileLoaderLoadException { public function __construct(array $resources, $code = null, $previous = null) { $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]); call_user_func('Exception::__construct', $message, $code, $previous); } } PK!W >Symfony/Component/Config/Exception/FileLoaderLoadException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Exception; /** * Exception class for when a resource cannot be loaded or imported. * * @author Ryan Weaver */ class FileLoaderLoadException extends \Exception { /** * @param string $resource The resource that could not be imported * @param string $sourceResource The original resource importing the new resource * @param integer $code The error code * @param \Exception $previous A previous exception */ public function __construct($resource, $sourceResource = null, $code = null, $previous = null) { if (null === $sourceResource) { $message = sprintf('Cannot load resource "%s".', $this->varToString($resource)); } else { $message = sprintf('Cannot import resource "%s" from "%s".', $this->varToString($resource), $this->varToString($sourceResource)); } // Is the resource located inside a bundle? if ('@' === $resource[0]) { $parts = explode(DIRECTORY_SEPARATOR, $resource); $bundle = substr($parts[0], 1); $message .= ' '.sprintf('Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle); } elseif ($previous) { // include the previous exception, to help the user see what might be the underlying cause $message .= ' '.sprintf('(%s)', $previous->getMessage()); } parent::__construct($message, $code, $previous); } protected function varToString($var) { if (is_object($var)) { return sprintf('Object(%s)', get_class($var)); } if (is_array($var)) { $a = array(); foreach ($var as $k => $v) { $a[] = sprintf('%s => %s', $k, $this->varToString($v)); } return sprintf("Array(%s)", implode(', ', $a)); } if (is_resource($var)) { return sprintf('Resource(%s)', get_resource_type($var)); } if (null === $var) { return 'null'; } if (false === $var) { return 'false'; } if (true === $var) { return 'true'; } return (string) $var; } } PK!k*Symfony/Component/Config/Util/XmlUtils.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Util; /** * XMLUtils is a bunch of utility methods to XML operations. * * This class contains static methods only and is not meant to be instantiated. * * @author Fabien Potencier * @author Martin Hasoň */ class XmlUtils { /** * This class should not be instantiated */ private function __construct() { } /** * Loads an XML file. * * @param string $file An XML file path * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation * * @return \DOMDocument * * @throws \InvalidArgumentException When loading of XML file returns error */ public static function loadFile($file, $schemaOrCallable = null) { $content = @file_get_contents($file); if ('' === trim($content)) { throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file)); } $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); libxml_clear_errors(); $dom = new \DOMDocument(); $dom->validateOnParse = true; if (!$dom->loadXML($content, LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) { libxml_disable_entity_loader($disableEntities); throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors))); } $dom->normalizeDocument(); libxml_use_internal_errors($internalErrors); libxml_disable_entity_loader($disableEntities); foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { throw new \InvalidArgumentException('Document types are not allowed.'); } } if (null !== $schemaOrCallable) { $internalErrors = libxml_use_internal_errors(true); libxml_clear_errors(); $e = null; if (is_callable($schemaOrCallable)) { try { $valid = call_user_func($schemaOrCallable, $dom, $internalErrors); } catch (\Exception $e) { $valid = false; } } elseif (!is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) { $valid = @$dom->schemaValidate($schemaOrCallable); } else { libxml_use_internal_errors($internalErrors); throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.'); } if (!$valid) { $messages = static::getXmlErrors($internalErrors); if (empty($messages)) { $messages = array(sprintf('The XML file "%s" is not valid.', $file)); } throw new \InvalidArgumentException(implode("\n", $messages), 0, $e); } libxml_use_internal_errors($internalErrors); } return $dom; } /** * Converts a \DomElement object to a PHP array. * * The following rules applies during the conversion: * * * Each tag is converted to a key value or an array * if there is more than one "value" * * * The content of a tag is set under a "value" key (bar) * if the tag also has some nested tags * * * The attributes are converted to keys () * * * The nested-tags are converted to keys (bar) * * @param \DomElement $element A \DomElement instance * @param Boolean $checkPrefix Check prefix in an element or an attribute name * * @return array A PHP array */ public static function convertDomElementToArray(\DomElement $element, $checkPrefix = true) { $prefix = (string) $element->prefix; $empty = true; $config = array(); foreach ($element->attributes as $name => $node) { if ($checkPrefix && !in_array((string) $node->prefix, array('', $prefix), true)) { continue; } $config[$name] = static::phpize($node->value); $empty = false; } $nodeValue = false; foreach ($element->childNodes as $node) { if ($node instanceof \DOMText) { if ('' !== trim($node->nodeValue)) { $nodeValue = trim($node->nodeValue); $empty = false; } } elseif ($checkPrefix && $prefix != (string) $node->prefix) { continue; } elseif (!$node instanceof \DOMComment) { $value = static::convertDomElementToArray($node, $checkPrefix); $key = $node->localName; if (isset($config[$key])) { if (!is_array($config[$key]) || !is_int(key($config[$key]))) { $config[$key] = array($config[$key]); } $config[$key][] = $value; } else { $config[$key] = $value; } $empty = false; } } if (false !== $nodeValue) { $value = static::phpize($nodeValue); if (count($config)) { $config['value'] = $value; } else { $config = $value; } } return !$empty ? $config : null; } /** * Converts an xml value to a PHP type. * * @param mixed $value * * @return mixed */ public static function phpize($value) { $value = (string) $value; $lowercaseValue = strtolower($value); switch (true) { case 'null' === $lowercaseValue: return null; case ctype_digit($value): $raw = $value; $cast = intval($value); return '0' == $value[0] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw); case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)): $raw = $value; $cast = intval($value); return '0' == $value[1] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw); case 'true' === $lowercaseValue: return true; case 'false' === $lowercaseValue: return false; case isset($value[1]) && '0b' == $value[0].$value[1]: return bindec($value); case is_numeric($value): return '0x' == $value[0].$value[1] ? hexdec($value) : floatval($value); case preg_match('/^(-|\+)?[0-9]+(\.[0-9]+)?$/', $value): return floatval($value); default: return $value; } } protected static function getXmlErrors($internalErrors) { $errors = array(); foreach (libxml_get_errors() as $error) { $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', $error->code, trim($error->message), $error->file ? $error->file : 'n/a', $error->line, $error->column ); } libxml_clear_errors(); libxml_use_internal_errors($internalErrors); return $errors; } } PK!I (Symfony/Component/Config/FileLocator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config; /** * FileLocator uses an array of pre-defined paths to find files. * * @author Fabien Potencier */ class FileLocator implements FileLocatorInterface { protected $paths; /** * Constructor. * * @param string|array $paths A path or an array of paths where to look for resources */ public function __construct($paths = array()) { $this->paths = (array) $paths; } /** * Returns a full path for a given file name. * * @param mixed $name The file name to locate * @param string $currentPath The current path * @param Boolean $first Whether to return the first occurrence or an array of filenames * * @return string|array The full path to the file|An array of file paths * * @throws \InvalidArgumentException When file is not found */ public function locate($name, $currentPath = null, $first = true) { if ($this->isAbsolutePath($name)) { if (!file_exists($name)) { throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $name)); } return $name; } $filepaths = array(); if (null !== $currentPath && file_exists($file = $currentPath.DIRECTORY_SEPARATOR.$name)) { if (true === $first) { return $file; } $filepaths[] = $file; } foreach ($this->paths as $path) { if (file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) { if (true === $first) { return $file; } $filepaths[] = $file; } } if (!$filepaths) { throw new \InvalidArgumentException(sprintf('The file "%s" does not exist (in: %s%s).', $name, null !== $currentPath ? $currentPath.', ' : '', implode(', ', $this->paths))); } return array_values(array_unique($filepaths)); } /** * Returns whether the file path is an absolute path. * * @param string $file A file path * * @return Boolean */ private function isAbsolutePath($file) { if ($file[0] == '/' || $file[0] == '\\' || (strlen($file) > 3 && ctype_alpha($file[0]) && $file[1] == ':' && ($file[2] == '\\' || $file[2] == '/') ) || null !== parse_url($file, PHP_URL_SCHEME) ) { return true; } return false; } } PK!__wP< < .Symfony/Component/Config/Loader/FileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; use Symfony\Component\Config\FileLocatorInterface; use Symfony\Component\Config\Exception\FileLoaderLoadException; use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException; /** * FileLoader is the abstract class used by all built-in loaders that are file based. * * @author Fabien Potencier */ abstract class FileLoader extends Loader { protected static $loading = array(); protected $locator; private $currentDir; /** * Constructor. * * @param FileLocatorInterface $locator A FileLocatorInterface instance */ public function __construct(FileLocatorInterface $locator) { $this->locator = $locator; } public function setCurrentDir($dir) { $this->currentDir = $dir; } public function getLocator() { return $this->locator; } /** * Imports a resource. * * @param mixed $resource A Resource * @param string $type The resource type * @param Boolean $ignoreErrors Whether to ignore import errors or not * @param string $sourceResource The original resource importing the new resource * * @return mixed * * @throws FileLoaderLoadException * @throws FileLoaderImportCircularReferenceException */ public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null) { try { $loader = $this->resolve($resource, $type); if ($loader instanceof FileLoader && null !== $this->currentDir) { // we fallback to the current locator to keep BC // as some some loaders do not call the parent __construct() // @deprecated should be removed in 3.0 $locator = $loader->getLocator() ?: $this->locator; $resource = $locator->locate($resource, $this->currentDir, false); } $resources = is_array($resource) ? $resource : array($resource); for ($i = 0; $i < $resourcesCount = count($resources); $i++ ) { if (isset(self::$loading[$resources[$i]])) { if ($i == $resourcesCount-1) { throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading)); } } else { $resource = $resources[$i]; break; } } self::$loading[$resource] = true; $ret = $loader->load($resource, $type); unset(self::$loading[$resource]); return $ret; } catch (FileLoaderImportCircularReferenceException $e) { throw $e; } catch (\Exception $e) { if (!$ignoreErrors) { // prevent embedded imports from nesting multiple exceptions if ($e instanceof FileLoaderLoadException) { throw $e; } throw new FileLoaderLoadException($resource, $sourceResource, null, $e); } } } } PK!))4Symfony/Component/Config/Loader/DelegatingLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; use Symfony\Component\Config\Exception\FileLoaderLoadException; /** * DelegatingLoader delegates loading to other loaders using a loader resolver. * * This loader acts as an array of LoaderInterface objects - each having * a chance to load a given resource (handled by the resolver) * * @author Fabien Potencier */ class DelegatingLoader extends Loader { /** * Constructor. * * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance */ public function __construct(LoaderResolverInterface $resolver) { $this->resolver = $resolver; } /** * Loads a resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return mixed * * @throws FileLoaderLoadException if no loader is found. */ public function load($resource, $type = null) { if (false === $loader = $this->resolver->resolve($resource, $type)) { throw new FileLoaderLoadException($resource); } return $loader->load($resource, $type); } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return false !== $this->resolver->resolve($resource, $type); } } PK!;Symfony/Component/Config/Loader/LoaderResolverInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; /** * LoaderResolverInterface selects a loader for a given resource. * * @author Fabien Potencier */ interface LoaderResolverInterface { /** * Returns a loader able to load the resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return LoaderInterface A LoaderInterface instance */ public function resolve($resource, $type = null); } PK!HPʉ2Symfony/Component/Config/Loader/LoaderResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; /** * LoaderResolver selects a loader for a given resource. * * A resource can be anything (e.g. a full path to a config file or a Closure). * Each loader determines whether it can load a resource and how. * * @author Fabien Potencier */ class LoaderResolver implements LoaderResolverInterface { /** * @var LoaderInterface[] An array of LoaderInterface objects */ private $loaders = array(); /** * Constructor. * * @param LoaderInterface[] $loaders An array of loaders */ public function __construct(array $loaders = array()) { foreach ($loaders as $loader) { $this->addLoader($loader); } } /** * Returns a loader able to load the resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return LoaderInterface|false A LoaderInterface instance */ public function resolve($resource, $type = null) { foreach ($this->loaders as $loader) { if ($loader->supports($resource, $type)) { return $loader; } } return false; } /** * Adds a loader. * * @param LoaderInterface $loader A LoaderInterface instance */ public function addLoader(LoaderInterface $loader) { $this->loaders[] = $loader; $loader->setResolver($this); } /** * Returns the registered loaders. * * @return LoaderInterface[] An array of LoaderInterface instances */ public function getLoaders() { return $this->loaders; } } PK!=*Symfony/Component/Config/Loader/Loader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; use Symfony\Component\Config\Exception\FileLoaderLoadException; /** * Loader is the abstract class used by all built-in loaders. * * @author Fabien Potencier */ abstract class Loader implements LoaderInterface { protected $resolver; /** * Gets the loader resolver. * * @return LoaderResolverInterface A LoaderResolverInterface instance */ public function getResolver() { return $this->resolver; } /** * Sets the loader resolver. * * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance */ public function setResolver(LoaderResolverInterface $resolver) { $this->resolver = $resolver; } /** * Imports a resource. * * @param mixed $resource A Resource * @param string $type The resource type * * @return mixed */ public function import($resource, $type = null) { return $this->resolve($resource, $type)->load($resource, $type); } /** * Finds a loader able to load an imported resource. * * @param mixed $resource A Resource * @param string $type The resource type * * @return LoaderInterface A LoaderInterface instance * * @throws FileLoaderLoadException if no loader is found */ public function resolve($resource, $type = null) { if ($this->supports($resource, $type)) { return $this; } $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type); if (false === $loader) { throw new FileLoaderLoadException($resource); } return $loader; } } PK!4993Symfony/Component/Config/Loader/LoaderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; /** * LoaderInterface is the interface implemented by all loader classes. * * @author Fabien Potencier */ interface LoaderInterface { /** * Loads a resource. * * @param mixed $resource The resource * @param string $type The resource type */ public function load($resource, $type = null); /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null); /** * Gets the loader resolver. * * @return LoaderResolverInterface A LoaderResolverInterface instance */ public function getResolver(); /** * Sets the loader resolver. * * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance */ public function setResolver(LoaderResolverInterface $resolver); } PK!:a (Symfony/Component/Config/ConfigCache.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Filesystem\Filesystem; /** * ConfigCache manages PHP cache files. * * When debug is enabled, it knows when to flush the cache * thanks to an array of ResourceInterface instances. * * @author Fabien Potencier */ class ConfigCache { private $debug; private $file; /** * Constructor. * * @param string $file The absolute cache path * @param Boolean $debug Whether debugging is enabled or not */ public function __construct($file, $debug) { $this->file = $file; $this->debug = (Boolean) $debug; } /** * Gets the cache file path. * * @return string The cache file path */ public function __toString() { return $this->file; } /** * Checks if the cache is still fresh. * * This method always returns true when debug is off and the * cache file exists. * * @return Boolean true if the cache is fresh, false otherwise */ public function isFresh() { if (!is_file($this->file)) { return false; } if (!$this->debug) { return true; } $metadata = $this->getMetaFile(); if (!is_file($metadata)) { return false; } $time = filemtime($this->file); $meta = unserialize(file_get_contents($metadata)); foreach ($meta as $resource) { if (!$resource->isFresh($time)) { return false; } } return true; } /** * Writes cache. * * @param string $content The content to write in the cache * @param ResourceInterface[] $metadata An array of ResourceInterface instances * * @throws \RuntimeException When cache file can't be wrote */ public function write($content, array $metadata = null) { $mode = 0666 & ~umask(); $filesystem = new Filesystem(); $filesystem->dumpFile($this->file, $content, null); @chmod($this->file, $mode); if (null !== $metadata && true === $this->debug) { $filesystem->dumpFile($this->getMetaFile(), serialize($metadata), null); @chmod($this->getMetaFile(), $mode); } } /** * Gets the meta file path. * * @return string The meta file path */ private function getMetaFile() { return $this->file.'.meta'; } } PK!\[0Symfony/Component/HttpKernel/KernelInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\Config\Loader\LoaderInterface; /** * The Kernel is the heart of the Symfony system. * * It manages an environment made of bundles. * * @author Fabien Potencier * * @api */ interface KernelInterface extends HttpKernelInterface, \Serializable { /** * Returns an array of bundles to register. * * @return BundleInterface[] An array of bundle instances. * * @api */ public function registerBundles(); /** * Loads the container configuration. * * @param LoaderInterface $loader A LoaderInterface instance * * @api */ public function registerContainerConfiguration(LoaderInterface $loader); /** * Boots the current kernel. * * @api */ public function boot(); /** * Shutdowns the kernel. * * This method is mainly useful when doing functional testing. * * @api */ public function shutdown(); /** * Gets the registered bundle instances. * * @return BundleInterface[] An array of registered bundle instances * * @api */ public function getBundles(); /** * Checks if a given class name belongs to an active bundle. * * @param string $class A class name * * @return Boolean true if the class belongs to an active bundle, false otherwise * * @api */ public function isClassInActiveBundle($class); /** * Returns a bundle and optionally its descendants by its name. * * @param string $name Bundle name * @param Boolean $first Whether to return the first bundle only or together with its descendants * * @return BundleInterface|BundleInterface[] A BundleInterface instance or an array of BundleInterface instances if $first is false * * @throws \InvalidArgumentException when the bundle is not enabled * * @api */ public function getBundle($name, $first = true); /** * Returns the file path for a given resource. * * A Resource can be a file or a directory. * * The resource name must follow the following pattern: * * @BundleName/path/to/a/file.something * * where BundleName is the name of the bundle * and the remaining part is the relative path in the bundle. * * If $dir is passed, and the first segment of the path is Resources, * this method will look for a file named: * * $dir/BundleName/path/without/Resources * * @param string $name A resource name to locate * @param string $dir A directory where to look for the resource first * @param Boolean $first Whether to return the first path or paths for all matching bundles * * @return string|array The absolute path of the resource or an array if $first is false * * @throws \InvalidArgumentException if the file cannot be found or the name is not valid * @throws \RuntimeException if the name contains invalid/unsafe characters * * @api */ public function locateResource($name, $dir = null, $first = true); /** * Gets the name of the kernel. * * @return string The kernel name * * @api */ public function getName(); /** * Gets the environment. * * @return string The current environment * * @api */ public function getEnvironment(); /** * Checks if debug mode is enabled. * * @return Boolean true if debug mode is enabled, false otherwise * * @api */ public function isDebug(); /** * Gets the application root dir. * * @return string The application root dir * * @api */ public function getRootDir(); /** * Gets the current container. * * @return ContainerInterface A ContainerInterface instance * * @api */ public function getContainer(); /** * Gets the request start time (not available if debug is disabled). * * @return integer The request start timestamp * * @api */ public function getStartTime(); /** * Gets the cache directory. * * @return string The cache directory * * @api */ public function getCacheDir(); /** * Gets the log directory. * * @return string The log directory * * @api */ public function getLogDir(); /** * Gets the charset of the application. * * @return string The charset * * @api */ public function getCharset(); } PK!?.\\'Symfony/Component/HttpKernel/Kernel.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\Loader\IniFileLoader; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass; use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\Loader\DelegatingLoader; use Symfony\Component\Config\ConfigCache; use Symfony\Component\ClassLoader\ClassCollectionLoader; /** * The Kernel is the heart of the Symfony system. * * It manages an environment made of bundles. * * @author Fabien Potencier * * @api */ abstract class Kernel implements KernelInterface, TerminableInterface { /** * @var BundleInterface[] */ protected $bundles = array(); protected $bundleMap; protected $container; protected $rootDir; protected $environment; protected $debug; protected $booted = false; protected $name; protected $startTime; protected $loadClassCache; const VERSION = '2.4.3'; const VERSION_ID = '20403'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '4'; const RELEASE_VERSION = '3'; const EXTRA_VERSION = ''; /** * Constructor. * * @param string $environment The environment * @param Boolean $debug Whether to enable debugging or not * * @api */ public function __construct($environment, $debug) { $this->environment = $environment; $this->debug = (Boolean) $debug; $this->rootDir = $this->getRootDir(); $this->name = $this->getName(); if ($this->debug) { $this->startTime = microtime(true); } $this->init(); } /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Move your logic in the constructor instead. */ public function init() { } public function __clone() { if ($this->debug) { $this->startTime = microtime(true); } $this->booted = false; $this->container = null; } /** * Boots the current kernel. * * @api */ public function boot() { if (true === $this->booted) { return; } if ($this->loadClassCache) { $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]); } // init bundles $this->initializeBundles(); // init container $this->initializeContainer(); foreach ($this->getBundles() as $bundle) { $bundle->setContainer($this->container); $bundle->boot(); } $this->booted = true; } /** * {@inheritdoc} * * @api */ public function terminate(Request $request, Response $response) { if (false === $this->booted) { return; } if ($this->getHttpKernel() instanceof TerminableInterface) { $this->getHttpKernel()->terminate($request, $response); } } /** * {@inheritdoc} * * @api */ public function shutdown() { if (false === $this->booted) { return; } $this->booted = false; foreach ($this->getBundles() as $bundle) { $bundle->shutdown(); $bundle->setContainer(null); } $this->container = null; } /** * {@inheritdoc} * * @api */ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { if (false === $this->booted) { $this->boot(); } return $this->getHttpKernel()->handle($request, $type, $catch); } /** * Gets a HTTP kernel from the container * * @return HttpKernel */ protected function getHttpKernel() { return $this->container->get('http_kernel'); } /** * {@inheritdoc} * * @api */ public function getBundles() { return $this->bundles; } /** * {@inheritdoc} * * @api */ public function isClassInActiveBundle($class) { foreach ($this->getBundles() as $bundle) { if (0 === strpos($class, $bundle->getNamespace())) { return true; } } return false; } /** * {@inheritdoc} * * @api */ public function getBundle($name, $first = true) { if (!isset($this->bundleMap[$name])) { throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, get_class($this))); } if (true === $first) { return $this->bundleMap[$name][0]; } return $this->bundleMap[$name]; } /** * Returns the file path for a given resource. * * A Resource can be a file or a directory. * * The resource name must follow the following pattern: * * @/path/to/a/file.something * * where BundleName is the name of the bundle * and the remaining part is the relative path in the bundle. * * If $dir is passed, and the first segment of the path is "Resources", * this method will look for a file named: * * $dir//path/without/Resources * * before looking in the bundle resource folder. * * @param string $name A resource name to locate * @param string $dir A directory where to look for the resource first * @param Boolean $first Whether to return the first path or paths for all matching bundles * * @return string|array The absolute path of the resource or an array if $first is false * * @throws \InvalidArgumentException if the file cannot be found or the name is not valid * @throws \RuntimeException if the name contains invalid/unsafe * @throws \RuntimeException if a custom resource is hidden by a resource in a derived bundle * * @api */ public function locateResource($name, $dir = null, $first = true) { if ('@' !== $name[0]) { throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name)); } if (false !== strpos($name, '..')) { throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name)); } $bundleName = substr($name, 1); $path = ''; if (false !== strpos($bundleName, '/')) { list($bundleName, $path) = explode('/', $bundleName, 2); } $isResource = 0 === strpos($path, 'Resources') && null !== $dir; $overridePath = substr($path, 9); $resourceBundle = null; $bundles = $this->getBundle($bundleName, false); $files = array(); foreach ($bundles as $bundle) { if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) { if (null !== $resourceBundle) { throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.', $file, $resourceBundle, $dir.'/'.$bundles[0]->getName().$overridePath )); } if ($first) { return $file; } $files[] = $file; } if (file_exists($file = $bundle->getPath().'/'.$path)) { if ($first && !$isResource) { return $file; } $files[] = $file; $resourceBundle = $bundle->getName(); } } if (count($files) > 0) { return $first && $isResource ? $files[0] : $files; } throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name)); } /** * {@inheritdoc} * * @api */ public function getName() { if (null === $this->name) { $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir)); } return $this->name; } /** * {@inheritdoc} * * @api */ public function getEnvironment() { return $this->environment; } /** * {@inheritdoc} * * @api */ public function isDebug() { return $this->debug; } /** * {@inheritdoc} * * @api */ public function getRootDir() { if (null === $this->rootDir) { $r = new \ReflectionObject($this); $this->rootDir = str_replace('\\', '/', dirname($r->getFileName())); } return $this->rootDir; } /** * {@inheritdoc} * * @api */ public function getContainer() { return $this->container; } /** * Loads the PHP class cache. * * This methods only registers the fact that you want to load the cache classes. * The cache will actually only be loaded when the Kernel is booted. * * That optimization is mainly useful when using the HttpCache class in which * case the class cache is not loaded if the Response is in the cache. * * @param string $name The cache name prefix * @param string $extension File extension of the resulting file */ public function loadClassCache($name = 'classes', $extension = '.php') { $this->loadClassCache = array($name, $extension); } /** * Used internally. */ public function setClassCache(array $classes) { file_put_contents($this->getCacheDir().'/classes.map', sprintf('debug ? $this->startTime : -INF; } /** * {@inheritdoc} * * @api */ public function getCacheDir() { return $this->rootDir.'/cache/'.$this->environment; } /** * {@inheritdoc} * * @api */ public function getLogDir() { return $this->rootDir.'/logs'; } /** * {@inheritdoc} * * @api */ public function getCharset() { return 'UTF-8'; } protected function doLoadClassCache($name, $extension) { if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) { ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension); } } /** * Initializes the data structures related to the bundle management. * * - the bundles property maps a bundle name to the bundle instance, * - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first). * * @throws \LogicException if two bundles share a common name * @throws \LogicException if a bundle tries to extend a non-registered bundle * @throws \LogicException if a bundle tries to extend itself * @throws \LogicException if two bundles extend the same ancestor */ protected function initializeBundles() { // init bundles $this->bundles = array(); $topMostBundles = array(); $directChildren = array(); foreach ($this->registerBundles() as $bundle) { $name = $bundle->getName(); if (isset($this->bundles[$name])) { throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name)); } $this->bundles[$name] = $bundle; if ($parentName = $bundle->getParent()) { if (isset($directChildren[$parentName])) { throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName])); } if ($parentName == $name) { throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name)); } $directChildren[$parentName] = $name; } else { $topMostBundles[$name] = $bundle; } } // look for orphans if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) { $diff = array_keys($diff); throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0])); } // inheritance $this->bundleMap = array(); foreach ($topMostBundles as $name => $bundle) { $bundleMap = array($bundle); $hierarchy = array($name); while (isset($directChildren[$name])) { $name = $directChildren[$name]; array_unshift($bundleMap, $this->bundles[$name]); $hierarchy[] = $name; } foreach ($hierarchy as $bundle) { $this->bundleMap[$bundle] = $bundleMap; array_pop($bundleMap); } } } /** * Gets the container class. * * @return string The container class */ protected function getContainerClass() { return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer'; } /** * Gets the container's base class. * * All names except Container must be fully qualified. * * @return string */ protected function getContainerBaseClass() { return 'Container'; } /** * Initializes the service container. * * The cached version of the service container is used when fresh, otherwise the * container is built. */ protected function initializeContainer() { $class = $this->getContainerClass(); $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug); $fresh = true; if (!$cache->isFresh()) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); $fresh = false; } require_once $cache; $this->container = new $class(); $this->container->set('kernel', $this); if (!$fresh && $this->container->has('cache_warmer')) { $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); } } /** * Returns the kernel parameters. * * @return array An array of kernel parameters */ protected function getKernelParameters() { $bundles = array(); foreach ($this->bundles as $name => $bundle) { $bundles[$name] = get_class($bundle); } return array_merge( array( 'kernel.root_dir' => $this->rootDir, 'kernel.environment' => $this->environment, 'kernel.debug' => $this->debug, 'kernel.name' => $this->name, 'kernel.cache_dir' => $this->getCacheDir(), 'kernel.logs_dir' => $this->getLogDir(), 'kernel.bundles' => $bundles, 'kernel.charset' => $this->getCharset(), 'kernel.container_class' => $this->getContainerClass(), ), $this->getEnvParameters() ); } /** * Gets the environment parameters. * * Only the parameters starting with "SYMFONY__" are considered. * * @return array An array of parameters */ protected function getEnvParameters() { $parameters = array(); foreach ($_SERVER as $key => $value) { if (0 === strpos($key, 'SYMFONY__')) { $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value; } } return $parameters; } /** * Builds the service container. * * @return ContainerBuilder The compiled service container * * @throws \RuntimeException */ protected function buildContainer() { foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) { if (!is_dir($dir)) { if (false === @mkdir($dir, 0777, true)) { throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir)); } } elseif (!is_writable($dir)) { throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir)); } } $container = $this->getContainerBuilder(); $container->addObjectResource($this); $this->prepareContainer($container); if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) { $container->merge($cont); } $container->addCompilerPass(new AddClassesToCachePass($this)); return $container; } /** * Prepares the ContainerBuilder before it is compiled. * * @param ContainerBuilder $container A ContainerBuilder instance */ protected function prepareContainer(ContainerBuilder $container) { $extensions = array(); foreach ($this->bundles as $bundle) { if ($extension = $bundle->getContainerExtension()) { $container->registerExtension($extension); $extensions[] = $extension->getAlias(); } if ($this->debug) { $container->addObjectResource($bundle); } } foreach ($this->bundles as $bundle) { $bundle->build($container); } // ensure these extensions are implicitly loaded $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); } /** * Gets a new ContainerBuilder instance used to build the service container. * * @return ContainerBuilder */ protected function getContainerBuilder() { $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters())); if (class_exists('ProxyManager\Configuration')) { $container->setProxyInstantiator(new RuntimeInstantiator()); } return $container; } /** * Dumps the service container to PHP code in the cache. * * @param ConfigCache $cache The config cache * @param ContainerBuilder $container The service container * @param string $class The name of the class to generate * @param string $baseClass The name of the container's base class */ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass) { // cache the container $dumper = new PhpDumper($container); if (class_exists('ProxyManager\Configuration')) { $dumper->setProxyDumper(new ProxyDumper()); } $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass)); if (!$this->debug) { $content = static::stripComments($content); } $cache->write($content, $container->getResources()); } /** * Returns a loader for the container. * * @param ContainerInterface $container The service container * * @return DelegatingLoader The loader */ protected function getContainerLoader(ContainerInterface $container) { $locator = new FileLocator($this); $resolver = new LoaderResolver(array( new XmlFileLoader($container, $locator), new YamlFileLoader($container, $locator), new IniFileLoader($container, $locator), new PhpFileLoader($container, $locator), new ClosureLoader($container), )); return new DelegatingLoader($resolver); } /** * Removes comments from a PHP source string. * * We don't use the PHP php_strip_whitespace() function * as we want the content to be readable and well-formatted. * * @param string $source A PHP string * * @return string The PHP string with the comments removed */ public static function stripComments($source) { if (!function_exists('token_get_all')) { return $source; } $rawChunk = ''; $output = ''; $tokens = token_get_all($source); $ignoreSpace = false; for (reset($tokens); false !== $token = current($tokens); next($tokens)) { if (is_string($token)) { $rawChunk .= $token; } elseif (T_START_HEREDOC === $token[0]) { $output .= $rawChunk.$token[1]; do { $token = next($tokens); $output .= $token[1]; } while ($token[0] !== T_END_HEREDOC); $rawChunk = ''; } elseif (T_WHITESPACE === $token[0]) { if ($ignoreSpace) { $ignoreSpace = false; continue; } // replace multiple new lines with a single newline $rawChunk .= preg_replace(array('/\n{2,}/S'), "\n", $token[1]); } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) { $ignoreSpace = true; } else { $rawChunk .= $token[1]; // The PHP-open tag already has a new-line if (T_OPEN_TAG === $token[0]) { $ignoreSpace = true; } } } $output .= $rawChunk; return $output; } public function serialize() { return serialize(array($this->environment, $this->debug)); } public function unserialize($data) { list($environment, $debug) = unserialize($data); $this->__construct($environment, $debug); } } PK!?Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheClearer; /** * ChainCacheClearer. * * @author Dustin Dobervich */ class ChainCacheClearer implements CacheClearerInterface { /** * @var array $clearers */ protected $clearers; /** * Constructs a new instance of ChainCacheClearer. * * @param array $clearers The initial clearers. */ public function __construct(array $clearers = array()) { $this->clearers = $clearers; } /** * {@inheritDoc} */ public function clear($cacheDir) { foreach ($this->clearers as $clearer) { $clearer->clear($cacheDir); } } /** * Adds a cache clearer to the aggregate. * * @param CacheClearerInterface $clearer */ public function add(CacheClearerInterface $clearer) { $this->clearers[] = $clearer; } } PK!Yxځ55CSymfony/Component/HttpKernel/CacheClearer/CacheClearerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheClearer; /** * CacheClearerInterface. * * @author Dustin Dobervich */ interface CacheClearerInterface { /** * Clears any caches necessary. * * @param string $cacheDir The cache directory. */ public function clear($cacheDir); } PK!z TT+Symfony/Component/HttpKernel/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Interface for classes able to warm up the cache. * * @author Fabien Potencier */ interface CacheWarmerInterface extends WarmableInterface { /** * Checks whether this warmer is optional or not. * * Optional warmers can be ignored on certain conditions. * * A warmer should return true if the cache can be * generated incrementally and on-demand. * * @return Boolean true if the warmer is optional, false otherwise */ public function isOptional(); } PK!^FF>Symfony/Component/HttpKernel/CacheWarmer/WarmableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Interface for classes that support warming their cache. * * @author Fabien Potencier */ interface WarmableInterface { /** * Warms up the cache. * * @param string $cacheDir The cache directory */ public function warmUp($cacheDir); } PK!8ee8Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Abstract cache warmer that knows how to write a file to the cache. * * @author Fabien Potencier */ abstract class CacheWarmer implements CacheWarmerInterface { protected function writeCacheFile($file, $content) { $tmpFile = tempnam(dirname($file), basename($file)); if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { @chmod($file, 0666 & ~umask()); return; } throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file)); } } PK!R!MMASymfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Aggregates several cache warmers into a single one. * * @author Fabien Potencier */ class CacheWarmerAggregate implements CacheWarmerInterface { protected $warmers = array(); protected $optionalsEnabled = false; public function __construct(array $warmers = array()) { foreach ($warmers as $warmer) { $this->add($warmer); } } public function enableOptionalWarmers() { $this->optionalsEnabled = true; } /** * Warms up the cache. * * @param string $cacheDir The cache directory */ public function warmUp($cacheDir) { foreach ($this->warmers as $warmer) { if (!$this->optionalsEnabled && $warmer->isOptional()) { continue; } $warmer->warmUp($cacheDir); } } /** * Checks whether this warmer is optional or not. * * @return Boolean always true */ public function isOptional() { return false; } public function setWarmers(array $warmers) { $this->warmers = array(); foreach ($warmers as $warmer) { $this->add($warmer); } } public function add(CacheWarmerInterface $warmer) { $this->warmers[] = $warmer; } } PK! KK3Symfony/Component/HttpKernel/Debug/ErrorHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Debug; use Symfony\Component\Debug\ErrorHandler as DebugErrorHandler; /** * ErrorHandler. * * @author Fabien Potencier * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead. */ class ErrorHandler extends DebugErrorHandler { } PK!97Symfony/Component/HttpKernel/Debug/ExceptionHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Debug; use Symfony\Component\Debug\ExceptionHandler as DebugExceptionHandler; /** * ExceptionHandler converts an exception to a Response object. * * @author Fabien Potencier * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead. */ class ExceptionHandler extends DebugExceptionHandler { } PK!eڮ55?Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Debug; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Profiler\Profiler; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; /** * Collects some data about event listeners. * * This event dispatcher delegates the dispatching to another one. * * @author Fabien Potencier */ class TraceableEventDispatcher implements EventDispatcherInterface, TraceableEventDispatcherInterface { private $logger; private $called = array(); private $stopwatch; private $dispatcher; private $wrappedListeners = array(); private $firstCalledEvent = array(); private $lastEventId = 0; /** * Constructor. * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param Stopwatch $stopwatch A Stopwatch instance * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) { $this->dispatcher = $dispatcher; $this->stopwatch = $stopwatch; $this->logger = $logger; } /** * Sets the profiler. * * The traceable event dispatcher does not use the profiler anymore. * The job is now done directly by the Profiler listener and the * data collectors themselves. * * @param Profiler|null $profiler A Profiler instance * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function setProfiler(Profiler $profiler = null) { } /** * {@inheritDoc} */ public function addListener($eventName, $listener, $priority = 0) { $this->dispatcher->addListener($eventName, $listener, $priority); } /** * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { $this->dispatcher->addSubscriber($subscriber); } /** * {@inheritdoc} */ public function removeListener($eventName, $listener) { return $this->dispatcher->removeListener($eventName, $listener); } /** * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { return $this->dispatcher->removeSubscriber($subscriber); } /** * {@inheritdoc} */ public function getListeners($eventName = null) { return $this->dispatcher->getListeners($eventName); } /** * {@inheritdoc} */ public function hasListeners($eventName = null) { return $this->dispatcher->hasListeners($eventName); } /** * {@inheritdoc} */ public function dispatch($eventName, Event $event = null) { if (null === $event) { $event = new Event(); } $eventId = ++$this->lastEventId; $this->preDispatch($eventName, $eventId, $event); $e = $this->stopwatch->start($eventName, 'section'); $this->firstCalledEvent[$eventName] = $this->stopwatch->start($eventName.'.loading', 'event_listener_loading'); if (!$this->dispatcher->hasListeners($eventName)) { $this->firstCalledEvent[$eventName]->stop(); } $this->dispatcher->dispatch($eventName, $event); unset($this->firstCalledEvent[$eventName]); if ($e->isStarted()) { $e->stop(); } $this->postDispatch($eventName, $eventId, $event); return $event; } /** * {@inheritDoc} */ public function getCalledListeners() { return $this->called; } /** * {@inheritDoc} */ public function getNotCalledListeners() { $notCalled = array(); foreach ($this->getListeners() as $name => $listeners) { foreach ($listeners as $listener) { $info = $this->getListenerInfo($listener, null, $name); if (!isset($this->called[$name.'.'.$info['pretty']])) { $notCalled[$name.'.'.$info['pretty']] = $info; } } } return $notCalled; } /** * Proxies all method calls to the original event dispatcher. * * @param string $method The method name * @param array $arguments The method arguments * * @return mixed */ public function __call($method, $arguments) { return call_user_func_array(array($this->dispatcher, $method), $arguments); } /** * This is a private method and must not be used. * * This method is public because it is used in a closure. * Whenever Symfony will require PHP 5.4, this could be changed * to a proper private method. */ public function logSkippedListeners($eventName, $eventId, Event $event, $listener) { if (null === $this->logger) { return; } $info = $this->getListenerInfo($listener, $eventId, $eventName); $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName)); $skippedListeners = $this->getListeners($eventName); $skipped = false; foreach ($skippedListeners as $skippedListener) { $skippedListener = $this->unwrapListener($skippedListener, $eventId); if ($skipped) { $info = $this->getListenerInfo($skippedListener, $eventId, $eventName); $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName)); } if ($skippedListener === $listener) { $skipped = true; } } } /** * This is a private method. * * This method is public because it is used in a closure. * Whenever Symfony will require PHP 5.4, this could be changed * to a proper private method. */ public function preListenerCall($eventName, $eventId, $listener) { // is it the first called listener? if (isset($this->firstCalledEvent[$eventName])) { $this->firstCalledEvent[$eventName]->stop(); unset($this->firstCalledEvent[$eventName]); } $info = $this->getListenerInfo($listener, $eventId, $eventName); if (null !== $this->logger) { $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty'])); } $this->called[$eventName.'.'.$info['pretty']] = $info; return $this->stopwatch->start(isset($info['class']) ? $info['class'] : $info['type'], 'event_listener'); } /** * Returns information about the listener * * @param object $listener The listener * @param string $eventName The event name * * @return array Information about the listener */ private function getListenerInfo($listener, $eventId, $eventName) { $listener = $this->unwrapListener($listener, $eventId); $info = array( 'event' => $eventName, ); if ($listener instanceof \Closure) { $info += array( 'type' => 'Closure', 'pretty' => 'closure' ); } elseif (is_string($listener)) { try { $r = new \ReflectionFunction($listener); $file = $r->getFileName(); $line = $r->getStartLine(); } catch (\ReflectionException $e) { $file = null; $line = null; } $info += array( 'type' => 'Function', 'function' => $listener, 'file' => $file, 'line' => $line, 'pretty' => $listener, ); } elseif (is_array($listener) || (is_object($listener) && is_callable($listener))) { if (!is_array($listener)) { $listener = array($listener, '__invoke'); } $class = is_object($listener[0]) ? get_class($listener[0]) : $listener[0]; try { $r = new \ReflectionMethod($class, $listener[1]); $file = $r->getFileName(); $line = $r->getStartLine(); } catch (\ReflectionException $e) { $file = null; $line = null; } $info += array( 'type' => 'Method', 'class' => $class, 'method' => $listener[1], 'file' => $file, 'line' => $line, 'pretty' => $class.'::'.$listener[1], ); } return $info; } private function preDispatch($eventName, $eventId, Event $event) { // wrap all listeners before they are called $this->wrappedListeners[$eventId] = new \SplObjectStorage(); $listeners = $this->dispatcher->getListeners($eventName); foreach ($listeners as $listener) { $this->dispatcher->removeListener($eventName, $listener); $wrapped = $this->wrapListener($eventName, $eventId, $listener); $this->wrappedListeners[$eventId][$wrapped] = $listener; $this->dispatcher->addListener($eventName, $wrapped); } switch ($eventName) { case KernelEvents::REQUEST: $this->stopwatch->openSection(); break; case KernelEvents::VIEW: case KernelEvents::RESPONSE: // stop only if a controller has been executed if ($this->stopwatch->isStarted('controller')) { $this->stopwatch->stop('controller'); } break; case KernelEvents::TERMINATE: $token = $event->getResponse()->headers->get('X-Debug-Token'); // There is a very special case when using builtin AppCache class as kernel wrapper, in the case // of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A]. // In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception // which must be caught. try { $this->stopwatch->openSection($token); } catch (\LogicException $e) {} break; } } private function postDispatch($eventName, $eventId, Event $event) { switch ($eventName) { case KernelEvents::CONTROLLER: $this->stopwatch->start('controller', 'section'); break; case KernelEvents::RESPONSE: $token = $event->getResponse()->headers->get('X-Debug-Token'); $this->stopwatch->stopSection($token); break; case KernelEvents::TERMINATE: // In the special case described in the `preDispatch` method above, the `$token` section // does not exist, then closing it throws an exception which must be caught. $token = $event->getResponse()->headers->get('X-Debug-Token'); try { $this->stopwatch->stopSection($token); } catch (\LogicException $e) {} break; } foreach ($this->wrappedListeners[$eventId] as $wrapped) { $this->dispatcher->removeListener($eventName, $wrapped); $this->dispatcher->addListener($eventName, $this->wrappedListeners[$eventId][$wrapped]); } unset($this->wrappedListeners[$eventId]); } private function wrapListener($eventName, $eventId, $listener) { $self = $this; return function (Event $event) use ($self, $eventName, $eventId, $listener) { $e = $self->preListenerCall($eventName, $eventId, $listener); call_user_func($listener, $event, $eventName, $self); if ($e->isStarted()) { $e->stop(); } if ($event->isPropagationStopped()) { $self->logSkippedListeners($eventName, $eventId, $event, $listener); } }; } private function unwrapListener($listener, $eventId) { // get the original listener if (is_object($listener)) { if (null === $eventId) { foreach (array_keys($this->wrappedListeners) as $eventId) { if (isset($this->wrappedListeners[$eventId][$listener])) { return $this->wrappedListeners[$eventId][$listener]; } } } elseif (isset($this->wrappedListeners[$eventId][$listener])) { return $this->wrappedListeners[$eventId][$listener]; } } return $listener; } } PK!></Symfony/Component/HttpKernel/Log/NullLogger.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Log; use Psr\Log\NullLogger as PsrNullLogger; /** * NullLogger. * * @author Fabien Potencier * * @api */ class NullLogger extends PsrNullLogger implements LoggerInterface { /** * @api * @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible. */ public function emerg($message, array $context = array()) { } /** * @api * @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible. */ public function crit($message, array $context = array()) { } /** * @api * @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible. */ public function err($message, array $context = array()) { } /** * @api * @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible. */ public function warn($message, array $context = array()) { } } PK!~[  4Symfony/Component/HttpKernel/Log/LoggerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Log; use Psr\Log\LoggerInterface as PsrLogger; /** * LoggerInterface. * * @author Fabien Potencier * * @deprecated since 2.2, to be removed in 3.0. Type-hint \Psr\Log\LoggerInterface instead. * @api */ interface LoggerInterface extends PsrLogger { /** * @api * @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible. */ public function emerg($message, array $context = array()); /** * @api * @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible. */ public function crit($message, array $context = array()); /** * @api * @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible. */ public function err($message, array $context = array()); /** * @api * @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible. */ public function warn($message, array $context = array()); } PK!J=[[9Symfony/Component/HttpKernel/Log/DebugLoggerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Log; /** * DebugLoggerInterface. * * @author Fabien Potencier */ interface DebugLoggerInterface { /** * Returns an array of logs. * * A log is an array with the following mandatory keys: * timestamp, message, priority, and priorityName. * It can also have an optional context key containing an array. * * @return array An array of logs */ public function getLogs(); /** * Returns the number of errors. * * @return integer The number of errors */ public function countErrors(); } PK!s s -Symfony/Component/HttpKernel/KernelEvents.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; /** * Contains all events thrown in the HttpKernel component * * @author Bernhard Schussek * * @api */ final class KernelEvents { /** * The REQUEST event occurs at the very beginning of request * dispatching * * This event allows you to create a response for a request before any * other code in the framework is executed. The event listener method * receives a Symfony\Component\HttpKernel\Event\GetResponseEvent * instance. * * @var string * * @api */ const REQUEST = 'kernel.request'; /** * The EXCEPTION event occurs when an uncaught exception appears * * This event allows you to create a response for a thrown exception or * to modify the thrown exception. The event listener method receives * a Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent * instance. * * @var string * * @api */ const EXCEPTION = 'kernel.exception'; /** * The VIEW event occurs when the return value of a controller * is not a Response instance * * This event allows you to create a response for the return value of the * controller. The event listener method receives a * Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent * instance. * * @var string * * @api */ const VIEW = 'kernel.view'; /** * The CONTROLLER event occurs once a controller was found for * handling a request * * This event allows you to change the controller that will handle the * request. The event listener method receives a * Symfony\Component\HttpKernel\Event\FilterControllerEvent instance. * * @var string * * @api */ const CONTROLLER = 'kernel.controller'; /** * The RESPONSE event occurs once a response was created for * replying to a request * * This event allows you to modify or replace the response that will be * replied. The event listener method receives a * Symfony\Component\HttpKernel\Event\FilterResponseEvent instance. * * @var string * * @api */ const RESPONSE = 'kernel.response'; /** * The TERMINATE event occurs once a response was sent * * This event allows you to run expensive post-response jobs. * The event listener method receives a * Symfony\Component\HttpKernel\Event\PostResponseEvent instance. * * @var string */ const TERMINATE = 'kernel.terminate'; /** * The REQUEST_FINISHED event occurs when a response was generated for a request. * * This event allows you to reset the global and environmental state of * the application, when it was changed during the request. * * @var string */ const FINISH_REQUEST = 'kernel.finish_request'; } PK!E^?Symfony/Component/HttpKernel/EventListener/ProfilerListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\PostResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Profiler\Profiler; use Symfony\Component\HttpFoundation\RequestMatcherInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * ProfilerListener collects data for the current request by listening to the onKernelResponse event. * * @author Fabien Potencier */ class ProfilerListener implements EventSubscriberInterface { protected $profiler; protected $matcher; protected $onlyException; protected $onlyMasterRequests; protected $exception; protected $requests = array(); protected $profiles; protected $requestStack; protected $parents; /** * Constructor. * * @param Profiler $profiler A Profiler instance * @param RequestMatcherInterface $matcher A RequestMatcher instance * @param Boolean $onlyException true if the profiler only collects data when an exception occurs, false otherwise * @param Boolean $onlyMasterRequests true if the profiler only collects data when the request is a master request, false otherwise */ public function __construct(Profiler $profiler, RequestMatcherInterface $matcher = null, $onlyException = false, $onlyMasterRequests = false, RequestStack $requestStack = null) { $this->profiler = $profiler; $this->matcher = $matcher; $this->onlyException = (Boolean) $onlyException; $this->onlyMasterRequests = (Boolean) $onlyMasterRequests; $this->profiles = new \SplObjectStorage(); $this->parents = new \SplObjectStorage(); $this->requestStack = $requestStack; } /** * Handles the onKernelException event. * * @param GetResponseForExceptionEvent $event A GetResponseForExceptionEvent instance */ public function onKernelException(GetResponseForExceptionEvent $event) { if ($this->onlyMasterRequests && !$event->isMasterRequest()) { return; } $this->exception = $event->getException(); } /** * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function onKernelRequest(GetResponseEvent $event) { if (null === $this->requestStack) { $this->requests[] = $event->getRequest(); } } /** * Handles the onKernelResponse event. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { $master = $event->isMasterRequest(); if ($this->onlyMasterRequests && !$master) { return; } if ($this->onlyException && null === $this->exception) { return; } $request = $event->getRequest(); $exception = $this->exception; $this->exception = null; if (null !== $this->matcher && !$this->matcher->matches($request)) { return; } if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) { return; } $this->profiles[$request] = $profile; if (null !== $this->requestStack) { $this->parents[$request] = $this->requestStack->getParentRequest(); } elseif (!$master) { // to be removed when requestStack is required array_pop($this->requests); $this->parents[$request] = end($this->requests); } } public function onKernelTerminate(PostResponseEvent $event) { // attach children to parents foreach ($this->profiles as $request) { // isset call should be removed when requestStack is required if (isset($this->parents[$request]) && null !== $parentRequest = $this->parents[$request]) { if (isset($this->profiles[$parentRequest])) { $this->profiles[$parentRequest]->addChild($this->profiles[$request]); } } } // save profiles foreach ($this->profiles as $request) { $this->profiler->saveProfile($this->profiles[$request]); } $this->profiles = new \SplObjectStorage(); $this->parents = new \SplObjectStorage(); $this->requests = array(); } public static function getSubscribedEvents() { return array( // kernel.request must be registered as early as possible to not break // when an exception is thrown in any other kernel.request listener KernelEvents::REQUEST => array('onKernelRequest', 1024), KernelEvents::RESPONSE => array('onKernelResponse', -100), KernelEvents::EXCEPTION => 'onKernelException', KernelEvents::TERMINATE => array('onKernelTerminate', -1024), ); } } PK! ?Symfony/Component/HttpKernel/EventListener/FragmentListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\IpUtils; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\UriSigner; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Handles content fragments represented by special URIs. * * All URL paths starting with /_fragment are handled as * content fragments by this listener. * * If the request does not come from a trusted IP, it throws an * AccessDeniedHttpException exception. * * @author Fabien Potencier */ class FragmentListener implements EventSubscriberInterface { private $signer; private $fragmentPath; /** * Constructor. * * @param UriSigner $signer A UriSigner instance * @param string $fragmentPath The path that triggers this listener */ public function __construct(UriSigner $signer, $fragmentPath = '/_fragment') { $this->signer = $signer; $this->fragmentPath = $fragmentPath; } /** * Fixes request attributes when the path is '/_fragment'. * * @param GetResponseEvent $event A GetResponseEvent instance * * @throws AccessDeniedHttpException if the request does not come from a trusted IP. */ public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) { return; } $this->validateRequest($request); parse_str($request->query->get('_path', ''), $attributes); $request->attributes->add($attributes); $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', array()), $attributes)); $request->query->remove('_path'); } protected function validateRequest(Request $request) { // is the Request safe? if (!$request->isMethodSafe()) { throw new AccessDeniedHttpException(); } // does the Request come from a trusted IP? $trustedIps = array_merge($this->getLocalIpAddresses(), $request->getTrustedProxies()); $remoteAddress = $request->server->get('REMOTE_ADDR'); if (IpUtils::checkIp($remoteAddress, $trustedIps)) { return; } // is the Request signed? // we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering) if ($this->signer->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().(null !== ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''))) { return; } throw new AccessDeniedHttpException(); } protected function getLocalIpAddresses() { return array('127.0.0.1', 'fe80::1', '::1'); } public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array(array('onKernelRequest', 48)), ); } } PK!@S>Symfony/Component/HttpKernel/EventListener/SessionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Sets the session in the request. * * @author Johannes M. Schmitt */ abstract class SessionListener implements EventSubscriberInterface { public function onKernelRequest(GetResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } $request = $event->getRequest(); $session = $this->getSession(); if (null === $session || $request->hasSession()) { return; } $request->setSession($session); } public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array('onKernelRequest', 128), ); } /** * Gets the session object. * * @return SessionInterface|null A SessionInterface instance of null if no session is available */ abstract protected function getSession(); } PK!|$CSymfony/Component/HttpKernel/EventListener/ErrorsLoggerListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Debug\ErrorHandler; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\KernelEvents; /** * Injects the logger into the ErrorHandler, so that it can log various errors. * * @author Colin Frei * @author Konstantin Myakshin */ class ErrorsLoggerListener implements EventSubscriberInterface { private $channel; private $logger; public function __construct($channel, LoggerInterface $logger = null) { $this->channel = $channel; $this->logger = $logger; } public function injectLogger() { if (null !== $this->logger) { ErrorHandler::setLogger($this->logger, $this->channel); } } public static function getSubscribedEvents() { return array(KernelEvents::REQUEST => 'injectLogger'); } } PK!$$GSymfony/Component/HttpKernel/EventListener/StreamedResponseListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * StreamedResponseListener is responsible for sending the Response * to the client. * * @author Fabien Potencier */ class StreamedResponseListener implements EventSubscriberInterface { /** * Filters the Response. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest()) { return; } $response = $event->getResponse(); if ($response instanceof StreamedResponse) { $response->send(); } } public static function getSubscribedEvents() { return array( KernelEvents::RESPONSE => array('onKernelResponse', -1024), ); } } PK! @Symfony/Component/HttpKernel/EventListener/ExceptionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Exception\FlattenException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * ExceptionListener. * * @author Fabien Potencier */ class ExceptionListener implements EventSubscriberInterface { protected $controller; protected $logger; public function __construct($controller, LoggerInterface $logger = null) { $this->controller = $controller; $this->logger = $logger; } public function onKernelException(GetResponseForExceptionEvent $event) { static $handling; if (true === $handling) { return false; } $handling = true; $exception = $event->getException(); $request = $event->getRequest(); $this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine())); $request = $this->duplicateRequest($exception, $request); try { $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, true); } catch (\Exception $e) { $this->logException($exception, sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage()), false); // set handling to false otherwise it wont be able to handle further more $handling = false; // re-throw the exception from within HttpKernel as this is a catch-all return; } $event->setResponse($response); $handling = false; } public static function getSubscribedEvents() { return array( KernelEvents::EXCEPTION => array('onKernelException', -128), ); } /** * Logs an exception. * * @param \Exception $exception The original \Exception instance * @param string $message The error message to log * @param Boolean $original False when the handling of the exception thrown another exception */ protected function logException(\Exception $exception, $message, $original = true) { $isCritical = !$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500; $context = array('exception' => $exception); if (null !== $this->logger) { if ($isCritical) { $this->logger->critical($message, $context); } else { $this->logger->error($message, $context); } } elseif (!$original || $isCritical) { error_log($message); } } /** * Clones the request for the exception. * * @param \Exception $exception The thrown exception. * @param Request $request The original request. * * @return Request $request The cloned request. */ protected function duplicateRequest(\Exception $exception, Request $request) { $attributes = array( '_controller' => $this->controller, 'exception' => FlattenException::create($exception), 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, // keep for BC -- as $format can be an argument of the controller callable // see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php // @deprecated in 2.4, to be removed in 3.0 'format' => $request->getRequestFormat(), ); $request = $request->duplicate(null, null, $attributes); $request->setMethod('GET'); return $request; } } PK!PCyy?Symfony/Component/HttpKernel/EventListener/ResponseListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * ResponseListener fixes the Response headers based on the Request. * * @author Fabien Potencier */ class ResponseListener implements EventSubscriberInterface { private $charset; public function __construct($charset) { $this->charset = $charset; } /** * Filters the Response. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest()) { return; } $response = $event->getResponse(); if (null === $response->getCharset()) { $response->setCharset($this->charset); } $response->prepare($event->getRequest()); } public static function getSubscribedEvents() { return array( KernelEvents::RESPONSE => 'onKernelResponse', ); } } PK!S "P P =Symfony/Component/HttpKernel/EventListener/LocaleListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Initializes the locale based on the current request. * * This listener works in 2 modes: * * * 2.3 compatibility mode where you must call setRequest whenever the Request changes. * * 2.4+ mode where you must pass a RequestStack instance in the constructor. * * @author Fabien Potencier */ class LocaleListener implements EventSubscriberInterface { private $router; private $defaultLocale; private $requestStack; /** * RequestStack will become required in 3.0. */ public function __construct($defaultLocale = 'en', RequestContextAwareInterface $router = null, RequestStack $requestStack = null) { $this->defaultLocale = $defaultLocale; $this->requestStack = $requestStack; $this->router = $router; } /** * Sets the current Request. * * This method was used to synchronize the Request, but as the HttpKernel * is doing that automatically now, you should never call it directly. * It is kept public for BC with the 2.3 version. * * @param Request|null $request A Request instance * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function setRequest(Request $request = null) { if (null === $request) { return; } $this->setLocale($request); $this->setRouterContext($request); } public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); $request->setDefaultLocale($this->defaultLocale); $this->setLocale($request); $this->setRouterContext($request); } public function onKernelFinishRequest(FinishRequestEvent $event) { if (null === $this->requestStack) { return; // removed when requestStack is required } if (null !== $parentRequest = $this->requestStack->getParentRequest()) { $this->setRouterContext($parentRequest); } } private function setLocale(Request $request) { if ($locale = $request->attributes->get('_locale')) { $request->setLocale($locale); } } private function setRouterContext(Request $request) { if (null !== $this->router) { $this->router->getContext()->setParameter('_locale', $request->getLocale()); } } public static function getSubscribedEvents() { return array( // must be registered after the Router to have access to the _locale KernelEvents::REQUEST => array(array('onKernelRequest', 16)), KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), ); } } PK!/)A A BSymfony/Component/HttpKernel/EventListener/TestSessionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * TestSessionListener. * * Saves session in test environment. * * @author Bulat Shakirzyanov * @author Fabien Potencier */ abstract class TestSessionListener implements EventSubscriberInterface { public function onKernelRequest(GetResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } // bootstrap the session $session = $this->getSession(); if (!$session) { return; } $cookies = $event->getRequest()->cookies; if ($cookies->has($session->getName())) { $session->setId($cookies->get($session->getName())); } } /** * Checks if session was initialized and saves if current request is master * Runs on 'kernel.response' in test environment * * @param FilterResponseEvent $event */ public function onKernelResponse(FilterResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } $session = $event->getRequest()->getSession(); if ($session && $session->isStarted()) { $session->save(); $params = session_get_cookie_params(); $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); } } public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array('onKernelRequest', 192), KernelEvents::RESPONSE => array('onKernelResponse', -128), ); } /** * Gets the session object. * * @return SessionInterface|null A SessionInterface instance of null if no session is available */ abstract protected function getSession(); } PK! --=Symfony/Component/HttpKernel/EventListener/RouterListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; /** * Initializes the context from the request and sets request attributes based on a matching route. * * This listener works in 2 modes: * * * 2.3 compatibility mode where you must call setRequest whenever the Request changes. * * 2.4+ mode where you must pass a RequestStack instance in the constructor. * * @author Fabien Potencier */ class RouterListener implements EventSubscriberInterface { private $matcher; private $context; private $logger; private $request; private $requestStack; /** * Constructor. * * RequestStack will become required in 3.0. * * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) * @param LoggerInterface|null $logger The logger * * @throws \InvalidArgumentException */ public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null, RequestStack $requestStack = null) { if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } if (null === $context && !$matcher instanceof RequestContextAwareInterface) { throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); } $this->matcher = $matcher; $this->context = $context ?: $matcher->getContext(); $this->requestStack = $requestStack; $this->logger = $logger; } /** * Sets the current Request. * * This method was used to synchronize the Request, but as the HttpKernel * is doing that automatically now, you should never call it directly. * It is kept public for BC with the 2.3 version. * * @param Request|null $request A Request instance * * @deprecated Deprecated since version 2.4, to be moved to a private function in 3.0. */ public function setRequest(Request $request = null) { if (null !== $request && $this->request !== $request) { $this->context->fromRequest($request); } $this->request = $request; } public function onKernelFinishRequest(FinishRequestEvent $event) { if (null === $this->requestStack) { return; // removed when requestStack is required } $this->setRequest($this->requestStack->getParentRequest()); } public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); // initialize the context that is also used by the generator (assuming matcher and generator share the same context instance) // we call setRequest even if most of the time, it has already been done to keep compatibility // with frameworks which do not use the Symfony service container // when we have a RequestStack, no need to do it if (null !== $this->requestStack) { $this->setRequest($request); } if ($request->attributes->has('_controller')) { // routing is already done return; } // add attributes based on the request (routing) try { // matching a request is more powerful than matching a URL path + context, so try that first if ($this->matcher instanceof RequestMatcherInterface) { $parameters = $this->matcher->matchRequest($request); } else { $parameters = $this->matcher->match($request->getPathInfo()); } if (null !== $this->logger) { $this->logger->info(sprintf('Matched route "%s" (parameters: %s)', $parameters['_route'], $this->parametersToString($parameters))); } $request->attributes->add($parameters); unset($parameters['_route']); unset($parameters['_controller']); $request->attributes->set('_route_params', $parameters); } catch (ResourceNotFoundException $e) { $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo()); if ($referer = $request->headers->get('referer')) { $message .= sprintf(' (from "%s")', $referer); } throw new NotFoundHttpException($message, $e); } catch (MethodNotAllowedException $e) { $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), implode(', ', $e->getAllowedMethods())); throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e); } } private function parametersToString(array $parameters) { $pieces = array(); foreach ($parameters as $key => $val) { $pieces[] = sprintf('"%s": "%s"', $key, (is_string($val) ? $val : json_encode($val))); } return implode(', ', $pieces); } public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array(array('onKernelRequest', 32)), KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), ); } } PK!^:Symfony/Component/HttpKernel/EventListener/EsiListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * EsiListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for ESI. * * @author Fabien Potencier */ class EsiListener implements EventSubscriberInterface { private $esi; /** * Constructor. * * @param Esi $esi An ESI instance */ public function __construct(Esi $esi = null) { $this->esi = $esi; } /** * Filters the Response. * * @param FilterResponseEvent $event A FilterResponseEvent instance */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest() || null === $this->esi) { return; } $this->esi->addSurrogateControl($event->getResponse()); } public static function getSubscribedEvents() { return array( KernelEvents::RESPONSE => 'onKernelResponse', ); } } PK!qK-##@Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel. * * @author Fabien Potencier */ class InlineFragmentRenderer extends RoutableFragmentRenderer { private $kernel; private $dispatcher; /** * Constructor. * * @param HttpKernelInterface $kernel A HttpKernelInterface instance * @param EventDispatcherInterface $dispatcher A EventDispatcherInterface instance */ public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null) { $this->kernel = $kernel; $this->dispatcher = $dispatcher; } /** * {@inheritdoc} * * Additional available options: * * * alt: an alternative URI to render in case of an error */ public function render($uri, Request $request, array $options = array()) { $reference = null; if ($uri instanceof ControllerReference) { $reference = $uri; // Remove attributes from the generated URI because if not, the Symfony // routing system will use them to populate the Request attributes. We don't // want that as we want to preserve objects (so we manually set Request attributes // below instead) $attributes = $reference->attributes; $reference->attributes = array(); // The request format and locale might have been overridden by the user foreach (array('_format', '_locale') as $key) { if (isset($attributes[$key])) { $reference->attributes[$key] = $attributes[$key]; } } $uri = $this->generateFragmentUri($uri, $request, false, false); $reference->attributes = array_merge($attributes, $reference->attributes); } $subRequest = $this->createSubRequest($uri, $request); // override Request attributes as they can be objects (which are not supported by the generated URI) if (null !== $reference) { $subRequest->attributes->add($reference->attributes); } $level = ob_get_level(); try { return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false); } catch (\Exception $e) { // we dispatch the exception event to trigger the logging // the response that comes back is simply ignored if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) { $event = new GetResponseForExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); } // let's clean up the output buffers that were created by the sub-request while (ob_get_level() > $level) { ob_get_clean(); } if (isset($options['alt'])) { $alt = $options['alt']; unset($options['alt']); return $this->render($alt, $request, $options); } if (!isset($options['ignore_errors']) || !$options['ignore_errors']) { throw $e; } return new Response(); } } protected function createSubRequest($uri, Request $request) { $cookies = $request->cookies->all(); $server = $request->server->all(); // Override the arguments to emulate a sub-request. // Sub-request object will point to localhost as client ip and real client ip // will be included into trusted header for client ip try { if ($trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)) { $currentXForwardedFor = $request->headers->get($trustedHeaderName, ''); $server['HTTP_'.$trustedHeaderName] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp(); } } catch (\InvalidArgumentException $e) { // Do nothing } $server['REMOTE_ADDR'] = '127.0.0.1'; $subRequest = Request::create($uri, 'get', array(), $cookies, array(), $server); if ($request->headers->has('Surrogate-Capability')) { $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability')); } if ($session = $request->getSession()) { $subRequest->setSession($session); } return $subRequest; } /** * {@inheritdoc} */ public function getName() { return 'inline'; } } PK!m3 3 BSymfony/Component/HttpKernel/Fragment/RoutableFragmentRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\EventListener\FragmentListener; /** * Adds the possibility to generate a fragment URI for a given Controller. * * @author Fabien Potencier */ abstract class RoutableFragmentRenderer implements FragmentRendererInterface { private $fragmentPath = '/_fragment'; /** * Sets the fragment path that triggers the fragment listener. * * @param string $path The path * * @see FragmentListener */ public function setFragmentPath($path) { $this->fragmentPath = $path; } /** * Generates a fragment URI for a given controller. * * @param ControllerReference $reference A ControllerReference instance * @param Request $request A Request instance * @param Boolean $absolute Whether to generate an absolute URL or not * @param Boolean $strict Whether to allow non-scalar attributes or not * * @return string A fragment URI */ protected function generateFragmentUri(ControllerReference $reference, Request $request, $absolute = false, $strict = true) { if ($strict) { $this->checkNonScalar($reference->attributes); } // We need to forward the current _format and _locale values as we don't have // a proper routing pattern to do the job for us. // This makes things inconsistent if you switch from rendering a controller // to rendering a route if the route pattern does not contain the special // _format and _locale placeholders. if (!isset($reference->attributes['_format'])) { $reference->attributes['_format'] = $request->getRequestFormat(); } if (!isset($reference->attributes['_locale'])) { $reference->attributes['_locale'] = $request->getLocale(); } $reference->attributes['_controller'] = $reference->controller; $reference->query['_path'] = http_build_query($reference->attributes, '', '&'); $path = $this->fragmentPath.'?'.http_build_query($reference->query, '', '&'); if ($absolute) { return $request->getUriForPath($path); } return $request->getBaseUrl().$path; } private function checkNonScalar($values) { foreach ($values as $key => $value) { if (is_array($value)) { $this->checkNonScalar($value); } elseif (!is_scalar($value) && null !== $value) { throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key)); } } } } PK!jg =Symfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\HttpCache\Esi; /** * Implements the ESI rendering strategy. * * @author Fabien Potencier */ class EsiFragmentRenderer extends RoutableFragmentRenderer { private $esi; private $inlineStrategy; /** * Constructor. * * The "fallback" strategy when ESI is not available should always be an * instance of InlineFragmentRenderer. * * @param Esi $esi An Esi instance * @param InlineFragmentRenderer $inlineStrategy The inline strategy to use when ESI is not supported */ public function __construct(Esi $esi = null, InlineFragmentRenderer $inlineStrategy) { $this->esi = $esi; $this->inlineStrategy = $inlineStrategy; } /** * {@inheritdoc} * * Note that if the current Request has no ESI capability, this method * falls back to use the inline rendering strategy. * * Additional available options: * * * alt: an alternative URI to render in case of an error * * comment: a comment to add when returning an esi:include tag * * @see Symfony\Component\HttpKernel\HttpCache\ESI */ public function render($uri, Request $request, array $options = array()) { if (!$this->esi || !$this->esi->hasSurrogateEsiCapability($request)) { return $this->inlineStrategy->render($uri, $request, $options); } if ($uri instanceof ControllerReference) { $uri = $this->generateFragmentUri($uri, $request); } $alt = isset($options['alt']) ? $options['alt'] : null; if ($alt instanceof ControllerReference) { $alt = $this->generateFragmentUri($alt, $request); } $tag = $this->esi->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : ''); return new Response($tag); } /** * {@inheritdoc} */ public function getName() { return 'esi'; } } PK!R9Symfony/Component/HttpKernel/Fragment/FragmentHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Controller\ControllerReference; /** * Renders a URI that represents a resource fragment. * * This class handles the rendering of resource fragments that are included into * a main resource. The handling of the rendering is managed by specialized renderers. * * This listener works in 2 modes: * * * 2.3 compatibility mode where you must call setRequest whenever the Request changes. * * 2.4+ mode where you must pass a RequestStack instance in the constructor. * * @author Fabien Potencier * * @see FragmentRendererInterface */ class FragmentHandler { private $debug; private $renderers = array(); private $request; private $requestStack; /** * Constructor. * * RequestStack will become required in 3.0. * * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances * @param Boolean $debug Whether the debug mode is enabled or not * @param RequestStack|null $requestStack The Request stack that controls the lifecycle of requests */ public function __construct(array $renderers = array(), $debug = false, RequestStack $requestStack = null) { $this->requestStack = $requestStack; foreach ($renderers as $renderer) { $this->addRenderer($renderer); } $this->debug = $debug; } /** * Adds a renderer. * * @param FragmentRendererInterface $renderer A FragmentRendererInterface instance */ public function addRenderer(FragmentRendererInterface $renderer) { $this->renderers[$renderer->getName()] = $renderer; } /** * Sets the current Request. * * This method was used to synchronize the Request, but as the HttpKernel * is doing that automatically now, you should never call it directly. * It is kept public for BC with the 2.3 version. * * @param Request|null $request A Request instance * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function setRequest(Request $request = null) { $this->request = $request; } /** * Renders a URI and returns the Response content. * * Available options: * * * ignore_errors: true to return an empty string in case of an error * * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance * @param string $renderer The renderer name * @param array $options An array of options * * @return string|null The Response content or null when the Response is streamed * * @throws \InvalidArgumentException when the renderer does not exist * @throws \LogicException when the Request is not successful */ public function render($uri, $renderer = 'inline', array $options = array()) { if (!isset($options['ignore_errors'])) { $options['ignore_errors'] = !$this->debug; } if (!isset($this->renderers[$renderer])) { throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer)); } if (!$request = $this->getRequest()) { throw new \LogicException('Rendering a fragment can only be done when handling a Request.'); } return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options)); } /** * Delivers the Response as a string. * * When the Response is a StreamedResponse, the content is streamed immediately * instead of being returned. * * @param Response $response A Response instance * * @return string|null The Response content or null when the Response is streamed * * @throws \RuntimeException when the Response is not successful */ protected function deliver(Response $response) { if (!$response->isSuccessful()) { throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->getRequest()->getUri(), $response->getStatusCode())); } if (!$response instanceof StreamedResponse) { return $response->getContent(); } $response->sendContent(); } private function getRequest() { return $this->requestStack ? $this->requestStack->getCurrentRequest() : $this->request; } } PK!5앾BSymfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; if (!defined('ENT_SUBSTITUTE')) { define('ENT_SUBSTITUTE', 8); } use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Templating\EngineInterface; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\UriSigner; /** * Implements the Hinclude rendering strategy. * * @author Fabien Potencier */ class HIncludeFragmentRenderer extends RoutableFragmentRenderer { private $globalDefaultTemplate; private $signer; private $templating; private $charset; /** * Constructor. * * @param EngineInterface|\Twig_Environment $templating An EngineInterface or a \Twig_Environment instance * @param UriSigner $signer A UriSigner instance * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) * @param string $charset */ public function __construct($templating = null, UriSigner $signer = null, $globalDefaultTemplate = null, $charset = 'utf-8') { $this->setTemplating($templating); $this->globalDefaultTemplate = $globalDefaultTemplate; $this->signer = $signer; $this->charset = $charset; } /** * Sets the templating engine to use to render the default content. * * @param EngineInterface|\Twig_Environment|null $templating An EngineInterface or a \Twig_Environment instance * * @throws \InvalidArgumentException */ public function setTemplating($templating) { if (null !== $templating && !$templating instanceof EngineInterface && !$templating instanceof \Twig_Environment) { throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of \Twig_Environment or Symfony\Component\Templating\EngineInterface'); } $this->templating = $templating; } /** * Checks if a templating engine has been set. * * @return Boolean true if the templating engine has been set, false otherwise */ public function hasTemplating() { return null !== $this->templating; } /** * {@inheritdoc} * * Additional available options: * * * default: The default content (it can be a template name or the content) * * id: An optional hx:include tag id attribute * * attributes: An optional array of hx:include tag attributes */ public function render($uri, Request $request, array $options = array()) { if ($uri instanceof ControllerReference) { if (null === $this->signer) { throw new \LogicException('You must use a proper URI when using the Hinclude rendering strategy or set a URL signer.'); } // we need to sign the absolute URI, but want to return the path only. $uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), strlen($request->getSchemeAndHttpHost())); } // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content. $uri = str_replace('&', '&', $uri); $template = isset($options['default']) ? $options['default'] : $this->globalDefaultTemplate; if (null !== $this->templating && $template && $this->templateExists($template)) { $content = $this->templating->render($template); } else { $content = $template; } $attributes = isset($options['attributes']) && is_array($options['attributes']) ? $options['attributes'] : array(); if (isset($options['id']) && $options['id']) { $attributes['id'] = $options['id']; } $renderedAttributes = ''; if (count($attributes) > 0) { foreach ($attributes as $attribute => $value) { $renderedAttributes .= sprintf( ' %s="%s"', htmlspecialchars($attribute, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset, false), htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset, false) ); } } return new Response(sprintf('%s', $uri, $renderedAttributes, $content)); } /** * @param string $template * * @return boolean */ private function templateExists($template) { if ($this->templating instanceof EngineInterface) { try { return $this->templating->exists($template); } catch (\InvalidArgumentException $e) { return false; } } $loader = $this->templating->getLoader(); if ($loader instanceof \Twig_ExistsLoaderInterface) { return $loader->exists($template); } try { $loader->getSource($template); return true; } catch (\Twig_Error_Loader $e) { } return false; } /** * {@inheritdoc} */ public function getName() { return 'hinclude'; } } PK!zCSymfony/Component/HttpKernel/Fragment/FragmentRendererInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpFoundation\Response; /** * Interface implemented by all rendering strategies. * * @author Fabien Potencier * * @see Symfony\Component\HttpKernel\FragmentRenderer */ interface FragmentRendererInterface { /** * Renders a URI and returns the Response content. * * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance * @param Request $request A Request instance * @param array $options An array of options * * @return Response A Response instance */ public function render($uri, Request $request, array $options = array()); /** * Gets the name of the strategy. * * @return string The strategy name */ public function getName(); } PK!ST;Symfony/Component/HttpKernel/Exception/FlattenException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException; /** * FlattenException wraps a PHP Exception to be able to serialize it. * * Basically, this class removes all objects from the trace. * * @author Fabien Potencier * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead. */ class FlattenException extends DebugFlattenException { } PK![G??BSymfony/Component/HttpKernel/Exception/BadRequestHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * BadRequestHttpException. * * @author Ben Ramsey */ class BadRequestHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(400, $message, $previous, array(), $code); } } PK!7GSymfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * TooManyRequestsHttpException. * * @author Ben Ramsey * @see http://tools.ietf.org/html/rfc6585 */ class TooManyRequestsHttpException extends HttpException { /** * Constructor. * * @param integer|string $retryAfter The number of seconds or HTTP-date after which the request may be retried * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0) { $headers = array(); if ($retryAfter) { $headers = array('Retry-After' => $retryAfter); } parent::__construct(429, $message, $previous, $headers, $code); } } PK!W1d8Symfony/Component/HttpKernel/Exception/HttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * HttpException. * * @author Kris Wallsmith */ class HttpException extends \RuntimeException implements HttpExceptionInterface { private $statusCode; private $headers; public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = array(), $code = 0) { $this->statusCode = $statusCode; $this->headers = $headers; parent::__construct($message, $code, $previous); } public function getStatusCode() { return $this->statusCode; } public function getHeaders() { return $this->headers; } } PK!N0;;@Symfony/Component/HttpKernel/Exception/ConflictHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * ConflictHttpException. * * @author Ben Ramsey */ class ConflictHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(409, $message, $previous, array(), $code); } } PK!C%؝SSLSymfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * UnsupportedMediaTypeHttpException. * * @author Ben Ramsey */ class UnsupportedMediaTypeHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(415, $message, $previous, array(), $code); } } PK!EEESymfony/Component/HttpKernel/Exception/NotAcceptableHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * NotAcceptableHttpException. * * @author Ben Ramsey */ class NotAcceptableHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(406, $message, $previous, array(), $code); } } PK!Ѕ33<Symfony/Component/HttpKernel/Exception/GoneHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * GoneHttpException. * * @author Ben Ramsey */ class GoneHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(410, $message, $previous, array(), $code); } } PK!^>Symfony/Component/HttpKernel/Exception/FatalErrorException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; use Symfony\Component\Debug\Exception\FatalErrorException as DebugFatalErrorException; /** * Fatal Error Exception. * * @author Konstanton Myakshin * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead. */ class FatalErrorException extends DebugFatalErrorException { } PK!)8*uuDSymfony/Component/HttpKernel/Exception/AccessDeniedHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * AccessDeniedHttpException. * * @author Fabien Potencier * @author Christophe Coevoet */ class AccessDeniedHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(403, $message, $previous, array(), $code); } } PK!+~~LSymfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * PreconditionRequiredHttpException. * * @author Ben Ramsey * @see http://tools.ietf.org/html/rfc6585 */ class PreconditionRequiredHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(428, $message, $previous, array(), $code); } } PK!+;XXJSymfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * ServiceUnavailableHttpException. * * @author Ben Ramsey */ class ServiceUnavailableHttpException extends HttpException { /** * Constructor. * * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0) { $headers = array(); if ($retryAfter) { $headers = array('Retry-After' => $retryAfter); } parent::__construct(503, $message, $previous, $headers, $code); } } PK!*DSymfony/Component/HttpKernel/Exception/UnauthorizedHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * UnauthorizedHttpException. * * @author Ben Ramsey */ class UnauthorizedHttpException extends HttpException { /** * Constructor. * * @param string $challenge WWW-Authenticate challenge string * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($challenge, $message = null, \Exception $previous = null, $code = 0) { $headers = array('WWW-Authenticate' => $challenge); parent::__construct(401, $message, $previous, $headers, $code); } } PK!瞻??@Symfony/Component/HttpKernel/Exception/NotFoundHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * NotFoundHttpException. * * @author Fabien Potencier */ class NotFoundHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(404, $message, $previous, array(), $code); } } PK!<~HSymfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * MethodNotAllowedHttpException. * * @author Kris Wallsmith */ class MethodNotAllowedHttpException extends HttpException { /** * Constructor. * * @param array $allow An array of allowed methods * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct(array $allow, $message = null, \Exception $previous = null, $code = 0) { $headers = array('Allow' => strtoupper(implode(', ', $allow))); parent::__construct(405, $message, $previous, $headers, $code); } } PK! GGFSymfony/Component/HttpKernel/Exception/LengthRequiredHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * LengthRequiredHttpException. * * @author Ben Ramsey */ class LengthRequiredHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(411, $message, $previous, array(), $code); } } PK!;COOJSymfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * PreconditionFailedHttpException. * * @author Ben Ramsey */ class PreconditionFailedHttpException extends HttpException { /** * Constructor. * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param integer $code The internal exception code */ public function __construct($message = null, \Exception $previous = null, $code = 0) { parent::__construct(412, $message, $previous, array(), $code); } } PK!rQrWASymfony/Component/HttpKernel/Exception/HttpExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Exception; /** * Interface for HTTP error exceptions. * * @author Kris Wallsmith */ interface HttpExceptionInterface { /** * Returns the status code. * * @return integer An HTTP response status code */ public function getStatusCode(); /** * Returns response headers. * * @return array Response headers */ public function getHeaders(); } PK!^t4Symfony/Component/HttpKernel/TerminableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Terminable extends the Kernel request/response cycle with dispatching a post * response event after sending the response and before shutting down the kernel. * * @author Jordi Boggiano * @author Pierre Minnieur * * @api */ interface TerminableInterface { /** * Terminates a request/response cycle. * * Should be called after sending the response and before shutting down the kernel. * * @param Request $request A Request instance * @param Response $response A Response instance * * @api */ public function terminate(Request $request, Response $response); } PK!=AA4Symfony/Component/HttpKernel/HttpKernelInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * HttpKernelInterface handles a Request to convert it to a Response. * * @author Fabien Potencier * * @api */ interface HttpKernelInterface { const MASTER_REQUEST = 1; const SUB_REQUEST = 2; /** * Handles a Request to convert it to a Response. * * When $catch is true, the implementation must catch all exceptions * and do its best to convert them to a Response instance. * * @param Request $request A Request instance * @param integer $type The type of the request * (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) * @param Boolean $catch Whether to catch exceptions or not * * @return Response A Response instance * * @throws \Exception When an Exception occurs during processing * * @api */ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true); } PK!kt$$+Symfony/Component/HttpKernel/HttpKernel.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\PostResponseEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * HttpKernel notifies events to convert a Request object to a Response one. * * @author Fabien Potencier * * @api */ class HttpKernel implements HttpKernelInterface, TerminableInterface { protected $dispatcher; protected $resolver; protected $requestStack; /** * Constructor * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance * @param RequestStack $requestStack A stack for master/sub requests * * @api */ public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null) { $this->dispatcher = $dispatcher; $this->resolver = $resolver; $this->requestStack = $requestStack ?: new RequestStack(); } /** * {@inheritdoc} * * @api */ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { try { return $this->handleRaw($request, $type); } catch (\Exception $e) { if (false === $catch) { $this->finishRequest($request, $type); throw $e; } return $this->handleException($e, $request, $type); } } /** * {@inheritdoc} * * @api */ public function terminate(Request $request, Response $response) { $this->dispatcher->dispatch(KernelEvents::TERMINATE, new PostResponseEvent($this, $request, $response)); } /** * Handles a request to convert it to a response. * * Exceptions are not caught. * * @param Request $request A Request instance * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) * * @return Response A Response instance * * @throws \LogicException If one of the listener does not behave as expected * @throws NotFoundHttpException When controller cannot be found */ private function handleRaw(Request $request, $type = self::MASTER_REQUEST) { $this->requestStack->push($request); // request $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch(KernelEvents::REQUEST, $event); if ($event->hasResponse()) { return $this->filterResponse($event->getResponse(), $request, $type); } // load controller if (false === $controller = $this->resolver->getController($request)) { throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?', $request->getPathInfo())); } $event = new FilterControllerEvent($this, $controller, $request, $type); $this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event); $controller = $event->getController(); // controller arguments $arguments = $this->resolver->getArguments($request, $controller); // call controller $response = call_user_func_array($controller, $arguments); // view if (!$response instanceof Response) { $event = new GetResponseForControllerResultEvent($this, $request, $type, $response); $this->dispatcher->dispatch(KernelEvents::VIEW, $event); if ($event->hasResponse()) { $response = $event->getResponse(); } if (!$response instanceof Response) { $msg = sprintf('The controller must return a response (%s given).', $this->varToString($response)); // the user may have forgotten to return something if (null === $response) { $msg .= ' Did you forget to add a return statement somewhere in your controller?'; } throw new \LogicException($msg); } } return $this->filterResponse($response, $request, $type); } /** * Filters a response object. * * @param Response $response A Response instance * @param Request $request An error message in case the response is not a Response object * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) * * @return Response The filtered Response instance * * @throws \RuntimeException if the passed object is not a Response instance */ private function filterResponse(Response $response, Request $request, $type) { $event = new FilterResponseEvent($this, $request, $type, $response); $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->finishRequest($request, $type); return $event->getResponse(); } /** * Publishes the finish request event, then pop the request from the stack. * * Note that the order of the operations is important here, otherwise * operations such as {@link RequestStack::getParentRequest()} can lead to * weird results. * * @param Request $request * @param int $type */ private function finishRequest(Request $request, $type) { $this->dispatcher->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this, $request, $type)); $this->requestStack->pop(); } /** * Handles an exception by trying to convert it to a Response. * * @param \Exception $e An \Exception instance * @param Request $request A Request instance * @param integer $type The type of the request * * @return Response A Response instance * * @throws \Exception */ private function handleException(\Exception $e, $request, $type) { $event = new GetResponseForExceptionEvent($this, $request, $type, $e); $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); // a listener might have replaced the exception $e = $event->getException(); if (!$event->hasResponse()) { $this->finishRequest($request, $type); throw $e; } $response = $event->getResponse(); // the developer asked for a specific status code if ($response->headers->has('X-Status-Code')) { $response->setStatusCode($response->headers->get('X-Status-Code')); $response->headers->remove('X-Status-Code'); } elseif (!$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { // ensure that we actually have an error response if ($e instanceof HttpExceptionInterface) { // keep the HTTP status code and headers $response->setStatusCode($e->getStatusCode()); $response->headers->add($e->getHeaders()); } else { $response->setStatusCode(500); } } try { return $this->filterResponse($response, $request, $type); } catch (\Exception $e) { return $response; } } private function varToString($var) { if (is_object($var)) { return sprintf('Object(%s)', get_class($var)); } if (is_array($var)) { $a = array(); foreach ($var as $k => $v) { $a[] = sprintf('%s => %s', $k, $this->varToString($v)); } return sprintf("Array(%s)", implode(', ', $a)); } if (is_resource($var)) { return sprintf('Resource(%s)', get_resource_type($var)); } if (null === $var) { return 'null'; } if (false === $var) { return 'false'; } if (true === $var) { return 'true'; } return (string) $var; } } PK!b b 9Symfony/Component/HttpKernel/HttpCache/StoreInterface.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Interface implemented by HTTP cache stores. * * @author Fabien Potencier */ interface StoreInterface { /** * Locates a cached Response for the Request provided. * * @param Request $request A Request instance * * @return Response|null A Response instance, or null if no cache entry was found */ public function lookup(Request $request); /** * Writes a cache entry to the store for the given Request and Response. * * Existing entries are read and any that match the response are removed. This * method calls write with the new list of cache entries. * * @param Request $request A Request instance * @param Response $response A Response instance * * @return string The key under which the response is stored */ public function write(Request $request, Response $response); /** * Invalidates all cache entries that match the request. * * @param Request $request A Request instance */ public function invalidate(Request $request); /** * Locks the cache for a given Request. * * @param Request $request A Request instance * * @return Boolean|string true if the lock is acquired, the path to the current lock otherwise */ public function lock(Request $request); /** * Releases the lock for the given Request. * * @param Request $request A Request instance * * @return Boolean False if the lock file does not exist or cannot be unlocked, true otherwise */ public function unlock(Request $request); /** * Returns whether or not a lock exists. * * @param Request $request A Request instance * * @return Boolean true if lock exists, false otherwise */ public function isLocked(Request $request); /** * Purges data for the given URL. * * @param string $url A URL * * @return Boolean true if the URL exists and has been purged, false otherwise */ public function purge($url); /** * Cleanups storage. */ public function cleanup(); } PK!M~CCLSymfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Response; /** * EsiResponseCacheStrategyInterface implementations know how to compute the * Response cache HTTP header based on the different ESI response cache headers. * * @author Fabien Potencier */ interface EsiResponseCacheStrategyInterface { /** * Adds a Response. * * @param Response $response */ public function add(Response $response); /** * Updates the Response HTTP headers based on the embedded Responses. * * @param Response $response */ public function update(Response $response); } PK!wn n .Symfony/Component/HttpKernel/HttpCache/Esi.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Esi implements the ESI capabilities to Request and Response instances. * * For more information, read the following W3C notes: * * * ESI Language Specification 1.0 (http://www.w3.org/TR/esi-lang) * * * Edge Architecture Specification (http://www.w3.org/TR/edge-arch) * * @author Fabien Potencier */ class Esi { private $contentTypes; /** * Constructor. * * @param array $contentTypes An array of content-type that should be parsed for ESI information. * (default: text/html, text/xml, application/xhtml+xml, and application/xml) */ public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xhtml+xml', 'application/xml')) { $this->contentTypes = $contentTypes; } /** * Returns a new cache strategy instance. * * @return EsiResponseCacheStrategyInterface A EsiResponseCacheStrategyInterface instance */ public function createCacheStrategy() { return new EsiResponseCacheStrategy(); } /** * Checks that at least one surrogate has ESI/1.0 capability. * * @param Request $request A Request instance * * @return Boolean true if one surrogate has ESI/1.0 capability, false otherwise */ public function hasSurrogateEsiCapability(Request $request) { if (null === $value = $request->headers->get('Surrogate-Capability')) { return false; } return false !== strpos($value, 'ESI/1.0'); } /** * Adds ESI/1.0 capability to the given Request. * * @param Request $request A Request instance */ public function addSurrogateEsiCapability(Request $request) { $current = $request->headers->get('Surrogate-Capability'); $new = 'symfony2="ESI/1.0"'; $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new); } /** * Adds HTTP headers to specify that the Response needs to be parsed for ESI. * * This method only adds an ESI HTTP header if the Response has some ESI tags. * * @param Response $response A Response instance */ public function addSurrogateControl(Response $response) { if (false !== strpos($response->getContent(), 'headers->set('Surrogate-Control', 'content="ESI/1.0"'); } } /** * Checks that the Response needs to be parsed for ESI tags. * * @param Response $response A Response instance * * @return Boolean true if the Response needs to be parsed, false otherwise */ public function needsEsiParsing(Response $response) { if (!$control = $response->headers->get('Surrogate-Control')) { return false; } return (Boolean) preg_match('#content="[^"]*ESI/1.0[^"]*"#', $control); } /** * Renders an ESI tag. * * @param string $uri A URI * @param string $alt An alternate URI * @param Boolean $ignoreErrors Whether to ignore errors or not * @param string $comment A comment to add as an esi:include tag * * @return string */ public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comment = '') { $html = sprintf('', $uri, $ignoreErrors ? ' onerror="continue"' : '', $alt ? sprintf(' alt="%s"', $alt) : '' ); if (!empty($comment)) { return sprintf("\n%s", $comment, $html); } return $html; } /** * Replaces a Response ESI tags with the included resource content. * * @param Request $request A Request instance * @param Response $response A Response instance * * @return Response */ public function process(Request $request, Response $response) { $this->request = $request; $type = $response->headers->get('Content-Type'); if (empty($type)) { $type = 'text/html'; } $parts = explode(';', $type); if (!in_array($parts[0], $this->contentTypes)) { return $response; } // we don't use a proper XML parser here as we can have ESI tags in a plain text response $content = $response->getContent(); $content = str_replace(array('', ''), $content); $content = preg_replace_callback('##', array($this, 'handleEsiIncludeTag'), $content); $content = preg_replace('#]*(?:/|#', '', $content); $content = preg_replace('#.*?#', '', $content); $response->setContent($content); $response->headers->set('X-Body-Eval', 'ESI'); // remove ESI/1.0 from the Surrogate-Control header if ($response->headers->has('Surrogate-Control')) { $value = $response->headers->get('Surrogate-Control'); if ('content="ESI/1.0"' == $value) { $response->headers->remove('Surrogate-Control'); } elseif (preg_match('#,\s*content="ESI/1.0"#', $value)) { $response->headers->set('Surrogate-Control', preg_replace('#,\s*content="ESI/1.0"#', '', $value)); } elseif (preg_match('#content="ESI/1.0",\s*#', $value)) { $response->headers->set('Surrogate-Control', preg_replace('#content="ESI/1.0",\s*#', '', $value)); } } } /** * Handles an ESI from the cache. * * @param HttpCache $cache An HttpCache instance * @param string $uri The main URI * @param string $alt An alternative URI * @param Boolean $ignoreErrors Whether to ignore errors or not * * @return string * * @throws \RuntimeException * @throws \Exception */ public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors) { $subRequest = Request::create($uri, 'get', array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all()); try { $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); if (!$response->isSuccessful()) { throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode())); } return $response->getContent(); } catch (\Exception $e) { if ($alt) { return $this->handle($cache, $alt, '', $ignoreErrors); } if (!$ignoreErrors) { throw $e; } } } /** * Handles an ESI include tag (called internally). * * @param array $attributes An array containing the attributes. * * @return string The response content for the include. * * @throws \RuntimeException */ private function handleEsiIncludeTag($attributes) { $options = array(); preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER); foreach ($matches as $set) { $options[$set[1]] = $set[2]; } if (!isset($options['src'])) { throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); } return sprintf('esi->handle($this, \'%s\', \'%s\', %s) ?>'."\n", $options['src'], isset($options['alt']) ? $options['alt'] : null, isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false' ); } } PK!#[[4Symfony/Component/HttpKernel/HttpCache/HttpCache.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\TerminableInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Cache provides HTTP caching. * * @author Fabien Potencier * * @api */ class HttpCache implements HttpKernelInterface, TerminableInterface { private $kernel; private $store; private $request; private $esi; private $esiCacheStrategy; private $options = array(); private $traces = array(); /** * Constructor. * * The available options are: * * * debug: If true, the traces are added as a HTTP header to ease debugging * * * default_ttl The number of seconds that a cache entry should be considered * fresh when no explicit freshness information is provided in * a response. Explicit Cache-Control or Expires headers * override this value. (default: 0) * * * private_headers Set of request headers that trigger "private" cache-control behavior * on responses that don't explicitly state whether the response is * public or private via a Cache-Control directive. (default: Authorization and Cookie) * * * allow_reload Specifies whether the client can force a cache reload by including a * Cache-Control "no-cache" directive in the request. Set it to ``true`` * for compliance with RFC 2616. (default: false) * * * allow_revalidate Specifies whether the client can force a cache revalidate by including * a Cache-Control "max-age=0" directive in the request. Set it to ``true`` * for compliance with RFC 2616. (default: false) * * * stale_while_revalidate Specifies the default number of seconds (the granularity is the second as the * Response TTL precision is a second) during which the cache can immediately return * a stale response while it revalidates it in the background (default: 2). * This setting is overridden by the stale-while-revalidate HTTP Cache-Control * extension (see RFC 5861). * * * stale_if_error Specifies the default number of seconds (the granularity is the second) during which * the cache can serve a stale response when an error is encountered (default: 60). * This setting is overridden by the stale-if-error HTTP Cache-Control extension * (see RFC 5861). * * @param HttpKernelInterface $kernel An HttpKernelInterface instance * @param StoreInterface $store A Store instance * @param Esi $esi An Esi instance * @param array $options An array of options */ public function __construct(HttpKernelInterface $kernel, StoreInterface $store, Esi $esi = null, array $options = array()) { $this->store = $store; $this->kernel = $kernel; $this->esi = $esi; // needed in case there is a fatal error because the backend is too slow to respond register_shutdown_function(array($this->store, 'cleanup')); $this->options = array_merge(array( 'debug' => false, 'default_ttl' => 0, 'private_headers' => array('Authorization', 'Cookie'), 'allow_reload' => false, 'allow_revalidate' => false, 'stale_while_revalidate' => 2, 'stale_if_error' => 60, ), $options); } /** * Gets the current store. * * @return StoreInterface $store A StoreInterface instance */ public function getStore() { return $this->store; } /** * Returns an array of events that took place during processing of the last request. * * @return array An array of events */ public function getTraces() { return $this->traces; } /** * Returns a log message for the events of the last request processing. * * @return string A log message */ public function getLog() { $log = array(); foreach ($this->traces as $request => $traces) { $log[] = sprintf('%s: %s', $request, implode(', ', $traces)); } return implode('; ', $log); } /** * Gets the Request instance associated with the master request. * * @return Request A Request instance */ public function getRequest() { return $this->request; } /** * Gets the Kernel instance * * @return HttpKernelInterface An HttpKernelInterface instance */ public function getKernel() { return $this->kernel; } /** * Gets the Esi instance * * @return Esi An Esi instance */ public function getEsi() { return $this->esi; } /** * {@inheritdoc} * * @api */ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism if (HttpKernelInterface::MASTER_REQUEST === $type) { $this->traces = array(); $this->request = $request; if (null !== $this->esi) { $this->esiCacheStrategy = $this->esi->createCacheStrategy(); } } $path = $request->getPathInfo(); if ($qs = $request->getQueryString()) { $path .= '?'.$qs; } $this->traces[$request->getMethod().' '.$path] = array(); if (!$request->isMethodSafe()) { $response = $this->invalidate($request, $catch); } elseif ($request->headers->has('expect')) { $response = $this->pass($request, $catch); } else { $response = $this->lookup($request, $catch); } $this->restoreResponseBody($request, $response); $response->setDate(new \DateTime(null, new \DateTimeZone('UTC'))); if (HttpKernelInterface::MASTER_REQUEST === $type && $this->options['debug']) { $response->headers->set('X-Symfony-Cache', $this->getLog()); } if (null !== $this->esi) { if (HttpKernelInterface::MASTER_REQUEST === $type) { $this->esiCacheStrategy->update($response); } else { $this->esiCacheStrategy->add($response); } } $response->prepare($request); $response->isNotModified($request); return $response; } /** * {@inheritdoc} * * @api */ public function terminate(Request $request, Response $response) { if ($this->getKernel() instanceof TerminableInterface) { $this->getKernel()->terminate($request, $response); } } /** * Forwards the Request to the backend without storing the Response in the cache. * * @param Request $request A Request instance * @param Boolean $catch Whether to process exceptions * * @return Response A Response instance */ protected function pass(Request $request, $catch = false) { $this->record($request, 'pass'); return $this->forward($request, $catch); } /** * Invalidates non-safe methods (like POST, PUT, and DELETE). * * @param Request $request A Request instance * @param Boolean $catch Whether to process exceptions * * @return Response A Response instance * * @throws \Exception * * @see RFC2616 13.10 */ protected function invalidate(Request $request, $catch = false) { $response = $this->pass($request, $catch); // invalidate only when the response is successful if ($response->isSuccessful() || $response->isRedirect()) { try { $this->store->invalidate($request, $catch); // As per the RFC, invalidate Location and Content-Location URLs if present foreach (array('Location', 'Content-Location') as $header) { if ($uri = $response->headers->get($header)) { $subRequest = Request::create($uri, 'get', array(), array(), array(), $request->server->all()); $this->store->invalidate($subRequest); } } $this->record($request, 'invalidate'); } catch (\Exception $e) { $this->record($request, 'invalidate-failed'); if ($this->options['debug']) { throw $e; } } } return $response; } /** * Lookups a Response from the cache for the given Request. * * When a matching cache entry is found and is fresh, it uses it as the * response without forwarding any request to the backend. When a matching * cache entry is found but is stale, it attempts to "validate" the entry with * the backend using conditional GET. When no matching cache entry is found, * it triggers "miss" processing. * * @param Request $request A Request instance * @param Boolean $catch whether to process exceptions * * @return Response A Response instance * * @throws \Exception */ protected function lookup(Request $request, $catch = false) { // if allow_reload and no-cache Cache-Control, allow a cache reload if ($this->options['allow_reload'] && $request->isNoCache()) { $this->record($request, 'reload'); return $this->fetch($request, $catch); } try { $entry = $this->store->lookup($request); } catch (\Exception $e) { $this->record($request, 'lookup-failed'); if ($this->options['debug']) { throw $e; } return $this->pass($request, $catch); } if (null === $entry) { $this->record($request, 'miss'); return $this->fetch($request, $catch); } if (!$this->isFreshEnough($request, $entry)) { $this->record($request, 'stale'); return $this->validate($request, $entry, $catch); } $this->record($request, 'fresh'); $entry->headers->set('Age', $entry->getAge()); return $entry; } /** * Validates that a cache entry is fresh. * * The original request is used as a template for a conditional * GET request with the backend. * * @param Request $request A Request instance * @param Response $entry A Response instance to validate * @param Boolean $catch Whether to process exceptions * * @return Response A Response instance */ protected function validate(Request $request, Response $entry, $catch = false) { $subRequest = clone $request; // send no head requests because we want content $subRequest->setMethod('GET'); // add our cached last-modified validator $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified')); // Add our cached etag validator to the environment. // We keep the etags from the client to handle the case when the client // has a different private valid entry which is not cached here. $cachedEtags = $entry->getEtag() ? array($entry->getEtag()) : array(); $requestEtags = $request->getEtags(); if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { $subRequest->headers->set('if_none_match', implode(', ', $etags)); } $response = $this->forward($subRequest, $catch, $entry); if (304 == $response->getStatusCode()) { $this->record($request, 'valid'); // return the response and not the cache entry if the response is valid but not cached $etag = $response->getEtag(); if ($etag && in_array($etag, $requestEtags) && !in_array($etag, $cachedEtags)) { return $response; } $entry = clone $entry; $entry->headers->remove('Date'); foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) { if ($response->headers->has($name)) { $entry->headers->set($name, $response->headers->get($name)); } } $response = $entry; } else { $this->record($request, 'invalid'); } if ($response->isCacheable()) { $this->store($request, $response); } return $response; } /** * Forwards the Request to the backend and determines whether the response should be stored. * * This methods is triggered when the cache missed or a reload is required. * * @param Request $request A Request instance * @param Boolean $catch whether to process exceptions * * @return Response A Response instance */ protected function fetch(Request $request, $catch = false) { $subRequest = clone $request; // send no head requests because we want content $subRequest->setMethod('GET'); // avoid that the backend sends no content $subRequest->headers->remove('if_modified_since'); $subRequest->headers->remove('if_none_match'); $response = $this->forward($subRequest, $catch); if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) { $response->setPrivate(true); } elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers->getCacheControlDirective('must-revalidate')) { $response->setTtl($this->options['default_ttl']); } if ($response->isCacheable()) { $this->store($request, $response); } return $response; } /** * Forwards the Request to the backend and returns the Response. * * @param Request $request A Request instance * @param Boolean $catch Whether to catch exceptions or not * @param Response $entry A Response instance (the stale entry if present, null otherwise) * * @return Response A Response instance */ protected function forward(Request $request, $catch = false, Response $entry = null) { if ($this->esi) { $this->esi->addSurrogateEsiCapability($request); } // modify the X-Forwarded-For header if needed $forwardedFor = $request->headers->get('X-Forwarded-For'); if ($forwardedFor) { $request->headers->set('X-Forwarded-For', $forwardedFor.', '.$request->server->get('REMOTE_ADDR')); } else { $request->headers->set('X-Forwarded-For', $request->server->get('REMOTE_ADDR')); } // fix the client IP address by setting it to 127.0.0.1 as HttpCache // is always called from the same process as the backend. $request->server->set('REMOTE_ADDR', '127.0.0.1'); // always a "master" request (as the real master request can be in cache) $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch); // FIXME: we probably need to also catch exceptions if raw === true // we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC if (null !== $entry && in_array($response->getStatusCode(), array(500, 502, 503, 504))) { if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) { $age = $this->options['stale_if_error']; } if (abs($entry->getTtl()) < $age) { $this->record($request, 'stale-if-error'); return $entry; } } $this->processResponseBody($request, $response); return $response; } /** * Checks whether the cache entry is "fresh enough" to satisfy the Request. * * @param Request $request A Request instance * @param Response $entry A Response instance * * @return Boolean true if the cache entry if fresh enough, false otherwise */ protected function isFreshEnough(Request $request, Response $entry) { if (!$entry->isFresh()) { return $this->lock($request, $entry); } if ($this->options['allow_revalidate'] && null !== $maxAge = $request->headers->getCacheControlDirective('max-age')) { return $maxAge > 0 && $maxAge >= $entry->getAge(); } return true; } /** * Locks a Request during the call to the backend. * * @param Request $request A Request instance * @param Response $entry A Response instance * * @return Boolean true if the cache entry can be returned even if it is staled, false otherwise */ protected function lock(Request $request, Response $entry) { // try to acquire a lock to call the backend $lock = $this->store->lock($request, $entry); // there is already another process calling the backend if (true !== $lock) { // check if we can serve the stale entry if (null === $age = $entry->headers->getCacheControlDirective('stale-while-revalidate')) { $age = $this->options['stale_while_revalidate']; } if (abs($entry->getTtl()) < $age) { $this->record($request, 'stale-while-revalidate'); // server the stale response while there is a revalidation return true; } // wait for the lock to be released $wait = 0; while ($this->store->isLocked($request) && $wait < 5000000) { usleep(50000); $wait += 50000; } if ($wait < 2000000) { // replace the current entry with the fresh one $new = $this->lookup($request); $entry->headers = $new->headers; $entry->setContent($new->getContent()); $entry->setStatusCode($new->getStatusCode()); $entry->setProtocolVersion($new->getProtocolVersion()); foreach ($new->headers->getCookies() as $cookie) { $entry->headers->setCookie($cookie); } } else { // backend is slow as hell, send a 503 response (to avoid the dog pile effect) $entry->setStatusCode(503); $entry->setContent('503 Service Unavailable'); $entry->headers->set('Retry-After', 10); } return true; } // we have the lock, call the backend return false; } /** * Writes the Response to the cache. * * @param Request $request A Request instance * @param Response $response A Response instance * * @throws \Exception */ protected function store(Request $request, Response $response) { try { $this->store->write($request, $response); $this->record($request, 'store'); $response->headers->set('Age', $response->getAge()); } catch (\Exception $e) { $this->record($request, 'store-failed'); if ($this->options['debug']) { throw $e; } } // now that the response is cached, release the lock $this->store->unlock($request); } /** * Restores the Response body. * * @param Request $request A Request instance * @param Response $response A Response instance * * @return Response A Response instance */ private function restoreResponseBody(Request $request, Response $response) { if ($request->isMethod('HEAD') || 304 === $response->getStatusCode()) { $response->setContent(null); $response->headers->remove('X-Body-Eval'); $response->headers->remove('X-Body-File'); return; } if ($response->headers->has('X-Body-Eval')) { ob_start(); if ($response->headers->has('X-Body-File')) { include $response->headers->get('X-Body-File'); } else { eval('; ?>'.$response->getContent().'setContent(ob_get_clean()); $response->headers->remove('X-Body-Eval'); if (!$response->headers->has('Transfer-Encoding')) { $response->headers->set('Content-Length', strlen($response->getContent())); } } elseif ($response->headers->has('X-Body-File')) { $response->setContent(file_get_contents($response->headers->get('X-Body-File'))); } else { return; } $response->headers->remove('X-Body-File'); } protected function processResponseBody(Request $request, Response $response) { if (null !== $this->esi && $this->esi->needsEsiParsing($response)) { $this->esi->process($request, $response); } } /** * Checks if the Request includes authorization or other sensitive information * that should cause the Response to be considered private by default. * * @param Request $request A Request instance * * @return Boolean true if the Request is private, false otherwise */ private function isPrivateRequest(Request $request) { foreach ($this->options['private_headers'] as $key) { $key = strtolower(str_replace('HTTP_', '', $key)); if ('cookie' === $key) { if (count($request->cookies->all())) { return true; } } elseif ($request->headers->has($key)) { return true; } } return false; } /** * Records that an event took place. * * @param Request $request A Request instance * @param string $event The event name */ private function record(Request $request, $event) { $path = $request->getPathInfo(); if ($qs = $request->getQueryString()) { $path .= '?'.$qs; } $this->traces[$request->getMethod().' '.$path][] = $event; } } PK!K:110Symfony/Component/HttpKernel/HttpCache/Store.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Store implements all the logic for storing cache metadata (Request and Response headers). * * @author Fabien Potencier */ class Store implements StoreInterface { protected $root; private $keyCache; private $locks; /** * Constructor. * * @param string $root The path to the cache directory */ public function __construct($root) { $this->root = $root; if (!is_dir($this->root)) { mkdir($this->root, 0777, true); } $this->keyCache = new \SplObjectStorage(); $this->locks = array(); } /** * Cleanups storage. */ public function cleanup() { // unlock everything foreach ($this->locks as $lock) { if (file_exists($lock)) { @unlink($lock); } } $error = error_get_last(); if (1 === $error['type'] && false === headers_sent()) { // send a 503 header('HTTP/1.0 503 Service Unavailable'); header('Retry-After: 10'); echo '503 Service Unavailable'; } } /** * Locks the cache for a given Request. * * @param Request $request A Request instance * * @return Boolean|string true if the lock is acquired, the path to the current lock otherwise */ public function lock(Request $request) { $path = $this->getPath($this->getCacheKey($request).'.lck'); if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true)) { return false; } $lock = @fopen($path, 'x'); if (false !== $lock) { fclose($lock); $this->locks[] = $path; return true; } return !file_exists($path) ?: $path; } /** * Releases the lock for the given Request. * * @param Request $request A Request instance * * @return Boolean False if the lock file does not exist or cannot be unlocked, true otherwise */ public function unlock(Request $request) { $file = $this->getPath($this->getCacheKey($request).'.lck'); return is_file($file) ? @unlink($file) : false; } public function isLocked(Request $request) { return is_file($this->getPath($this->getCacheKey($request).'.lck')); } /** * Locates a cached Response for the Request provided. * * @param Request $request A Request instance * * @return Response|null A Response instance, or null if no cache entry was found */ public function lookup(Request $request) { $key = $this->getCacheKey($request); if (!$entries = $this->getMetadata($key)) { return null; } // find a cached entry that matches the request. $match = null; foreach ($entries as $entry) { if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? $entry[1]['vary'][0] : '', $request->headers->all(), $entry[0])) { $match = $entry; break; } } if (null === $match) { return null; } list($req, $headers) = $match; if (is_file($body = $this->getPath($headers['x-content-digest'][0]))) { return $this->restoreResponse($headers, $body); } // TODO the metaStore referenced an entity that doesn't exist in // the entityStore. We definitely want to return nil but we should // also purge the entry from the meta-store when this is detected. return null; } /** * Writes a cache entry to the store for the given Request and Response. * * Existing entries are read and any that match the response are removed. This * method calls write with the new list of cache entries. * * @param Request $request A Request instance * @param Response $response A Response instance * * @return string The key under which the response is stored * * @throws \RuntimeException */ public function write(Request $request, Response $response) { $key = $this->getCacheKey($request); $storedEnv = $this->persistRequest($request); // write the response body to the entity store if this is the original response if (!$response->headers->has('X-Content-Digest')) { $digest = $this->generateContentDigest($response); if (false === $this->save($digest, $response->getContent())) { throw new \RuntimeException('Unable to store the entity.'); } $response->headers->set('X-Content-Digest', $digest); if (!$response->headers->has('Transfer-Encoding')) { $response->headers->set('Content-Length', strlen($response->getContent())); } } // read existing cache entries, remove non-varying, and add this one to the list $entries = array(); $vary = $response->headers->get('vary'); foreach ($this->getMetadata($key) as $entry) { if (!isset($entry[1]['vary'][0])) { $entry[1]['vary'] = array(''); } if ($vary != $entry[1]['vary'][0] || !$this->requestsMatch($vary, $entry[0], $storedEnv)) { $entries[] = $entry; } } $headers = $this->persistResponse($response); unset($headers['age']); array_unshift($entries, array($storedEnv, $headers)); if (false === $this->save($key, serialize($entries))) { throw new \RuntimeException('Unable to store the metadata.'); } return $key; } /** * Returns content digest for $response. * * @param Response $response * * @return string */ protected function generateContentDigest(Response $response) { return 'en'.hash('sha256', $response->getContent()); } /** * Invalidates all cache entries that match the request. * * @param Request $request A Request instance * * @throws \RuntimeException */ public function invalidate(Request $request) { $modified = false; $key = $this->getCacheKey($request); $entries = array(); foreach ($this->getMetadata($key) as $entry) { $response = $this->restoreResponse($entry[1]); if ($response->isFresh()) { $response->expire(); $modified = true; $entries[] = array($entry[0], $this->persistResponse($response)); } else { $entries[] = $entry; } } if ($modified) { if (false === $this->save($key, serialize($entries))) { throw new \RuntimeException('Unable to store the metadata.'); } } } /** * Determines whether two Request HTTP header sets are non-varying based on * the vary response header value provided. * * @param string $vary A Response vary header * @param array $env1 A Request HTTP header array * @param array $env2 A Request HTTP header array * * @return Boolean true if the two environments match, false otherwise */ private function requestsMatch($vary, $env1, $env2) { if (empty($vary)) { return true; } foreach (preg_split('/[\s,]+/', $vary) as $header) { $key = strtr(strtolower($header), '_', '-'); $v1 = isset($env1[$key]) ? $env1[$key] : null; $v2 = isset($env2[$key]) ? $env2[$key] : null; if ($v1 !== $v2) { return false; } } return true; } /** * Gets all data associated with the given key. * * Use this method only if you know what you are doing. * * @param string $key The store key * * @return array An array of data associated with the key */ private function getMetadata($key) { if (false === $entries = $this->load($key)) { return array(); } return unserialize($entries); } /** * Purges data for the given URL. * * @param string $url A URL * * @return Boolean true if the URL exists and has been purged, false otherwise */ public function purge($url) { if (is_file($path = $this->getPath($this->getCacheKey(Request::create($url))))) { unlink($path); return true; } return false; } /** * Loads data for the given key. * * @param string $key The store key * * @return string The data associated with the key */ private function load($key) { $path = $this->getPath($key); return is_file($path) ? file_get_contents($path) : false; } /** * Save data for the given key. * * @param string $key The store key * @param string $data The data to store * * @return Boolean */ private function save($key, $data) { $path = $this->getPath($key); if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true)) { return false; } $tmpFile = tempnam(dirname($path), basename($path)); if (false === $fp = @fopen($tmpFile, 'wb')) { return false; } @fwrite($fp, $data); @fclose($fp); if ($data != file_get_contents($tmpFile)) { return false; } if (false === @rename($tmpFile, $path)) { return false; } @chmod($path, 0666 & ~umask()); } public function getPath($key) { return $this->root.DIRECTORY_SEPARATOR.substr($key, 0, 2).DIRECTORY_SEPARATOR.substr($key, 2, 2).DIRECTORY_SEPARATOR.substr($key, 4, 2).DIRECTORY_SEPARATOR.substr($key, 6); } /** * Generates a cache key for the given Request. * * This method should return a key that must only depend on a * normalized version of the request URI. * * If the same URI can have more than one representation, based on some * headers, use a Vary header to indicate them, and each representation will * be stored independently under the same cache key. * * @param Request $request A Request instance * * @return string A key for the given Request */ protected function generateCacheKey(Request $request) { return 'md'.hash('sha256', $request->getUri()); } /** * Returns a cache key for the given Request. * * @param Request $request A Request instance * * @return string A key for the given Request */ private function getCacheKey(Request $request) { if (isset($this->keyCache[$request])) { return $this->keyCache[$request]; } return $this->keyCache[$request] = $this->generateCacheKey($request); } /** * Persists the Request HTTP headers. * * @param Request $request A Request instance * * @return array An array of HTTP headers */ private function persistRequest(Request $request) { return $request->headers->all(); } /** * Persists the Response HTTP headers. * * @param Response $response A Response instance * * @return array An array of HTTP headers */ private function persistResponse(Response $response) { $headers = $response->headers->all(); $headers['X-Status'] = array($response->getStatusCode()); return $headers; } /** * Restores a Response from the HTTP headers and body. * * @param array $headers An array of HTTP headers for the Response * @param string $body The Response body * * @return Response */ private function restoreResponse($headers, $body = null) { $status = $headers['X-Status'][0]; unset($headers['X-Status']); if (null !== $body) { $headers['X-Body-File'] = array($body); } return new Response($body, $status, $headers); } } PK!/) CSymfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.phpnu[ * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Response; /** * EsiResponseCacheStrategy knows how to compute the Response cache HTTP header * based on the different ESI response cache headers. * * This implementation changes the master response TTL to the smallest TTL received * or force validation if one of the ESI has validation cache strategy. * * @author Fabien Potencier */ class EsiResponseCacheStrategy implements EsiResponseCacheStrategyInterface { private $cacheable = true; private $embeddedResponses = 0; private $ttls = array(); private $maxAges = array(); /** * {@inheritdoc} */ public function add(Response $response) { if ($response->isValidateable()) { $this->cacheable = false; } else { $this->ttls[] = $response->getTtl(); $this->maxAges[] = $response->getMaxAge(); } $this->embeddedResponses++; } /** * {@inheritdoc} */ public function update(Response $response) { // if we have no embedded Response, do nothing if (0 === $this->embeddedResponses) { return; } // Remove validation related headers in order to avoid browsers using // their own cache, because some of the response content comes from // at least one embedded response (which likely has a different caching strategy). if ($response->isValidateable()) { $response->setEtag(null); $response->setLastModified(null); $this->cacheable = false; } if (!$this->cacheable) { $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); return; } $this->ttls[] = $response->getTtl(); $this->maxAges[] = $response->getMaxAge(); if (null !== $maxAge = min($this->maxAges)) { $response->setSharedMaxAge($maxAge); $response->headers->set('Age', $maxAge - min($this->ttls)); } $response->setMaxAge(0); } } PK!Jz*Symfony/Component/HttpKernel/UriSigner.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; /** * Signs URIs. * * @author Fabien Potencier */ class UriSigner { private $secret; /** * Constructor. * * @param string $secret A secret */ public function __construct($secret) { $this->secret = $secret; } /** * Signs a URI. * * The given URI is signed by adding a _hash query string parameter * which value depends on the URI and the secret. * * @param string $uri A URI to sign * * @return string The signed URI */ public function sign($uri) { return $uri.(false === (strpos($uri, '?')) ? '?' : '&').'_hash='.$this->computeHash($uri); } /** * Checks that a URI contains the correct hash. * * The _hash query string parameter must be the last one * (as it is generated that way by the sign() method, it should * never be a problem). * * @param string $uri A signed URI * * @return Boolean True if the URI is signed correctly, false otherwise */ public function check($uri) { if (!preg_match('/^(.*)(?:\?|&)_hash=(.+?)$/', $uri, $matches)) { return false; } return $this->computeHash($matches[1]) === $matches[2]; } private function computeHash($uri) { return urlencode(base64_encode(hash_hmac('sha256', $uri, $this->secret, true))); } } PK!d3Symfony/Component/HttpKernel/Config/FileLocator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Config; use Symfony\Component\Config\FileLocator as BaseFileLocator; use Symfony\Component\HttpKernel\KernelInterface; /** * FileLocator uses the KernelInterface to locate resources in bundles. * * @author Fabien Potencier */ class FileLocator extends BaseFileLocator { private $kernel; private $path; /** * Constructor. * * @param KernelInterface $kernel A KernelInterface instance * @param null|string $path The path the global resource directory * @param array $paths An array of paths where to look for resources */ public function __construct(KernelInterface $kernel, $path = null, array $paths = array()) { $this->kernel = $kernel; if (null !== $path) { $this->path = $path; $paths[] = $path; } parent::__construct($paths); } /** * {@inheritdoc} */ public function locate($file, $currentPath = null, $first = true) { if ('@' === $file[0]) { return $this->kernel->locateResource($file, $this->path, $first); } return parent::locate($file, $currentPath, $first); } } PK!!ll.Symfony/Component/HttpKernel/Bundle/Bundle.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Bundle; use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\Console\Application; use Symfony\Component\Finder\Finder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; /** * An implementation of BundleInterface that adds a few conventions * for DependencyInjection extensions and Console commands. * * @author Fabien Potencier * * @api */ abstract class Bundle extends ContainerAware implements BundleInterface { protected $name; protected $extension; protected $path; /** * Boots the Bundle. */ public function boot() { } /** * Shutdowns the Bundle. */ public function shutdown() { } /** * Builds the bundle. * * It is only ever called once when the cache is empty. * * This method can be overridden to register compilation passes, * other extensions, ... * * @param ContainerBuilder $container A ContainerBuilder instance */ public function build(ContainerBuilder $container) { } /** * Returns the bundle's container extension. * * @return ExtensionInterface|null The container extension * * @throws \LogicException * * @api */ public function getContainerExtension() { if (null === $this->extension) { $basename = preg_replace('/Bundle$/', '', $this->getName()); $class = $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension'; if (class_exists($class)) { $extension = new $class(); // check naming convention $expectedAlias = Container::underscore($basename); if ($expectedAlias != $extension->getAlias()) { throw new \LogicException(sprintf( 'The extension alias for the default extension of a '. 'bundle must be the underscored version of the '. 'bundle name ("%s" instead of "%s")', $expectedAlias, $extension->getAlias() )); } $this->extension = $extension; } else { $this->extension = false; } } if ($this->extension) { return $this->extension; } } /** * Gets the Bundle namespace. * * @return string The Bundle namespace * * @api */ public function getNamespace() { $class = get_class($this); return substr($class, 0, strrpos($class, '\\')); } /** * Gets the Bundle directory path. * * @return string The Bundle absolute path * * @api */ public function getPath() { if (null === $this->path) { $reflected = new \ReflectionObject($this); $this->path = dirname($reflected->getFileName()); } return $this->path; } /** * Returns the bundle parent name. * * @return string The Bundle parent name it overrides or null if no parent * * @api */ public function getParent() { return null; } /** * Returns the bundle name (the class short name). * * @return string The Bundle name * * @api */ final public function getName() { if (null !== $this->name) { return $this->name; } $name = get_class($this); $pos = strrpos($name, '\\'); return $this->name = false === $pos ? $name : substr($name, $pos + 1); } /** * Finds and registers Commands. * * Override this method if your bundle commands do not follow the conventions: * * * Commands are in the 'Command' sub-directory * * Commands extend Symfony\Component\Console\Command\Command * * @param Application $application An Application instance */ public function registerCommands(Application $application) { if (!is_dir($dir = $this->getPath().'/Command')) { return; } $finder = new Finder(); $finder->files()->name('*Command.php')->in($dir); $prefix = $this->getNamespace().'\\Command'; foreach ($finder as $file) { $ns = $prefix; if ($relativePath = $file->getRelativePath()) { $ns .= '\\'.strtr($relativePath, '/', '\\'); } $class = $ns.'\\'.$file->getBasename('.php'); if ($this->container) { $alias = 'console.command.'.strtolower(str_replace('\\', '_', $class)); if ($this->container->has($alias)) { continue; } } $r = new \ReflectionClass($class); if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) { $application->add($r->newInstance()); } } } } PK!3a7Symfony/Component/HttpKernel/Bundle/BundleInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Bundle; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; /** * BundleInterface. * * @author Fabien Potencier * * @api */ interface BundleInterface extends ContainerAwareInterface { /** * Boots the Bundle. * * @api */ public function boot(); /** * Shutdowns the Bundle. * * @api */ public function shutdown(); /** * Builds the bundle. * * It is only ever called once when the cache is empty. * * @param ContainerBuilder $container A ContainerBuilder instance * * @api */ public function build(ContainerBuilder $container); /** * Returns the container extension that should be implicitly loaded. * * @return ExtensionInterface|null The default extension or null if there is none * * @api */ public function getContainerExtension(); /** * Returns the bundle name that this bundle overrides. * * Despite its name, this method does not imply any parent/child relationship * between the bundles, just a way to extend and override an existing * bundle. * * @return string The Bundle name it overrides or null if no parent * * @api */ public function getParent(); /** * Returns the bundle name (the class short name). * * @return string The Bundle name * * @api */ public function getName(); /** * Gets the Bundle namespace. * * @return string The Bundle namespace * * @api */ public function getNamespace(); /** * Gets the Bundle directory path. * * The path should always be returned as a Unix path (with /). * * @return string The Bundle absolute path * * @api */ public function getPath(); } PK!BWzll@Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; class MongoDbProfilerStorage implements ProfilerStorageInterface { protected $dsn; protected $lifetime; private $mongo; /** * Constructor. * * @param string $dsn A data source name * @param string $username Not used * @param string $password Not used * @param integer $lifetime The lifetime to use for the purge */ public function __construct($dsn, $username = '', $password = '', $lifetime = 86400) { $this->dsn = $dsn; $this->lifetime = (int) $lifetime; } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { $cursor = $this->getMongo()->find($this->buildQuery($ip, $url, $method, $start, $end), array('_id', 'parent', 'ip', 'method', 'url', 'time'))->sort(array('time' => -1))->limit($limit); $tokens = array(); foreach ($cursor as $profile) { $tokens[] = $this->getData($profile); } return $tokens; } /** * {@inheritdoc} */ public function purge() { $this->getMongo()->remove(array()); } /** * {@inheritdoc} */ public function read($token) { $profile = $this->getMongo()->findOne(array('_id' => $token, 'data' => array('$exists' => true))); if (null !== $profile) { $profile = $this->createProfileFromData($this->getData($profile)); } return $profile; } /** * {@inheritdoc} */ public function write(Profile $profile) { $this->cleanup(); $record = array( '_id' => $profile->getToken(), 'parent' => $profile->getParentToken(), 'data' => base64_encode(serialize($profile->getCollectors())), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime() ); $result = $this->getMongo()->update(array('_id' => $profile->getToken()), array_filter($record, function ($v) { return !empty($v); }), array('upsert' => true)); return (boolean) (isset($result['ok']) ? $result['ok'] : $result); } /** * Internal convenience method that returns the instance of the MongoDB Collection * * @return \MongoCollection * * @throws \RuntimeException */ protected function getMongo() { if (null !== $this->mongo) { return $this->mongo; } if (!$parsedDsn = $this->parseDsn($this->dsn)) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use MongoDB with an invalid dsn "%s". The expected format is "mongodb://[user:pass@]host/database/collection"', $this->dsn)); } list($server, $database, $collection) = $parsedDsn; $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? '\Mongo' : '\MongoClient'; $mongo = new $mongoClass($server); return $this->mongo = $mongo->selectCollection($database, $collection); } /** * @param array $data * * @return Profile */ protected function createProfileFromData(array $data) { $profile = $this->getProfile($data); if ($data['parent']) { $parent = $this->getMongo()->findOne(array('_id' => $data['parent'], 'data' => array('$exists' => true))); if ($parent) { $profile->setParent($this->getProfile($this->getData($parent))); } } $profile->setChildren($this->readChildren($data['token'])); return $profile; } /** * @param string $token * * @return Profile[] An array of Profile instances */ protected function readChildren($token) { $profiles = array(); $cursor = $this->getMongo()->find(array('parent' => $token, 'data' => array('$exists' => true))); foreach ($cursor as $d) { $profiles[] = $this->getProfile($this->getData($d)); } return $profiles; } protected function cleanup() { $this->getMongo()->remove(array('time' => array('$lt' => time() - $this->lifetime))); } /** * @param string $ip * @param string $url * @param string $method * @param int $start * @param int $end * * @return array */ private function buildQuery($ip, $url, $method, $start, $end) { $query = array(); if (!empty($ip)) { $query['ip'] = $ip; } if (!empty($url)) { $query['url'] = $url; } if (!empty($method)) { $query['method'] = $method; } if (!empty($start) || !empty($end)) { $query['time'] = array(); } if (!empty($start)) { $query['time']['$gte'] = $start; } if (!empty($end)) { $query['time']['$lte'] = $end; } return $query; } /** * @param array $data * * @return array */ private function getData(array $data) { return array( 'token' => $data['_id'], 'parent' => isset($data['parent']) ? $data['parent'] : null, 'ip' => isset($data['ip']) ? $data['ip'] : null, 'method' => isset($data['method']) ? $data['method'] : null, 'url' => isset($data['url']) ? $data['url'] : null, 'time' => isset($data['time']) ? $data['time'] : null, 'data' => isset($data['data']) ? $data['data'] : null, ); } /** * @param array $data * * @return Profile */ private function getProfile(array $data) { $profile = new Profile($data['token']); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors(unserialize(base64_decode($data['data']))); return $profile; } /** * @param string $dsn * * @return null|array Array($server, $database, $collection) */ private function parseDsn($dsn) { if (!preg_match('#^(mongodb://.*)/(.*)/(.*)$#', $dsn, $matches)) { return; } $server = $matches[1]; $database = $matches[2]; $collection = $matches[3]; preg_match('#^mongodb://(([^:]+):?(.*)(?=@))?@?([^/]*)(.*)$#', $server, $matchesServer); if ('' == $matchesServer[5] && '' != $matches[2]) { $server .= '/'.$matches[2]; } return array($server, $database, $collection); } } PK!  2Symfony/Component/HttpKernel/Profiler/Profiler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Psr\Log\LoggerInterface; /** * Profiler. * * @author Fabien Potencier */ class Profiler { /** * @var ProfilerStorageInterface */ private $storage; /** * @var DataCollectorInterface[] */ private $collectors = array(); /** * @var LoggerInterface */ private $logger; /** * @var Boolean */ private $enabled = true; /** * Constructor. * * @param ProfilerStorageInterface $storage A ProfilerStorageInterface instance * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null) { $this->storage = $storage; $this->logger = $logger; } /** * Disables the profiler. */ public function disable() { $this->enabled = false; } /** * Enables the profiler. */ public function enable() { $this->enabled = true; } /** * Loads the Profile for the given Response. * * @param Response $response A Response instance * * @return Profile A Profile instance */ public function loadProfileFromResponse(Response $response) { if (!$token = $response->headers->get('X-Debug-Token')) { return false; } return $this->loadProfile($token); } /** * Loads the Profile for the given token. * * @param string $token A token * * @return Profile A Profile instance */ public function loadProfile($token) { return $this->storage->read($token); } /** * Saves a Profile. * * @param Profile $profile A Profile instance * * @return Boolean */ public function saveProfile(Profile $profile) { // late collect foreach ($profile->getCollectors() as $collector) { if ($collector instanceof LateDataCollectorInterface) { $collector->lateCollect(); } } if (!($ret = $this->storage->write($profile)) && null !== $this->logger) { $this->logger->warning('Unable to store the profiler information.'); } return $ret; } /** * Purges all data from the storage. */ public function purge() { $this->storage->purge(); } /** * Exports the current profiler data. * * @param Profile $profile A Profile instance * * @return string The exported data */ public function export(Profile $profile) { return base64_encode(serialize($profile)); } /** * Imports data into the profiler storage. * * @param string $data A data string as exported by the export() method * * @return Profile A Profile instance */ public function import($data) { $profile = unserialize(base64_decode($data)); if ($this->storage->read($profile->getToken())) { return false; } $this->saveProfile($profile); return $profile; } /** * Finds profiler tokens for the given criteria. * * @param string $ip The IP * @param string $url The URL * @param string $limit The maximum number of tokens to return * @param string $method The request method * @param string $start The start date to search from * @param string $end The end date to search to * * @return array An array of tokens * * @see http://fr2.php.net/manual/en/datetime.formats.php for the supported date/time formats */ public function find($ip, $url, $limit, $method, $start, $end) { if ('' != $start && null !== $start) { $start = new \DateTime($start); $start = $start->getTimestamp(); } else { $start = null; } if ('' != $end && null !== $end) { $end = new \DateTime($end); $end = $end->getTimestamp(); } else { $end = null; } return $this->storage->find($ip, $url, $limit, $method, $start, $end); } /** * Collects data for the given Response. * * @param Request $request A Request instance * @param Response $response A Response instance * @param \Exception $exception An exception instance if the request threw one * * @return Profile|null A Profile instance or null if the profiler is disabled */ public function collect(Request $request, Response $response, \Exception $exception = null) { if (false === $this->enabled) { return; } $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); $profile->setTime(time()); $profile->setUrl($request->getUri()); $profile->setIp($request->getClientIp()); $profile->setMethod($request->getMethod()); $response->headers->set('X-Debug-Token', $profile->getToken()); foreach ($this->collectors as $collector) { $collector->collect($request, $response, $exception); // we need to clone for sub-requests $profile->addCollector(clone $collector); } return $profile; } /** * Gets the Collectors associated with this profiler. * * @return array An array of collectors */ public function all() { return $this->collectors; } /** * Sets the Collectors associated with this profiler. * * @param DataCollectorInterface[] $collectors An array of collectors */ public function set(array $collectors = array()) { $this->collectors = array(); foreach ($collectors as $collector) { $this->add($collector); } } /** * Adds a Collector. * * @param DataCollectorInterface $collector A DataCollectorInterface instance */ public function add(DataCollectorInterface $collector) { $this->collectors[$collector->getName()] = $collector; } /** * Returns true if a Collector for the given name exists. * * @param string $name A collector name * * @return Boolean */ public function has($name) { return isset($this->collectors[$name]); } /** * Gets a Collector by name. * * @param string $name A collector name * * @return DataCollectorInterface A DataCollectorInterface instance * * @throws \InvalidArgumentException if the collector does not exist */ public function get($name) { if (!isset($this->collectors[$name])) { throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); } return $this->collectors[$name]; } } PK!$ BSymfony/Component/HttpKernel/Profiler/MemcachedProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Memcached Profiler Storage * * @author Andrej Hudec */ class MemcachedProfilerStorage extends BaseMemcacheProfilerStorage { /** * @var \Memcached */ private $memcached; /** * Internal convenience method that returns the instance of the Memcached * * @return \Memcached * * @throws \RuntimeException */ protected function getMemcached() { if (null === $this->memcached) { if (!preg_match('#^memcached://(?(?=\[.*\])\[(.*)\]|(.*)):(.*)$#', $this->dsn, $matches)) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Memcached with an invalid dsn "%s". The expected format is "memcached://[host]:port".', $this->dsn)); } $host = $matches[1] ?: $matches[2]; $port = $matches[3]; $memcached = new \Memcached(); // disable compression to allow appending $memcached->setOption(\Memcached::OPT_COMPRESSION, false); $memcached->addServer($host, $port); $this->memcached = $memcached; } return $this->memcached; } /** * Set instance of the Memcached * * @param \Memcached $memcached */ public function setMemcached($memcached) { $this->memcached = $memcached; } /** * {@inheritdoc} */ protected function getValue($key) { return $this->getMemcached()->get($key); } /** * {@inheritdoc} */ protected function setValue($key, $value, $expiration = 0) { return $this->getMemcached()->set($key, $value, time() + $expiration); } /** * {@inheritdoc} */ protected function delete($key) { return $this->getMemcached()->delete($key); } /** * {@inheritdoc} */ protected function appendValue($key, $value, $expiration = 0) { $memcached = $this->getMemcached(); if (!$result = $memcached->append($key, $value)) { return $memcached->set($key, $value, $expiration); } return $result; } } PK!rLUBSymfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * ProfilerStorageInterface. * * @author Fabien Potencier */ interface ProfilerStorageInterface { /** * Finds profiler tokens for the given criteria. * * @param string $ip The IP * @param string $url The URL * @param string $limit The maximum number of tokens to return * @param string $method The request method * @param int|null $start The start date to search from * @param int|null $end The end date to search to * * @return array An array of tokens */ public function find($ip, $url, $limit, $method, $start = null, $end = null); /** * Reads data associated with the given token. * * The method returns false if the token does not exist in the storage. * * @param string $token A token * * @return Profile The profile associated with token */ public function read($token); /** * Saves a Profile. * * @param Profile $profile A Profile instance * * @return Boolean Write operation successful */ public function write(Profile $profile); /** * Purges all data from the database. */ public function purge(); } PK!TsX X >Symfony/Component/HttpKernel/Profiler/MysqlProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * A ProfilerStorage for Mysql * * @author Jan Schumann */ class MysqlProfilerStorage extends PdoProfilerStorage { /** * {@inheritdoc} */ protected function initDb() { if (null === $this->db) { if (0 !== strpos($this->dsn, 'mysql')) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Mysql with an invalid dsn "%s". The expected format is "mysql:dbname=database_name;host=host_name".', $this->dsn)); } if (!class_exists('PDO') || !in_array('mysql', \PDO::getAvailableDrivers(), true)) { throw new \RuntimeException('You need to enable PDO_Mysql extension for the profiler to run properly.'); } $db = new \PDO($this->dsn, $this->username, $this->password); $db->exec('CREATE TABLE IF NOT EXISTS sf_profiler_data (token VARCHAR(255) PRIMARY KEY, data LONGTEXT, ip VARCHAR(64), method VARCHAR(6), url VARCHAR(255), time INTEGER UNSIGNED, parent VARCHAR(255), created_at INTEGER UNSIGNED, KEY (created_at), KEY (ip), KEY (method), KEY (url), KEY (parent))'); $this->db = $db; } return $this->db; } /** * {@inheritdoc} */ protected function buildCriteria($ip, $url, $start, $end, $limit, $method) { $criteria = array(); $args = array(); if ($ip = preg_replace('/[^\d\.]/', '', $ip)) { $criteria[] = 'ip LIKE :ip'; $args[':ip'] = '%'.$ip.'%'; } if ($url) { $criteria[] = 'url LIKE :url'; $args[':url'] = '%'.addcslashes($url, '%_\\').'%'; } if ($method) { $criteria[] = 'method = :method'; $args[':method'] = $method; } if (!empty($start)) { $criteria[] = 'time >= :start'; $args[':start'] = $start; } if (!empty($end)) { $criteria[] = 'time <= :end'; $args[':end'] = $end; } return array($criteria, $args); } } PK!N''>Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * RedisProfilerStorage stores profiling information in Redis. * * @author Andrej Hudec * @author Stephane PY */ class RedisProfilerStorage implements ProfilerStorageInterface { const TOKEN_PREFIX = 'sf_profiler_'; const REDIS_OPT_SERIALIZER = 1; const REDIS_OPT_PREFIX = 2; const REDIS_SERIALIZER_NONE = 0; const REDIS_SERIALIZER_PHP = 1; protected $dsn; protected $lifetime; /** * @var \Redis */ private $redis; /** * Constructor. * * @param string $dsn A data source name * @param string $username Not used * @param string $password Not used * @param int $lifetime The lifetime to use for the purge */ public function __construct($dsn, $username = '', $password = '', $lifetime = 86400) { $this->dsn = $dsn; $this->lifetime = (int) $lifetime; } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { $indexName = $this->getIndexName(); if (!$indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE)) { return array(); } $profileList = array_reverse(explode("\n", $indexContent)); $result = array(); foreach ($profileList as $item) { if ($limit === 0) { break; } if ($item == '') { continue; } list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = explode("\t", $item, 6); $itemTime = (int) $itemTime; if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) { continue; } if (!empty($start) && $itemTime < $start) { continue; } if (!empty($end) && $itemTime > $end) { continue; } $result[] = array( 'token' => $itemToken, 'ip' => $itemIp, 'method' => $itemMethod, 'url' => $itemUrl, 'time' => $itemTime, 'parent' => $itemParent, ); --$limit; } return $result; } /** * {@inheritdoc} */ public function purge() { // delete only items from index $indexName = $this->getIndexName(); $indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE); if (!$indexContent) { return false; } $profileList = explode("\n", $indexContent); $result = array(); foreach ($profileList as $item) { if ($item == '') { continue; } if (false !== $pos = strpos($item, "\t")) { $result[] = $this->getItemName(substr($item, 0, $pos)); } } $result[] = $indexName; return $this->delete($result); } /** * {@inheritdoc} */ public function read($token) { if (empty($token)) { return false; } $profile = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP); if (false !== $profile) { $profile = $this->createProfileFromData($token, $profile); } return $profile; } /** * {@inheritdoc} */ public function write(Profile $profile) { $data = array( 'token' => $profile->getToken(), 'parent' => $profile->getParentToken(), 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()), 'data' => $profile->getCollectors(), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime(), ); $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken())); if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime, self::REDIS_SERIALIZER_PHP)) { if (!$profileIndexed) { // Add to index $indexName = $this->getIndexName(); $indexRow = implode("\t", array( $profile->getToken(), $profile->getIp(), $profile->getMethod(), $profile->getUrl(), $profile->getTime(), $profile->getParentToken(), ))."\n"; return $this->appendValue($indexName, $indexRow, $this->lifetime); } return true; } return false; } /** * Internal convenience method that returns the instance of Redis. * * @return \Redis * * @throws \RuntimeException */ protected function getRedis() { if (null === $this->redis) { $data = parse_url($this->dsn); if (false === $data || !isset($data['scheme']) || $data['scheme'] !== 'redis' || !isset($data['host']) || !isset($data['port'])) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Redis with an invalid dsn "%s". The minimal expected format is "redis://[host]:port".', $this->dsn)); } if (!extension_loaded('redis')) { throw new \RuntimeException('RedisProfilerStorage requires that the redis extension is loaded.'); } $redis = new \Redis(); $redis->connect($data['host'], $data['port']); if (isset($data['path'])) { $redis->select(substr($data['path'], 1)); } if (isset($data['pass'])) { $redis->auth($data['pass']); } $redis->setOption(self::REDIS_OPT_PREFIX, self::TOKEN_PREFIX); $this->redis = $redis; } return $this->redis; } /** * Set instance of the Redis * * @param \Redis $redis */ public function setRedis($redis) { $this->redis = $redis; } private function createProfileFromData($token, $data, $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors($data['data']); if (!$parent && $data['parent']) { $parent = $this->read($data['parent']); } if ($parent) { $profile->setParent($parent); } foreach ($data['children'] as $token) { if (!$token) { continue; } if (!$childProfileData = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP)) { continue; } $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile)); } return $profile; } /** * Gets the item name. * * @param string $token * * @return string */ private function getItemName($token) { $name = $token; if ($this->isItemNameValid($name)) { return $name; } return false; } /** * Gets the name of the index. * * @return string */ private function getIndexName() { $name = 'index'; if ($this->isItemNameValid($name)) { return $name; } return false; } private function isItemNameValid($name) { $length = strlen($name); if ($length > 2147483648) { throw new \RuntimeException(sprintf('The Redis item key "%s" is too long (%s bytes). Allowed maximum size is 2^31 bytes.', $name, $length)); } return true; } /** * Retrieves an item from the Redis server. * * @param string $key * @param int $serializer * * @return mixed */ private function getValue($key, $serializer = self::REDIS_SERIALIZER_NONE) { $redis = $this->getRedis(); $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer); return $redis->get($key); } /** * Stores an item on the Redis server under the specified key. * * @param string $key * @param mixed $value * @param int $expiration * @param int $serializer * * @return Boolean */ private function setValue($key, $value, $expiration = 0, $serializer = self::REDIS_SERIALIZER_NONE) { $redis = $this->getRedis(); $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer); return $redis->setex($key, $expiration, $value); } /** * Appends data to an existing item on the Redis server. * * @param string $key * @param string $value * @param int $expiration * * @return Boolean */ private function appendValue($key, $value, $expiration = 0) { $redis = $this->getRedis(); $redis->setOption(self::REDIS_OPT_SERIALIZER, self::REDIS_SERIALIZER_NONE); if ($redis->exists($key)) { $redis->append($key, $value); return $redis->setTimeout($key, $expiration); } return $redis->setex($key, $expiration, $value); } /** * Removes the specified keys. * * @param array $keys * * @return Boolean */ private function delete(array $keys) { return (bool) $this->getRedis()->delete($keys); } } PK!<Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Base PDO storage for profiling information in a PDO database. * * @author Fabien Potencier * @author Jan Schumann */ abstract class PdoProfilerStorage implements ProfilerStorageInterface { protected $dsn; protected $username; protected $password; protected $lifetime; protected $db; /** * Constructor. * * @param string $dsn A data source name * @param string $username The username for the database * @param string $password The password for the database * @param integer $lifetime The lifetime to use for the purge */ public function __construct($dsn, $username = '', $password = '', $lifetime = 86400) { $this->dsn = $dsn; $this->username = $username; $this->password = $password; $this->lifetime = (int) $lifetime; } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { if (null === $start) { $start = 0; } if (null === $end) { $end = time(); } list($criteria, $args) = $this->buildCriteria($ip, $url, $start, $end, $limit, $method); $criteria = $criteria ? 'WHERE '.implode(' AND ', $criteria) : ''; $db = $this->initDb(); $tokens = $this->fetch($db, 'SELECT token, ip, method, url, time, parent FROM sf_profiler_data '.$criteria.' ORDER BY time DESC LIMIT '.((integer) $limit), $args); $this->close($db); return $tokens; } /** * {@inheritdoc} */ public function read($token) { $db = $this->initDb(); $args = array(':token' => $token); $data = $this->fetch($db, 'SELECT data, parent, ip, method, url, time FROM sf_profiler_data WHERE token = :token LIMIT 1', $args); $this->close($db); if (isset($data[0]['data'])) { return $this->createProfileFromData($token, $data[0]); } return null; } /** * {@inheritdoc} */ public function write(Profile $profile) { $db = $this->initDb(); $args = array( ':token' => $profile->getToken(), ':parent' => $profile->getParentToken(), ':data' => base64_encode(serialize($profile->getCollectors())), ':ip' => $profile->getIp(), ':method' => $profile->getMethod(), ':url' => $profile->getUrl(), ':time' => $profile->getTime(), ':created_at' => time(), ); try { if ($this->has($profile->getToken())) { $this->exec($db, 'UPDATE sf_profiler_data SET parent = :parent, data = :data, ip = :ip, method = :method, url = :url, time = :time, created_at = :created_at WHERE token = :token', $args); } else { $this->exec($db, 'INSERT INTO sf_profiler_data (token, parent, data, ip, method, url, time, created_at) VALUES (:token, :parent, :data, :ip, :method, :url, :time, :created_at)', $args); } $this->cleanup(); $status = true; } catch (\Exception $e) { $status = false; } $this->close($db); return $status; } /** * {@inheritdoc} */ public function purge() { $db = $this->initDb(); $this->exec($db, 'DELETE FROM sf_profiler_data'); $this->close($db); } /** * Build SQL criteria to fetch records by ip and url * * @param string $ip The IP * @param string $url The URL * @param string $start The start period to search from * @param string $end The end period to search to * @param string $limit The maximum number of tokens to return * @param string $method The request method * * @return array An array with (criteria, args) */ abstract protected function buildCriteria($ip, $url, $start, $end, $limit, $method); /** * Initializes the database * * @throws \RuntimeException When the requested database driver is not installed */ abstract protected function initDb(); protected function cleanup() { $db = $this->initDb(); $this->exec($db, 'DELETE FROM sf_profiler_data WHERE created_at < :time', array(':time' => time() - $this->lifetime)); $this->close($db); } protected function exec($db, $query, array $args = array()) { $stmt = $this->prepareStatement($db, $query); foreach ($args as $arg => $val) { $stmt->bindValue($arg, $val, is_int($val) ? \PDO::PARAM_INT : \PDO::PARAM_STR); } $success = $stmt->execute(); if (!$success) { throw new \RuntimeException(sprintf('Error executing query "%s"', $query)); } } protected function prepareStatement($db, $query) { try { $stmt = $db->prepare($query); } catch (\Exception $e) { $stmt = false; } if (false === $stmt) { throw new \RuntimeException('The database cannot successfully prepare the statement'); } return $stmt; } protected function fetch($db, $query, array $args = array()) { $stmt = $this->prepareStatement($db, $query); foreach ($args as $arg => $val) { $stmt->bindValue($arg, $val, is_int($val) ? \PDO::PARAM_INT : \PDO::PARAM_STR); } $stmt->execute(); $return = $stmt->fetchAll(\PDO::FETCH_ASSOC); return $return; } protected function close($db) { } protected function createProfileFromData($token, $data, $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors(unserialize(base64_decode($data['data']))); if (!$parent && !empty($data['parent'])) { $parent = $this->read($data['parent']); } if ($parent) { $profile->setParent($parent); } $profile->setChildren($this->readChildren($token, $profile)); return $profile; } /** * Reads the child profiles for the given token. * * @param string $token The parent token * @param string $parent The parent instance * * @return Profile[] An array of Profile instance */ protected function readChildren($token, $parent) { $db = $this->initDb(); $data = $this->fetch($db, 'SELECT token, data, ip, method, url, time FROM sf_profiler_data WHERE parent = :token', array(':token' => $token)); $this->close($db); if (!$data) { return array(); } $profiles = array(); foreach ($data as $d) { $profiles[] = $this->createProfileFromData($d['token'], $d, $parent); } return $profiles; } /** * Returns whether data for the given token already exists in storage. * * @param string $token The profile token * * @return string */ protected function has($token) { $db = $this->initDb(); $tokenExists = $this->fetch($db, 'SELECT 1 FROM sf_profiler_data WHERE token = :token LIMIT 1', array(':token' => $token)); $this->close($db); return !empty($tokenExists); } } PK!iY~2 2 ASymfony/Component/HttpKernel/Profiler/MemcacheProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Memcache Profiler Storage * * @author Andrej Hudec */ class MemcacheProfilerStorage extends BaseMemcacheProfilerStorage { /** * @var \Memcache */ private $memcache; /** * Internal convenience method that returns the instance of the Memcache * * @return \Memcache * * @throws \RuntimeException */ protected function getMemcache() { if (null === $this->memcache) { if (!preg_match('#^memcache://(?(?=\[.*\])\[(.*)\]|(.*)):(.*)$#', $this->dsn, $matches)) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Memcache with an invalid dsn "%s". The expected format is "memcache://[host]:port".', $this->dsn)); } $host = $matches[1] ?: $matches[2]; $port = $matches[3]; $memcache = new \Memcache(); $memcache->addServer($host, $port); $this->memcache = $memcache; } return $this->memcache; } /** * Set instance of the Memcache * * @param \Memcache $memcache */ public function setMemcache($memcache) { $this->memcache = $memcache; } /** * {@inheritdoc} */ protected function getValue($key) { return $this->getMemcache()->get($key); } /** * {@inheritdoc} */ protected function setValue($key, $value, $expiration = 0) { return $this->getMemcache()->set($key, $value, false, time() + $expiration); } /** * {@inheritdoc} */ protected function delete($key) { return $this->getMemcache()->delete($key); } /** * {@inheritdoc} */ protected function appendValue($key, $value, $expiration = 0) { $memcache = $this->getMemcache(); if (method_exists($memcache, 'append')) { // Memcache v3.0 if (!$result = $memcache->append($key, $value, false, $expiration)) { return $memcache->set($key, $value, false, $expiration); } return $result; } // simulate append in Memcache <3.0 $content = $memcache->get($key); return $memcache->set($key, $content.$value, false, $expiration); } } PK! 1Symfony/Component/HttpKernel/Profiler/Profile.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; /** * Profile. * * @author Fabien Potencier */ class Profile { private $token; /** * @var DataCollectorInterface[] */ private $collectors = array(); private $ip; private $method; private $url; private $time; /** * @var Profile */ private $parent; /** * @var Profile[] */ private $children = array(); /** * Constructor. * * @param string $token The token */ public function __construct($token) { $this->token = $token; } /** * Sets the token. * * @param string $token The token */ public function setToken($token) { $this->token = $token; } /** * Gets the token. * * @return string The token */ public function getToken() { return $this->token; } /** * Sets the parent token * * @param Profile $parent The parent Profile */ public function setParent(Profile $parent) { $this->parent = $parent; } /** * Returns the parent profile. * * @return Profile The parent profile */ public function getParent() { return $this->parent; } /** * Returns the parent token. * * @return null|string The parent token */ public function getParentToken() { return $this->parent ? $this->parent->getToken() : null; } /** * Returns the IP. * * @return string The IP */ public function getIp() { return $this->ip; } /** * Sets the IP. * * @param string $ip */ public function setIp($ip) { $this->ip = $ip; } /** * Returns the request method. * * @return string The request method */ public function getMethod() { return $this->method; } public function setMethod($method) { $this->method = $method; } /** * Returns the URL. * * @return string The URL */ public function getUrl() { return $this->url; } public function setUrl($url) { $this->url = $url; } /** * Returns the time. * * @return string The time */ public function getTime() { if (null === $this->time) { return 0; } return $this->time; } public function setTime($time) { $this->time = $time; } /** * Finds children profilers. * * @return Profile[] An array of Profile */ public function getChildren() { return $this->children; } /** * Sets children profiler. * * @param Profile[] $children An array of Profile */ public function setChildren(array $children) { $this->children = array(); foreach ($children as $child) { $this->addChild($child); } } /** * Adds the child token * * @param Profile $child The child Profile */ public function addChild(Profile $child) { $this->children[] = $child; $child->setParent($this); } /** * Gets a Collector by name. * * @param string $name A collector name * * @return DataCollectorInterface A DataCollectorInterface instance * * @throws \InvalidArgumentException if the collector does not exist */ public function getCollector($name) { if (!isset($this->collectors[$name])) { throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); } return $this->collectors[$name]; } /** * Gets the Collectors associated with this profile. * * @return DataCollectorInterface[] */ public function getCollectors() { return $this->collectors; } /** * Sets the Collectors associated with this profile. * * @param DataCollectorInterface[] $collectors */ public function setCollectors(array $collectors) { $this->collectors = array(); foreach ($collectors as $collector) { $this->addCollector($collector); } } /** * Adds a Collector. * * @param DataCollectorInterface $collector A DataCollectorInterface instance */ public function addCollector(DataCollectorInterface $collector) { $this->collectors[$collector->getName()] = $collector; } /** * Returns true if a Collector for the given name exists. * * @param string $name A collector name * * @return Boolean */ public function hasCollector($name) { return isset($this->collectors[$name]); } public function __sleep() { return array('token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time'); } } PK!tESymfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Base Memcache storage for profiling information in a Memcache. * * @author Andrej Hudec */ abstract class BaseMemcacheProfilerStorage implements ProfilerStorageInterface { const TOKEN_PREFIX = 'sf_profiler_'; protected $dsn; protected $lifetime; /** * Constructor. * * @param string $dsn A data source name * @param string $username * @param string $password * @param int $lifetime The lifetime to use for the purge */ public function __construct($dsn, $username = '', $password = '', $lifetime = 86400) { $this->dsn = $dsn; $this->lifetime = (int) $lifetime; } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { $indexName = $this->getIndexName(); $indexContent = $this->getValue($indexName); if (!$indexContent) { return array(); } $profileList = explode("\n", $indexContent); $result = array(); foreach ($profileList as $item) { if ($limit === 0) { break; } if ($item=='') { continue; } list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = explode("\t", $item, 6); $itemTime = (int) $itemTime; if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) { continue; } if (!empty($start) && $itemTime < $start) { continue; } if (!empty($end) && $itemTime > $end) { continue; } $result[$itemToken] = array( 'token' => $itemToken, 'ip' => $itemIp, 'method' => $itemMethod, 'url' => $itemUrl, 'time' => $itemTime, 'parent' => $itemParent, ); --$limit; } usort($result, function ($a, $b) { if ($a['time'] === $b['time']) { return 0; } return $a['time'] > $b['time'] ? -1 : 1; }); return $result; } /** * {@inheritdoc} */ public function purge() { // delete only items from index $indexName = $this->getIndexName(); $indexContent = $this->getValue($indexName); if (!$indexContent) { return false; } $profileList = explode("\n", $indexContent); foreach ($profileList as $item) { if ($item == '') { continue; } if (false !== $pos = strpos($item, "\t")) { $this->delete($this->getItemName(substr($item, 0, $pos))); } } return $this->delete($indexName); } /** * {@inheritdoc} */ public function read($token) { if (empty($token)) { return false; } $profile = $this->getValue($this->getItemName($token)); if (false !== $profile) { $profile = $this->createProfileFromData($token, $profile); } return $profile; } /** * {@inheritdoc} */ public function write(Profile $profile) { $data = array( 'token' => $profile->getToken(), 'parent' => $profile->getParentToken(), 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()), 'data' => $profile->getCollectors(), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime(), ); $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken())); if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime)) { if (!$profileIndexed) { // Add to index $indexName = $this->getIndexName(); $indexRow = implode("\t", array( $profile->getToken(), $profile->getIp(), $profile->getMethod(), $profile->getUrl(), $profile->getTime(), $profile->getParentToken(), ))."\n"; return $this->appendValue($indexName, $indexRow, $this->lifetime); } return true; } return false; } /** * Retrieve item from the memcache server * * @param string $key * * @return mixed */ abstract protected function getValue($key); /** * Store an item on the memcache server under the specified key * * @param string $key * @param mixed $value * @param int $expiration * * @return boolean */ abstract protected function setValue($key, $value, $expiration = 0); /** * Delete item from the memcache server * * @param string $key * * @return boolean */ abstract protected function delete($key); /** * Append data to an existing item on the memcache server * @param string $key * @param string $value * @param int $expiration * * @return boolean */ abstract protected function appendValue($key, $value, $expiration = 0); private function createProfileFromData($token, $data, $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors($data['data']); if (!$parent && $data['parent']) { $parent = $this->read($data['parent']); } if ($parent) { $profile->setParent($parent); } foreach ($data['children'] as $token) { if (!$token) { continue; } if (!$childProfileData = $this->getValue($this->getItemName($token))) { continue; } $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile)); } return $profile; } /** * Get item name * * @param string $token * * @return string */ private function getItemName($token) { $name = self::TOKEN_PREFIX.$token; if ($this->isItemNameValid($name)) { return $name; } return false; } /** * Get name of index * * @return string */ private function getIndexName() { $name = self::TOKEN_PREFIX.'index'; if ($this->isItemNameValid($name)) { return $name; } return false; } private function isItemNameValid($name) { $length = strlen($name); if ($length > 250) { throw new \RuntimeException(sprintf('The memcache item key "%s" is too long (%s bytes). Allowed maximum size is 250 bytes.', $name, $length)); } return true; } } PK!t}[?Symfony/Component/HttpKernel/Profiler/SqliteProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * SqliteProfilerStorage stores profiling information in a SQLite database. * * @author Fabien Potencier */ class SqliteProfilerStorage extends PdoProfilerStorage { /** * @throws \RuntimeException When neither of SQLite3 or PDO_SQLite extension is enabled */ protected function initDb() { if (null === $this->db || $this->db instanceof \SQLite3) { if (0 !== strpos($this->dsn, 'sqlite')) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Sqlite with an invalid dsn "%s". The expected format is "sqlite:/path/to/the/db/file".', $this->dsn)); } if (class_exists('SQLite3')) { $db = new \SQLite3(substr($this->dsn, 7, strlen($this->dsn)), \SQLITE3_OPEN_READWRITE | \SQLITE3_OPEN_CREATE); if (method_exists($db, 'busyTimeout')) { // busyTimeout only exists for PHP >= 5.3.3 $db->busyTimeout(1000); } } elseif (class_exists('PDO') && in_array('sqlite', \PDO::getAvailableDrivers(), true)) { $db = new \PDO($this->dsn); } else { throw new \RuntimeException('You need to enable either the SQLite3 or PDO_SQLite extension for the profiler to run properly.'); } $db->exec('PRAGMA temp_store=MEMORY; PRAGMA journal_mode=MEMORY;'); $db->exec('CREATE TABLE IF NOT EXISTS sf_profiler_data (token STRING, data STRING, ip STRING, method STRING, url STRING, time INTEGER, parent STRING, created_at INTEGER)'); $db->exec('CREATE INDEX IF NOT EXISTS data_created_at ON sf_profiler_data (created_at)'); $db->exec('CREATE INDEX IF NOT EXISTS data_ip ON sf_profiler_data (ip)'); $db->exec('CREATE INDEX IF NOT EXISTS data_method ON sf_profiler_data (method)'); $db->exec('CREATE INDEX IF NOT EXISTS data_url ON sf_profiler_data (url)'); $db->exec('CREATE INDEX IF NOT EXISTS data_parent ON sf_profiler_data (parent)'); $db->exec('CREATE UNIQUE INDEX IF NOT EXISTS data_token ON sf_profiler_data (token)'); $this->db = $db; } return $this->db; } protected function exec($db, $query, array $args = array()) { if ($db instanceof \SQLite3) { $stmt = $this->prepareStatement($db, $query); foreach ($args as $arg => $val) { $stmt->bindValue($arg, $val, is_int($val) ? \SQLITE3_INTEGER : \SQLITE3_TEXT); } $res = $stmt->execute(); if (false === $res) { throw new \RuntimeException(sprintf('Error executing SQLite query "%s"', $query)); } $res->finalize(); } else { parent::exec($db, $query, $args); } } protected function fetch($db, $query, array $args = array()) { $return = array(); if ($db instanceof \SQLite3) { $stmt = $this->prepareStatement($db, $query, true); foreach ($args as $arg => $val) { $stmt->bindValue($arg, $val, is_int($val) ? \SQLITE3_INTEGER : \SQLITE3_TEXT); } $res = $stmt->execute(); while ($row = $res->fetchArray(\SQLITE3_ASSOC)) { $return[] = $row; } $res->finalize(); $stmt->close(); } else { $return = parent::fetch($db, $query, $args); } return $return; } /** * {@inheritdoc} */ protected function buildCriteria($ip, $url, $start, $end, $limit, $method) { $criteria = array(); $args = array(); if ($ip = preg_replace('/[^\d\.]/', '', $ip)) { $criteria[] = 'ip LIKE :ip'; $args[':ip'] = '%'.$ip.'%'; } if ($url) { $criteria[] = 'url LIKE :url ESCAPE "\"'; $args[':url'] = '%'.addcslashes($url, '%_\\').'%'; } if ($method) { $criteria[] = 'method = :method'; $args[':method'] = $method; } if (!empty($start)) { $criteria[] = 'time >= :start'; $args[':start'] = $start; } if (!empty($end)) { $criteria[] = 'time <= :end'; $args[':end'] = $end; } return array($criteria, $args); } protected function close($db) { if ($db instanceof \SQLite3) { $db->close(); } } } PK!\Y`=Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Storage for profiler using files. * * @author Alexandre Salomé */ class FileProfilerStorage implements ProfilerStorageInterface { /** * Folder where profiler data are stored. * * @var string */ private $folder; /** * Constructs the file storage using a "dsn-like" path. * * Example : "file:/path/to/the/storage/folder" * * @param string $dsn The DSN * * @throws \RuntimeException */ public function __construct($dsn) { if (0 !== strpos($dsn, 'file:')) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn)); } $this->folder = substr($dsn, 5); if (!is_dir($this->folder)) { mkdir($this->folder, 0777, true); } } /** * {@inheritdoc} */ public function find($ip, $url, $limit, $method, $start = null, $end = null) { $file = $this->getIndexFilename(); if (!file_exists($file)) { return array(); } $file = fopen($file, 'r'); fseek($file, 0, SEEK_END); $result = array(); while (count($result) < $limit && $line = $this->readLineFromFile($file)) { list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent) = str_getcsv($line); $csvTime = (int) $csvTime; if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method)) { continue; } if (!empty($start) && $csvTime < $start) { continue; } if (!empty($end) && $csvTime > $end) { continue; } $result[$csvToken] = array( 'token' => $csvToken, 'ip' => $csvIp, 'method' => $csvMethod, 'url' => $csvUrl, 'time' => $csvTime, 'parent' => $csvParent, ); } fclose($file); return array_values($result); } /** * {@inheritdoc} */ public function purge() { $flags = \FilesystemIterator::SKIP_DOTS; $iterator = new \RecursiveDirectoryIterator($this->folder, $flags); $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST); foreach ($iterator as $file) { if (is_file($file)) { unlink($file); } else { rmdir($file); } } } /** * {@inheritdoc} */ public function read($token) { if (!$token || !file_exists($file = $this->getFilename($token))) { return null; } return $this->createProfileFromData($token, unserialize(file_get_contents($file))); } /** * {@inheritdoc} */ public function write(Profile $profile) { $file = $this->getFilename($profile->getToken()); $profileIndexed = is_file($file); if (!$profileIndexed) { // Create directory $dir = dirname($file); if (!is_dir($dir)) { mkdir($dir, 0777, true); } } // Store profile $data = array( 'token' => $profile->getToken(), 'parent' => $profile->getParentToken(), 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()), 'data' => $profile->getCollectors(), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime(), ); if (false === file_put_contents($file, serialize($data))) { return false; } if (!$profileIndexed) { // Add to index if (false === $file = fopen($this->getIndexFilename(), 'a')) { return false; } fputcsv($file, array( $profile->getToken(), $profile->getIp(), $profile->getMethod(), $profile->getUrl(), $profile->getTime(), $profile->getParentToken(), )); fclose($file); } return true; } /** * Gets filename to store data, associated to the token. * * @param string $token * * @return string The profile filename */ protected function getFilename($token) { // Uses 4 last characters, because first are mostly the same. $folderA = substr($token, -2, 2); $folderB = substr($token, -4, 2); return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token; } /** * Gets the index filename. * * @return string The index filename */ protected function getIndexFilename() { return $this->folder.'/index.csv'; } /** * Reads a line in the file, backward. * * This function automatically skips the empty lines and do not include the line return in result value. * * @param resource $file The file resource, with the pointer placed at the end of the line to read * * @return mixed A string representing the line or null if beginning of file is reached */ protected function readLineFromFile($file) { $line = ''; $position = ftell($file); if (0 === $position) { return null; } while (true) { $chunkSize = min($position, 1024); $position -= $chunkSize; fseek($file, $position); if (0 === $chunkSize) { // bof reached break; } $buffer = fread($file, $chunkSize); if (false === ($upTo = strrpos($buffer, "\n"))) { $line = $buffer.$line; continue; } $position += $upTo; $line = substr($buffer, $upTo + 1).$line; fseek($file, max(0, $position), SEEK_SET); if ('' !== $line) { break; } } return '' === $line ? null : $line; } protected function createProfileFromData($token, $data, $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setCollectors($data['data']); if (!$parent && $data['parent']) { $parent = $this->read($data['parent']); } if ($parent) { $profile->setParent($parent); } foreach ($data['children'] as $token) { if (!$token || !file_exists($file = $this->getFilename($token))) { continue; } $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile)); } return $profile; } } PK!,&&8Symfony/Component/HttpKernel/Event/PostResponseEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Allows to execute logic after a response was sent * * @author Jordi Boggiano */ class PostResponseEvent extends Event { /** * The kernel in which this event was thrown * @var HttpKernelInterface */ private $kernel; private $request; private $response; public function __construct(HttpKernelInterface $kernel, Request $request, Response $response) { $this->kernel = $kernel; $this->request = $request; $this->response = $response; } /** * Returns the kernel in which this event was thrown. * * @return HttpKernelInterface */ public function getKernel() { return $this->kernel; } /** * Returns the request for which this event was thrown. * * @return Request */ public function getRequest() { return $this->request; } /** * Returns the response for which this event was thrown. * * @return Response */ public function getResponse() { return $this->response; } } PK! 79Symfony/Component/HttpKernel/Event/FinishRequestEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; /** * Triggered whenever a request is fully processed. * * @author Benjamin Eberlei */ class FinishRequestEvent extends KernelEvent { } PK!`g:Symfony/Component/HttpKernel/Event/FilterResponseEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Allows to filter a Response object * * You can call getResponse() to retrieve the current response. With * setResponse() you can set a new response that will be returned to the * browser. * * @author Bernhard Schussek * * @api */ class FilterResponseEvent extends KernelEvent { /** * The current response object * @var Response */ private $response; public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, Response $response) { parent::__construct($kernel, $request, $requestType); $this->setResponse($response); } /** * Returns the current response object * * @return Response * * @api */ public function getResponse() { return $this->response; } /** * Sets a new response object * * @param Response $response * * @api */ public function setResponse(Response $response) { $this->response = $response; } } PK!٨.kkJSymfony/Component/HttpKernel/Event/GetResponseForControllerResultEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; /** * Allows to create a response for the return value of a controller * * Call setResponse() to set the response that will be returned for the * current request. The propagation of this event is stopped as soon as a * response is set. * * @author Bernhard Schussek * * @api */ class GetResponseForControllerResultEvent extends GetResponseEvent { /** * The return value of the controller * * @var mixed */ private $controllerResult; public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, $controllerResult) { parent::__construct($kernel, $request, $requestType); $this->controllerResult = $controllerResult; } /** * Returns the return value of the controller. * * @return mixed The controller return value * * @api */ public function getControllerResult() { return $this->controllerResult; } /** * Assigns the return value of the controller. * * @param mixed $controllerResult The controller return value * * @api */ public function setControllerResult($controllerResult) { $this->controllerResult = $controllerResult; } } PK!9I7Symfony/Component/HttpKernel/Event/GetResponseEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Response; /** * Allows to create a response for a request * * Call setResponse() to set the response that will be returned for the * current request. The propagation of this event is stopped as soon as a * response is set. * * @author Bernhard Schussek * * @api */ class GetResponseEvent extends KernelEvent { /** * The response object * @var Response */ private $response; /** * Returns the response object * * @return Response * * @api */ public function getResponse() { return $this->response; } /** * Sets a response and stops event propagation * * @param Response $response * * @api */ public function setResponse(Response $response) { $this->response = $response; $this->stopPropagation(); } /** * Returns whether a response was set * * @return Boolean Whether a response was set * * @api */ public function hasResponse() { return null !== $this->response; } } PK!9CSymfony/Component/HttpKernel/Event/GetResponseForExceptionEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; /** * Allows to create a response for a thrown exception * * Call setResponse() to set the response that will be returned for the * current request. The propagation of this event is stopped as soon as a * response is set. * * You can also call setException() to replace the thrown exception. This * exception will be thrown if no response is set during processing of this * event. * * @author Bernhard Schussek * * @api */ class GetResponseForExceptionEvent extends GetResponseEvent { /** * The exception object * @var \Exception */ private $exception; public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, \Exception $e) { parent::__construct($kernel, $request, $requestType); $this->setException($e); } /** * Returns the thrown exception * * @return \Exception The thrown exception * * @api */ public function getException() { return $this->exception; } /** * Replaces the thrown exception * * This exception will be thrown if no response is set in the event. * * @param \Exception $exception The thrown exception * * @api */ public function setException(\Exception $exception) { $this->exception = $exception; } } PK!% <Symfony/Component/HttpKernel/Event/FilterControllerEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; /** * Allows filtering of a controller callable * * You can call getController() to retrieve the current controller. With * setController() you can set a new controller that is used in the processing * of the request. * * Controllers should be callables. * * @author Bernhard Schussek * * @api */ class FilterControllerEvent extends KernelEvent { /** * The current controller * @var callable */ private $controller; public function __construct(HttpKernelInterface $kernel, $controller, Request $request, $requestType) { parent::__construct($kernel, $request, $requestType); $this->setController($controller); } /** * Returns the current controller * * @return callable * * @api */ public function getController() { return $this->controller; } /** * Sets a new controller * * @param callable $controller * * @throws \LogicException * * @api */ public function setController($controller) { // controller must be a callable if (!is_callable($controller)) { throw new \LogicException(sprintf('The controller must be a callable (%s given).', $this->varToString($controller))); } $this->controller = $controller; } private function varToString($var) { if (is_object($var)) { return sprintf('Object(%s)', get_class($var)); } if (is_array($var)) { $a = array(); foreach ($var as $k => $v) { $a[] = sprintf('%s => %s', $k, $this->varToString($v)); } return sprintf("Array(%s)", implode(', ', $a)); } if (is_resource($var)) { return sprintf('Resource(%s)', get_resource_type($var)); } if (null === $var) { return 'null'; } if (false === $var) { return 'false'; } if (true === $var) { return 'true'; } return (string) $var; } } PK!}x2Symfony/Component/HttpKernel/Event/KernelEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\Event; /** * Base class for events thrown in the HttpKernel component * * @author Bernhard Schussek * * @api */ class KernelEvent extends Event { /** * The kernel in which this event was thrown * @var HttpKernelInterface */ private $kernel; /** * The request the kernel is currently processing * @var Request */ private $request; /** * The request type the kernel is currently processing. One of * HttpKernelInterface::MASTER_REQUEST and HttpKernelInterface::SUB_REQUEST * @var integer */ private $requestType; public function __construct(HttpKernelInterface $kernel, Request $request, $requestType) { $this->kernel = $kernel; $this->request = $request; $this->requestType = $requestType; } /** * Returns the kernel in which this event was thrown * * @return HttpKernelInterface * * @api */ public function getKernel() { return $this->kernel; } /** * Returns the request the kernel is currently processing * * @return Request * * @api */ public function getRequest() { return $this->request; } /** * Returns the request type the kernel is currently processing * * @return integer One of HttpKernelInterface::MASTER_REQUEST and * HttpKernelInterface::SUB_REQUEST * * @api */ public function getRequestType() { return $this->requestType; } /** * Checks if this is a master request. * * @return Boolean True if the request is a master request * * @api */ public function isMasterRequest() { return HttpKernelInterface::MASTER_REQUEST === $this->requestType; } } PK!N#FF'Symfony/Component/HttpKernel/Client.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\BrowserKit\Client as BaseClient; use Symfony\Component\BrowserKit\Request as DomRequest; use Symfony\Component\BrowserKit\Response as DomResponse; use Symfony\Component\BrowserKit\Cookie as DomCookie; use Symfony\Component\BrowserKit\History; use Symfony\Component\BrowserKit\CookieJar; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Client simulates a browser and makes requests to a Kernel object. * * @author Fabien Potencier * * @api */ class Client extends BaseClient { protected $kernel; /** * Constructor. * * @param HttpKernelInterface $kernel An HttpKernel instance * @param array $server The server parameters (equivalent of $_SERVER) * @param History $history A History instance to store the browser history * @param CookieJar $cookieJar A CookieJar instance to store the cookies */ public function __construct(HttpKernelInterface $kernel, array $server = array(), History $history = null, CookieJar $cookieJar = null) { // These class properties must be set before calling the parent constructor, as it may depend on it. $this->kernel = $kernel; $this->followRedirects = false; parent::__construct($server, $history, $cookieJar); } /** * {@inheritdoc} * * @return Request|null A Request instance */ public function getRequest() { return parent::getRequest(); } /** * {@inheritdoc} * * @return Response|null A Response instance */ public function getResponse() { return parent::getResponse(); } /** * Makes a request. * * @param Request $request A Request instance * * @return Response A Response instance */ protected function doRequest($request) { $response = $this->kernel->handle($request); if ($this->kernel instanceof TerminableInterface) { $this->kernel->terminate($request, $response); } return $response; } /** * Returns the script to execute when the request must be insulated. * * @param Request $request A Request instance * * @return string */ protected function getScript($request) { $kernel = str_replace("'", "\\'", serialize($this->kernel)); $request = str_replace("'", "\\'", serialize($request)); $r = new \ReflectionClass('\\Symfony\\Component\\ClassLoader\\ClassLoader'); $requirePath = str_replace("'", "\\'", $r->getFileName()); $symfonyPath = str_replace("'", "\\'", realpath(__DIR__.'/../../..')); $code = <<addPrefix('Symfony', '$symfonyPath'); \$loader->register(); \$kernel = unserialize('$kernel'); \$request = unserialize('$request'); EOF; return $code.$this->getHandleScript(); } protected function getHandleScript() { return <<<'EOF' $response = $kernel->handle($request); if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) { $kernel->terminate($request, $response); } echo serialize($response); EOF; } /** * Converts the BrowserKit request to a HttpKernel request. * * @param DomRequest $request A DomRequest instance * * @return Request A Request instance */ protected function filterRequest(DomRequest $request) { $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent()); $httpRequest->files->replace($this->filterFiles($httpRequest->files->all())); return $httpRequest; } /** * Filters an array of files. * * This method created test instances of UploadedFile so that the move() * method can be called on those instances. * * If the size of a file is greater than the allowed size (from php.ini) then * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE. * * @see Symfony\Component\HttpFoundation\File\UploadedFile * * @param array $files An array of files * * @return array An array with all uploaded files marked as already moved */ protected function filterFiles(array $files) { $filtered = array(); foreach ($files as $key => $value) { if (is_array($value)) { $filtered[$key] = $this->filterFiles($value); } elseif ($value instanceof UploadedFile) { if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) { $filtered[$key] = new UploadedFile( '', $value->getClientOriginalName(), $value->getClientMimeType(), 0, UPLOAD_ERR_INI_SIZE, true ); } else { $filtered[$key] = new UploadedFile( $value->getPathname(), $value->getClientOriginalName(), $value->getClientMimeType(), $value->getClientSize(), $value->getError(), true ); } } else { $filtered[$key] = $value; } } return $filtered; } /** * Converts the HttpKernel response to a BrowserKit response. * * @param Response $response A Response instance * * @return DomResponse A DomResponse instance */ protected function filterResponse($response) { $headers = $response->headers->all(); if ($response->headers->getCookies()) { $cookies = array(); foreach ($response->headers->getCookies() as $cookie) { $cookies[] = new DomCookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); } $headers['Set-Cookie'] = $cookies; } // this is needed to support StreamedResponse ob_start(); $response->sendContent(); $content = ob_get_clean(); return new DomResponse($content, $response->getStatusCode(), $headers); } } PK! <ISymfony/Component/HttpKernel/DataCollector/LateDataCollectorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; /** * LateDataCollectorInterface. * * @author Fabien Potencier */ interface LateDataCollectorInterface { /** * Collects data as late as possible. */ public function lateCollect(); } PK!8ESymfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\FlattenException; /** * ExceptionDataCollector. * * @author Fabien Potencier */ class ExceptionDataCollector extends DataCollector { /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { if (null !== $exception) { $this->data = array( 'exception' => FlattenException::create($exception), ); } } /** * Checks if the exception is not null. * * @return Boolean true if the exception is not null, false otherwise */ public function hasException() { return isset($this->data['exception']); } /** * Gets the exception. * * @return \Exception The exception */ public function getException() { return $this->data['exception']; } /** * Gets the exception message. * * @return string The exception message */ public function getMessage() { return $this->data['exception']->getMessage(); } /** * Gets the exception code. * * @return integer The exception code */ public function getCode() { return $this->data['exception']->getCode(); } /** * Gets the status code. * * @return integer The status code */ public function getStatusCode() { return $this->data['exception']->getStatusCode(); } /** * Gets the exception trace. * * @return array The exception trace */ public function getTrace() { return $this->data['exception']->getTrace(); } /** * {@inheritdoc} */ public function getName() { return 'exception'; } } PK!2~~BSymfony/Component/HttpKernel/DataCollector/ConfigDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * ConfigDataCollector. * * @author Fabien Potencier */ class ConfigDataCollector extends DataCollector { private $kernel; private $name; private $version; /** * Constructor. * * @param string $name The name of the application using the web profiler * @param string $version The version of the application using the web profiler */ public function __construct($name = null, $version = null) { $this->name = $name; $this->version = $version; } /** * Sets the Kernel associated with this Request. * * @param KernelInterface $kernel A KernelInterface instance */ public function setKernel(KernelInterface $kernel = null) { $this->kernel = $kernel; } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { $this->data = array( 'app_name' => $this->name, 'app_version' => $this->version, 'token' => $response->headers->get('X-Debug-Token'), 'symfony_version' => Kernel::VERSION, 'name' => isset($this->kernel) ? $this->kernel->getName() : 'n/a', 'env' => isset($this->kernel) ? $this->kernel->getEnvironment() : 'n/a', 'debug' => isset($this->kernel) ? $this->kernel->isDebug() : 'n/a', 'php_version' => PHP_VERSION, 'xdebug_enabled' => extension_loaded('xdebug'), 'eaccel_enabled' => extension_loaded('eaccelerator') && ini_get('eaccelerator.enable'), 'apc_enabled' => extension_loaded('apc') && ini_get('apc.enabled'), 'xcache_enabled' => extension_loaded('xcache') && ini_get('xcache.cacher'), 'wincache_enabled' => extension_loaded('wincache') && ini_get('wincache.ocenabled'), 'zend_opcache_enabled' => extension_loaded('Zend OPcache') && ini_get('opcache.enable'), 'bundles' => array(), 'sapi_name' => php_sapi_name() ); if (isset($this->kernel)) { foreach ($this->kernel->getBundles() as $name => $bundle) { $this->data['bundles'][$name] = $bundle->getPath(); } } } public function getApplicationName() { return $this->data['app_name']; } public function getApplicationVersion() { return $this->data['app_version']; } /** * Gets the token. * * @return string The token */ public function getToken() { return $this->data['token']; } /** * Gets the Symfony version. * * @return string The Symfony version */ public function getSymfonyVersion() { return $this->data['symfony_version']; } /** * Gets the PHP version. * * @return string The PHP version */ public function getPhpVersion() { return $this->data['php_version']; } /** * Gets the application name. * * @return string The application name */ public function getAppName() { return $this->data['name']; } /** * Gets the environment. * * @return string The environment */ public function getEnv() { return $this->data['env']; } /** * Returns true if the debug is enabled. * * @return Boolean true if debug is enabled, false otherwise */ public function isDebug() { return $this->data['debug']; } /** * Returns true if the XDebug is enabled. * * @return Boolean true if XDebug is enabled, false otherwise */ public function hasXDebug() { return $this->data['xdebug_enabled']; } /** * Returns true if EAccelerator is enabled. * * @return Boolean true if EAccelerator is enabled, false otherwise */ public function hasEAccelerator() { return $this->data['eaccel_enabled']; } /** * Returns true if APC is enabled. * * @return Boolean true if APC is enabled, false otherwise */ public function hasApc() { return $this->data['apc_enabled']; } /** * Returns true if Zend OPcache is enabled * * @return Boolean true if Zend OPcache is enabled, false otherwise */ public function hasZendOpcache() { return $this->data['zend_opcache_enabled']; } /** * Returns true if XCache is enabled. * * @return Boolean true if XCache is enabled, false otherwise */ public function hasXCache() { return $this->data['xcache_enabled']; } /** * Returns true if WinCache is enabled. * * @return Boolean true if WinCache is enabled, false otherwise */ public function hasWinCache() { return $this->data['wincache_enabled']; } /** * Returns true if any accelerator is enabled. * * @return Boolean true if any accelerator is enabled, false otherwise */ public function hasAccelerator() { return $this->hasApc() || $this->hasZendOpcache() || $this->hasEAccelerator() || $this->hasXCache() || $this->hasWinCache(); } public function getBundles() { return $this->data['bundles']; } /** * Gets the PHP SAPI name. * * @return string The environment */ public function getSapiName() { return $this->data['sapi_name']; } /** * {@inheritdoc} */ public function getName() { return 'config'; } } PK!.ESymfony/Component/HttpKernel/DataCollector/DataCollectorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * DataCollectorInterface. * * @author Fabien Potencier * * @api */ interface DataCollectorInterface { /** * Collects data for the given Request and Response. * * @param Request $request A Request instance * @param Response $response A Response instance * @param \Exception $exception An Exception instance * * @api */ public function collect(Request $request, Response $response, \Exception $exception = null); /** * Returns the name of the collector. * * @return string The collector name * * @api */ public function getName(); } PK!޹ BSymfony/Component/HttpKernel/DataCollector/LoggerDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Debug\ErrorHandler; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; /** * LogDataCollector. * * @author Fabien Potencier */ class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface { private $logger; public function __construct($logger = null) { if (null !== $logger && $logger instanceof DebugLoggerInterface) { $this->logger = $logger; } } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { // everything is done as late as possible } /** * {@inheritdoc} */ public function lateCollect() { if (null !== $this->logger) { $this->data = array( 'error_count' => $this->logger->countErrors(), 'logs' => $this->sanitizeLogs($this->logger->getLogs()), 'deprecation_count' => $this->computeDeprecationCount() ); } } /** * Gets the called events. * * @return array An array of called events * * @see TraceableEventDispatcherInterface */ public function countErrors() { return isset($this->data['error_count']) ? $this->data['error_count'] : 0; } /** * Gets the logs. * * @return array An array of logs */ public function getLogs() { return isset($this->data['logs']) ? $this->data['logs'] : array(); } public function countDeprecations() { return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0; } /** * {@inheritdoc} */ public function getName() { return 'logger'; } private function sanitizeLogs($logs) { foreach ($logs as $i => $log) { $logs[$i]['context'] = $this->sanitizeContext($log['context']); } return $logs; } private function sanitizeContext($context) { if (is_array($context)) { foreach ($context as $key => $value) { $context[$key] = $this->sanitizeContext($value); } return $context; } if (is_resource($context)) { return sprintf('Resource(%s)', get_resource_type($context)); } if (is_object($context)) { return sprintf('Object(%s)', get_class($context)); } return $context; } private function computeDeprecationCount() { $count = 0; foreach ($this->logger->getLogs() as $log) { if (isset($log['context']['type']) && ErrorHandler::TYPE_DEPRECATION === $log['context']['type']) { $count++; } } return $count; } } PK!@:o o BSymfony/Component/HttpKernel/DataCollector/RouterDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; /** * RouterDataCollector. * * @author Fabien Potencier */ class RouterDataCollector extends DataCollector { protected $controllers; public function __construct() { $this->controllers = new \SplObjectStorage(); $this->data = array( 'redirect' => false, 'url' => null, 'route' => null, ); } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { if ($response instanceof RedirectResponse) { $this->data['redirect'] = true; $this->data['url'] = $response->getTargetUrl(); if ($this->controllers->contains($request)) { $this->data['route'] = $this->guessRoute($request, $this->controllers[$request]); } } unset($this->controllers[$request]); } protected function guessRoute(Request $request, $controller) { return 'n/a'; } /** * Remembers the controller associated to each request. * * @param FilterControllerEvent $event The filter controller event */ public function onKernelController(FilterControllerEvent $event) { $this->controllers[$event->getRequest()] = $event->getController(); } /** * @return Boolean Whether this request will result in a redirect */ public function getRedirect() { return $this->data['redirect']; } /** * @return string|null The target URL */ public function getTargetUrl() { return $this->data['url']; } /** * @return string|null The target route */ public function getTargetRoute() { return $this->data['route']; } /** * {@inheritdoc} */ public function getName() { return 'router'; } } PK! +66ASymfony/Component/HttpKernel/DataCollector/Util/ValueExporter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector\Util; /** * @author Bernhard Schussek */ class ValueExporter { /** * Converts a PHP value to a string. * * @param mixed $value The PHP value * * @return string The string representation of the given value */ public function exportValue($value) { if (is_object($value)) { return sprintf('Object(%s)', get_class($value)); } if (is_array($value)) { $a = array(); foreach ($value as $k => $v) { $a[] = sprintf('%s => %s', $k, $this->exportValue($v)); } return sprintf("Array(%s)", implode(', ', $a)); } if (is_resource($value)) { return sprintf('Resource(%s)', get_resource_type($value)); } if (null === $value) { return 'null'; } if (false === $value) { return 'false'; } if (true === $value) { return 'true'; } return (string) $value; } } PK!IYz((CSymfony/Component/HttpKernel/DataCollector/RequestDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\HeaderBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * RequestDataCollector. * * @author Fabien Potencier */ class RequestDataCollector extends DataCollector implements EventSubscriberInterface { protected $controllers; public function __construct() { $this->controllers = new \SplObjectStorage(); } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { $responseHeaders = $response->headers->all(); $cookies = array(); foreach ($response->headers->getCookies() as $cookie) { $cookies[] = $this->getCookieHeader($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); } if (count($cookies) > 0) { $responseHeaders['Set-Cookie'] = $cookies; } $attributes = array(); foreach ($request->attributes->all() as $key => $value) { if ('_route' === $key && is_object($value)) { $attributes['_route'] = $this->varToString($value->getPath()); } elseif ('_route_params' === $key) { foreach ($value as $key => $v) { $attributes['_route_params'][$key] = $this->varToString($v); } } else { $attributes[$key] = $this->varToString($value); } } $content = null; try { $content = $request->getContent(); } catch (\LogicException $e) { // the user already got the request content as a resource $content = false; } $sessionMetadata = array(); $sessionAttributes = array(); $flashes = array(); if ($request->hasSession()) { $session = $request->getSession(); if ($session->isStarted()) { $sessionMetadata['Created'] = date(DATE_RFC822, $session->getMetadataBag()->getCreated()); $sessionMetadata['Last used'] = date(DATE_RFC822, $session->getMetadataBag()->getLastUsed()); $sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime(); $sessionAttributes = $session->all(); $flashes = $session->getFlashBag()->peekAll(); } } $statusCode = $response->getStatusCode(); $this->data = array( 'format' => $request->getRequestFormat(), 'content' => $content, 'content_type' => $response->headers->get('Content-Type') ? $response->headers->get('Content-Type') : 'text/html', 'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '', 'status_code' => $statusCode, 'request_query' => $request->query->all(), 'request_request' => $request->request->all(), 'request_headers' => $request->headers->all(), 'request_server' => $request->server->all(), 'request_cookies' => $request->cookies->all(), 'request_attributes' => $attributes, 'response_headers' => $responseHeaders, 'session_metadata' => $sessionMetadata, 'session_attributes' => $sessionAttributes, 'flashes' => $flashes, 'path_info' => $request->getPathInfo(), 'controller' => 'n/a', 'locale' => $request->getLocale(), ); if (isset($this->data['request_headers']['php-auth-pw'])) { $this->data['request_headers']['php-auth-pw'] = '******'; } if (isset($this->data['request_server']['PHP_AUTH_PW'])) { $this->data['request_server']['PHP_AUTH_PW'] = '******'; } if (isset($this->controllers[$request])) { $controller = $this->controllers[$request]; if (is_array($controller)) { try { $r = new \ReflectionMethod($controller[0], $controller[1]); $this->data['controller'] = array( 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0], 'method' => $controller[1], 'file' => $r->getFilename(), 'line' => $r->getStartLine(), ); } catch (\ReflectionException $re) { if (is_callable($controller)) { // using __call or __callStatic $this->data['controller'] = array( 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0], 'method' => $controller[1], 'file' => 'n/a', 'line' => 'n/a', ); } } } elseif ($controller instanceof \Closure) { $r = new \ReflectionFunction($controller); $this->data['controller'] = array( 'class' => $r->getName(), 'method' => null, 'file' => $r->getFilename(), 'line' => $r->getStartLine(), ); } else { $this->data['controller'] = (string) $controller ?: 'n/a'; } unset($this->controllers[$request]); } } public function getPathInfo() { return $this->data['path_info']; } public function getRequestRequest() { return new ParameterBag($this->data['request_request']); } public function getRequestQuery() { return new ParameterBag($this->data['request_query']); } public function getRequestHeaders() { return new HeaderBag($this->data['request_headers']); } public function getRequestServer() { return new ParameterBag($this->data['request_server']); } public function getRequestCookies() { return new ParameterBag($this->data['request_cookies']); } public function getRequestAttributes() { return new ParameterBag($this->data['request_attributes']); } public function getResponseHeaders() { return new ResponseHeaderBag($this->data['response_headers']); } public function getSessionMetadata() { return $this->data['session_metadata']; } public function getSessionAttributes() { return $this->data['session_attributes']; } public function getFlashes() { return $this->data['flashes']; } public function getContent() { return $this->data['content']; } public function getContentType() { return $this->data['content_type']; } public function getStatusText() { return $this->data['status_text']; } public function getStatusCode() { return $this->data['status_code']; } public function getFormat() { return $this->data['format']; } public function getLocale() { return $this->data['locale']; } /** * Gets the route name. * * The _route request attributes is automatically set by the Router Matcher. * * @return string The route */ public function getRoute() { return isset($this->data['request_attributes']['_route']) ? $this->data['request_attributes']['_route'] : ''; } /** * Gets the route parameters. * * The _route_params request attributes is automatically set by the RouterListener. * * @return array The parameters */ public function getRouteParams() { return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params'] : array(); } /** * Gets the controller. * * @return string The controller as a string */ public function getController() { return $this->data['controller']; } public function onKernelController(FilterControllerEvent $event) { $this->controllers[$event->getRequest()] = $event->getController(); } public static function getSubscribedEvents() { return array(KernelEvents::CONTROLLER => 'onKernelController'); } /** * {@inheritdoc} */ public function getName() { return 'request'; } private function getCookieHeader($name, $value, $expires, $path, $domain, $secure, $httponly) { $cookie = sprintf('%s=%s', $name, urlencode($value)); if (0 !== $expires) { if (is_numeric($expires)) { $expires = (int) $expires; } elseif ($expires instanceof \DateTime) { $expires = $expires->getTimestamp(); } else { $expires = strtotime($expires); if (false === $expires || -1 == $expires) { throw new \InvalidArgumentException(sprintf('The "expires" cookie parameter is not valid.', $expires)); } } $cookie .= '; expires='.str_replace('+0000', '', \DateTime::createFromFormat('U', $expires, new \DateTimeZone('GMT'))->format('D, d-M-Y H:i:s T')); } if ($domain) { $cookie .= '; domain='.$domain; } $cookie .= '; path='.$path; if ($secure) { $cookie .= '; secure'; } if ($httponly) { $cookie .= '; httponly'; } return $cookie; } } PK! ASymfony/Component/HttpKernel/DataCollector/EventDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; /** * EventDataCollector. * * @author Fabien Potencier */ class EventDataCollector extends DataCollector implements LateDataCollectorInterface { protected $dispatcher; public function __construct(EventDispatcherInterface $dispatcher = null) { $this->dispatcher = $dispatcher; } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { $this->data = array( 'called_listeners' => array(), 'not_called_listeners' => array(), ); } public function lateCollect() { if ($this->dispatcher instanceof TraceableEventDispatcherInterface) { $this->setCalledListeners($this->dispatcher->getCalledListeners()); $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners()); } } /** * Sets the called listeners. * * @param array $listeners An array of called listeners * * @see TraceableEventDispatcherInterface */ public function setCalledListeners(array $listeners) { $this->data['called_listeners'] = $listeners; } /** * Gets the called listeners. * * @return array An array of called listeners * * @see TraceableEventDispatcherInterface */ public function getCalledListeners() { return $this->data['called_listeners']; } /** * Sets the not called listeners. * * @param array $listeners An array of not called listeners * * @see TraceableEventDispatcherInterface */ public function setNotCalledListeners(array $listeners) { $this->data['not_called_listeners'] = $listeners; } /** * Gets the not called listeners. * * @return array An array of not called listeners * * @see TraceableEventDispatcherInterface */ public function getNotCalledListeners() { return $this->data['not_called_listeners']; } /** * {@inheritdoc} */ public function getName() { return 'events'; } } PK!ƏGV @Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\KernelInterface; /** * TimeDataCollector. * * @author Fabien Potencier */ class TimeDataCollector extends DataCollector implements LateDataCollectorInterface { protected $kernel; protected $stopwatch; public function __construct(KernelInterface $kernel = null, $stopwatch = null) { $this->kernel = $kernel; $this->stopwatch = $stopwatch; } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { if (null !== $this->kernel) { $startTime = $this->kernel->getStartTime(); } else { $startTime = $request->server->get('REQUEST_TIME_FLOAT', $request->server->get('REQUEST_TIME')); } $this->data = array( 'token' => $response->headers->get('X-Debug-Token'), 'start_time' => $startTime * 1000, 'events' => array(), ); } /** * {@inheritdoc} */ public function lateCollect() { if (null !== $this->stopwatch && isset($this->data['token'])) { $this->setEvents($this->stopwatch->getSectionEvents($this->data['token'])); } unset($this->data['token']); } /** * Sets the request events. * * @param array $events The request events */ public function setEvents(array $events) { foreach ($events as $event) { $event->ensureStopped(); } $this->data['events'] = $events; } /** * Gets the request events. * * @return array The request events */ public function getEvents() { return $this->data['events']; } /** * Gets the request elapsed time. * * @return float The elapsed time */ public function getDuration() { if (!isset($this->data['events']['__section__'])) { return 0; } $lastEvent = $this->data['events']['__section__']; return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime(); } /** * Gets the initialization time. * * This is the time spent until the beginning of the request handling. * * @return float The elapsed time */ public function getInitTime() { if (!isset($this->data['events']['__section__'])) { return 0; } return $this->data['events']['__section__']->getOrigin() - $this->getStartTime(); } /** * Gets the request time. * * @return integer The time */ public function getStartTime() { return $this->data['start_time']; } /** * {@inheritdoc} */ public function getName() { return 'time'; } } PK!n--<Symfony/Component/HttpKernel/DataCollector/DataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; /** * DataCollector. * * Children of this class must store the collected data in the data property. * * @author Fabien Potencier * @author Bernhard Schussek */ abstract class DataCollector implements DataCollectorInterface, \Serializable { protected $data; /** * @var ValueExporter */ private $valueExporter; public function serialize() { return serialize($this->data); } public function unserialize($data) { $this->data = unserialize($data); } /** * Converts a PHP variable to a string. * * @param mixed $var A PHP variable * * @return string The string representation of the variable */ protected function varToString($var) { if (null === $this->valueExporter) { $this->valueExporter = new ValueExporter(); } return $this->valueExporter->exportValue($var); } } PK!(; ; BSymfony/Component/HttpKernel/DataCollector/MemoryDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * MemoryDataCollector. * * @author Fabien Potencier */ class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface { public function __construct() { $this->data = array( 'memory' => 0, 'memory_limit' => $this->convertToBytes(ini_get('memory_limit')), ); } /** * {@inheritdoc} */ public function collect(Request $request, Response $response, \Exception $exception = null) { $this->updateMemoryUsage(); } /** * {@inheritdoc} */ public function lateCollect() { $this->updateMemoryUsage(); } /** * Gets the memory. * * @return integer The memory */ public function getMemory() { return $this->data['memory']; } /** * Gets the PHP memory limit. * * @return integer The memory limit */ public function getMemoryLimit() { return $this->data['memory_limit']; } /** * Updates the memory usage data. */ public function updateMemoryUsage() { $this->data['memory'] = memory_get_peak_usage(true); } /** * {@inheritdoc} */ public function getName() { return 'memory'; } private function convertToBytes($memoryLimit) { if ('-1' === $memoryLimit) { return -1; } $memoryLimit = strtolower($memoryLimit); $max = strtolower(ltrim($memoryLimit, '+')); if (0 === strpos($max, '0x')) { $max = intval($max, 16); } elseif (0 === strpos($max, '0')) { $max = intval($max, 8); } else { $max = intval($max); } switch (substr($memoryLimit, -1)) { case 't': $max *= 1024; case 'g': $max *= 1024; case 'm': $max *= 1024; case 'k': $max *= 1024; } return $max; } } PK!^/|GooGSymfony/Component/HttpKernel/Controller/ControllerResolverInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\HttpFoundation\Request; /** * A ControllerResolverInterface implementation knows how to determine the * controller to execute based on a Request object. * * It can also determine the arguments to pass to the Controller. * * A Controller can be any valid PHP callable. * * @author Fabien Potencier * * @api */ interface ControllerResolverInterface { /** * Returns the Controller instance associated with a Request. * * As several resolvers can exist for a single application, a resolver must * return false when it is not able to determine the controller. * * The resolver must only throw an exception when it should be able to load * controller but cannot because of some errors made by the developer. * * @param Request $request A Request instance * * @return callable|false A PHP callable representing the Controller, * or false if this resolver is not able to determine the controller * * @throws \LogicException If the controller can't be found * * @api */ public function getController(Request $request); /** * Returns the arguments to pass to the controller. * * @param Request $request A Request instance * @param callable $controller A PHP callable * * @return array An array of arguments to pass to the controller * * @throws \RuntimeException When value for argument given is not provided * * @api */ public function getArguments(Request $request, $controller); } PK!|  GSymfony/Component/HttpKernel/Controller/TraceableControllerResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\HttpFoundation\Request; /** * TraceableControllerResolver. * * @author Fabien Potencier */ class TraceableControllerResolver implements ControllerResolverInterface { private $resolver; private $stopwatch; /** * Constructor. * * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance * @param Stopwatch $stopwatch A Stopwatch instance */ public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch) { $this->resolver = $resolver; $this->stopwatch = $stopwatch; } /** * {@inheritdoc} */ public function getController(Request $request) { $e = $this->stopwatch->start('controller.get_callable'); $ret = $this->resolver->getController($request); $e->stop(); return $ret; } /** * {@inheritdoc} */ public function getArguments(Request $request, $controller) { $e = $this->stopwatch->start('controller.get_arguments'); $ret = $this->resolver->getArguments($request, $controller); $e->stop(); return $ret; } } PK!xXX?Symfony/Component/HttpKernel/Controller/ControllerReference.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; /** * Acts as a marker and a data holder for a Controller. * * Some methods in Symfony accept both a URI (as a string) or a controller as * an argument. In the latter case, instead of passing an array representing * the controller, you can use an instance of this class. * * @author Fabien Potencier * * @see Symfony\Component\HttpKernel\FragmentRenderer * @see Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface */ class ControllerReference { public $controller; public $attributes = array(); public $query = array(); /** * Constructor. * * @param string $controller The controller name * @param array $attributes An array of parameters to add to the Request attributes * @param array $query An array of parameters to add to the Request query string */ public function __construct($controller, array $attributes = array(), array $query = array()) { $this->controller = $controller; $this->attributes = $attributes; $this->query = $query; } } PK!NCtt>Symfony/Component/HttpKernel/Controller/ControllerResolver.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; /** * ControllerResolver. * * This implementation uses the '_controller' request attribute to determine * the controller to execute and uses the request attributes to determine * the controller method arguments. * * @author Fabien Potencier * * @api */ class ControllerResolver implements ControllerResolverInterface { private $logger; /** * Constructor. * * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; } /** * {@inheritdoc} * * This method looks for a '_controller' request attribute that represents * the controller name (a string like ClassName::MethodName). * * @api */ public function getController(Request $request) { if (!$controller = $request->attributes->get('_controller')) { if (null !== $this->logger) { $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing'); } return false; } if (is_array($controller)) { return $controller; } if (is_object($controller)) { if (method_exists($controller, '__invoke')) { return $controller; } throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo())); } if (false === strpos($controller, ':')) { if (method_exists($controller, '__invoke')) { return new $controller(); } elseif (function_exists($controller)) { return $controller; } } $callable = $this->createController($controller); if (!is_callable($callable)) { throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', $controller, $request->getPathInfo())); } return $callable; } /** * {@inheritdoc} * * @api */ public function getArguments(Request $request, $controller) { if (is_array($controller)) { $r = new \ReflectionMethod($controller[0], $controller[1]); } elseif (is_object($controller) && !$controller instanceof \Closure) { $r = new \ReflectionObject($controller); $r = $r->getMethod('__invoke'); } else { $r = new \ReflectionFunction($controller); } return $this->doGetArguments($request, $controller, $r->getParameters()); } protected function doGetArguments(Request $request, $controller, array $parameters) { $attributes = $request->attributes->all(); $arguments = array(); foreach ($parameters as $param) { if (array_key_exists($param->name, $attributes)) { $arguments[] = $attributes[$param->name]; } elseif ($param->getClass() && $param->getClass()->isInstance($request)) { $arguments[] = $request; } elseif ($param->isDefaultValueAvailable()) { $arguments[] = $param->getDefaultValue(); } else { if (is_array($controller)) { $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); } elseif (is_object($controller)) { $repr = get_class($controller); } else { $repr = $controller; } throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name)); } } return $arguments; } /** * Returns a callable for the given controller. * * @param string $controller A Controller string * * @return mixed A PHP callable * * @throws \InvalidArgumentException */ protected function createController($controller) { if (false === strpos($controller, '::')) { throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller)); } list($class, $method) = explode('::', $controller, 2); if (!class_exists($class)) { throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); } return array(new $class(), $method); } } PK!;M>Symfony/Component/HttpKernel/DependencyInjection/Extension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension; /** * Allow adding classes to the class cache. * * @author Fabien Potencier */ abstract class Extension extends BaseExtension { private $classes = array(); /** * Gets the classes to cache. * * @return array An array of classes */ public function getClassesToCompile() { return $this->classes; } /** * Adds classes to the class cache. * * @param array $classes An array of classes */ public function addClassesToCompile(array $classes) { $this->classes = array_merge($this->classes, $classes); } } PK!6V V MSymfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Scope; /** * Adds a managed request scope. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class ContainerAwareHttpKernel extends HttpKernel { protected $container; /** * Constructor. * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param ContainerInterface $container A ContainerInterface instance * @param ControllerResolverInterface $controllerResolver A ControllerResolverInterface instance * @param RequestStack $requestStack A stack for master/sub requests */ public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver, RequestStack $requestStack = null) { parent::__construct($dispatcher, $controllerResolver, $requestStack); $this->container = $container; // the request scope might have been created before (see FrameworkBundle) if (!$container->hasScope('request')) { $container->addScope(new Scope('request')); } } /** * {@inheritdoc} */ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { $request->headers->set('X-Php-Ob-Level', ob_get_level()); $this->container->enterScope('request'); $this->container->set('request', $request, 'request'); try { $response = parent::handle($request, $type, $catch); } catch (\Exception $e) { $this->container->set('request', null, 'request'); $this->container->leaveScope('request'); throw $e; } $this->container->set('request', null, 'request'); $this->container->leaveScope('request'); return $response; } } PK!kJSymfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; /** * Compiler pass to register tagged services for an event dispatcher. */ class RegisterListenersPass implements CompilerPassInterface { /** * @var string */ protected $dispatcherService; /** * @var string */ protected $listenerTag; /** * @var string */ protected $subscriberTag; /** * Constructor. * * @param string $dispatcherService Service name of the event dispatcher in processed container * @param string $listenerTag Tag name used for listener * @param string $subscriberTag Tag name used for subscribers */ public function __construct($dispatcherService = 'event_dispatcher', $listenerTag = 'kernel.event_listener', $subscriberTag = 'kernel.event_subscriber') { $this->dispatcherService = $dispatcherService; $this->listenerTag = $listenerTag; $this->subscriberTag = $subscriberTag; } public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) { return; } $definition = $container->findDefinition($this->dispatcherService); foreach ($container->findTaggedServiceIds($this->listenerTag) as $id => $events) { $def = $container->getDefinition($id); if (!$def->isPublic()) { throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id)); } if ($def->isAbstract()) { throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event listeners are lazy-loaded.', $id)); } foreach ($events as $event) { $priority = isset($event['priority']) ? $event['priority'] : 0; if (!isset($event['event'])) { throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); } if (!isset($event['method'])) { $event['method'] = 'on'.preg_replace_callback(array( '/(?<=\b)[a-z]/i', '/[^a-z0-9]/i', ), function ($matches) { return strtoupper($matches[0]); }, $event['event']); $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); } $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority)); } } foreach ($container->findTaggedServiceIds($this->subscriberTag) as $id => $attributes) { $def = $container->getDefinition($id); if (!$def->isPublic()) { throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id)); } // We must assume that the class value has been correctly filled, even if the service is created by a factory $class = $def->getClass(); $refClass = new \ReflectionClass($class); $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; if (!$refClass->implementsInterface($interface)) { throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); } $definition->addMethodCall('addSubscriberService', array($id, $class)); } } } PK!u__JSymfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * This extension sub-class provides first-class integration with the * Config/Definition Component. * * You can use this as base class if you * * a) use the Config/Definition component for configuration * b) your configuration class is named "Configuration" and * c) the configuration class resides in the DependencyInjection sub-folder * * @author Johannes M. Schmitt */ abstract class ConfigurableExtension extends Extension { /** * {@inheritDoc} */ final public function load(array $configs, ContainerBuilder $container) { $this->loadInternal($this->processConfiguration($this->getConfiguration($configs, $container), $configs), $container); } /** * Configures the passed container according to the merged configuration. * * @param array $mergedConfig * @param ContainerBuilder $container */ abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container); } PK!&!#ffTSymfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Ensures certain extensions are always loaded. * * @author Kris Wallsmith */ class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass { private $extensions; public function __construct(array $extensions) { $this->extensions = $extensions; } public function process(ContainerBuilder $container) { foreach ($this->extensions as $extension) { if (!count($container->getExtensionConfig($extension))) { $container->loadFromExtension($extension, array()); } } parent::process($container); } } PK!QNRJSymfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\HttpKernel\Kernel; /** * Sets the classes to compile in the cache for the container. * * @author Fabien Potencier */ class AddClassesToCachePass implements CompilerPassInterface { private $kernel; public function __construct(Kernel $kernel) { $this->kernel = $kernel; } /** * {@inheritDoc} */ public function process(ContainerBuilder $container) { $classes = array(); foreach ($container->getExtensions() as $extension) { if ($extension instanceof Extension) { $classes = array_merge($classes, $extension->getClassesToCompile()); } } $this->kernel->setClassCache(array_unique($container->getParameterBag()->resolveValue($classes))); } } PK!a 9Symfony/Component/ClassLoader/ApcUniversalClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ApcUniversalClassLoader implements a "universal" autoloader cached in APC for PHP 5.3. * * It is able to load classes that use either: * * * The technical interoperability standards for PHP 5.3 namespaces and * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md); * * * The PEAR naming convention for classes (http://pear.php.net/). * * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be * looked for in a list of locations to ease the vendoring of a sub-set of * classes for large projects. * * Example usage: * * require 'vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; * require 'vendor/symfony/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; * * use Symfony\Component\ClassLoader\ApcUniversalClassLoader; * * $loader = new ApcUniversalClassLoader('apc.prefix.'); * * // register classes with namespaces * $loader->registerNamespaces(array( * 'Symfony\Component' => __DIR__.'/component', * 'Symfony' => __DIR__.'/framework', * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), * )); * * // register a library using the PEAR naming convention * $loader->registerPrefixes(array( * 'Swift_' => __DIR__.'/Swift', * )); * * // activate the autoloader * $loader->register(); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * @author Fabien Potencier * @author Kris Wallsmith * * @api */ class ApcUniversalClassLoader extends UniversalClassLoader { private $prefix; /** * Constructor. * * @param string $prefix A prefix to create a namespace in APC * * @throws \RuntimeException * * @api */ public function __construct($prefix) { if (!extension_loaded('apc')) { throw new \RuntimeException('Unable to use ApcUniversalClassLoader as APC is not enabled.'); } $this->prefix = $prefix; } /** * Finds a file by class name while caching lookups to APC. * * @param string $class A class name to resolve to file * * @return string|null The path, if found */ public function findFile($class) { if (false === $file = apc_fetch($this->prefix.$class)) { apc_store($this->prefix.$class, $file = parent::findFile($class)); } return $file; } } PK!PЩ 3Symfony/Component/ClassLoader/XcacheClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * XcacheClassLoader implements a wrapping autoloader cached in Xcache for PHP 5.3. * * It expects an object implementing a findFile method to find the file. This * allows using it as a wrapper around the other loaders of the component (the * ClassLoader and the UniversalClassLoader for instance) but also around any * other autoloader following this convention (the Composer one for instance) * * $loader = new ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * $cachedLoader = new XcacheClassLoader('my_prefix', $loader); * * // activate the cached autoloader * $cachedLoader->register(); * * // eventually deactivate the non-cached loader if it was registered previously * // to be sure to use the cached one. * $loader->unregister(); * * @author Fabien Potencier * @author Kris Wallsmith * @author Kim Hemsø Rasmussen * * @api */ class XcacheClassLoader { private $prefix; private $classFinder; /** * Constructor. * * @param string $prefix A prefix to create a namespace in Xcache * @param object $classFinder An object that implements findFile() method. * * @throws \RuntimeException * @throws \InvalidArgumentException * * @api */ public function __construct($prefix, $classFinder) { if (!extension_loaded('Xcache')) { throw new \RuntimeException('Unable to use XcacheClassLoader as Xcache is not enabled.'); } if (!method_exists($classFinder, 'findFile')) { throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); } $this->prefix = $prefix; $this->classFinder = $classFinder; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds a file by class name while caching lookups to Xcache. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { if (xcache_isset($this->prefix.$class)) { $file = xcache_get($this->prefix.$class); } else { $file = $this->classFinder->findFile($class); xcache_set($this->prefix.$class, $file); } return $file; } } PK!"KUU,Symfony/Component/ClassLoader/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * A class loader that uses a mapping file to look up paths. * * @author Fabien Potencier */ class MapClassLoader { private $map = array(); /** * Constructor. * * @param array $map A map where keys are classes and values the absolute file path */ public function __construct(array $map) { $this->map = $map; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Loads the given class or interface. * * @param string $class The name of the class */ public function loadClass($class) { if (isset($this->map[$class])) { require $this->map[$class]; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|null The path, if found */ public function findFile($class) { if (isset($this->map[$class])) { return $this->map[$class]; } } } PK!w!));Symfony/Component/ClassLoader/DebugUniversalClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * Checks that the class is actually declared in the included file. * * @author Fabien Potencier */ class DebugUniversalClassLoader extends UniversalClassLoader { /** * Replaces all regular UniversalClassLoader instances by a DebugUniversalClassLoader ones. */ public static function enable() { if (!is_array($functions = spl_autoload_functions())) { return; } foreach ($functions as $function) { spl_autoload_unregister($function); } foreach ($functions as $function) { if (is_array($function) && $function[0] instanceof UniversalClassLoader) { $loader = new static(); $loader->registerNamespaceFallbacks($function[0]->getNamespaceFallbacks()); $loader->registerPrefixFallbacks($function[0]->getPrefixFallbacks()); $loader->registerNamespaces($function[0]->getNamespaces()); $loader->registerPrefixes($function[0]->getPrefixes()); $loader->useIncludePath($function[0]->getUseIncludePath()); $function[0] = $loader; } spl_autoload_register($function); } } /** * {@inheritDoc} */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) { throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); } } } } PK!v . .7Symfony/Component/ClassLoader/ClassCollectionLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ClassCollectionLoader. * * @author Fabien Potencier */ class ClassCollectionLoader { private static $loaded; private static $seen; private static $useTokenizer = true; /** * Loads a list of classes and caches them in one big file. * * @param array $classes An array of classes to load * @param string $cacheDir A cache directory * @param string $name The cache name prefix * @param Boolean $autoReload Whether to flush the cache when the cache is stale or not * @param Boolean $adaptive Whether to remove already declared classes or not * @param string $extension File extension of the resulting file * * @throws \InvalidArgumentException When class can't be loaded */ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = false, $extension = '.php') { // each $name can only be loaded once per PHP process if (isset(self::$loaded[$name])) { return; } self::$loaded[$name] = true; $declared = array_merge(get_declared_classes(), get_declared_interfaces()); if (function_exists('get_declared_traits')) { $declared = array_merge($declared, get_declared_traits()); } if ($adaptive) { // don't include already declared classes $classes = array_diff($classes, $declared); // the cache is different depending on which classes are already declared $name = $name.'-'.substr(hash('sha256', implode('|', $classes)), 0, 5); } $classes = array_unique($classes); $cache = $cacheDir.'/'.$name.$extension; // auto-reload $reload = false; if ($autoReload) { $metadata = $cache.'.meta'; if (!is_file($metadata) || !is_file($cache)) { $reload = true; } else { $time = filemtime($cache); $meta = unserialize(file_get_contents($metadata)); sort($meta[1]); sort($classes); if ($meta[1] != $classes) { $reload = true; } else { foreach ($meta[0] as $resource) { if (!is_file($resource) || filemtime($resource) > $time) { $reload = true; break; } } } } } if (!$reload && is_file($cache)) { require_once $cache; return; } $files = array(); $content = ''; foreach (self::getOrderedClasses($classes) as $class) { if (in_array($class->getName(), $declared)) { continue; } $files[] = $class->getFileName(); $c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName())); // fakes namespace declaration for global code if (!$class->inNamespace()) { $c = "\nnamespace\n{\n".$c."\n}\n"; } $c = self::fixNamespaceDeclarations('getName()])) { return array(); } self::$seen[$class->getName()] = true; $classes = array($class); $parent = $class; while (($parent = $parent->getParentClass()) && $parent->isUserDefined() && !isset(self::$seen[$parent->getName()])) { self::$seen[$parent->getName()] = true; array_unshift($classes, $parent); } $traits = array(); if (function_exists('get_declared_traits')) { foreach ($classes as $c) { foreach (self::resolveDependencies(self::computeTraitDeps($c), $c) as $trait) { if ($trait !== $c) { $traits[] = $trait; } } } } return array_merge(self::getInterfaces($class), $traits, $classes); } private static function getInterfaces(\ReflectionClass $class) { $classes = array(); foreach ($class->getInterfaces() as $interface) { $classes = array_merge($classes, self::getInterfaces($interface)); } if ($class->isUserDefined() && $class->isInterface() && !isset(self::$seen[$class->getName()])) { self::$seen[$class->getName()] = true; $classes[] = $class; } return $classes; } private static function computeTraitDeps(\ReflectionClass $class) { $traits = $class->getTraits(); $deps = array($class->getName() => $traits); while ($trait = array_pop($traits)) { if ($trait->isUserDefined() && !isset(self::$seen[$trait->getName()])) { self::$seen[$trait->getName()] = true; $traitDeps = $trait->getTraits(); $deps[$trait->getName()] = $traitDeps; $traits = array_merge($traits, $traitDeps); } } return $deps; } /** * Dependencies resolution. * * This function does not check for circular dependencies as it should never * occur with PHP traits. * * @param array $tree The dependency tree * @param \ReflectionClass $node The node * @param \ArrayObject $resolved An array of already resolved dependencies * @param \ArrayObject $unresolved An array of dependencies to be resolved * * @return \ArrayObject The dependencies for the given node * * @throws \RuntimeException if a circular dependency is detected */ private static function resolveDependencies(array $tree, $node, \ArrayObject $resolved = null, \ArrayObject $unresolved = null) { if (null === $resolved) { $resolved = new \ArrayObject(); } if (null === $unresolved) { $unresolved = new \ArrayObject(); } $nodeName = $node->getName(); $unresolved[$nodeName] = $node; foreach ($tree[$nodeName] as $dependency) { if (!$resolved->offsetExists($dependency->getName())) { self::resolveDependencies($tree, $dependency, $resolved, $unresolved); } } $resolved[$nodeName] = $node; unset($unresolved[$nodeName]); return $resolved; } } PK!a.e"e"6Symfony/Component/ClassLoader/UniversalClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * UniversalClassLoader implements a "universal" autoloader for PHP 5.3. * * It is able to load classes that use either: * * * The technical interoperability standards for PHP 5.3 namespaces and * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md); * * * The PEAR naming convention for classes (http://pear.php.net/). * * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be * looked for in a list of locations to ease the vendoring of a sub-set of * classes for large projects. * * Example usage: * * $loader = new UniversalClassLoader(); * * // register classes with namespaces * $loader->registerNamespaces(array( * 'Symfony\Component' => __DIR__.'/component', * 'Symfony' => __DIR__.'/framework', * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), * )); * * // register a library using the PEAR naming convention * $loader->registerPrefixes(array( * 'Swift_' => __DIR__.'/Swift', * )); * * * // to enable searching the include path (e.g. for PEAR packages) * $loader->useIncludePath(true); * * // activate the autoloader * $loader->register(); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * @author Fabien Potencier * * @api */ class UniversalClassLoader { private $namespaces = array(); private $prefixes = array(); private $namespaceFallbacks = array(); private $prefixFallbacks = array(); private $useIncludePath = false; /** * Turns on searching the include for class files. Allows easy loading * of installed PEAR packages * * @param Boolean $useIncludePath */ public function useIncludePath($useIncludePath) { $this->useIncludePath = $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return Boolean */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Gets the configured namespaces. * * @return array A hash with namespaces as keys and directories as values */ public function getNamespaces() { return $this->namespaces; } /** * Gets the configured class prefixes. * * @return array A hash with class prefixes as keys and directories as values */ public function getPrefixes() { return $this->prefixes; } /** * Gets the directory(ies) to use as a fallback for namespaces. * * @return array An array of directories */ public function getNamespaceFallbacks() { return $this->namespaceFallbacks; } /** * Gets the directory(ies) to use as a fallback for class prefixes. * * @return array An array of directories */ public function getPrefixFallbacks() { return $this->prefixFallbacks; } /** * Registers the directory to use as a fallback for namespaces. * * @param array $dirs An array of directories * * @api */ public function registerNamespaceFallbacks(array $dirs) { $this->namespaceFallbacks = $dirs; } /** * Registers a directory to use as a fallback for namespaces. * * @param string $dir A directory */ public function registerNamespaceFallback($dir) { $this->namespaceFallbacks[] = $dir; } /** * Registers directories to use as a fallback for class prefixes. * * @param array $dirs An array of directories * * @api */ public function registerPrefixFallbacks(array $dirs) { $this->prefixFallbacks = $dirs; } /** * Registers a directory to use as a fallback for class prefixes. * * @param string $dir A directory */ public function registerPrefixFallback($dir) { $this->prefixFallbacks[] = $dir; } /** * Registers an array of namespaces * * @param array $namespaces An array of namespaces (namespaces as keys and locations as values) * * @api */ public function registerNamespaces(array $namespaces) { foreach ($namespaces as $namespace => $locations) { $this->namespaces[$namespace] = (array) $locations; } } /** * Registers a namespace. * * @param string $namespace The namespace * @param array|string $paths The location(s) of the namespace * * @api */ public function registerNamespace($namespace, $paths) { $this->namespaces[$namespace] = (array) $paths; } /** * Registers an array of classes using the PEAR naming convention. * * @param array $classes An array of classes (prefixes as keys and locations as values) * * @api */ public function registerPrefixes(array $classes) { foreach ($classes as $prefix => $locations) { $this->prefixes[$prefix] = (array) $locations; } } /** * Registers a set of classes using the PEAR naming convention. * * @param string $prefix The classes prefix * @param array|string $paths The location(s) of the classes * * @api */ public function registerPrefix($prefix, $paths) { $this->prefixes[$prefix] = (array) $paths; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not * * @api */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|null The path, if found */ public function findFile($class) { if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $namespace = substr($class, 0, $pos); $className = substr($class, $pos + 1); $normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; foreach ($this->namespaces as $ns => $dirs) { if (0 !== strpos($namespace, $ns)) { continue; } foreach ($dirs as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } foreach ($this->namespaceFallbacks as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } else { // PEAR-like class name $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; foreach ($this->prefixes as $prefix => $dirs) { if (0 !== strpos($class, $prefix)) { continue; } foreach ($dirs as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } foreach ($this->prefixFallbacks as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) { return $file; } } } PK!S  2Symfony/Component/ClassLoader/DebugClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * Autoloader checking if the class is really defined in the file found. * * The DebugClassLoader will wrap all registered autoloaders providing a * findFile method and will throw an exception if a file is found but does * not declare the class. * * @author Fabien Potencier * @author Christophe Coevoet * * @api * * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use the DebugClassLoader provided by the Debug component instead. */ class DebugClassLoader { private $classFinder; /** * Constructor. * * @param object $classFinder * * @api */ public function __construct($classFinder) { $this->classFinder = $classFinder; } /** * Gets the wrapped class loader. * * @return object a class loader instance */ public function getClassLoader() { return $this->classFinder; } /** * Replaces all autoloaders implementing a findFile method by a DebugClassLoader wrapper. */ public static function enable() { if (!is_array($functions = spl_autoload_functions())) { return; } foreach ($functions as $function) { spl_autoload_unregister($function); } foreach ($functions as $function) { if (is_array($function) && !$function[0] instanceof self && method_exists($function[0], 'findFile')) { $function = array(new static($function[0]), 'loadClass'); } spl_autoload_register($function); } } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Finds a file by class name * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { return $this->classFinder->findFile($class); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded * * @throws \RuntimeException */ public function loadClass($class) { if ($file = $this->classFinder->findFile($class)) { require $file; if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) { if (false !== strpos($class, '/')) { throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); } throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); } return true; } } } PK!O5Symfony/Component/ClassLoader/WinCacheClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * WinCacheClassLoader implements a wrapping autoloader cached in WinCache. * * It expects an object implementing a findFile method to find the file. This * allow using it as a wrapper around the other loaders of the component (the * ClassLoader and the UniversalClassLoader for instance) but also around any * other autoloader following this convention (the Composer one for instance) * * $loader = new ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * $cachedLoader = new WinCacheClassLoader('my_prefix', $loader); * * // activate the cached autoloader * $cachedLoader->register(); * * // eventually deactivate the non-cached loader if it was registered previously * // to be sure to use the cached one. * $loader->unregister(); * * @author Fabien Potencier * @author Kris Wallsmith * @author Artem Ryzhkov */ class WinCacheClassLoader { private $prefix; /** * The class loader object being decorated. * * @var \Symfony\Component\ClassLoader\ClassLoader * A class loader object that implements the findFile() method. */ protected $decorated; /** * Constructor. * * @param string $prefix The WinCache namespace prefix to use. * @param object $decorated A class loader object that implements the findFile() method. * * @throws \RuntimeException * @throws \InvalidArgumentException */ public function __construct($prefix, $decorated) { if (!extension_loaded('wincache')) { throw new \RuntimeException('Unable to use WinCacheClassLoader as WinCache is not enabled.'); } if (!method_exists($decorated, 'findFile')) { throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); } $this->prefix = $prefix; $this->decorated = $decorated; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds a file by class name while caching lookups to WinCache. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { if (false === $file = wincache_ucache_get($this->prefix.$class)) { wincache_ucache_set($this->prefix.$class, $file = $this->decorated->findFile($class), 0); } return $file; } /** * Passes through all unknown calls onto the decorated object. */ public function __call($method, $args) { return call_user_func_array(array($this->decorated, $method), $args); } } PK!?wy 3Symfony/Component/ClassLoader/ClassMapGenerator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ClassMapGenerator * * @author Gyula Sallai */ class ClassMapGenerator { /** * Generate a class map file * * @param array|string $dirs Directories or a single path to search in * @param string $file The name of the class map file */ public static function dump($dirs, $file) { $dirs = (array) $dirs; $maps = array(); foreach ($dirs as $dir) { $maps = array_merge($maps, static::createMap($dir)); } file_put_contents($file, sprintf('isFile()) { continue; } $path = $file->getRealPath(); if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') { continue; } $classes = self::findClasses($path); foreach ($classes as $class) { $map[$class] = $path; } } return $map; } /** * Extract the classes in the given file * * @param string $path The file to check * * @return array The found classes */ private static function findClasses($path) { $contents = file_get_contents($path); $tokens = token_get_all($contents); $T_TRAIT = version_compare(PHP_VERSION, '5.4', '<') ? -1 : T_TRAIT; $classes = array(); $namespace = ''; for ($i = 0, $max = count($tokens); $i < $max; $i++) { $token = $tokens[$i]; if (is_string($token)) { continue; } $class = ''; switch ($token[0]) { case T_NAMESPACE: $namespace = ''; // If there is a namespace, extract it while (($t = $tokens[++$i]) && is_array($t)) { if (in_array($t[0], array(T_STRING, T_NS_SEPARATOR))) { $namespace .= $t[1]; } } $namespace .= '\\'; break; case T_CLASS: case T_INTERFACE: case $T_TRAIT: // Find the classname while (($t = $tokens[++$i]) && is_array($t)) { if (T_STRING === $t[0]) { $class .= $t[1]; } elseif ($class !== '' && T_WHITESPACE == $t[0]) { break; } } $classes[] = ltrim($namespace.$class, '\\'); break; default: break; } } return $classes; } } PK!lOݫ0Symfony/Component/ClassLoader/ApcClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ApcClassLoader implements a wrapping autoloader cached in APC for PHP 5.3. * * It expects an object implementing a findFile method to find the file. This * allow using it as a wrapper around the other loaders of the component (the * ClassLoader and the UniversalClassLoader for instance) but also around any * other autoloader following this convention (the Composer one for instance) * * $loader = new ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * $cachedLoader = new ApcClassLoader('my_prefix', $loader); * * // activate the cached autoloader * $cachedLoader->register(); * * // eventually deactivate the non-cached loader if it was registered previously * // to be sure to use the cached one. * $loader->unregister(); * * @author Fabien Potencier * @author Kris Wallsmith * * @api */ class ApcClassLoader { private $prefix; /** * The class loader object being decorated. * * @var \Symfony\Component\ClassLoader\ClassLoader * A class loader object that implements the findFile() method. */ protected $decorated; /** * Constructor. * * @param string $prefix The APC namespace prefix to use. * @param object $decorated A class loader object that implements the findFile() method. * * @throws \RuntimeException * @throws \InvalidArgumentException * * @api */ public function __construct($prefix, $decorated) { if (!extension_loaded('apc')) { throw new \RuntimeException('Unable to use ApcClassLoader as APC is not enabled.'); } if (!method_exists($decorated, 'findFile')) { throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); } $this->prefix = $prefix; $this->decorated = $decorated; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds a file by class name while caching lookups to APC. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { if (false === $file = apc_fetch($this->prefix.$class)) { apc_store($this->prefix.$class, $file = $this->decorated->findFile($class)); } return $file; } /** * Passes through all unknown calls onto the decorated object. */ public function __call($method, $args) { return call_user_func_array(array($this->decorated, $method), $args); } } PK!v'-Symfony/Component/ClassLoader/ClassLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ClassLoader implements an PSR-0 class loader * * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md * * $loader = new ClassLoader(); * * // register classes with namespaces * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); * $loader->addPrefix('Symfony', __DIR__.'/framework'); * * // activate the autoloader * $loader->register(); * * // to enable searching the include path (e.g. for PEAR packages) * $loader->setUseIncludePath(true); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * @author Fabien Potencier * @author Jordi Boggiano */ class ClassLoader { private $prefixes = array(); private $fallbackDirs = array(); private $useIncludePath = false; /** * Returns prefixes. * * @return array */ public function getPrefixes() { return $this->prefixes; } /** * Returns fallback directories. * * @return array */ public function getFallbackDirs() { return $this->fallbackDirs; } /** * Adds prefixes. * * @param array $prefixes Prefixes to add */ public function addPrefixes(array $prefixes) { foreach ($prefixes as $prefix => $path) { $this->addPrefix($prefix, $path); } } /** * Registers a set of classes * * @param string $prefix The classes prefix * @param array|string $paths The location(s) of the classes */ public function addPrefix($prefix, $paths) { if (!$prefix) { foreach ((array) $paths as $path) { $this->fallbackDirs[] = $path; } return; } if (isset($this->prefixes[$prefix])) { $this->prefixes[$prefix] = array_merge( $this->prefixes[$prefix], (array) $paths ); } else { $this->prefixes[$prefix] = (array) $paths; } } /** * Turns on searching the include for class files. * * @param Boolean $useIncludePath */ public function setUseIncludePath($useIncludePath) { $this->useIncludePath = $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return Boolean */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return Boolean|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|null The path, if found */ public function findFile($class) { if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR; $className = substr($class, $pos + 1); } else { // PEAR-like class name $classPath = null; $className = $class; } $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; foreach ($this->prefixes as $prefix => $dirs) { if ($class === strstr($class, $prefix)) { foreach ($dirs as $dir) { if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { return $dir.DIRECTORY_SEPARATOR.$classPath; } } } } foreach ($this->fallbackDirs as $dir) { if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { return $dir.DIRECTORY_SEPARATOR.$classPath; } } if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) { return $file; } } } PK!] I I :Symfony/Component/DependencyInjection/SimpleXMLElement.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\ExpressionLanguage\Expression; /** * SimpleXMLElement class. * * @author Fabien Potencier */ class SimpleXMLElement extends \SimpleXMLElement { /** * Converts an attribute as a PHP type. * * @param string $name * * @return mixed */ public function getAttributeAsPhp($name) { return self::phpize($this[$name]); } /** * Returns arguments as valid PHP types. * * @param string $name * @param Boolean $lowercase * * @return mixed */ public function getArgumentsAsPhp($name, $lowercase = true) { $arguments = array(); foreach ($this->$name as $arg) { if (isset($arg['name'])) { $arg['key'] = (string) $arg['name']; } $key = isset($arg['key']) ? (string) $arg['key'] : (!$arguments ? 0 : max(array_keys($arguments)) + 1); // parameter keys are case insensitive if ('parameter' == $name && $lowercase) { $key = strtolower($key); } // this is used by DefinitionDecorator to overwrite a specific // argument of the parent definition if (isset($arg['index'])) { $key = 'index_'.$arg['index']; } switch ($arg['type']) { case 'service': $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; if (isset($arg['on-invalid']) && 'ignore' == $arg['on-invalid']) { $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; } elseif (isset($arg['on-invalid']) && 'null' == $arg['on-invalid']) { $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; } if (isset($arg['strict'])) { $strict = self::phpize($arg['strict']); } else { $strict = true; } $arguments[$key] = new Reference((string) $arg['id'], $invalidBehavior, $strict); break; case 'expression': $arguments[$key] = new Expression((string) $arg); break; case 'collection': $arguments[$key] = $arg->getArgumentsAsPhp($name, false); break; case 'string': $arguments[$key] = (string) $arg; break; case 'constant': $arguments[$key] = constant((string) $arg); break; default: $arguments[$key] = self::phpize($arg); } } return $arguments; } /** * Converts an xml value to a PHP type. * * @param mixed $value * * @return mixed */ public static function phpize($value) { return XmlUtils::phpize($value); } } PK!l5/Symfony/Component/DependencyInjection/Alias.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * @api */ class Alias { private $id; private $public; /** * Constructor. * * @param string $id Alias identifier * @param Boolean $public If this alias is public * * @api */ public function __construct($id, $public = true) { $this->id = strtolower($id); $this->public = $public; } /** * Checks if this DI Alias should be public or not. * * @return Boolean * * @api */ public function isPublic() { return $this->public; } /** * Sets if this Alias is public. * * @param Boolean $boolean If this Alias should be public * * @api */ public function setPublic($boolean) { $this->public = (Boolean) $boolean; } /** * Returns the Id of this alias. * * @return string The alias id * * @api */ public function __toString() { return $this->id; } } PK!MSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; use Symfony\Component\DependencyInjection\Definition; /** * Lazy proxy dumper capable of generating the instantiation logic PHP code for proxied services. * * @author Marco Pivetta */ interface DumperInterface { /** * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container. * * @param Definition $definition * * @return bool */ public function isProxyCandidate(Definition $definition); /** * Generates the code to be used to instantiate a proxy in the dumped factory code. * * @param Definition $definition * @param string $id service identifier * * @return string */ public function getProxyFactoryCode(Definition $definition, $id); /** * Generates the code for the lazy proxy. * * @param Definition $definition * * @return string */ public function getProxyCode(Definition $definition); } PK!ҳHSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; use Symfony\Component\DependencyInjection\Definition; /** * Null dumper, negates any proxy code generation for any given service definition. * * @author Marco Pivetta */ class NullDumper implements DumperInterface { /** * {@inheritDoc} */ public function isProxyCandidate(Definition $definition) { return false; } /** * {@inheritDoc} */ public function getProxyFactoryCode(Definition $definition, $id) { return ''; } /** * {@inheritDoc} */ public function getProxyCode(Definition $definition) { return ''; } } PK!JJVSymfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; /** * Lazy proxy instantiator, capable of instantiating a proxy given a container, the * service definitions and a callback that produces the real service instance. * * @author Marco Pivetta */ interface InstantiatorInterface { /** * Instantiates a proxy object. * * @param ContainerInterface $container the container from which the service is being requested * @param Definition $definition the definition of the requested service * @param string $id identifier of the requested service * @param callable $realInstantiator zero-argument callback that is capable of producing the real * service instance * * @return object */ public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator); } PK!innXSymfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; /** * {@inheritDoc} * * Noop proxy instantiator - simply produces the real service instead of a proxy instance. * * @author Marco Pivetta */ class RealServiceInstantiator implements InstantiatorInterface { /** * {@inheritDoc} */ public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator) { return call_user_func($realInstantiator); } } PK!$772Symfony/Component/DependencyInjection/Variable.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Represents a variable. * * $var = new Variable('a'); * * will be dumped as * * $a * * by the PHP dumper. * * @author Johannes M. Schmitt */ class Variable { private $name; /** * Constructor * * @param string $name */ public function __construct($name) { $this->name = $name; } /** * Converts the object to a string * * @return string */ public function __toString() { return $this->name; } } PK!U" " CSymfony/Component/DependencyInjection/ParameterBag/ParameterBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * Holds parameters. * * @author Fabien Potencier * * @api */ class ParameterBag implements ParameterBagInterface { protected $parameters = array(); protected $resolved = false; /** * Constructor. * * @param array $parameters An array of parameters * * @api */ public function __construct(array $parameters = array()) { $this->add($parameters); } /** * Clears all parameters. * * @api */ public function clear() { $this->parameters = array(); } /** * Adds parameters to the service container parameters. * * @param array $parameters An array of parameters * * @api */ public function add(array $parameters) { foreach ($parameters as $key => $value) { $this->parameters[strtolower($key)] = $value; } } /** * Gets the service container parameters. * * @return array An array of parameters * * @api */ public function all() { return $this->parameters; } /** * Gets a service container parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws ParameterNotFoundException if the parameter is not defined * * @api */ public function get($name) { $name = strtolower($name); if (!array_key_exists($name, $this->parameters)) { if (!$name) { throw new ParameterNotFoundException($name); } $alternatives = array(); foreach (array_keys($this->parameters) as $key) { $lev = levenshtein($name, $key); if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) { $alternatives[] = $key; } } throw new ParameterNotFoundException($name, null, null, null, $alternatives); } return $this->parameters[$name]; } /** * Sets a service container parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function set($name, $value) { $this->parameters[strtolower($name)] = $value; } /** * Returns true if a parameter name is defined. * * @param string $name The parameter name * * @return Boolean true if the parameter name is defined, false otherwise * * @api */ public function has($name) { return array_key_exists(strtolower($name), $this->parameters); } /** * Removes a parameter. * * @param string $name The parameter name * * @api */ public function remove($name) { unset($this->parameters[strtolower($name)]); } /** * Replaces parameter placeholders (%name%) by their values for all parameters. */ public function resolve() { if ($this->resolved) { return; } $parameters = array(); foreach ($this->parameters as $key => $value) { try { $value = $this->resolveValue($value); $parameters[$key] = $this->unescapeValue($value); } catch (ParameterNotFoundException $e) { $e->setSourceKey($key); throw $e; } } $this->parameters = $parameters; $this->resolved = true; } /** * Replaces parameter placeholders (%name%) by their values. * * @param mixed $value A value * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) * * @return mixed The resolved value * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected * @throws RuntimeException when a given parameter has a type problem. */ public function resolveValue($value, array $resolving = array()) { if (is_array($value)) { $args = array(); foreach ($value as $k => $v) { $args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving); } return $args; } if (!is_string($value)) { return $value; } return $this->resolveString($value, $resolving); } /** * Resolves parameters inside a string * * @param string $value The string to resolve * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) * * @return string The resolved string * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected * @throws RuntimeException when a given parameter has a type problem. */ public function resolveString($value, array $resolving = array()) { // we do this to deal with non string values (Boolean, integer, ...) // as the preg_replace_callback throw an exception when trying // a non-string in a parameter value if (preg_match('/^%([^%\s]+)%$/', $value, $match)) { $key = strtolower($match[1]); if (isset($resolving[$key])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } $resolving[$key] = true; return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); } $self = $this; return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($self, $resolving, $value) { // skip %% if (!isset($match[1])) { return '%%'; } $key = strtolower($match[1]); if (isset($resolving[$key])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } $resolved = $self->get($key); if (!is_string($resolved) && !is_numeric($resolved)) { throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, gettype($resolved), $value)); } $resolved = (string) $resolved; $resolving[$key] = true; return $self->isResolved() ? $resolved : $self->resolveString($resolved, $resolving); }, $value); } public function isResolved() { return $this->resolved; } /** * {@inheritDoc} */ public function escapeValue($value) { if (is_string($value)) { return str_replace('%', '%%', $value); } if (is_array($value)) { $result = array(); foreach ($value as $k => $v) { $result[$k] = $this->escapeValue($v); } return $result; } return $value; } public function unescapeValue($value) { if (is_string($value)) { return str_replace('%%', '%', $value); } if (is_array($value)) { $result = array(); foreach ($value as $k => $v) { $result[$k] = $this->unescapeValue($v); } return $result; } return $value; } } PK!ܮP8 LSymfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; /** * ParameterBagInterface. * * @author Fabien Potencier * * @api */ interface ParameterBagInterface { /** * Clears all parameters. * * @api */ public function clear(); /** * Adds parameters to the service container parameters. * * @param array $parameters An array of parameters * * @api */ public function add(array $parameters); /** * Gets the service container parameters. * * @return array An array of parameters * * @api */ public function all(); /** * Gets a service container parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws ParameterNotFoundException if the parameter is not defined * * @api */ public function get($name); /** * Sets a service container parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function set($name, $value); /** * Returns true if a parameter name is defined. * * @param string $name The parameter name * * @return Boolean true if the parameter name is defined, false otherwise * * @api */ public function has($name); /** * Replaces parameter placeholders (%name%) by their values for all parameters. */ public function resolve(); /** * Replaces parameter placeholders (%name%) by their values. * * @param mixed $value A value * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist */ public function resolveValue($value); /** * Escape parameter placeholders % * * @param mixed $value * * @return mixed */ public function escapeValue($value); /** * Unescape parameter placeholders % * * @param mixed $value * * @return mixed */ public function unescapeValue($value); } PK!ךISymfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\Exception\LogicException; /** * Holds read-only parameters. * * @author Fabien Potencier * * @api */ class FrozenParameterBag extends ParameterBag { /** * Constructor. * * For performance reasons, the constructor assumes that * all keys are already lowercased. * * This is always the case when used internally. * * @param array $parameters An array of parameters * * @api */ public function __construct(array $parameters = array()) { $this->parameters = $parameters; $this->resolved = true; } /** * {@inheritDoc} * * @api */ public function clear() { throw new LogicException('Impossible to call clear() on a frozen ParameterBag.'); } /** * {@inheritDoc} * * @api */ public function add(array $parameters) { throw new LogicException('Impossible to call add() on a frozen ParameterBag.'); } /** * {@inheritDoc} * * @api */ public function set($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } } PK!,xmm/Symfony/Component/DependencyInjection/Scope.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Scope class. * * @author Johannes M. Schmitt * * @api */ class Scope implements ScopeInterface { private $name; private $parentName; /** * @api */ public function __construct($name, $parentName = ContainerInterface::SCOPE_CONTAINER) { $this->name = $name; $this->parentName = $parentName; } /** * @api */ public function getName() { return $this->name; } /** * @api */ public function getParentName() { return $this->parentName; } } PK! ]]4Symfony/Component/DependencyInjection/autoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Scope Interface. * * @author Johannes M. Schmitt * * @api */ interface ScopeInterface { /** * @api */ public function getName(); /** * @api */ public function getParentName(); } PK!BtBBJSymfony/Component/DependencyInjection/IntrospectableContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * IntrospectableContainerInterface defines additional introspection functionality * for containers, allowing logic to be implemented based on a Container's state. * * @author Evan Villemez * */ interface IntrospectableContainerInterface extends ContainerInterface { /** * Check for whether or not a service has been initialized. * * @param string $id * * @return Boolean true if the service has been initialized, false otherwise * */ public function initialized($id); } PK! O,JSymfony/Component/DependencyInjection/Exception/BadMethodCallException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base BadMethodCallException for Dependency Injection component. */ class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface { } PK! LSymfony/Component/DependencyInjection/Exception/ServiceNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a non-existent service is requested. * * @author Johannes M. Schmitt */ class ServiceNotFoundException extends InvalidArgumentException { private $id; private $sourceId; public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = array()) { if (null === $sourceId) { $msg = sprintf('You have requested a non-existent service "%s".', $id); } else { $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id); } if ($alternatives) { if (1 == count($alternatives)) { $msg .= ' Did you mean this: "'; } else { $msg .= ' Did you mean one of these: "'; } $msg .= implode('", "', $alternatives).'"?'; } parent::__construct($msg, 0, $previous); $this->id = $id; $this->sourceId = $sourceId; } public function getId() { return $this->id; } public function getSourceId() { return $this->sourceId; } } PK!{HSymfony/Component/DependencyInjection/Exception/OutOfBoundsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base OutOfBoundsException for Dependency Injection component. */ class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface { } PK!9FSymfony/Component/DependencyInjection/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base ExceptionInterface for Dependency Injection component. * * @author Fabien Potencier * @author Bulat Shakirzyanov */ interface ExceptionInterface { } PK! +DSymfony/Component/DependencyInjection/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base RuntimeException for Dependency Injection component. * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK!\ NSymfony/Component/DependencyInjection/Exception/ParameterNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a non-existent parameter is used. * * @author Fabien Potencier */ class ParameterNotFoundException extends InvalidArgumentException { private $key; private $sourceId; private $sourceKey; private $alternatives; /** * Constructor. * * @param string $key The requested parameter key * @param string $sourceId The service id that references the non-existent parameter * @param string $sourceKey The parameter key that references the non-existent parameter * @param \Exception $previous The previous exception * @param string[] $alternatives Some parameter name alternatives */ public function __construct($key, $sourceId = null, $sourceKey = null, \Exception $previous = null, array $alternatives = array()) { $this->key = $key; $this->sourceId = $sourceId; $this->sourceKey = $sourceKey; $this->alternatives = $alternatives; parent::__construct('', 0, $previous); $this->updateRepr(); } public function updateRepr() { if (null !== $this->sourceId) { $this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key); } elseif (null !== $this->sourceKey) { $this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key); } else { $this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key); } if ($this->alternatives) { if (1 == count($this->alternatives)) { $this->message .= ' Did you mean this: "'; } else { $this->message .= ' Did you mean one of these: "'; } $this->message .= implode('", "', $this->alternatives).'"?'; } } public function getKey() { return $this->key; } public function getSourceId() { return $this->sourceId; } public function getSourceKey() { return $this->sourceKey; } public function setSourceId($sourceId) { $this->sourceId = $sourceId; $this->updateRepr(); } public function setSourceKey($sourceKey) { $this->sourceKey = $sourceKey; $this->updateRepr(); } } PK!I_JSymfony/Component/DependencyInjection/Exception/InactiveScopeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when you try to create a service of an inactive scope. * * @author Johannes M. Schmitt */ class InactiveScopeException extends RuntimeException { private $serviceId; private $scope; public function __construct($serviceId, $scope, \Exception $previous = null) { parent::__construct(sprintf('You cannot create a service ("%s") of an inactive scope ("%s").', $serviceId, $scope), 0, $previous); $this->serviceId = $serviceId; $this->scope = $scope; } public function getServiceId() { return $this->serviceId; } public function getScope() { return $this->scope; } } PK!zSSymfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Thrown when a scope widening injection is detected. * * @author Johannes M. Schmitt */ class ScopeWideningInjectionException extends RuntimeException { private $sourceServiceId; private $sourceScope; private $destServiceId; private $destScope; public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null) { parent::__construct(sprintf( 'Scope Widening Injection detected: The definition "%s" references the service "%s" which belongs to a narrower scope. ' .'Generally, it is safer to either move "%s" to scope "%s" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "%s" each time it is needed. ' .'In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.', $sourceServiceId, $destServiceId, $sourceServiceId, $destScope, $destServiceId ), 0, $previous); $this->sourceServiceId = $sourceServiceId; $this->sourceScope = $sourceScope; $this->destServiceId = $destServiceId; $this->destScope = $destScope; } public function getSourceServiceId() { return $this->sourceServiceId; } public function getSourceScope() { return $this->sourceScope; } public function getDestServiceId() { return $this->destServiceId; } public function getDestScope() { return $this->destScope; } } PK!l.BSymfony/Component/DependencyInjection/Exception/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base LogicException for Dependency Injection component. */ class LogicException extends \LogicException implements ExceptionInterface { } PK!]USymfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a circular reference is detected. * * @author Johannes M. Schmitt */ class ServiceCircularReferenceException extends RuntimeException { private $serviceId; private $path; public function __construct($serviceId, array $path, \Exception $previous = null) { parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous); $this->serviceId = $serviceId; $this->path = $path; } public function getServiceId() { return $this->serviceId; } public function getPath() { return $this->path; } } PK!LSymfony/Component/DependencyInjection/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base InvalidArgumentException for Dependency Injection component. * * @author Bulat Shakirzyanov */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK!= ԥSSymfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when the a scope crossing injection is detected. * * @author Johannes M. Schmitt */ class ScopeCrossingInjectionException extends RuntimeException { private $sourceServiceId; private $sourceScope; private $destServiceId; private $destScope; public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null) { parent::__construct(sprintf( 'Scope Crossing Injection detected: The definition "%s" references the service "%s" which belongs to another scope hierarchy. ' .'This service might not be available consistently. Generally, it is safer to either move the definition "%s" to scope "%s", or ' .'declare "%s" as a child scope of "%s". If you can be sure that the other scope is always active, you can set the reference to strict=false to get rid of this error.', $sourceServiceId, $destServiceId, $sourceServiceId, $destScope, $sourceScope, $destScope ), 0, $previous); $this->sourceServiceId = $sourceServiceId; $this->sourceScope = $sourceScope; $this->destServiceId = $destServiceId; $this->destScope = $destScope; } public function getSourceServiceId() { return $this->sourceServiceId; } public function getSourceScope() { return $this->sourceScope; } public function getDestServiceId() { return $this->destServiceId; } public function getDestScope() { return $this->destScope; } } PK!qBWSymfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a circular reference in a parameter is detected. * * @author Fabien Potencier */ class ParameterCircularReferenceException extends RuntimeException { private $parameters; public function __construct($parameters, \Exception $previous = null) { parent::__construct(sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous); $this->parameters = $parameters; } public function getParameters() { return $this->parameters; } } PK!q8IASymfony/Component/DependencyInjection/ContainerAwareInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * ContainerAwareInterface should be implemented by classes that depends on a Container. * * @author Fabien Potencier * * @api */ interface ContainerAwareInterface { /** * Sets the Container. * * @param ContainerInterface|null $container A ContainerInterface instance or null * * @api */ public function setContainer(ContainerInterface $container = null); } PK!-&:Symfony/Component/DependencyInjection/ContainerBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; use Symfony\Component\ExpressionLanguage\Expression; /** * ContainerBuilder is a DI container that provides an API to easily describe services. * * @author Fabien Potencier * * @api */ class ContainerBuilder extends Container implements TaggedContainerInterface { /** * @var ExtensionInterface[] */ private $extensions = array(); /** * @var ExtensionInterface[] */ private $extensionsByNs = array(); /** * @var Definition[] */ private $definitions = array(); /** * @var Definition[] */ private $obsoleteDefinitions = array(); /** * @var Alias[] */ private $aliasDefinitions = array(); /** * @var ResourceInterface[] */ private $resources = array(); private $extensionConfigs = array(); /** * @var Compiler */ private $compiler; private $trackResources = true; /** * @var InstantiatorInterface|null */ private $proxyInstantiator; /** * @var ExpressionLanguage|null */ private $expressionLanguage; /** * Sets the track resources flag. * * If you are not using the loaders and therefore don't want * to depend on the Config component, set this flag to false. * * @param Boolean $track true if you want to track resources, false otherwise */ public function setResourceTracking($track) { $this->trackResources = (Boolean) $track; } /** * Checks if resources are tracked. * * @return Boolean true if resources are tracked, false otherwise */ public function isTrackingResources() { return $this->trackResources; } /** * Sets the instantiator to be used when fetching proxies. * * @param InstantiatorInterface $proxyInstantiator */ public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) { $this->proxyInstantiator = $proxyInstantiator; } /** * Registers an extension. * * @param ExtensionInterface $extension An extension instance * * @api */ public function registerExtension(ExtensionInterface $extension) { $this->extensions[$extension->getAlias()] = $extension; if (false !== $extension->getNamespace()) { $this->extensionsByNs[$extension->getNamespace()] = $extension; } } /** * Returns an extension by alias or namespace. * * @param string $name An alias or a namespace * * @return ExtensionInterface An extension instance * * @throws LogicException if the extension is not registered * * @api */ public function getExtension($name) { if (isset($this->extensions[$name])) { return $this->extensions[$name]; } if (isset($this->extensionsByNs[$name])) { return $this->extensionsByNs[$name]; } throw new LogicException(sprintf('Container extension "%s" is not registered', $name)); } /** * Returns all registered extensions. * * @return ExtensionInterface[] An array of ExtensionInterface * * @api */ public function getExtensions() { return $this->extensions; } /** * Checks if we have an extension. * * @param string $name The name of the extension * * @return Boolean If the extension exists * * @api */ public function hasExtension($name) { return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]); } /** * Returns an array of resources loaded to build this configuration. * * @return ResourceInterface[] An array of resources * * @api */ public function getResources() { return array_unique($this->resources); } /** * Adds a resource for this configuration. * * @param ResourceInterface $resource A resource instance * * @return ContainerBuilder The current instance * * @api */ public function addResource(ResourceInterface $resource) { if (!$this->trackResources) { return $this; } $this->resources[] = $resource; return $this; } /** * Sets the resources for this configuration. * * @param ResourceInterface[] $resources An array of resources * * @return ContainerBuilder The current instance * * @api */ public function setResources(array $resources) { if (!$this->trackResources) { return $this; } $this->resources = $resources; return $this; } /** * Adds the object class hierarchy as resources. * * @param object $object An object instance * * @return ContainerBuilder The current instance * * @api */ public function addObjectResource($object) { if ($this->trackResources) { $this->addClassResource(new \ReflectionClass($object)); } return $this; } /** * Adds the given class hierarchy as resources. * * @param \ReflectionClass $class * * @return ContainerBuilder The current instance */ public function addClassResource(\ReflectionClass $class) { if (!$this->trackResources) { return $this; } do { $this->addResource(new FileResource($class->getFileName())); } while ($class = $class->getParentClass()); return $this; } /** * Loads the configuration for an extension. * * @param string $extension The extension alias or namespace * @param array $values An array of values that customizes the extension * * @return ContainerBuilder The current instance * @throws BadMethodCallException When this ContainerBuilder is frozen * * @throws \LogicException if the container is frozen * * @api */ public function loadFromExtension($extension, array $values = array()) { if ($this->isFrozen()) { throw new BadMethodCallException('Cannot load from an extension on a frozen container.'); } $namespace = $this->getExtension($extension)->getAlias(); $this->extensionConfigs[$namespace][] = $values; return $this; } /** * Adds a compiler pass. * * @param CompilerPassInterface $pass A compiler pass * @param string $type The type of compiler pass * * @return ContainerBuilder The current instance * * @api */ public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) { $this->getCompiler()->addPass($pass, $type); $this->addObjectResource($pass); return $this; } /** * Returns the compiler pass config which can then be modified. * * @return PassConfig The compiler pass config * * @api */ public function getCompilerPassConfig() { return $this->getCompiler()->getPassConfig(); } /** * Returns the compiler. * * @return Compiler The compiler * * @api */ public function getCompiler() { if (null === $this->compiler) { $this->compiler = new Compiler(); } return $this->compiler; } /** * Returns all Scopes. * * @return array An array of scopes * * @api */ public function getScopes() { return $this->scopes; } /** * Returns all Scope children. * * @return array An array of scope children. * * @api */ public function getScopeChildren() { return $this->scopeChildren; } /** * Sets a service. * * @param string $id The service identifier * @param object $service The service instance * @param string $scope The scope * * @throws BadMethodCallException When this ContainerBuilder is frozen * * @api */ public function set($id, $service, $scope = self::SCOPE_CONTAINER) { $id = strtolower($id); if ($this->isFrozen()) { // setting a synthetic service on a frozen container is alright if ( (!isset($this->definitions[$id]) && !isset($this->obsoleteDefinitions[$id])) || (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic()) || (isset($this->obsoleteDefinitions[$id]) && !$this->obsoleteDefinitions[$id]->isSynthetic()) ) { throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id)); } } if (isset($this->definitions[$id])) { $this->obsoleteDefinitions[$id] = $this->definitions[$id]; } unset($this->definitions[$id], $this->aliasDefinitions[$id]); parent::set($id, $service, $scope); if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized()) { $this->synchronize($id); } } /** * Removes a service definition. * * @param string $id The service identifier * * @api */ public function removeDefinition($id) { unset($this->definitions[strtolower($id)]); } /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return Boolean true if the service is defined, false otherwise * * @api */ public function has($id) { $id = strtolower($id); return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id); } /** * Gets a service. * * @param string $id The service identifier * @param integer $invalidBehavior The behavior when the service does not exist * * @return object The associated service * * @throws InvalidArgumentException when no definitions are available * @throws InactiveScopeException when the current scope is not active * @throws LogicException when a circular dependency is detected * @throws \Exception * * @see Reference * * @api */ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { $id = strtolower($id); try { return parent::get($id, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); } catch (InactiveScopeException $e) { if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return null; } throw $e; } catch (InvalidArgumentException $e) { if (isset($this->loading[$id])) { throw new LogicException(sprintf('The service "%s" has a circular reference to itself.', $id), 0, $e); } if (!$this->hasDefinition($id) && isset($this->aliasDefinitions[$id])) { return $this->get($this->aliasDefinitions[$id]); } try { $definition = $this->getDefinition($id); } catch (InvalidArgumentException $e) { if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return null; } throw $e; } $this->loading[$id] = true; try { $service = $this->createService($definition, $id); } catch (\Exception $e) { unset($this->loading[$id]); if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return null; } throw $e; } unset($this->loading[$id]); return $service; } } /** * Merges a ContainerBuilder with the current ContainerBuilder configuration. * * Service definitions overrides the current defined ones. * * But for parameters, they are overridden by the current ones. It allows * the parameters passed to the container constructor to have precedence * over the loaded ones. * * $container = new ContainerBuilder(array('foo' => 'bar')); * $loader = new LoaderXXX($container); * $loader->load('resource_name'); * $container->register('foo', new stdClass()); * * In the above example, even if the loaded resource defines a foo * parameter, the value will still be 'bar' as defined in the ContainerBuilder * constructor. * * @param ContainerBuilder $container The ContainerBuilder instance to merge. * * * @throws BadMethodCallException When this ContainerBuilder is frozen * * @api */ public function merge(ContainerBuilder $container) { if ($this->isFrozen()) { throw new BadMethodCallException('Cannot merge on a frozen container.'); } $this->addDefinitions($container->getDefinitions()); $this->addAliases($container->getAliases()); $this->getParameterBag()->add($container->getParameterBag()->all()); if ($this->trackResources) { foreach ($container->getResources() as $resource) { $this->addResource($resource); } } foreach ($this->extensions as $name => $extension) { if (!isset($this->extensionConfigs[$name])) { $this->extensionConfigs[$name] = array(); } $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name)); } } /** * Returns the configuration array for the given extension. * * @param string $name The name of the extension * * @return array An array of configuration * * @api */ public function getExtensionConfig($name) { if (!isset($this->extensionConfigs[$name])) { $this->extensionConfigs[$name] = array(); } return $this->extensionConfigs[$name]; } /** * Prepends a config array to the configs of the given extension. * * @param string $name The name of the extension * @param array $config The config to set */ public function prependExtensionConfig($name, array $config) { if (!isset($this->extensionConfigs[$name])) { $this->extensionConfigs[$name] = array(); } array_unshift($this->extensionConfigs[$name], $config); } /** * Compiles the container. * * This method passes the container to compiler * passes whose job is to manipulate and optimize * the container. * * The main compiler passes roughly do four things: * * * The extension configurations are merged; * * Parameter values are resolved; * * The parameter bag is frozen; * * Extension loading is disabled. * * @api */ public function compile() { $compiler = $this->getCompiler(); if ($this->trackResources) { foreach ($compiler->getPassConfig()->getPasses() as $pass) { $this->addObjectResource($pass); } } $compiler->compile($this); if ($this->trackResources) { foreach ($this->definitions as $definition) { if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) { $this->addClassResource(new \ReflectionClass($class)); } } } $this->extensionConfigs = array(); parent::compile(); } /** * Gets all service ids. * * @return array An array of all defined service ids */ public function getServiceIds() { return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds())); } /** * Adds the service aliases. * * @param array $aliases An array of aliases * * @api */ public function addAliases(array $aliases) { foreach ($aliases as $alias => $id) { $this->setAlias($alias, $id); } } /** * Sets the service aliases. * * @param array $aliases An array of aliases * * @api */ public function setAliases(array $aliases) { $this->aliasDefinitions = array(); $this->addAliases($aliases); } /** * Sets an alias for an existing service. * * @param string $alias The alias to create * @param string|Alias $id The service to alias * * @throws InvalidArgumentException if the id is not a string or an Alias * @throws InvalidArgumentException if the alias is for itself * * @api */ public function setAlias($alias, $id) { $alias = strtolower($alias); if (is_string($id)) { $id = new Alias($id); } elseif (!$id instanceof Alias) { throw new InvalidArgumentException('$id must be a string, or an Alias object.'); } if ($alias === strtolower($id)) { throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias)); } unset($this->definitions[$alias]); $this->aliasDefinitions[$alias] = $id; } /** * Removes an alias. * * @param string $alias The alias to remove * * @api */ public function removeAlias($alias) { unset($this->aliasDefinitions[strtolower($alias)]); } /** * Returns true if an alias exists under the given identifier. * * @param string $id The service identifier * * @return Boolean true if the alias exists, false otherwise * * @api */ public function hasAlias($id) { return isset($this->aliasDefinitions[strtolower($id)]); } /** * Gets all defined aliases. * * @return Alias[] An array of aliases * * @api */ public function getAliases() { return $this->aliasDefinitions; } /** * Gets an alias. * * @param string $id The service identifier * * @return Alias An Alias instance * * @throws InvalidArgumentException if the alias does not exist * * @api */ public function getAlias($id) { $id = strtolower($id); if (!$this->hasAlias($id)) { throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id)); } return $this->aliasDefinitions[$id]; } /** * Registers a service definition. * * This methods allows for simple registration of service definition * with a fluid interface. * * @param string $id The service identifier * @param string $class The service class * * @return Definition A Definition instance * * @api */ public function register($id, $class = null) { return $this->setDefinition(strtolower($id), new Definition($class)); } /** * Adds the service definitions. * * @param Definition[] $definitions An array of service definitions * * @api */ public function addDefinitions(array $definitions) { foreach ($definitions as $id => $definition) { $this->setDefinition($id, $definition); } } /** * Sets the service definitions. * * @param Definition[] $definitions An array of service definitions * * @api */ public function setDefinitions(array $definitions) { $this->definitions = array(); $this->addDefinitions($definitions); } /** * Gets all service definitions. * * @return Definition[] An array of Definition instances * * @api */ public function getDefinitions() { return $this->definitions; } /** * Sets a service definition. * * @param string $id The service identifier * @param Definition $definition A Definition instance * * @return Definition the service definition * * @throws BadMethodCallException When this ContainerBuilder is frozen * * @api */ public function setDefinition($id, Definition $definition) { if ($this->isFrozen()) { throw new BadMethodCallException('Adding definition to a frozen container is not allowed'); } $id = strtolower($id); unset($this->aliasDefinitions[$id]); return $this->definitions[$id] = $definition; } /** * Returns true if a service definition exists under the given identifier. * * @param string $id The service identifier * * @return Boolean true if the service definition exists, false otherwise * * @api */ public function hasDefinition($id) { return array_key_exists(strtolower($id), $this->definitions); } /** * Gets a service definition. * * @param string $id The service identifier * * @return Definition A Definition instance * * @throws InvalidArgumentException if the service definition does not exist * * @api */ public function getDefinition($id) { $id = strtolower($id); if (!$this->hasDefinition($id)) { throw new InvalidArgumentException(sprintf('The service definition "%s" does not exist.', $id)); } return $this->definitions[$id]; } /** * Gets a service definition by id or alias. * * The method "unaliases" recursively to return a Definition instance. * * @param string $id The service identifier or alias * * @return Definition A Definition instance * * @throws InvalidArgumentException if the service definition does not exist * * @api */ public function findDefinition($id) { while ($this->hasAlias($id)) { $id = (string) $this->getAlias($id); } return $this->getDefinition($id); } /** * Creates a service for a service definition. * * @param Definition $definition A service definition instance * @param string $id The service identifier * @param Boolean $tryProxy Whether to try proxying the service with a lazy proxy * * @return object The service described by the service definition * * @throws RuntimeException When the scope is inactive * @throws RuntimeException When the factory definition is incomplete * @throws RuntimeException When the service is a synthetic service * @throws InvalidArgumentException When configure callable is not callable * * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code */ public function createService(Definition $definition, $id, $tryProxy = true) { if ($definition->isSynthetic()) { throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); } if ($tryProxy && $definition->isLazy()) { $container = $this; $proxy = $this ->getProxyInstantiator() ->instantiateProxy( $container, $definition, $id, function () use ($definition, $id, $container) { return $container->createService($definition, $id, false); } ); $this->shareService($definition, $proxy, $id); return $proxy; } $parameterBag = $this->getParameterBag(); if (null !== $definition->getFile()) { require_once $parameterBag->resolveValue($definition->getFile()); } $arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments()))); if (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryClass()) { $factory = $parameterBag->resolveValue($definition->getFactoryClass()); } elseif (null !== $definition->getFactoryService()) { $factory = $this->get($parameterBag->resolveValue($definition->getFactoryService())); } else { throw new RuntimeException(sprintf('Cannot create service "%s" from factory method without a factory service or factory class.', $id)); } $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments); } else { $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass())); $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); } if ($tryProxy || !$definition->isLazy()) { // share only if proxying failed, or if not a proxy $this->shareService($definition, $service, $id); } foreach ($definition->getMethodCalls() as $call) { $this->callMethod($service, $call); } $properties = $this->resolveServices($parameterBag->resolveValue($definition->getProperties())); foreach ($properties as $name => $value) { $service->$name = $value; } if ($callable = $definition->getConfigurator()) { if (is_array($callable)) { $callable[0] = $callable[0] instanceof Reference ? $this->get((string) $callable[0]) : $parameterBag->resolveValue($callable[0]); } if (!is_callable($callable)) { throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service))); } call_user_func($callable, $service); } return $service; } /** * Replaces service references by the real service instance and evaluates expressions. * * @param mixed $value A value * * @return mixed The same value with all service references replaced by * the real service instances and all expressions evaluated */ public function resolveServices($value) { if (is_array($value)) { foreach ($value as &$v) { $v = $this->resolveServices($v); } } elseif ($value instanceof Reference) { $value = $this->get((string) $value, $value->getInvalidBehavior()); } elseif ($value instanceof Definition) { $value = $this->createService($value, null); } elseif ($value instanceof Expression) { $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this)); } return $value; } /** * Returns service ids for a given tag. * * Example: * * $container->register('foo')->addTag('my.tag', array('hello' => 'world')); * * $serviceIds = $container->findTaggedServiceIds('my.tag'); * foreach ($serviceIds as $serviceId => $tags) { * foreach ($tags as $tag) { * echo $tag['hello']; * } * } * * @param string $name The tag name * * @return array An array of tags with the tagged service as key, holding a list of attribute arrays. * * @api */ public function findTaggedServiceIds($name) { $tags = array(); foreach ($this->getDefinitions() as $id => $definition) { if ($definition->hasTag($name)) { $tags[$id] = $definition->getTag($name); } } return $tags; } /** * Returns all tags the defined services use. * * @return array An array of tags */ public function findTags() { $tags = array(); foreach ($this->getDefinitions() as $id => $definition) { $tags = array_merge(array_keys($definition->getTags()), $tags); } return array_unique($tags); } /** * Returns the Service Conditionals. * * @param mixed $value An array of conditionals to return. * * @return array An array of Service conditionals */ public static function getServiceConditionals($value) { $services = array(); if (is_array($value)) { foreach ($value as $v) { $services = array_unique(array_merge($services, self::getServiceConditionals($v))); } } elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE) { $services[] = (string) $value; } return $services; } /** * Retrieves the currently set proxy instantiator or instantiates one. * * @return InstantiatorInterface */ private function getProxyInstantiator() { if (!$this->proxyInstantiator) { $this->proxyInstantiator = new RealServiceInstantiator(); } return $this->proxyInstantiator; } /** * Synchronizes a service change. * * This method updates all services that depend on the given * service by calling all methods referencing it. * * @param string $id A service id */ private function synchronize($id) { foreach ($this->definitions as $definitionId => $definition) { // only check initialized services if (!$this->initialized($definitionId)) { continue; } foreach ($definition->getMethodCalls() as $call) { foreach ($call[1] as $argument) { if ($argument instanceof Reference && $id == (string) $argument) { $this->callMethod($this->get($definitionId), $call); } } } } } private function callMethod($service, $call) { $services = self::getServiceConditionals($call[1]); foreach ($services as $s) { if (!$this->has($s)) { return; } } call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1]))); } /** * Shares a given service in the container * * @param Definition $definition * @param mixed $service * @param string $id * * @throws InactiveScopeException */ private function shareService(Definition $definition, $service, $id) { if (self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) { throw new InactiveScopeException($id, $scope); } $this->services[$lowerId = strtolower($id)] = $service; if (self::SCOPE_CONTAINER !== $scope) { $this->scopedServices[$scope][$lowerId] = $service; } } } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK!c!89894Symfony/Component/DependencyInjection/Definition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; /** * Definition represents a service definition. * * @author Fabien Potencier * * @api */ class Definition { private $class; private $file; private $factoryClass; private $factoryMethod; private $factoryService; private $scope = ContainerInterface::SCOPE_CONTAINER; private $properties = array(); private $calls = array(); private $configurator; private $tags = array(); private $public = true; private $synthetic = false; private $abstract = false; private $synchronized = false; private $lazy = false; protected $arguments; /** * Constructor. * * @param string|null $class The service class * @param array $arguments An array of arguments to pass to the service constructor * * @api */ public function __construct($class = null, array $arguments = array()) { $this->class = $class; $this->arguments = $arguments; } /** * Sets the name of the class that acts as a factory using the factory method, * which will be invoked statically. * * @param string $factoryClass The factory class name * * @return Definition The current instance * * @api */ public function setFactoryClass($factoryClass) { $this->factoryClass = $factoryClass; return $this; } /** * Gets the factory class. * * @return string|null The factory class name * * @api */ public function getFactoryClass() { return $this->factoryClass; } /** * Sets the factory method able to create an instance of this class. * * @param string $factoryMethod The factory method name * * @return Definition The current instance * * @api */ public function setFactoryMethod($factoryMethod) { $this->factoryMethod = $factoryMethod; return $this; } /** * Gets the factory method. * * @return string|null The factory method name * * @api */ public function getFactoryMethod() { return $this->factoryMethod; } /** * Sets the name of the service that acts as a factory using the factory method. * * @param string $factoryService The factory service id * * @return Definition The current instance * * @api */ public function setFactoryService($factoryService) { $this->factoryService = $factoryService; return $this; } /** * Gets the factory service id. * * @return string|null The factory service id * * @api */ public function getFactoryService() { return $this->factoryService; } /** * Sets the service class. * * @param string $class The service class * * @return Definition The current instance * * @api */ public function setClass($class) { $this->class = $class; return $this; } /** * Gets the service class. * * @return string|null The service class * * @api */ public function getClass() { return $this->class; } /** * Sets the arguments to pass to the service constructor/factory method. * * @param array $arguments An array of arguments * * @return Definition The current instance * * @api */ public function setArguments(array $arguments) { $this->arguments = $arguments; return $this; } /** * @api */ public function setProperties(array $properties) { $this->properties = $properties; return $this; } /** * @api */ public function getProperties() { return $this->properties; } /** * @api */ public function setProperty($name, $value) { $this->properties[$name] = $value; return $this; } /** * Adds an argument to pass to the service constructor/factory method. * * @param mixed $argument An argument * * @return Definition The current instance * * @api */ public function addArgument($argument) { $this->arguments[] = $argument; return $this; } /** * Sets a specific argument * * @param integer $index * @param mixed $argument * * @return Definition The current instance * * @throws OutOfBoundsException When the replaced argument does not exist * * @api */ public function replaceArgument($index, $argument) { if ($index < 0 || $index > count($this->arguments) - 1) { throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1)); } $this->arguments[$index] = $argument; return $this; } /** * Gets the arguments to pass to the service constructor/factory method. * * @return array The array of arguments * * @api */ public function getArguments() { return $this->arguments; } /** * Gets an argument to pass to the service constructor/factory method. * * @param integer $index * * @return mixed The argument value * * @throws OutOfBoundsException When the argument does not exist * * @api */ public function getArgument($index) { if ($index < 0 || $index > count($this->arguments) - 1) { throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1)); } return $this->arguments[$index]; } /** * Sets the methods to call after service initialization. * * @param array $calls An array of method calls * * @return Definition The current instance * * @api */ public function setMethodCalls(array $calls = array()) { $this->calls = array(); foreach ($calls as $call) { $this->addMethodCall($call[0], $call[1]); } return $this; } /** * Adds a method to call after service initialization. * * @param string $method The method name to call * @param array $arguments An array of arguments to pass to the method call * * @return Definition The current instance * * @throws InvalidArgumentException on empty $method param * * @api */ public function addMethodCall($method, array $arguments = array()) { if (empty($method)) { throw new InvalidArgumentException(sprintf('Method name cannot be empty.')); } $this->calls[] = array($method, $arguments); return $this; } /** * Removes a method to call after service initialization. * * @param string $method The method name to remove * * @return Definition The current instance * * @api */ public function removeMethodCall($method) { foreach ($this->calls as $i => $call) { if ($call[0] === $method) { unset($this->calls[$i]); break; } } return $this; } /** * Check if the current definition has a given method to call after service initialization. * * @param string $method The method name to search for * * @return Boolean * * @api */ public function hasMethodCall($method) { foreach ($this->calls as $call) { if ($call[0] === $method) { return true; } } return false; } /** * Gets the methods to call after service initialization. * * @return array An array of method calls * * @api */ public function getMethodCalls() { return $this->calls; } /** * Sets tags for this definition * * @param array $tags * * @return Definition the current instance * * @api */ public function setTags(array $tags) { $this->tags = $tags; return $this; } /** * Returns all tags. * * @return array An array of tags * * @api */ public function getTags() { return $this->tags; } /** * Gets a tag by name. * * @param string $name The tag name * * @return array An array of attributes * * @api */ public function getTag($name) { return isset($this->tags[$name]) ? $this->tags[$name] : array(); } /** * Adds a tag for this definition. * * @param string $name The tag name * @param array $attributes An array of attributes * * @return Definition The current instance * * @api */ public function addTag($name, array $attributes = array()) { $this->tags[$name][] = $attributes; return $this; } /** * Whether this definition has a tag with the given name * * @param string $name * * @return Boolean * * @api */ public function hasTag($name) { return isset($this->tags[$name]); } /** * Clears all tags for a given name. * * @param string $name The tag name * * @return Definition */ public function clearTag($name) { if (isset($this->tags[$name])) { unset($this->tags[$name]); } return $this; } /** * Clears the tags for this definition. * * @return Definition The current instance * * @api */ public function clearTags() { $this->tags = array(); return $this; } /** * Sets a file to require before creating the service. * * @param string $file A full pathname to include * * @return Definition The current instance * * @api */ public function setFile($file) { $this->file = $file; return $this; } /** * Gets the file to require before creating the service. * * @return string|null The full pathname to include * * @api */ public function getFile() { return $this->file; } /** * Sets the scope of the service * * @param string $scope Whether the service must be shared or not * * @return Definition The current instance * * @api */ public function setScope($scope) { $this->scope = $scope; return $this; } /** * Returns the scope of the service * * @return string * * @api */ public function getScope() { return $this->scope; } /** * Sets the visibility of this service. * * @param Boolean $boolean * * @return Definition The current instance * * @api */ public function setPublic($boolean) { $this->public = (Boolean) $boolean; return $this; } /** * Whether this service is public facing * * @return Boolean * * @api */ public function isPublic() { return $this->public; } /** * Sets the synchronized flag of this service. * * @param Boolean $boolean * * @return Definition The current instance * * @api */ public function setSynchronized($boolean) { $this->synchronized = (Boolean) $boolean; return $this; } /** * Whether this service is synchronized. * * @return Boolean * * @api */ public function isSynchronized() { return $this->synchronized; } /** * Sets the lazy flag of this service. * * @param Boolean $lazy * * @return Definition The current instance */ public function setLazy($lazy) { $this->lazy = (Boolean) $lazy; return $this; } /** * Whether this service is lazy. * * @return Boolean */ public function isLazy() { return $this->lazy; } /** * Sets whether this definition is synthetic, that is not constructed by the * container, but dynamically injected. * * @param Boolean $boolean * * @return Definition the current instance * * @api */ public function setSynthetic($boolean) { $this->synthetic = (Boolean) $boolean; return $this; } /** * Whether this definition is synthetic, that is not constructed by the * container, but dynamically injected. * * @return Boolean * * @api */ public function isSynthetic() { return $this->synthetic; } /** * Whether this definition is abstract, that means it merely serves as a * template for other definitions. * * @param Boolean $boolean * * @return Definition the current instance * * @api */ public function setAbstract($boolean) { $this->abstract = (Boolean) $boolean; return $this; } /** * Whether this definition is abstract, that means it merely serves as a * template for other definitions. * * @return Boolean * * @api */ public function isAbstract() { return $this->abstract; } /** * Sets a configurator to call after the service is fully initialized. * * @param callable $callable A PHP callable * * @return Definition The current instance * * @api */ public function setConfigurator($callable) { $this->configurator = $callable; return $this; } /** * Gets the configurator to call after the service is fully initialized. * * @return callable|null The PHP callable to call * * @api */ public function getConfigurator() { return $this->configurator; } } PK!uii8Symfony/Component/DependencyInjection/ContainerAware.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * A simple implementation of ContainerAwareInterface. * * @author Fabien Potencier * * @api */ abstract class ContainerAware implements ContainerAwareInterface { /** * @var ContainerInterface * * @api */ protected $container; /** * Sets the Container associated with this Controller. * * @param ContainerInterface $container A ContainerInterface instance * * @api */ public function setContainer(ContainerInterface $container = null) { $this->container = $container; } } PK!H 8=Symfony/Component/DependencyInjection/ContainerAwareTrait.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * ContainerAware trait. * * @author Fabien Potencier */ trait ContainerAwareTrait { /** * @var ContainerInterface */ protected $container; /** * Sets the Container associated with this Controller. * * @param ContainerInterface $container A ContainerInterface instance */ public function setContainer(ContainerInterface $container = null) { $this->container = $container; } } PK!BSymfony/Component/DependencyInjection/TaggedContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * TaggedContainerInterface is the interface implemented when a container knows how to deals with tags. * * @author Fabien Potencier * * @api */ interface TaggedContainerInterface extends ContainerInterface { /** * Returns service ids for a given tag. * * @param string $name The tag name * * @return array An array of tags * * @api */ public function findTaggedServiceIds($name); } PK!A:$:$;Symfony/Component/DependencyInjection/Dumper/YamlDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\Yaml\Dumper as YmlDumper; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\ExpressionLanguage\Expression; /** * YamlDumper dumps a service container as a YAML string. * * @author Fabien Potencier * * @api */ class YamlDumper extends Dumper { private $dumper; /** * Constructor. * * @param ContainerBuilder $container The service container to dump * * @api */ public function __construct(ContainerBuilder $container) { parent::__construct($container); $this->dumper = new YmlDumper(); } /** * Dumps the service container as an YAML string. * * @param array $options An array of options * * @return string A YAML string representing of the service container * * @api */ public function dump(array $options = array()) { return $this->addParameters()."\n".$this->addServices(); } /** * Adds a service * * @param string $id * @param Definition $definition * * @return string */ private function addService($id, $definition) { $code = " $id:\n"; if ($definition->getClass()) { $code .= sprintf(" class: %s\n", $definition->getClass()); } if (!$definition->isPublic()) { $code .= " public: false\n"; } $tagsCode = ''; foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $att = array(); foreach ($attributes as $key => $value) { $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value)); } $att = $att ? ', '.implode(' ', $att) : ''; $tagsCode .= sprintf(" - { name: %s%s }\n", $this->dumper->dump($name), $att); } } if ($tagsCode) { $code .= " tags:\n".$tagsCode; } if ($definition->getFile()) { $code .= sprintf(" file: %s\n", $definition->getFile()); } if ($definition->isSynthetic()) { $code .= sprintf(" synthetic: true\n"); } if ($definition->isSynchronized()) { $code .= sprintf(" synchronized: true\n"); } if ($definition->getFactoryClass()) { $code .= sprintf(" factory_class: %s\n", $definition->getFactoryClass()); } if ($definition->isLazy()) { $code .= sprintf(" lazy: true\n"); } if ($definition->getFactoryMethod()) { $code .= sprintf(" factory_method: %s\n", $definition->getFactoryMethod()); } if ($definition->getFactoryService()) { $code .= sprintf(" factory_service: %s\n", $definition->getFactoryService()); } if ($definition->getArguments()) { $code .= sprintf(" arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0)); } if ($definition->getProperties()) { $code .= sprintf(" properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0)); } if ($definition->getMethodCalls()) { $code .= sprintf(" calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12)); } if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) { $code .= sprintf(" scope: %s\n", $scope); } if ($callable = $definition->getConfigurator()) { if (is_array($callable)) { if ($callable[0] instanceof Reference) { $callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]); } else { $callable = array($callable[0], $callable[1]); } } $code .= sprintf(" configurator: %s\n", $this->dumper->dump($callable, 0)); } return $code; } /** * Adds a service alias * * @param string $alias * @param Alias $id * * @return string */ private function addServiceAlias($alias, $id) { if ($id->isPublic()) { return sprintf(" %s: @%s\n", $alias, $id); } else { return sprintf(" %s:\n alias: %s\n public: false", $alias, $id); } } /** * Adds services * * @return string */ private function addServices() { if (!$this->container->getDefinitions()) { return ''; } $code = "services:\n"; foreach ($this->container->getDefinitions() as $id => $definition) { $code .= $this->addService($id, $definition); } $aliases = $this->container->getAliases(); foreach ($aliases as $alias => $id) { while (isset($aliases[(string) $id])) { $id = $aliases[(string) $id]; } $code .= $this->addServiceAlias($alias, $id); } return $code; } /** * Adds parameters * * @return string */ private function addParameters() { if (!$this->container->getParameterBag()->all()) { return ''; } $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isFrozen()); return $this->dumper->dump(array('parameters' => $parameters), 2); } /** * Dumps the value to YAML format * * @param mixed $value * * @return mixed * * @throws RuntimeException When trying to dump object or resource */ private function dumpValue($value) { if (is_array($value)) { $code = array(); foreach ($value as $k => $v) { $code[$k] = $this->dumpValue($v); } return $code; } elseif ($value instanceof Reference) { return $this->getServiceCall((string) $value, $value); } elseif ($value instanceof Parameter) { return $this->getParameterCall((string) $value); } elseif ($value instanceof Expression) { return $this->getExpressionCall((string) $value); } elseif (is_object($value) || is_resource($value)) { throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); } return $value; } /** * Gets the service call. * * @param string $id * @param Reference $reference * * @return string */ private function getServiceCall($id, Reference $reference = null) { if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { return sprintf('@?%s', $id); } return sprintf('@%s', $id); } /** * Gets parameter call. * * @param string $id * * @return string */ private function getParameterCall($id) { return sprintf('%%%s%%', $id); } private function getExpressionCall($expression) { return sprintf('@=%s', $expression); } /** * Prepares parameters. * * @param array $parameters * @param Boolean $escape * * @return array */ private function prepareParameters($parameters, $escape = true) { $filtered = array(); foreach ($parameters as $key => $value) { if (is_array($value)) { $value = $this->prepareParameters($value, $escape); } elseif ($value instanceof Reference || is_string($value) && 0 === strpos($value, '@')) { $value = '@'.$value; } $filtered[$key] = $value; } return $escape ? $this->escape($filtered) : $filtered; } /** * Escapes arguments * * @param array $arguments * * @return array */ private function escape($arguments) { $args = array(); foreach ($arguments as $k => $v) { if (is_array($v)) { $args[$k] = $this->escape($v); } elseif (is_string($v)) { $args[$k] = str_replace('%', '%%', $v); } else { $args[$k] = $v; } } return $args; } } PK!N/++7Symfony/Component/DependencyInjection/Dumper/Dumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Dumper is the abstract class for all built-in dumpers. * * @author Fabien Potencier * * @api */ abstract class Dumper implements DumperInterface { protected $container; /** * Constructor. * * @param ContainerBuilder $container The service container to dump * * @api */ public function __construct(ContainerBuilder $container) { $this->container = $container; } } PK!%%?Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; /** * GraphvizDumper dumps a service container as a graphviz file. * * You can convert the generated dot file with the dot utility (http://www.graphviz.org/): * * dot -Tpng container.dot > foo.png * * @author Fabien Potencier */ class GraphvizDumper extends Dumper { private $nodes; private $edges; private $options = array( 'graph' => array('ratio' => 'compress'), 'node' => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'), 'edge' => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5), 'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'), 'node.definition' => array('fillcolor' => '#eeeeee'), 'node.missing' => array('fillcolor' => '#ff9999', 'style' => 'filled'), ); /** * Dumps the service container as a graphviz graph. * * Available options: * * * graph: The default options for the whole graph * * node: The default options for nodes * * edge: The default options for edges * * node.instance: The default options for services that are defined directly by object instances * * node.definition: The default options for services that are defined via service definition instances * * node.missing: The default options for missing services * * @param array $options An array of options * * @return string The dot representation of the service container */ public function dump(array $options = array()) { foreach (array('graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing') as $key) { if (isset($options[$key])) { $this->options[$key] = array_merge($this->options[$key], $options[$key]); } } $this->nodes = $this->findNodes(); $this->edges = array(); foreach ($this->container->getDefinitions() as $id => $definition) { $this->edges[$id] = array_merge( $this->findEdges($id, $definition->getArguments(), true, ''), $this->findEdges($id, $definition->getProperties(), false, '') ); foreach ($definition->getMethodCalls() as $call) { $this->edges[$id] = array_merge( $this->edges[$id], $this->findEdges($id, $call[1], false, $call[0].'()') ); } } return $this->startDot().$this->addNodes().$this->addEdges().$this->endDot(); } /** * Returns all nodes. * * @return string A string representation of all nodes */ private function addNodes() { $code = ''; foreach ($this->nodes as $id => $node) { $aliases = $this->getAliases($id); $code .= sprintf(" node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id.($aliases ? ' ('.implode(', ', $aliases).')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes'])); } return $code; } /** * Returns all edges. * * @return string A string representation of all edges */ private function addEdges() { $code = ''; foreach ($this->edges as $id => $edges) { foreach ($edges as $edge) { $code .= sprintf(" node_%s -> node_%s [label=\"%s\" style=\"%s\"];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed'); } } return $code; } /** * Finds all edges belonging to a specific service id. * * @param string $id The service id used to find edges * @param array $arguments An array of arguments * @param Boolean $required * @param string $name * * @return array An array of edges */ private function findEdges($id, $arguments, $required, $name) { $edges = array(); foreach ($arguments as $argument) { if ($argument instanceof Parameter) { $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null; } elseif (is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) { $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null; } if ($argument instanceof Reference) { if (!$this->container->has((string) $argument)) { $this->nodes[(string) $argument] = array('name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']); } $edges[] = array('name' => $name, 'required' => $required, 'to' => $argument); } elseif (is_array($argument)) { $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name)); } } return $edges; } /** * Finds all nodes. * * @return array An array of all nodes */ private function findNodes() { $nodes = array(); $container = $this->cloneContainer(); foreach ($container->getDefinitions() as $id => $definition) { $nodes[$id] = array('class' => str_replace('\\', '\\\\', $this->container->getParameterBag()->resolveValue($definition->getClass())), 'attributes' => array_merge($this->options['node.definition'], array('style' => ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope() ? 'filled' : 'dotted'))); $container->setDefinition($id, new Definition('stdClass')); } foreach ($container->getServiceIds() as $id) { $service = $container->get($id); if (in_array($id, array_keys($container->getAliases()))) { continue; } if (!$container->hasDefinition($id)) { $class = ('service_container' === $id) ? get_class($this->container) : get_class($service); $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => $this->options['node.instance']); } } return $nodes; } private function cloneContainer() { $parameterBag = new ParameterBag($this->container->getParameterBag()->all()); $container = new ContainerBuilder($parameterBag); $container->setDefinitions($this->container->getDefinitions()); $container->setAliases($this->container->getAliases()); $container->setResources($this->container->getResources()); foreach ($this->container->getScopes() as $scope) { $container->addScope($scope); } foreach ($this->container->getExtensions() as $extension) { $container->registerExtension($extension); } return $container; } /** * Returns the start dot. * * @return string The string representation of a start dot */ private function startDot() { return sprintf("digraph sc {\n %s\n node [%s];\n edge [%s];\n\n", $this->addOptions($this->options['graph']), $this->addOptions($this->options['node']), $this->addOptions($this->options['edge']) ); } /** * Returns the end dot. * * @return string */ private function endDot() { return "}\n"; } /** * Adds attributes * * @param array $attributes An array of attributes * * @return string A comma separated list of attributes */ private function addAttributes($attributes) { $code = array(); foreach ($attributes as $k => $v) { $code[] = sprintf('%s="%s"', $k, $v); } return $code ? ', '.implode(', ', $code) : ''; } /** * Adds options * * @param array $options An array of options * * @return string A space separated list of options */ private function addOptions($options) { $code = array(); foreach ($options as $k => $v) { $code[] = sprintf('%s="%s"', $k, $v); } return implode(' ', $code); } /** * Dotizes an identifier. * * @param string $id The identifier to dotize * * @return string A dotized string */ private function dotize($id) { return strtolower(preg_replace('/[^\w]/i', '_', $id)); } /** * Compiles an array of aliases for a specified service id. * * @param string $id A service id * * @return array An array of aliases */ private function getAliases($id) { $aliases = array(); foreach ($this->container->getAliases() as $alias => $origin) { if ($id == $origin) { $aliases[] = $alias; } } return $aliases; } } PK!"^ :Symfony/Component/DependencyInjection/Dumper/PhpDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; use Symfony\Component\DependencyInjection\ExpressionLanguage; use Symfony\Component\ExpressionLanguage\Expression; /** * PhpDumper dumps a service container as a PHP class. * * @author Fabien Potencier * @author Johannes M. Schmitt * * @api */ class PhpDumper extends Dumper { /** * Characters that might appear in the generated variable name as first character * @var string */ const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz'; /** * Characters that might appear in the generated variable name as any but the first character * @var string */ const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_'; private $inlinedDefinitions; private $definitionVariables; private $referenceVariables; private $variableCount; private $reservedVariables = array('instance', 'class'); private $expressionLanguage; /** * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface */ private $proxyDumper; /** * {@inheritDoc} * * @api */ public function __construct(ContainerBuilder $container) { parent::__construct($container); $this->inlinedDefinitions = new \SplObjectStorage(); } /** * Sets the dumper to be used when dumping proxies in the generated container. * * @param ProxyDumper $proxyDumper */ public function setProxyDumper(ProxyDumper $proxyDumper) { $this->proxyDumper = $proxyDumper; } /** * Dumps the service container as a PHP class. * * Available options: * * * class: The class name * * base_class: The base class name * * namespace: The class namespace * * @param array $options An array of options * * @return string A PHP class representing of the service container * * @api */ public function dump(array $options = array()) { $options = array_merge(array( 'class' => 'ProjectServiceContainer', 'base_class' => 'Container', 'namespace' => '', ), $options); $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']); if ($this->container->isFrozen()) { $code .= $this->addFrozenConstructor(); } else { $code .= $this->addConstructor(); } $code .= $this->addServices(). $this->addDefaultParametersMethod(). $this->endClass(). $this->addProxyClasses() ; return $code; } /** * Retrieves the currently set proxy dumper or instantiates one. * * @return ProxyDumper */ private function getProxyDumper() { if (!$this->proxyDumper) { $this->proxyDumper = new NullDumper(); } return $this->proxyDumper; } /** * Generates Service local temp variables. * * @param string $cId * @param string $definition * * @return string */ private function addServiceLocalTempVariables($cId, $definition) { static $template = " \$%s = %s;\n"; $localDefinitions = array_merge( array($definition), $this->getInlinedDefinitions($definition) ); $calls = $behavior = array(); foreach ($localDefinitions as $iDefinition) { $this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior); $this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior); $this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior); } $code = ''; foreach ($calls as $id => $callCount) { if ('service_container' === $id || $id === $cId) { continue; } if ($callCount > 1) { $name = $this->getNextVariableName(); $this->referenceVariables[$id] = new Variable($name); if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) { $code .= sprintf($template, $name, $this->getServiceCall($id)); } else { $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE))); } } } if ('' !== $code) { $code .= "\n"; } return $code; } /** * Generates code for the proxies to be attached after the container class * * @return string */ private function addProxyClasses() { /* @var $definitions Definition[] */ $definitions = array_filter( $this->container->getDefinitions(), array($this->getProxyDumper(), 'isProxyCandidate') ); $code = ''; foreach ($definitions as $definition) { $code .= "\n" . $this->getProxyDumper()->getProxyCode($definition); } return $code; } /** * Generates the require_once statement for service includes. * * @param string $id The service id * @param Definition $definition * * @return string */ private function addServiceInclude($id, $definition) { $template = " require_once %s;\n"; $code = ''; if (null !== $file = $definition->getFile()) { $code .= sprintf($template, $this->dumpValue($file)); } foreach ($this->getInlinedDefinitions($definition) as $definition) { if (null !== $file = $definition->getFile()) { $code .= sprintf($template, $this->dumpValue($file)); } } if ('' !== $code) { $code .= "\n"; } return $code; } /** * Generates the inline definition of a service. * * @param string $id * @param Definition $definition * * @return string * * @throws RuntimeException When the factory definition is incomplete * @throws ServiceCircularReferenceException When a circular reference is detected */ private function addServiceInlinedDefinitions($id, $definition) { $code = ''; $variableMap = $this->definitionVariables; $nbOccurrences = new \SplObjectStorage(); $processed = new \SplObjectStorage(); $inlinedDefinitions = $this->getInlinedDefinitions($definition); foreach ($inlinedDefinitions as $definition) { if (false === $nbOccurrences->contains($definition)) { $nbOccurrences->offsetSet($definition, 1); } else { $i = $nbOccurrences->offsetGet($definition); $nbOccurrences->offsetSet($definition, $i + 1); } } foreach ($inlinedDefinitions as $sDefinition) { if ($processed->contains($sDefinition)) { continue; } $processed->offsetSet($sDefinition); $class = $this->dumpValue($sDefinition->getClass()); if ($nbOccurrences->offsetGet($sDefinition) > 1 || $sDefinition->getMethodCalls() || $sDefinition->getProperties() || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) { $name = $this->getNextVariableName(); $variableMap->offsetSet($sDefinition, new Variable($name)); // a construct like: // $a = new ServiceA(ServiceB $b); $b = new ServiceB(ServiceA $a); // this is an indication for a wrong implementation, you can circumvent this problem // by setting up your service structure like this: // $b = new ServiceB(); // $a = new ServiceA(ServiceB $b); // $b->setServiceA(ServiceA $a); if ($this->hasReference($id, $sDefinition->getArguments())) { throw new ServiceCircularReferenceException($id, array($id)); } $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = '); if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) { $code .= $this->addServiceMethodCalls(null, $sDefinition, $name); $code .= $this->addServiceProperties(null, $sDefinition, $name); $code .= $this->addServiceConfigurator(null, $sDefinition, $name); } $code .= "\n"; } } return $code; } /** * Adds the service return statement. * * @param string $id Service id * @param Definition $definition * * @return string */ private function addServiceReturn($id, $definition) { if ($this->isSimpleInstance($id, $definition)) { return " }\n"; } return "\n return \$instance;\n }\n"; } /** * Generates the service instance. * * @param string $id * @param Definition $definition * * @return string * * @throws InvalidArgumentException * @throws RuntimeException */ private function addServiceInstance($id, $definition) { $class = $this->dumpValue($definition->getClass()); if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); } $simple = $this->isSimpleInstance($id, $definition); $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); $instantiation = ''; if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { $instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance'); } elseif (!$isProxyCandidate && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { $instantiation = "\$this->services['$id'] = \$this->scopedServices['$scope']['$id'] = ".($simple ? '' : '$instance'); } elseif (!$simple) { $instantiation = '$instance'; } $return = ''; if ($simple) { $return = 'return '; } else { $instantiation .= ' = '; } $code = $this->addNewInstance($id, $definition, $return, $instantiation); if (!$simple) { $code .= "\n"; } return $code; } /** * Checks if the definition is a simple instance. * * @param string $id * @param Definition $definition * * @return Boolean */ private function isSimpleInstance($id, $definition) { foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) { if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) { continue; } if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) { return false; } } return true; } /** * Adds method calls to a service definition. * * @param string $id * @param Definition $definition * @param string $variableName * * @return string */ private function addServiceMethodCalls($id, $definition, $variableName = 'instance') { $calls = ''; foreach ($definition->getMethodCalls() as $call) { $arguments = array(); foreach ($call[1] as $value) { $arguments[] = $this->dumpValue($value); } $calls .= $this->wrapServiceConditionals($call[1], sprintf(" \$%s->%s(%s);\n", $variableName, $call[0], implode(', ', $arguments))); } return $calls; } private function addServiceProperties($id, $definition, $variableName = 'instance') { $code = ''; foreach ($definition->getProperties() as $name => $value) { $code .= sprintf(" \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value)); } return $code; } /** * Generates the inline definition setup. * * @param string $id * @param Definition $definition * @return string */ private function addServiceInlinedDefinitionsSetup($id, $definition) { $this->referenceVariables[$id] = new Variable('instance'); $code = ''; $processed = new \SplObjectStorage(); foreach ($this->getInlinedDefinitions($definition) as $iDefinition) { if ($processed->contains($iDefinition)) { continue; } $processed->offsetSet($iDefinition); if (!$this->hasReference($id, $iDefinition->getMethodCalls(), true) && !$this->hasReference($id, $iDefinition->getProperties(), true)) { continue; } // if the instance is simple, the return statement has already been generated // so, the only possible way to get there is because of a circular reference if ($this->isSimpleInstance($id, $definition)) { throw new ServiceCircularReferenceException($id, array($id)); } $name = (string) $this->definitionVariables->offsetGet($iDefinition); $code .= $this->addServiceMethodCalls(null, $iDefinition, $name); $code .= $this->addServiceProperties(null, $iDefinition, $name); $code .= $this->addServiceConfigurator(null, $iDefinition, $name); } if ('' !== $code) { $code .= "\n"; } return $code; } /** * Adds configurator definition * * @param string $id * @param Definition $definition * @param string $variableName * * @return string */ private function addServiceConfigurator($id, $definition, $variableName = 'instance') { if (!$callable = $definition->getConfigurator()) { return ''; } if (is_array($callable)) { if ($callable[0] instanceof Reference) { return sprintf(" %s->%s(\$%s);\n", $this->getServiceCall((string) $callable[0]), $callable[1], $variableName); } return sprintf(" call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); } return sprintf(" %s(\$%s);\n", $callable, $variableName); } /** * Adds a service * * @param string $id * @param Definition $definition * * @return string */ private function addService($id, $definition) { $this->definitionVariables = new \SplObjectStorage(); $this->referenceVariables = array(); $this->variableCount = 0; $return = array(); if ($definition->isSynthetic()) { $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically'; } elseif ($class = $definition->getClass()) { $return[] = sprintf("@return %s A %s instance.", 0 === strpos($class, '%') ? 'object' : $class, $class); } elseif ($definition->getFactoryClass()) { $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryClass(), $definition->getFactoryMethod()); } elseif ($definition->getFactoryService()) { $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryService(), $definition->getFactoryMethod()); } $scope = $definition->getScope(); if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { if ($return && 0 === strpos($return[count($return) - 1], '@return')) { $return[] = ''; } $return[] = sprintf("@throws InactiveScopeException when the '%s' service is requested while the '%s' scope is not active", $id, $scope); } $return = implode("\n * ", $return); $doc = ''; if (ContainerInterface::SCOPE_PROTOTYPE !== $scope) { $doc .= <<isPublic()) { $doc .= <<isLazy()) { $lazyInitialization = '$lazyLoad = true'; $lazyInitializationDoc = "\n * @param boolean \$lazyLoad whether to try lazy-loading the service with a proxy\n *"; } else { $lazyInitialization = ''; $lazyInitializationDoc = ''; } // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); $visibility = $isProxyCandidate ? 'public' : 'protected'; $code = <<camelize($id)}Service($lazyInitialization) { EOF; $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id) : ''; if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { $code .= <<scopedServices['$scope'])) { throw new InactiveScopeException('$id', '$scope'); } EOF; } if ($definition->isSynthetic()) { $code .= sprintf(" throw new RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n }\n", $id); } else { $code .= $this->addServiceInclude($id, $definition). $this->addServiceLocalTempVariables($id, $definition). $this->addServiceInlinedDefinitions($id, $definition). $this->addServiceInstance($id, $definition). $this->addServiceInlinedDefinitionsSetup($id, $definition). $this->addServiceMethodCalls($id, $definition). $this->addServiceProperties($id, $definition). $this->addServiceConfigurator($id, $definition). $this->addServiceReturn($id, $definition) ; } $this->definitionVariables = null; $this->referenceVariables = null; return $code; } /** * Adds multiple services * * @return string */ private function addServices() { $publicServices = $privateServices = $synchronizers = ''; $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { if ($definition->isPublic()) { $publicServices .= $this->addService($id, $definition); } else { $privateServices .= $this->addService($id, $definition); } $synchronizers .= $this->addServiceSynchronizer($id, $definition); } return $publicServices.$synchronizers.$privateServices; } /** * Adds synchronizer methods. * * @param string $id A service identifier * @param Definition $definition A Definition instance */ private function addServiceSynchronizer($id, Definition $definition) { if (!$definition->isSynchronized()) { return; } $code = ''; foreach ($this->container->getDefinitions() as $definitionId => $definition) { foreach ($definition->getMethodCalls() as $call) { foreach ($call[1] as $argument) { if ($argument instanceof Reference && $id == (string) $argument) { $arguments = array(); foreach ($call[1] as $value) { $arguments[] = $this->dumpValue($value); } $call = $this->wrapServiceConditionals($call[1], sprintf("\$this->get('%s')->%s(%s);", $definitionId, $call[0], implode(', ', $arguments))); $code .= <<initialized('$definitionId')) { $call } EOF; } } } } if (!$code) { return; } return <<camelize($id)}Service() { $code } EOF; } private function addNewInstance($id, Definition $definition, $return, $instantiation) { $class = $this->dumpValue($definition->getClass()); $arguments = array(); foreach ($definition->getArguments() as $value) { $arguments[] = $this->dumpValue($value); } if (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryClass()) { return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : ''); } if (null !== $definition->getFactoryService()) { return sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments)); } throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id)); } if (false !== strpos($class, '$')) { return sprintf(" \$class = %s;\n\n $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); } return sprintf(" $return{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); } /** * Adds the class headers. * * @param string $class Class name * @param string $baseClass The name of the base class * @param string $namespace The class namespace * * @return string */ private function startClass($class, $baseClass, $namespace) { $bagClass = $this->container->isFrozen() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;'; $namespaceLine = $namespace ? "namespace $namespace;\n" : ''; return <<container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null; $code = <<container->getScopes()) > 0) { $code .= "\n"; $code .= " \$this->scopes = ".$this->dumpValue($scopes).";\n"; $code .= " \$this->scopeChildren = ".$this->dumpValue($this->container->getScopeChildren()).";\n"; } $code .= $this->addMethodMap(); $code .= $this->addAliases(); $code .= <<container->getParameterBag()->all()) { $code .= "\n \$this->parameters = \$this->getDefaultParameters();\n"; } $code .= <<services = \$this->scopedServices = \$this->scopeStacks = array(); \$this->set('service_container', \$this); EOF; $code .= "\n"; if (count($scopes = $this->container->getScopes()) > 0) { $code .= " \$this->scopes = ".$this->dumpValue($scopes).";\n"; $code .= " \$this->scopeChildren = ".$this->dumpValue($this->container->getScopeChildren()).";\n"; } else { $code .= " \$this->scopes = array();\n"; $code .= " \$this->scopeChildren = array();\n"; } $code .= $this->addMethodMap(); $code .= $this->addAliases(); $code .= <<container->getDefinitions()) { return ''; } $code = " \$this->methodMap = array(\n"; ksort($definitions); foreach ($definitions as $id => $definition) { $code .= ' '.var_export($id, true).' => '.var_export('get'.$this->camelize($id).'Service', true).",\n"; } return $code . " );\n"; } /** * Adds the aliases property definition * * @return string */ private function addAliases() { if (!$aliases = $this->container->getAliases()) { if ($this->container->isFrozen()) { return "\n \$this->aliases = array();\n"; } else { return ''; } } $code = " \$this->aliases = array(\n"; ksort($aliases); foreach ($aliases as $alias => $id) { $id = (string) $id; while (isset($aliases[$id])) { $id = (string) $aliases[$id]; } $code .= ' '.var_export($alias, true).' => '.var_export($id, true).",\n"; } return $code . " );\n"; } /** * Adds default parameters method. * * @return string */ private function addDefaultParametersMethod() { if (!$this->container->getParameterBag()->all()) { return ''; } $parameters = $this->exportParameters($this->container->getParameterBag()->all()); $code = ''; if ($this->container->isFrozen()) { $code .= <<parameters[\$name]) || array_key_exists(\$name, \$this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', \$name)); } return \$this->parameters[\$name]; } /** * {@inheritdoc} */ public function hasParameter(\$name) { \$name = strtolower(\$name); return isset(\$this->parameters[\$name]) || array_key_exists(\$name, \$this->parameters); } /** * {@inheritdoc} */ public function setParameter(\$name, \$value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } /** * {@inheritDoc} */ public function getParameterBag() { if (null === \$this->parameterBag) { \$this->parameterBag = new FrozenParameterBag(\$this->parameters); } return \$this->parameterBag; } EOF; } $code .= << $value) { if (is_array($value)) { $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4); } elseif ($value instanceof Variable) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key)); } elseif ($value instanceof Definition) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path.'/'.$key)); } elseif ($value instanceof Reference) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key)); } elseif ($value instanceof Expression) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key)); } else { $value = var_export($value, true); } $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value); } return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 4)); } /** * Ends the class definition. * * @return string */ private function endClass() { return <<has('%s')", $service); } // re-indent the wrapped code $code = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code))); return sprintf(" if (%s) {\n%s }\n", implode(' && ', $conditions), $code); } /** * Builds service calls from arguments. * * @param array $arguments * @param array &$calls By reference * @param array &$behavior By reference */ private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->getServiceCallsFromArguments($argument, $calls, $behavior); } elseif ($argument instanceof Reference) { $id = (string) $argument; if (!isset($calls[$id])) { $calls[$id] = 0; } if (!isset($behavior[$id])) { $behavior[$id] = $argument->getInvalidBehavior(); } elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) { $behavior[$id] = $argument->getInvalidBehavior(); } $calls[$id] += 1; } } } /** * Returns the inline definition. * * @param Definition $definition * * @return array */ private function getInlinedDefinitions(Definition $definition) { if (false === $this->inlinedDefinitions->contains($definition)) { $definitions = array_merge( $this->getDefinitionsFromArguments($definition->getArguments()), $this->getDefinitionsFromArguments($definition->getMethodCalls()), $this->getDefinitionsFromArguments($definition->getProperties()) ); $this->inlinedDefinitions->offsetSet($definition, $definitions); return $definitions; } return $this->inlinedDefinitions->offsetGet($definition); } /** * Gets the definition from arguments. * * @param array $arguments * * @return array */ private function getDefinitionsFromArguments(array $arguments) { $definitions = array(); foreach ($arguments as $argument) { if (is_array($argument)) { $definitions = array_merge($definitions, $this->getDefinitionsFromArguments($argument)); } elseif ($argument instanceof Definition) { $definitions = array_merge( $definitions, $this->getInlinedDefinitions($argument), array($argument) ); } } return $definitions; } /** * Checks if a service id has a reference. * * @param string $id * @param array $arguments * @param Boolean $deep * @param array $visited * * @return Boolean */ private function hasReference($id, array $arguments, $deep = false, array $visited = array()) { foreach ($arguments as $argument) { if (is_array($argument)) { if ($this->hasReference($id, $argument, $deep, $visited)) { return true; } } elseif ($argument instanceof Reference) { $argumentId = (string) $argument; if ($id === $argumentId) { return true; } if ($deep && !isset($visited[$argumentId])) { $visited[$argumentId] = true; $service = $this->container->getDefinition($argumentId); $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties()); if ($this->hasReference($id, $arguments, $deep, $visited)) { return true; } } } } return false; } /** * Dumps values. * * @param array $value * @param Boolean $interpolate * * @return string * * @throws RuntimeException */ private function dumpValue($value, $interpolate = true) { if (is_array($value)) { $code = array(); foreach ($value as $k => $v) { $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)); } return sprintf('array(%s)', implode(', ', $code)); } elseif ($value instanceof Definition) { if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) { return $this->dumpValue($this->definitionVariables->offsetGet($value), $interpolate); } if (count($value->getMethodCalls()) > 0) { throw new RuntimeException('Cannot dump definitions which have method calls.'); } if (null !== $value->getConfigurator()) { throw new RuntimeException('Cannot dump definitions which have a configurator.'); } $arguments = array(); foreach ($value->getArguments() as $argument) { $arguments[] = $this->dumpValue($argument); } $class = $this->dumpValue($value->getClass()); if (false !== strpos($class, '$')) { throw new RuntimeException('Cannot dump definitions which have a variable class name.'); } if (null !== $value->getFactoryMethod()) { if (null !== $value->getFactoryClass()) { return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass()), $value->getFactoryMethod(), count($arguments) > 0 ? ', '.implode(', ', $arguments) : ''); } elseif (null !== $value->getFactoryService()) { return sprintf("%s->%s(%s)", $this->getServiceCall($value->getFactoryService()), $value->getFactoryMethod(), implode(', ', $arguments)); } else { throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.'); } } return sprintf("new \\%s(%s)", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); } elseif ($value instanceof Variable) { return '$'.$value; } elseif ($value instanceof Reference) { if (null !== $this->referenceVariables && isset($this->referenceVariables[$id = (string) $value])) { return $this->dumpValue($this->referenceVariables[$id], $interpolate); } return $this->getServiceCall((string) $value, $value); } elseif ($value instanceof Expression) { return $this->getExpressionLanguage()->compile((string) $value, array('container')); } elseif ($value instanceof Parameter) { return $this->dumpParameter($value); } elseif (true === $interpolate && is_string($value)) { if (preg_match('/^%([^%]+)%$/', $value, $match)) { // we do this to deal with non string values (Boolean, integer, ...) // the preg_replace_callback converts them to strings return $this->dumpParameter(strtolower($match[1])); } else { $that = $this; $replaceParameters = function ($match) use ($that) { return "'.".$that->dumpParameter(strtolower($match[2])).".'"; }; $code = str_replace('%%', '%', preg_replace_callback('/(?container->isFrozen() && $this->container->hasParameter($name)) { return $this->dumpValue($this->container->getParameter($name), false); } return sprintf("\$this->getParameter('%s')", strtolower($name)); } /** * Gets a service call * * @param string $id * @param Reference $reference * * @return string */ private function getServiceCall($id, Reference $reference = null) { if ('service_container' === $id) { return '$this'; } if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { return sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); } else { if ($this->container->hasAlias($id)) { $id = (string) $this->container->getAlias($id); } return sprintf('$this->get(\'%s\')', $id); } } /** * Convert a service id to a valid PHP method name. * * @param string $id * * @return string * * @throws InvalidArgumentException */ private function camelize($id) { $name = Container::camelize($id); if (!preg_match('/^[a-zA-Z0-9_\x7f-\xff]+$/', $name)) { throw new InvalidArgumentException(sprintf('Service id "%s" cannot be converted to a valid PHP method name.', $id)); } return $name; } /** * Returns the next name to use * * @return string */ private function getNextVariableName() { $firstChars = self::FIRST_CHARS; $firstCharsLength = strlen($firstChars); $nonFirstChars = self::NON_FIRST_CHARS; $nonFirstCharsLength = strlen($nonFirstChars); while (true) { $name = ''; $i = $this->variableCount; if ('' === $name) { $name .= $firstChars[$i%$firstCharsLength]; $i = intval($i/$firstCharsLength); } while ($i > 0) { $i -= 1; $name .= $nonFirstChars[$i%$nonFirstCharsLength]; $i = intval($i/$nonFirstCharsLength); } $this->variableCount += 1; // check that the name is not reserved if (in_array($name, $this->reservedVariables, true)) { continue; } return $name; } } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } } PK!}@Symfony/Component/DependencyInjection/Dumper/DumperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; /** * DumperInterface is the interface implemented by service container dumper classes. * * @author Fabien Potencier * * @api */ interface DumperInterface { /** * Dumps the service container. * * @param array $options An array of options * * @return string The representation of the service container * * @api */ public function dump(array $options = array()); } PK!**:Symfony/Component/DependencyInjection/Dumper/XmlDumper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\ExpressionLanguage\Expression; /** * XmlDumper dumps a service container as an XML string. * * @author Fabien Potencier * @author Martin Hasoň * * @api */ class XmlDumper extends Dumper { /** * @var \DOMDocument */ private $document; /** * Dumps the service container as an XML string. * * @param array $options An array of options * * @return string An xml string representing of the service container * * @api */ public function dump(array $options = array()) { $this->document = new \DOMDocument('1.0', 'utf-8'); $this->document->formatOutput = true; $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container'); $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd'); $this->addParameters($container); $this->addServices($container); $this->document->appendChild($container); $xml = $this->document->saveXML(); $this->document = null; return $xml; } /** * Adds parameters. * * @param \DOMElement $parent */ private function addParameters(\DOMElement $parent) { $data = $this->container->getParameterBag()->all(); if (!$data) { return; } if ($this->container->isFrozen()) { $data = $this->escape($data); } $parameters = $this->document->createElement('parameters'); $parent->appendChild($parameters); $this->convertParameters($data, 'parameter', $parameters); } /** * Adds method calls. * * @param array $methodcalls * @param \DOMElement $parent */ private function addMethodCalls(array $methodcalls, \DOMElement $parent) { foreach ($methodcalls as $methodcall) { $call = $this->document->createElement('call'); $call->setAttribute('method', $methodcall[0]); if (count($methodcall[1])) { $this->convertParameters($methodcall[1], 'argument', $call); } $parent->appendChild($call); } } /** * Adds a service. * * @param Definition $definition * @param string $id * @param \DOMElement $parent */ private function addService($definition, $id, \DOMElement $parent) { $service = $this->document->createElement('service'); if (null !== $id) { $service->setAttribute('id', $id); } if ($definition->getClass()) { $service->setAttribute('class', $definition->getClass()); } if ($definition->getFactoryMethod()) { $service->setAttribute('factory-method', $definition->getFactoryMethod()); } if ($definition->getFactoryService()) { $service->setAttribute('factory-service', $definition->getFactoryService()); } if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) { $service->setAttribute('scope', $scope); } if (!$definition->isPublic()) { $service->setAttribute('public', 'false'); } if ($definition->isSynthetic()) { $service->setAttribute('synthetic', 'true'); } if ($definition->isSynchronized()) { $service->setAttribute('synchronized', 'true'); } if ($definition->isLazy()) { $service->setAttribute('lazy', 'true'); } foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $tag = $this->document->createElement('tag'); $tag->setAttribute('name', $name); foreach ($attributes as $key => $value) { $tag->setAttribute($key, $value); } $service->appendChild($tag); } } if ($definition->getFile()) { $file = $this->document->createElement('file'); $file->appendChild($this->document->createTextNode($definition->getFile())); $service->appendChild($file); } if ($parameters = $definition->getArguments()) { $this->convertParameters($parameters, 'argument', $service); } if ($parameters = $definition->getProperties()) { $this->convertParameters($parameters, 'property', $service, 'name'); } $this->addMethodCalls($definition->getMethodCalls(), $service); if ($callable = $definition->getConfigurator()) { $configurator = $this->document->createElement('configurator'); if (is_array($callable)) { $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $configurator->setAttribute('method', $callable[1]); } else { $configurator->setAttribute('function', $callable); } $service->appendChild($configurator); } $parent->appendChild($service); } /** * Adds a service alias. * * @param string $alias * @param Alias $id * @param \DOMElement $parent */ private function addServiceAlias($alias, Alias $id, \DOMElement $parent) { $service = $this->document->createElement('service'); $service->setAttribute('id', $alias); $service->setAttribute('alias', $id); if (!$id->isPublic()) { $service->setAttribute('public', 'false'); } $parent->appendChild($service); } /** * Adds services. * * @param \DOMElement $parent */ private function addServices(\DOMElement $parent) { $definitions = $this->container->getDefinitions(); if (!$definitions) { return; } $services = $this->document->createElement('services'); foreach ($definitions as $id => $definition) { $this->addService($definition, $id, $services); } $aliases = $this->container->getAliases(); foreach ($aliases as $alias => $id) { while (isset($aliases[(string) $id])) { $id = $aliases[(string) $id]; } $this->addServiceAlias($alias, $id, $services); } $parent->appendChild($services); } /** * Converts parameters. * * @param array $parameters * @param string $type * @param \DOMElement $parent * @param string $keyAttribute */ private function convertParameters($parameters, $type, \DOMElement $parent, $keyAttribute = 'key') { $withKeys = array_keys($parameters) !== range(0, count($parameters) - 1); foreach ($parameters as $key => $value) { $element = $this->document->createElement($type); if ($withKeys) { $element->setAttribute($keyAttribute, $key); } if (is_array($value)) { $element->setAttribute('type', 'collection'); $this->convertParameters($value, $type, $element, 'key'); } elseif ($value instanceof Reference) { $element->setAttribute('type', 'service'); $element->setAttribute('id', (string) $value); $behaviour = $value->getInvalidBehavior(); if ($behaviour == ContainerInterface::NULL_ON_INVALID_REFERENCE) { $element->setAttribute('on-invalid', 'null'); } elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) { $element->setAttribute('on-invalid', 'ignore'); } if (!$value->isStrict()) { $element->setAttribute('strict', 'false'); } } elseif ($value instanceof Definition) { $element->setAttribute('type', 'service'); $this->addService($value, null, $element); } elseif ($value instanceof Expression) { $element->setAttribute('type', 'expression'); $text = $this->document->createTextNode(self::phpToXml((string) $value)); $element->appendChild($text); } else { if (in_array($value, array('null', 'true', 'false'), true)) { $element->setAttribute('type', 'string'); } $text = $this->document->createTextNode(self::phpToXml($value)); $element->appendChild($text); } $parent->appendChild($element); } } /** * Escapes arguments * * @param array $arguments * * @return array */ private function escape($arguments) { $args = array(); foreach ($arguments as $k => $v) { if (is_array($v)) { $args[$k] = $this->escape($v); } elseif (is_string($v)) { $args[$k] = str_replace('%', '%%', $v); } else { $args[$k] = $v; } } return $args; } /** * Converts php types to xml types. * * @param mixed $value Value to convert * * @return string * * @throws RuntimeException When trying to dump object or resource */ public static function phpToXml($value) { switch (true) { case null === $value: return 'null'; case true === $value: return 'true'; case false === $value: return 'false'; case $value instanceof Parameter: return '%'.$value.'%'; case is_object($value) || is_resource($value): throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); default: return (string) $value; } } } PK!;Yޯ<Symfony/Component/DependencyInjection/ExpressionLanguage.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; /** * Adds some function to the default ExpressionLanguage. * * To get a service, use service('request'). * To get a parameter, use parameter('kernel.debug'). * * @author Fabien Potencier */ class ExpressionLanguage extends BaseExpressionLanguage { protected function registerFunctions() { parent::registerFunctions(); $this->register('service', function ($arg) { return sprintf('$this->get(%s)', $arg); }, function (array $variables, $value) { return $variables['container']->get($value); }); $this->register('parameter', function ($arg) { return sprintf('$this->getParameter(%s)', $arg); }, function (array $variables, $value) { return $variables['container']->getParameter($value); }); } } PK!U穌PP=Symfony/Component/DependencyInjection/DefinitionDecorator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; /** * This definition decorates another definition. * * @author Johannes M. Schmitt * * @api */ class DefinitionDecorator extends Definition { private $parent; private $changes = array(); /** * Constructor. * * @param string $parent The id of Definition instance to decorate. * * @api */ public function __construct($parent) { parent::__construct(); $this->parent = $parent; } /** * Returns the Definition being decorated. * * @return string * * @api */ public function getParent() { return $this->parent; } /** * Returns all changes tracked for the Definition object. * * @return array An array of changes for this Definition * * @api */ public function getChanges() { return $this->changes; } /** * {@inheritDoc} * * @api */ public function setClass($class) { $this->changes['class'] = true; return parent::setClass($class); } /** * {@inheritDoc} * * @api */ public function setFactoryClass($class) { $this->changes['factory_class'] = true; return parent::setFactoryClass($class); } /** * {@inheritDoc} * * @api */ public function setFactoryMethod($method) { $this->changes['factory_method'] = true; return parent::setFactoryMethod($method); } /** * {@inheritDoc} * * @api */ public function setFactoryService($service) { $this->changes['factory_service'] = true; return parent::setFactoryService($service); } /** * {@inheritDoc} * * @api */ public function setConfigurator($callable) { $this->changes['configurator'] = true; return parent::setConfigurator($callable); } /** * {@inheritDoc} * * @api */ public function setFile($file) { $this->changes['file'] = true; return parent::setFile($file); } /** * {@inheritDoc} * * @api */ public function setPublic($boolean) { $this->changes['public'] = true; return parent::setPublic($boolean); } /** * {@inheritDoc} * * @api */ public function setLazy($boolean) { $this->changes['lazy'] = true; return parent::setLazy($boolean); } /** * Gets an argument to pass to the service constructor/factory method. * * If replaceArgument() has been used to replace an argument, this method * will return the replacement value. * * @param integer $index * * @return mixed The argument value * * @throws OutOfBoundsException When the argument does not exist * * @api */ public function getArgument($index) { if (array_key_exists('index_'.$index, $this->arguments)) { return $this->arguments['index_'.$index]; } $lastIndex = count(array_filter(array_keys($this->arguments), 'is_int')) - 1; if ($index < 0 || $index > $lastIndex) { throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, $lastIndex)); } return $this->arguments[$index]; } /** * You should always use this method when overwriting existing arguments * of the parent definition. * * If you directly call setArguments() keep in mind that you must follow * certain conventions when you want to overwrite the arguments of the * parent definition, otherwise your arguments will only be appended. * * @param integer $index * @param mixed $value * * @return DefinitionDecorator the current instance * @throws InvalidArgumentException when $index isn't an integer * * @api */ public function replaceArgument($index, $value) { if (!is_int($index)) { throw new InvalidArgumentException('$index must be an integer.'); } $this->arguments['index_'.$index] = $value; return $this; } } PK!-R],,3Symfony/Component/DependencyInjection/Reference.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Reference represents a service reference. * * @author Fabien Potencier * * @api */ class Reference { private $id; private $invalidBehavior; private $strict; /** * Constructor. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * @param Boolean $strict Sets how this reference is validated * * @see Container */ public function __construct($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $strict = true) { $this->id = strtolower($id); $this->invalidBehavior = $invalidBehavior; $this->strict = $strict; } /** * __toString. * * @return string The service identifier */ public function __toString() { return $this->id; } /** * Returns the behavior to be used when the service does not exist. * * @return int */ public function getInvalidBehavior() { return $this->invalidBehavior; } /** * Returns true when this Reference is strict * * @return Boolean */ public function isStrict() { return $this->strict; } } PK!Ua--;Symfony/Component/DependencyInjection/Loader/FileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader; use Symfony\Component\Config\FileLocatorInterface; /** * FileLoader is the abstract class used by all built-in loaders that are file based. * * @author Fabien Potencier */ abstract class FileLoader extends BaseFileLoader { protected $container; /** * Constructor. * * @param ContainerBuilder $container A ContainerBuilder instance * @param FileLocatorInterface $locator A FileLocator instance */ public function __construct(ContainerBuilder $container, FileLocatorInterface $locator) { $this->container = $container; parent::__construct($locator); } } PK!ӸBj>Symfony/Component/DependencyInjection/Loader/IniFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * IniFileLoader loads parameters from INI files. * * @author Fabien Potencier */ class IniFileLoader extends FileLoader { /** * Loads a resource. * * @param mixed $file The resource * @param string $type The resource type * * @throws InvalidArgumentException When ini file is not valid */ public function load($file, $type = null) { $path = $this->locator->locate($file); $this->container->addResource(new FileResource($path)); $result = parse_ini_file($path, true); if (false === $result || array() === $result) { throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $file)); } if (isset($result['parameters']) && is_array($result['parameters'])) { foreach ($result['parameters'] as $key => $value) { $this->container->setParameter($key, $value); } } } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return is_string($resource) && 'ini' === pathinfo($resource, PATHINFO_EXTENSION); } } PK! >Symfony/Component/DependencyInjection/Loader/ClosureLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Loader\Loader; /** * ClosureLoader loads service definitions from a PHP closure. * * The Closure has access to the container as its first argument. * * @author Fabien Potencier */ class ClosureLoader extends Loader { private $container; /** * Constructor. * * @param ContainerBuilder $container A ContainerBuilder instance */ public function __construct(ContainerBuilder $container) { $this->container = $container; } /** * Loads a Closure. * * @param \Closure $closure The resource * @param string $type The resource type */ public function load($closure, $type = null) { call_user_func($closure, $this->container); } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return $resource instanceof \Closure; } } PK!((>Symfony/Component/DependencyInjection/Loader/PhpFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Resource\FileResource; /** * PhpFileLoader loads service definitions from a PHP file. * * The PHP file is required and the $container variable can be * used within the file to change the container. * * @author Fabien Potencier */ class PhpFileLoader extends FileLoader { /** * Loads a PHP file. * * @param mixed $file The resource * @param string $type The resource type */ public function load($file, $type = null) { // the container and loader variables are exposed to the included file below $container = $this->container; $loader = $this; $path = $this->locator->locate($file); $this->setCurrentDir(dirname($path)); $this->container->addResource(new FileResource($path)); include $path; } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION); } } PK!z#aQSymfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsdnu[ PK!L88>Symfony/Component/DependencyInjection/Loader/XmlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\SimpleXMLElement; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * XmlFileLoader loads XML files service definitions. * * @author Fabien Potencier */ class XmlFileLoader extends FileLoader { /** * Loads an XML file. * * @param mixed $file The resource * @param string $type The resource type */ public function load($file, $type = null) { $path = $this->locator->locate($file); $xml = $this->parseFile($path); $xml->registerXPathNamespace('container', 'http://symfony.com/schema/dic/services'); $this->container->addResource(new FileResource($path)); // anonymous services $this->processAnonymousServices($xml, $path); // imports $this->parseImports($xml, $path); // parameters $this->parseParameters($xml, $path); // extensions $this->loadFromExtensions($xml); // services $this->parseDefinitions($xml, $path); } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION); } /** * Parses parameters * * @param SimpleXMLElement $xml * @param string $file */ private function parseParameters(SimpleXMLElement $xml, $file) { if (!$xml->parameters) { return; } $this->container->getParameterBag()->add($xml->parameters->getArgumentsAsPhp('parameter')); } /** * Parses imports * * @param SimpleXMLElement $xml * @param string $file */ private function parseImports(SimpleXMLElement $xml, $file) { if (false === $imports = $xml->xpath('//container:imports/container:import')) { return; } foreach ($imports as $import) { $this->setCurrentDir(dirname($file)); $this->import((string) $import['resource'], null, (Boolean) $import->getAttributeAsPhp('ignore-errors'), $file); } } /** * Parses multiple definitions * * @param SimpleXMLElement $xml * @param string $file */ private function parseDefinitions(SimpleXMLElement $xml, $file) { if (false === $services = $xml->xpath('//container:services/container:service')) { return; } foreach ($services as $service) { $this->parseDefinition((string) $service['id'], $service, $file); } } /** * Parses an individual Definition * * @param string $id * @param SimpleXMLElement $service * @param string $file */ private function parseDefinition($id, $service, $file) { if ((string) $service['alias']) { $public = true; if (isset($service['public'])) { $public = $service->getAttributeAsPhp('public'); } $this->container->setAlias($id, new Alias((string) $service['alias'], $public)); return; } if (isset($service['parent'])) { $definition = new DefinitionDecorator((string) $service['parent']); } else { $definition = new Definition(); } foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'lazy', 'abstract') as $key) { if (isset($service[$key])) { $method = 'set'.str_replace('-', '', $key); $definition->$method((string) $service->getAttributeAsPhp($key)); } } if ($service->file) { $definition->setFile((string) $service->file); } $definition->setArguments($service->getArgumentsAsPhp('argument')); $definition->setProperties($service->getArgumentsAsPhp('property')); if (isset($service->configurator)) { if (isset($service->configurator['function'])) { $definition->setConfigurator((string) $service->configurator['function']); } else { if (isset($service->configurator['service'])) { $class = new Reference((string) $service->configurator['service'], ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false); } else { $class = (string) $service->configurator['class']; } $definition->setConfigurator(array($class, (string) $service->configurator['method'])); } } foreach ($service->call as $call) { $definition->addMethodCall((string) $call['method'], $call->getArgumentsAsPhp('argument')); } foreach ($service->tag as $tag) { $parameters = array(); foreach ($tag->attributes() as $name => $value) { if ('name' === $name) { continue; } if (false !== strpos($name, '-') && false === strpos($name, '_') && !array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) { $parameters[$normalizedName] = SimpleXMLElement::phpize($value); } // keep not normalized key for BC too $parameters[$name] = SimpleXMLElement::phpize($value); } $definition->addTag((string) $tag['name'], $parameters); } $this->container->setDefinition($id, $definition); } /** * Parses a XML file. * * @param string $file Path to a file * * @return SimpleXMLElement * * @throws InvalidArgumentException When loading of XML file returns error */ protected function parseFile($file) { try { $dom = XmlUtils::loadFile($file, array($this, 'validateSchema')); } catch (\InvalidArgumentException $e) { throw new InvalidArgumentException(sprintf('Unable to parse file "%s".', $file), $e->getCode(), $e); } $this->validateExtensions($dom, $file); return simplexml_import_dom($dom, 'Symfony\\Component\\DependencyInjection\\SimpleXMLElement'); } /** * Processes anonymous services * * @param SimpleXMLElement $xml * @param string $file */ private function processAnonymousServices(SimpleXMLElement $xml, $file) { $definitions = array(); $count = 0; // anonymous services as arguments/properties if (false !== $nodes = $xml->xpath('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]')) { foreach ($nodes as $node) { // give it a unique name $id = sprintf('%s_%d', hash('sha256', $file), ++$count); $node['id'] = $id; $definitions[$id] = array($node->service, $file, false); $node->service['id'] = $id; } } // anonymous services "in the wild" if (false !== $nodes = $xml->xpath('//container:services/container:service[not(@id)]')) { foreach ($nodes as $node) { // give it a unique name $id = sprintf('%s_%d', hash('sha256', $file), ++$count); $node['id'] = $id; $definitions[$id] = array($node, $file, true); $node->service['id'] = $id; } } // resolve definitions krsort($definitions); foreach ($definitions as $id => $def) { // anonymous services are always private $def[0]['public'] = false; $this->parseDefinition($id, $def[0], $def[1]); $oNode = dom_import_simplexml($def[0]); if (true === $def[2]) { $nNode = new \DOMElement('_services'); $oNode->parentNode->replaceChild($nNode, $oNode); $nNode->setAttribute('id', $id); } else { $oNode->parentNode->removeChild($oNode); } } } /** * Validates a documents XML schema. * * @param \DOMDocument $dom * * @return Boolean * * @throws RuntimeException When extension references a non-existent XSD file */ public function validateSchema(\DOMDocument $dom) { $schemaLocations = array('http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd')); if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) { $items = preg_split('/\s+/', $element); for ($i = 0, $nb = count($items); $i < $nb; $i += 2) { if (!$this->container->hasExtension($items[$i])) { continue; } if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) { $path = str_replace($extension->getNamespace(), str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]); if (!is_file($path)) { throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', get_class($extension), $path)); } $schemaLocations[$items[$i]] = $path; } } } $tmpfiles = array(); $imports = ''; foreach ($schemaLocations as $namespace => $location) { $parts = explode('/', $location); if (0 === stripos($location, 'phar://')) { $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); if ($tmpfile) { copy($location, $tmpfile); $tmpfiles[] = $tmpfile; $parts = explode('/', str_replace('\\', '/', $tmpfile)); } } $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts)); $imports .= sprintf(' '."\n", $namespace, $location); } $source = << $imports EOF ; $valid = @$dom->schemaValidateSource($source); foreach ($tmpfiles as $tmpfile) { @unlink($tmpfile); } return $valid; } /** * Validates an extension. * * @param \DOMDocument $dom * @param string $file * * @throws InvalidArgumentException When no extension is found corresponding to a tag */ private function validateExtensions(\DOMDocument $dom, $file) { foreach ($dom->documentElement->childNodes as $node) { if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) { continue; } // can it be handled by an extension? if (!$this->container->hasExtension($node->namespaceURI)) { $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getNamespace(); }, $this->container->getExtensions())); throw new InvalidArgumentException(sprintf( 'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none' )); } } } /** * Loads from an extension. * * @param SimpleXMLElement $xml */ private function loadFromExtensions(SimpleXMLElement $xml) { foreach (dom_import_simplexml($xml)->childNodes as $node) { if (!$node instanceof \DOMElement || $node->namespaceURI === 'http://symfony.com/schema/dic/services') { continue; } $values = static::convertDomElementToArray($node); if (!is_array($values)) { $values = array(); } $this->container->loadFromExtension($node->namespaceURI, $values); } } /** * Converts a \DomElement object to a PHP array. * * The following rules applies during the conversion: * * * Each tag is converted to a key value or an array * if there is more than one "value" * * * The content of a tag is set under a "value" key (bar) * if the tag also has some nested tags * * * The attributes are converted to keys () * * * The nested-tags are converted to keys (bar) * * @param \DomElement $element A \DomElement instance * * @return array A PHP array */ public static function convertDomElementToArray(\DomElement $element) { return XmlUtils::convertDomElementToArray($element); } } PK!!+++?Symfony/Component/DependencyInjection/Loader/YamlFileLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\ExpressionLanguage\Expression; /** * YamlFileLoader loads YAML files service definitions. * * The YAML format does not support anonymous services (cf. the XML loader). * * @author Fabien Potencier */ class YamlFileLoader extends FileLoader { private $yamlParser; /** * Loads a Yaml file. * * @param mixed $file The resource * @param string $type The resource type */ public function load($file, $type = null) { $path = $this->locator->locate($file); $content = $this->loadFile($path); $this->container->addResource(new FileResource($path)); // empty file if (null === $content) { return; } // imports $this->parseImports($content, $path); // parameters if (isset($content['parameters'])) { foreach ($content['parameters'] as $key => $value) { $this->container->setParameter($key, $this->resolveServices($value)); } } // extensions $this->loadFromExtensions($content); // services $this->parseDefinitions($content, $file); } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean true if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION); } /** * Parses all imports * * @param array $content * @param string $file */ private function parseImports($content, $file) { if (!isset($content['imports'])) { return; } foreach ($content['imports'] as $import) { $this->setCurrentDir(dirname($file)); $this->import($import['resource'], null, isset($import['ignore_errors']) ? (Boolean) $import['ignore_errors'] : false, $file); } } /** * Parses definitions * * @param array $content * @param string $file */ private function parseDefinitions($content, $file) { if (!isset($content['services'])) { return; } foreach ($content['services'] as $id => $service) { $this->parseDefinition($id, $service, $file); } } /** * Parses a definition. * * @param string $id * @param array $service * @param string $file * * @throws InvalidArgumentException When tags are invalid */ private function parseDefinition($id, $service, $file) { if (is_string($service) && 0 === strpos($service, '@')) { $this->container->setAlias($id, substr($service, 1)); return; } elseif (isset($service['alias'])) { $public = !array_key_exists('public', $service) || (Boolean) $service['public']; $this->container->setAlias($id, new Alias($service['alias'], $public)); return; } if (isset($service['parent'])) { $definition = new DefinitionDecorator($service['parent']); } else { $definition = new Definition(); } if (isset($service['class'])) { $definition->setClass($service['class']); } if (isset($service['scope'])) { $definition->setScope($service['scope']); } if (isset($service['synthetic'])) { $definition->setSynthetic($service['synthetic']); } if (isset($service['synchronized'])) { $definition->setSynchronized($service['synchronized']); } if (isset($service['lazy'])) { $definition->setLazy($service['lazy']); } if (isset($service['public'])) { $definition->setPublic($service['public']); } if (isset($service['abstract'])) { $definition->setAbstract($service['abstract']); } if (isset($service['factory_class'])) { $definition->setFactoryClass($service['factory_class']); } if (isset($service['factory_method'])) { $definition->setFactoryMethod($service['factory_method']); } if (isset($service['factory_service'])) { $definition->setFactoryService($service['factory_service']); } if (isset($service['file'])) { $definition->setFile($service['file']); } if (isset($service['arguments'])) { $definition->setArguments($this->resolveServices($service['arguments'])); } if (isset($service['properties'])) { $definition->setProperties($this->resolveServices($service['properties'])); } if (isset($service['configurator'])) { if (is_string($service['configurator'])) { $definition->setConfigurator($service['configurator']); } else { $definition->setConfigurator(array($this->resolveServices($service['configurator'][0]), $service['configurator'][1])); } } if (isset($service['calls'])) { foreach ($service['calls'] as $call) { $args = isset($call[1]) ? $this->resolveServices($call[1]) : array(); $definition->addMethodCall($call[0], $args); } } if (isset($service['tags'])) { if (!is_array($service['tags'])) { throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s.', $id, $file)); } foreach ($service['tags'] as $tag) { if (!isset($tag['name'])) { throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file)); } $name = $tag['name']; unset($tag['name']); foreach ($tag as $attribute => $value) { if (!is_scalar($value) && null !== $value) { throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s.', $id, $name, $attribute, $file)); } } $definition->addTag($name, $tag); } } $this->container->setDefinition($id, $definition); } /** * Loads a YAML file. * * @param string $file * * @return array The file content */ protected function loadFile($file) { if (!stream_is_local($file)) { throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $file)); } if (!file_exists($file)) { throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } return $this->validate($this->yamlParser->parse(file_get_contents($file)), $file); } /** * Validates a YAML file. * * @param mixed $content * @param string $file * * @return array * * @throws InvalidArgumentException When service file is not valid */ private function validate($content, $file) { if (null === $content) { return $content; } if (!is_array($content)) { throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file)); } foreach (array_keys($content) as $namespace) { if (in_array($namespace, array('imports', 'parameters', 'services'))) { continue; } if (!$this->container->hasExtension($namespace)) { $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions())); throw new InvalidArgumentException(sprintf( 'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $namespace, $file, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none' )); } } return $content; } /** * Resolves services. * * @param string $value * * @return Reference */ private function resolveServices($value) { if (is_array($value)) { $value = array_map(array($this, 'resolveServices'), $value); } elseif (is_string($value) && 0 === strpos($value, '@=')) { return new Expression(substr($value, 2)); } elseif (is_string($value) && 0 === strpos($value, '@')) { if (0 === strpos($value, '@@')) { $value = substr($value, 1); $invalidBehavior = null; } elseif (0 === strpos($value, '@?')) { $value = substr($value, 2); $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; } else { $value = substr($value, 1); $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; } if ('=' === substr($value, -1)) { $value = substr($value, 0, -1); $strict = false; } else { $strict = true; } if (null !== $invalidBehavior) { $value = new Reference($value, $invalidBehavior, $strict); } } return $value; } /** * Loads from Extensions * * @param array $content */ private function loadFromExtensions($content) { foreach ($content as $namespace => $values) { if (in_array($namespace, array('imports', 'parameters', 'services'))) { continue; } if (!is_array($values)) { $values = array(); } $this->container->loadFromExtension($namespace, $values); } } } PK!Gp5 5 ;Symfony/Component/DependencyInjection/Compiler/Compiler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * This class is used to remove circular dependencies between individual passes. * * @author Johannes M. Schmitt * * @api */ class Compiler { private $passConfig; private $log = array(); private $loggingFormatter; private $serviceReferenceGraph; /** * Constructor. */ public function __construct() { $this->passConfig = new PassConfig(); $this->serviceReferenceGraph = new ServiceReferenceGraph(); $this->loggingFormatter = new LoggingFormatter(); } /** * Returns the PassConfig. * * @return PassConfig The PassConfig instance * * @api */ public function getPassConfig() { return $this->passConfig; } /** * Returns the ServiceReferenceGraph. * * @return ServiceReferenceGraph The ServiceReferenceGraph instance * * @api */ public function getServiceReferenceGraph() { return $this->serviceReferenceGraph; } /** * Returns the logging formatter which can be used by compilation passes. * * @return LoggingFormatter */ public function getLoggingFormatter() { return $this->loggingFormatter; } /** * Adds a pass to the PassConfig. * * @param CompilerPassInterface $pass A compiler pass * @param string $type The type of the pass * * @api */ public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) { $this->passConfig->addPass($pass, $type); } /** * Adds a log message. * * @param string $string The log message */ public function addLogMessage($string) { $this->log[] = $string; } /** * Returns the log. * * @return array Log array */ public function getLog() { return $this->log; } /** * Run the Compiler and process all Passes. * * @param ContainerBuilder $container * * @api */ public function compile(ContainerBuilder $container) { foreach ($this->passConfig->getPasses() as $pass) { $pass->process($container); } } } PK!0є##?Symfony/Component/DependencyInjection/Compiler/RepeatedPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * A pass that might be run repeatedly. * * @author Johannes M. Schmitt */ class RepeatedPass implements CompilerPassInterface { /** * @var Boolean */ private $repeat = false; /** * @var RepeatablePassInterface[] */ private $passes; /** * Constructor. * * @param RepeatablePassInterface[] $passes An array of RepeatablePassInterface objects * * @throws InvalidArgumentException when the passes don't implement RepeatablePassInterface */ public function __construct(array $passes) { foreach ($passes as $pass) { if (!$pass instanceof RepeatablePassInterface) { throw new InvalidArgumentException('$passes must be an array of RepeatablePassInterface.'); } $pass->setRepeatedPass($this); } $this->passes = $passes; } /** * Process the repeatable passes that run more than once. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->repeat = false; foreach ($this->passes as $pass) { $pass->process($container); } if ($this->repeat) { $this->process($container); } } /** * Sets if the pass should repeat */ public function setRepeat() { $this->repeat = true; } /** * Returns the passes * * @return RepeatablePassInterface[] An array of RepeatablePassInterface objects */ public function getPasses() { return $this->passes; } } PK!LFFUSymfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; /** * Replaces aliases with actual service definitions, effectively removing these * aliases. * * @author Johannes M. Schmitt */ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface { private $compiler; private $formatter; private $sourceId; /** * Process the Container to replace aliases with service definitions. * * @param ContainerBuilder $container * * @throws InvalidArgumentException if the service definition does not exist */ public function process(ContainerBuilder $container) { $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); foreach ($container->getAliases() as $id => $alias) { $aliasId = (string) $alias; try { $definition = $container->getDefinition($aliasId); } catch (InvalidArgumentException $e) { throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with "%s".', $alias, $id), null, $e); } if ($definition->isPublic()) { continue; } $definition->setPublic(true); $container->setDefinition($id, $definition); $container->removeDefinition($aliasId); $this->updateReferences($container, $aliasId, $id); // we have to restart the process due to concurrent modification of // the container $this->process($container); break; } } /** * Updates references to remove aliases. * * @param ContainerBuilder $container The container * @param string $currentId The alias identifier being replaced * @param string $newId The id of the service the alias points to */ private function updateReferences($container, $currentId, $newId) { foreach ($container->getAliases() as $id => $alias) { if ($currentId === (string) $alias) { $container->setAlias($id, $newId); } } foreach ($container->getDefinitions() as $id => $definition) { $this->sourceId = $id; $definition->setArguments( $this->updateArgumentReferences($definition->getArguments(), $currentId, $newId) ); $definition->setMethodCalls( $this->updateArgumentReferences($definition->getMethodCalls(), $currentId, $newId) ); $definition->setProperties( $this->updateArgumentReferences($definition->getProperties(), $currentId, $newId) ); } } /** * Updates argument references. * * @param array $arguments An array of Arguments * @param string $currentId The alias identifier * @param string $newId The identifier the alias points to * * @return array */ private function updateArgumentReferences(array $arguments, $currentId, $newId) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->updateArgumentReferences($argument, $currentId, $newId); } elseif ($argument instanceof Reference) { if ($currentId === (string) $argument) { $arguments[$k] = new Reference($newId, $argument->getInvalidBehavior()); $this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $this->sourceId, $currentId, $newId)); } } } return $arguments; } } PK!C\Z=Symfony/Component/DependencyInjection/Compiler/PassConfig.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * Compiler Pass Configuration * * This class has a default configuration embedded. * * @author Johannes M. Schmitt * * @api */ class PassConfig { const TYPE_AFTER_REMOVING = 'afterRemoving'; const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization'; const TYPE_BEFORE_REMOVING = 'beforeRemoving'; const TYPE_OPTIMIZE = 'optimization'; const TYPE_REMOVE = 'removing'; private $mergePass; private $afterRemovingPasses = array(); private $beforeOptimizationPasses = array(); private $beforeRemovingPasses = array(); private $optimizationPasses; private $removingPasses; /** * Constructor. */ public function __construct() { $this->mergePass = new MergeExtensionConfigurationPass(); $this->optimizationPasses = array( new ResolveDefinitionTemplatesPass(), new ResolveParameterPlaceHoldersPass(), new CheckDefinitionValidityPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), new AnalyzeServiceReferencesPass(true), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), ); $this->removingPasses = array( new RemovePrivateAliasesPass(), new RemoveAbstractDefinitionsPass(), new ReplaceAliasByActualDefinitionPass(), new RepeatedPass(array( new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass(), new AnalyzeServiceReferencesPass(), new RemoveUnusedDefinitionsPass(), )), new CheckExceptionOnInvalidReferenceBehaviorPass(), ); } /** * Returns all passes in order to be processed. * * @return array An array of all passes to process * * @api */ public function getPasses() { return array_merge( array($this->mergePass), $this->beforeOptimizationPasses, $this->optimizationPasses, $this->beforeRemovingPasses, $this->removingPasses, $this->afterRemovingPasses ); } /** * Adds a pass. * * @param CompilerPassInterface $pass A Compiler pass * @param string $type The pass type * * @throws InvalidArgumentException when a pass type doesn't exist * * @api */ public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION) { $property = $type.'Passes'; if (!isset($this->$property)) { throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type)); } $passes = &$this->$property; $passes[] = $pass; } /** * Gets all passes for the AfterRemoving pass. * * @return array An array of passes * * @api */ public function getAfterRemovingPasses() { return $this->afterRemovingPasses; } /** * Gets all passes for the BeforeOptimization pass. * * @return array An array of passes * * @api */ public function getBeforeOptimizationPasses() { return $this->beforeOptimizationPasses; } /** * Gets all passes for the BeforeRemoving pass. * * @return array An array of passes * * @api */ public function getBeforeRemovingPasses() { return $this->beforeRemovingPasses; } /** * Gets all passes for the Optimization pass. * * @return array An array of passes * * @api */ public function getOptimizationPasses() { return $this->optimizationPasses; } /** * Gets all passes for the Removing pass. * * @return array An array of passes * * @api */ public function getRemovingPasses() { return $this->removingPasses; } /** * Gets all passes for the Merge pass. * * @return array An array of passes * * @api */ public function getMergePass() { return $this->mergePass; } /** * Sets the Merge Pass. * * @param CompilerPassInterface $pass The merge pass * * @api */ public function setMergePass(CompilerPassInterface $pass) { $this->mergePass = $pass; } /** * Sets the AfterRemoving passes. * * @param array $passes An array of passes * * @api */ public function setAfterRemovingPasses(array $passes) { $this->afterRemovingPasses = $passes; } /** * Sets the BeforeOptimization passes. * * @param array $passes An array of passes * * @api */ public function setBeforeOptimizationPasses(array $passes) { $this->beforeOptimizationPasses = $passes; } /** * Sets the BeforeRemoving passes. * * @param array $passes An array of passes * * @api */ public function setBeforeRemovingPasses(array $passes) { $this->beforeRemovingPasses = $passes; } /** * Sets the Optimization passes. * * @param array $passes An array of passes * * @api */ public function setOptimizationPasses(array $passes) { $this->optimizationPasses = $passes; } /** * Sets the Removing passes. * * @param array $passes An array of passes * * @api */ public function setRemovingPasses(array $passes) { $this->removingPasses = $passes; } } PK!x7LSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; /** * Represents an edge in your service graph. * * Value is typically a reference. * * @author Johannes M. Schmitt */ class ServiceReferenceGraphEdge { private $sourceNode; private $destNode; private $value; /** * Constructor. * * @param ServiceReferenceGraphNode $sourceNode * @param ServiceReferenceGraphNode $destNode * @param string $value */ public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null) { $this->sourceNode = $sourceNode; $this->destNode = $destNode; $this->value = $value; } /** * Returns the value of the edge * * @return ServiceReferenceGraphNode */ public function getValue() { return $this->value; } /** * Returns the source node * * @return ServiceReferenceGraphNode */ public function getSourceNode() { return $this->sourceNode; } /** * Returns the destination node * * @return ServiceReferenceGraphNode */ public function getDestNode() { return $this->destNode; } } PK! MSymfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException; use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException; /** * Checks the validity of references * * The following checks are performed by this pass: * - target definitions are not abstract * - target definitions are of equal or wider scope * - target definitions are in the same scope hierarchy * * @author Johannes M. Schmitt */ class CheckReferenceValidityPass implements CompilerPassInterface { private $container; private $currentId; private $currentDefinition; private $currentScope; private $currentScopeAncestors; private $currentScopeChildren; /** * Processes the ContainerBuilder to validate References. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; $children = $this->container->getScopeChildren(); $ancestors = array(); $scopes = $this->container->getScopes(); foreach ($scopes as $name => $parent) { $ancestors[$name] = array($parent); while (isset($scopes[$parent])) { $ancestors[$name][] = $parent = $scopes[$parent]; } } foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $this->currentId = $id; $this->currentDefinition = $definition; $this->currentScope = $scope = $definition->getScope(); if (ContainerInterface::SCOPE_CONTAINER === $scope) { $this->currentScopeChildren = array_keys($scopes); $this->currentScopeAncestors = array(); } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope) { $this->currentScopeChildren = isset($children[$scope]) ? $children[$scope] : array(); $this->currentScopeAncestors = isset($ancestors[$scope]) ? $ancestors[$scope] : array(); } $this->validateReferences($definition->getArguments()); $this->validateReferences($definition->getMethodCalls()); $this->validateReferences($definition->getProperties()); } } /** * Validates an array of References. * * @param array $arguments An array of Reference objects * * @throws RuntimeException when there is a reference to an abstract definition. */ private function validateReferences(array $arguments) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->validateReferences($argument); } elseif ($argument instanceof Reference) { $targetDefinition = $this->getDefinition((string) $argument); if (null !== $targetDefinition && $targetDefinition->isAbstract()) { throw new RuntimeException(sprintf( 'The definition "%s" has a reference to an abstract definition "%s". ' .'Abstract definitions cannot be the target of references.', $this->currentId, $argument )); } $this->validateScope($argument, $targetDefinition); } } } /** * Validates the scope of a single Reference. * * @param Reference $reference * @param Definition $definition * * @throws ScopeWideningInjectionException when the definition references a service of a narrower scope * @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy */ private function validateScope(Reference $reference, Definition $definition = null) { if (ContainerInterface::SCOPE_PROTOTYPE === $this->currentScope) { return; } if (!$reference->isStrict()) { return; } if (null === $definition) { return; } if ($this->currentScope === $scope = $definition->getScope()) { return; } $id = (string) $reference; if (in_array($scope, $this->currentScopeChildren, true)) { throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope); } if (!in_array($scope, $this->currentScopeAncestors, true)) { throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope); } } /** * Returns the Definition given an id. * * @param string $id Definition identifier * * @return Definition */ private function getDefinition($id) { if (!$this->container->hasDefinition($id)) { return null; } return $this->container->getDefinition($id); } } PK!iZ NSymfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Removes unused service definitions from the container. * * @author Johannes M. Schmitt */ class RemoveUnusedDefinitionsPass implements RepeatablePassInterface { private $repeatedPass; /** * {@inheritDoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes the ContainerBuilder to remove unused definitions. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); $graph = $compiler->getServiceReferenceGraph(); $hasChanged = false; foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isPublic()) { continue; } if ($graph->hasNode($id)) { $edges = $graph->getNode($id)->getInEdges(); $referencingAliases = array(); $sourceIds = array(); foreach ($edges as $edge) { $node = $edge->getSourceNode(); $sourceIds[] = $node->getId(); if ($node->isAlias()) { $referencingAliases[] = $node->getValue(); } } $isReferenced = (count(array_unique($sourceIds)) - count($referencingAliases)) > 0; } else { $referencingAliases = array(); $isReferenced = false; } if (1 === count($referencingAliases) && false === $isReferenced) { $container->setDefinition((string) reset($referencingAliases), $definition); $definition->setPublic(true); $container->removeDefinition($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'replaces alias '.reset($referencingAliases))); } elseif (0 === count($referencingAliases) && false === $isReferenced) { $container->removeDefinition($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'unused')); $hasChanged = true; } } if ($hasChanged) { $this->repeatedPass->setRepeat(); } } } PK!!?KSymfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Remove private aliases from the container. They were only used to establish * dependencies between services, and these dependencies have been resolved in * one of the previous passes. * * @author Johannes M. Schmitt */ class RemovePrivateAliasesPass implements CompilerPassInterface { /** * Removes private aliases from the ContainerBuilder * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); foreach ($container->getAliases() as $id => $alias) { if ($alias->isPublic()) { continue; } $container->removeAlias($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'private alias')); } } } PK!U*''PSymfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Removes abstract Definitions * */ class RemoveAbstractDefinitionsPass implements CompilerPassInterface { /** * Removes abstract definitions from the ContainerBuilder * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isAbstract()) { $container->removeDefinition($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'abstract')); } } } } PK!mOSymfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Inline service definitions where this is possible. * * @author Johannes M. Schmitt */ class InlineServiceDefinitionsPass implements RepeatablePassInterface { private $repeatedPass; private $graph; private $compiler; private $formatter; private $currentId; /** * {@inheritDoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes the ContainerBuilder for inline service definitions. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); $this->graph = $this->compiler->getServiceReferenceGraph(); foreach ($container->getDefinitions() as $id => $definition) { $this->currentId = $id; $definition->setArguments( $this->inlineArguments($container, $definition->getArguments()) ); $definition->setMethodCalls( $this->inlineArguments($container, $definition->getMethodCalls()) ); $definition->setProperties( $this->inlineArguments($container, $definition->getProperties()) ); } } /** * Processes inline arguments. * * @param ContainerBuilder $container The ContainerBuilder * @param array $arguments An array of arguments * * @return array */ private function inlineArguments(ContainerBuilder $container, array $arguments) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->inlineArguments($container, $argument); } elseif ($argument instanceof Reference) { if (!$container->hasDefinition($id = (string) $argument)) { continue; } if ($this->isInlineableDefinition($container, $id, $definition = $container->getDefinition($id))) { $this->compiler->addLogMessage($this->formatter->formatInlineService($this, $id, $this->currentId)); if (ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope()) { $arguments[$k] = $definition; } else { $arguments[$k] = clone $definition; } } } elseif ($argument instanceof Definition) { $argument->setArguments($this->inlineArguments($container, $argument->getArguments())); $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls())); $argument->setProperties($this->inlineArguments($container, $argument->getProperties())); } } return $arguments; } /** * Checks if the definition is inlineable. * * @param ContainerBuilder $container * @param string $id * @param Definition $definition * * @return Boolean If the definition is inlineable */ private function isInlineableDefinition(ContainerBuilder $container, $id, Definition $definition) { if (ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) { return true; } if ($definition->isPublic() || $definition->isLazy()) { return false; } if (!$this->graph->hasNode($id)) { return true; } if ($this->currentId == $id) { return false; } $ids = array(); foreach ($this->graph->getNode($id)->getInEdges() as $edge) { $ids[] = $edge->getSourceNode()->getId(); } if (count(array_unique($ids)) > 1) { return false; } return $container->getDefinition(reset($ids))->getScope() === $definition->getScope(); } } PK!iJT OSymfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * Emulates the invalid behavior if the reference is not found within the * container. * * @author Johannes M. Schmitt */ class ResolveInvalidReferencesPass implements CompilerPassInterface { private $container; /** * Process the ContainerBuilder to resolve invalid references. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $definition->setArguments( $this->processArguments($definition->getArguments()) ); $calls = array(); foreach ($definition->getMethodCalls() as $call) { try { $calls[] = array($call[0], $this->processArguments($call[1], true)); } catch (RuntimeException $ignore) { // this call is simply removed } } $definition->setMethodCalls($calls); $properties = array(); foreach ($definition->getProperties() as $name => $value) { try { $value = $this->processArguments(array($value), true); $properties[$name] = reset($value); } catch (RuntimeException $ignore) { // ignore property } } $definition->setProperties($properties); } } /** * Processes arguments to determine invalid references. * * @param array $arguments An array of Reference objects * @param Boolean $inMethodCall * * @return array * * @throws RuntimeException When the config is invalid */ private function processArguments(array $arguments, $inMethodCall = false) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->processArguments($argument, $inMethodCall); } elseif ($argument instanceof Reference) { $id = (string) $argument; $invalidBehavior = $argument->getInvalidBehavior(); $exists = $this->container->has($id); // resolve invalid behavior if (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { $arguments[$k] = null; } elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { if ($inMethodCall) { throw new RuntimeException('Method shouldn\'t be called.'); } $arguments[$k] = null; } } } return $arguments; } } PK!P P QSymfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Replaces all references to aliases with references to the actual service. * * @author Johannes M. Schmitt */ class ResolveReferencesToAliasesPass implements CompilerPassInterface { private $container; /** * Processes the ContainerBuilder to replace references to aliases with actual service references. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $definition->setArguments($this->processArguments($definition->getArguments())); $definition->setMethodCalls($this->processArguments($definition->getMethodCalls())); $definition->setProperties($this->processArguments($definition->getProperties())); } foreach ($container->getAliases() as $id => $alias) { $aliasId = (string) $alias; if ($aliasId !== $defId = $this->getDefinitionId($aliasId)) { $container->setAlias($id, new Alias($defId, $alias->isPublic())); } } } /** * Processes the arguments to replace aliases. * * @param array $arguments An array of References * * @return array An array of References */ private function processArguments(array $arguments) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->processArguments($argument); } elseif ($argument instanceof Reference) { $defId = $this->getDefinitionId($id = (string) $argument); if ($defId !== $id) { $arguments[$k] = new Reference($defId, $argument->getInvalidBehavior(), $argument->isStrict()); } } } return $arguments; } /** * Resolves an alias into a definition id. * * @param string $id The definition or alias id to resolve * * @return string The definition id with aliases resolved */ private function getDefinitionId($id) { while ($this->container->hasAlias($id)) { $id = (string) $this->container->getAlias($id); } return $id; } } PK!V%) ) HSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * This is a directed graph of your services. * * This information can be used by your compiler passes instead of collecting * it themselves which improves performance quite a lot. * * @author Johannes M. Schmitt */ class ServiceReferenceGraph { /** * @var ServiceReferenceGraphNode[] */ private $nodes = array(); /** * Checks if the graph has a specific node. * * @param string $id Id to check * * @return Boolean */ public function hasNode($id) { return isset($this->nodes[$id]); } /** * Gets a node by identifier. * * @param string $id The id to retrieve * * @return ServiceReferenceGraphNode The node matching the supplied identifier * * @throws InvalidArgumentException if no node matches the supplied identifier */ public function getNode($id) { if (!isset($this->nodes[$id])) { throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id)); } return $this->nodes[$id]; } /** * Returns all nodes. * * @return ServiceReferenceGraphNode[] An array of all ServiceReferenceGraphNode objects */ public function getNodes() { return $this->nodes; } /** * Clears all nodes. */ public function clear() { $this->nodes = array(); } /** * Connects 2 nodes together in the Graph. * * @param string $sourceId * @param string $sourceValue * @param string $destId * @param string $destValue * @param string $reference */ public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null) { $sourceNode = $this->createNode($sourceId, $sourceValue); $destNode = $this->createNode($destId, $destValue); $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference); $sourceNode->addOutEdge($edge); $destNode->addInEdge($edge); } /** * Creates a graph node. * * @param string $id * @param string $value * * @return ServiceReferenceGraphNode */ private function createNode($id, $value) { if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) { return $this->nodes[$id]; } return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value); } } PK![ LSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Alias; /** * Represents a node in your service graph. * * Value is typically a definition, or an alias. * * @author Johannes M. Schmitt */ class ServiceReferenceGraphNode { private $id; private $inEdges = array(); private $outEdges = array(); private $value; /** * Constructor. * * @param string $id The node identifier * @param mixed $value The node value */ public function __construct($id, $value) { $this->id = $id; $this->value = $value; } /** * Adds an in edge to this node. * * @param ServiceReferenceGraphEdge $edge */ public function addInEdge(ServiceReferenceGraphEdge $edge) { $this->inEdges[] = $edge; } /** * Adds an out edge to this node. * * @param ServiceReferenceGraphEdge $edge */ public function addOutEdge(ServiceReferenceGraphEdge $edge) { $this->outEdges[] = $edge; } /** * Checks if the value of this node is an Alias. * * @return Boolean True if the value is an Alias instance */ public function isAlias() { return $this->value instanceof Alias; } /** * Checks if the value of this node is a Definition. * * @return Boolean True if the value is a Definition instance */ public function isDefinition() { return $this->value instanceof Definition; } /** * Returns the identifier. * * @return string */ public function getId() { return $this->id; } /** * Returns the in edges. * * @return array The in ServiceReferenceGraphEdge array */ public function getInEdges() { return $this->inEdges; } /** * Returns the out edges. * * @return array The out ServiceReferenceGraphEdge array */ public function getOutEdges() { return $this->outEdges; } /** * Returns the value of this Node * * @return mixed The value */ public function getValue() { return $this->value; } } PK!ϒQSymfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * This replaces all DefinitionDecorator instances with their equivalent fully * merged Definition instance. * * @author Johannes M. Schmitt */ class ResolveDefinitionTemplatesPass implements CompilerPassInterface { private $container; private $compiler; private $formatter; /** * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); foreach (array_keys($container->getDefinitions()) as $id) { // yes, we are specifically fetching the definition from the // container to ensure we are not operating on stale data $definition = $container->getDefinition($id); if (!$definition instanceof DefinitionDecorator || $definition->isAbstract()) { continue; } $this->resolveDefinition($id, $definition); } } /** * Resolves the definition * * @param string $id The definition identifier * @param DefinitionDecorator $definition * * @return Definition * * @throws \RuntimeException When the definition is invalid */ private function resolveDefinition($id, DefinitionDecorator $definition) { if (!$this->container->hasDefinition($parent = $definition->getParent())) { throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $id)); } $parentDef = $this->container->getDefinition($parent); if ($parentDef instanceof DefinitionDecorator) { $parentDef = $this->resolveDefinition($parent, $parentDef); } $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent)); $def = new Definition(); // merge in parent definition // purposely ignored attributes: scope, abstract, tags $def->setClass($parentDef->getClass()); $def->setArguments($parentDef->getArguments()); $def->setMethodCalls($parentDef->getMethodCalls()); $def->setProperties($parentDef->getProperties()); $def->setFactoryClass($parentDef->getFactoryClass()); $def->setFactoryMethod($parentDef->getFactoryMethod()); $def->setFactoryService($parentDef->getFactoryService()); $def->setConfigurator($parentDef->getConfigurator()); $def->setFile($parentDef->getFile()); $def->setPublic($parentDef->isPublic()); $def->setLazy($parentDef->isLazy()); // overwrite with values specified in the decorator $changes = $definition->getChanges(); if (isset($changes['class'])) { $def->setClass($definition->getClass()); } if (isset($changes['factory_class'])) { $def->setFactoryClass($definition->getFactoryClass()); } if (isset($changes['factory_method'])) { $def->setFactoryMethod($definition->getFactoryMethod()); } if (isset($changes['factory_service'])) { $def->setFactoryService($definition->getFactoryService()); } if (isset($changes['configurator'])) { $def->setConfigurator($definition->getConfigurator()); } if (isset($changes['file'])) { $def->setFile($definition->getFile()); } if (isset($changes['public'])) { $def->setPublic($definition->isPublic()); } if (isset($changes['lazy'])) { $def->setLazy($definition->isLazy()); } // merge arguments foreach ($definition->getArguments() as $k => $v) { if (is_numeric($k)) { $def->addArgument($v); continue; } if (0 !== strpos($k, 'index_')) { throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k)); } $index = (integer) substr($k, strlen('index_')); $def->replaceArgument($index, $v); } // merge properties foreach ($definition->getProperties() as $k => $v) { $def->setProperty($k, $v); } // append method calls if (count($calls = $definition->getMethodCalls()) > 0) { $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); } // these attributes are always taken from the child $def->setAbstract($definition->isAbstract()); $def->setScope($definition->getScope()); $def->setTags($definition->getTags()); // set new definition on container $this->container->setDefinition($id, $def); return $def; } } PK!nnSSymfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; /** * Resolves all parameter placeholders "%somevalue%" to their real values. * * @author Johannes M. Schmitt */ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface { /** * Processes the ContainerBuilder to resolve parameter placeholders. * * @param ContainerBuilder $container * * @throws ParameterNotFoundException */ public function process(ContainerBuilder $container) { $parameterBag = $container->getParameterBag(); foreach ($container->getDefinitions() as $id => $definition) { try { $definition->setClass($parameterBag->resolveValue($definition->getClass())); $definition->setFile($parameterBag->resolveValue($definition->getFile())); $definition->setArguments($parameterBag->resolveValue($definition->getArguments())); $calls = array(); foreach ($definition->getMethodCalls() as $name => $arguments) { $calls[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($arguments); } $definition->setMethodCalls($calls); $definition->setProperties($parameterBag->resolveValue($definition->getProperties())); } catch (ParameterNotFoundException $e) { $e->setSourceId($id); throw $e; } } $aliases = array(); foreach ($container->getAliases() as $name => $target) { $aliases[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($target); } $container->setAliases($aliases); $parameterBag->resolve(); } } PK!X\\RSymfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; /** * Merges extension configs into the container builder * * @author Fabien Potencier */ class MergeExtensionConfigurationPass implements CompilerPassInterface { /** * {@inheritDoc} */ public function process(ContainerBuilder $container) { $parameters = $container->getParameterBag()->all(); $definitions = $container->getDefinitions(); $aliases = $container->getAliases(); foreach ($container->getExtensions() as $extension) { if ($extension instanceof PrependExtensionInterface) { $extension->prepend($container); } } foreach ($container->getExtensions() as $name => $extension) { if (!$config = $container->getExtensionConfig($name)) { // this extension was not called continue; } $config = $container->getParameterBag()->resolveValue($config); $tmpContainer = new ContainerBuilder($container->getParameterBag()); $tmpContainer->setResourceTracking($container->isTrackingResources()); $tmpContainer->addObjectResource($extension); $extension->load($config, $tmpContainer); $container->merge($tmpContainer); } $container->addDefinitions($definitions); $container->addAliases($aliases); $container->getParameterBag()->add($parameters); } } PK!_9HSymfony/Component/DependencyInjection/Compiler/CompilerPassInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Interface that must be implemented by compilation passes * * @author Johannes M. Schmitt * * @api */ interface CompilerPassInterface { /** * You can modify the container here before it is dumped to PHP code. * * @param ContainerBuilder $container * * @api */ public function process(ContainerBuilder $container); } PK!EųJSymfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; /** * Interface that must be implemented by passes that are run as part of an * RepeatedPass. * * @author Johannes M. Schmitt */ interface RepeatablePassInterface extends CompilerPassInterface { /** * Sets the RepeatedPass interface. * * @param RepeatedPass $repeatedPass */ public function setRepeatedPass(RepeatedPass $repeatedPass); } PK!b[_66_Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Checks that all references are pointing to a valid service. * * @author Johannes M. Schmitt */ class CheckExceptionOnInvalidReferenceBehaviorPass implements CompilerPassInterface { private $container; private $sourceId; public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $id => $definition) { $this->sourceId = $id; $this->processDefinition($definition); } } private function processDefinition(Definition $definition) { $this->processReferences($definition->getArguments()); $this->processReferences($definition->getMethodCalls()); $this->processReferences($definition->getProperties()); } private function processReferences(array $arguments) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->processReferences($argument); } elseif ($argument instanceof Definition) { $this->processDefinition($argument); } elseif ($argument instanceof Reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $argument->getInvalidBehavior()) { $destId = (string) $argument; if (!$this->container->has($destId)) { throw new ServiceNotFoundException($destId, $this->sourceId); } } } } } PK!@ q q NSymfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Checks your services for circular references * * References from method calls are ignored since we might be able to resolve * these references depending on the order in which services are called. * * Circular reference from method calls will only be detected at run-time. * * @author Johannes M. Schmitt */ class CheckCircularReferencesPass implements CompilerPassInterface { private $currentId; private $currentPath; private $checkedNodes; /** * Checks the ContainerBuilder object for circular references. * * @param ContainerBuilder $container The ContainerBuilder instances */ public function process(ContainerBuilder $container) { $graph = $container->getCompiler()->getServiceReferenceGraph(); $this->checkedNodes = array(); foreach ($graph->getNodes() as $id => $node) { $this->currentId = $id; $this->currentPath = array($id); $this->checkOutEdges($node->getOutEdges()); } } /** * Checks for circular references. * * @param ServiceReferenceGraphEdge[] $edges An array of Edges * * @throws ServiceCircularReferenceException When a circular reference is found. */ private function checkOutEdges(array $edges) { foreach ($edges as $edge) { $node = $edge->getDestNode(); $id = $node->getId(); if (empty($this->checkedNodes[$id])) { $searchKey = array_search($id, $this->currentPath); $this->currentPath[] = $id; if (false !== $searchKey) { throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey)); } $this->checkOutEdges($node->getOutEdges()); $this->checkedNodes[$id] = true; array_pop($this->currentPath); } } } } PK!ddNSymfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * This pass validates each definition individually only taking the information * into account which is contained in the definition itself. * * Later passes can rely on the following, and specifically do not need to * perform these checks themselves: * * - non synthetic, non abstract services always have a class set * - synthetic services are always public * - synthetic services are always of non-prototype scope * * @author Johannes M. Schmitt */ class CheckDefinitionValidityPass implements CompilerPassInterface { /** * Processes the ContainerBuilder to validate the Definition. * * @param ContainerBuilder $container * * @throws RuntimeException When the Definition is invalid */ public function process(ContainerBuilder $container) { foreach ($container->getDefinitions() as $id => $definition) { // synthetic service is public if ($definition->isSynthetic() && !$definition->isPublic()) { throw new RuntimeException(sprintf( 'A synthetic service ("%s") must be public.', $id )); } // synthetic service has non-prototype scope if ($definition->isSynthetic() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) { throw new RuntimeException(sprintf( 'A synthetic service ("%s") cannot be of scope "prototype".', $id )); } // non-synthetic, non-abstract service has class if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) { if ($definition->getFactoryClass() || $definition->getFactoryService()) { throw new RuntimeException(sprintf( 'Please add the class to service "%s" even if it is constructed by a factory ' .'since we might need to add method calls based on compile-time checks.', $id )); } throw new RuntimeException(sprintf( 'The definition for "%s" has no class. If you intend to inject ' .'this service dynamically at runtime, please mark it as synthetic=true. ' .'If this is an abstract definition solely used by child definitions, ' .'please add abstract=true, otherwise specify a class to get rid of this error.', $id )); } // tag attribute values must be scalars foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { foreach ($attributes as $attribute => $value) { if (!is_scalar($value) && null !== $value) { throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute)); } } } } } } } PK!ۻǠOSymfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Run this pass before passes that need to know more about the relation of * your services. * * This class will populate the ServiceReferenceGraph with information. You can * retrieve the graph in other passes from the compiler. * * @author Johannes M. Schmitt */ class AnalyzeServiceReferencesPass implements RepeatablePassInterface { private $graph; private $container; private $currentId; private $currentDefinition; private $repeatedPass; private $onlyConstructorArguments; /** * Constructor. * * @param Boolean $onlyConstructorArguments Sets this Service Reference pass to ignore method calls */ public function __construct($onlyConstructorArguments = false) { $this->onlyConstructorArguments = (Boolean) $onlyConstructorArguments; } /** * {@inheritDoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes a ContainerBuilder object to populate the service reference graph. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; $this->graph = $container->getCompiler()->getServiceReferenceGraph(); $this->graph->clear(); foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $this->currentId = $id; $this->currentDefinition = $definition; $this->processArguments($definition->getArguments()); if (!$this->onlyConstructorArguments) { $this->processArguments($definition->getMethodCalls()); $this->processArguments($definition->getProperties()); if ($definition->getConfigurator()) { $this->processArguments(array($definition->getConfigurator())); } } } foreach ($container->getAliases() as $id => $alias) { $this->graph->connect($id, $alias, (string) $alias, $this->getDefinition((string) $alias), null); } } /** * Processes service definitions for arguments to find relationships for the service graph. * * @param array $arguments An array of Reference or Definition objects relating to service definitions */ private function processArguments(array $arguments) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->processArguments($argument); } elseif ($argument instanceof Reference) { $this->graph->connect( $this->currentId, $this->currentDefinition, $this->getDefinitionId((string) $argument), $this->getDefinition((string) $argument), $argument ); } elseif ($argument instanceof Definition) { $this->processArguments($argument->getArguments()); $this->processArguments($argument->getMethodCalls()); $this->processArguments($argument->getProperties()); } } } /** * Returns a service definition given the full name or an alias. * * @param string $id A full id or alias for a service definition. * * @return Definition|null The definition related to the supplied id */ private function getDefinition($id) { $id = $this->getDefinitionId($id); return null === $id ? null : $this->container->getDefinition($id); } private function getDefinitionId($id) { while ($this->container->hasAlias($id)) { $id = (string) $this->container->getAlias($id); } if (!$this->container->hasDefinition($id)) { return null; } return $id; } } PK!CSymfony/Component/DependencyInjection/Compiler/LoggingFormatter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; /** * Used to format logging messages during the compilation. * * @author Johannes M. Schmitt */ class LoggingFormatter { public function formatRemoveService(CompilerPassInterface $pass, $id, $reason) { return $this->format($pass, sprintf('Removed service "%s"; reason: %s', $id, $reason)); } public function formatInlineService(CompilerPassInterface $pass, $id, $target) { return $this->format($pass, sprintf('Inlined service "%s" to "%s".', $id, $target)); } public function formatUpdateReference(CompilerPassInterface $pass, $serviceId, $oldDestId, $newDestId) { return $this->format($pass, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $serviceId, $oldDestId, $newDestId)); } public function formatResolveInheritance(CompilerPassInterface $pass, $childId, $parentId) { return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId)); } public function format(CompilerPassInterface $pass, $message) { return sprintf('%s: %s', get_class($pass), $message); } } PK!EBEB3Symfony/Component/DependencyInjection/Container.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; /** * Container is a dependency injection container. * * It gives access to object instances (services). * * Services and parameters are simple key/pair stores. * * Parameter and service keys are case insensitive. * * A service id can contain lowercased letters, digits, underscores, and dots. * Underscores are used to separate words, and dots to group services * under namespaces: * *
    *
  • request
  • *
  • mysql_session_storage
  • *
  • symfony.mysql_session_storage
  • *
* * A service can also be defined by creating a method named * getXXXService(), where XXX is the camelized version of the id: * *
    *
  • request -> getRequestService()
  • *
  • mysql_session_storage -> getMysqlSessionStorageService()
  • *
  • symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()
  • *
* * The container can have three possible behaviors when a service does not exist: * * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) * * NULL_ON_INVALID_REFERENCE: Returns null * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference * (for instance, ignore a setter if the service does not exist) * * @author Fabien Potencier * @author Johannes M. Schmitt * * @api */ class Container implements IntrospectableContainerInterface { /** * @var ParameterBagInterface */ protected $parameterBag; protected $services = array(); protected $methodMap = array(); protected $aliases = array(); protected $scopes = array(); protected $scopeChildren = array(); protected $scopedServices = array(); protected $scopeStacks = array(); protected $loading = array(); /** * Constructor. * * @param ParameterBagInterface $parameterBag A ParameterBagInterface instance * * @api */ public function __construct(ParameterBagInterface $parameterBag = null) { $this->parameterBag = $parameterBag ?: new ParameterBag(); $this->set('service_container', $this); } /** * Compiles the container. * * This method does two things: * * * Parameter values are resolved; * * The parameter bag is frozen. * * @api */ public function compile() { $this->parameterBag->resolve(); $this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); } /** * Returns true if the container parameter bag are frozen. * * @return Boolean true if the container parameter bag are frozen, false otherwise * * @api */ public function isFrozen() { return $this->parameterBag instanceof FrozenParameterBag; } /** * Gets the service container parameter bag. * * @return ParameterBagInterface A ParameterBagInterface instance * * @api */ public function getParameterBag() { return $this->parameterBag; } /** * Gets a parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws InvalidArgumentException if the parameter is not defined * * @api */ public function getParameter($name) { return $this->parameterBag->get($name); } /** * Checks if a parameter exists. * * @param string $name The parameter name * * @return Boolean The presence of parameter in container * * @api */ public function hasParameter($name) { return $this->parameterBag->has($name); } /** * Sets a parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function setParameter($name, $value) { $this->parameterBag->set($name, $value); } /** * Sets a service. * * Setting a service to null resets the service: has() returns false and get() * behaves in the same way as if the service was never created. * * @param string $id The service identifier * @param object $service The service instance * @param string $scope The scope of the service * * @throws RuntimeException When trying to set a service in an inactive scope * @throws InvalidArgumentException When trying to set a service in the prototype scope * * @api */ public function set($id, $service, $scope = self::SCOPE_CONTAINER) { if (self::SCOPE_PROTOTYPE === $scope) { throw new InvalidArgumentException(sprintf('You cannot set service "%s" of scope "prototype".', $id)); } $id = strtolower($id); if (self::SCOPE_CONTAINER !== $scope) { if (!isset($this->scopedServices[$scope])) { throw new RuntimeException(sprintf('You cannot set service "%s" of inactive scope.', $id)); } $this->scopedServices[$scope][$id] = $service; } $this->services[$id] = $service; if (method_exists($this, $method = 'synchronize'.strtr($id, array('_' => '', '.' => '_', '\\' => '_')).'Service')) { $this->$method(); } if (self::SCOPE_CONTAINER !== $scope && null === $service) { unset($this->scopedServices[$scope][$id]); } if (null === $service) { unset($this->services[$id]); } } /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return Boolean true if the service is defined, false otherwise * * @api */ public function has($id) { $id = strtolower($id); return isset($this->services[$id]) || array_key_exists($id, $this->services) || isset($this->aliases[$id]) || method_exists($this, 'get'.strtr($id, array('_' => '', '.' => '_', '\\' => '_')).'Service') ; } /** * Gets a service. * * If a service is defined both through a set() method and * with a get{$id}Service() method, the former has always precedence. * * @param string $id The service identifier * @param integer $invalidBehavior The behavior when the service does not exist * * @return object The associated service * * @throws InvalidArgumentException if the service is not defined * @throws ServiceCircularReferenceException When a circular reference is detected * @throws ServiceNotFoundException When the service is not defined * * @see Reference * * @api */ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE) { // Attempt to retrieve the service by checking first aliases then // available services. Service IDs are case insensitive, however since // this method can be called thousands of times during a request, avoid // calling strtolower() unless necessary. foreach (array(false, true) as $strtolower) { if ($strtolower) { $id = strtolower($id); } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } // Re-use shared service instance if it exists. if (isset($this->services[$id]) || array_key_exists($id, $this->services)) { return $this->services[$id]; } } if (isset($this->loading[$id])) { throw new ServiceCircularReferenceException($id, array_keys($this->loading)); } if (isset($this->methodMap[$id])) { $method = $this->methodMap[$id]; } elseif (method_exists($this, $method = 'get'.strtr($id, array('_' => '', '.' => '_', '\\' => '_')).'Service')) { // $method is set to the right value, proceed } else { if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { if (!$id) { throw new ServiceNotFoundException($id); } $alternatives = array(); foreach (array_keys($this->services) as $key) { $lev = levenshtein($id, $key); if ($lev <= strlen($id) / 3 || false !== strpos($key, $id)) { $alternatives[] = $key; } } throw new ServiceNotFoundException($id, null, null, $alternatives); } return null; } $this->loading[$id] = true; try { $service = $this->$method(); } catch (\Exception $e) { unset($this->loading[$id]); if (array_key_exists($id, $this->services)) { unset($this->services[$id]); } if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return null; } throw $e; } unset($this->loading[$id]); return $service; } /** * Returns true if the given service has actually been initialized * * @param string $id The service identifier * * @return Boolean true if service has already been initialized, false otherwise */ public function initialized($id) { $id = strtolower($id); return isset($this->services[$id]) || array_key_exists($id, $this->services); } /** * Gets all service ids. * * @return array An array of all defined service ids */ public function getServiceIds() { $ids = array(); $r = new \ReflectionClass($this); foreach ($r->getMethods() as $method) { if (preg_match('/^get(.+)Service$/', $method->name, $match)) { $ids[] = self::underscore($match[1]); } } return array_unique(array_merge($ids, array_keys($this->services))); } /** * This is called when you enter a scope * * @param string $name * * @throws RuntimeException When the parent scope is inactive * @throws InvalidArgumentException When the scope does not exist * * @api */ public function enterScope($name) { if (!isset($this->scopes[$name])) { throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name)); } if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) { throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name])); } // check if a scope of this name is already active, if so we need to // remove all services of this scope, and those of any of its child // scopes from the global services map if (isset($this->scopedServices[$name])) { $services = array($this->services, $name => $this->scopedServices[$name]); unset($this->scopedServices[$name]); foreach ($this->scopeChildren[$name] as $child) { if (isset($this->scopedServices[$child])) { $services[$child] = $this->scopedServices[$child]; unset($this->scopedServices[$child]); } } // update global map $this->services = call_user_func_array('array_diff_key', $services); array_shift($services); // add stack entry for this scope so we can restore the removed services later if (!isset($this->scopeStacks[$name])) { $this->scopeStacks[$name] = new \SplStack(); } $this->scopeStacks[$name]->push($services); } $this->scopedServices[$name] = array(); } /** * This is called to leave the current scope, and move back to the parent * scope. * * @param string $name The name of the scope to leave * * @throws InvalidArgumentException if the scope is not active * * @api */ public function leaveScope($name) { if (!isset($this->scopedServices[$name])) { throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name)); } // remove all services of this scope, or any of its child scopes from // the global service map $services = array($this->services, $this->scopedServices[$name]); unset($this->scopedServices[$name]); foreach ($this->scopeChildren[$name] as $child) { if (!isset($this->scopedServices[$child])) { continue; } $services[] = $this->scopedServices[$child]; unset($this->scopedServices[$child]); } $this->services = call_user_func_array('array_diff_key', $services); // check if we need to restore services of a previous scope of this type if (isset($this->scopeStacks[$name]) && count($this->scopeStacks[$name]) > 0) { $services = $this->scopeStacks[$name]->pop(); $this->scopedServices += $services; foreach ($services as $array) { foreach ($array as $id => $service) { $this->set($id, $service, $name); } } } } /** * Adds a scope to the container. * * @param ScopeInterface $scope * * @throws InvalidArgumentException * * @api */ public function addScope(ScopeInterface $scope) { $name = $scope->getName(); $parentScope = $scope->getParentName(); if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) { throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name)); } if (isset($this->scopes[$name])) { throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name)); } if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) { throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope)); } $this->scopes[$name] = $parentScope; $this->scopeChildren[$name] = array(); // normalize the child relations while ($parentScope !== self::SCOPE_CONTAINER) { $this->scopeChildren[$parentScope][] = $name; $parentScope = $this->scopes[$parentScope]; } } /** * Returns whether this container has a certain scope * * @param string $name The name of the scope * * @return Boolean * * @api */ public function hasScope($name) { return isset($this->scopes[$name]); } /** * Returns whether this scope is currently active * * This does not actually check if the passed scope actually exists. * * @param string $name * * @return Boolean * * @api */ public function isScopeActive($name) { return isset($this->scopedServices[$name]); } /** * Camelizes a string. * * @param string $id A string to camelize * * @return string The camelized string */ public static function camelize($id) { return strtr(ucwords(strtr($id, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => '')); } /** * A string to underscore. * * @param string $id The string to underscore * * @return string The underscored string */ public static function underscore($id) { return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($id, '_', '.'))); } } PK!E?<Symfony/Component/DependencyInjection/ContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; /** * ContainerInterface is the interface implemented by service container classes. * * @author Fabien Potencier * @author Johannes M. Schmitt * * @api */ interface ContainerInterface { const EXCEPTION_ON_INVALID_REFERENCE = 1; const NULL_ON_INVALID_REFERENCE = 2; const IGNORE_ON_INVALID_REFERENCE = 3; const SCOPE_CONTAINER = 'container'; const SCOPE_PROTOTYPE = 'prototype'; /** * Sets a service. * * @param string $id The service identifier * @param object $service The service instance * @param string $scope The scope of the service * * @api */ public function set($id, $service, $scope = self::SCOPE_CONTAINER); /** * Gets a service. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * * @return object The associated service * * @throws InvalidArgumentException if the service is not defined * @throws ServiceCircularReferenceException When a circular reference is detected * @throws ServiceNotFoundException When the service is not defined * * @see Reference * * @api */ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE); /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return Boolean true if the service is defined, false otherwise * * @api */ public function has($id); /** * Gets a parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws InvalidArgumentException if the parameter is not defined * * @api */ public function getParameter($name); /** * Checks if a parameter exists. * * @param string $name The parameter name * * @return Boolean The presence of parameter in container * * @api */ public function hasParameter($name); /** * Sets a parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function setParameter($name, $value); /** * Enters the given scope * * @param string $name * * @api */ public function enterScope($name); /** * Leaves the current scope, and re-enters the parent scope * * @param string $name * * @api */ public function leaveScope($name); /** * Adds a scope to the container * * @param ScopeInterface $scope * * @api */ public function addScope(ScopeInterface $scope); /** * Whether this container has the given scope * * @param string $name * * @return Boolean * * @api */ public function hasScope($name); /** * Determines whether the given scope is currently active. * * It does however not check if the scope actually exists. * * @param string $name * * @return Boolean * * @api */ public function isScopeActive($name); } PK!o =Symfony/Component/DependencyInjection/Extension/Extension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Config\Definition\ConfigurationInterface; /** * Provides useful features shared by many extensions. * * @author Fabien Potencier */ abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface { /** * Returns the base path for the XSD files. * * @return string The XSD base path */ public function getXsdValidationBasePath() { return false; } /** * Returns the namespace to be used for this extension (XML namespace). * * @return string The XML namespace */ public function getNamespace() { return 'http://example.org/schema/dic/'.$this->getAlias(); } /** * Returns the recommended alias to use in XML. * * This alias is also the mandatory prefix to use when using YAML. * * This convention is to remove the "Extension" postfix from the class * name and then lowercase and underscore the result. So: * * AcmeHelloExtension * * becomes * * acme_hello * * This can be overridden in a sub-class to specify the alias manually. * * @return string The alias * * @throws BadMethodCallException When the extension name does not follow conventions */ public function getAlias() { $className = get_class($this); if (substr($className, -9) != 'Extension') { throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.'); } $classBaseName = substr(strrchr($className, '\\'), 1, -9); return Container::underscore($classBaseName); } /** * {@inheritDoc} */ public function getConfiguration(array $config, ContainerBuilder $container) { $reflected = new \ReflectionClass($this); $namespace = $reflected->getNamespaceName(); $class = $namespace.'\\Configuration'; if (class_exists($class)) { $r = new \ReflectionClass($class); $container->addResource(new FileResource($r->getFileName())); if (!method_exists($class, '__construct')) { $configuration = new $class(); return $configuration; } } return null; } final protected function processConfiguration(ConfigurationInterface $configuration, array $configs) { $processor = new Processor(); return $processor->processConfiguration($configuration, $configs); } /** * @param ContainerBuilder $container * @param array $config * * @return Boolean Whether the configuration is enabled * * @throws InvalidArgumentException When the config is not enableable */ protected function isConfigEnabled(ContainerBuilder $container, array $config) { if (!array_key_exists('enabled', $config)) { throw new InvalidArgumentException("The config array has no 'enabled' key."); } return (Boolean) $container->getParameterBag()->resolveValue($config['enabled']); } } PK!DSFSymfony/Component/DependencyInjection/Extension/ExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * ExtensionInterface is the interface implemented by container extension classes. * * @author Fabien Potencier * * @api */ interface ExtensionInterface { /** * Loads a specific configuration. * * @param array $config An array of configuration values * @param ContainerBuilder $container A ContainerBuilder instance * * @throws \InvalidArgumentException When provided tag is not defined in this extension * * @api */ public function load(array $config, ContainerBuilder $container); /** * Returns the namespace to be used for this extension (XML namespace). * * @return string The XML namespace * * @api */ public function getNamespace(); /** * Returns the base path for the XSD files. * * @return string The XSD base path * * @api */ public function getXsdValidationBasePath(); /** * Returns the recommended alias to use in XML. * * This alias is also the mandatory prefix to use when using YAML. * * @return string The alias * * @api */ public function getAlias(); } PK!JSSymfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; /** * ConfigurationExtensionInterface is the interface implemented by container extension classes. * * @author Kevin Bond */ interface ConfigurationExtensionInterface { /** * Returns extension configuration * * @param array $config $config An array of configuration values * @param ContainerBuilder $container A ContainerBuilder instance * * @return ConfigurationInterface|null The configuration or null */ public function getConfiguration(array $config, ContainerBuilder $container); } PK!CoMMMSymfony/Component/DependencyInjection/Extension/PrependExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; interface PrependExtensionInterface { /** * Allow an extension to prepend the extension configurations. * * @param ContainerBuilder $container */ public function prepend(ContainerBuilder $container); } PK!F"3Symfony/Component/DependencyInjection/Parameter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Parameter represents a parameter reference. * * @author Fabien Potencier * * @api */ class Parameter { private $id; /** * Constructor. * * @param string $id The parameter key */ public function __construct($id) { $this->id = $id; } /** * __toString. * * @return string The parameter key */ public function __toString() { return (string) $this->id; } } PK!'P ezc/Base/metadata.phpnu[reader = new ezcBaseMetaDataTarballReader; break; case 'pear': $this->reader = new ezcBaseMetaDataPearReader; break; default: throw new ezcBaseMetaDataReaderException( "Unknown install method '$installMethod'." ); break; } } /** * Returns the version string for the installed eZ Components bundle. * * A version string such as "2008.2.2" is returned. * * @return string */ public function getBundleVersion() { return $this->reader->getBundleVersion(); } /** * Returns a PHP version string that describes the required PHP version for * this installed eZ Components bundle. * * @return string */ public function getRequiredPhpVersion() { return $this->reader->getRequiredPhpVersion(); } /** * Returns whether $componentName is installed * * If installed with PEAR, it checks the PEAR registry whether the * component is there. In case the tarball installation method is used, it * will return true for every component that exists (because all of them * are then available). * * @return bool */ public function isComponentInstalled( $componentName ) { return $this->reader->isComponentInstalled( $componentName ); } /** * Returns the version string of the available $componentName or false when * the component is not installed. * * @return string */ public function getComponentVersion( $componentName ) { return $this->reader->getComponentVersion( $componentName ); } /** * Returns a list of components that $componentName depends on. * * If $componentName is left empty, all installed components are returned. * * The returned array has as keys the component names, and as values the * version of the components. * * @return array(string=>string). */ public function getComponentDependencies( $componentName = null ) { if ( $componentName === null ) { return $this->reader->getComponentDependencies(); } else { return $this->reader->getComponentDependencies( $componentName ); } } } ?> PK!:||ezc/Base/ezc_bootstrap.phpnu[ PK!ezc/Base/options/autoload.phpnu[mixed) $options */ public function __construct( array $options = array() ) { $this->preload = false; $this->debug = false; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'debug': case 'preload': if ( !is_bool( $value ) ) { throw new ezcBaseValueException( $name, $value, 'bool' ); } $this->properties[$name] = $value; break; default: throw new ezcBasePropertyNotFoundException( $name ); } } } ?> PK!|R  )ezc/Base/structs/repository_directory.phpnu[type = $type; $this->basePath = $basePath; $this->autoloadPath = $autoloadPath; } /** * Returns a new instance of this class with the data specified by $array. * * $array contains all the data members of this class in the form: * array('member_name'=>value). * * __set_state makes this class exportable with var_export. * var_export() generates code, that calls this method when it * is parsed with PHP. * * @param array(string=>mixed) $array * @return ezcBaseRepositoryDirectory */ static public function __set_state( array $array ) { return new ezcBaseRepositoryDirectory( $array['type'], $array['basePath'], $array['autoloadPath'] ); } } ?> PK!S،&ezc/Base/structs/file_find_context.phpnu[elements = $elements; $this->count = $count; $this->size = $size; } /** * Returns a new instance of this class with the data specified by $array. * * $array contains all the data members of this class in the form: * array('member_name'=>value). * * __set_state makes this class exportable with var_export. * var_export() generates code, that calls this method when it * is parsed with PHP. * * @param array(string=>mixed) $array * @return ezcBaseFileFindContext */ static public function __set_state( array $array ) { return new ezcBaseFileFindContext( $array['elements'], $array['count'], $array['size'] ); } } ?> PK!jezc/Base/metadata/tarball.phpnu[xml = simplexml_load_file( $filename ); } /** * Returns the version string for the installed eZ Components bundle. * * A version string such as "2008.2.2" is returned. * * @return string */ public function getBundleVersion() { return (string) $this->xml->version; } /** * Returns a PHP version string that describes the required PHP version for * this installed eZ Components bundle. * * @return string */ public function getRequiredPhpVersion() { return (string) $this->xml->deps->php; } /** * Returns whether $componentName is installed * * Returns true for every component that exists (because all of them are * then available). * * @return bool */ public function isComponentInstalled( $componentName ) { $root = $this->xml->deps->packages->package; foreach ( $root as $package ) { if ( (string) $package['name'] == $componentName ) { return true; } } return false; } /** * Returns the version string of the available $componentName or false when * the component is not installed. * * @return string */ public function getComponentVersion( $componentName ) { $root = $this->xml->deps->packages->package; foreach ( $root as $package ) { if ( (string) $package['name'] == $componentName ) { return (string) $package['version']; } } return false; } /** * Returns a list of components that $componentName depends on. * * If $componentName is left empty, all installed components are returned. * * The returned array has as keys the component names, and as values the * version of the components. It returns null of the $componentName * is not found. * * @return array(string=>string). */ public function getComponentDependencies( $componentName = null ) { $baseVersion = false; $root = $this->xml->deps->packages; $found = $componentName === null ? true : false; // in case $componentName != null, we loop through all the components // in the file, and figure out the new root that we can list dependency // packages from. foreach ( $root->package as $package ) { if ( (string) $package['name'] == 'Base' ) { $baseVersion = $package['version']; } if ( !$found && (string) $package['name'] == $componentName ) { $root = $package->deps; $found = true; } } if ( !$found ) { return null; } // We always add the Base dependency even though it's not in the dependency file. $deps = array(); $deps['Base'] = (string) $baseVersion; if ( !isset( $root->package ) ) { return $deps; } foreach ( $root->package as $package ) { $deps[(string) $package['name']] = (string) $package['version']; } return $deps; } } ?> PK!myv  ezc/Base/metadata/pear.phpnu[registry = new PEAR_Registry; } /** * Returns the version string for the installed eZ Components bundle. * * A version string such as "2008.2.2" is returned. * * @return string */ public function getBundleVersion() { @$packageInfo = $this->registry->packageInfo( 'ezcomponents', null, 'components.ez.no' ); return $packageInfo['version']['release']; } /** * Returns a PHP version string that describes the required PHP version for * this installed eZ Components bundle. * * @return string */ public function getRequiredPhpVersion() { @$packageInfo = $this->registry->packageInfo( 'ezcomponents', null, 'components.ez.no' ); if ( array_key_exists( 'required', $packageInfo['dependencies'] ) ) { return $packageInfo['dependencies']['required']['php']['min']; } return $packageInfo['dependencies']['php']['min']; } /** * Returns whether $componentName is installed * * Checks the PEAR registry whether the component is there. * * @return bool */ public function isComponentInstalled( $componentName ) { @$packageInfo = $this->registry->packageInfo( $componentName, null, 'components.ez.no' ); return is_array( $packageInfo ); } /** * Returns the version string of the available $componentName or false when * the component is not installed. * * @return string */ public function getComponentVersion( $componentName ) { @$packageInfo = $this->registry->packageInfo( $componentName, null, 'components.ez.no' ); $release = $packageInfo['version']['release']; return $release === null ? false : $release; } /** * Returns a list of components that $componentName depends on. * * If $componentName is left empty, all installed components are returned. * * The returned array has as keys the component names, and as values the * version of the components. * * @return array(string=>string). */ public function getComponentDependencies( $componentName = 'ezcomponents' ) { @$packageInfo = $this->registry->packageInfo( $componentName, 'dependencies', 'components.ez.no' ); if ( isset( $packageInfo['required']['package'] ) ) { $deps = array(); if ( isset( $packageInfo['required']['package']['name'] ) ) { $deps[$packageInfo['required']['package']['name']] = $packageInfo['required']['package']['min']; } else { foreach ( $packageInfo['required']['package'] as $package ) { $deps[$package['name']] = $package['min']; } } return $deps; } return array(); } } ?> PK!BX++ezc/Base/features.phpnu[ * * * * @package Base * @version 1.8 */ class ezcBaseFeatures { /** * Used to store the path of the ImageMagick convert utility. * * It is initialized in the {@link getImageConvertExecutable()} function. * * @var string */ private static $imageConvert = null; /** * Used to store the path of the ImageMagick identify utility. * * It is initialized in the {@link getImageIdentifyExecutable()} function. * * @var string */ private static $imageIdentify = null; /** * Used to store the operating system. * * It is initialized in the {@link os()} function. * * @var string */ private static $os = null; /** * Determines if hardlinks are supported. * * @return bool */ public static function supportsLink() { return function_exists( 'link' ); } /** * Determines if symlinks are supported. * * @return bool */ public static function supportsSymLink() { return function_exists( 'symlink' ); } /** * Determines if posix uids are supported. * * @return bool */ public static function supportsUserId() { return function_exists( 'posix_getpwuid' ); } /** * Determines if the ImageMagick convert utility is installed. * * @return bool */ public static function hasImageConvert() { return !is_null( self::getImageConvertExecutable() ); } /** * Returns the path to the ImageMagick convert utility. * * On Linux, Unix,... it will return something like: /usr/bin/convert * On Windows it will return something like: C:\Windows\System32\convert.exe * * @return string */ public static function getImageConvertExecutable() { if ( !is_null( self::$imageConvert ) ) { return self::$imageConvert; } return ( self::$imageConvert = self::findExecutableInPath( 'convert' ) ); } /** * Determines if the ImageMagick identify utility is installed. * * @return bool */ public static function hasImageIdentify() { return !is_null( self::getImageIdentifyExecutable() ); } /** * Returns the path to the ImageMagick identify utility. * * On Linux, Unix,... it will return something like: /usr/bin/identify * On Windows it will return something like: C:\Windows\System32\identify.exe * * @return string */ public static function getImageIdentifyExecutable() { if ( !is_null( self::$imageIdentify ) ) { return self::$imageIdentify; } return ( self::$imageIdentify = self::findExecutableInPath( 'identify' ) ); } /** * Determines if the specified extension is loaded. * * If $version is specified, the specified extension will be tested also * against the version of the loaded extension. * * Examples: * * hasExtensionSupport( 'gzip' ); * * will return true if gzip extension is loaded. * * * hasExtensionSupport( 'pdo_mysql', '1.0.2' ); * * will return true if pdo_mysql extension is loaded and its version is at least 1.0.2. * * @param string $extension * @param string $version * @return bool */ public static function hasExtensionSupport( $extension, $version = null ) { if ( is_null( $version ) ) { return extension_loaded( $extension ); } return extension_loaded( $extension ) && version_compare( phpversion( $extension ), $version, ">=" ) ; } /** * Determines if the specified function is available. * * Examples: * * ezcBaseFeatures::hasFunction( 'imagepstext' ); * * will return true if support for Type 1 fonts is available with your GD * extension. * * @param string $functionName * @return bool */ public static function hasFunction( $functionName ) { return function_exists( $functionName ); } /** * Returns if a given class exists. * Checks for a given class name and returns if this class exists or not. * Catches the ezcBaseAutoloadException and returns false, if it was thrown. * * @param string $className The class to check for. * @param bool $autoload True to use __autoload(), otherwise false. * @return bool True if the class exists. Otherwise false. */ public static function classExists( $className, $autoload = true ) { try { if ( class_exists( $className, $autoload ) ) { return true; } return false; } catch ( ezcBaseAutoloadException $e ) { return false; } } /** * Returns the operating system on which PHP is running. * * This method returns a sanitized form of the OS name, example * return values are "Windows", "Mac", "Linux" and "FreeBSD". In * all other cases it returns the value of the internal PHP constant * PHP_OS. * * @return string */ public static function os() { if ( is_null( self::$os ) ) { $uname = php_uname( 's' ); if ( substr( $uname, 0, 7 ) == 'Windows' ) { self::$os = 'Windows'; } elseif ( substr( $uname, 0, 3 ) == 'Mac' ) { self::$os = 'Mac'; } elseif ( strtolower( $uname ) == 'linux' ) { self::$os = 'Linux'; } elseif ( strtolower( substr( $uname, 0, 7 ) ) == 'freebsd' ) { self::$os = 'FreeBSD'; } else { self::$os = PHP_OS; } } return self::$os; } /** * Returns the path of the specified executable, if it can be found in the system's path. * * It scans the PATH enviroment variable based on the OS to find the * $fileName. For Windows, the path is with \, not /. If $fileName is not * found, it returns null. * * @todo consider using getenv( 'PATH' ) instead of $_ENV['PATH'] * (but that won't work under IIS) * * @param string $fileName * @return string */ public static function findExecutableInPath( $fileName ) { if ( array_key_exists( 'PATH', $_ENV ) ) { $envPath = trim( $_ENV['PATH'] ); } else if ( ( $envPath = getenv( 'PATH' ) ) !== false ) { $envPath = trim( $envPath ); } if ( is_string( $envPath ) && strlen( trim( $envPath ) ) == 0 ) { $envPath = false; } switch ( self::os() ) { case 'Unix': case 'FreeBSD': case 'Mac': case 'MacOS': case 'Darwin': case 'Linux': case 'SunOS': if ( $envPath ) { $dirs = explode( ':', $envPath ); foreach ( $dirs as $dir ) { // The @-operator is used here mainly to avoid // open_basedir warnings. If open_basedir (or any other // circumstance) prevents the desired file from being // accessed, it is fine for file_exists() to return // false, since it is useless for use then, anyway. if ( file_exists( "{$dir}/{$fileName}" ) ) { return "{$dir}/{$fileName}"; } } } // The @-operator is used here mainly to avoid open_basedir // warnings. If open_basedir (or any other circumstance) // prevents the desired file from being accessed, it is fine // for file_exists() to return false, since it is useless for // use then, anyway. elseif ( @file_exists( "./{$fileName}" ) ) { return $fileName; } break; case 'Windows': if ( $envPath ) { $dirs = explode( ';', $envPath ); foreach ( $dirs as $dir ) { // The @-operator is used here mainly to avoid // open_basedir warnings. If open_basedir (or any other // circumstance) prevents the desired file from being // accessed, it is fine for file_exists() to return // false, since it is useless for use then, anyway. if ( @file_exists( "{$dir}\\{$fileName}.exe" ) ) { return "{$dir}\\{$fileName}.exe"; } } } // The @-operator is used here mainly to avoid open_basedir // warnings. If open_basedir (or any other circumstance) // prevents the desired file from being accessed, it is fine // for file_exists() to return false, since it is useless for // use then, anyway. elseif ( @file_exists( "{$fileName}.exe" ) ) { return "{$fileName}.exe"; } break; } return null; } /** * Reset the cached information. * * @return void * @access private * @ignore */ public static function reset() { self::$imageIdentify = null; self::$imageConvert = null; self::$os = null; } } ?> PK!lVV%ezc/Base/exceptions/setting_value.phpnu[ PK!HDfPEE&ezc/Base/exceptions/file_not_found.phpnu[ PK!Ū!ezc/Base/exceptions/exception.phpnu[originalMessage = $message; if ( php_sapi_name() == 'cli' ) { parent::__construct( $message ); } else { parent::__construct( htmlspecialchars( $message ) ); } } } ?> PK!@c*ezc/Base/exceptions/property_not_found.phpnu[ PK!u3 ezc/Base/exceptions/whatever.phpnu[ PK!b993ezc/Base/exceptions/functionality_not_supported.phpnu[ PK!ll.ezc/Base/exceptions/invalid_callback_class.phpnu[ PK!!ezc/Base/exceptions/file_io.phpnu[ PK!ӥ'ezc/Base/exceptions/file_permission.phpnu[ PK!²Giezc/Base/exceptions/value.phpnu[ PK!R~11+ezc/Base/exceptions/extension_not_found.phpnu[ PK!Ն((&ezc/Base/exceptions/file_exception.phpnu[ PK!aa+ezc/Base/exceptions/property_permission.phpnu[ PK!^M@@,ezc/Base/exceptions/invalid_parent_class.phpnu[ PK!{QQ6ezc/Base/exceptions/double_class_repository_prefix.phpnu[ PK!0ezc/Base/exceptions/init_callback_configured.phpnu[ PK!rr ezc/Base/exceptions/autoload.phpnu[autoloadPath ); } parent::__construct( "Could not find a class to file mapping for '{$className}'. Searched for ". implode( ', ', $files ) . " in: " . implode( ', ', $paths ) ); } } ?> PK!םOO)ezc/Base/exceptions/setting_not_found.phpnu[ PK!UJXezc/Base/options.phpnu[mixed) */ protected $properties; /** * Construct a new options object. * Options are constructed from an option array by default. The constructor * automatically passes the given options to the __set() method to set them * in the class. * * @throws ezcBasePropertyNotFoundException * If trying to access a non existent property. * @throws ezcBaseValueException * If the value for a property is out of range. * @param array(string=>mixed) $options The initial options to set. */ public function __construct( array $options = array() ) { foreach ( $options as $option => $value ) { $this->__set( $option, $value ); } } /** * Merge an array into the actual options object. * This method merges an array of new options into the actual options object. * * @throws ezcBasePropertyNotFoundException * If trying to access a non existent property. * @throws ezcBaseValueException * If the value for a property is out of range. * @param array(string=>mixed) $newOptions The new options. */ public function merge( array $newOptions ) { foreach ( $newOptions as $key => $value ) { $this->__set( $key, $value ); } } /** * Property get access. * Simply returns a given option. * * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @param string $propertyName The name of the option to get. * @return mixed The option value. * @ignore * * @throws ezcBasePropertyNotFoundException * if the given property does not exist. * @throws ezcBasePropertyPermissionException * if the property to be set is a write-only property. */ public function __get( $propertyName ) { if ( $this->__isset( $propertyName ) === true ) { return $this->properties[$propertyName]; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Sets an option. * This method is called when an option is set. * * @param string $propertyName The name of the option to set. * @param mixed $propertyValue The option value. * @ignore * * @throws ezcBasePropertyNotFoundException * if the given property does not exist. * @throws ezcBaseValueException * if the value to be assigned to a property is invalid. * @throws ezcBasePropertyPermissionException * if the property to be set is a read-only property. */ abstract public function __set( $propertyName, $propertyValue ); /** * Returns if a option exists. * * @param string $propertyName Option name to check for. * @return bool Whether the option exists. * @ignore */ public function __isset( $propertyName ) { return array_key_exists( $propertyName, $this->properties ); } /** * Returns if an option exists. * Allows isset() using ArrayAccess. * * @param string $propertyName The name of the option to get. * @return bool Whether the option exists. */ public function offsetExists( $propertyName ) { return $this->__isset( $propertyName ); } /** * Returns an option value. * Get an option value by ArrayAccess. * * @throws ezcBasePropertyNotFoundException * If $propertyName is not a key in the $properties array. * @param string $propertyName The name of the option to get. * @return mixed The option value. */ public function offsetGet( $propertyName ) { return $this->__get( $propertyName ); } /** * Set an option. * Sets an option using ArrayAccess. * * @throws ezcBasePropertyNotFoundException * If $propertyName is not a key in the $properties array. * @throws ezcBaseValueException * If the value for a property is out of range. * @param string $propertyName The name of the option to set. * @param mixed $propertyValue The value for the option. */ public function offsetSet( $propertyName, $propertyValue ) { $this->__set( $propertyName, $propertyValue ); } /** * Unset an option. * Unsets an option using ArrayAccess. * * @throws ezcBasePropertyNotFoundException * If $propertyName is not a key in the $properties array. * @throws ezcBaseValueException * If a the value for a property is out of range. * @param string $propertyName The name of the option to unset. */ public function offsetUnset( $propertyName ) { $this->__set( $propertyName, null ); } } ?> PK!4QEQEezc/Base/file.phpnu[ * * * * @package Base * @version 1.8 * @mainclass */ class ezcBaseFile { /** * This is the callback used by findRecursive to collect data. * * This callback method works together with walkRecursive() and is called * for every file/and or directory. The $context is a callback specific * container in which data can be stored and shared between the different * calls to the callback function. The walkRecursive() function also passes * in the full absolute directory in $sourceDir, the filename in $fileName * and file information (such as size, modes, types) as an array as * returned by PHP's stat() in the $fileInfo parameter. * * @param ezcBaseFileFindContext $context * @param string $sourceDir * @param string $fileName * @param array(stat) $fileInfo */ static protected function findRecursiveCallback( ezcBaseFileFindContext $context, $sourceDir, $fileName, $fileInfo ) { // ignore if we have a directory if ( $fileInfo['mode'] & 0x4000 ) { return; } // update the statistics $context->elements[] = $sourceDir . DIRECTORY_SEPARATOR . $fileName; $context->count++; $context->size += $fileInfo['size']; } /** * Walks files and directories recursively on a file system * * This method walks over a directory and calls a callback from every file * and directory it finds. You can use $includeFilters to include only * specific files, and $excludeFilters to exclude certain files from being * returned. The function will always go into subdirectories even if the * entry would not have passed the filters. * * The callback is passed in the $callback parameter, and the * $callbackContext will be send to the callback function/method as * parameter so that you can store data in there that persists with all the * calls and recursive calls to this method. It's up to the callback method * to do something useful with this. The callback function's parameters are * in order: * *
    *
  • ezcBaseFileFindContext $context
  • *
  • string $sourceDir
  • *
  • string $fileName
  • *
  • array(stat) $fileInfo
  • *
* * See {@see findRecursiveCallback()} for an example of a callback function. * * Filters are regular expressions and are therefore required to have * starting and ending delimiters. The Perl Compatible syntax is used as * regular expression language. * * @param string $sourceDir * @param array(string) $includeFilters * @param array(string) $excludeFilters * @param callback $callback * @param mixed $callbackContext * * @throws ezcBaseFileNotFoundException if the $sourceDir directory is not * a directory or does not exist. * @throws ezcBaseFilePermissionException if the $sourceDir directory could * not be opened for reading. * @return array */ static public function walkRecursive( $sourceDir, array $includeFilters = array(), array $excludeFilters = array(), $callback, &$callbackContext ) { if ( !is_dir( $sourceDir ) ) { throw new ezcBaseFileNotFoundException( $sourceDir, 'directory' ); } $elements = array(); $d = @dir( $sourceDir ); if ( !$d ) { throw new ezcBaseFilePermissionException( $sourceDir, ezcBaseFileException::READ ); } while ( ( $entry = $d->read() ) !== false ) { if ( $entry == '.' || $entry == '..' ) { continue; } $fileInfo = @stat( $sourceDir . DIRECTORY_SEPARATOR . $entry ); if ( !$fileInfo ) { $fileInfo = array( 'size' => 0, 'mode' => 0 ); } if ( $fileInfo['mode'] & 0x4000 ) { // We need to ignore the Permission exceptions here as it can // be normal that a directory can not be accessed. We only need // the exception if the top directory could not be read. try { call_user_func_array( $callback, array( $callbackContext, $sourceDir, $entry, $fileInfo ) ); $subList = self::walkRecursive( $sourceDir . DIRECTORY_SEPARATOR . $entry, $includeFilters, $excludeFilters, $callback, $callbackContext ); $elements = array_merge( $elements, $subList ); } catch ( ezcBaseFilePermissionException $e ) { } } else { // By default a file is included in the return list $ok = true; // Iterate over the $includeFilters and prohibit the file from // being returned when atleast one of them does not match foreach ( $includeFilters as $filter ) { if ( !preg_match( $filter, $sourceDir . DIRECTORY_SEPARATOR . $entry ) ) { $ok = false; break; } } // Iterate over the $excludeFilters and prohibit the file from // being returns when atleast one of them matches foreach ( $excludeFilters as $filter ) { if ( preg_match( $filter, $sourceDir . DIRECTORY_SEPARATOR . $entry ) ) { $ok = false; break; } } // If everything's allright, call the callback and add the // entry to the elements array if ( $ok ) { call_user_func( $callback, $callbackContext, $sourceDir, $entry, $fileInfo ); $elements[] = $sourceDir . DIRECTORY_SEPARATOR . $entry; } } } sort( $elements ); return $elements; } /** * Finds files recursively on a file system * * With this method you can scan the file system for files. You can use * $includeFilters to include only specific files, and $excludeFilters to * exclude certain files from being returned. The function will always go * into subdirectories even if the entry would not have passed the filters. * It uses the {@see walkRecursive()} method to do the actually recursion. * * Filters are regular expressions and are therefore required to have * starting and ending delimiters. The Perl Compatible syntax is used as * regular expression language. * * If you pass an empty array to the $statistics argument, the function * will in details about the number of files found into the 'count' array * element, and the total filesize in the 'size' array element. Because this * argument is passed by reference, you *have* to pass a variable and you * can not pass a constant value such as "array()". * * @param string $sourceDir * @param array(string) $includeFilters * @param array(string) $excludeFilters * @param array() $statistics * * @throws ezcBaseFileNotFoundException if the $sourceDir directory is not * a directory or does not exist. * @throws ezcBaseFilePermissionException if the $sourceDir directory could * not be opened for reading. * @return array */ static public function findRecursive( $sourceDir, array $includeFilters = array(), array $excludeFilters = array(), &$statistics = null ) { // init statistics array if ( !is_array( $statistics ) || !array_key_exists( 'size', $statistics ) || !array_key_exists( 'count', $statistics ) ) { $statistics['size'] = 0; $statistics['count'] = 0; } // create the context, and then start walking over the array $context = new ezcBaseFileFindContext; self::walkRecursive( $sourceDir, $includeFilters, $excludeFilters, array( 'ezcBaseFile', 'findRecursiveCallback' ), $context ); // collect the statistics $statistics['size'] = $context->size; $statistics['count'] = $context->count; // return the found and pattern-matched files sort( $context->elements ); return $context->elements; } /** * Removes files and directories recursively from a file system * * This method recursively removes the $directory and all its contents. * You should be extremely careful with this method as it has the * potential to erase everything that the current user has access to. * * @param string $directory */ static public function removeRecursive( $directory ) { $sourceDir = realpath( $directory ); if ( !$sourceDir ) { throw new ezcBaseFileNotFoundException( $directory, 'directory' ); } $d = @dir( $sourceDir ); if ( !$d ) { throw new ezcBaseFilePermissionException( $directory, ezcBaseFileException::READ ); } // check if we can remove the dir $parentDir = realpath( $directory . DIRECTORY_SEPARATOR . '..' ); if ( !is_writable( $parentDir ) ) { throw new ezcBaseFilePermissionException( $parentDir, ezcBaseFileException::WRITE ); } // loop over contents while ( ( $entry = $d->read() ) !== false ) { if ( $entry == '.' || $entry == '..' ) { continue; } if ( is_dir( $sourceDir . DIRECTORY_SEPARATOR . $entry ) ) { self::removeRecursive( $sourceDir . DIRECTORY_SEPARATOR . $entry ); } else { if ( @unlink( $sourceDir . DIRECTORY_SEPARATOR . $entry ) === false ) { throw new ezcBaseFilePermissionException( $directory . DIRECTORY_SEPARATOR . $entry, ezcBaseFileException::REMOVE ); } } } $d->close(); rmdir( $sourceDir ); } /** * Recursively copy a file or directory. * * Recursively copy a file or directory in $source to the given * destination. If a depth is given, the operation will stop, if the given * recursion depth is reached. A depth of -1 means no limit, while a depth * of 0 means, that only the current file or directory will be copied, * without any recursion. * * You may optionally define modes used to create files and directories. * * @throws ezcBaseFileNotFoundException * If the $sourceDir directory is not a directory or does not exist. * @throws ezcBaseFilePermissionException * If the $sourceDir directory could not be opened for reading, or the * destination is not writeable. * * @param string $source * @param string $destination * @param int $depth * @param int $dirMode * @param int $fileMode * @return void */ static public function copyRecursive( $source, $destination, $depth = -1, $dirMode = 0775, $fileMode = 0664 ) { // Check if source file exists at all. if ( !is_file( $source ) && !is_dir( $source ) ) { throw new ezcBaseFileNotFoundException( $source ); } // Destination file should NOT exist if ( is_file( $destination ) || is_dir( $destination ) ) { throw new ezcBaseFilePermissionException( $destination, ezcBaseFileException::WRITE ); } // Skip non readable files in source directory if ( !is_readable( $source ) ) { return; } // Copy if ( is_dir( $source ) ) { mkdir( $destination ); // To ignore umask, umask() should not be changed with // multithreaded servers... chmod( $destination, $dirMode ); } elseif ( is_file( $source ) ) { copy( $source, $destination ); chmod( $destination, $fileMode ); } if ( ( $depth === 0 ) || ( !is_dir( $source ) ) ) { // Do not recurse (any more) return; } // Recurse $dh = opendir( $source ); while ( ( $file = readdir( $dh ) ) !== false ) { if ( ( $file === '.' ) || ( $file === '..' ) ) { continue; } self::copyRecursive( $source . '/' . $file, $destination . '/' . $file, $depth - 1, $dirMode, $fileMode ); } } /** * Calculates the relative path of the file/directory '$path' to a given * $base path. * * $path and $base should be fully absolute paths. This function returns the * answer of "How do I go from $base to $path". If the $path and $base are * the same path, the function returns '.'. This method does not touch the * filesystem. * * @param string $path * @param string $base * @return string */ static public function calculateRelativePath( $path, $base ) { // Sanitize the paths to use the correct directory separator for the platform $path = strtr( $path, '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR ); $base = strtr( $base, '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR ); $base = explode( DIRECTORY_SEPARATOR, $base ); $path = explode( DIRECTORY_SEPARATOR, $path ); // If the paths are the same we return if ( $base === $path ) { return '.'; } $result = ''; $pathPart = array_shift( $path ); $basePart = array_shift( $base ); while ( $pathPart == $basePart ) { $pathPart = array_shift( $path ); $basePart = array_shift( $base ); } if ( $pathPart != null ) { array_unshift( $path, $pathPart ); } if ( $basePart != null ) { array_unshift( $base, $basePart ); } $result = str_repeat( '..' . DIRECTORY_SEPARATOR, count( $base ) ); // prevent a trailing DIRECTORY_SEPARATOR in case there is only a .. if ( count( $path ) == 0 ) { $result = substr( $result, 0, -strlen( DIRECTORY_SEPARATOR ) ); } $result .= join( DIRECTORY_SEPARATOR, $path ); return $result; } /** * Returns whether the passed $path is an absolute path, giving the current $os. * * With the $os parameter you can tell this function to use the semantics * for a different operating system to determine whether a path is * absolute. The $os argument defaults to the OS that the script is running * on. * * @param string $path * @param string $os * @return bool */ public static function isAbsolutePath( $path, $os = null ) { if ( $os === null ) { $os = ezcBaseFeatures::os(); } // Stream wrapper like phar can also be considered absolute paths if ( preg_match( '(^[a-z]{3,}://)S', $path ) ) { return true; } switch ( $os ) { case 'Windows': // Sanitize the paths to use the correct directory separator for the platform $path = strtr( $path, '\\/', '\\\\' ); // Absolute paths with drive letter: X:\ if ( preg_match( '@^[A-Z]:\\\\@i', $path ) ) { return true; } // Absolute paths with network paths: \\server\share\ if ( preg_match( '@^\\\\\\\\[A-Z]+\\\\[^\\\\]@i', $path ) ) { return true; } break; case 'Mac': case 'Linux': case 'FreeBSD': default: // Sanitize the paths to use the correct directory separator for the platform $path = strtr( $path, '\\/', '//' ); if ( $path[0] == '/' ) { return true; } } return false; } } ?> PK!S]KKezc/Base/init.phpnu[ * * * * You will also need to configure which callback class to call. This you do * with the ezcBaseInit::setCallback() method. The following examples sets the * callback classname for the configuration identifier * 'ezcInitConfigurationManager' to 'cfgConfigurationManager': * * * * * * The class 'cfgConfigurationManager' is required to implement the * ezcBaseConfigurationInitializer interface, which defines only one method: * configureObject(). An example on how to implement such a class could be: * * * init( 'ezcConfigurationIniReader', 'settings', array( 'useComments' => true ) ); * } * } * ?> * * * Of course the implementation of this callback class is up to the application * developer that uses the component (in this example the Configuration * component's class ezcConfigurationManager). * * @package Base * @version 1.8 */ class ezcBaseInit { /** * Contains the callback where the identifier is the key of the array, and the classname to callback to the value. * * @var array(string=>string) */ static private $callbackMap = array(); /** * Adds the classname $callbackClassname as callback for the identifier $identifier. * * @param string $identifier * @param string $callbackClassname */ public static function setCallback( $identifier, $callbackClassname ) { if ( array_key_exists( $identifier, self::$callbackMap ) ) { throw new ezcBaseInitCallbackConfiguredException( $identifier, self::$callbackMap[$identifier] ); } else { // Check if the passed classname actually exists if ( !ezcBaseFeatures::classExists( $callbackClassname, true ) ) { throw new ezcBaseInitInvalidCallbackClassException( $callbackClassname ); } // Check if the passed classname actually implements the interface. if ( !in_array( 'ezcBaseConfigurationInitializer', class_implements( $callbackClassname ) ) ) { throw new ezcBaseInitInvalidCallbackClassException( $callbackClassname ); } self::$callbackMap[$identifier] = $callbackClassname; } } /** * Uses the configured callback belonging to $identifier to configure the $object. * * The method will return the return value of the callback method, or null * in case there was no callback set for the specified $identifier. * * @param string $identifier * @param object $object * @return mixed */ public static function fetchConfig( $identifier, $object ) { if ( isset( self::$callbackMap[$identifier] ) ) { $callbackClassname = self::$callbackMap[$identifier]; return call_user_func( array( $callbackClassname, 'configureObject' ), $object ); } return null; } } ?> PK!/#ezc/Base/interfaces/persistable.phpnu[mixed) */ public function getState(); /** * Accepts an array containing data for one or more of the class' properties. * * @param array $properties */ public function setState( array $properties ); } ?> PK!4ei"ezc/Base/interfaces/exportable.phpnu[ PK!PBs|1ezc/Base/interfaces/configuration_initializer.phpnu[ PK!%N N ezc/Base/base_autoload.phpnu[ 'Base/exceptions/exception.php', 'ezcBaseFileException' => 'Base/exceptions/file_exception.php', 'ezcBaseAutoloadException' => 'Base/exceptions/autoload.php', 'ezcBaseDoubleClassRepositoryPrefixException' => 'Base/exceptions/double_class_repository_prefix.php', 'ezcBaseExtensionNotFoundException' => 'Base/exceptions/extension_not_found.php', 'ezcBaseFileIoException' => 'Base/exceptions/file_io.php', 'ezcBaseFileNotFoundException' => 'Base/exceptions/file_not_found.php', 'ezcBaseFilePermissionException' => 'Base/exceptions/file_permission.php', 'ezcBaseFunctionalityNotSupportedException' => 'Base/exceptions/functionality_not_supported.php', 'ezcBaseInitCallbackConfiguredException' => 'Base/exceptions/init_callback_configured.php', 'ezcBaseInitInvalidCallbackClassException' => 'Base/exceptions/invalid_callback_class.php', 'ezcBaseInvalidParentClassException' => 'Base/exceptions/invalid_parent_class.php', 'ezcBasePropertyNotFoundException' => 'Base/exceptions/property_not_found.php', 'ezcBasePropertyPermissionException' => 'Base/exceptions/property_permission.php', 'ezcBaseSettingNotFoundException' => 'Base/exceptions/setting_not_found.php', 'ezcBaseSettingValueException' => 'Base/exceptions/setting_value.php', 'ezcBaseValueException' => 'Base/exceptions/value.php', 'ezcBaseWhateverException' => 'Base/exceptions/whatever.php', 'ezcBaseOptions' => 'Base/options.php', 'ezcBaseStruct' => 'Base/struct.php', 'ezcBase' => 'Base/base.php', 'ezcBaseAutoloadOptions' => 'Base/options/autoload.php', 'ezcBaseConfigurationInitializer' => 'Base/interfaces/configuration_initializer.php', 'ezcBaseExportable' => 'Base/interfaces/exportable.php', 'ezcBaseFeatures' => 'Base/features.php', 'ezcBaseFile' => 'Base/file.php', 'ezcBaseFileFindContext' => 'Base/structs/file_find_context.php', 'ezcBaseInit' => 'Base/init.php', 'ezcBaseMetaData' => 'Base/metadata.php', 'ezcBaseMetaDataPearReader' => 'Base/metadata/pear.php', 'ezcBaseMetaDataTarballReader' => 'Base/metadata/tarball.php', 'ezcBasePersistable' => 'Base/interfaces/persistable.php', 'ezcBaseRepositoryDirectory' => 'Base/structs/repository_directory.php', ); ?> PK!xr44ezc/Base/struct.phpnu[ PK!array) */ protected static $repositoryDirs = array(); /** * This variable stores all the elements from the autoload arrays. When a * new autoload file is loaded, their files are added to this array. * * @var array(string=>string) */ protected static $autoloadArray = array(); /** * This variable stores all the elements from the autoload arrays for * external repositories. When a new autoload file is loaded, their files * are added to this array. * * @var array(string=>string) */ protected static $externalAutoloadArray = array(); /** * Options for the ezcBase class. * * @var ezcBaseOptions */ static private $options; /** * Associates an option object with this static class. * * @param ezcBaseAutoloadOptions $options */ static public function setOptions( ezcBaseAutoloadOptions $options ) { self::$options = $options; } /** * Tries to autoload the given className. If the className could be found * this method returns true, otherwise false. * * This class caches the requested class names (including the ones who * failed to load). * * @param string $className The name of the class that should be loaded. * * @return bool */ public static function autoload( $className ) { ezcBase::setPackageDir(); // Check whether the classname is already in the cached autoloadArray. if ( array_key_exists( $className, ezcBase::$autoloadArray ) ) { // Is it registered as 'unloadable'? if ( ezcBase::$autoloadArray[$className] == false ) { return false; } ezcBase::loadFile( ezcBase::$autoloadArray[$className] ); return true; } // Check whether the classname is already in the cached autoloadArray // for external repositories. if ( array_key_exists( $className, ezcBase::$externalAutoloadArray ) ) { // Is it registered as 'unloadable'? if ( ezcBase::$externalAutoloadArray[$className] == false ) { return false; } ezcBase::loadExternalFile( ezcBase::$externalAutoloadArray[$className] ); return true; } // Not cached, so load the autoload from the package. // Matches the first and optionally the second 'word' from the classname. $fileNames = array(); if ( preg_match( "/^([a-z0-9]*)([A-Z][a-z0-9]*)?([A-Z][a-z0-9]*)?/", $className, $matches ) !== false ) { $autoloadFile = ""; // Try to match with both names, if available. switch ( sizeof( $matches ) ) { case 4: // check for x_y_autoload.php $autoloadFile = strtolower( "{$matches[2]}_{$matches[3]}_autoload.php" ); $fileNames[] = $autoloadFile; if ( ezcBase::requireFile( $autoloadFile, $className, $matches[1] ) ) { return true; } // break intentionally missing. case 3: // check for x_autoload.php $autoloadFile = strtolower( "{$matches[2]}_autoload.php" ); $fileNames[] = $autoloadFile; if ( ezcBase::requireFile( $autoloadFile, $className, $matches[1] ) ) { return true; } // break intentionally missing. case 2: // check for autoload.php $autoloadFile = 'autoload.php'; $fileNames[] = $autoloadFile; if ( ezcBase::requireFile( $autoloadFile, $className, $matches[1] ) ) { return true; } break; } // Maybe there is another autoload available. // Register this classname as false. ezcBase::$autoloadArray[$className] = false; } $path = ezcBase::$packageDir . 'autoload/'; $realPath = realpath( $path ); if ( $realPath == '' ) { // Can not be tested, because if this happens, then the autoload // environment has not been set-up correctly. trigger_error( "Couldn't find autoload directory '$path'", E_USER_ERROR ); } $dirs = self::getRepositoryDirectories(); if ( ezcBase::$options && ezcBase::$options->debug ) { throw new ezcBaseAutoloadException( $className, $fileNames, $dirs ); } return false; } /** * Sets the current working directory to $directory. * * @param string $directory */ public static function setWorkingDirectory( $directory ) { self::$libraryMode = 'custom'; self::$currentWorkingDirectory = $directory; } /** * Figures out the base path of the eZ Components installation. * * It stores the path that it finds in a static member variable. The path * depends on the installation method of the eZ Components. The SVN version * has a different path than the PEAR installed version. */ protected static function setPackageDir() { if ( ezcBase::$packageDir !== null ) { return; } // Get the path to the components. $baseDir = dirname( __FILE__ ); switch ( ezcBase::$libraryMode ) { case "custom": ezcBase::$packageDir = self::$currentWorkingDirectory . '/'; break; case "devel": case "tarball": ezcBase::$packageDir = $baseDir. "/../../"; break; case "pear"; ezcBase::$packageDir = $baseDir. "/../"; break; } } /** * Tries to load the autoload array and, if loaded correctly, includes the class. * * @param string $fileName Name of the autoload file. * @param string $className Name of the class that should be autoloaded. * @param string $prefix The prefix of the class repository. * * @return bool True is returned when the file is correctly loaded. * Otherwise false is returned. */ protected static function requireFile( $fileName, $className, $prefix ) { $autoloadDir = ezcBase::$packageDir . "autoload/"; // We need the full path to the fileName. The method file_exists() doesn't // automatically check the (php.ini) library paths. Therefore: // file_exists( "ezc/autoload/$fileName" ) doesn't work. if ( $prefix === 'ezc' && file_exists( "$autoloadDir$fileName" ) ) { $array = require( "$autoloadDir$fileName" ); if ( is_array( $array) && array_key_exists( $className, $array ) ) { // Add the array to the cache, and include the requested file. ezcBase::$autoloadArray = array_merge( ezcBase::$autoloadArray, $array ); if ( ezcBase::$options !== null && ezcBase::$options->preload && !preg_match( '/Exception$/', $className ) ) { foreach ( $array as $loadClassName => $file ) { if ( $loadClassName !== 'ezcBase' && !class_exists( $loadClassName, false ) && !interface_exists( $loadClassName, false ) && !preg_match( '/Exception$/', $loadClassName ) /*&& !class_exists( $loadClassName, false ) && !interface_exists( $loadClassName, false )*/ ) { ezcBase::loadFile( ezcBase::$autoloadArray[$loadClassName] ); } } } else { ezcBase::loadFile( ezcBase::$autoloadArray[$className] ); } return true; } } // It is not in components autoload/ dir. // try to search in additional dirs. foreach ( ezcBase::$repositoryDirs as $repositoryPrefix => $extraDir ) { if ( gettype( $repositoryPrefix ) === 'string' && $repositoryPrefix !== $prefix ) { continue; } if ( file_exists( $extraDir['autoloadDirPath'] . '/' . $fileName ) ) { $array = array(); $originalArray = require( $extraDir['autoloadDirPath'] . '/' . $fileName ); // Building paths. // Resulting path to class definition file consists of: // path to extra directory with autoload file + // basePath provided for current extra directory + // path to class definition file stored in autoload file. foreach ( $originalArray as $class => $classPath ) { $array[$class] = $extraDir['basePath'] . '/' . $classPath; } if ( is_array( $array ) && array_key_exists( $className, $array ) ) { // Add the array to the cache, and include the requested file. ezcBase::$externalAutoloadArray = array_merge( ezcBase::$externalAutoloadArray, $array ); ezcBase::loadExternalFile( ezcBase::$externalAutoloadArray[$className] ); return true; } } } // Nothing found :-(. return false; } /** * Loads, require(), the given file name. If we are in development mode, * "/src/" is inserted into the path. * * @param string $file The name of the file that should be loaded. */ protected static function loadFile( $file ) { switch ( ezcBase::$libraryMode ) { case "devel": case "tarball": list( $first, $second ) = explode( '/', $file, 2 ); $file = $first . "/src/" . $second; break; case "custom": list( $first, $second ) = explode( '/', $file, 2 ); // Add the "src/" after the package name. if ( $first == 'Base' || $first == 'UnitTest' ) { list( $first, $second ) = explode( '/', $file, 2 ); $file = $first . "/src/" . $second; } else { list( $first, $second, $third ) = explode( '/', $file, 3 ); $file = $first . '/' . $second . "/src/" . $third; } break; case "pear": /* do nothing, it's already correct */ break; } if ( file_exists( ezcBase::$packageDir . $file ) ) { require( ezcBase::$packageDir . $file ); } else { // Can not be tested, because if this happens, then one of the // components has a broken autoload file. throw new ezcBaseFileNotFoundException( ezcBase::$packageDir.$file ); } } /** * Loads, require(), the given file name from an external package. * * @param string $file The name of the file that should be loaded. */ protected static function loadExternalFile( $file ) { if ( file_exists( $file ) ) { require( $file ); } else { throw new ezcBaseFileNotFoundException( $file ); } } /** * Checks for dependencies on PHP versions or extensions * * The function as called by the $component component checks for the $type * dependency. The dependency $type is compared against the $value. The * function aborts the script if the dependency is not matched. * * @param string $component * @param int $type * @param mixed $value */ public static function checkDependency( $component, $type, $value ) { switch ( $type ) { case self::DEP_PHP_EXTENSION: if ( extension_loaded( $value ) ) { return; } else { // Can not be tested as it would abort the PHP script. die( "\nThe {$component} component depends on the default PHP extension '{$value}', which is not loaded.\n" ); } break; case self::DEP_PHP_VERSION: $phpVersion = phpversion(); if ( version_compare( $phpVersion, $value, '>=' ) ) { return; } else { // Can not be tested as it would abort the PHP script. die( "\nThe {$component} component depends on the PHP version '{$value}', but the current version is '{$phpVersion}'.\n" ); } break; } } /** * Return the list of directories that contain class repositories. * * The path to the eZ components directory is always included in the result * array. Each element in the returned array has the format of: * packageDirectory => ezcBaseRepositoryDirectory * * @return array(string=>ezcBaseRepositoryDirectory) */ public static function getRepositoryDirectories() { $autoloadDirs = array(); ezcBase::setPackageDir(); $repositoryDir = self::$currentWorkingDirectory ? self::$currentWorkingDirectory : ( realpath( dirname( __FILE__ ) . '/../../' ) ); $autoloadDirs['ezc'] = new ezcBaseRepositoryDirectory( ezcBaseRepositoryDirectory::TYPE_INTERNAL, $repositoryDir, $repositoryDir . "/autoload" ); foreach ( ezcBase::$repositoryDirs as $extraDirKey => $extraDirArray ) { $repositoryDirectory = new ezcBaseRepositoryDirectory( ezcBaseRepositoryDirectory::TYPE_EXTERNAL, realpath( $extraDirArray['basePath'] ), realpath( $extraDirArray['autoloadDirPath'] ) ); $autoloadDirs[$extraDirKey] = $repositoryDirectory; } return $autoloadDirs; } /** * Adds an additional class repository. * * Used for adding class repositoryies outside the eZ components to be * loaded by the autoload system. * * This function takes two arguments: $basePath is the base path for the * whole class repository and $autoloadDirPath the path where autoload * files for this repository are found. The paths in the autoload files are * relative to the package directory as specified by the $basePath * argument. I.e. class definition file will be searched at location * $basePath + path to the class definition file as stored in the autoload * file. * * addClassRepository() should be called somewhere in code before external classes * are used. * * Example: * Take the following facts: *
    *
  • there is a class repository stored in the directory "./repos"
  • *
  • autoload files for that repository are stored in "./repos/autoloads"
  • *
  • there are two components in this repository: "Me" and "You"
  • *
  • the "Me" component has the classes "erMyClass1" and "erMyClass2"
  • *
  • the "You" component has the classes "erYourClass1" and "erYourClass2"
  • *
* * In this case you would need to create the following files in * "./repos/autoloads". Please note that the part before _autoload.php in * the filename is the first part of the classname, not considering * the all lower-case letter prefix. * * "my_autoload.php": * * 'Me/myclass1.php', * 'erMyClass2' => 'Me/myclass2.php', * ); * ?> * * * "your_autoload.php": * * 'You/yourclass1.php', * 'erYourClass2' => 'You/yourclass2.php', * ); * ?> * * * The directory structure for the external repository is then: * * ./repos/autoloads/my_autoload.php * ./repos/autoloads/you_autoload.php * ./repos/Me/myclass1.php * ./repos/Me/myclass2.php * ./repos/You/yourclass1.php * ./repos/You/yourclass2.php * * * To use this repository with the autoload mechanism you have to use the * following code: * * * * * @throws ezcBaseFileNotFoundException if $autoloadDirPath or $basePath do not exist. * @param string $basePath * @param string $autoloadDirPath * @param string $prefix */ public static function addClassRepository( $basePath, $autoloadDirPath = null, $prefix = null ) { // check if base path exists if ( !is_dir( $basePath ) ) { throw new ezcBaseFileNotFoundException( $basePath, 'base directory' ); } // calculate autoload path if it wasn't given if ( is_null( $autoloadDirPath ) ) { $autoloadDirPath = $basePath . '/autoload'; } // check if autoload dir exists if ( !is_dir( $autoloadDirPath ) ) { throw new ezcBaseFileNotFoundException( $autoloadDirPath, 'autoload directory' ); } // add info to $repositoryDirs if ( $prefix === null ) { $array = array( 'basePath' => $basePath, 'autoloadDirPath' => $autoloadDirPath ); // add info to the list of extra dirs ezcBase::$repositoryDirs[] = $array; } else { if ( array_key_exists( $prefix, ezcBase::$repositoryDirs ) ) { throw new ezcBaseDoubleClassRepositoryPrefixException( $prefix, $basePath, $autoloadDirPath ); } // add info to the list of extra dirs, and use the prefix to identify the new repository. ezcBase::$repositoryDirs[$prefix] = array( 'basePath' => $basePath, 'autoloadDirPath' => $autoloadDirPath ); } } /** * Returns the base path of the eZ Components installation * * This method returns the base path, including a trailing directory * separator. * * @return string */ public static function getInstallationPath() { self::setPackageDir(); $path = realpath( self::$packageDir ); if ( substr( $path, -1 ) !== DIRECTORY_SEPARATOR ) { $path .= DIRECTORY_SEPARATOR; } return $path; } /** * Sets the development mode to the one specified. * * @param int $runMode */ public static function setRunMode( $runMode ) { if ( !in_array( $runMode, array( ezcBase::MODE_PRODUCTION, ezcBase::MODE_DEVELOPMENT ) ) ) { throw new ezcBaseValueException( 'runMode', $runMode, 'ezcBase::MODE_PRODUCTION or ezcBase::MODE_DEVELOPMENT' ); } self::$runMode = $runMode; } /** * Returns the current development mode. * * @return int */ public static function getRunMode() { return self::$runMode; } /** * Returns true when we are in development mode. * * @return bool */ public static function inDevMode() { return self::$runMode == ezcBase::MODE_DEVELOPMENT; } /** * Returns the installation method * * Possible return values are 'custom', 'devel', 'tarball' and 'pear'. Only * 'tarball' and 'pear' are returned for user-installed versions. * * @return string */ public static function getInstallMethod() { return self::$libraryMode; } } ?> PK!B!)s,s,ezc/ConsoleTools/table/row.phpnu[ * // Create new table row * $row = new ezcConsoleTableRow(); * * // Set default format of the row's cells * $row->format = 'headline'; * * // On the fly create the cell no 0 * $row[0]->content = 'Name'; * // On the fly create the cell no 1 * $row[1]->content = 'Cellphone'; * * // Change a setting on cell 0 * $row[0]->align = ezcConsoleTable::ALIGN_CENTER; * * // Iterate through the row's cells. * foreach ( $row as $cell ) * { * var_dump( $cell ); * } * * // Set the default align property for all cells in the row * $row->align = ezcConsoleTable::ALIGN_CENTER; * * * * This class stores the rows for the {@link ezcConsoleTable} class. * * @property string $borderFormat * Set the format applied to the borders of this row. See * {@link ezcConsoleOutput} * @property string $format * Format applied to cell contents of cells marked with * format "default" in this row. * @property mixed $align * Alignment applied to cells marked with * ezcConsoleTable::ALIGN_DEFAULT. * * @package ConsoleTools * @version 1.6.1 */ class ezcConsoleTableRow implements Countable, Iterator, ArrayAccess { /** * Container to hold the properties * * @var array(string=>mixed) */ protected $properties; /** * The cells of the row. * * @var array(ezcConsoleTableCell) */ protected $cells = array(); /** * Create a new ezcConsoleProgressbarRow. * Creates a new ezcConsoleProgressbarRow. * * This method takes any number of {@link ezcConsoleTableCell} objects as * parameter, which will be added as table cells to the row in their * specified order. * * @throws ezcBaseValueException * If a parameter is not of type {@link ezcConsoleTableCell}. */ public function __construct() { $this->properties['borderFormat'] = 'default'; $this->properties['format'] = 'default'; $this->properties['align'] = ezcConsoleTable::ALIGN_DEFAULT; if ( func_num_args() > 0 ) { foreach ( func_get_args() as $id => $arg ) { if ( !( $arg instanceof ezcConsoleTableCell ) ) { throw new ezcBaseValueException( 'Parameter'.$id, $arg, 'ezcConsoleTableCell' ); } $this->cells[] = $arg; } } } /** * Returns if the given offset exists. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. * * @param int $offset The offset to check. * @return bool True when the offset exists, otherwise false. * * @throws ezcBaseValueException * If a non numeric cell ID is requested. */ public function offsetExists( $offset ) { if ( !is_int( $offset ) || $offset < 0 ) { throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' ); } return isset( $this->cells[$offset] ); } /** * Returns the element with the given offset. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. In case of the * ezcConsoleTableRow class this method always returns a valid cell object * since it creates them on the fly, if a given item does not exist. * * @param int $offset The offset to check. * @return ezcConsoleTableCell * * @throws ezcBaseValueException * If a non numeric cell ID is requested. */ public function offsetGet( $offset ) { if ( !isset( $offset ) ) { $offset = count( $this ); $this->cells[$offset] = new ezcConsoleTableCell(); } if ( !is_int( $offset ) || $offset < 0 ) { throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' ); } if ( !isset( $this->cells[$offset] ) ) { $this->cells[$offset] = new ezcConsoleTableCell(); } return $this->cells[$offset]; } /** * Set the element with the given offset. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. * * @param int $offset The offset to assign an item to. * @param ezcConsoleTableCell $value The cell to assign. * @return void * * @throws ezcBaseValueException * If a non numeric cell ID is requested. * @throws ezcBaseValueException * If the provided value is not of type {@ling ezcConsoleTableCell}. */ public function offsetSet( $offset, $value ) { if ( !( $value instanceof ezcConsoleTableCell ) ) { throw new ezcBaseValueException( 'value', $value, 'ezcConsoleTableCell' ); } if ( !isset( $offset ) ) { $offset = count( $this ); } if ( !is_int( $offset ) || $offset < 0 ) { throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' ); } $this->cells[$offset] = $value; } /** * Unset the element with the given offset. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. * * @param int $offset The offset to unset the value for. * @return void * * @throws ezcBaseValueException * If a non numeric cell ID is requested. */ public function offsetUnset( $offset ) { if ( !is_int( $offset ) || $offset < 0 ) { throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' ); } if ( isset( $this->cells[$offset] ) ) { unset( $this->cells[$offset] ); } } /** * Returns the number of cells in the row. * This method is part of the Countable interface to allow the usage of * PHP's count() function to check how many cells this row has. * * @return int Number of cells in this row. */ public function count() { $keys = array_keys( $this->cells ); return count( $keys ) > 0 ? ( end( $keys ) + 1 ) : 0; } /** * Returns the currently selected cell. * This method is part of the Iterator interface to allow acces to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return ezcConsoleTableCell The currently selected cell. */ public function current() { return current( $this->cells ); } /** * Returns the key of the currently selected cell. * This method is part of the Iterator interface to allow acces to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return int The key of the currently selected cell. */ public function key() { return key( $this->cells ); } /** * Returns the next cell and selects it or false on the last cell. * This method is part of the Iterator interface to allow acces to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return mixed ezcConsoleTableCell if the next cell exists, or false. */ public function next() { return next( $this->cells ); } /** * Selects the very first cell and returns it. * This method is part of the Iterator interface to allow acces to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return ezcConsoleTableCell The very first cell of this row. */ public function rewind() { return reset( $this->cells ); } /** * Returns if the current cell is valid. * This method is part of the Iterator interface to allow acces to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return ezcConsoleTableCell The very first cell of this row. */ public function valid() { return current( $this->cells ) !== false; } /** * Property read access. * * @param string $key Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __get( $key ) { if ( isset( $this->properties[$key] ) ) { return $this->properties[$key]; } throw new ezcBasePropertyNotFoundException( $key ); } /** * Property write access. * * @param string $key Name of the property. * @param mixed $val The value for the property. * * @throws ezcBaseValueException * If a the value submitted for the align is not in the range of * {@link ezcConsoleTable::ALIGN_LEFT}, * {@link ezcConsoleTable::ALIGN_CENTER}, * {@link ezcConsoleTable::ALIGN_RIGHT}, * {@link ezcConsoleTable::ALIGN_DEFAULT} * * @ignore */ public function __set( $key, $val ) { switch ( $key ) { case 'format': case 'borderFormat': if ( is_string( $val ) === false || strlen( $val ) < 1 ) { throw new ezcBaseValueException( $key, $val, "string, length > 0" ); } break; case 'align': if ( $val !== ezcConsoleTable::ALIGN_LEFT && $val !== ezcConsoleTable::ALIGN_CENTER && $val !== ezcConsoleTable::ALIGN_RIGHT && $val !== ezcConsoleTable::ALIGN_DEFAULT ) { throw new ezcBaseValueException( $key, $val, 'ezcConsoleTable::ALIGN_DEFAULT, ezcConsoleTable::ALIGN_LEFT, ezcConsoleTable::ALIGN_CENTER, ezcConsoleTable::ALIGN_RIGHT' ); } break; default: throw new ezcBasePropertyNotFoundException( $key ); } $this->properties[$key] = $val; } /** * Property isset access. * * @param string $key Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $key ) { switch ( $key ) { case 'format': case 'borderFormat': case 'align': return true; default: return false; } } } ?> PK!'rwezc/ConsoleTools/table/cell.phpnu[mixed) */ protected $properties; /** * Create a new ezcConsoleProgressbarCell. * Creates a new ezcConsoleProgressbarCell. You can either submit the cell * data through the constructor or set them as properties. * * @param string $content Content of the cell. * @param string $format Format to display the cell with. * @param mixed $align Alignment of the content in the cell. * @return void */ public function __construct( $content = '', $format = 'default', $align = ezcConsoleTable::ALIGN_DEFAULT ) { $this->__set( 'content', $content ); $this->__set( 'format', $format ); $this->__set( 'align', $align ); } /** * Property read access. * * @param string $key Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __get( $key ) { if ( isset( $this->properties[$key] ) ) { return $this->properties[$key]; } throw new ezcBasePropertyNotFoundException( $key ); } /** * Property write access. * * @param string $key Name of the property. * @param mixed $val The value for the property. * * @throws ezcBaseValueException * If a the value submitted for the align is not in the range of * {@link ezcConsoleTable::ALIGN_LEFT}, * {@link ezcConsoleTable::ALIGN_CENTER}, * {@link ezcConsoleTable::ALIGN_RIGHT}, * {@link ezcConsoleTable::ALIGN_DEFAULT} * * @ignore */ public function __set( $key, $val ) { switch ( $key ) { case 'content': if ( is_string( $val ) === false ) { throw new ezcBaseValueException( $key, $val, "string" ); } break; case 'format': if ( is_string( $val ) === false || strlen( $val ) < 1 ) { throw new ezcBaseValueException( $key, $val, "string, length > 0" ); } break; case 'align': if ( $val !== ezcConsoleTable::ALIGN_LEFT && $val !== ezcConsoleTable::ALIGN_CENTER && $val !== ezcConsoleTable::ALIGN_RIGHT && $val !== ezcConsoleTable::ALIGN_DEFAULT ) { throw new ezcBaseValueException( $key, $val, 'ezcConsoleTable::ALIGN_DEFAULT, ezcConsoleTable::ALIGN_LEFT, ezcConsoleTable::ALIGN_CENTER, ezcConsoleTable::ALIGN_RIGHT' ); } break; default: throw new ezcBasePropertyNotFoundException( $key ); } $this->properties[$key] = $val; return; } /** * Property isset access. * * @param string $key Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $key ) { switch ( $key ) { case 'content': case 'format': case 'align': return true; default: break; } return false; } } ?> PK!\Ѫ77 ezc/ConsoleTools/progressbar.phpnu[ * $out = new ezcConsoleOutput(); * * // Create progress bar itself * $progress = new ezcConsoleProgressbar( $out, 100, array( 'step' => 5 ) ); * * $progress->options->emptyChar = '-'; * $progress->options->progressChar = '#'; * $progress->options->formatString = "Uploading file : %act%/%max% kb [%bar%]"; * * // Perform actions * $i = 0; * while ( $i++ < 20 ) * { * // Do whatever you want to indicate progress for * usleep( mt_rand( 20000, 2000000 ) ); * // Advance the progressbar by one step ( uploading 5k per run ) * $progress->advance(); * } * * // Finish progress bar and jump to next line. * $progress->finish(); * * $out->outputText( "Successfully uploaded .\n", 'success' ); * * * @property ezcConsoleProgressbarOptions $options * Contains the options for this class. * @property int $max * The maximum progress value to reach. * * @package ConsoleTools * @version 1.6.1 * @mainclass */ class ezcConsoleProgressbar { /** * Container to hold the properties * * @var array(string=>mixed) */ protected $properties; /** * Storage for actual values to be replaced in the format string. * Actual values are stored here and will be inserted into the bar * before printing it. * * @var array(string=>string) */ protected $valueMap = array( 'bar' => '', 'fraction' => '', 'act' => '', 'max' => '', ); /** * Stores the bar utilization. * * This array saves how much space a specific part of the bar utilizes to not * recalculate those on every step. * * @var array(string=>int) */ protected $measures = array( 'barSpace' => 0, 'fractionSpace' => 0, 'actSpace' => 0, 'maxSpace' => 0, 'fixedCharSpace' => 0, ); /** * The current step the progress bar should show. * * @var int */ protected $currentStep = 0; /** * The maximum number of steps to go. * Calculated once from the settings. * * @var int */ protected $numSteps = 0; /** * The ezcConsoleOutput object to use. * * @var ezcConsoleOutput */ protected $output; /** * Indicates if the starting point for the bar has been stored. * Per default this is false to indicate that no start position has been * stored, yet. * * @var bool */ protected $started = false; /** * Tool object to perform multi-byte encoding safe string operations. * * @var ezcConsoleStringTool */ private $stringTool; /** * Creates a new progress bar. * * @param ezcConsoleOutput $outHandler Handler to utilize for output * @param int $max Maximum value, where progressbar * reaches 100%. * @param array(string=>string) $options Options * * @see ezcConsoleProgressbar::$options */ public function __construct( ezcConsoleOutput $outHandler, $max, array $options = array() ) { $this->output = $outHandler; $this->stringTool = new ezcConsoleStringTool(); $this->__set( 'max', $max ); $this->properties['options'] = new ezcConsoleProgressbarOptions( $options ); } /** * Set new options. * This method allows you to change the options of progressbar. * * @param ezcConsoleProgresbarOptions $options The options to set. * * @throws ezcBaseSettingNotFoundException * If you tried to set a non-existent option value. * @throws ezcBaseSettingValueException * If the value is not valid for the desired option. * @throws ezcBaseValueException * If you submit neither an array nor an instance of * ezcConsoleProgresbarOptions. */ public function setOptions( $options ) { if ( is_array( $options ) ) { $this->properties['options']->merge( $options ); } else if ( $options instanceof ezcConsoleProgressbarOptions ) { $this->properties['options'] = $options; } else { throw new ezcBaseValueException( "options", $options, "instance of ezcConsoleProgressbarOptions" ); } } /** * Returns the current options. * Returns the options currently set for this progressbar. * * @return ezcConsoleProgressbarOptions The current options. */ public function getOptions() { return $this->properties['options']; } /** * Property read access. * * @param string $key Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __get( $key ) { switch ( $key ) { case 'options': return $this->properties['options']; case 'step': // Step is now an option return $this->properties['options']->step; case 'max': return $this->properties[$key]; default: break; } throw new ezcBasePropertyNotFoundException( $key ); } /** * Property write access. * * @param string $key Name of the property. * @param mixed $val The value for the property. * * @throws ezcBasePropertyNotFoundException * If a desired property could not be found. * @throws ezcBaseValueException * If a desired property value is out of range. * @ignore */ public function __set( $key, $val ) { switch ( $key ) { case 'options': if ( !( $val instanceof ezcConsoleProgressbarOptions ) ) { throw new ezcBaseValueException( 'options', $val, 'instance of ezcConsoleProgressbarOptions' ); }; break; case 'max': if ( ( !is_int( $val ) && !is_float( $val ) ) || $val < 0 ) { throw new ezcBaseValueException( $key, $val, 'number >= 0' ); } break; case 'step': if ( ( !is_int( $val ) && !is_float( $val ) ) || $val < 0 ) { throw new ezcBaseValueException( $key, $val, 'number >= 0' ); } // Step is now an option. $this->properties['options']->step = $val; return; default: throw new ezcBasePropertyNotFoundException( $key ); break; } // Changes settings or options, need for recalculating measures $this->started = false; $this->properties[$key] = $val; } /** * Property isset access. * * @param string $key Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $key ) { switch ( $key ) { case 'options': case 'max': case 'step': return true; } return false; } /** * Start the progress bar * Starts the progress bar and sticks it to the current line. * No output will be done yet. Call {@link ezcConsoleProgressbar::output()} * to print the bar. * * @return void */ public function start() { $this->calculateMeasures(); $this->output->storePos(); $this->started = true; } /** * Draw the progress bar. * Prints the progress-bar to the screen. If start() has not been called * yet, the current line is used for {@link ezcConsolProgressbar::start()}. * * @return void */ public function output() { if ( $this->options->minVerbosity > $this->output->options->verbosityLevel || ( $this->options->maxVerbosity !== false && $this->options->maxVerbosity < $this->output->options->verbosityLevel ) ) { // Do not print progress bar if verbosity level is lower than it's // output objects value. return; } if ( $this->started === false ) { $this->start(); } $this->output->restorePos(); if ( ezcBaseFeatures::os() === "Windows" ) { echo str_repeat( "\x8", $this->options->width ); } $this->generateValues(); echo $this->insertValues(); } /** * Advance the progress bar. * Advances the progress bar by $step steps. Redraws the bar by default, * using the {@link ezcConsoleProgressbar::output()} method. * * @param bool $redraw Whether to redraw the bar immediately. * @param int $step How many steps to advance. * @return void */ public function advance( $redraw = true, $step = 1 ) { $this->currentStep += $step; if ( $redraw === true && $this->currentStep % $this->properties['options']->redrawFrequency === 0 ) { $this->output(); } } /** * Finish the progress bar. * Finishes the bar (jump to 100% if not happened yet,...) and jumps * to the next line to allow new output. Also resets the values of the * output handler used, if changed. * * @return void */ public function finish() { $this->currentStep = $this->numSteps; $this->output(); } /** * Generate all values to be replaced in the format string. * * @return void */ protected function generateValues() { // Bar $barFilledSpace = ceil( $this->measures['barSpace'] / $this->numSteps * $this->currentStep ); // Sanitize value if it gets to large by rounding $barFilledSpace = $barFilledSpace > $this->measures['barSpace'] ? $this->measures['barSpace'] : $barFilledSpace; $bar = $this->stringTool->strPad( $this->stringTool->strPad( $this->properties['options']->progressChar, $barFilledSpace, $this->properties['options']->barChar, STR_PAD_LEFT ), $this->measures['barSpace'], $this->properties['options']->emptyChar, STR_PAD_RIGHT ); $this->valueMap['bar'] = $bar; // Fraction $fractionVal = sprintf( $this->properties['options']->fractionFormat, ( $fractionVal = ( $this->properties['options']->step * $this->currentStep ) / $this->max * 100 ) > 100 ? 100 : $fractionVal ); $this->valueMap['fraction'] = $this->stringTool->strPad( $fractionVal, iconv_strlen( sprintf( $this->properties['options']->fractionFormat, 100 ), 'UTF-8' ), ' ', STR_PAD_LEFT ); // Act / max $actVal = sprintf( $this->properties['options']->actFormat, ( $actVal = $this->currentStep * $this->properties['options']->step ) > $this->max ? $this->max : $actVal ); $this->valueMap['act'] = $this->stringTool->strPad( $actVal, iconv_strlen( sprintf( $this->properties['options']->actFormat, $this->max ), 'UTF-8' ), ' ', STR_PAD_LEFT ); $this->valueMap['max'] = sprintf( $this->properties['options']->maxFormat, $this->max ); } /** * Insert values into bar format string. * * @return void */ protected function insertValues() { $bar = $this->properties['options']->formatString; foreach ( $this->valueMap as $name => $val ) { $bar = str_replace( "%{$name}%", $val, $bar ); } return $bar; } /** * Calculate several measures necessary to generate a bar. * * @return void */ protected function calculateMeasures() { // Calc number of steps bar goes through $this->numSteps = ( int ) round( $this->max / $this->properties['options']->step ); // Calculate measures $this->measures['fixedCharSpace'] = iconv_strlen( $this->stripEscapeSequences( $this->insertValues() ), 'UTF-8' ); if ( iconv_strpos( $this->properties['options']->formatString, '%max%', 0, 'UTF-8' ) !== false ) { $this->measures['maxSpace'] = iconv_strlen( sprintf( $this->properties['options']->maxFormat, $this->max ), 'UTF-8' ); } if ( iconv_strpos( $this->properties['options']->formatString, '%act%', 0, 'UTF-8' ) !== false ) { $this->measures['actSpace'] = iconv_strlen( sprintf( $this->properties['options']->actFormat, $this->max ), 'UTF-8' ); } if ( iconv_strpos( $this->properties['options']->formatString, '%fraction%', 0, 'UTF-8' ) !== false ) { $this->measures['fractionSpace'] = iconv_strlen( sprintf( $this->properties['options']->fractionFormat, 100 ), 'UTF-8' ); } $this->measures['barSpace'] = $this->properties['options']->width - array_sum( $this->measures ); } /** * Strip all escape sequences from a string to measure it's size correctly. * * @param mixed $str * @return void */ protected function stripEscapeSequences( $str ) { return preg_replace( '/\033\[[0-9a-f;]*m/i', '', $str ); } } ?> PK! L^ezc/ConsoleTools/statusbar.phpnu[ * // Construction * $status = new ezcConsoleStatusbar( new ezcConsoleOutput() ); * * // Set option * $status->options['successChar'] = '*'; * * // Run statusbar * foreach ( $files as $file ) * { * $res = $file->upload(); * // Add status if form of bool true/false to statusbar. * $status->add( $res ); // $res is true or false * } * * // Retreive and display final statusbar results * $msg = $status->getSuccess() . ' succeeded, ' . $status->getFailure() . ' failed.'; * $out->outputText( "Finished uploading files: $msg\n" ); * * * @property ezcConsoleStatusbarOptions $options * Contains the options for this class. * * @package ConsoleTools * @version 1.6.1 * @mainclass */ class ezcConsoleStatusbar { /** * Container to hold the properties * * @var array(string=>mixed) */ protected $properties; /** * The ezcConsoleOutput object to use. * * @var ezcConsoleOutput */ protected $outputHandler; /** * Counter for success and failure outputs. * * @var array(bool=>int) */ protected $counter = array( true => 0, false => 0, ); /** * Creates a new status bar. * * @param ezcConsoleOutput $outHandler Handler to utilize for output * @param array(string=>string) $options Options * * @see ezcConsoleStatusbar::$options */ public function __construct( ezcConsoleOutput $outHandler, array $options = array() ) { $this->outputHandler = $outHandler; $this->properties['options'] = new ezcConsoleStatusbarOptions( $options ); } /** * Property read access. * * @param string $key Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __get( $key ) { switch ( $key ) { case 'options': return $this->properties['options']; break; } if ( isset( $this->properties['options']->$key ) ) { return $this->properties['options']->$key; } throw new ezcBasePropertyNotFoundException( $key ); } /** * Set new options. * This method allows you to change the options of a statusbar. * * @param array(string=>string)|ezcConsoleOutputOptions $options The options to set. * * @throws ezcBaseSettingNotFoundException * If you tried to set a non-existent option value. * @throws ezcBaseSettingValueException * If the value is not valid for the desired option. * @throws ezcBaseValueException * If you submit neither an array nor an instance of * ezcConsoleOutputOptions. */ public function setOptions( $options ) { if ( is_array( $options ) ) { $this->properties['options']->merge( $options ); } else if ( $options instanceof ezcConsoleStatusbarOptions ) { $this->properties['options'] = $options; } else { throw new ezcBaseValueException( "options", $options, "instance of ezcConsoleStatusbarOptions" ); } } /** * Property write access. * * @param string $key Name of the property. * @param mixed $val The value for the property. * * @throws ezcBasePropertyNotFoundException * If a desired property could not be found. * @throws ezcBaseValueException * If a desired property value is out of range. * @ignore */ public function __set( $key, $val ) { switch ( $key ) { // Those two are here for BC reasons only, it is proper to // use $statusbar->options->successChar instead of just // $statusbar->successChar. case 'successChar': case 'failureChar': // No checks necessary here, already performed in // ezcConsoleStatusbarOptions break; case "options": if ( ( $val instanceof ezcConsoleStatusbarOptions ) === false ) { throw new ezcBaseValueException( $key, $val, 'ezcConsoleStatusbarOptions' ); } $this->properties[$key] = $val; return; default: throw new ezcBasePropertyNotFoundException( $key ); } $this->properties['options'][$key] = $val; } /** * Property isset access. * * @param string $key Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $key ) { return isset( $this->properties['options'][$key] ) || isset( $this->properties[$key] ); } /** * Returns the current options. * Returns the options currently set for this progressbar. * * @return ezcConsoleStatusbarOptions The current options. */ public function getOptions() { return $this->properties['options']; } /** * Add a status to the status bar. * Adds a new status to the bar which is printed immediately. If the * cursor is currently not at the beginning of a line, it will move to * the next line. * * @param bool $status Print successChar on true, failureChar on false. * @return void */ public function add( $status ) { if ( is_bool( $status ) === false ) { trigger_error( 'Unknown status '.var_export( $status, true ).'.', E_USER_WARNING ); $status = (bool) $status; } switch ( $status ) { case true: $this->outputHandler->outputText( $this->properties['options']['successChar'], 'success' ); break; case false: $this->outputHandler->outputText( $this->properties['options']['failureChar'], 'failure' ); break; } $this->counter[$status]++; } /** * Reset the state of the status-bar object to its initial one. * * @return void */ public function reset() { foreach ( $this->counter as $status => $count ) { $this->counter[$status] = 0; } } /** * Returns number of successes during the run. * Returns the number of success characters printed from this status bar. * * @return int Number of successes. */ public function getSuccessCount() { return $this->counter[true]; } /** * Returns number of failures during the run. * Returns the number of failure characters printed from this status bar. * * @return int Number of failures. */ public function getFailureCount() { return $this->counter[false]; } } ?> PK!5tt%ezc/ConsoleTools/console_autoload.phpnu[ 'ConsoleTools/exceptions/exception.php', 'ezcConsoleArgumentException' => 'ConsoleTools/exceptions/argument.php', 'ezcConsoleOptionException' => 'ConsoleTools/exceptions/option.php', 'ezcConsoleArgumentAlreadyRegisteredException' => 'ConsoleTools/exceptions/argument_already_registered.php', 'ezcConsoleArgumentMandatoryViolationException' => 'ConsoleTools/exceptions/argument_mandatory_violation.php', 'ezcConsoleArgumentTypeViolationException' => 'ConsoleTools/exceptions/argument_type_violation.php', 'ezcConsoleDialogAbortException' => 'ConsoleTools/exceptions/dialog_abort.php', 'ezcConsoleInvalidOptionNameException' => 'ConsoleTools/exceptions/invalid_option_name.php', 'ezcConsoleInvalidOutputTargetException' => 'ConsoleTools/exceptions/invalid_output_target.php', 'ezcConsoleNoPositionStoredException' => 'ConsoleTools/exceptions/no_position_stored.php', 'ezcConsoleNoValidDialogResultException' => 'ConsoleTools/exceptions/no_valid_dialog_result.php', 'ezcConsoleOptionAlreadyRegisteredException' => 'ConsoleTools/exceptions/option_already_registered.php', 'ezcConsoleOptionArgumentsViolationException' => 'ConsoleTools/exceptions/option_arguments_violation.php', 'ezcConsoleOptionDependencyViolationException' => 'ConsoleTools/exceptions/option_dependency_violation.php', 'ezcConsoleOptionExclusionViolationException' => 'ConsoleTools/exceptions/option_exclusion_violation.php', 'ezcConsoleOptionMandatoryViolationException' => 'ConsoleTools/exceptions/option_mandatory_violation.php', 'ezcConsoleOptionMissingValueException' => 'ConsoleTools/exceptions/option_missing_value.php', 'ezcConsoleOptionNoAliasException' => 'ConsoleTools/exceptions/option_no_alias.php', 'ezcConsoleOptionNotExistsException' => 'ConsoleTools/exceptions/option_not_exists.php', 'ezcConsoleOptionStringNotWellformedException' => 'ConsoleTools/exceptions/option_string_not_wellformed.php', 'ezcConsoleOptionTooManyValuesException' => 'ConsoleTools/exceptions/option_too_many_values.php', 'ezcConsoleOptionTypeViolationException' => 'ConsoleTools/exceptions/option_type_violation.php', 'ezcConsoleTooManyArgumentsException' => 'ConsoleTools/exceptions/argument_too_many.php', 'ezcConsoleDialogValidator' => 'ConsoleTools/interfaces/dialog_validator.php', 'ezcConsoleQuestionDialogValidator' => 'ConsoleTools/interfaces/question_dialog_validator.php', 'ezcConsoleDialog' => 'ConsoleTools/interfaces/dialog.php', 'ezcConsoleDialogOptions' => 'ConsoleTools/options/dialog.php', 'ezcConsoleInputHelpGenerator' => 'ConsoleTools/interfaces/input_help_generator.php', 'ezcConsoleInputValidator' => 'ConsoleTools/interfaces/input_validator.php', 'ezcConsoleMenuDialogValidator' => 'ConsoleTools/interfaces/menu_dialog_validator.php', 'ezcConsoleQuestionDialogCollectionValidator' => 'ConsoleTools/dialog/validators/question_dialog_collection.php', 'ezcConsoleArgument' => 'ConsoleTools/input/argument.php', 'ezcConsoleArguments' => 'ConsoleTools/input/arguments.php', 'ezcConsoleDialogViewer' => 'ConsoleTools/dialog_viewer.php', 'ezcConsoleInput' => 'ConsoleTools/input.php', 'ezcConsoleInputStandardHelpGenerator' => 'ConsoleTools/input/help_generators/standard.php', 'ezcConsoleMenuDialog' => 'ConsoleTools/dialog/menu_dialog.php', 'ezcConsoleMenuDialogDefaultValidator' => 'ConsoleTools/dialog/validators/menu_dialog_default.php', 'ezcConsoleMenuDialogOptions' => 'ConsoleTools/options/menu_dialog.php', 'ezcConsoleOption' => 'ConsoleTools/input/option.php', 'ezcConsoleOptionRule' => 'ConsoleTools/structs/option_rule.php', 'ezcConsoleOutput' => 'ConsoleTools/output.php', 'ezcConsoleOutputFormat' => 'ConsoleTools/structs/output_format.php', 'ezcConsoleOutputFormats' => 'ConsoleTools/structs/output_formats.php', 'ezcConsoleOutputOptions' => 'ConsoleTools/options/output.php', 'ezcConsoleProgressMonitor' => 'ConsoleTools/progressmonitor.php', 'ezcConsoleProgressMonitorOptions' => 'ConsoleTools/options/progressmonitor.php', 'ezcConsoleProgressbar' => 'ConsoleTools/progressbar.php', 'ezcConsoleProgressbarOptions' => 'ConsoleTools/options/progressbar.php', 'ezcConsoleQuestionDialog' => 'ConsoleTools/dialog/question_dialog.php', 'ezcConsoleQuestionDialogMappingValidator' => 'ConsoleTools/dialog/validators/question_dialog_mapping.php', 'ezcConsoleQuestionDialogOptions' => 'ConsoleTools/options/question_dialog.php', 'ezcConsoleQuestionDialogRegexValidator' => 'ConsoleTools/dialog/validators/question_dialog_regex.php', 'ezcConsoleQuestionDialogTypeValidator' => 'ConsoleTools/dialog/validators/question_dialog_type.php', 'ezcConsoleStandardInputValidator' => 'ConsoleTools/input/validators/standard.php', 'ezcConsoleStatusbar' => 'ConsoleTools/statusbar.php', 'ezcConsoleStatusbarOptions' => 'ConsoleTools/options/statusbar.php', 'ezcConsoleStringTool' => 'ConsoleTools/tools/string.php', 'ezcConsoleTable' => 'ConsoleTools/table.php', 'ezcConsoleTableCell' => 'ConsoleTools/table/cell.php', 'ezcConsoleTableOptions' => 'ConsoleTools/options/table.php', 'ezcConsoleTableRow' => 'ConsoleTools/table/row.php', ); ?> PK!O!ezc/ConsoleTools/tools/string.phpnu[= $width ) { $newtext .= iconv_substr( $str, $laststart, $current - $laststart, 'UTF-8' ) . $break; $laststart = $current + 1; } $lastspace = $current; } // Special cut case, if no space has been seen else if ( $current - $laststart >= $width && $cut && $laststart >= $lastspace ) { $newtext .= iconv_substr( $str, $laststart, $current - $laststart, 'UTF-8' ) . $break; $laststart = $lastspace = $current; } // Usual case that line got longer than expected else if ( $current - $laststart >= $width && $laststart < $lastspace ) { $newtext .= iconv_substr( $str, $laststart, $lastspace - $laststart, 'UTF-8' ) . $break; // $laststart = $lastspace = $lastspace + 1; $laststart = ++$lastspace; } } // Rest of the string if ( $laststart !== $current ) { $newtext .= iconv_substr( $str, $laststart, $current - $laststart, 'UTF-8' ); } return $newtext; } /** * Binary safe str_pad() replacement. * * This method is a multi-byte encoding safe replacement for the PHP * function str_pad(). It mimics exactly the behavior of str_pad(), but * uses iconv_* functions with UTF-8 encoding. The parameters received by * this method equal the parameters of {@link http://php.net/str_pad * str_pad()}. Note: Make sure to hand only UTF-8 encoded content to this * method. * * @param string $input * @param int $padLength * @param string $padString * @param int $padType * @return string */ public function strPad( $input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT ) { $input = (string) $input; $strLen = iconv_strlen( $input, 'UTF-8' ); $padStrLen = iconv_strlen( $padString, 'UTF-8' ); if ( $strLen >= $padLength ) { return $input; } if ( $padType === STR_PAD_BOTH ) { return $this->strPad( $this->strPad( $input, $strLen + ceil( ( $padLength - $strLen ) / 2 ), $padString ), $padLength, $padString, STR_PAD_LEFT ); } $fullStrRepeats = (int) ( ( $padLength - $strLen ) / $padStrLen ); $partlyPad = iconv_substr( $padString, 0, ( ( $padLength - $strLen ) % $padStrLen ) ); $padding = str_repeat( $padString, $fullStrRepeats ) . $partlyPad; switch ( $padType ) { case STR_PAD_LEFT: return $padding . $input; case STR_PAD_RIGHT: default: return $input . $padding; } } } ?> PK!;o!"ezc/ConsoleTools/dialog_viewer.phpnu[ * // Instatiate dialog in $dialog ... * ezcConsoleDialogViewer::displayDialog( $dialog ); * * * For implementing a custom dialog, the method {@link readLine()} method can be * used to read a line of input from the user. * * @package ConsoleTools * @version 1.6.1 */ class ezcConsoleDialogViewer { /** * Displays a dialog and returns a valid result from it. * This methods displays a dialog in a loop, until it received a valid * result from it and returns this result. * * @param ezcConsoleDialog $dialog The dialog to display. * @return mixed The result from this dialog. */ public static function displayDialog( ezcConsoleDialog $dialog ) { do { $dialog->display(); } while ( $dialog->hasValidResult() === false ); return $dialog->getResult(); } /** * Returns a line from STDIN. * The returned line is fully trimmed. * * @return string * @throws ezcConsoleDialogAbortException * if the user closes STDIN using -D. */ public static function readLine() { $res = trim( fgets( STDIN ) ); if ( feof( STDIN ) ) { throw new ezcConsoleDialogAbortException(); } return $res; } } ?> PK!+ezc/ConsoleTools/dialog/question_dialog.phpnu[ null, "output" => null, ); /** * Creates a new question dialog. * Creates a new menu dialog to be displayed to the user. All behaviour is * defined through the $options parameter. The $output parameter is used to * display the dialog in the {@link display()} method. * * @param ezcConsoleOutput $output Output object. * @param ezcConsoleQuestionDialogOptions $options Options. * @return void */ public function __construct( ezcConsoleOutput $output, ezcConsoleQuestionDialogOptions $options = null ) { $this->output = $output; $this->options = $options === null ? new ezcConsoleQuestionDialogOptions() : $options; } /** * Returns if the dialog retrieved a valid result. * If a valid result has already been received, this method returns true, * otherwise false. * * @return bool If a valid result was retrieved. */ public function hasValidResult() { return $this->result !== null; } /** * Returns the result retrieved. * If no valid result was retreived, yet, this method should throw an * ezcConsoleNoValidDialogResultException. * * If no valid result was retreived, yet, this method throws an * ezcConsoleNoValidDialogResultException. Use {@link hasValidResult()} to * avoid this. * * @return mixed The retreived result. * * @throws ezcDialogNoValidResultException * if this method is called without a valid result being retrieved * by the object. Use {@link hasValidResult()} to avoid this * exception. */ public function getResult() { if ( $this->result === null ) { throw new ezcConsoleNoValidDialogResultException(); } return $this->result; } /** * Displays the dialog and retreives a value from the user. * Displays the dialog and retreives the desired answer from the user. If * the a valid result is retrieved, it can be obtained using {@link * getResult()}. The method {@link hasValidResult()} can be used to check * if a valid result is available. * * @return void * @throws ezcConsoleDialogAbortException * if the user closes STDIN using -D. */ public function display() { $this->reset(); $this->output->outputText( $this->options->text . ( $this->options->showResults === true ? " " . $this->options->validator->getResultString() : "" ) . " ", $this->options->format ); $result = $this->options->validator->fixup( ezcConsoleDialogViewer::readLine() ); if ( $this->options->validator->validate( $result ) ) { $this->result = $result; } } /** * Reset the dialog. * Resets a possibly received result and all changes made to the dialog * during {@link display()}. After that, the dialog can be re-used. All * option values are kept. * * @return void */ public function reset() { $this->result = null; } /** * Returns a ready to use yes/no question dialog. * Returns a question dialog, which requests the answers "y" for "yes" or * "n" for "no" from the user. The answer is converted to lower-case. * * * // Would you like to proceed? (y/n) * $dialog = ezcConsoleDialog( $out, "Would you like to proceed?" ); * * // Would you like to proceed? (y/n) [n] * $dialog = ezcConsoleDialog( $out, "Would you like to proceed?", "n" ); * * * @param ezcConsoleOutput $out Output object. * @param string $questionString Question string. * @param string $default "y" or "n", if default value is desired. * @return ezcConsoleQuestionDialog The created dialog. */ public static function YesNoQuestion( ezcConsoleOutput $out, $questionString, $default = null ) { $opts = new ezcConsoleQuestionDialogOptions(); $opts->text = $questionString; $opts->showResults = true; $opts->validator = new ezcConsoleQuestionDialogMappingValidator( array( "y", "n" ), $default, ezcConsoleQuestionDialogCollectionValidator::CONVERT_LOWER, array( 'yes' => 'y', 'no' => 'n', ) ); return new ezcConsoleQuestionDialog( $out, $opts ); } /** * Property read access. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * * @param string $propertyName Name of the property. * @return mixed Value of the property or null. * @ignore */ public function __get( $propertyName ) { if ( array_key_exists( $propertyName, $this->properties ) ) { return $this->properties[$propertyName]; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyPermissionException * If the property you try to access is read-only. * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "options": if ( ( $propertyValue instanceof ezcConsoleQuestionDialogOptions ) === false ) { throw new ezcBaseValueException( $propertyName, ( is_object( $propertyValue ) ? get_class( $propertyValue ) : gettype( $propertyValue ) ), "instance of ezcConsoleQuestionDialogOptions" ); } break; case "output": if ( ( $propertyValue instanceof ezcConsoleOutput ) === false ) { throw new ezcBaseValueException( $propertyName, ( is_object( $propertyValue ) ? get_class( $propertyValue ) : gettype( $propertyValue ) ), "instance of ezcConsoleOutput" ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $propertyValue; } /** * Property isset access. * * @param string $propertyName Name of the property to check. * @return bool If the property exists or not. * @ignore */ public function __isset( $propertyName ) { return array_key_exists( $propertyName, $this->properties ); } } ?> PK!egO<ezc/ConsoleTools/dialog/validators/question_dialog_regex.phpnu[mixed) */ protected $properties = array( "pattern" => null, "default" => null, ); /** * Create a new question dialog regex validator. * Create a new question dialog regex validator, which validates the result * specified against a given regular expression. The delimiters and * eventual modifiers must be included in the pattern. If not value is * provided by the user a possibly set $default value is used instead. * * * @param string $pattern Pattern to validate against. * @param mixed $default Default value. * @return void */ public function __construct( $pattern, $default = null ) { $this->pattern = $pattern; $this->default = $default; } /** * Returns if the given result is valid. * Returns if the result matches the regular expression. * * @param mixed $result The received result. * @return bool If the result is valid. */ public function validate( $result ) { if ( $result === "" ) { return $this->default !== null; } return preg_match( $this->pattern, $result ) > 0; } /** * Returns a fixed version of the result, if possible. * If no result was provided by the user, the default value will be * returned, if set. * * @param mixed $result The received result. * @return mixed The manipulated result. */ public function fixup( $result ) { if ( $result === "" && $this->default !== null ) { return $this->default; } return $result; } /** * Returns a string representing valid results. * Returns the string that will be displayed with the question to * indicate valid results to the user and a possibly set default, if * available. * * @return string */ public function getResultString() { return "(match {$this->pattern})" . ( $this->default !== null ? " [{$this->default}]" : "" ); } /** * Property read access. * * @param string $propertyName Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __get( $propertyName ) { if ( $this->__isset( $propertyName ) ) { return $this->properties[$propertyName]; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @throws ezcBaseValueException * If a the value for a property is out of range. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "pattern": if ( is_string( $propertyValue ) === false || strlen( $propertyValue ) < 2 ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "string, length > 1" ); } break; case "default": if ( is_scalar( $propertyValue ) === false && $propertyValue !== null ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "scalar" ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $propertyValue; } /** * Property isset access. * * @param string $propertyName Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $propertyName ) { return array_key_exists( $propertyName, $this->properties ); } } ?> PK!,M??;ezc/ConsoleTools/dialog/validators/question_dialog_type.phpnu[ self::TYPE_STRING, "default" => null, ); /** * Creates a new question dialog type validator. * Creates a new question dialog type validator, which validates the result * specified to be of a certaon type. The $type must be one of the TYPE_* * constants in this class. If no value is provided by the user a possibly * set $default value is used instead. * * @param int $type One of ezcConsoleQuestionDialogTypeValidator::TYPE_*. * @param mixed $default Default value according to $type. * @return void */ public function __construct( $type = self::TYPE_STRING, $default = null ) { $this->type = $type; $this->default = $default; } /** * Returns if the given result is valid. * Returns if the result is of the given type. * * @param mixed $result The result to check. * @return bool True if the result is valid. Otherwise false. */ public function validate( $result ) { if ( $result === "" ) { return $this->default !== null; } switch ( $this->type ) { case self::TYPE_INT: return is_int( $result ); case self::TYPE_FLOAT: return is_float( $result ); case self::TYPE_BOOL: return is_bool( $result ); case self::TYPE_STRING: default: return is_string( $result ); } } /** * Returns a fixed version of the result, if possible. * Returns the value casted into the correct type or the default value, if * it exists and the result is empty. * * @param mixed $result The result received. * @return mixed The manipulated result. */ public function fixup( $result ) { if ( $result === "" && $this->default !== null ) { return $this->default; } switch ( $this->type ) { case self::TYPE_INT: return ( preg_match( "/^[0-9\-]+$/", $result ) !== 0 ) ? (int) $result : $result; case self::TYPE_FLOAT: return ( preg_match( "/^[0-9.E\-]+$/i", $result ) !== 0 ) ? (float) $result : $result; case self::TYPE_BOOL: switch ( $result ) { case "1": case "true": return true; case "0": case "false": return false; } case self::TYPE_STRING: default: return $result; } } /** * Returns a string representing valid results. * Returns the string that can will be displayed with the question to * indicate valid results to the user and a possibly set default, if * available. * * @return string */ public function getResultString() { $res = "(<%s>)" . ( $this->default !== null ? " [{$this->default}]" : "" ); switch ( $this->type ) { case self::TYPE_INT: return sprintf( $res, "int" ); case self::TYPE_FLOAT: return sprintf( $res, "float" ); case self::TYPE_BOOL: return sprintf( $res, "bool" ); case self::TYPE_STRING: default: return sprintf( $res, "string" ); } } /** * Property read access. * * @param string $propertyName Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __get( $propertyName ) { if ( isset( $this->$propertyName ) ) { return $this->properties[$propertyName]; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @throws ezcBaseValueException * If a the value for a property is out of range. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "type": if ( $propertyValue !== self::TYPE_STRING && $propertyValue !== self::TYPE_INT && $propertyValue !== self::TYPE_FLOAT && $propertyValue !== self::TYPE_BOOL ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleQuestionDialogTypeValidator::TYPE_*" ); } break; case "default": if ( is_scalar( $propertyValue ) === false && $propertyValue !== null ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "scalar" ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $propertyValue; } /** * Property isset access. * * @param string $propertyName Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $propertyName ) { return array_key_exists( $propertyName, $this->properties ); } } ?> PK!:ezc/ConsoleTools/dialog/validators/menu_dialog_default.phpnu[ array(), "default" => null, "conversion" => self::CONVERT_NONE, ); /** * Creates a new menu default validator. * Creates a validator specified by the given parameters. The $elements * array specifies the possible menu items to select from. The item * identifier (the key of the array) is used to validate the result. The * assigned text is displayed as the menu item text. If no result is * provided and an optionally provided default value is used. The * $conversion parameter can be used to get a conversion applied to the * result before validating it. * * @param array $elements The elements of the menu. * @param mixed $default The default value. * @param int $conversion The conversion to apply. * @return void */ public function __construct( array $elements = array(), $default = null, $conversion = self::CONVERT_NONE ) { $this->elements = $elements; $this->default = $default; $this->conversion = $conversion; } /** * Returns if the given result is valid. * Checks if the given result is a valid key in the $elements property. * * @param mixed $result The received result. * @return bool If the result is valid. */ public function validate( $result ) { return isset( $this->elements[$result] ); } /** * Returns a fixed version of the result, if possible. * Converts the given result according to the conversion defined in the * $conversion property. * * @param mixed $result The received result. * @return mixed The manipulated result. */ public function fixup( $result ) { if ( $result === "" && $this->default !== null ) { return $this->default; } switch ( $this->conversion ) { case self::CONVERT_LOWER: return strtolower( $result ); case self::CONVERT_UPPER: return strtoupper( $result ); case self::CONVERT_NONE: default: return $result; } } /** * Returns a string representing the default value. * For example "[y]" to indicate that "y" is the preselected result and * will be chosen if no result is provided. * * @return string The result string. */ public function getResultString() { return $this->default === null ? "" : "[{$this->default}]"; } /** * Returns an array of the elements to display. * * @return array(string=>string) Elements to display. */ public function getElements() { return $this->elements; } /** * Property read access. * * @param string $propertyName Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __get( $propertyName ) { if ( isset( $this->$propertyName ) ) { return $this->properties[$propertyName]; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @throws ezcBaseValueException * If a the value for a property is out of range. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "elements": if ( is_array( $propertyValue ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "array" ); } break; case "default": if ( is_scalar( $propertyValue ) === false && $propertyValue !== null ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "scalar" ); } break; case "conversion": if ( $propertyValue !== self::CONVERT_NONE && $propertyValue !== self::CONVERT_UPPER && $propertyValue !== self::CONVERT_LOWER ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleMenuDialogDefaultValidator::CONVERT_*" ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $propertyValue; } /** * Property isset access. * * @param string $propertyName Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $propertyName ) { return array_key_exists( $propertyName, $this->properties ); } } ?> PK!->ezc/ConsoleTools/dialog/validators/question_dialog_mapping.phpnu[ * array( * 'yes' => 'y', * 'no' => 'n', * '1' => 'y', * '0' => 'n' * ) * * While the corresponding collection of valid answers would look like * this: * * array( * 'y', 'n' * ) * * If the answer 'yes' is received by the validator, it is mapped to 'y', * therefore considered valid and 'y' is returned as the received value. * * @package ConsoleTools * @version 1.6.1 * * @property array(string) $collection * The collection of valid answers. * @property mixed $default * Default value. * @property int $conversion * ezcConsoleDialogValidator::CONVERT_NONE (default) or * ezcConsoleDialogValidator::CONVERT_LOWER or * ezcConsoleDialogValidator::CONVERT_UPPER. * @property array(string=>string) $map * Mapping of answers to valid answers (e.g. array('yes' => 'y') to * map 'yes' to 'y' while 'y' must be in $collection). */ class ezcConsoleQuestionDialogMappingValidator extends ezcConsoleQuestionDialogCollectionValidator { /** * Creates a new question dialog mapping validator. * Creates a new question dialog mapping validator, which validates the * result specified by the user against an array of valid results * ($collection). If not value is provided by the user a possibly set * $default value is used instead. The $conversion parameter can optionally * define a conversion to be performed on the result before validating it. * Valid conversions are defined by the CONVERT_* constants in this class. * * While this functionality is already provided by {@link * ezcConsoleQuestionDialogCollectionValidator}, the additional $map * paramater allows the sepcification of a map of result values. These * mapping is then checked for matches, before a received answer is * validated against the collection. * * @param array(string) $collection The collection of valid results. * @param mixed $default Optional default value. * @param int $conversion CONVERT_* constant. * @param array(string=>string) $map * @return void */ public function __construct( array $collection, $default = null, $conversion = self::CONVERT_NONE, array $map = array() ) { // Initialize additional property $this->properties['map'] = $map; parent::__construct( $collection, $default, $conversion ); } /** * Returns a fixed version of the result, if possible. * Converts the given result according to the conversion defined in the * $conversion property. * * @param mixed $result The received result. * @return mixed The manipulated result. */ public function fixup( $result ) { if ( $result === "" && $this->default !== null ) { return $this->default; } switch ( $this->conversion ) { case self::CONVERT_UPPER: $result = strtoupper( $result ); break; case self::CONVERT_LOWER: $result = strtolower( $result ); break; } return ( isset( $this->map[$result] ) ? $this->map[$result] : $result ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @throws ezcBaseValueException * If a the value for a property is out of range. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "map": if ( is_array( $propertyValue ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "array" ); } break; default: return parent::__set( $propertyName, $propertyValue ); } $this->properties[$propertyName] = $propertyValue; } } ?> PK!H!Aezc/ConsoleTools/dialog/validators/question_dialog_collection.phpnu[ array(), "default" => null, "conversion" => self::CONVERT_NONE, ); /** * Creates a new question dialog collection validator. * Creates a new question dialog collection validator, which validates the * result specified by the user against an array of valid results * ($collection). If not value is provided by the user a possibly set * $default value is used instead. The $conversion parameter can optionally * define a conversion to be performed on the result before validating it. * Valid conversions are defined by the CONVERT_* constants in this class. * * @param array $collection The collection of valid results. * @param mixed $default Optional default value. * @param int $conversion CONVERT_* constant. * @return void */ public function __construct( array $collection, $default = null, $conversion = self::CONVERT_NONE ) { $this->collection = $collection; $this->default = $default; $this->conversion = $conversion; } /** * Returns if the given result is valid. * Returns if the result is in the $collection array. * * @param mixed $result The received result. * @return bool If the result is valid. */ public function validate( $result ) { return in_array( $result, $this->collection ); } /** * Returns a fixed version of the result, if possible. * Converts the given result according to the conversion defined in the * $conversion property. * * @param mixed $result The received result. * @return mixed The manipulated result. */ public function fixup( $result ) { if ( $result === "" && $this->default !== null ) { return $this->default; } switch ( $this->conversion ) { case self::CONVERT_UPPER: return strtoupper( $result ); case self::CONVERT_LOWER: return strtolower( $result ); default: return $result; } } /** * Returns a string representing valid results. * Returns the string that will be displayed with the question to * indicate valid results to the user and a possibly set default, if * available. * * @return string */ public function getResultString() { return "(" . implode( "/", $this->collection ) . ")" . ( $this->default !== null ? " [{$this->default}]" : "" ); } /** * Property read access. * * @param string $propertyName Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __get( $propertyName ) { if ( isset( $this->$propertyName ) ) { return $this->properties[$propertyName]; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @throws ezcBaseValueException * If a the value for a property is out of range. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "collection": if ( is_array( $propertyValue ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "array" ); } break; case "default": if ( is_scalar( $propertyValue ) === false && $propertyValue !== null ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "scalar" ); } break; case "conversion": if ( $propertyValue !== self::CONVERT_NONE && $propertyValue !== self::CONVERT_UPPER && $propertyValue !== self::CONVERT_LOWER ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleQuestionDialogCollectionValidator::CONVERT_*" ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $propertyValue; } /** * Property isset access. * * @param string $propertyName Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $propertyName ) { return array_key_exists( $propertyName, $this->properties ); } } ?> PK!kx2'ezc/ConsoleTools/dialog/menu_dialog.phpnu[ null, "output" => null, ); /** * Creates a new menu dialog. * Creates a new question dialog to be displayed to the user. All behaviour is * defined through the $options parameter. The $output parameter is used to * display the dialog in the {@link display()} method. * * @param ezcConsoleOutput $output Output object. * @param ezcConsoleMenuDialogOptions $options The options. * @return void */ public function __construct( ezcConsoleOutput $output, ezcConsoleMenuDialogOptions $options = null ) { $this->output = $output; $this->options = $options === null ? new ezcConsoleMenuDialogOptions() : $options; } /** * Returns if the dialog retrieved a valid result. * If a valid result has already been received, this method returns true, * otherwise false. * * @return bool If a valid result was retrieved. */ public function hasValidResult() { return ( $this->result !== null ); } /** * Returns the result retrieved. * If no valid result was retreived, yet, this method throws an * ezcConsoleNoValidDialogResultException. Use {@link hasValidResult()} to * avoid this. * * @return mixed The retreived result. * * @throws ezcDialogNoValidResultException * if this method is called without a valid result being retrieved * by the object. Use {@link hasValidResult()} to avoid this * exception. */ public function getResult() { if ( $this->result === null ) { throw new ezcConsoleNoValidDialogResultException(); } return $this->result; } /** * Displays the dialog and retreives a value from the user. * Displays the dialog and retreives the desired answer from the user. If * the a valid result is retrieved, it can be obtained using {@link * getResult()}. The method {@link hasValidResult()} can be used to check * if a valid result is available. * * @return void * @throws ezcConsoleDialogAbortException * if the user closes STDIN using -D. */ public function display() { $this->reset(); $text = "{$this->options->text}\n"; foreach ( $this->options->validator->getElements() as $key => $entry ) { $text .= sprintf( $this->options->formatString, $key, $entry ); } $text .= "\n{$this->options->selectText}{$this->options->validator->getResultString()} "; $this->output->outputText( $text, $this->options->format ); $result = $this->options->validator->fixup( ezcConsoleDialogViewer::readLine() ); if ( $this->options->validator->validate( $result ) ) { $this->result = $result; } } /** * Reset the dialog. * Resets a possibly received result and all changes made to the dialog * during {@link display()}. After that, the dialog can be re-used. All * option values are kept. * * @return void */ public function reset() { $this->result = null; } /** * Property read access. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * * @param string $propertyName Name of the property. * @return mixed Value of the property or null. * @ignore */ public function __get( $propertyName ) { if ( array_key_exists( $propertyName, $this->properties ) ) { return $this->properties[$propertyName]; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyPermissionException * If the property you try to access is read-only. * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "options": if ( ( $propertyValue instanceof ezcConsoleMenuDialogOptions ) === false ) { throw new ezcBaseValueException( $propertyName, ( is_object( $propertyValue ) ? get_class( $propertyValue ) : gettype( $propertyValue ) ), "instance of ezcConsoleMenuDialogOptions" ); } break; case "output": if ( ( $propertyValue instanceof ezcConsoleOutput ) === false ) { throw new ezcBaseValueException( $propertyName, ( is_object( $propertyValue ) ? get_class( $propertyValue ) : gettype( $propertyValue ) ), "instance of ezcConsoleOutput" ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $propertyValue; } /** * Property isset access. * * @param string $propertyName Name of the property to check. * @return bool If the property exists or not. * @ignore */ public function __isset( $propertyName ) { return array_key_exists( $propertyName, $this->properties ); } } ?> PK!%p%pezc/ConsoleTools/table.phpnu[format. The second dimension gives * you direct access to the cells of your table, like $table[0][0] accesses the * first cell in the first row of your table. You can access its properties * diretly here, too. This works like e.g. $table[0][0]->format. Table row and * cell objects are created on the fly, when you access them for the first time. * You can also create them as if you simply create new array elements. E.g. * $table[] creates a new row in the table. * * * // Initialize the console output handler * $out = new ezcConsoleOutput(); * // Define a new format "headline" * $out->formats->headline->color = 'red'; * $out->formats->headline->style = array( 'bold' ); * // Define a new format "sum" * $out->formats->sum->color = 'blue'; * $out->formats->sum->style = array( 'negative' ); * * // Create a new table * $table = new ezcConsoleTable( $out, 60 ); * * // Create first row and in it the first cell * $table[0][0]->content = 'Headline 1'; * * // Create 3 more cells in row 0 * for ( $i = 2; $i < 5; $i++ ) * { * $table[0][]->content = "Headline $i"; * } * * $data = array( 1, 2, 3, 4 ); * * // Create some more data in the table... * foreach ( $data as $value ) * { * // Create a new row each time and set it's contents to the actual value * $table[][0]->content = $value; * } * * // Set another border format for our headline row * $table[0]->borderFormat = 'headline'; * * // Set the content format for all cells of the 3rd row to "sum" * $table[2]->format = 'sum'; * * $table->outputTable(); * * * @property ezcConsoleTableOptions $options * Contains the options for this class. * @property int $width * Width of the table. * * @see ezcConsoleOutput * @package ConsoleTools * @version 1.6.1 * @mainclass */ class ezcConsoleTable implements Countable, Iterator, ArrayAccess { /** * Automatically wrap text to fit into a column. * @see ezcConsoleTable::$options */ const WRAP_AUTO = 1; /** * Do not wrap text. Columns will be extended to fit the largest text. * ATTENTION: This is risky! * @see ezcConsoleTable::$options */ const WRAP_NONE = 2; /** * Text will be cut to fit into a column. * @see ezcConsoleTable::$options */ const WRAP_CUT = 3; /** * Align text in the default direction. */ const ALIGN_DEFAULT = -1; /** * Align text in cells to the right. */ const ALIGN_LEFT = STR_PAD_RIGHT; /** * Align text in cells to the left. */ const ALIGN_RIGHT = STR_PAD_LEFT; /** * Align text in cells to the center. */ const ALIGN_CENTER = STR_PAD_BOTH; /** * The width given by settings must be used even if the data allows it smaller. */ const WIDTH_FIXED = 1; /** * The width given by settings is a maximum value, if data allows it, the table gets smaller. */ const WIDTH_MAX = 2; /** * Container to hold the properties * * @var array(string=>mixed) */ protected $properties; /** * The ezcConsoleOutput object to use. * * @var ezcConsoleOutput */ protected $outputHandler; /** * Collection of the rows that are contained in the table. * * @var array(ezcConsoleTableRow) */ protected $rows; /** * Tool object for multi-byte encoding safe string operations. * * @var ezcConsoleStringTool */ private $stringTool; /** * Creates a new table. * * @param ezcConsoleOutput $outHandler Output handler to utilize * @param int $width Overall width of the table (chars). * @param array $options Options * * @see ezcConsoleTable::$options * * @throws ezcBaseValueException On an invalid setting. */ public function __construct( ezcConsoleOutput $outHandler, $width, $options = array() ) { $this->rows = array(); $this->outputHandler = $outHandler; $this->stringTool = new ezcConsoleStringTool(); $this->__set( 'width', $width ); if ( $options instanceof ezcConsoleTableOptions ) { $this->properties['options'] = $options; } else if ( is_array( $options ) ) { $this->properties['options'] = new ezcConsoleTableOptions( $options ); } else { throw new ezcBaseValueException( "options", $options, "array" ); } } /** * Set new options. * This method allows you to change the options of the table. * * @param ezcConsoleTableOptions $options The options to set. * * @throws ezcBaseSettingNotFoundException * If you tried to set a non-existent option value. * @throws ezcBaseSettingValueException * If the value is not valid for the desired option. * @throws ezcBaseValueException * If you submit neither an array nor an instance of * ezcConsoleTableOptions. */ public function setOptions( $options = array() ) { if ( is_array( $options ) ) { $this->properties['options']->merge( $options ); } else if ( $options instanceof ezcConsoleTableOptions ) { $this->properties['options'] = $options; } else { throw new ezcBaseValueException( "options", $options, "instance of ezcConsoleTableOptions" ); } } /** * Returns the current options. * Returns the options currently set for this table. * * @return ezcConsoleTableOptions The current options. */ public function getOptions() { return $this->properties['options']; } /** * Returns the table in an array. * * Returns the entire table as an array of printable lines. Each element of * the array represents a physical line of the drawn table, including all * borders and stuff, so you can simply print the table using * * echo implode( "\n" , $table->getTable() ): * * which is basically what {@link ezcConsoleTable::outputTable()} does. * * @return array An array representation of the table. */ public function getTable() { return $this->generateTable(); } /** * Output the table. * Prints the complete table to the console. * * @return void */ public function outputTable() { echo implode( PHP_EOL, $this->generateTable() ); } /** * Returns the table in a string. * * @return string */ public function __toString() { return implode( PHP_EOL, $this->generateTable() ); } /** * Returns if the given offset exists. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. * * @param int $offset The offset to check. * @return bool True when the offset exists, otherwise false. * * @throws ezcBaseValueException * If a non numeric row ID is requested. */ public function offsetExists( $offset ) { if ( !is_int( $offset ) || $offset < 0 ) { throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' ); } return isset( $this->rows[$offset] ); } // From here only interface method implementations follow, which are not intended for direct usage /** * Returns the element with the given offset. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. In case of the * ezcConsoleTable class this method always returns a valid row object * since it creates them on the fly, if a given item does not exist. * * @param int $offset The offset to check. * @return ezcConsoleTableCell * * @throws ezcBaseValueException * If a non numeric row ID is requested. */ public function offsetGet( $offset ) { $offset = ( $offset === null ) ? count( $this->rows ) : $offset; if ( !is_int( $offset ) || $offset < 0 ) { throw new ezcBaseValueException( 'offset', $offset, 'int >= 0 or null' ); } if ( !isset( $this->rows[$offset] ) ) { $this->rows[$offset] = new ezcConsoleTableRow(); } return $this->rows[$offset]; } /** * Set the element with the given offset. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. * * @param int $offset The offset to assign an item to. * @param ezcConsoleTableRow $value The row to assign. * @return void * * @throws ezcBaseValueException * If a non numeric row ID is requested. * @throws ezcBaseValueException * If the provided value is not of type {@link ezcConsoleTableRow}. */ public function offsetSet( $offset, $value ) { if ( !( $value instanceof ezcConsoleTableRow ) ) { throw new ezcBaseValueException( 'value', $value, 'ezcConsoleTableRow' ); } if ( !isset( $offset ) ) { $offset = count( $this ); } if ( !is_int( $offset ) || $offset < 0 ) { throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' ); } $this->rows[$offset] = $value; } /** * Unset the element with the given offset. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. * * @param int $offset The offset to unset the value for. * @return void * * @throws ezcBaseValueException * If a non numeric row ID is requested. */ public function offsetUnset( $offset ) { if ( !is_int( $offset ) || $offset < 0 ) { throw new ezcBaseValueException( 'offset', $offset, 'int >= 0' ); } if ( isset( $this->rows[$offset] ) ) { unset( $this->rows[$offset] ); } } /** * Returns the number of cells in the row. * This method is part of the Countable interface to allow the usage of * PHP's count() function to check how many cells this row has. * * @return int Number of cells in this row. */ public function count() { $keys = array_keys( $this->rows ); return count( $keys ) > 0 ? ( end( $keys ) + 1 ) : 0; } /** * Returns the currently selected cell. * This method is part of the Iterator interface to allow access to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return ezcConsoleTableCell The currently selected cell. */ public function current() { return current( $this->rows ); } /** * Returns the key of the currently selected cell. * This method is part of the Iterator interface to allow access to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return int The key of the currently selected cell. */ public function key() { return key( $this->rows ); } /** * Returns the next cell and selects it or false on the last cell. * This method is part of the Iterator interface to allow access to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return mixed ezcConsoleTableCell if the next cell exists, or false. */ public function next() { return next( $this->rows ); } /** * Selects the very first cell and returns it. * This method is part of the Iterator interface to allow access to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return ezcConsoleTableCell The very first cell of this row. */ public function rewind() { return reset( $this->rows ); } /** * Returns if the current cell is valid. * This method is part of the Iterator interface to allow access to the * cells of this row by iterating over it like an array (e.g. using * foreach). * * @return ezcConsoleTableCell The very first cell of this row. */ public function valid() { return current( $this->rows ) !== false; } /** * Property read access. * * @param string $key Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __get( $key ) { switch ( $key ) { case 'options': case 'width': return $this->properties[$key]; default: break; } throw new ezcBasePropertyNotFoundException( $key ); } /** * Property write access. * * @param string $key Name of the property. * @param mixed $val The value for the property. * * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @throws ezcBaseValueException * If a the value for a property is out of range. * @ignore */ public function __set( $key, $val ) { switch ( $key ) { case 'options': if ( !( $val instanceof ezcConsoleTableOptions ) ) { throw new ezcBaseValueException( $key, $val, 'ezcConsoleTableOptions' ); } $this->properties['options'] = $val; return; case 'width': if ( $val < 1 ) { throw new ezcBaseValueException( $key, $val, 'int > 0' ); } $this->properties[$key] = $val; return; default: break; } throw new ezcBasePropertyNotFoundException( $key ); } /** * Property isset access. * * @param string $key Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $key ) { switch ( $key ) { case 'options': case 'width': case 'cols': return true; } return false; } /** * Generate the complete table as an array. * * @return array(string) The table. */ private function generateTable() { $colWidth = $this->getColWidths(); $table = array(); if ( $this->options->lineVertical !== null ) { $table[] = $this->generateBorder( $colWidth, ( isset( $this[0] ) ? $this[0]->borderFormat : 'default' ) ); } // Rows submitted by the user for ( $i = 0; $i < count( $this->rows ); $i++ ) { // Auto broken rows foreach ( $this->breakRows( $this->rows[$i], $colWidth ) as $brkRow => $brkCells ) { $table[] = $this->generateRow( $brkCells, $colWidth, $this->rows[$i] ); } $afterBorderFormat = isset( $this->rows[$i + 1] ) && $this->rows[$i + 1]->borderFormat != 'default' ? $this->rows[$i + 1]->borderFormat : $this->rows[$i]->borderFormat; if ( $this->options->lineVertical !== null ) { $table[] = $this->generateBorder( $colWidth, $afterBorderFormat ); } } // Empty tables need closing border if ( $this->options->lineVertical !== null && count( $this->rows ) == null ) { $table[] = $this->generateBorder( $colWidth, 'default' ); } return $table; } /** * Generate top/bottom borders of rows. * * @param array(int) $colWidth Array of column width. * @param string $format Format name. * @return string The Border string. */ private function generateBorder( $colWidth, $format ) { $border = ''; foreach ( $colWidth as $col => $width ) { $border .= ( $this->options->lineHorizontal !== null ? $this->properties['options']->corner : '' ) . str_repeat( $this->properties['options']->lineVertical, $width + ( 2 * iconv_strlen( $this->properties['options']->colPadding, 'UTF-8' ) ) ); } $border .= ( $this->options->lineHorizontal !== null ? $this->properties['options']->corner : '' ); return $this->formatText( $border, $format ); } /** * Generate a single physical row. * This method generates the string for a single physical table row. * * @param array(string) $cells Cells of the row. * @param array(int) $colWidth Calculated columns widths. * @param ezcConsoleTableRow $row The row to generate. * @return string The row. */ private function generateRow( $cells, $colWidth, $row ) { $rowData = ''; for ( $cell = 0; $cell < count( $colWidth ); $cell++ ) { $align = $this->determineAlign( $row, $cell ); $format = $this->determineFormat( $row, $cell ); $borderFormat = $this->determineBorderFormat( $row ); $data = isset( $cells[$cell] ) ? $cells[$cell] : ''; $rowData .= $this->formatText( $this->properties['options']->lineHorizontal, $borderFormat ); $rowData .= $this->properties['options']->colPadding; $rowData .= $this->formatText( $this->stringTool->strPad( $data, $colWidth[$cell], ' ', $align ), $format ); $rowData .= $this->properties['options']->colPadding; } $rowData .= $this->formatText( $this->properties['options']->lineHorizontal, $row->borderFormat ); return $rowData; } /** * Determine the alignment of a cell. * Walks the inheritance path upwards to determine the alignment of a * cell. Checks first, if the cell has it's own alignment (apart from * ezcConsoleTable::ALIGN_DEFAULT). If not, checks the row for an * alignment setting and uses the default alignment if not found. * * @param ezcConsoleTableRow $row The row this cell belongs to. * @param int $cellId Index of the desired cell. * @return int An alignement constant (ezcConsoleTable::ALIGN_*). */ private function determineAlign( $row, $cellId = 0 ) { return ( $row[$cellId]->align !== ezcConsoleTable::ALIGN_DEFAULT ? $row[$cellId]->align : ( $row->align !== ezcConsoleTable::ALIGN_DEFAULT ? $row->align : ( $this->properties['options']->defaultAlign !== ezcConsoleTable::ALIGN_DEFAULT ? $this->properties['options']->defaultAlign : ezcConsoleTable::ALIGN_LEFT ) ) ); } /** * Determine the format of a cells content. * Walks the inheritance path upwards to determine the format of a * cells content. Checks first, if the cell has it's own format (apart * from 'default'). If not, checks the row for a format setting and * uses the default format if not found. * * @param ezcConsoleTableRow $row The row this cell belongs to. * @param int $cellId Index of the desired cell. * @return string A format name. */ private function determineFormat( $row, $cellId ) { return ( $row[$cellId]->format != 'default' ? $row[$cellId]->format : ( $row->format !== 'default' ? $row->format : $this->properties['options']->defaultFormat ) ); } /** * Determine the format of a rows border. * Walks the inheritance path upwards to determine the format of a * rows border. Checks first, if the row has it's own format (apart * from 'default'). If not, uses the default format. * * @param ezcConsoleTableRow $row The row this cell belongs to. * @return string A format name. */ private function determineBorderFormat( $row ) { return $row->borderFormat !== 'default' ? $row->borderFormat : $this->properties['options']->defaultBorderFormat; } /** * Returns auto broken rows from an array of cells. * The data provided by a user may not fit into a cell calculated by the * class. In this case, the data can be automatically wrapped. The table * row then spans over multiple physical console lines. * * @param array(string) $cells Array of cells in one row. * @param array(int) $colWidth Columns widths array. * @return array(string) Physical rows generated out of this row. */ private function breakRows( $cells, $colWidth ) { $rows = array(); // Iterate through cells of the row foreach ( $colWidth as $cell => $width ) { $data = $cells[$cell]->content; // Physical row id, start with 0 for each row $row = 0; // Split into multiple physical rows if manual breaks exist $dataLines = explode( "\n", $data ); foreach ( $dataLines as $dataLine ) { // Does the physical row fit? if ( iconv_strlen( $dataLine, 'UTF-8' ) > ( $colWidth[$cell] ) ) { switch ( $this->properties['options']->colWrap ) { case ezcConsoleTable::WRAP_AUTO: $subLines = explode( "\n", $this->stringTool->wordwrap( $dataLine, $colWidth[$cell], "\n", true ) ); foreach ( $subLines as $lineNo => $line ) { $rows[$row++][$cell] = $line; } break; case ezcConsoleTable::WRAP_CUT: $rows[$row++][$cell] = iconv_substr( $dataLine, 0, $colWidth[$cell], 'UTF-8' ); break; case ezcConsoleTable::WRAP_NONE: default: $rows[$row++][$cell] = $dataLine; break; } } else { $rows[$row++][$cell] = $dataLine; } } } return $rows; } /** * Determine width of each single column. * * @return void */ private function getColWidths() { if ( is_array( $this->properties['options']->colWidth ) ) { return $this->properties['options']->colWidth; } // Determine number of columns: $colCount = 0; foreach ( $this->rows as $row ) { $colCount = max( sizeof( $row ), $colCount ); } if ( $colCount === 0 ) { return array( $this->width ); } $borderWidth = iconv_strlen( $this->properties['options']->lineHorizontal, 'UTF-8' ); // Subtract border and padding chars from global width $globalWidth = $this->width - ( // Per column: 2 * border padding + 1 border $colCount * ( 2 * iconv_strlen( $this->properties['options']->colPadding, 'UTF-8' ) + $borderWidth ) // 1 Additional border ) - $borderWidth; // Width of a column if each is made equal $colNormWidth = round( $globalWidth / $colCount ); $colMaxWidth = array(); // Determine the longest data for each column foreach ( $this->rows as $row => $cells ) { foreach ( $cells as $col => $cell ) { $contentLength = 0; foreach ( explode( PHP_EOL, $cell->content ) as $contentRow ) { $contentLength = max( $contentLength, iconv_strlen( $contentRow, 'UTF-8' ) ); } $colMaxWidth[$col] = isset( $colMaxWidth[$col] ) ? max( $colMaxWidth[$col], $contentLength ) : $contentLength; } } $colWidth = array(); $colWidthOverflow = array(); $spareWidth = 0; // Make columns best fit foreach ( $colMaxWidth as $col => $maxWidth ) { // Does the largest data of the column fit into the average size // + what we have in spare from earlier columns? if ( $maxWidth <= ( $colNormWidth + $spareWidth ) ) { // We fit in, make the column as large as necessary $colWidth[$col] = $maxWidth; $spareWidth += ( $colNormWidth - $maxWidth ); } else { // Does not fit, use maximal possible width $colWidth[$col] = $colNormWidth + $spareWidth; $spareWidth = 0; // Store overflow for second processing step $colWidthOverflow[$col] = $maxWidth - $colWidth[$col]; } } // Do we have spare to give to the columns again? if ( $spareWidth > 0 ) { // Second processing step if ( count( $colWidthOverflow ) > 0 ) { $overflowSum = array_sum( $colWidthOverflow ); foreach ( $colWidthOverflow as $col => $overflow ); { $colWidth[$col] += floor( $overflow / $overflowSum * $spareWidth ); } } elseif ( $this->properties['options']->widthType === ezcConsoleTable::WIDTH_FIXED ) { $widthSum = array_sum( $colWidth ); foreach ( $colWidth as $col => $width ) { $colWidth[$col] += floor( $width / $widthSum * $spareWidth ); } } } // Finally sanitize values from rounding issues, if necessary if ( ( $colSum = array_sum( $colWidth ) ) != $globalWidth && $this->properties['options']->widthType === ezcConsoleTable::WIDTH_FIXED ) { $colWidth[count( $colWidth ) - 1] -= $colSum - $globalWidth; } return $colWidth; } /** * Returns the given $text formatted with $format. * * In case $useFormats is set to false in the output handler, the text is * returned as given, without any formatting. * * @param string $text * @param string $format * @return string */ private function formatText( $text, $format ) { if ( $this->outputHandler->options->useFormats ) { return $this->outputHandler->formatText( $text, $format ); } else { return $text; } } } ?> PK!, ,ezc/ConsoleTools/options/question_dialog.phpnu[mixed) $options The initial options to set. */ public function __construct( array $options = array() ) { $this->properties["text"] = "Please enter a value: "; $this->properties["validator"] = new ezcConsoleQuestionDialogTypeValidator(); $this->properties["showResults"] = false; parent::__construct( $options ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyPermissionException * If the property you try to access is read-only. * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "text": if ( is_string( $propertyValue ) === false || strlen( $propertyValue ) < 1 ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "string, length > 0" ); } break; case "showResults": if ( is_bool( $propertyValue ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "bool" ); } break; case "validator": if ( ( $propertyValue instanceof ezcConsoleQuestionDialogValidator ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleQuestionDialogValidator" ); } break; default: parent::__set( $propertyName, $propertyValue ); return; } $this->properties[$propertyName] = $propertyValue; } } ?> PK!ͅ(ezc/ConsoleTools/options/progressbar.phpnu[$verbosityLevel} * that is needed by the progress bar to be rendered. If * $verbosityLevel is lower, the bar is skipped. Default is 0 to * render always. * @property int $maxVerbosity * Defines the maximum {ezcConsoleOutputOptions->$verbosityLevel} on * which the progress bar is rendered. If $verbosityLevel is higher, * the bar is skipped. Default is false, to render always. * * @package ConsoleTools * @version 1.6.1 */ class ezcConsoleProgressbarOptions extends ezcBaseOptions { protected $properties = array( 'barChar' => "+", 'emptyChar' => "-", 'formatString' => "%act% / %max% [%bar%] %fraction%%", 'fractionFormat' => "%01.2f", 'progressChar' => ">", 'redrawFrequency' => 1, 'step' => 1, 'width' => 78, 'actFormat' => '%.0f', 'maxFormat' => '%.0f', 'minVerbosity' => 1, 'maxVerbosity' => false, ); /** * Option write access. * * @throws ezcBasePropertyNotFoundException * If a desired property could not be found. * @throws ezcBaseValueException * If a desired property value is out of range. * * @param string $key Name of the property. * @param mixed $value The value for the property. * @ignore */ public function __set( $key, $value ) { switch ( $key ) { case "barChar": case "emptyChar": case "progressChar": case "formatString": case "fractionFormat": case "actFormat": case "maxFormat": if ( is_string( $value ) === false || strlen( $value ) < 1 ) { throw new ezcBaseValueException( $key, $value, 'string, not empty' ); } break; case "width": if ( !is_int( $value ) || $value < 5 ) { throw new ezcBaseValueException( $key, $value, 'int >= 5' ); } break; case "redrawFrequency": case "step": if ( ( !is_int( $value ) && !is_float( $value ) ) || $value < 1 ) { throw new ezcBaseValueException( $key, $value, 'int > 0' ); } break; case 'minVerbosity': if ( !is_int( $value ) || $value < 0 ) { throw new ezcBaseValueException( $key, $value, 'int >= 0' ); } break; case 'maxVerbosity': if ( ( !is_int( $value ) || $value < 0 ) && $value !== false ) { throw new ezcBaseValueException( $key, $value, 'int >= 0 or false' ); } break; default: throw new ezcBasePropertyNotFoundException( $key ); } $this->properties[$key] = $value; } } ?> PK!y&ezc/ConsoleTools/options/statusbar.phpnu[ "+", 'failureChar' => "-", ); /** * Option write access. * * @throws ezcBasePropertyNotFoundException * If a desired property could not be found. * @throws ezcBaseValueException * If a desired property value is out of range. * * @param string $key Name of the property. * @param mixed $value The value for the property. * @ignore */ public function __set( $key, $value ) { switch ( $key ) { case "successChar": case "failureChar": if ( is_string( $value ) === false || strlen( $value ) < 1 ) { throw new ezcBaseValueException( $key, $value, 'string, not empty' ); } break; default: throw new ezcBasePropertyNotFoundException( $key ); } $this->properties[$key] = $value; } } ?> PK!88HH"ezc/ConsoleTools/options/table.phpnu[ 'auto', 'colWrap' => ezcConsoleTable::WRAP_AUTO, 'defaultAlign' => ezcConsoleTable::ALIGN_LEFT, 'colPadding' => ' ', 'widthType' => ezcConsoleTable::WIDTH_MAX, 'lineVertical' => '-', 'lineHorizontal' => '|', 'corner' => '+', 'defaultFormat' => 'default', 'defaultBorderFormat' => 'default', ); /** * Construct a new options object. * * NOTE: For backwards compatibility reasons the old method of instantiating this class is kept, * but the usage of the new version (providing an option array) is highly encouraged. * * @param array(string=>mixed) $options The initial options to set. * @return void * * @throws ezcBasePropertyNotFoundException * If the value for the property options is not an instance of * @throws ezcBaseValueException * If the value for a property is out of range. */ public function __construct() { $args = func_get_args(); if ( func_num_args() === 1 && is_array( $args[0] ) && !is_int( key( $args[0] ) ) ) { parent::__construct( $args[0] ); } else { foreach ( $args as $id => $val ) { switch ( $id ) { case 0: $this->__set( 'colWidth', $val ); break; case 1: $this->__set( 'colWrap', $val ); break; case 2: $this->__set( 'defaultAlign', $val ); break; case 3: $this->__set( 'colPadding', $val ); break; case 4: $this->__set( 'widthType', $val ); break; case 5: $this->__set( 'lineVertical', $val ); break; case 6: $this->__set( 'lineHorizontal', $val ); break; case 7: $this->__set( 'corner', $val ); break; case 8: $this->__set( 'defaultFormat', $val ); break; case 9: $this->__set( 'defaultBorderFormat', $val ); break; } } } } /** * Property write access. * * @throws ezcBasePropertyNotFoundException * If a desired property could not be found. * @throws ezcBaseValueException * If a desired property value is out of range. * * @param string $propertyName Name of the property. * @param mixed $val The value for the property. * @ignore */ public function __set( $propertyName, $val ) { switch ( $propertyName ) { case 'colWidth': if ( is_array( $val ) === false && ( is_string( $val ) && $val !== 'auto' ) ) { throw new ezcBaseValueException( $propertyName, $val, 'array(int) or "auto"' ); } break; case 'colWrap': if ( $val !== ezcConsoleTable::WRAP_AUTO && $val !== ezcConsoleTable::WRAP_NONE && $val !== ezcConsoleTable::WRAP_CUT ) { throw new ezcBaseValueException( $propertyName, $val, 'ezcConsoleTable::WRAP_AUTO, ezcConsoleTable::WRAP_NONE, ezcConsoleTable::WRAP_CUT' ); } break; case 'defaultAlign': if ( $val !== ezcConsoleTable::ALIGN_DEFAULT && $val !== ezcConsoleTable::ALIGN_LEFT && $val !== ezcConsoleTable::ALIGN_CENTER && $val !== ezcConsoleTable::ALIGN_RIGHT ) { throw new ezcBaseValueException( $propertyName, $val, 'ezcConsoleTable::ALIGN_DEFAULT, ezcConsoleTable::ALIGN_LEFT, ezcConsoleTable::ALIGN_CENTER, ezcConsoleTable::ALIGN_RIGHT' ); } break; case 'colPadding': if ( !is_string( $val ) ) { throw new ezcBaseValueException( $propertyName, $val, 'string' ); } break; case 'widthType': if ( $val !== ezcConsoleTable::WIDTH_MAX && $val !== ezcConsoleTable::WIDTH_FIXED ) { throw new ezcBaseValueException( $propertyName, $val, 'ezcConsoleTable::WIDTH_MAX, ezcConsoleTable::WIDTH_FIXED' ); } break; case 'lineVertical': case 'lineHorizontal': case 'corner': if ( ( is_string( $val ) === false || strlen( $val ) !== 1 ) && $val !== null ) { throw new ezcBaseValueException( $propertyName, $val, 'string, length = 1, or null' ); } break; case 'defaultFormat': if ( is_string( $val ) === false || strlen( $val ) < 1 ) { throw new ezcBaseValueException( $propertyName, $val, 'string, length = 1' ); } break; case 'defaultBorderFormat': if ( is_string( $val ) === false || strlen( $val ) < 1 ) { throw new ezcBaseValueException( $propertyName, $val, 'string, length = 1' ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $val; } } ?> PK!*..#ezc/ConsoleTools/options/dialog.phpnu[mixed) */ protected $properties = array( "format" => "default", "validator" => null ); /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyPermissionException * If the property you try to access is read-only. * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "format": if ( is_string( $propertyValue ) === false || strlen( $propertyValue ) < 1 ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "string, length > 0" ); } break; case "validator": if ( ( $propertyValue instanceof ezcConsoleDialogValidator ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleDialogValidator" ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $propertyValue; } } ?> PK! BB,ezc/ConsoleTools/options/progressmonitor.phpnu[ '%8.1f%% %s %s', ); /** * Option write access. * * @throws ezcBasePropertyNotFoundException * If a desired property could not be found. * @throws ezcBaseValueException * If a desired property value is out of range. * * @param string $key Name of the property. * @param mixed $value The value for the property. * @ignore */ public function __set( $key, $value ) { switch ( $key ) { case "formatString": if ( is_string( $value ) === false || strlen( $value ) < 1 ) { throw new ezcBaseValueException( $key, $value, 'string, not empty' ); } break; default: throw new ezcBasePropertyNotFoundException( $key ); } $this->properties[$key] = $value; } } ?> PK!'J  #ezc/ConsoleTools/options/output.phpnu[mixed) $options The initial options to set. * @return void * * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @throws ezcBaseValueException * If a the value for a property is out of range. */ public function __construct() { $this->properties['verbosityLevel'] = 1; $this->properties['autobreak'] = 0; $this->properties['useFormats'] = true; $args = func_get_args(); if ( func_num_args() === 1 && is_array( $args[0] ) ) { parent::__construct( $args[0] ); } else { foreach ( $args as $id => $val ) { switch ( $id ) { case 0: $this->__set( "verbosityLevel", $val ); break; case 1: $this->__set( "autobreak", $val ); break; case 2: $this->__set( "useFormats", $val ); break; } } } } /** * Property write access. * * @throws ezcBasePropertyNotFoundException * If a desired property could not be found. * @throws ezcBaseValueException * If a desired property value is out of range. * * @param string $propertyName Name of the property. * @param mixed $val The value for the property. * @ignore */ public function __set( $propertyName, $val ) { switch ( $propertyName ) { case 'verbosityLevel': case 'autobreak': if ( !is_int( $val ) || $val < 0 ) { throw new ezcBaseValueException( $propertyName, $val, 'int >= 0' ); } break; case 'useFormats': if ( !is_bool( $val ) ) { throw new ezcBaseValueException( $propertyName, $val, 'bool' ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $val; } } ?> PK!Q(ezc/ConsoleTools/options/menu_dialog.phpnu[mixed) $options The initial options to set. */ public function __construct( array $options = array() ) { $this->properties["text"] = "Please choose an item."; $this->properties["formatString"] = "%3s) %s\n"; $this->properties["selectText"] = "Select: "; $this->properties["validator"] = new ezcConsoleMenuDialogDefaultValidator(); parent::__construct( $options ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyPermissionException * If the property you try to access is read-only. * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "text": if ( is_string( $propertyValue ) === false || strlen( $propertyValue ) < 1 ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "string, length > 0" ); } break; case "selectText": if ( is_string( $propertyValue ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "string" ); } break; case "formatString": if ( is_string( $propertyValue ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "string" ); } break; case "validator": if ( ( $propertyValue instanceof ezcConsoleMenuDialogValidator ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleMenuDialogValidator" ); } default: parent::__set( $propertyName, $propertyValue ); } $this->properties[$propertyName] = $propertyValue; } } ?> PK!cgg*ezc/ConsoleTools/structs/output_format.phpnu[mixed) */ protected $properties = array( 'color' => 'default', 'style' => array( 'default' ), 'bgcolor' => 'default', 'target' => ezcConsoleOutput::TARGET_OUTPUT, ); /** * Create a new ezcConsoleOutputFormat object. * Creates a new object of this class. * * @param string $color Name of a color value. * @param array(string) $style Names of style values. * @param string $bgcolor Name of a bgcolor value. * @param string $target Target output stream. */ public function __construct( $color = 'default', array $style = null, $bgcolor = 'default', $target = ezcConsoleOutput::TARGET_OUTPUT ) { $this->__set( 'color', $color ); $this->__set( 'style', isset( $style ) ? $style : array( 'default' ) ); $this->__set( 'bgcolor', $bgcolor ); $this->__set( 'target', $target ); } /** * Overloaded __get() method to gain read-only access to some attributes. * * @param string $propertyName Name of the property to read. * @return mixed Desired value if exists, otherwise null. * @ignore */ public function __get( $propertyName ) { switch ( $propertyName ) { case 'style': return (array) $this->properties[$propertyName]; case 'color': case 'bgcolor': case 'target': return $this->properties[$propertyName]; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } } /** * Overloaded __set() method to gain read-only access to properties. * It also performs checks on setting others. * * @throws ezcBasePropertyNotFoundException * If the setting you try to access does not exists * @throws ezcBaseValueException * If trying to set an invalid value for a setting. * * @param string $propertyName Name of the attrinbute to access. * @param string $val The value to set. * @ignore */ public function __set( $propertyName, $val ) { if ( !isset( $this->properties[$propertyName] ) ) { throw new ezcBasePropertyNotFoundException( $propertyName ); } // Extry handling of multi styles if ( $propertyName === 'style' ) { if ( !is_array( $val ) ) $val = array( $val ); foreach ( $val as $style ) { if ( !ezcConsoleOutput::isValidFormatCode( $propertyName, $style ) ) { throw new ezcBaseValueException( $propertyName, $style, 'valid ezcConsoleOutput format code' ); } } $this->properties['style'] = $val; return; } // Continue normal handling if ( ( $propertyName === "color" || $propertyName === "bgcolor" ) && !ezcConsoleOutput::isValidFormatCode( $propertyName, $val ) ) { throw new ezcBaseValueException( $propertyName, $val, 'valid ezcConsoleOutput format code' ); } $this->properties[$propertyName] = $val; } /** * Property isset access. * * @param string $propertyName Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $propertyName ) { return isset( $this->properties[$propertyName] ); } } ?> PK!#j''+ezc/ConsoleTools/structs/output_formats.phpnu[ * // New ezcConsoleOutput * // $output->format is instance of ezcConsoleOutputFormats. * $output = new ezcConsoleOutput(); * * // Default format - color = blue * $output->formats->default->color = 'blue'; * // Default format - weight = bold * $output->formats->default->style = array( 'bold' ); * * // New format "important" - color = red * $output->formats->important->color = 'red'; * // Format "important" - background color = black * $output->formats->important->bgcolor = 'black'; * * * @package ConsoleTools * @version 1.6.1 */ class ezcConsoleOutputFormats implements Iterator, Countable { /** * Array of ezcConsoleOutputFormat. * * @var array(ezcConsoleOutputFormat) */ protected $formats = array(); /** * Create a new ezcConsoleOutputFormats object. * * Creates a new, empty object of this class. It also adds a default * format. */ public function __construct() { $this->formats['default'] = new ezcConsoleOutputFormat(); $this->formats['success'] = new ezcConsoleOutputFormat(); $this->formats['success']->color = 'green'; $this->formats['success']->style = array( 'bold' ); $this->formats['failure'] = new ezcConsoleOutputFormat(); $this->formats['failure']->color = 'red'; $this->formats['failure']->style = array( 'bold' ); } /** * Returns the current Iterator value. * * Implementation of {@link Iterator::current()}. * * @return ezcConsoleOutputFormat */ public function current() { return current( $this->formats ); } /** * Advances the Iterator to the next element. * * Implementation of {@link Iterator::next()}. * * @return ezcConsoleOutputFormat|bool */ public function next() { return next( $this->formats ); } /** * Returns the current Iterator key. * * Implementation of {@link Iterator::key()}. * * @return string */ public function key() { return key( $this->formats ); } /** * Resets the Iterator to the first element. * * Implementation of {@link Iterator::rewind()}. * * @return ezcConsoleOutputFormat */ public function rewind() { return reset( $this->formats ); } /** * Checks if the current Iterator position is still valid. * * Implementation of {@link Iterator::valid()}. * * @return bool */ public function valid() { return ( current( $this->formats ) !== false ); } /** * Returns the number of registered formats. * * Implementation of {@link Countable::count()}. * * @return void */ public function count() { return count( $this->formats ); } /** * Read access to the formats. * * Formats are accessed directly like properties of this object. If a * format does not exist, it is created on the fly (using default values), * * @param string $formatName * @return ezcConsoleOutputFormat The format. */ public function __get( $formatName ) { if ( !isset( $this->formats[$formatName] ) ) { $this->formats[$formatName] = new ezcConsoleOutputFormat(); } return $this->formats[$formatName]; } /** * Write access to the formats. * * Formats are accessed directly like properties of this object. If a * format does not exist, it is created on the fly (using default values), * * @param string $formatName * @param ezcConsoleOutputFormat $val The format defintion. * @return void */ public function __set( $formatName, ezcConsoleOutputFormat $val ) { $this->formats[$formatName] = $val; } /** * Property isset access. * * @param string $formatName Name of the property. * @return bool True is the property is set, otherwise false. */ public function __isset( $formatName ) { return isset( $this->formats[$formatName] ); } } ?> PK!!{D(ezc/ConsoleTools/structs/option_rule.phpnu[option ezcConsoleOption, contains the parameter that this rule refers to. * - values array(string), contains a list of values that are accepted. * * @see ezcConsoleOption * * @package ConsoleTools * @version 1.6.1 */ class ezcConsoleOptionRule { /** * Properties. * * @var array */ protected $properties = array( 'option' => null, 'values' => array(), 'ifSet' => true ); /** * Creates a new option rule. * * Creates a new option rule. Per default the $values parameter * is an empty array, which determines that the option may accept any * value. To indicate that a option may only have certain values, * place them inside tha $values array. For example to indicate an option * may have the values 'a', 'b' and 'c' use: * * * $rule = new ezcConsoleOptionRule( $option, array( 'a', 'b', 'c' ) ); * * * If you want to allow only 1 specific value for an option, you do not * need to wrap this into an array, when creating the rule. Simply use * * * $rule = new ezcConsoleOptionRule( $option, 'a' ); * * * to create a rule, that allows the desired option only to accept the * value 'a'. * * The $ifSet parameter determines, if the rule is validated when its option * is set or left out. If $ifSet is true, the rule is validated when the * option is set. Otherwise the rule is validated if the option was not set * by the user. * * @param ezcConsoleOption $option The option to refer to. * @param mixed $values The affected values. * @param bool $ifSet */ public function __construct( ezcConsoleOption $option, array $values = array(), $ifSet = true ) { $this->__set( 'option', $option ); $this->__set( 'values', $values ); $this->__set( 'ifSet', $ifSet ); } /** * Property read access. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * * @param string $propertyName Name of the property. * @return mixed Value of the property or null. * @ignore */ public function __get( $propertyName ) { switch ( $propertyName ) { case 'option': return $this->properties['option']; case 'values': return $this->properties['values']; case 'ifSet': return $this->properties['ifSet']; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $propertyValue The value for the property. * * @throws ezcBasePropertyPermissionException * If the property you try to access is read-only. * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case 'option': if ( !( $propertyValue instanceof ezcConsoleOption ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcConsoleOption' ); } $this->properties['option'] = $propertyValue; return; case 'values': if ( !is_array( $propertyValue ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'array' ); } $this->properties['values'] = $propertyValue; return; case 'ifSet': if ( !is_bool( $propertyValue ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); } $this->properties['ifSet'] = $propertyValue; return; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property isset access. * * @param string $propertyName Name of the property to check. * @return bool If the property exists or not. * @ignore */ public function __isset( $propertyName ) { switch ( $propertyName ) { case 'option': case 'values': case 'ifSet': return true; } return false; } } ?> PK!\)|1ezc/ConsoleTools/exceptions/argument_too_many.phpnu[ PK!:  <ezc/ConsoleTools/exceptions/option_string_not_wellformed.phpnu[ PK!%agg:ezc/ConsoleTools/exceptions/option_mandatory_violation.phpnu[long}' is mandatory but was not submitted." ); } } ?> PK!J8&ezc/ConsoleTools/exceptions/option.phpnu[ PK!<ezc/ConsoleTools/exceptions/argument_mandatory_violation.phpnu[name}' is mandatory but was not submitted." ); } } ?> PK!:ezc/ConsoleTools/exceptions/option_exclusion_violation.phpnu[long}' excludes the option '{$excludedOption->long}'"; if ( $valueRange !== null ) { $message .= " to have a value in '{$valueRange}'"; } $message .= " but this one was submitted."; parent::__construct( $message ); } } ?> PK!5ezc/ConsoleTools/exceptions/option_type_violation.phpnu[type ) { case ezcConsoleInput::TYPE_NONE: $typeName = 'none'; break; case ezcConsoleInput::TYPE_INT: $typeName = 'int'; break; } parent::__construct( "The option '{$option->long}' expects a value of type '{$typeName}', but received the value '{$value}'." ); } } ?> PK! 7)ezc/ConsoleTools/exceptions/exception.phpnu[ PK!e8##1ezc/ConsoleTools/exceptions/option_not_exists.phpnu[ PK!arr7ezc/ConsoleTools/exceptions/argument_type_violation.phpnu[type ) { case ezcConsoleInput::TYPE_INT: $typeName = 'int'; break; } parent::__construct( "The argument '{$arg->name}' expects a value of type '{$typeName}', but received the value '{$value}'." ); } } ?> PK!XXDD;ezc/ConsoleTools/exceptions/argument_already_registered.phpnu[ PK!] 5(ezc/ConsoleTools/exceptions/argument.phpnu[ PK!ī2ezc/ConsoleTools/exceptions/no_position_stored.phpnu[ PK! a3ezc/ConsoleTools/exceptions/invalid_option_name.phpnu[ PK!|9ezc/ConsoleTools/exceptions/option_already_registered.phpnu[ PK!J:ezc/ConsoleTools/exceptions/option_arguments_violation.phpnu[long}' excludes the usage of arguments, but arguments have been submitted." ); } } ?> PK!BW95ezc/ConsoleTools/exceptions/invalid_output_target.phpnu[ PK!H6ezc/ConsoleTools/exceptions/no_valid_dialog_result.phpnu[ PK!=?,ezc/ConsoleTools/exceptions/dialog_abort.phpnu[-D to a dialog instead of a valid answer. * * @package ConsoleTools * @version 1.6.1 */ class ezcConsoleDialogAbortException extends ezcConsoleException { /** * Creates a new exception object. * * @param string $name Name of the already existing option. * @return void */ public function __construct() { parent::__construct( "User send EOF." ); } } ?> PK!ř4ezc/ConsoleTools/exceptions/option_missing_value.phpnu[long}' expects a value, but none was submitted." ); } } ?> PK!;ezc/ConsoleTools/exceptions/option_dependency_violation.phpnu[long}' depends on the option '{$dependantOption->long}' "; if ( $valueRange !== null ) { $message .= "to have a value in '{$valueRange}' "; } $message .= "but this one was not submitted."; parent::__construct( $message ); } } ?> PK!s  /ezc/ConsoleTools/exceptions/option_no_alias.phpnu[ PK!vv6ezc/ConsoleTools/exceptions/option_too_many_values.phpnu[long}' expects a single value, but multiple were submitted." ); } } ?> PK!= RLL!ezc/ConsoleTools/input/option.phpnu[mixed) */ protected $properties; /** * Dependency rules of this parameter. * * @see ezcConsoleOption::addDependency() * @see ezcConsoleOption::removeDependency() * @see ezcConsoleOption::hasDependency() * @see ezcConsoleOption::getDependencies() * @see ezcConsoleOption::resetDependencies() * * @var array(string=>ezcConsoleParamemterRule) */ protected $dependencies = array(); /** * Exclusion rules of this parameter. * * @see ezcConsoleOption::addExclusion() * @see ezcConsoleOption::removeExclusion() * @see ezcConsoleOption::hasExclusion() * @see ezcConsoleOption::getExclusions() * @see ezcConsoleOption::resetExclusions() * * @var array(string=>ezcConsoleParamemterRule) */ protected $exclusions = array(); /** * The value the parameter was assigned to when being submitted. * Boolean false indicates the parameter was not submitted, boolean * true means the parameter was submitted, but did not have a value. * In any other case, this caries the submitted value. * * @var mixed */ public $value = false; /** * Create a new parameter struct. * Creates a new basic parameter struct with the base information "$short" * (the short name of the parameter) and "$long" (the long version). You * simply apply these parameters as strings (without '-' or '--'). So * * * $param = new ezcConsoleOption( 'f', 'file' ); * * * will result in a parameter that can be accessed using * * * $ mytool -f * * * or * * * $ mytool --file * * . * * The newly created parameter contains only it's 2 names and each other * attribute is set to it's default value. You can simply manipulate * those attributes by accessing them directly. * * @param string $short Short name of the parameter without '-' (eg. 'f'). * @param string $long Long name of the parameter without '--' (eg. 'file'). * @param int $type Value type of the parameter. One of ezcConsoleInput::TYPE_*. * @param mixed $default Default value the parameter holds if not submitted. * @param bool $multiple If the parameter may be submitted multiple times. * @param string $shorthelp Short help text. * @param string $longhelp Long help text. * @param array(ezcConsoleOptionRule) $dependencies Dependency rules. * @param array(ezcConsoleOptionRule) $exclusions Exclusion rules. * @param bool $arguments Whether supplying arguments is allowed when this parameter is set. * @param bool $mandatory Whether the parameter must be always submitted. * @param bool $isHelpOption Indicates that the given parameter is a help * option. If a help option is set, all rule * checking is skipped (dependency/exclusion/ * mandatory). * * @throws ezcConsoleInvalidOptionNameException If the option names start with a "-" * sign or contain whitespaces. */ public function __construct( $short = '', $long, $type = ezcConsoleInput::TYPE_NONE, $default = null, $multiple = false, $shorthelp = 'No help available.', $longhelp = 'Sorry, there is no help text available for this parameter.', array $dependencies = array(), array $exclusions = array(), $arguments = true, $mandatory = false, $isHelpOption = false ) { $this->properties['short'] = ''; $this->properties['long'] = ''; $this->properties['arguments'] = $arguments; if ( !self::validateOptionName( $short ) ) { throw new ezcConsoleInvalidOptionNameException( $short ); } $this->properties['short'] = $short; if ( !self::validateOptionName( $long ) ) { throw new ezcConsoleInvalidOptionNameException( $long ); } $this->properties['long'] = $long; $this->__set( "type", $type !== null ? $type : ezcConsoleInput::TYPE_NONE ); $this->__set( "multiple", $multiple !== null ? $multiple : false ); $this->__set( "default", $default !== null ? $default : null ); $this->__set( "shorthelp", $shorthelp !== null ? $shorthelp : 'No help available.' ); $this->__set( "longhelp", $longhelp !== null ? $longhelp : 'Sorry, there is no help text available for this parameter.' ); $dependencies = $dependencies !== null && is_array( $dependencies ) ? $dependencies : array(); foreach ( $dependencies as $dep ) { $this->addDependency( $dep ); } $exclusions = $exclusions !== null && is_array( $exclusions ) ? $exclusions : array(); foreach ( $exclusions as $exc ) { $this->addExclusion( $exc ); } $this->__set( "mandatory", $mandatory !== null ? $mandatory : false ); $this->__set( "isHelpOption", $isHelpOption !== null ? $isHelpOption : false ); } /** * Add a new dependency for a parameter. * This registeres a new dependency rule with the parameter. If you try * to add an already registered rule it will simply be ignored. Else, * the submitted rule will be added to the parameter as a dependency. * * @param ezcConsoleOptionRule $rule The rule to add. * @return void */ public function addDependency( ezcConsoleOptionRule $rule ) { foreach ( $this->dependencies as $existRule ) { if ( $rule == $existRule ) { return; } } $this->dependencies[] = $rule; } /** * Remove a dependency rule from a parameter. * This removes a given rule from a parameter, if it exists. If the rule is * not registered with the parameter, the method call will simply be ignored. * * @param ezcConsoleOptionRule $rule The rule to be removed. * @return void */ public function removeDependency( ezcConsoleOptionRule $rule ) { foreach ( $this->dependencies as $id => $existRule ) { if ( $rule == $existRule ) { unset( $this->dependencies[$id] ); } } } /** * Remove all dependency rule referring to a parameter. * This removes all dependency rules from a parameter, that refer to as specific * parameter. If no rule is registered with this parameter as reference, the * method call will simply be ignored. * * @param ezcConsoleOption $param The param to be check for rules. * @return void */ public function removeAllDependencies( ezcConsoleOption $param ) { foreach ( $this->dependencies as $id => $rule ) { if ( $rule->option == $param ) { unset( $this->dependencies[$id] ); } } } /** * Returns if a dependency to the given option exists. * Returns true if a dependency rule to the given option is registered, * otherwise false. * * @param ezcConsoleOption $param The param to check if a dependency exists to. * @return bool True if rule is registered, otherwise false. */ public function hasDependency( ezcConsoleOption $param ) { foreach ( $this->dependencies as $id => $rule ) { if ( $rule->option == $param ) { return true; } } return false; } /** * Returns the dependency rules registered with this parameter. * Returns an array of registered dependencies. * * For example: * * array( * 0 => ezcConsoleOptionRule, * 1 => ezcConsoleOptionRule, * 2 => ezcConsoleOptionRule, * ); * * * @return array(ezcConsoleOptionRule) Dependency definition. */ public function getDependencies() { return $this->dependencies; } /** * Reset existing dependency rules. * Deletes all registered dependency rules from the option definition. * * @return void */ public function resetDependencies() { $this->dependencies = array(); } /** * Add a new exclusion for an option. * This registeres a new exclusion rule with the option. If you try * to add an already registered rule it will simply be ignored. Else, * the submitted rule will be added to the option as a exclusion. * * @param ezcConsoleOptionRule $rule The rule to add. * @return void */ public function addExclusion( ezcConsoleOptionRule $rule ) { foreach ( $this->exclusions as $existRule ) { if ( $rule == $existRule ) { return; } } $this->exclusions[] = $rule; } /** * Remove a exclusion rule from a option. * This removes a given rule from a option, if it exists. If the rule is * not registered with the option, the method call will simply be ignored. * * @param ezcConsoleOptionRule $rule The rule to be removed. * @return void */ public function removeExclusion( ezcConsoleOptionRule $rule ) { foreach ( $this->exclusions as $id => $existRule ) { if ( $rule == $existRule ) { unset( $this->exclusions[$id] ); } } } /** * Remove all exclusion rule referring to a option. * This removes all exclusion rules from a option, that refer to as specific * option. If no rule is registered with this option as reference, the * method call will simply be ignored. * * @param ezcConsoleOption $param The option to remove rule for. * @return void */ public function removeAllExclusions( ezcConsoleOption $param ) { foreach ( $this->exclusions as $id => $rule ) { if ( $rule->option == $param ) { unset( $this->exclusions[$id] ); } } } /** * Returns if a given exclusion rule is registered with the option. * Returns true if a exclusion rule to the given option is registered, * otherwise false. * * @param ezcConsoleOption $param The param to check if exclusions exist for. * @return bool True if rule is registered, otherwise false. */ public function hasExclusion( ezcConsoleOption $param ) { foreach ( $this->exclusions as $id => $rule ) { if ( $rule->option == $param ) { return true; } } return false; } /** * Returns the exclusion rules registered with this parameter. * Returns an array of registered exclusions. * * For example: * * array( * 0 => ezcConsoleOptionRule, * 1 => ezcConsoleOptionRule, * 2 => ezcConsoleOptionRule, * ); * * * @return array(ezcConsoleOptionRule) Exclusions definition. */ public function getExclusions() { return $this->exclusions; } /** * Reset existing exclusion rules. * Deletes all registered exclusion rules from the option definition. * * @return void */ public function resetExclusions() { $this->exclusions = array(); } /** * Property read access. * Provides read access to the properties of the object. * * @param string $key The name of the property. * @return mixed The value if property exists and isset, otherwise null. * @ignore */ public function __get( $key ) { switch ( $key ) { case 'short': case 'long': case 'type': case 'default': case 'multiple': case 'shorthelp': case 'longhelp': case 'arguments': case 'isHelpOption': case 'mandatory': return $this->properties[$key]; case 'dependencies': default: throw new ezcBasePropertyNotFoundException( $key ); } } /** * Property write access. * * @param string $key Name of the property. * @param mixed $val The value for the property. * * @throws ezcBasePropertyPermissionException * If the property you try to access is read-only. * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * @ignore */ public function __set( $key, $val ) { switch ( $key ) { case 'type': if ( $val !== ezcConsoleInput::TYPE_NONE && $val !== ezcConsoleInput::TYPE_INT && $val !== ezcConsoleInput::TYPE_STRING ) { throw new ezcBaseValueException( $key, $val, 'ezcConsoleInput::TYPE_STRING, ezcConsoleInput::TYPE_INT or ezcConsoleInput::TYPE_NONE' ); } break; case 'default': if ( ( is_scalar( $val ) === false && $val !== null ) ) { // Newly allow arrays, if multiple is true if ( $this->multiple === true && is_array( $val ) === true ) { break; } throw new ezcBaseValueException( $key, $val, 'a string or a number, if multiple == true also an array' ); } break; case 'multiple': if ( !is_bool( $val ) ) { throw new ezcBaseValueException( $key, $val, 'bool' ); } break; case 'shorthelp': if ( !is_string( $val ) ) { throw new ezcBaseValueException( $key, $val, 'string' ); } break; case 'longhelp': if ( !is_string( $val ) ) { throw new ezcBaseValueException( $key, $val, 'string' ); } break; case 'arguments': if ( !is_bool( $val ) ) { throw new ezcBaseValueException( $key, $val, 'bool' ); } break; case 'mandatory': if ( !is_bool( $val ) ) { throw new ezcBaseValueException( $key, $val, 'bool' ); } break; case 'isHelpOption': if ( !is_bool( $val ) ) { throw new ezcBaseValueException( $key, $val, 'bool' ); } break; case 'long': case 'short': throw new ezcBasePropertyPermissionException( $key, ezcBasePropertyPermissionException::READ ); break; default: throw new ezcBasePropertyNotFoundException( $key ); break; } $this->properties[$key] = $val; } /** * Property isset access. * * @param string $key Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $key ) { switch ( $key ) { case 'short': case 'long': case 'type': case 'default': case 'multiple': case 'shorthelp': case 'longhelp': case 'arguments': case 'isHelpOption': case 'mandatory': return ( $this->properties[$key] !== null ); } return false; } /** * Returns if a given name if valid for use as a parameter name a parameter. * Checks if a given parameter name is generally valid for use. It checks a) * that the name does not start with '-' or '--' and b) if it contains * whitespaces. Note, that this method does not check any conflicts with already * used parameter names. * * @param string $name The name to check. * @return bool True if the name is valid, otherwise false. */ public static function validateOptionName( $name ) { if ( substr( $name, 0, 1 ) === '-' || strpos( $name, ' ' ) !== false ) { return false; } return true; } } ?> PK! t^^$ezc/ConsoleTools/input/arguments.phpnu[ezcConsoleArgument) */ protected $named = array(); /** * Returns if the given offset exists. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. Valid offsets are integers or * strings. If an integer is used, it refers to the position in the command * line. A string refers to the arguments name property. * * @param mixed $offset The offset to check. * @return bool True when the offset exists, otherwise false. * * @throws ezcBaseValueException * If the provided offset is neither an integer, nor a string. */ public function offsetExists( $offset ) { switch ( gettype( $offset ) ) { case "string": return array_key_exists( $offset, $this->named ); case "integer": return array_key_exists( $offset, $this->ordered ); default: throw new ezcBaseValueException( "offset", $offset, "string or int" ); } } /** * Returns the element with the given offset. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. Valid offsets are integers or * strings. If an integer is used, it refers to the position in the command * line. A string refers to the arguments name property. * * @param string|integer $offset The offset to check. * @return ezcConsoleArgument * * @throws ezcBaseValueException * If the provided offset is neither an integer, nor a string. */ public function offsetGet( $offset ) { switch ( gettype( $offset ) ) { case "string": if ( isset( $this[$offset] ) ) { return $this->named[$offset]; } break; case "integer": if ( isset( $this[$offset] ) ) { return $this->ordered[$offset]; } break; default: throw new ezcBaseValueException( "offset", $offset, "string or int" ); } throw new ezcBasePropertyNotFoundException( $offset ); } /** * Set the element with the given offset. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. In contrast to the other * ArrayAccess implementations of this class, this method allows only integer * keys. * * @param int $offset The offset to assign an item to. * @param ezcConsoleArgument $value The argument object to register. * @return void * * @throws ezcBaseValueException * If a non integer offset is provided. * @throws ezcBaseValueException * If the provided value is not of type {@ling ezcConsoleTableRow}. * @throws ezcConsoleArgumentAlreadyRegisteredException * If an argument with the given offset or name is already registered. */ public function offsetSet( $offset, $value ) { // Determine key if not set (using $obj[] = ...) if ( $offset === null ) { $offset = count( $this->ordered ) === 0 ? 0 : max( array_keys( $this->ordered ) ) + 1; } // Set access only allowed with integer values if ( !is_int( $offset ) ) { throw new ezcBaseValueException( "offset", $offset, "int" ); } switch ( true ) { case ( $value instanceof ezcConsoleArgument ): if ( isset( $this->ordered[$offset] ) ) { throw new ezcConsoleArgumentAlreadyRegisteredException( $offset, ezcConsoleArgumentAlreadyRegisteredException::ORDERED ); } if ( isset( $this->named[$value->name] ) ) { throw new ezcConsoleArgumentAlreadyRegisteredException( $value->name, ezcConsoleArgumentAlreadyRegisteredException::NAMED ); } $this->named[$value->name] = $value; $this->ordered[$offset] = $value; break; case ( $value === null ): // Aliasing unset() with assignement to null unset( $this->named[$this->ordered[$offset]->name] ); unset( $this->ordered[$offset] ); break; default: throw new ezcBaseValueException( "value", $value, "ezcConsoleArgument or null" ); } } /** * Unset the element with the given offset. * This method is part of the ArrayAccess interface to allow access to the * data of this object as if it was an array. In contrast to the other * ArrayAccess implementations of this class, this method allows only integer * keys. * * @param int $offset The offset to unset the value for. * @return void * * @throws ezcBaseValueException * If a non numeric row offset is used. */ public function offsetUnset( $offset ) { // Set access only allowed with integer values if ( is_int( $offset ) === false ) { throw new ezcBaseValueException( "offset", $offset, "int" ); } unset( $this->named[$this->ordered[$offset]->name] ); unset( $this->ordered[$offset] ); } /** * Returns the currently selected argument from the list. * Used by foreach-Loops. * * @return ezcConsoleArgument */ public function current() { return current( $this->ordered ); } /** * Returns the key of the currently selected argument from the list. * Used by foreach-Loops. In contrast to the iteration direction, which is * defined by the ordered list of arguments, this is the name of the * argument. * * @return string */ public function key() { return key( $this->ordered ); } /** * Advances the internal pointer to the next argument and returns it. * Used by foreach-Loops. * * @return ezcConsoleArgument */ public function next() { return next( $this->ordered ); } /** * Rewinds the internal pointer to the first argument and returns it. * Used by foreach-Loops. * * @return ezcConsoleArgument */ public function rewind() { // Called before foreach ksort( $this->ordered ); return reset( $this->ordered ); } /** * Checks if the current position is valid. * Used by foreach-Loops. * * @return bool */ public function valid() { return ( current( $this->ordered ) !== false ); } /** * Returns the number of registered arguments. * * @return int */ public function count() { return count( $this->ordered ); } } ?> PK!%663ezc/ConsoleTools/input/help_generators/standard.phpnu[input = $input; } /** * Generates help information as a multidimensional array. * * This method generates a tabular view on the help information of a * program. The returned array has the following structure: * * * array( * 0 => ' * * Each row of the array represents the help information for a single option. * The first cell of a row contains the option name (maybe short, long or * both), the second cell contains the help text of the option. * * The returned array is used by {@link ezcConsoleInput} for different * purposes. * For example, the user can retrieve it raw through the * {@link ezcConsoleInput::getHelp()} method, he can generate a help * {@link ezcConsoleTable} through {@link ezcConsoleInput::getHelpTable()} * are can generate a printable help text through {@link * ezcConsoleInput::getHelpText()}. * * The parameter $long defines if the long or short help text of the * options should be used in the second cell of the returned array. The * $optionsFilter parameter is used to restrict the generated help to a certain * sub-set of options. It consists of an array of short or long names of * the options to include. * * @param bool $long * @param array(string) $optionsFilter * @return array(array(string)) */ public function generateUngroupedOptionHelp( $long = false, array $optionsFilter = null ) { $help = array(); foreach ( $this->input->getOptions() as $id => $param ) { if ( $optionsFilter === null || in_array( $param->short, $optionsFilter ) || in_array( $param->long, $optionsFilter ) ) { $help[] = $this->getOptionHelpRow( $long, $param ); } } return $help; } /** * Generates help information as a multidimensional array, grouped in categories. * * This method behaves similar to {@link generateUngroupedOptionHelp()}. In * contrast to the latter one, this method returns an array with 1 * dimension more, grouping options into categories. The $groups parameter * defines the categories to generate. Each category may contain an * arbitrary number of options, options might occur in different * categories. * * The returned array has the follorwing format: * * * ' => array( * 0 => array( * 0 => ' * * The $long parameter, as in {@link generateUngroupedOptionHelp()} * determines if the options short or long help is to be used. The * $params array can in addition be used to determine if a parameter * is displayed at all. If $optionsFilter is submitted and is not null, * only options listed in it will be shown in the help at all. * * @param array(string=>array(string)) $groups * @param bool $long * @param array(string) $params * @return array(string=>array(array(string))) */ public function generateGroupedOptionHelp( array $groups, $long = false, array $optionsFilter = null ) { $help = array(); foreach ( $groups as $groupName => $groupOptions ) { foreach ( $groupOptions as $optionName ) { $option = $this->input->getOption( $optionName ); if ( $optionsFilter === null || in_array( $option->short, $optionsFilter ) || in_array( $option->long, $optionsFilter ) ) { $help[$groupName][] = $this->getOptionHelpRow( $long, $option ); } } } return $help; } /** * Generates help information as a multi-dimensonal array for the given $argumentDefinition. * * This method generates a tabular help information for the given * $argumentDefinition in the following format: * * * array( * 0 => '', * 1 => '' * ), * 1 => array( * 0 => '', * 1 => '' * ), * // ... * ) * ?> * * * The $long parameter defines if the long of short help text should be * used. * * @param bool $long * @return array(array(string)) */ public function generateArgumentHelp( $long = false ) { $help = array(); if ( $this->input->argumentDefinition !== null ) { foreach ( $this->input->argumentDefinition as $arg ) { $argSynopsis = "<%s:%s>"; switch ( $arg->type ) { case ezcConsoleInput::TYPE_INT: $type = "int"; break; case ezcConsoleInput::TYPE_STRING: $type = "string"; break; } $argSynopsis = sprintf( $argSynopsis, $type, $arg->name ); $help[] = ( $long === true ) ? array( $argSynopsis, $arg->longhelp . ( $arg->mandatory === false ? ' (optional' . ( $arg->default !== null ? ', default = ' . ( is_array( $arg->default ) ? "'" . implode( "' '", $arg->default ) . "'" : "'$arg->default'" ) : '' ) . ')' : '' ) ) : array( $argSynopsis, $arg->shorthelp ); } } return $help; } /** * Creates 1 text row for displaying options help. * * Returns a single array entry for the {@link getOptionHelpRow()} method. * * @param bool $long * @param ezcConsoleOption $param * @return string */ private function getOptionHelpRow( $long, ezcConsoleOption $param ) { return array( ( $param->short !== "" ? '-' . $param->short . ' / ' : "" ) . '--' . $param->long, $long == false ? $param->shorthelp : $param->longhelp, ); } /** * Generates a command line synopsis for the options and arguments. * * This method generates a synopsis string that lists the options and * parameters available, indicating their usage. If $optionsFilter is * submitted, only the options named in this array (short or long variant) * will be included in the synopsis. * * @param array(string) $optionsFilter * @return string */ public function generateSynopsis( array $optionFilter = null ) { $usedOptions = array( 'short' => array(), 'long' => array() ); $allowsArgs = true; $synopsis = '$ ' . ( isset( $argv ) && sizeof( $argv ) > 0 ? $argv[0] : $_SERVER['argv'][0] ) . ' '; foreach ( $this->input->getOptions() as $option ) { if ( $optionFilter === null || in_array( $option->short, $optionFilter ) || in_array( $option->long, $optionFilter ) ) { $synopsis .= $this->createOptionSynopsis( $option, $usedOptions, $allowsArgs ); } } if ( $this->input->argumentDefinition === null ) { // Old handling $synopsis .= " [[--] ]"; } else { $synopsis .= "[--] " . $this->createArgumentsSynopsis(); } return $synopsis; } /** * Returns the synopsis string for a single option and its dependencies. * * This method returns a part of the program synopsis, specifically for a * certain parameter. The method recursively adds depending parameters up * to the 2nd depth level to the synopsis. The second parameter is used * to store the short names of all options that have already been used in * the synopsis (to avoid adding an option twice). The 3rd parameter * determines the actual deps in the option dependency recursion to * terminate that after 2 recursions. * * @param ezcConsoleOption $option The option to include. * @param array(string) $usedOptions Array of used option short names. * @param int $depth Current recursion depth. * @return string The synopsis for this parameter. */ private function createOptionSynopsis( ezcConsoleOption $option, &$usedOptions, $depth = 0 ) { $synopsis = ''; // Break after a nesting level of 2 if ( $depth++ > 2 || ( in_array( $option->short, $usedOptions['short'] ) && in_array( $option->long, $usedOptions['long'] ) ) ) return $synopsis; $usedOptions['short'][] = $option->short; $usedOptions['long'][] = $option->long; $synopsis .= $option->short !== "" ? "-{$option->short}" : "--{$option->long}"; if ( isset( $option->default ) ) { $synopsis .= " " . ( $option->type === ezcConsoleInput::TYPE_STRING ? '"' : '' ) . $option->default . ( $option->type === ezcConsoleInput::TYPE_STRING ? '"' : '' ); } else if ( $option->type !== ezcConsoleInput::TYPE_NONE ) { $synopsis .= " "; switch ( $option->type ) { case ezcConsoleInput::TYPE_STRING: $synopsis .= ""; break; case ezcConsoleInput::TYPE_INT: $synopsis .= ""; break; } } foreach ( $option->getDependencies() as $rule ) { $deeperSynopsis = $this->createOptionSynopsis( $rule->option, $usedOptions, $depth ); $synopsis .= ( iconv_strlen( trim( $deeperSynopsis ), 'UTF-8' ) > 0 ? ' ' . $deeperSynopsis : '' ); } if ( $option->arguments === false ) { $allowsArgs = false; } // Make the whole thing optional? if ( $option->mandatory === false ) { $synopsis = "[$synopsis]"; } return $synopsis . ' '; } /** * Generate synopsis for arguments. * * @return string The synopsis string. */ private function createArgumentsSynopsis() { $mandatory = true; $synopsises = array(); foreach ( $this->input->argumentDefinition as $arg ) { $argSynopsis = ""; if ( $arg->mandatory === false ) { $mandatory = false; } $argSynopsis .= "<%s:%s>"; switch ( $arg->type ) { case ezcConsoleInput::TYPE_INT: $type = "int"; break; case ezcConsoleInput::TYPE_STRING: $type = "string"; break; } $argSynopsis = sprintf( $argSynopsis, $type, $arg->name ); $synopsises[] = $mandatory === false ? "[$argSynopsis]" : $argSynopsis; if ( $arg->multiple === true ) { $synopsises[] = "[$argSynopsis ...]"; break; } } return implode( " ", $synopsises ); } } ?> PK!p#ezc/ConsoleTools/input/argument.phpnu[ null, "type" => ezcConsoleInput::TYPE_STRING, "shorthelp" => "No help available.", "longhelp" => "There is no help for this argument available.", "mandatory" => true, "multiple" => false, "default" => null, "value" => null, ); /** * Creates a new console argument object. * Creates a new console argument object, which represents a single * argument on the shell. Arguments are stored insiede * {@link ezcConsoleArguments} which is used with {@link ezcConsoleInput}. * * For the type property see {@link ezcConsoleInput::TYPE_STRING} and * {@link ezcConsoleInput::TYPE_INT}. If 1 argument is defined as optional * ($mandatory = false), all following arguments are autolamtically * considered optional, too. * * @param string $name The name for the argument. Must be unique. * @param int $type The value type. * @param string $shorthelp A short help text. * @param string $longhelp A long help text- * @param bool $mandatory Whether the argument is mandatory. * @param bool $multiple Whether the argument accepts multiple values. * @param mixed $default A default value, if not mandatory. * @return void */ public function __construct( $name = null, $type = ezcConsoleInput::TYPE_STRING, $shorthelp = "No help available.", $longhelp = "There is no help for this argument available.", $mandatory = true, $multiple = false, $default = null ) { if ( !is_string( $name ) || strlen( $name ) < 1 ) { throw new ezcBaseValueException( "name", $name, "string, length > 0" ); } $this->properties["name"] = $name; $this->type = $type; $this->shorthelp = $shorthelp; $this->longhelp = $longhelp; $this->mandatory = $mandatory; $this->multiple = $multiple; $this->default = $default; } /** * Property set access. * * @param string $propertyName Name of the property. * @param string $propertyValue Valze for the property. * @return void * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "name": throw new ezcBasePropertyPermissionException( $propertyName, ezcBasePropertyPermissionException::READ ); break; case "type": if ( $propertyValue !== ezcConsoleInput::TYPE_INT && $propertyValue !== ezcConsoleInput::TYPE_STRING ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "string, length > 0" ); } break; case "shorthelp": case "longhelp": if ( is_string( $propertyValue ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "string" ); } break; case "mandatory": case "multiple": if ( is_bool( $propertyValue ) === false ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "bool" ); } break; case "default": if ( is_scalar( $propertyValue ) === false && is_array( $propertyValue ) === false && $propertyValue !== null ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "array, scalar or null" ); } break; case "value": if ( is_scalar( $propertyValue ) === false && is_array( $propertyValue ) === false && $propertyValue !== null ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "string or null" ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $propertyValue; } /** * Property read access. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * * @param string $propertyName Name of the property. * @return mixed Value of the property or null. * @ignore */ public function __get( $propertyName ) { if ( isset( $this->$propertyName ) ) { return $this->properties[$propertyName]; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property isset access. * * @param string $propertyName Name of the property. * @return bool True is the property is set, otherwise false. * @ignore */ public function __isset( $propertyName ) { return array_key_exists( $propertyName, $this->properties ); } } ?> PK!&T.ezc/ConsoleTools/input/validators/standard.phpnu[ $option ) { if ( $option->mandatory === true && $option->value === false ) { throw new ezcConsoleOptionMandatoryViolationException( $option ); } $this->validateDependencies( $option ); $this->validateExclusions( $option ); if ( $option->arguments === false && $option->value !== false && $hasArguments ) { throw new ezcConsoleOptionArgumentsViolationException( $option ); } } } /** * Validated option dependencies. * * Validates dependencies by $option. * * @param ezcConsoleOption $option. */ private function validateDependencies( ezcConsoleOption $option ) { $optSet = ( $option->value !== false && ( !is_array( $option->value ) || $option->value !== array() ) ); foreach ( $option->getDependencies() as $dep ) { if ( $dep->ifSet === $optSet ) { $this->validateDependency( $option, $dep ); } } } /** * Validates a single dependency. * * Validates the dependency $dep, which is set in the $srcOpt. * * @param ezcConsoleOption $srcOpt * @param ezcConsoleOptionRule $dep */ private function validateDependency( ezcConsoleOption $srcOpt, ezcConsoleOptionRule $dep ) { $optValue = $dep->option->value; if ( $optValue === false || $optValue === array() ) { throw new ezcConsoleOptionDependencyViolationException( $srcOpt, $dep->option ); } if ( $dep->values !== array() ) { $optVals = ( is_array( $optValue ) ? $optValue : array( $optValue) ); $unrecognizedVals = array_diff( $optVals, $dep->values ); if ( $unrecognizedVals !== array() ) { throw new ezcConsoleOptionDependencyViolationException( $srcOpt, $dep->option, implode( ', ', $dep->values ) ); } } } /** * Validated option exclusions. * * Validates exclusions by $option. * * @param ezcConsoleOption $option. */ private function validateExclusions( ezcConsoleOption $option ) { $optSet = ( $option->value !== false && ( !is_array( $option->value ) || $option->value !== array() ) ); foreach ( $option->getExclusions() as $excl ) { if ( $excl->ifSet === $optSet ) { $this->validateExclusion( $option, $excl ); } } } /** * Validates a single exclusion. * * Validates the exclusion $excl, which is set in the $srcOpt. * * @param ezcConsoleOption $srcOpt * @param ezcConsoleOptionRule $excl */ private function validateExclusion( ezcConsoleOption $srcOpt, ezcConsoleOptionRule $excl ) { $optValue = $excl->option->value; if ( $optValue !== false && $optValue !== array() && $excl->values === array() ) { throw new ezcConsoleOptionExclusionViolationException( $srcOpt, $excl->option ); } $optVals = ( is_array( $optValue ) ? $optValue : array( $optValue ) ); $forbiddenVals = array_intersect( $optVals, $excl->values ); if ( $forbiddenVals !== array() ) { throw new ezcConsoleOptionExclusionViolationException( $srcOpt, $excl->option, implode( ', ', $excl->values ) ); } } } ?> PK!T\GGezc/ConsoleTools/input.phpnu[ * $optionHandler = new ezcConsoleInput(); * * // Register simple parameter -h/--help * $optionHandler->registerOption( new ezcConsoleOption( 'h', 'help' ) ); * * // Register complex parameter -f/--file * $file = new ezcConsoleOption( * 'f', * 'file', * ezcConsoleInput::TYPE_STRING, * null, * false, * 'Process a file.', * 'Processes a single file.' * ); * $optionHandler->registerOption( $file ); * * // Manipulate parameter -f/--file after registration * $file->multiple = true; * * // Register another complex parameter that depends on -f and excludes -h * $dir = new ezcConsoleOption( * 'd', * 'dir', * ezcConsoleInput::TYPE_STRING, * null, * true, * 'Process a directory.', * 'Processes a complete directory.', * array( new ezcConsoleOptionRule( $optionHandler->getOption( 'f' ) ) ), * array( new ezcConsoleOptionRule( $optionHandler->getOption( 'h' ) ) ) * ); * $optionHandler->registerOption( $dir ); * * // Register an alias for this parameter * $optionHandler->registerAlias( 'e', 'extended-dir', $dir ); * * // Process registered parameters and handle errors * try * { * $optionHandler->process( array( 'example_input.php', '-h' ) ); * } * catch ( ezcConsoleOptionException $e ) * { * echo $e->getMessage(); * exit( 1 ); * } * * // Process a single parameter * $file = $optionHandler->getOption( 'f' ); * if ( $file->value === false ) * { * echo "Parameter -{$file->short}/--{$file->long} was not submitted.\n"; * } * elseif ( $file->value === true ) * { * echo "Parameter -{$file->short}/--{$file->long} was submitted without value.\n"; * } * else * { * echo "Parameter -{$file->short}/--{$file->long} was submitted with value '".var_export($file->value, true)."'.\n"; * } * * // Process all parameters at once: * foreach ( $optionHandler->getOptionValues() as $paramShort => $val ) * { * switch ( true ) * { * case $val === false: * echo "Parameter $paramShort was not submitted.\n"; * break; * case $val === true: * echo "Parameter $paramShort was submitted without a value.\n"; * break; * case is_array( $val ): * echo "Parameter $paramShort was submitted multiple times with value: '".implode(', ', $val)."'.\n"; * break; * default: * echo "Parameter $paramShort was submitted with value: '$val'.\n"; * break; * } * } * * * @package ConsoleTools * @version 1.6.1 * @mainclass * * @property ezcConsoleArguments $argumentDefinition Optional argument definition. */ class ezcConsoleInput { /** * Option does not carry a value. */ const TYPE_NONE = 1; /** * Option takes an integer value. */ const TYPE_INT = 2; /** * Option takes a string value. */ const TYPE_STRING = 3; /** * Array of option definitions, indexed by number. * * This array stores the ezcConsoleOption objects representing * the options. * * For lookup of an option after its short or long values the attributes * {@link ezcConsoleInput::$optionShort} * {@link ezcConsoleInput::$optionLong} * are used. * * @var array(array) */ private $options = array(); /** * Short option names. * * Each references a key in {@link ezcConsoleInput::$options}. * * @var array(string=>int) */ private $optionShort = array(); /** * Long option names. * * Each references a key in {@link ezcConsoleInput::$options}. * * @var array(string=>int) */ private $optionLong = array(); /** * Arguments, if submitted, are stored here. * * @var array(string) */ private $arguments = array(); /** * Wether the process() method has already been called. * * @var bool */ private $processed = false; /** * Indicates if an option was submitted, that has the isHelpOption flag set. * * @var bool */ private $helpOptionSet = false; /** * Tool object for multi-byte encoding safe string operations. * * @var ezcConsoleStringTool */ private $stringTool; /** * Input validator. * * @var ezcConsoleInputValidator */ private $validator; /** * Help generator. * * @var ezcConsoleInputHelpGenerator */ private $helpGenerator; /** * Collection of properties. * * @var array(string=>mixed) */ protected $properties = array(); /** * Creates an input handler. */ public function __construct() { $this->argumentDefinition = null; $this->stringTool = new ezcConsoleStringTool(); // @TODO Verify interface and make plugable $this->validator = new ezcConsoleStandardInputValidator(); $this->helpGenerator = new ezcConsoleInputStandardHelpGenerator( $this ); } /** * Registers the new option $option. * * This method adds the new option $option to your option collection. If * already an option with the assigned short or long value exists, an * exception will be thrown. * * @see ezcConsoleInput::unregisterOption() * * @param ezcConsoleOption $option * * @return ezcConsoleOption The recently registered option. */ public function registerOption( ezcConsoleOption $option ) { foreach ( $this->optionShort as $short => $ref ) { if ( $short === $option->short ) { throw new ezcConsoleOptionAlreadyRegisteredException( $short ); } } foreach ( $this->optionLong as $long => $ref ) { if ( $long === $option->long ) { throw new ezcConsoleOptionAlreadyRegisteredException( $long ); } } $this->options[] = $option; $this->optionLong[$option->long] = $option; if ( $option->short !== "" ) { $this->optionShort[$option->short] = $option; } return $option; } /** * Registers an alias for an option. * * Registers a new alias for an existing option. Aliases can * be used as if they were a normal option. * * The alias is registered with the short option name $short and the * long option name $long. The alias references to the existing * option $option. * * @see ezcConsoleInput::unregisterAlias() * * @param string $short * @param string $long * @param ezcConsoleOption $option * * * @throws ezcConsoleOptionNotExistsException * If the referenced option is not registered. * @throws ezcConsoleOptionAlreadyRegisteredException * If another option/alias has taken the provided short or long name. * @return void */ public function registerAlias( $short, $long, ezcConsoleOption $option ) { if ( !isset( $this->optionShort[$option->short] ) || !isset( $this->optionLong[$option->long] ) ) { throw new ezcConsoleOptionNotExistsException( $option->long ); } if ( isset( $this->optionShort[$short] ) || isset( $this->optionLong[$long] ) ) { throw new ezcConsoleOptionAlreadyRegisteredException( isset( $this->optionShort[$short] ) ? "-$short" : "--$long" ); } $this->optionShort[$short] = $option; $this->optionLong[$long] = $option; } /** * Registers options according to a string specification. * * Accepts a string to define parameters and registers all parameters as * options accordingly. String definition, specified in $optionDef, looks * like this: * * * [s:|size:][u:|user:][a:|all:] * * * This string registers 3 parameters: * -s / --size * -u / --user * -a / --all * * @param string $optionDef * @return void * * @throws ezcConsoleOptionStringNotWellformedException * If provided string does not have the correct format. */ public function registerOptionString( $optionDef ) { $regex = '\[([a-z0-9-]+)([:?*+])?([^|]*)\|([a-z0-9-]+)([:?*+])?\]'; // Check string for wellformedness if ( preg_match( "/^($regex)+$/", $optionDef ) == 0 ) { throw new ezcConsoleOptionStringNotWellformedException( "Option definition not wellformed: \"$optionDef\"" ); } if ( preg_match_all( "/$regex/", $optionDef, $matches ) ) { foreach ( $matches[1] as $id => $short ) { $option = null; $option = new ezcConsoleOption( $short, $matches[4][$id] ); if ( !empty( $matches[2][$id] ) || !empty( $matches[5][$id] ) ) { switch ( !empty( $matches[2][$id] ) ? $matches[2][$id] : $matches[5][$id] ) { case '*': // Allows 0 or more occurances $option->multiple = true; break; case '+': // Allows 1 or more occurances $option->multiple = true; $option->type = self::TYPE_STRING; break; case '?': $option->type = self::TYPE_STRING; $option->default = ''; break; default: break; } } if ( !empty( $matches[3][$id] ) ) { $option->default = $matches[3][$id]; } $this->registerOption( $option ); } } } /** * Removes an option. * * This function removes an option. All dependencies to that * specific option are removed completely from every other registered * option. * * @see ezcConsoleInput::registerOption() * * @param ezcConsoleOption $option The option object to unregister. * * @throws ezcConsoleOptionNotExistsException * If requesting a not registered option. * @return void */ public function unregisterOption( ezcConsoleOption $option ) { $found = false; foreach ( $this->options as $id => $existParam ) { if ( $existParam === $option ) { $found = true; unset( $this->options[$id] ); continue; } $existParam->removeAllExclusions( $option ); $existParam->removeAllDependencies( $option ); } if ( $found === false ) { throw new ezcConsoleOptionNotExistsException( $option->long ); } foreach ( $this->optionLong as $name => $existParam ) { if ( $existParam === $option ) { unset( $this->optionLong[$name] ); } } foreach ( $this->optionShort as $name => $existParam ) { if ( $existParam === $option ) { unset( $this->optionShort[$name] ); } } } /** * Removes an alias to an option. * * This function removes an alias with the short name $short and long * name $long. * * @see ezcConsoleInput::registerAlias() * * @throws ezcConsoleOptionNoAliasException * If the requested short/long name belongs to a real parameter instead. * * @param string $short * @param string $long * @return void * * @todo Check if $short and $long refer to the same option! */ public function unregisterAlias( $short, $long ) { foreach ( $this->options as $id => $option ) { if ( $option->short === $short ) { throw new ezcConsoleOptionNoAliasException( $short ); } if ( $option->long === $long ) { throw new ezcConsoleOptionNoAliasException( $long ); } } if ( isset( $this->optionShort[$short] ) ) { unset( $this->optionShort[$short] ); } if ( isset( $this->optionLong[$long] ) ) { unset( $this->optionLong[$long] ); } } /** * Returns the definition object for the option with the name $name. * * This method receives the long or short name of an option and * returns the ezcConsoleOption object. * * @param string $name Short or long name of the option (without - or --). * @return ezcConsoleOption * * @throws ezcConsoleOptionNotExistsException * If requesting a not registered parameter. */ public function getOption( $name ) { $name = $name; if ( isset( $this->optionShort[$name] ) ) { return $this->optionShort[$name]; } if ( isset( $this->optionLong[$name] ) ) { return $this->optionLong[$name]; } throw new ezcConsoleOptionNotExistsException( $name ); } /** * Process the input parameters. * * Actually process the input options and arguments according to the actual * settings. * * Per default this method uses $argc and $argv for processing. You can * override this setting with your own input, if necessary, using the * parameters of this method. (Attention, first argument is always the pro * gram name itself!) * * All exceptions thrown by this method contain an additional attribute "option" * which specifies the parameter on which the error occurred. * * @param array(string) $args The arguments * @return void * * @throws ezcConsoleOptionNotExistsException * If an option that was submitted does not exist. * @throws ezcConsoleOptionDependencyViolationException * If a dependency rule was violated. * @throws ezcConsoleOptionExclusionViolationException * If an exclusion rule was violated. * @throws ezcConsoleOptionTypeViolationException * If the type of a submitted value violates the options type rule. * @throws ezcConsoleOptionArgumentsViolationException * If arguments are passed although a parameter disallowed them. * * @see ezcConsoleOptionException */ public function process( array $args = null ) { if ( $this->processed ) { $this->reset(); } $this->processed = true; if ( !isset( $args ) ) { $args = isset( $argv ) ? $argv : isset( $_SERVER['argv'] ) ? $_SERVER['argv'] : array(); } $nextIndex = $this->processOptions( $args ); if ( $this->helpOptionSet() ) { // No need to parse arguments return; } $this->processArguments( $args, $nextIndex ); $this->checkRules(); $this->setOptionDefaults(); } /** * Sets defaults for options that have not been submitted. * * Checks all options if they have been submited. If not and a default * values is present, this is set as the options value. */ private function setOptionDefaults() { foreach ( $this->options as $option ) { if ( $option->value === false || $option->value === array() ) { // Default value to set? if ( $option->default !== null ) { $option->value = $option->default; } } } } /** * Reads the submitted options from $args array. * * Returns the next index to check for arguments. * * @param array(string) $args * @returns int * * @throws ezcConsoleOptionNotExistsException * if a submitted option does not exist. * @throws ezcConsoleOptionTooManyValuesException * if an option that expects only a single value was submitted * with multiple values. * @throws ezcConsoleOptionTypeViolationException * if an option was submitted with a value of the wrong type. * @throws ezcConsoleOptionMissingValueException * if an option thats expects a value was submitted without. */ private function processOptions( array $args ) { $numArgs = count( $args ); $i = 1; while ( $i < $numArgs ) { if ( $args[$i] === '--' ) { break; } // Equalize parameter handling (long params with =) if ( iconv_substr( $args[$i], 0, 2, 'UTF-8' ) == '--' ) { $this->preprocessLongOption( $args, $i ); // Update number of args, changed by preprocessLongOption() $numArgs = count( $args ); } // Check for parameter if ( iconv_substr( $args[$i], 0, 1, 'UTF-8' ) === '-' ) { if ( !$this->hasOption( preg_replace( '/^-*/', '', $args[$i] ) ) ) { throw new ezcConsoleOptionNotExistsException( $args[$i] ); } $this->processOption( $args, $i ); } // Must be the arguments else { break; } } // Move pointer over argument sign isset( $args[$i] ) && $args[$i] == '--' ? ++$i : $i; return $i; } /** * Resets all option and argument values. * * This method is called automatically by {@link process()}, if this method * is called twice or more, and may also be used to manually reset the * values of all registered {@ezcConsoleOption} and {@link * ezcConsoleArgument} objects. */ public function reset() { foreach ( $this->options as $option ) { $option->value = false; } if ( $this->argumentDefinition !== null ) { foreach ( $this->argumentDefinition as $argument ) { $argument->value = null; } } $this->arguments = array(); } /** * Returns true if an option with the given name exists, otherwise false. * * Checks if an option with the given name is registered. * * @param string $name Short or long name of the option. * @return bool True if option exists, otherwise false. */ public function hasOption( $name ) { try { $param = $this->getOption( $name ); } catch ( ezcConsoleOptionNotExistsException $e ) { return false; } return true; } /** * Returns an array of all registered options. * * Returns an array of all registered options in the following format: * * array( * 0 => ezcConsoleOption, * 1 => ezcConsoleOption, * 2 => ezcConsoleOption, * ... * ); * * * @return array(string=>ezcConsoleOption) Registered options. */ public function getOptions() { return $this->options; } /** * Returns the values of all submitted options. * * Returns an array of all values submitted to the options. The array is * indexed by the parameters short name (excluding the '-' prefix). The array * does not contain any parameter, which value is 'false' (meaning: the * parameter was not submitted). * * @param bool $longnames Wheather to use longnames for indexing. * @return array(string=>mixed) */ public function getOptionValues( $longnames = false ) { $res = array(); foreach ( $this->options as $param ) { if ( $param->value !== false ) { $res[( $longnames === true ) ? $param->long : $param->short] = $param->value; } } return $res; } /** * Returns arguments provided to the program. * * This method returns all arguments provided to a program in an * int indexed array. Arguments are sorted in the way * they are submitted to the program. You can disable arguments * through the 'arguments' flag of a parameter, if you want * to disallow arguments. * * Arguments are either the last part of the program call (if the * last parameter is not a 'multiple' one) or divided via the '--' * method which is commonly used on Unix (if the last parameter * accepts multiple values this is required). * * @return array(string) Arguments. */ public function getArguments() { return $this->arguments; } /** * Get help information for your options. * * This method returns an array of help information for your options, * indexed by int. Each help info has 2 fields: * * 0 => The options names (" / ") * 1 => The help text (depending on the $long parameter) * * The $long options determines if you want to get the short or long help * texts. The array returned can be used by {@link ezcConsoleTable}. * * If using the second options, you can filter the options shown in the * help output (e.g. to show short help for related options). Provide * as simple number indexed array of short and/or long values to set a filter. * * The $paramGrouping option can be used to group options in the help * output. The structure of this array parameter is as follows: * * * array( * 'First section' => array( * 'input', * 'output' * 'overwrite', * ), * 'Second section' => array( * 'v', * 'h', * ), * ) * * * As can be seen, short option names are possible as well as long ones. * The key of the first array level is the name of the section, which is * assigned to an array of options to group under this section. The $params * parameter still influences if an option is displayed at all. * * @param bool $long * @param array(string) $params * @param array(string=>array(string)) $paramGrouping * @return array(array(string)) Table structure as explained. * * @apichange In future versions, the default values of $params will change * to null instead of an empty array. Giving an empty array for * these will then be taken literally. */ public function getHelp( $long = false, array $params = array(), array $paramGrouping = null ) { // New handling $params = ( $params === array() || $params === null ? null : $params ); $help = array(); if ( $paramGrouping === null ) { // Original handling $help = $this->getOptionHelpWithoutGrouping( $long, $params ); } else { $help = $this->getOptionHelpWithGrouping( $long, $params, $paramGrouping ); } if ( $this->argumentDefinition !== null ) { $help[] = array( "Arguments:", '' ); $argumentsHelp = $this->helpGenerator->generateArgumentHelp( $long ); if ( $argumentsHelp === array() ) { $help[] = array( '', "No arguments available." ); } else { $help = array_merge( $help, $argumentsHelp ); } } return $help; } /** * Creates the option help array in the original, ungrouped way. * * Creates the original help array generated by {@link getHelp()}. The * $long and $params options are the same as they are for this method. * * @param bool $long * @param array $params * @return array */ private function getOptionHelpWithoutGrouping( $long, $params ) { return $this->helpGenerator->generateUngroupedOptionHelp( $long, $params ); } /** * Generates options helo array with ordering and grouping. * * @param mixed $long * @param mixed $params * @param mixed $paramGrouping * @return array() */ private function getOptionHelpWithGrouping( $long, $params, $paramGrouping ) { $rawHelp = $this->helpGenerator->generateGroupedOptionHelp( $paramGrouping, $long, $params ); $help = array(); $first = true; foreach ( $rawHelp as $category => $optionsHelp ) { if ( !$first ) { $help[] = array( '', '' ); } else { $first = false; } $help[] = array( $category, '' ); $help = array_merge( $help, $optionsHelp ); } return $help; } /** * Get help information for your options as a table. * * This method provides the information returned by * {@link ezcConsoleInput::getHelp()} in a table. * * The $paramGrouping option can be used to group options in the help * output. The structure of this array parameter is as follows: * * * array( * 'First section' => array( * 'input', * 'output' * 'overwrite', * ), * 'Second section' => array( * 'v', * 'h', * ), * ) * * * As can be seen, short option names are possible as well as long ones. * The key of the first array level is the name of the section, which is * assigned to an array of options to group under this section. The $params * parameter still influences if an option as displayed at all. * * @param ezcConsoleTable $table The table object to fill. * @param bool $long Set this to true for getting the * long help version. * @param array(string) $params Set of option names to generate help * for, default is all. * @param array(string=>array(string)) $paramGrouping * @return ezcConsoleTable The filled table. */ public function getHelpTable( ezcConsoleTable $table, $long = false, array $params = array(), $paramGrouping = null ) { $help = $this->getHelp( $long, $params, $paramGrouping ); $i = 0; foreach ( $help as $row ) { $table[$i][0]->content = $row[0]; $table[$i++][1]->content = $row[1]; } return $table; } /** * Returns a standard help output for your program. * * This method generates a help text as it's commonly known from Unix * command line programs. The output will contain the synopsis, your * provided program description and the selected parameter help * as also provided by {@link ezcConsoleInput::getHelp()}. The returned * string can directly be printed to the console. * * The $paramGrouping option can be used to group options in the help * output. The structure of this array parameter is as follows: * * * array( * 'First section' => array( * 'input', * 'output' * 'overwrite', * ), * 'Second section' => array( * 'v', * 'h', * ), * ) * * * As can be seen, short option names are possible as well as long ones. * The key of the first array level is the name of the section, which is * assigned to an array of options to group under this section. The $params * parameter still influences if an option as displayed at all. * * @param string $programDesc The description of your program. * @param int $width The width to adjust the output text to. * @param bool $long Set this to true for getting the long * help version. * @param array(string) $params Set of option names to generate help * for, default is all. * @param array(string=>array(string)) $paramGrouping * @return string The generated help text. */ public function getHelpText( $programDesc, $width = 80, $long = false, array $params = null, $paramGrouping = null ) { $help = $this->getHelp( $long, ( $params == null ? array() : $params ), $paramGrouping ); // Determine max length of first column text. $maxLength = 0; foreach ( $help as $row ) { $maxLength = max( $maxLength, iconv_strlen( $row[0], 'UTF-8' ) ); } // Width of left column $leftColWidth = $maxLength + 2; // Width of righ column $rightColWidth = $width - $leftColWidth; $res = 'Usage: ' . $this->getSynopsis( $params ) . PHP_EOL; $res .= $this->stringTool->wordwrap( $programDesc, $width, PHP_EOL ); $res .= PHP_EOL . PHP_EOL; foreach ( $help as $row ) { $rowParts = explode( "\n", $this->stringTool->wordwrap( $row[1], $rightColWidth ) ); $res .= $this->stringTool->strPad( $row[0], $leftColWidth, ' ' ); $res .= $rowParts[0] . PHP_EOL; // @TODO: Fix function call in loop header for ( $i = 1; $i < sizeof( $rowParts ); $i++ ) { $res .= str_repeat( ' ', $leftColWidth ) . $rowParts[$i] . PHP_EOL; } } return $res; } /** * Returns the synopsis string for the program. * * This gives you a synopsis definition for the options and arguments * defined with this instance of ezcConsoleInput. You can filter the * options named in the synopsis by submitting their short names in an * array as the parameter of this method. If the parameter $optionNames * is set, only those options are listed in the synopsis. * * @param array(string) $optionNames * @return string */ public function getSynopsis( array $optionNames = null ) { return $this->helpGenerator->generateSynopsis( $optionNames ); } /** * Returns if a help option was set. * This method returns if an option was submitted, which was defined to be * a help option, using the isHelpOption flag. * * @return bool If a help option was set. */ public function helpOptionSet() { return $this->helpOptionSet; } /** * Property read access. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. * * @param string $propertyName Name of the property. * @return mixed Value of the property or null. * @ignore */ public function __get( $propertyName ) { if ( !isset( $this->$propertyName ) ) { throw new ezcBasePropertyNotFoundException( $propertyName ); } return $this->properties[$propertyName]; } /** * Property set access. * * @param string $propertyName * @param string $propertyValue * @ignore * @return void */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case "argumentDefinition": if ( ( $propertyValue instanceof ezcConsoleArguments ) === false && $propertyValue !== null ) { throw new ezcBaseValueException( $propertyName, $propertyValue, "ezcConsoleArguments" ); } break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } $this->properties[$propertyName] = $propertyValue; } /** * Property isset access. * * @param string $propertyName Name of the property. * @return bool True if the property is set, otherwise false. * @ignore */ public function __isset( $propertyName ) { return array_key_exists( $propertyName, $this->properties ); } /** * Returns the synopsis string for a single option and its dependencies. * * This method returns a part of the program synopsis, specifically for a * certain parameter. The method recursively adds depending parameters up * to the 2nd depth level to the synopsis. The second parameter is used * to store the short names of all options that have already been used in * the synopsis (to avoid adding an option twice). The 3rd parameter * determines the actual deps in the option dependency recursion to * terminate that after 2 recursions. * * @param ezcConsoleOption $option The option to include. * @param array(string) $usedOptions Array of used option short names. * @param int $depth Current recursion depth. * @return string The synopsis for this parameter. * * @apichange This method is deprecates. Implement your own {@link * ezcConsoleInputHelpGenerator} instead, as soon as the * interface is made public. */ protected function createOptionSynopsis( ezcConsoleOption $option, &$usedOptions, $depth = 0 ) { $synopsis = ''; // Break after a nesting level of 2 if ( $depth++ > 2 || ( in_array( $option->short, $usedOptions['short'] ) && in_array( $option->long, $usedOptions['long'] ) ) ) return $synopsis; $usedOptions['short'][] = $option->short; $usedOptions['long'][] = $option->long; $synopsis .= $option->short !== "" ? "-{$option->short}" : "--{$option->long}"; if ( isset( $option->default ) ) { $synopsis .= " " . ( $option->type === ezcConsoleInput::TYPE_STRING ? '"' : '' ) . $option->default . ( $option->type === ezcConsoleInput::TYPE_STRING ? '"' : '' ); } else if ( $option->type !== ezcConsoleInput::TYPE_NONE ) { $synopsis .= " "; switch ( $option->type ) { case ezcConsoleInput::TYPE_STRING: $synopsis .= ""; break; case ezcConsoleInput::TYPE_INT: $synopsis .= ""; break; } } foreach ( $option->getDependencies() as $rule ) { $deeperSynopsis = $this->createOptionSynopsis( $rule->option, $usedOptions, $depth ); $synopsis .= ( iconv_strlen( trim( $deeperSynopsis ), 'UTF-8' ) > 0 ? ' ' . $deeperSynopsis : '' ); } if ( $option->arguments === false ) { $allowsArgs = false; } // Make the whole thing optional? if ( $option->mandatory === false ) { $synopsis = "[$synopsis]"; } return $synopsis . ' '; } /** * Process an option. * * This method does the processing of a single option. * * @param array(string) $args The arguments array. * @param int $i The current position in the arguments array. * @return void * * @throws ezcConsoleOptionTooManyValuesException * If an option that expects only a single value was submitted * with multiple values. * @throws ezcConsoleOptionTypeViolationException * If an option was submitted with a value of the wrong type. * @throws ezcConsoleOptionMissingValueException * If an option thats expects a value was submitted without. */ private function processOption( array $args, &$i ) { $option = $this->getOption( preg_replace( '/^-+/', '', $args[$i++] ) ); // Is the actual option a help option? if ( $option->isHelpOption === true ) { $this->helpOptionSet = true; } // No value expected if ( $option->type === ezcConsoleInput::TYPE_NONE ) { // No value expected if ( isset( $args[$i] ) && iconv_substr( $args[$i], 0, 1, 'UTF-8' ) !== '-' && sizeof( $args ) > ( $i + 1 ) ) { // But one found throw new ezcConsoleOptionTypeViolationException( $option, $args[$i] ); } // Multiple occurance possible if ( $option->multiple === true ) { $option->value[] = true; } else { $option->value = true; } // Everything fine, nothing to do return $i; } // Value expected, check for it if ( isset( $args[$i] ) && iconv_substr( $args[$i], 0, 1, 'UTF-8' ) !== '-' ) { // Type check if ( $this->isCorrectType( $option->type, $args[$i] ) === false ) { throw new ezcConsoleOptionTypeViolationException( $option, $args[$i] ); } // Multiple values possible if ( $option->multiple === true ) { $option->value[] = $args[$i]; } // Only single value expected, check for multiple elseif ( isset( $option->value ) && $option->value !== false ) { throw new ezcConsoleOptionTooManyValuesException( $option ); } else { $option->value = $args[$i]; } $i++; } // Value found? If not, use default, if available if ( !isset( $option->value ) || $option->value === false || ( is_array( $option->value ) && count( $option->value ) === 0) ) { throw new ezcConsoleOptionMissingValueException( $option ); } } /** * Process arguments given to the program. * * @param array(string) $args The arguments array. * @param int $i Current index in arguments array. * @return void */ private function processArguments( array $args, &$i ) { $numArgs = count( $args ); if ( $this->argumentDefinition === null || $this->argumentsAllowed() === false ) { // Old argument handling, also used of a set option sets disallowing arguments while ( $i < $numArgs ) { $this->arguments[] = $args[$i++]; } } else { $mandatory = true; foreach ( $this->argumentDefinition as $arg ) { // Check if all followinga arguments are optional if ( $arg->mandatory === false ) { $mandatory = false; } // Check if the current argument is present and mandatory if ( $mandatory === true ) { if ( !isset( $args[$i] ) ) { throw new ezcConsoleArgumentMandatoryViolationException( $arg ); } } else { // Arguments are optional, if no more left: return. if ( !isset( $args[$i] ) ) { // Optional and no more arguments left, assign default $arg->value = $arg->default; continue; } } if ( $arg->multiple === true ) { $arg->value = array(); for ( $i = $i; $i < $numArgs; ++$i ) { if ( $this->isCorrectType( $arg->type, $args[$i] ) === false ) { throw new ezcConsoleArgumentTypeViolationException( $arg, $args[$i] ); } $arg->value = array_merge( $arg->value, array( $args[$i] ) ); // Keep old handling, too $this->arguments[] = $args[$i]; } return; } else { if ( $this->isCorrectType( $arg->type, $args[$i] ) === false ) { throw new ezcConsoleArgumentTypeViolationException( $arg, $args[$i] ); } $arg->value = $args[$i]; // Keep old handling, too $this->arguments[] = $args[$i]; } ++$i; } if ( $i < $numArgs ) { throw new ezcConsoleTooManyArgumentsException( $args, $i ); } } } /** * Returns if arguments are allowed with the current option submition. * * @return bool If arguments allowed. */ protected function argumentsAllowed() { foreach ( $this->options as $id => $option ) { if ( $option->value !== false && $option->arguments === false ) { return false; } } return true; } /** * Check the rules that may be associated with an option. * * Options are allowed to have rules associated for dependencies to other * options and exclusion of other options or arguments. This method * processes the checks. * * @throws ezcConsoleException * in case validation fails. */ private function checkRules() { // If a help option is set, skip rule checking if ( $this->helpOptionSet === true ) { return; } $this->validator->validateOptions( $this->options, ( $this->arguments !== array() ) ); } /** * Checks if a value is of a given type. Converts the value to the * correct PHP type on success. * * @param int $type The type to check for. One of self::TYPE_*. * @param string $val The value to check. Will possibly altered! * @return bool True on succesful check, otherwise false. */ private function isCorrectType( $type, &$val ) { $res = false; switch ( $type ) { case ezcConsoleInput::TYPE_STRING: $res = true; $val = preg_replace( '/^(["\'])(.*)\1$/', '\2', $val ); break; case ezcConsoleInput::TYPE_INT: $res = preg_match( '/^[0-9]+$/', $val ) ? true : false; if ( $res ) { $val = ( int ) $val; } break; } return $res; } /** * Split parameter and value for long option names. * * This method checks for long options, if the value is passed using =. If * this is the case parameter and value get split and replaced in the * arguments array. * * @param array(string) $args The arguments array * @param int $i Current arguments array position * @return void */ private function preprocessLongOption( array &$args, $i ) { // Value given? if ( preg_match( '/^--\w+\=[^ ]/i', $args[$i] ) ) { // Split param and value and replace current param $parts = explode( '=', $args[$i], 2 ); array_splice( $args, $i, 1, $parts ); } } } ?> PK!JqVV$ezc/ConsoleTools/progressmonitor.phpnu[ * // Construction * $status = new ezcConsoleProgressMonitor( new ezcConsoleOutput(), 42 ); * * // Run statusbar * foreach ( $files as $file ) * { * $res = $file->upload(); * // Add a status-entry to be printed. * $status->addEntry( 'UPLOAD', $file->path ); * // Result like " 2.5% UPLOAD /var/upload/test.png" * } * * * @property ezcConsoleProgressMonitorOptions $options * Contains the options for this class. * * @package ConsoleTools * @version 1.6.1 * @mainclass */ class ezcConsoleProgressMonitor { /** * Options * * @var ezcConsoleProgressMonitorOptions */ protected $options; /** * The ezcConsoleOutput object to use. * * @var ezcConsoleOutput */ protected $outputHandler; /** * Counter for the items already printed. * * @var int */ protected $counter = 0; /** * The number of entries to expect. * * @var int */ protected $max; /** * Creates a new progress monitor. * The $outputHandler parameter will be used to display the progress * monitor. $max is the number of monitor items to expect. $options can be * used to define the behaviour of the monitor * {@link ezcConsoleProgressMonitorOptions}. * * @param ezcConsoleOutput $outHandler Handler to utilize for output * @param int $max Number of items to expect * @param array(string=>string) $options Options. * * @see ezcConsoleProgressMonitor::$options */ public function __construct( ezcConsoleOutput $outHandler, $max, array $options = array() ) { $this->outputHandler = $outHandler; $this->max = $max; $this->options = new ezcConsoleProgressMonitorOptions( $options ); } /** * Property read access. * * @param string $key Name of the property. * @return mixed Value of the property or null. * * @throws ezcBasePropertyNotFoundException * If the the desired property is not found. */ public function __get( $key ) { switch ( $key ) { case 'options': return $this->options; break; } throw new ezcBasePropertyNotFoundException( $key ); } /** * Property write access. * * @param string $propertyName Name of the property. * @param mixed $val The value for the property. * * @throws ezcBaseValueException * If a the value for the property options is not an instance of * ezcConsoleProgressMonitorOptions. * @return void */ public function __set( $propertyName, $val ) { switch ( $propertyName ) { case 'options': if ( !( $val instanceof ezcConsoleProgressMonitorOptions ) ) { throw new ezcBaseValueException( $propertyName, $val, 'instance of ezcConsoleProgressMonitorOptions' ); } $this->options = $val; return; } throw new ezcBasePropertyNotFoundException( $propertyName ); } /** * Property isset access. * * @param string $propertyName Name of the property. * @return bool True is the property is set, otherwise false. */ public function __isset( $propertyName ) { switch ( $propertyName ) { case 'options': return true; } return false; } /** * Set new options. * This method allows you to change the options of an progress monitor. * * @param ezcConsoleProgressMonitorOptions $options The options to set. * * @throws ezcBaseSettingNotFoundException * If you tried to set a non-existent option value. * @throws ezcBaseSettingValueException * If the value is not valid for the desired option. * @throws ezcBaseValueException * If you submit neither an array nor an instance of * ezcConsoleProgressMonitorOptions. */ public function setOptions( $options ) { if ( is_array( $options ) ) { $this->options->merge( $options ); } else if ( $options instanceof ezcConsoleProgressMonitorOptions ) { $this->options = $options; } else { throw new ezcBaseValueException( "options", $options, "instance of ezcConsoleProgressMonitorOptions" ); } } /** * Returns the currently set options. * Returns the currently set option array. * * @return ezcConsoleProgressMonitorOptions The options. */ public function getOptions() { return $this->options; } /** * Print a status entry. * Prints a new status entry to the console and updates the internal counter. * * @param string $tag The tag to print (second argument in the * formatString). * @param string $data The data to be printed in the status entry (third * argument in the format string). * @return void */ public function addEntry( $tag, $data ) { $this->counter++; $percentage = $this->counter / $this->max * 100; $this->outputHandler->outputLine( sprintf( $this->options['formatString'], $percentage, $tag, $data ) ); } } ?> PK!wQO~4ezc/ConsoleTools/interfaces/input_help_generator.phpnu[ * array( * 0 => '
// tag. $this->assertMatchesXpath('' . $html, '/form [ ./tr [ ./td [./label[@for="name_field2"]] /following-sibling::td [./input[@id="name_field2"]] ] /following-sibling::tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] ] ' ); } public function testFormEndWithoutRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'text') ->getForm() ->createView(); $this->renderWidget($view['field1']); // Rest should only contain field2, but isn't rendered $html = $this->renderEnd($view, array('render_rest' => false)); $this->assertEquals('', $html); } public function testWidgetContainerAttributes() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), )); $form->add('text', 'text'); $html = $this->renderWidget($form->createView()); // compare plain HTML to check the whitespace $this->assertContains('
', $html); } public function testWidgetContainerAttributeNameRepeatedIfTrue() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('foo' => true), )); $html = $this->renderWidget($form->createView()); // foo="foo" $this->assertContains('
', $html); } public function testWidgetContainerAttributeHiddenIfFalse() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('foo' => false), )); $html = $this->renderWidget($form->createView()); // no foo $this->assertContains('
', $html); } } PK!KKBtest/Form/Symfony/Component/Form/Tests/FormPerformanceTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Test\FormPerformanceTestCase as BaseFormPerformanceTestCase; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormPerformanceTestCase instead. */ abstract class FormPerformanceTestCase extends BaseFormPerformanceTestCase { } PK!@U=test/Form/Symfony/Component/Form/Tests/AbstractLayoutTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Csrf\CsrfExtension; abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormIntegrationTestCase { protected $csrfTokenManager; protected function setUp() { if (!extension_loaded('intl')) { $this->markTestSkipped('The "intl" extension is not available'); } \Locale::setDefault('en'); $this->csrfTokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); parent::setUp(); } protected function getExtensions() { return array( new CsrfExtension($this->csrfTokenManager), ); } protected function tearDown() { $this->csrfTokenManager = null; parent::tearDown(); } protected function assertXpathNodeValue(\DomElement $element, $expression, $nodeValue) { $xpath = new \DOMXPath($element->ownerDocument); $nodeList = $xpath->evaluate($expression); $this->assertEquals(1, $nodeList->length); $this->assertEquals($nodeValue, $nodeList->item(0)->nodeValue); } protected function assertMatchesXpath($html, $expression, $count = 1) { $dom = new \DomDocument('UTF-8'); try { // Wrap in node so we can load HTML with multiple tags at // the top level $dom->loadXml(''.$html.''); } catch (\Exception $e) { $this->fail(sprintf( "Failed loading HTML:\n\n%s\n\nError: %s", $html, $e->getMessage() )); } $xpath = new \DOMXPath($dom); $nodeList = $xpath->evaluate('/root'.$expression); if ($nodeList->length != $count) { $dom->formatOutput = true; $this->fail(sprintf( "Failed asserting that \n\n%s\n\nmatches exactly %s. Matches %s in \n\n%s", $expression, $count == 1 ? 'once' : $count.' times', $nodeList->length == 1 ? 'once' : $nodeList->length.' times', // strip away and substr($dom->saveHTML(), 6, -8) )); } } protected function assertWidgetMatchesXpath(FormView $view, array $vars, $xpath) { // include ampersands everywhere to validate escaping $html = $this->renderWidget($view, array_merge(array( 'id' => 'my&id', 'attr' => array('class' => 'my&class'), ), $vars)); $xpath = trim($xpath).' [@id="my&id"] [@class="my&class"]'; $this->assertMatchesXpath($html, $xpath); } abstract protected function renderForm(FormView $view, array $vars = array()); abstract protected function renderEnctype(FormView $view); abstract protected function renderLabel(FormView $view, $label = null, array $vars = array()); abstract protected function renderErrors(FormView $view); abstract protected function renderWidget(FormView $view, array $vars = array()); abstract protected function renderRow(FormView $view, array $vars = array()); abstract protected function renderRest(FormView $view, array $vars = array()); abstract protected function renderStart(FormView $view, array $vars = array()); abstract protected function renderEnd(FormView $view, array $vars = array()); abstract protected function setTheme(FormView $view, array $themes); public function testEnctype() { $form = $this->factory->createNamedBuilder('name', 'form') ->add('file', 'file') ->getForm(); $this->assertEquals('enctype="multipart/form-data"', $this->renderEnctype($form->createView())); } public function testNoEnctype() { $form = $this->factory->createNamedBuilder('name', 'form') ->add('text', 'text') ->getForm(); $this->assertEquals('', $this->renderEnctype($form->createView())); } public function testLabel() { $form = $this->factory->createNamed('name', 'text'); $view = $form->createView(); $this->renderWidget($view, array('label' => 'foo')); $html = $this->renderLabel($view); $this->assertMatchesXpath($html, '/label [@for="name"] [.="[trans]Name[/trans]"] ' ); } public function testLabelOnForm() { $form = $this->factory->createNamed('name', 'date'); $view = $form->createView(); $this->renderWidget($view, array('label' => 'foo')); $html = $this->renderLabel($view); $this->assertMatchesXpath($html, '/label [@class="required"] [.="[trans]Name[/trans]"] ' ); } public function testLabelWithCustomTextPassedAsOption() { $form = $this->factory->createNamed('name', 'text', null, array( 'label' => 'Custom label', )); $html = $this->renderLabel($form->createView()); $this->assertMatchesXpath($html, '/label [@for="name"] [.="[trans]Custom label[/trans]"] ' ); } public function testLabelWithCustomTextPassedDirectly() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), 'Custom label'); $this->assertMatchesXpath($html, '/label [@for="name"] [.="[trans]Custom label[/trans]"] ' ); } public function testLabelWithCustomTextPassedAsOptionAndDirectly() { $form = $this->factory->createNamed('name', 'text', null, array( 'label' => 'Custom label', )); $html = $this->renderLabel($form->createView(), 'Overridden label'); $this->assertMatchesXpath($html, '/label [@for="name"] [.="[trans]Overridden label[/trans]"] ' ); } public function testLabelDoesNotRenderFieldAttributes() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), null, array( 'attr' => array( 'class' => 'my&class' ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="required"] ' ); } public function testLabelWithCustomAttributesPassedDirectly() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), null, array( 'label_attr' => array( 'class' => 'my&class' ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="my&class required"] ' ); } public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), 'Custom label', array( 'label_attr' => array( 'class' => 'my&class' ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="my&class required"] [.="[trans]Custom label[/trans]"] ' ); } // https://github.com/symfony/symfony/issues/5029 public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() { $form = $this->factory->createNamed('name', 'text', null, array( 'label' => 'Custom label', )); $html = $this->renderLabel($form->createView(), null, array( 'label_attr' => array( 'class' => 'my&class' ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="my&class required"] [.="[trans]Custom label[/trans]"] ' ); } public function testErrors() { $form = $this->factory->createNamed('name', 'text'); $form->addError(new FormError('[trans]Error 1[/trans]')); $form->addError(new FormError('[trans]Error 2[/trans]')); $view = $form->createView(); $html = $this->renderErrors($view); $this->assertMatchesXpath($html, '/ul [ ./li[.="[trans]Error 1[/trans]"] /following-sibling::li[.="[trans]Error 2[/trans]"] ] [count(./li)=2] ' ); } public function testOverrideWidgetBlock() { // see custom_widgets.html.twig $form = $this->factory->createNamed('text_id', 'text'); $html = $this->renderWidget($form->createView()); $this->assertMatchesXpath($html, '/div [ ./input [@type="text"] [@id="text_id"] ] [@id="container"] ' ); } public function testCheckedCheckbox() { $form = $this->factory->createNamed('name', 'checkbox', true); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="checkbox"] [@name="name"] [@checked="checked"] [@value="1"] ' ); } public function testUncheckedCheckbox() { $form = $this->factory->createNamed('name', 'checkbox', false); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="checkbox"] [@name="name"] [not(@checked)] ' ); } public function testCheckboxWithValue() { $form = $this->factory->createNamed('name', 'checkbox', false, array( 'value' => 'foo&bar', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="checkbox"] [@name="name"] [@value="foo&bar"] ' ); } public function testSingleChoice() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => false, )); // If the field is collapsed, has no "multiple" attribute, is required but // has *no* empty value, the "required" must not be added, otherwise // the resulting HTML is invalid. // https://github.com/symfony/symfony/issues/8942 // HTML 5 spec // http://www.w3.org/html/wg/drafts/html/master/forms.html#placeholder-label-option // "If a select element has a required attribute specified, does not // have a multiple attribute specified, and has a display size of 1, // then the select element must have a placeholder label option." $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ' ); } public function testSingleChoiceWithPreferred() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'preferred_choices' => array('&b'), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array('separator' => '-- sep --'), '/select [@name="name"] [not(@required)] [ ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] /following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceWithPreferredAndNoSeparator() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'preferred_choices' => array('&b'), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array('separator' => null), '/select [@name="name"] [not(@required)] [ ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] ] [count(./option)=2] ' ); } public function testSingleChoiceWithPreferredAndBlankSeparator() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'preferred_choices' => array('&b'), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array('separator' => ''), '/select [@name="name"] [not(@required)] [ ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] /following-sibling::option[@disabled="disabled"][not(@selected)][.=""] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] ] [count(./option)=3] ' ); } public function testChoiceWithOnlyPreferred() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'preferred_choices' => array('&a', '&b'), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [count(./option)=2] ' ); } public function testSingleChoiceNonRequired() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => false, 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [ ./option[@value=""][.="[trans][/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceNonRequiredNoneSelected() { $form = $this->factory->createNamed('name', 'choice', null, array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => false, 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [ ./option[@value=""][.="[trans][/trans]"] /following-sibling::option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceWithNonRequiredEmptyValue() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => false, 'required' => false, 'empty_value' => 'Select&Anything&Not&Me', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [ ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Anything&Not&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceRequiredWithEmptyValue() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => true, 'multiple' => false, 'expanded' => false, 'empty_value' => 'Test&Me' )); // The "disabled" attribute was removed again due to a bug in the // BlackBerry 10 browser. // See https://github.com/symfony/symfony/pull/7678 $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [@required="required"] [ ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Test&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceRequiredWithEmptyValueViaView() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => true, 'multiple' => false, 'expanded' => false, )); // The "disabled" attribute was removed again due to a bug in the // BlackBerry 10 browser. // See https://github.com/symfony/symfony/pull/7678 $this->assertWidgetMatchesXpath($form->createView(), array('empty_value' => ''), '/select [@name="name"] [@required="required"] [ ./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceGrouped() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array( 'Group&1' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'Group&2' => array('&c' => 'Choice&C'), ), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./optgroup[@label="[trans]Group&1[/trans]"] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ] [./optgroup[@label="[trans]Group&2[/trans]"] [./option[@value="&c"][not(@selected)][.="[trans]Choice&C[/trans]"]] [count(./option)=1] ] [count(./optgroup)=2] ' ); } public function testMultipleChoice() { $form = $this->factory->createNamed('name', 'choice', array('&a'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => true, 'multiple' => true, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name[]"] [@required="required"] [@multiple="multiple"] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ' ); } public function testMultipleChoiceSkipsEmptyValue() { $form = $this->factory->createNamed('name', 'choice', array('&a'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => true, 'expanded' => false, 'empty_value' => 'Test&Me' )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name[]"] [@multiple="multiple"] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ' ); } public function testMultipleChoiceNonRequired() { $form = $this->factory->createNamed('name', 'choice', array('&a'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => false, 'multiple' => true, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name[]"] [@multiple="multiple"] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ' ); } public function testSingleChoiceExpanded() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(./input)=3] ' ); } public function testSingleChoiceExpandedWithEmptyValue() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => true, 'empty_value' => 'Test&Me' )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] /following-sibling::label[@for="name_placeholder"][.="[trans]Test&Me[/trans]"] /following-sibling::input[@type="radio"][@name="name"][@id="name_0"][@checked] /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(./input)=4] ' ); } public function testSingleChoiceExpandedWithBooleanValue() { $form = $this->factory->createNamed('name', 'choice', true, array( 'choices' => array('1' => 'Choice&A', '0' => 'Choice&B'), 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input[@type="radio"][@name="name"][@id="name_0"][@checked] /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(./input)=3] ' ); } public function testMultipleChoiceExpanded() { $form = $this->factory->createNamed('name', 'choice', array('&a', '&c'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B', '&c' => 'Choice&C'), 'multiple' => true, 'expanded' => true, 'required' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] /following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] /following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] /following-sibling::label[@for="name_2"][.="[trans]Choice&C[/trans]"] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(./input)=4] ' ); } public function testCountry() { $form = $this->factory->createNamed('name', 'country', 'AT'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] [count(./option)>200] ' ); } public function testCountryWithEmptyValue() { $form = $this->factory->createNamed('name', 'country', 'AT', array( 'empty_value' => 'Select&Country', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Country[/trans]"]] [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] [count(./option)>201] ' ); } public function testDateTime() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'with_seconds' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@id="name_date"] [ ./select [@id="name_date_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_date_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_date_year"] [./option[@value="2011"][@selected="selected"]] ] /following-sibling::div [@id="name_time"] [ ./select [@id="name_time_hour"] [./option[@value="4"][@selected="selected"]] /following-sibling::select [@id="name_time_minute"] [./option[@value="5"][@selected="selected"]] ] ] [count(.//select)=5] ' ); } public function testDateTimeWithEmptyValueGlobal() { $form = $this->factory->createNamed('name', 'datetime', null, array( 'input' => 'string', 'empty_value' => 'Change&Me', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@id="name_date"] [ ./select [@id="name_date_month"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_date_day"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_date_year"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] /following-sibling::div [@id="name_time"] [ ./select [@id="name_time_hour"] [./option[@value=""][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_time_minute"] [./option[@value=""][.="[trans]Change&Me[/trans]"]] ] ] [count(.//select)=5] ' ); } public function testDateTimeWithHourAndMinute() { $data = array('year' => '2011', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5'); $form = $this->factory->createNamed('name', 'datetime', $data, array( 'input' => 'array', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@id="name_date"] [ ./select [@id="name_date_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_date_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_date_year"] [./option[@value="2011"][@selected="selected"]] ] /following-sibling::div [@id="name_time"] [ ./select [@id="name_time_hour"] [./option[@value="4"][@selected="selected"]] /following-sibling::select [@id="name_time_minute"] [./option[@value="5"][@selected="selected"]] ] ] [count(.//select)=5] ' ); } public function testDateTimeWithSeconds() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'with_seconds' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@id="name_date"] [ ./select [@id="name_date_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_date_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_date_year"] [./option[@value="2011"][@selected="selected"]] ] /following-sibling::div [@id="name_time"] [ ./select [@id="name_time_hour"] [./option[@value="4"][@selected="selected"]] /following-sibling::select [@id="name_time_minute"] [./option[@value="5"][@selected="selected"]] /following-sibling::select [@id="name_time_second"] [./option[@value="6"][@selected="selected"]] ] ] [count(.//select)=6] ' ); } public function testDateTimeSingleText() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'date_widget' => 'single_text', 'time_widget' => 'single_text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input [@type="date"] [@id="name_date"] [@name="name[date]"] [@value="2011-02-03"] /following-sibling::input [@type="time"] [@id="name_time"] [@name="name[time]"] [@value="04:05"] ] ' ); } public function testDateTimeWithWidgetSingleText() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'widget' => 'single_text', 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="datetime"] [@name="name"] [@value="2011-02-03T04:05:06Z"] ' ); } public function testDateTimeWithWidgetSingleTextIgnoreDateAndTimeWidgets() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'date_widget' => 'choice', 'time_widget' => 'choice', 'widget' => 'single_text', 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="datetime"] [@name="name"] [@value="2011-02-03T04:05:06Z"] ' ); } public function testDateChoice() { $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( 'input' => 'string', 'widget' => 'choice', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_year"] [./option[@value="2011"][@selected="selected"]] ] [count(./select)=3] ' ); } public function testDateChoiceWithEmptyValueGlobal() { $form = $this->factory->createNamed('name', 'date', null, array( 'input' => 'string', 'widget' => 'choice', 'empty_value' => 'Change&Me', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_day"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_year"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] [count(./select)=3] ' ); } public function testDateChoiceWithEmptyValueOnYear() { $form = $this->factory->createNamed('name', 'date', null, array( 'input' => 'string', 'widget' => 'choice', 'required' => false, 'empty_value' => array('year' => 'Change&Me'), )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value="1"]] /following-sibling::select [@id="name_day"] [./option[@value="1"]] /following-sibling::select [@id="name_year"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] [count(./select)=3] ' ); } public function testDateText() { $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( 'input' => 'string', 'widget' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input [@id="name_month"] [@type="text"] [@value="2"] /following-sibling::input [@id="name_day"] [@type="text"] [@value="3"] /following-sibling::input [@id="name_year"] [@type="text"] [@value="2011"] ] [count(./input)=3] ' ); } public function testDateSingleText() { $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( 'input' => 'string', 'widget' => 'single_text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="date"] [@name="name"] [@value="2011-02-03"] ' ); } public function testDateErrorBubbling() { $form = $this->factory->createNamedBuilder('form', 'form') ->add('date', 'date') ->getForm(); $form->get('date')->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $this->assertEmpty($this->renderErrors($view)); $this->assertNotEmpty($this->renderErrors($view['date'])); } public function testBirthDay() { $form = $this->factory->createNamed('name', 'birthday', '2000-02-03', array( 'input' => 'string', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_year"] [./option[@value="2000"][@selected="selected"]] ] [count(./select)=3] ' ); } public function testBirthDayWithEmptyValue() { $form = $this->factory->createNamed('name', 'birthday', '1950-01-01', array( 'input' => 'string', 'empty_value' => '', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_day"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_year"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] [./option[@value="1950"][@selected="selected"]] ] [count(./select)=3] ' ); } public function testEmail() { $form = $this->factory->createNamed('name', 'email', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="email"] [@name="name"] [@value="foo&bar"] [not(@maxlength)] ' ); } public function testEmailWithMaxLength() { $form = $this->factory->createNamed('name', 'email', 'foo&bar', array( 'max_length' => 123, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="email"] [@name="name"] [@value="foo&bar"] [@maxlength="123"] ' ); } public function testFile() { $form = $this->factory->createNamed('name', 'file'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="file"] ' ); } public function testHidden() { $form = $this->factory->createNamed('name', 'hidden', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="hidden"] [@name="name"] [@value="foo&bar"] ' ); } public function testReadOnly() { $form = $this->factory->createNamed('name', 'text', null, array( 'read_only' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@readonly="readonly"] ' ); } public function testDisabled() { $form = $this->factory->createNamed('name', 'text', null, array( 'disabled' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@disabled="disabled"] ' ); } public function testInteger() { $form = $this->factory->createNamed('name', 'integer', 123); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="number"] [@name="name"] [@value="123"] ' ); } public function testLanguage() { $form = $this->factory->createNamed('name', 'language', 'de'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./option[@value="de"][@selected="selected"][.="[trans]German[/trans]"]] [count(./option)>200] ' ); } public function testLocale() { $form = $this->factory->createNamed('name', 'locale', 'de_AT'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./option[@value="de_AT"][@selected="selected"][.="[trans]German (Austria)[/trans]"]] [count(./option)>200] ' ); } public function testMoney() { $form = $this->factory->createNamed('name', 'money', 1234.56, array( 'currency' => 'EUR', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="1234.56"] [contains(.., "€")] ' ); } public function testNumber() { $form = $this->factory->createNamed('name', 'number', 1234.56); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="1234.56"] ' ); } public function testPassword() { $form = $this->factory->createNamed('name', 'password', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="password"] [@name="name"] ' ); } public function testPasswordSubmittedWithNotAlwaysEmpty() { $form = $this->factory->createNamed('name', 'password', null, array( 'always_empty' => false, )); $form->submit('foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="password"] [@name="name"] [@value="foo&bar"] ' ); } public function testPasswordWithMaxLength() { $form = $this->factory->createNamed('name', 'password', 'foo&bar', array( 'max_length' => 123, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="password"] [@name="name"] [@maxlength="123"] ' ); } public function testPercent() { $form = $this->factory->createNamed('name', 'percent', 0.1); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="10"] [contains(.., "%")] ' ); } public function testCheckedRadio() { $form = $this->factory->createNamed('name', 'radio', true); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="radio"] [@name="name"] [@checked="checked"] [@value="1"] ' ); } public function testUncheckedRadio() { $form = $this->factory->createNamed('name', 'radio', false); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="radio"] [@name="name"] [not(@checked)] ' ); } public function testRadioWithValue() { $form = $this->factory->createNamed('name', 'radio', false, array( 'value' => 'foo&bar', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="radio"] [@name="name"] [@value="foo&bar"] ' ); } public function testTextarea() { $form = $this->factory->createNamed('name', 'textarea', 'foo&bar', array( 'pattern' => 'foo', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/textarea [@name="name"] [not(@pattern)] [.="foo&bar"] ' ); } public function testText() { $form = $this->factory->createNamed('name', 'text', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="foo&bar"] [not(@maxlength)] ' ); } public function testTextWithMaxLength() { $form = $this->factory->createNamed('name', 'text', 'foo&bar', array( 'max_length' => 123, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="foo&bar"] [@maxlength="123"] ' ); } public function testSearch() { $form = $this->factory->createNamed('name', 'search', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="search"] [@name="name"] [@value="foo&bar"] [not(@maxlength)] ' ); } public function testTime() { $form = $this->factory->createNamed('name', 'time', '04:05:06', array( 'input' => 'string', 'with_seconds' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_hour"] [not(@size)] [./option[@value="4"][@selected="selected"]] /following-sibling::select [@id="name_minute"] [not(@size)] [./option[@value="5"][@selected="selected"]] ] [count(./select)=2] ' ); } public function testTimeWithSeconds() { $form = $this->factory->createNamed('name', 'time', '04:05:06', array( 'input' => 'string', 'with_seconds' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_hour"] [not(@size)] [./option[@value="4"][@selected="selected"]] [count(./option)>23] /following-sibling::select [@id="name_minute"] [not(@size)] [./option[@value="5"][@selected="selected"]] [count(./option)>59] /following-sibling::select [@id="name_second"] [not(@size)] [./option[@value="6"][@selected="selected"]] [count(./option)>59] ] [count(./select)=3] ' ); } public function testTimeText() { $form = $this->factory->createNamed('name', 'time', '04:05:06', array( 'input' => 'string', 'widget' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input [@type="text"] [@id="name_hour"] [@name="name[hour]"] [@value="04"] [@size="1"] [@required="required"] /following-sibling::input [@type="text"] [@id="name_minute"] [@name="name[minute]"] [@value="05"] [@size="1"] [@required="required"] ] [count(./input)=2] ' ); } public function testTimeSingleText() { $form = $this->factory->createNamed('name', 'time', '04:05:06', array( 'input' => 'string', 'widget' => 'single_text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="time"] [@name="name"] [@value="04:05"] [not(@size)] ' ); } public function testTimeWithEmptyValueGlobal() { $form = $this->factory->createNamed('name', 'time', null, array( 'input' => 'string', 'empty_value' => 'Change&Me', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_hour"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] [count(./option)>24] /following-sibling::select [@id="name_minute"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] [count(./option)>60] ] [count(./select)=2] ' ); } public function testTimeWithEmptyValueOnYear() { $form = $this->factory->createNamed('name', 'time', null, array( 'input' => 'string', 'required' => false, 'empty_value' => array('hour' => 'Change&Me'), )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_hour"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] [count(./option)>24] /following-sibling::select [@id="name_minute"] [./option[@value="1"]] [count(./option)>59] ] [count(./select)=2] ' ); } public function testTimeErrorBubbling() { $form = $this->factory->createNamedBuilder('form', 'form') ->add('time', 'time') ->getForm(); $form->get('time')->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $this->assertEmpty($this->renderErrors($view)); $this->assertNotEmpty($this->renderErrors($view['time'])); } public function testTimezone() { $form = $this->factory->createNamed('name', 'timezone', 'Europe/Vienna'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [./optgroup [@label="[trans]Europe[/trans]"] [./option[@value="Europe/Vienna"][@selected="selected"][.="[trans]Vienna[/trans]"]] ] [count(./optgroup)>10] [count(.//option)>200] ' ); } public function testTimezoneWithEmptyValue() { $form = $this->factory->createNamed('name', 'timezone', null, array( 'empty_value' => 'Select&Timezone', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Timezone[/trans]"]] [count(./optgroup)>10] [count(.//option)>201] ' ); } public function testUrl() { $url = 'http://www.google.com?foo1=bar1&foo2=bar2'; $form = $this->factory->createNamed('name', 'url', $url); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="url"] [@name="name"] [@value="http://www.google.com?foo1=bar1&foo2=bar2"] ' ); } public function testCollectionPrototype() { $form = $this->factory->createNamedBuilder('name', 'form', array('items' => array('one', 'two', 'three'))) ->add('items', 'collection', array('allow_add' => true)) ->getForm() ->createView(); $html = $this->renderWidget($form); $this->assertMatchesXpath($html, '//div[@id="name_items"][@data-prototype] | //table[@id="name_items"][@data-prototype]' ); } public function testEmptyRootFormName() { $form = $this->factory->createNamedBuilder('', 'form') ->add('child', 'text') ->getForm(); $this->assertMatchesXpath($this->renderWidget($form->createView()), '//input[@type="hidden"][@id="_token"][@name="_token"] | //input[@type="text"][@id="child"][@name="child"]' , 2); } public function testButton() { $form = $this->factory->createNamed('name', 'button'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/button[@type="button"][@name="name"][.="[trans]Name[/trans]"]' ); } public function testButtonLabelIsEmpty() { $form = $this->factory->createNamed('name', 'button'); $this->assertSame('', $this->renderLabel($form->createView())); } public function testSubmit() { $form = $this->factory->createNamed('name', 'submit'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/button[@type="submit"][@name="name"]' ); } public function testReset() { $form = $this->factory->createNamed('name', 'reset'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/button[@type="reset"][@name="name"]' ); } public function testStartTag() { $form = $this->factory->create('form', null, array( 'method' => 'get', 'action' => 'http://example.com/directory' )); $html = $this->renderStart($form->createView()); $this->assertSame('
', $html); } public function testStartTagForPutRequest() { $form = $this->factory->create('form', null, array( 'method' => 'put', 'action' => 'http://example.com/directory' )); $html = $this->renderStart($form->createView()); $this->assertMatchesXpath($html . '', '/form [./input[@type="hidden"][@name="_method"][@value="PUT"]] [@method="post"] [@action="http://example.com/directory"]' ); } public function testStartTagWithOverriddenVars() { $form = $this->factory->create('form', null, array( 'method' => 'put', 'action' => 'http://example.com/directory', )); $html = $this->renderStart($form->createView(), array( 'method' => 'post', 'action' => 'http://foo.com/directory' )); $this->assertSame('
', $html); } public function testStartTagForMultipartForm() { $form = $this->factory->createBuilder('form', null, array( 'method' => 'get', 'action' => 'http://example.com/directory' )) ->add('file', 'file') ->getForm(); $html = $this->renderStart($form->createView()); $this->assertSame('', $html); } public function testStartTagWithExtraAttributes() { $form = $this->factory->create('form', null, array( 'method' => 'get', 'action' => 'http://example.com/directory' )); $html = $this->renderStart($form->createView(), array( 'attr' => array('class' => 'foobar'), )); $this->assertSame('', $html); } public function testWidgetAttributes() { $form = $this->factory->createNamed('text', 'text', 'value', array( 'required' => true, 'disabled' => true, 'read_only' => true, 'max_length' => 10, 'pattern' => '\d+', 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), )); $html = $this->renderWidget($form->createView()); // compare plain HTML to check the whitespace $this->assertSame('', $html); } public function testWidgetAttributeNameRepeatedIfTrue() { $form = $this->factory->createNamed('text', 'text', 'value', array( 'attr' => array('foo' => true), )); $html = $this->renderWidget($form->createView()); // foo="foo" $this->assertSame('', $html); } public function testWidgetAttributeHiddenIfFalse() { $form = $this->factory->createNamed('text', 'text', 'value', array( 'attr' => array('foo' => false), )); $html = $this->renderWidget($form->createView()); // no foo $this->assertSame('', $html); } public function testButtonAttributes() { $form = $this->factory->createNamed('button', 'button', null, array( 'disabled' => true, 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), )); $html = $this->renderWidget($form->createView()); // compare plain HTML to check the whitespace $this->assertSame('', $html); } public function testButtonAttributeNameRepeatedIfTrue() { $form = $this->factory->createNamed('button', 'button', null, array( 'attr' => array('foo' => true), )); $html = $this->renderWidget($form->createView()); // foo="foo" $this->assertSame('', $html); } public function testButtonAttributeHiddenIfFalse() { $form = $this->factory->createNamed('button', 'button', null, array( 'attr' => array('foo' => false), )); $html = $this->renderWidget($form->createView()); // no foo $this->assertSame('', $html); } } PK!:test/Form/Symfony/Component/Form/Tests/Guess/GuessTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Guess; use Symfony\Component\Form\Guess\Guess; class TestGuess extends Guess {} class GuessTest extends \PHPUnit_Framework_TestCase { public function testGetBestGuessReturnsGuessWithHighestConfidence() { $guess1 = new TestGuess(Guess::MEDIUM_CONFIDENCE); $guess2 = new TestGuess(Guess::LOW_CONFIDENCE); $guess3 = new TestGuess(Guess::HIGH_CONFIDENCE); $this->assertSame($guess3, Guess::getBestGuess(array($guess1, $guess2, $guess3))); } /** * @expectedException \InvalidArgumentException */ public function testGuessExpectsValidConfidence() { new TestGuess(5); } } PK!uEtest/Form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; /** * This class is a hand written simplified version of PHP native `ArrayObject` * class, to show that it behaves differently than the PHP native implementation. */ class CustomArrayObject implements \ArrayAccess, \IteratorAggregate, \Countable, \Serializable { private $array; public function __construct(array $array = null) { $this->array = $array ?: array(); } public function offsetExists($offset) { return array_key_exists($offset, $this->array); } public function offsetGet($offset) { return $this->array[$offset]; } public function offsetSet($offset, $value) { if (null === $offset) { $this->array[] = $value; } else { $this->array[$offset] = $value; } } public function offsetUnset($offset) { unset($this->array[$offset]); } public function getIterator() { return new \ArrayIterator($this->array); } public function count() { return count($this->array); } public function serialize() { return serialize($this->array); } public function unserialize($serialized) { $this->array = (array) unserialize((string) $serialized); } } PK!x:test/Form/Symfony/Component/Form/Tests/Fixtures/Author.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; class Author { public $firstName; private $lastName; private $australian; public $child; private $readPermissions; private $privateProperty; public function setLastName($lastName) { $this->lastName = $lastName; } public function getLastName() { return $this->lastName; } private function getPrivateGetter() { return 'foobar'; } public function setAustralian($australian) { $this->australian = $australian; } public function isAustralian() { return $this->australian; } public function setReadPermissions($bool) { $this->readPermissions = $bool; } public function hasReadPermissions() { return $this->readPermissions; } private function isPrivateIsser() { return true; } public function getPrivateSetter() { } private function setPrivateSetter($data) { } } PK!3test/Form/Symfony/Component/Form/Tests/Fixtures/foonu[PK![َGtest/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; class FooTypeBazExtension extends AbstractTypeExtension { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setAttribute('baz', 'x'); } public function getExtendedType() { return 'foo'; } } PK!*;test/Form/Symfony/Component/Form/Tests/Fixtures/FooType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FooType extends AbstractType { public function getName() { return 'foo'; } public function getParent() { return null; } } PK!:.zFtest/Form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.phpnu[getFormFactory(); $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) { $form = $event->getForm(); $type = $form->getName() % 2 === 0 ? 'text' : 'textarea'; $form->add('title', $type); }); } public function getName() { return 'alternating_row'; } } PK!֫v>test/Form/Symfony/Component/Form/Tests/Fixtures/AuthorType.phpnu[add('firstName') ->add('lastName') ; } public function getName() { return 'author'; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', )); } } PK!#o>test/Form/Symfony/Component/Form/Tests/Fixtures/FooSubType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FooSubType extends AbstractType { public function getName() { return 'foo_sub_type'; } public function getParent() { return 'foo'; } } PK!8Atest/Form/Symfony/Component/Form/Tests/Fixtures/TestExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\FormTypeExtensionInterface; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\FormExtensionInterface; class TestExtension implements FormExtensionInterface { private $types = array(); private $extensions = array(); private $guesser; public function __construct(FormTypeGuesserInterface $guesser) { $this->guesser = $guesser; } public function addType(FormTypeInterface $type) { $this->types[$type->getName()] = $type; } public function getType($name) { return isset($this->types[$name]) ? $this->types[$name] : null; } public function hasType($name) { return isset($this->types[$name]); } public function addTypeExtension(FormTypeExtensionInterface $extension) { $type = $extension->getExtendedType(); if (!isset($this->extensions[$type])) { $this->extensions[$type] = array(); } $this->extensions[$type][] = $extension; } public function getTypeExtensions($name) { return isset($this->extensions[$name]) ? $this->extensions[$name] : array(); } public function hasTypeExtensions($name) { return isset($this->extensions[$name]); } public function getTypeGuesser() { return $this->guesser; } } PK!x  Gtest/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; class FooTypeBarExtension extends AbstractTypeExtension { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setAttribute('bar', 'x'); } public function getAllowedOptionValues() { return array( 'a_or_b' => array('c'), ); } public function getExtendedType() { return 'foo'; } } PK!m^2++Ptest/Form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FooSubTypeWithParentInstance extends AbstractType { public function getName() { return 'foo_sub_type_parent_instance'; } public function getParent() { return new FooType(); } } PK!!uGtest/Form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class FixedFilterListener implements EventSubscriberInterface { private $mapping; public function __construct(array $mapping) { $this->mapping = array_merge(array( 'preSubmit' => array(), 'onSubmit' => array(), 'preSetData' => array(), ), $mapping); } public function preSubmit(FormEvent $event) { $data = $event->getData(); if (isset($this->mapping['preSubmit'][$data])) { $event->setData($this->mapping['preSubmit'][$data]); } } public function onSubmit(FormEvent $event) { $data = $event->getData(); if (isset($this->mapping['onSubmit'][$data])) { $event->setData($this->mapping['onSubmit'][$data]); } } public function preSetData(FormEvent $event) { $data = $event->getData(); if (isset($this->mapping['preSetData'][$data])) { $event->setData($this->mapping['preSetData'][$data]); } } public static function getSubscribedEvents() { return array( FormEvents::PRE_SUBMIT => 'preSubmit', FormEvents::SUBMIT => 'onSubmit', FormEvents::PRE_SET_DATA => 'preSetData', ); } } PK!ŲUUHtest/Form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\RuntimeException; class FixedDataTransformer implements DataTransformerInterface { private $mapping; public function __construct(array $mapping) { $this->mapping = $mapping; } public function transform($value) { if (!array_key_exists($value, $this->mapping)) { throw new RuntimeException(sprintf('No mapping for value "%s"', $value)); } return $this->mapping[$value]; } public function reverseTransform($value) { $result = array_search($value, $this->mapping, true); if ($result === false) { throw new RuntimeException(sprintf('No reverse mapping for value "%s"', $value)); } return $result; } } PK!JRR:test/Form/Symfony/Component/Form/Tests/FormFactoryTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\ValueGuess; use Symfony\Component\Form\Guess\TypeGuess; use Symfony\Component\Form\Tests\Fixtures\Author; use Symfony\Component\Form\Tests\Fixtures\FooType; use Symfony\Component\Form\Tests\Fixtures\FooSubType; use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance; /** * @author Bernhard Schussek */ class FormFactoryTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $guesser1; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $guesser2; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $registry; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $resolvedTypeFactory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $builder; /** * @var FormFactory */ private $factory; protected function setUp() { $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactoryInterface'); $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->registry = $this->getMock('Symfony\Component\Form\FormRegistryInterface'); $this->builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface'); $this->factory = new FormFactory($this->registry, $this->resolvedTypeFactory); $this->registry->expects($this->any()) ->method('getTypeGuesser') ->will($this->returnValue(new FormTypeGuesserChain(array( $this->guesser1, $this->guesser2, )))); } public function testCreateNamedBuilderWithTypeName() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('type') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', null, $options)); } public function testCreateNamedBuilderWithTypeInstance() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $type = new FooType(); $resolvedType = $this->getMockResolvedType(); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options)); } public function testCreateNamedBuilderWithTypeInstanceWithParentType() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $type = new FooSubType(); $resolvedType = $this->getMockResolvedType(); $parentResolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('foo') ->will($this->returnValue($parentResolvedType)); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type, array(), $parentResolvedType) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options)); } public function testCreateNamedBuilderWithTypeInstanceWithParentTypeInstance() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $type = new FooSubTypeWithParentInstance(); $resolvedType = $this->getMockResolvedType(); $parentResolvedType = $this->getMockResolvedType(); $this->resolvedTypeFactory->expects($this->at(0)) ->method('createResolvedType') ->with($type->getParent()) ->will($this->returnValue($parentResolvedType)); $this->resolvedTypeFactory->expects($this->at(1)) ->method('createResolvedType') ->with($type, array(), $parentResolvedType) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options)); } public function testCreateNamedBuilderWithResolvedTypeInstance() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $resolvedType, null, $options)); } public function testCreateNamedBuilderFillsDataOption() { $givenOptions = array('a' => '1', 'b' => '2'); $expectedOptions = array_merge($givenOptions, array('data' => 'DATA')); $resolvedOptions = array('a' => '2', 'b' => '3', 'data' => 'DATA'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('type') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $expectedOptions) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', 'DATA', $givenOptions)); } public function testCreateNamedBuilderDoesNotOverrideExistingDataOption() { $options = array('a' => '1', 'b' => '2', 'data' => 'CUSTOM'); $resolvedOptions = array('a' => '2', 'b' => '3', 'data' => 'CUSTOM'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('type') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', 'DATA', $options)); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException * @expectedExceptionMessage Expected argument of type "string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface", "stdClass" given */ public function testCreateNamedBuilderThrowsUnderstandableException() { $this->factory->createNamedBuilder('name', new \stdClass()); } public function testCreateUsesTypeNameIfTypeGivenAsString() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('TYPE') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'TYPE', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->builder->expects($this->once()) ->method('getForm') ->will($this->returnValue('FORM')); $this->assertSame('FORM', $this->factory->create('TYPE', null, $options)); } public function testCreateUsesTypeNameIfTypeGivenAsObject() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $resolvedType->expects($this->once()) ->method('getName') ->will($this->returnValue('TYPE')); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'TYPE', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->builder->expects($this->once()) ->method('getForm') ->will($this->returnValue('FORM')); $this->assertSame('FORM', $this->factory->create($resolvedType, null, $options)); } public function testCreateNamed() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('type') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->builder->expects($this->once()) ->method('getForm') ->will($this->returnValue('FORM')); $this->assertSame('FORM', $this->factory->createNamed('name', 'type', null, $options)); } public function testCreateBuilderForPropertyWithoutTypeGuesser() { $registry = $this->getMock('Symfony\Component\Form\FormRegistryInterface'); $factory = $this->getMockBuilder('Symfony\Component\Form\FormFactory') ->setMethods(array('createNamedBuilder')) ->setConstructorArgs(array($registry, $this->resolvedTypeFactory)) ->getMock(); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array()) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence() { $this->guesser1->expects($this->once()) ->method('guessType') ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'text', array('max_length' => 10), Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) ->method('guessType') ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'password', array('max_length' => 7), Guess::HIGH_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'password', null, array('max_length' => 7)) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderCreatesTextFormIfNoGuess() { $this->guesser1->expects($this->once()) ->method('guessType') ->with('Application\Author', 'firstName') ->will($this->returnValue(null)); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text') ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); $this->assertEquals('builderInstance', $this->builder); } public function testOptionsCanBeOverridden() { $this->guesser1->expects($this->once()) ->method('guessType') ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'text', array('max_length' => 10), Guess::MEDIUM_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array('max_length' => 11)) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( 'Application\Author', 'firstName', null, array('max_length' => 11) ); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderUsesMaxLengthIfFound() { $this->guesser1->expects($this->once()) ->method('guessMaxLength') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( 15, Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) ->method('guessMaxLength') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( 20, Guess::HIGH_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array('max_length' => 20)) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( 'Application\Author', 'firstName' ); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderUsesRequiredSettingWithHighestConfidence() { $this->guesser1->expects($this->once()) ->method('guessRequired') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( true, Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) ->method('guessRequired') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( false, Guess::HIGH_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array('required' => false)) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( 'Application\Author', 'firstName' ); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderUsesPatternIfFound() { $this->guesser1->expects($this->once()) ->method('guessPattern') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( '[a-z]', Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) ->method('guessPattern') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( '[a-zA-Z]', Guess::HIGH_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array('pattern' => '[a-zA-Z]')) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( 'Application\Author', 'firstName' ); $this->assertEquals('builderInstance', $this->builder); } private function getMockFactory(array $methods = array()) { return $this->getMockBuilder('Symfony\Component\Form\FormFactory') ->setMethods($methods) ->setConstructorArgs(array($this->registry, $this->resolvedTypeFactory)) ->getMock(); } private function getMockResolvedType() { return $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); } private function getMockType() { return $this->getMock('Symfony\Component\Form\FormTypeInterface'); } } PK!ȔfVA6A6Btest/Form/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Util; use Symfony\Component\Form\Util\OrderedHashMap; /** * @author Bernhard Schussek */ class OrderedHashMapTest extends \PHPUnit_Framework_TestCase { public function testGet() { $map = new OrderedHashMap(); $map['first'] = 1; $this->assertSame(1, $map['first']); } /** * @expectedException \OutOfBoundsException */ public function testGetNonExistingFails() { $map = new OrderedHashMap(); $map['first']; } public function testInsertStringKeys() { $map = new OrderedHashMap(); $map['first'] = 1; $map['second'] = 2; $this->assertSame(array('first' => 1, 'second' => 2), iterator_to_array($map)); } public function testInsertNullKeys() { $map = new OrderedHashMap(); $map[] = 1; $map['foo'] = 2; $map[] = 3; $this->assertSame(array(0 => 1, 'foo' => 2, 1 => 3), iterator_to_array($map)); } /** * Updates should not change the position of an element, otherwise we could * turn foreach loops into endless loops if they change the current * element: * * foreach ($map as $index => $value) { * $map[$index] = $value + 1; * } * * And we don't want this, right? :) */ public function testUpdateDoesNotChangeElementPosition() { $map = new OrderedHashMap(); $map['first'] = 1; $map['second'] = 2; $map['first'] = 1; $this->assertSame(array('first' => 1, 'second' => 2), iterator_to_array($map)); } public function testIsset() { $map = new OrderedHashMap(); $map['first'] = 1; $this->assertTrue(isset($map['first'])); } public function testIssetReturnsFalseForNonExisting() { $map = new OrderedHashMap(); $this->assertFalse(isset($map['first'])); } public function testIssetReturnsFalseForNull() { $map = new OrderedHashMap(); $map['first'] = null; $this->assertFalse(isset($map['first'])); } public function testUnset() { $map = new OrderedHashMap(); $map['first'] = 1; $map['second'] = 2; unset($map['first']); $this->assertSame(array('second' => 2), iterator_to_array($map)); } public function testUnsetNonExistingSucceeds() { $map = new OrderedHashMap(); unset($map['first']); } public function testEmptyIteration() { $map = new OrderedHashMap(); $it = $map->getIterator(); $it->rewind(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsInsertion() { $map = new OrderedHashMap(array('first' => 1)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('first', $it->key()); $this->assertSame(1, $it->current()); // dynamic modification $map['added'] = 2; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('first', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('added', $it->key()); $this->assertSame(2, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionAndInsertion() { $map = new OrderedHashMap(array('first' => 1, 'removed' => 2)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('first', $it->key()); $this->assertSame(1, $it->current()); // dynamic modification unset($map['removed']); $map['added'] = 3; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('first', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('added', $it->key()); $this->assertSame(3, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionOfCurrentElement() { $map = new OrderedHashMap(array('removed' => 1, 'next' => 2)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); unset($map['removed']); // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationIgnoresReplacementOfCurrentElement() { $map = new OrderedHashMap(array('replaced' => 1, 'next' => 2)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); $map['replaced'] = 3; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionOfCurrentAndLastElement() { $map = new OrderedHashMap(array('removed' => 1)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); unset($map['removed']); // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationIgnoresReplacementOfCurrentAndLastElement() { $map = new OrderedHashMap(array('replaced' => 1)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); $map['replaced'] = 2; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionOfPreviousElement() { $map = new OrderedHashMap(array('removed' => 1, 'next' => 2, 'onemore' => 3)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); unset($map['removed']); // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('onemore', $it->key()); $this->assertSame(3, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationIgnoresReplacementOfPreviousElement() { $map = new OrderedHashMap(array('replaced' => 1, 'next' => 2, 'onemore' => 3)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); $map['replaced'] = 4; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('onemore', $it->key()); $this->assertSame(3, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionOfMultiplePreviousElements() { $map = new OrderedHashMap(array('removed' => 1, 'alsoremoved' => 2, 'next' => 3, 'onemore' => 4)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('alsoremoved', $it->key()); $this->assertSame(2, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(3, $it->current()); unset($map['removed'], $map['alsoremoved']); // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(3, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('onemore', $it->key()); $this->assertSame(4, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testParallelIteration() { $map = new OrderedHashMap(array('first' => 1, 'second' => 2)); $it1 = $map->getIterator(); $it2 = $map->getIterator(); $it1->rewind(); $this->assertTrue($it1->valid()); $this->assertSame('first', $it1->key()); $this->assertSame(1, $it1->current()); $it2->rewind(); $this->assertTrue($it2->valid()); $this->assertSame('first', $it2->key()); $this->assertSame(1, $it2->current()); // 1: continue iteration $it1->next(); $this->assertTrue($it1->valid()); $this->assertSame('second', $it1->key()); $this->assertSame(2, $it1->current()); // 2: remains unchanged $this->assertTrue($it2->valid()); $this->assertSame('first', $it2->key()); $this->assertSame(1, $it2->current()); // 1: advance to end of map $it1->next(); $this->assertFalse($it1->valid()); $this->assertNull($it1->key()); $this->assertNull($it1->current()); // 2: remains unchanged $this->assertTrue($it2->valid()); $this->assertSame('first', $it2->key()); $this->assertSame(1, $it2->current()); // 2: continue iteration $it2->next(); $this->assertTrue($it2->valid()); $this->assertSame('second', $it2->key()); $this->assertSame(2, $it2->current()); // 1: remains unchanged $this->assertFalse($it1->valid()); $this->assertNull($it1->key()); $this->assertNull($it1->current()); // 2: advance to end of map $it2->next(); $this->assertFalse($it2->valid()); $this->assertNull($it2->key()); $this->assertNull($it2->current()); // 1: remains unchanged $this->assertFalse($it1->valid()); $this->assertNull($it1->key()); $this->assertNull($it1->current()); } public function testCount() { $map = new OrderedHashMap(); $map[] = 1; $map['foo'] = 2; unset($map[0]); $map[] = 3; $this->assertSame(2, count($map)); } } PK!znznz;test/Form/Symfony/Component/Form/Tests/CompoundFormTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Forms; use Symfony\Component\Form\FormView; use Symfony\Component\Form\SubmitButtonBuilder; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; class CompoundFormTest extends AbstractFormTest { public function testValidIfAllChildrenAreValid() { $this->form->add($this->getBuilder('firstName')->getForm()); $this->form->add($this->getBuilder('lastName')->getForm()); $this->form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); $this->assertTrue($this->form->isValid()); } public function testInvalidIfChildIsInvalid() { $this->form->add($this->getBuilder('firstName')->getForm()); $this->form->add($this->getBuilder('lastName')->getForm()); $this->form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); $this->form->get('lastName')->addError(new FormError('Invalid')); $this->assertFalse($this->form->isValid()); } public function testValidIfChildIsNotSubmitted() { $this->form->add($this->getBuilder('firstName')->getForm()); $this->form->add($this->getBuilder('lastName')->getForm()); $this->form->submit(array( 'firstName' => 'Bernhard', )); // "lastName" is not "valid" because it was not submitted. This happens // for example in PATCH requests. The parent form should still be // considered valid. $this->assertTrue($this->form->isValid()); } public function testDisabledFormsValidEvenIfChildrenInvalid() { $form = $this->getBuilder('person') ->setDisabled(true) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add($this->getBuilder('name')) ->getForm(); $form->submit(array('name' => 'Jacques Doe')); $form->get('name')->addError(new FormError('Invalid')); $this->assertTrue($form->isValid()); } public function testSubmitForwardsNullIfNotClearMissingButValueIsExplicitlyNull() { $child = $this->getMockForm('firstName'); $this->form->add($child); $child->expects($this->once()) ->method('submit') ->with($this->equalTo(null)); $this->form->submit(array('firstName' => null), false); } public function testSubmitForwardsNullIfValueIsMissing() { $child = $this->getMockForm('firstName'); $this->form->add($child); $child->expects($this->once()) ->method('submit') ->with($this->equalTo(null)); $this->form->submit(array()); } public function testSubmitDoesNotForwardNullIfNotClearMissing() { $child = $this->getMockForm('firstName'); $this->form->add($child); $child->expects($this->never()) ->method('submit'); $this->form->submit(array(), false); } public function testSubmitDoesNotAddExtraFieldForNullValues() { $factory = Forms::createFormFactoryBuilder() ->getFormFactory(); $child = $factory->create('file', null, array('auto_initialize' => false)); $this->form->add($child); $this->form->submit(array('file' => null), false); $this->assertCount(0, $this->form->getExtraData()); } public function testClearMissingFlagIsForwarded() { $child = $this->getMockForm('firstName'); $this->form->add($child); $child->expects($this->once()) ->method('submit') ->with($this->equalTo('foo'), false); $this->form->submit(array('firstName' => 'foo'), false); } public function testCloneChildren() { $child = $this->getBuilder('child')->getForm(); $this->form->add($child); $clone = clone $this->form; $this->assertNotSame($this->form, $clone); $this->assertNotSame($child, $clone['child']); $this->assertNotSame($this->form['child'], $clone['child']); } public function testNotEmptyIfChildNotEmpty() { $child = $this->getMockForm(); $child->expects($this->once()) ->method('isEmpty') ->will($this->returnValue(false)); $this->form->setData(null); $this->form->add($child); $this->assertFalse($this->form->isEmpty()); } public function testAdd() { $child = $this->getBuilder('foo')->getForm(); $this->form->add($child); $this->assertTrue($this->form->has('foo')); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array('foo' => $child), $this->form->all()); } public function testAddUsingNameAndType() { $child = $this->getBuilder('foo')->getForm(); $this->factory->expects($this->once()) ->method('createNamed') ->with('foo', 'text', null, array( 'bar' => 'baz', 'auto_initialize' => false, )) ->will($this->returnValue($child)); $this->form->add('foo', 'text', array('bar' => 'baz')); $this->assertTrue($this->form->has('foo')); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array('foo' => $child), $this->form->all()); } public function testAddUsingIntegerNameAndType() { $child = $this->getBuilder(0)->getForm(); $this->factory->expects($this->once()) ->method('createNamed') ->with('0', 'text', null, array( 'bar' => 'baz', 'auto_initialize' => false, )) ->will($this->returnValue($child)); // in order to make casting unnecessary $this->form->add(0, 'text', array('bar' => 'baz')); $this->assertTrue($this->form->has(0)); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array(0 => $child), $this->form->all()); } public function testAddUsingNameButNoType() { $this->form = $this->getBuilder('name', null, '\stdClass') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $child = $this->getBuilder('foo')->getForm(); $this->factory->expects($this->once()) ->method('createForProperty') ->with('\stdClass', 'foo') ->will($this->returnValue($child)); $this->form->add('foo'); $this->assertTrue($this->form->has('foo')); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array('foo' => $child), $this->form->all()); } public function testAddUsingNameButNoTypeAndOptions() { $this->form = $this->getBuilder('name', null, '\stdClass') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $child = $this->getBuilder('foo')->getForm(); $this->factory->expects($this->once()) ->method('createForProperty') ->with('\stdClass', 'foo', null, array( 'bar' => 'baz', 'auto_initialize' => false, )) ->will($this->returnValue($child)); $this->form->add('foo', null, array('bar' => 'baz')); $this->assertTrue($this->form->has('foo')); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array('foo' => $child), $this->form->all()); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testAddThrowsExceptionIfAlreadySubmitted() { $this->form->submit(array()); $this->form->add($this->getBuilder('foo')->getForm()); } public function testRemove() { $child = $this->getBuilder('foo')->getForm(); $this->form->add($child); $this->form->remove('foo'); $this->assertNull($child->getParent()); $this->assertCount(0, $this->form); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testRemoveThrowsExceptionIfAlreadySubmitted() { $this->form->add($this->getBuilder('foo')->setCompound(false)->getForm()); $this->form->submit(array('foo' => 'bar')); $this->form->remove('foo'); } public function testRemoveIgnoresUnknownName() { $this->form->remove('notexisting'); } public function testArrayAccess() { $child = $this->getBuilder('foo')->getForm(); $this->form[] = $child; $this->assertTrue(isset($this->form['foo'])); $this->assertSame($child, $this->form['foo']); unset($this->form['foo']); $this->assertFalse(isset($this->form['foo'])); } public function testCountable() { $this->form->add($this->getBuilder('foo')->getForm()); $this->form->add($this->getBuilder('bar')->getForm()); $this->assertCount(2, $this->form); } public function testIterator() { $this->form->add($this->getBuilder('foo')->getForm()); $this->form->add($this->getBuilder('bar')->getForm()); $this->assertSame($this->form->all(), iterator_to_array($this->form)); } public function testAddMapsViewDataToFormIfInitialized() { $test = $this; $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => 'bar', ))) ->setData('foo') ->getForm(); $child = $this->getBuilder()->getForm(); $mapper->expects($this->once()) ->method('mapDataToForms') ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator')) ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child, $test) { $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); $test->assertSame(array($child), iterator_to_array($iterator)); })); $form->initialize(); $form->add($child); } public function testAddDoesNotMapViewDataToFormIfNotInitialized() { $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->getForm(); $child = $this->getBuilder()->getForm(); $mapper->expects($this->never()) ->method('mapDataToForms'); $form->add($child); } public function testAddDoesNotMapViewDataToFormIfInheritData() { $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->setInheritData(true) ->getForm(); $child = $this->getBuilder()->getForm(); $mapper->expects($this->never()) ->method('mapDataToForms'); $form->initialize(); $form->add($child); } public function testSetDataSupportsDynamicAdditionAndRemovalOfChildren() { $form = $this->getBuilder() ->setCompound(true) // We test using PropertyPathMapper on purpose. The traversal logic // is currently contained in InheritDataAwareIterator, but even // if that changes, this test should still function. ->setDataMapper(new PropertyPathMapper()) ->getForm(); $child = $this->getMockForm('child'); $childToBeRemoved = $this->getMockForm('removed'); $childToBeAdded = $this->getMockForm('added'); $form->add($child); $form->add($childToBeRemoved); $child->expects($this->once()) ->method('setData') ->will($this->returnCallback(function () use ($form, $childToBeAdded) { $form->remove('removed'); $form->add($childToBeAdded); })); $childToBeRemoved->expects($this->never()) ->method('setData'); // once when it it is created, once when it is added $childToBeAdded->expects($this->exactly(2)) ->method('setData'); // pass NULL to all children $form->setData(array()); } public function testSetDataMapsViewDataToChildren() { $test = $this; $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => 'bar', ))) ->getForm(); $form->add($child1 = $this->getBuilder('firstName')->getForm()); $form->add($child2 = $this->getBuilder('lastName')->getForm()); $mapper->expects($this->once()) ->method('mapDataToForms') ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator')) ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) { $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator)); })); $form->setData('foo'); } public function testSubmitSupportsDynamicAdditionAndRemovalOfChildren() { $child = $this->getMockForm('child'); $childToBeRemoved = $this->getMockForm('removed'); $childToBeAdded = $this->getMockForm('added'); $this->form->add($child); $this->form->add($childToBeRemoved); $form = $this->form; $child->expects($this->once()) ->method('submit') ->will($this->returnCallback(function () use ($form, $childToBeAdded) { $form->remove('removed'); $form->add($childToBeAdded); })); $childToBeRemoved->expects($this->never()) ->method('submit'); $childToBeAdded->expects($this->once()) ->method('submit'); // pass NULL to all children $this->form->submit(array()); } public function testSubmitMapsSubmittedChildrenOntoExistingViewData() { $test = $this; $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => 'bar', ))) ->setData('foo') ->getForm(); $form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm()); $form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm()); $mapper->expects($this->once()) ->method('mapFormsToData') ->with($this->isInstanceOf('\RecursiveIteratorIterator'), 'bar') ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) { $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator)); $test->assertEquals('Bernhard', $child1->getData()); $test->assertEquals('Schussek', $child2->getData()); })); $form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); } public function testMapFormsToDataIsNotInvokedIfInheritData() { $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->setInheritData(true) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => 'bar', ))) ->getForm(); $form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm()); $form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm()); $mapper->expects($this->never()) ->method('mapFormsToData'); $form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); } /* * https://github.com/symfony/symfony/issues/4480 */ public function testSubmitRestoresViewDataIfCompoundAndEmpty() { $mapper = $this->getDataMapper(); $object = new \stdClass(); $form = $this->getBuilder('name', null, 'stdClass') ->setCompound(true) ->setDataMapper($mapper) ->setData($object) ->getForm(); $form->submit(array()); $this->assertSame($object, $form->getData()); } public function testSubmitMapsSubmittedChildrenOntoEmptyData() { $test = $this; $mapper = $this->getDataMapper(); $object = new \stdClass(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->setEmptyData($object) ->setData(null) ->getForm(); $form->add($child = $this->getBuilder('name')->setCompound(false)->getForm()); $mapper->expects($this->once()) ->method('mapFormsToData') ->with($this->isInstanceOf('\RecursiveIteratorIterator'), $object) ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child, $test) { $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); $test->assertSame(array('name' => $child), iterator_to_array($iterator)); })); $form->submit(array( 'name' => 'Bernhard', )); } public function requestMethodProvider() { return array( array('POST'), array('PUT'), array('DELETE'), array('PATCH'), ); } /** * @dataProvider requestMethodProvider */ public function testSubmitPostOrPutRequest($method) { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $values = array( 'author' => array( 'name' => 'Bernhard', 'image' => array('filename' => 'foobar.png'), ), ); $files = array( 'author' => array( 'error' => array('image' => UPLOAD_ERR_OK), 'name' => array('image' => 'upload.png'), 'size' => array('image' => 123), 'tmp_name' => array('image' => $path), 'type' => array('image' => 'image/png'), ), ); $request = new Request(array(), $values, array(), array(), $files, array( 'REQUEST_METHOD' => $method, )); $form = $this->getBuilder('author') ->setMethod($method) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); $form->handleRequest($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); $this->assertEquals('Bernhard', $form['name']->getData()); $this->assertEquals($file, $form['image']->getData()); unlink($path); } /** * @dataProvider requestMethodProvider */ public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $values = array( 'name' => 'Bernhard', 'extra' => 'data', ); $files = array( 'image' => array( 'error' => UPLOAD_ERR_OK, 'name' => 'upload.png', 'size' => 123, 'tmp_name' => $path, 'type' => 'image/png', ), ); $request = new Request(array(), $values, array(), array(), $files, array( 'REQUEST_METHOD' => $method, )); $form = $this->getBuilder('') ->setMethod($method) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); $form->handleRequest($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); $this->assertEquals('Bernhard', $form['name']->getData()); $this->assertEquals($file, $form['image']->getData()); $this->assertEquals(array('extra' => 'data'), $form->getExtraData()); unlink($path); } /** * @dataProvider requestMethodProvider */ public function testSubmitPostOrPutRequestWithSingleChildForm($method) { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $files = array( 'image' => array( 'error' => UPLOAD_ERR_OK, 'name' => 'upload.png', 'size' => 123, 'tmp_name' => $path, 'type' => 'image/png', ), ); $request = new Request(array(), array(), array(), array(), $files, array( 'REQUEST_METHOD' => $method, )); $form = $this->getBuilder('image') ->setMethod($method) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->handleRequest($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); $this->assertEquals($file, $form->getData()); unlink($path); } /** * @dataProvider requestMethodProvider */ public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($method) { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $values = array( 'name' => 'Bernhard', ); $request = new Request(array(), $values, array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); $form = $this->getBuilder('name') ->setMethod($method) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->handleRequest($request); $this->assertEquals('Bernhard', $form->getData()); unlink($path); } public function testSubmitGetRequest() { $values = array( 'author' => array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', ), ); $request = new Request($values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $form = $this->getBuilder('author') ->setMethod('GET') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); $form->handleRequest($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); } public function testSubmitGetRequestWithEmptyRootFormName() { $values = array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', 'extra' => 'data' ); $request = new Request($values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $form = $this->getBuilder('') ->setMethod('GET') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); $form->handleRequest($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); $this->assertEquals(array('extra' => 'data'), $form->getExtraData()); } public function testGetErrorsAsStringDeep() { $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $this->form->addError(new FormError('Error!')); $parent->add($this->form); $parent->add($this->getBuilder('foo')->getForm()); $this->assertEquals("name:\n ERROR: Error!\nfoo:\n No errors\n", $parent->getErrorsAsString()); } // Basic cases are covered in SimpleFormTest public function testCreateViewWithChildren() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $options = array('a' => 'Foo', 'b' => 'Bar'); $field1 = $this->getMockForm('foo'); $field2 = $this->getMockForm('bar'); $view = new FormView(); $field1View = new FormView(); $field2View = new FormView(); $this->form = $this->getBuilder('form', null, null, $options) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setType($type) ->getForm(); $this->form->add($field1); $this->form->add($field2); $test = $this; $assertChildViewsEqual = function (array $childViews) use ($test) { return function (FormView $view) use ($test, $childViews) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertSame($childViews, $view->children); }; }; // First create the view $type->expects($this->once()) ->method('createView') ->will($this->returnValue($view)); // Then build it for the form itself $type->expects($this->once()) ->method('buildView') ->with($view, $this->form, $options) ->will($this->returnCallback($assertChildViewsEqual(array()))); // Then add the first child form $field1->expects($this->once()) ->method('createView') ->will($this->returnValue($field1View)); // Then the second child form $field2->expects($this->once()) ->method('createView') ->will($this->returnValue($field2View)); // Again build the view for the form itself. This time the child views // exist. $type->expects($this->once()) ->method('finishView') ->with($view, $this->form, $options) ->will($this->returnCallback($assertChildViewsEqual(array('foo' => $field1View, 'bar' => $field2View)))); $this->assertSame($view, $this->form->createView()); } public function testNoClickedButtonBeforeSubmission() { $this->assertNull($this->form->getClickedButton()); } public function testNoClickedButton() { $button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton') ->setConstructorArgs(array(new SubmitButtonBuilder('submit'))) ->setMethods(array('isClicked')) ->getMock(); $button->expects($this->any()) ->method('isClicked') ->will($this->returnValue(false)); $parentForm = $this->getBuilder('parent')->getForm(); $nestedForm = $this->getBuilder('nested')->getForm(); $this->form->setParent($parentForm); $this->form->add($button); $this->form->add($nestedForm); $this->form->submit(array()); $this->assertNull($this->form->getClickedButton()); } public function testClickedButton() { $button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton') ->setConstructorArgs(array(new SubmitButtonBuilder('submit'))) ->setMethods(array('isClicked')) ->getMock(); $button->expects($this->any()) ->method('isClicked') ->will($this->returnValue(true)); $this->form->add($button); $this->form->submit(array()); $this->assertSame($button, $this->form->getClickedButton()); } public function testClickedButtonFromNestedForm() { $button = $this->getBuilder('submit')->getForm(); $nestedForm = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($this->getBuilder('nested'))) ->setMethods(array('getClickedButton')) ->getMock(); $nestedForm->expects($this->any()) ->method('getClickedButton') ->will($this->returnValue($button)); $this->form->add($nestedForm); $this->form->submit(array()); $this->assertSame($button, $this->form->getClickedButton()); } public function testClickedButtonFromParentForm() { $button = $this->getBuilder('submit')->getForm(); $parentForm = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($this->getBuilder('parent'))) ->setMethods(array('getClickedButton')) ->getMock(); $parentForm->expects($this->any()) ->method('getClickedButton') ->will($this->returnValue($button)); $this->form->setParent($parentForm); $this->form->submit(array()); $this->assertSame($button, $this->form->getClickedButton()); } protected function createForm() { return $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); } } PK!dAtest/Form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormFactoryBuilder; use Symfony\Component\Form\Tests\Fixtures\FooType; class FormFactoryBuilderTest extends \PHPUnit_Framework_TestCase { private $registry; private $guesser; private $type; protected function setUp() { $factory = new \ReflectionClass('Symfony\Component\Form\FormFactory'); $this->registry = $factory->getProperty('registry'); $this->registry->setAccessible(true); $this->guesser = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->type = new FooType(); } public function testAddType() { $factoryBuilder = new FormFactoryBuilder(); $factoryBuilder->addType($this->type); $factory = $factoryBuilder->getFormFactory(); $registry = $this->registry->getValue($factory); $extensions = $registry->getExtensions(); $this->assertCount(1, $extensions); $this->assertTrue($extensions[0]->hasType($this->type->getName())); $this->assertNull($extensions[0]->getTypeGuesser()); } public function testAddTypeGuesser() { $factoryBuilder = new FormFactoryBuilder(); $factoryBuilder->addTypeGuesser($this->guesser); $factory = $factoryBuilder->getFormFactory(); $registry = $this->registry->getValue($factory); $extensions = $registry->getExtensions(); $this->assertCount(1, $extensions); $this->assertNotNull($extensions[0]->getTypeGuesser()); } } PK!̈́;test/Form/Symfony/Component/Form/Tests/FormRegistryTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormRegistry; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\Tests\Fixtures\TestExtension; use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance; use Symfony\Component\Form\Tests\Fixtures\FooSubType; use Symfony\Component\Form\Tests\Fixtures\FooTypeBazExtension; use Symfony\Component\Form\Tests\Fixtures\FooTypeBarExtension; use Symfony\Component\Form\Tests\Fixtures\FooType; /** * @author Bernhard Schussek */ class FormRegistryTest extends \PHPUnit_Framework_TestCase { /** * @var FormRegistry */ private $registry; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $resolvedTypeFactory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $guesser1; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $guesser2; /** * @var TestExtension */ private $extension1; /** * @var TestExtension */ private $extension2; protected function setUp() { $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactory'); $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->extension1 = new TestExtension($this->guesser1); $this->extension2 = new TestExtension($this->guesser2); $this->registry = new FormRegistry(array( $this->extension1, $this->extension2, ), $this->resolvedTypeFactory); } public function testGetTypeFromExtension() { $type = new FooType(); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->extension2->addType($type); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $resolvedType = $this->registry->getType('foo'); $this->assertSame($resolvedType, $this->registry->getType('foo')); } public function testGetTypeWithTypeExtensions() { $type = new FooType(); $ext1 = new FooTypeBarExtension(); $ext2 = new FooTypeBazExtension(); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->extension2->addType($type); $this->extension1->addTypeExtension($ext1); $this->extension2->addTypeExtension($ext2); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type, array($ext1, $ext2)) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $this->assertSame($resolvedType, $this->registry->getType('foo')); } public function testGetTypeConnectsParent() { $parentType = new FooType(); $type = new FooSubType(); $parentResolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->extension1->addType($parentType); $this->extension2->addType($type); $this->resolvedTypeFactory->expects($this->at(0)) ->method('createResolvedType') ->with($parentType) ->will($this->returnValue($parentResolvedType)); $this->resolvedTypeFactory->expects($this->at(1)) ->method('createResolvedType') ->with($type, array(), $parentResolvedType) ->will($this->returnValue($resolvedType)); $parentResolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo_sub_type')); $this->assertSame($resolvedType, $this->registry->getType('foo_sub_type')); } public function testGetTypeConnectsParentIfGetParentReturnsInstance() { $type = new FooSubTypeWithParentInstance(); $parentResolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->extension1->addType($type); $this->resolvedTypeFactory->expects($this->at(0)) ->method('createResolvedType') ->with($this->isInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType')) ->will($this->returnValue($parentResolvedType)); $this->resolvedTypeFactory->expects($this->at(1)) ->method('createResolvedType') ->with($type, array(), $parentResolvedType) ->will($this->returnValue($resolvedType)); $parentResolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo_sub_type_parent_instance')); $this->assertSame($resolvedType, $this->registry->getType('foo_sub_type_parent_instance')); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testGetTypeThrowsExceptionIfParentNotFound() { $type = new FooSubType(); $this->extension1->addType($type); $this->registry->getType($type); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ public function testGetTypeThrowsExceptionIfTypeNotFound() { $this->registry->getType('bar'); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testGetTypeThrowsExceptionIfNoString() { $this->registry->getType(array()); } public function testHasTypeAfterLoadingFromExtension() { $type = new FooType(); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $this->assertFalse($this->registry->hasType('foo')); $this->extension2->addType($type); $this->assertTrue($this->registry->hasType('foo')); } public function testGetTypeGuesser() { $expectedGuesser = new FormTypeGuesserChain(array($this->guesser1, $this->guesser2)); $this->assertEquals($expectedGuesser, $this->registry->getTypeGuesser()); $registry = new FormRegistry( array($this->getMock('Symfony\Component\Form\FormExtensionInterface')), $this->resolvedTypeFactory); $this->assertNull($registry->getTypeGuesser()); } public function testGetExtensions() { $expectedExtensions = array($this->extension1, $this->extension2); $this->assertEquals($expectedExtensions, $this->registry->getExtensions()); } } PK!]9}}9test/Form/Symfony/Component/Form/Tests/FormConfigTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * @author Bernhard Schussek */ class FormConfigTest extends \PHPUnit_Framework_TestCase { public function getHtml4Ids() { return array( array('z0', true), array('A0', true), array('A9', true), array('Z0', true), array('#', false), array('a#', false), array('a$', false), array('a%', false), array('a ', false), array("a\t", false), array("a\n", false), array('a-', true), array('a_', true), array('a:', true), // Periods are allowed by the HTML4 spec, but disallowed by us // because they break the generated property paths array('a.', false), // Contrary to the HTML4 spec, we allow names starting with a // number, otherwise naming fields by collection indices is not // possible. // For root forms, leading digits will be stripped from the // "id" attribute to produce valid HTML4. array('0', true), array('9', true), // Contrary to the HTML4 spec, we allow names starting with an // underscore, since this is already a widely used practice in // Symfony2. // For root forms, leading underscores will be stripped from the // "id" attribute to produce valid HTML4. array('_', true), // Integers are allowed array(0, true), array(123, true), // NULL is allowed array(null, true), // Other types are not array(1.23, false), array(5., false), array(true, false), array(new \stdClass(), false), ); } /** * @dataProvider getHtml4Ids */ public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted) { $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); try { new FormConfigBuilder($name, null, $dispatcher); if (!$accepted) { $this->fail(sprintf('The value "%s" should not be accepted', $name)); } } catch (UnexpectedTypeException $e) { // if the value was not accepted, but should be, rethrow exception if ($accepted) { throw $e; } } catch (InvalidArgumentException $e) { // if the value was not accepted, but should be, rethrow exception if ($accepted) { throw $e; } } } public function testGetRequestHandlerCreatesNativeRequestHandlerIfNotSet() { $config = $this->getConfigBuilder()->getFormConfig(); $this->assertInstanceOf('Symfony\Component\Form\NativeRequestHandler', $config->getRequestHandler()); } public function testGetRequestHandlerReusesNativeRequestHandlerInstance() { $config1 = $this->getConfigBuilder()->getFormConfig(); $config2 = $this->getConfigBuilder()->getFormConfig(); $this->assertSame($config1->getRequestHandler(), $config2->getRequestHandler()); } public function testSetMethodAllowsGet() { $this->getConfigBuilder()->setMethod('GET'); } public function testSetMethodAllowsPost() { $this->getConfigBuilder()->setMethod('POST'); } public function testSetMethodAllowsPut() { $this->getConfigBuilder()->setMethod('PUT'); } public function testSetMethodAllowsDelete() { $this->getConfigBuilder()->setMethod('DELETE'); } public function testSetMethodAllowsPatch() { $this->getConfigBuilder()->setMethod('PATCH'); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ public function testSetMethodDoesNotAllowOtherValues() { $this->getConfigBuilder()->setMethod('foo'); } private function getConfigBuilder($name = 'name') { $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); return new FormConfigBuilder($name, null, $dispatcher); } } PK!>)bbEtest/Form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; /** * @author Bernhard Schussek */ abstract class AbstractRequestHandlerTest extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\Form\RequestHandlerInterface */ protected $requestHandler; protected $request; protected function setUp() { $this->requestHandler = $this->getRequestHandler(); $this->request = null; } public function methodExceptGetProvider() { return array( array('POST'), array('PUT'), array('DELETE'), array('PATCH'), ); } public function methodProvider() { return array_merge(array( array('GET'), ), $this->methodExceptGetProvider()); } /** * @dataProvider methodProvider */ public function testSubmitIfNameInRequest($method) { $form = $this->getMockForm('param1', $method); $this->setRequestData($method, array( 'param1' => 'DATA', )); $form->expects($this->once()) ->method('submit') ->with('DATA', 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodProvider */ public function testDoNotSubmitIfWrongRequestMethod($method) { $form = $this->getMockForm('param1', $method); $otherMethod = 'POST' === $method ? 'PUT' : 'POST'; $this->setRequestData($otherMethod, array( 'param1' => 'DATA', )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testDoNoSubmitSimpleFormIfNameNotInRequestAndNotGetRequest($method) { $form = $this->getMockForm('param1', $method, false); $this->setRequestData($method, array( 'paramx' => array(), )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testDoNotSubmitCompoundFormIfNameNotInRequestAndNotGetRequest($method) { $form = $this->getMockForm('param1', $method, true); $this->setRequestData($method, array( 'paramx' => array(), )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } public function testDoNotSubmitIfNameNotInRequestAndGetRequest() { $form = $this->getMockForm('param1', 'GET'); $this->setRequestData('GET', array( 'paramx' => array(), )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodProvider */ public function testSubmitFormWithEmptyNameIfAtLeastOneFieldInRequest($method) { $form = $this->getMockForm('', $method); $form->expects($this->any()) ->method('all') ->will($this->returnValue(array( 'param1' => $this->getMockForm('param1'), 'param2' => $this->getMockForm('param2'), ))); $this->setRequestData($method, $requestData = array( 'param1' => 'submitted value', 'paramx' => 'submitted value', )); $form->expects($this->once()) ->method('submit') ->with($requestData, 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodProvider */ public function testDoNotSubmitFormWithEmptyNameIfNoFieldInRequest($method) { $form = $this->getMockForm('', $method); $form->expects($this->any()) ->method('all') ->will($this->returnValue(array( 'param1' => $this->getMockForm('param1'), 'param2' => $this->getMockForm('param2'), ))); $this->setRequestData($method, array( 'paramx' => 'submitted value', )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testMergeParamsAndFiles($method) { $form = $this->getMockForm('param1', $method); $file = $this->getMockFile(); $this->setRequestData($method, array( 'param1' => array( 'field1' => 'DATA', ), ), array( 'param1' => array( 'field2' => $file, ), )); $form->expects($this->once()) ->method('submit') ->with(array( 'field1' => 'DATA', 'field2' => $file, ), 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testParamTakesPrecedenceOverFile($method) { $form = $this->getMockForm('param1', $method); $file = $this->getMockFile(); $this->setRequestData($method, array( 'param1' => 'DATA', ), array( 'param1' => $file, )); $form->expects($this->once()) ->method('submit') ->with('DATA', 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testSubmitFileIfNoParam($method) { $form = $this->getMockForm('param1', $method); $file = $this->getMockFile(); $this->setRequestData($method, array( 'param1' => null, ), array( 'param1' => $file, )); $form->expects($this->once()) ->method('submit') ->with($file, 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } abstract protected function setRequestData($method, $data, $files = array()); abstract protected function getRequestHandler(); abstract protected function getMockFile(); protected function getMockForm($name, $method = null, $compound = true) { $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); $config->expects($this->any()) ->method('getMethod') ->will($this->returnValue($method)); $config->expects($this->any()) ->method('getCompound') ->will($this->returnValue($compound)); $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $form->expects($this->any()) ->method('getName') ->will($this->returnValue($name)); $form->expects($this->any()) ->method('getConfig') ->will($this->returnValue($config)); return $form; } } PK!ū@d22?test/Form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\ResolvedFormType; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ class ResolvedFormTypeTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataMapper; private $parentType; private $type; private $extension1; private $extension2; private $parentResolvedType; private $resolvedType; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface'); $this->parentType = $this->getMockFormType(); $this->type = $this->getMockFormType(); $this->extension1 = $this->getMockFormTypeExtension(); $this->extension2 = $this->getMockFormTypeExtension(); $this->parentResolvedType = new ResolvedFormType($this->parentType); $this->resolvedType = new ResolvedFormType($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType); } public function testGetOptionsResolver() { if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { $this->markTestSkipped('This test requires PHPUnit 3.7.'); } $test = $this; $i = 0; $assertIndexAndAddOption = function ($index, $option, $default) use (&$i, $test) { return function (OptionsResolverInterface $resolver) use (&$i, $test, $index, $option, $default) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals($index, $i, 'Executed at index '.$index); ++$i; $resolver->setDefaults(array($option => $default)); }; }; // First the default options are generated for the super type $this->parentType->expects($this->once()) ->method('setDefaultOptions') ->will($this->returnCallback($assertIndexAndAddOption(0, 'a', 'a_default'))); // The form type itself $this->type->expects($this->once()) ->method('setDefaultOptions') ->will($this->returnCallback($assertIndexAndAddOption(1, 'b', 'b_default'))); // And its extensions $this->extension1->expects($this->once()) ->method('setDefaultOptions') ->will($this->returnCallback($assertIndexAndAddOption(2, 'c', 'c_default'))); $this->extension2->expects($this->once()) ->method('setDefaultOptions') ->will($this->returnCallback($assertIndexAndAddOption(3, 'd', 'd_default'))); $givenOptions = array('a' => 'a_custom', 'c' => 'c_custom'); $resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default'); $resolver = $this->resolvedType->getOptionsResolver(); $this->assertEquals($resolvedOptions, $resolver->resolve($givenOptions)); } public function testCreateBuilder() { if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { $this->markTestSkipped('This test requires PHPUnit 3.7.'); } $givenOptions = array('a' => 'a_custom', 'c' => 'c_custom'); $resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default'); $optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface'); $this->resolvedType = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormType') ->setConstructorArgs(array($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType)) ->setMethods(array('getOptionsResolver')) ->getMock(); $this->resolvedType->expects($this->once()) ->method('getOptionsResolver') ->will($this->returnValue($optionsResolver)); $optionsResolver->expects($this->once()) ->method('resolve') ->with($givenOptions) ->will($this->returnValue($resolvedOptions)); $factory = $this->getMockFormFactory(); $builder = $this->resolvedType->createBuilder($factory, 'name', $givenOptions); $this->assertSame($this->resolvedType, $builder->getType()); $this->assertSame($resolvedOptions, $builder->getOptions()); $this->assertNull($builder->getDataClass()); } public function testCreateBuilderWithDataClassOption() { if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { $this->markTestSkipped('This test requires PHPUnit 3.7.'); } $givenOptions = array('data_class' => 'Foo'); $resolvedOptions = array('data_class' => '\stdClass'); $optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface'); $this->resolvedType = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormType') ->setConstructorArgs(array($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType)) ->setMethods(array('getOptionsResolver')) ->getMock(); $this->resolvedType->expects($this->once()) ->method('getOptionsResolver') ->will($this->returnValue($optionsResolver)); $optionsResolver->expects($this->once()) ->method('resolve') ->with($givenOptions) ->will($this->returnValue($resolvedOptions)); $factory = $this->getMockFormFactory(); $builder = $this->resolvedType->createBuilder($factory, 'name', $givenOptions); $this->assertSame($this->resolvedType, $builder->getType()); $this->assertSame($resolvedOptions, $builder->getOptions()); $this->assertSame('\stdClass', $builder->getDataClass()); } public function testBuildForm() { if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { $this->markTestSkipped('This test requires PHPUnit 3.7.'); } $test = $this; $i = 0; $assertIndex = function ($index) use (&$i, $test) { return function () use (&$i, $test, $index) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals($index, $i, 'Executed at index '.$index); ++$i; }; }; $options = array('a' => 'Foo', 'b' => 'Bar'); $builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface'); // First the form is built for the super type $this->parentType->expects($this->once()) ->method('buildForm') ->with($builder, $options) ->will($this->returnCallback($assertIndex(0))); // Then the type itself $this->type->expects($this->once()) ->method('buildForm') ->with($builder, $options) ->will($this->returnCallback($assertIndex(1))); // Then its extensions $this->extension1->expects($this->once()) ->method('buildForm') ->with($builder, $options) ->will($this->returnCallback($assertIndex(2))); $this->extension2->expects($this->once()) ->method('buildForm') ->with($builder, $options) ->will($this->returnCallback($assertIndex(3))); $this->resolvedType->buildForm($builder, $options); } public function testCreateView() { $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $view = $this->resolvedType->createView($form); $this->assertInstanceOf('Symfony\Component\Form\FormView', $view); $this->assertNull($view->parent); } public function testCreateViewWithParent() { $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $parentView = $this->getMock('Symfony\Component\Form\FormView'); $view = $this->resolvedType->createView($form, $parentView); $this->assertInstanceOf('Symfony\Component\Form\FormView', $view); $this->assertSame($parentView, $view->parent); } public function testBuildView() { $options = array('a' => '1', 'b' => '2'); $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $test = $this; $i = 0; $assertIndex = function ($index) use (&$i, $test) { return function () use (&$i, $test, $index) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals($index, $i, 'Executed at index '.$index); ++$i; }; }; // First the super type $this->parentType->expects($this->once()) ->method('buildView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(0))); // Then the type itself $this->type->expects($this->once()) ->method('buildView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(1))); // Then its extensions $this->extension1->expects($this->once()) ->method('buildView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(2))); $this->extension2->expects($this->once()) ->method('buildView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(3))); $this->resolvedType->buildView($view, $form, $options); } public function testFinishView() { $options = array('a' => '1', 'b' => '2'); $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $test = $this; $i = 0; $assertIndex = function ($index) use (&$i, $test) { return function () use (&$i, $test, $index) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals($index, $i, 'Executed at index '.$index); ++$i; }; }; // First the super type $this->parentType->expects($this->once()) ->method('finishView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(0))); // Then the type itself $this->type->expects($this->once()) ->method('finishView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(1))); // Then its extensions $this->extension1->expects($this->once()) ->method('finishView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(2))); $this->extension2->expects($this->once()) ->method('finishView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(3))); $this->resolvedType->finishView($view, $form, $options); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getMockFormType() { return $this->getMock('Symfony\Component\Form\FormTypeInterface'); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getMockFormTypeExtension() { return $this->getMock('Symfony\Component\Form\FormTypeExtensionInterface'); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getMockFormFactory() { return $this->getMock('Symfony\Component\Form\FormFactoryInterface'); } /** * @param string $name * @param array $options * * @return FormBuilder */ protected function getBuilder($name = 'name', array $options = array()) { return new FormBuilder($name, null, $this->dispatcher, $this->factory, $options); } } PK!O )KKBtest/Form/Symfony/Component/Form/Tests/FormIntegrationTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Test\FormIntegrationTestCase as BaseFormIntegrationTestCase; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormIntegrationTestCase instead. */ abstract class FormIntegrationTestCase extends BaseFormIntegrationTestCase { } PK!K)ooFtest/Form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; /** * @author Bernhard Schussek */ class CompoundFormPerformanceTest extends \Symfony\Component\Form\Tests\FormPerformanceTestCase { /** * Create a compound form multiple times, as happens in a collection form * * @group benchmark */ public function testArrayBasedForm() { $this->setMaxRunningTime(1); for ($i = 0; $i < 40; ++$i) { $form = $this->factory->createBuilder('form') ->add('firstName', 'text') ->add('lastName', 'text') ->add('gender', 'choice', array( 'choices' => array('male' => 'Male', 'female' => 'Female'), 'required' => false, )) ->add('age', 'number') ->add('birthDate', 'birthday') ->add('city', 'choice', array( // simulate 300 different cities 'choices' => range(1, 300), )) ->getForm(); // load the form into a view $form->createView(); } } } PK!tٴ;test/Form/Symfony/Component/Form/Tests/FormRendererTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; class FormRendererTest extends \PHPUnit_Framework_TestCase { public function testHumanize() { $renderer = $this->getMockBuilder('Symfony\Component\Form\FormRenderer') ->setMethods(null) ->disableOriginalConstructor() ->getMock() ; $this->assertEquals('Is active', $renderer->humanize('is_active')); $this->assertEquals('Is active', $renderer->humanize('isActive')); } } PK!d!!Ctest/Form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\NativeRequestHandler; /** * @author Bernhard Schussek */ class NativeRequestHandlerTest extends AbstractRequestHandlerTest { private static $serverBackup; public static function setUpBeforeClass() { self::$serverBackup = $_SERVER; } protected function setUp() { parent::setUp(); $_GET = array(); $_POST = array(); $_FILES = array(); $_SERVER = array( // PHPUnit needs this entry 'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'], ); } protected function tearDown() { parent::tearDown(); $_GET = array(); $_POST = array(); $_FILES = array(); $_SERVER = self::$serverBackup; } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequestShouldBeNull() { $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), 'request'); } public function testMethodOverrideHeaderTakesPrecedenceIfPost() { $form = $this->getMockForm('param1', 'PUT'); $this->setRequestData('POST', array( 'param1' => 'DATA', )); $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; $form->expects($this->once()) ->method('submit') ->with('DATA'); $this->requestHandler->handleRequest($form, $this->request); } public function testConvertEmptyUploadedFilesToNull() { $form = $this->getMockForm('param1', 'POST', false); $this->setRequestData('POST', array(), array('param1' => array( 'name' => '', 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_NO_FILE, 'size' => 0 ))); $form->expects($this->once()) ->method('submit') ->with($this->identicalTo(null)); $this->requestHandler->handleRequest($form, $this->request); } public function testFixBuggyFilesArray() { $form = $this->getMockForm('param1', 'POST', false); $this->setRequestData('POST', array(), array('param1' => array( 'name' => array( 'field' => 'upload.txt', ), 'type' => array( 'field' => 'text/plain', ), 'tmp_name' => array( 'field' => 'owfdskjasdfsa', ), 'error' => array( 'field' => UPLOAD_ERR_OK, ), 'size' => array( 'field' => 100, ), ))); $form->expects($this->once()) ->method('submit') ->with(array( 'field' => array( 'name' => 'upload.txt', 'type' => 'text/plain', 'tmp_name' => 'owfdskjasdfsa', 'error' => UPLOAD_ERR_OK, 'size' => 100, ), )); $this->requestHandler->handleRequest($form, $this->request); } public function testFixBuggyNestedFilesArray() { $form = $this->getMockForm('param1', 'POST'); $this->setRequestData('POST', array(), array('param1' => array( 'name' => array( 'field' => array('subfield' => 'upload.txt'), ), 'type' => array( 'field' => array('subfield' => 'text/plain'), ), 'tmp_name' => array( 'field' => array('subfield' => 'owfdskjasdfsa'), ), 'error' => array( 'field' => array('subfield' => UPLOAD_ERR_OK), ), 'size' => array( 'field' => array('subfield' => 100), ), ))); $form->expects($this->once()) ->method('submit') ->with(array( 'field' => array( 'subfield' => array( 'name' => 'upload.txt', 'type' => 'text/plain', 'tmp_name' => 'owfdskjasdfsa', 'error' => UPLOAD_ERR_OK, 'size' => 100, ), ), )); $this->requestHandler->handleRequest($form, $this->request); } public function testMethodOverrideHeaderIgnoredIfNotPost() { $form = $this->getMockForm('param1', 'POST'); $this->setRequestData('GET', array( 'param1' => 'DATA', )); $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } protected function setRequestData($method, $data, $files = array()) { if ('GET' === $method) { $_GET = $data; $_FILES = array(); } else { $_POST = $data; $_FILES = $files; } $_SERVER = array( 'REQUEST_METHOD' => $method, // PHPUnit needs this entry 'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'], ); } protected function getRequestHandler() { return new NativeRequestHandler(); } protected function getMockFile() { return array( 'name' => 'upload.txt', 'type' => 'text/plain', 'tmp_name' => 'owfdskjasdfsa', 'error' => UPLOAD_ERR_OK, 'size' => 100, ); } } PK!:test/Form/Symfony/Component/Form/Tests/FormBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormBuilder; class FormBuilderTest extends \PHPUnit_Framework_TestCase { private $dispatcher; private $factory; private $builder; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->builder = null; } /** * Changing the name is not allowed, otherwise the name and property path * are not synchronized anymore * * @see FormType::buildForm */ public function testNoSetName() { $this->assertFalse(method_exists($this->builder, 'setName')); } public function testAddNameNoStringAndNoInteger() { $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); $this->builder->add(true); } public function testAddTypeNoString() { $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); $this->builder->add('foo', 1234); } public function testAddWithGuessFluent() { $this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory); $builder = $this->builder->add('foo'); $this->assertSame($builder, $this->builder); } public function testAddIsFluent() { $builder = $this->builder->add('foo', 'text', array('bar' => 'baz')); $this->assertSame($builder, $this->builder); } public function testAdd() { $this->assertFalse($this->builder->has('foo')); $this->builder->add('foo', 'text'); $this->assertTrue($this->builder->has('foo')); } public function testAddIntegerName() { $this->assertFalse($this->builder->has(0)); $this->builder->add(0, 'text'); $this->assertTrue($this->builder->has(0)); } public function testAll() { $this->factory->expects($this->once()) ->method('createNamedBuilder') ->with('foo', 'text') ->will($this->returnValue(new FormBuilder('foo', null, $this->dispatcher, $this->factory))); $this->assertCount(0, $this->builder->all()); $this->assertFalse($this->builder->has('foo')); $this->builder->add('foo', 'text'); $children = $this->builder->all(); $this->assertTrue($this->builder->has('foo')); $this->assertCount(1, $children); $this->assertArrayHasKey('foo', $children); } /* * https://github.com/symfony/symfony/issues/4693 */ public function testMaintainOrderOfLazyAndExplicitChildren() { $this->builder->add('foo', 'text'); $this->builder->add($this->getFormBuilder('bar')); $this->builder->add('baz', 'text'); $children = $this->builder->all(); $this->assertSame(array('foo', 'bar', 'baz'), array_keys($children)); } public function testAddFormType() { $this->assertFalse($this->builder->has('foo')); $this->builder->add('foo', $this->getMock('Symfony\Component\Form\FormTypeInterface')); $this->assertTrue($this->builder->has('foo')); } public function testRemove() { $this->builder->add('foo', 'text'); $this->builder->remove('foo'); $this->assertFalse($this->builder->has('foo')); } public function testRemoveUnknown() { $this->builder->remove('foo'); $this->assertFalse($this->builder->has('foo')); } // https://github.com/symfony/symfony/pull/4826 public function testRemoveAndGetForm() { $this->builder->add('foo', 'text'); $this->builder->remove('foo'); $form = $this->builder->getForm(); $this->assertInstanceOf('Symfony\Component\Form\Form', $form); } public function testCreateNoTypeNo() { $this->factory->expects($this->once()) ->method('createNamedBuilder') ->with('foo', 'text', null, array()) ; $this->builder->create('foo'); } public function testGetUnknown() { $this->setExpectedException('Symfony\Component\Form\Exception\InvalidArgumentException', 'The child with the name "foo" does not exist.'); $this->builder->get('foo'); } public function testGetExplicitType() { $expectedType = 'text'; $expectedName = 'foo'; $expectedOptions = array('bar' => 'baz'); $this->factory->expects($this->once()) ->method('createNamedBuilder') ->with($expectedName, $expectedType, null, $expectedOptions) ->will($this->returnValue($this->getFormBuilder())); $this->builder->add($expectedName, $expectedType, $expectedOptions); $builder = $this->builder->get($expectedName); $this->assertNotSame($builder, $this->builder); } public function testGetGuessedType() { $expectedName = 'foo'; $expectedOptions = array('bar' => 'baz'); $this->factory->expects($this->once()) ->method('createBuilderForProperty') ->with('stdClass', $expectedName, null, $expectedOptions) ->will($this->returnValue($this->getFormBuilder())); $this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory); $this->builder->add($expectedName, null, $expectedOptions); $builder = $this->builder->get($expectedName); $this->assertNotSame($builder, $this->builder); } public function testGetFormConfigErasesReferences() { $builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); $builder->add(new FormBuilder('child', null, $this->dispatcher, $this->factory)); $config = $builder->getFormConfig(); $reflClass = new \ReflectionClass($config); $children = $reflClass->getProperty('children'); $unresolvedChildren = $reflClass->getProperty('unresolvedChildren'); $children->setAccessible(true); $unresolvedChildren->setAccessible(true); $this->assertEmpty($children->getValue($config)); $this->assertEmpty($unresolvedChildren->getValue($config)); } private function getFormBuilder($name = 'name') { $mock = $this->getMockBuilder('Symfony\Component\Form\FormBuilder') ->disableOriginalConstructor() ->getMock(); $mock->expects($this->any()) ->method('getName') ->will($this->returnValue($name)); return $mock; } } PK!RmhZTZT@test/Form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Tests\Fixtures\AlternatingRowType; use Symfony\Component\Security\Csrf\CsrfToken; abstract class AbstractDivLayoutTest extends AbstractLayoutTest { public function testRow() { $form = $this->factory->createNamed('name', 'text'); $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name"] /following-sibling::ul [./li[.="[trans]Error![/trans]"]] [count(./li)=1] /following-sibling::input[@id="name"] ] ' ); } public function testRowOverrideVariables() { $view = $this->factory->createNamed('name', 'text')->createView(); $html = $this->renderRow($view, array( 'attr' => array('class' => 'my&class'), 'label' => 'foo&bar', 'label_attr' => array('class' => 'my&label&class'), )); $this->assertMatchesXpath($html, '/div [ ./label[@for="name"][@class="my&label&class required"][.="[trans]foo&bar[/trans]"] /following-sibling::input[@id="name"][@class="my&class"] ] ' ); } public function testRepeatedRow() { $form = $this->factory->createNamed('name', 'repeated'); $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); // The errors of the form are not rendered by intention! // In practice, repeated fields cannot have errors as all errors // on them are mapped to the first child. // (see RepeatedTypeValidatorExtension) $this->assertMatchesXpath($html, '/div [ ./label[@for="name_first"] /following-sibling::input[@id="name_first"] ] /following-sibling::div [ ./label[@for="name_second"] /following-sibling::input[@id="name_second"] ] ' ); } public function testButtonRow() { $form = $this->factory->createNamed('name', 'button'); $view = $form->createView(); $html = $this->renderRow($view); $this->assertMatchesXpath($html, '/div [ ./button[@type="button"][@name="name"] ] [count(//label)=0] ' ); } public function testRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'repeated') ->add('field3', 'text') ->add('field4', 'text') ->getForm() ->createView(); // Render field2 row -> does not implicitly call renderWidget because // it is a repeated field! $this->renderRow($view['field2']); // Render field3 widget $this->renderWidget($view['field3']); // Rest should only contain field1 and field4 $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name_field1"] /following-sibling::input[@type="text"][@id="name_field1"] ] /following-sibling::div [ ./label[@for="name_field4"] /following-sibling::input[@type="text"][@id="name_field4"] ] [count(../div)=2] [count(..//label)=2] [count(..//input)=3] /following-sibling::input [@type="hidden"] [@id="name__token"] ' ); } public function testRestWithChildrenForms() { $child1 = $this->factory->createNamedBuilder('child1', 'form') ->add('field1', 'text') ->add('field2', 'text'); $child2 = $this->factory->createNamedBuilder('child2', 'form') ->add('field1', 'text') ->add('field2', 'text'); $view = $this->factory->createNamedBuilder('parent', 'form') ->add($child1) ->add($child2) ->getForm() ->createView(); // Render child1.field1 row $this->renderRow($view['child1']['field1']); // Render child2.field2 widget (remember that widget don't render label) $this->renderWidget($view['child2']['field2']); // Rest should only contain child1.field2 and child2.field1 $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[not(@for)] /following-sibling::div[@id="parent_child1"] [ ./div [ ./label[@for="parent_child1_field2"] /following-sibling::input[@id="parent_child1_field2"] ] ] ] /following-sibling::div [ ./label[not(@for)] /following-sibling::div[@id="parent_child2"] [ ./div [ ./label[@for="parent_child2_field1"] /following-sibling::input[@id="parent_child2_field1"] ] ] ] [count(//label)=4] [count(//input[@type="text"])=2] /following-sibling::input[@type="hidden"][@id="parent__token"] ' ); } public function testRestAndRepeatedWithRow() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('first', 'text') ->add('password', 'repeated') ->getForm() ->createView(); $this->renderRow($view['password']); $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name_first"] /following-sibling::input[@type="text"][@id="name_first"] ] [count(.//input)=1] /following-sibling::input [@type="hidden"] [@id="name__token"] ' ); } public function testRestAndRepeatedWithRowPerChild() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('first', 'text') ->add('password', 'repeated') ->getForm() ->createView(); $this->renderRow($view['password']['first']); $this->renderRow($view['password']['second']); $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name_first"] /following-sibling::input[@type="text"][@id="name_first"] ] [count(.//input)=1] [count(.//label)=1] /following-sibling::input [@type="hidden"] [@id="name__token"] ' ); } public function testRestAndRepeatedWithWidgetPerChild() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('first', 'text') ->add('password', 'repeated') ->getForm() ->createView(); // The password form is considered as rendered as all its children // are rendered $this->renderWidget($view['password']['first']); $this->renderWidget($view['password']['second']); $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name_first"] /following-sibling::input[@type="text"][@id="name_first"] ] [count(//input)=2] [count(//label)=1] /following-sibling::input [@type="hidden"] [@id="name__token"] ' ); } public function testCollection() { $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div[./input[@type="text"][@value="a"]] /following-sibling::div[./input[@type="text"][@value="b"]] ] [count(./div[./input])=2] ' ); } // https://github.com/symfony/symfony/issues/5038 public function testCollectionWithAlternatingRowTypes() { $data = array( array('title' => 'a'), array('title' => 'b'), ); $form = $this->factory->createNamed('name', 'collection', $data, array( 'type' => new AlternatingRowType(), )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div[./div/div/input[@type="text"][@value="a"]] /following-sibling::div[./div/div/textarea[.="b"]] ] [count(./div[./div/div/input])=1] [count(./div[./div/div/textarea])=1] ' ); } public function testEmptyCollection() { $form = $this->factory->createNamed('name', 'collection', array(), array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [./input[@type="hidden"][@id="name__token"]] [count(./div)=0] ' ); } public function testCollectionRow() { $collection = $this->factory->createNamedBuilder( 'collection', 'collection', array('a', 'b'), array('type' => 'text') ); $form = $this->factory->createNamedBuilder('form', 'form') ->add($collection) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[not(@for)] /following-sibling::div [ ./div [ ./label[@for="form_collection_0"] /following-sibling::input[@type="text"][@value="a"] ] /following-sibling::div [ ./label[@for="form_collection_1"] /following-sibling::input[@type="text"][@value="b"] ] ] ] /following-sibling::input[@type="hidden"][@id="form__token"] ] [count(.//input)=3] ' ); } public function testForm() { $form = $this->factory->createNamedBuilder('name', 'form') ->setMethod('PUT') ->setAction('http://example.com') ->add('firstName', 'text') ->add('lastName', 'text') ->getForm(); // include ampersands everywhere to validate escaping $html = $this->renderForm($form->createView(), array( 'id' => 'my&id', 'attr' => array('class' => 'my&class'), )); $this->assertMatchesXpath($html, '/form [ ./input[@type="hidden"][@name="_method"][@value="PUT"] /following-sibling::div [ ./div [ ./label[@for="name_firstName"] /following-sibling::input[@type="text"][@id="name_firstName"] ] /following-sibling::div [ ./label[@for="name_lastName"] /following-sibling::input[@type="text"][@id="name_lastName"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(.//input)=3] [@id="my&id"] [@class="my&class"] ] [@method="post"] [@action="http://example.com"] [@class="my&class"] ' ); } public function testFormWidget() { $form = $this->factory->createNamedBuilder('name', 'form') ->add('firstName', 'text') ->add('lastName', 'text') ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[@for="name_firstName"] /following-sibling::input[@type="text"][@id="name_firstName"] ] /following-sibling::div [ ./label[@for="name_lastName"] /following-sibling::input[@type="text"][@id="name_lastName"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(.//input)=3] ' ); } // https://github.com/symfony/symfony/issues/2308 public function testNestedFormError() { $form = $this->factory->createNamedBuilder('name', 'form') ->add($this->factory ->createNamedBuilder('child', 'form', null, array('error_bubbling' => false)) ->add('grandChild', 'form') ) ->getForm(); $form->get('child')->addError(new FormError('[trans]Error![/trans]')); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div/label /following-sibling::ul[./li[.="[trans]Error![/trans]"]] ] [count(.//li[.="[trans]Error![/trans]"])=1] ' ); } public function testCsrf() { $this->csrfTokenManager->expects($this->any()) ->method('getToken') ->will($this->returnValue(new CsrfToken('token_id', 'foo&bar'))); $form = $this->factory->createNamedBuilder('name', 'form') ->add($this->factory // No CSRF protection on nested forms ->createNamedBuilder('child', 'form') ->add($this->factory->createNamedBuilder('grandchild', 'text')) ) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div /following-sibling::input[@type="hidden"][@id="name__token"][@value="foo&bar"] ] [count(.//input[@type="hidden"])=1] ' ); } public function testRepeated() { $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[@for="name_first"] /following-sibling::input[@type="text"][@id="name_first"] ] /following-sibling::div [ ./label[@for="name_second"] /following-sibling::input[@type="text"][@id="name_second"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(.//input)=3] ' ); } public function testRepeatedWithCustomOptions() { $form = $this->factory->createNamed('name', 'repeated', null, array( // the global required value cannot be overridden 'first_options' => array('label' => 'Test', 'required' => false), 'second_options' => array('label' => 'Test2') )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[@for="name_first"][.="[trans]Test[/trans]"] /following-sibling::input[@type="text"][@id="name_first"][@required="required"] ] /following-sibling::div [ ./label[@for="name_second"][.="[trans]Test2[/trans]"] /following-sibling::input[@type="text"][@id="name_second"][@required="required"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(.//input)=3] ' ); } public function testSearchInputName() { $form = $this->factory->createNamedBuilder('full', 'form') ->add('name', 'search') ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[@for="full_name"] /following-sibling::input[@type="search"][@id="full_name"][@name="full[name]"] ] /following-sibling::input[@type="hidden"][@id="full__token"] ] [count(//input)=2] ' ); } public function testLabelHasNoId() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderRow($form->createView()); $this->assertMatchesXpath($html, '/div [ ./label[@for="name"][not(@id)] /following-sibling::input[@id="name"] ] ' ); } public function testLabelIsNotRenderedWhenSetToFalse() { $form = $this->factory->createNamed('name', 'text', null, array( 'label' => false )); $html = $this->renderRow($form->createView()); $this->assertMatchesXpath($html, '/div [ ./input[@id="name"] ] [count(//label)=0] ' ); } /** * @dataProvider themeBlockInheritanceProvider */ public function testThemeBlockInheritance($theme) { $view = $this->factory ->createNamed('name', 'email') ->createView() ; $this->setTheme($view, $theme); $this->assertMatchesXpath( $this->renderWidget($view), '/input[@type="email"][@rel="theme"]' ); } /** * @dataProvider themeInheritanceProvider */ public function testThemeInheritance($parentTheme, $childTheme) { $child = $this->factory->createNamedBuilder('child', 'form') ->add('field', 'text'); $view = $this->factory->createNamedBuilder('parent', 'form') ->add('field', 'text') ->add($child) ->getForm() ->createView() ; $this->setTheme($view, $parentTheme); $this->setTheme($view['child'], $childTheme); $this->assertWidgetMatchesXpath($view, array(), '/div [ ./div [ ./label[.="parent"] /following-sibling::input[@type="text"] ] /following-sibling::div [ ./label[.="child"] /following-sibling::div [ ./div [ ./label[.="child"] /following-sibling::input[@type="text"] ] ] ] /following-sibling::input[@type="hidden"] ] ' ); } /** * The block "_name_child_label" should be overridden in the theme of the * implemented driver. */ public function testCollectionRowWithCustomBlock() { $collection = array('one', 'two', 'three'); $form = $this->factory->createNamedBuilder('name', 'collection', $collection) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div[./label[.="Custom label: [trans]0[/trans]"]] /following-sibling::div[./label[.="Custom label: [trans]1[/trans]"]] /following-sibling::div[./label[.="Custom label: [trans]2[/trans]"]] ] ' ); } public function testFormEndWithRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'text') ->getForm() ->createView(); $this->renderWidget($view['field1']); // Rest should only contain field2 $html = $this->renderEnd($view); // Insert the start tag, the end tag should be rendered by the helper $this->assertMatchesXpath('' . $html, '/form [ ./div [ ./label[@for="name_field2"] /following-sibling::input[@type="text"][@id="name_field2"] ] /following-sibling::input [@type="hidden"] [@id="name__token"] ] ' ); } public function testFormEndWithoutRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'text') ->getForm() ->createView(); $this->renderWidget($view['field1']); // Rest should only contain field2, but isn't rendered $html = $this->renderEnd($view, array('render_rest' => false)); $this->assertEquals('', $html); } public function testWidgetContainerAttributes() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), )); $form->add('text', 'text'); $html = $this->renderWidget($form->createView()); // compare plain HTML to check the whitespace $this->assertContains('
', $html); } public function testWidgetContainerAttributeNameRepeatedIfTrue() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('foo' => true), )); $html = $this->renderWidget($form->createView()); // foo="foo" $this->assertContains('
', $html); } public function testWidgetContainerAttributeHiddenIfFalse() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('foo' => false), )); $html = $this->renderWidget($form->createView()); // no foo $this->assertContains('
', $html); } } PK!k/6  ;test/Form/Symfony/Component/Form/Tests/AbstractFormTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; abstract class AbstractFormTest extends \PHPUnit_Framework_TestCase { /** * @var EventDispatcherInterface */ protected $dispatcher; /** * @var \Symfony\Component\Form\FormFactoryInterface */ protected $factory; /** * @var \Symfony\Component\Form\FormInterface */ protected $form; protected function setUp() { // We need an actual dispatcher to use the deprecated // bindRequest() method $this->dispatcher = new EventDispatcher(); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->createForm(); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->form = null; } /** * @return \Symfony\Component\Form\FormInterface */ abstract protected function createForm(); /** * @param string $name * @param EventDispatcherInterface $dispatcher * @param string $dataClass * @param array $options * * @return FormBuilder */ protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null, $dataClass = null, array $options = array()) { return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory, $options); } /** * @param string $name * * @return \PHPUnit_Framework_MockObject_MockObject */ protected function getMockForm($name = 'name') { $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); $form->expects($this->any()) ->method('getName') ->will($this->returnValue($name)); $form->expects($this->any()) ->method('getConfig') ->will($this->returnValue($config)); return $form; } /** * @return \PHPUnit_Framework_MockObject_MockObject */ protected function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ protected function getDataTransformer() { return $this->getMock('Symfony\Component\Form\DataTransformerInterface'); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ protected function getFormValidator() { return $this->getMock('Symfony\Component\Form\FormValidatorInterface'); } } PK!rM{{9test/Form/Symfony/Component/Form/Tests/SimpleFormTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; use Symfony\Component\Form\Tests\Fixtures\FixedFilterListener; class SimpleFormTest_Countable implements \Countable { private $count; public function __construct($count) { $this->count = $count; } public function count() { return $this->count; } } class SimpleFormTest_Traversable implements \IteratorAggregate { private $iterator; public function __construct($count) { $this->iterator = new \ArrayIterator($count > 0 ? array_fill(0, $count, 'Foo') : array()); } public function getIterator() { return $this->iterator; } } class SimpleFormTest extends AbstractFormTest { public function testDataIsInitializedToConfiguredValue() { $model = new FixedDataTransformer(array( 'default' => 'foo', )); $view = new FixedDataTransformer(array( 'foo' => 'bar', )); $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addViewTransformer($view); $config->addModelTransformer($model); $config->setData('default'); $form = new Form($config); $this->assertSame('default', $form->getData()); $this->assertSame('foo', $form->getNormData()); $this->assertSame('bar', $form->getViewData()); } // https://github.com/symfony/symfony/commit/d4f4038f6daf7cf88ca7c7ab089473cce5ebf7d8#commitcomment-1632879 public function testDataIsInitializedFromSubmit() { $mock = $this->getMockBuilder('\stdClass') ->setMethods(array('preSetData', 'preSubmit')) ->getMock(); $mock->expects($this->at(0)) ->method('preSetData'); $mock->expects($this->at(1)) ->method('preSubmit'); $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addEventListener(FormEvents::PRE_SET_DATA, array($mock, 'preSetData')); $config->addEventListener(FormEvents::PRE_SUBMIT, array($mock, 'preSubmit')); $form = new Form($config); // no call to setData() or similar where the object would be // initialized otherwise $form->submit('foobar'); } // https://github.com/symfony/symfony/pull/7789 public function testFalseIsConvertedToNull() { $mock = $this->getMockBuilder('\stdClass') ->setMethods(array('preBind')) ->getMock(); $mock->expects($this->once()) ->method('preBind') ->with($this->callback(function ($event) { return null === $event->getData(); })); $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addEventListener(FormEvents::PRE_BIND, array($mock, 'preBind')); $form = new Form($config); $form->bind(false); $this->assertTrue($form->isValid()); $this->assertNull($form->getData()); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testSubmitThrowsExceptionIfAlreadySubmitted() { $this->form->submit(array()); $this->form->submit(array()); } public function testSubmitIsIgnoredIfDisabled() { $form = $this->getBuilder() ->setDisabled(true) ->setData('initial') ->getForm(); $form->submit('new'); $this->assertEquals('initial', $form->getData()); $this->assertTrue($form->isSubmitted()); } public function testNeverRequiredIfParentNotRequired() { $parent = $this->getBuilder()->setRequired(false)->getForm(); $child = $this->getBuilder()->setRequired(true)->getForm(); $child->setParent($parent); $this->assertFalse($child->isRequired()); } public function testRequired() { $parent = $this->getBuilder()->setRequired(true)->getForm(); $child = $this->getBuilder()->setRequired(true)->getForm(); $child->setParent($parent); $this->assertTrue($child->isRequired()); } public function testNotRequired() { $parent = $this->getBuilder()->setRequired(true)->getForm(); $child = $this->getBuilder()->setRequired(false)->getForm(); $child->setParent($parent); $this->assertFalse($child->isRequired()); } public function testAlwaysDisabledIfParentDisabled() { $parent = $this->getBuilder()->setDisabled(true)->getForm(); $child = $this->getBuilder()->setDisabled(false)->getForm(); $child->setParent($parent); $this->assertTrue($child->isDisabled()); } public function testDisabled() { $parent = $this->getBuilder()->setDisabled(false)->getForm(); $child = $this->getBuilder()->setDisabled(true)->getForm(); $child->setParent($parent); $this->assertTrue($child->isDisabled()); } public function testNotDisabled() { $parent = $this->getBuilder()->setDisabled(false)->getForm(); $child = $this->getBuilder()->setDisabled(false)->getForm(); $child->setParent($parent); $this->assertFalse($child->isDisabled()); } public function testGetRootReturnsRootOfParent() { $parent = $this->getMockForm(); $parent->expects($this->once()) ->method('getRoot') ->will($this->returnValue('ROOT')); $this->form->setParent($parent); $this->assertEquals('ROOT', $this->form->getRoot()); } public function testGetRootReturnsSelfIfNoParent() { $this->assertSame($this->form, $this->form->getRoot()); } public function testEmptyIfEmptyArray() { $this->form->setData(array()); $this->assertTrue($this->form->isEmpty()); } public function testEmptyIfEmptyCountable() { $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Countable(0)); $this->assertTrue($this->form->isEmpty()); } public function testNotEmptyIfFilledCountable() { $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Countable(1)); $this->assertFalse($this->form->isEmpty()); } public function testEmptyIfEmptyTraversable() { $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Traversable(0)); $this->assertTrue($this->form->isEmpty()); } public function testNotEmptyIfFilledTraversable() { $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Traversable(1)); $this->assertFalse($this->form->isEmpty()); } public function testEmptyIfNull() { $this->form->setData(null); $this->assertTrue($this->form->isEmpty()); } public function testEmptyIfEmptyString() { $this->form->setData(''); $this->assertTrue($this->form->isEmpty()); } public function testNotEmptyIfText() { $this->form->setData('foobar'); $this->assertFalse($this->form->isEmpty()); } public function testValidIfSubmitted() { $form = $this->getBuilder()->getForm(); $form->submit('foobar'); $this->assertTrue($form->isValid()); } public function testValidIfSubmittedAndDisabled() { $form = $this->getBuilder()->setDisabled(true)->getForm(); $form->submit('foobar'); $this->assertTrue($form->isValid()); } public function testNotValidIfNotSubmitted() { $this->assertFalse($this->form->isValid()); } public function testNotValidIfErrors() { $form = $this->getBuilder()->getForm(); $form->submit('foobar'); $form->addError(new FormError('Error!')); $this->assertFalse($form->isValid()); } public function testHasErrors() { $this->form->addError(new FormError('Error!')); $this->assertCount(1, $this->form->getErrors()); } public function testHasNoErrors() { $this->assertCount(0, $this->form->getErrors()); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testSetParentThrowsExceptionIfAlreadySubmitted() { $this->form->submit(array()); $this->form->setParent($this->getBuilder('parent')->getForm()); } public function testSubmitted() { $form = $this->getBuilder()->getForm(); $form->submit('foobar'); $this->assertTrue($form->isSubmitted()); } public function testNotSubmitted() { $this->assertFalse($this->form->isSubmitted()); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testSetDataThrowsExceptionIfAlreadySubmitted() { $this->form->submit(array()); $this->form->setData(null); } public function testSetDataClonesObjectIfNotByReference() { $data = new \stdClass(); $form = $this->getBuilder('name', null, '\stdClass')->setByReference(false)->getForm(); $form->setData($data); $this->assertNotSame($data, $form->getData()); $this->assertEquals($data, $form->getData()); } public function testSetDataDoesNotCloneObjectIfByReference() { $data = new \stdClass(); $form = $this->getBuilder('name', null, '\stdClass')->setByReference(true)->getForm(); $form->setData($data); $this->assertSame($data, $form->getData()); } public function testSetDataExecutesTransformationChain() { // use real event dispatcher now $form = $this->getBuilder('name', new EventDispatcher()) ->addEventSubscriber(new FixedFilterListener(array( 'preSetData' => array( 'app' => 'filtered', ), ))) ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'filtered' => 'norm', ))) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'norm' => 'client', ))) ->getForm(); $form->setData('app'); $this->assertEquals('filtered', $form->getData()); $this->assertEquals('norm', $form->getNormData()); $this->assertEquals('client', $form->getViewData()); } public function testSetDataExecutesViewTransformersInOrder() { $form = $this->getBuilder() ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'first' => 'second', ))) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'second' => 'third', ))) ->getForm(); $form->setData('first'); $this->assertEquals('third', $form->getViewData()); } public function testSetDataExecutesModelTransformersInReverseOrder() { $form = $this->getBuilder() ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'second' => 'third', ))) ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'first' => 'second', ))) ->getForm(); $form->setData('first'); $this->assertEquals('third', $form->getNormData()); } /* * When there is no data transformer, the data must have the same format * in all three representations */ public function testSetDataConvertsScalarToStringIfNoTransformer() { $form = $this->getBuilder()->getForm(); $form->setData(1); $this->assertSame('1', $form->getData()); $this->assertSame('1', $form->getNormData()); $this->assertSame('1', $form->getViewData()); } /* * Data in client format should, if possible, always be a string to * facilitate differentiation between '0' and '' */ public function testSetDataConvertsScalarToStringIfOnlyModelTransformer() { $form = $this->getBuilder() ->addModelTransformer(new FixedDataTransformer(array( '' => '', 1 => 23, ))) ->getForm(); $form->setData(1); $this->assertSame(1, $form->getData()); $this->assertSame(23, $form->getNormData()); $this->assertSame('23', $form->getViewData()); } /* * NULL remains NULL in app and norm format to remove the need to treat * empty values and NULL explicitly in the application */ public function testSetDataConvertsNullToStringIfNoTransformer() { $form = $this->getBuilder()->getForm(); $form->setData(null); $this->assertNull($form->getData()); $this->assertNull($form->getNormData()); $this->assertSame('', $form->getViewData()); } public function testSetDataIsIgnoredIfDataIsLocked() { $form = $this->getBuilder() ->setData('default') ->setDataLocked(true) ->getForm(); $form->setData('foobar'); $this->assertSame('default', $form->getData()); } public function testSubmitConvertsEmptyToNullIfNoTransformer() { $form = $this->getBuilder()->getForm(); $form->submit(''); $this->assertNull($form->getData()); $this->assertNull($form->getNormData()); $this->assertSame('', $form->getViewData()); } public function testSubmitExecutesTransformationChain() { // use real event dispatcher now $form = $this->getBuilder('name', new EventDispatcher()) ->addEventSubscriber(new FixedFilterListener(array( 'preSubmit' => array( 'client' => 'filteredclient', ), 'onSubmit' => array( 'norm' => 'filterednorm', ), ))) ->addViewTransformer(new FixedDataTransformer(array( '' => '', // direction is reversed! 'norm' => 'filteredclient', 'filterednorm' => 'cleanedclient' ))) ->addModelTransformer(new FixedDataTransformer(array( '' => '', // direction is reversed! 'app' => 'filterednorm', ))) ->getForm(); $form->submit('client'); $this->assertEquals('app', $form->getData()); $this->assertEquals('filterednorm', $form->getNormData()); $this->assertEquals('cleanedclient', $form->getViewData()); } public function testSubmitExecutesViewTransformersInReverseOrder() { $form = $this->getBuilder() ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'third' => 'second', ))) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'second' => 'first', ))) ->getForm(); $form->submit('first'); $this->assertEquals('third', $form->getNormData()); } public function testSubmitExecutesModelTransformersInOrder() { $form = $this->getBuilder() ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'second' => 'first', ))) ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'third' => 'second', ))) ->getForm(); $form->submit('first'); $this->assertEquals('third', $form->getData()); } public function testSynchronizedByDefault() { $this->assertTrue($this->form->isSynchronized()); } public function testSynchronizedAfterSubmission() { $this->form->submit('foobar'); $this->assertTrue($this->form->isSynchronized()); } public function testNotSynchronizedIfViewReverseTransformationFailed() { $transformer = $this->getDataTransformer(); $transformer->expects($this->once()) ->method('reverseTransform') ->will($this->throwException(new TransformationFailedException())); $form = $this->getBuilder() ->addViewTransformer($transformer) ->getForm(); $form->submit('foobar'); $this->assertFalse($form->isSynchronized()); } public function testNotSynchronizedIfModelReverseTransformationFailed() { $transformer = $this->getDataTransformer(); $transformer->expects($this->once()) ->method('reverseTransform') ->will($this->throwException(new TransformationFailedException())); $form = $this->getBuilder() ->addModelTransformer($transformer) ->getForm(); $form->submit('foobar'); $this->assertFalse($form->isSynchronized()); } public function testEmptyDataCreatedBeforeTransforming() { $form = $this->getBuilder() ->setEmptyData('foo') ->addViewTransformer(new FixedDataTransformer(array( '' => '', // direction is reversed! 'bar' => 'foo', ))) ->getForm(); $form->submit(''); $this->assertEquals('bar', $form->getData()); } public function testEmptyDataFromClosure() { $test = $this; $form = $this->getBuilder() ->setEmptyData(function ($form) use ($test) { // the form instance is passed to the closure to allow use // of form data when creating the empty value $test->assertInstanceOf('Symfony\Component\Form\FormInterface', $form); return 'foo'; }) ->addViewTransformer(new FixedDataTransformer(array( '' => '', // direction is reversed! 'bar' => 'foo', ))) ->getForm(); $form->submit(''); $this->assertEquals('bar', $form->getData()); } public function testSubmitResetsErrors() { $this->form->addError(new FormError('Error!')); $this->form->submit('foobar'); $this->assertSame(array(), $this->form->getErrors()); } public function testCreateView() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $form = $this->getBuilder()->setType($type)->getForm(); $type->expects($this->once()) ->method('createView') ->with($form) ->will($this->returnValue($view)); $this->assertSame($view, $form->createView()); } public function testCreateViewWithParent() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $parentForm = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $parentView = $this->getMock('Symfony\Component\Form\FormView'); $form = $this->getBuilder()->setType($type)->getForm(); $form->setParent($parentForm); $parentForm->expects($this->once()) ->method('createView') ->will($this->returnValue($parentView)); $type->expects($this->once()) ->method('createView') ->with($form, $parentView) ->will($this->returnValue($view)); $this->assertSame($view, $form->createView()); } public function testCreateViewWithExplicitParent() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $parentView = $this->getMock('Symfony\Component\Form\FormView'); $form = $this->getBuilder()->setType($type)->getForm(); $type->expects($this->once()) ->method('createView') ->with($form, $parentView) ->will($this->returnValue($view)); $this->assertSame($view, $form->createView($parentView)); } public function testGetErrorsAsString() { $this->form->addError(new FormError('Error!')); $this->assertEquals("ERROR: Error!\n", $this->form->getErrorsAsString()); } public function testFormCanHaveEmptyName() { $form = $this->getBuilder('')->getForm(); $this->assertEquals('', $form->getName()); } public function testSetNullParentWorksWithEmptyName() { $form = $this->getBuilder('')->getForm(); $form->setParent(null); $this->assertNull($form->getParent()); } /** * @expectedException \Symfony\Component\Form\Exception\LogicException * @expectedExceptionMessage A form with an empty name cannot have a parent form. */ public function testFormCannotHaveEmptyNameNotInRootLevel() { $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add($this->getBuilder('')) ->getForm(); } public function testGetPropertyPathReturnsConfiguredPath() { $form = $this->getBuilder()->setPropertyPath('address.street')->getForm(); $this->assertEquals(new PropertyPath('address.street'), $form->getPropertyPath()); } // see https://github.com/symfony/symfony/issues/3903 public function testGetPropertyPathDefaultsToNameIfParentHasDataClass() { $parent = $this->getBuilder(null, null, 'stdClass') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name')->getForm(); $parent->add($form); $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); } // see https://github.com/symfony/symfony/issues/3903 public function testGetPropertyPathDefaultsToIndexedNameIfParentDataClassIsNull() { $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name')->getForm(); $parent->add($form); $this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath()); } public function testGetPropertyPathDefaultsToNameIfFirstParentWithoutInheritDataHasDataClass() { $grandParent = $this->getBuilder(null, null, 'stdClass') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setInheritData(true) ->getForm(); $form = $this->getBuilder('name')->getForm(); $grandParent->add($parent); $parent->add($form); $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); } public function testGetPropertyPathDefaultsToIndexedNameIfDataClassOfFirstParentWithoutInheritDataIsNull() { $grandParent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setInheritData(true) ->getForm(); $form = $this->getBuilder('name')->getForm(); $grandParent->add($parent); $parent->add($form); $this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath()); } /** * @expectedException \Symfony\Component\Form\Exception\LogicException */ public function testViewDataMustNotBeObjectIfDataClassIsNull() { $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => new \stdClass(), ))); $form = new Form($config); $form->setData('foo'); } public function testViewDataMayBeArrayAccessIfDataClassIsNull() { $arrayAccess = $this->getMock('\ArrayAccess'); $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => $arrayAccess, ))); $form = new Form($config); $form->setData('foo'); $this->assertSame($arrayAccess, $form->getViewData()); } /** * @expectedException \Symfony\Component\Form\Exception\LogicException */ public function testViewDataMustBeObjectIfDataClassIsSet() { $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); $config->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => array('bar' => 'baz'), ))); $form = new Form($config); $form->setData('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testSetDataCannotInvokeItself() { // Cycle detection to prevent endless loops $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); $config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { $event->getForm()->setData('bar'); }); $form = new Form($config); $form->setData('foo'); } public function testSubmittingWrongDataIsIgnored() { $test = $this; $child = $this->getBuilder('child', $this->dispatcher); $child->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($test) { // child form doesn't receive the wrong data that is submitted on parent $test->assertNull($event->getData()); }); $parent = $this->getBuilder('parent', new EventDispatcher()) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add($child) ->getForm(); $parent->submit('not-an-array'); } public function testHandleRequestForwardsToRequestHandler() { $handler = $this->getMock('Symfony\Component\Form\RequestHandlerInterface'); $form = $this->getBuilder() ->setRequestHandler($handler) ->getForm(); $handler->expects($this->once()) ->method('handleRequest') ->with($this->identicalTo($form), 'REQUEST'); $this->assertSame($form, $form->handleRequest('REQUEST')); } public function testFormInheritsParentData() { $child = $this->getBuilder('child') ->setInheritData(true); $parent = $this->getBuilder('parent') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setData('foo') ->addModelTransformer(new FixedDataTransformer(array( 'foo' => 'norm[foo]', ))) ->addViewTransformer(new FixedDataTransformer(array( 'norm[foo]' => 'view[foo]', ))) ->add($child) ->getForm(); $this->assertSame('foo', $parent->get('child')->getData()); $this->assertSame('norm[foo]', $parent->get('child')->getNormData()); $this->assertSame('view[foo]', $parent->get('child')->getViewData()); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testInheritDataDisallowsSetData() { $form = $this->getBuilder() ->setInheritData(true) ->getForm(); $form->setData('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testGetDataRequiresParentToBeSetIfInheritData() { $form = $this->getBuilder() ->setInheritData(true) ->getForm(); $form->getData(); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testGetNormDataRequiresParentToBeSetIfInheritData() { $form = $this->getBuilder() ->setInheritData(true) ->getForm(); $form->getNormData(); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testGetViewDataRequiresParentToBeSetIfInheritData() { $form = $this->getBuilder() ->setInheritData(true) ->getForm(); $form->getViewData(); } public function testPostSubmitDataIsNullIfInheritData() { $test = $this; $form = $this->getBuilder() ->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($test) { $test->assertNull($event->getData()); }) ->setInheritData(true) ->getForm(); $form->submit('foo'); } public function testSubmitIsNeverFiredIfInheritData() { $test = $this; $form = $this->getBuilder() ->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) use ($test) { $test->fail('The SUBMIT event should not be fired'); }) ->setInheritData(true) ->getForm(); $form->submit('foo'); } public function testInitializeSetsDefaultData() { $config = $this->getBuilder()->setData('DEFAULT')->getFormConfig(); $form = $this->getMock('Symfony\Component\Form\Form', array('setData'), array($config)); $form->expects($this->once()) ->method('setData') ->with($this->identicalTo('DEFAULT')); /* @var Form $form */ $form->initialize(); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testInitializeFailsIfParent() { $parent = $this->getBuilder()->setRequired(false)->getForm(); $child = $this->getBuilder()->setRequired(true)->getForm(); $child->setParent($parent); $child->initialize(); } protected function createForm() { return $this->getBuilder()->getForm(); } } PK!ۿtctest/Form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\EventListener; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; class ValidationListenerTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $validator; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $violationMapper; /** * @var ValidationListener */ private $listener; private $message; private $messageTemplate; private $params; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); $this->violationMapper = $this->getMock('Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface'); $this->listener = new ValidationListener($this->validator, $this->violationMapper); $this->message = 'Message'; $this->messageTemplate = 'Message template'; $this->params = array('foo' => 'bar'); } private function getConstraintViolation($code = null) { return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code); } private function getBuilder($name = 'name', $propertyPath = null, $dataClass = null) { $builder = new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory); $builder->setPropertyPath(new PropertyPath($propertyPath ?: $name)); $builder->setAttribute('error_mapping', array()); $builder->setErrorBubbling(false); $builder->setMapped(true); return $builder; } private function getForm($name = 'name', $propertyPath = null, $dataClass = null) { return $this->getBuilder($name, $propertyPath, $dataClass)->getForm(); } private function getMockForm() { return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } // More specific mapping tests can be found in ViolationMapperTest public function testMapViolation() { $violation = $this->getConstraintViolation(); $form = $this->getForm('street'); $this->validator->expects($this->once()) ->method('validate') ->will($this->returnValue(array($violation))); $this->violationMapper->expects($this->once()) ->method('mapViolation') ->with($violation, $form, false); $this->listener->validateForm(new FormEvent($form, null)); } public function testMapViolationAllowsNonSyncIfInvalid() { $violation = $this->getConstraintViolation(Form::ERR_INVALID); $form = $this->getForm('street'); $this->validator->expects($this->once()) ->method('validate') ->will($this->returnValue(array($violation))); $this->violationMapper->expects($this->once()) ->method('mapViolation') // pass true now ->with($violation, $form, true); $this->listener->validateForm(new FormEvent($form, null)); } public function testValidateIgnoresNonRoot() { $form = $this->getMockForm(); $form->expects($this->once()) ->method('isRoot') ->will($this->returnValue(false)); $this->validator->expects($this->never()) ->method('validate'); $this->violationMapper->expects($this->never()) ->method('mapViolation'); $this->listener->validateForm(new FormEvent($form, null)); } public function testValidateWithEmptyViolationList() { $form = $this->getMockForm(); $form->expects($this->once()) ->method('isRoot') ->will($this->returnValue(true)); $this->validator ->expects($this->once()) ->method('validate') ->will($this->returnValue(new ConstraintViolationList())); $this->violationMapper ->expects($this->never()) ->method('mapViolation'); $this->listener->validateForm(new FormEvent($form, null)); } } PK!EY޵Ttest/Form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Util; class ServerParamsTest extends \PHPUnit_Framework_TestCase { /** @dataProvider getGetPostMaxSizeTestData */ public function testGetPostMaxSize($size, $bytes) { $serverParams = $this->getMock('Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize')); $serverParams ->expects($this->any()) ->method('getNormalizedIniPostMaxSize') ->will($this->returnValue(strtoupper($size))); $this->assertEquals($bytes, $serverParams->getPostMaxSize()); } public function getGetPostMaxSizeTestData() { return array( array('2k', 2048), array('2 k', 2048), array('8m', 8 * 1024 * 1024), array('+2 k', 2048), array('+2???k', 2048), array('0x10', 16), array('0xf', 15), array('010', 8), array('+0x10 k', 16 * 1024), array('1g', 1024 * 1024 * 1024), array('-1', -1), array('0', 0), array('2mk', 2048), // the unit must be the last char, so in this case 'k', not 'm' ); } } PK!l" Wtest/Form/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator; use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\Type; /** * @author franek */ class ValidatorTypeGuesserTest extends \PHPUnit_Framework_TestCase { private $typeGuesser; public function setUp() { if (!class_exists('Symfony\Component\Validator\Constraint')) { $this->markTestSkipped('The "Validator" component is not available'); } $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->typeGuesser = new ValidatorTypeGuesser($metadataFactory); } public function testGuessMaxLengthForConstraintWithMaxValue() { $constraint = new Length(array('max' => '2')); $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result); $this->assertEquals(2, $result->getValue()); $this->assertEquals(Guess::HIGH_CONFIDENCE, $result->getConfidence()); } public function testGuessMaxLengthForConstraintWithMinValue() { $constraint = new Length(array('min' => '2')); $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); $this->assertNull($result); } /** * @dataProvider dataProviderTestGuessMaxLengthForConstraintWithType */ public function testGuessMaxLengthForConstraintWithType($type) { $constraint = new Type($type); $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result); $this->assertEquals(null, $result->getValue()); $this->assertEquals(Guess::MEDIUM_CONFIDENCE, $result->getConfidence()); } public static function dataProviderTestGuessMaxLengthForConstraintWithType() { return array ( array('double'), array('float'), array('numeric'), array('real') ); } } PK! gtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; use Symfony\Component\Form\Test\FormPerformanceTestCase; use Symfony\Component\Validator\Validation; /** * @author Bernhard Schussek */ class FormValidatorPerformanceTest extends FormPerformanceTestCase { protected function getExtensions() { return array( new ValidatorExtension(Validation::createValidator()), ); } /** * findClickedButton() used to have an exponential number of calls * * @group benchmark */ public function testValidationPerformance() { $this->setMaxRunningTime(1); $builder = $this->factory->createBuilder('form'); for ($i = 0; $i < 40; ++$i) { $builder->add($i, 'form'); $builder->get($i) ->add('a') ->add('b') ->add('c'); } $form = $builder->getForm(); $form->submit(null); } } PK!ِGbGb\test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator; use Symfony\Component\Form\SubmitButtonBuilder; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; /** * @author Bernhard Schussek */ class FormValidatorTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $serverParams; /** * @var FormValidator */ private $validator; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->serverParams = $this->getMock( 'Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize', 'getContentLength') ); $this->validator = new FormValidator($this->serverParams); } public function testValidate() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array('group1', 'group2')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testValidateConstraints() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); $options = array( 'validation_groups' => array('group1', 'group2'), 'constraints' => array($constraint1, $constraint2), ); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); // First default constraints $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); // Then custom constraints $context->expects($this->at(2)) ->method('validateValue') ->with($object, $constraint1, 'data', 'group1'); $context->expects($this->at(3)) ->method('validateValue') ->with($object, $constraint2, 'data', 'group2'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateIfParentWithoutCascadeValidation() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $options = array('validation_groups' => array('group1', 'group2')); $form = $this->getBuilder('name', '\stdClass', $options)->getForm(); $parent->add($form); $form->setData($object); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testValidateConstraintsEvenIfNoCascadeValidation() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $options = array( 'validation_groups' => array('group1', 'group2'), 'constraints' => array($constraint1, $constraint2), ); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $parent->add($form); $context->expects($this->at(0)) ->method('validateValue') ->with($object, $constraint1, 'data', 'group1'); $context->expects($this->at(1)) ->method('validateValue') ->with($object, $constraint2, 'data', 'group2'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateIfNoValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( 'validation_groups' => array(), )) ->setData($object) ->getForm(); $form->setData($object); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateConstraintsIfNoValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); $options = array( 'validation_groups' => array(), 'constraints' => array($constraint1, $constraint2), ); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); // Launch transformer $form->submit(array()); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateIfNotSynchronized() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( 'invalid_message' => 'invalid_message_key', // Invalid message parameters must be supported, because the // invalid message can be a translation key // see https://github.com/symfony/symfony/issues/5144 'invalid_message_parameters' => array('{{ foo }}' => 'bar'), )) ->setData($object) ->addViewTransformer(new CallbackTransformer( function ($data) { return $data; }, function () { throw new TransformationFailedException(); } )) ->getForm(); // Launch transformer $form->submit('foo'); $context->expects($this->never()) ->method('validate'); $context->expects($this->once()) ->method('addViolation') ->with( 'invalid_message_key', array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), 'foo' ); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testAddInvalidErrorEvenIfNoValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( 'invalid_message' => 'invalid_message_key', // Invalid message parameters must be supported, because the // invalid message can be a translation key // see https://github.com/symfony/symfony/issues/5144 'invalid_message_parameters' => array('{{ foo }}' => 'bar'), 'validation_groups' => array(), )) ->setData($object) ->addViewTransformer(new CallbackTransformer( function ($data) { return $data; }, function () { throw new TransformationFailedException(); } )) ->getForm(); // Launch transformer $form->submit('foo'); $context->expects($this->never()) ->method('validate'); $context->expects($this->once()) ->method('addViolation') ->with( 'invalid_message_key', array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), 'foo' ); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateConstraintsIfNotSynchronized() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); $options = array( 'validation_groups' => array('group1', 'group2'), 'constraints' => array($constraint1, $constraint2), ); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->addViewTransformer(new CallbackTransformer( function ($data) { return $data; }, function () { throw new TransformationFailedException(); } )) ->getForm(); // Launch transformer $form->submit(array()); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } // https://github.com/symfony/symfony/issues/4359 public function testDontMarkInvalidIfAnyChildIsNotSynchronized() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $failingTransformer = new CallbackTransformer( function ($data) { return $data; }, function () { throw new TransformationFailedException(); } ); $form = $this->getBuilder('name', '\stdClass') ->setData($object) ->addViewTransformer($failingTransformer) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add( $this->getBuilder('child') ->addViewTransformer($failingTransformer) ) ->getForm(); // Launch transformer $form->submit(array('child' => 'foo')); $context->expects($this->never()) ->method('addViolation'); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testHandleCallbackValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array($this, 'getValidationGroups')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontExecuteFunctionNames() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => 'header'); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'header', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testHandleClosureValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); }); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testUseValidationGroupOfClickedButton() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getForm('name', '\stdClass', array( 'validation_groups' => 'form_group', )); $parent->add($form); $parent->add($this->getSubmitButton('submit', array( 'validation_groups' => 'button_group', ))); $parent->submit(array('name' => $object, 'submit' => '')); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'button_group', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontUseValidationGroupOfUnclickedButton() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getForm('name', '\stdClass', array( 'validation_groups' => 'form_group', )); $parent->add($form); $parent->add($this->getSubmitButton('submit', array( 'validation_groups' => 'button_group', ))); $form->setData($object); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'form_group', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testUseInheritedValidationGroup() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( 'validation_groups' => 'group', 'cascade_validation' => true, ); $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name', '\stdClass')->getForm(); $parent->add($form); $form->setData($object); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'group', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testUseInheritedCallbackValidationGroup() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( 'validation_groups' => array($this, 'getValidationGroups'), 'cascade_validation' => true, ); $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name', '\stdClass')->getForm(); $parent->add($form); $form->setData($object); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testUseInheritedClosureValidationGroup() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( 'validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); }, 'cascade_validation' => true, ); $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name', '\stdClass')->getForm(); $parent->add($form); $form->setData($object); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testAppendPropertyPath() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass') ->setData($object) ->getForm(); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'Default', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontWalkScalars() { $context = $this->getMockExecutionContext(); $form = $this->getBuilder() ->setData('scalar') ->getForm(); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testViolationIfExtraData() { $context = $this->getMockExecutionContext(); $form = $this->getBuilder('parent', null, array('extra_fields_message' => 'Extra!')) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add($this->getBuilder('child')) ->getForm(); $form->submit(array('foo' => 'bar')); $context->expects($this->once()) ->method('addViolation') ->with( 'Extra!', array('{{ extra_fields }}' => 'foo'), array('foo' => 'bar') ); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } /** * @dataProvider getPostMaxSizeFixtures */ public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, array $params = array()) { $this->serverParams->expects($this->once()) ->method('getContentLength') ->will($this->returnValue($contentLength)); $this->serverParams->expects($this->any()) ->method('getNormalizedIniPostMaxSize') ->will($this->returnValue($iniMax)); $context = $this->getMockExecutionContext(); $options = array('post_max_size_message' => 'Max {{ max }}!'); $form = $this->getBuilder('name', null, $options)->getForm(); for ($i = 0; $i < $nbViolation; ++$i) { if (0 === $i && count($params) > 0) { $context->expects($this->at($i)) ->method('addViolation') ->with($options['post_max_size_message'], $params); } else { $context->expects($this->at($i)) ->method('addViolation'); } } $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function getPostMaxSizeFixtures() { return array( array(pow(1024, 3) + 1, '1G', 1, array('{{ max }}' => '1G')), array(pow(1024, 3), '1G', 0), array(pow(1024, 2) + 1, '1M', 1, array('{{ max }}' => '1M')), array(pow(1024, 2), '1M', 0), array(1024 + 1, '1K', 1, array('{{ max }}' => '1K')), array(1024, '1K', 0), array(null, '1K', 0), array(1024, '', 0), array(1024, 0, 0), ); } public function testNoViolationIfNotRoot() { $this->serverParams->expects($this->once()) ->method('getContentLength') ->will($this->returnValue(1025)); $this->serverParams->expects($this->never()) ->method('getNormalizedIniPostMaxSize'); $context = $this->getMockExecutionContext(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getForm(); $parent->add($form); $context->expects($this->never()) ->method('addViolation'); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } /** * Access has to be public, as this method is called via callback array * in {@link testValidateFormDataCanHandleCallbackValidationGroups()} * and {@link testValidateFormDataUsesInheritedCallbackValidationGroup()} */ public function getValidationGroups(FormInterface $form) { return array('group1', 'group2'); } private function getMockExecutionContext() { return $this->getMock('Symfony\Component\Validator\ExecutionContextInterface'); } /** * @param string $name * @param string $dataClass * @param array $options * * @return FormBuilder */ private function getBuilder($name = 'name', $dataClass = null, array $options = array()) { $options = array_replace(array( 'constraints' => array(), 'invalid_message_parameters' => array(), ), $options); return new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory, $options); } private function getForm($name = 'name', $dataClass = null, array $options = array()) { return $this->getBuilder($name, $dataClass, $options)->getForm(); } private function getSubmitButton($name = 'name', array $options = array()) { $builder = new SubmitButtonBuilder($name, $options); return $builder->getForm(); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } } PK!$Ǵ`test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPath; /** * @author Bernhard Schussek */ class ViolationPathTest extends \PHPUnit_Framework_TestCase { public function providePaths() { return array( array('children[address]', array( array('address', true, true), )), array('children[address].children[street]', array( array('address', true, true), array('street', true, true), )), array('children[address][street]', array( array('address', true, true), ), 'children[address]'), array('children[address].data', array( array('address', true, true), ), 'children[address]'), array('children[address].data.street', array( array('address', true, true), array('street', false, false), )), array('children[address].data[street]', array( array('address', true, true), array('street', false, true), )), array('children[address].children[street].data.name', array( array('address', true, true), array('street', true, true), array('name', false, false), )), array('children[address].children[street].data[name]', array( array('address', true, true), array('street', true, true), array('name', false, true), )), array('data.address', array( array('address', false, false), )), array('data[address]', array( array('address', false, true), )), array('data.address.street', array( array('address', false, false), array('street', false, false), )), array('data[address].street', array( array('address', false, true), array('street', false, false), )), array('data.address[street]', array( array('address', false, false), array('street', false, true), )), array('data[address][street]', array( array('address', false, true), array('street', false, true), )), // A few invalid examples array('data', array(), ''), array('children', array(), ''), array('children.address', array(), ''), array('children.address[street]', array(), ''), ); } /** * @dataProvider providePaths */ public function testCreatePath($string, $entries, $slicedPath = null) { if (null === $slicedPath) { $slicedPath = $string; } $path = new ViolationPath($string); $this->assertSame($slicedPath, $path->__toString()); $this->assertSame(count($entries), count($path->getElements())); $this->assertSame(count($entries), $path->getLength()); foreach ($entries as $index => $entry) { $this->assertEquals($entry[0], $path->getElement($index)); $this->assertSame($entry[1], $path->mapsForm($index)); $this->assertSame($entry[2], $path->isIndex($index)); $this->assertSame(!$entry[2], $path->isProperty($index)); } } public function provideParents() { return array( array('children[address]', null), array('children[address].children[street]', 'children[address]'), array('children[address].data.street', 'children[address]'), array('children[address].data[street]', 'children[address]'), array('data.address', null), array('data.address.street', 'data.address'), array('data.address[street]', 'data.address'), array('data[address].street', 'data[address]'), array('data[address][street]', 'data[address]'), ); } /** * @dataProvider provideParents */ public function testGetParent($violationPath, $parentPath) { $path = new ViolationPath($violationPath); $parent = $parentPath === null ? null : new ViolationPath($parentPath); $this->assertEquals($parent, $path->getParent()); } public function testGetElement() { $path = new ViolationPath('children[address].data[street].name'); $this->assertEquals('street', $path->getElement(1)); } /** * @expectedException \OutOfBoundsException */ public function testGetElementDoesNotAcceptInvalidIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->getElement(3); } /** * @expectedException \OutOfBoundsException */ public function testGetElementDoesNotAcceptNegativeIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->getElement(-1); } public function testIsProperty() { $path = new ViolationPath('children[address].data[street].name'); $this->assertFalse($path->isProperty(1)); $this->assertTrue($path->isProperty(2)); } /** * @expectedException \OutOfBoundsException */ public function testIsPropertyDoesNotAcceptInvalidIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->isProperty(3); } /** * @expectedException \OutOfBoundsException */ public function testIsPropertyDoesNotAcceptNegativeIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->isProperty(-1); } public function testIsIndex() { $path = new ViolationPath('children[address].data[street].name'); $this->assertTrue($path->isIndex(1)); $this->assertFalse($path->isIndex(2)); } /** * @expectedException \OutOfBoundsException */ public function testIsIndexDoesNotAcceptInvalidIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->isIndex(3); } /** * @expectedException \OutOfBoundsException */ public function testIsIndexDoesNotAcceptNegativeIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->isIndex(-1); } public function testMapsForm() { $path = new ViolationPath('children[address].data[street].name'); $this->assertTrue($path->mapsForm(0)); $this->assertFalse($path->mapsForm(1)); $this->assertFalse($path->mapsForm(2)); } /** * @expectedException \OutOfBoundsException */ public function testMapsFormDoesNotAcceptInvalidIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->mapsForm(3); } /** * @expectedException \OutOfBoundsException */ public function testMapsFormDoesNotAcceptNegativeIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->mapsForm(-1); } } PK!@1,,btest/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\ConstraintViolation; /** * @author Bernhard Schussek */ class ViolationMapperTest extends \PHPUnit_Framework_TestCase { const LEVEL_0 = 0; const LEVEL_1 = 1; const LEVEL_1B = 2; const LEVEL_2 = 3; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var ViolationMapper */ private $mapper; /** * @var string */ private $message; /** * @var string */ private $messageTemplate; /** * @var array */ private $params; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->mapper = new ViolationMapper(); $this->message = 'Message'; $this->messageTemplate = 'Message template'; $this->params = array('foo' => 'bar'); } protected function getForm($name = 'name', $propertyPath = null, $dataClass = null, $errorMapping = array(), $inheritData = false, $synchronized = true) { $config = new FormConfigBuilder($name, $dataClass, $this->dispatcher, array( 'error_mapping' => $errorMapping, )); $config->setMapped(true); $config->setInheritData($inheritData); $config->setPropertyPath($propertyPath); $config->setCompound(true); $config->setDataMapper($this->getDataMapper()); if (!$synchronized) { $config->addViewTransformer(new CallbackTransformer( function ($normData) { return $normData; }, function () { throw new TransformationFailedException(); } )); } return new Form($config); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } /** * @param $propertyPath * * @return ConstraintViolation */ protected function getConstraintViolation($propertyPath) { return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, $propertyPath, null); } /** * @return FormError */ protected function getFormError() { return new FormError($this->message, $this->messageTemplate, $this->params); } public function testMapToFormInheritingParentDataIfDataDoesNotMatch() { $violation = $this->getConstraintViolation('children[address].data.foo'); $parent = $this->getForm('parent'); $child = $this->getForm('address', 'address', null, array(), true); $grandChild = $this->getForm('street'); $parent->add($child); $child->add($grandChild); $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $child->getName().' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function testFollowDotRules() { $violation = $this->getConstraintViolation('data.foo'); $parent = $this->getForm('parent', null, null, array( 'foo' => 'address', )); $child = $this->getForm('address', null, null, array( '.' => 'street', )); $grandChild = $this->getForm('street', null, null, array( '.' => 'name', )); $grandGrandChild = $this->getForm('name'); $parent->add($child); $child->add($grandChild); $grandChild->add($grandGrandChild); $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandGrandChild->getErrors(), $grandGrandChild->getName().' should have an error, but has none'); } public function testAbortMappingIfNotSynchronized() { $violation = $this->getConstraintViolation('children[address].data.street'); $parent = $this->getForm('parent'); $child = $this->getForm('address', 'address', null, array(), false, false); // even though "street" is synchronized, it should not have any errors // due to its parent not being synchronized $grandChild = $this->getForm('street' , 'street'); $parent->add($child); $child->add($grandChild); // submit to invoke the transformer and mark the form unsynchronized $parent->submit(array()); $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function testAbortDotRuleMappingIfNotSynchronized() { $violation = $this->getConstraintViolation('data.address'); $parent = $this->getForm('parent'); $child = $this->getForm('address', 'address', null, array( '.' => 'street', ), false, false); // even though "street" is synchronized, it should not have any errors // due to its parent not being synchronized $grandChild = $this->getForm('street'); $parent->add($child); $child->add($grandChild); // submit to invoke the transformer and mark the form unsynchronized $parent->submit(array()); $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function provideDefaultTests() { // The mapping must be deterministic! If a child has the property path "[street]", // "data[street]" should be mapped, but "data.street" should not! return array( // mapping target, child name, its property path, grand child name, its property path, violation path array(self::LEVEL_0, 'address', 'address', 'street', 'street', ''), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street'), array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street.prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street]'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street.prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street]'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street].prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street.prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street]'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street].prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street.prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street]'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street].prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street.prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street]'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street].prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street.prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street]'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address]'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street].prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street.prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street]'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street].prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street.prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street]'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street]'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street]'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street]'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street]'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office]'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street]'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street]'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street].prop'), // Edge cases which must not occur array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].children[street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].data.street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].data.address.street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.address.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].children[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].data.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.street'), ); } /** * @dataProvider provideDefaultTests */ public function testDefaultErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent'); $child = $this->getForm($childName, $childPath); $grandChild = $this->getForm($grandChildName, $grandChildPath); $parent->add($child); $child->add($grandChild); $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } public function provideCustomDataErrorTests() { return array( // mapping target, error mapping, child name, its property path, grand child name, its property path, violation path array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address]'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo]'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address]'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo'), array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo]'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo'), array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.prop'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo]'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].prop'), array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo'), array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo]'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar.prop'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar]'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar].prop'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar.prop'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar]'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar].prop'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar].prop'), // Edge cases array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'), ); } /** * @dataProvider provideCustomDataErrorTests */ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo)); $child = $this->getForm($childName, $childPath); $grandChild = $this->getForm($grandChildName, $grandChildPath); $parent->add($child); $child->add($grandChild); // Add a field mapped to the first element of $mapFrom // to try to distract the algorithm // Only add it if we expect the error to come up on a different // level than LEVEL_0, because in this case the error would // (correctly) be mapped to the distraction field if ($target !== self::LEVEL_0) { $mapFromPath = new PropertyPath($mapFrom); $mapFromPrefix = $mapFromPath->isIndex(0) ? '['.$mapFromPath->getElement(0).']' : $mapFromPath->getElement(0); $distraction = $this->getForm('distraction', $mapFromPrefix); $parent->add($distraction); } $this->mapper->mapViolation($violation, $parent); if ($target !== self::LEVEL_0) { $this->assertCount(0, $distraction->getErrors(), 'distraction should not have an error, but has one'); } if (self::LEVEL_0 === $target) { $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } public function provideCustomFormErrorTests() { // This case is different than the data errors, because here the // left side of the mapping refers to the property path of the actual // children. In other words, a child error only works if // 1) the error actually maps to an existing child and // 2) the property path of that child (relative to the form providing // the mapping) matches the left side of the mapping return array( // mapping target, map from, map to, child name, its property path, grand child name, its property path, violation path array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street].prop'), // Property path of the erroneous field and mapping must match exactly array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street]'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street]'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'), // Map to a nested child array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo]'), array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo]'), array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo]'), array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo]'), // Map from a nested child array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), ); } /** * @dataProvider provideCustomFormErrorTests */ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName, $errorPath, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo)); $child = $this->getForm($childName, $childPath); $grandChild = $this->getForm($grandChildName, $grandChildPath); $errorChild = $this->getForm($errorName, $errorPath); $parent->add($child); $parent->add($errorChild); $child->add($grandChild); $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1B === $target) { $this->assertEquals(array($this->getFormError()), $errorChild->getErrors(), $errorName.' should have an error, but has none'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } public function provideErrorTestsForFormInheritingParentData() { return array( // mapping target, child name, its property path, grand child name, its property path, violation path array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'), ); } /** * @dataProvider provideErrorTestsForFormInheritingParentData */ public function testErrorMappingForFormInheritingParentData($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent'); $child = $this->getForm($childName, $childPath, null, array(), true); $grandChild = $this->getForm($grandChildName, $grandChildPath); $parent->add($child); $child->add($grandChild); $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } } PK!`f[Ptest/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; abstract class TypeTestCase extends BaseTypeTestCase { protected $validator; protected function setUp() { $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->validator->expects($this->once())->method('getMetadataFactory')->will($this->returnValue($metadataFactory)); $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $metadataFactory->expects($this->once())->method('getMetadataFor')->will($this->returnValue($metadata)); parent::setUp(); } protected function tearDown() { $this->validator = null; parent::tearDown(); } protected function getExtensions() { return array_merge(parent::getExtensions(), array( new ValidatorExtension($this->validator), )); } } PK!Y xx^test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Test\FormInterface; /** * @author Bernhard Schussek */ abstract class BaseValidatorExtensionTest extends TypeTestCase { public function testValidationGroupNullByDefault() { $form = $this->createForm(); $this->assertNull($form->getConfig()->getOption('validation_groups')); } public function testValidationGroupsTransformedToArray() { $form = $this->createForm(array( 'validation_groups' => 'group', )); $this->assertEquals(array('group'), $form->getConfig()->getOption('validation_groups')); } public function testValidationGroupsCanBeSetToArray() { $form = $this->createForm(array( 'validation_groups' => array('group1', 'group2'), )); $this->assertEquals(array('group1', 'group2'), $form->getConfig()->getOption('validation_groups')); } public function testValidationGroupsCanBeSetToFalse() { $form = $this->createForm(array( 'validation_groups' => false, )); $this->assertEquals(array(), $form->getConfig()->getOption('validation_groups')); } public function testValidationGroupsCanBeSetToCallback() { $form = $this->createForm(array( 'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'), )); $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); } public function testValidationGroupsCanBeSetToClosure() { $form = $this->createForm(array( 'validation_groups' => function (FormInterface $form) { return null; }, )); $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); } abstract protected function createForm(array $options = array()); } PK!Smdtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; class SubmitTypeValidatorExtensionTest extends BaseValidatorExtensionTest { protected function createForm(array $options = array()) { return $this->factory->create('submit', null, $options); } } PK!7>lˉbtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Validator\ConstraintViolationList; class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest { public function testSubmitValidatesData() { $builder = $this->factory->createBuilder( 'form', null, array( 'validation_groups' => 'group', ) ); $builder->add('firstName', 'form'); $form = $builder->getForm(); $this->validator->expects($this->once()) ->method('validate') ->with($this->equalTo($form)) ->will($this->returnValue(new ConstraintViolationList())); // specific data is irrelevant $form->submit(array()); } protected function createForm(array $options = array()) { return $this->factory->create('form', null, $options); } } PK!1 itest/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\HttpFoundation\EventListener; use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Test\DeprecationErrorHandler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; /** * @author Bernhard Schussek */ class BindRequestListenerTest extends \PHPUnit_Framework_TestCase { private $values; private $filesPlain; private $filesNested; /** * @var UploadedFile */ private $uploadedFile; protected function setUp() { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $this->values = array( 'name' => 'Bernhard', 'image' => array('filename' => 'foobar.png'), ); $this->filesPlain = array( 'image' => array( 'error' => UPLOAD_ERR_OK, 'name' => 'upload.png', 'size' => 123, 'tmp_name' => $path, 'type' => 'image/png' ), ); $this->filesNested = array( 'error' => array('image' => UPLOAD_ERR_OK), 'name' => array('image' => 'upload.png'), 'size' => array('image' => 123), 'tmp_name' => array('image' => $path), 'type' => array('image' => 'image/png'), ); $this->uploadedFile = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); } protected function tearDown() { unlink($this->uploadedFile->getRealPath()); } public function requestMethodProvider() { return array( array('POST'), array('PUT'), array('DELETE'), array('PATCH'), ); } /** * @dataProvider requestMethodProvider */ public function testSubmitRequest($method) { $values = array('author' => $this->values); $files = array('author' => $this->filesNested); $request = new Request(array(), $values, array(), array(), $files, array( 'REQUEST_METHOD' => $method, )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', 'image' => $this->uploadedFile, ), $event->getData()); } /** * @dataProvider requestMethodProvider */ public function testSubmitRequestWithEmptyName($method) { $request = new Request(array(), $this->values, array(), array(), $this->filesPlain, array( 'REQUEST_METHOD' => $method, )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('', null, $dispatcher); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', 'image' => $this->uploadedFile, ), $event->getData()); } /** * @dataProvider requestMethodProvider */ public function testSubmitEmptyRequestToCompoundForm($method) { $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(true); $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); // Default to empty array $this->assertEquals(array(), $event->getData()); } /** * @dataProvider requestMethodProvider */ public function testSubmitEmptyRequestToSimpleForm($method) { $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(false); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); // Default to null $this->assertNull($event->getData()); } public function testSubmitGetRequest() { $values = array('author' => $this->values); $request = new Request($values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', 'image' => array('filename' => 'foobar.png'), ), $event->getData()); } public function testSubmitGetRequestWithEmptyName() { $request = new Request($this->values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('', null, $dispatcher); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', 'image' => array('filename' => 'foobar.png'), ), $event->getData()); } public function testSubmitEmptyGetRequestToCompoundForm() { $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(true); $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array(), $event->getData()); } public function testSubmitEmptyGetRequestToSimpleForm() { $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(false); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertNull($event->getData()); } } PK!f͍ffdtest/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\HttpFoundation; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\Tests\AbstractRequestHandlerTest; use Symfony\Component\HttpFoundation\Request; /** * @author Bernhard Schussek */ class HttpFoundationRequestHandlerTest extends AbstractRequestHandlerTest { /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequestShouldNotBeNull() { $this->requestHandler->handleRequest($this->getMockForm('name', 'GET')); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequestShouldBeInstanceOfRequest() { $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), new \stdClass()); } protected function setRequestData($method, $data, $files = array()) { $this->request = Request::create('http://localhost', $method, $data, array(), $files); } protected function getRequestHandler() { return new HttpFoundationRequestHandler(); } protected function getMockFile() { return $this->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') ->disableOriginalConstructor() ->getMock(); } } PK!%u^test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; class SessionCsrfProviderTest extends \PHPUnit_Framework_TestCase { protected $provider; protected $session; protected function setUp() { $this->session = $this->getMock( 'Symfony\Component\HttpFoundation\Session\Session', array(), array(), '', false // don't call constructor ); $this->provider = new SessionCsrfProvider($this->session, 'SECRET'); } protected function tearDown() { $this->provider = null; $this->session = null; } public function testGenerateCsrfToken() { $this->session->expects($this->once()) ->method('getId') ->will($this->returnValue('ABCDEF')); $token = $this->provider->generateCsrfToken('foo'); $this->assertEquals(sha1('SECRET'.'foo'.'ABCDEF'), $token); } public function testIsCsrfTokenValidSucceeds() { $this->session->expects($this->once()) ->method('getId') ->will($this->returnValue('ABCDEF')); $token = sha1('SECRET'.'foo'.'ABCDEF'); $this->assertTrue($this->provider->isCsrfTokenValid('foo', $token)); } public function testIsCsrfTokenValidFails() { $this->session->expects($this->once()) ->method('getId') ->will($this->returnValue('ABCDEF')); $token = sha1('SECRET'.'bar'.'ABCDEF'); $this->assertFalse($this->provider->isCsrfTokenValid('foo', $token)); } } PK!_Nn^test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; /** * @runTestsInSeparateProcesses */ class DefaultCsrfProviderTest extends \PHPUnit_Framework_TestCase { protected $provider; public static function setUpBeforeClass() { ini_set('session.save_handler', 'files'); ini_set('session.save_path', sys_get_temp_dir()); } protected function setUp() { $this->provider = new DefaultCsrfProvider('SECRET'); } protected function tearDown() { $this->provider = null; } public function testGenerateCsrfToken() { session_start(); $token = $this->provider->generateCsrfToken('foo'); $this->assertEquals(sha1('SECRET'.'foo'.session_id()), $token); } public function testGenerateCsrfTokenOnUnstartedSession() { session_id('touti'); if (!version_compare(PHP_VERSION, '5.4', '>=')) { $this->markTestSkipped('This test requires PHP >= 5.4'); } $this->assertSame(PHP_SESSION_NONE, session_status()); $token = $this->provider->generateCsrfToken('foo'); $this->assertEquals(sha1('SECRET'.'foo'.session_id()), $token); $this->assertSame(PHP_SESSION_ACTIVE, session_status()); } public function testIsCsrfTokenValidSucceeds() { session_start(); $token = sha1('SECRET'.'foo'.session_id()); $this->assertTrue($this->provider->isCsrfTokenValid('foo', $token)); } public function testIsCsrfTokenValidFails() { session_start(); $token = sha1('SECRET'.'bar'.session_id()); $this->assertFalse($this->provider->isCsrfTokenValid('foo', $token)); } } PK!Abtest/Form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase { protected $dispatcher; protected $factory; protected $tokenManager; protected $form; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); $this->form = $this->getBuilder('post') ->setDataMapper($this->getDataMapper()) ->getForm(); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->tokenManager = null; $this->form = null; } protected function getBuilder($name = 'name') { return new FormBuilder($name, null, $this->dispatcher, $this->factory, array('compound' => true)); } protected function getForm($name = 'name') { return $this->getBuilder($name)->getForm(); } protected function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } protected function getMockForm() { return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } // https://github.com/symfony/symfony/pull/5838 public function testStringFormData() { $data = "XP4HUzmHPi"; $event = new FormEvent($this->form, $data); $validation = new CsrfValidationListener('csrf', $this->tokenManager, 'unknown', 'Invalid.'); $validation->preSubmit($event); // Validate accordingly $this->assertSame($data, $event->getData()); } } PK!L?..Xtest/Form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Csrf\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\Form\Extension\Csrf\CsrfExtension; use Symfony\Component\Security\Csrf\CsrfToken; class FormTypeCsrfExtensionTest_ChildType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { // The form needs a child in order to trigger CSRF protection by // default $builder->add('name', 'text'); } public function getName() { return 'csrf_collection_test'; } } class FormTypeCsrfExtensionTest extends TypeTestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ protected $tokenManager; /** * @var \PHPUnit_Framework_MockObject_MockObject */ protected $translator; protected function setUp() { $this->tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface'); parent::setUp(); } protected function tearDown() { $this->tokenManager = null; $this->translator = null; parent::tearDown(); } protected function getExtensions() { return array_merge(parent::getExtensions(), array( new CsrfExtension($this->tokenManager, $this->translator), )); } public function testCsrfProtectionByDefaultIfRootAndCompound() { $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'compound' => true, )) ->createView(); $this->assertTrue(isset($view['csrf'])); } public function testNoCsrfProtectionByDefaultIfCompoundButNotRoot() { $view = $this->factory ->createNamedBuilder('root', 'form') ->add($this->factory ->createNamedBuilder('form', 'form', null, array( 'csrf_field_name' => 'csrf', 'compound' => true, )) ) ->getForm() ->get('form') ->createView(); $this->assertFalse(isset($view['csrf'])); } public function testNoCsrfProtectionByDefaultIfRootButNotCompound() { $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'compound' => false, )) ->createView(); $this->assertFalse(isset($view['csrf'])); } public function testCsrfProtectionCanBeDisabled() { $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_protection' => false, 'compound' => true, )) ->createView(); $this->assertFalse(isset($view['csrf'])); } public function testGenerateCsrfToken() { $this->tokenManager->expects($this->once()) ->method('getToken') ->with('TOKEN_ID') ->will($this->returnValue(new CsrfToken('TOKEN_ID', 'token'))); $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->createView(); $this->assertEquals('token', $view['csrf']->vars['value']); } public function testGenerateCsrfTokenUsesFormNameAsIntentionByDefault() { $this->tokenManager->expects($this->once()) ->method('getToken') ->with('FORM_NAME') ->will($this->returnValue('token')); $view = $this->factory ->createNamed('FORM_NAME', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'compound' => true, )) ->createView(); $this->assertEquals('token', $view['csrf']->vars['value']); } public function testGenerateCsrfTokenUsesTypeClassAsIntentionIfEmptyFormName() { $this->tokenManager->expects($this->once()) ->method('getToken') ->with('Symfony\Component\Form\Extension\Core\Type\FormType') ->will($this->returnValue('token')); $view = $this->factory ->createNamed('', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'compound' => true, )) ->createView(); $this->assertEquals('token', $view['csrf']->vars['value']); } public function provideBoolean() { return array( array(true), array(false), ); } /** * @dataProvider provideBoolean */ public function testValidateTokenOnSubmitIfRootAndCompound($valid) { $this->tokenManager->expects($this->once()) ->method('isTokenValid') ->with(new CsrfToken('TOKEN_ID', 'token')) ->will($this->returnValue($valid)); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->add('child', 'text') ->getForm(); $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); // Remove token from data $this->assertSame(array('child' => 'foobar'), $form->getData()); // Validate accordingly $this->assertSame($valid, $form->isValid()); } /** * @dataProvider provideBoolean */ public function testValidateTokenOnSubmitIfRootAndCompoundUsesFormNameAsIntentionByDefault($valid) { $this->tokenManager->expects($this->once()) ->method('isTokenValid') ->with(new CsrfToken('FORM_NAME', 'token')) ->will($this->returnValue($valid)); $form = $this->factory ->createNamedBuilder('FORM_NAME', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'compound' => true, )) ->add('child', 'text') ->getForm(); $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); // Remove token from data $this->assertSame(array('child' => 'foobar'), $form->getData()); // Validate accordingly $this->assertSame($valid, $form->isValid()); } /** * @dataProvider provideBoolean */ public function testValidateTokenOnSubmitIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName($valid) { $this->tokenManager->expects($this->once()) ->method('isTokenValid') ->with(new CsrfToken('Symfony\Component\Form\Extension\Core\Type\FormType', 'token')) ->will($this->returnValue($valid)); $form = $this->factory ->createNamedBuilder('', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'compound' => true, )) ->add('child', 'text') ->getForm(); $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); // Remove token from data $this->assertSame(array('child' => 'foobar'), $form->getData()); // Validate accordingly $this->assertSame($valid, $form->isValid()); } public function testFailIfRootAndCompoundAndTokenMissing() { $this->tokenManager->expects($this->never()) ->method('isTokenValid'); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->add('child', 'text') ->getForm(); $form->submit(array( 'child' => 'foobar', // token is missing )); // Remove token from data $this->assertSame(array('child' => 'foobar'), $form->getData()); // Validate accordingly $this->assertFalse($form->isValid()); } public function testDontValidateTokenIfCompoundButNoRoot() { $this->tokenManager->expects($this->never()) ->method('isTokenValid'); $form = $this->factory ->createNamedBuilder('root', 'form') ->add($this->factory ->createNamedBuilder('form', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ) ->getForm() ->get('form'); $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); } public function testDontValidateTokenIfRootButNotCompound() { $this->tokenManager->expects($this->never()) ->method('isTokenValid'); $form = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => false, )); $form->submit(array( 'csrf' => 'token', )); } public function testNoCsrfProtectionOnPrototype() { $prototypeView = $this->factory ->create('collection', null, array( 'type' => new FormTypeCsrfExtensionTest_ChildType(), 'options' => array( 'csrf_field_name' => 'csrf', ), 'prototype' => true, 'allow_add' => true, )) ->createView() ->vars['prototype']; $this->assertFalse(isset($prototypeView['csrf'])); $this->assertCount(1, $prototypeView); } public function testsTranslateCustomErrorMessage() { $this->tokenManager->expects($this->once()) ->method('isTokenValid') ->with(new CsrfToken('TOKEN_ID', 'token')) ->will($this->returnValue(false)); $this->translator->expects($this->once()) ->method('trans') ->with('Foobar') ->will($this->returnValue('[trans]Foobar[/trans]')); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_message' => 'Foobar', 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->getForm(); $form->submit(array( 'csrf' => 'token', )); $errors = $form->getErrors(); $this->assertGreaterThan(0, count($errors)); $this->assertEquals(new FormError('[trans]Foobar[/trans]'), $errors[0]); } } PK!܏##Wtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhashnu[GIF87a,D;PK!* * atest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase { private $choiceList; protected function setUp() { parent::setUp(); $this->choiceList = new SimpleChoiceList(array('' => 'Empty', 0 => 'A', 1 => 'B')); } protected function tearDown() { parent::tearDown(); $listener = null; } public function testFixRadio() { $data = '1'; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($this->choiceList, true); $listener->preSubmit($event); // Indices in SimpleChoiceList are zero-based generated integers $this->assertEquals(array(2 => '1'), $event->getData()); } public function testFixZero() { $data = '0'; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($this->choiceList, true); $listener->preSubmit($event); // Indices in SimpleChoiceList are zero-based generated integers $this->assertEquals(array(1 => '0'), $event->getData()); } public function testFixEmptyString() { $data = ''; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($this->choiceList, true); $listener->preSubmit($event); // Indices in SimpleChoiceList are zero-based generated integers $this->assertEquals(array(0 => ''), $event->getData()); } public function testConvertEmptyStringToPlaceholderIfNotFound() { $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B')); $data = ''; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($list, true); $listener->preSubmit($event); $this->assertEquals(array('placeholder' => ''), $event->getData()); } public function testDontConvertEmptyStringToPlaceholderIfNoPlaceholderUsed() { $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B')); $data = ''; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($list, false); $listener->preSubmit($event); $this->assertEquals(array(), $event->getData()); } } PK!!$$^test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase { private $dispatcher; private $factory; private $form; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->form = null; } protected function getBuilder($name = 'name') { return new FormBuilder($name, null, $this->dispatcher, $this->factory); } protected function getForm($name = 'name') { return $this->getBuilder($name)->getForm(); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } protected function getMockForm() { return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } public function testPreSetDataResizesForm() { $this->form->add($this->getForm('0')); $this->form->add($this->getForm('1')); $this->factory->expects($this->at(0)) ->method('createNamed') ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('1'))); $this->factory->expects($this->at(1)) ->method('createNamed') ->with(2, 'text', null, array('property_path' => '[2]', 'max_length' => 10, 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('2'))); $data = array(1 => 'string', 2 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array('max_length' => '10'), false, false); $listener->preSetData($event); $this->assertFalse($this->form->has('0')); $this->assertTrue($this->form->has('1')); $this->assertTrue($this->form->has('2')); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testPreSetDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSetData($event); } public function testPreSetDataDealsWithNullData() { $this->factory->expects($this->never())->method('createNamed'); $data = null; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSetData($event); } public function testPreSubmitResizesUpIfAllowAdd() { $this->form->add($this->getForm('0')); $this->factory->expects($this->once()) ->method('createNamed') ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('1'))); $data = array(0 => 'string', 1 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array('max_length' => 10), true, false); $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); $this->assertTrue($this->form->has('1')); } public function testPreSubmitResizesDownIfAllowDelete() { $this->form->add($this->getForm('0')); $this->form->add($this->getForm('1')); $data = array(0 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); $this->assertFalse($this->form->has('1')); } // fix for https://github.com/symfony/symfony/pull/493 public function testPreSubmitRemovesZeroKeys() { $this->form->add($this->getForm('0')); $data = array(); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preSubmit($event); $this->assertFalse($this->form->has('0')); } public function testPreSubmitDoesNothingIfNotAllowAddNorAllowDelete() { $this->form->add($this->getForm('0')); $this->form->add($this->getForm('1')); $data = array(0 => 'string', 2 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); $this->assertTrue($this->form->has('1')); $this->assertFalse($this->form->has('2')); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testPreSubmitRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSubmit($event); } public function testPreSubmitDealsWithNullData() { $this->form->add($this->getForm('1')); $data = null; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preSubmit($event); $this->assertFalse($this->form->has('1')); } // fixes https://github.com/symfony/symfony/pull/40 public function testPreSubmitDealsWithEmptyData() { $this->form->add($this->getForm('1')); $data = ''; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preSubmit($event); $this->assertFalse($this->form->has('1')); } public function testOnSubmitNormDataRemovesEntriesMissingInTheFormIfAllowDelete() { $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onSubmit($event); $this->assertEquals(array(1 => 'second'), $event->getData()); } public function testOnSubmitNormDataDoesNothingIfNotAllowDelete() { $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->onSubmit($event); $this->assertEquals($data, $event->getData()); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testOnSubmitNormDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->onSubmit($event); } public function testOnSubmitNormDataDealsWithNullData() { $this->form->add($this->getForm('1')); $data = null; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onSubmit($event); $this->assertEquals(array(), $event->getData()); } public function testOnSubmitDealsWithObjectBackedIteratorAggregate() { $this->form->add($this->getForm('1')); $data = new \ArrayObject(array(0 => 'first', 1 => 'second', 2 => 'third')); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onSubmit($event); $this->assertArrayNotHasKey(0, $event->getData()); $this->assertArrayNotHasKey(2, $event->getData()); } public function testOnSubmitDealsWithArrayBackedIteratorAggregate() { $this->form->add($this->getForm('1')); $data = new ArrayCollection(array(0 => 'first', 1 => 'second', 2 => 'third')); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onSubmit($event); $this->assertArrayNotHasKey(0, $event->getData()); $this->assertArrayNotHasKey(2, $event->getData()); } } PK!fk5s3 3 Xtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; class TrimListenerTest extends \PHPUnit_Framework_TestCase { public function testTrim() { $data = " Foo! "; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new TrimListener(); $filter->preSubmit($event); $this->assertEquals('Foo!', $event->getData()); } public function testTrimSkipNonStrings() { $data = 1234; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new TrimListener(); $filter->preSubmit($event); $this->assertSame(1234, $event->getData()); } /** * @dataProvider codePointProvider */ public function testTrimUtf8($chars) { if (!function_exists('mb_check_encoding')) { $this->markTestSkipped('The "mb_check_encoding" function is not available'); } $data = mb_convert_encoding(pack('H*', implode('', $chars)), 'UTF-8', 'UCS-2BE'); $data = $data."ab\ncd".$data; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new TrimListener(); $filter->preSubmit($event); $this->assertSame("ab\ncd", $event->getData(), 'TrimListener should trim character(s): '.implode(', ', $chars)); } public function codePointProvider() { return array( 'General category: Separator' => array(array('0020', '00A0', '1680', '180E', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '200A', '2028', '2029', '202F', '205F', '3000')), 'General category: Other, control' => array(array('0009', '000A', '000B', '000C', '000D', '0085')), //'General category: Other, format. ZERO WIDTH SPACE' => array(array('200B')), ); } } PK!B+Kntest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormBuilder; class MergeCollectionListenerArrayObjectTest extends MergeCollectionListenerTest { protected function getData(array $data) { return new \ArrayObject($data); } protected function getBuilder($name = 'name') { return new FormBuilder($name, '\ArrayObject', $this->dispatcher, $this->factory); } } PK!@ڦttest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\Tests\Fixtures\CustomArrayObject; use Symfony\Component\Form\FormBuilder; class MergeCollectionListenerCustomArrayObjectTest extends MergeCollectionListenerTest { protected function getData(array $data) { return new CustomArrayObject($data); } protected function getBuilder($name = 'name') { return new FormBuilder($name, 'Symfony\Component\Form\Tests\Fixtures\CustomArrayObject', $this->dispatcher, $this->factory); } } PK!Э htest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormBuilder; class MergeCollectionListenerArrayTest extends MergeCollectionListenerTest { protected function getData(array $data) { return $data; } protected function getBuilder($name = 'name') { return new FormBuilder($name, null, $this->dispatcher, $this->factory); } } PK!ggbtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase { public function testFixHttpUrl() { $data = "www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onSubmit($event); $this->assertEquals('http://www.symfony.com', $event->getData()); } public function testSkipKnownUrl() { $data = "http://www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onSubmit($event); $this->assertEquals('http://www.symfony.com', $event->getData()); } public function testSkipOtherProtocol() { $data = "ftp://www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onSubmit($event); $this->assertEquals('ftp://www.symfony.com', $event->getData()); } } PK!O&ctest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase { protected $dispatcher; protected $factory; protected $form; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->getForm('axes'); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->form = null; } abstract protected function getBuilder($name = 'name'); protected function getForm($name = 'name', $propertyPath = null) { $propertyPath = $propertyPath ?: $name; return $this->getBuilder($name)->setAttribute('property_path', $propertyPath)->getForm(); } protected function getMockForm() { return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } public function getBooleanMatrix1() { return array( array(true), array(false), ); } public function getBooleanMatrix2() { return array( array(true, true), array(true, false), array(false, true), array(false, false), ); } abstract protected function getData(array $data); /** * @dataProvider getBooleanMatrix1 */ public function testAddExtraEntriesIfAllowAdd($allowDelete) { $originalData = $this->getData(array(1 => 'second')); $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $listener = new MergeCollectionListener(true, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // The original object was modified if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // The original object matches the new object $this->assertEquals($newData, $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testAddExtraEntriesIfAllowAddDontOverwriteExistingIndices($allowDelete) { $originalData = $this->getData(array(1 => 'first')); $newData = $this->getData(array(0 => 'first', 1 => 'second')); $listener = new MergeCollectionListener(true, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // The original object was modified if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // The original object matches the new object $this->assertEquals($this->getData(array(1 => 'first', 2 => 'second')), $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testDoNothingIfNotAllowAdd($allowDelete) { $originalDataArray = array(1 => 'second'); $originalData = $this->getData($originalDataArray); $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $listener = new MergeCollectionListener(false, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // We still have the original object if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // Nothing was removed $this->assertEquals($this->getData($originalDataArray), $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testRemoveMissingEntriesIfAllowDelete($allowAdd) { $originalData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $newData = $this->getData(array(1 => 'second')); $listener = new MergeCollectionListener($allowAdd, true); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // The original object was modified if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // The original object matches the new object $this->assertEquals($newData, $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testDoNothingIfNotAllowDelete($allowAdd) { $originalDataArray = array(0 => 'first', 1 => 'second', 2 => 'third'); $originalData = $this->getData($originalDataArray); $newData = $this->getData(array(1 => 'second')); $listener = new MergeCollectionListener($allowAdd, false); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // We still have the original object if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // Nothing was removed $this->assertEquals($this->getData($originalDataArray), $event->getData()); } /** * @dataProvider getBooleanMatrix2 * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequireArrayOrTraversable($allowAdd, $allowDelete) { $newData = 'no array or traversable'; $event = new FormEvent($this->form, $newData); $listener = new MergeCollectionListener($allowAdd, $allowDelete); $listener->onSubmit($event); } public function testDealWithNullData() { $originalData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $newData = null; $listener = new MergeCollectionListener(false, false); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); $this->assertSame($originalData, $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testDealWithNullOriginalDataIfAllowAdd($allowDelete) { $originalData = null; $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $listener = new MergeCollectionListener(true, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); $this->assertSame($newData, $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testDontDealWithNullOriginalDataIfNotAllowAdd($allowDelete) { $originalData = null; $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $listener = new MergeCollectionListener(false, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); $this->assertNull($event->getData()); } } PK! Ytest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class ObjectChoiceListTest_EntityWithToString { private $property; public function __construct($property) { $this->property = $property; } public function __toString() { return $this->property; } } class ObjectChoiceListTest extends AbstractChoiceListTest { private $obj1; private $obj2; private $obj3; private $obj4; protected function setUp() { $this->obj1 = (object) array('name' => 'A'); $this->obj2 = (object) array('name' => 'B'); $this->obj3 = (object) array('name' => 'C'); $this->obj4 = (object) array('name' => 'D'); parent::setUp(); } public function testInitArray() { $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), 'name', array($this->obj2) ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array(1 => new ChoiceView($this->obj2, '1', 'B')), $this->list->getPreferredViews()); $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews()); } public function testInitNestedArray() { $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')) ), $this->list->getRemainingViews()); } public function testInitArrayWithGroupPath() { $this->obj1 = (object) array('name' => 'A', 'category' => 'Group 1'); $this->obj2 = (object) array('name' => 'B', 'category' => 'Group 1'); $this->obj3 = (object) array('name' => 'C', 'category' => 'Group 2'); $this->obj4 = (object) array('name' => 'D', 'category' => 'Group 2'); // Objects with NULL groups are not grouped $obj5 = (object) array('name' => 'E', 'category' => null); // Objects without the group property are not grouped either // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf $obj6 = (object) array('name' => 'F'); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4, $obj5, $obj6), 'name', array($this->obj2, $this->obj3), 'category' ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4, $obj5, $obj6), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3', '4', '5'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')), 4 => new ChoiceView($obj5, '4', 'E'), 5 => new ChoiceView($obj6, '5', 'F'), ), $this->list->getRemainingViews()); } /** * @expectedException \InvalidArgumentException */ public function testInitArrayWithGroupPathThrowsExceptionIfNestedArray() { $this->obj1 = (object) array('name' => 'A', 'category' => 'Group 1'); $this->obj2 = (object) array('name' => 'B', 'category' => 'Group 1'); $this->obj3 = (object) array('name' => 'C', 'category' => 'Group 2'); $this->obj4 = (object) array('name' => 'D', 'category' => 'Group 2'); new ObjectChoiceList( array( 'Group 1' => array($this->obj1, $this->obj2), 'Group 2' => array($this->obj3, $this->obj4), ), 'name', array($this->obj2, $this->obj3), 'category' ); } public function testInitArrayWithValuePath() { $this->obj1 = (object) array('name' => 'A', 'id' => 10); $this->obj2 = (object) array('name' => 'B', 'id' => 20); $this->obj3 = (object) array('name' => 'C', 'id' => 30); $this->obj4 = (object) array('name' => 'D', 'id' => 40); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), 'name', array($this->obj2, $this->obj3), null, 'id' ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('10', '20', '30', '40'), $this->list->getValues()); $this->assertEquals(array(1 => new ChoiceView($this->obj2, '20', 'B'), 2 => new ChoiceView($this->obj3, '30', 'C')), $this->list->getPreferredViews()); $this->assertEquals(array(0 => new ChoiceView($this->obj1, '10', 'A'), 3 => new ChoiceView($this->obj4, '40', 'D')), $this->list->getRemainingViews()); } public function testInitArrayUsesToString() { $this->obj1 = new ObjectChoiceListTest_EntityWithToString('A'); $this->obj2 = new ObjectChoiceListTest_EntityWithToString('B'); $this->obj3 = new ObjectChoiceListTest_EntityWithToString('C'); $this->obj4 = new ObjectChoiceListTest_EntityWithToString('D'); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4) ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 1 => new ChoiceView($this->obj2, '1', 'B'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews()); } /** * @expectedException \Symfony\Component\Form\Exception\StringCastException */ public function testInitArrayThrowsExceptionIfToStringNotFound() { $this->obj1 = new ObjectChoiceListTest_EntityWithToString('A'); $this->obj2 = new ObjectChoiceListTest_EntityWithToString('B'); $this->obj3 = (object) array('name' => 'C'); $this->obj4 = new ObjectChoiceListTest_EntityWithToString('D'); new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4) ); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { return new ObjectChoiceList( array( 'Group 1' => array($this->obj1, $this->obj2), 'Group 2' => array($this->obj3, $this->obj4), ), 'name', array($this->obj2, $this->obj3) ); } protected function getChoices() { return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); } protected function getIndices() { return array(0, 1, 2, 3); } } PK!.p))Stest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class ChoiceListTest extends AbstractChoiceListTest { private $obj1; private $obj2; private $obj3; private $obj4; protected function setUp() { $this->obj1 = new \stdClass(); $this->obj2 = new \stdClass(); $this->obj3 = new \stdClass(); $this->obj4 = new \stdClass(); parent::setUp(); } public function testInitArray() { $this->list = new ChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), array('A', 'B', 'C', 'D'), array($this->obj2) ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array(1 => new ChoiceView($this->obj2, '1', 'B')), $this->list->getPreferredViews()); $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews()); } /** * Necessary for interoperability with MongoDB cursors or ORM relations as * choices parameter. A choice itself that is an object implementing \Traversable * is not treated as hierarchical structure, but as-is. */ public function testInitNestedTraversable() { $traversableChoice = new \ArrayIterator(array($this->obj3, $this->obj4)); $this->list = new ChoiceList( new \ArrayIterator(array( 'Group' => array($this->obj1, $this->obj2), 'Not a Group' => $traversableChoice )), array( 'Group' => array('A', 'B'), 'Not a Group' => 'C', ), array($this->obj2) ); $this->assertSame(array($this->obj1, $this->obj2, $traversableChoice), $this->list->getChoices()); $this->assertSame(array('0', '1', '2'), $this->list->getValues()); $this->assertEquals(array( 'Group' => array(1 => new ChoiceView($this->obj2, '1', 'B')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group' => array(0 => new ChoiceView($this->obj1, '0', 'A')), 2 => new ChoiceView($traversableChoice, '2', 'C') ), $this->list->getRemainingViews()); } public function testInitNestedArray() { $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')) ), $this->list->getRemainingViews()); } /** * @expectedException \InvalidArgumentException */ public function testInitWithInsufficientLabels() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), array('A') ); } public function testInitWithLabelsContainingNull() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), array('A', null) ); $this->assertEquals( array(0 => new ChoiceView($this->obj1, '0', 'A'), 1 => new ChoiceView($this->obj2, '1', null)), $this->list->getRemainingViews() ); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { return new ChoiceList( array( 'Group 1' => array($this->obj1, $this->obj2), 'Group 2' => array($this->obj3, $this->obj4), ), array( 'Group 1' => array('A', 'B'), 'Group 2' => array('C', 'D'), ), array($this->obj2, $this->obj3) ); } protected function getChoices() { return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); } protected function getIndices() { return array(0, 1, 2, 3); } } PK!![[test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; /** * @author Bernhard Schussek */ abstract class AbstractChoiceListTest extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected $list; /** * @var array */ protected $choices; /** * @var array */ protected $values; /** * @var array */ protected $indices; /** * @var array */ protected $labels; /** * @var mixed */ protected $choice1; /** * @var mixed */ protected $choice2; /** * @var mixed */ protected $choice3; /** * @var mixed */ protected $choice4; /** * @var string */ protected $value1; /** * @var string */ protected $value2; /** * @var string */ protected $value3; /** * @var string */ protected $value4; /** * @var int|string */ protected $index1; /** * @var int|string */ protected $index2; /** * @var int|string */ protected $index3; /** * @var int|string */ protected $index4; /** * @var string */ protected $label1; /** * @var string */ protected $label2; /** * @var string */ protected $label3; /** * @var string */ protected $label4; protected function setUp() { parent::setUp(); $this->list = $this->createChoiceList(); $this->choices = $this->getChoices(); $this->indices = $this->getIndices(); $this->values = $this->getValues(); $this->labels = $this->getLabels(); // allow access to the individual entries without relying on their indices reset($this->choices); reset($this->indices); reset($this->values); reset($this->labels); for ($i = 1; $i <= 4; ++$i) { $this->{'choice'.$i} = current($this->choices); $this->{'index'.$i} = current($this->indices); $this->{'value'.$i} = current($this->values); $this->{'label'.$i} = current($this->labels); next($this->choices); next($this->indices); next($this->values); next($this->labels); } } public function testGetChoices() { $this->assertSame($this->choices, $this->list->getChoices()); } public function testGetValues() { $this->assertSame($this->values, $this->list->getValues()); } public function testGetIndicesForChoices() { $choices = array($this->choice1, $this->choice2); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForChoicesPreservesKeys() { $choices = array(5 => $this->choice1, 8 => $this->choice2); $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForChoicesPreservesOrder() { $choices = array($this->choice2, $this->choice1); $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForChoicesIgnoresNonExistingChoices() { $choices = array($this->choice1, $this->choice2, 'foobar'); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForChoicesEmpty() { $this->assertSame(array(), $this->list->getIndicesForChoices(array())); } public function testGetIndicesForValues() { // values and indices are always the same $values = array($this->value1, $this->value2); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); } public function testGetIndicesForValuesPreservesKeys() { // values and indices are always the same $values = array(5 => $this->value1, 8 => $this->value2); $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForValues($values)); } public function testGetIndicesForValuesPreservesOrder() { $values = array($this->value2, $this->value1); $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForValues($values)); } public function testGetIndicesForValuesIgnoresNonExistingValues() { $values = array($this->value1, $this->value2, 'foobar'); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); } public function testGetIndicesForValuesEmpty() { $this->assertSame(array(), $this->list->getIndicesForValues(array())); } public function testGetChoicesForValues() { $values = array($this->value1, $this->value2); $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); } public function testGetChoicesForValuesPreservesKeys() { $values = array(5 => $this->value1, 8 => $this->value2); $this->assertSame(array(5 => $this->choice1, 8 => $this->choice2), $this->list->getChoicesForValues($values)); } public function testGetChoicesForValuesPreservesOrder() { $values = array($this->value2, $this->value1); $this->assertSame(array($this->choice2, $this->choice1), $this->list->getChoicesForValues($values)); } public function testGetChoicesForValuesIgnoresNonExistingValues() { $values = array($this->value1, $this->value2, 'foobar'); $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); } // https://github.com/symfony/symfony/issues/3446 public function testGetChoicesForValuesEmpty() { $this->assertSame(array(), $this->list->getChoicesForValues(array())); } public function testGetValuesForChoices() { $choices = array($this->choice1, $this->choice2); $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); } public function testGetValuesForChoicesPreservesKeys() { $choices = array(5 => $this->choice1, 8 => $this->choice2); $this->assertSame(array(5 => $this->value1, 8 => $this->value2), $this->list->getValuesForChoices($choices)); } public function testGetValuesForChoicesPreservesOrder() { $choices = array($this->choice2, $this->choice1); $this->assertSame(array($this->value2, $this->value1), $this->list->getValuesForChoices($choices)); } public function testGetValuesForChoicesIgnoresNonExistingChoices() { $choices = array($this->choice1, $this->choice2, 'foobar'); $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); } public function testGetValuesForChoicesEmpty() { $this->assertSame(array(), $this->list->getValuesForChoices(array())); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ abstract protected function createChoiceList(); abstract protected function getChoices(); abstract protected function getLabels(); abstract protected function getValues(); abstract protected function getIndices(); } PK!gUI Wtest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class LazyChoiceListTest extends \PHPUnit_Framework_TestCase { private $list; protected function setUp() { parent::setUp(); $this->list = new LazyChoiceListTest_Impl(new SimpleChoiceList(array( 'a' => 'A', 'b' => 'B', 'c' => 'C', ), array('b'))); } protected function tearDown() { parent::tearDown(); $this->list = null; } public function testGetChoices() { $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getChoices()); } public function testGetValues() { $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getValues()); } public function testGetPreferredViews() { $this->assertEquals(array(1 => new ChoiceView('b', 'b', 'B')), $this->list->getPreferredViews()); } public function testGetRemainingViews() { $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews()); } public function testGetIndicesForChoices() { $choices = array('b', 'c'); $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForValues() { $values = array('b', 'c'); $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); } public function testGetChoicesForValues() { $values = array('b', 'c'); $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); } public function testGetValuesForChoices() { $choices = array('b', 'c'); $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ public function testLoadChoiceListShouldReturnChoiceList() { $list = new LazyChoiceListTest_InvalidImpl(); $list->getChoices(); } } class LazyChoiceListTest_Impl extends LazyChoiceList { private $choiceList; public function __construct($choiceList) { $this->choiceList = $choiceList; } protected function loadChoiceList() { return $this->choiceList; } } class LazyChoiceListTest_InvalidImpl extends LazyChoiceList { protected function loadChoiceList() { return new \stdClass(); } } PK!R Ytest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class SimpleChoiceListTest extends AbstractChoiceListTest { public function testInitArray() { $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C'); $this->list = new SimpleChoiceList($choices, array('b')); $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getChoices()); $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getValues()); $this->assertEquals(array(1 => new ChoiceView('b', 'b', 'B')), $this->list->getPreferredViews()); $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews()); } public function testInitNestedArray() { $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'), $this->list->getChoices()); $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView('b', 'b', 'B')), 'Group 2' => array(2 => new ChoiceView('c', 'c', 'C')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView('a', 'a', 'A')), 'Group 2' => array(3 => new ChoiceView('d', 'd', 'D')) ), $this->list->getRemainingViews()); } /** * @dataProvider dirtyValuesProvider */ public function testGetValuesForChoicesDealsWithDirtyValues($choice, $value) { $choices = array( '0' => 'Zero', '1' => 'One', '' => 'Empty', '1.23' => 'Float', 'foo' => 'Foo', 'foo10' => 'Foo 10', ); $this->list = new SimpleChoiceList($choices, array()); $this->assertSame(array($value), $this->list->getValuesForChoices(array($choice))); } public function dirtyValuesProvider() { return array( array(0, '0'), array('0', '0'), array('1', '1'), array(false, '0'), array(true, '1'), array('', ''), array(null, ''), array('1.23', '1.23'), array('foo', 'foo'), array('foo10', 'foo10'), ); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { return new SimpleChoiceList(array( 'Group 1' => array('a' => 'A', 'b' => 'B'), 'Group 2' => array('c' => 'C', 'd' => 'D'), ), array('b', 'c')); } protected function getChoices() { return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); } protected function getIndices() { return array(0, 1, 2, 3); } } PK!x`test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; class SimpleNumericChoiceListTest extends AbstractChoiceListTest { public function testGetIndicesForChoicesDealsWithNumericChoices() { // Pass choices as strings although they are integers $choices = array('0', '1'); $this->assertSame(array(0, 1), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForValuesDealsWithNumericValues() { // Pass values as strings although they are integers $values = array('0', '1'); $this->assertSame(array(0, 1), $this->list->getIndicesForValues($values)); } public function testGetChoicesForValuesDealsWithNumericValues() { // Pass values as strings although they are integers $values = array('0', '1'); $this->assertSame(array(0, 1), $this->list->getChoicesForValues($values)); } public function testGetValuesForChoicesDealsWithNumericValues() { // Pass values as strings although they are integers $values = array('0', '1'); $this->assertSame(array('0', '1'), $this->list->getValuesForChoices($values)); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { return new SimpleChoiceList(array( 'Group 1' => array(0 => 'A', 1 => 'B'), 'Group 2' => array(2 => 'C', 3 => 'D'), ), array(1, 2)); } protected function getChoices() { return array(0 => 0, 1 => 1, 2 => 2, 3 => 3); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); } protected function getIndices() { return array(0, 1, 2, 3); } } PK!?R8..[test/Form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormConfigInterface; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase { /** * @var PropertyPathMapper */ private $mapper; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $propertyAccessor; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->propertyAccessor = $this->getMock('Symfony\Component\PropertyAccess\PropertyAccessorInterface'); $this->mapper = new PropertyPathMapper($this->propertyAccessor); } /** * @param $path * @return \PHPUnit_Framework_MockObject_MockObject */ private function getPropertyPath($path) { return $this->getMockBuilder('Symfony\Component\PropertyAccess\PropertyPath') ->setConstructorArgs(array($path)) ->setMethods(array('getValue', 'setValue')) ->getMock(); } /** * @param FormConfigInterface $config * @param Boolean $synchronized * @param Boolean $submitted * @return \PHPUnit_Framework_MockObject_MockObject */ private function getForm(FormConfigInterface $config, $synchronized = true, $submitted = true) { $form = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($config)) ->setMethods(array('isSynchronized', 'isSubmitted')) ->getMock(); $form->expects($this->any()) ->method('isSynchronized') ->will($this->returnValue($synchronized)); $form->expects($this->any()) ->method('isSubmitted') ->will($this->returnValue($submitted)); return $form; } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } public function testMapDataToFormsPassesObjectRefIfByReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->once()) ->method('getValue') ->with($car, $propertyPath) ->will($this->returnValue($engine)); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $form = $this->getForm($config); $this->mapper->mapDataToForms($car, array($form)); // Can't use isIdentical() above because mocks always clone their // arguments which can't be disabled in PHPUnit 3.6 $this->assertSame($engine, $form->getData()); } public function testMapDataToFormsPassesObjectCloneIfNotByReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->once()) ->method('getValue') ->with($car, $propertyPath) ->will($this->returnValue($engine)); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(false); $config->setPropertyPath($propertyPath); $form = $this->getForm($config); $this->mapper->mapDataToForms($car, array($form)); $this->assertNotSame($engine, $form->getData()); $this->assertEquals($engine, $form->getData()); } public function testMapDataToFormsIgnoresEmptyPropertyPath() { $car = new \stdClass(); $config = new FormConfigBuilder(null, '\stdClass', $this->dispatcher); $config->setByReference(true); $form = $this->getForm($config); $this->assertNull($form->getPropertyPath()); $this->mapper->mapDataToForms($car, array($form)); $this->assertNull($form->getData()); } public function testMapDataToFormsIgnoresUnmapped() { $car = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('getValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setMapped(false); $config->setPropertyPath($propertyPath); $form = $this->getForm($config); $this->mapper->mapDataToForms($car, array($form)); $this->assertNull($form->getData()); } public function testMapDataToFormsSetsDefaultDataIfPassedDataIsNull() { $default = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('getValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($default); $form = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($config)) ->setMethods(array('setData')) ->getMock(); $form->expects($this->once()) ->method('setData') ->with($default); $this->mapper->mapDataToForms(null, array($form)); } public function testMapDataToFormsSetsDefaultDataIfPassedDataIsEmptyArray() { $default = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('getValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($default); $form = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($config)) ->setMethods(array('setData')) ->getMock(); $form->expects($this->once()) ->method('setData') ->with($default); $this->mapper->mapDataToForms(array(), array($form)); } public function testMapFormsToDataWritesBackIfNotByReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->once()) ->method('setValue') ->with($car, $propertyPath, $engine); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(false); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataWritesBackIfByReferenceButNoReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->once()) ->method('setValue') ->with($car, $propertyPath, $engine); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataWritesBackIfByReferenceAndReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); // $car already contains the reference of $engine $this->propertyAccessor->expects($this->once()) ->method('getValue') ->with($car, $propertyPath) ->will($this->returnValue($engine)); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresUnmapped() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $config->setMapped(false); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresUnsubmittedForms() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config, true, false); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresEmptyData() { $car = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData(null); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresUnsynchronized() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config, false); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresDisabled() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $config->setDisabled(true); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } } PK!4ftest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer; class ChoiceToValueTransformerTest extends \PHPUnit_Framework_TestCase { protected $transformer; protected function setUp() { $list = new SimpleChoiceList(array('' => 'A', 0 => 'B', 1 => 'C')); $this->transformer = new ChoiceToValueTransformer($list); } protected function tearDown() { $this->transformer = null; } public function transformProvider() { return array( // more extensive test set can be found in FormUtilTest array(0, '0'), array(false, '0'), array('', ''), ); } /** * @dataProvider transformProvider */ public function testTransform($in, $out) { $this->assertSame($out, $this->transformer->transform($in)); } public function reverseTransformProvider() { return array( // values are expected to be valid choice keys already and stay // the same array('0', 0), array('', null), array(null, null), ); } /** * @dataProvider reverseTransformProvider */ public function testReverseTransform($in, $out) { $this->assertSame($out, $this->transformer->reverseTransform($in)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsScalar() { $this->transformer->reverseTransform(array()); } } PK!qtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class PercentToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } public function testTransform() { $transformer = new PercentToLocalizedStringTransformer(); $this->assertEquals('10', $transformer->transform(0.1)); $this->assertEquals('15', $transformer->transform(0.15)); $this->assertEquals('12', $transformer->transform(0.1234)); $this->assertEquals('200', $transformer->transform(2)); } public function testTransformEmpty() { $transformer = new PercentToLocalizedStringTransformer(); $this->assertEquals('', $transformer->transform(null)); } public function testTransformWithInteger() { $transformer = new PercentToLocalizedStringTransformer(null, 'integer'); $this->assertEquals('0', $transformer->transform(0.1)); $this->assertEquals('1', $transformer->transform(1)); $this->assertEquals('15', $transformer->transform(15)); $this->assertEquals('16', $transformer->transform(15.9)); } public function testTransformWithPrecision() { $transformer = new PercentToLocalizedStringTransformer(2); $this->assertEquals('12,34', $transformer->transform(0.1234)); } public function testReverseTransform() { $transformer = new PercentToLocalizedStringTransformer(); $this->assertEquals(0.1, $transformer->reverseTransform('10')); $this->assertEquals(0.15, $transformer->reverseTransform('15')); $this->assertEquals(0.12, $transformer->reverseTransform('12')); $this->assertEquals(2, $transformer->reverseTransform('200')); } public function testReverseTransformEmpty() { $transformer = new PercentToLocalizedStringTransformer(); $this->assertNull($transformer->reverseTransform('')); } public function testReverseTransformWithInteger() { $transformer = new PercentToLocalizedStringTransformer(null, 'integer'); $this->assertEquals(10, $transformer->reverseTransform('10')); $this->assertEquals(15, $transformer->reverseTransform('15')); $this->assertEquals(12, $transformer->reverseTransform('12')); $this->assertEquals(200, $transformer->reverseTransform('200')); } public function testReverseTransformWithPrecision() { $transformer = new PercentToLocalizedStringTransformer(2); $this->assertEquals(0.1234, $transformer->reverseTransform('12,34')); } public function testTransformExpectsNumeric() { $transformer = new PercentToLocalizedStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->transform('foo'); } public function testReverseTransformExpectsString() { $transformer = new PercentToLocalizedStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->reverseTransform(1); } } PK!Ws**rtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase { protected $dateTime; protected $dateTimeWithoutSeconds; protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); $this->dateTime = new \DateTime('2010-02-03 04:05:06 UTC'); $this->dateTimeWithoutSeconds = new \DateTime('2010-02-03 04:05:00 UTC'); } protected function tearDown() { $this->dateTime = null; $this->dateTimeWithoutSeconds = null; } public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { if ($expected instanceof \DateTime && $actual instanceof \DateTime) { $expected = $expected->format('c'); $actual = $actual->format('c'); } parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); } public function dataProvider() { return array( array(\IntlDateFormatter::SHORT, null, null, '03.02.10 04:05', '2010-02-03 04:05:00 UTC'), array(\IntlDateFormatter::MEDIUM, null, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'), array(\IntlDateFormatter::LONG, null, null, '03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'), array(\IntlDateFormatter::FULL, null, null, 'Mittwoch, 03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'), array(\IntlDateFormatter::SHORT, \IntlDateFormatter::NONE, null, '03.02.10', '2010-02-03 00:00:00 UTC'), array(\IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE, null, '03.02.2010', '2010-02-03 00:00:00 UTC'), array(\IntlDateFormatter::LONG, \IntlDateFormatter::NONE, null, '03. Februar 2010', '2010-02-03 00:00:00 UTC'), array(\IntlDateFormatter::FULL, \IntlDateFormatter::NONE, null, 'Mittwoch, 03. Februar 2010', '2010-02-03 00:00:00 UTC'), array(null, \IntlDateFormatter::SHORT, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'), array(null, \IntlDateFormatter::MEDIUM, null, '03.02.2010 04:05:06', '2010-02-03 04:05:06 UTC'), array(null, \IntlDateFormatter::LONG, null, '03.02.2010 04:05:06 GMT', '2010-02-03 04:05:06 UTC'), // see below for extra test case for time format FULL array(\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT, null, '04:05', '1970-01-01 04:05:00 UTC'), array(\IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM, null, '04:05:06', '1970-01-01 04:05:06 UTC'), array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, '04:05:06 GMT', '1970-01-01 04:05:06 UTC'), array(null, null, 'yyyy-MM-dd HH:mm:00', '2010-02-03 04:05:00', '2010-02-03 04:05:00 UTC'), array(null, null, 'yyyy-MM-dd HH:mm', '2010-02-03 04:05', '2010-02-03 04:05:00 UTC'), array(null, null, 'yyyy-MM-dd HH', '2010-02-03 04', '2010-02-03 04:00:00 UTC'), array(null, null, 'yyyy-MM-dd', '2010-02-03', '2010-02-03 00:00:00 UTC'), array(null, null, 'yyyy-MM', '2010-02', '2010-02-01 00:00:00 UTC'), array(null, null, 'yyyy', '2010', '2010-01-01 00:00:00 UTC'), array(null, null, 'dd-MM-yyyy', '03-02-2010', '2010-02-03 00:00:00 UTC'), array(null, null, 'HH:mm:ss', '04:05:06', '1970-01-01 04:05:06 UTC'), array(null, null, 'HH:mm:00', '04:05:00', '1970-01-01 04:05:00 UTC'), array(null, null, 'HH:mm', '04:05', '1970-01-01 04:05:00 UTC'), array(null, null, 'HH', '04', '1970-01-01 04:00:00 UTC'), ); } /** * @dataProvider dataProvider */ public function testTransform($dateFormat, $timeFormat, $pattern, $output, $input) { $transformer = new DateTimeToLocalizedStringTransformer( 'UTC', 'UTC', $dateFormat, $timeFormat, \IntlDateFormatter::GREGORIAN, $pattern ); $input = new \DateTime($input); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformFullTime() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); $this->assertEquals('03.02.2010 04:05:06 GMT', $transformer->transform($this->dateTime)); } public function testTransformToDifferentLocale() { \Locale::setDefault('en_US'); $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); $this->assertEquals('Feb 3, 2010, 4:05 AM', $transformer->transform($this->dateTime)); } public function testTransformEmpty() { $transformer = new DateTimeToLocalizedStringTransformer(); $this->assertSame('', $transformer->transform(null)); } public function testTransformWithDifferentTimezones() { $transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong'); $input = new \DateTime('2010-02-03 04:05:06 America/New_York'); $dateTime = clone $input; $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertEquals($dateTime->format('d.m.Y H:i'), $transformer->transform($input)); } public function testTransformWithDifferentPatterns() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss'); $this->assertEquals('02*2010*03 04|05|06', $transformer->transform($this->dateTime)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformRequiresValidDateTime() { $transformer = new DateTimeToLocalizedStringTransformer(); $transformer->transform('2010-01-01'); } public function testTransformWrapsIntlErrors() { $transformer = new DateTimeToLocalizedStringTransformer(); // HOW TO REPRODUCE? //$this->setExpectedException('Symfony\Component\Form\Extension\Core\DataTransformer\Transdate_formationFailedException'); //$transformer->transform(1.5); } /** * @dataProvider dataProvider */ public function testReverseTransform($dateFormat, $timeFormat, $pattern, $input, $output) { $transformer = new DateTimeToLocalizedStringTransformer( 'UTC', 'UTC', $dateFormat, $timeFormat, \IntlDateFormatter::GREGORIAN, $pattern ); $output = new \DateTime($output); $this->assertEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformFullTime() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('03.02.2010 04:05:06 GMT+00:00')); } public function testReverseTransformFromDifferentLocale() { \Locale::setDefault('en_US'); $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010, 04:05 AM')); } public function testReverseTransformWithDifferentTimezones() { $transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong'); $dateTime = new \DateTime('2010-02-03 04:05:00 Asia/Hong_Kong'); $dateTime->setTimezone(new \DateTimeZone('America/New_York')); $this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('03.02.2010 04:05')); } public function testReverseTransformWithDifferentPatterns() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss'); $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('02*2010*03 04|05|06')); } public function testReverseTransformEmpty() { $transformer = new DateTimeToLocalizedStringTransformer(); $this->assertNull($transformer->reverseTransform('')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresString() { $transformer = new DateTimeToLocalizedStringTransformer(); $transformer->reverseTransform(12345); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWrapsIntlErrors() { $transformer = new DateTimeToLocalizedStringTransformer(); $transformer->reverseTransform('12345'); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testValidateDateFormatOption() { new DateTimeToLocalizedStringTransformer(null, null, 'foobar'); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testValidateTimeFormatOption() { new DateTimeToLocalizedStringTransformer(null, null, null, 'foobar'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNonExistingDate() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::SHORT); $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('31.04.10 04:05')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformOutOfTimestampRange() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); $transformer->reverseTransform('1789-07-14'); } } PK!Ub,,Ztest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; abstract class DateTimeTestCase extends \PHPUnit_Framework_TestCase { public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) { self::assertEquals($expected->format('c'), $actual->format('c')); } } PK!}! ! ltest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; class DateTimeToTimestampTransformerTest extends DateTimeTestCase { public function testTransform() { $transformer = new DateTimeToTimestampTransformer('UTC', 'UTC'); $input = new \DateTime('2010-02-03 04:05:06 UTC'); $output = $input->format('U'); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformEmpty() { $transformer = new DateTimeToTimestampTransformer(); $this->assertNull($transformer->transform(null)); } public function testTransformWithDifferentTimezones() { $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York'); $input = new \DateTime('2010-02-03 04:05:06 America/New_York'); $output = $input->format('U'); $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformFromDifferentTimezone() { $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'UTC'); $input = new \DateTime('2010-02-03 04:05:06 Asia/Hong_Kong'); $dateTime = clone $input; $dateTime->setTimezone(new \DateTimeZone('UTC')); $output = $dateTime->format('U'); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformExpectsDateTime() { $transformer = new DateTimeToTimestampTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->transform('1234'); } public function testReverseTransform() { $reverseTransformer = new DateTimeToTimestampTransformer('UTC', 'UTC'); $output = new \DateTime('2010-02-03 04:05:06 UTC'); $input = $output->format('U'); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } public function testReverseTransformEmpty() { $reverseTransformer = new DateTimeToTimestampTransformer(); $this->assertNull($reverseTransformer->reverseTransform(null)); } public function testReverseTransformWithDifferentTimezones() { $reverseTransformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York'); $output = new \DateTime('2010-02-03 04:05:06 America/New_York'); $input = $output->format('U'); $output->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } public function testReverseTransformExpectsValidTimestamp() { $reverseTransformer = new DateTimeToTimestampTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $reverseTransformer->reverseTransform('2010-2010-2010'); } } PK!=C?C?htest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; class DateTimeToArrayTransformerTest extends DateTimeTestCase { public function testTransform() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC'); $input = new \DateTime('2010-02-03 04:05:06 UTC'); $output = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', ); $this->assertSame($output, $transformer->transform($input)); } public function testTransformEmpty() { $transformer = new DateTimeToArrayTransformer(); $output = array( 'year' => '', 'month' => '', 'day' => '', 'hour' => '', 'minute' => '', 'second' => '', ); $this->assertSame($output, $transformer->transform(null)); } public function testTransformEmptyWithFields() { $transformer = new DateTimeToArrayTransformer(null, null, array('year', 'minute', 'second')); $output = array( 'year' => '', 'minute' => '', 'second' => '', ); $this->assertSame($output, $transformer->transform(null)); } public function testTransformWithFields() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC', array('year', 'month', 'minute', 'second')); $input = new \DateTime('2010-02-03 04:05:06 UTC'); $output = array( 'year' => '2010', 'month' => '2', 'minute' => '5', 'second' => '6', ); $this->assertSame($output, $transformer->transform($input)); } public function testTransformWithPadding() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC', null, true); $input = new \DateTime('2010-02-03 04:05:06 UTC'); $output = array( 'year' => '2010', 'month' => '02', 'day' => '03', 'hour' => '04', 'minute' => '05', 'second' => '06', ); $this->assertSame($output, $transformer->transform($input)); } public function testTransformDifferentTimezones() { $transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong'); $input = new \DateTime('2010-02-03 04:05:06 America/New_York'); $dateTime = new \DateTime('2010-02-03 04:05:06 America/New_York'); $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $output = array( 'year' => (string) (int) $dateTime->format('Y'), 'month' => (string) (int) $dateTime->format('m'), 'day' => (string) (int) $dateTime->format('d'), 'hour' => (string) (int) $dateTime->format('H'), 'minute' => (string) (int) $dateTime->format('i'), 'second' => (string) (int) $dateTime->format('s'), ); $this->assertSame($output, $transformer->transform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformRequiresDateTime() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform('12345'); } public function testReverseTransform() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC'); $input = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', ); $output = new \DateTime('2010-02-03 04:05:06 UTC'); $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformWithSomeZero() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC'); $input = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '0', 'second' => '0', ); $output = new \DateTime('2010-02-03 04:00:00 UTC'); $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformCompletelyEmpty() { $transformer = new DateTimeToArrayTransformer(); $input = array( 'year' => '', 'month' => '', 'day' => '', 'hour' => '', 'minute' => '', 'second' => '', ); $this->assertNull($transformer->reverseTransform($input)); } public function testReverseTransformCompletelyEmptySubsetOfFields() { $transformer = new DateTimeToArrayTransformer(null, null, array('year', 'month', 'day')); $input = array( 'year' => '', 'month' => '', 'day' => '', ); $this->assertNull($transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyYear() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyMonth() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyDay() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyHour() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyMinute() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptySecond() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', )); } public function testReverseTransformNull() { $transformer = new DateTimeToArrayTransformer(); $this->assertNull($transformer->reverseTransform(null)); } public function testReverseTransformDifferentTimezones() { $transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong'); $input = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', ); $output = new \DateTime('2010-02-03 04:05:06 Asia/Hong_Kong'); $output->setTimezone(new \DateTimeZone('America/New_York')); $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformToDifferentTimezone() { $transformer = new DateTimeToArrayTransformer('Asia/Hong_Kong', 'UTC'); $input = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', ); $output = new \DateTime('2010-02-03 04:05:06 UTC'); $output->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresArray() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform('12345'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeYear() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '-1', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeMonth() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '-1', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeDay() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '-1', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeHour() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '-1', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeMinute() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '-1', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeSecond() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '-1', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithInvalidMonth() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '13', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithInvalidDay() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '31', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithStringDay() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => 'bazinga', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithStringMonth() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => 'bazinga', 'day' => '31', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithStringYear() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => 'bazinga', 'month' => '2', 'day' => '31', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithEmptyStringHour() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '31', 'hour' => '', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithEmptyStringMinute() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '31', 'hour' => '4', 'minute' => '', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithEmptyStringSecond() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '31', 'hour' => '4', 'minute' => '5', 'second' => '', )); } } PK!etest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; class ArrayToPartsTransformerTest extends \PHPUnit_Framework_TestCase { private $transformer; protected function setUp() { $this->transformer = new ArrayToPartsTransformer(array( 'first' => array('a', 'b', 'c'), 'second' => array('d', 'e', 'f'), )); } protected function tearDown() { $this->transformer = null; } public function testTransform() { $input = array( 'a' => '1', 'b' => '2', 'c' => '3', 'd' => '4', 'e' => '5', 'f' => '6', ); $output = array( 'first' => array( 'a' => '1', 'b' => '2', 'c' => '3', ), 'second' => array( 'd' => '4', 'e' => '5', 'f' => '6', ), ); $this->assertSame($output, $this->transformer->transform($input)); } public function testTransformEmpty() { $output = array( 'first' => null, 'second' => null, ); $this->assertSame($output, $this->transformer->transform(null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformRequiresArray() { $this->transformer->transform('12345'); } public function testReverseTransform() { $input = array( 'first' => array( 'a' => '1', 'b' => '2', 'c' => '3', ), 'second' => array( 'd' => '4', 'e' => '5', 'f' => '6', ), ); $output = array( 'a' => '1', 'b' => '2', 'c' => '3', 'd' => '4', 'e' => '5', 'f' => '6', ); $this->assertSame($output, $this->transformer->reverseTransform($input)); } public function testReverseTransformCompletelyEmpty() { $input = array( 'first' => '', 'second' => '', ); $this->assertNull($this->transformer->reverseTransform($input)); } public function testReverseTransformCompletelyNull() { $input = array( 'first' => null, 'second' => null, ); $this->assertNull($this->transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyNull() { $input = array( 'first' => array( 'a' => '1', 'b' => '2', 'c' => '3', ), 'second' => null, ); $this->transformer->reverseTransform($input); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresArray() { $this->transformer->reverseTransform('12345'); } } PK!\Rbtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; class DataTransformerChainTest extends \PHPUnit_Framework_TestCase { public function testTransform() { $transformer1 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); $transformer1->expects($this->once()) ->method('transform') ->with($this->identicalTo('foo')) ->will($this->returnValue('bar')); $transformer2 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); $transformer2->expects($this->once()) ->method('transform') ->with($this->identicalTo('bar')) ->will($this->returnValue('baz')); $chain = new DataTransformerChain(array($transformer1, $transformer2)); $this->assertEquals('baz', $chain->transform('foo')); } public function testReverseTransform() { $transformer2 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); $transformer2->expects($this->once()) ->method('reverseTransform') ->with($this->identicalTo('foo')) ->will($this->returnValue('bar')); $transformer1 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); $transformer1->expects($this->once()) ->method('reverseTransform') ->with($this->identicalTo('bar')) ->will($this->returnValue('baz')); $chain = new DataTransformerChain(array($transformer1, $transformer2)); $this->assertEquals('baz', $chain->reverseTransform('foo')); } } PK!6htest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer; class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase { const TRUE_VALUE = '1'; /** * @var BooleanToStringTransformer */ protected $transformer; protected function setUp() { $this->transformer = new BooleanToStringTransformer(self::TRUE_VALUE); } protected function tearDown() { $this->transformer = null; } public function testTransform() { $this->assertEquals(self::TRUE_VALUE, $this->transformer->transform(true)); $this->assertNull($this->transformer->transform(false)); } // https://github.com/symfony/symfony/issues/8989 public function testTransformAcceptsNull() { $this->assertNull($this->transformer->transform(null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformFailsIfString() { $this->transformer->transform('1'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformFailsIfInteger() { $this->transformer->reverseTransform(1); } public function testReverseTransform() { $this->assertTrue($this->transformer->reverseTransform(self::TRUE_VALUE)); $this->assertTrue($this->transformer->reverseTransform('foobar')); $this->assertTrue($this->transformer->reverseTransform('')); $this->assertFalse($this->transformer->reverseTransform(null)); } } PK!Y@zjjotest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class MoneyToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } public function testTransform() { $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); $this->assertEquals('1,23', $transformer->transform(123)); } public function testTransformExpectsNumeric() { $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->transform('abcd'); } public function testTransformEmpty() { $transformer = new MoneyToLocalizedStringTransformer(); $this->assertSame('', $transformer->transform(null)); } public function testReverseTransform() { $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); $this->assertEquals(123, $transformer->reverseTransform('1,23')); } public function testReverseTransformExpectsString() { $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->reverseTransform(12345); } public function testReverseTransformEmpty() { $transformer = new MoneyToLocalizedStringTransformer(); $this->assertNull($transformer->reverseTransform('')); } } PK!]e"jtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; class DateTimeToRfc3339TransformerTest extends DateTimeTestCase { protected $dateTime; protected $dateTimeWithoutSeconds; protected function setUp() { parent::setUp(); $this->dateTime = new \DateTime('2010-02-03 04:05:06 UTC'); $this->dateTimeWithoutSeconds = new \DateTime('2010-02-03 04:05:00 UTC'); } protected function tearDown() { $this->dateTime = null; $this->dateTimeWithoutSeconds = null; } public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE) { if ($expected instanceof \DateTime && $actual instanceof \DateTime) { $expected = $expected->format('c'); $actual = $actual->format('c'); } parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); } public function allProvider() { return array( array('UTC', 'UTC', '2010-02-03 04:05:06 UTC', '2010-02-03T04:05:06Z'), array('UTC', 'UTC', null, ''), array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:06 America/New_York', '2010-02-03T17:05:06+08:00'), array('America/New_York', 'Asia/Hong_Kong', null, ''), array('UTC', 'Asia/Hong_Kong', '2010-02-03 04:05:06 UTC', '2010-02-03T12:05:06+08:00'), array('America/New_York', 'UTC', '2010-02-03 04:05:06 America/New_York', '2010-02-03T09:05:06Z'), ); } public function transformProvider() { return $this->allProvider(); } public function reverseTransformProvider() { return array_merge($this->allProvider(), array( // format without seconds, as appears in some browsers array('UTC', 'UTC', '2010-02-03 04:05:00 UTC', '2010-02-03T04:05Z'), array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:00 America/New_York', '2010-02-03T17:05+08:00'), array('Europe/Amsterdam', 'Europe/Amsterdam', '2013-08-21 10:30:00 Europe/Amsterdam', '2013-08-21T08:30:00Z') )); } /** * @dataProvider transformProvider */ public function testTransform($fromTz, $toTz, $from, $to) { $transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz); $this->assertSame($to, $transformer->transform(null !== $from ? new \DateTime($from) : null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformRequiresValidDateTime() { $transformer = new DateTimeToRfc3339Transformer(); $transformer->transform('2010-01-01'); } /** * @dataProvider reverseTransformProvider */ public function testReverseTransform($toTz, $fromTz, $to, $from) { $transformer = new DateTimeToRfc3339Transformer($toTz, $fromTz); if (null !== $to) { $this->assertDateTimeEquals(new \DateTime($to), $transformer->reverseTransform($from)); } else { $this->assertSame($to, $transformer->reverseTransform($from)); } } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresString() { $transformer = new DateTimeToRfc3339Transformer(); $transformer->reverseTransform(12345); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNonExistingDate() { $transformer = new DateTimeToRfc3339Transformer('UTC', 'UTC'); $transformer->reverseTransform('2010-04-31T04:05Z'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsValidDateString() { $transformer = new DateTimeToRfc3339Transformer('UTC', 'UTC'); $transformer->reverseTransform('2010-2010-2010'); } } PK!Nz.z.qtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class IntegerToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } public function transformWithRoundingProvider() { return array( // towards positive infinity (1.6 -> 2, -1.6 -> -1) array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING), array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING), array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING), // towards negative infinity (1.6 -> 1, -1.6 -> -2) array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR), array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR), array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR), // away from zero (1.6 -> 2, -1.6 -> 2) array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_UP), array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_UP), array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP), array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP), // towards zero (1.6 -> 1, -1.6 -> -1) array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), // round halves (.5) to the next even number array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1233.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1232.5, '1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1233.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1232.5, '-1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), // round halves (.5) away from zero array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), // round halves (.5) towards zero array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), ); } /** * @dataProvider transformWithRoundingProvider */ public function testTransformWithRounding($input, $output, $roundingMode) { $transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode); $this->assertEquals($output, $transformer->transform($input)); } public function testReverseTransform() { $transformer = new IntegerToLocalizedStringTransformer(); $this->assertEquals(1, $transformer->reverseTransform('1')); $this->assertEquals(1, $transformer->reverseTransform('1,5')); $this->assertEquals(1234, $transformer->reverseTransform('1234,5')); $this->assertEquals(12345, $transformer->reverseTransform('12345,912')); } public function testReverseTransformEmpty() { $transformer = new IntegerToLocalizedStringTransformer(); $this->assertNull($transformer->reverseTransform('')); } public function testReverseTransformWithGrouping() { $transformer = new IntegerToLocalizedStringTransformer(null, true); $this->assertEquals(1234, $transformer->reverseTransform('1.234,5')); $this->assertEquals(12345, $transformer->reverseTransform('12.345,912')); $this->assertEquals(1234, $transformer->reverseTransform('1234,5')); $this->assertEquals(12345, $transformer->reverseTransform('12345,912')); } public function reverseTransformWithRoundingProvider() { return array( // towards positive infinity (1.6 -> 2, -1.6 -> -1) array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING), array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING), array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING), // towards negative infinity (1.6 -> 1, -1.6 -> -2) array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR), array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR), array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR), // away from zero (1.6 -> 2, -1.6 -> 2) array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_UP), array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_UP), array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_UP), array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_UP), // towards zero (1.6 -> 1, -1.6 -> -1) array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), // round halves (.5) to the next even number array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('1233,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('1232,5', 1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1233,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1232,5', -1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), // round halves (.5) away from zero array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), // round halves (.5) towards zero array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), ); } /** * @dataProvider reverseTransformWithRoundingProvider */ public function testReverseTransformWithRounding($input, $output, $roundingMode) { $transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode); $this->assertEquals($output, $transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsString() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform(1); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsValidNumber() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNaN() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('NaN'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNaN2() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('nan'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsInfinity() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('∞'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNegativeInfinity() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('-∞'); } } PK!`nonoptest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } public function provideTransformations() { return array( array(null, '', 'de_AT'), array(1, '1', 'de_AT'), array(1.5, '1,5', 'de_AT'), array(1234.5, '1234,5', 'de_AT'), array(12345.912, '12345,912', 'de_AT'), array(1234.5, '1234,5', 'ru'), array(1234.5, '1234,5', 'fi'), ); } /** * @dataProvider provideTransformations */ public function testTransform($from, $to, $locale) { \Locale::setDefault($locale); $transformer = new NumberToLocalizedStringTransformer(); $this->assertSame($to, $transformer->transform($from)); } public function provideTransformationsWithGrouping() { return array( array(1234.5, '1.234,5', 'de_AT'), array(12345.912, '12.345,912', 'de_AT'), array(1234.5, '1 234,5', 'fr'), array(1234.5, '1 234,5', 'ru'), array(1234.5, '1 234,5', 'fi'), ); } /** * @dataProvider provideTransformationsWithGrouping */ public function testTransformWithGrouping($from, $to, $locale) { \Locale::setDefault($locale); $transformer = new NumberToLocalizedStringTransformer(null, true); $this->assertSame($to, $transformer->transform($from)); } public function testTransformWithPrecision() { $transformer = new NumberToLocalizedStringTransformer(2); $this->assertEquals('1234,50', $transformer->transform(1234.5)); $this->assertEquals('678,92', $transformer->transform(678.916)); } public function transformWithRoundingProvider() { return array( // towards positive infinity (1.6 -> 2, -1.6 -> -1) array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING), // towards negative infinity (1.6 -> 1, -1.6 -> -2) array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR), // away from zero (1.6 -> 2, -1.6 -> 2) array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_UP), array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_UP), array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_UP), array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_UP), array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_UP), array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_UP), array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP), array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP), // towards zero (1.6 -> 1, -1.6 -> -1) array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), // round halves (.5) to the next even number array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, 1233.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, 1232.5, '1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1233.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1232.5, '-1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.35, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.25, '123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.35, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.25, '-123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), // round halves (.5) away from zero array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP), // round halves (.5) towards zero array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), ); } /** * @dataProvider transformWithRoundingProvider */ public function testTransformWithRounding($precision, $input, $output, $roundingMode) { $transformer = new NumberToLocalizedStringTransformer($precision, null, $roundingMode); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformDoesNotRoundIfNoPrecision() { $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN); $this->assertEquals('1234,547', $transformer->transform(1234.547)); } /** * @dataProvider provideTransformations */ public function testReverseTransform($to, $from, $locale) { \Locale::setDefault($locale); $transformer = new NumberToLocalizedStringTransformer(); $this->assertEquals($to, $transformer->reverseTransform($from)); } /** * @dataProvider provideTransformationsWithGrouping */ public function testReverseTransformWithGrouping($to, $from, $locale) { \Locale::setDefault($locale); $transformer = new NumberToLocalizedStringTransformer(null, true); $this->assertEquals($to, $transformer->reverseTransform($from)); } // https://github.com/symfony/symfony/issues/7609 public function testReverseTransformWithGroupingAndFixedSpaces() { if (!extension_loaded('mbstring')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } \Locale::setDefault('ru'); $transformer = new NumberToLocalizedStringTransformer(null, true); $this->assertEquals(1234.5, $transformer->reverseTransform("1\xc2\xa0234,5")); } public function testReverseTransformWithGroupingButWithoutGroupSeparator() { $transformer = new NumberToLocalizedStringTransformer(null, true); // omit group separator $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(12345.912, $transformer->reverseTransform('12345,912')); } public function reverseTransformWithRoundingProvider() { return array( // towards positive infinity (1.6 -> 2, -1.6 -> -1) array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING), // towards negative infinity (1.6 -> 1, -1.6 -> -2) array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR), // away from zero (1.6 -> 2, -1.6 -> 2) array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_UP), array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_UP), array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_UP), array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_UP), array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_UP), array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_UP), array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_UP), array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_UP), // towards zero (1.6 -> 1, -1.6 -> -1) array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), // round halves (.5) to the next even number array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '1233,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '1232,5', 1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1233,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1232,5', -1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,35', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,25', 123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,35', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,25', -123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), // round halves (.5) away from zero array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP), // round halves (.5) towards zero array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), ); } /** * @dataProvider reverseTransformWithRoundingProvider */ public function testReverseTransformWithRounding($precision, $input, $output, $roundingMode) { $transformer = new NumberToLocalizedStringTransformer($precision, null, $roundingMode); $this->assertEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformDoesNotRoundIfNoPrecision() { $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN); $this->assertEquals(1234.547, $transformer->reverseTransform('1234,547')); } public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() { \Locale::setDefault('fr'); $transformer = new NumberToLocalizedStringTransformer(null, true); // completely valid format $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); // accept dots $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); // omit group separator $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() { $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1.234.5'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep() { $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1234.5'); } public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsDotButNoGroupingUsed() { \Locale::setDefault('fr'); $transformer = new NumberToLocalizedStringTransformer(); $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); } public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma() { \Locale::setDefault('bg'); $transformer = new NumberToLocalizedStringTransformer(null, true); // completely valid format $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); // accept commas $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); // omit group separator $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma() { \Locale::setDefault('en'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1,234,5'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsCommaWithNoGroupSep() { \Locale::setDefault('en'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1234,5'); } public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsCommaButNoGroupingUsed() { \Locale::setDefault('en'); $transformer = new NumberToLocalizedStringTransformer(); $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformExpectsNumeric() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->transform('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsString() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform(1); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsValidNumber() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @link https://github.com/symfony/symfony/issues/3161 */ public function testReverseTransformDisallowsNaN() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('NaN'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNaN2() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('nan'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsInfinity() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('∞'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsInfinity2() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('∞,123'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNegativeInfinity() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('-∞'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsLeadingExtraCharacters() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('foo123'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo3" */ public function testReverseTransformDisallowsCenteredExtraCharacters() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('12foo3'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo8" */ public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte() { if (!extension_loaded('mbstring')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } \Locale::setDefault('ru'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform("12\xc2\xa0345,67foo8"); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo8" */ public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage() { if (!extension_loaded('mbstring')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } \Locale::setDefault('ru'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform("12\xc2\xa0345,67foo8 \xc2\xa0\t"); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo" */ public function testReverseTransformDisallowsTrailingExtraCharacters() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('123foo'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo" */ public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte() { if (!extension_loaded('mbstring')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } \Locale::setDefault('ru'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform("12\xc2\xa0345,678foo"); } } PK!?+< < jtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer; class ValueToDuplicatesTransformerTest extends \PHPUnit_Framework_TestCase { private $transformer; protected function setUp() { $this->transformer = new ValueToDuplicatesTransformer(array('a', 'b', 'c')); } protected function tearDown() { $this->transformer = null; } public function testTransform() { $output = array( 'a' => 'Foo', 'b' => 'Foo', 'c' => 'Foo', ); $this->assertSame($output, $this->transformer->transform('Foo')); } public function testTransformEmpty() { $output = array( 'a' => null, 'b' => null, 'c' => null, ); $this->assertSame($output, $this->transformer->transform(null)); } public function testReverseTransform() { $input = array( 'a' => 'Foo', 'b' => 'Foo', 'c' => 'Foo', ); $this->assertSame('Foo', $this->transformer->reverseTransform($input)); } public function testReverseTransformCompletelyEmpty() { $input = array( 'a' => '', 'b' => '', 'c' => '', ); $this->assertNull($this->transformer->reverseTransform($input)); } public function testReverseTransformCompletelyNull() { $input = array( 'a' => null, 'b' => null, 'c' => null, ); $this->assertNull($this->transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyNull() { $input = array( 'a' => 'Foo', 'b' => 'Foo', 'c' => null, ); $this->transformer->reverseTransform($input); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDifferences() { $input = array( 'a' => 'Foo', 'b' => 'Bar', 'c' => 'Foo', ); $this->transformer->reverseTransform($input); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresArray() { $this->transformer->reverseTransform('12345'); } } PK!fJetest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; class BaseDateTimeTransformerTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException * @expectedExceptionMessage this_timezone_does_not_exist */ public function testConstructFailsIfInputTimezoneIsInvalid() { $this->getMock( 'Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer', array(), array('this_timezone_does_not_exist') ); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException * @expectedExceptionMessage that_timezone_does_not_exist */ public function testConstructFailsIfOutputTimezoneIsInvalid() { $this->getMock( 'Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer', array(), array(null, 'that_timezone_does_not_exist') ); } } PK!.bc))htest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer; class ChoicesToValuesTransformerTest extends \PHPUnit_Framework_TestCase { protected $transformer; protected function setUp() { $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B', 2 => 'C')); $this->transformer = new ChoicesToValuesTransformer($list); } protected function tearDown() { $this->transformer = null; } public function testTransform() { // Value strategy in SimpleChoiceList is to copy and convert to string $in = array(0, 1, 2); $out = array('0', '1', '2'); $this->assertSame($out, $this->transformer->transform($in)); } public function testTransformNull() { $this->assertSame(array(), $this->transformer->transform(null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformExpectsArray() { $this->transformer->transform('foobar'); } public function testReverseTransform() { // values are expected to be valid choices and stay the same $in = array('0', '1', '2'); $out = array(0, 1, 2); $this->assertSame($out, $this->transformer->reverseTransform($in)); } public function testReverseTransformNull() { $this->assertSame(array(), $this->transformer->reverseTransform(null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsArray() { $this->transformer->reverseTransform('foobar'); } } PK!JWitest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; class DateTimeToStringTransformerTest extends DateTimeTestCase { public function dataProvider() { $data = array( array('Y-m-d H:i:s', '2010-02-03 16:05:06', '2010-02-03 16:05:06 UTC'), array('Y-m-d H:i:00', '2010-02-03 16:05:00', '2010-02-03 16:05:00 UTC'), array('Y-m-d H:i', '2010-02-03 16:05', '2010-02-03 16:05:00 UTC'), array('Y-m-d H', '2010-02-03 16', '2010-02-03 16:00:00 UTC'), array('Y-m-d', '2010-02-03', '2010-02-03 00:00:00 UTC'), array('Y-m', '2010-12', '2010-12-01 00:00:00 UTC'), array('Y', '2010', '2010-01-01 00:00:00 UTC'), array('d-m-Y', '03-02-2010', '2010-02-03 00:00:00 UTC'), array('H:i:s', '16:05:06', '1970-01-01 16:05:06 UTC'), array('H:i:00', '16:05:00', '1970-01-01 16:05:00 UTC'), array('H:i', '16:05', '1970-01-01 16:05:00 UTC'), array('H', '16', '1970-01-01 16:00:00 UTC'), // different day representations array('Y-m-j', '2010-02-3', '2010-02-03 00:00:00 UTC'), array('z', '33', '1970-02-03 00:00:00 UTC'), // not bijective // this will not work as PHP will use actual date to replace missing info // and after change of date will lookup for closest Wednesday // i.e. value: 2010-02, PHP value: 2010-02-(today i.e. 20), parsed date: 2010-02-24 //array('Y-m-D', '2010-02-Wed', '2010-02-03 00:00:00 UTC'), //array('Y-m-l', '2010-02-Wednesday', '2010-02-03 00:00:00 UTC'), // different month representations array('Y-n-d', '2010-2-03', '2010-02-03 00:00:00 UTC'), array('Y-M-d', '2010-Feb-03', '2010-02-03 00:00:00 UTC'), array('Y-F-d', '2010-February-03', '2010-02-03 00:00:00 UTC'), // different year representations array('y-m-d', '10-02-03', '2010-02-03 00:00:00 UTC'), // different time representations array('G:i:s', '16:05:06', '1970-01-01 16:05:06 UTC'), array('g:i:s a', '4:05:06 pm', '1970-01-01 16:05:06 UTC'), array('h:i:s a', '04:05:06 pm', '1970-01-01 16:05:06 UTC'), // seconds since Unix array('U', '1265213106', '2010-02-03 16:05:06 UTC'), ); // This test will fail < 5.3.9 - see https://bugs.php.net/51994 if (version_compare(phpversion(), '5.3.9', '>=')) { $data[] = array('Y-z', '2010-33', '2010-02-03 00:00:00 UTC'); } return $data; } /** * @dataProvider dataProvider */ public function testTransform($format, $output, $input) { $transformer = new DateTimeToStringTransformer('UTC', 'UTC', $format); $input = new \DateTime($input); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformEmpty() { $transformer = new DateTimeToStringTransformer(); $this->assertSame('', $transformer->transform(null)); } public function testTransformWithDifferentTimezones() { $transformer = new DateTimeToStringTransformer('Asia/Hong_Kong', 'America/New_York', 'Y-m-d H:i:s'); $input = new \DateTime('2010-02-03 12:05:06 America/New_York'); $output = $input->format('Y-m-d H:i:s'); $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformExpectsDateTime() { $transformer = new DateTimeToStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->transform('1234'); } /** * @dataProvider dataProvider */ public function testReverseTransformUsingPipe($format, $input, $output) { if (version_compare(phpversion(), '5.3.7', '<')) { $this->markTestSkipped('Pipe usage requires PHP 5.3.7 or newer.'); } $reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format, true); $output = new \DateTime($output); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } /** * @dataProvider dataProvider */ public function testReverseTransformWithoutUsingPipe($format, $input, $output) { $reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format, false); $output = new \DateTime($output); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } public function testReverseTransformEmpty() { $reverseTransformer = new DateTimeToStringTransformer(); $this->assertNull($reverseTransformer->reverseTransform('')); } public function testReverseTransformWithDifferentTimezones() { $reverseTransformer = new DateTimeToStringTransformer('America/New_York', 'Asia/Hong_Kong', 'Y-m-d H:i:s'); $output = new \DateTime('2010-02-03 16:05:06 Asia/Hong_Kong'); $input = $output->format('Y-m-d H:i:s'); $output->setTimeZone(new \DateTimeZone('America/New_York')); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } public function testReverseTransformExpectsString() { $reverseTransformer = new DateTimeToStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $reverseTransformer->reverseTransform(1234); } public function testReverseTransformExpectsValidDateString() { $reverseTransformer = new DateTimeToStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $reverseTransformer->reverseTransform('2010-2010-2010'); } public function testReverseTransformWithNonExistingDate() { $reverseTransformer = new DateTimeToStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $reverseTransformer->reverseTransform('2010-04-31'); } } PK!W@@Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Intl\Util\IntlTestHelper; class LanguageTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testCountriesAreSelectable() { $form = $this->factory->create('language'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false); $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'British English'), $choices, '', false, false); $this->assertContains(new ChoiceView('en_US', 'en_US', 'U.S. English'), $choices, '', false, false); $this->assertContains(new ChoiceView('fr', 'fr', 'French'), $choices, '', false, false); $this->assertContains(new ChoiceView('my', 'my', 'Burmese'), $choices, '', false, false); } public function testMultipleLanguagesIsNotIncluded() { $form = $this->factory->create('language', 'language'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertNotContains(new ChoiceView('mul', 'mul', 'Mehrsprachig'), $choices, '', false, false); } } PK!xaaMtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Intl\Util\IntlTestHelper; class LocaleTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testLocalesAreSelectable() { $form = $this->factory->create('locale'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false); $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'English (United Kingdom)'), $choices, '', false, false); $this->assertContains(new ChoiceView('zh_Hant_MO', 'zh_Hant_MO', 'Chinese (Traditional, Macau SAR China)'), $choices, '', false, false); } } PK!CMtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; /** * @author Bernhard Schussek */ class ButtonTypeTest extends BaseTypeTest { public function testCreateButtonInstances() { $this->assertInstanceOf('Symfony\Component\Form\Button', $this->factory->create('button')); } protected function getTestedType() { return 'button'; } } PK!'\\Ktest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormError; use Symfony\Component\Intl\Util\IntlTestHelper; class DateTypeTest extends TypeTestCase { protected function setUp() { parent::setUp(); // we test against "de_AT", so we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testInvalidWidgetOption() { $this->factory->create('date', null, array( 'widget' => 'fake_widget', )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testInvalidInputOption() { $this->factory->create('date', null, array( 'input' => 'fake_input', )); } public function testSubmitFromSingleTextDateTimeWithDefaultFormat() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'datetime', )); $form->submit('2010-06-02'); $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); $this->assertEquals('2010-06-02', $form->getViewData()); } public function testSubmitFromSingleTextDateTime() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'datetime', )); $form->submit('2.6.2010'); $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); } public function testSubmitFromSingleTextString() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'string', )); $form->submit('2.6.2010'); $this->assertEquals('2010-06-02', $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); } public function testSubmitFromSingleTextTimestamp() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'timestamp', )); $form->submit('2.6.2010'); $dateTime = new \DateTime('2010-06-02 UTC'); $this->assertEquals($dateTime->format('U'), $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); } public function testSubmitFromSingleTextRaw() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'array', )); $form->submit('2.6.2010'); $output = array( 'day' => '2', 'month' => '6', 'year' => '2010', ); $this->assertEquals($output, $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); } public function testSubmitFromText() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'text', )); $text = array( 'day' => '2', 'month' => '6', 'year' => '2010', ); $form->submit($text); $dateTime = new \DateTime('2010-06-02 UTC'); $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals($text, $form->getViewData()); } public function testSubmitFromChoice() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', )); $text = array( 'day' => '2', 'month' => '6', 'year' => '2010', ); $form->submit($text); $dateTime = new \DateTime('2010-06-02 UTC'); $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals($text, $form->getViewData()); } public function testSubmitFromChoiceEmpty() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', 'required' => false, )); $text = array( 'day' => '', 'month' => '', 'year' => '', ); $form->submit($text); $this->assertNull($form->getData()); $this->assertEquals($text, $form->getViewData()); } public function testSubmitFromInputDateTimeDifferentPattern() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'datetime', )); $form->submit('06*2010*02'); $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); } public function testSubmitFromInputStringDifferentPattern() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'string', )); $form->submit('06*2010*02'); $this->assertEquals('2010-06-02', $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); } public function testSubmitFromInputTimestampDifferentPattern() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'timestamp', )); $form->submit('06*2010*02'); $dateTime = new \DateTime('2010-06-02 UTC'); $this->assertEquals($dateTime->format('U'), $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); } public function testSubmitFromInputRawDifferentPattern() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'array', )); $form->submit('06*2010*02'); $output = array( 'day' => '2', 'month' => '6', 'year' => '2010', ); $this->assertEquals($output, $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); } /** * @dataProvider provideDateFormats */ public function testDatePatternWithFormatOption($format, $pattern) { $form = $this->factory->create('date', null, array( 'format' => $format, )); $view = $form->createView(); $this->assertEquals($pattern, $view->vars['date_pattern']); } public function provideDateFormats() { return array( array('dMy', '{{ day }}{{ month }}{{ year }}'), array('d-M-yyyy', '{{ day }}-{{ month }}-{{ year }}'), array('M d y', '{{ month }} {{ day }} {{ year }}'), ); } /** * This test is to check that the strings '0', '1', '2', '3' are not accepted * as valid IntlDateFormatter constants for FULL, LONG, MEDIUM or SHORT respectively. * * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsNoPattern() { $this->factory->create('date', null, array( 'format' => '0', 'widget' => 'single_text', 'input' => 'string', )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatDoesNotContainYearMonthAndDay() { $this->factory->create('date', null, array( 'months' => array(6, 7), 'format' => 'yy', )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsNoConstant() { $this->factory->create('date', null, array( 'format' => 105, )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsInvalid() { $this->factory->create('date', null, array( 'format' => array(), )); } public function testSetDataWithDifferentTimezones() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'America/New_York', 'view_timezone' => 'Pacific/Tahiti', 'input' => 'string', 'widget' => 'single_text', )); $form->setData('2010-06-02'); $this->assertEquals('01.06.2010', $form->getViewData()); } public function testSetDataWithDifferentTimezonesDateTime() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'America/New_York', 'view_timezone' => 'Pacific/Tahiti', 'input' => 'datetime', 'widget' => 'single_text', )); $dateTime = new \DateTime('2010-06-02 America/New_York'); $form->setData($dateTime); $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals('01.06.2010', $form->getViewData()); } public function testYearsOption() { $form = $this->factory->create('date', null, array( 'years' => array(2010, 2011), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('2010', '2010', '2010'), new ChoiceView('2011', '2011', '2011'), ), $view['year']->vars['choices']); } public function testMonthsOption() { $form = $this->factory->create('date', null, array( 'months' => array(6, 7), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['month']->vars['choices']); } public function testMonthsOptionShortFormat() { $form = $this->factory->create('date', null, array( 'months' => array(1, 4), 'format' => 'dd.MMM.yy', )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('1', '1', 'Jän'), new ChoiceView('4', '4', 'Apr.') ), $view['month']->vars['choices']); } public function testMonthsOptionLongFormat() { $form = $this->factory->create('date', null, array( 'months' => array(1, 4), 'format' => 'dd.MMMM.yy', )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('1', '1', 'Jänner'), new ChoiceView('4', '4', 'April'), ), $view['month']->vars['choices']); } public function testMonthsOptionLongFormatWithDifferentTimezone() { $form = $this->factory->create('date', null, array( 'months' => array(1, 4), 'format' => 'dd.MMMM.yy', )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('1', '1', 'Jänner'), new ChoiceView('4', '4', 'April'), ), $view['month']->vars['choices']); } public function testIsDayWithinRangeReturnsTrueIfWithin() { $form = $this->factory->create('date', null, array( 'days' => array(6, 7), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['day']->vars['choices']); } public function testIsPartiallyFilledReturnsFalseIfSingleText() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', )); $form->submit('7.6.2010'); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', )); $form->submit(array( 'day' => '', 'month' => '', 'year' => '', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyFilled() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', )); $form->submit(array( 'day' => '2', 'month' => '6', 'year' => '2010', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsTrueIfChoiceAndDayEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', )); $form->submit(array( 'day' => '', 'month' => '6', 'year' => '2010', )); $this->assertTrue($form->isPartiallyFilled()); } public function testPassDatePatternToView() { $form = $this->factory->create('date'); $view = $form->createView(); $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']); } public function testPassDatePatternToViewDifferentFormat() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::LONG, )); $view = $form->createView(); $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']); } public function testPassDatePatternToViewDifferentPattern() { $form = $this->factory->create('date', null, array( 'format' => 'MMyyyydd' )); $view = $form->createView(); $this->assertSame('{{ month }}{{ year }}{{ day }}', $view->vars['date_pattern']); } public function testPassDatePatternToViewDifferentPatternWithSeparators() { $form = $this->factory->create('date', null, array( 'format' => 'MM*yyyy*dd' )); $view = $form->createView(); $this->assertSame('{{ month }}*{{ year }}*{{ day }}', $view->vars['date_pattern']); } public function testDontPassDatePatternIfText() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertFalse(isset($view->vars['date_pattern'])); } public function testPassWidgetToView() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertSame('single_text', $view->vars['widget']); } // Bug fix public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set // to null in the type $this->factory->create('date', new \DateTime()); } public function testSingleTextWidgetShouldUseTheRightInputType() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertEquals('date', $view->vars['type']); } public function testPassDefaultEmptyValueToViewIfNotRequired() { $form = $this->factory->create('date', null, array( 'required' => false, )); $view = $form->createView(); $this->assertSame('', $view['year']->vars['empty_value']); $this->assertSame('', $view['month']->vars['empty_value']); $this->assertSame('', $view['day']->vars['empty_value']); } public function testPassNoEmptyValueToViewIfRequired() { $form = $this->factory->create('date', null, array( 'required' => true, )); $view = $form->createView(); $this->assertNull($view['year']->vars['empty_value']); $this->assertNull($view['month']->vars['empty_value']); $this->assertNull($view['day']->vars['empty_value']); } public function testPassEmptyValueAsString() { $form = $this->factory->create('date', null, array( 'empty_value' => 'Empty', )); $view = $form->createView(); $this->assertSame('Empty', $view['year']->vars['empty_value']); $this->assertSame('Empty', $view['month']->vars['empty_value']); $this->assertSame('Empty', $view['day']->vars['empty_value']); } public function testPassEmptyValueAsArray() { $form = $this->factory->create('date', null, array( 'empty_value' => array( 'year' => 'Empty year', 'month' => 'Empty month', 'day' => 'Empty day', ), )); $view = $form->createView(); $this->assertSame('Empty year', $view['year']->vars['empty_value']); $this->assertSame('Empty month', $view['month']->vars['empty_value']); $this->assertSame('Empty day', $view['day']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() { $form = $this->factory->create('date', null, array( 'required' => false, 'empty_value' => array( 'year' => 'Empty year', 'day' => 'Empty day', ), )); $view = $form->createView(); $this->assertSame('Empty year', $view['year']->vars['empty_value']); $this->assertSame('', $view['month']->vars['empty_value']); $this->assertSame('Empty day', $view['day']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddNullIfRequired() { $form = $this->factory->create('date', null, array( 'required' => true, 'empty_value' => array( 'year' => 'Empty year', 'day' => 'Empty day', ), )); $view = $form->createView(); $this->assertSame('Empty year', $view['year']->vars['empty_value']); $this->assertNull($view['month']->vars['empty_value']); $this->assertSame('Empty day', $view['day']->vars['empty_value']); } public function testPassHtml5TypeIfSingleTextAndHtml5Format() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertSame('date', $view->vars['type']); } public function testDontPassHtml5TypeIfNotHtml5Format() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', 'format' => \IntlDateFormatter::MEDIUM, )); $view = $form->createView(); $this->assertFalse(isset($view->vars['type'])); } public function testDontPassHtml5TypeIfNotSingleText() { $form = $this->factory->create('date', null, array( 'widget' => 'text', )); $view = $form->createView(); $this->assertFalse(isset($view->vars['type'])); } public function provideCompoundWidgets() { return array( array('text'), array('choice'), ); } /** * @dataProvider provideCompoundWidgets */ public function testYearErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('date', null, array( 'widget' => $widget, )); $form['year']->addError($error); $this->assertSame(array(), $form['year']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @dataProvider provideCompoundWidgets */ public function testMonthErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('date', null, array( 'widget' => $widget, )); $form['month']->addError($error); $this->assertSame(array(), $form['month']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @dataProvider provideCompoundWidgets */ public function testDayErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('date', null, array( 'widget' => $widget, )); $form['day']->addError($error); $this->assertSame(array(), $form['day']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } public function testYearsFor32BitsMachines() { if (4 !== PHP_INT_SIZE) { $this->markTestSkipped( 'PHP must be compiled in 32 bit mode to run this test'); } $form = $this->factory->create('date', null, array( 'years' => range(1900, 2040), )); $view = $form->createView(); $listChoices = array(); foreach (range(1902, 2037) as $y) { $listChoices[] = new ChoiceView($y, $y, $y); } $this->assertEquals($listChoices, $view['year']->vars['choices']); } } PK!vzwLLQtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Form; class CollectionTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testContainsNoChildByDefault() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $this->assertCount(0, $form); } public function testSetDataAdjustsSize() { $form = $this->factory->create('collection', null, array( 'type' => 'text', 'options' => array( 'max_length' => 20, ), )); $form->setData(array('foo@foo.com', 'foo@bar.com')); $this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]); $this->assertInstanceOf('Symfony\Component\Form\Form', $form[1]); $this->assertCount(2, $form); $this->assertEquals('foo@foo.com', $form[0]->getData()); $this->assertEquals('foo@bar.com', $form[1]->getData()); $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length')); $this->assertEquals(20, $form[1]->getConfig()->getOption('max_length')); $form->setData(array('foo@baz.com')); $this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]); $this->assertFalse(isset($form[1])); $this->assertCount(1, $form); $this->assertEquals('foo@baz.com', $form[0]->getData()); $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length')); } public function testThrowsExceptionIfObjectIsNotTraversable() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); $form->setData(new \stdClass()); } public function testNotResizedIfSubmittedWithMissingData() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $form->setData(array('foo@foo.com', 'bar@bar.com')); $form->submit(array('foo@bar.com')); $this->assertTrue($form->has('0')); $this->assertTrue($form->has('1')); $this->assertEquals('foo@bar.com', $form[0]->getData()); $this->assertEquals('', $form[1]->getData()); } public function testResizedDownIfSubmittedWithMissingDataAndAllowDelete() { $form = $this->factory->create('collection', null, array( 'type' => 'text', 'allow_delete' => true, )); $form->setData(array('foo@foo.com', 'bar@bar.com')); $form->submit(array('foo@foo.com')); $this->assertTrue($form->has('0')); $this->assertFalse($form->has('1')); $this->assertEquals('foo@foo.com', $form[0]->getData()); $this->assertEquals(array('foo@foo.com'), $form->getData()); } public function testNotResizedIfSubmittedWithExtraData() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $form->setData(array('foo@bar.com')); $form->submit(array('foo@foo.com', 'bar@bar.com')); $this->assertTrue($form->has('0')); $this->assertFalse($form->has('1')); $this->assertEquals('foo@foo.com', $form[0]->getData()); } public function testResizedUpIfSubmittedWithExtraDataAndAllowAdd() { $form = $this->factory->create('collection', null, array( 'type' => 'text', 'allow_add' => true, )); $form->setData(array('foo@bar.com')); $form->submit(array('foo@bar.com', 'bar@bar.com')); $this->assertTrue($form->has('0')); $this->assertTrue($form->has('1')); $this->assertEquals('foo@bar.com', $form[0]->getData()); $this->assertEquals('bar@bar.com', $form[1]->getData()); $this->assertEquals(array('foo@bar.com', 'bar@bar.com'), $form->getData()); } public function testAllowAddButNoPrototype() { $form = $this->factory->create('collection', null, array( 'type' => 'form', 'allow_add' => true, 'prototype' => false, )); $this->assertFalse($form->has('__name__')); } public function testPrototypeMultipartPropagation() { $form = $this->factory ->create('collection', null, array( 'type' => 'file', 'allow_add' => true, 'prototype' => true, )) ; $this->assertTrue($form->createView()->vars['multipart']); } public function testGetDataDoesNotContainsPrototypeNameBeforeDataAreSet() { $form = $this->factory->create('collection', array(), array( 'type' => 'file', 'prototype' => true, 'allow_add' => true, )); $data = $form->getData(); $this->assertFalse(isset($data['__name__'])); } public function testGetDataDoesNotContainsPrototypeNameAfterDataAreSet() { $form = $this->factory->create('collection', array(), array( 'type' => 'file', 'allow_add' => true, 'prototype' => true, )); $form->setData(array('foobar.png')); $data = $form->getData(); $this->assertFalse(isset($data['__name__'])); } public function testPrototypeNameOption() { $form = $this->factory->create('collection', null, array( 'type' => 'form', 'prototype' => true, 'allow_add' => true, )); $this->assertSame('__name__', $form->getConfig()->getAttribute('prototype')->getName(), '__name__ is the default'); $form = $this->factory->create('collection', null, array( 'type' => 'form', 'prototype' => true, 'allow_add' => true, 'prototype_name' => '__test__', )); $this->assertSame('__test__', $form->getConfig()->getAttribute('prototype')->getName()); } public function testPrototypeDefaultLabel() { $form = $this->factory->create('collection', array(), array( 'type' => 'file', 'allow_add' => true, 'prototype' => true, 'prototype_name' => '__test__', )); $this->assertSame('__test__label__', $form->createView()->vars['prototype']->vars['label']); } } PK!(__Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; class PasswordTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testEmptyIfNotSubmitted() { $form = $this->factory->create('password'); $form->setData('pAs5w0rd'); $view = $form->createView(); $this->assertSame('', $view->vars['value']); } public function testEmptyIfSubmitted() { $form = $this->factory->create('password'); $form->submit('pAs5w0rd'); $view = $form->createView(); $this->assertSame('', $view->vars['value']); } public function testNotEmptyIfSubmittedAndNotAlwaysEmpty() { $form = $this->factory->create('password', null, array('always_empty' => false)); $form->submit('pAs5w0rd'); $view = $form->createView(); $this->assertSame('pAs5w0rd', $view->vars['value']); } public function testNotTrimmed() { $form = $this->factory->create('password', null); $form->submit(' pAs5w0rd '); $data = $form->getData(); $this->assertSame(' pAs5w0rd ', $data); } } PK!x=t=t=Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\FormError; use Symfony\Component\Intl\Util\IntlTestHelper; class DateTimeTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testSubmitDateTime() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'date_widget' => 'choice', 'time_widget' => 'choice', 'input' => 'datetime', )); $form->submit(array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', 'minute' => '4', ), )); $dateTime = new \DateTime('2010-06-02 03:04:00 UTC'); $this->assertDateTimeEquals($dateTime, $form->getData()); } public function testSubmitString() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'date_widget' => 'choice', 'time_widget' => 'choice', )); $form->submit(array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', 'minute' => '4', ), )); $this->assertEquals('2010-06-02 03:04:00', $form->getData()); } public function testSubmitTimestamp() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'timestamp', 'date_widget' => 'choice', 'time_widget' => 'choice', )); $form->submit(array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', 'minute' => '4', ), )); $dateTime = new \DateTime('2010-06-02 03:04:00 UTC'); $this->assertEquals($dateTime->format('U'), $form->getData()); } public function testSubmitWithoutMinutes() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'date_widget' => 'choice', 'time_widget' => 'choice', 'input' => 'datetime', 'with_minutes' => false, )); $form->setData(new \DateTime('2010-06-02 03:04:05 UTC')); $input = array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', ), ); $form->submit($input); $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:00:00 UTC'), $form->getData()); } public function testSubmitWithSeconds() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'date_widget' => 'choice', 'time_widget' => 'choice', 'input' => 'datetime', 'with_seconds' => true, )); $form->setData(new \DateTime('2010-06-02 03:04:05 UTC')); $input = array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', 'minute' => '4', 'second' => '5', ), ); $form->submit($input); $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:04:05 UTC'), $form->getData()); } public function testSubmitDifferentTimezones() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'America/New_York', 'view_timezone' => 'Pacific/Tahiti', 'date_widget' => 'choice', 'time_widget' => 'choice', 'input' => 'string', 'with_seconds' => true, )); $dateTime = new \DateTime('2010-06-02 03:04:05 Pacific/Tahiti'); $form->submit(array( 'date' => array( 'day' => (int) $dateTime->format('d'), 'month' => (int) $dateTime->format('m'), 'year' => (int) $dateTime->format('Y'), ), 'time' => array( 'hour' => (int) $dateTime->format('H'), 'minute' => (int) $dateTime->format('i'), 'second' => (int) $dateTime->format('s'), ), )); $dateTime->setTimezone(new \DateTimeZone('America/New_York')); $this->assertEquals($dateTime->format('Y-m-d H:i:s'), $form->getData()); } public function testSubmitDifferentTimezonesDateTime() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'America/New_York', 'view_timezone' => 'Pacific/Tahiti', 'widget' => 'single_text', 'input' => 'datetime', )); $outputTime = new \DateTime('2010-06-02 03:04:00 Pacific/Tahiti'); $form->submit('2010-06-02T03:04:00-10:00'); $outputTime->setTimezone(new \DateTimeZone('America/New_York')); $this->assertDateTimeEquals($outputTime, $form->getData()); $this->assertEquals('2010-06-02T03:04:00-10:00', $form->getViewData()); } public function testSubmitStringSingleText() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', )); $form->submit('2010-06-02T03:04:00Z'); $this->assertEquals('2010-06-02 03:04:00', $form->getData()); $this->assertEquals('2010-06-02T03:04:00Z', $form->getViewData()); } public function testSubmitStringSingleTextWithSeconds() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', 'with_seconds' => true, )); $form->submit('2010-06-02T03:04:05Z'); $this->assertEquals('2010-06-02 03:04:05', $form->getData()); $this->assertEquals('2010-06-02T03:04:05Z', $form->getViewData()); } public function testSubmitDifferentPattern() { $form = $this->factory->create('datetime', null, array( 'date_format' => 'MM*yyyy*dd', 'date_widget' => 'single_text', 'time_widget' => 'single_text', 'input' => 'datetime', )); $dateTime = new \DateTime('2010-06-02 03:04'); $form->submit(array( 'date' => '06*2010*02', 'time' => '03:04', )); $this->assertDateTimeEquals($dateTime, $form->getData()); } // Bug fix public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set // to null in the type $this->factory->create('datetime', new \DateTime()); } public function testSingleTextWidgetShouldUseTheRightInputType() { $form = $this->factory->create('datetime', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertEquals('datetime', $view->vars['type']); } public function testPassDefaultEmptyValueToViewIfNotRequired() { $form = $this->factory->create('datetime', null, array( 'required' => false, 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('', $view['date']['year']->vars['empty_value']); $this->assertSame('', $view['date']['month']->vars['empty_value']); $this->assertSame('', $view['date']['day']->vars['empty_value']); $this->assertSame('', $view['time']['hour']->vars['empty_value']); $this->assertSame('', $view['time']['minute']->vars['empty_value']); $this->assertSame('', $view['time']['second']->vars['empty_value']); } public function testPassNoEmptyValueToViewIfRequired() { $form = $this->factory->create('datetime', null, array( 'required' => true, 'with_seconds' => true, )); $view = $form->createView(); $this->assertNull($view['date']['year']->vars['empty_value']); $this->assertNull($view['date']['month']->vars['empty_value']); $this->assertNull($view['date']['day']->vars['empty_value']); $this->assertNull($view['time']['hour']->vars['empty_value']); $this->assertNull($view['time']['minute']->vars['empty_value']); $this->assertNull($view['time']['second']->vars['empty_value']); } public function testPassEmptyValueAsString() { $form = $this->factory->create('datetime', null, array( 'empty_value' => 'Empty', 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty', $view['date']['year']->vars['empty_value']); $this->assertSame('Empty', $view['date']['month']->vars['empty_value']); $this->assertSame('Empty', $view['date']['day']->vars['empty_value']); $this->assertSame('Empty', $view['time']['hour']->vars['empty_value']); $this->assertSame('Empty', $view['time']['minute']->vars['empty_value']); $this->assertSame('Empty', $view['time']['second']->vars['empty_value']); } public function testPassEmptyValueAsArray() { $form = $this->factory->create('datetime', null, array( 'empty_value' => array( 'year' => 'Empty year', 'month' => 'Empty month', 'day' => 'Empty day', 'hour' => 'Empty hour', 'minute' => 'Empty minute', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); $this->assertSame('Empty month', $view['date']['month']->vars['empty_value']); $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); $this->assertSame('Empty minute', $view['time']['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() { $form = $this->factory->create('datetime', null, array( 'required' => false, 'empty_value' => array( 'year' => 'Empty year', 'day' => 'Empty day', 'hour' => 'Empty hour', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); $this->assertSame('', $view['date']['month']->vars['empty_value']); $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); $this->assertSame('', $view['time']['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddNullIfRequired() { $form = $this->factory->create('datetime', null, array( 'required' => true, 'empty_value' => array( 'year' => 'Empty year', 'day' => 'Empty day', 'hour' => 'Empty hour', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); $this->assertNull($view['date']['month']->vars['empty_value']); $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); $this->assertNull($view['time']['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); } public function testPassHtml5TypeIfSingleTextAndHtml5Format() { $form = $this->factory->create('datetime', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertSame('datetime', $view->vars['type']); } public function testDontPassHtml5TypeIfNotHtml5Format() { $form = $this->factory->create('datetime', null, array( 'widget' => 'single_text', 'format' => 'yyyy-MM-dd HH:mm', )); $view = $form->createView(); $this->assertFalse(isset($view->vars['type'])); } public function testDontPassHtml5TypeIfNotSingleText() { $form = $this->factory->create('datetime', null, array( 'widget' => 'text', )); $view = $form->createView(); $this->assertFalse(isset($view->vars['type'])); } public function testDateTypeChoiceErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null); $form['date']->addError($error); $this->assertSame(array(), $form['date']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } public function testDateTypeSingleTextErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null, array( 'date_widget' => 'single_text' )); $form['date']->addError($error); $this->assertSame(array(), $form['date']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } public function testTimeTypeChoiceErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null); $form['time']->addError($error); $this->assertSame(array(), $form['time']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } public function testTimeTypeSingleTextErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null, array( 'time_widget' => 'single_text' )); $form['time']->addError($error); $this->assertSame(array(), $form['time']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } } PK!P!Jtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; class UrlTypeTest extends TypeTestCase { public function testSubmitAddsDefaultProtocolIfNoneIsIncluded() { $form = $this->factory->create('url', 'name'); $form->submit('www.domain.com'); $this->assertSame('http://www.domain.com', $form->getData()); $this->assertSame('http://www.domain.com', $form->getViewData()); } public function testSubmitAddsNoDefaultProtocolIfAlreadyIncluded() { $form = $this->factory->create('url', null, array( 'default_protocol' => 'http', )); $form->submit('ftp://www.domain.com'); $this->assertSame('ftp://www.domain.com', $form->getData()); $this->assertSame('ftp://www.domain.com', $form->getViewData()); } public function testSubmitAddsNoDefaultProtocolIfEmpty() { $form = $this->factory->create('url', null, array( 'default_protocol' => 'http', )); $form->submit(''); $this->assertNull($form->getData()); $this->assertSame('', $form->getViewData()); } public function testSubmitAddsNoDefaultProtocolIfSetToNull() { $form = $this->factory->create('url', null, array( 'default_protocol' => null, )); $form->submit('www.domain.com'); $this->assertSame('www.domain.com', $form->getData()); $this->assertSame('www.domain.com', $form->getViewData()); } } PK!X:::Ktest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\TypeTestCase instead. */ abstract class TypeTestCase extends BaseTypeTestCase { } PK!Ntest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Intl\Util\IntlTestHelper; class CountryTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testCountriesAreSelectable() { $form = $this->factory->create('country'); $view = $form->createView(); $choices = $view->vars['choices']; // Don't check objects for identity $this->assertContains(new ChoiceView('DE', 'DE', 'Germany'), $choices, '', false, false); $this->assertContains(new ChoiceView('GB', 'GB', 'United Kingdom'), $choices, '', false, false); $this->assertContains(new ChoiceView('US', 'US', 'United States'), $choices, '', false, false); $this->assertContains(new ChoiceView('FR', 'FR', 'France'), $choices, '', false, false); $this->assertContains(new ChoiceView('MY', 'MY', 'Malaysia'), $choices, '', false, false); } public function testUnknownCountryIsNotIncluded() { $form = $this->factory->create('country', 'country'); $view = $form->createView(); $choices = $view->vars['choices']; foreach ($choices as $choice) { if ('ZZ' === $choice->value) { $this->fail('Should not contain choice "ZZ"'); } } } } PK!_*GXtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Test\FormPerformanceTestCase; /** * @author Bernhard Schussek */ class ChoiceTypePerformanceTest extends FormPerformanceTestCase { /** * This test case is realistic in collection forms where each * row contains the same choice field. * * @group benchmark */ public function testSameChoiceFieldCreatedMultipleTimes() { $this->setMaxRunningTime(1); $choices = range(1, 300); for ($i = 0; $i < 100; ++$i) { $this->factory->create('choice', rand(1, 400), array( 'choices' => $choices, )); } } } PK!{MKKtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; /** * @author Bernhard Schussek */ abstract class BaseTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testPassDisabledAsOption() { $form = $this->factory->create($this->getTestedType(), null, array('disabled' => true)); $this->assertTrue($form->isDisabled()); } public function testPassIdAndNameToView() { $view = $this->factory->createNamed('name', $this->getTestedType()) ->createView(); $this->assertEquals('name', $view->vars['id']); $this->assertEquals('name', $view->vars['name']); $this->assertEquals('name', $view->vars['full_name']); } public function testStripLeadingUnderscoresAndDigitsFromId() { $view = $this->factory->createNamed('_09name', $this->getTestedType()) ->createView(); $this->assertEquals('name', $view->vars['id']); $this->assertEquals('_09name', $view->vars['name']); $this->assertEquals('_09name', $view->vars['full_name']); } public function testPassIdAndNameToViewWithParent() { $view = $this->factory->createNamedBuilder('parent', 'form') ->add('child', $this->getTestedType()) ->getForm() ->createView(); $this->assertEquals('parent_child', $view['child']->vars['id']); $this->assertEquals('child', $view['child']->vars['name']); $this->assertEquals('parent[child]', $view['child']->vars['full_name']); } public function testPassIdAndNameToViewWithGrandParent() { $builder = $this->factory->createNamedBuilder('parent', 'form') ->add('child', 'form'); $builder->get('child')->add('grand_child', $this->getTestedType()); $view = $builder->getForm()->createView(); $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']); $this->assertEquals('grand_child', $view['child']['grand_child']->vars['name']); $this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->vars['full_name']); } public function testPassTranslationDomainToView() { $form = $this->factory->create($this->getTestedType(), null, array( 'translation_domain' => 'domain', )); $view = $form->createView(); $this->assertSame('domain', $view->vars['translation_domain']); } public function testInheritTranslationDomainFromParent() { $view = $this->factory ->createNamedBuilder('parent', 'form', null, array( 'translation_domain' => 'domain', )) ->add('child', $this->getTestedType()) ->getForm() ->createView(); $this->assertEquals('domain', $view['child']->vars['translation_domain']); } public function testPreferOwnTranslationDomain() { $view = $this->factory ->createNamedBuilder('parent', 'form', null, array( 'translation_domain' => 'parent_domain', )) ->add('child', $this->getTestedType(), array( 'translation_domain' => 'domain', )) ->getForm() ->createView(); $this->assertEquals('domain', $view['child']->vars['translation_domain']); } public function testDefaultTranslationDomain() { $view = $this->factory->createNamedBuilder('parent', 'form') ->add('child', $this->getTestedType()) ->getForm() ->createView(); $this->assertEquals('messages', $view['child']->vars['translation_domain']); } public function testPassLabelToView() { $form = $this->factory->createNamed('__test___field', $this->getTestedType(), null, array('label' => 'My label')); $view = $form->createView(); $this->assertSame('My label', $view->vars['label']); } public function testPassMultipartFalseToView() { $form = $this->factory->create($this->getTestedType()); $view = $form->createView(); $this->assertFalse($view->vars['multipart']); } abstract protected function getTestedType(); } PK!ސ/Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class TimezoneTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testTimezonesAreSelectable() { $form = $this->factory->create('timezone'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertArrayHasKey('Africa', $choices); $this->assertContains(new ChoiceView('Africa/Kinshasa', 'Africa/Kinshasa', 'Kinshasa'), $choices['Africa'], '', false, false); $this->assertArrayHasKey('America', $choices); $this->assertContains(new ChoiceView('America/New_York', 'America/New_York', 'New York'), $choices['America'], '', false, false); } } PK!dwҢSJSJKtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormError; use Symfony\Component\Intl\Util\IntlTestHelper; class TimeTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testSubmitDateTime() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', )); $input = array( 'hour' => '3', 'minute' => '4', ); $form->submit($input); $dateTime = new \DateTime('1970-01-01 03:04:00 UTC'); $this->assertEquals($dateTime, $form->getData()); $this->assertEquals($input, $form->getViewData()); } public function testSubmitString() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', )); $input = array( 'hour' => '3', 'minute' => '4', ); $form->submit($input); $this->assertEquals('03:04:00', $form->getData()); $this->assertEquals($input, $form->getViewData()); } public function testSubmitTimestamp() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'timestamp', )); $input = array( 'hour' => '3', 'minute' => '4', ); $form->submit($input); $dateTime = new \DateTime('1970-01-01 03:04:00 UTC'); $this->assertEquals($dateTime->format('U'), $form->getData()); $this->assertEquals($input, $form->getViewData()); } public function testSubmitArray() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'array', )); $input = array( 'hour' => '3', 'minute' => '4', ); $form->submit($input); $this->assertEquals($input, $form->getData()); $this->assertEquals($input, $form->getViewData()); } public function testSubmitDatetimeSingleText() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', 'widget' => 'single_text', )); $form->submit('03:04'); $this->assertEquals(new \DateTime('1970-01-01 03:04:00 UTC'), $form->getData()); $this->assertEquals('03:04', $form->getViewData()); } public function testSubmitDatetimeSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', 'widget' => 'single_text', 'with_minutes' => false, )); $form->submit('03'); $this->assertEquals(new \DateTime('1970-01-01 03:00:00 UTC'), $form->getData()); $this->assertEquals('03', $form->getViewData()); } public function testSubmitArraySingleText() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', )); $data = array( 'hour' => '3', 'minute' => '4', ); $form->submit('03:04'); $this->assertEquals($data, $form->getData()); $this->assertEquals('03:04', $form->getViewData()); } public function testSubmitArraySingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', 'with_minutes' => false, )); $data = array( 'hour' => '3', ); $form->submit('03'); $this->assertEquals($data, $form->getData()); $this->assertEquals('03', $form->getViewData()); } public function testSubmitArraySingleTextWithSeconds() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', 'with_seconds' => true, )); $data = array( 'hour' => '3', 'minute' => '4', 'second' => '5', ); $form->submit('03:04:05'); $this->assertEquals($data, $form->getData()); $this->assertEquals('03:04:05', $form->getViewData()); } public function testSubmitStringSingleText() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', )); $form->submit('03:04'); $this->assertEquals('03:04:00', $form->getData()); $this->assertEquals('03:04', $form->getViewData()); } public function testSubmitStringSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', 'with_minutes' => false, )); $form->submit('03'); $this->assertEquals('03:00:00', $form->getData()); $this->assertEquals('03', $form->getViewData()); } public function testSetDataWithoutMinutes() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', 'with_minutes' => false, )); $form->setData(new \DateTime('03:04:05 UTC')); $this->assertEquals(array('hour' => 3), $form->getViewData()); } public function testSetDataWithSeconds() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', 'with_seconds' => true, )); $form->setData(new \DateTime('03:04:05 UTC')); $this->assertEquals(array('hour' => 3, 'minute' => 4, 'second' => 5), $form->getViewData()); } public function testSetDataDifferentTimezones() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'America/New_York', 'view_timezone' => 'Asia/Hong_Kong', 'input' => 'string', 'with_seconds' => true, )); $dateTime = new \DateTime('2013-01-01 12:04:05'); $dateTime->setTimezone(new \DateTimeZone('America/New_York')); $form->setData($dateTime->format('H:i:s')); $outputTime = clone $dateTime; $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $displayedData = array( 'hour' => (int) $outputTime->format('H'), 'minute' => (int) $outputTime->format('i'), 'second' => (int) $outputTime->format('s') ); $this->assertEquals($displayedData, $form->getViewData()); } public function testSetDataDifferentTimezonesDateTime() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'America/New_York', 'view_timezone' => 'Asia/Hong_Kong', 'input' => 'datetime', 'with_seconds' => true, )); $dateTime = new \DateTime('12:04:05'); $dateTime->setTimezone(new \DateTimeZone('America/New_York')); $form->setData($dateTime); $outputTime = clone $dateTime; $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $displayedData = array( 'hour' => (int) $outputTime->format('H'), 'minute' => (int) $outputTime->format('i'), 'second' => (int) $outputTime->format('s') ); $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals($displayedData, $form->getViewData()); } public function testHoursOption() { $form = $this->factory->create('time', null, array( 'hours' => array(6, 7), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['hour']->vars['choices']); } public function testIsMinuteWithinRangeReturnsTrueIfWithin() { $form = $this->factory->create('time', null, array( 'minutes' => array(6, 7), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['minute']->vars['choices']); } public function testIsSecondWithinRangeReturnsTrueIfWithin() { $form = $this->factory->create('time', null, array( 'seconds' => array(6, 7), 'with_seconds' => true, )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['second']->vars['choices']); } public function testIsPartiallyFilledReturnsFalseIfCompletelyEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', )); $form->submit(array( 'hour' => '', 'minute' => '', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfCompletelyEmptyWithSeconds() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '', 'minute' => '', 'second' => '', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfCompletelyFilled() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', )); $form->submit(array( 'hour' => '0', 'minute' => '0', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfCompletelyFilledWithSeconds() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '0', 'minute' => '0', 'second' => '0', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsTrueIfChoiceAndHourEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '', 'minute' => '0', 'second' => '0', )); $this->assertTrue($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsTrueIfChoiceAndMinuteEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '0', 'minute' => '', 'second' => '0', )); $this->assertTrue($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsTrueIfChoiceAndSecondsEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '0', 'minute' => '0', 'second' => '', )); $this->assertTrue($form->isPartiallyFilled()); } // Bug fix public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set // to null in the type $this->factory->create('time', new \DateTime()); } public function testSingleTextWidgetShouldUseTheRightInputType() { $form = $this->factory->create('time', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertEquals('time', $view->vars['type']); } public function testPassDefaultEmptyValueToViewIfNotRequired() { $form = $this->factory->create('time', null, array( 'required' => false, 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('', $view['hour']->vars['empty_value']); $this->assertSame('', $view['minute']->vars['empty_value']); $this->assertSame('', $view['second']->vars['empty_value']); } public function testPassNoEmptyValueToViewIfRequired() { $form = $this->factory->create('time', null, array( 'required' => true, 'with_seconds' => true, )); $view = $form->createView(); $this->assertNull($view['hour']->vars['empty_value']); $this->assertNull($view['minute']->vars['empty_value']); $this->assertNull($view['second']->vars['empty_value']); } public function testPassEmptyValueAsString() { $form = $this->factory->create('time', null, array( 'empty_value' => 'Empty', 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty', $view['hour']->vars['empty_value']); $this->assertSame('Empty', $view['minute']->vars['empty_value']); $this->assertSame('Empty', $view['second']->vars['empty_value']); } public function testPassEmptyValueAsArray() { $form = $this->factory->create('time', null, array( 'empty_value' => array( 'hour' => 'Empty hour', 'minute' => 'Empty minute', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); $this->assertSame('Empty minute', $view['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['second']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() { $form = $this->factory->create('time', null, array( 'required' => false, 'empty_value' => array( 'hour' => 'Empty hour', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); $this->assertSame('', $view['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['second']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddNullIfRequired() { $form = $this->factory->create('time', null, array( 'required' => true, 'empty_value' => array( 'hour' => 'Empty hour', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); $this->assertNull($view['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['second']->vars['empty_value']); } public function provideCompoundWidgets() { return array( array('text'), array('choice'), ); } /** * @dataProvider provideCompoundWidgets */ public function testHourErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('time', null, array( 'widget' => $widget, )); $form['hour']->addError($error); $this->assertSame(array(), $form['hour']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @dataProvider provideCompoundWidgets */ public function testMinuteErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('time', null, array( 'widget' => $widget, )); $form['minute']->addError($error); $this->assertSame(array(), $form['minute']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @dataProvider provideCompoundWidgets */ public function testSecondErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('time', null, array( 'widget' => $widget, 'with_seconds' => true, )); $form['second']->addError($error); $this->assertSame(array(), $form['second']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidConfigurationException */ public function testInitializeWithSecondsAndWithoutMinutes() { $this->factory->create('time', null, array( 'with_minutes' => false, 'with_seconds' => true, )); } } PK!/Ltest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Intl\Util\IntlTestHelper; class MoneyTypeTest extends TypeTestCase { protected function setUp() { // we test against different locales, so we need the full // implementation IntlTestHelper::requireFullIntl($this); parent::setUp(); } public function testPassMoneyPatternToView() { \Locale::setDefault('de_DE'); $form = $this->factory->create('money'); $view = $form->createView(); $this->assertSame('{{ widget }} €', $view->vars['money_pattern']); } public function testMoneyPatternWorksForYen() { \Locale::setDefault('en_US'); $form = $this->factory->create('money', null, array('currency' => 'JPY')); $view = $form->createView(); $this->assertTrue((Boolean) strstr($view->vars['money_pattern'], '¥')); } // https://github.com/symfony/symfony/issues/5458 public function testPassDifferentPatternsForDifferentCurrencies() { \Locale::setDefault('de_DE'); $form1 = $this->factory->create('money', null, array('currency' => 'GBP')); $form2 = $this->factory->create('money', null, array('currency' => 'EUR')); $view1 = $form1->createView(); $view2 = $form2->createView(); $this->assertSame('{{ widget }} £', $view1->vars['money_pattern']); $this->assertSame('{{ widget }} €', $view2->vars['money_pattern']); } } PK!JMtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Intl\Util\IntlTestHelper; class NumberTypeTest extends TypeTestCase { protected function setUp() { parent::setUp(); // we test against "de_DE", so we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_DE'); } public function testDefaultFormatting() { $form = $this->factory->create('number'); $form->setData('12345.67890'); $view = $form->createView(); $this->assertSame('12345,679', $view->vars['value']); } public function testDefaultFormattingWithGrouping() { $form = $this->factory->create('number', null, array('grouping' => true)); $form->setData('12345.67890'); $view = $form->createView(); $this->assertSame('12.345,679', $view->vars['value']); } public function testDefaultFormattingWithPrecision() { $form = $this->factory->create('number', null, array('precision' => 2)); $form->setData('12345.67890'); $view = $form->createView(); $this->assertSame('12345,68', $view->vars['value']); } public function testDefaultFormattingWithRounding() { $form = $this->factory->create('number', null, array('precision' => 0, 'rounding_mode' => \NumberFormatter::ROUND_UP)); $form->setData('12345.54321'); $view = $form->createView(); $this->assertSame('12346', $view->vars['value']); } } PK!}C%%Mtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; /** * @author Bernhard Schussek */ class SubmitTypeTest extends TypeTestCase { public function testCreateSubmitButtonInstances() { $this->assertInstanceOf('Symfony\Component\Form\SubmitButton', $this->factory->create('submit')); } public function testNotClickedByDefault() { $button = $this->factory->create('submit'); $this->assertFalse($button->isClicked()); } public function testNotClickedIfSubmittedWithNull() { $button = $this->factory->create('submit'); $button->submit(null); $this->assertFalse($button->isClicked()); } public function testClickedIfSubmittedWithEmptyString() { $button = $this->factory->create('submit'); $button->submit(''); $this->assertTrue($button->isClicked()); } public function testClickedIfSubmittedWithUnemptyString() { $button = $this->factory->create('submit'); $button->submit('foo'); $this->assertTrue($button->isClicked()); } public function testSubmitCanBeAddedToForm() { $form = $this->factory ->createBuilder('form') ->getForm(); $this->assertSame($form, $form->add('send', 'submit')); } } PK!!]i00Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Intl\Util\IntlTestHelper; class CurrencyTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testCurrenciesAreSelectable() { $form = $this->factory->create('currency'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertContains(new ChoiceView('EUR', 'EUR', 'Euro'), $choices, '', false, false); $this->assertContains(new ChoiceView('USD', 'USD', 'US Dollar'), $choices, '', false, false); $this->assertContains(new ChoiceView('SIT', 'SIT', 'Slovenian Tolar'), $choices, '', false, false); } } PK!IJOtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\CallbackTransformer; class CheckboxTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testDataIsFalseByDefault() { $form = $this->factory->create('checkbox'); $this->assertFalse($form->getData()); $this->assertFalse($form->getNormData()); $this->assertNull($form->getViewData()); } public function testPassValueToView() { $form = $this->factory->create('checkbox', null, array('value' => 'foobar')); $view = $form->createView(); $this->assertEquals('foobar', $view->vars['value']); } public function testCheckedIfDataTrue() { $form = $this->factory->create('checkbox'); $form->setData(true); $view = $form->createView(); $this->assertTrue($view->vars['checked']); } public function testCheckedIfDataTrueWithEmptyValue() { $form = $this->factory->create('checkbox', null, array('value' => '')); $form->setData(true); $view = $form->createView(); $this->assertTrue($view->vars['checked']); } public function testNotCheckedIfDataFalse() { $form = $this->factory->create('checkbox'); $form->setData(false); $view = $form->createView(); $this->assertFalse($view->vars['checked']); } public function testSubmitWithValueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => 'foobar', )); $form->submit('foobar'); $this->assertTrue($form->getData()); $this->assertEquals('foobar', $form->getViewData()); } public function testSubmitWithRandomValueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => 'foobar', )); $form->submit('krixikraxi'); $this->assertTrue($form->getData()); $this->assertEquals('foobar', $form->getViewData()); } public function testSubmitWithValueUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => 'foobar', )); $form->submit(null); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); } public function testSubmitWithEmptyValueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); $form->submit(''); $this->assertTrue($form->getData()); $this->assertSame('', $form->getViewData()); } public function testSubmitWithEmptyValueUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); $form->submit(null); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); } public function testSubmitWithEmptyValueAndFalseUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); $form->submit(false); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); } public function testSubmitWithEmptyValueAndTrueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); $form->submit(true); $this->assertTrue($form->getData()); $this->assertSame('', $form->getViewData()); } /** * @dataProvider provideCustomModelTransformerData */ public function testCustomModelTransformer($data, $checked) { // present a binary status field as a checkbox $transformer = new CallbackTransformer( function ($value) { return 'checked' == $value; }, function ($value) { return $value ? 'checked' : 'unchecked'; } ); $form = $this->factory->createBuilder('checkbox') ->addModelTransformer($transformer) ->getForm(); $form->setData($data); $view = $form->createView(); $this->assertSame($data, $form->getData()); $this->assertSame($checked, $form->getNormData()); $this->assertEquals($checked, $view->vars['checked']); } public function provideCustomModelTransformerData() { return array( array('checked', true), array('unchecked', false), ); } } PK!ñIOtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; class RepeatedTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { protected $form; protected function setUp() { parent::setUp(); $this->form = $this->factory->create('repeated', null, array( 'type' => 'text', )); $this->form->setData(null); } public function testSetData() { $this->form->setData('foobar'); $this->assertEquals('foobar', $this->form['first']->getData()); $this->assertEquals('foobar', $this->form['second']->getData()); } public function testSetOptions() { $form = $this->factory->create('repeated', null, array( 'type' => 'text', 'options' => array('label' => 'Global'), )); $this->assertEquals('Global', $form['first']->getConfig()->getOption('label')); $this->assertEquals('Global', $form['second']->getConfig()->getOption('label')); $this->assertTrue($form['first']->isRequired()); $this->assertTrue($form['second']->isRequired()); } public function testSetOptionsPerChild() { $form = $this->factory->create('repeated', null, array( // the global required value cannot be overridden 'type' => 'text', 'first_options' => array('label' => 'Test', 'required' => false), 'second_options' => array('label' => 'Test2') )); $this->assertEquals('Test', $form['first']->getConfig()->getOption('label')); $this->assertEquals('Test2', $form['second']->getConfig()->getOption('label')); $this->assertTrue($form['first']->isRequired()); $this->assertTrue($form['second']->isRequired()); } public function testSetRequired() { $form = $this->factory->create('repeated', null, array( 'required' => false, 'type' => 'text', )); $this->assertFalse($form['first']->isRequired()); $this->assertFalse($form['second']->isRequired()); } public function testSetErrorBubblingToTrue() { $form = $this->factory->create('repeated', null, array( 'error_bubbling' => true, )); $this->assertTrue($form->getConfig()->getOption('error_bubbling')); $this->assertTrue($form['first']->getConfig()->getOption('error_bubbling')); $this->assertTrue($form['second']->getConfig()->getOption('error_bubbling')); } public function testSetErrorBubblingToFalse() { $form = $this->factory->create('repeated', null, array( 'error_bubbling' => false, )); $this->assertFalse($form->getConfig()->getOption('error_bubbling')); $this->assertFalse($form['first']->getConfig()->getOption('error_bubbling')); $this->assertFalse($form['second']->getConfig()->getOption('error_bubbling')); } public function testSetErrorBubblingIndividually() { $form = $this->factory->create('repeated', null, array( 'error_bubbling' => true, 'options' => array('error_bubbling' => false), 'second_options' => array('error_bubbling' => true), )); $this->assertTrue($form->getConfig()->getOption('error_bubbling')); $this->assertFalse($form['first']->getConfig()->getOption('error_bubbling')); $this->assertTrue($form['second']->getConfig()->getOption('error_bubbling')); } public function testSetOptionsPerChildAndOverwrite() { $form = $this->factory->create('repeated', null, array( 'type' => 'text', 'options' => array('label' => 'Label'), 'second_options' => array('label' => 'Second label') )); $this->assertEquals('Label', $form['first']->getConfig()->getOption('label')); $this->assertEquals('Second label', $form['second']->getConfig()->getOption('label')); $this->assertTrue($form['first']->isRequired()); $this->assertTrue($form['second']->isRequired()); } public function testSubmitUnequal() { $input = array('first' => 'foo', 'second' => 'bar'); $this->form->submit($input); $this->assertEquals('foo', $this->form['first']->getViewData()); $this->assertEquals('bar', $this->form['second']->getViewData()); $this->assertFalse($this->form->isSynchronized()); $this->assertEquals($input, $this->form->getViewData()); $this->assertNull($this->form->getData()); } public function testSubmitEqual() { $input = array('first' => 'foo', 'second' => 'foo'); $this->form->submit($input); $this->assertEquals('foo', $this->form['first']->getViewData()); $this->assertEquals('foo', $this->form['second']->getViewData()); $this->assertTrue($this->form->isSynchronized()); $this->assertEquals($input, $this->form->getViewData()); $this->assertEquals('foo', $this->form->getData()); } } PK!kƅNtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Intl\Util\IntlTestHelper; class IntegerTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testSubmitCastsToInteger() { $form = $this->factory->create('integer'); $form->submit('1.678'); $this->assertSame(1, $form->getData()); $this->assertSame('1', $form->getViewData()); } } PK!IEMtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { private $choices = array( 'a' => 'Bernhard', 'b' => 'Fabien', 'c' => 'Kris', 'd' => 'Jon', 'e' => 'Roman', ); private $numericChoices = array( 0 => 'Bernhard', 1 => 'Fabien', 2 => 'Kris', 3 => 'Jon', 4 => 'Roman', ); private $objectChoices; protected $groupedChoices = array( 'Symfony' => array( 'a' => 'Bernhard', 'b' => 'Fabien', 'c' => 'Kris', ), 'Doctrine' => array( 'd' => 'Jon', 'e' => 'Roman', ) ); protected function setUp() { parent::setUp(); $this->objectChoices = array( (object) array('id' => 1, 'name' => 'Bernhard'), (object) array('id' => 2, 'name' => 'Fabien'), (object) array('id' => 3, 'name' => 'Kris'), (object) array('id' => 4, 'name' => 'Jon'), (object) array('id' => 5, 'name' => 'Roman'), ); } protected function tearDown() { parent::tearDown(); $this->objectChoices = null; } /** * @expectedException \PHPUnit_Framework_Error */ public function testChoicesOptionExpectsArray() { $this->factory->create('choice', null, array( 'choices' => new \ArrayObject(), )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testChoiceListOptionExpectsChoiceListInterface() { $this->factory->create('choice', null, array( 'choice_list' => array('foo' => 'foo'), )); } public function testChoiceListAndChoicesCanBeEmpty() { $this->factory->create('choice'); } public function testExpandedChoicesOptionsTurnIntoChildren() { $form = $this->factory->create('choice', null, array( 'expanded' => true, 'choices' => $this->choices, )); $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); } public function testPlaceholderPresentOnNonRequiredExpandedSingleChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $this->assertTrue(isset($form['placeholder'])); $this->assertCount(count($this->choices) + 1, $form, 'Each choice should become a new field'); } public function testPlaceholderNotPresentIfRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $this->assertFalse(isset($form['placeholder'])); $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); } public function testPlaceholderNotPresentIfMultiple() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $this->assertFalse(isset($form['placeholder'])); $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); } public function testPlaceholderNotPresentIfEmptyChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => array( '' => 'Empty', 1 => 'Not empty', ), )); $this->assertFalse(isset($form['placeholder'])); $this->assertCount(2, $form, 'Each choice should become a new field'); } public function testExpandedChoicesOptionsAreFlattened() { $form = $this->factory->create('choice', null, array( 'expanded' => true, 'choices' => $this->groupedChoices, )); $flattened = array(); foreach ($this->groupedChoices as $choices) { $flattened = array_merge($flattened, array_keys($choices)); } $this->assertCount($form->count(), $flattened, 'Each nested choice should become a new field, not the groups'); foreach ($flattened as $value => $choice) { $this->assertTrue($form->has($value), 'Flattened choice is named after it\'s value'); } } public function testExpandedCheckboxesAreNeverRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); foreach ($form as $child) { $this->assertFalse($child->isRequired()); } } public function testExpandedRadiosAreRequiredIfChoiceChildIsRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); foreach ($form as $child) { $this->assertTrue($child->isRequired()); } } public function testExpandedRadiosAreNotRequiredIfChoiceChildIsNotRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); foreach ($form as $child) { $this->assertFalse($child->isRequired()); } } public function testSubmitSingleNonExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => false, 'choices' => $this->choices, )); $form->submit('b'); $this->assertEquals('b', $form->getData()); $this->assertEquals('b', $form->getViewData()); } public function testSubmitSingleNonExpandedInvalidChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => false, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertNull($form->getData()); $this->assertEquals('foobar', $form->getViewData()); $this->assertFalse($form->isSynchronized()); } public function testSubmitSingleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => false, 'choice_list' => new ObjectChoiceList( $this->objectChoices, // label path 'name', array(), null, // value path 'id' ), )); // "id" value of the second entry $form->submit('2'); $this->assertEquals($this->objectChoices[1], $form->getData()); $this->assertEquals('2', $form->getViewData()); } public function testSubmitMultipleNonExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->choices, )); $form->submit(array('a', 'b')); $this->assertEquals(array('a', 'b'), $form->getData()); $this->assertEquals(array('a', 'b'), $form->getViewData()); } public function testSubmitMultipleNonExpandedInvalidScalarChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertNull($form->getData()); $this->assertEquals('foobar', $form->getViewData()); $this->assertFalse($form->isSynchronized()); } public function testSubmitMultipleNonExpandedInvalidArrayChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->choices, )); $form->submit(array('a', 'foobar')); $this->assertNull($form->getData()); $this->assertEquals(array('a', 'foobar'), $form->getViewData()); $this->assertFalse($form->isSynchronized()); } public function testSubmitMultipleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choice_list' => new ObjectChoiceList( $this->objectChoices, // label path 'name', array(), null, // value path 'id' ), )); $form->submit(array('2', '3')); $this->assertEquals(array($this->objectChoices[1], $this->objectChoices[2]), $form->getData()); $this->assertEquals(array('2', '3'), $form->getViewData()); } public function testSubmitSingleExpandedRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit('b'); $this->assertSame('b', $form->getData()); $this->assertSame(array( 0 => false, 1 => true, 2 => false, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('b', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedRequiredInvalidChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertSame(null, $form->getData()); $this->assertSame('foobar', $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit('b'); $this->assertSame('b', $form->getData()); $this->assertSame(array( 0 => false, 1 => true, 2 => false, 3 => false, 4 => false, 'placeholder' => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form['placeholder']->getViewData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('b', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequiredInvalidChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertSame(null, $form->getData()); $this->assertSame('foobar', $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedRequiredNull() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit(null); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedRequiredEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit(''); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedRequiredFalse() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit(false); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequiredNull() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit(null); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, 'placeholder' => true, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertTrue($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('', $form['placeholder']->getViewData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequiredEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit(''); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, 'placeholder' => true, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertTrue($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('', $form['placeholder']->getViewData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequiredFalse() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit(false); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, 'placeholder' => true, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertTrue($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('', $form['placeholder']->getViewData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedWithEmptyChild() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'choices' => array( '' => 'Empty', 1 => 'Not empty', ), )); $form->submit(''); $this->assertNull($form->getData()); $this->assertTrue($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertSame('', $form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); } public function testSubmitSingleExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'choice_list' => new ObjectChoiceList( $this->objectChoices, // label path 'name', array(), null, // value path 'id' ), )); $form->submit('2'); $this->assertSame($this->objectChoices[1], $form->getData()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('2', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNumericChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'choices' => $this->numericChoices, )); $form->submit('1'); $this->assertSame(1, $form->getData()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('1', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->choices, )); $form->submit(array('a', 'c')); $this->assertSame(array('a', 'c'), $form->getData()); $this->assertSame(array( 0 => true, 1 => false, 2 => true, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertTrue($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertTrue($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('a', $form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertSame('c', $form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedInvalidScalarChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertNull($form->getData()); $this->assertSame('foobar', $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedInvalidArrayChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->choices, )); $form->submit(array('a', 'foobar')); $this->assertNull($form->getData()); $this->assertSame(array('a', 'foobar'), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->choices, )); $form->submit(array()); $this->assertSame(array(), $form->getData()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedWithEmptyChild() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => array( '' => 'Empty', 1 => 'Not Empty', 2 => 'Not Empty 2', ) )); $form->submit(array('', '2')); $this->assertSame(array('', 2), $form->getData()); $this->assertTrue($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertTrue($form[2]->getData()); $this->assertSame('', $form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertSame('2', $form[2]->getViewData()); } public function testSubmitMultipleExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choice_list' => new ObjectChoiceList( $this->objectChoices, // label path 'name', array(), null, // value path 'id' ), )); $form->submit(array('1', '2')); $this->assertSame(array($this->objectChoices[0], $this->objectChoices[1]), $form->getData()); $this->assertTrue($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('1', $form[0]->getViewData()); $this->assertSame('2', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedNumericChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->numericChoices, )); $form->submit(array('1', '2')); $this->assertSame(array(1, 2), $form->getData()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertTrue($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('1', $form[1]->getViewData()); $this->assertSame('2', $form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } /* * We need this functionality to create choice fields for Boolean types, * e.g. false => 'No', true => 'Yes' */ public function testSetDataSingleNonExpandedAcceptsBoolean() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => false, 'choices' => $this->numericChoices, )); $form->setData(false); $this->assertFalse($form->getData()); $this->assertEquals('0', $form->getViewData()); } public function testSetDataMultipleNonExpandedAcceptsBoolean() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->numericChoices, )); $form->setData(array(false, true)); $this->assertEquals(array(false, true), $form->getData()); $this->assertEquals(array('0', '1'), $form->getViewData()); } public function testPassRequiredToView() { $form = $this->factory->create('choice', null, array( 'choices' => $this->choices, )); $view = $form->createView(); $this->assertTrue($view->vars['required']); } public function testPassNonRequiredToView() { $form = $this->factory->create('choice', null, array( 'required' => false, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertFalse($view->vars['required']); } public function testPassMultipleToView() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertTrue($view->vars['multiple']); } public function testPassExpandedToView() { $form = $this->factory->create('choice', null, array( 'expanded' => true, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertTrue($view->vars['expanded']); } public function testEmptyValueIsNullByDefaultIfRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'required' => true, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertNull($view->vars['empty_value']); } public function testEmptyValueIsEmptyStringByDefaultIfNotRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'required' => false, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertSame('', $view->vars['empty_value']); } /** * @dataProvider getOptionsWithEmptyValue */ public function testPassEmptyValueToView($multiple, $expanded, $required, $emptyValue, $viewValue) { $form = $this->factory->create('choice', null, array( 'multiple' => $multiple, 'expanded' => $expanded, 'required' => $required, 'empty_value' => $emptyValue, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertEquals($viewValue, $view->vars['empty_value']); $this->assertFalse($view->vars['empty_value_in_choices']); } /** * @dataProvider getOptionsWithEmptyValue */ public function testDontPassEmptyValueIfContainedInChoices($multiple, $expanded, $required, $emptyValue, $viewValue) { $form = $this->factory->create('choice', null, array( 'multiple' => $multiple, 'expanded' => $expanded, 'required' => $required, 'empty_value' => $emptyValue, 'choices' => array('a' => 'A', '' => 'Empty'), )); $view = $form->createView(); $this->assertNull($view->vars['empty_value']); $this->assertTrue($view->vars['empty_value_in_choices']); } public function getOptionsWithEmptyValue() { return array( // single non-expanded array(false, false, false, 'foobar', 'foobar'), array(false, false, false, '', ''), array(false, false, false, null, null), array(false, false, false, false, null), array(false, false, true, 'foobar', 'foobar'), array(false, false, true, '', ''), array(false, false, true, null, null), array(false, false, true, false, null), // single expanded array(false, true, false, 'foobar', 'foobar'), // radios should never have an empty label array(false, true, false, '', 'None'), array(false, true, false, null, null), array(false, true, false, false, null), array(false, true, true, 'foobar', 'foobar'), // radios should never have an empty label array(false, true, true, '', 'None'), array(false, true, true, null, null), array(false, true, true, false, null), // multiple non-expanded array(true, false, false, 'foobar', null), array(true, false, false, '', null), array(true, false, false, null, null), array(true, false, false, false, null), array(true, false, true, 'foobar', null), array(true, false, true, '', null), array(true, false, true, null, null), array(true, false, true, false, null), // multiple expanded array(true, true, false, 'foobar', null), array(true, true, false, '', null), array(true, true, false, null, null), array(true, true, false, false, null), array(true, true, true, 'foobar', null), array(true, true, true, '', null), array(true, true, true, null, null), array(true, true, true, false, null), ); } public function testPassChoicesToView() { $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D'); $form = $this->factory->create('choice', null, array( 'choices' => $choices, )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('a', 'a', 'A'), new ChoiceView('b', 'b', 'B'), new ChoiceView('c', 'c', 'C'), new ChoiceView('d', 'd', 'D'), ), $view->vars['choices']); } public function testPassPreferredChoicesToView() { $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D'); $form = $this->factory->create('choice', null, array( 'choices' => $choices, 'preferred_choices' => array('b', 'd'), )); $view = $form->createView(); $this->assertEquals(array( 0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C'), ), $view->vars['choices']); $this->assertEquals(array( 1 => new ChoiceView('b', 'b', 'B'), 3 => new ChoiceView('d', 'd', 'D'), ), $view->vars['preferred_choices']); } public function testPassHierarchicalChoicesToView() { $form = $this->factory->create('choice', null, array( 'choices' => $this->groupedChoices, 'preferred_choices' => array('b', 'd'), )); $view = $form->createView(); $this->assertEquals(array( 'Symfony' => array( 0 => new ChoiceView('a', 'a', 'Bernhard'), 2 => new ChoiceView('c', 'c', 'Kris'), ), 'Doctrine' => array( 4 => new ChoiceView('e', 'e', 'Roman'), ), ), $view->vars['choices']); $this->assertEquals(array( 'Symfony' => array( 1 => new ChoiceView('b', 'b', 'Fabien'), ), 'Doctrine' => array( 3 => new ChoiceView('d', 'd', 'Jon'), ), ), $view->vars['preferred_choices']); } public function testPassChoiceDataToView() { $obj1 = (object) array('value' => 'a', 'label' => 'A'); $obj2 = (object) array('value' => 'b', 'label' => 'B'); $obj3 = (object) array('value' => 'c', 'label' => 'C'); $obj4 = (object) array('value' => 'd', 'label' => 'D'); $form = $this->factory->create('choice', null, array( 'choice_list' => new ObjectChoiceList(array($obj1, $obj2, $obj3, $obj4), 'label', array(), null, 'value'), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView($obj1, 'a', 'A'), new ChoiceView($obj2, 'b', 'B'), new ChoiceView($obj3, 'c', 'C'), new ChoiceView($obj4, 'd', 'D'), ), $view->vars['choices']); } public function testAdjustFullNameForMultipleNonExpanded() { $form = $this->factory->createNamed('name', 'choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertSame('name[]', $view->vars['full_name']); } // https://github.com/symfony/symfony/issues/3298 public function testInitializeWithEmptyChoices() { $this->factory->createNamed('name', 'choice', null, array( 'choices' => array(), )); } public function testInitializeWithDefaultObjectChoice() { $obj1 = (object) array('value' => 'a', 'label' => 'A'); $obj2 = (object) array('value' => 'b', 'label' => 'B'); $obj3 = (object) array('value' => 'c', 'label' => 'C'); $obj4 = (object) array('value' => 'd', 'label' => 'D'); $form = $this->factory->create('choice', null, array( 'choice_list' => new ObjectChoiceList(array($obj1, $obj2, $obj3, $obj4), 'label', array(), null, 'value'), // Used to break because "data_class" was inferred, which needs to // remain null in every case (because it refers to the view format) 'data' => $obj3, )); // Trigger data initialization $form->getViewData(); } } PK!jGgJgJKtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Form\Form; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Tests\Fixtures\Author; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; use Symfony\Component\Form\FormError; class FormTest_AuthorWithoutRefSetter { protected $reference; protected $referenceCopy; public function __construct($reference) { $this->reference = $reference; $this->referenceCopy = $reference; } // The returned object should be modified by reference without having // to provide a setReference() method public function getReference() { return $this->reference; } // The returned object is a copy, so setReferenceCopy() must be used // to update it public function getReferenceCopy() { return is_object($this->referenceCopy) ? clone $this->referenceCopy : $this->referenceCopy; } public function setReferenceCopy($reference) { $this->referenceCopy = $reference; } } class FormTypeTest extends BaseTypeTest { public function testCreateFormInstances() { $this->assertInstanceOf('Symfony\Component\Form\Form', $this->factory->create('form')); } public function testPassRequiredAsOption() { $form = $this->factory->create('form', null, array('required' => false)); $this->assertFalse($form->isRequired()); $form = $this->factory->create('form', null, array('required' => true)); $this->assertTrue($form->isRequired()); } public function testSubmittedDataIsTrimmedBeforeTransforming() { $form = $this->factory->createBuilder('form') ->addViewTransformer(new FixedDataTransformer(array( null => '', 'reverse[a]' => 'a', ))) ->setCompound(false) ->getForm(); $form->submit(' a '); $this->assertEquals('a', $form->getViewData()); $this->assertEquals('reverse[a]', $form->getData()); } public function testSubmittedDataIsNotTrimmedBeforeTransformingIfNoTrimming() { $form = $this->factory->createBuilder('form', null, array('trim' => false)) ->addViewTransformer(new FixedDataTransformer(array( null => '', 'reverse[ a ]' => ' a ', ))) ->setCompound(false) ->getForm(); $form->submit(' a '); $this->assertEquals(' a ', $form->getViewData()); $this->assertEquals('reverse[ a ]', $form->getData()); } public function testNonReadOnlyFormWithReadOnlyParentIsReadOnly() { $view = $this->factory->createNamedBuilder('parent', 'form', null, array('read_only' => true)) ->add('child', 'form') ->getForm() ->createView(); $this->assertTrue($view['child']->vars['read_only']); } public function testReadOnlyFormWithNonReadOnlyParentIsReadOnly() { $view = $this->factory->createNamedBuilder('parent', 'form') ->add('child', 'form', array('read_only' => true)) ->getForm() ->createView(); $this->assertTrue($view['child']->vars['read_only']); } public function testNonReadOnlyFormWithNonReadOnlyParentIsNotReadOnly() { $view = $this->factory->createNamedBuilder('parent', 'form') ->add('child', 'form') ->getForm() ->createView(); $this->assertFalse($view['child']->vars['read_only']); } public function testPassMaxLengthToView() { $form = $this->factory->create('form', null, array('max_length' => 10)); $view = $form->createView(); $this->assertSame(10, $view->vars['max_length']); } public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => false, )); $builder->add('firstName', 'text'); $builder->add('lastName', 'text'); $form = $builder->getForm(); $form->setData(null); // partially empty, still an object is created $form->submit(array('firstName' => 'Bernhard', 'lastName' => '')); $author = new Author(); $author->firstName = 'Bernhard'; $author->setLastName(''); $this->assertEquals($author, $form->getData()); } public function testSubmitWithEmptyDataCreatesObjectIfInitiallySubmittedWithObject() { $builder = $this->factory->createBuilder('form', null, array( // data class is inferred from the passed object 'data' => new Author(), 'required' => false, )); $builder->add('firstName', 'text'); $builder->add('lastName', 'text'); $form = $builder->getForm(); $form->setData(null); // partially empty, still an object is created $form->submit(array('firstName' => 'Bernhard', 'lastName' => '')); $author = new Author(); $author->firstName = 'Bernhard'; $author->setLastName(''); $this->assertEquals($author, $form->getData()); } public function testSubmitWithEmptyDataCreatesArrayIfDataClassIsNull() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => null, 'required' => false, )); $builder->add('firstName', 'text'); $form = $builder->getForm(); $form->setData(null); $form->submit(array('firstName' => 'Bernhard')); $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); } public function testSubmitEmptyWithEmptyDataCreatesNoObjectIfNotRequired() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => false, )); $builder->add('firstName', 'text'); $builder->add('lastName', 'text'); $form = $builder->getForm(); $form->setData(null); $form->submit(array('firstName' => '', 'lastName' => '')); $this->assertNull($form->getData()); } public function testSubmitEmptyWithEmptyDataCreatesObjectIfRequired() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => true, )); $builder->add('firstName', 'text'); $builder->add('lastName', 'text'); $form = $builder->getForm(); $form->setData(null); $form->submit(array('firstName' => '', 'lastName' => '')); $this->assertEquals(new Author(), $form->getData()); } /* * We need something to write the field values into */ public function testSubmitWithEmptyDataStoresArrayIfNoClassAvailable() { $form = $this->factory->createBuilder('form') ->add('firstName', 'text') ->getForm(); $form->setData(null); $form->submit(array('firstName' => 'Bernhard')); $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); } public function testSubmitWithEmptyDataPassesEmptyStringToTransformerIfNotCompound() { $form = $this->factory->createBuilder('form') ->addViewTransformer(new FixedDataTransformer(array( // required for the initial, internal setData(null) null => 'null', // required to test that submit(null) is converted to '' 'empty' => '', ))) ->setCompound(false) ->getForm(); $form->submit(null); $this->assertSame('empty', $form->getData()); } public function testSubmitWithEmptyDataUsesEmptyDataOption() { $author = new Author(); $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'empty_data' => $author, )); $builder->add('firstName', 'text'); $form = $builder->getForm(); $form->submit(array('firstName' => 'Bernhard')); $this->assertSame($author, $form->getData()); $this->assertEquals('Bernhard', $author->firstName); } public function provideZeros() { return array( array(0, '0'), array('0', '0'), array('00000', '00000'), ); } /** * @dataProvider provideZeros * @see https://github.com/symfony/symfony/issues/1986 */ public function testSetDataThroughParamsWithZero($data, $dataAsString) { $form = $this->factory->create('form', null, array( 'data' => $data, 'compound' => false, )); $view = $form->createView(); $this->assertFalse($form->isEmpty()); $this->assertSame($dataAsString, $view->vars['value']); $this->assertSame($dataAsString, $form->getData()); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testAttributesException() { $this->factory->create('form', null, array('attr' => '')); } public function testNameCanBeEmptyString() { $form = $this->factory->createNamed('', 'form'); $this->assertEquals('', $form->getName()); } public function testSubformDoesntCallSetters() { $author = new FormTest_AuthorWithoutRefSetter(new Author()); $builder = $this->factory->createBuilder('form', $author); $builder->add('reference', 'form', array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', )); $builder->get('reference')->add('firstName', 'text'); $form = $builder->getForm(); $form->submit(array( // reference has a getter, but not setter 'reference' => array( 'firstName' => 'Foo', ) )); $this->assertEquals('Foo', $author->getReference()->firstName); } public function testSubformCallsSettersIfTheObjectChanged() { // no reference $author = new FormTest_AuthorWithoutRefSetter(null); $newReference = new Author(); $builder = $this->factory->createBuilder('form', $author); $builder->add('referenceCopy', 'form', array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', )); $builder->get('referenceCopy')->add('firstName', 'text'); $form = $builder->getForm(); $form['referenceCopy']->setData($newReference); // new author object $form->submit(array( // referenceCopy has a getter that returns a copy 'referenceCopy' => array( 'firstName' => 'Foo', ) )); $this->assertEquals('Foo', $author->getReferenceCopy()->firstName); } public function testSubformCallsSettersIfByReferenceIsFalse() { $author = new FormTest_AuthorWithoutRefSetter(new Author()); $builder = $this->factory->createBuilder('form', $author); $builder->add('referenceCopy', 'form', array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'by_reference' => false )); $builder->get('referenceCopy')->add('firstName', 'text'); $form = $builder->getForm(); $form->submit(array( // referenceCopy has a getter that returns a copy 'referenceCopy' => array( 'firstName' => 'Foo', ) )); // firstName can only be updated if setReferenceCopy() was called $this->assertEquals('Foo', $author->getReferenceCopy()->firstName); } public function testSubformCallsSettersIfReferenceIsScalar() { $author = new FormTest_AuthorWithoutRefSetter('scalar'); $builder = $this->factory->createBuilder('form', $author); $builder->add('referenceCopy', 'form'); $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer( function () {}, function ($value) { // reverseTransform return 'foobar'; } )); $form = $builder->getForm(); $form->submit(array( 'referenceCopy' => array(), // doesn't matter actually )); // firstName can only be updated if setReferenceCopy() was called $this->assertEquals('foobar', $author->getReferenceCopy()); } public function testSubformAlwaysInsertsIntoArrays() { $ref1 = new Author(); $ref2 = new Author(); $author = array('referenceCopy' => $ref1); $builder = $this->factory->createBuilder('form'); $builder->setData($author); $builder->add('referenceCopy', 'form'); $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer( function () {}, function ($value) use ($ref2) { // reverseTransform return $ref2; } )); $form = $builder->getForm(); $form->submit(array( 'referenceCopy' => array('a' => 'b'), // doesn't matter actually )); // the new reference was inserted into the array $author = $form->getData(); $this->assertSame($ref2, $author['referenceCopy']); } public function testPassMultipartTrueIfAnyChildIsMultipartToView() { $view = $this->factory->createBuilder('form') ->add('foo', 'text') ->add('bar', 'file') ->getForm() ->createView(); $this->assertTrue($view->vars['multipart']); } public function testViewIsNotRenderedByDefault() { $view = $this->factory->createBuilder('form') ->add('foo', 'form') ->getForm() ->createView(); $this->assertFalse($view->isRendered()); } public function testErrorBubblingIfCompound() { $form = $this->factory->create('form', null, array( 'compound' => true, )); $this->assertTrue($form->getConfig()->getErrorBubbling()); } public function testNoErrorBubblingIfNotCompound() { $form = $this->factory->create('form', null, array( 'compound' => false, )); $this->assertFalse($form->getConfig()->getErrorBubbling()); } public function testOverrideErrorBubbling() { $form = $this->factory->create('form', null, array( 'compound' => false, 'error_bubbling' => true, )); $this->assertTrue($form->getConfig()->getErrorBubbling()); } public function testPropertyPath() { $form = $this->factory->create('form', null, array( 'property_path' => 'foo', )); $this->assertEquals(new PropertyPath('foo'), $form->getPropertyPath()); $this->assertTrue($form->getConfig()->getMapped()); } public function testPropertyPathNullImpliesDefault() { $form = $this->factory->createNamed('name', 'form', null, array( 'property_path' => null, )); $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); $this->assertTrue($form->getConfig()->getMapped()); } public function testNotMapped() { $form = $this->factory->create('form', null, array( 'property_path' => 'foo', 'mapped' => false, )); $this->assertEquals(new PropertyPath('foo'), $form->getPropertyPath()); $this->assertFalse($form->getConfig()->getMapped()); } public function testViewValidNotSubmitted() { $form = $this->factory->create('form'); $view = $form->createView(); $this->assertTrue($view->vars['valid']); } public function testViewNotValidSubmitted() { $form = $this->factory->create('form'); $form->submit(array()); $form->addError(new FormError('An error')); $view = $form->createView(); $this->assertFalse($view->vars['valid']); } public function testViewSubmittedNotSubmitted() { $form = $this->factory->create('form'); $view = $form->createView(); $this->assertFalse($view->vars['submitted']); } public function testViewSubmittedSubmitted() { $form = $this->factory->create('form'); $form->submit(array()); $view = $form->createView(); $this->assertTrue($view->vars['submitted']); } public function testDataOptionSupersedesSetDataCalls() { $form = $this->factory->create('form', null, array( 'data' => 'default', 'compound' => false, )); $form->setData('foobar'); $this->assertSame('default', $form->getData()); } public function testDataOptionSupersedesSetDataCallsIfNull() { $form = $this->factory->create('form', null, array( 'data' => null, 'compound' => false, )); $form->setData('foobar'); $this->assertNull($form->getData()); } public function testNormDataIsPassedToView() { $view = $this->factory->createBuilder('form') ->addViewTransformer(new FixedDataTransformer(array( 'foo' => 'bar', ))) ->setData('foo') ->getForm() ->createView(); $this->assertSame('foo', $view->vars['data']); $this->assertSame('bar', $view->vars['value']); } // https://github.com/symfony/symfony/issues/6862 public function testPassZeroLabelToView() { $view = $this->factory->create('form', null, array( 'label' => '0' )) ->createView(); $this->assertSame('0', $view->vars['label']); } public function testCanGetErrorsWhenButtonInForm() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => false, )); $builder->add('foo', 'text'); $builder->add('submit', 'submit'); $form = $builder->getForm(); //This method should not throw a Fatal Error Exception. $form->getErrorsAsString(); } protected function getTestedType() { return 'form'; } } PK!&Ktest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; class FileTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { // https://github.com/symfony/symfony/pull/5028 public function testSetData() { $form = $this->factory->createBuilder('file')->getForm(); $data = $this->createUploadedFileMock('abcdef', 'original.jpg', true); $form->setData($data); $this->assertSame($data, $form->getData()); } public function testSubmit() { $form = $this->factory->createBuilder('file')->getForm(); $data = $this->createUploadedFileMock('abcdef', 'original.jpg', true); $form->submit($data); $this->assertSame($data, $form->getData()); } // https://github.com/symfony/symfony/issues/6134 public function testSubmitEmpty() { $form = $this->factory->createBuilder('file')->getForm(); $form->submit(null); $this->assertNull($form->getData()); } public function testDontPassValueToView() { $form = $this->factory->create('file'); $form->submit(array( 'file' => $this->createUploadedFileMock('abcdef', 'original.jpg', true), )); $view = $form->createView(); $this->assertEquals('', $view->vars['value']); } private function createUploadedFileMock($name, $originalName, $valid) { $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') ->disableOriginalConstructor() ->getMock() ; $file ->expects($this->any()) ->method('getBasename') ->will($this->returnValue($name)) ; $file ->expects($this->any()) ->method('getClientOriginalName') ->will($this->returnValue($originalName)) ; $file ->expects($this->any()) ->method('isValid') ->will($this->returnValue($valid)) ; return $file; } } PK!>>Xtest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\DataCollector; use Symfony\Component\Form\Extension\DataCollector\FormDataCollector; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormView; class FormDataCollectorTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataExtractor; /** * @var FormDataCollector */ private $dataCollector; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataMapper; /** * @var Form */ private $form; /** * @var Form */ private $childForm; /** * @var FormView */ private $view; /** * @var FormView */ private $childView; protected function setUp() { $this->dataExtractor = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataExtractorInterface'); $this->dataCollector = new FormDataCollector($this->dataExtractor); $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface'); $this->form = $this->createForm('name'); $this->childForm = $this->createForm('child'); $this->view = new FormView(); $this->childView = new FormView(); } public function testBuildPreliminaryFormTree() { $this->form->add($this->childForm); $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($this->childForm) ->will($this->returnValue(array('config' => 'bar'))); $this->dataExtractor->expects($this->at(2)) ->method('extractDefaultData') ->with($this->form) ->will($this->returnValue(array('default_data' => 'foo'))); $this->dataExtractor->expects($this->at(3)) ->method('extractDefaultData') ->with($this->childForm) ->will($this->returnValue(array('default_data' => 'bar'))); $this->dataExtractor->expects($this->at(4)) ->method('extractSubmittedData') ->with($this->form) ->will($this->returnValue(array('submitted_data' => 'foo'))); $this->dataExtractor->expects($this->at(5)) ->method('extractSubmittedData') ->with($this->childForm) ->will($this->returnValue(array('submitted_data' => 'bar'))); $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->collectDefaultData($this->form); $this->dataCollector->collectSubmittedData($this->form); $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'default_data' => 'foo', 'submitted_data' => 'foo', 'children' => array( 'child' => array( 'config' => 'bar', 'default_data' => 'bar', 'submitted_data' => 'bar', 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testBuildMultiplePreliminaryFormTrees() { $form1 = $this->createForm('form1'); $form2 = $this->createForm('form2'); $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($form1) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($form2) ->will($this->returnValue(array('config' => 'bar'))); $this->dataCollector->collectConfiguration($form1); $this->dataCollector->collectConfiguration($form2); $this->dataCollector->buildPreliminaryFormTree($form1); $this->assertSame(array( 'forms' => array( 'form1' => array( 'config' => 'foo', 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); $this->dataCollector->buildPreliminaryFormTree($form2); $this->assertSame(array( 'forms' => array( 'form1' => array( 'config' => 'foo', 'children' => array(), ), 'form2' => array( 'config' => 'bar', 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testBuildSamePreliminaryFormTreeMultipleTimes() { $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractDefaultData') ->with($this->form) ->will($this->returnValue(array('default_data' => 'foo'))); $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); $this->dataCollector->collectDefaultData($this->form); $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'default_data' => 'foo', 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testBuildPreliminaryFormTreeWithoutCollectingAnyData() { $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testBuildFinalFormTree() { $this->form->add($this->childForm); $this->view->children['child'] = $this->childView; $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($this->childForm) ->will($this->returnValue(array('config' => 'bar'))); $this->dataExtractor->expects($this->at(2)) ->method('extractDefaultData') ->with($this->form) ->will($this->returnValue(array('default_data' => 'foo'))); $this->dataExtractor->expects($this->at(3)) ->method('extractDefaultData') ->with($this->childForm) ->will($this->returnValue(array('default_data' => 'bar'))); $this->dataExtractor->expects($this->at(4)) ->method('extractSubmittedData') ->with($this->form) ->will($this->returnValue(array('submitted_data' => 'foo'))); $this->dataExtractor->expects($this->at(5)) ->method('extractSubmittedData') ->with($this->childForm) ->will($this->returnValue(array('submitted_data' => 'bar'))); $this->dataExtractor->expects($this->at(6)) ->method('extractViewVariables') ->with($this->view) ->will($this->returnValue(array('view_vars' => 'foo'))); $this->dataExtractor->expects($this->at(7)) ->method('extractViewVariables') ->with($this->childView) ->will($this->returnValue(array('view_vars' => 'bar'))); $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->collectDefaultData($this->form); $this->dataCollector->collectSubmittedData($this->form); $this->dataCollector->collectViewVariables($this->view); $this->dataCollector->buildFinalFormTree($this->form, $this->view); $this->assertSame(array( 'forms' => array( 'name' => array( 'view_vars' => 'foo', 'config' => 'foo', 'default_data' => 'foo', 'submitted_data' => 'foo', 'children' => array( 'child' => array( 'view_vars' => 'bar', 'config' => 'bar', 'default_data' => 'bar', 'submitted_data' => 'bar', 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testFinalFormReliesOnFormViewStructure() { $this->form->add($this->createForm('first')); $this->form->add($this->createForm('second')); $this->view->children['second'] = $this->childView; $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'children' => array( 'first' => array( 'children' => array(), ), 'second' => array( 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); $this->dataCollector->buildFinalFormTree($this->form, $this->view); $this->assertSame(array( 'forms' => array( 'name' => array( 'children' => array( // "first" not present in FormView 'second' => array( 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testChildViewsCanBeWithoutCorrespondingChildForms() { // don't add $this->childForm to $this->form! $this->view->children['child'] = $this->childView; $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($this->childForm) ->will($this->returnValue(array('config' => 'bar'))); // explicitly call collectConfiguration(), since $this->childForm is not // contained in the form tree $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->collectConfiguration($this->childForm); $this->dataCollector->buildFinalFormTree($this->form, $this->view); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'children' => array( 'child' => array( // no "config" key 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testChildViewsWithoutCorrespondingChildFormsMayBeExplicitlyAssociated() { // don't add $this->childForm to $this->form! $this->view->children['child'] = $this->childView; // but associate the two $this->dataCollector->associateFormWithView($this->childForm, $this->childView); $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($this->childForm) ->will($this->returnValue(array('config' => 'bar'))); // explicitly call collectConfiguration(), since $this->childForm is not // contained in the form tree $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->collectConfiguration($this->childForm); $this->dataCollector->buildFinalFormTree($this->form, $this->view); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'children' => array( 'child' => array( 'config' => 'bar', 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testCollectSubmittedDataCountsErrors() { $form1 = $this->createForm('form1'); $childForm1 = $this->createForm('child1'); $form2 = $this->createForm('form2'); $form1->add($childForm1); $this->dataExtractor->expects($this->at(0)) ->method('extractSubmittedData') ->with($form1) ->will($this->returnValue(array('errors' => array('foo')))); $this->dataExtractor->expects($this->at(1)) ->method('extractSubmittedData') ->with($childForm1) ->will($this->returnValue(array('errors' => array('bar', 'bam')))); $this->dataExtractor->expects($this->at(2)) ->method('extractSubmittedData') ->with($form2) ->will($this->returnValue(array('errors' => array('baz')))); $this->dataCollector->collectSubmittedData($form1); $data = $this->dataCollector->getData(); $this->assertSame(3, $data['nb_errors']); $this->dataCollector->collectSubmittedData($form2); $data = $this->dataCollector->getData(); $this->assertSame(4, $data['nb_errors']); } private function createForm($name) { $builder = new FormBuilder($name, null, $this->dispatcher, $this->factory); $builder->setCompound(true); $builder->setDataMapper($this->dataMapper); return $builder->getForm(); } } PK!b,<<]test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\DataCollector; use Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension; /** * @covers Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension */ class DataCollectorExtensionTest extends \PHPUnit_Framework_TestCase { /** * @var DataCollectorExtension */ private $extension; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataCollector; public function setUp() { $this->dataCollector = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface'); $this->extension = new DataCollectorExtension($this->dataCollector); } public function testLoadTypeExtensions() { $typeExtensions = $this->extension->getTypeExtensions('form'); $this->assertInternalType('array', $typeExtensions); $this->assertCount(1, $typeExtensions); $this->assertInstanceOf('Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension', array_shift($typeExtensions)); } } PK!{(,,Xtest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\DataCollector; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\DataCollector\FormDataExtractor; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; class FormDataExtractorTest_SimpleValueExporter extends ValueExporter { /** * {@inheritdoc} */ public function exportValue($value) { return var_export($value, true); } } /** * @author Bernhard Schussek */ class FormDataExtractorTest extends \PHPUnit_Framework_TestCase { /** * @var FormDataExtractorTest_SimpleValueExporter */ private $valueExporter; /** * @var FormDataExtractor */ private $dataExtractor; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; protected function setUp() { $this->valueExporter = new FormDataExtractorTest_SimpleValueExporter(); $this->dataExtractor = new FormDataExtractor($this->valueExporter); $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); } public function testExtractConfiguration() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $type->expects($this->any()) ->method('getName') ->will($this->returnValue('type_name')); $type->expects($this->any()) ->method('getInnerType') ->will($this->returnValue(new \stdClass())); $form = $this->createBuilder('name') ->setType($type) ->getForm(); $this->assertSame(array( 'id' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', 'passed_options' => array(), 'resolved_options' => array(), ), $this->dataExtractor->extractConfiguration($form)); } public function testExtractConfigurationSortsPassedOptions() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $type->expects($this->any()) ->method('getName') ->will($this->returnValue('type_name')); $type->expects($this->any()) ->method('getInnerType') ->will($this->returnValue(new \stdClass())); $options = array( 'b' => 'foo', 'a' => 'bar', 'c' => 'baz', ); $form = $this->createBuilder('name') ->setType($type) // passed options are stored in an attribute by // ResolvedTypeDataCollectorProxy ->setAttribute('data_collector/passed_options', $options) ->getForm(); $this->assertSame(array( 'id' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', 'passed_options' => array( 'a' => "'bar'", 'b' => "'foo'", 'c' => "'baz'", ), 'resolved_options' => array(), ), $this->dataExtractor->extractConfiguration($form)); } public function testExtractConfigurationSortsResolvedOptions() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $type->expects($this->any()) ->method('getName') ->will($this->returnValue('type_name')); $type->expects($this->any()) ->method('getInnerType') ->will($this->returnValue(new \stdClass())); $options = array( 'b' => 'foo', 'a' => 'bar', 'c' => 'baz', ); $form = $this->createBuilder('name', $options) ->setType($type) ->getForm(); $this->assertSame(array( 'id' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', 'passed_options' => array(), 'resolved_options' => array( 'a' => "'bar'", 'b' => "'foo'", 'c' => "'baz'", ), ), $this->dataExtractor->extractConfiguration($form)); } public function testExtractConfigurationBuildsIdRecursively() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $type->expects($this->any()) ->method('getName') ->will($this->returnValue('type_name')); $type->expects($this->any()) ->method('getInnerType') ->will($this->returnValue(new \stdClass())); $grandParent = $this->createBuilder('grandParent') ->setCompound(true) ->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')) ->getForm(); $parent = $this->createBuilder('parent') ->setCompound(true) ->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')) ->getForm(); $form = $this->createBuilder('name') ->setType($type) ->getForm(); $grandParent->add($parent); $parent->add($form); $this->assertSame(array( 'id' => 'grandParent_parent_name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', 'passed_options' => array(), 'resolved_options' => array(), ), $this->dataExtractor->extractConfiguration($form)); } public function testExtractDefaultData() { $form = $this->createBuilder('name')->getForm(); $form->setData('Foobar'); $this->assertSame(array( 'default_data' => array( 'norm' => "'Foobar'", ), 'submitted_data' => array(), ), $this->dataExtractor->extractDefaultData($form)); } public function testExtractDefaultDataStoresModelDataIfDifferent() { $form = $this->createBuilder('name') ->addModelTransformer(new FixedDataTransformer(array( 'Foo' => 'Bar' ))) ->getForm(); $form->setData('Foo'); $this->assertSame(array( 'default_data' => array( 'norm' => "'Bar'", 'model' => "'Foo'", ), 'submitted_data' => array(), ), $this->dataExtractor->extractDefaultData($form)); } public function testExtractDefaultDataStoresViewDataIfDifferent() { $form = $this->createBuilder('name') ->addViewTransformer(new FixedDataTransformer(array( 'Foo' => 'Bar' ))) ->getForm(); $form->setData('Foo'); $this->assertSame(array( 'default_data' => array( 'norm' => "'Foo'", 'view' => "'Bar'", ), 'submitted_data' => array(), ), $this->dataExtractor->extractDefaultData($form)); } public function testExtractSubmittedData() { $form = $this->createBuilder('name')->getForm(); $form->submit('Foobar'); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Foobar'", ), 'errors' => array(), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractSubmittedDataStoresModelDataIfDifferent() { $form = $this->createBuilder('name') ->addModelTransformer(new FixedDataTransformer(array( 'Foo' => 'Bar', '' => '', ))) ->getForm(); $form->submit('Bar'); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Bar'", 'model' => "'Foo'", ), 'errors' => array(), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractSubmittedDataStoresViewDataIfDifferent() { $form = $this->createBuilder('name') ->addViewTransformer(new FixedDataTransformer(array( 'Foo' => 'Bar', '' => '', ))) ->getForm(); $form->submit('Bar'); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Foo'", 'view' => "'Bar'", ), 'errors' => array(), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractSubmittedDataStoresErrors() { $form = $this->createBuilder('name')->getForm(); $form->submit('Foobar'); $form->addError(new FormError('Invalid!')); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Foobar'", ), 'errors' => array( array('message' => 'Invalid!'), ), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractSubmittedDataRemembersIfNonSynchronized() { $form = $this->createBuilder('name') ->addModelTransformer(new CallbackTransformer( function () {}, function () { throw new TransformationFailedException('Fail!'); } )) ->getForm(); $form->submit('Foobar'); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Foobar'", 'model' => 'NULL', ), 'errors' => array(), 'synchronized' => 'false', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractViewVariables() { $view = new FormView(); $view->vars = array( 'b' => 'foo', 'a' => 'bar', 'c' => 'baz', 'id' => 'foo_bar', ); $this->assertSame(array( 'id' => 'foo_bar', 'view_vars' => array( 'a' => "'bar'", 'b' => "'foo'", 'c' => "'baz'", 'id' => "'foo_bar'", ), ), $this->dataExtractor->extractViewVariables($view)); } /** * @param string $name * @param array $options * * @return FormBuilder */ private function createBuilder($name, array $options = array()) { return new FormBuilder($name, null, $this->dispatcher, $this->factory, $options); } } PK!qftest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\DataCollector\Type; use Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension; class DataCollectorTypeExtensionTest extends \PHPUnit_Framework_TestCase { /** * @var DataCollectorTypeExtension */ private $extension; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataCollector; public function setUp() { $this->dataCollector = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface'); $this->extension = new DataCollectorTypeExtension($this->dataCollector); } public function testGetExtendedType() { $this->assertEquals('form', $this->extension->getExtendedType()); } public function testBuildForm() { $builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface'); $builder->expects($this->atLeastOnce()) ->method('addEventSubscriber') ->with($this->isInstanceOf('Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener')); $this->extension->buildForm($builder, array()); } } PK!'@test/Form/Symfony/Component/Form/Tests/AbstractExtensionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Form\Tests\Fixtures\FooType; class AbstractExtensionTest extends \PHPUnit_Framework_TestCase { public function testHasType() { $loader = new ConcreteExtension(); $this->assertTrue($loader->hasType('foo')); $this->assertFalse($loader->hasType('bar')); } public function testGetType() { $loader = new ConcreteExtension(); $this->assertInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType', $loader->getType('foo')); } } class ConcreteExtension extends AbstractExtension { protected function loadTypes() { return array(new FooType()); } protected function loadTypeGuesser() { } } PK!g 331test/Form/Symfony/Component/Form/phpunit.xml.distnu[ ./Tests/ ./ ./Tests ./vendor PK!ԍZP5P5Itest/Security/Symfony/Component/Security/Acl/Tests/Voter/AclVoterTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Voter; use Symfony\Component\Security\Acl\Exception\NoAceFoundException; use Symfony\Component\Security\Acl\Voter\FieldVote; use Symfony\Component\Security\Acl\Exception\AclNotFoundException; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Acl\Voter\AclVoter; class AclVoterTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getSupportsAttributeTests */ public function testSupportsAttribute($attribute, $supported) { list($voter,, $permissionMap,,) = $this->getVoter(); $permissionMap ->expects($this->once()) ->method('contains') ->with($this->identicalTo($attribute)) ->will($this->returnValue($supported)) ; $this->assertSame($supported, $voter->supportsAttribute($attribute)); } public function getSupportsAttributeTests() { return array( array('foo', true), array('foo', false), ); } /** * @dataProvider getSupportsClassTests */ public function testSupportsClass($class) { list($voter,,,,) = $this->getVoter(); $this->assertTrue($voter->supportsClass($class)); } public function getSupportsClassTests() { return array( array('foo'), array('bar'), array('moo'), ); } public function testVote() { list($voter,, $permissionMap,,) = $this->getVoter(); $permissionMap ->expects($this->atLeastOnce()) ->method('getMasks') ->will($this->returnValue(null)) ; $this->assertSame(VoterInterface::ACCESS_ABSTAIN, $voter->vote($this->getToken(), null, array('VIEW', 'EDIT', 'DELETE'))); } /** * @dataProvider getTrueFalseTests */ public function testVoteWhenNoObjectIsPassed($allowIfObjectIdentityUnavailable) { list($voter,, $permissionMap,,) = $this->getVoter($allowIfObjectIdentityUnavailable); $permissionMap ->expects($this->once()) ->method('getMasks') ->will($this->returnValue(array())) ; if ($allowIfObjectIdentityUnavailable) { $vote = VoterInterface::ACCESS_GRANTED; } else { $vote = VoterInterface::ACCESS_ABSTAIN; } $this->assertSame($vote, $voter->vote($this->getToken(), null, array('VIEW'))); } /** * @dataProvider getTrueFalseTests */ public function testVoteWhenOidStrategyReturnsNull($allowIfUnavailable) { list($voter,, $permissionMap, $oidStrategy,) = $this->getVoter($allowIfUnavailable); $permissionMap ->expects($this->once()) ->method('getMasks') ->will($this->returnValue(array())) ; $oidStrategy ->expects($this->once()) ->method('getObjectIdentity') ->will($this->returnValue(null)) ; if ($allowIfUnavailable) { $vote = VoterInterface::ACCESS_GRANTED; } else { $vote = VoterInterface::ACCESS_ABSTAIN; } $this->assertSame($vote, $voter->vote($this->getToken(), new \stdClass(), array('VIEW'))); } public function getTrueFalseTests() { return array(array(true), array(false)); } public function testVoteNoAclFound() { list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter(); $permissionMap ->expects($this->once()) ->method('getMasks') ->will($this->returnValue(array())) ; $oidStrategy ->expects($this->once()) ->method('getObjectIdentity') ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo'))) ; $sidStrategy ->expects($this->once()) ->method('getSecurityIdentities') ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO')))) ; $provider ->expects($this->once()) ->method('findAcl') ->with($this->equalTo($oid), $this->equalTo($sids)) ->will($this->throwException(new AclNotFoundException('Not found.'))) ; $this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new \stdClass(), array('VIEW'))); } /** * @dataProvider getTrueFalseTests */ public function testVoteGrantsAccess($grant) { list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter(); $permissionMap ->expects($this->once()) ->method('getMasks') ->with($this->equalTo('VIEW')) ->will($this->returnValue($masks = array(1, 2, 3))) ; $oidStrategy ->expects($this->once()) ->method('getObjectIdentity') ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo'))) ; $sidStrategy ->expects($this->once()) ->method('getSecurityIdentities') ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO')))) ; $provider ->expects($this->once()) ->method('findAcl') ->with($this->equalTo($oid), $this->equalTo($sids)) ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface'))) ; $acl ->expects($this->once()) ->method('isGranted') ->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse()) ->will($this->returnValue($grant)) ; if ($grant) { $vote = VoterInterface::ACCESS_GRANTED; } else { $vote = VoterInterface::ACCESS_DENIED; } $this->assertSame($vote, $voter->vote($this->getToken(), new \stdClass(), array('VIEW'))); } public function testVoteNoAceFound() { list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter(); $permissionMap ->expects($this->once()) ->method('getMasks') ->with($this->equalTo('VIEW')) ->will($this->returnValue($masks = array(1, 2, 3))) ; $oidStrategy ->expects($this->once()) ->method('getObjectIdentity') ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo'))) ; $sidStrategy ->expects($this->once()) ->method('getSecurityIdentities') ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO')))) ; $provider ->expects($this->once()) ->method('findAcl') ->with($this->equalTo($oid), $this->equalTo($sids)) ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface'))) ; $acl ->expects($this->once()) ->method('isGranted') ->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse()) ->will($this->throwException(new NoAceFoundException('No ACE'))) ; $this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new \stdClass(), array('VIEW'))); } /** * @dataProvider getTrueFalseTests */ public function testVoteGrantsFieldAccess($grant) { list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter(); $permissionMap ->expects($this->once()) ->method('getMasks') ->with($this->equalTo('VIEW')) ->will($this->returnValue($masks = array(1, 2, 3))) ; $oidStrategy ->expects($this->once()) ->method('getObjectIdentity') ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo'))) ; $sidStrategy ->expects($this->once()) ->method('getSecurityIdentities') ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO')))) ; $provider ->expects($this->once()) ->method('findAcl') ->with($this->equalTo($oid), $this->equalTo($sids)) ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface'))) ; $acl ->expects($this->once()) ->method('isFieldGranted') ->with($this->identicalTo('foo'), $this->identicalTo($masks), $this->equalTo($sids), $this->isFalse()) ->will($this->returnValue($grant)) ; if ($grant) { $vote = VoterInterface::ACCESS_GRANTED; } else { $vote = VoterInterface::ACCESS_DENIED; } $this->assertSame($vote, $voter->vote($this->getToken(), new FieldVote(new \stdClass(), 'foo'), array('VIEW'))); } public function testVoteNoFieldAceFound() { list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter(); $permissionMap ->expects($this->once()) ->method('getMasks') ->with($this->equalTo('VIEW')) ->will($this->returnValue($masks = array(1, 2, 3))) ; $oidStrategy ->expects($this->once()) ->method('getObjectIdentity') ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo'))) ; $sidStrategy ->expects($this->once()) ->method('getSecurityIdentities') ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO')))) ; $provider ->expects($this->once()) ->method('findAcl') ->with($this->equalTo($oid), $this->equalTo($sids)) ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface'))) ; $acl ->expects($this->once()) ->method('isFieldGranted') ->with($this->identicalTo('foo'), $this->identicalTo($masks), $this->equalTo($sids), $this->isFalse()) ->will($this->throwException(new NoAceFoundException('No ACE'))) ; $this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new FieldVote(new \stdClass(), 'foo'), array('VIEW'))); } public function testWhenReceivingAnObjectIdentityInterfaceWeDontRetrieveANewObjectIdentity() { list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter(); $oid = new ObjectIdentity('someID','someType'); $permissionMap ->expects($this->once()) ->method('getMasks') ->with($this->equalTo('VIEW')) ->will($this->returnValue($masks = array(1, 2, 3))) ; $oidStrategy ->expects($this->never()) ->method('getObjectIdentity') ; $sidStrategy ->expects($this->once()) ->method('getSecurityIdentities') ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO')))) ; $provider ->expects($this->once()) ->method('findAcl') ->with($this->equalTo($oid), $this->equalTo($sids)) ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface'))) ; $acl ->expects($this->once()) ->method('isGranted') ->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse()) ->will($this->throwException(new NoAceFoundException('No ACE'))) ; $voter->vote($this->getToken(), $oid, array('VIEW')); } protected function getToken() { return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); } protected function getVoter($allowIfObjectIdentityUnavailable = true) { $provider = $this->getMock('Symfony\Component\Security\Acl\Model\AclProviderInterface'); $permissionMap = $this->getMock('Symfony\Component\Security\Acl\Permission\PermissionMapInterface'); $oidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface'); $sidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface'); return array( new AclVoter($provider, $oidStrategy, $sidStrategy, $permissionMap, null, $allowIfObjectIdentityUnavailable), $provider, $permissionMap, $oidStrategy, $sidStrategy, ); } } PK!޻>QQRtest/Security/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Dbal; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Model\FieldEntryInterface; use Symfony\Component\Security\Acl\Model\AuditableEntryInterface; use Symfony\Component\Security\Acl\Model\EntryInterface; use Symfony\Component\Security\Acl\Domain\Entry; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Domain\Acl; use Symfony\Component\Security\Acl\Exception\AclNotFoundException; use Symfony\Component\Security\Acl\Exception\ConcurrentModificationException; use Symfony\Component\Security\Acl\Dbal\AclProvider; use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy; use Symfony\Component\Security\Acl\Dbal\MutableAclProvider; use Symfony\Component\Security\Acl\Dbal\Schema; use Doctrine\DBAL\DriverManager; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; class MutableAclProviderTest extends \PHPUnit_Framework_TestCase { protected $con; public static function assertAceEquals(EntryInterface $a, EntryInterface $b) { self::assertInstanceOf(get_class($a), $b); foreach (array('getId', 'getMask', 'getStrategy', 'isGranting') as $getter) { self::assertSame($a->$getter(), $b->$getter()); } self::assertTrue($a->getSecurityIdentity()->equals($b->getSecurityIdentity())); self::assertSame($a->getAcl()->getId(), $b->getAcl()->getId()); if ($a instanceof AuditableEntryInterface) { self::assertSame($a->isAuditSuccess(), $b->isAuditSuccess()); self::assertSame($a->isAuditFailure(), $b->isAuditFailure()); } if ($a instanceof FieldEntryInterface) { self::assertSame($a->getField(), $b->getField()); } } /** * @expectedException \Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException */ public function testCreateAclThrowsExceptionWhenAclAlreadyExists() { $provider = $this->getProvider(); $oid = new ObjectIdentity('123456', 'FOO'); $provider->createAcl($oid); $provider->createAcl($oid); } public function testCreateAcl() { $provider = $this->getProvider(); $oid = new ObjectIdentity('123456', 'FOO'); $acl = $provider->createAcl($oid); $cachedAcl = $provider->findAcl($oid); $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl); $this->assertSame($acl, $cachedAcl); $this->assertTrue($acl->getObjectIdentity()->equals($oid)); } public function testDeleteAcl() { $provider = $this->getProvider(); $oid = new ObjectIdentity(1, 'Foo'); $acl = $provider->createAcl($oid); $provider->deleteAcl($oid); $loadedAcls = $this->getField($provider, 'loadedAcls'); $this->assertCount(0, $loadedAcls['Foo']); try { $provider->findAcl($oid); $this->fail('ACL has not been properly deleted.'); } catch (AclNotFoundException $notFound) { } } public function testDeleteAclDeletesChildren() { $provider = $this->getProvider(); $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo')); $parentAcl = $provider->createAcl(new ObjectIdentity(2, 'Foo')); $acl->setParentAcl($parentAcl); $provider->updateAcl($acl); $provider->deleteAcl($parentAcl->getObjectIdentity()); try { $provider->findAcl(new ObjectIdentity(1, 'Foo')); $this->fail('Child-ACLs have not been deleted.'); } catch (AclNotFoundException $notFound) { } } public function testFindAclsAddsPropertyListener() { $provider = $this->getProvider(); $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo')); $propertyChanges = $this->getField($provider, 'propertyChanges'); $this->assertCount(1, $propertyChanges); $this->assertTrue($propertyChanges->contains($acl)); $this->assertEquals(array(), $propertyChanges->offsetGet($acl)); $listeners = $this->getField($acl, 'listeners'); $this->assertSame($provider, $listeners[0]); } public function testFindAclsAddsPropertyListenerOnlyOnce() { $provider = $this->getProvider(); $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo')); $acl = $provider->findAcl(new ObjectIdentity(1, 'Foo')); $propertyChanges = $this->getField($provider, 'propertyChanges'); $this->assertCount(1, $propertyChanges); $this->assertTrue($propertyChanges->contains($acl)); $this->assertEquals(array(), $propertyChanges->offsetGet($acl)); $listeners = $this->getField($acl, 'listeners'); $this->assertCount(1, $listeners); $this->assertSame($provider, $listeners[0]); } public function testFindAclsAddsPropertyListenerToParentAcls() { $provider = $this->getProvider(); $this->importAcls($provider, array( 'main' => array( 'object_identifier' => '1', 'class_type' => 'foo', 'parent_acl' => 'parent', ), 'parent' => array( 'object_identifier' => '1', 'class_type' => 'anotherFoo', ) )); $propertyChanges = $this->getField($provider, 'propertyChanges'); $this->assertCount(0, $propertyChanges); $acl = $provider->findAcl(new ObjectIdentity('1', 'foo')); $this->assertCount(2, $propertyChanges); $this->assertTrue($propertyChanges->contains($acl)); $this->assertTrue($propertyChanges->contains($acl->getParentAcl())); } /** * @expectedException \InvalidArgumentException */ public function testPropertyChangedDoesNotTrackUnmanagedAcls() { $provider = $this->getProvider(); $acl = new Acl(1, new ObjectIdentity(1, 'foo'), new PermissionGrantingStrategy(), array(), false); $provider->propertyChanged($acl, 'classAces', array(), array('foo')); } public function testPropertyChangedTracksChangesToAclProperties() { $provider = $this->getProvider(); $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo')); $propertyChanges = $this->getField($provider, 'propertyChanges'); $provider->propertyChanged($acl, 'entriesInheriting', false, true); $changes = $propertyChanges->offsetGet($acl); $this->assertTrue(isset($changes['entriesInheriting'])); $this->assertFalse($changes['entriesInheriting'][0]); $this->assertTrue($changes['entriesInheriting'][1]); $provider->propertyChanged($acl, 'entriesInheriting', true, false); $provider->propertyChanged($acl, 'entriesInheriting', false, true); $provider->propertyChanged($acl, 'entriesInheriting', true, false); $changes = $propertyChanges->offsetGet($acl); $this->assertFalse(isset($changes['entriesInheriting'])); } public function testPropertyChangedTracksChangesToAceProperties() { $provider = $this->getProvider(); $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo')); $ace = new Entry(1, $acl, new UserSecurityIdentity('foo', 'FooClass'), 'all', 1, true, true, true); $ace2 = new Entry(2, $acl, new UserSecurityIdentity('foo', 'FooClass'), 'all', 1, true, true, true); $propertyChanges = $this->getField($provider, 'propertyChanges'); $provider->propertyChanged($ace, 'mask', 1, 3); $changes = $propertyChanges->offsetGet($acl); $this->assertTrue(isset($changes['aces'])); $this->assertInstanceOf('\SplObjectStorage', $changes['aces']); $this->assertTrue($changes['aces']->contains($ace)); $aceChanges = $changes['aces']->offsetGet($ace); $this->assertTrue(isset($aceChanges['mask'])); $this->assertEquals(1, $aceChanges['mask'][0]); $this->assertEquals(3, $aceChanges['mask'][1]); $provider->propertyChanged($ace, 'strategy', 'all', 'any'); $changes = $propertyChanges->offsetGet($acl); $this->assertTrue(isset($changes['aces'])); $this->assertInstanceOf('\SplObjectStorage', $changes['aces']); $this->assertTrue($changes['aces']->contains($ace)); $aceChanges = $changes['aces']->offsetGet($ace); $this->assertTrue(isset($aceChanges['mask'])); $this->assertTrue(isset($aceChanges['strategy'])); $this->assertEquals('all', $aceChanges['strategy'][0]); $this->assertEquals('any', $aceChanges['strategy'][1]); $provider->propertyChanged($ace, 'mask', 3, 1); $changes = $propertyChanges->offsetGet($acl); $aceChanges = $changes['aces']->offsetGet($ace); $this->assertFalse(isset($aceChanges['mask'])); $this->assertTrue(isset($aceChanges['strategy'])); $provider->propertyChanged($ace2, 'mask', 1, 3); $provider->propertyChanged($ace, 'strategy', 'any', 'all'); $changes = $propertyChanges->offsetGet($acl); $this->assertTrue(isset($changes['aces'])); $this->assertFalse($changes['aces']->contains($ace)); $this->assertTrue($changes['aces']->contains($ace2)); $provider->propertyChanged($ace2, 'mask', 3, 4); $provider->propertyChanged($ace2, 'mask', 4, 1); $changes = $propertyChanges->offsetGet($acl); $this->assertFalse(isset($changes['aces'])); } /** * @expectedException \InvalidArgumentException */ public function testUpdateAclDoesNotAcceptUntrackedAcls() { $provider = $this->getProvider(); $acl = new Acl(1, new ObjectIdentity(1, 'Foo'), new PermissionGrantingStrategy(), array(), true); $provider->updateAcl($acl); } public function testUpdateDoesNothingWhenThereAreNoChanges() { $con = $this->getMock('Doctrine\DBAL\Connection', array(), array(), '', false); $con ->expects($this->never()) ->method('beginTransaction') ; $con ->expects($this->never()) ->method('executeQuery') ; $provider = new MutableAclProvider($con, new PermissionGrantingStrategy(), array()); $acl = new Acl(1, new ObjectIdentity(1, 'Foo'), new PermissionGrantingStrategy(), array(), true); $propertyChanges = $this->getField($provider, 'propertyChanges'); $propertyChanges->offsetSet($acl, array()); $provider->updateAcl($acl); } public function testUpdateAclThrowsExceptionOnConcurrentModificationOfSharedProperties() { $provider = $this->getProvider(); $acl1 = $provider->createAcl(new ObjectIdentity(1, 'Foo')); $acl2 = $provider->createAcl(new ObjectIdentity(2, 'Foo')); $acl3 = $provider->createAcl(new ObjectIdentity(1, 'AnotherFoo')); $sid = new RoleSecurityIdentity('ROLE_FOO'); $acl1->insertClassAce($sid, 1); $acl3->insertClassAce($sid, 1); $provider->updateAcl($acl1); $provider->updateAcl($acl3); $acl2->insertClassAce($sid, 16); $provider->updateAcl($acl2); $acl1->insertClassAce($sid, 3); $acl2->insertClassAce($sid, 5); try { $provider->updateAcl($acl1); $this->fail('Provider failed to detect a concurrent modification.'); } catch (ConcurrentModificationException $ex) { } } public function testUpdateAcl() { $provider = $this->getProvider(); $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo')); $sid = new UserSecurityIdentity('johannes', 'FooClass'); $acl->setEntriesInheriting(!$acl->isEntriesInheriting()); $acl->insertObjectAce($sid, 1); $acl->insertClassAce($sid, 5, 0, false); $acl->insertObjectAce($sid, 2, 1, true); $acl->insertClassFieldAce('field', $sid, 2, 0, true); $provider->updateAcl($acl); $acl->updateObjectAce(0, 3); $acl->deleteObjectAce(1); $acl->updateObjectAuditing(0, true, false); $acl->updateClassFieldAce(0, 'field', 15); $provider->updateAcl($acl); $reloadProvider = $this->getProvider(); $reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo')); $this->assertNotSame($acl, $reloadedAcl); $this->assertSame($acl->isEntriesInheriting(), $reloadedAcl->isEntriesInheriting()); $aces = $acl->getObjectAces(); $reloadedAces = $reloadedAcl->getObjectAces(); $this->assertEquals(count($aces), count($reloadedAces)); foreach ($aces as $index => $ace) { $this->assertAceEquals($ace, $reloadedAces[$index]); } } public function testUpdateAclWorksForChangingTheParentAcl() { $provider = $this->getProvider(); $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo')); $parentAcl = $provider->createAcl(new ObjectIdentity(1, 'AnotherFoo')); $acl->setParentAcl($parentAcl); $provider->updateAcl($acl); $reloadProvider = $this->getProvider(); $reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo')); $this->assertNotSame($acl, $reloadedAcl); $this->assertSame($parentAcl->getId(), $reloadedAcl->getParentAcl()->getId()); } public function testUpdateAclUpdatesChildAclsCorrectly() { $provider = $this->getProvider(); $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo')); $parentAcl = $provider->createAcl(new ObjectIdentity(1, 'Bar')); $acl->setParentAcl($parentAcl); $provider->updateAcl($acl); $parentParentAcl = $provider->createAcl(new ObjectIdentity(1, 'Baz')); $parentAcl->setParentAcl($parentParentAcl); $provider->updateAcl($parentAcl); $newParentParentAcl = $provider->createAcl(new ObjectIdentity(2, 'Baz')); $parentAcl->setParentAcl($newParentParentAcl); $provider->updateAcl($parentAcl); $reloadProvider = $this->getProvider(); $reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo')); $this->assertEquals($newParentParentAcl->getId(), $reloadedAcl->getParentAcl()->getParentAcl()->getId()); } public function testUpdateAclInsertingMultipleObjectFieldAcesThrowsDBConstraintViolations() { $provider = $this->getProvider(); $oid = new ObjectIdentity(1, 'Foo'); $sid1 = new UserSecurityIdentity('johannes', 'FooClass'); $sid2 = new UserSecurityIdentity('guilro', 'FooClass'); $sid3 = new UserSecurityIdentity('bmaz', 'FooClass'); $fieldName = 'fieldName'; $acl = $provider->createAcl($oid); $acl->insertObjectFieldAce($fieldName, $sid1, 4); $provider->updateAcl($acl); $acl = $provider->findAcl($oid); $acl->insertObjectFieldAce($fieldName, $sid2, 4); $provider->updateAcl($acl); $acl = $provider->findAcl($oid); $acl->insertObjectFieldAce($fieldName, $sid3, 4); $provider->updateAcl($acl); } public function testUpdateAclDeletingObjectFieldAcesThrowsDBConstraintViolations() { $provider = $this->getProvider(); $oid = new ObjectIdentity(1, 'Foo'); $sid1 = new UserSecurityIdentity('johannes', 'FooClass'); $sid2 = new UserSecurityIdentity('guilro', 'FooClass'); $sid3 = new UserSecurityIdentity('bmaz', 'FooClass'); $fieldName = 'fieldName'; $acl = $provider->createAcl($oid); $acl->insertObjectFieldAce($fieldName, $sid1, 4); $provider->updateAcl($acl); $acl = $provider->findAcl($oid); $acl->insertObjectFieldAce($fieldName, $sid2, 4); $provider->updateAcl($acl); $index = 0; $acl->deleteObjectFieldAce($index, $fieldName); $provider->updateAcl($acl); $acl = $provider->findAcl($oid); $acl->insertObjectFieldAce($fieldName, $sid3, 4); $provider->updateAcl($acl); } /** * Data must have the following format: * array( * *name* => array( * 'object_identifier' => *required* * 'class_type' => *required*, * 'parent_acl' => *name (optional)* * ), * ) * * @param AclProvider $provider * @param array $data * @throws \InvalidArgumentException * @throws \Exception */ protected function importAcls(AclProvider $provider, array $data) { $aclIds = $parentAcls = array(); $con = $this->getField($provider, 'connection'); $con->beginTransaction(); try { foreach ($data as $name => $aclData) { if (!isset($aclData['object_identifier'], $aclData['class_type'])) { throw new \InvalidArgumentException('"object_identifier", and "class_type" must be present.'); } $this->callMethod($provider, 'createObjectIdentity', array(new ObjectIdentity($aclData['object_identifier'], $aclData['class_type']))); $aclId = $con->lastInsertId(); $aclIds[$name] = $aclId; $sql = $this->callMethod($provider, 'getInsertObjectIdentityRelationSql', array($aclId, $aclId)); $con->executeQuery($sql); if (isset($aclData['parent_acl'])) { if (isset($aclIds[$aclData['parent_acl']])) { $con->executeQuery("UPDATE acl_object_identities SET parent_object_identity_id = ".$aclIds[$aclData['parent_acl']]." WHERE id = ".$aclId); $con->executeQuery($this->callMethod($provider, 'getInsertObjectIdentityRelationSql', array($aclId, $aclIds[$aclData['parent_acl']]))); } else { $parentAcls[$aclId] = $aclData['parent_acl']; } } } foreach ($parentAcls as $aclId => $name) { if (!isset($aclIds[$name])) { throw new \InvalidArgumentException(sprintf('"%s" does not exist.', $name)); } $con->executeQuery(sprintf("UPDATE acl_object_identities SET parent_object_identity_id = %d WHERE id = %d", $aclIds[$name], $aclId)); $con->executeQuery($this->callMethod($provider, 'getInsertObjectIdentityRelationSql', array($aclId, $aclIds[$name]))); } $con->commit(); } catch (\Exception $e) { $con->rollBack(); throw $e; } } protected function callMethod($object, $method, array $args) { $method = new \ReflectionMethod($object, $method); $method->setAccessible(true); return $method->invokeArgs($object, $args); } protected function setUp() { if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) { self::markTestSkipped('This test requires SQLite support in your environment'); } $this->con = DriverManager::getConnection(array( 'driver' => 'pdo_sqlite', 'memory' => true, )); // import the schema $schema = new Schema($this->getOptions()); foreach ($schema->toSql($this->con->getDatabasePlatform()) as $sql) { $this->con->exec($sql); } } protected function tearDown() { $this->con = null; } protected function getField($object, $field) { $reflection = new \ReflectionProperty($object, $field); $reflection->setAccessible(true); return $reflection->getValue($object); } public function setField($object, $field, $value) { $reflection = new \ReflectionProperty($object, $field); $reflection->setAccessible(true); $reflection->setValue($object, $value); $reflection->setAccessible(false); } protected function getOptions() { return array( 'oid_table_name' => 'acl_object_identities', 'oid_ancestors_table_name' => 'acl_object_identity_ancestors', 'class_table_name' => 'acl_classes', 'sid_table_name' => 'acl_security_identities', 'entry_table_name' => 'acl_entries', ); } protected function getStrategy() { return new PermissionGrantingStrategy(); } protected function getProvider($cache = null) { return new MutableAclProvider($this->con, $this->getStrategy(), $this->getOptions(), $cache); } } PK!  Ttest/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Dbal; use Symfony\Component\Security\Acl\Dbal\AclProvider; use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Acl\Dbal\Schema; use Doctrine\DBAL\DriverManager; /** * @group benchmark */ class AclProviderBenchmarkTest extends \PHPUnit_Framework_TestCase { /** @var \Doctrine\DBAL\Connection */ protected $con; protected $insertClassStmt; protected $insertSidStmt; protected $insertOidAncestorStmt; protected $insertOidStmt; protected $insertEntryStmt; protected function setUp() { try { $this->con = DriverManager::getConnection(array( 'driver' => 'pdo_mysql', 'host' => 'localhost', 'user' => 'root', 'dbname' => 'testdb', )); $this->con->connect(); } catch (\Exception $e) { $this->markTestSkipped('Unable to connect to the database: '.$e->getMessage()); } } protected function tearDown() { $this->con = null; } public function testFindAcls() { // $this->generateTestData(); // get some random test object identities from the database $oids = array(); $stmt = $this->con->executeQuery("SELECT object_identifier, class_type FROM acl_object_identities o INNER JOIN acl_classes c ON c.id = o.class_id ORDER BY RAND() LIMIT 25"); foreach ($stmt->fetchAll() as $oid) { $oids[] = new ObjectIdentity($oid['object_identifier'], $oid['class_type']); } $provider = $this->getProvider(); $start = microtime(true); $provider->findAcls($oids); $time = microtime(true) - $start; echo "Total Time: ".$time."s\n"; } /** * This generates a huge amount of test data to be used mainly for benchmarking * purposes, not so much for testing. That's why it's not called by default. */ protected function generateTestData() { $sm = $this->con->getSchemaManager(); $sm->dropAndCreateDatabase('testdb'); $this->con->exec("USE testdb"); // import the schema $schema = new Schema($options = $this->getOptions()); foreach ($schema->toSql($this->con->getDatabasePlatform()) as $sql) { $this->con->exec($sql); } // setup prepared statements $this->insertClassStmt = $this->con->prepare('INSERT INTO acl_classes (id, class_type) VALUES (?, ?)'); $this->insertSidStmt = $this->con->prepare('INSERT INTO acl_security_identities (id, identifier, username) VALUES (?, ?, ?)'); $this->insertOidStmt = $this->con->prepare('INSERT INTO acl_object_identities (id, class_id, object_identifier, parent_object_identity_id, entries_inheriting) VALUES (?, ?, ?, ?, ?)'); $this->insertEntryStmt = $this->con->prepare('INSERT INTO acl_entries (id, class_id, object_identity_id, field_name, ace_order, security_identity_id, mask, granting, granting_strategy, audit_success, audit_failure) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); $this->insertOidAncestorStmt = $this->con->prepare('INSERT INTO acl_object_identity_ancestors (object_identity_id, ancestor_id) VALUES (?, ?)'); for ($i=0; $i<40000; $i++) { $this->generateAclHierarchy(); } } protected function generateAclHierarchy() { $rootId = $this->generateAcl($this->chooseClassId(), null, array()); $this->generateAclLevel(rand(1, 15), $rootId, array($rootId)); } protected function generateAclLevel($depth, $parentId, $ancestors) { $level = count($ancestors); for ($i=0,$t=rand(1, 10); $i<$t; $i++) { $id = $this->generateAcl($this->chooseClassId(), $parentId, $ancestors); if ($level < $depth) { $this->generateAclLevel($depth, $id, array_merge($ancestors, array($id))); } } } protected function chooseClassId() { static $id = 1000; if ($id === 1000 || ($id < 1500 && rand(0, 1))) { $this->insertClassStmt->execute(array($id, $this->getRandomString(rand(20, 100), 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\\_'))); $id += 1; return $id-1; } else { return rand(1000, $id-1); } } protected function generateAcl($classId, $parentId, $ancestors) { static $id = 1000; $this->insertOidStmt->execute(array( $id, $classId, $this->getRandomString(rand(20, 50)), $parentId, rand(0, 1), )); $this->insertOidAncestorStmt->execute(array($id, $id)); foreach ($ancestors as $ancestor) { $this->insertOidAncestorStmt->execute(array($id, $ancestor)); } $this->generateAces($classId, $id); $id += 1; return $id-1; } protected function chooseSid() { static $id = 1000; if ($id === 1000 || ($id < 11000 && rand(0, 1))) { $this->insertSidStmt->execute(array( $id, $this->getRandomString(rand(5, 30)), rand(0, 1) )); $id += 1; return $id-1; } else { return rand(1000, $id-1); } } protected function generateAces($classId, $objectId) { static $id = 1000; $sids = array(); $fieldOrder = array(); for ($i=0; $i<=30; $i++) { $fieldName = rand(0, 1) ? null : $this->getRandomString(rand(10, 20)); do { $sid = $this->chooseSid(); } while (array_key_exists($sid, $sids) && in_array($fieldName, $sids[$sid], true)); $fieldOrder[$fieldName] = array_key_exists($fieldName, $fieldOrder) ? $fieldOrder[$fieldName]+1 : 0; if (!isset($sids[$sid])) { $sids[$sid] = array(); } $sids[$sid][] = $fieldName; $strategy = rand(0, 2); if ($strategy === 0) { $strategy = PermissionGrantingStrategy::ALL; } elseif ($strategy === 1) { $strategy = PermissionGrantingStrategy::ANY; } else { $strategy = PermissionGrantingStrategy::EQUAL; } // id, cid, oid, field, order, sid, mask, granting, strategy, a success, a failure $this->insertEntryStmt->execute(array( $id, $classId, rand(0, 5) ? $objectId : null, $fieldName, $fieldOrder[$fieldName], $sid, $this->generateMask(), rand(0, 1), $strategy, rand(0, 1), rand(0, 1), )); $id += 1; } } protected function generateMask() { $i = rand(1, 30); $mask = 0; while ($i <= 30) { $mask |= 1 << rand(0, 30); $i++; } return $mask; } protected function getRandomString($length, $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') { $s = ''; $cLength = strlen($chars); while (strlen($s) < $length) { $s .= $chars[mt_rand(0, $cLength-1)]; } return $s; } protected function getOptions() { return array( 'oid_table_name' => 'acl_object_identities', 'oid_ancestors_table_name' => 'acl_object_identity_ancestors', 'class_table_name' => 'acl_classes', 'sid_table_name' => 'acl_security_identities', 'entry_table_name' => 'acl_entries', ); } protected function getStrategy() { return new PermissionGrantingStrategy(); } protected function getProvider() { return new AclProvider($this->con, $this->getStrategy(), $this->getOptions()); } } PK!'(''Ktest/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Dbal; use Symfony\Component\Security\Acl\Dbal\AclProvider; use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Acl\Dbal\Schema; use Doctrine\DBAL\DriverManager; class AclProviderTest extends \PHPUnit_Framework_TestCase { protected $con; protected $insertClassStmt; protected $insertEntryStmt; protected $insertOidStmt; protected $insertOidAncestorStmt; protected $insertSidStmt; /** * @expectedException \Symfony\Component\Security\Acl\Exception\AclNotFoundException * @expectedMessage There is no ACL for the given object identity. */ public function testFindAclThrowsExceptionWhenNoAclExists() { $this->getProvider()->findAcl(new ObjectIdentity('foo', 'foo')); } public function testFindAclsThrowsExceptionUnlessAnACLIsFoundForEveryOID() { $oids = array(); $oids[] = new ObjectIdentity('1', 'foo'); $oids[] = new ObjectIdentity('foo', 'foo'); try { $this->getProvider()->findAcls($oids); $this->fail('Provider did not throw an expected exception.'); } catch (\Exception $ex) { $this->assertInstanceOf('Symfony\Component\Security\Acl\Exception\AclNotFoundException', $ex); $this->assertInstanceOf('Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException', $ex); $partialResult = $ex->getPartialResult(); $this->assertTrue($partialResult->contains($oids[0])); $this->assertFalse($partialResult->contains($oids[1])); } } public function testFindAcls() { $oids = array(); $oids[] = new ObjectIdentity('1', 'foo'); $oids[] = new ObjectIdentity('2', 'foo'); $provider = $this->getProvider(); $acls = $provider->findAcls($oids); $this->assertInstanceOf('SplObjectStorage', $acls); $this->assertCount(2, $acls); $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl0 = $acls->offsetGet($oids[0])); $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl1 = $acls->offsetGet($oids[1])); $this->assertTrue($oids[0]->equals($acl0->getObjectIdentity())); $this->assertTrue($oids[1]->equals($acl1->getObjectIdentity())); } public function testFindAclsWithDifferentTypes() { $oids = array(); $oids[] = new ObjectIdentity('123', 'Bundle\SomeVendor\MyBundle\Entity\SomeEntity'); $oids[] = new ObjectIdentity('123', 'Bundle\MyBundle\Entity\AnotherEntity'); $provider = $this->getProvider(); $acls = $provider->findAcls($oids); $this->assertInstanceOf('SplObjectStorage', $acls); $this->assertCount(2, $acls); $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl0 = $acls->offsetGet($oids[0])); $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl1 = $acls->offsetGet($oids[1])); $this->assertTrue($oids[0]->equals($acl0->getObjectIdentity())); $this->assertTrue($oids[1]->equals($acl1->getObjectIdentity())); } public function testFindAclCachesAclInMemory() { $oid = new ObjectIdentity('1', 'foo'); $provider = $this->getProvider(); $acl = $provider->findAcl($oid); $this->assertSame($acl, $cAcl = $provider->findAcl($oid)); $cAces = $cAcl->getObjectAces(); foreach ($acl->getObjectAces() as $index => $ace) { $this->assertSame($ace, $cAces[$index]); } } public function testFindAcl() { $oid = new ObjectIdentity('1', 'foo'); $provider = $this->getProvider(); $acl = $provider->findAcl($oid); $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl); $this->assertTrue($oid->equals($acl->getObjectIdentity())); $this->assertEquals(4, $acl->getId()); $this->assertCount(0, $acl->getClassAces()); $this->assertCount(0, $this->getField($acl, 'classFieldAces')); $this->assertCount(3, $acl->getObjectAces()); $this->assertCount(0, $this->getField($acl, 'objectFieldAces')); $aces = $acl->getObjectAces(); $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Entry', $aces[0]); $this->assertTrue($aces[0]->isGranting()); $this->assertTrue($aces[0]->isAuditSuccess()); $this->assertTrue($aces[0]->isAuditFailure()); $this->assertEquals('all', $aces[0]->getStrategy()); $this->assertSame(2, $aces[0]->getMask()); // check ACE are in correct order $i = 0; foreach ($aces as $index => $ace) { $this->assertEquals($i, $index); $i++; } $sid = $aces[0]->getSecurityIdentity(); $this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\UserSecurityIdentity', $sid); $this->assertEquals('john.doe', $sid->getUsername()); $this->assertEquals('SomeClass', $sid->getClass()); } protected function setUp() { if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) { self::markTestSkipped('This test requires SQLite support in your environment'); } $this->con = DriverManager::getConnection(array( 'driver' => 'pdo_sqlite', 'memory' => true, )); // import the schema $schema = new Schema($options = $this->getOptions()); foreach ($schema->toSql($this->con->getDatabasePlatform()) as $sql) { $this->con->exec($sql); } // populate the schema with some test data $this->insertClassStmt = $this->con->prepare('INSERT INTO acl_classes (id, class_type) VALUES (?, ?)'); foreach ($this->getClassData() as $data) { $this->insertClassStmt->execute($data); } $this->insertSidStmt = $this->con->prepare('INSERT INTO acl_security_identities (id, identifier, username) VALUES (?, ?, ?)'); foreach ($this->getSidData() as $data) { $this->insertSidStmt->execute($data); } $this->insertOidStmt = $this->con->prepare('INSERT INTO acl_object_identities (id, class_id, object_identifier, parent_object_identity_id, entries_inheriting) VALUES (?, ?, ?, ?, ?)'); foreach ($this->getOidData() as $data) { $this->insertOidStmt->execute($data); } $this->insertEntryStmt = $this->con->prepare('INSERT INTO acl_entries (id, class_id, object_identity_id, field_name, ace_order, security_identity_id, mask, granting, granting_strategy, audit_success, audit_failure) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); foreach ($this->getEntryData() as $data) { $this->insertEntryStmt->execute($data); } $this->insertOidAncestorStmt = $this->con->prepare('INSERT INTO acl_object_identity_ancestors (object_identity_id, ancestor_id) VALUES (?, ?)'); foreach ($this->getOidAncestorData() as $data) { $this->insertOidAncestorStmt->execute($data); } } protected function tearDown() { $this->con = null; } protected function getField($object, $field) { $reflection = new \ReflectionProperty($object, $field); $reflection->setAccessible(true); return $reflection->getValue($object); } protected function getEntryData() { // id, cid, oid, field, order, sid, mask, granting, strategy, a success, a failure return array( array(1, 1, 1, null, 0, 1, 1, 1, 'all', 1, 1), array(2, 1, 1, null, 1, 2, 1 << 2 | 1 << 1, 0, 'any', 0, 0), array(3, 3, 4, null, 0, 1, 2, 1, 'all', 1, 1), array(4, 3, 4, null, 2, 2, 1, 1, 'all', 1, 1), array(5, 3, 4, null, 1, 3, 1, 1, 'all', 1, 1), ); } protected function getOidData() { // id, cid, oid, parent_oid, entries_inheriting return array( array(1, 1, '123', null, 1), array(2, 2, '123', 1, 1), array(3, 2, 'i:3:123', 1, 1), array(4, 3, '1', 2, 1), array(5, 3, '2', 2, 1), ); } protected function getOidAncestorData() { return array( array(1, 1), array(2, 1), array(2, 2), array(3, 1), array(3, 3), array(4, 2), array(4, 1), array(4, 4), array(5, 2), array(5, 1), array(5, 5), ); } protected function getSidData() { return array( array(1, 'SomeClass-john.doe', 1), array(2, 'MyClass-john.doe@foo.com', 1), array(3, 'FooClass-123', 1), array(4, 'MooClass-ROLE_USER', 1), array(5, 'ROLE_USER', 0), array(6, 'IS_AUTHENTICATED_FULLY', 0), ); } protected function getClassData() { return array( array(1, 'Bundle\SomeVendor\MyBundle\Entity\SomeEntity'), array(2, 'Bundle\MyBundle\Entity\AnotherEntity'), array(3, 'foo'), ); } protected function getOptions() { return array( 'oid_table_name' => 'acl_object_identities', 'oid_ancestors_table_name' => 'acl_object_identity_ancestors', 'class_table_name' => 'acl_classes', 'sid_table_name' => 'acl_security_identities', 'entry_table_name' => 'acl_entries', ); } protected function getStrategy() { return new PermissionGrantingStrategy(); } protected function getProvider() { return new AclProvider($this->con, $this->getStrategy(), $this->getOptions()); } } PK!ˆ5Mtest/Security/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; class AuditLoggerTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getTestLogData */ public function testLogIfNeeded($granting, $audit) { $logger = $this->getLogger(); $ace = $this->getEntry(); if (true === $granting) { $ace ->expects($this->once()) ->method('isAuditSuccess') ->will($this->returnValue($audit)) ; $ace ->expects($this->never()) ->method('isAuditFailure') ; } else { $ace ->expects($this->never()) ->method('isAuditSuccess') ; $ace ->expects($this->once()) ->method('isAuditFailure') ->will($this->returnValue($audit)) ; } if (true === $audit) { $logger ->expects($this->once()) ->method('doLog') ->with($this->equalTo($granting), $this->equalTo($ace)) ; } else { $logger ->expects($this->never()) ->method('doLog') ; } $logger->logIfNeeded($granting, $ace); } public function getTestLogData() { return array( array(true, false), array(true, true), array(false, false), array(false, true), ); } protected function getEntry() { return $this->getMock('Symfony\Component\Security\Acl\Model\AuditableEntryInterface'); } protected function getLogger() { return $this->getMockForAbstractClass('Symfony\Component\Security\Acl\Domain\AuditLogger'); } } PK!6x}&&Ltest/Security/Symfony/Component/Security/Acl/Tests/Domain/FieldEntryTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; use Symfony\Component\Security\Acl\Domain\FieldEntry; class FieldEntryTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $ace = $this->getAce(); $this->assertEquals('foo', $ace->getField()); } public function testSerializeUnserialize() { $ace = $this->getAce(); $serialized = serialize($ace); $uAce = unserialize($serialized); $this->assertNull($uAce->getAcl()); $this->assertInstanceOf('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface', $uAce->getSecurityIdentity()); $this->assertEquals($ace->getId(), $uAce->getId()); $this->assertEquals($ace->getField(), $uAce->getField()); $this->assertEquals($ace->getMask(), $uAce->getMask()); $this->assertEquals($ace->getStrategy(), $uAce->getStrategy()); $this->assertEquals($ace->isGranting(), $uAce->isGranting()); $this->assertEquals($ace->isAuditSuccess(), $uAce->isAuditSuccess()); $this->assertEquals($ace->isAuditFailure(), $uAce->isAuditFailure()); } protected function getAce($acl = null, $sid = null) { if (null === $acl) { $acl = $this->getAcl(); } if (null === $sid) { $sid = $this->getSid(); } return new FieldEntry( 123, $acl, 'foo', $sid, 'foostrat', 123456, true, false, true ); } protected function getAcl() { return $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface'); } protected function getSid() { return $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface'); } } PK!+&Ptest/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain { use Symfony\Component\Security\Acl\Domain\ObjectIdentity; class ObjectIdentityTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $id = new ObjectIdentity('fooid', 'footype'); $this->assertEquals('fooid', $id->getIdentifier()); $this->assertEquals('footype', $id->getType()); } // Test that constructor never changes passed type, even with proxies public function testConstructorWithProxy() { $id = new ObjectIdentity('fooid', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject'); $this->assertEquals('fooid', $id->getIdentifier()); $this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType()); } public function testFromDomainObjectPrefersInterfaceOverGetId() { $domainObject = $this->getMock('Symfony\Component\Security\Acl\Model\DomainObjectInterface'); $domainObject ->expects($this->once()) ->method('getObjectIdentifier') ->will($this->returnValue('getObjectIdentifier()')) ; $domainObject ->expects($this->never()) ->method('getId') ->will($this->returnValue('getId()')) ; $id = ObjectIdentity::fromDomainObject($domainObject); $this->assertEquals('getObjectIdentifier()', $id->getIdentifier()); } public function testFromDomainObjectWithoutInterface() { $id = ObjectIdentity::fromDomainObject(new TestDomainObject()); $this->assertEquals('getId()', $id->getIdentifier()); $this->assertEquals('Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType()); } public function testFromDomainObjectWithProxy() { $id = ObjectIdentity::fromDomainObject(new \Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject()); $this->assertEquals('getId()', $id->getIdentifier()); $this->assertEquals('Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType()); } /** * @dataProvider getCompareData */ public function testEquals($oid1, $oid2, $equal) { if ($equal) { $this->assertTrue($oid1->equals($oid2)); } else { $this->assertFalse($oid1->equals($oid2)); } } public function getCompareData() { return array( array(new ObjectIdentity('123', 'foo'), new ObjectIdentity('123', 'foo'), true), array(new ObjectIdentity('123', 'foo'), new ObjectIdentity(123, 'foo'), true), array(new ObjectIdentity('1', 'foo'), new ObjectIdentity('2', 'foo'), false), array(new ObjectIdentity('1', 'bla'), new ObjectIdentity('1', 'blub'), false), ); } } class TestDomainObject { public function getObjectIdentifier() { return 'getObjectIdentifier()'; } public function getId() { return 'getId()'; } } } namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain { class TestDomainObject extends \Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject { } } PK!_~atest/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityRetrievalStrategyTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; use Symfony\Component\Security\Acl\Domain\ObjectIdentityRetrievalStrategy; class ObjectIdentityRetrievalStrategyTest extends \PHPUnit_Framework_TestCase { public function testGetObjectIdentityReturnsNullForInvalidDomainObject() { $strategy = new ObjectIdentityRetrievalStrategy(); $this->assertNull($strategy->getObjectIdentity('foo')); } public function testGetObjectIdentity() { $strategy = new ObjectIdentityRetrievalStrategy(); $domainObject = new DomainObject(); $objectIdentity = $strategy->getObjectIdentity($domainObject); $this->assertEquals($domainObject->getId(), $objectIdentity->getIdentifier()); $this->assertEquals(get_class($domainObject), $objectIdentity->getType()); } } class DomainObject { public function getId() { return 'foo'; } } PK!H H Rtest/Security/Symfony/Component/Security/Acl/Tests/Domain/DoctrineAclCacheTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy; use Symfony\Component\Security\Acl\Domain\Acl; use Symfony\Component\Security\Acl\Domain\DoctrineAclCache; use Doctrine\Common\Cache\ArrayCache; class DoctrineAclCacheTest extends \PHPUnit_Framework_TestCase { protected $permissionGrantingStrategy; /** * @expectedException \InvalidArgumentException * @dataProvider getEmptyValue */ public function testConstructorDoesNotAcceptEmptyPrefix($empty) { new DoctrineAclCache(new ArrayCache(), $this->getPermissionGrantingStrategy(), $empty); } public function getEmptyValue() { return array( array(null), array(false), array(''), ); } public function test() { $cache = $this->getCache(); $aclWithParent = $this->getAcl(1); $acl = $this->getAcl(); $cache->putInCache($aclWithParent); $cache->putInCache($acl); $cachedAcl = $cache->getFromCacheByIdentity($acl->getObjectIdentity()); $this->assertEquals($acl->getId(), $cachedAcl->getId()); $this->assertNull($acl->getParentAcl()); $cachedAclWithParent = $cache->getFromCacheByIdentity($aclWithParent->getObjectIdentity()); $this->assertEquals($aclWithParent->getId(), $cachedAclWithParent->getId()); $this->assertNotNull($cachedParentAcl = $cachedAclWithParent->getParentAcl()); $this->assertEquals($aclWithParent->getParentAcl()->getId(), $cachedParentAcl->getId()); } protected function getAcl($depth = 0) { static $id = 1; $acl = new Acl($id, new ObjectIdentity($id, 'foo'), $this->getPermissionGrantingStrategy(), array(), $depth > 0); // insert some ACEs $sid = new UserSecurityIdentity('johannes', 'Foo'); $acl->insertClassAce($sid, 1); $acl->insertClassFieldAce('foo', $sid, 1); $acl->insertObjectAce($sid, 1); $acl->insertObjectFieldAce('foo', $sid, 1); $id++; if ($depth > 0) { $acl->setParentAcl($this->getAcl($depth - 1)); } return $acl; } protected function getPermissionGrantingStrategy() { if (null === $this->permissionGrantingStrategy) { $this->permissionGrantingStrategy = new PermissionGrantingStrategy(); } return $this->permissionGrantingStrategy; } protected function getCache($cacheDriver = null, $prefix = DoctrineAclCache::PREFIX) { if (null === $cacheDriver) { $cacheDriver = new ArrayCache(); } return new DoctrineAclCache($cacheDriver, $this->getPermissionGrantingStrategy(), $prefix); } } PK!v\test/Security/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\Acl; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy; use Symfony\Component\Security\Acl\Exception\NoAceFoundException; class PermissionGrantingStrategyTest extends \PHPUnit_Framework_TestCase { public function testIsGrantedObjectAcesHavePriority() { $strategy = new PermissionGrantingStrategy(); $acl = $this->getAcl($strategy); $sid = new UserSecurityIdentity('johannes', 'Foo'); $acl->insertClassAce($sid, 1); $acl->insertObjectAce($sid, 1, 0, false); $this->assertFalse($strategy->isGranted($acl, array(1), array($sid))); } public function testIsGrantedFallsBackToClassAcesIfNoApplicableObjectAceWasFound() { $strategy = new PermissionGrantingStrategy(); $acl = $this->getAcl($strategy); $sid = new UserSecurityIdentity('johannes', 'Foo'); $acl->insertClassAce($sid, 1); $this->assertTrue($strategy->isGranted($acl, array(1), array($sid))); } public function testIsGrantedFavorsLocalAcesOverParentAclAces() { $strategy = new PermissionGrantingStrategy(); $sid = new UserSecurityIdentity('johannes', 'Foo'); $acl = $this->getAcl($strategy); $acl->insertClassAce($sid, 1); $parentAcl = $this->getAcl($strategy); $acl->setParentAcl($parentAcl); $parentAcl->insertClassAce($sid, 1, 0, false); $this->assertTrue($strategy->isGranted($acl, array(1), array($sid))); } public function testIsGrantedFallsBackToParentAcesIfNoLocalAcesAreApplicable() { $strategy = new PermissionGrantingStrategy(); $sid = new UserSecurityIdentity('johannes', 'Foo'); $anotherSid = new UserSecurityIdentity('ROLE_USER', 'Foo'); $acl = $this->getAcl($strategy); $acl->insertClassAce($anotherSid, 1, 0, false); $parentAcl = $this->getAcl($strategy); $acl->setParentAcl($parentAcl); $parentAcl->insertClassAce($sid, 1); $this->assertTrue($strategy->isGranted($acl, array(1), array($sid))); } /** * @expectedException \Symfony\Component\Security\Acl\Exception\NoAceFoundException */ public function testIsGrantedReturnsExceptionIfNoAceIsFound() { $strategy = new PermissionGrantingStrategy(); $acl = $this->getAcl($strategy); $sid = new UserSecurityIdentity('johannes', 'Foo'); $strategy->isGranted($acl, array(1), array($sid)); } public function testIsGrantedFirstApplicableEntryMakesUltimateDecisionForPermissionIdentityCombination() { $strategy = new PermissionGrantingStrategy(); $acl = $this->getAcl($strategy); $sid = new UserSecurityIdentity('johannes', 'Foo'); $aSid = new RoleSecurityIdentity('ROLE_USER'); $acl->insertClassAce($aSid, 1); $acl->insertClassAce($sid, 1, 1, false); $acl->insertClassAce($sid, 1, 2); $this->assertFalse($strategy->isGranted($acl, array(1), array($sid, $aSid))); $acl->insertObjectAce($sid, 1, 0, false); $acl->insertObjectAce($aSid, 1, 1); $this->assertFalse($strategy->isGranted($acl, array(1), array($sid, $aSid))); } public function testIsGrantedCallsAuditLoggerOnGrant() { $strategy = new PermissionGrantingStrategy(); $acl = $this->getAcl($strategy); $sid = new UserSecurityIdentity('johannes', 'Foo'); $logger = $this->getMock('Symfony\Component\Security\Acl\Model\AuditLoggerInterface'); $logger ->expects($this->once()) ->method('logIfNeeded') ; $strategy->setAuditLogger($logger); $acl->insertObjectAce($sid, 1); $acl->updateObjectAuditing(0, true, false); $this->assertTrue($strategy->isGranted($acl, array(1), array($sid))); } public function testIsGrantedCallsAuditLoggerOnDeny() { $strategy = new PermissionGrantingStrategy(); $acl = $this->getAcl($strategy); $sid = new UserSecurityIdentity('johannes', 'Foo'); $logger = $this->getMock('Symfony\Component\Security\Acl\Model\AuditLoggerInterface'); $logger ->expects($this->once()) ->method('logIfNeeded') ; $strategy->setAuditLogger($logger); $acl->insertObjectAce($sid, 1, 0, false); $acl->updateObjectAuditing(0, false, true); $this->assertFalse($strategy->isGranted($acl, array(1), array($sid))); } /** * @dataProvider getAllStrategyTests */ public function testIsGrantedStrategies($maskStrategy, $aceMask, $requiredMask, $result) { $strategy = new PermissionGrantingStrategy(); $acl = $this->getAcl($strategy); $sid = new UserSecurityIdentity('johannes', 'Foo'); $acl->insertObjectAce($sid, $aceMask, 0, true, $maskStrategy); if (false === $result) { try { $strategy->isGranted($acl, array($requiredMask), array($sid)); $this->fail('The ACE is not supposed to match.'); } catch (NoAceFoundException $noAce) { } } else { $this->assertTrue($strategy->isGranted($acl, array($requiredMask), array($sid))); } } public function getAllStrategyTests() { return array( array('all', 1 << 0 | 1 << 1, 1 << 0, true), array('all', 1 << 0 | 1 << 1, 1 << 2, false), array('all', 1 << 0 | 1 << 10, 1 << 0 | 1 << 10, true), array('all', 1 << 0 | 1 << 1, 1 << 0 | 1 << 1 || 1 << 2, false), array('any', 1 << 0 | 1 << 1, 1 << 0, true), array('any', 1 << 0 | 1 << 1, 1 << 0 | 1 << 2, true), array('any', 1 << 0 | 1 << 1, 1 << 2, false), array('equal', 1 << 0 | 1 << 1, 1 << 0, false), array('equal', 1 << 0 | 1 << 1, 1 << 1, false), array('equal', 1 << 0 | 1 << 1, 1 << 0 | 1 << 1, true), ); } protected function getAcl($strategy) { static $id = 1; return new Acl($id++, new ObjectIdentity(1, 'Foo'), $strategy, array(), true); } } PK!/bAbAEtest/Security/Symfony/Component/Security/Acl/Tests/Domain/AclTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Acl\Domain\Acl; class AclTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $acl = new Acl(1, $oid = new ObjectIdentity('foo', 'foo'), $permissionStrategy = new PermissionGrantingStrategy(), array(), true); $this->assertSame(1, $acl->getId()); $this->assertSame($oid, $acl->getObjectIdentity()); $this->assertNull($acl->getParentAcl()); $this->assertTrue($acl->isEntriesInheriting()); } /** * @expectedException \OutOfBoundsException * @dataProvider getDeleteAceTests */ public function testDeleteAceThrowsExceptionOnInvalidIndex($type) { $acl = $this->getAcl(); $acl->{'delete'.$type.'Ace'}(0); } /** * @dataProvider getDeleteAceTests */ public function testDeleteAce($type) { $acl = $this->getAcl(); $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 1); $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 2, 1); $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 3, 2); $listener = $this->getListener(array( $type.'Aces', 'aceOrder', 'aceOrder', $type.'Aces', )); $acl->addPropertyChangedListener($listener); $this->assertCount(3, $acl->{'get'.$type.'Aces'}()); $acl->{'delete'.$type.'Ace'}(0); $this->assertCount(2, $aces = $acl->{'get'.$type.'Aces'}()); $this->assertEquals(2, $aces[0]->getMask()); $this->assertEquals(3, $aces[1]->getMask()); $acl->{'delete'.$type.'Ace'}(1); $this->assertCount(1, $aces = $acl->{'get'.$type.'Aces'}()); $this->assertEquals(2, $aces[0]->getMask()); } public function getDeleteAceTests() { return array( array('class'), array('object'), ); } /** * @expectedException \OutOfBoundsException * @dataProvider getDeleteFieldAceTests */ public function testDeleteFieldAceThrowsExceptionOnInvalidIndex($type) { $acl = $this->getAcl(); $acl->{'delete'.$type.'Ace'}('foo', 0); } /** * @dataProvider getDeleteFieldAceTests */ public function testDeleteFieldAce($type) { $acl = $this->getAcl(); $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1, 0); $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 2, 1); $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 3, 2); $listener = $this->getListener(array( $type.'Aces', 'aceOrder', 'aceOrder', $type.'Aces', )); $acl->addPropertyChangedListener($listener); $this->assertCount(3, $acl->{'get'.$type.'Aces'}('foo')); $acl->{'delete'.$type.'Ace'}(0, 'foo'); $this->assertCount(2, $aces = $acl->{'get'.$type.'Aces'}('foo')); $this->assertEquals(2, $aces[0]->getMask()); $this->assertEquals(3, $aces[1]->getMask()); $acl->{'delete'.$type.'Ace'}(1, 'foo'); $this->assertCount(1, $aces = $acl->{'get'.$type.'Aces'}('foo')); $this->assertEquals(2, $aces[0]->getMask()); } public function getDeleteFieldAceTests() { return array( array('classField'), array('objectField'), ); } /** * @dataProvider getInsertAceTests */ public function testInsertAce($property, $method) { $acl = $this->getAcl(); $listener = $this->getListener(array( $property, 'aceOrder', $property, 'aceOrder', $property )); $acl->addPropertyChangedListener($listener); $sid = new RoleSecurityIdentity('foo'); $acl->$method($sid, 1); $acl->$method($sid, 2); $acl->$method($sid, 3, 1, false); $this->assertCount(3, $aces = $acl->{'get'.$property}()); $this->assertEquals(2, $aces[0]->getMask()); $this->assertEquals(3, $aces[1]->getMask()); $this->assertEquals(1, $aces[2]->getMask()); } /** * @expectedException \OutOfBoundsException * @dataProvider getInsertAceTests */ public function testInsertClassAceThrowsExceptionOnInvalidIndex($property, $method) { $acl = $this->getAcl(); $acl->$method(new RoleSecurityIdentity('foo'), 1, 1); } public function getInsertAceTests() { return array( array('classAces', 'insertClassAce'), array('objectAces', 'insertObjectAce'), ); } /** * @dataProvider getInsertFieldAceTests */ public function testInsertClassFieldAce($property, $method) { $acl = $this->getAcl(); $listener = $this->getListener(array( $property, $property, 'aceOrder', $property, 'aceOrder', 'aceOrder', $property, )); $acl->addPropertyChangedListener($listener); $sid = new RoleSecurityIdentity('foo'); $acl->$method('foo', $sid, 1); $acl->$method('foo2', $sid, 1); $acl->$method('foo', $sid, 3); $acl->$method('foo', $sid, 2); $this->assertCount(3, $aces = $acl->{'get'.$property}('foo')); $this->assertCount(1, $acl->{'get'.$property}('foo2')); $this->assertEquals(2, $aces[0]->getMask()); $this->assertEquals(3, $aces[1]->getMask()); $this->assertEquals(1, $aces[2]->getMask()); } /** * @expectedException \OutOfBoundsException * @dataProvider getInsertFieldAceTests */ public function testInsertClassFieldAceThrowsExceptionOnInvalidIndex($property, $method) { $acl = $this->getAcl(); $acl->$method('foo', new RoleSecurityIdentity('foo'), 1, 1); } public function getInsertFieldAceTests() { return array( array('classFieldAces', 'insertClassFieldAce'), array('objectFieldAces', 'insertObjectFieldAce'), ); } public function testIsFieldGranted() { $sids = array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_IDDQD')); $masks = array(1, 2, 4); $strategy = $this->getMock('Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface'); $acl = new Acl(1, new ObjectIdentity(1, 'foo'), $strategy, array(), true); $strategy ->expects($this->once()) ->method('isFieldGranted') ->with($this->equalTo($acl), $this->equalTo('foo'), $this->equalTo($masks), $this->equalTo($sids), $this->isTrue()) ->will($this->returnValue(true)) ; $this->assertTrue($acl->isFieldGranted('foo', $masks, $sids, true)); } public function testIsGranted() { $sids = array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_IDDQD')); $masks = array(1, 2, 4); $strategy = $this->getMock('Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface'); $acl = new Acl(1, new ObjectIdentity(1, 'foo'), $strategy, array(), true); $strategy ->expects($this->once()) ->method('isGranted') ->with($this->equalTo($acl), $this->equalTo($masks), $this->equalTo($sids), $this->isTrue()) ->will($this->returnValue(true)) ; $this->assertTrue($acl->isGranted($masks, $sids, true)); } public function testSetGetParentAcl() { $acl = $this->getAcl(); $parentAcl = $this->getAcl(); $listener = $this->getListener(array('parentAcl')); $acl->addPropertyChangedListener($listener); $this->assertNull($acl->getParentAcl()); $acl->setParentAcl($parentAcl); $this->assertSame($parentAcl, $acl->getParentAcl()); $acl->setParentAcl(null); $this->assertNull($acl->getParentAcl()); } public function testSetIsEntriesInheriting() { $acl = $this->getAcl(); $listener = $this->getListener(array('entriesInheriting')); $acl->addPropertyChangedListener($listener); $this->assertTrue($acl->isEntriesInheriting()); $acl->setEntriesInheriting(false); $this->assertFalse($acl->isEntriesInheriting()); } public function testIsSidLoadedWhenAllSidsAreLoaded() { $acl = $this->getAcl(); $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo'))); $this->assertTrue($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO', 'Foo'))); } public function testIsSidLoaded() { $acl = new Acl(1, new ObjectIdentity('1', 'foo'), new PermissionGrantingStrategy(), array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('johannes', 'Bar')), true); $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo'))); $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('johannes', 'Bar'))); $this->assertTrue($acl->isSidLoaded(array( new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('johannes', 'Bar'), ))); $this->assertFalse($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO'))); $this->assertFalse($acl->isSidLoaded(new UserSecurityIdentity('schmittjoh@gmail.com', 'Moo'))); $this->assertFalse($acl->isSidLoaded(array( new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('johannes', 'Bar'), new RoleSecurityIdentity('ROLE_FOO'), ))); } /** * @dataProvider getUpdateAceTests * @expectedException \OutOfBoundsException */ public function testUpdateAceThrowsOutOfBoundsExceptionOnInvalidIndex($type) { $acl = $this->getAcl(); $acl->{'update'.$type}(0, 1); } /** * @dataProvider getUpdateAceTests */ public function testUpdateAce($type) { $acl = $this->getAcl(); $acl->{'insert'.$type}(new RoleSecurityIdentity('foo'), 1); $listener = $this->getListener(array( 'mask', 'mask', 'strategy', )); $acl->addPropertyChangedListener($listener); $aces = $acl->{'get'.$type.'s'}(); $ace = reset($aces); $this->assertEquals(1, $ace->getMask()); $this->assertEquals('all', $ace->getStrategy()); $acl->{'update'.$type}(0, 3); $this->assertEquals(3, $ace->getMask()); $this->assertEquals('all', $ace->getStrategy()); $acl->{'update'.$type}(0, 1, 'foo'); $this->assertEquals(1, $ace->getMask()); $this->assertEquals('foo', $ace->getStrategy()); } public function getUpdateAceTests() { return array( array('classAce'), array('objectAce'), ); } /** * @dataProvider getUpdateFieldAceTests * @expectedException \OutOfBoundsException */ public function testUpdateFieldAceThrowsExceptionOnInvalidIndex($type) { $acl = $this->getAcl(); $acl->{'update'.$type}(0, 'foo', 1); } /** * @dataProvider getUpdateFieldAceTests */ public function testUpdateFieldAce($type) { $acl = $this->getAcl(); $acl->{'insert'.$type}('foo', new UserSecurityIdentity('foo', 'Foo'), 1); $listener = $this->getListener(array( 'mask', 'mask', 'strategy' )); $acl->addPropertyChangedListener($listener); $aces = $acl->{'get'.$type.'s'}('foo'); $ace = reset($aces); $this->assertEquals(1, $ace->getMask()); $this->assertEquals('all', $ace->getStrategy()); $acl->{'update'.$type}(0, 'foo', 3); $this->assertEquals(3, $ace->getMask()); $this->assertEquals('all', $ace->getStrategy()); $acl->{'update'.$type}(0, 'foo', 1, 'foo'); $this->assertEquals(1, $ace->getMask()); $this->assertEquals('foo', $ace->getStrategy()); } public function getUpdateFieldAceTests() { return array( array('classFieldAce'), array('objectFieldAce'), ); } /** * @dataProvider getUpdateAuditingTests * @expectedException \OutOfBoundsException */ public function testUpdateAuditingThrowsExceptionOnInvalidIndex($type) { $acl = $this->getAcl(); $acl->{'update'.$type.'Auditing'}(0, true, false); } /** * @dataProvider getUpdateAuditingTests */ public function testUpdateAuditing($type) { $acl = $this->getAcl(); $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 1); $listener = $this->getListener(array( 'auditFailure', 'auditSuccess', 'auditFailure', )); $acl->addPropertyChangedListener($listener); $aces = $acl->{'get'.$type.'Aces'}(); $ace = reset($aces); $this->assertFalse($ace->isAuditSuccess()); $this->assertFalse($ace->isAuditFailure()); $acl->{'update'.$type.'Auditing'}(0, false, true); $this->assertFalse($ace->isAuditSuccess()); $this->assertTrue($ace->isAuditFailure()); $acl->{'update'.$type.'Auditing'}(0, true, false); $this->assertTrue($ace->isAuditSuccess()); $this->assertFalse($ace->isAuditFailure()); } public function getUpdateAuditingTests() { return array( array('class'), array('object'), ); } /** * @expectedException \InvalidArgumentException * @dataProvider getUpdateFieldAuditingTests */ public function testUpdateFieldAuditingThrowsExceptionOnInvalidField($type) { $acl = $this->getAcl(); $acl->{'update'.$type.'Auditing'}(0, 'foo', true, true); } /** * @expectedException \OutOfBoundsException * @dataProvider getUpdateFieldAuditingTests */ public function testUpdateFieldAuditingThrowsExceptionOnInvalidIndex($type) { $acl = $this->getAcl(); $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1); $acl->{'update'.$type.'Auditing'}(1, 'foo', true, false); } /** * @dataProvider getUpdateFieldAuditingTests */ public function testUpdateFieldAuditing($type) { $acl = $this->getAcl(); $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1); $listener = $this->getListener(array( 'auditSuccess', 'auditSuccess', 'auditFailure', )); $acl->addPropertyChangedListener($listener); $aces = $acl->{'get'.$type.'Aces'}('foo'); $ace = reset($aces); $this->assertFalse($ace->isAuditSuccess()); $this->assertFalse($ace->isAuditFailure()); $acl->{'update'.$type.'Auditing'}(0, 'foo', true, false); $this->assertTrue($ace->isAuditSuccess()); $this->assertFalse($ace->isAuditFailure()); $acl->{'update'.$type.'Auditing'}(0, 'foo', false, true); $this->assertFalse($ace->isAuditSuccess()); $this->assertTrue($ace->isAuditFailure()); } public function getUpdateFieldAuditingTests() { return array( array('classField'), array('objectField'), ); } protected function getListener($expectedChanges) { $aceProperties = array('aceOrder', 'mask', 'strategy', 'auditSuccess', 'auditFailure'); $listener = $this->getMock('Doctrine\Common\PropertyChangedListener'); foreach ($expectedChanges as $index => $property) { if (in_array($property, $aceProperties)) { $class = 'Symfony\Component\Security\Acl\Domain\Entry'; } else { $class = 'Symfony\Component\Security\Acl\Domain\Acl'; } $listener ->expects($this->at($index)) ->method('propertyChanged') ->with($this->isInstanceOf($class), $this->equalTo($property)) ; } return $listener; } protected function getAcl() { return new Acl(1, new ObjectIdentity(1, 'foo'), new PermissionGrantingStrategy(), array(), true); } } PK!5Vtest/Security/Symfony/Component/Security/Acl/Tests/Domain/RoleSecurityIdentityTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; class RoleSecurityIdentityTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $id = new RoleSecurityIdentity('ROLE_FOO'); $this->assertEquals('ROLE_FOO', $id->getRole()); } public function testConstructorWithRoleInstance() { $id = new RoleSecurityIdentity(new Role('ROLE_FOO')); $this->assertEquals('ROLE_FOO', $id->getRole()); } /** * @dataProvider getCompareData */ public function testEquals($id1, $id2, $equal) { if ($equal) { $this->assertTrue($id1->equals($id2)); } else { $this->assertFalse($id1->equals($id2)); } } public function getCompareData() { return array( array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_FOO'), true), array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity(new Role('ROLE_FOO')), true), array(new RoleSecurityIdentity('ROLE_USER'), new RoleSecurityIdentity('ROLE_FOO'), false), array(new RoleSecurityIdentity('ROLE_FOO'), new UserSecurityIdentity('ROLE_FOO', 'Foo'), false), ); } } PK!a( ( Vtest/Security/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; class UserSecurityIdentityTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $id = new UserSecurityIdentity('foo', 'Foo'); $this->assertEquals('foo', $id->getUsername()); $this->assertEquals('Foo', $id->getClass()); } // Test that constructor never changes the type, even for proxies public function testConstructorWithProxy() { $id = new UserSecurityIdentity('foo', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\Foo'); $this->assertEquals('foo', $id->getUsername()); $this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\Foo', $id->getClass()); } /** * @dataProvider getCompareData */ public function testEquals($id1, $id2, $equal) { $this->assertSame($equal, $id1->equals($id2)); } public function getCompareData() { $account = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface') ->setMockClassName('USI_AccountImpl') ->getMock(); $account ->expects($this->any()) ->method('getUsername') ->will($this->returnValue('foo')) ; $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->any()) ->method('getUser') ->will($this->returnValue($account)) ; return array( array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('foo', 'Foo'), true), array(new UserSecurityIdentity('foo', 'Bar'), new UserSecurityIdentity('foo', 'Foo'), false), array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('bar', 'Foo'), false), array(new UserSecurityIdentity('foo', 'Foo'), UserSecurityIdentity::fromAccount($account), false), array(new UserSecurityIdentity('bla', 'Foo'), new UserSecurityIdentity('blub', 'Foo'), false), array(new UserSecurityIdentity('foo', 'Foo'), new RoleSecurityIdentity('foo'), false), array(new UserSecurityIdentity('foo', 'Foo'), UserSecurityIdentity::fromToken($token), false), array(new UserSecurityIdentity('foo', 'USI_AccountImpl'), UserSecurityIdentity::fromToken($token), true), ); } } PK!amctest/Security/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Domain\SecurityIdentityRetrievalStrategy; class SecurityIdentityRetrievalStrategyTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getSecurityIdentityRetrievalTests */ public function testGetSecurityIdentities($user, array $roles, $authenticationStatus, array $sids) { $strategy = $this->getStrategy($roles, $authenticationStatus); if ('anonymous' === $authenticationStatus) { $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken') ->disableOriginalConstructor() ->getMock(); } else { $class = ''; if (is_string($user)) { $class = 'MyCustomTokenImpl'; } $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface') ->setMockClassName($class) ->getMock(); } $token ->expects($this->once()) ->method('getRoles') ->will($this->returnValue(array('foo'))) ; if ('anonymous' === $authenticationStatus) { $token ->expects($this->never()) ->method('getUser') ; } else { $token ->expects($this->once()) ->method('getUser') ->will($this->returnValue($user)) ; } $extractedSids = $strategy->getSecurityIdentities($token); foreach ($extractedSids as $index => $extractedSid) { if (!isset($sids[$index])) { $this->fail(sprintf('Expected SID at index %d, but there was none.', true)); } if (false === $sids[$index]->equals($extractedSid)) { $this->fail(sprintf('Index: %d, expected SID "%s", but got "%s".', $index, $sids[$index], $extractedSid)); } } } public function getSecurityIdentityRetrievalTests() { return array( array($this->getAccount('johannes', 'FooUser'), array('ROLE_USER', 'ROLE_SUPERADMIN'), 'fullFledged', array( new UserSecurityIdentity('johannes', 'FooUser'), new RoleSecurityIdentity('ROLE_USER'), new RoleSecurityIdentity('ROLE_SUPERADMIN'), new RoleSecurityIdentity('IS_AUTHENTICATED_FULLY'), new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'), new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'), )), array('johannes', array('ROLE_FOO'), 'fullFledged', array( new UserSecurityIdentity('johannes', 'MyCustomTokenImpl'), new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('IS_AUTHENTICATED_FULLY'), new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'), new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'), )), array(new CustomUserImpl('johannes'), array('ROLE_FOO'), 'fullFledged', array( new UserSecurityIdentity('johannes', 'Symfony\Component\Security\Acl\Tests\Domain\CustomUserImpl'), new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('IS_AUTHENTICATED_FULLY'), new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'), new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'), )), array($this->getAccount('foo', 'FooBarUser'), array('ROLE_FOO'), 'rememberMe', array( new UserSecurityIdentity('foo', 'FooBarUser'), new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'), new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'), )), array('guest', array('ROLE_FOO'), 'anonymous', array( new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'), )) ); } protected function getAccount($username, $class) { $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface', array(), array(), $class); $account ->expects($this->any()) ->method('getUsername') ->will($this->returnValue($username)) ; return $account; } protected function getStrategy(array $roles = array(), $authenticationStatus = 'fullFledged') { $roleHierarchy = $this->getMock('Symfony\Component\Security\Core\Role\RoleHierarchyInterface'); $roleHierarchy ->expects($this->once()) ->method('getReachableRoles') ->with($this->equalTo(array('foo'))) ->will($this->returnValue($roles)) ; $trustResolver = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver', array(), array('', '')); $trustResolver ->expects($this->at(0)) ->method('isAnonymous') ->will($this->returnValue('anonymous' === $authenticationStatus)) ; if ('fullFledged' === $authenticationStatus) { $trustResolver ->expects($this->once()) ->method('isFullFledged') ->will($this->returnValue(true)) ; $trustResolver ->expects($this->never()) ->method('isRememberMe') ; } elseif ('rememberMe' === $authenticationStatus) { $trustResolver ->expects($this->once()) ->method('isFullFledged') ->will($this->returnValue(false)) ; $trustResolver ->expects($this->once()) ->method('isRememberMe') ->will($this->returnValue(true)) ; } else { $trustResolver ->expects($this->at(1)) ->method('isAnonymous') ->will($this->returnValue(true)) ; $trustResolver ->expects($this->once()) ->method('isFullFledged') ->will($this->returnValue(false)) ; $trustResolver ->expects($this->once()) ->method('isRememberMe') ->will($this->returnValue(false)) ; } return new SecurityIdentityRetrievalStrategy($roleHierarchy, $trustResolver); } } class CustomUserImpl { protected $name; public function __construct($name) { $this->name = $name; } public function __toString() { return $this->name; } } PK!F@ Gtest/Security/Symfony/Component/Security/Acl/Tests/Domain/EntryTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Domain; use Symfony\Component\Security\Acl\Domain\Entry; class EntryTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $ace = $this->getAce($acl = $this->getAcl(), $sid = $this->getSid()); $this->assertEquals(123, $ace->getId()); $this->assertSame($acl, $ace->getAcl()); $this->assertSame($sid, $ace->getSecurityIdentity()); $this->assertEquals('foostrat', $ace->getStrategy()); $this->assertEquals(123456, $ace->getMask()); $this->assertTrue($ace->isGranting()); $this->assertTrue($ace->isAuditSuccess()); $this->assertFalse($ace->isAuditFailure()); } public function testSetAuditSuccess() { $ace = $this->getAce(); $this->assertTrue($ace->isAuditSuccess()); $ace->setAuditSuccess(false); $this->assertFalse($ace->isAuditSuccess()); $ace->setAuditsuccess(true); $this->assertTrue($ace->isAuditSuccess()); } public function testSetAuditFailure() { $ace = $this->getAce(); $this->assertFalse($ace->isAuditFailure()); $ace->setAuditFailure(true); $this->assertTrue($ace->isAuditFailure()); $ace->setAuditFailure(false); $this->assertFalse($ace->isAuditFailure()); } public function testSetMask() { $ace = $this->getAce(); $this->assertEquals(123456, $ace->getMask()); $ace->setMask(4321); $this->assertEquals(4321, $ace->getMask()); } public function testSetStrategy() { $ace = $this->getAce(); $this->assertEquals('foostrat', $ace->getStrategy()); $ace->setStrategy('foo'); $this->assertEquals('foo', $ace->getStrategy()); } public function testSerializeUnserialize() { $ace = $this->getAce(); $serialized = serialize($ace); $uAce = unserialize($serialized); $this->assertNull($uAce->getAcl()); $this->assertInstanceOf('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface', $uAce->getSecurityIdentity()); $this->assertEquals($ace->getId(), $uAce->getId()); $this->assertEquals($ace->getMask(), $uAce->getMask()); $this->assertEquals($ace->getStrategy(), $uAce->getStrategy()); $this->assertEquals($ace->isGranting(), $uAce->isGranting()); $this->assertEquals($ace->isAuditSuccess(), $uAce->isAuditSuccess()); $this->assertEquals($ace->isAuditFailure(), $uAce->isAuditFailure()); } protected function getAce($acl = null, $sid = null) { if (null === $acl) { $acl = $this->getAcl(); } if (null === $sid) { $sid = $this->getSid(); } return new Entry( 123, $acl, $sid, 'foostrat', 123456, true, false, true ); } protected function getAcl() { return $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface'); } protected function getSid() { return $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface'); } } PK!yyXtest/Security/Symfony/Component/Security/Acl/Tests/Permission/BasicPermissionMapTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Permission; use Symfony\Component\Security\Acl\Permission\BasicPermissionMap; class BasicPermissionMapTest extends \PHPUnit_Framework_TestCase { public function testGetMasksReturnsNullWhenNotSupportedMask() { $map = new BasicPermissionMap(); $this->assertNull($map->getMasks('IS_AUTHENTICATED_REMEMBERED', null)); } } PK!eE Qtest/Security/Symfony/Component/Security/Acl/Tests/Permission/MaskBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Acl\Tests\Permission; use Symfony\Component\Security\Acl\Permission\MaskBuilder; class MaskBuilderTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \InvalidArgumentException * @dataProvider getInvalidConstructorData */ public function testConstructorWithNonInteger($invalidMask) { new MaskBuilder($invalidMask); } public function getInvalidConstructorData() { return array( array(234.463), array('asdgasdf'), array(array()), array(new \stdClass()), ); } public function testConstructorWithoutArguments() { $builder = new MaskBuilder(); $this->assertEquals(0, $builder->get()); } public function testConstructor() { $builder = new MaskBuilder(123456); $this->assertEquals(123456, $builder->get()); } public function testAddAndRemove() { $builder = new MaskBuilder(); $builder ->add('view') ->add('eDiT') ->add('ownEr') ; $mask = $builder->get(); $this->assertEquals(MaskBuilder::MASK_VIEW, $mask & MaskBuilder::MASK_VIEW); $this->assertEquals(MaskBuilder::MASK_EDIT, $mask & MaskBuilder::MASK_EDIT); $this->assertEquals(MaskBuilder::MASK_OWNER, $mask & MaskBuilder::MASK_OWNER); $this->assertEquals(0, $mask & MaskBuilder::MASK_MASTER); $this->assertEquals(0, $mask & MaskBuilder::MASK_CREATE); $this->assertEquals(0, $mask & MaskBuilder::MASK_DELETE); $this->assertEquals(0, $mask & MaskBuilder::MASK_UNDELETE); $builder->remove('edit')->remove('OWner'); $mask = $builder->get(); $this->assertEquals(0, $mask & MaskBuilder::MASK_EDIT); $this->assertEquals(0, $mask & MaskBuilder::MASK_OWNER); $this->assertEquals(MaskBuilder::MASK_VIEW, $mask & MaskBuilder::MASK_VIEW); } public function testGetPattern() { $builder = new MaskBuilder(); $this->assertEquals(MaskBuilder::ALL_OFF, $builder->getPattern()); $builder->add('view'); $this->assertEquals(str_repeat('.', 31).'V', $builder->getPattern()); $builder->add('owner'); $this->assertEquals(str_repeat('.', 24).'N......V', $builder->getPattern()); $builder->add(1 << 10); $this->assertEquals(str_repeat('.', 21).MaskBuilder::ON.'..N......V', $builder->getPattern()); } public function testReset() { $builder = new MaskBuilder(); $this->assertEquals(0, $builder->get()); $builder->add('view'); $this->assertTrue($builder->get() > 0); $builder->reset(); $this->assertEquals(0, $builder->get()); } } PK!ܲ#&;;=test/Security/Symfony/Component/Security/Acl/phpunit.xml.distnu[ ./Tests/ ./ ./vendor ./Tests PK!C)!"!"Vtest/Security/Symfony/Component/Security/Tests/Http/Firewall/ExceptionListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Tests\Http\Firewall; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Symfony\Component\Security\Http\Firewall\ExceptionListener; use Symfony\Component\Security\Http\HttpUtils; class ExceptionListenerTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getAuthenticationExceptionProvider */ public function testAuthenticationExceptionWithoutEntryPoint(\Exception $exception, \Exception $eventException = null) { $event = $this->createEvent($exception); $listener = $this->createExceptionListener(); $listener->onKernelException($event); $this->assertNull($event->getResponse()); $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException()); } /** * @dataProvider getAuthenticationExceptionProvider */ public function testAuthenticationExceptionWithEntryPoint(\Exception $exception, \Exception $eventException = null) { $event = $this->createEvent($exception = new AuthenticationException()); $listener = $this->createExceptionListener(null, null, null, $this->createEntryPoint()); $listener->onKernelException($event); $this->assertEquals('OK', $event->getResponse()->getContent()); $this->assertSame($exception, $event->getException()); } public function getAuthenticationExceptionProvider() { return array( array(new AuthenticationException()), array(new \LogicException('random', 0, $e = new AuthenticationException()), $e), array(new \LogicException('random', 0, $e = new AuthenticationException('embed', 0, new AuthenticationException())), $e), array(new \LogicException('random', 0, $e = new AuthenticationException('embed', 0, new AccessDeniedException())), $e), array(new AuthenticationException('random', 0, new \LogicException())), ); } /** * @dataProvider getAccessDeniedExceptionProvider */ public function testAccessDeniedExceptionFullFledgedAndWithoutAccessDeniedHandlerAndWithoutErrorPage(\Exception $exception, \Exception $eventException = null) { $event = $this->createEvent($exception); $listener = $this->createExceptionListener(null, $this->createTrustResolver(true)); $listener->onKernelException($event); $this->assertNull($event->getResponse()); $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException()->getPrevious()); } /** * @dataProvider getAccessDeniedExceptionProvider */ public function testAccessDeniedExceptionFullFledgedAndWithoutAccessDeniedHandlerAndWithErrorPage(\Exception $exception, \Exception $eventException = null) { $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $kernel->expects($this->once())->method('handle')->will($this->returnValue(new Response('error'))); $event = $this->createEvent($exception, $kernel); $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils'); $httpUtils->expects($this->once())->method('createRequest')->will($this->returnValue(Request::create('/error'))); $listener = $this->createExceptionListener(null, $this->createTrustResolver(true), $httpUtils, null, '/error'); $listener->onKernelException($event); $this->assertEquals('error', $event->getResponse()->getContent()); $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException()->getPrevious()); } /** * @dataProvider getAccessDeniedExceptionProvider */ public function testAccessDeniedExceptionFullFledgedAndWithAccessDeniedHandlerAndWithoutErrorPage(\Exception $exception, \Exception $eventException = null) { $event = $this->createEvent($exception); $accessDeniedHandler = $this->getMock('Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface'); $accessDeniedHandler->expects($this->once())->method('handle')->will($this->returnValue(new Response('error'))); $listener = $this->createExceptionListener(null, $this->createTrustResolver(true), null, null, null, $accessDeniedHandler); $listener->onKernelException($event); $this->assertEquals('error', $event->getResponse()->getContent()); $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException()->getPrevious()); } /** * @dataProvider getAccessDeniedExceptionProvider */ public function testAccessDeniedExceptionNotFullFledged(\Exception $exception, \Exception $eventException = null) { $event = $this->createEvent($exception); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context->expects($this->once())->method('getToken')->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))); $listener = $this->createExceptionListener($context, $this->createTrustResolver(false), null, $this->createEntryPoint()); $listener->onKernelException($event); $this->assertEquals('OK', $event->getResponse()->getContent()); $this->assertSame(null === $eventException ? $exception : $eventException, $event->getException()->getPrevious()); } public function getAccessDeniedExceptionProvider() { return array( array(new AccessDeniedException()), array(new \LogicException('random', 0, $e = new AccessDeniedException()), $e), array(new \LogicException('random', 0, $e = new AccessDeniedException('embed', new AccessDeniedException())), $e), array(new \LogicException('random', 0, $e = new AccessDeniedException('embed', new AuthenticationException())), $e), array(new AccessDeniedException('random', new \LogicException())), ); } private function createEntryPoint() { $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface'); $entryPoint->expects($this->once())->method('start')->will($this->returnValue(new Response('OK'))); return $entryPoint; } private function createTrustResolver($fullFledged) { $trustResolver = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface'); $trustResolver->expects($this->once())->method('isFullFledged')->will($this->returnValue($fullFledged)); return $trustResolver; } private function createEvent(\Exception $exception, $kernel = null) { if (null === $kernel) { $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); } return new GetResponseForExceptionEvent($kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $exception); } private function createExceptionListener(SecurityContextInterface $context = null, AuthenticationTrustResolverInterface $trustResolver = null, HttpUtils $httpUtils = null, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null) { return new ExceptionListener( $context ? $context : $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'), $trustResolver ? $trustResolver : $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface'), $httpUtils ? $httpUtils : $this->getMock('Symfony\Component\Security\Http\HttpUtils'), 'key', $authenticationEntryPoint, $errorPage, $accessDeniedHandler ); } } PK!sf[[Ltest/Security/Symfony/Component/Security/Tests/Core/User/UserCheckerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Tests\Core\User; use Symfony\Component\Security\Core\User\UserChecker; class UserCheckerTest extends \PHPUnit_Framework_TestCase { public function testCheckPostAuthNotAdvancedUserInterface() { $checker = new UserChecker(); $this->assertNull($checker->checkPostAuth($this->getMock('Symfony\Component\Security\Core\User\UserInterface'))); } public function testCheckPostAuthPass() { $checker = new UserChecker(); $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface'); $account->expects($this->once())->method('isCredentialsNonExpired')->will($this->returnValue(true)); $this->assertNull($checker->checkPostAuth($account)); } /** * @expectedException \Symfony\Component\Security\Core\Exception\CredentialsExpiredException */ public function testCheckPostAuthCredentialsExpired() { $checker = new UserChecker(); $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface'); $account->expects($this->once())->method('isCredentialsNonExpired')->will($this->returnValue(false)); $checker->checkPostAuth($account); } public function testCheckPreAuthNotAdvancedUserInterface() { $checker = new UserChecker(); $this->assertNull($checker->checkPreAuth($this->getMock('Symfony\Component\Security\Core\User\UserInterface'))); } public function testCheckPreAuthPass() { $checker = new UserChecker(); $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface'); $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(true)); $account->expects($this->once())->method('isEnabled')->will($this->returnValue(true)); $account->expects($this->once())->method('isAccountNonExpired')->will($this->returnValue(true)); $this->assertNull($checker->checkPreAuth($account)); } /** * @expectedException \Symfony\Component\Security\Core\Exception\LockedException */ public function testCheckPreAuthAccountLocked() { $checker = new UserChecker(); $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface'); $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(false)); $checker->checkPreAuth($account); } /** * @expectedException \Symfony\Component\Security\Core\Exception\DisabledException */ public function testCheckPreAuthDisabled() { $checker = new UserChecker(); $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface'); $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(true)); $account->expects($this->once())->method('isEnabled')->will($this->returnValue(false)); $checker->checkPreAuth($account); } /** * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException */ public function testCheckPreAuthAccountExpired() { $checker = new UserChecker(); $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface'); $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(true)); $account->expects($this->once())->method('isEnabled')->will($this->returnValue(true)); $account->expects($this->once())->method('isAccountNonExpired')->will($this->returnValue(false)); $checker->checkPreAuth($account); } } PK!!!Utest/Security/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Tests\Core\User; use Symfony\Component\Security\Core\User\InMemoryUserProvider; use Symfony\Component\Security\Core\User\User; class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $provider = new InMemoryUserProvider(array( 'fabien' => array( 'password' => 'foo', 'enabled' => false, 'roles' => array('ROLE_USER'), ), )); $user = $provider->loadUserByUsername('fabien'); $this->assertEquals('foo', $user->getPassword()); $this->assertEquals(array('ROLE_USER'), $user->getRoles()); $this->assertFalse($user->isEnabled()); } public function testCreateUser() { $provider = new InMemoryUserProvider(); $provider->createUser(new User('fabien', 'foo')); $user = $provider->loadUserByUsername('fabien'); $this->assertEquals('foo', $user->getPassword()); } /** * @expectedException \LogicException */ public function testCreateUserAlreadyExist() { $provider = new InMemoryUserProvider(); $provider->createUser(new User('fabien', 'foo')); $provider->createUser(new User('fabien', 'foo')); } /** * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException */ public function testLoadUserByUsernameDoesNotExist() { $provider = new InMemoryUserProvider(); $provider->loadUserByUsername('fabien'); } } PK!2nBB`test/Security/Symfony/Component/Security/Tests/Core/Authentication/Token/RememberMeTokenTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Tests\Core\Authentication\Token; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Core\Role\Role; class RememberMeTokenTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $user = $this->getUser(); $token = new RememberMeToken($user, 'fookey', 'foo'); $this->assertEquals('fookey', $token->getProviderKey()); $this->assertEquals('foo', $token->getKey()); $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles()); $this->assertSame($user, $token->getUser()); $this->assertTrue($token->isAuthenticated()); } /** * @expectedException \InvalidArgumentException */ public function testConstructorKeyCannotBeNull() { new RememberMeToken( $this->getUser(), null, null ); } /** * @expectedException \InvalidArgumentException */ public function testConstructorKeyCannotBeEmptyString() { new RememberMeToken( $this->getUser(), '', '' ); } /** * @expectedException \PHPUnit_Framework_Error * @dataProvider getUserArguments */ public function testConstructorUserCannotBeNull($user) { new RememberMeToken($user, 'foo', 'foo'); } public function getUserArguments() { return array( array(null), array('foo'), ); } protected function getUser($roles = array('ROLE_FOO')) { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user ->expects($this->once()) ->method('getRoles') ->will($this->returnValue($roles)) ; return $user; } } PK!9#  9test/Security/Symfony/Component/Security/phpunit.xml.distnu[ ./Acl/Tests/ ./Core/Tests/ ./Http/Tests/ ./ ./vendor ./Acl/Tests ./Core/Tests ./Http/Tests PK!g3%%Dtest/Security/Symfony/Component/Security/Http/Tests/FirewallTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests; use Symfony\Component\Security\Http\Firewall; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; class FirewallTest extends \PHPUnit_Framework_TestCase { public function testOnKernelRequestRegistersExceptionListener() { $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $listener = $this->getMock('Symfony\Component\Security\Http\Firewall\ExceptionListener', array(), array(), '', false); $listener ->expects($this->once()) ->method('register') ->with($this->equalTo($dispatcher)) ; $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $map = $this->getMock('Symfony\Component\Security\Http\FirewallMapInterface'); $map ->expects($this->once()) ->method('getListeners') ->with($this->equalTo($request)) ->will($this->returnValue(array(array(), $listener))) ; $event = new GetResponseEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST); $firewall = new Firewall($map, $dispatcher); $firewall->onKernelRequest($event); } public function testOnKernelRequestStopsWhenThereIsAResponse() { $response = $this->getMock('Symfony\Component\HttpFoundation\Response'); $first = $this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface'); $first ->expects($this->once()) ->method('handle') ; $second = $this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface'); $second ->expects($this->never()) ->method('handle') ; $map = $this->getMock('Symfony\Component\Security\Http\FirewallMapInterface'); $map ->expects($this->once()) ->method('getListeners') ->will($this->returnValue(array(array($first, $second), null))) ; $event = $this->getMock( 'Symfony\Component\HttpKernel\Event\GetResponseEvent', array('hasResponse'), array( $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false), HttpKernelInterface::MASTER_REQUEST ) ); $event ->expects($this->once()) ->method('hasResponse') ->will($this->returnValue(true)) ; $firewall = new Firewall($map, $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface')); $firewall->onKernelRequest($event); } public function testOnKernelRequestWithSubRequest() { $map = $this->getMock('Symfony\Component\Security\Http\FirewallMapInterface'); $map ->expects($this->never()) ->method('getListeners') ; $event = new GetResponseEvent( $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $this->getMock('Symfony\Component\HttpFoundation\Request'), HttpKernelInterface::SUB_REQUEST ); $firewall = new Firewall($map, $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface')); $firewall->onKernelRequest($event); $this->assertFalse($event->hasResponse()); } } PK!+MbbGtest/Security/Symfony/Component/Security/Http/Tests/FirewallMapTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests; use Symfony\Component\Security\Http\FirewallMap; use Symfony\Component\HttpFoundation\Request; class FirewallMapTest extends \PHPUnit_Framework_TestCase { public function testGetListeners() { $map = new FirewallMap(); $request = new Request(); $notMatchingMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher'); $notMatchingMatcher ->expects($this->once()) ->method('matches') ->with($this->equalTo($request)) ->will($this->returnValue(false)) ; $map->add($notMatchingMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface'))); $matchingMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher'); $matchingMatcher ->expects($this->once()) ->method('matches') ->with($this->equalTo($request)) ->will($this->returnValue(true)) ; $theListener = $this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface'); $theException = $this->getMock('Symfony\Component\Security\Http\Firewall\ExceptionListener', array(), array(), '', false); $map->add($matchingMatcher, array($theListener), $theException); $tooLateMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher'); $tooLateMatcher ->expects($this->never()) ->method('matches') ; $map->add($tooLateMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface'))); list($listeners, $exception) = $map->getListeners($request); $this->assertEquals(array($theListener), $listeners); $this->assertEquals($theException, $exception); } public function testGetListenersWithAnEntryHavingNoRequestMatcher() { $map = new FirewallMap(); $request = new Request(); $notMatchingMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher'); $notMatchingMatcher ->expects($this->once()) ->method('matches') ->with($this->equalTo($request)) ->will($this->returnValue(false)) ; $map->add($notMatchingMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface'))); $theListener = $this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface'); $theException = $this->getMock('Symfony\Component\Security\Http\Firewall\ExceptionListener', array(), array(), '', false); $map->add(null, array($theListener), $theException); $tooLateMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher'); $tooLateMatcher ->expects($this->never()) ->method('matches') ; $map->add($tooLateMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface'))); list($listeners, $exception) = $map->getListeners($request); $this->assertEquals(array($theListener), $listeners); $this->assertEquals($theException, $exception); } public function testGetListenersWithNoMatchingEntry() { $map = new FirewallMap(); $request = new Request(); $notMatchingMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcher'); $notMatchingMatcher ->expects($this->once()) ->method('matches') ->with($this->equalTo($request)) ->will($this->returnValue(false)) ; $map->add($notMatchingMatcher, array($this->getMock('Symfony\Component\Security\Http\Firewall\ListenerInterface'))); list($listeners, $exception) = $map->getListeners($request); $this->assertEquals(array(), $listeners); $this->assertNull($exception); } } PK!%%Etest/Security/Symfony/Component/Security/Http/Tests/HttpUtilsTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Http\HttpUtils; class HttpUtilsTest extends \PHPUnit_Framework_TestCase { public function testCreateRedirectResponseWithPath() { $utils = new HttpUtils($this->getUrlGenerator()); $response = $utils->createRedirectResponse($this->getRequest(), '/foobar'); $this->assertTrue($response->isRedirect('http://localhost/foobar')); $this->assertEquals(302, $response->getStatusCode()); } public function testCreateRedirectResponseWithAbsoluteUrl() { $utils = new HttpUtils($this->getUrlGenerator()); $response = $utils->createRedirectResponse($this->getRequest(), 'http://symfony.com/'); $this->assertTrue($response->isRedirect('http://symfony.com/')); } public function testCreateRedirectResponseWithRouteName() { $utils = new HttpUtils($urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')); $urlGenerator ->expects($this->any()) ->method('generate') ->with('foobar', array(), true) ->will($this->returnValue('http://localhost/foo/bar')) ; $urlGenerator ->expects($this->any()) ->method('getContext') ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext'))) ; $response = $utils->createRedirectResponse($this->getRequest(), 'foobar'); $this->assertTrue($response->isRedirect('http://localhost/foo/bar')); } public function testCreateRequestWithPath() { $request = $this->getRequest(); $request->server->set('Foo', 'bar'); $utils = new HttpUtils($this->getUrlGenerator()); $subRequest = $utils->createRequest($request, '/foobar'); $this->assertEquals('GET', $subRequest->getMethod()); $this->assertEquals('/foobar', $subRequest->getPathInfo()); $this->assertEquals('bar', $subRequest->server->get('Foo')); } public function testCreateRequestWithRouteName() { $utils = new HttpUtils($urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')); $urlGenerator ->expects($this->once()) ->method('generate') ->will($this->returnValue('/foo/bar')) ; $urlGenerator ->expects($this->any()) ->method('getContext') ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext'))) ; $subRequest = $utils->createRequest($this->getRequest(), 'foobar'); $this->assertEquals('/foo/bar', $subRequest->getPathInfo()); } public function testCreateRequestWithAbsoluteUrl() { $utils = new HttpUtils($this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')); $subRequest = $utils->createRequest($this->getRequest(), 'http://symfony.com/'); $this->assertEquals('/', $subRequest->getPathInfo()); } public function testCreateRequestPassesSessionToTheNewRequest() { $request = $this->getRequest(); $request->setSession($session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface')); $utils = new HttpUtils($this->getUrlGenerator()); $subRequest = $utils->createRequest($request, '/foobar'); $this->assertSame($session, $subRequest->getSession()); } /** * @dataProvider provideSecurityContextAttributes */ public function testCreateRequestPassesSecurityContextAttributesToTheNewRequest($attribute) { $request = $this->getRequest(); $request->attributes->set($attribute, 'foo'); $utils = new HttpUtils($this->getUrlGenerator()); $subRequest = $utils->createRequest($request, '/foobar'); $this->assertSame('foo', $subRequest->attributes->get($attribute)); } public function provideSecurityContextAttributes() { return array( array(SecurityContextInterface::AUTHENTICATION_ERROR), array(SecurityContextInterface::ACCESS_DENIED_ERROR), array(SecurityContextInterface::LAST_USERNAME) ); } public function testCheckRequestPath() { $utils = new HttpUtils($this->getUrlGenerator()); $this->assertTrue($utils->checkRequestPath($this->getRequest(), '/')); $this->assertFalse($utils->checkRequestPath($this->getRequest(), '/foo')); $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo%20bar'), '/foo bar')); // Plus must not decoded to space $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo+bar'), '/foo+bar')); // Checking unicode $this->assertTrue($utils->checkRequestPath($this->getRequest(urlencode('/вход')), '/вход')); } public function testCheckRequestPathWithUrlMatcherAndResourceNotFound() { $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); $urlMatcher ->expects($this->any()) ->method('match') ->with('/') ->will($this->throwException(new ResourceNotFoundException())) ; $utils = new HttpUtils(null, $urlMatcher); $this->assertFalse($utils->checkRequestPath($this->getRequest(), 'foobar')); } public function testCheckRequestPathWithUrlMatcherAndMethodNotAllowed() { $request = $this->getRequest(); $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface'); $urlMatcher ->expects($this->any()) ->method('matchRequest') ->with($request) ->will($this->throwException(new MethodNotAllowedException(array()))) ; $utils = new HttpUtils(null, $urlMatcher); $this->assertFalse($utils->checkRequestPath($request, 'foobar')); } public function testCheckRequestPathWithUrlMatcherAndResourceFoundByUrl() { $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); $urlMatcher ->expects($this->any()) ->method('match') ->with('/foo/bar') ->will($this->returnValue(array('_route' => 'foobar'))) ; $utils = new HttpUtils(null, $urlMatcher); $this->assertTrue($utils->checkRequestPath($this->getRequest('/foo/bar'), 'foobar')); } public function testCheckRequestPathWithUrlMatcherAndResourceFoundByRequest() { $request = $this->getRequest(); $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface'); $urlMatcher ->expects($this->any()) ->method('matchRequest') ->with($request) ->will($this->returnValue(array('_route' => 'foobar'))) ; $utils = new HttpUtils(null, $urlMatcher); $this->assertTrue($utils->checkRequestPath($request, 'foobar')); } /** * @expectedException \RuntimeException */ public function testCheckRequestPathWithUrlMatcherLoadingException() { $urlMatcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); $urlMatcher ->expects($this->any()) ->method('match') ->will($this->throwException(new \RuntimeException())) ; $utils = new HttpUtils(null, $urlMatcher); $utils->checkRequestPath($this->getRequest(), 'foobar'); } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage Matcher must either implement UrlMatcherInterface or RequestMatcherInterface */ public function testUrlMatcher() { new HttpUtils($this->getUrlGenerator(), new \stdClass()); } public function testGenerateUriRemovesQueryString() { $utils = new HttpUtils($this->getUrlGenerator('/foo/bar')); $this->assertEquals('/foo/bar', $utils->generateUri(new Request(), 'route_name')); $utils = new HttpUtils($this->getUrlGenerator('/foo/bar?param=value')); $this->assertEquals('/foo/bar', $utils->generateUri(new Request(), 'route_name')); } /** * @expectedException \LogicException * @expectedExceptionMessage You must provide a UrlGeneratorInterface instance to be able to use routes. */ public function testUrlGeneratorIsRequiredToGenerateUrl() { $utils = new HttpUtils(); $utils->generateUri(new Request(), 'route_name'); } private function getUrlGenerator($generatedUrl = '/foo/bar') { $urlGenerator = $this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface'); $urlGenerator ->expects($this->any()) ->method('generate') ->will($this->returnValue($generatedUrl)) ; return $urlGenerator; } private function getRequest($path = '/') { return Request::create($path, 'get'); } } PK!ck~ ~ ctest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/FormAuthenticationEntryPointTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\EntryPoint; use Symfony\Component\Security\Http\EntryPoint\FormAuthenticationEntryPoint; use Symfony\Component\HttpKernel\HttpKernelInterface; class FormAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase { public function testStart() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $response = $this->getMock('Symfony\Component\HttpFoundation\Response'); $httpKernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils'); $httpUtils ->expects($this->once()) ->method('createRedirectResponse') ->with($this->equalTo($request), $this->equalTo('/the/login/path')) ->will($this->returnValue($response)) ; $entryPoint = new FormAuthenticationEntryPoint($httpKernel, $httpUtils, '/the/login/path', false); $this->assertEquals($response, $entryPoint->start($request)); } public function testStartWithUseForward() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $subRequest = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $response = new \Symfony\Component\HttpFoundation\Response('', 200); $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils'); $httpUtils ->expects($this->once()) ->method('createRequest') ->with($this->equalTo($request), $this->equalTo('/the/login/path')) ->will($this->returnValue($subRequest)) ; $httpKernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $httpKernel ->expects($this->once()) ->method('handle') ->with($this->equalTo($subRequest), $this->equalTo(HttpKernelInterface::SUB_REQUEST)) ->will($this->returnValue($response)) ; $entryPoint = new FormAuthenticationEntryPoint($httpKernel, $httpUtils, '/the/login/path', true); $entryPointResponse = $entryPoint->start($request); $this->assertEquals($response, $entryPointResponse); $this->assertEquals(401, $entryPointResponse->headers->get('X-Status-Code')); } } PK!edtest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/BasicAuthenticationEntryPointTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\EntryPoint; use Symfony\Component\Security\Http\EntryPoint\BasicAuthenticationEntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; class BasicAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase { public function testStart() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $authException = new AuthenticationException('The exception message'); $entryPoint = new BasicAuthenticationEntryPoint('TheRealmName'); $response = $entryPoint->start($request, $authException); $this->assertEquals('Basic realm="TheRealmName"', $response->headers->get('WWW-Authenticate')); $this->assertEquals(401, $response->getStatusCode()); } public function testStartWithoutAuthException() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $entryPoint = new BasicAuthenticationEntryPoint('TheRealmName'); $response = $entryPoint->start($request); $this->assertEquals('Basic realm="TheRealmName"', $response->headers->get('WWW-Authenticate')); $this->assertEquals(401, $response->getStatusCode()); } } PK!-Ɔ dtest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/RetryAuthenticationEntryPointTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\EntryPoint; use Symfony\Component\Security\Http\EntryPoint\RetryAuthenticationEntryPoint; use Symfony\Component\HttpFoundation\Request; class RetryAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider dataForStart */ public function testStart($httpPort, $httpsPort, $request, $expectedUrl) { $entryPoint = new RetryAuthenticationEntryPoint($httpPort, $httpsPort); $response = $entryPoint->start($request); $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response); $this->assertEquals($expectedUrl, $response->headers->get('Location')); } public function dataForStart() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { return array(array()); } return array( array( 80, 443, Request::create('http://localhost/foo/bar?baz=bat'), 'https://localhost/foo/bar?baz=bat' ), array( 80, 443, Request::create('https://localhost/foo/bar?baz=bat'), 'http://localhost/foo/bar?baz=bat' ), array( 80, 123, Request::create('http://localhost/foo/bar?baz=bat'), 'https://localhost:123/foo/bar?baz=bat' ), array( 8080, 443, Request::create('https://localhost/foo/bar?baz=bat'), 'http://localhost:8080/foo/bar?baz=bat' ) ); } } PK!GrT  etest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\EntryPoint; use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\NonceExpiredException; class DigestAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase { public function testStart() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $authenticationException = new AuthenticationException('TheAuthenticationExceptionMessage'); $entryPoint = new DigestAuthenticationEntryPoint('TheRealmName', 'TheKey'); $response = $entryPoint->start($request, $authenticationException); $this->assertEquals(401, $response->getStatusCode()); $this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}"$/', $response->headers->get('WWW-Authenticate')); } public function testStartWithNoException() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $entryPoint = new DigestAuthenticationEntryPoint('TheRealmName', 'TheKey'); $response = $entryPoint->start($request); $this->assertEquals(401, $response->getStatusCode()); $this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}"$/', $response->headers->get('WWW-Authenticate')); } public function testStartWithNonceExpiredException() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $nonceExpiredException = new NonceExpiredException('TheNonceExpiredExceptionMessage'); $entryPoint = new DigestAuthenticationEntryPoint('TheRealmName', 'TheKey'); $response = $entryPoint->start($request, $nonceExpiredException); $this->assertEquals(401, $response->getStatusCode()); $this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}", stale="true"$/', $response->headers->get('WWW-Authenticate')); } } PK!Ғ)Wtest/Security/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Firewall\RememberMeListener; use Symfony\Component\HttpFoundation\Request; class RememberMeListenerTest extends \PHPUnit_Framework_TestCase { public function testOnCoreSecurityDoesNotTryToPopulateNonEmptySecurityContext() { list($listener, $context, $service,,) = $this->getListener(); $context ->expects($this->once()) ->method('getToken') ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))) ; $context ->expects($this->never()) ->method('setToken') ; $this->assertNull($listener->handle($this->getGetResponseEvent())); } public function testOnCoreSecurityDoesNothingWhenNoCookieIsSet() { list($listener, $context, $service,,) = $this->getListener(); $context ->expects($this->once()) ->method('getToken') ->will($this->returnValue(null)) ; $service ->expects($this->once()) ->method('autoLogin') ->will($this->returnValue(null)) ; $event = $this->getGetResponseEvent(); $event ->expects($this->once()) ->method('getRequest') ->will($this->returnValue(new Request())) ; $this->assertNull($listener->handle($event)); } public function testOnCoreSecurityIgnoresAuthenticationExceptionThrownByAuthenticationManagerImplementation() { list($listener, $context, $service, $manager,) = $this->getListener(); $context ->expects($this->once()) ->method('getToken') ->will($this->returnValue(null)) ; $service ->expects($this->once()) ->method('autoLogin') ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))) ; $service ->expects($this->once()) ->method('loginFail') ; $exception = new AuthenticationException('Authentication failed.'); $manager ->expects($this->once()) ->method('authenticate') ->will($this->throwException($exception)) ; $event = $this->getGetResponseEvent(); $event ->expects($this->once()) ->method('getRequest') ->will($this->returnValue(new Request())) ; $listener->handle($event); } public function testOnCoreSecurity() { list($listener, $context, $service, $manager,) = $this->getListener(); $context ->expects($this->once()) ->method('getToken') ->will($this->returnValue(null)) ; $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $service ->expects($this->once()) ->method('autoLogin') ->will($this->returnValue($token)) ; $context ->expects($this->once()) ->method('setToken') ->with($this->equalTo($token)) ; $manager ->expects($this->once()) ->method('authenticate') ->will($this->returnValue($token)) ; $event = $this->getGetResponseEvent(); $event ->expects($this->once()) ->method('getRequest') ->will($this->returnValue(new Request())) ; $listener->handle($event); } protected function getGetResponseEvent() { return $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); } protected function getFilterResponseEvent() { return $this->getMock('Symfony\Component\HttpKernel\Event\FilterResponseEvent', array(), array(), '', false); } protected function getListener() { $listener = new RememberMeListener( $context = $this->getContext(), $service = $this->getService(), $manager = $this->getManager(), $logger = $this->getLogger() ); return array($listener, $context, $service, $manager, $logger); } protected function getLogger() { return $this->getMock('Psr\Log\LoggerInterface'); } protected function getManager() { return $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); } protected function getService() { return $this->getMock('Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface'); } protected function getContext() { return $this->getMockBuilder('Symfony\Component\Security\Core\SecurityContext') ->disableOriginalConstructor() ->getMock(); } } PK!G  Ttest/Security/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\Security\Http\Firewall\ChannelListener; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpFoundation\Response; class ChannelListenerTest extends \PHPUnit_Framework_TestCase { public function testHandleWithNotSecuredRequestAndHttpChannel() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $request ->expects($this->any()) ->method('isSecure') ->will($this->returnValue(false)) ; $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface'); $accessMap ->expects($this->any()) ->method('getPatterns') ->with($this->equalTo($request)) ->will($this->returnValue(array(array(), 'http'))) ; $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface'); $entryPoint ->expects($this->never()) ->method('start') ; $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $event ->expects($this->never()) ->method('setResponse') ; $listener = new ChannelListener($accessMap, $entryPoint); $listener->handle($event); } public function testHandleWithSecuredRequestAndHttpsChannel() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $request ->expects($this->any()) ->method('isSecure') ->will($this->returnValue(true)) ; $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface'); $accessMap ->expects($this->any()) ->method('getPatterns') ->with($this->equalTo($request)) ->will($this->returnValue(array(array(), 'https'))) ; $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface'); $entryPoint ->expects($this->never()) ->method('start') ; $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $event ->expects($this->never()) ->method('setResponse') ; $listener = new ChannelListener($accessMap, $entryPoint); $listener->handle($event); } public function testHandleWithNotSecuredRequestAndHttpsChannel() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $request ->expects($this->any()) ->method('isSecure') ->will($this->returnValue(false)) ; $response = new Response(); $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface'); $accessMap ->expects($this->any()) ->method('getPatterns') ->with($this->equalTo($request)) ->will($this->returnValue(array(array(), 'https'))) ; $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface'); $entryPoint ->expects($this->once()) ->method('start') ->with($this->equalTo($request)) ->will($this->returnValue($response)) ; $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $event ->expects($this->once()) ->method('setResponse') ->with($this->equalTo($response)) ; $listener = new ChannelListener($accessMap, $entryPoint); $listener->handle($event); } public function testHandleWithSecuredRequestAndHttpChannel() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $request ->expects($this->any()) ->method('isSecure') ->will($this->returnValue(true)) ; $response = new Response(); $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface'); $accessMap ->expects($this->any()) ->method('getPatterns') ->with($this->equalTo($request)) ->will($this->returnValue(array(array(), 'http'))) ; $entryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface'); $entryPoint ->expects($this->once()) ->method('start') ->with($this->equalTo($request)) ->will($this->returnValue($response)) ; $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $event ->expects($this->once()) ->method('setResponse') ->with($this->equalTo($response)) ; $listener = new ChannelListener($accessMap, $entryPoint); $listener->handle($event); } } PK!e dtest/Security/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\Security\Http\Firewall\AnonymousAuthenticationListener; class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase { public function testHandleWithContextHavingAToken() { $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))) ; $context ->expects($this->never()) ->method('setToken') ; $listener = new AnonymousAuthenticationListener($context, 'TheKey'); $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false)); } public function testHandleWithContextHavingNoToken() { $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue(null)) ; $context ->expects($this->once()) ->method('setToken') ->with(self::logicalAnd( $this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken'), $this->attributeEqualTo('key', 'TheKey') )) ; $listener = new AnonymousAuthenticationListener($context, 'TheKey'); $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false)); } public function testHandledEventIsLogged() { if (!interface_exists('Psr\Log\LoggerInterface')) { $this->markTestSkipped('The "LoggerInterface" is not available'); } $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $logger = $this->getMock('Psr\Log\LoggerInterface'); $logger->expects($this->once()) ->method('info') ->with('Populated SecurityContext with an anonymous Token') ; $listener = new AnonymousAuthenticationListener($context, 'TheKey', $logger); $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false)); } } PK!K$$`test/Security/Symfony/Component/Security/Http/Tests/Firewall/BasicAuthenticationListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Http\Firewall\BasicAuthenticationListener; use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager; class BasicAuthenticationListenerTest extends \PHPUnit_Framework_TestCase { public function testHandleWithValidUsernameAndPasswordServerParameters() { $request = new Request(array(), array(), array(), array(), array(), array( 'PHP_AUTH_USER' => 'TheUsername', 'PHP_AUTH_PW' => 'ThePassword' )); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue(null)) ; $context ->expects($this->once()) ->method('setToken') ->with($this->equalTo($token)) ; $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $authenticationManager ->expects($this->once()) ->method('authenticate') ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')) ->will($this->returnValue($token)) ; $listener = new BasicAuthenticationListener( $context, $authenticationManager, 'TheProviderKey', $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface') ); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } public function testHandleWhenAuthenticationFails() { $request = new Request(array(), array(), array(), array(), array(), array( 'PHP_AUTH_USER' => 'TheUsername', 'PHP_AUTH_PW' => 'ThePassword' )); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue(null)) ; $context ->expects($this->never()) ->method('setToken') ; $response = new Response(); $authenticationEntryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface'); $authenticationEntryPoint ->expects($this->any()) ->method('start') ->with($this->equalTo($request), $this->isInstanceOf('Symfony\Component\Security\Core\Exception\AuthenticationException')) ->will($this->returnValue($response)) ; $listener = new BasicAuthenticationListener( $context, new AuthenticationProviderManager(array($this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface'))), 'TheProviderKey', $authenticationEntryPoint ); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $event ->expects($this->once()) ->method('setResponse') ->with($this->equalTo($response)) ; $listener->handle($event); } public function testHandleWithNoUsernameServerParameter() { $request = new Request(); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->never()) ->method('getToken') ; $listener = new BasicAuthenticationListener( $context, $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), 'TheProviderKey', $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface') ); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } public function testHandleWithASimilarAuthenticatedToken() { $request = new Request(array(), array(), array(), array(), array(), array('PHP_AUTH_USER' => 'TheUsername')); $token = new UsernamePasswordToken('TheUsername', 'ThePassword', 'TheProviderKey', array('ROLE_FOO')); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue($token)) ; $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $authenticationManager ->expects($this->never()) ->method('authenticate') ; $listener = new BasicAuthenticationListener( $context, $authenticationManager, 'TheProviderKey', $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface') ); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage $providerKey must not be empty */ public function testItRequiresProviderKey() { new BasicAuthenticationListener( $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'), $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), '', $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface') ); } public function testHandleWithADifferentAuthenticatedToken() { $request = new Request(array(), array(), array(), array(), array(), array( 'PHP_AUTH_USER' => 'TheUsername', 'PHP_AUTH_PW' => 'ThePassword' )); $token = new PreAuthenticatedToken('TheUser', 'TheCredentials', 'TheProviderKey', array('ROLE_FOO')); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue($token)) ; $context ->expects($this->never()) ->method('setToken') ; $response = new Response(); $authenticationEntryPoint = $this->getMock('Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface'); $authenticationEntryPoint ->expects($this->any()) ->method('start') ->with($this->equalTo($request), $this->isInstanceOf('Symfony\Component\Security\Core\Exception\AuthenticationException')) ->will($this->returnValue($response)) ; $listener = new BasicAuthenticationListener( $context, new AuthenticationProviderManager(array($this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface'))), 'TheProviderKey', $authenticationEntryPoint ); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $event ->expects($this->once()) ->method('setResponse') ->with($this->equalTo($response)) ; $listener->handle($event); } } PK!lOtest/Security/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\Security\Http\Firewall\DigestData; class DigestDataTest extends \PHPUnit_Framework_TestCase { public function testGetResponse() { $digestAuth = new DigestData( 'username="user", realm="Welcome, robot!", ' . 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' . 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' . 'response="b52938fc9e6d7c01be7702ece9031b42"' ); $this->assertEquals('b52938fc9e6d7c01be7702ece9031b42', $digestAuth->getResponse()); } public function testGetUsername() { $digestAuth = new DigestData( 'username="user", realm="Welcome, robot!", ' . 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' . 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' . 'response="b52938fc9e6d7c01be7702ece9031b42"' ); $this->assertEquals('user', $digestAuth->getUsername()); } public function testGetUsernameWithQuote() { $digestAuth = new DigestData( 'username="\"user\"", realm="Welcome, robot!", ' . 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' . 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' . 'response="b52938fc9e6d7c01be7702ece9031b42"' ); $this->assertEquals('"user"', $digestAuth->getUsername()); } public function testGetUsernameWithQuoteAndEscape() { $digestAuth = new DigestData( 'username="\"u\\\\\"ser\"", realm="Welcome, robot!", ' . 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' . 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' . 'response="b52938fc9e6d7c01be7702ece9031b42"' ); $this->assertEquals('"u\\"ser"', $digestAuth->getUsername()); } public function testGetUsernameWithSingleQuote() { $digestAuth = new DigestData( 'username="\"u\'ser\"", realm="Welcome, robot!", ' . 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' . 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' . 'response="b52938fc9e6d7c01be7702ece9031b42"' ); $this->assertEquals('"u\'ser"', $digestAuth->getUsername()); } public function testGetUsernameWithSingleQuoteAndEscape() { $digestAuth = new DigestData( 'username="\"u\\\'ser\"", realm="Welcome, robot!", ' . 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' . 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' . 'response="b52938fc9e6d7c01be7702ece9031b42"' ); $this->assertEquals('"u\\\'ser"', $digestAuth->getUsername()); } public function testGetUsernameWithEscape() { $digestAuth = new DigestData( 'username="\"u\\ser\"", realm="Welcome, robot!", ' . 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' . 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' . 'response="b52938fc9e6d7c01be7702ece9031b42"' ); $this->assertEquals('"u\\ser"', $digestAuth->getUsername()); } public function testValidateAndDecode() { $time = microtime(true); $key = 'ThisIsAKey'; $nonce = base64_encode($time.':'.md5($time.':'.$key)); $digestAuth = new DigestData( 'username="user", realm="Welcome, robot!", nonce="'.$nonce.'", ' . 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' . 'response="b52938fc9e6d7c01be7702ece9031b42"' ); try { $digestAuth->validateAndDecode($key, 'Welcome, robot!'); } catch (\Exception $e) { $this->fail(sprintf('testValidateAndDecode fail with message: %s', $e->getMessage())); } } public function testCalculateServerDigest() { $this->calculateServerDigest('user', 'Welcome, robot!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); } public function testCalculateServerDigestWithQuote() { $this->calculateServerDigest('\"user\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); } public function testCalculateServerDigestWithQuoteAndEscape() { $this->calculateServerDigest('\"u\\\\\"ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); } public function testCalculateServerDigestEscape() { $this->calculateServerDigest('\"u\\ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); $this->calculateServerDigest('\"u\\ser\\\\\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); } public function testIsNonceExpired() { $time = microtime(true) + 10; $key = 'ThisIsAKey'; $nonce = base64_encode($time.':'.md5($time.':'.$key)); $digestAuth = new DigestData( 'username="user", realm="Welcome, robot!", nonce="'.$nonce.'", ' . 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' . 'response="b52938fc9e6d7c01be7702ece9031b42"' ); $digestAuth->validateAndDecode($key, 'Welcome, robot!'); $this->assertFalse($digestAuth->isNonceExpired()); } protected function setUp() { class_exists('Symfony\Component\Security\Http\Firewall\DigestAuthenticationListener', true); } private function calculateServerDigest($username, $realm, $password, $key, $nc, $cnonce, $qop, $method, $uri) { $time = microtime(true); $nonce = base64_encode($time.':'.md5($time.':'.$key)); $response = md5( md5($username.':'.$realm.':'.$password).':'.$nonce.':'.$nc.':'.$cnonce.':'.$qop.':'.md5($method.':'.$uri) ); $digest = sprintf('username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%s, qop="%s", response="%s"', $username, $realm, $nonce, $uri, $cnonce, $nc, $qop, $response ); $digestAuth = new DigestData($digest); $this->assertEquals($digestAuth->getResponse(), $digestAuth->calculateServerDigest($password, $method)); } } PK!jz9""Ttest/Security/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\SecurityContext; use Symfony\Component\Security\Http\Firewall\ContextListener; class ContextListenerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { $this->securityContext = new SecurityContext( $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface') ); } protected function tearDown() { unset($this->securityContext); } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage $contextKey must not be empty */ public function testItRequiresContextKey() { new ContextListener( $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'), array(), '' ); } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage User provider "stdClass" must implement "Symfony\Component\Security\Core\User\UserProviderInterface */ public function testUserProvidersNeedToImplementAnInterface() { new ContextListener( $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'), array(new \stdClass()), 'key123' ); } public function testOnKernelResponseWillAddSession() { $session = $this->runSessionOnKernelResponse( new UsernamePasswordToken('test1', 'pass1', 'phpunit'), null ); $token = unserialize($session->get('_security_session')); $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $token); $this->assertEquals('test1', $token->getUsername()); } public function testOnKernelResponseWillReplaceSession() { $session = $this->runSessionOnKernelResponse( new UsernamePasswordToken('test1', 'pass1', 'phpunit'), 'C:10:"serialized"' ); $token = unserialize($session->get('_security_session')); $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $token); $this->assertEquals('test1', $token->getUsername()); } public function testOnKernelResponseWillRemoveSession() { $session = $this->runSessionOnKernelResponse( null, 'C:10:"serialized"' ); $this->assertFalse($session->has('_security_session')); } public function testOnKernelResponseWithoutSession() { $this->securityContext->setToken(new UsernamePasswordToken('test1', 'pass1', 'phpunit')); $request = new Request(); $session = new Session(new MockArraySessionStorage()); $request->setSession($session); $event = new FilterResponseEvent( $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST, new Response() ); $listener = new ContextListener($this->securityContext, array(), 'session'); $listener->onKernelResponse($event); $this->assertTrue($session->isStarted()); } public function testOnKernelResponseWithoutSessionNorToken() { $request = new Request(); $session = new Session(new MockArraySessionStorage()); $request->setSession($session); $event = new FilterResponseEvent( $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST, new Response() ); $listener = new ContextListener($this->securityContext, array(), 'session'); $listener->onKernelResponse($event); $this->assertFalse($session->isStarted()); } /** * @dataProvider provideInvalidToken */ public function testInvalidTokenInSession($token) { $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') ->disableOriginalConstructor() ->getMock(); $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface'); $event->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)); $request->expects($this->any()) ->method('hasPreviousSession') ->will($this->returnValue(true)); $request->expects($this->any()) ->method('getSession') ->will($this->returnValue($session)); $session->expects($this->any()) ->method('get') ->with('_security_key123') ->will($this->returnValue($token)); $context->expects($this->once()) ->method('setToken') ->with(null); $listener = new ContextListener($context, array(), 'key123'); $listener->handle($event); } public function provideInvalidToken() { return array( array(serialize(new \__PHP_Incomplete_Class())), array(serialize(null)), array(null) ); } public function testHandleAddsKernelResponseListener() { $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') ->disableOriginalConstructor() ->getMock(); $listener = new ContextListener($context, array(), 'key123', null, $dispatcher); $event->expects($this->any()) ->method('isMasterRequest') ->will($this->returnValue(true)); $event->expects($this->any()) ->method('getRequest') ->will($this->returnValue($this->getMock('Symfony\Component\HttpFoundation\Request'))); $dispatcher->expects($this->once()) ->method('addListener') ->with(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); $listener->handle($event); } public function testHandleRemovesTokenIfNoPreviousSessionWasFound() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $request->expects($this->any())->method('hasPreviousSession')->will($this->returnValue(false)); $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') ->disableOriginalConstructor() ->getMock(); $event->expects($this->any())->method('getRequest')->will($this->returnValue($request)); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context->expects($this->once())->method('setToken')->with(null); $listener = new ContextListener($context, array(), 'key123'); $listener->handle($event); } protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); if ($original !== null) { $session->set('_security_session', $original); } $this->securityContext->setToken($newToken); $request = new Request(); $request->setSession($session); $request->cookies->set('MOCKSESSID', true); $event = new FilterResponseEvent( $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST, new Response() ); $listener = new ContextListener($this->securityContext, array(), 'session'); $listener->onKernelResponse($event); return $session; } } PK!<%%etest/Security/Symfony/Component/Security/Http/Tests/Firewall/AbstractPreAuthenticatedListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; class AbstractPreAuthenticatedListenerTest extends \PHPUnit_Framework_TestCase { public function testHandleWithValidValues() { $userCredentials = array('TheUser', 'TheCredentials'); $request = new Request(array(), array(), array(), array(), array(), array()); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue(null)) ; $context ->expects($this->once()) ->method('setToken') ->with($this->equalTo($token)) ; $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $authenticationManager ->expects($this->once()) ->method('authenticate') ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken')) ->will($this->returnValue($token)) ; $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array( $context, $authenticationManager, 'TheProviderKey' )); $listener ->expects($this->once()) ->method('getPreAuthenticatedData') ->will($this->returnValue($userCredentials)); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } public function testHandleWhenAuthenticationFails() { $userCredentials = array('TheUser', 'TheCredentials'); $request = new Request(array(), array(), array(), array(), array(), array()); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue(null)) ; $context ->expects($this->never()) ->method('setToken') ; $exception = new AuthenticationException('Authentication failed.'); $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $authenticationManager ->expects($this->once()) ->method('authenticate') ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken')) ->will($this->throwException($exception)) ; $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array( $context, $authenticationManager, 'TheProviderKey' )); $listener ->expects($this->once()) ->method('getPreAuthenticatedData') ->will($this->returnValue($userCredentials)); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } public function testHandleWhenAuthenticationFailsWithDifferentToken() { $userCredentials = array('TheUser', 'TheCredentials'); $token = new UsernamePasswordToken('TheUsername', 'ThePassword', 'TheProviderKey', array('ROLE_FOO')); $request = new Request(array(), array(), array(), array(), array(), array()); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue($token)) ; $context ->expects($this->never()) ->method('setToken') ; $exception = new AuthenticationException('Authentication failed.'); $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $authenticationManager ->expects($this->once()) ->method('authenticate') ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken')) ->will($this->throwException($exception)) ; $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array( $context, $authenticationManager, 'TheProviderKey' )); $listener ->expects($this->once()) ->method('getPreAuthenticatedData') ->will($this->returnValue($userCredentials)); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } public function testHandleWithASimilarAuthenticatedToken() { $userCredentials = array('TheUser', 'TheCredentials'); $request = new Request(array(), array(), array(), array(), array(), array()); $token = new PreAuthenticatedToken('TheUser', 'TheCredentials', 'TheProviderKey', array('ROLE_FOO')); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue($token)) ; $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $authenticationManager ->expects($this->never()) ->method('authenticate') ; $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array( $context, $authenticationManager, 'TheProviderKey' )); $listener ->expects($this->once()) ->method('getPreAuthenticatedData') ->will($this->returnValue($userCredentials)); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } public function testHandleWithAnInvalidSimilarToken() { $userCredentials = array('TheUser', 'TheCredentials'); $request = new Request(array(), array(), array(), array(), array(), array()); $token = new PreAuthenticatedToken('AnotherUser', 'TheCredentials', 'TheProviderKey', array('ROLE_FOO')); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue($token)) ; $context ->expects($this->once()) ->method('setToken') ->with($this->equalTo(null)) ; $exception = new AuthenticationException('Authentication failed.'); $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $authenticationManager ->expects($this->once()) ->method('authenticate') ->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken')) ->will($this->throwException($exception)) ; $listener = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Firewall\AbstractPreAuthenticatedListener', array( $context, $authenticationManager, 'TheProviderKey' )); $listener ->expects($this->once()) ->method('getPreAuthenticatedData') ->will($this->returnValue($userCredentials)); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } } PK!qStest/Security/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\Security\Http\Firewall\AccessListener; class AccessListenerTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException */ public function testHandleWhenTheAccessDecisionManagerDecidesToRefuseAccess() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface'); $accessMap ->expects($this->any()) ->method('getPatterns') ->with($this->equalTo($request)) ->will($this->returnValue(array(array('foo' => 'bar'), null))) ; $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->any()) ->method('isAuthenticated') ->will($this->returnValue(true)) ; $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue($token)) ; $accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'); $accessDecisionManager ->expects($this->once()) ->method('decide') ->with($this->equalTo($token), $this->equalTo(array('foo' => 'bar')), $this->equalTo($request)) ->will($this->returnValue(false)) ; $listener = new AccessListener( $context, $accessDecisionManager, $accessMap, $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface') ); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } public function testHandleWhenTheTokenIsNotAuthenticated() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface'); $accessMap ->expects($this->any()) ->method('getPatterns') ->with($this->equalTo($request)) ->will($this->returnValue(array(array('foo' => 'bar'), null))) ; $notAuthenticatedToken = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $notAuthenticatedToken ->expects($this->any()) ->method('isAuthenticated') ->will($this->returnValue(false)) ; $authenticatedToken = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $authenticatedToken ->expects($this->any()) ->method('isAuthenticated') ->will($this->returnValue(true)) ; $authManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $authManager ->expects($this->once()) ->method('authenticate') ->with($this->equalTo($notAuthenticatedToken)) ->will($this->returnValue($authenticatedToken)) ; $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue($notAuthenticatedToken)) ; $context ->expects($this->once()) ->method('setToken') ->with($this->equalTo($authenticatedToken)) ; $accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'); $accessDecisionManager ->expects($this->once()) ->method('decide') ->with($this->equalTo($authenticatedToken), $this->equalTo(array('foo' => 'bar')), $this->equalTo($request)) ->will($this->returnValue(true)) ; $listener = new AccessListener( $context, $accessDecisionManager, $accessMap, $authManager ); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } public function testHandleWhenThereIsNoAccessMapEntryMatchingTheRequest() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request', array(), array(), '', false, false); $accessMap = $this->getMock('Symfony\Component\Security\Http\AccessMapInterface'); $accessMap ->expects($this->any()) ->method('getPatterns') ->with($this->equalTo($request)) ->will($this->returnValue(array(null, null))) ; $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->never()) ->method('isAuthenticated') ; $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue($token)) ; $listener = new AccessListener( $context, $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'), $accessMap, $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface') ); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $event ->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; $listener->handle($event); } /** * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException */ public function testHandleWhenTheSecurityContextHasNoToken() { $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $context ->expects($this->any()) ->method('getToken') ->will($this->returnValue(null)) ; $listener = new AccessListener( $context, $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'), $this->getMock('Symfony\Component\Security\Http\AccessMapInterface'), $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface') ); $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); $listener->handle($event); } } PK!VkStest/Security/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Http\Firewall\LogoutListener; class LogoutListenerTest extends \PHPUnit_Framework_TestCase { public function testHandleUnmatchedPath() { list($listener, $context, $httpUtils, $options) = $this->getListener(); list($event, $request) = $this->getGetResponseEvent(); $event->expects($this->never()) ->method('setResponse'); $httpUtils->expects($this->once()) ->method('checkRequestPath') ->with($request, $options['logout_path']) ->will($this->returnValue(false)); $listener->handle($event); } public function testHandleMatchedPathWithSuccessHandlerAndCsrfValidation() { $successHandler = $this->getSuccessHandler(); $tokenManager = $this->getTokenManager(); list($listener, $context, $httpUtils, $options) = $this->getListener($successHandler, $tokenManager); list($event, $request) = $this->getGetResponseEvent(); $request->query->set('_csrf_token', 'token'); $httpUtils->expects($this->once()) ->method('checkRequestPath') ->with($request, $options['logout_path']) ->will($this->returnValue(true)); $tokenManager->expects($this->once()) ->method('isTokenValid') ->will($this->returnValue(true)); $successHandler->expects($this->once()) ->method('onLogoutSuccess') ->with($request) ->will($this->returnValue($response = new Response())); $context->expects($this->once()) ->method('getToken') ->will($this->returnValue($token = $this->getToken())); $handler = $this->getHandler(); $handler->expects($this->once()) ->method('logout') ->with($request, $response, $token); $context->expects($this->once()) ->method('setToken') ->with(null); $event->expects($this->once()) ->method('setResponse') ->with($response); $listener->addHandler($handler); $listener->handle($event); } public function testHandleMatchedPathWithoutSuccessHandlerAndCsrfValidation() { $successHandler = $this->getSuccessHandler(); list($listener, $context, $httpUtils, $options) = $this->getListener($successHandler); list($event, $request) = $this->getGetResponseEvent(); $httpUtils->expects($this->once()) ->method('checkRequestPath') ->with($request, $options['logout_path']) ->will($this->returnValue(true)); $successHandler->expects($this->once()) ->method('onLogoutSuccess') ->with($request) ->will($this->returnValue($response = new Response())); $context->expects($this->once()) ->method('getToken') ->will($this->returnValue($token = $this->getToken())); $handler = $this->getHandler(); $handler->expects($this->once()) ->method('logout') ->with($request, $response, $token); $context->expects($this->once()) ->method('setToken') ->with(null); $event->expects($this->once()) ->method('setResponse') ->with($response); $listener->addHandler($handler); $listener->handle($event); } /** * @expectedException \RuntimeException */ public function testSuccessHandlerReturnsNonResponse() { $successHandler = $this->getSuccessHandler(); list($listener, $context, $httpUtils, $options) = $this->getListener($successHandler); list($event, $request) = $this->getGetResponseEvent(); $httpUtils->expects($this->once()) ->method('checkRequestPath') ->with($request, $options['logout_path']) ->will($this->returnValue(true)); $successHandler->expects($this->once()) ->method('onLogoutSuccess') ->with($request) ->will($this->returnValue(null)); $listener->handle($event); } /** * @expectedException \Symfony\Component\Security\Core\Exception\LogoutException */ public function testCsrfValidationFails() { $tokenManager = $this->getTokenManager(); list($listener, $context, $httpUtils, $options) = $this->getListener(null, $tokenManager); list($event, $request) = $this->getGetResponseEvent(); $request->query->set('_csrf_token', 'token'); $httpUtils->expects($this->once()) ->method('checkRequestPath') ->with($request, $options['logout_path']) ->will($this->returnValue(true)); $tokenManager->expects($this->once()) ->method('isTokenValid') ->will($this->returnValue(false)); $listener->handle($event); } private function getTokenManager() { return $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); } private function getContext() { return $this->getMockBuilder('Symfony\Component\Security\Core\SecurityContext') ->disableOriginalConstructor() ->getMock(); } private function getGetResponseEvent() { $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') ->disableOriginalConstructor() ->getMock(); $event->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request = new Request())); return array($event, $request); } private function getHandler() { return $this->getMock('Symfony\Component\Security\Http\Logout\LogoutHandlerInterface'); } private function getHttpUtils() { return $this->getMockBuilder('Symfony\Component\Security\Http\HttpUtils') ->disableOriginalConstructor() ->getMock(); } private function getListener($successHandler = null, $tokenManager = null) { $listener = new LogoutListener( $context = $this->getContext(), $httpUtils = $this->getHttpUtils(), $successHandler ?: $this->getSuccessHandler(), $options = array( 'csrf_parameter' => '_csrf_token', 'intention' => 'logout', 'logout_path' => '/logout', 'target_url' => '/', ), $tokenManager ); return array($listener, $context, $httpUtils, $options); } private function getSuccessHandler() { return $this->getMock('Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface'); } private function getToken() { return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); } } PK!@&@&Wtest/Security/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\Security\Http\Firewall\SwitchUserListener; class SwitchUserListenerTest extends \PHPUnit_Framework_TestCase { private $securityContext; private $userProvider; private $userChecker; private $accessDecisionManager; private $request; private $event; protected function setUp() { $this->securityContext = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $this->userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); $this->userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); $this->accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'); $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $this->request->query = $this->getMock('Symfony\Component\HttpFoundation\ParameterBag'); $this->request->server = $this->getMock('Symfony\Component\HttpFoundation\ServerBag'); $this->event = $this->getEvent($this->request); } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage $providerKey must not be empty */ public function testProviderKeyIsRequired() { new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, '', $this->accessDecisionManager); } public function testEventIsIgnoredIfUsernameIsNotPassedWithTheRequest() { $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue(null)); $this->event->expects($this->never())->method('setResponse'); $this->securityContext->expects($this->never())->method('setToken'); $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); } /** * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException */ public function testExitUserThrowsAuthenticationExceptionIfOriginalTokenCannotBeFound() { $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface'))); $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token)); $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('_exit')); $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); } public function testExitUserUpdatesToken() { $originalToken = $this->getToken(); $role = $this->getMockBuilder('Symfony\Component\Security\Core\Role\SwitchUserRole') ->disableOriginalConstructor() ->getMock(); $role->expects($this->any())->method('getSource')->will($this->returnValue($originalToken)); $this->securityContext->expects($this->any()) ->method('getToken') ->will($this->returnValue($this->getToken(array($role)))); $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('_exit')); $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/')); $this->request->query->expects($this->once())->method('remove','_switch_user'); $this->request->query->expects($this->any())->method('all')->will($this->returnValue(array())); $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', ''); $this->securityContext->expects($this->once()) ->method('setToken')->with($originalToken); $this->event->expects($this->once()) ->method('setResponse')->with($this->isInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse')); $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); } /** * @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException */ public function testSwitchUserIsDissallowed() { $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface'))); $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token)); $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba')); $this->accessDecisionManager->expects($this->once()) ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) ->will($this->returnValue(false)); $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); } public function testSwitchUser() { $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface'))); $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user->expects($this->any())->method('getRoles')->will($this->returnValue(array())); $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token)); $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba')); $this->request->query->expects($this->once())->method('remove','_switch_user'); $this->request->query->expects($this->any())->method('all')->will($this->returnValue(array())); $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/')); $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', ''); $this->accessDecisionManager->expects($this->once()) ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) ->will($this->returnValue(true)); $this->userProvider->expects($this->once()) ->method('loadUserByUsername')->with('kuba') ->will($this->returnValue($user)); $this->userChecker->expects($this->once()) ->method('checkPostAuth')->with($user); $this->securityContext->expects($this->once()) ->method('setToken')->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')); $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); } public function testSwitchUserKeepsOtherQueryStringParameters() { $token = $this->getToken(array($this->getMock('Symfony\Component\Security\Core\Role\RoleInterface'))); $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user->expects($this->any())->method('getRoles')->will($this->returnValue(array())); $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($token)); $this->request->expects($this->any())->method('get')->with('_switch_user')->will($this->returnValue('kuba')); $this->request->query->expects($this->once())->method('remove','_switch_user'); $this->request->query->expects($this->any())->method('all')->will($this->returnValue(array('page'=>3,'section'=>2))); $this->request->expects($this->any())->method('getUri')->will($this->returnValue('/')); $this->request->server->expects($this->once())->method('set')->with('QUERY_STRING', 'page=3§ion=2'); $this->accessDecisionManager->expects($this->once()) ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) ->will($this->returnValue(true)); $this->userProvider->expects($this->once()) ->method('loadUserByUsername')->with('kuba') ->will($this->returnValue($user)); $this->userChecker->expects($this->once()) ->method('checkPostAuth')->with($user); $this->securityContext->expects($this->once()) ->method('setToken')->with($this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')); $listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); } private function getEvent($request) { $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') ->disableOriginalConstructor() ->getMock(); $event->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)); return $event; } private function getToken(array $roles = array()) { $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token->expects($this->any()) ->method('getRoles') ->will($this->returnValue($roles)); return $token; } } PK!LMM_test/Security/Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Firewall; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\Firewall\X509AuthenticationListener; class X509AuthenticationListenerTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider dataProviderGetPreAuthenticatedData */ public function testGetPreAuthenticatedData($user, $credentials) { $serverVars = array(); if ('' !== $user) { $serverVars['SSL_CLIENT_S_DN_Email'] = $user; } if ('' !== $credentials) { $serverVars['SSL_CLIENT_S_DN'] = $credentials; } $request = new Request(array(), array(), array(), array(), array(), $serverVars); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $listener = new X509AuthenticationListener( $context, $authenticationManager, 'TheProviderKey' ); $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData'); $method->setAccessible(true); $result = $method->invokeArgs($listener, array($request)); $this->assertSame($result, array($user, $credentials)); } public static function dataProviderGetPreAuthenticatedData() { return array( 'validValues' => array('TheUser', 'TheCredentials'), 'noCredentials' => array('TheUser', ''), ); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testGetPreAuthenticatedDataNoUser() { $request = new Request(array(), array(), array(), array(), array(), array()); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $listener = new X509AuthenticationListener( $context, $authenticationManager, 'TheProviderKey' ); $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData'); $method->setAccessible(true); $result = $method->invokeArgs($listener, array($request)); } public function testGetPreAuthenticatedDataWithDifferentKeys() { $userCredentials = array('TheUser', 'TheCredentials'); $request = new Request(array(), array(), array(), array(), array(), array( 'TheUserKey' => 'TheUser', 'TheCredentialsKey' => 'TheCredentials' )); $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $listener = new X509AuthenticationListener( $context, $authenticationManager, 'TheProviderKey', 'TheUserKey', 'TheCredentialsKey' ); $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData'); $method->setAccessible(true); $result = $method->invokeArgs($listener, array($request)); $this->assertSame($result, $userCredentials); } } PK!xWEtest/Security/Symfony/Component/Security/Http/Tests/AccessMapTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests; use Symfony\Component\Security\Http\AccessMap; class AccessMapTest extends \PHPUnit_Framework_TestCase { public function testReturnsFirstMatchedPattern() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $requestMatcher1 = $this->getRequestMatcher($request, false); $requestMatcher2 = $this->getRequestMatcher($request, true); $map = new AccessMap(); $map->add($requestMatcher1, array('ROLE_ADMIN'), 'http'); $map->add($requestMatcher2, array('ROLE_USER'), 'https'); $this->assertSame(array(array('ROLE_USER'), 'https'), $map->getPatterns($request)); } public function testReturnsEmptyPatternIfNoneMatched() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $requestMatcher = $this->getRequestMatcher($request, false); $map = new AccessMap(); $map->add($requestMatcher, array('ROLE_USER'), 'https'); $this->assertSame(array(null, null), $map->getPatterns($request)); } private function getRequestMatcher($request, $matches) { $requestMatcher = $this->getMock('Symfony\Component\HttpFoundation\RequestMatcherInterface'); $requestMatcher->expects($this->once()) ->method('matches')->with($request) ->will($this->returnValue($matches)); return $requestMatcher; } } PK!F8F8mtest/Security/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\RememberMe; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices; use Symfony\Component\Security\Core\Exception\TokenNotFoundException; use Symfony\Component\Security\Core\Exception\CookieTheftException; use Symfony\Component\Security\Core\Util\SecureRandom; class PersistentTokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase { public function testAutoLoginReturnsNullWhenNoCookie() { $service = $this->getService(null, array('name' => 'foo')); $this->assertNull($service->autoLogin(new Request())); } public function testAutoLoginThrowsExceptionOnInvalidCookie() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => false, 'remember_me_parameter' => 'foo')); $request = new Request(); $request->request->set('foo', 'true'); $request->cookies->set('foo', 'foo'); $this->assertNull($service->autoLogin($request)); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testAutoLoginThrowsExceptionOnNonExistentToken() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => false, 'remember_me_parameter' => 'foo')); $request = new Request(); $request->request->set('foo', 'true'); $request->cookies->set('foo', $this->encodeCookie(array( $series = 'fooseries', $tokenValue = 'foovalue', ))); $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface'); $tokenProvider ->expects($this->once()) ->method('loadTokenBySeries') ->will($this->throwException(new TokenNotFoundException('Token not found.'))) ; $service->setTokenProvider($tokenProvider); $this->assertNull($service->autoLogin($request)); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testAutoLoginReturnsNullOnNonExistentUser() { $userProvider = $this->getProvider(); $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600, 'secure' => false, 'httponly' => false)); $request = new Request(); $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue'))); $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface'); $tokenProvider ->expects($this->once()) ->method('loadTokenBySeries') ->will($this->returnValue(new PersistentToken('fooclass', 'fooname', 'fooseries', 'foovalue', new \DateTime()))) ; $service->setTokenProvider($tokenProvider); $userProvider ->expects($this->once()) ->method('loadUserByUsername') ->will($this->throwException(new UsernameNotFoundException('user not found'))) ; $this->assertNull($service->autoLogin($request)); $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)); } public function testAutoLoginThrowsExceptionOnStolenCookieAndRemovesItFromThePersistentBackend() { $userProvider = $this->getProvider(); $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true)); $request = new Request(); $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue'))); $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface'); $service->setTokenProvider($tokenProvider); $tokenProvider ->expects($this->once()) ->method('loadTokenBySeries') ->will($this->returnValue(new PersistentToken('fooclass', 'foouser', 'fooseries', 'anotherFooValue', new \DateTime()))) ; $tokenProvider ->expects($this->once()) ->method('deleteTokenBySeries') ->with($this->equalTo('fooseries')) ->will($this->returnValue(null)) ; try { $service->autoLogin($request); $this->fail('Expected CookieTheftException was not thrown.'); } catch (CookieTheftException $theft) { } $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)); } public function testAutoLoginDoesNotAcceptAnExpiredCookie() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600)); $request = new Request(); $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue'))); $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface'); $tokenProvider ->expects($this->once()) ->method('loadTokenBySeries') ->with($this->equalTo('fooseries')) ->will($this->returnValue(new PersistentToken('fooclass', 'username', 'fooseries', 'foovalue', new \DateTime('yesterday')))) ; $service->setTokenProvider($tokenProvider); $this->assertNull($service->autoLogin($request)); $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)); } public function testAutoLogin() { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user ->expects($this->once()) ->method('getRoles') ->will($this->returnValue(array('ROLE_FOO'))) ; $userProvider = $this->getProvider(); $userProvider ->expects($this->once()) ->method('loadUserByUsername') ->with($this->equalTo('foouser')) ->will($this->returnValue($user)) ; $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'secure' => false, 'httponly' => false, 'always_remember_me' => true, 'lifetime' => 3600)); $request = new Request(); $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue'))); $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface'); $tokenProvider ->expects($this->once()) ->method('loadTokenBySeries') ->with($this->equalTo('fooseries')) ->will($this->returnValue(new PersistentToken('fooclass', 'foouser', 'fooseries', 'foovalue', new \DateTime()))) ; $service->setTokenProvider($tokenProvider); $returnedToken = $service->autoLogin($request); $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', $returnedToken); $this->assertSame($user, $returnedToken->getUser()); $this->assertEquals('fookey', $returnedToken->getKey()); $this->assertTrue($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)); } public function testLogout() { $service = $this->getService(null, array('name' => 'foo', 'path' => '/foo', 'domain' => 'foodomain.foo')); $request = new Request(); $request->cookies->set('foo', $this->encodeCookie(array('fooseries', 'foovalue'))); $response = new Response(); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface'); $tokenProvider ->expects($this->once()) ->method('deleteTokenBySeries') ->with($this->equalTo('fooseries')) ->will($this->returnValue(null)) ; $service->setTokenProvider($tokenProvider); $service->logout($request, $response, $token); $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME); $this->assertTrue($cookie->isCleared()); $this->assertEquals('/foo', $cookie->getPath()); $this->assertEquals('foodomain.foo', $cookie->getDomain()); } public function testLogoutSimplyIgnoresNonSetRequestCookie() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $response = new Response(); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface'); $tokenProvider ->expects($this->never()) ->method('deleteTokenBySeries') ; $service->setTokenProvider($tokenProvider); $service->logout($request, $response, $token); $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME); $this->assertTrue($cookie->isCleared()); $this->assertEquals('/', $cookie->getPath()); $this->assertNull($cookie->getDomain()); } public function testLogoutSimplyIgnoresInvalidCookie() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $request->cookies->set('foo', 'somefoovalue'); $response = new Response(); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface'); $tokenProvider ->expects($this->never()) ->method('deleteTokenBySeries') ; $service->setTokenProvider($tokenProvider); $service->logout($request, $response, $token); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testLoginFail() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $this->assertFalse($request->attributes->has(RememberMeServicesInterface::COOKIE_ATTR_NAME)); $service->loginFail($request); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testLoginSuccessSetsCookieWhenLoggedInWithNonRememberMeTokenInterfaceImplementation() { $service = $this->getService(null, array('name' => 'foo', 'domain' => 'myfoodomain.foo', 'path' => '/foo/path', 'secure' => true, 'httponly' => true, 'lifetime' => 3600, 'always_remember_me' => true)); $request = new Request(); $response = new Response(); $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $account ->expects($this->once()) ->method('getUsername') ->will($this->returnValue('foo')) ; $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->any()) ->method('getUser') ->will($this->returnValue($account)) ; $tokenProvider = $this->getMock('Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface'); $tokenProvider ->expects($this->once()) ->method('createNewToken') ; $service->setTokenProvider($tokenProvider); $cookies = $response->headers->getCookies(); $this->assertCount(0, $cookies); $service->loginSuccess($request, $response, $token); $cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $cookie = $cookies['myfoodomain.foo']['/foo/path']['foo']; $this->assertFalse($cookie->isCleared()); $this->assertTrue($cookie->isSecure()); $this->assertTrue($cookie->isHttpOnly()); $this->assertTrue($cookie->getExpiresTime() > time() + 3590 && $cookie->getExpiresTime() < time() + 3610); $this->assertEquals('myfoodomain.foo', $cookie->getDomain()); $this->assertEquals('/foo/path', $cookie->getPath()); } protected function encodeCookie(array $parts) { $service = $this->getService(); $r = new \ReflectionMethod($service, 'encodeCookie'); $r->setAccessible(true); return $r->invoke($service, $parts); } protected function getService($userProvider = null, $options = array(), $logger = null) { if (null === $userProvider) { $userProvider = $this->getProvider(); } return new PersistentTokenBasedRememberMeServices(array($userProvider), 'fookey', 'fookey', $options, $logger, new SecureRandom(sys_get_temp_dir().'/_sf2.seed')); } protected function getProvider() { $provider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); $provider ->expects($this->any()) ->method('supportsClass') ->will($this->returnValue(true)) ; return $provider; } } PK!䗥1#1#atest/Security/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\RememberMe; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase { public function testGetRememberMeParameter() { $service = $this->getService(null, array('remember_me_parameter' => 'foo')); $this->assertEquals('foo', $service->getRememberMeParameter()); } public function testGetKey() { $service = $this->getService(); $this->assertEquals('fookey', $service->getKey()); } public function testAutoLoginReturnsNullWhenNoCookie() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); $this->assertNull($service->autoLogin(new Request())); } /** * @expectedException \RuntimeException */ public function testAutoLoginThrowsExceptionWhenImplementationDoesNotReturnUserInterface() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $request->cookies->set('foo', 'foo'); $service ->expects($this->once()) ->method('processAutoLoginCookie') ->will($this->returnValue(null)) ; $service->autoLogin($request); } public function testAutoLogin() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $request->cookies->set('foo', 'foo'); $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user ->expects($this->once()) ->method('getRoles') ->will($this->returnValue(array())) ; $service ->expects($this->once()) ->method('processAutoLoginCookie') ->will($this->returnValue($user)) ; $returnedToken = $service->autoLogin($request); $this->assertSame($user, $returnedToken->getUser()); $this->assertSame('fookey', $returnedToken->getKey()); $this->assertSame('fookey', $returnedToken->getProviderKey()); } public function testLogout() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $response = new Response(); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $service->logout($request, $response, $token); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testLoginFail() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $service->loginFail($request); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testLoginSuccessIsNotProcessedWhenTokenDoesNotContainUserInterfaceImplementation() { $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true, 'path' => null, 'domain' => null)); $request = new Request(); $response = new Response(); $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->once()) ->method('getUser') ->will($this->returnValue('foo')) ; $service ->expects($this->never()) ->method('onLoginSuccess') ; $this->assertFalse($request->request->has('foo')); $service->loginSuccess($request, $response, $token); } public function testLoginSuccessIsNotProcessedWhenRememberMeIsNotRequested() { $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $response = new Response(); $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->once()) ->method('getUser') ->will($this->returnValue($account)) ; $service ->expects($this->never()) ->method('onLoginSuccess') ->will($this->returnValue(null)) ; $this->assertFalse($request->request->has('foo')); $service->loginSuccess($request, $response, $token); } public function testLoginSuccessWhenRememberMeAlwaysIsTrue() { $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true, 'path' => null, 'domain' => null)); $request = new Request(); $response = new Response(); $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->once()) ->method('getUser') ->will($this->returnValue($account)) ; $service ->expects($this->once()) ->method('onLoginSuccess') ->will($this->returnValue(null)) ; $service->loginSuccess($request, $response, $token); } /** * @dataProvider getPositiveRememberMeParameterValues */ public function testLoginSuccessWhenRememberMeParameterWithPathIsPositive($value) { $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo[bar]', 'path' => null, 'domain' => null)); $request = new Request(); $request->request->set('foo', array('bar' => $value)); $response = new Response(); $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->once()) ->method('getUser') ->will($this->returnValue($account)) ; $service ->expects($this->once()) ->method('onLoginSuccess') ->will($this->returnValue(true)) ; $service->loginSuccess($request, $response, $token); } /** * @dataProvider getPositiveRememberMeParameterValues */ public function testLoginSuccessWhenRememberMeParameterIsPositive($value) { $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => false, 'remember_me_parameter' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $request->request->set('foo', $value); $response = new Response(); $account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->once()) ->method('getUser') ->will($this->returnValue($account)) ; $service ->expects($this->once()) ->method('onLoginSuccess') ->will($this->returnValue(true)) ; $service->loginSuccess($request, $response, $token); } public function getPositiveRememberMeParameterValues() { return array( array('true'), array('1'), array('on'), array('yes'), ); } protected function getService($userProvider = null, $options = array(), $logger = null) { if (null === $userProvider) { $userProvider = $this->getProvider(); } return $this->getMockForAbstractClass('Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices', array( array($userProvider), 'fookey', 'fookey', $options, $logger )); } protected function getProvider() { $provider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); $provider ->expects($this->any()) ->method('supportsClass') ->will($this->returnValue(true)) ; return $provider; } } PK!gZ)Z)ctest/Security/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\RememberMe; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices; class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase { public function testAutoLoginReturnsNullWhenNoCookie() { $service = $this->getService(null, array('name' => 'foo')); $this->assertNull($service->autoLogin(new Request())); } public function testAutoLoginThrowsExceptionOnInvalidCookie() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => false, 'remember_me_parameter' => 'foo')); $request = new Request(); $request->request->set('foo', 'true'); $request->cookies->set('foo', 'foo'); $this->assertNull($service->autoLogin($request)); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testAutoLoginThrowsExceptionOnNonExistentUser() { $userProvider = $this->getProvider(); $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600)); $request = new Request(); $request->cookies->set('foo', $this->getCookie('fooclass', 'foouser', time()+3600, 'foopass')); $userProvider ->expects($this->once()) ->method('loadUserByUsername') ->will($this->throwException(new UsernameNotFoundException('user not found'))) ; $this->assertNull($service->autoLogin($request)); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testAutoLoginDoesNotAcceptCookieWithInvalidHash() { $userProvider = $this->getProvider(); $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600)); $request = new Request(); $request->cookies->set('foo', base64_encode('class:'.base64_encode('foouser').':123456789:fooHash')); $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user ->expects($this->once()) ->method('getPassword') ->will($this->returnValue('foopass')) ; $userProvider ->expects($this->once()) ->method('loadUserByUsername') ->with($this->equalTo('foouser')) ->will($this->returnValue($user)) ; $this->assertNull($service->autoLogin($request)); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testAutoLoginDoesNotAcceptAnExpiredCookie() { $userProvider = $this->getProvider(); $service = $this->getService($userProvider, array('name' => 'foo', 'path' => null, 'domain' => null, 'always_remember_me' => true, 'lifetime' => 3600)); $request = new Request(); $request->cookies->set('foo', $this->getCookie('fooclass', 'foouser', time() - 1, 'foopass')); $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user ->expects($this->once()) ->method('getPassword') ->will($this->returnValue('foopass')) ; $userProvider ->expects($this->once()) ->method('loadUserByUsername') ->with($this->equalTo('foouser')) ->will($this->returnValue($user)) ; $this->assertNull($service->autoLogin($request)); $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } public function testAutoLogin() { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user ->expects($this->once()) ->method('getRoles') ->will($this->returnValue(array('ROLE_FOO'))) ; $user ->expects($this->once()) ->method('getPassword') ->will($this->returnValue('foopass')) ; $userProvider = $this->getProvider(); $userProvider ->expects($this->once()) ->method('loadUserByUsername') ->with($this->equalTo('foouser')) ->will($this->returnValue($user)) ; $service = $this->getService($userProvider, array('name' => 'foo', 'always_remember_me' => true, 'lifetime' => 3600)); $request = new Request(); $request->cookies->set('foo', $this->getCookie('fooclass', 'foouser', time()+3600, 'foopass')); $returnedToken = $service->autoLogin($request); $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', $returnedToken); $this->assertSame($user, $returnedToken->getUser()); $this->assertEquals('fookey', $returnedToken->getKey()); } public function testLogout() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); $request = new Request(); $response = new Response(); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $service->logout($request, $response, $token); $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME); $this->assertTrue($cookie->isCleared()); $this->assertEquals('/', $cookie->getPath()); $this->assertNull($cookie->getDomain()); } public function testLoginFail() { $service = $this->getService(null, array('name' => 'foo', 'path' => '/foo', 'domain' => 'foodomain.foo')); $request = new Request(); $response = new Response(); $service->loginFail($request, $response); $cookie = $request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME); $this->assertTrue($cookie->isCleared()); $this->assertEquals('/foo', $cookie->getPath()); $this->assertEquals('foodomain.foo', $cookie->getDomain()); } public function testLoginSuccessIgnoresTokensWhichDoNotContainAnUserInterfaceImplementation() { $service = $this->getService(null, array('name' => 'foo', 'always_remember_me' => true, 'path' => null, 'domain' => null)); $request = new Request(); $response = new Response(); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token ->expects($this->once()) ->method('getUser') ->will($this->returnValue('foo')) ; $cookies = $response->headers->getCookies(); $this->assertCount(0, $cookies); $service->loginSuccess($request, $response, $token); $cookies = $response->headers->getCookies(); $this->assertCount(0, $cookies); } public function testLoginSuccess() { $service = $this->getService(null, array('name' => 'foo', 'domain' => 'myfoodomain.foo', 'path' => '/foo/path', 'secure' => true, 'httponly' => true, 'lifetime' => 3600, 'always_remember_me' => true)); $request = new Request(); $response = new Response(); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user ->expects($this->once()) ->method('getPassword') ->will($this->returnValue('foopass')) ; $user ->expects($this->once()) ->method('getUsername') ->will($this->returnValue('foouser')) ; $token ->expects($this->atLeastOnce()) ->method('getUser') ->will($this->returnValue($user)) ; $cookies = $response->headers->getCookies(); $this->assertCount(0, $cookies); $service->loginSuccess($request, $response, $token); $cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $cookie = $cookies['myfoodomain.foo']['/foo/path']['foo']; $this->assertFalse($cookie->isCleared()); $this->assertTrue($cookie->isSecure()); $this->assertTrue($cookie->isHttpOnly()); $this->assertTrue($cookie->getExpiresTime() > time() + 3590 && $cookie->getExpiresTime() < time() + 3610); $this->assertEquals('myfoodomain.foo', $cookie->getDomain()); $this->assertEquals('/foo/path', $cookie->getPath()); } protected function getCookie($class, $username, $expires, $password) { $service = $this->getService(); $r = new \ReflectionMethod($service, 'generateCookieValue'); $r->setAccessible(true); return $r->invoke($service, $class, $username, $expires, $password); } protected function encodeCookie(array $parts) { $service = $this->getService(); $r = new \ReflectionMethod($service, 'encodeCookie'); $r->setAccessible(true); return $r->invoke($service, $parts); } protected function getService($userProvider = null, $options = array(), $logger = null) { if (null === $userProvider) { $userProvider = $this->getProvider(); } $service = new TokenBasedRememberMeServices(array($userProvider), 'fookey', 'fookey', $options, $logger); return $service; } protected function getProvider() { $provider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); $provider ->expects($this->any()) ->method('supportsClass') ->will($this->returnValue(true)) ; return $provider; } } PK!ʅ Wtest/Security/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\RememberMe; use Symfony\Component\Security\Http\RememberMe\ResponseListener; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpKernel\KernelEvents; class ResponseListenerTest extends \PHPUnit_Framework_TestCase { public function testRememberMeCookieIsSentWithResponse() { $cookie = new Cookie('rememberme'); $request = $this->getRequest(array( RememberMeServicesInterface::COOKIE_ATTR_NAME => $cookie )); $response = $this->getResponse(); $response->headers->expects($this->once())->method('setCookie')->with($cookie); $listener = new ResponseListener(); $listener->onKernelResponse($this->getEvent($request, $response)); } public function testRememberMeCookieIsNotSendWithResponse() { $request = $this->getRequest(); $response = $this->getResponse(); $response->headers->expects($this->never())->method('setCookie'); $listener = new ResponseListener(); $listener->onKernelResponse($this->getEvent($request, $response)); } public function testItSubscribesToTheOnKernelResponseEvent() { $listener = new ResponseListener(); $this->assertSame(array(KernelEvents::RESPONSE => 'onKernelResponse'), ResponseListener::getSubscribedEvents()); } private function getRequest(array $attributes = array()) { $request = new Request(); foreach ($attributes as $name => $value) { $request->attributes->set($name, $value); } return $request; } private function getResponse() { $response = $this->getMock('Symfony\Component\HttpFoundation\Response'); $response->headers = $this->getMock('Symfony\Component\HttpFoundation\ResponseHeaderBag'); return $response; } private function getEvent($request, $response) { $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\FilterResponseEvent') ->disableOriginalConstructor() ->getMock(); $event->expects($this->any())->method('getRequest')->will($this->returnValue($request)); $event->expects($this->any())->method('getResponse')->will($this->returnValue($response)); return $event; } } PK!Y Ң atest/Security/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Session; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy; class SessionAuthenticationStrategyTest extends \PHPUnit_Framework_TestCase { public function testSessionIsNotChanged() { $request = $this->getRequest(); $request->expects($this->never())->method('getSession'); $strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::NONE); $strategy->onAuthentication($request, $this->getToken()); } /** * @expectedException \RuntimeException * @expectedExceptionMessage Invalid session authentication strategy "foo" */ public function testUnsupportedStrategy() { $request = $this->getRequest(); $request->expects($this->never())->method('getSession'); $strategy = new SessionAuthenticationStrategy('foo'); $strategy->onAuthentication($request, $this->getToken()); } public function testSessionIsMigrated() { $session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface'); $session->expects($this->once())->method('migrate'); $strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE); $strategy->onAuthentication($this->getRequest($session), $this->getToken()); } public function testSessionIsInvalidated() { $session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface'); $session->expects($this->once())->method('invalidate'); $strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::INVALIDATE); $strategy->onAuthentication($this->getRequest($session), $this->getToken()); } private function getRequest($session = null) { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); if (null !== $session) { $request->expects($this->any())->method('getSession')->will($this->returnValue($session)); } return $request; } private function getToken() { return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); } } PK! {{^test/Security/Symfony/Component/Security/Http/Tests/Logout/DefaultLogoutSuccessHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Logout; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Http\Logout\DefaultLogoutSuccessHandler; class DefaultLogoutSuccessHandlerTest extends \PHPUnit_Framework_TestCase { public function testLogout() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $response = $this->getMock('Symfony\Component\HttpFoundation\Response'); $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils'); $httpUtils->expects($this->once()) ->method('createRedirectResponse') ->with($request, '/dashboard') ->will($this->returnValue($response)); $handler = new DefaultLogoutSuccessHandler($httpUtils, '/dashboard'); $result = $handler->onLogoutSuccess($request); $this->assertSame($response, $result); } } PK!]ͷWtest/Security/Symfony/Component/Security/Http/Tests/Logout/SessionLogoutHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Logout; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Http\Logout\SessionLogoutHandler; class SessionLogoutHandlerTest extends \PHPUnit_Framework_TestCase { public function testLogout() { $handler = new SessionLogoutHandler(); $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $response = new Response(); $session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session', array(), array(), '', false); $request ->expects($this->once()) ->method('getSession') ->will($this->returnValue($session)) ; $session ->expects($this->once()) ->method('invalidate') ; $handler->logout($request, $response, $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); } } PK!k  ^test/Security/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Logout; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\Logout\CookieClearingLogoutHandler; class CookieClearingLogoutHandlerTest extends \PHPUnit_Framework_TestCase { public function testLogout() { $request = new Request(); $response = new Response(); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $handler = new CookieClearingLogoutHandler(array('foo' => array('path' => '/foo', 'domain' => 'foo.foo'), 'foo2' => array('path' => null, 'domain' => null))); $cookies = $response->headers->getCookies(); $this->assertCount(0, $cookies); $handler->logout($request, $response, $token); $cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertCount(2, $cookies); $cookie = $cookies['foo.foo']['/foo']['foo']; $this->assertEquals('foo', $cookie->getName()); $this->assertEquals('/foo', $cookie->getPath()); $this->assertEquals('foo.foo', $cookie->getDomain()); $this->assertTrue($cookie->isCleared()); $cookie = $cookies['']['/']['foo2']; $this->assertStringStartsWith('foo2', $cookie->getName()); $this->assertEquals('/', $cookie->getPath()); $this->assertNull($cookie->getDomain()); $this->assertTrue($cookie->isCleared()); } } PK!$antest/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Authentication; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; class DefaultAuthenticationFailureHandlerTest extends \PHPUnit_Framework_TestCase { private $httpKernel = null; private $httpUtils = null; private $logger = null; private $request = null; private $session = null; private $exception = null; protected function setUp() { $this->httpKernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $this->httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils'); $this->logger = $this->getMock('Psr\Log\LoggerInterface'); $this->session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface'); $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $this->request->expects($this->any())->method('getSession')->will($this->returnValue($this->session)); $this->exception = $this->getMock('Symfony\Component\Security\Core\Exception\AuthenticationException'); } public function testForward() { $options = array('failure_forward' => true); $subRequest = $this->getRequest(); $subRequest->attributes->expects($this->once()) ->method('set')->with(SecurityContextInterface::AUTHENTICATION_ERROR, $this->exception); $this->httpUtils->expects($this->once()) ->method('createRequest')->with($this->request, '/login') ->will($this->returnValue($subRequest)); $response = $this->getMock('Symfony\Component\HttpFoundation\Response'); $this->httpKernel->expects($this->once()) ->method('handle')->with($subRequest, HttpKernelInterface::SUB_REQUEST) ->will($this->returnValue($response)); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger); $result = $handler->onAuthenticationFailure($this->request, $this->exception); $this->assertSame($response, $result); } public function testRedirect() { $response = $this->getMock('Symfony\Component\HttpFoundation\Response'); $this->httpUtils->expects($this->once()) ->method('createRedirectResponse')->with($this->request, '/login') ->will($this->returnValue($response)); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, array(), $this->logger); $result = $handler->onAuthenticationFailure($this->request, $this->exception); $this->assertSame($response, $result); } public function testExceptionIsPersistedInSession() { $this->session->expects($this->once()) ->method('set')->with(SecurityContextInterface::AUTHENTICATION_ERROR, $this->exception); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, array(), $this->logger); $handler->onAuthenticationFailure($this->request, $this->exception); } public function testExceptionIsPassedInRequestOnForward() { $options = array('failure_forward' => true); $subRequest = $this->getRequest(); $subRequest->attributes->expects($this->once()) ->method('set')->with(SecurityContextInterface::AUTHENTICATION_ERROR, $this->exception); $this->httpUtils->expects($this->once()) ->method('createRequest')->with($this->request, '/login') ->will($this->returnValue($subRequest)); $this->session->expects($this->never())->method('set'); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger); $handler->onAuthenticationFailure($this->request, $this->exception); } public function testRedirectIsLogged() { $this->logger->expects($this->once())->method('debug')->with('Redirecting to /login'); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, array(), $this->logger); $handler->onAuthenticationFailure($this->request, $this->exception); } public function testForwardIsLogged() { $options = array('failure_forward' => true); $this->httpUtils->expects($this->once()) ->method('createRequest')->with($this->request, '/login') ->will($this->returnValue($this->getRequest())); $this->logger->expects($this->once())->method('debug')->with('Forwarding to /login'); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger); $handler->onAuthenticationFailure($this->request, $this->exception); } public function testFailurePathCanBeOverwritten() { $options = array('failure_path' => '/auth/login'); $this->httpUtils->expects($this->once()) ->method('createRedirectResponse')->with($this->request, '/auth/login'); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger); $handler->onAuthenticationFailure($this->request, $this->exception); } public function testFailurePathCanBeOverwrittenWithRequest() { $this->request->expects($this->once()) ->method('get')->with('_failure_path', null, true) ->will($this->returnValue('/auth/login')); $this->httpUtils->expects($this->once()) ->method('createRedirectResponse')->with($this->request, '/auth/login'); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, array(), $this->logger); $handler->onAuthenticationFailure($this->request, $this->exception); } public function testFailurePathParameterCanBeOverwritten() { $options = array('failure_path_parameter' => '_my_failure_path'); $this->request->expects($this->once()) ->method('get')->with('_my_failure_path', null, true) ->will($this->returnValue('/auth/login')); $this->httpUtils->expects($this->once()) ->method('createRedirectResponse')->with($this->request, '/auth/login'); $handler = new DefaultAuthenticationFailureHandler($this->httpKernel, $this->httpUtils, $options, $this->logger); $handler->onAuthenticationFailure($this->request, $this->exception); } private function getRequest() { $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $request->attributes = $this->getMock('Symfony\Component\HttpFoundation\ParameterBag'); return $request; } } PK!/w!w!ftest/Security/Symfony/Component/Security/Http/Tests/Authentication/SimpleAuthenticationHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\Authentication\SimpleAuthenticationHandler; class SimpleAuthenticationHandlerTest extends \PHPUnit_Framework_TestCase { private $successHandler; private $failureHandler; private $request; private $token; private $authenticationException; private $response; public function setUp() { $this->successHandler = $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface'); $this->failureHandler = $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface'); $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $this->token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $this->authenticationException = $this->getMock('Symfony\Component\Security\Core\Exception\AuthenticationException'); $this->response = $this->getMock('Symfony\Component\HttpFoundation\Response'); } public function testOnAuthenticationSuccessFallsBackToDefaultHandlerIfSimpleIsNotASuccessHandler() { $authenticator = $this->getMock('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface'); $this->successHandler->expects($this->once()) ->method('onAuthenticationSuccess') ->with($this->request, $this->token) ->will($this->returnValue($this->response)); $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($this->response, $result); } public function testOnAuthenticationSuccessCallsSimpleAuthenticator() { $this->successHandler->expects($this->never()) ->method('onAuthenticationSuccess'); $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestSuccessHandlerInterface'); $authenticator->expects($this->once()) ->method('onAuthenticationSuccess') ->with($this->request, $this->token) ->will($this->returnValue($this->response)); $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($this->response, $result); } /** * @expectedException \UnexpectedValueException * @expectedExceptionMessage onAuthenticationSuccess method must return null to use the default success handler, or a Response object */ public function testOnAuthenticationSuccessThrowsAnExceptionIfNonResponseIsReturned() { $this->successHandler->expects($this->never()) ->method('onAuthenticationSuccess'); $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestSuccessHandlerInterface'); $authenticator->expects($this->once()) ->method('onAuthenticationSuccess') ->with($this->request, $this->token) ->will($this->returnValue(new \stdClass())); $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler); $handler->onAuthenticationSuccess($this->request, $this->token); } public function testOnAuthenticationSuccessFallsBackToDefaultHandlerIfNullIsReturned() { $this->successHandler->expects($this->once()) ->method('onAuthenticationSuccess') ->with($this->request, $this->token) ->will($this->returnValue($this->response)); $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestSuccessHandlerInterface'); $authenticator->expects($this->once()) ->method('onAuthenticationSuccess') ->with($this->request, $this->token) ->will($this->returnValue(null)); $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($this->response, $result); } public function testOnAuthenticationFailureFallsBackToDefaultHandlerIfSimpleIsNotAFailureHandler() { $authenticator = $this->getMock('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface'); $this->failureHandler->expects($this->once()) ->method('onAuthenticationFailure') ->with($this->request, $this->authenticationException) ->will($this->returnValue($this->response)); $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler); $result = $handler->onAuthenticationFailure($this->request, $this->authenticationException); $this->assertSame($this->response, $result); } public function testOnAuthenticationFailureCallsSimpleAuthenticator() { $this->failureHandler->expects($this->never()) ->method('onAuthenticationFailure'); $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestFailureHandlerInterface'); $authenticator->expects($this->once()) ->method('onAuthenticationFailure') ->with($this->request, $this->authenticationException) ->will($this->returnValue($this->response)); $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler); $result = $handler->onAuthenticationFailure($this->request, $this->authenticationException); $this->assertSame($this->response, $result); } /** * @expectedException \UnexpectedValueException * @expectedExceptionMessage onAuthenticationFailure method must return null to use the default failure handler, or a Response object */ public function testOnAuthenticationFailureThrowsAnExceptionIfNonResponseIsReturned() { $this->failureHandler->expects($this->never()) ->method('onAuthenticationFailure'); $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestFailureHandlerInterface'); $authenticator->expects($this->once()) ->method('onAuthenticationFailure') ->with($this->request, $this->authenticationException) ->will($this->returnValue(new \stdClass())); $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler); $handler->onAuthenticationFailure($this->request, $this->authenticationException); } public function testOnAuthenticationFailureFallsBackToDefaultHandlerIfNullIsReturned() { $this->failureHandler->expects($this->once()) ->method('onAuthenticationFailure') ->with($this->request, $this->authenticationException) ->will($this->returnValue($this->response)); $authenticator = $this->getMockForAbstractClass('Symfony\Component\Security\Http\Tests\TestFailureHandlerInterface'); $authenticator->expects($this->once()) ->method('onAuthenticationFailure') ->with($this->request, $this->authenticationException) ->will($this->returnValue(null)); $handler = new SimpleAuthenticationHandler($authenticator, $this->successHandler, $this->failureHandler); $result = $handler->onAuthenticationFailure($this->request, $this->authenticationException); $this->assertSame($this->response, $result); } } interface TestSuccessHandlerInterface extends AuthenticationSuccessHandlerInterface, SimpleAuthenticatorInterface { } interface TestFailureHandlerInterface extends AuthenticationFailureHandlerInterface, SimpleAuthenticatorInterface { } PK!id]zntest/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Tests\Authentication; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler; class DefaultAuthenticationSuccessHandlerTest extends \PHPUnit_Framework_TestCase { private $httpUtils = null; private $request = null; private $token = null; protected function setUp() { $this->httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils'); $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request'); $this->request->headers = $this->getMock('Symfony\Component\HttpFoundation\HeaderBag'); $this->token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); } public function testRequestIsRedirected() { $response = $this->expectRedirectResponse('/'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($response, $result); } public function testDefaultTargetPathCanBeForced() { $options = array( 'always_use_default_target_path' => true, 'default_target_path' => '/dashboard' ); $response = $this->expectRedirectResponse('/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($response, $result); } public function testTargetPathIsPassedWithRequest() { $this->request->expects($this->once()) ->method('get')->with('_target_path') ->will($this->returnValue('/dashboard')); $response = $this->expectRedirectResponse('/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($response, $result); } public function testTargetPathParameterIsCustomised() { $options = array('target_path_parameter' => '_my_target_path'); $this->request->expects($this->once()) ->method('get')->with('_my_target_path') ->will($this->returnValue('/dashboard')); $response = $this->expectRedirectResponse('/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($response, $result); } public function testTargetPathIsTakenFromTheSession() { $session = $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface'); $session->expects($this->once()) ->method('get')->with('_security.admin.target_path') ->will($this->returnValue('/admin/dashboard')); $session->expects($this->once()) ->method('remove')->with('_security.admin.target_path'); $this->request->expects($this->any()) ->method('getSession') ->will($this->returnValue($session)); $response = $this->expectRedirectResponse('/admin/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); $handler->setProviderKey('admin'); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($response, $result); } public function testTargetPathIsPassedAsReferer() { $options = array('use_referer' => true); $this->request->headers->expects($this->once()) ->method('get')->with('Referer') ->will($this->returnValue('/dashboard')); $response = $this->expectRedirectResponse('/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($response, $result); } public function testRefererHasToBeDifferentThatLoginUrl() { $options = array('use_referer' => true); $this->request->headers->expects($this->any()) ->method('get')->with('Referer') ->will($this->returnValue('/login')); $this->httpUtils->expects($this->once()) ->method('generateUri')->with($this->request, '/login') ->will($this->returnValue('/login')); $response = $this->expectRedirectResponse('/'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($response, $result); } public function testRefererTargetPathIsIgnoredByDefault() { $this->request->headers->expects($this->never())->method('get'); $response = $this->expectRedirectResponse('/'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); $result = $handler->onAuthenticationSuccess($this->request, $this->token); $this->assertSame($response, $result); } private function expectRedirectResponse($path) { $response = $this->getMock('Symfony\Component\HttpFoundation\Response'); $this->httpUtils->expects($this->once()) ->method('createRedirectResponse') ->with($this->request, $path) ->will($this->returnValue($response)); return $response; } } PK!?k,.<<>test/Security/Symfony/Component/Security/Http/phpunit.xml.distnu[ ./Tests/ ./ ./vendor ./Tests PK!|G   btest/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\Tests\TokenStorage; use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage; /** * @author Bernhard Schussek * * @runTestsInSeparateProcesses */ class NativeSessionTokenStorageTest extends \PHPUnit_Framework_TestCase { const SESSION_NAMESPACE = 'foobar'; /** * @var NativeSessionTokenStorage */ private $storage; public static function setUpBeforeClass() { ini_set('session.save_handler', 'files'); ini_set('session.save_path', sys_get_temp_dir()); parent::setUpBeforeClass(); } protected function setUp() { $_SESSION = array(); $this->storage = new NativeSessionTokenStorage(self::SESSION_NAMESPACE); } public function testStoreTokenInClosedSession() { $this->storage->setToken('token_id', 'TOKEN'); $this->assertSame(array(self::SESSION_NAMESPACE => array('token_id' => 'TOKEN')), $_SESSION); } public function testStoreTokenInClosedSessionWithExistingSessionId() { if (version_compare(PHP_VERSION, '5.4', '<')) { $this->markTestSkipped('This test requires PHP 5.4 or later.'); } session_id('foobar'); $this->assertSame(PHP_SESSION_NONE, session_status()); $this->storage->setToken('token_id', 'TOKEN'); $this->assertSame(PHP_SESSION_ACTIVE, session_status()); $this->assertSame(array(self::SESSION_NAMESPACE => array('token_id' => 'TOKEN')), $_SESSION); } public function testStoreTokenInActiveSession() { session_start(); $this->storage->setToken('token_id', 'TOKEN'); $this->assertSame(array(self::SESSION_NAMESPACE => array('token_id' => 'TOKEN')), $_SESSION); } /** * @depends testStoreTokenInClosedSession */ public function testCheckToken() { $this->assertFalse($this->storage->hasToken('token_id')); $this->storage->setToken('token_id', 'TOKEN'); $this->assertTrue($this->storage->hasToken('token_id')); } /** * @depends testStoreTokenInClosedSession */ public function testGetExistingToken() { $this->storage->setToken('token_id', 'TOKEN'); $this->assertSame('TOKEN', $this->storage->getToken('token_id')); } /** * @expectedException \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException */ public function testGetNonExistingToken() { $this->storage->getToken('token_id'); } /** * @depends testCheckToken */ public function testRemoveNonExistingToken() { $this->assertNull($this->storage->removeToken('token_id')); $this->assertFalse($this->storage->hasToken('token_id')); } /** * @depends testCheckToken */ public function testRemoveExistingToken() { $this->storage->setToken('token_id', 'TOKEN'); $this->assertSame('TOKEN', $this->storage->removeToken('token_id')); $this->assertFalse($this->storage->hasToken('token_id')); } } PK!WW\test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\Tests\TokenStorage; use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage; /** * @author Bernhard Schussek */ class SessionTokenStorageTest extends \PHPUnit_Framework_TestCase { const SESSION_NAMESPACE = 'foobar'; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $session; /** * @var SessionTokenStorage */ private $storage; protected function setUp() { if (!interface_exists('Symfony\Component\HttpFoundation\Session\SessionInterface')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); } $this->session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface') ->disableOriginalConstructor() ->getMock(); $this->storage = new SessionTokenStorage($this->session, self::SESSION_NAMESPACE); } public function testStoreTokenInClosedSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(false)); $this->session->expects($this->once()) ->method('start'); $this->session->expects($this->once()) ->method('set') ->with(self::SESSION_NAMESPACE.'/token_id', 'TOKEN'); $this->storage->setToken('token_id', 'TOKEN'); } public function testStoreTokenInActiveSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(true)); $this->session->expects($this->never()) ->method('start'); $this->session->expects($this->once()) ->method('set') ->with(self::SESSION_NAMESPACE.'/token_id', 'TOKEN'); $this->storage->setToken('token_id', 'TOKEN'); } public function testCheckTokenInClosedSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(false)); $this->session->expects($this->once()) ->method('start'); $this->session->expects($this->once()) ->method('has') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue('RESULT')); $this->assertSame('RESULT', $this->storage->hasToken('token_id')); } public function testCheckTokenInActiveSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(true)); $this->session->expects($this->never()) ->method('start'); $this->session->expects($this->once()) ->method('has') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue('RESULT')); $this->assertSame('RESULT', $this->storage->hasToken('token_id')); } public function testGetExistingTokenFromClosedSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(false)); $this->session->expects($this->once()) ->method('start'); $this->session->expects($this->once()) ->method('has') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue(true)); $this->session->expects($this->once()) ->method('get') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue('RESULT')); $this->assertSame('RESULT', $this->storage->getToken('token_id')); } public function testGetExistingTokenFromActiveSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(true)); $this->session->expects($this->never()) ->method('start'); $this->session->expects($this->once()) ->method('has') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue(true)); $this->session->expects($this->once()) ->method('get') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue('RESULT')); $this->assertSame('RESULT', $this->storage->getToken('token_id')); } /** * @expectedException \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException */ public function testGetNonExistingTokenFromClosedSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(false)); $this->session->expects($this->once()) ->method('start'); $this->session->expects($this->once()) ->method('has') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue(false)); $this->storage->getToken('token_id'); } /** * @expectedException \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException */ public function testGetNonExistingTokenFromActiveSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(true)); $this->session->expects($this->never()) ->method('start'); $this->session->expects($this->once()) ->method('has') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue(false)); $this->storage->getToken('token_id'); } public function testRemoveNonExistingTokenFromClosedSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(false)); $this->session->expects($this->once()) ->method('start'); $this->session->expects($this->once()) ->method('remove') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue(null)); $this->assertNull($this->storage->removeToken('token_id')); } public function testRemoveNonExistingTokenFromActiveSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(true)); $this->session->expects($this->never()) ->method('start'); $this->session->expects($this->once()) ->method('remove') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue(null)); $this->assertNull($this->storage->removeToken('token_id')); } public function testRemoveExistingTokenFromClosedSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(false)); $this->session->expects($this->once()) ->method('start'); $this->session->expects($this->once()) ->method('remove') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue('TOKEN')); $this->assertSame('TOKEN', $this->storage->removeToken('token_id')); } public function testRemoveExistingTokenFromActiveSession() { $this->session->expects($this->any()) ->method('isStarted') ->will($this->returnValue(true)); $this->session->expects($this->never()) ->method('start'); $this->session->expects($this->once()) ->method('remove') ->with(self::SESSION_NAMESPACE.'/token_id') ->will($this->returnValue('TOKEN')); $this->assertSame('TOKEN', $this->storage->removeToken('token_id')); } } PK!-kkLtest/Security/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\Tests; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManager; /** * @author Bernhard Schussek */ class CsrfTokenManagerTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $generator; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $storage; /** * @var CsrfTokenManager */ private $manager; protected function setUp() { $this->generator = $this->getMock('Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface'); $this->storage = $this->getMock('Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface'); $this->manager = new CsrfTokenManager($this->generator, $this->storage); } protected function tearDown() { $this->generator = null; $this->storage = null; $this->manager = null; } public function testGetNonExistingToken() { $this->storage->expects($this->once()) ->method('hasToken') ->with('token_id') ->will($this->returnValue(false)); $this->generator->expects($this->once()) ->method('generateToken') ->will($this->returnValue('TOKEN')); $this->storage->expects($this->once()) ->method('setToken') ->with('token_id', 'TOKEN'); $token = $this->manager->getToken('token_id'); $this->assertInstanceOf('Symfony\Component\Security\Csrf\CsrfToken', $token); $this->assertSame('token_id', $token->getId()); $this->assertSame('TOKEN', $token->getValue()); } public function testUseExistingTokenIfAvailable() { $this->storage->expects($this->once()) ->method('hasToken') ->with('token_id') ->will($this->returnValue(true)); $this->storage->expects($this->once()) ->method('getToken') ->with('token_id') ->will($this->returnValue('TOKEN')); $token = $this->manager->getToken('token_id'); $this->assertInstanceOf('Symfony\Component\Security\Csrf\CsrfToken', $token); $this->assertSame('token_id', $token->getId()); $this->assertSame('TOKEN', $token->getValue()); } public function testRefreshTokenAlwaysReturnsNewToken() { $this->storage->expects($this->never()) ->method('hasToken'); $this->generator->expects($this->once()) ->method('generateToken') ->will($this->returnValue('TOKEN')); $this->storage->expects($this->once()) ->method('setToken') ->with('token_id', 'TOKEN'); $token = $this->manager->refreshToken('token_id'); $this->assertInstanceOf('Symfony\Component\Security\Csrf\CsrfToken', $token); $this->assertSame('token_id', $token->getId()); $this->assertSame('TOKEN', $token->getValue()); } public function testMatchingTokenIsValid() { $this->storage->expects($this->once()) ->method('hasToken') ->with('token_id') ->will($this->returnValue(true)); $this->storage->expects($this->once()) ->method('getToken') ->with('token_id') ->will($this->returnValue('TOKEN')); $this->assertTrue($this->manager->isTokenValid(new CsrfToken('token_id', 'TOKEN'))); } public function testNonMatchingTokenIsNotValid() { $this->storage->expects($this->once()) ->method('hasToken') ->with('token_id') ->will($this->returnValue(true)); $this->storage->expects($this->once()) ->method('getToken') ->with('token_id') ->will($this->returnValue('TOKEN')); $this->assertFalse($this->manager->isTokenValid(new CsrfToken('token_id', 'FOOBAR'))); } public function testNonExistingTokenIsNotValid() { $this->storage->expects($this->once()) ->method('hasToken') ->with('token_id') ->will($this->returnValue(false)); $this->storage->expects($this->never()) ->method('getToken'); $this->assertFalse($this->manager->isTokenValid(new CsrfToken('token_id', 'FOOBAR'))); } public function testRemoveToken() { $this->storage->expects($this->once()) ->method('removeToken') ->with('token_id') ->will($this->returnValue('REMOVED_TOKEN')); $this->assertSame('REMOVED_TOKEN', $this->manager->removeToken('token_id')); } } PK!3z((`test/Security/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Csrf\Tests\TokenGenerator; use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator; /** * @author Bernhard Schussek */ class UriSafeTokenGeneratorTest extends \PHPUnit_Framework_TestCase { const ENTROPY = 1000; /** * A non alpha-numeric byte string * @var string */ private static $bytes; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $random; /** * @var UriSafeTokenGenerator */ private $generator; public static function setUpBeforeClass() { self::$bytes = base64_decode('aMf+Tct/RLn2WQ=='); } protected function setUp() { $this->random = $this->getMock('Symfony\Component\Security\Core\Util\SecureRandomInterface'); $this->generator = new UriSafeTokenGenerator($this->random, self::ENTROPY); } protected function tearDown() { $this->random = null; $this->generator = null; } public function testGenerateToken() { $this->random->expects($this->once()) ->method('nextBytes') ->with(self::ENTROPY/8) ->will($this->returnValue(self::$bytes)); $token = $this->generator->generateToken(); $this->assertTrue(ctype_print($token), 'is printable'); $this->assertStringNotMatchesFormat('%S+%S', $token, 'is URI safe'); $this->assertStringNotMatchesFormat('%S/%S', $token, 'is URI safe'); $this->assertStringNotMatchesFormat('%S=%S', $token, 'is URI safe'); } } PK!*<<>test/Security/Symfony/Component/Security/Csrf/phpunit.xml.distnu[ ./Tests/ ./ ./vendor ./Tests PK!ׄHAnnKtest/Security/Symfony/Component/Security/Core/Tests/SecurityContextTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests; use Symfony\Component\Security\Core\SecurityContext; class SecurityContextTest extends \PHPUnit_Framework_TestCase { public function testVoteAuthenticatesTokenIfNecessary() { $authManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); $decisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'); $context = new SecurityContext($authManager, $decisionManager); $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $authManager ->expects($this->once()) ->method('authenticate') ->with($this->equalTo($token)) ->will($this->returnValue($newToken = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))) ; $decisionManager ->expects($this->once()) ->method('decide') ->will($this->returnValue(true)) ; $this->assertTrue($context->isGranted('foo')); $this->assertSame($newToken, $context->getToken()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException */ public function testVoteWithoutAuthenticationToken() { $context = new SecurityContext( $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface') ); $context->isGranted('ROLE_FOO'); } public function testIsGranted() { $manager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'); $manager->expects($this->once())->method('decide')->will($this->returnValue(false)); $context = new SecurityContext($this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), $manager); $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $token ->expects($this->once()) ->method('isAuthenticated') ->will($this->returnValue(true)) ; $this->assertFalse($context->isGranted('ROLE_FOO')); $manager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface'); $manager->expects($this->once())->method('decide')->will($this->returnValue(true)); $context = new SecurityContext($this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), $manager); $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $token ->expects($this->once()) ->method('isAuthenticated') ->will($this->returnValue(true)) ; $this->assertTrue($context->isGranted('ROLE_FOO')); } public function testGetSetToken() { $context = new SecurityContext( $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface') ); $this->assertNull($context->getToken()); $context->setToken($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->assertSame($token, $context->getToken()); } } PK!xFEtest/Security/Symfony/Component/Security/Core/Tests/Role/RoleTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Role; use Symfony\Component\Security\Core\Role\Role; class RoleTest extends \PHPUnit_Framework_TestCase { public function testGetRole() { $role = new Role('FOO'); $this->assertEquals('FOO', $role->getRole()); } } PK!tSNtest/Security/Symfony/Component/Security/Core/Tests/Role/RoleHierarchyTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Role; use Symfony\Component\Security\Core\Role\RoleHierarchy; use Symfony\Component\Security\Core\Role\Role; class RoleHierarchyTest extends \PHPUnit_Framework_TestCase { public function testGetReachableRoles() { $role = new RoleHierarchy(array( 'ROLE_ADMIN' => array('ROLE_USER'), 'ROLE_SUPER_ADMIN' => array('ROLE_ADMIN', 'ROLE_FOO'), )); $this->assertEquals(array(new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_USER')))); $this->assertEquals(array(new Role('ROLE_FOO')), $role->getReachableRoles(array(new Role('ROLE_FOO')))); $this->assertEquals(array(new Role('ROLE_ADMIN'), new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_ADMIN')))); $this->assertEquals(array(new Role('ROLE_FOO'), new Role('ROLE_ADMIN'), new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_FOO'), new Role('ROLE_ADMIN')))); $this->assertEquals(array(new Role('ROLE_SUPER_ADMIN'), new Role('ROLE_ADMIN'), new Role('ROLE_FOO'), new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_SUPER_ADMIN')))); } } PK!{{Otest/Security/Symfony/Component/Security/Core/Tests/Role/SwitchUserRoleTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Role; use Symfony\Component\Security\Core\Role\SwitchUserRole; class SwitchUserRoleTest extends \PHPUnit_Framework_TestCase { public function testGetSource() { $role = new SwitchUserRole('FOO', $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->assertSame($token, $role->getSource()); } public function testGetRole() { $role = new SwitchUserRole('FOO', $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->assertEquals('FOO', $role->getRole()); } } PK!rnnYtest/Security/Symfony/Component/Security/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Encoder; use Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder; class Pbkdf2PasswordEncoderTest extends \PHPUnit_Framework_TestCase { public function testIsPasswordValid() { $encoder = new Pbkdf2PasswordEncoder('sha256', false, 1, 40); $this->assertTrue($encoder->isPasswordValid('c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab106974c75607c8a3', 'password', '')); } public function testEncodePassword() { $encoder = new Pbkdf2PasswordEncoder('sha256', false, 1, 40); $this->assertSame('c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab106974c75607c8a3', $encoder->encodePassword('password', '')); $encoder = new Pbkdf2PasswordEncoder('sha256', true, 1, 40); $this->assertSame('wSMvEPYnFf2gaufAogN8oZszzxA7cnulbYcMEfKQoqsQaXTHVgfIow==', $encoder->encodePassword('password', '')); $encoder = new Pbkdf2PasswordEncoder('sha256', false, 2, 40); $this->assertSame('8bc2f9167a81cdcfad1235cd9047f1136271c1f978fcfcb35e22dbeafa4634f6fd2214218ed63ebb', $encoder->encodePassword('password', '')); } /** * @expectedException \LogicException */ public function testEncodePasswordAlgorithmDoesNotExist() { $encoder = new Pbkdf2PasswordEncoder('foobar'); $encoder->encodePassword('password', ''); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testEncodePasswordLength() { $encoder = new Pbkdf2PasswordEncoder('foobar'); $encoder->encodePassword(str_repeat('a', 5000), 'salt'); } public function testCheckPasswordLength() { $encoder = new Pbkdf2PasswordEncoder('foobar'); $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt')); } } PK!6\test/Security/Symfony/Component/Security/Core/Tests/Encoder/PlaintextPasswordEncoderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Encoder; use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder; class PlaintextPasswordEncoderTest extends \PHPUnit_Framework_TestCase { public function testIsPasswordValid() { $encoder = new PlaintextPasswordEncoder(); $this->assertTrue($encoder->isPasswordValid('foo', 'foo', '')); $this->assertFalse($encoder->isPasswordValid('bar', 'foo', '')); $this->assertFalse($encoder->isPasswordValid('FOO', 'foo', '')); $encoder = new PlaintextPasswordEncoder(true); $this->assertTrue($encoder->isPasswordValid('foo', 'foo', '')); $this->assertFalse($encoder->isPasswordValid('bar', 'foo', '')); $this->assertTrue($encoder->isPasswordValid('FOO', 'foo', '')); } public function testEncodePassword() { $encoder = new PlaintextPasswordEncoder(); $this->assertSame('foo', $encoder->encodePassword('foo', '')); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testEncodePasswordLength() { $encoder = new PlaintextPasswordEncoder(); $encoder->encodePassword(str_repeat('a', 5000), 'salt'); } public function testCheckPasswordLength() { $encoder = new PlaintextPasswordEncoder(); $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt')); } } PK!L' Wtest/Security/Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Encoder; use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder; class PasswordEncoder extends BasePasswordEncoder { public function encodePassword($raw, $salt) { } public function isPasswordValid($encoded, $raw, $salt) { } } class BasePasswordEncoderTest extends \PHPUnit_Framework_TestCase { public function testComparePassword() { $this->assertTrue($this->invokeComparePasswords('password', 'password')); $this->assertFalse($this->invokeComparePasswords('password', 'foo')); } public function testDemergePasswordAndSalt() { $this->assertEquals(array('password', 'salt'), $this->invokeDemergePasswordAndSalt('password{salt}')); $this->assertEquals(array('password', ''), $this->invokeDemergePasswordAndSalt('password')); $this->assertEquals(array('', ''), $this->invokeDemergePasswordAndSalt('')); } public function testMergePasswordAndSalt() { $this->assertEquals('password{salt}', $this->invokeMergePasswordAndSalt('password', 'salt')); $this->assertEquals('password', $this->invokeMergePasswordAndSalt('password', '')); } /** * @expectedException \InvalidArgumentException */ public function testMergePasswordAndSaltWithException() { $this->invokeMergePasswordAndSalt('password', '{foo}'); } public function testIsPasswordTooLong() { $this->assertTrue($this->invokeIsPasswordTooLong(str_repeat('a', 10000))); $this->assertFalse($this->invokeIsPasswordTooLong(str_repeat('a', 10))); } protected function invokeDemergePasswordAndSalt($password) { $encoder = new PasswordEncoder(); $r = new \ReflectionObject($encoder); $m = $r->getMethod('demergePasswordAndSalt'); $m->setAccessible(true); return $m->invoke($encoder, $password); } protected function invokeMergePasswordAndSalt($password, $salt) { $encoder = new PasswordEncoder(); $r = new \ReflectionObject($encoder); $m = $r->getMethod('mergePasswordAndSalt'); $m->setAccessible(true); return $m->invoke($encoder, $password, $salt); } protected function invokeComparePasswords($p1, $p2) { $encoder = new PasswordEncoder(); $r = new \ReflectionObject($encoder); $m = $r->getMethod('comparePasswords'); $m->setAccessible(true); return $m->invoke($encoder, $p1, $p2); } protected function invokeIsPasswordTooLong($p) { $encoder = new PasswordEncoder(); $r = new \ReflectionObject($encoder); $m = $r->getMethod('isPasswordTooLong'); $m->setAccessible(true); return $m->invoke($encoder, $p); } } PK!%sRtest/Security/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Encoder; use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder; use Symfony\Component\Security\Core\Encoder\EncoderFactory; use Symfony\Component\Security\Core\User\User; use Symfony\Component\Security\Core\User\UserInterface; class EncoderFactoryTest extends \PHPUnit_Framework_TestCase { public function testGetEncoderWithMessageDigestEncoder() { $factory = new EncoderFactory(array('Symfony\Component\Security\Core\User\UserInterface' => array( 'class' => 'Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder', 'arguments' => array('sha512', true, 5), ))); $encoder = $factory->getEncoder($this->getMock('Symfony\Component\Security\Core\User\UserInterface')); $expectedEncoder = new MessageDigestPasswordEncoder('sha512', true, 5); $this->assertEquals($expectedEncoder->encodePassword('foo', 'moo'), $encoder->encodePassword('foo', 'moo')); } public function testGetEncoderWithService() { $factory = new EncoderFactory(array( 'Symfony\Component\Security\Core\User\UserInterface' => new MessageDigestPasswordEncoder('sha1'), )); $encoder = $factory->getEncoder($this->getMock('Symfony\Component\Security\Core\User\UserInterface')); $expectedEncoder = new MessageDigestPasswordEncoder('sha1'); $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', '')); $encoder = $factory->getEncoder(new User('user', 'pass')); $expectedEncoder = new MessageDigestPasswordEncoder('sha1'); $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', '')); } public function testGetEncoderWithClassName() { $factory = new EncoderFactory(array( 'Symfony\Component\Security\Core\User\UserInterface' => new MessageDigestPasswordEncoder('sha1'), )); $encoder = $factory->getEncoder('Symfony\Component\Security\Core\Tests\Encoder\SomeChildUser'); $expectedEncoder = new MessageDigestPasswordEncoder('sha1'); $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', '')); } public function testGetEncoderConfiguredForConcreteClassWithService() { $factory = new EncoderFactory(array( 'Symfony\Component\Security\Core\User\User' => new MessageDigestPasswordEncoder('sha1'), )); $encoder = $factory->getEncoder(new User('user', 'pass')); $expectedEncoder = new MessageDigestPasswordEncoder('sha1'); $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', '')); } public function testGetEncoderConfiguredForConcreteClassWithClassName() { $factory = new EncoderFactory(array( 'Symfony\Component\Security\Core\Tests\Encoder\SomeUser' => new MessageDigestPasswordEncoder('sha1'), )); $encoder = $factory->getEncoder('Symfony\Component\Security\Core\Tests\Encoder\SomeChildUser'); $expectedEncoder = new MessageDigestPasswordEncoder('sha1'); $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', '')); } } class SomeUser implements UserInterface { public function getRoles() {} public function getPassword() {} public function getSalt() {} public function getUsername() {} public function eraseCredentials() {} } class SomeChildUser extends SomeUser { } PK!e5`test/Security/Symfony/Component/Security/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Encoder; use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder; class MessageDigestPasswordEncoderTest extends \PHPUnit_Framework_TestCase { public function testIsPasswordValid() { $encoder = new MessageDigestPasswordEncoder('sha256', false, 1); $this->assertTrue($encoder->isPasswordValid(hash('sha256', 'password'), 'password', '')); } public function testEncodePassword() { $encoder = new MessageDigestPasswordEncoder('sha256', false, 1); $this->assertSame(hash('sha256', 'password'), $encoder->encodePassword('password', '')); $encoder = new MessageDigestPasswordEncoder('sha256', true, 1); $this->assertSame(base64_encode(hash('sha256', 'password', true)), $encoder->encodePassword('password', '')); $encoder = new MessageDigestPasswordEncoder('sha256', false, 2); $this->assertSame(hash('sha256', hash('sha256', 'password', true).'password'), $encoder->encodePassword('password', '')); } /** * @expectedException \LogicException */ public function testEncodePasswordAlgorithmDoesNotExist() { $encoder = new MessageDigestPasswordEncoder('foobar'); $encoder->encodePassword('password', ''); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testEncodePasswordLength() { $encoder = new MessageDigestPasswordEncoder(); $encoder->encodePassword(str_repeat('a', 5000), 'salt'); } public function testCheckPasswordLength() { $encoder = new MessageDigestPasswordEncoder(); $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt')); } } PK!!? Ytest/Security/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Encoder; use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder; /** * @author Elnur Abdurrakhimov */ class BCryptPasswordEncoderTest extends \PHPUnit_Framework_TestCase { const PASSWORD = 'password'; const BYTES = '0123456789abcdef'; const VALID_COST = '04'; /** * @expectedException \InvalidArgumentException */ public function testCostBelowRange() { new BCryptPasswordEncoder(3); } /** * @expectedException \InvalidArgumentException */ public function testCostAboveRange() { new BCryptPasswordEncoder(32); } public function testCostInRange() { for ($cost = 4; $cost <= 31; $cost++) { new BCryptPasswordEncoder($cost); } } public function testResultLength() { $this->skipIfPhpVersionIsNotSupported(); $encoder = new BCryptPasswordEncoder(self::VALID_COST); $result = $encoder->encodePassword(self::PASSWORD, null); $this->assertEquals(60, strlen($result)); } public function testValidation() { $this->skipIfPhpVersionIsNotSupported(); $encoder = new BCryptPasswordEncoder(self::VALID_COST); $result = $encoder->encodePassword(self::PASSWORD, null); $this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, null)); $this->assertFalse($encoder->isPasswordValid($result, 'anotherPassword', null)); } private function skipIfPhpVersionIsNotSupported() { if (version_compare(phpversion(), '5.3.7', '<')) { $this->markTestSkipped('Requires PHP >= 5.3.7'); } } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testEncodePasswordLength() { $encoder = new BCryptPasswordEncoder(self::VALID_COST); $encoder->encodePassword(str_repeat('a', 5000), 'salt'); } public function testCheckPasswordLength() { $encoder = new BCryptPasswordEncoder(self::VALID_COST); $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt')); } } PK!gtest/Security/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Validator\Constraints; use Symfony\Component\Security\Core\Validator\Constraints\UserPassword; use Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator; class UserPasswordValidatorTest extends \PHPUnit_Framework_TestCase { const PASSWORD_VALID = true; const PASSWORD_INVALID = false; protected $context; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); } protected function tearDown() { $this->context = null; } public function testPasswordIsValid() { $user = $this->createUser(); $securityContext = $this->createSecurityContext($user); $encoder = $this->createPasswordEncoder(static::PASSWORD_VALID); $encoderFactory = $this->createEncoderFactory($encoder); $validator = new UserPasswordValidator($securityContext, $encoderFactory); $validator->initialize($this->context); $this ->context ->expects($this->never()) ->method('addViolation') ; $validator->validate('secret', new UserPassword()); } public function testPasswordIsNotValid() { $user = $this->createUser(); $securityContext = $this->createSecurityContext($user); $encoder = $this->createPasswordEncoder(static::PASSWORD_INVALID); $encoderFactory = $this->createEncoderFactory($encoder); $validator = new UserPasswordValidator($securityContext, $encoderFactory); $validator->initialize($this->context); $this ->context ->expects($this->once()) ->method('addViolation') ; $validator->validate('secret', new UserPassword()); } public function testUserIsNotValid() { $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); $user = $this->getMock('Foo\Bar\User'); $encoderFactory = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface'); $securityContext = $this->createSecurityContext($user); $validator = new UserPasswordValidator($securityContext, $encoderFactory); $validator->initialize($this->context); $validator->validate('secret', new UserPassword()); } protected function createUser() { $mock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $mock ->expects($this->once()) ->method('getPassword') ->will($this->returnValue('s3Cr3t')) ; $mock ->expects($this->once()) ->method('getSalt') ->will($this->returnValue('^S4lt$')) ; return $mock; } protected function createPasswordEncoder($isPasswordValid = true) { $mock = $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface'); $mock ->expects($this->once()) ->method('isPasswordValid') ->will($this->returnValue($isPasswordValid)) ; return $mock; } protected function createEncoderFactory($encoder = null) { $mock = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface'); $mock ->expects($this->once()) ->method('getEncoder') ->will($this->returnValue($encoder)) ; return $mock; } protected function createSecurityContext($user = null) { $token = $this->createAuthenticationToken($user); $mock = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); $mock ->expects($this->once()) ->method('getToken') ->will($this->returnValue($token)) ; return $mock; } protected function createAuthenticationToken($user = null) { $mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $mock ->expects($this->once()) ->method('getUser') ->will($this->returnValue($user)) ; return $mock; } } PK!K NMtest/Security/Symfony/Component/Security/Core/Tests/Util/SecureRandomTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Util; use Symfony\Component\Security\Core\Util\SecureRandom; class SecureRandomTest extends \PHPUnit_Framework_TestCase { /** * T1: Monobit test * * @dataProvider getSecureRandoms */ public function testMonobit($secureRandom) { $nbOnBits = substr_count($this->getBitSequence($secureRandom, 20000), '1'); $this->assertTrue($nbOnBits > 9654 && $nbOnBits < 10346, 'Monobit test failed, number of turned on bits: '.$nbOnBits); } /** * T2: Chi-square test with 15 degrees of freedom (chi-Quadrat-Anpassungstest) * * @dataProvider getSecureRandoms */ public function testPoker($secureRandom) { $b = $this->getBitSequence($secureRandom, 20000); $c = array(); for ($i = 0; $i <= 15; $i++) { $c[$i] = 0; } for ($j = 1; $j <= 5000; $j++) { $k = 4 * $j - 1; $c[8 * $b[$k - 3] + 4 * $b[$k - 2] + 2 * $b[$k - 1] + $b[$k]] += 1; } $f = 0; for ($i = 0; $i <= 15; $i++) { $f += $c[$i] * $c[$i]; } $Y = 16/5000 * $f - 5000; $this->assertTrue($Y > 1.03 && $Y < 57.4, 'Poker test failed, Y = '.$Y); } /** * Run test * * @dataProvider getSecureRandoms */ public function testRun($secureRandom) { $b = $this->getBitSequence($secureRandom, 20000); $runs = array(); for ($i = 1; $i <= 6; $i++) { $runs[$i] = 0; } $addRun = function ($run) use (&$runs) { if ($run > 6) { $run = 6; } $runs[$run] += 1; }; $currentRun = 0; $lastBit = null; for ($i = 0; $i < 20000; $i++) { if ($lastBit === $b[$i]) { $currentRun += 1; } else { if ($currentRun > 0) { $addRun($currentRun); } $lastBit = $b[$i]; $currentRun = 0; } } if ($currentRun > 0) { $addRun($currentRun); } $this->assertTrue($runs[1] > 2267 && $runs[1] < 2733, 'Runs of length 1 outside of defined interval: '.$runs[1]); $this->assertTrue($runs[2] > 1079 && $runs[2] < 1421, 'Runs of length 2 outside of defined interval: '.$runs[2]); $this->assertTrue($runs[3] > 502 && $runs[3] < 748, 'Runs of length 3 outside of defined interval: '.$runs[3]); $this->assertTrue($runs[4] > 233 && $runs[4] < 402, 'Runs of length 4 outside of defined interval: '.$runs[4]); $this->assertTrue($runs[5] > 90 && $runs[5] < 223, 'Runs of length 5 outside of defined interval: '.$runs[5]); $this->assertTrue($runs[6] > 90 && $runs[6] < 233, 'Runs of length 6 outside of defined interval: '.$runs[6]); } /** * Long-run test * * @dataProvider getSecureRandoms */ public function testLongRun($secureRandom) { $b = $this->getBitSequence($secureRandom, 20000); $longestRun = $currentRun = 0; $lastBit = null; for ($i = 0; $i < 20000; $i++) { if ($lastBit === $b[$i]) { $currentRun += 1; } else { if ($currentRun > $longestRun) { $longestRun = $currentRun; } $lastBit = $b[$i]; $currentRun = 0; } } if ($currentRun > $longestRun) { $longestRun = $currentRun; } $this->assertTrue($longestRun < 34, 'Failed longest run test: '.$longestRun); } /** * Serial Correlation (Autokorrelationstest) * * @dataProvider getSecureRandoms */ public function testSerialCorrelation($secureRandom) { $shift = rand(1, 5000); $b = $this->getBitSequence($secureRandom, 20000); $Z = 0; for ($i = 0; $i < 5000; $i++) { $Z += $b[$i] === $b[$i + $shift] ? 1 : 0; } $this->assertTrue($Z > 2326 && $Z < 2674, 'Failed serial correlation test: '.$Z); } public function getSecureRandoms() { $secureRandoms = array(); // only add if openssl is indeed present $secureRandom = new SecureRandom(); if ($this->hasOpenSsl($secureRandom)) { $secureRandoms[] = array($secureRandom); } // no-openssl with custom seed provider $secureRandom = new SecureRandom(sys_get_temp_dir().'/_sf2.seed'); $this->disableOpenSsl($secureRandom); $secureRandoms[] = array($secureRandom); return $secureRandoms; } protected function disableOpenSsl($secureRandom) { $ref = new \ReflectionProperty($secureRandom, 'useOpenSsl'); $ref->setAccessible(true); $ref->setValue($secureRandom, false); $ref->setAccessible(false); } protected function hasOpenSsl($secureRandom) { $ref = new \ReflectionProperty($secureRandom, 'useOpenSsl'); $ref->setAccessible(true); $ret = $ref->getValue($secureRandom); $ref->setAccessible(false); return $ret; } private function getBitSequence($secureRandom, $length) { $bitSequence = ''; for ($i = 0; $i < $length; $i += 40) { $value = unpack('H*', $secureRandom->nextBytes(5)); $value = str_pad(base_convert($value[1], 16, 2), 40, '0', STR_PAD_LEFT); $bitSequence .= $value; } return substr($bitSequence, 0, $length); } } PK!n;SSLtest/Security/Symfony/Component/Security/Core/Tests/Util/StringUtilsTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Util; use Symfony\Component\Security\Core\Util\StringUtils; class StringUtilsTest extends \PHPUnit_Framework_TestCase { public function testEquals() { $this->assertTrue(StringUtils::equals('password', 'password')); $this->assertFalse(StringUtils::equals('password', 'foo')); } } PK!Ktest/Security/Symfony/Component/Security/Core/Tests/Util/ClassUtilsTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Util { use Symfony\Component\Security\Core\Util\ClassUtils; class ClassUtilsTest extends \PHPUnit_Framework_TestCase { public static function dataGetClass() { return array( array('stdClass', 'stdClass'), array('Symfony\Component\Security\Core\Util\ClassUtils', 'Symfony\Component\Security\Core\Util\ClassUtils'), array('MyProject\Proxies\__CG__\stdClass', 'stdClass'), array('MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\stdClass', 'stdClass'), array('MyProject\Proxies\__CG__\Symfony\Component\Security\Core\Tests\Util\ChildObject', 'Symfony\Component\Security\Core\Tests\Util\ChildObject'), array(new TestObject(), 'Symfony\Component\Security\Core\Tests\Util\TestObject'), array(new \Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Core\Tests\Util\TestObject(), 'Symfony\Component\Security\Core\Tests\Util\TestObject'), ); } /** * @dataProvider dataGetClass */ public function testGetRealClass($object, $expectedClassName) { $this->assertEquals($expectedClassName, ClassUtils::getRealClass($object)); } } class TestObject { } } namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Core\Tests\Util { class TestObject extends \Symfony\Component\Security\Core\Tests\Util\TestObject { } } PK!I-_test/Security/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authorization; use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; class AccessDecisionManagerTest extends \PHPUnit_Framework_TestCase { public function testSupportsClass() { $manager = new AccessDecisionManager(array( $this->getVoterSupportsClass(true), $this->getVoterSupportsClass(false), )); $this->assertTrue($manager->supportsClass('FooClass')); $manager = new AccessDecisionManager(array( $this->getVoterSupportsClass(false), $this->getVoterSupportsClass(false), )); $this->assertFalse($manager->supportsClass('FooClass')); } public function testSupportsAttribute() { $manager = new AccessDecisionManager(array( $this->getVoterSupportsAttribute(true), $this->getVoterSupportsAttribute(false), )); $this->assertTrue($manager->supportsAttribute('foo')); $manager = new AccessDecisionManager(array( $this->getVoterSupportsAttribute(false), $this->getVoterSupportsAttribute(false), )); $this->assertFalse($manager->supportsAttribute('foo')); } /** * @expectedException \InvalidArgumentException */ public function testSetVotersEmpty() { $manager = new AccessDecisionManager(array()); } /** * @expectedException \InvalidArgumentException */ public function testSetUnsupportedStrategy() { new AccessDecisionManager(array($this->getVoter(VoterInterface::ACCESS_GRANTED)), 'fooBar'); } /** * @dataProvider getStrategyTests */ public function testStrategies($strategy, $voters, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions, $expected) { $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $manager = new AccessDecisionManager($voters, $strategy, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions); $this->assertSame($expected, $manager->decide($token, array('ROLE_FOO'))); } public function getStrategyTests() { return array( // affirmative array('affirmative', $this->getVoters(1, 0, 0), false, true, true), array('affirmative', $this->getVoters(1, 2, 0), false, true, true), array('affirmative', $this->getVoters(0, 1, 0), false, true, false), array('affirmative', $this->getVoters(0, 0, 1), false, true, false), array('affirmative', $this->getVoters(0, 0, 1), true, true, true), // consensus array('consensus', $this->getVoters(1, 0, 0), false, true, true), array('consensus', $this->getVoters(1, 2, 0), false, true, false), array('consensus', $this->getVoters(2, 1, 0), false, true, true), array('consensus', $this->getVoters(0, 0, 1), false, true, false), array('consensus', $this->getVoters(0, 0, 1), true, true, true), array('consensus', $this->getVoters(2, 2, 0), false, true, true), array('consensus', $this->getVoters(2, 2, 1), false, true, true), array('consensus', $this->getVoters(2, 2, 0), false, false, false), array('consensus', $this->getVoters(2, 2, 1), false, false, false), // unanimous array('unanimous', $this->getVoters(1, 0, 0), false, true, true), array('unanimous', $this->getVoters(1, 0, 1), false, true, true), array('unanimous', $this->getVoters(1, 1, 0), false, true, false), array('unanimous', $this->getVoters(0, 0, 2), false, true, false), array('unanimous', $this->getVoters(0, 0, 2), true, true, true), ); } protected function getVoters($grants, $denies, $abstains) { $voters = array(); for ($i = 0; $i < $grants; $i++) { $voters[] = $this->getVoter(VoterInterface::ACCESS_GRANTED); } for ($i = 0; $i < $denies; $i++) { $voters[] = $this->getVoter(VoterInterface::ACCESS_DENIED); } for ($i = 0; $i < $abstains; $i++) { $voters[] = $this->getVoter(VoterInterface::ACCESS_ABSTAIN); } return $voters; } protected function getVoter($vote) { $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface'); $voter->expects($this->any()) ->method('vote') ->will($this->returnValue($vote)); ; return $voter; } protected function getVoterSupportsClass($ret) { $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface'); $voter->expects($this->any()) ->method('supportsClass') ->will($this->returnValue($ret)); ; return $voter; } protected function getVoterSupportsAttribute($ret) { $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface'); $voter->expects($this->any()) ->method('supportsAttribute') ->will($this->returnValue($ret)); ; return $voter; } } PK!bdw \test/Security/Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authorization; use Symfony\Component\Security\Core\Authorization\ExpressionLanguage; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\User\User; class ExpressionLanguageTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider provider */ public function testIsAuthenticated($token, $expression, $result, array $roles = array()) { $anonymousTokenClass = 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken'; $rememberMeTokenClass = 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken'; $expressionLanguage = new ExpressionLanguage(); $trustResolver = new AuthenticationTrustResolver($anonymousTokenClass, $rememberMeTokenClass); $context = array(); $context['trust_resolver'] = $trustResolver; $context['token'] = $token; $context['roles'] = $roles; $this->assertEquals($result, $expressionLanguage->evaluate($expression, $context)); } public function provider() { $roles = array('ROLE_USER', 'ROLE_ADMIN'); $user = new User('username', 'password', $roles); $noToken = null; $anonymousToken = new AnonymousToken('firewall', 'anon.'); $rememberMeToken = new RememberMeToken($user, 'providerkey', 'firewall'); $usernamePasswordToken = new UsernamePasswordToken('username', 'password', 'providerkey', $roles); return array( array($noToken, 'is_anonymous()', false), array($noToken, 'is_authenticated()', false), array($noToken, 'is_fully_authenticated()', false), array($noToken, 'is_remember_me()', false), array($noToken, "has_role('ROLE_USER')", false), array($anonymousToken, 'is_anonymous()', true), array($anonymousToken, 'is_authenticated()', false), array($anonymousToken, 'is_fully_authenticated()', false), array($anonymousToken, 'is_remember_me()', false), array($anonymousToken, "has_role('ROLE_USER')", false), array($rememberMeToken, 'is_anonymous()', false), array($rememberMeToken, 'is_authenticated()', true), array($rememberMeToken, 'is_fully_authenticated()', false), array($rememberMeToken, 'is_remember_me()', true), array($rememberMeToken, "has_role('ROLE_FOO')", false, $roles), array($rememberMeToken, "has_role('ROLE_USER')", true, $roles), array($usernamePasswordToken, 'is_anonymous()', false), array($usernamePasswordToken, 'is_authenticated()', true), array($usernamePasswordToken, 'is_fully_authenticated()', true), array($usernamePasswordToken, 'is_remember_me()', false), array($usernamePasswordToken, "has_role('ROLE_FOO')", false, $roles), array($usernamePasswordToken, "has_role('ROLE_USER')", true, $roles), ); } } PK!Ƕ' _test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/ExpressionVoterTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authorization\Voter; use Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Role\Role; class ExpressionVoterTest extends \PHPUnit_Framework_TestCase { public function testSupportsAttribute() { $expression = $this->createExpression(); $expressionLanguage = $this->getMock('Symfony\Component\Security\Core\Authorization\ExpressionLanguage'); $voter = new ExpressionVoter($expressionLanguage, $this->createTrustResolver(), $this->createRoleHierarchy()); $this->assertTrue($voter->supportsAttribute($expression)); } /** * @dataProvider getVoteTests */ public function testVote($roles, $attributes, $expected, $tokenExpectsGetRoles = true, $expressionLanguageExpectsEvaluate = true) { $voter = new ExpressionVoter($this->createExpressionLanguage($expressionLanguageExpectsEvaluate), $this->createTrustResolver()); $this->assertSame($expected, $voter->vote($this->getToken($roles, $tokenExpectsGetRoles), null, $attributes)); } public function getVoteTests() { return array( array(array(), array(), VoterInterface::ACCESS_ABSTAIN, false, false), array(array(), array('FOO'), VoterInterface::ACCESS_ABSTAIN, false, false), array(array(), array($this->createExpression()), VoterInterface::ACCESS_DENIED, true, false), array(array('ROLE_FOO'), array($this->createExpression(), $this->createExpression()), VoterInterface::ACCESS_GRANTED), array(array('ROLE_BAR', 'ROLE_FOO'), array($this->createExpression()), VoterInterface::ACCESS_GRANTED), ); } protected function getToken(array $roles, $tokenExpectsGetRoles = true) { foreach ($roles as $i => $role) { $roles[$i] = new Role($role); } $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); if ($tokenExpectsGetRoles) { $token->expects($this->once()) ->method('getRoles') ->will($this->returnValue($roles)); } return $token; } protected function createExpressionLanguage($expressionLanguageExpectsEvaluate = true) { $mock = $this->getMock('Symfony\Component\Security\Core\Authorization\ExpressionLanguage'); if ($expressionLanguageExpectsEvaluate) { $mock->expects($this->once()) ->method('evaluate') ->will($this->returnValue(true)); } return $mock; } protected function createTrustResolver() { return $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface'); } protected function createRoleHierarchy() { return $this->getMock('Symfony\Component\Security\Core\Role\RoleHierarchyInterface'); } protected function createExpression() { return $this->getMockBuilder('Symfony\Component\ExpressionLanguage\Expression') ->disableOriginalConstructor() ->getMock(); } } PK!jqoYtest/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleVoterTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authorization\Voter; use Symfony\Component\Security\Core\Authorization\Voter\RoleVoter; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Role\Role; class RoleVoterTest extends \PHPUnit_Framework_TestCase { public function testSupportsClass() { $voter = new RoleVoter(); $this->assertTrue($voter->supportsClass('Foo')); } /** * @dataProvider getVoteTests */ public function testVote($roles, $attributes, $expected) { $voter = new RoleVoter(); $this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes)); } public function getVoteTests() { return array( array(array(), array(), VoterInterface::ACCESS_ABSTAIN), array(array(), array('FOO'), VoterInterface::ACCESS_ABSTAIN), array(array(), array('ROLE_FOO'), VoterInterface::ACCESS_DENIED), array(array('ROLE_FOO'), array('ROLE_FOO'), VoterInterface::ACCESS_GRANTED), array(array('ROLE_FOO'), array('FOO', 'ROLE_FOO'), VoterInterface::ACCESS_GRANTED), array(array('ROLE_BAR', 'ROLE_FOO'), array('ROLE_FOO'), VoterInterface::ACCESS_GRANTED), ); } protected function getToken(array $roles) { foreach ($roles as $i => $role) { $roles[$i] = new Role($role); } $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $token->expects($this->once()) ->method('getRoles') ->will($this->returnValue($roles)); ; return $token; } } PK!RMMbtest/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authorization\Voter; use Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Role\RoleHierarchy; class RoleHierarchyVoterTest extends RoleVoterTest { /** * @dataProvider getVoteTests */ public function testVote($roles, $attributes, $expected) { $voter = new RoleHierarchyVoter(new RoleHierarchy(array('ROLE_FOO' => array('ROLE_FOOBAR')))); $this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes)); } public function getVoteTests() { return array_merge(parent::getVoteTests(), array( array(array('ROLE_FOO'), array('ROLE_FOOBAR'), VoterInterface::ACCESS_GRANTED), )); } } PK! , , btest/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver; use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; class AuthenticatedVoterTest extends \PHPUnit_Framework_TestCase { public function testSupportsClass() { $voter = new AuthenticatedVoter($this->getResolver()); $this->assertTrue($voter->supportsClass('stdClass')); } /** * @dataProvider getVoteTests */ public function testVote($authenticated, $attributes, $expected) { $voter = new AuthenticatedVoter($this->getResolver()); $this->assertSame($expected, $voter->vote($this->getToken($authenticated), null, $attributes)); } public function getVoteTests() { return array( array('fully', array(), VoterInterface::ACCESS_ABSTAIN), array('fully', array('FOO'), VoterInterface::ACCESS_ABSTAIN), array('remembered', array(), VoterInterface::ACCESS_ABSTAIN), array('remembered', array('FOO'), VoterInterface::ACCESS_ABSTAIN), array('anonymously', array(), VoterInterface::ACCESS_ABSTAIN), array('anonymously', array('FOO'), VoterInterface::ACCESS_ABSTAIN), array('fully', array('IS_AUTHENTICATED_ANONYMOUSLY'), VoterInterface::ACCESS_GRANTED), array('remembered', array('IS_AUTHENTICATED_ANONYMOUSLY'), VoterInterface::ACCESS_GRANTED), array('anonymously', array('IS_AUTHENTICATED_ANONYMOUSLY'), VoterInterface::ACCESS_GRANTED), array('fully', array('IS_AUTHENTICATED_REMEMBERED'), VoterInterface::ACCESS_GRANTED), array('remembered', array('IS_AUTHENTICATED_REMEMBERED'), VoterInterface::ACCESS_GRANTED), array('anonymously', array('IS_AUTHENTICATED_REMEMBERED'), VoterInterface::ACCESS_DENIED), array('fully', array('IS_AUTHENTICATED_FULLY'), VoterInterface::ACCESS_GRANTED), array('remembered', array('IS_AUTHENTICATED_FULLY'), VoterInterface::ACCESS_DENIED), array('anonymously', array('IS_AUTHENTICATED_FULLY'), VoterInterface::ACCESS_DENIED), ); } protected function getResolver() { return new AuthenticationTrustResolver( 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken', 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken' ); } protected function getToken($authenticated) { if ('fully' === $authenticated) { return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); } elseif ('remembered' === $authenticated) { return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('setPersistent'), array(), '', false); } else { return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', null, array('', '')); } } } PK!LS(Etest/Security/Symfony/Component/Security/Core/Tests/User/UserTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\User; use Symfony\Component\Security\Core\User\User; class UserTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\Security\Core\User\User::__construct * @expectedException \InvalidArgumentException */ public function testConstructorException() { new User('', 'superpass'); } /** * @covers Symfony\Component\Security\Core\User\User::__construct * @covers Symfony\Component\Security\Core\User\User::getRoles */ public function testGetRoles() { $user = new User('fabien', 'superpass'); $this->assertEquals(array(), $user->getRoles()); $user = new User('fabien', 'superpass', array('ROLE_ADMIN')); $this->assertEquals(array('ROLE_ADMIN'), $user->getRoles()); } /** * @covers Symfony\Component\Security\Core\User\User::__construct * @covers Symfony\Component\Security\Core\User\User::getPassword */ public function testGetPassword() { $user = new User('fabien', 'superpass'); $this->assertEquals('superpass', $user->getPassword()); } /** * @covers Symfony\Component\Security\Core\User\User::__construct * @covers Symfony\Component\Security\Core\User\User::getUsername */ public function testGetUsername() { $user = new User('fabien', 'superpass'); $this->assertEquals('fabien', $user->getUsername()); } /** * @covers Symfony\Component\Security\Core\User\User::getSalt */ public function testGetSalt() { $user = new User('fabien', 'superpass'); $this->assertEquals('', $user->getSalt()); } /** * @covers Symfony\Component\Security\Core\User\User::isAccountNonExpired */ public function testIsAccountNonExpired() { $user = new User('fabien', 'superpass'); $this->assertTrue($user->isAccountNonExpired()); $user = new User('fabien', 'superpass', array(), true, false); $this->assertFalse($user->isAccountNonExpired()); } /** * @covers Symfony\Component\Security\Core\User\User::isCredentialsNonExpired */ public function testIsCredentialsNonExpired() { $user = new User('fabien', 'superpass'); $this->assertTrue($user->isCredentialsNonExpired()); $user = new User('fabien', 'superpass', array(), true, true, false); $this->assertFalse($user->isCredentialsNonExpired()); } /** * @covers Symfony\Component\Security\Core\User\User::isAccountNonLocked */ public function testIsAccountNonLocked() { $user = new User('fabien', 'superpass'); $this->assertTrue($user->isAccountNonLocked()); $user = new User('fabien', 'superpass', array(), true, true, true, false); $this->assertFalse($user->isAccountNonLocked()); } /** * @covers Symfony\Component\Security\Core\User\User::isEnabled */ public function testIsEnabled() { $user = new User('fabien', 'superpass'); $this->assertTrue($user->isEnabled()); $user = new User('fabien', 'superpass', array(), false); $this->assertFalse($user->isEnabled()); } /** * @covers Symfony\Component\Security\Core\User\User::eraseCredentials */ public function testEraseCredentials() { $user = new User('fabien', 'superpass'); $user->eraseCredentials(); $this->assertEquals('superpass', $user->getPassword()); } } PK!qRtest/Security/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\User; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\User\ChainUserProvider; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; class ChainUserProviderTest extends \PHPUnit_Framework_TestCase { public function testLoadUserByUsername() { $provider1 = $this->getProvider(); $provider1 ->expects($this->once()) ->method('loadUserByUsername') ->with($this->equalTo('foo')) ->will($this->throwException(new UsernameNotFoundException('not found'))) ; $provider2 = $this->getProvider(); $provider2 ->expects($this->once()) ->method('loadUserByUsername') ->with($this->equalTo('foo')) ->will($this->returnValue($account = $this->getAccount())) ; $provider = new ChainUserProvider(array($provider1, $provider2)); $this->assertSame($account, $provider->loadUserByUsername('foo')); } /** * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException */ public function testLoadUserByUsernameThrowsUsernameNotFoundException() { $provider1 = $this->getProvider(); $provider1 ->expects($this->once()) ->method('loadUserByUsername') ->with($this->equalTo('foo')) ->will($this->throwException(new UsernameNotFoundException('not found'))) ; $provider2 = $this->getProvider(); $provider2 ->expects($this->once()) ->method('loadUserByUsername') ->with($this->equalTo('foo')) ->will($this->throwException(new UsernameNotFoundException('not found'))) ; $provider = new ChainUserProvider(array($provider1, $provider2)); $provider->loadUserByUsername('foo'); } public function testRefreshUser() { $provider1 = $this->getProvider(); $provider1 ->expects($this->once()) ->method('refreshUser') ->will($this->throwException(new UnsupportedUserException('unsupported'))) ; $provider2 = $this->getProvider(); $provider2 ->expects($this->once()) ->method('refreshUser') ->will($this->returnValue($account = $this->getAccount())) ; $provider = new ChainUserProvider(array($provider1, $provider2)); $this->assertSame($account, $provider->refreshUser($this->getAccount())); } public function testRefreshUserAgain() { $provider1 = $this->getProvider(); $provider1 ->expects($this->once()) ->method('refreshUser') ->will($this->throwException(new UsernameNotFoundException('not found'))) ; $provider2 = $this->getProvider(); $provider2 ->expects($this->once()) ->method('refreshUser') ->will($this->returnValue($account = $this->getAccount())) ; $provider = new ChainUserProvider(array($provider1, $provider2)); $this->assertSame($account, $provider->refreshUser($this->getAccount())); } /** * @expectedException \Symfony\Component\Security\Core\Exception\UnsupportedUserException */ public function testRefreshUserThrowsUnsupportedUserException() { $provider1 = $this->getProvider(); $provider1 ->expects($this->once()) ->method('refreshUser') ->will($this->throwException(new UnsupportedUserException('unsupported'))) ; $provider2 = $this->getProvider(); $provider2 ->expects($this->once()) ->method('refreshUser') ->will($this->throwException(new UnsupportedUserException('unsupported'))) ; $provider = new ChainUserProvider(array($provider1, $provider2)); $provider->refreshUser($this->getAccount()); } public function testSupportsClass() { $provider1 = $this->getProvider(); $provider1 ->expects($this->once()) ->method('supportsClass') ->with($this->equalTo('foo')) ->will($this->returnValue(false)) ; $provider2 = $this->getProvider(); $provider2 ->expects($this->once()) ->method('supportsClass') ->with($this->equalTo('foo')) ->will($this->returnValue(true)) ; $provider = new ChainUserProvider(array($provider1, $provider2)); $this->assertTrue($provider->supportsClass('foo')); } public function testSupportsClassWhenNotSupported() { $provider1 = $this->getProvider(); $provider1 ->expects($this->once()) ->method('supportsClass') ->with($this->equalTo('foo')) ->will($this->returnValue(false)) ; $provider2 = $this->getProvider(); $provider2 ->expects($this->once()) ->method('supportsClass') ->with($this->equalTo('foo')) ->will($this->returnValue(false)) ; $provider = new ChainUserProvider(array($provider1, $provider2)); $this->assertFalse($provider->supportsClass('foo')); } protected function getAccount() { return $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); } protected function getProvider() { return $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); } } PK!$stest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider; class AnonymousAuthenticationProviderTest extends \PHPUnit_Framework_TestCase { public function testSupports() { $provider = $this->getProvider('foo'); $this->assertTrue($provider->supports($this->getSupportedToken('foo'))); $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))); } public function testAuthenticateWhenTokenIsNotSupported() { $provider = $this->getProvider('foo'); $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testAuthenticateWhenKeyIsNotValid() { $provider = $this->getProvider('foo'); $this->assertNull($provider->authenticate($this->getSupportedToken('bar'))); } public function testAuthenticate() { $provider = $this->getProvider('foo'); $token = $this->getSupportedToken('foo'); $this->assertSame($token, $provider->authenticate($token)); } protected function getSupportedToken($key) { $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', array('getKey'), array(), '', false); $token->expects($this->any()) ->method('getKey') ->will($this->returnValue($key)) ; return $token; } protected function getProvider($key) { return new AnonymousAuthenticationProvider($key); } } PK!P[.[.mtest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\Provider; use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder; use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider; class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException */ public function testRetrieveUserWhenProviderDoesNotReturnAnUserInterface() { $provider = $this->getProvider('fabien'); $method = new \ReflectionMethod($provider, 'retrieveUser'); $method->setAccessible(true); $method->invoke($provider, 'fabien', $this->getSupportedToken()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException */ public function testRetrieveUserWhenUsernameIsNotFound() { $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface'); $userProvider->expects($this->once()) ->method('loadUserByUsername') ->will($this->throwException($this->getMock('Symfony\\Component\\Security\\Core\\Exception\\UsernameNotFoundException', null, array(), '', false))) ; $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface')); $method = new \ReflectionMethod($provider, 'retrieveUser'); $method->setAccessible(true); $method->invoke($provider, 'fabien', $this->getSupportedToken()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException */ public function testRetrieveUserWhenAnExceptionOccurs() { $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface'); $userProvider->expects($this->once()) ->method('loadUserByUsername') ->will($this->throwException($this->getMock('RuntimeException', null, array(), '', false))) ; $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface')); $method = new \ReflectionMethod($provider, 'retrieveUser'); $method->setAccessible(true); $method->invoke($provider, 'fabien', $this->getSupportedToken()); } public function testRetrieveUserReturnsUserFromTokenOnReauthentication() { $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface'); $userProvider->expects($this->never()) ->method('loadUserByUsername') ; $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'); $token = $this->getSupportedToken(); $token->expects($this->once()) ->method('getUser') ->will($this->returnValue($user)) ; $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface')); $reflection = new \ReflectionMethod($provider, 'retrieveUser'); $reflection->setAccessible(true); $result = $reflection->invoke($provider, null, $token); $this->assertSame($user, $result); } public function testRetrieveUser() { $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'); $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface'); $userProvider->expects($this->once()) ->method('loadUserByUsername') ->will($this->returnValue($user)) ; $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface')); $method = new \ReflectionMethod($provider, 'retrieveUser'); $method->setAccessible(true); $this->assertSame($user, $method->invoke($provider, 'fabien', $this->getSupportedToken())); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testCheckAuthenticationWhenCredentialsAreEmpty() { $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface'); $encoder ->expects($this->never()) ->method('isPasswordValid') ; $provider = $this->getProvider(null, null, $encoder); $method = new \ReflectionMethod($provider, 'checkAuthentication'); $method->setAccessible(true); $token = $this->getSupportedToken(); $token ->expects($this->once()) ->method('getCredentials') ->will($this->returnValue('')) ; $method->invoke( $provider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'), $token ); } public function testCheckAuthenticationWhenCredentialsAre0() { $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface'); $encoder ->expects($this->once()) ->method('isPasswordValid') ->will($this->returnValue(true)) ; $provider = $this->getProvider(null, null, $encoder); $method = new \ReflectionMethod($provider, 'checkAuthentication'); $method->setAccessible(true); $token = $this->getSupportedToken(); $token ->expects($this->once()) ->method('getCredentials') ->will($this->returnValue('0')) ; $method->invoke( $provider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'), $token ); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testCheckAuthenticationWhenCredentialsAreNotValid() { $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface'); $encoder->expects($this->once()) ->method('isPasswordValid') ->will($this->returnValue(false)) ; $provider = $this->getProvider(null, null, $encoder); $method = new \ReflectionMethod($provider, 'checkAuthentication'); $method->setAccessible(true); $token = $this->getSupportedToken(); $token->expects($this->once()) ->method('getCredentials') ->will($this->returnValue('foo')) ; $method->invoke($provider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'), $token); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testCheckAuthenticationDoesNotReauthenticateWhenPasswordHasChanged() { $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'); $user->expects($this->once()) ->method('getPassword') ->will($this->returnValue('foo')) ; $token = $this->getSupportedToken(); $token->expects($this->once()) ->method('getUser') ->will($this->returnValue($user)); $dbUser = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'); $dbUser->expects($this->once()) ->method('getPassword') ->will($this->returnValue('newFoo')) ; $provider = $this->getProvider(); $reflection = new \ReflectionMethod($provider, 'checkAuthentication'); $reflection->setAccessible(true); $reflection->invoke($provider, $dbUser, $token); } public function testCheckAuthenticationWhenTokenNeedsReauthenticationWorksWithoutOriginalCredentials() { $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'); $user->expects($this->once()) ->method('getPassword') ->will($this->returnValue('foo')) ; $token = $this->getSupportedToken(); $token->expects($this->once()) ->method('getUser') ->will($this->returnValue($user)); $dbUser = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'); $dbUser->expects($this->once()) ->method('getPassword') ->will($this->returnValue('foo')) ; $provider = $this->getProvider(); $reflection = new \ReflectionMethod($provider, 'checkAuthentication'); $reflection->setAccessible(true); $reflection->invoke($provider, $dbUser, $token); } public function testCheckAuthentication() { $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface'); $encoder->expects($this->once()) ->method('isPasswordValid') ->will($this->returnValue(true)) ; $provider = $this->getProvider(null, null, $encoder); $method = new \ReflectionMethod($provider, 'checkAuthentication'); $method->setAccessible(true); $token = $this->getSupportedToken(); $token->expects($this->once()) ->method('getCredentials') ->will($this->returnValue('foo')) ; $method->invoke($provider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'), $token); } protected function getSupportedToken() { $mock = $this->getMock('Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken', array('getCredentials', 'getUser', 'getProviderKey'), array(), '', false); $mock ->expects($this->any()) ->method('getProviderKey') ->will($this->returnValue('key')) ; return $mock; } protected function getProvider($user = null, $userChecker = null, $passwordEncoder = null) { $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface'); if (null !== $user) { $userProvider->expects($this->once()) ->method('loadUserByUsername') ->will($this->returnValue($user)) ; } if (null === $userChecker) { $userChecker = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'); } if (null === $passwordEncoder) { $passwordEncoder = new PlaintextPasswordEncoder(); } $encoderFactory = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'); $encoderFactory ->expects($this->any()) ->method('getEncoder') ->will($this->returnValue($passwordEncoder)) ; return new DaoAuthenticationProvider($userProvider, $userChecker, 'key', $encoderFactory); } } PK!וGi&i&ntest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\SwitchUserRole; use Symfony\Component\Security\Core\Exception\BadCredentialsException; class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase { public function testSupports() { $provider = $this->getProvider(); $this->assertTrue($provider->supports($this->getSupportedToken())); $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))); } public function testAuthenticateWhenTokenIsNotSupported() { $provider = $this->getProvider(); $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))); } /** * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException */ public function testAuthenticateWhenUsernameIsNotFound() { $provider = $this->getProvider(false, false); $provider->expects($this->once()) ->method('retrieveUser') ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\UsernameNotFoundException', null, array(), '', false))) ; $provider->authenticate($this->getSupportedToken()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testAuthenticateWhenUsernameIsNotFoundAndHideIsTrue() { $provider = $this->getProvider(false, true); $provider->expects($this->once()) ->method('retrieveUser') ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\UsernameNotFoundException', null, array(), '', false))) ; $provider->authenticate($this->getSupportedToken()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException */ public function testAuthenticateWhenProviderDoesNotReturnAnUserInterface() { $provider = $this->getProvider(false, true); $provider->expects($this->once()) ->method('retrieveUser') ->will($this->returnValue(null)) ; $provider->authenticate($this->getSupportedToken()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\CredentialsExpiredException */ public function testAuthenticateWhenPreChecksFails() { $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); $userChecker->expects($this->once()) ->method('checkPreAuth') ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\CredentialsExpiredException', null, array(), '', false))) ; $provider = $this->getProvider($userChecker); $provider->expects($this->once()) ->method('retrieveUser') ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface'))) ; $provider->authenticate($this->getSupportedToken()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException */ public function testAuthenticateWhenPostChecksFails() { $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); $userChecker->expects($this->once()) ->method('checkPostAuth') ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\AccountExpiredException', null, array(), '', false))) ; $provider = $this->getProvider($userChecker); $provider->expects($this->once()) ->method('retrieveUser') ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface'))) ; $provider->authenticate($this->getSupportedToken()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException * @expectedExceptionMessage Bad credentials */ public function testAuthenticateWhenPostCheckAuthenticationFails() { $provider = $this->getProvider(); $provider->expects($this->once()) ->method('retrieveUser') ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface'))) ; $provider->expects($this->once()) ->method('checkAuthentication') ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\BadCredentialsException', null, array(), '', false))) ; $provider->authenticate($this->getSupportedToken()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException * @expectedExceptionMessage Foo */ public function testAuthenticateWhenPostCheckAuthenticationFailsWithHideFalse() { $provider = $this->getProvider(false, false); $provider->expects($this->once()) ->method('retrieveUser') ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface'))) ; $provider->expects($this->once()) ->method('checkAuthentication') ->will($this->throwException(new BadCredentialsException('Foo'))) ; $provider->authenticate($this->getSupportedToken()); } public function testAuthenticate() { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user->expects($this->once()) ->method('getRoles') ->will($this->returnValue(array('ROLE_FOO'))) ; $provider = $this->getProvider(); $provider->expects($this->once()) ->method('retrieveUser') ->will($this->returnValue($user)) ; $token = $this->getSupportedToken(); $token->expects($this->once()) ->method('getCredentials') ->will($this->returnValue('foo')) ; $token->expects($this->once()) ->method('getRoles') ->will($this->returnValue(array())) ; $authToken = $provider->authenticate($token); $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken); $this->assertSame($user, $authToken->getUser()); $this->assertEquals(array(new Role('ROLE_FOO')), $authToken->getRoles()); $this->assertEquals('foo', $authToken->getCredentials()); $this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes'); } public function testAuthenticateWithPreservingRoleSwitchUserRole() { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user->expects($this->once()) ->method('getRoles') ->will($this->returnValue(array('ROLE_FOO'))) ; $provider = $this->getProvider(); $provider->expects($this->once()) ->method('retrieveUser') ->will($this->returnValue($user)) ; $token = $this->getSupportedToken(); $token->expects($this->once()) ->method('getCredentials') ->will($this->returnValue('foo')) ; $switchUserRole = new SwitchUserRole('foo', $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $token->expects($this->once()) ->method('getRoles') ->will($this->returnValue(array($switchUserRole))) ; $authToken = $provider->authenticate($token); $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken); $this->assertSame($user, $authToken->getUser()); $this->assertContains(new Role('ROLE_FOO'), $authToken->getRoles(), '', false, false); $this->assertContains($switchUserRole, $authToken->getRoles()); $this->assertEquals('foo', $authToken->getCredentials()); $this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes'); } protected function getSupportedToken() { $mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', array('getCredentials', 'getProviderKey', 'getRoles'), array(), '', false); $mock ->expects($this->any()) ->method('getProviderKey') ->will($this->returnValue('key')) ; $mock->setAttributes(array('foo' => 'bar')); return $mock; } protected function getProvider($userChecker = false, $hide = true) { if (false === $userChecker) { $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); } return $this->getMockForAbstractClass('Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider', array($userChecker, 'key', $hide)); } } PK!75ttttest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Provider\RememberMeAuthenticationProvider; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Core\Role\Role; class RememberMeAuthenticationProviderTest extends \PHPUnit_Framework_TestCase { public function testSupports() { $provider = $this->getProvider(); $this->assertTrue($provider->supports($this->getSupportedToken())); $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))); } public function testAuthenticateWhenTokenIsNotSupported() { $provider = $this->getProvider(); $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); $this->assertNull($provider->authenticate($token)); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testAuthenticateWhenKeysDoNotMatch() { $provider = $this->getProvider(null, 'key1'); $token = $this->getSupportedToken(null, 'key2'); $provider->authenticate($token); } /** * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException */ public function testAuthenticateWhenPostChecksFails() { $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); $userChecker->expects($this->once()) ->method('checkPostAuth') ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\AccountExpiredException', null, array(), '', false))) ; $provider = $this->getProvider($userChecker); $provider->authenticate($this->getSupportedToken()); } public function testAuthenticate() { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user->expects($this->exactly(2)) ->method('getRoles') ->will($this->returnValue(array('ROLE_FOO'))) ; $provider = $this->getProvider(); $token = $this->getSupportedToken($user); $authToken = $provider->authenticate($token); $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', $authToken); $this->assertSame($user, $authToken->getUser()); $this->assertEquals(array(new Role('ROLE_FOO')), $authToken->getRoles()); $this->assertEquals('', $authToken->getCredentials()); } protected function getSupportedToken($user = null, $key = 'test') { if (null === $user) { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user ->expects($this->any()) ->method('getRoles') ->will($this->returnValue(array())) ; } $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('getProviderKey'), array($user, 'foo', $key)); $token ->expects($this->once()) ->method('getProviderKey') ->will($this->returnValue('foo')) ; return $token; } protected function getProvider($userChecker = null, $key = 'test') { if (null === $userChecker) { $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); } return new RememberMeAuthenticationProvider($userChecker, $key, 'foo'); } } PK!ZZztest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Provider\PreAuthenticatedAuthenticationProvider; class PreAuthenticatedAuthenticationProviderTest extends \PHPUnit_Framework_TestCase { public function testSupports() { $provider = $this->getProvider(); $this->assertTrue($provider->supports($this->getSupportedToken())); $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))); $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken') ->disableOriginalConstructor() ->getMock() ; $token ->expects($this->once()) ->method('getProviderKey') ->will($this->returnValue('foo')) ; $this->assertFalse($provider->supports($token)); } public function testAuthenticateWhenTokenIsNotSupported() { $provider = $this->getProvider(); $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))); } /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ public function testAuthenticateWhenNoUserIsSet() { $provider = $this->getProvider(); $provider->authenticate($this->getSupportedToken('')); } public function testAuthenticate() { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user ->expects($this->once()) ->method('getRoles') ->will($this->returnValue(array())) ; $provider = $this->getProvider($user); $token = $provider->authenticate($this->getSupportedToken('fabien', 'pass')); $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', $token); $this->assertEquals('pass', $token->getCredentials()); $this->assertEquals('key', $token->getProviderKey()); $this->assertEquals(array(), $token->getRoles()); $this->assertEquals(array('foo' => 'bar'), $token->getAttributes(), '->authenticate() copies token attributes'); $this->assertSame($user, $token->getUser()); } /** * @expectedException \Symfony\Component\Security\Core\Exception\LockedException */ public function testAuthenticateWhenUserCheckerThrowsException() { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); $userChecker->expects($this->once()) ->method('checkPostAuth') ->will($this->throwException($this->getMock('Symfony\Component\Security\Core\Exception\LockedException', null, array(), '', false))) ; $provider = $this->getProvider($user, $userChecker); $provider->authenticate($this->getSupportedToken('fabien')); } protected function getSupportedToken($user = false, $credentials = false) { $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', array('getUser', 'getCredentials', 'getProviderKey'), array(), '', false); if (false !== $user) { $token->expects($this->once()) ->method('getUser') ->will($this->returnValue($user)) ; } if (false !== $credentials) { $token->expects($this->once()) ->method('getCredentials') ->will($this->returnValue($credentials)) ; } $token ->expects($this->any()) ->method('getProviderKey') ->will($this->returnValue('key')) ; $token->setAttributes(array('foo' => 'bar')); return $token; } protected function getProvider($user = null, $userChecker = null) { $userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); if (null !== $user) { $userProvider->expects($this->once()) ->method('loadUserByUsername') ->will($this->returnValue($user)) ; } if (null === $userChecker) { $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); } return new PreAuthenticatedAuthenticationProvider($userProvider, $userChecker, 'key'); } } PK!htest/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication; use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager; use Symfony\Component\Security\Core\Exception\ProviderNotFoundException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AccountStatusException; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; class AuthenticationProviderManagerTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \InvalidArgumentException */ public function testAuthenticateWithoutProviders() { new AuthenticationProviderManager(array()); } public function testAuthenticateWhenNoProviderSupportsToken() { $manager = new AuthenticationProviderManager(array( $this->getAuthenticationProvider(false), )); try { $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->fail(); } catch (ProviderNotFoundException $e) { $this->assertSame($token, $e->getToken()); } } public function testAuthenticateWhenProviderReturnsAccountStatusException() { $manager = new AuthenticationProviderManager(array( $this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AccountStatusException'), )); try { $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->fail(); } catch (AccountStatusException $e) { $this->assertSame($token, $e->getToken()); } } public function testAuthenticateWhenProviderReturnsAuthenticationException() { $manager = new AuthenticationProviderManager(array( $this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AuthenticationException'), )); try { $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->fail(); } catch (AuthenticationException $e) { $this->assertSame($token, $e->getToken()); } } public function testAuthenticateWhenOneReturnsAuthenticationExceptionButNotAll() { $manager = new AuthenticationProviderManager(array( $this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AuthenticationException'), $this->getAuthenticationProvider(true, $expected = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')), )); $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->assertSame($expected, $token); } public function testAuthenticateReturnsTokenOfTheFirstMatchingProvider() { $second = $this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface'); $second ->expects($this->never()) ->method('supports') ; $manager = new AuthenticationProviderManager(array( $this->getAuthenticationProvider(true, $expected = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')), $second, )); $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->assertSame($expected, $token); } public function testEraseCredentialFlag() { $manager = new AuthenticationProviderManager(array( $this->getAuthenticationProvider(true, $token = new UsernamePasswordToken('foo', 'bar', 'key')), )); $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->assertEquals('', $token->getCredentials()); $manager = new AuthenticationProviderManager(array( $this->getAuthenticationProvider(true, $token = new UsernamePasswordToken('foo', 'bar', 'key')), ), false); $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')); $this->assertEquals('bar', $token->getCredentials()); } protected function getAuthenticationProvider($supports, $token = null, $exception = null) { $provider = $this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface'); $provider->expects($this->once()) ->method('supports') ->will($this->returnValue($supports)) ; if (null !== $token) { $provider->expects($this->once()) ->method('authenticate') ->will($this->returnValue($token)) ; } elseif (null !== $exception) { $provider->expects($this->once()) ->method('authenticate') ->will($this->throwException($this->getMock($exception, null, array(), '', false))) ; } return $provider; } } PK! ktest/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\RememberMe; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; use Symfony\Component\Security\Core\Authentication\RememberMe\InMemoryTokenProvider; class InMemoryTokenProviderTest extends \PHPUnit_Framework_TestCase { public function testCreateNewToken() { $provider = new InMemoryTokenProvider(); $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTime()); $provider->createNewToken($token); $this->assertSame($provider->loadTokenBySeries('foo'), $token); } /** * @expectedException \Symfony\Component\Security\Core\Exception\TokenNotFoundException */ public function testLoadTokenBySeriesThrowsNotFoundException() { $provider = new InMemoryTokenProvider(); $provider->loadTokenBySeries('foo'); } public function testUpdateToken() { $provider = new InMemoryTokenProvider(); $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTime()); $provider->createNewToken($token); $provider->updateToken('foo', 'newFoo', $lastUsed = new \DateTime()); $token = $provider->loadTokenBySeries('foo'); $this->assertEquals('newFoo', $token->getTokenValue()); $this->assertSame($token->getLastUsed(), $lastUsed); } /** * @expectedException \Symfony\Component\Security\Core\Exception\TokenNotFoundException */ public function testDeleteToken() { $provider = new InMemoryTokenProvider(); $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTime()); $provider->createNewToken($token); $provider->deleteTokenBySeries('foo'); $provider->loadTokenBySeries('foo'); } } PK!Betest/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/PersistentTokenTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\RememberMe; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; class PersistentTokenTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $lastUsed = new \DateTime(); $token = new PersistentToken('fooclass', 'fooname', 'fooseries', 'footokenvalue', $lastUsed); $this->assertEquals('fooclass', $token->getClass()); $this->assertEquals('fooname', $token->getUsername()); $this->assertEquals('fooseries', $token->getSeries()); $this->assertEquals('footokenvalue', $token->getTokenValue()); $this->assertSame($lastUsed, $token->getLastUsed()); } } PK!I?  ftest/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationTrustResolverTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver; class AuthenticationTrustResolverTest extends \PHPUnit_Framework_TestCase { public function testIsAnonymous() { $resolver = $this->getResolver(); $this->assertFalse($resolver->isAnonymous(null)); $this->assertFalse($resolver->isAnonymous($this->getToken())); $this->assertFalse($resolver->isAnonymous($this->getRememberMeToken())); $this->assertTrue($resolver->isAnonymous($this->getAnonymousToken())); } public function testIsRememberMe() { $resolver = $this->getResolver(); $this->assertFalse($resolver->isRememberMe(null)); $this->assertFalse($resolver->isRememberMe($this->getToken())); $this->assertFalse($resolver->isRememberMe($this->getAnonymousToken())); $this->assertTrue($resolver->isRememberMe($this->getRememberMeToken())); } public function testisFullFledged() { $resolver = $this->getResolver(); $this->assertFalse($resolver->isFullFledged(null)); $this->assertFalse($resolver->isFullFledged($this->getAnonymousToken())); $this->assertFalse($resolver->isFullFledged($this->getRememberMeToken())); $this->assertTrue($resolver->isFullFledged($this->getToken())); } protected function getToken() { return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); } protected function getAnonymousToken() { return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', null, array('', '')); } protected function getRememberMeToken() { return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('setPersistent'), array(), '', false); } protected function getResolver() { return new AuthenticationTrustResolver( 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken', 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken' ); } } PK!B3$$^test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\Token; use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\SwitchUserRole; class TestUser { protected $name; public function __construct($name) { $this->name = $name; } public function __toString() { return $this->name; } } class ConcreteToken extends AbstractToken { private $credentials = 'credentials_value'; public function __construct($user, array $roles = array()) { parent::__construct($roles); $this->setUser($user); } public function serialize() { return serialize(array($this->credentials, parent::serialize())); } public function unserialize($serialized) { list($this->credentials, $parentStr) = unserialize($serialized); parent::unserialize($parentStr); } public function getCredentials() {} } class AbstractTokenTest extends \PHPUnit_Framework_TestCase { public function testGetUsername() { $token = $this->getToken(array('ROLE_FOO')); $token->setUser('fabien'); $this->assertEquals('fabien', $token->getUsername()); $token->setUser(new TestUser('fabien')); $this->assertEquals('fabien', $token->getUsername()); $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user->expects($this->once())->method('getUsername')->will($this->returnValue('fabien')); $token->setUser($user); $this->assertEquals('fabien', $token->getUsername()); } public function testEraseCredentials() { $token = $this->getToken(array('ROLE_FOO')); $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user->expects($this->once())->method('eraseCredentials'); $token->setUser($user); $token->eraseCredentials(); } /** * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::serialize * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::unserialize */ public function testSerialize() { $token = $this->getToken(array('ROLE_FOO')); $token->setAttributes(array('foo' => 'bar')); $uToken = unserialize(serialize($token)); $this->assertEquals($token->getRoles(), $uToken->getRoles()); $this->assertEquals($token->getAttributes(), $uToken->getAttributes()); } public function testSerializeParent() { $user = new TestUser('fabien'); $token = new ConcreteToken($user, array('ROLE_FOO')); $parentToken = new ConcreteToken($user, array(new SwitchUserRole('ROLE_PREVIOUS', $token))); $uToken = unserialize(serialize($parentToken)); $this->assertEquals( current($parentToken->getRoles())->getSource()->getUser(), current($uToken->getRoles())->getSource()->getUser() ); } /** * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::__construct */ public function testConstructor() { $token = $this->getToken(array('ROLE_FOO')); $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles()); $token = $this->getToken(array(new Role('ROLE_FOO'))); $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles()); $token = $this->getToken(array(new Role('ROLE_FOO'), 'ROLE_BAR')); $this->assertEquals(array(new Role('ROLE_FOO'), new Role('ROLE_BAR')), $token->getRoles()); } /** * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::isAuthenticated * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::setAuthenticated */ public function testAuthenticatedFlag() { $token = $this->getToken(); $this->assertFalse($token->isAuthenticated()); $token->setAuthenticated(true); $this->assertTrue($token->isAuthenticated()); $token->setAuthenticated(false); $this->assertFalse($token->isAuthenticated()); } /** * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::getAttributes * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::setAttributes * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::hasAttribute * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::getAttribute * @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::setAttribute */ public function testAttributes() { $attributes = array('foo' => 'bar'); $token = $this->getToken(); $token->setAttributes($attributes); $this->assertEquals($attributes, $token->getAttributes(), '->getAttributes() returns the token attributes'); $this->assertEquals('bar', $token->getAttribute('foo'), '->getAttribute() returns the value of an attribute'); $token->setAttribute('foo', 'foo'); $this->assertEquals('foo', $token->getAttribute('foo'), '->setAttribute() changes the value of an attribute'); $this->assertTrue($token->hasAttribute('foo'), '->hasAttribute() returns true if the attribute is defined'); $this->assertFalse($token->hasAttribute('oof'), '->hasAttribute() returns false if the attribute is not defined'); try { $token->getAttribute('foobar'); $this->fail('->getAttribute() throws an \InvalidArgumentException exception when the attribute does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->getAttribute() throws an \InvalidArgumentException exception when the attribute does not exist'); $this->assertEquals('This token has no "foobar" attribute.', $e->getMessage(), '->getAttribute() throws an \InvalidArgumentException exception when the attribute does not exist'); } } /** * @dataProvider getUsers */ public function testSetUser($user) { $token = $this->getToken(); $token->setUser($user); $this->assertSame($user, $token->getUser()); } public function getUsers() { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $advancedUser = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface'); return array( array($advancedUser), array($user), array(new TestUser('foo')), array('foo'), ); } /** * @dataProvider getUserChanges */ public function testSetUserSetsAuthenticatedToFalseWhenUserChanges($firstUser, $secondUser) { $token = $this->getToken(); $token->setAuthenticated(true); $this->assertTrue($token->isAuthenticated()); $token->setUser($firstUser); $this->assertTrue($token->isAuthenticated()); $token->setUser($secondUser); $this->assertFalse($token->isAuthenticated()); } public function getUserChanges() { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $advancedUser = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface'); return array( array( 'foo', 'bar', ), array( 'foo', new TestUser('bar'), ), array( 'foo', $user, ), array( 'foo', $advancedUser ), array( $user, 'foo' ), array( $advancedUser, 'foo' ), array( $user, new TestUser('foo'), ), array( $advancedUser, new TestUser('foo'), ), array( new TestUser('foo'), new TestUser('bar'), ), array( new TestUser('foo'), 'bar', ), array( new TestUser('foo'), $user, ), array( new TestUser('foo'), $advancedUser, ), array( $user, $advancedUser ), array( $advancedUser, $user ), ); } /** * @dataProvider getUsers */ public function testSetUserDoesNotSetAuthenticatedToFalseWhenUserDoesNotChange($user) { $token = $this->getToken(); $token->setAuthenticated(true); $this->assertTrue($token->isAuthenticated()); $token->setUser($user); $this->assertTrue($token->isAuthenticated()); $token->setUser($user); $this->assertTrue($token->isAuthenticated()); } protected function getToken(array $roles = array()) { return $this->getMockForAbstractClass('Symfony\Component\Security\Core\Authentication\Token\AbstractToken', array($roles)); } } PK!jKKftest/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\Token; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Role\Role; class UsernamePasswordTokenTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $token = new UsernamePasswordToken('foo', 'bar', 'key'); $this->assertFalse($token->isAuthenticated()); $token = new UsernamePasswordToken('foo', 'bar', 'key', array('ROLE_FOO')); $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles()); $this->assertTrue($token->isAuthenticated()); $this->assertEquals('key', $token->getProviderKey()); } /** * @expectedException \LogicException */ public function testSetAuthenticatedToTrue() { $token = new UsernamePasswordToken('foo', 'bar', 'key'); $token->setAuthenticated(true); } public function testSetAuthenticatedToFalse() { $token = new UsernamePasswordToken('foo', 'bar', 'key'); $token->setAuthenticated(false); $this->assertFalse($token->isAuthenticated()); } public function testEraseCredentials() { $token = new UsernamePasswordToken('foo', 'bar', 'key'); $token->eraseCredentials(); $this->assertEquals('', $token->getCredentials()); } public function testToString() { $token = new UsernamePasswordToken('foo', '', 'foo', array('A', 'B')); $this->assertEquals('UsernamePasswordToken(user="foo", authenticated=true, roles="A, B")', (string) $token); } } PK!dftest/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\Token; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\Security\Core\Role\Role; class PreAuthenticatedTokenTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $token = new PreAuthenticatedToken('foo', 'bar', 'key'); $this->assertFalse($token->isAuthenticated()); $token = new PreAuthenticatedToken('foo', 'bar', 'key', array('ROLE_FOO')); $this->assertTrue($token->isAuthenticated()); $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles()); $this->assertEquals('key', $token->getProviderKey()); } public function testGetCredentials() { $token = new PreAuthenticatedToken('foo', 'bar', 'key'); $this->assertEquals('bar', $token->getCredentials()); } public function testGetUser() { $token = new PreAuthenticatedToken('foo', 'bar', 'key'); $this->assertEquals('foo', $token->getUser()); } public function testEraseCredentials() { $token = new PreAuthenticatedToken('foo', 'bar', 'key'); $token->eraseCredentials(); $this->assertEquals('', $token->getCredentials()); } } PK!ۛ_test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AnonymousTokenTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Core\Tests\Authentication\Token; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Role\Role; class AnonymousTokenTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $token = new AnonymousToken('foo', 'bar'); $this->assertTrue($token->isAuthenticated()); $token = new AnonymousToken('foo', 'bar', array('ROLE_FOO')); $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles()); } public function testGetKey() { $token = new AnonymousToken('foo', 'bar'); $this->assertEquals('foo', $token->getKey()); } public function testGetCredentials() { $token = new AnonymousToken('foo', 'bar'); $this->assertEquals('', $token->getCredentials()); } public function testGetUser() { $token = new AnonymousToken('foo', 'bar'); $this->assertEquals('bar', $token->getUser()); } } PK!]P<<>test/Security/Symfony/Component/Security/Core/phpunit.xml.distnu[ ./Tests/ ./ ./vendor ./Tests PK!nLtest/Validator/Symfony/Component/Validator/Tests/ConstraintViolationTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests; use Symfony\Component\Validator\ConstraintViolation; class ConstraintViolationTest extends \PHPUnit_Framework_TestCase { public function testToStringHandlesArrays() { $violation = new ConstraintViolation( 'Array', '{{ value }}', array('{{ value }}' => array(1, 2, 3)), 'Root', 'property.path', null ); $expected = <<assertSame($expected, (string) $violation); } public function testToStringHandlesArrayRoots() { $violation = new ConstraintViolation( '42 cannot be used here', 'this is the message template', array(), array('some_value' => 42), 'some_value', null ); $expected = <<assertSame($expected, (string) $violation); } } PK!zJ.4 Ptest/Validator/Symfony/Component/Validator/Tests/ConstraintViolationListTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; class ConstraintViolationListTest extends \PHPUnit_Framework_TestCase { protected $list; protected function setUp() { $this->list = new ConstraintViolationList(); } protected function tearDown() { $this->list = null; } public function testInit() { $this->assertCount(0, $this->list); } public function testInitWithViolations() { $violation = $this->getViolation('Error'); $this->list = new ConstraintViolationList(array($violation)); $this->assertCount(1, $this->list); $this->assertSame($violation, $this->list[0]); } public function testAdd() { $violation = $this->getViolation('Error'); $this->list->add($violation); $this->assertCount(1, $this->list); $this->assertSame($violation, $this->list[0]); } public function testAddAll() { $violations = array( 10 => $this->getViolation('Error 1'), 20 => $this->getViolation('Error 2'), 30 => $this->getViolation('Error 3'), ); $otherList = new ConstraintViolationList($violations); $this->list->addAll($otherList); $this->assertCount(3, $this->list); $this->assertSame($violations[10], $this->list[0]); $this->assertSame($violations[20], $this->list[1]); $this->assertSame($violations[30], $this->list[2]); } public function testIterator() { $violations = array( 10 => $this->getViolation('Error 1'), 20 => $this->getViolation('Error 2'), 30 => $this->getViolation('Error 3'), ); $this->list = new ConstraintViolationList($violations); // indices are reset upon adding -> array_values() $this->assertSame(array_values($violations), iterator_to_array($this->list)); } public function testArrayAccess() { $violation = $this->getViolation('Error'); $this->list[] = $violation; $this->assertSame($violation, $this->list[0]); $this->assertTrue(isset($this->list[0])); unset($this->list[0]); $this->assertFalse(isset($this->list[0])); $this->list[10] = $violation; $this->assertSame($violation, $this->list[10]); $this->assertTrue(isset($this->list[10])); } public function testToString() { $this->list = new ConstraintViolationList(array( $this->getViolation('Error 1', 'Root'), $this->getViolation('Error 2', 'Root', 'foo.bar'), $this->getViolation('Error 3', 'Root', '[baz]'), $this->getViolation('Error 4', '', 'foo.bar'), $this->getViolation('Error 5', '', '[baz]'), )); $expected = <<assertEquals($expected, (string) $this->list); } protected function getViolation($message, $root = null, $propertyPath = null) { return new ConstraintViolation($message, $message, array(), $root, $propertyPath, null); } } PK!pggXtest/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; class FailingConstraintValidator extends ConstraintValidator { public function validate($value, Constraint $constraint) { $this->context->addViolation($constraint->message, array()); return; } } PK!5*Itest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintB.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; /** @Annotation */ class ConstraintB extends Constraint { public function getTargets() { return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT); } } PK!]qqItest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintC.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; /** @Annotation */ class ConstraintC extends Constraint { public $option1; public function getRequiredOptions() { return array('option1'); } public function getTargets() { return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT); } } PK!&Itest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; /** @Annotation */ class ConstraintA extends Constraint { public $property1; public $property2; public function getDefaultOption() { return 'property2'; } public function getTargets() { return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT); } } PK!ߛ[[Dtest/Validator/Symfony/Component/Validator/Tests/Fixtures/Entity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\ExecutionContextInterface; /** * @Symfony\Component\Validator\Tests\Fixtures\ConstraintA * @Assert\GroupSequence({"Foo", "Entity"}) * @Assert\Callback({"Symfony\Component\Validator\Tests\Fixtures\CallbackClass", "callback"}) */ class Entity extends EntityParent implements EntityInterface { /** * @Assert\NotNull * @Assert\Range(min=3) * @Assert\All({@Assert\NotNull, @Assert\Range(min=3)}), * @Assert\All(constraints={@Assert\NotNull, @Assert\Range(min=3)}) * @Assert\Collection(fields={ * "foo" = {@Assert\NotNull, @Assert\Range(min=3)}, * "bar" = @Assert\Range(min=5) * }) * @Assert\Choice(choices={"A", "B"}, message="Must be one of %choices%") */ protected $firstName; protected $lastName; public $reference; private $internal; public $data = 'Overridden data'; public function __construct($internal = null) { $this->internal = $internal; } public function getInternal() { return $this->internal.' from getter'; } /** * @Assert\NotNull */ public function getLastName() { return $this->lastName; } public function getData() { return 'Overridden data'; } /** * @Assert\Callback */ public function validateMe(ExecutionContextInterface $context) { } /** * @Assert\Callback */ public static function validateMeStatic($object, ExecutionContextInterface $context) { } } PK!pTqZtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; /** @Annotation */ class ConstraintWithValueAsDefault extends Constraint { public $property; public $value; public function getDefaultOption() { return 'value'; } public function getTargets() { return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT); } } PK!@wQtest/Validator/Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Exception\NoSuchMetadataException; use Symfony\Component\Validator\Mapping\ClassMetadata; class FakeMetadataFactory implements MetadataFactoryInterface { protected $metadatas = array(); public function getMetadataFor($class) { if (is_object($class)) { $class = get_class($class); } if (!is_string($class)) { throw new NoSuchMetadataException(sprintf('No metadata for type %s', gettype($class))); } if (!isset($this->metadatas[$class])) { throw new NoSuchMetadataException(sprintf('No metadata for "%s"', $class)); } return $this->metadatas[$class]; } public function hasMetadataFor($class) { if (is_object($class)) { $class = get_class($class); } if (!is_string($class)) { return false; } return isset($this->metadatas[$class]); } public function addMetadata(ClassMetadata $metadata) { $this->metadatas[$metadata->getClassName()] = $metadata; } } PK!aCCMtest/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; interface EntityInterface { } PK! ?>Rtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\ExecutionContextInterface; class ConstraintAValidator extends ConstraintValidator { public static $passedContext; public function initialize(ExecutionContextInterface $context) { parent::initialize($context); self::$passedContext = $context; } public function validate($value, Constraint $constraint) { if ('VALID' != $value) { $this->context->addViolation('message', array('param' => 'value')); return; } return; } } PK!^tMtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; class ClassConstraint extends Constraint { public function getTargets() { return self::CLASS_CONSTRAINT; } } PK!88Jtest/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityParent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraints\NotNull; class EntityParent { protected $firstName; private $internal; private $data = 'Data'; /** * @NotNull */ protected $other; public function getData() { return 'Data'; } } PK!h  Ytest/Validator/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\GroupSequenceProviderInterface; /** * @Assert\GroupSequenceProvider */ class GroupSequenceProviderEntity implements GroupSequenceProviderInterface { public $firstName; public $lastName; protected $groups = array(); public function setGroups($groups) { $this->groups = $groups; } public function getGroupSequence() { return $this->groups; } } PK!5>Qtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; /** @Annotation */ class ConstraintWithValue extends Constraint { public $property; public $value; public function getDefaultOption() { return 'property'; } public function getTargets() { return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT); } } PK!= 2Otest/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; class FailingConstraint extends Constraint { public $message = 'Failed'; public function getTargets() { return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT); } } PK!Ol99Gtest/Validator/Symfony/Component/Validator/Tests/Fixtures/Reference.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; class Reference { } PK!2 Otest/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; class InvalidConstraint extends Constraint { } PK!j/Itest/Validator/Symfony/Component/Validator/Tests/Fixtures/FilesLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Mapping\Loader\FilesLoader as BaseFilesLoader; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; abstract class FilesLoader extends BaseFilesLoader { protected $timesCalled = 0; protected $loader; public function __construct(array $paths, LoaderInterface $loader) { $this->loader = $loader; parent::__construct($paths); } protected function getFileLoaderInstance($file) { $this->timesCalled++; return $this->loader; } public function getTimesCalled() { return $this->timesCalled; } } PK!Y/Ktest/Validator/Symfony/Component/Validator/Tests/Fixtures/CallbackClass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\ExecutionContextInterface; /** * @author Bernhard Schussek */ class CallbackClass { public static function callback($object, ExecutionContextInterface $context) { } } PK!JJXtest/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; class InvalidConstraintValidator { } PK!G#iPtest/Validator/Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; class PropertyConstraint extends Constraint { public function getTargets() { return self::PROPERTY_CONSTRAINT; } } PK!Ε_) ) Itest/Validator/Symfony/Component/Validator/Tests/ValidatorBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests; use Symfony\Component\Validator\ValidatorBuilder; use Symfony\Component\Validator\ValidatorBuilderInterface; class ValidatorBuilderTest extends \PHPUnit_Framework_TestCase { /** * @var ValidatorBuilderInterface */ protected $builder; protected function setUp() { $this->builder = new ValidatorBuilder(); } protected function tearDown() { $this->builder = null; } public function testAddObjectInitializer() { $this->assertSame($this->builder, $this->builder->addObjectInitializer( $this->getMock('Symfony\Component\Validator\ObjectInitializerInterface') )); } public function testAddObjectInitializers() { $this->assertSame($this->builder, $this->builder->addObjectInitializers(array())); } public function testAddXmlMapping() { $this->assertSame($this->builder, $this->builder->addXmlMapping('mapping')); } public function testAddXmlMappings() { $this->assertSame($this->builder, $this->builder->addXmlMappings(array())); } public function testAddYamlMapping() { $this->assertSame($this->builder, $this->builder->addYamlMapping('mapping')); } public function testAddYamlMappings() { $this->assertSame($this->builder, $this->builder->addYamlMappings(array())); } public function testAddMethodMapping() { $this->assertSame($this->builder, $this->builder->addMethodMapping('mapping')); } public function testAddMethodMappings() { $this->assertSame($this->builder, $this->builder->addMethodMappings(array())); } public function testEnableAnnotationMapping() { $this->assertSame($this->builder, $this->builder->enableAnnotationMapping()); } public function testDisableAnnotationMapping() { $this->assertSame($this->builder, $this->builder->disableAnnotationMapping()); } public function testSetMetadataCache() { $this->assertSame($this->builder, $this->builder->setMetadataCache( $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface')) ); } public function testSetConstraintValidatorFactory() { $this->assertSame($this->builder, $this->builder->setConstraintValidatorFactory( $this->getMock('Symfony\Component\Validator\ConstraintValidatorFactoryInterface')) ); } public function testSetTranslator() { $this->assertSame($this->builder, $this->builder->setTranslator( $this->getMock('Symfony\Component\Translation\TranslatorInterface')) ); } public function testSetTranslationDomain() { $this->assertSame($this->builder, $this->builder->setTranslationDomain('TRANS_DOMAIN')); } } PK!>Ntest/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Exception\GroupDefinitionException; use Symfony\Component\Validator\Tests\Fixtures\Entity; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint; class ClassMetadataTest extends \PHPUnit_Framework_TestCase { const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; const PROVIDERCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'; protected $metadata; protected function setUp() { $this->metadata = new ClassMetadata(self::CLASSNAME); } protected function tearDown() { $this->metadata = null; } public function testAddConstraintDoesNotAcceptValid() { $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); $this->metadata->addConstraint(new Valid()); } public function testAddConstraintRequiresClassConstraints() { $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); $this->metadata->addConstraint(new PropertyConstraint()); } public function testAddPropertyConstraints() { $this->metadata->addPropertyConstraint('firstName', new ConstraintA()); $this->metadata->addPropertyConstraint('lastName', new ConstraintB()); $this->assertEquals(array('firstName', 'lastName'), $this->metadata->getConstrainedProperties()); } public function testMergeConstraintsMergesClassConstraints() { $parent = new ClassMetadata(self::PARENTCLASS); $parent->addConstraint(new ConstraintA()); $this->metadata->mergeConstraints($parent); $this->metadata->addConstraint(new ConstraintA()); $constraints = array( new ConstraintA(array('groups' => array( 'Default', 'EntityParent', 'Entity', ))), new ConstraintA(array('groups' => array( 'Default', 'Entity', ))), ); $this->assertEquals($constraints, $this->metadata->getConstraints()); } public function testMergeConstraintsMergesMemberConstraints() { $parent = new ClassMetadata(self::PARENTCLASS); $parent->addPropertyConstraint('firstName', new ConstraintA()); $this->metadata->mergeConstraints($parent); $this->metadata->addPropertyConstraint('firstName', new ConstraintA()); $constraints = array( new ConstraintA(array('groups' => array( 'Default', 'EntityParent', 'Entity', ))), new ConstraintA(array('groups' => array( 'Default', 'Entity', ))), ); $members = $this->metadata->getMemberMetadatas('firstName'); $this->assertCount(1, $members); $this->assertEquals(self::PARENTCLASS, $members[0]->getClassName()); $this->assertEquals($constraints, $members[0]->getConstraints()); } public function testMemberMetadatas() { $this->metadata->addPropertyConstraint('firstName', new ConstraintA()); $this->assertTrue($this->metadata->hasMemberMetadatas('firstName')); $this->assertFalse($this->metadata->hasMemberMetadatas('non_existant_field')); } public function testMergeConstraintsKeepsPrivateMembersSeparate() { $parent = new ClassMetadata(self::PARENTCLASS); $parent->addPropertyConstraint('internal', new ConstraintA()); $this->metadata->mergeConstraints($parent); $this->metadata->addPropertyConstraint('internal', new ConstraintA()); $parentConstraints = array( new ConstraintA(array('groups' => array( 'Default', 'EntityParent', 'Entity', ))), ); $constraints = array( new ConstraintA(array('groups' => array( 'Default', 'Entity', ))), ); $members = $this->metadata->getMemberMetadatas('internal'); $this->assertCount(2, $members); $this->assertEquals(self::PARENTCLASS, $members[0]->getClassName()); $this->assertEquals($parentConstraints, $members[0]->getConstraints()); $this->assertEquals(self::CLASSNAME, $members[1]->getClassName()); $this->assertEquals($constraints, $members[1]->getConstraints()); } public function testGetReflectionClass() { $reflClass = new \ReflectionClass(self::CLASSNAME); $this->assertEquals($reflClass, $this->metadata->getReflectionClass()); } public function testSerialize() { $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A'))); $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup'))); $this->metadata->addPropertyConstraint('firstName', new ConstraintA()); $this->metadata->addGetterConstraint('lastName', new ConstraintB()); $metadata = unserialize(serialize($this->metadata)); $this->assertEquals($this->metadata, $metadata); } public function testGroupSequencesWorkIfContainingDefaultGroup() { $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup())); } public function testGroupSequencesFailIfNotContainingDefaultGroup() { $this->setExpectedException('Symfony\Component\Validator\Exception\GroupDefinitionException'); $this->metadata->setGroupSequence(array('Foo', 'Bar')); } public function testGroupSequencesFailIfContainingDefault() { $this->setExpectedException('Symfony\Component\Validator\Exception\GroupDefinitionException'); $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup(), Constraint::DEFAULT_GROUP)); } /** * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException */ public function testGroupSequenceFailsIfGroupSequenceProviderIsSet() { $metadata = new ClassMetadata(self::PROVIDERCLASS); $metadata->setGroupSequenceProvider(true); $metadata->setGroupSequence(array('GroupSequenceProviderEntity', 'Foo')); } /** * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException */ public function testGroupSequenceProviderFailsIfGroupSequenceIsSet() { $metadata = new ClassMetadata(self::PROVIDERCLASS); $metadata->setGroupSequence(array('GroupSequenceProviderEntity', 'Foo')); $metadata->setGroupSequenceProvider(true); } /** * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException */ public function testGroupSequenceProviderFailsIfDomainClassIsInvalid() { $metadata = new ClassMetadata('stdClass'); $metadata->setGroupSequenceProvider(true); } public function testGroupSequenceProvider() { $metadata = new ClassMetadata(self::PROVIDERCLASS); $metadata->setGroupSequenceProvider(true); $this->assertTrue($metadata->isGroupSequenceProvider()); } } PK!FUtest/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping; use Symfony\Component\Validator\Tests\Fixtures\Entity; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Mapping\ClassMetadataFactory; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; class ClassMetadataFactoryTest extends \PHPUnit_Framework_TestCase { const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; public function testLoadClassMetadata() { $factory = new ClassMetadataFactory(new TestLoader()); $metadata = $factory->getMetadataFor(self::PARENTCLASS); $constraints = array( new ConstraintA(array('groups' => array('Default', 'EntityParent'))), ); $this->assertEquals($constraints, $metadata->getConstraints()); } public function testMergeParentConstraints() { $factory = new ClassMetadataFactory(new TestLoader()); $metadata = $factory->getMetadataFor(self::CLASSNAME); $constraints = array( new ConstraintA(array('groups' => array( 'Default', 'EntityParent', 'Entity', ))), new ConstraintA(array('groups' => array( 'Default', 'EntityInterface', 'Entity', ))), new ConstraintA(array('groups' => array( 'Default', 'Entity', ))), ); $this->assertEquals($constraints, $metadata->getConstraints()); } public function testWriteMetadataToCache() { $cache = $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface'); $factory = new ClassMetadataFactory(new TestLoader(), $cache); $tester = $this; $constraints = array( new ConstraintA(array('groups' => array('Default', 'EntityParent'))), ); $cache->expects($this->never()) ->method('has'); $cache->expects($this->once()) ->method('read') ->with($this->equalTo(self::PARENTCLASS)) ->will($this->returnValue(false)); $cache->expects($this->once()) ->method('write') ->will($this->returnCallback(function ($metadata) use ($tester, $constraints) { $tester->assertEquals($constraints, $metadata->getConstraints()); })); $metadata = $factory->getMetadataFor(self::PARENTCLASS); $this->assertEquals(self::PARENTCLASS, $metadata->getClassName()); $this->assertEquals($constraints, $metadata->getConstraints()); } public function testReadMetadataFromCache() { $loader = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface'); $cache = $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface'); $factory = new ClassMetadataFactory($loader, $cache); $tester = $this; $metadata = new ClassMetadata(self::PARENTCLASS); $metadata->addConstraint(new ConstraintA()); $loader->expects($this->never()) ->method('loadClassMetadata'); $cache->expects($this->never()) ->method('has'); $cache->expects($this->once()) ->method('read') ->will($this->returnValue($metadata)); $this->assertEquals($metadata,$factory->getMetadataFor(self::PARENTCLASS)); } } class TestLoader implements LoaderInterface { public function loadClassMetadata(ClassMetadata $metadata) { $metadata->addConstraint(new ConstraintA()); } } PK!)Ptest/Validator/Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Mapping\ElementMetadata; class ElementMetadataTest extends \PHPUnit_Framework_TestCase { protected $metadata; protected function setUp() { $this->metadata = new TestElementMetadata(); } protected function tearDown() { $this->metadata = null; } public function testAddConstraints() { $this->metadata->addConstraint($constraint1 = new ConstraintA()); $this->metadata->addConstraint($constraint2 = new ConstraintA()); $this->assertEquals(array($constraint1, $constraint2), $this->metadata->getConstraints()); } public function testMultipleConstraintsOfTheSameType() { $constraint1 = new ConstraintA(array('property1' => 'A')); $constraint2 = new ConstraintA(array('property1' => 'B')); $this->metadata->addConstraint($constraint1); $this->metadata->addConstraint($constraint2); $this->assertEquals(array($constraint1, $constraint2), $this->metadata->getConstraints()); } public function testFindConstraintsByGroup() { $constraint1 = new ConstraintA(array('groups' => 'TestGroup')); $constraint2 = new ConstraintB(); $this->metadata->addConstraint($constraint1); $this->metadata->addConstraint($constraint2); $this->assertEquals(array($constraint1), $this->metadata->findConstraints('TestGroup')); } public function testSerialize() { $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A'))); $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup'))); $metadata = unserialize(serialize($this->metadata)); $this->assertEquals($this->metadata, $metadata); } } class TestElementMetadata extends ElementMetadata {} PK!D Otest/Validator/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Mapping\MemberMetadata; class MemberMetadataTest extends \PHPUnit_Framework_TestCase { protected $metadata; protected function setUp() { $this->metadata = new TestMemberMetadata( 'Symfony\Component\Validator\Tests\Fixtures\Entity', 'getLastName', 'lastName' ); } protected function tearDown() { $this->metadata = null; } public function testAddValidSetsMemberToCascaded() { $result = $this->metadata->addConstraint(new Valid()); $this->assertEquals(array(), $this->metadata->getConstraints()); $this->assertEquals($result, $this->metadata); $this->assertTrue($this->metadata->isCascaded()); } public function testAddOtherConstraintDoesNotSetMemberToCascaded() { $result = $this->metadata->addConstraint($constraint = new ConstraintA()); $this->assertEquals(array($constraint), $this->metadata->getConstraints()); $this->assertEquals($result, $this->metadata); $this->assertFalse($this->metadata->isCascaded()); } public function testAddConstraintRequiresClassConstraints() { $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); $this->metadata->addConstraint(new ClassConstraint()); } public function testSerialize() { $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A'))); $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup'))); $metadata = unserialize(serialize($this->metadata)); $this->assertEquals($this->metadata, $metadata); } public function testSerializeCollectionCascaded() { $this->metadata->addConstraint(new Valid(array('traverse' => true, 'deep' => false))); $metadata = unserialize(serialize($this->metadata)); $this->assertEquals($this->metadata, $metadata); } public function testSerializeCollectionCascadedDeeply() { $this->metadata->addConstraint(new Valid(array('traverse' => true, 'deep' => true))); $metadata = unserialize(serialize($this->metadata)); $this->assertEquals($this->metadata, $metadata); } public function testSerializeCollectionNotCascaded() { $this->metadata->addConstraint(new Valid(array('traverse' => false))); $metadata = unserialize(serialize($this->metadata)); $this->assertEquals($this->metadata, $metadata); } } class TestMemberMetadata extends MemberMetadata { public function getPropertyValue($object) { } protected function newReflectionMember($object) { } } PK!W_ϘOtest/Validator/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping; use Symfony\Component\Validator\Mapping\GetterMetadata; use Symfony\Component\Validator\Tests\Fixtures\Entity; class GetterMetadataTest extends \PHPUnit_Framework_TestCase { const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; public function testInvalidPropertyName() { $this->setExpectedException('Symfony\Component\Validator\Exception\ValidatorException'); new GetterMetadata(self::CLASSNAME, 'foobar'); } public function testGetPropertyValueFromPublicGetter() { // private getters don't work yet because ReflectionMethod::setAccessible() // does not exist yet in a stable PHP release $entity = new Entity('foobar'); $metadata = new GetterMetadata(self::CLASSNAME, 'internal'); $this->assertEquals('foobar from getter', $metadata->getPropertyValue($entity)); } public function testGetPropertyValueFromOverriddenPublicGetter() { $entity = new Entity(); $metadata = new GetterMetadata(self::CLASSNAME, 'data'); $this->assertEquals('Overridden data', $metadata->getPropertyValue($entity)); } } PK!", Otest/Validator/Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping\Cache; use Symfony\Component\Validator\Mapping\Cache\ApcCache; class ApcCacheTest extends \PHPUnit_Framework_TestCase { protected function setUp() { if (!extension_loaded('apc') || !ini_get('apc.enable_cli')) { $this->markTestSkipped('APC is not loaded.'); } } public function testWrite() { $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata') ->disableOriginalConstructor() ->setMethods(array('getClassName')) ->getMock(); $meta->expects($this->once()) ->method('getClassName') ->will($this->returnValue('bar')); $cache = new ApcCache('foo'); $cache->write($meta); $this->assertInstanceOf('Symfony\\Component\\Validator\\Mapping\\ClassMetadata', apc_fetch('foobar'), '->write() stores metadata in APC'); } public function testHas() { $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata') ->disableOriginalConstructor() ->setMethods(array('getClassName')) ->getMock(); $meta->expects($this->once()) ->method('getClassName') ->will($this->returnValue('bar')); apc_delete('foobar'); $cache = new ApcCache('foo'); $this->assertFalse($cache->has('bar'), '->has() returns false when there is no entry'); $cache->write($meta); $this->assertTrue($cache->has('bar'), '->has() returns true when the is an entry'); } public function testRead() { $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata') ->disableOriginalConstructor() ->setMethods(array('getClassName')) ->getMock(); $meta->expects($this->once()) ->method('getClassName') ->will($this->returnValue('bar')); $cache = new ApcCache('foo'); $cache->write($meta); $this->assertInstanceOf('Symfony\\Component\\Validator\\Mapping\\ClassMetadata', $cache->read('bar'), '->read() returns metadata'); } } PK!os%eeYtest/Validator/Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping; use Symfony\Component\Validator\Mapping\BlackholeMetadataFactory; class BlackholeMetadataFactoryTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \LogicException */ public function testGetMetadataForThrowsALogicException() { $metadataFactory = new BlackholeMetadataFactory(); $metadataFactory->getMetadataFor('foo'); } public function testHasMetadataForReturnsFalse() { $metadataFactory = new BlackholeMetadataFactory(); $this->assertFalse($metadataFactory->hasMetadataFor('foo')); } } PK!ug  Stest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping\Loader; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\LoaderChain; class LoaderChainTest extends \PHPUnit_Framework_TestCase { public function testAllLoadersAreCalled() { $metadata = new ClassMetadata('\stdClass'); $loader1 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface'); $loader1->expects($this->once()) ->method('loadClassMetadata') ->with($this->equalTo($metadata)); $loader2 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface'); $loader2->expects($this->once()) ->method('loadClassMetadata') ->with($this->equalTo($metadata)); $chain = new LoaderChain(array( $loader1, $loader2, )); $chain->loadClassMetadata($metadata); } public function testReturnsTrueIfAnyLoaderReturnedTrue() { $metadata = new ClassMetadata('\stdClass'); $loader1 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface'); $loader1->expects($this->any()) ->method('loadClassMetadata') ->will($this->returnValue(true)); $loader2 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface'); $loader2->expects($this->any()) ->method('loadClassMetadata') ->will($this->returnValue(false)); $chain = new LoaderChain(array( $loader1, $loader2, )); $this->assertTrue($chain->loadClassMetadata($metadata)); } public function testReturnsFalseIfNoLoaderReturnedTrue() { $metadata = new ClassMetadata('\stdClass'); $loader1 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface'); $loader1->expects($this->any()) ->method('loadClassMetadata') ->will($this->returnValue(false)); $loader2 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface'); $loader2->expects($this->any()) ->method('loadClassMetadata') ->will($this->returnValue(false)); $chain = new LoaderChain(array( $loader1, $loader2, )); $this->assertFalse($chain->loadClassMetadata($metadata)); } } PK!=btest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xmlnu[ Symfony\Component\Validator\Tests\Fixtures\ PK!Dk Vtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xmlnu[ Symfony\Component\Validator\Tests\Fixtures\ Foo Entity validateMe validateMeStatic Symfony\Component\Validator\Tests\Fixtures\CallbackClass callback A B PK!-Vtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.ymlnu[namespaces: custom: Symfony\Component\Validator\Tests\Fixtures\ Symfony\Component\Validator\Tests\Fixtures\Entity: group_sequence: - Foo - Entity constraints: # Custom constraint - Symfony\Component\Validator\Tests\Fixtures\ConstraintA: ~ # Custom constraint with namespaces prefix - "custom:ConstraintB": ~ # Callbacks - Callback: validateMe - Callback: validateMeStatic - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] properties: firstName: # Constraint without value - NotNull: ~ # Constraint with single value - Range: min: 3 # Constraint with multiple values - Choice: [A, B] # Constraint with child constraints - All: - NotNull: ~ - Range: min: 3 # Option with child constraints - All: constraints: - NotNull: ~ - Range: min: 3 # Value with child constraints - Collection: fields: foo: - NotNull: ~ - Range: min: 3 bar: - Range: min: 5 # Constraint with options - Choice: { choices: [A, B], message: Must be one of %choices% } dummy: getters: lastName: - NotNull: ~ Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity: group_sequence_provider: true PK!{%uZtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping\Loader; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; class StaticMethodLoaderTest extends \PHPUnit_Framework_TestCase { public function testLoadClassMetadataReturnsTrueIfSuccessful() { $loader = new StaticMethodLoader('loadMetadata'); $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderEntity'); $this->assertTrue($loader->loadClassMetadata($metadata)); } public function testLoadClassMetadataReturnsFalseIfNotSuccessful() { $loader = new StaticMethodLoader('loadMetadata'); $metadata = new ClassMetadata('\stdClass'); $this->assertFalse($loader->loadClassMetadata($metadata)); } public function testLoadClassMetadata() { $loader = new StaticMethodLoader('loadMetadata'); $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderEntity'); $loader->loadClassMetadata($metadata); $this->assertEquals(StaticLoaderEntity::$invokedWith, $metadata); } public function testLoadClassMetadataDoesNotRepeatLoadWithParentClasses() { $loader = new StaticMethodLoader('loadMetadata'); $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderDocument'); $loader->loadClassMetadata($metadata); $this->assertCount(0, $metadata->getConstraints()); $loader = new StaticMethodLoader('loadMetadata'); $metadata = new ClassMetadata(__NAMESPACE__.'\BaseStaticLoaderDocument'); $loader->loadClassMetadata($metadata); $this->assertCount(1, $metadata->getConstraints()); } public function testLoadClassMetadataIgnoresInterfaces() { $loader = new StaticMethodLoader('loadMetadata'); $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderInterface'); $loader->loadClassMetadata($metadata); $this->assertCount(0, $metadata->getConstraints()); } public function testLoadClassMetadataInAbstractClasses() { $loader = new StaticMethodLoader('loadMetadata'); $metadata = new ClassMetadata(__NAMESPACE__.'\AbstractStaticLoader'); $loader->loadClassMetadata($metadata); $this->assertCount(1, $metadata->getConstraints()); } public function testLoadClassMetadataIgnoresAbstractMethods() { $loader = new StaticMethodLoader('loadMetadata'); try { include __DIR__ . '/AbstractMethodStaticLoader.php'; $this->fail('AbstractMethodStaticLoader should produce a strict standard error.'); } catch (\Exception $e) { } $metadata = new ClassMetadata(__NAMESPACE__.'\AbstractMethodStaticLoader'); $loader->loadClassMetadata($metadata); $this->assertCount(0, $metadata->getConstraints()); } } interface StaticLoaderInterface { public static function loadMetadata(ClassMetadata $metadata); } abstract class AbstractStaticLoader { public static function loadMetadata(ClassMetadata $metadata) { $metadata->addConstraint(new ConstraintA()); } } class StaticLoaderEntity { public static $invokedWith = null; public static function loadMetadata(ClassMetadata $metadata) { self::$invokedWith = $metadata; } } class StaticLoaderDocument extends BaseStaticLoaderDocument { } class BaseStaticLoaderDocument { public static function loadMetadata(ClassMetadata $metadata) { $metadata->addConstraint(new ConstraintA()); } } PK!mXtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping\Loader; use Doctrine\Common\Annotations\AnnotationReader; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase { public function testLoadClassMetadataReturnsTrueIfSuccessful() { $reader = new AnnotationReader(); $loader = new AnnotationLoader($reader); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $this->assertTrue($loader->loadClassMetadata($metadata)); } public function testLoadClassMetadataReturnsFalseIfNotSuccessful() { $loader = new AnnotationLoader(new AnnotationReader()); $metadata = new ClassMetadata('\stdClass'); $this->assertFalse($loader->loadClassMetadata($metadata)); } public function testLoadClassMetadata() { $loader = new AnnotationLoader(new AnnotationReader()); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $loader->loadClassMetadata($metadata); $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $expected->setGroupSequence(array('Foo', 'Entity')); $expected->addConstraint(new ConstraintA()); $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback'))); $expected->addConstraint(new Callback('validateMe')); $expected->addConstraint(new Callback('validateMeStatic')); $expected->addPropertyConstraint('firstName', new NotNull()); $expected->addPropertyConstraint('firstName', new Range(array('min' => 3))); $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3))))); $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3)))))); $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array( 'foo' => array(new NotNull(), new Range(array('min' => 3))), 'bar' => new Range(array('min' => 5)), )))); $expected->addPropertyConstraint('firstName', new Choice(array( 'message' => 'Must be one of %choices%', 'choices' => array('A', 'B'), ))); $expected->addGetterConstraint('lastName', new NotNull()); // load reflection class so that the comparison passes $expected->getReflectionClass(); $this->assertEquals($expected, $metadata); } /** * Test MetaData merge with parent annotation. */ public function testLoadParentClassMetadata() { $loader = new AnnotationLoader(new AnnotationReader()); // Load Parent MetaData $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent'); $loader->loadClassMetadata($parent_metadata); $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent'); $expected_parent->addPropertyConstraint('other', new NotNull()); $expected_parent->getReflectionClass(); $this->assertEquals($expected_parent, $parent_metadata); } /** * Test MetaData merge with parent annotation. */ public function testLoadClassMetadataAndMerge() { $loader = new AnnotationLoader(new AnnotationReader()); // Load Parent MetaData $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent'); $loader->loadClassMetadata($parent_metadata); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); // Merge parent metaData. $metadata->mergeConstraints($parent_metadata); $loader->loadClassMetadata($metadata); $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent'); $expected_parent->addPropertyConstraint('other', new NotNull()); $expected_parent->getReflectionClass(); $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $expected->mergeConstraints($expected_parent); $expected->setGroupSequence(array('Foo', 'Entity')); $expected->addConstraint(new ConstraintA()); $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback'))); $expected->addConstraint(new Callback('validateMe')); $expected->addConstraint(new Callback('validateMeStatic')); $expected->addPropertyConstraint('firstName', new NotNull()); $expected->addPropertyConstraint('firstName', new Range(array('min' => 3))); $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3))))); $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3)))))); $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array( 'foo' => array(new NotNull(), new Range(array('min' => 3))), 'bar' => new Range(array('min' => 5)), )))); $expected->addPropertyConstraint('firstName', new Choice(array( 'message' => 'Must be one of %choices%', 'choices' => array('A', 'B'), ))); $expected->addGetterConstraint('lastName', new NotNull()); // load reflection class so that the comparison passes $expected->getReflectionClass(); $this->assertEquals($expected, $metadata); } public function testLoadGroupSequenceProviderAnnotation() { $loader = new AnnotationLoader(new AnnotationReader()); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); $loader->loadClassMetadata($metadata); $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); $expected->setGroupSequenceProvider(true); $expected->getReflectionClass(); $this->assertEquals($expected, $metadata); } } PK!NVtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping\Loader; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase { public function testLoadClassMetadataReturnsFalseIfEmpty() { $loader = new YamlFileLoader(__DIR__.'/empty-mapping.yml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $this->assertFalse($loader->loadClassMetadata($metadata)); } /** * @expectedException \InvalidArgumentException */ public function testLoadClassMetadataThrowsExceptionIfNotAnArray() { $loader = new YamlFileLoader(__DIR__.'/nonvalid-mapping.yml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $loader->loadClassMetadata($metadata); } public function testLoadClassMetadataReturnsTrueIfSuccessful() { $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $this->assertTrue($loader->loadClassMetadata($metadata)); } public function testLoadClassMetadataReturnsFalseIfNotSuccessful() { $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml'); $metadata = new ClassMetadata('\stdClass'); $this->assertFalse($loader->loadClassMetadata($metadata)); } public function testLoadClassMetadata() { $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $loader->loadClassMetadata($metadata); $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $expected->setGroupSequence(array('Foo', 'Entity')); $expected->addConstraint(new ConstraintA()); $expected->addConstraint(new ConstraintB()); $expected->addConstraint(new Callback('validateMe')); $expected->addConstraint(new Callback('validateMeStatic')); $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback'))); $expected->addPropertyConstraint('firstName', new NotNull()); $expected->addPropertyConstraint('firstName', new Range(array('min' => 3))); $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B'))); $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3))))); $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3)))))); $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array( 'foo' => array(new NotNull(), new Range(array('min' => 3))), 'bar' => array(new Range(array('min' => 5))), )))); $expected->addPropertyConstraint('firstName', new Choice(array( 'message' => 'Must be one of %choices%', 'choices' => array('A', 'B'), ))); $expected->addGetterConstraint('lastName', new NotNull()); $this->assertEquals($expected, $metadata); } public function testLoadGroupSequenceProvider() { $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); $loader->loadClassMetadata($metadata); $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); $expected->setGroupSequenceProvider(true); $this->assertEquals($expected, $metadata); } } PK!N;Otest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xmlnu[ PK!Qtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.ymlnu[PK!QiUtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping\Loader; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Constraints\Regex; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase { public function testLoadClassMetadataReturnsTrueIfSuccessful() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $this->assertTrue($loader->loadClassMetadata($metadata)); } public function testLoadClassMetadataReturnsFalseIfNotSuccessful() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml'); $metadata = new ClassMetadata('\stdClass'); $this->assertFalse($loader->loadClassMetadata($metadata)); } public function testLoadClassMetadata() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $loader->loadClassMetadata($metadata); $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $expected->setGroupSequence(array('Foo', 'Entity')); $expected->addConstraint(new ConstraintA()); $expected->addConstraint(new ConstraintB()); $expected->addConstraint(new Callback('validateMe')); $expected->addConstraint(new Callback('validateMeStatic')); $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback'))); $expected->addPropertyConstraint('firstName', new NotNull()); $expected->addPropertyConstraint('firstName', new Range(array('min' => 3))); $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B'))); $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3))))); $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3)))))); $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array( 'foo' => array(new NotNull(), new Range(array('min' => 3))), 'bar' => array(new Range(array('min' => 5))), )))); $expected->addPropertyConstraint('firstName', new Choice(array( 'message' => 'Must be one of %choices%', 'choices' => array('A', 'B'), ))); $expected->addGetterConstraint('lastName', new NotNull()); $this->assertEquals($expected, $metadata); } public function testLoadClassMetadataWithNonStrings() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-non-strings.xml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $loader->loadClassMetadata($metadata); $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $expected->addPropertyConstraint('firstName', new Regex(array('pattern' => '/^1/', 'match' => false))); $properties = $metadata->getPropertyMetadata('firstName'); $constraints = $properties[0]->getConstraints(); $this->assertFalse($constraints[0]->match); } public function testLoadGroupSequenceProvider() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); $loader->loadClassMetadata($metadata); $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); $expected->setGroupSequenceProvider(true); $this->assertEquals($expected, $metadata); } /** * @expectedException \Symfony\Component\Validator\Exception\MappingException * @expectedExceptionMessage Document types are not allowed. */ public function testDocTypeIsNotAllowed() { $loader = new XmlFileLoader(__DIR__.'/withdoctype.xml'); $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); $loader->loadClassMetadata($metadata); } } PK!e2~Ttest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.ymlnu[foo PK!^test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping\Loader; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; use Symfony\Component\Validator\Mapping\ClassMetadata; class FilesLoaderTest extends \PHPUnit_Framework_TestCase { public function testCallsGetFileLoaderInstanceForeachPath() { $loader = $this->getFilesLoader($this->getFileLoader()); $this->assertEquals(4, $loader->getTimesCalled()); } public function testCallsActualFileLoaderForMetadata() { $fileLoader = $this->getFileLoader(); $fileLoader->expects($this->exactly(4)) ->method('loadClassMetadata'); $loader = $this->getFilesLoader($fileLoader); $loader->loadClassMetadata(new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity')); } public function getFilesLoader(LoaderInterface $loader) { return $this->getMockForAbstractClass('Symfony\Component\Validator\Tests\Fixtures\FilesLoader', array(array( __DIR__.'/constraint-mapping.xml', __DIR__.'/constraint-mapping.yaml', __DIR__.'/constraint-mapping.test', __DIR__.'/constraint-mapping.txt', ), $loader)); } public function getFileLoader() { return $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface'); } } PK!{dQtest/Validator/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Mapping; use Symfony\Component\Validator\Mapping\PropertyMetadata; use Symfony\Component\Validator\Tests\Fixtures\Entity; class PropertyMetadataTest extends \PHPUnit_Framework_TestCase { const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; public function testInvalidPropertyName() { $this->setExpectedException('Symfony\Component\Validator\Exception\ValidatorException'); new PropertyMetadata(self::CLASSNAME, 'foobar'); } public function testGetPropertyValueFromPrivateProperty() { $entity = new Entity('foobar'); $metadata = new PropertyMetadata(self::CLASSNAME, 'internal'); $this->assertEquals('foobar', $metadata->getPropertyValue($entity)); } public function testGetPropertyValueFromOverriddenPrivateProperty() { $entity = new Entity('foobar'); $metadata = new PropertyMetadata(self::PARENTCLASS, 'data'); $this->assertTrue($metadata->isPublic($entity)); $this->assertEquals('Overridden data', $metadata->getPropertyValue($entity)); } } PK!~6FFJtest/Validator/Symfony/Component/Validator/Tests/ValidationVisitorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests; use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Tests\Fixtures\Reference; use Symfony\Component\Validator\DefaultTranslator; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint; use Symfony\Component\Validator\Tests\Fixtures\ConstraintAValidator; use Symfony\Component\Validator\Tests\Fixtures\Entity; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\ConstraintValidatorFactory; use Symfony\Component\Validator\ValidationVisitor; /** * @author Bernhard Schussek */ class ValidationVisitorTest extends \PHPUnit_Framework_TestCase { const CLASS_NAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; /** * @var ValidationVisitor */ private $visitor; /** * @var FakeMetadataFactory */ private $metadataFactory; /** * @var ClassMetadata */ private $metadata; protected function setUp() { $this->metadataFactory = new FakeMetadataFactory(); $this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator()); $this->metadata = new ClassMetadata(self::CLASS_NAME); $this->metadataFactory->addMetadata($this->metadata); } protected function tearDown() { $this->metadataFactory = null; $this->visitor = null; $this->metadata = null; } public function testValidatePassesCorrectClassAndProperty() { $this->metadata->addConstraint(new ConstraintA()); $entity = new Entity(); $this->visitor->validate($entity, 'Default', ''); $context = ConstraintAValidator::$passedContext; $this->assertEquals('Symfony\Component\Validator\Tests\Fixtures\Entity', $context->getClassName()); $this->assertNull($context->getPropertyName()); } public function testValidateConstraints() { $this->metadata->addConstraint(new ConstraintA()); $this->visitor->validate(new Entity(), 'Default', ''); $this->assertCount(1, $this->visitor->getViolations()); } public function testValidateTwiceValidatesConstraintsOnce() { $this->metadata->addConstraint(new ConstraintA()); $entity = new Entity(); $this->visitor->validate($entity, 'Default', ''); $this->visitor->validate($entity, 'Default', ''); $this->assertCount(1, $this->visitor->getViolations()); } public function testValidateDifferentObjectsValidatesTwice() { $this->metadata->addConstraint(new ConstraintA()); $this->visitor->validate(new Entity(), 'Default', ''); $this->visitor->validate(new Entity(), 'Default', ''); $this->assertCount(2, $this->visitor->getViolations()); } public function testValidateTwiceInDifferentGroupsValidatesTwice() { $this->metadata->addConstraint(new ConstraintA()); $this->metadata->addConstraint(new ConstraintA(array('groups' => 'Custom'))); $entity = new Entity(); $this->visitor->validate($entity, 'Default', ''); $this->visitor->validate($entity, 'Custom', ''); $this->assertCount(2, $this->visitor->getViolations()); } public function testValidatePropertyConstraints() { $this->metadata->addPropertyConstraint('firstName', new ConstraintA()); $this->visitor->validate(new Entity(), 'Default', ''); $this->assertCount(1, $this->visitor->getViolations()); } public function testValidateGetterConstraints() { $this->metadata->addGetterConstraint('lastName', new ConstraintA()); $this->visitor->validate(new Entity(), 'Default', ''); $this->assertCount(1, $this->visitor->getViolations()); } public function testValidateInDefaultGroupTraversesGroupSequence() { $entity = new Entity(); $this->metadata->addPropertyConstraint('firstName', new FailingConstraint(array( 'groups' => 'First', ))); $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array( 'groups' => 'Default', ))); $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup())); $this->visitor->validate($entity, 'Default', ''); // After validation of group "First" failed, no more group was // validated $violations = new ConstraintViolationList(array( new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', 'firstName', '' ), )); $this->assertEquals($violations, $this->visitor->getViolations()); } public function testValidateInGroupSequencePropagatesDefaultGroup() { $entity = new Entity(); $entity->reference = new Reference(); $this->metadata->addPropertyConstraint('reference', new Valid()); $this->metadata->setGroupSequence(array($this->metadata->getDefaultGroup())); $referenceMetadata = new ClassMetadata(get_class($entity->reference)); $referenceMetadata->addConstraint(new FailingConstraint(array( // this constraint is only evaluated if group "Default" is // propagated to the reference 'groups' => 'Default', ))); $this->metadataFactory->addMetadata($referenceMetadata); $this->visitor->validate($entity, 'Default', ''); // The validation of the reference's FailingConstraint in group // "Default" was launched $violations = new ConstraintViolationList(array( new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', 'reference', $entity->reference ), )); $this->assertEquals($violations, $this->visitor->getViolations()); } public function testValidateInOtherGroupTraversesNoGroupSequence() { $entity = new Entity(); $this->metadata->addPropertyConstraint('firstName', new FailingConstraint(array( 'groups' => 'First', ))); $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array( 'groups' => $this->metadata->getDefaultGroup(), ))); $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup())); $this->visitor->validate($entity, $this->metadata->getDefaultGroup(), ''); // Only group "Second" was validated $violations = new ConstraintViolationList(array( new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', 'lastName', '' ), )); $this->assertEquals($violations, $this->visitor->getViolations()); } public function testValidateCascadedPropertyValidatesReferences() { $entity = new Entity(); $entity->reference = new Entity(); // add a constraint for the entity that always fails $this->metadata->addConstraint(new FailingConstraint()); // validate entity when validating the property "reference" $this->metadata->addPropertyConstraint('reference', new Valid()); // invoke validation on an object $this->visitor->validate($entity, 'Default', ''); $violations = new ConstraintViolationList(array( // generated by the root object new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', '', $entity ), // generated by the reference new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', 'reference', $entity->reference ), )); $this->assertEquals($violations, $this->visitor->getViolations()); } public function testValidateCascadedPropertyValidatesArraysByDefault() { $entity = new Entity(); $entity->reference = array('key' => new Entity()); // add a constraint for the entity that always fails $this->metadata->addConstraint(new FailingConstraint()); // validate array when validating the property "reference" $this->metadata->addPropertyConstraint('reference', new Valid()); $this->visitor->validate($entity, 'Default', ''); $violations = new ConstraintViolationList(array( // generated by the root object new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', '', $entity ), // generated by the reference new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', 'reference[key]', $entity->reference['key'] ), )); $this->assertEquals($violations, $this->visitor->getViolations()); } public function testValidateCascadedPropertyValidatesTraversableByDefault() { $entity = new Entity(); $entity->reference = new \ArrayIterator(array('key' => new Entity())); // add a constraint for the entity that always fails $this->metadata->addConstraint(new FailingConstraint()); // validate array when validating the property "reference" $this->metadata->addPropertyConstraint('reference', new Valid()); $this->visitor->validate($entity, 'Default', ''); $violations = new ConstraintViolationList(array( // generated by the root object new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', '', $entity ), // generated by the reference new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', 'reference[key]', $entity->reference['key'] ), )); $this->assertEquals($violations, $this->visitor->getViolations()); } public function testValidateCascadedPropertyDoesNotValidateTraversableIfDisabled() { $entity = new Entity(); $entity->reference = new \ArrayIterator(array('key' => new Entity())); $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator')); // add a constraint for the entity that always fails $this->metadata->addConstraint(new FailingConstraint()); // validate array when validating the property "reference" $this->metadata->addPropertyConstraint('reference', new Valid(array( 'traverse' => false, ))); $this->visitor->validate($entity, 'Default', ''); $violations = new ConstraintViolationList(array( // generated by the root object new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', '', $entity ), // nothing generated by the reference! )); $this->assertEquals($violations, $this->visitor->getViolations()); } public function testMetadataMayNotExistIfTraversalIsEnabled() { $entity = new Entity(); $entity->reference = new \ArrayIterator(); $this->metadata->addPropertyConstraint('reference', new Valid(array( 'traverse' => true, ))); $this->visitor->validate($entity, 'Default', ''); } /** * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException */ public function testMetadataMustExistIfTraversalIsDisabled() { $entity = new Entity(); $entity->reference = new \ArrayIterator(); $this->metadata->addPropertyConstraint('reference', new Valid(array( 'traverse' => false, ))); $this->visitor->validate($entity, 'Default', ''); } public function testValidateCascadedPropertyDoesNotRecurseByDefault() { $entity = new Entity(); $entity->reference = new \ArrayIterator(array( // The inner iterator should not be traversed by default 'key' => new \ArrayIterator(array( 'nested' => new Entity(), )), )); $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator')); // add a constraint for the entity that always fails $this->metadata->addConstraint(new FailingConstraint()); // validate iterator when validating the property "reference" $this->metadata->addPropertyConstraint('reference', new Valid()); $this->visitor->validate($entity, 'Default', ''); $violations = new ConstraintViolationList(array( // generated by the root object new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', '', $entity ), // nothing generated by the reference! )); $this->assertEquals($violations, $this->visitor->getViolations()); } // https://github.com/symfony/symfony/issues/6246 public function testValidateCascadedPropertyRecursesArraysByDefault() { $entity = new Entity(); $entity->reference = array( 'key' => array( 'nested' => new Entity(), ), ); // add a constraint for the entity that always fails $this->metadata->addConstraint(new FailingConstraint()); // validate iterator when validating the property "reference" $this->metadata->addPropertyConstraint('reference', new Valid()); $this->visitor->validate($entity, 'Default', ''); $violations = new ConstraintViolationList(array( // generated by the root object new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', '', $entity ), // nothing generated by the reference! new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', 'reference[key][nested]', $entity->reference['key']['nested'] ), )); $this->assertEquals($violations, $this->visitor->getViolations()); } public function testValidateCascadedPropertyRecursesIfDeepIsSet() { $entity = new Entity(); $entity->reference = new \ArrayIterator(array( // The inner iterator should now be traversed 'key' => new \ArrayIterator(array( 'nested' => new Entity(), )), )); // add a constraint for the entity that always fails $this->metadata->addConstraint(new FailingConstraint()); // validate iterator when validating the property "reference" $this->metadata->addPropertyConstraint('reference', new Valid(array( 'deep' => true, ))); $this->visitor->validate($entity, 'Default', ''); $violations = new ConstraintViolationList(array( // generated by the root object new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', '', $entity ), // nothing generated by the reference! new ConstraintViolation( 'Failed', 'Failed', array(), 'Root', 'reference[key][nested]', $entity->reference['key']['nested'] ), )); $this->assertEquals($violations, $this->visitor->getViolations()); } public function testValidateCascadedPropertyDoesNotValidateNestedScalarValues() { $entity = new Entity(); $entity->reference = array('scalar', 'values'); // validate array when validating the property "reference" $this->metadata->addPropertyConstraint('reference', new Valid()); $this->visitor->validate($entity, 'Default', ''); $this->assertCount(0, $this->visitor->getViolations()); } public function testValidateCascadedPropertyDoesNotValidateNullValues() { $entity = new Entity(); $entity->reference = null; $this->metadata->addPropertyConstraint('reference', new Valid()); $this->visitor->validate($entity, 'Default', ''); $this->assertCount(0, $this->visitor->getViolations()); } /** * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException */ public function testValidateCascadedPropertyRequiresObjectOrArray() { $entity = new Entity(); $entity->reference = 'no object'; $this->metadata->addPropertyConstraint('reference', new Valid()); $this->visitor->validate($entity, 'Default', ''); } } PK!Ky'$'$Btest/Validator/Symfony/Component/Validator/Tests/ValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests; use Symfony\Component\Validator\Tests\Fixtures\Entity; use Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity; use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory; use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint; use Symfony\Component\Validator\Validator; use Symfony\Component\Validator\DefaultTranslator; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Component\Validator\ConstraintValidatorFactory; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Mapping\ClassMetadata; class ValidatorTest extends \PHPUnit_Framework_TestCase { /** * @var FakeMetadataFactory */ private $metadataFactory; /** * @var Validator */ private $validator; protected function setUp() { $this->metadataFactory = new FakeMetadataFactory(); $this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator()); } protected function tearDown() { $this->metadataFactory = null; $this->validator = null; } public function testValidateDefaultGroup() { $entity = new Entity(); $metadata = new ClassMetadata(get_class($entity)); $metadata->addPropertyConstraint('firstName', new FailingConstraint()); $metadata->addPropertyConstraint('lastName', new FailingConstraint(array( 'groups' => 'Custom', ))); $this->metadataFactory->addMetadata($metadata); // Only the constraint of group "Default" failed $violations = new ConstraintViolationList(); $violations->add(new ConstraintViolation( 'Failed', 'Failed', array(), $entity, 'firstName', '' )); $this->assertEquals($violations, $this->validator->validate($entity)); } public function testValidateOneGroup() { $entity = new Entity(); $metadata = new ClassMetadata(get_class($entity)); $metadata->addPropertyConstraint('firstName', new FailingConstraint()); $metadata->addPropertyConstraint('lastName', new FailingConstraint(array( 'groups' => 'Custom', ))); $this->metadataFactory->addMetadata($metadata); // Only the constraint of group "Custom" failed $violations = new ConstraintViolationList(); $violations->add(new ConstraintViolation( 'Failed', 'Failed', array(), $entity, 'lastName', '' )); $this->assertEquals($violations, $this->validator->validate($entity, 'Custom')); } public function testValidateMultipleGroups() { $entity = new Entity(); $metadata = new ClassMetadata(get_class($entity)); $metadata->addPropertyConstraint('firstName', new FailingConstraint(array( 'groups' => 'First', ))); $metadata->addPropertyConstraint('lastName', new FailingConstraint(array( 'groups' => 'Second', ))); $this->metadataFactory->addMetadata($metadata); // The constraints of both groups failed $violations = new ConstraintViolationList(); $violations->add(new ConstraintViolation( 'Failed', 'Failed', array(), $entity, 'firstName', '' )); $violations->add(new ConstraintViolation( 'Failed', 'Failed', array(), $entity, 'lastName', '' )); $result = $this->validator->validate($entity, array('First', 'Second')); $this->assertEquals($violations, $result); } public function testValidateGroupSequenceProvider() { $entity = new GroupSequenceProviderEntity(); $metadata = new ClassMetadata(get_class($entity)); $metadata->addPropertyConstraint('firstName', new FailingConstraint(array( 'groups' => 'First', ))); $metadata->addPropertyConstraint('lastName', new FailingConstraint(array( 'groups' => 'Second', ))); $metadata->setGroupSequenceProvider(true); $this->metadataFactory->addMetadata($metadata); $violations = new ConstraintViolationList(); $violations->add(new ConstraintViolation( 'Failed', 'Failed', array(), $entity, 'firstName', '' )); $entity->setGroups(array('First')); $result = $this->validator->validate($entity); $this->assertEquals($violations, $result); $violations = new ConstraintViolationList(); $violations->add(new ConstraintViolation( 'Failed', 'Failed', array(), $entity, 'lastName', '' )); $entity->setGroups(array('Second')); $result = $this->validator->validate($entity); $this->assertEquals($violations, $result); $entity->setGroups(array()); $result = $this->validator->validate($entity); $this->assertEquals(new ConstraintViolationList(), $result); } public function testValidateProperty() { $entity = new Entity(); $metadata = new ClassMetadata(get_class($entity)); $metadata->addPropertyConstraint('firstName', new FailingConstraint()); $this->metadataFactory->addMetadata($metadata); $result = $this->validator->validateProperty($entity, 'firstName'); $this->assertCount(1, $result); $result = $this->validator->validateProperty($entity, 'lastName'); $this->assertCount(0, $result); } public function testValidatePropertyValue() { $entity = new Entity(); $metadata = new ClassMetadata(get_class($entity)); $metadata->addPropertyConstraint('firstName', new FailingConstraint()); $this->metadataFactory->addMetadata($metadata); $result = $this->validator->validatePropertyValue(get_class($entity), 'firstName', 'Bernhard'); $this->assertCount(1, $result); } public function testValidateValue() { $violations = new ConstraintViolationList(); $violations->add(new ConstraintViolation( 'Failed', 'Failed', array(), 'Bernhard', '', 'Bernhard' )); $this->assertEquals($violations, $this->validator->validateValue('Bernhard', new FailingConstraint())); } /** * @expectedException \Symfony\Component\Validator\Exception\ValidatorException */ public function testValidateValueRejectsValid() { $entity = new Entity(); $metadata = new ClassMetadata(get_class($entity)); $this->metadataFactory->addMetadata($metadata); $this->validator->validateValue($entity, new Valid()); } /** * @expectedException \Symfony\Component\Validator\Exception\ValidatorException */ public function testValidatePropertyFailsIfPropertiesNotSupported() { // $metadata does not implement PropertyMetadataContainerInterface $metadata = $this->getMock('Symfony\Component\Validator\MetadataInterface'); $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->metadataFactory->expects($this->any()) ->method('getMetadataFor') ->with('VALUE') ->will($this->returnValue($metadata)); $this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator()); $this->validator->validateProperty('VALUE', 'someProperty'); } /** * @expectedException \Symfony\Component\Validator\Exception\ValidatorException */ public function testValidatePropertyValueFailsIfPropertiesNotSupported() { // $metadata does not implement PropertyMetadataContainerInterface $metadata = $this->getMock('Symfony\Component\Validator\MetadataInterface'); $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->metadataFactory->expects($this->any()) ->method('getMetadataFor') ->with('VALUE') ->will($this->returnValue($metadata)); $this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator()); $this->validator->validatePropertyValue('VALUE', 'someProperty', 'propertyValue'); } public function testGetMetadataFactory() { $this->assertInstanceOf( 'Symfony\Component\Validator\MetadataFactoryInterface', $this->validator->getMetadataFactory() ); } } PK!P6))Itest/Validator/Symfony/Component/Validator/Tests/ExecutionContextTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Component\Validator\ExecutionContext; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\ValidationVisitor; use Symfony\Component\Validator\ConstraintValidatorFactory; class ExecutionContextTest extends \PHPUnit_Framework_TestCase { const TRANS_DOMAIN = 'trans_domain'; private $visitor; private $violations; private $metadata; private $metadataFactory; private $globalContext; private $translator; /** * @var ExecutionContext */ private $context; protected function setUp() { $this->visitor = $this->getMockBuilder('Symfony\Component\Validator\ValidationVisitor') ->disableOriginalConstructor() ->getMock(); $this->violations = new ConstraintViolationList(); $this->metadata = $this->getMock('Symfony\Component\Validator\MetadataInterface'); $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->globalContext = $this->getMock('Symfony\Component\Validator\GlobalExecutionContextInterface'); $this->globalContext->expects($this->any()) ->method('getRoot') ->will($this->returnValue('Root')); $this->globalContext->expects($this->any()) ->method('getViolations') ->will($this->returnValue($this->violations)); $this->globalContext->expects($this->any()) ->method('getVisitor') ->will($this->returnValue($this->visitor)); $this->globalContext->expects($this->any()) ->method('getMetadataFactory') ->will($this->returnValue($this->metadataFactory)); $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface'); $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', 'foo.bar'); } protected function tearDown() { $this->globalContext = null; $this->context = null; } public function testInit() { $this->assertCount(0, $this->context->getViolations()); $this->assertSame('Root', $this->context->getRoot()); $this->assertSame('foo.bar', $this->context->getPropertyPath()); $this->assertSame('Group', $this->context->getGroup()); } public function testClone() { $clone = clone $this->context; // Cloning the context keeps the reference to the original violation // list. This way we can efficiently duplicate context instances during // the validation run and only modify the properties that need to be // changed. $this->assertSame($this->context->getViolations(), $clone->getViolations()); } public function testAddViolation() { $this->translator->expects($this->once()) ->method('trans') ->with('Error', array('foo' => 'bar')) ->will($this->returnValue('Translated error')); $this->context->addViolation('Error', array('foo' => 'bar'), 'invalid'); $this->assertEquals(new ConstraintViolationList(array( new ConstraintViolation( 'Translated error', 'Error', array('foo' => 'bar'), 'Root', 'foo.bar', 'invalid' ), )), $this->context->getViolations()); } public function testAddViolationUsesPreconfiguredValueIfNotPassed() { $this->translator->expects($this->once()) ->method('trans') ->with('Error', array()) ->will($this->returnValue('Translated error')); $this->context->addViolation('Error'); $this->assertEquals(new ConstraintViolationList(array( new ConstraintViolation( 'Translated error', 'Error', array(), 'Root', 'foo.bar', 'currentValue' ), )), $this->context->getViolations()); } public function testAddViolationUsesPassedNullValue() { $this->translator->expects($this->once()) ->method('trans') ->with('Error', array('foo1' => 'bar1')) ->will($this->returnValue('Translated error')); $this->translator->expects($this->once()) ->method('transChoice') ->with('Choice error', 1, array('foo2' => 'bar2')) ->will($this->returnValue('Translated choice error')); // passed null value should override preconfigured value "invalid" $this->context->addViolation('Error', array('foo1' => 'bar1'), null); $this->context->addViolation('Choice error', array('foo2' => 'bar2'), null, 1); $this->assertEquals(new ConstraintViolationList(array( new ConstraintViolation( 'Translated error', 'Error', array('foo1' => 'bar1'), 'Root', 'foo.bar', null ), new ConstraintViolation( 'Translated choice error', 'Choice error', array('foo2' => 'bar2'), 'Root', 'foo.bar', null, 1 ), )), $this->context->getViolations()); } public function testAddViolationAt() { $this->translator->expects($this->once()) ->method('trans') ->with('Error', array('foo' => 'bar')) ->will($this->returnValue('Translated error')); // override preconfigured property path $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), 'invalid'); $this->assertEquals(new ConstraintViolationList(array( new ConstraintViolation( 'Translated error', 'Error', array('foo' => 'bar'), 'Root', 'foo.bar.bam.baz', 'invalid' ), )), $this->context->getViolations()); } public function testAddViolationAtUsesPreconfiguredValueIfNotPassed() { $this->translator->expects($this->once()) ->method('trans') ->with('Error', array()) ->will($this->returnValue('Translated error')); $this->context->addViolationAt('bam.baz', 'Error'); $this->assertEquals(new ConstraintViolationList(array( new ConstraintViolation( 'Translated error', 'Error', array(), 'Root', 'foo.bar.bam.baz', 'currentValue' ), )), $this->context->getViolations()); } public function testAddViolationAtUsesPassedNullValue() { $this->translator->expects($this->once()) ->method('trans') ->with('Error', array('foo' => 'bar')) ->will($this->returnValue('Translated error')); $this->translator->expects($this->once()) ->method('transChoice') ->with('Choice error', 2, array('foo' => 'bar')) ->will($this->returnValue('Translated choice error')); // passed null value should override preconfigured value "invalid" $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), null); $this->context->addViolationAt('bam.baz', 'Choice error', array('foo' => 'bar'), null, 2); $this->assertEquals(new ConstraintViolationList(array( new ConstraintViolation( 'Translated error', 'Error', array('foo' => 'bar'), 'Root', 'foo.bar.bam.baz', null ), new ConstraintViolation( 'Translated choice error', 'Choice error', array('foo' => 'bar'), 'Root', 'foo.bar.bam.baz', null, 2 ), )), $this->context->getViolations()); } public function testAddViolationPluralTranslationError() { $this->translator->expects($this->once()) ->method('transChoice') ->with('foo') ->will($this->throwException(new \InvalidArgumentException())); $this->translator->expects($this->once()) ->method('trans') ->with('foo'); $this->context->addViolation('foo', array(), null, 2); } public function testGetPropertyPath() { $this->assertEquals('foo.bar', $this->context->getPropertyPath()); } public function testGetPropertyPathWithIndexPath() { $this->assertEquals('foo.bar[bam]', $this->context->getPropertyPath('[bam]')); } public function testGetPropertyPathWithEmptyPath() { $this->assertEquals('foo.bar', $this->context->getPropertyPath('')); } public function testGetPropertyPathWithEmptyCurrentPropertyPath() { $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', ''); $this->assertEquals('bam.baz', $this->context->getPropertyPath('bam.baz')); } public function testGetPropertyPathWithNestedCollectionsMixed() { $constraints = new Collection(array( 'foo' => new Collection(array( 'foo' => new ConstraintA(), 'bar' => new ConstraintA(), )), 'name' => new ConstraintA() )); $visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), $this->translator); $context = new ExecutionContext($visitor, $this->translator, self::TRANS_DOMAIN); $context->validateValue(array('foo' => array('foo' => 'VALID')), $constraints); $violations = $context->getViolations(); $this->assertEquals('[name]', $violations[1]->getPropertyPath()); } } class ExecutionContextTest_TestClass { public $myProperty; } PK! Qtest/Validator/Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\ExecutionContext; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\AllValidator; class AllValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new AllValidator(); $this->validator->initialize($this->context); $this->context->expects($this->any()) ->method('getGroup') ->will($this->returnValue('MyGroup')); } protected function tearDown() { $this->validator = null; $this->context = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new All(new Range(array('min' => 4)))); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testThrowsExceptionIfNotTraversable() { $this->validator->validate('foo.barbar', new All(new Range(array('min' => 4)))); } /** * @dataProvider getValidArguments */ public function testWalkSingleConstraint($array) { $constraint = new Range(array('min' => 4)); $i = 1; foreach ($array as $key => $value) { $this->context->expects($this->at($i++)) ->method('validateValue') ->with($value, $constraint, '['.$key.']', 'MyGroup'); } $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($array, new All($constraint)); } /** * @dataProvider getValidArguments */ public function testWalkMultipleConstraints($array) { $constraint1 = new Range(array('min' => 4)); $constraint2 = new NotNull(); $constraints = array($constraint1, $constraint2); $i = 1; foreach ($array as $key => $value) { $this->context->expects($this->at($i++)) ->method('validateValue') ->with($value, $constraint1, '['.$key.']', 'MyGroup'); $this->context->expects($this->at($i++)) ->method('validateValue') ->with($value, $constraint2, '['.$key.']', 'MyGroup'); } $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($array, new All($constraints)); } public function getValidArguments() { return array( array(array(5, 6, 7)), array(new \ArrayObject(array(5, 6, 7))), ); } } PK!ĀDDStest/Validator/Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Regex; use Symfony\Component\Validator\Constraints\RegexValidator; class RegexValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new RegexValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Regex(array('pattern' => '/^[0-9]+$/'))); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Regex(array('pattern' => '/^[0-9]+$/'))); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Regex(array('pattern' => '/^[0-9]+$/'))); } /** * @dataProvider getValidValues */ public function testValidValues($value) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Regex(array('pattern' => '/^[0-9]+$/')); $this->validator->validate($value, $constraint); } public function getValidValues() { return array( array(0), array('0'), array('090909'), array(90909), ); } /** * @dataProvider getInvalidValues */ public function testInvalidValues($value) { $constraint = new Regex(array( 'pattern' => '/^[0-9]+$/', 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $value, )); $this->validator->validate($value, $constraint); } public function getInvalidValues() { return array( array('abcd'), array('090foo'), ); } public function testConstraintGetDefaultOption() { $constraint = new Regex(array( 'pattern' => '/^[0-9]+$/', )); $this->assertEquals('pattern', $constraint->getDefaultOption()); } public function testHtmlPatternEscaping() { $constraint = new Regex(array( 'pattern' => '/^[0-9]+\/$/', )); $this->assertEquals('[0-9]+/', $constraint->getHtmlPattern()); $constraint = new Regex(array( 'pattern' => '#^[0-9]+\#$#', )); $this->assertEquals('[0-9]+#', $constraint->getHtmlPattern()); } public function testHtmlPattern() { // Specified htmlPattern $constraint = new Regex(array( 'pattern' => '/^[a-z]+$/i', 'htmlPattern' => '[a-zA-Z]+', )); $this->assertEquals('[a-zA-Z]+', $constraint->getHtmlPattern()); // Disabled htmlPattern $constraint = new Regex(array( 'pattern' => '/^[a-z]+$/i', 'htmlPattern' => false, )); $this->assertNull($constraint->getHtmlPattern()); // Cannot be converted $constraint = new Regex(array( 'pattern' => '/^[a-z]+$/i', )); $this->assertNull($constraint->getHtmlPattern()); // Automatically converted $constraint = new Regex(array( 'pattern' => '/^[a-z]+$/', )); $this->assertEquals('[a-z]+', $constraint->getHtmlPattern()); // Automatically converted, adds .* $constraint = new Regex(array( 'pattern' => '/[a-z]+/', )); $this->assertEquals('.*[a-z]+.*', $constraint->getHtmlPattern()); // Dropped because of match=false $constraint = new Regex(array( 'pattern' => '/[a-z]+/', 'match' => false )); $this->assertNull($constraint->getHtmlPattern()); } } PK! Q]test/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\LessThanOrEqual; use Symfony\Component\Validator\Constraints\LessThanOrEqualValidator; /** * @author Daniel Holmes */ class LessThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCase { protected function createValidator() { return new LessThanOrEqualValidator(); } protected function createConstraint(array $options) { return new LessThanOrEqual($options); } /** * {@inheritDoc} */ public function provideValidComparisons() { return array( array(1, 2), array(1, 1), array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')), array(new \DateTime('2000-01-01'), new \DateTime('2020-01-01')), array(new ComparisonTest_Class(4), new ComparisonTest_Class(5)), array(new ComparisonTest_Class(5), new ComparisonTest_Class(5)), array('a', 'a'), array('a', 'z'), array(null, 1), ); } /** * {@inheritDoc} */ public function provideInvalidComparisons() { return array( array(2, 1, '1', 'integer'), array(new \DateTime('2010-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'), array(new ComparisonTest_Class(5), new ComparisonTest_Class(4), '4', __NAMESPACE__.'\ComparisonTest_Class'), array('c', 'b', "'b'", 'string') ); } } PK!;55Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Issn; use Symfony\Component\Validator\Constraints\IssnValidator; /** * @see https://en.wikipedia.org/wiki/Issn */ class IssnValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; public function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new IssnValidator(); $this->validator->initialize($this->context); } public function getValidLowerCasedIssn() { return array( array('2162-321x'), array('2160-200x'), array('1537-453x'), array('1937-710x'), array('0002-922x'), array('1553-345x'), array('1553-619x'), ); } public function getValidNonHyphenatedIssn() { return array( array('2162321X'), array('01896016'), array('15744647'), array('14350645'), array('07174055'), array('20905076'), array('14401592'), ); } public function getFullValidIssn() { return array( array('1550-7416'), array('1539-8560'), array('2156-5376'), array('1119-023X'), array('1684-5315'), array('1996-0786'), array('1684-5374'), array('1996-0794'), ); } public function getValidIssn() { return array_merge( $this->getValidLowerCasedIssn(), $this->getValidNonHyphenatedIssn(), $this->getFullValidIssn() ); } public function getInvalidFormatedIssn() { return array( array(0), array('1539'), array('2156-537A') ); } public function getInvalidValueIssn() { return array( array('1119-0231'), array('1684-5312'), array('1996-0783'), array('1684-537X'), array('1996-0795'), ); } public function getInvalidIssn() { return array_merge( $this->getInvalidFormatedIssn(), $this->getInvalidValueIssn() ); } public function testNullIsValid() { $constraint = new Issn(); $this->context ->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, $constraint); } public function testEmptyStringIsValid() { $constraint = new Issn(); $this->context ->expects($this->never()) ->method('addViolation'); $this->validator->validate('', $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $constraint = new Issn(); $this->validator->validate(new \stdClass(), $constraint); } /** * @dataProvider getValidLowerCasedIssn */ public function testCaseSensitiveIssns($issn) { $constraint = new Issn(array('caseSensitive' => true)); $this->context ->expects($this->once()) ->method('addViolation') ->with($constraint->message); $this->validator->validate($issn, $constraint); } /** * @dataProvider getValidNonHyphenatedIssn */ public function testRequireHyphenIssns($issn) { $constraint = new Issn(array('requireHyphen' => true)); $this->context ->expects($this->once()) ->method('addViolation') ->with($constraint->message); $this->validator->validate($issn, $constraint); } /** * @dataProvider getValidIssn */ public function testValidIssn($issn) { $constraint = new Issn(); $this->context ->expects($this->never()) ->method('addViolation'); $this->validator->validate($issn, $constraint); } /** * @dataProvider getInvalidFormatedIssn */ public function testInvalidFormatIssn($issn) { $constraint = new Issn(); $this->context ->expects($this->once()) ->method('addViolation') ->with($constraint->message); $this->validator->validate($issn, $constraint); } /** * @dataProvider getInvalidValueIssn */ public function testInvalidValueIssn($issn) { $constraint = new Issn(); $this->context ->expects($this->once()) ->method('addViolation') ->with($constraint->message); $this->validator->validate($issn, $constraint); } /** * @dataProvider getInvalidIssn */ public function testInvalidIssn($issn) { $constraint = new Issn(); $this->context ->expects($this->once()) ->method('addViolation'); $this->validator->validate($issn, $constraint); } } PK!K1K1Ptest/Validator/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Ip; use Symfony\Component\Validator\Constraints\IpValidator; class IpValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new IpValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Ip()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Ip()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Ip()); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testInvalidValidatorVersion() { $ip = new Ip(array( 'version' => 666, )); } /** * @dataProvider getValidIpsV4 */ public function testValidIpsV4($ip) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($ip, new Ip(array( 'version' => Ip::V4, ))); } public function getValidIpsV4() { return array( array('0.0.0.0'), array('10.0.0.0'), array('123.45.67.178'), array('172.16.0.0'), array('192.168.1.0'), array('224.0.0.1'), array('255.255.255.255'), array('127.0.0.0'), ); } /** * @dataProvider getValidIpsV6 */ public function testValidIpsV6($ip) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($ip, new Ip(array( 'version' => Ip::V6, ))); } public function getValidIpsV6() { return array( array('2001:0db8:85a3:0000:0000:8a2e:0370:7334'), array('2001:0DB8:85A3:0000:0000:8A2E:0370:7334'), array('2001:0Db8:85a3:0000:0000:8A2e:0370:7334'), array('fdfe:dcba:9876:ffff:fdc6:c46b:bb8f:7d4c'), array('fdc6:c46b:bb8f:7d4c:fdc6:c46b:bb8f:7d4c'), array('fdc6:c46b:bb8f:7d4c:0000:8a2e:0370:7334'), array('fe80:0000:0000:0000:0202:b3ff:fe1e:8329'), array('fe80:0:0:0:202:b3ff:fe1e:8329'), array('fe80::202:b3ff:fe1e:8329'), array('0:0:0:0:0:0:0:0'), array('::'), array('0::'), array('::0'), array('0::0'), // IPv4 mapped to IPv6 array('2001:0db8:85a3:0000:0000:8a2e:0.0.0.0'), array('::0.0.0.0'), array('::255.255.255.255'), array('::123.45.67.178'), ); } /** * @dataProvider getValidIpsAll */ public function testValidIpsAll($ip) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($ip, new Ip(array( 'version' => Ip::ALL, ))); } public function getValidIpsAll() { return array_merge($this->getValidIpsV4(), $this->getValidIpsV6()); } /** * @dataProvider getInvalidIpsV4 */ public function testInvalidIpsV4($ip) { $constraint = new Ip(array( 'version' => Ip::V4, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidIpsV4() { return array( array('0'), array('0.0'), array('0.0.0'), array('256.0.0.0'), array('0.256.0.0'), array('0.0.256.0'), array('0.0.0.256'), array('-1.0.0.0'), array('foobar'), ); } /** * @dataProvider getInvalidPrivateIpsV4 */ public function testInvalidPrivateIpsV4($ip) { $constraint = new Ip(array( 'version' => Ip::V4_NO_PRIV, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidPrivateIpsV4() { return array( array('10.0.0.0'), array('172.16.0.0'), array('192.168.1.0'), ); } /** * @dataProvider getInvalidReservedIpsV4 */ public function testInvalidReservedIpsV4($ip) { $constraint = new Ip(array( 'version' => Ip::V4_NO_RES, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidReservedIpsV4() { return array( array('0.0.0.0'), array('224.0.0.1'), array('255.255.255.255'), ); } /** * @dataProvider getInvalidPublicIpsV4 */ public function testInvalidPublicIpsV4($ip) { $constraint = new Ip(array( 'version' => Ip::V4_ONLY_PUBLIC, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidPublicIpsV4() { return array_merge($this->getInvalidPrivateIpsV4(), $this->getInvalidReservedIpsV4()); } /** * @dataProvider getInvalidIpsV6 */ public function testInvalidIpsV6($ip) { $constraint = new Ip(array( 'version' => Ip::V6, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidIpsV6() { return array( array('z001:0db8:85a3:0000:0000:8a2e:0370:7334'), array('fe80'), array('fe80:8329'), array('fe80:::202:b3ff:fe1e:8329'), array('fe80::202:b3ff::fe1e:8329'), // IPv4 mapped to IPv6 array('2001:0db8:85a3:0000:0000:8a2e:0370:0.0.0.0'), array('::0.0'), array('::0.0.0'), array('::256.0.0.0'), array('::0.256.0.0'), array('::0.0.256.0'), array('::0.0.0.256'), ); } /** * @dataProvider getInvalidPrivateIpsV6 */ public function testInvalidPrivateIpsV6($ip) { $constraint = new Ip(array( 'version' => Ip::V6_NO_PRIV, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidPrivateIpsV6() { return array( array('fdfe:dcba:9876:ffff:fdc6:c46b:bb8f:7d4c'), array('fdc6:c46b:bb8f:7d4c:fdc6:c46b:bb8f:7d4c'), array('fdc6:c46b:bb8f:7d4c:0000:8a2e:0370:7334'), ); } /** * @dataProvider getInvalidReservedIpsV6 */ public function testInvalidReservedIpsV6($ip) { $constraint = new Ip(array( 'version' => Ip::V6_NO_RES, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidReservedIpsV6() { // Quoting after official filter documentation: // "FILTER_FLAG_NO_RES_RANGE = This flag does not apply to IPv6 addresses." // Full description: http://php.net/manual/en/filter.filters.flags.php return $this->getInvalidIpsV6(); } /** * @dataProvider getInvalidPublicIpsV6 */ public function testInvalidPublicIpsV6($ip) { $constraint = new Ip(array( 'version' => Ip::V6_ONLY_PUBLIC, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidPublicIpsV6() { return array_merge($this->getInvalidPrivateIpsV6(), $this->getInvalidReservedIpsV6()); } /** * @dataProvider getInvalidIpsAll */ public function testInvalidIpsAll($ip) { $constraint = new Ip(array( 'version' => Ip::ALL, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidIpsAll() { return array_merge($this->getInvalidIpsV4(), $this->getInvalidIpsV6()); } /** * @dataProvider getInvalidPrivateIpsAll */ public function testInvalidPrivateIpsAll($ip) { $constraint = new Ip(array( 'version' => Ip::ALL_NO_PRIV, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidPrivateIpsAll() { return array_merge($this->getInvalidPrivateIpsV4(), $this->getInvalidPrivateIpsV6()); } /** * @dataProvider getInvalidReservedIpsAll */ public function testInvalidReservedIpsAll($ip) { $constraint = new Ip(array( 'version' => Ip::ALL_NO_RES, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidReservedIpsAll() { return array_merge($this->getInvalidReservedIpsV4(), $this->getInvalidReservedIpsV6()); } /** * @dataProvider getInvalidPublicIpsAll */ public function testInvalidPublicIpsAll($ip) { $constraint = new Ip(array( 'version' => Ip::ALL_ONLY_PUBLIC, 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $ip, )); $this->validator->validate($ip, $constraint); } public function getInvalidPublicIpsAll() { return array_merge($this->getInvalidPublicIpsV4(), $this->getInvalidPublicIpsV6()); } } PK!rHitest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; /** * This class is a hand written simplified version of PHP native `ArrayObject` * class, to show that it behaves differently than the PHP native implementation. */ class CustomArrayObject implements \ArrayAccess, \IteratorAggregate, \Countable, \Serializable { private $array; public function __construct(array $array = null) { $this->array = $array ?: array(); } public function offsetExists($offset) { return array_key_exists($offset, $this->array); } public function offsetGet($offset) { return $this->array[$offset]; } public function offsetSet($offset, $value) { if (null === $offset) { $this->array[] = $value; } else { $this->array[$offset] = $value; } } public function offsetUnset($offset) { unset($this->array[$offset]); } public function getIterator() { return new \ArrayIterator($this->array); } public function count() { return count($this->array); } public function serialize() { return serialize($this->array); } public function unserialize($serialized) { $this->array = (array) unserialize((string) $serialized); } } class CollectionValidatorCustomArrayObjectTest extends CollectionValidatorTest { public function prepareTestData(array $contents) { return new CustomArrayObject($contents); } } PK!GRfUtest/Validator/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotNullValidator; class NotNullValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new NotNullValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } /** * @dataProvider getValidValues */ public function testValidValues($value) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($value, new NotNull()); } public function getValidValues() { return array( array(0), array(false), array(true), array(''), ); } public function testNullIsInvalid() { $constraint = new NotNull(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( )); $this->validator->validate(null, $constraint); } } PK!I Otest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Required; use Symfony\Component\Validator\Constraints\Optional; use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\Valid; /** * @author Bernhard Schussek */ class CollectionTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testRejectInvalidFieldsOption() { new Collection(array( 'fields' => 'foo', )); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testRejectNonConstraints() { new Collection(array( 'foo' => 'bar', )); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testRejectValidConstraint() { new Collection(array( 'foo' => new Valid(), )); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testRejectValidConstraintWithinOptional() { new Collection(array( 'foo' => new Optional(new Valid()), )); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testRejectValidConstraintWithinRequired() { new Collection(array( 'foo' => new Required(new Valid()), )); } public function testAcceptOptionalConstraintAsOneElementArray() { $collection1 = new Collection(array( "fields" => array( "alternate_email" => array( new Optional(new Email()), ), ), )); $collection2 = new Collection(array( "fields" => array( "alternate_email" => new Optional(new Email()), ), )); $this->assertEquals($collection1, $collection2); } public function testAcceptRequiredConstraintAsOneElementArray() { $collection1 = new Collection(array( "fields" => array( "alternate_email" => array( new Required(new Email()), ), ), )); $collection2 = new Collection(array( "fields" => array( "alternate_email" => new Required(new Email()), ), )); $this->assertEquals($collection1, $collection2); } } PK!WXtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\HttpFoundation\File\File; class FileValidatorObjectTest extends FileValidatorTest { protected function getFile($filename) { return new File($filename); } } PK!s{*pQQRtest/Validator/Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\True; use Symfony\Component\Validator\Constraints\TrueValidator; class TrueValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new TrueValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new True()); } public function testTrueIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(true, new True()); } public function testFalseIsInvalid() { $constraint = new True(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( )); $this->validator->validate(false, $constraint); } } PK!|++Wtest/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gifnu[GIF89a! ,L ;PK!J++Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gifnu[GIF89a! ,L ;PK!Ѝ!!Ntest/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gifnu[GIF89a,;PK!)mRTtest/Validator/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\LengthValidator; class LengthValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new LengthValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Length(6)); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Length(6)); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Length(5)); } public function getThreeOrLessCharacters() { return array( array(12), array('12'), array('üü', true), array('éé', true), array(123), array('123'), array('üüü', true), array('ééé', true), ); } public function getFourCharacters() { return array( array(1234), array('1234'), array('üüüü', true), array('éééé', true), ); } public function getNotFourCharacters() { return array_merge( $this->getThreeOrLessCharacters(), $this->getFiveOrMoreCharacters() ); } public function getFiveOrMoreCharacters() { return array( array(12345), array('12345'), array('üüüüü', true), array('ééééé', true), array(123456), array('123456'), array('üüüüüü', true), array('éééééé', true), ); } /** * @dataProvider getFiveOrMoreCharacters */ public function testValidValuesMin($value, $mbOnly = false) { if ($mbOnly && !function_exists('mb_strlen')) { $this->markTestSkipped('mb_strlen does not exist'); } $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Length(array('min' => 5)); $this->validator->validate($value, $constraint); } /** * @dataProvider getThreeOrLessCharacters */ public function testValidValuesMax($value, $mbOnly = false) { if ($mbOnly && !function_exists('mb_strlen')) { $this->markTestSkipped('mb_strlen does not exist'); } $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Length(array('max' => 3)); $this->validator->validate($value, $constraint); } /** * @dataProvider getFourCharacters */ public function testValidValuesExact($value, $mbOnly = false) { if ($mbOnly && !function_exists('mb_strlen')) { $this->markTestSkipped('mb_strlen does not exist'); } $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Length(4); $this->validator->validate($value, $constraint); } /** * @dataProvider getThreeOrLessCharacters */ public function testInvalidValuesMin($value, $mbOnly = false) { if ($mbOnly && !function_exists('mb_strlen')) { $this->markTestSkipped('mb_strlen does not exist'); } $constraint = new Length(array( 'min' => 4, 'minMessage' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', $this->identicalTo(array( '{{ value }}' => (string) $value, '{{ limit }}' => 4, )), $this->identicalTo($value), 4); $this->validator->validate($value, $constraint); } /** * @dataProvider getFiveOrMoreCharacters */ public function testInvalidValuesMax($value, $mbOnly = false) { if ($mbOnly && !function_exists('mb_strlen')) { $this->markTestSkipped('mb_strlen does not exist'); } $constraint = new Length(array( 'max' => 4, 'maxMessage' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', $this->identicalTo(array( '{{ value }}' => (string) $value, '{{ limit }}' => 4, )), $this->identicalTo($value), 4); $this->validator->validate($value, $constraint); } /** * @dataProvider getNotFourCharacters */ public function testInvalidValuesExact($value, $mbOnly = false) { if ($mbOnly && !function_exists('mb_strlen')) { $this->markTestSkipped('mb_strlen does not exist'); } $constraint = new Length(array( 'min' => 4, 'max' => 4, 'exactMessage' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', $this->identicalTo(array( '{{ value }}' => (string) $value, '{{ limit }}' => 4, )), $this->identicalTo($value), 4); $this->validator->validate($value, $constraint); } public function testConstraintGetDefaultOption() { $constraint = new Length(5); $this->assertEquals(5, $constraint->min); $this->assertEquals(5, $constraint->max); } } PK!̈́ Ttest/Validator/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\Validator\Constraints\Locale; use Symfony\Component\Validator\Constraints\LocaleValidator; class LocaleValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { IntlTestHelper::requireIntl($this); $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new LocaleValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Locale()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Locale()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Locale()); } /** * @dataProvider getValidLocales */ public function testValidLocales($locale) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($locale, new Locale()); } public function getValidLocales() { return array( array('en'), array('en_US'), array('pt'), array('pt_PT'), array('zh_Hans'), ); } /** * @dataProvider getInvalidLocales */ public function testInvalidLocales($locale) { $constraint = new Locale(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $locale, )); $this->validator->validate($locale, $constraint); } public function getInvalidLocales() { return array( array('EN'), array('foobar'), ); } } PK!sVVXtest/Validator/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\NotEqualTo; use Symfony\Component\Validator\Constraints\NotEqualToValidator; /** * @author Daniel Holmes */ class NotEqualToValidatorTest extends AbstractComparisonValidatorTestCase { protected function createValidator() { return new NotEqualToValidator(); } protected function createConstraint(array $options) { return new NotEqualTo($options); } /** * {@inheritDoc} */ public function provideValidComparisons() { return array( array(1, 2), array('22', '333'), array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01')), array(new ComparisonTest_Class(6), new ComparisonTest_Class(5)), array(null, 1), ); } /** * {@inheritDoc} */ public function provideInvalidComparisons() { return array( array(3, 3, '3', 'integer'), array('2', 2, '2', 'integer'), array('a', 'a', "'a'", 'string'), array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'), array(new ComparisonTest_Class(5), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'), ); } } PK!8w w Stest/Validator/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\EmailValidator; class EmailValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new EmailValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Email()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Email()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Email()); } /** * @dataProvider getValidEmails */ public function testValidEmails($email) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($email, new Email()); } public function getValidEmails() { return array( array('fabien@symfony.com'), array('example@example.co.uk'), array('fabien_potencier@example.fr'), ); } /** * @dataProvider getInvalidEmails */ public function testInvalidEmails($email) { $constraint = new Email(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $email, )); $this->validator->validate($email, $constraint); } public function getInvalidEmails() { return array( array('example'), array('example@'), array('example@localhost'), array('example@example.com@example.com'), ); } } PK! w88\test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; class CountValidatorCountableTest_Countable implements \Countable { private $content; public function __construct(array $content) { $this->content = $content; } public function count() { return count($this->content); } } /** * @author Bernhard Schussek */ class CountValidatorCountableTest extends CountValidatorTest { protected function createCollection(array $content) { return new CountValidatorCountableTest_Countable($content); } } PK!];XwwStest/Validator/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Blank; use Symfony\Component\Validator\Constraints\BlankValidator; class BlankValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new BlankValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Blank()); } public function testBlankIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Blank()); } /** * @dataProvider getInvalidValues */ public function testInvalidValues($value) { $constraint = new Blank(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $value, )); $this->validator->validate($value, $constraint); } public function getInvalidValues() { return array( array('foobar'), array(0), array(false), array(1234), ); } } PK!3ê dtest/Validator/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\AbstractComparisonValidator; class ComparisonTest_Class { protected $value; public function __construct($value) { $this->value = $value; } public function __toString() { return (string) $this->value; } } /** * @author Daniel Holmes */ abstract class AbstractComparisonValidatorTestCase extends \PHPUnit_Framework_TestCase { private $validator; private $context; protected function setUp() { $this->validator = $this->createValidator(); $this->context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext') ->disableOriginalConstructor() ->getMock(); $this->validator->initialize($this->context); } /** * @return AbstractComparisonValidator */ abstract protected function createValidator(); public function testThrowsConstraintExceptionIfNoValueOrProperty() { $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); $comparison = $this->createConstraint(array()); $this->validator->validate('some value', $comparison); } /** * @dataProvider provideValidComparisons * @param mixed $dirtyValue * @param mixed $comparisonValue */ public function testValidComparisonToValue($dirtyValue, $comparisonValue) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = $this->createConstraint(array('value' => $comparisonValue)); $this->context->expects($this->any()) ->method('getPropertyPath') ->will($this->returnValue('property1')); $this->validator->validate($dirtyValue, $constraint); } /** * @return array */ abstract public function provideValidComparisons(); /** * @dataProvider provideInvalidComparisons * @param mixed $dirtyValue * @param mixed $comparedValue * @param mixed $comparedValueString * @param string $comparedValueType */ public function testInvalidComparisonToValue($dirtyValue, $comparedValue, $comparedValueString, $comparedValueType) { $constraint = $this->createConstraint(array('value' => $comparedValue)); $constraint->message = 'Constraint Message'; $this->context->expects($this->any()) ->method('getPropertyPath') ->will($this->returnValue('property1')); $this->context->expects($this->once()) ->method('addViolation') ->with('Constraint Message', array( '{{ value }}' => $comparedValueString, '{{ compared_value }}' => $comparedValueString, '{{ compared_value_type }}' => $comparedValueType )); $this->validator->validate($dirtyValue, $constraint); } /** * @return array */ abstract public function provideInvalidComparisons(); /** * @param array $options Options for the constraint * @return Constraint */ abstract protected function createConstraint(array $options); } PK!7aTtest/Validator/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Constraints\ChoiceValidator; function choice_callback() { return array('foo', 'bar'); } class ChoiceValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; public static function staticCallback() { return array('foo', 'bar'); } protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new ChoiceValidator(); $this->validator->initialize($this->context); $this->context->expects($this->any()) ->method('getClassName') ->will($this->returnValue(__CLASS__)); } protected function tearDown() { $this->context = null; $this->validator = null; } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectArrayIfMultipleIsTrue() { $constraint = new Choice(array( 'choices' => array('foo', 'bar'), 'multiple' => true, )); $this->validator->validate('asdf', $constraint); } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Choice(array('choices' => array('foo', 'bar')))); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testChoicesOrCallbackExpected() { $this->validator->validate('foobar', new Choice()); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testValidCallbackExpected() { $this->validator->validate('foobar', new Choice(array('callback' => 'abcd'))); } public function testValidChoiceArray() { $constraint = new Choice(array('choices' => array('foo', 'bar'))); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('bar', $constraint); } public function testValidChoiceCallbackFunction() { $constraint = new Choice(array('callback' => __NAMESPACE__.'\choice_callback')); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('bar', $constraint); } public function testValidChoiceCallbackClosure() { $constraint = new Choice(array('callback' => function () { return array('foo', 'bar'); })); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('bar', $constraint); } public function testValidChoiceCallbackStaticMethod() { $constraint = new Choice(array('callback' => array(__CLASS__, 'staticCallback'))); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('bar', $constraint); } public function testValidChoiceCallbackContextMethod() { $constraint = new Choice(array('callback' => 'staticCallback')); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('bar', $constraint); } public function testMultipleChoices() { $constraint = new Choice(array( 'choices' => array('foo', 'bar', 'baz'), 'multiple' => true, )); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(array('baz', 'bar'), $constraint); } public function testInvalidChoice() { $constraint = new Choice(array( 'choices' => array('foo', 'bar'), 'message' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => 'baz', ), null, null); $this->validator->validate('baz', $constraint); } public function testInvalidChoiceMultiple() { $constraint = new Choice(array( 'choices' => array('foo', 'bar'), 'multipleMessage' => 'myMessage', 'multiple' => true, )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => 'baz', )); $this->validator->validate(array('foo', 'baz'), $constraint); } public function testTooFewChoices() { $constraint = new Choice(array( 'choices' => array('foo', 'bar', 'moo', 'maa'), 'multiple' => true, 'min' => 2, 'minMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ limit }}' => 2, ), null, 2); $this->validator->validate(array('foo'), $constraint); } public function testTooManyChoices() { $constraint = new Choice(array( 'choices' => array('foo', 'bar', 'moo', 'maa'), 'multiple' => true, 'max' => 2, 'maxMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ limit }}' => 2, ), null, 2); $this->validator->validate(array('foo', 'bar', 'moo'), $constraint); } public function testNonStrict() { $constraint = new Choice(array( 'choices' => array(1, 2), 'strict' => false, )); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('2', $constraint); $this->validator->validate(2, $constraint); } public function testStrictAllowsExactValue() { $constraint = new Choice(array( 'choices' => array(1, 2), 'strict' => true, )); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(2, $constraint); } public function testStrictDisallowsDifferentType() { $constraint = new Choice(array( 'choices' => array(1, 2), 'strict' => true, 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => '2', )); $this->validator->validate('2', $constraint); } public function testNonStrictWithMultipleChoices() { $constraint = new Choice(array( 'choices' => array(1, 2, 3), 'multiple' => true, 'strict' => false )); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(array('2', 3), $constraint); } public function testStrictWithMultipleChoices() { $constraint = new Choice(array( 'choices' => array(1, 2, 3), 'multiple' => true, 'strict' => true, 'multipleMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => '3', )); $this->validator->validate(array(2, '3'), $constraint); } } PK!2((Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\File; use Symfony\Component\Validator\Constraints\FileValidator; use Symfony\Component\HttpFoundation\File\UploadedFile; abstract class FileValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected $path; protected $file; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new FileValidator(); $this->validator->initialize($this->context); $this->path = sys_get_temp_dir().DIRECTORY_SEPARATOR.'FileValidatorTest'; $this->file = fopen($this->path, 'w'); } protected function tearDown() { fclose($this->file); $this->context = null; $this->validator = null; $this->path = null; $this->file = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new File()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new File()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleTypeOrFile() { $this->validator->validate(new \stdClass(), new File()); } public function testValidFile() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($this->path, new File()); } public function testValidUploadedfile() { $this->context->expects($this->never()) ->method('addViolation'); $file = new UploadedFile($this->path, 'originalName', null, null, null, true); $this->validator->validate($file, new File()); } public function testTooLargeBytes() { fwrite($this->file, str_repeat('0', 11)); $constraint = new File(array( 'maxSize' => 10, 'maxSizeMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ limit }}' => '10', '{{ size }}' => '11', '{{ suffix }}' => 'bytes', '{{ file }}' => $this->path, )); $this->validator->validate($this->getFile($this->path), $constraint); } public function testTooLargeKiloBytes() { fwrite($this->file, str_repeat('0', 1400)); $constraint = new File(array( 'maxSize' => '1k', 'maxSizeMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ limit }}' => '1', '{{ size }}' => '1.4', '{{ suffix }}' => 'kB', '{{ file }}' => $this->path, )); $this->validator->validate($this->getFile($this->path), $constraint); } public function testTooLargeMegaBytes() { fwrite($this->file, str_repeat('0', 1400000)); $constraint = new File(array( 'maxSize' => '1M', 'maxSizeMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ limit }}' => '1', '{{ size }}' => '1.4', '{{ suffix }}' => 'MB', '{{ file }}' => $this->path, )); $this->validator->validate($this->getFile($this->path), $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testInvalidMaxSize() { $constraint = new File(array( 'maxSize' => '1abc', )); $this->validator->validate($this->path, $constraint); } public function testValidMimeType() { $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\File') ->disableOriginalConstructor() ->getMock() ; $file ->expects($this->once()) ->method('getPathname') ->will($this->returnValue($this->path)) ; $file ->expects($this->once()) ->method('getMimeType') ->will($this->returnValue('image/jpg')) ; $this->context->expects($this->never()) ->method('addViolation'); $constraint = new File(array( 'mimeTypes' => array('image/png', 'image/jpg'), )); $this->validator->validate($file, $constraint); } public function testValidWildcardMimeType() { $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\File') ->disableOriginalConstructor() ->getMock() ; $file ->expects($this->once()) ->method('getPathname') ->will($this->returnValue($this->path)) ; $file ->expects($this->once()) ->method('getMimeType') ->will($this->returnValue('image/jpg')) ; $this->context->expects($this->never()) ->method('addViolation'); $constraint = new File(array( 'mimeTypes' => array('image/*'), )); $this->validator->validate($file, $constraint); } public function testInvalidMimeType() { $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\File') ->disableOriginalConstructor() ->getMock() ; $file ->expects($this->once()) ->method('getPathname') ->will($this->returnValue($this->path)) ; $file ->expects($this->once()) ->method('getMimeType') ->will($this->returnValue('application/pdf')) ; $constraint = new File(array( 'mimeTypes' => array('image/png', 'image/jpg'), 'mimeTypesMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ type }}' => '"application/pdf"', '{{ types }}' => '"image/png", "image/jpg"', '{{ file }}' => $this->path, )); $this->validator->validate($file, $constraint); } public function testInvalidWildcardMimeType() { $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\File') ->disableOriginalConstructor() ->getMock() ; $file ->expects($this->once()) ->method('getPathname') ->will($this->returnValue($this->path)) ; $file ->expects($this->once()) ->method('getMimeType') ->will($this->returnValue('application/pdf')) ; $constraint = new File(array( 'mimeTypes' => array('image/*', 'image/jpg'), 'mimeTypesMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ type }}' => '"application/pdf"', '{{ types }}' => '"image/*", "image/jpg"', '{{ file }}' => $this->path, )); $this->validator->validate($file, $constraint); } /** * @dataProvider uploadedFileErrorProvider */ public function testUploadedFileError($error, $message, array $params = array(), $maxSize = null) { $file = new UploadedFile('/path/to/file', 'originalName', 'mime', 0, $error); $constraint = new File(array( $message => 'myMessage', 'maxSize' => $maxSize )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', $params); $this->validator->validate($file, $constraint); } public function uploadedFileErrorProvider() { $tests = array( array(UPLOAD_ERR_FORM_SIZE, 'uploadFormSizeErrorMessage'), array(UPLOAD_ERR_PARTIAL, 'uploadPartialErrorMessage'), array(UPLOAD_ERR_NO_FILE, 'uploadNoFileErrorMessage'), array(UPLOAD_ERR_NO_TMP_DIR, 'uploadNoTmpDirErrorMessage'), array(UPLOAD_ERR_CANT_WRITE, 'uploadCantWriteErrorMessage'), array(UPLOAD_ERR_EXTENSION, 'uploadExtensionErrorMessage'), ); if (class_exists('Symfony\Component\HttpFoundation\File\UploadedFile')) { // when no maxSize is specified on constraint, it should use the ini value $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array( '{{ limit }}' => UploadedFile::getMaxFilesize(), '{{ suffix }}' => 'bytes', )); // it should use the smaller limitation (maxSize option in this case) $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array( '{{ limit }}' => 1, '{{ suffix }}' => 'bytes', ), '1'); // it correctly parses the maxSize option and not only uses simple string comparison // 1000M should be bigger than the ini value $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array( '{{ limit }}' => UploadedFile::getMaxFilesize(), '{{ suffix }}' => 'bytes', ), '1000M'); } return $tests; } abstract protected function getFile($filename); } PK!Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\CardScheme; use Symfony\Component\Validator\Constraints\CardSchemeValidator; class CardSchemeValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new CardSchemeValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new CardScheme(array('schemes' => array()))); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new CardScheme(array('schemes' => array()))); } /** * @dataProvider getValidNumbers */ public function testValidNumbers($scheme, $number) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($number, new CardScheme(array('schemes' => $scheme))); } /** * @dataProvider getInvalidNumbers */ public function testInvalidNumbers($scheme, $number) { $this->context->expects($this->once()) ->method('addViolation'); $this->validator->validate($number, new CardScheme(array('schemes' => $scheme))); } public function getValidNumbers() { return array( array('AMEX', '378282246310005'), array('AMEX', '371449635398431'), array('AMEX', '378734493671000'), array('AMEX', '347298508610146'), array('CHINA_UNIONPAY', '6228888888888888'), array('CHINA_UNIONPAY', '62288888888888888'), array('CHINA_UNIONPAY', '622888888888888888'), array('CHINA_UNIONPAY', '6228888888888888888'), array('DINERS', '30569309025904'), array('DINERS', '36088894118515'), array('DINERS', '38520000023237'), array('DISCOVER', '6011111111111117'), array('DISCOVER', '6011000990139424'), array('INSTAPAYMENT', '6372476031350068'), array('INSTAPAYMENT', '6385537775789749'), array('INSTAPAYMENT', '6393440808445746'), array('JCB', '3530111333300000'), array('JCB', '3566002020360505'), array('JCB', '213112345678901'), array('JCB', '180012345678901'), array('LASER', '6304678107004080'), array('LASER', '6706440607428128629'), array('LASER', '6771656738314582216'), array('MAESTRO', '6759744069209'), array('MAESTRO', '5020507657408074712'), array('MAESTRO', '6759744069209'), array('MAESTRO', '6759744069209'), array('MASTERCARD', '5555555555554444'), array('MASTERCARD', '5105105105105100'), array('VISA', '4111111111111111'), array('VISA', '4012888888881881'), array('VISA', '4222222222222'), array(array('AMEX', 'VISA'), '4111111111111111'), array(array('AMEX', 'VISA'), '378282246310005'), array(array('JCB', 'MASTERCARD'), '5105105105105100'), array(array('VISA', 'MASTERCARD'), '5105105105105100'), ); } public function getInvalidNumbers() { return array( array('VISA', '42424242424242424242'), array('AMEX', '357298508610146'), array('DINERS', '31569309025904'), array('DINERS', '37088894118515'), array('INSTAPAYMENT', '6313440808445746'), array('CHINA_UNIONPAY', '622888888888888'), array('CHINA_UNIONPAY', '62288888888888888888'), array('AMEX', '30569309025904'), // DINERS number array('AMEX', 'invalid'), // A string array('AMEX', 0), // a lone number array('AMEX', '0'), // a lone number array('AMEX', '000000000000'), // a lone number array('DINERS', '3056930'), // only first part of the number array('DISCOVER', '1117'), // only last 4 digits ); } } PK!{r>KRtest/Validator/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Isbn; use Symfony\Component\Validator\Constraints\IsbnValidator; /** * @see https://en.wikipedia.org/wiki/Isbn */ class IsbnValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; public function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new IsbnValidator(); $this->validator->initialize($this->context); } public function getValidIsbn10() { return array( array('2723442284'), array('2723442276'), array('2723455041'), array('2070546810'), array('2711858839'), array('2756406767'), array('2870971648'), array('226623854X'), array('2851806424'), array('0321812700'), array('0-45122-5244'), array('0-4712-92311'), ); } public function getInvalidIsbn10() { return array( array('1234567890'), array('987'), array('0987656789'), array(0), array('7-35622-5444'), array('0-4X19-92611'), array('0_45122_5244'), array('2870#971#648'), ); } public function getValidIsbn13() { return array( array('978-2723442282'), array('978-2723442275'), array('978-2723455046'), array('978-2070546817'), array('978-2711858835'), array('978-2756406763'), array('978-2870971642'), array('978-2266238540'), array('978-2851806420'), array('978-0321812704'), array('978-0451225245'), array('978-0471292319'), ); } public function getInvalidIsbn13() { return array( array('1234567890'), array('987'), array('0987656789'), array(0), array('0-4X19-9261981'), array('978-0321513774'), array('979-0431225385'), array('980-0474292319'), array('978_0451225245'), array('978#0471292319'), ); } public function getValidIsbn() { return array_merge( $this->getValidIsbn10(), $this->getValidIsbn13() ); } public function getInvalidIsbn() { return array_merge( $this->getInvalidIsbn10(), $this->getInvalidIsbn13() ); } public function testNullIsValid() { $constraint = new Isbn(true); $this->context ->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, $constraint); } public function testEmptyStringIsValid() { $constraint = new Isbn(true); $this->context ->expects($this->never()) ->method('addViolation'); $this->validator->validate('', $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $constraint = new Isbn(true); $this->validator->validate(new \stdClass(), $constraint); } /** * @dataProvider getValidIsbn10 */ public function testValidIsbn10($isbn) { $constraint = new Isbn(array('isbn10' => true)); $this->context ->expects($this->never()) ->method('addViolation'); $this->validator->validate($isbn, $constraint); } /** * @dataProvider getInvalidIsbn10 */ public function testInvalidIsbn10($isbn) { $constraint = new Isbn(array('isbn10' => true)); $this->context ->expects($this->once()) ->method('addViolation') ->with($constraint->isbn10Message); $this->validator->validate($isbn, $constraint); } /** * @dataProvider getValidIsbn13 */ public function testValidIsbn13($isbn) { $constraint = new Isbn(array('isbn13' => true)); $this->context ->expects($this->never()) ->method('addViolation'); $this->validator->validate($isbn, $constraint); } /** * @dataProvider getInvalidIsbn13 */ public function testInvalidIsbn13($isbn) { $constraint = new Isbn(array('isbn13' => true)); $this->context ->expects($this->once()) ->method('addViolation') ->with($constraint->isbn13Message); $this->validator->validate($isbn, $constraint); } /** * @dataProvider getValidIsbn */ public function testValidIsbn($isbn) { $constraint = new Isbn(array('isbn10' => true, 'isbn13' => true)); $this->context ->expects($this->never()) ->method('addViolation'); $this->validator->validate($isbn, $constraint); } /** * @dataProvider getInvalidIsbn */ public function testInvalidIsbn($isbn) { $constraint = new Isbn(array('isbn10' => true, 'isbn13' => true)); $this->context ->expects($this->once()) ->method('addViolation') ->with($constraint->bothIsbnMessage); $this->validator->validate($isbn, $constraint); } } PK!jTL99Utest/Validator/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\EqualTo; use Symfony\Component\Validator\Constraints\EqualToValidator; /** * @author Daniel Holmes */ class EqualToValidatorTest extends AbstractComparisonValidatorTestCase { protected function createValidator() { return new EqualToValidator(); } protected function createConstraint(array $options) { return new EqualTo($options); } /** * {@inheritDoc} */ public function provideValidComparisons() { return array( array(3, 3), array(3, '3'), array('a', 'a'), array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')), array(new ComparisonTest_Class(5), new ComparisonTest_Class(5)), array(null, 1), ); } /** * {@inheritDoc} */ public function provideInvalidComparisons() { return array( array(1, 2, '2', 'integer'), array('22', '333', "'333'", 'string'), array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'), array(new ComparisonTest_Class(4), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'), ); } } PK!$&Ytest/Validator/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\IdenticalTo; use Symfony\Component\Validator\Constraints\IdenticalToValidator; /** * @author Daniel Holmes */ class IdenticalToValidatorTest extends AbstractComparisonValidatorTestCase { protected function createValidator() { return new IdenticalToValidator(); } protected function createConstraint(array $options) { return new IdenticalTo($options); } /** * {@inheritDoc} */ public function provideValidComparisons() { $date = new \DateTime('2000-01-01'); $object = new ComparisonTest_Class(2); return array( array(3, 3), array('a', 'a'), array($date, $date), array($object, $object), array(null, 1), ); } /** * {@inheritDoc} */ public function provideInvalidComparisons() { return array( array(1, 2, '2', 'integer'), array(2, '2', "'2'", 'string'), array('22', '333', "'333'", 'string'), array(new \DateTime('2001-01-01'), new \DateTime('2001-01-01'), '2001-01-01 00:00:00', 'DateTime'), array(new \DateTime('2001-01-01'), new \DateTime('1999-01-01'), '1999-01-01 00:00:00', 'DateTime'), array(new ComparisonTest_Class(4), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'), ); } } PK!|=ctest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; class CollectionValidatorArrayObjectTest extends CollectionValidatorTest { public function prepareTestData(array $contents) { return new \ArrayObject($contents); } } PK!z0 Utest/Validator/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\Validator\Constraints\Country; use Symfony\Component\Validator\Constraints\CountryValidator; class CountryValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { IntlTestHelper::requireIntl($this); $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new CountryValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Country()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Country()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Country()); } /** * @dataProvider getValidCountries */ public function testValidCountries($country) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($country, new Country()); } public function getValidCountries() { return array( array('GB'), array('AT'), array('MY'), ); } /** * @dataProvider getInvalidCountries */ public function testInvalidCountries($country) { $constraint = new Country(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $country, )); $this->validator->validate($country, $constraint); } public function getInvalidCountries() { return array( array('foobar'), array('EN'), ); } public function testValidateUsingCountrySpecificLocale() { \Locale::setDefault('en_GB'); $existingCountry = 'GB'; $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($existingCountry, new Country()); } } PK!rZcc\test/Validator/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\NotIdenticalTo; use Symfony\Component\Validator\Constraints\NotIdenticalToValidator; /** * @author Daniel Holmes */ class NotIdenticalToValidatorTest extends AbstractComparisonValidatorTestCase { protected function createValidator() { return new NotIdenticalToValidator(); } protected function createConstraint(array $options) { return new NotIdenticalTo($options); } /** * {@inheritDoc} */ public function provideValidComparisons() { return array( array(1, 2), array('2', 2), array('22', '333'), array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01')), array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')), array(null, 1), ); } /** * {@inheritDoc} */ public function provideInvalidComparisons() { $date = new \DateTime('2000-01-01'); $object = new ComparisonTest_Class(2); return array( array(3, 3, '3', 'integer'), array('a', 'a', "'a'", 'string'), array($date, $date, '2000-01-01 00:00:00', 'DateTime'), array($object, $object, '2', __NAMESPACE__.'\ComparisonTest_Class'), ); } } PK!CNNQtest/Validator/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Url; use Symfony\Component\Validator\Constraints\UrlValidator; class UrlValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new UrlValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Url()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Url()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Url()); } /** * @dataProvider getValidUrls */ public function testValidUrls($url) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($url, new Url()); } public function getValidUrls() { return array( array('http://a.pl'), array('http://www.google.com'), array('http://www.google.museum'), array('https://google.com/'), array('https://google.com:80/'), array('http://www.example.coop/'), array('http://www.test-example.com/'), array('http://www.symfony.com/'), array('http://symfony.fake/blog/'), array('http://symfony.com/?'), array('http://symfony.com/search?type=&q=url+validator'), array('http://symfony.com/#'), array('http://symfony.com/#?'), array('http://www.symfony.com/doc/current/book/validation.html#supported-constraints'), array('http://very.long.domain.name.com/'), array('http://127.0.0.1/'), array('http://127.0.0.1:80/'), array('http://[::1]/'), array('http://[::1]:80/'), array('http://[1:2:3::4:5:6:7]/'), array('http://sãopaulo.com/'), array('http://xn--sopaulo-xwa.com/'), array('http://sãopaulo.com.br/'), array('http://xn--sopaulo-xwa.com.br/'), array('http://пример.испытание/'), array('http://xn--e1afmkfd.xn--80akhbyknj4f/'), array('http://مثال.إختبار/'), array('http://xn--mgbh0fb.xn--kgbechtv/'), array('http://例子.测试/'), array('http://xn--fsqu00a.xn--0zwm56d/'), array('http://例子.測試/'), array('http://xn--fsqu00a.xn--g6w251d/'), array('http://例え.テスト/'), array('http://xn--r8jz45g.xn--zckzah/'), array('http://مثال.آزمایشی/'), array('http://xn--mgbh0fb.xn--hgbk6aj7f53bba/'), array('http://실례.테스트/'), array('http://xn--9n2bp8q.xn--9t4b11yi5a/'), array('http://العربية.idn.icann.org/'), array('http://xn--ogb.idn.icann.org/'), array('http://xn--e1afmkfd.xn--80akhbyknj4f.xn--e1afmkfd/'), array('http://xn--espaa-rta.xn--ca-ol-fsay5a/'), array('http://xn--d1abbgf6aiiy.xn--p1ai/'), array('http://☎.com/'), ); } /** * @dataProvider getInvalidUrls */ public function testInvalidUrls($url) { $constraint = new Url(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $url, )); $this->validator->validate($url, $constraint); } public function getInvalidUrls() { return array( array('google.com'), array('://google.com'), array('http ://google.com'), array('http:/google.com'), array('http://goog_le.com'), array('http://google.com::aa'), array('http://google.com:aa'), array('http://symfony.com?'), array('http://symfony.com#'), array('ftp://google.fr'), array('faked://google.fr'), array('http://127.0.0.1:aa/'), array('ftp://[::1]/'), array('http://[::1'), ); } /** * @dataProvider getValidCustomUrls */ public function testCustomProtocolIsValid($url) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Url(array( 'protocols' => array('ftp', 'file', 'git') )); $this->validator->validate($url, $constraint); } public function getValidCustomUrls() { return array( array('ftp://google.com'), array('file://127.0.0.1'), array('git://[::1]/'), ); } } PK!(3Jtest/Validator/Symfony/Component/Validator/Tests/Constraints/ValidTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Valid; /** * @author Bernhard Schussek */ class ValidTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testRejectGroupsOption() { new Valid(array('groups' => 'foo')); } } PK!A Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\Validator\Constraints\Currency; use Symfony\Component\Validator\Constraints\CurrencyValidator; class CurrencyValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { IntlTestHelper::requireIntl($this); $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new CurrencyValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Currency()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Currency()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Currency()); } /** * @dataProvider getValidCurrencies */ public function testValidCurrencies($currency) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($currency, new Currency()); } /** * @dataProvider getValidCurrencies **/ public function testValidCurrenciesWithCountrySpecificLocale($currency) { \Locale::setDefault('en_GB'); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($currency, new Currency()); } public function getValidCurrencies() { return array( array('EUR'), array('USD'), array('SIT'), array('AUD'), array('CAD'), ); } /** * @dataProvider getInvalidCurrencies */ public function testInvalidCurrencies($currency) { $constraint = new Currency(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $currency, )); $this->validator->validate($currency, $constraint); } public function getInvalidCurrencies() { return array( array('EN'), array('foobar'), ); } } PK!BHtest/Validator/Symfony/Component/Validator/Tests/Constraints/AllTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Valid; /** * @author Bernhard Schussek */ class AllTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testRejectNonConstraints() { new All(array( 'foo', )); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testRejectValidConstraint() { new All(array( new Valid(), )); } } PK!p)D D Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Luhn; use Symfony\Component\Validator\Constraints\LuhnValidator; class LuhnValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new LuhnValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Luhn()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Luhn()); } /** * @dataProvider getValidNumbers */ public function testValidNumbers($number) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($number, new Luhn()); } public function getValidNumbers() { return array( array('42424242424242424242'), array('378282246310005'), array('371449635398431'), array('378734493671000'), array('5610591081018250'), array('30569309025904'), array('38520000023237'), array('6011111111111117'), array('6011000990139424'), array('3530111333300000'), array('3566002020360505'), array('5555555555554444'), array('5105105105105100'), array('4111111111111111'), array('4012888888881881'), array('4222222222222'), array('5019717010103742'), array('6331101999990016'), ); } /** * @dataProvider getInvalidNumbers */ public function testInvalidNumbers($number) { $constraint = new Luhn(); $this->context->expects($this->once()) ->method('addViolation') ->with($constraint->message); $this->validator->validate($number, $constraint); } public function getInvalidNumbers() { return array( array('1234567812345678'), array('4222222222222222'), array('0000000000000000'), ); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException * @dataProvider getInvalidTypes */ public function testInvalidTypes($number) { $constraint = new Luhn(); $this->validator->validate($number, $constraint); } public function getInvalidTypes() { return array( array(0), array(123), array(42424242424242424242), array(378282246310005), array(371449635398431), ); } } PK!͸Stest/Validator/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\RangeValidator; class RangeValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new RangeValidator(); $this->validator->initialize($this->context); } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Range(array('min' => 10, 'max' => 20))); } public function getTenToTwenty() { return array( array(10.00001), array(19.99999), array('10.00001'), array('19.99999'), array(10), array(20), array(10.0), array(20.0), ); } public function getLessThanTen() { return array( array(9.99999), array('9.99999'), array(5), array(1.0), ); } public function getMoreThanTwenty() { return array( array(20.000001), array('20.000001'), array(21), array(30.0), ); } /** * @dataProvider getTenToTwenty */ public function testValidValuesMin($value) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Range(array('min' => 10)); $this->validator->validate($value, $constraint); } /** * @dataProvider getTenToTwenty */ public function testValidValuesMax($value) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Range(array('max' => 20)); $this->validator->validate($value, $constraint); } /** * @dataProvider getTenToTwenty */ public function testValidValuesMinMax($value) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Range(array('min' => 10, 'max' => 20)); $this->validator->validate($value, $constraint); } /** * @dataProvider getLessThanTen */ public function testInvalidValuesMin($value) { $constraint = new Range(array( 'min' => 10, 'minMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', $this->identicalTo(array( '{{ value }}' => $value, '{{ limit }}' => 10, ))); $this->validator->validate($value, $constraint); } /** * @dataProvider getMoreThanTwenty */ public function testInvalidValuesMax($value) { $constraint = new Range(array( 'max' => 20, 'maxMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', $this->identicalTo(array( '{{ value }}' => $value, '{{ limit }}' => 20, ))); $this->validator->validate($value, $constraint); } /** * @dataProvider getMoreThanTwenty */ public function testInvalidValuesCombinedMax($value) { $constraint = new Range(array( 'min' => 10, 'max' => 20, 'minMessage' => 'myMinMessage', 'maxMessage' => 'myMaxMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMaxMessage', $this->identicalTo(array( '{{ value }}' => $value, '{{ limit }}' => 20, ))); $this->validator->validate($value, $constraint); } /** * @dataProvider getLessThanTen */ public function testInvalidValuesCombinedMin($value) { $constraint = new Range(array( 'min' => 10, 'max' => 20, 'minMessage' => 'myMinMessage', 'maxMessage' => 'myMaxMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMinMessage', $this->identicalTo(array( '{{ value }}' => $value, '{{ limit }}' => 10, ))); $this->validator->validate($value, $constraint); } public function getInvalidValues() { return array( array(9.999999), array(20.000001), array('9.999999'), array('20.000001'), array(new \stdClass()), ); } public function testMinMessageIsSet() { $constraint = new Range(array( 'min' => 10, 'max' => 20, 'minMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => 9, '{{ limit }}' => 10, )); $this->validator->validate(9, $constraint); } public function testMaxMessageIsSet() { $constraint = new Range(array( 'min' => 10, 'max' => 20, 'maxMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => 21, '{{ limit }}' => 20, )); $this->validator->validate(21, $constraint); } } PK!Qs(s(Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\ExecutionContext; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\CallbackValidator; class CallbackValidatorTest_Class { public static function validateCallback($object, ExecutionContext $context) { $context->addViolation('Callback message', array('{{ value }}' => 'foobar'), 'invalidValue'); return false; } } class CallbackValidatorTest_Object { public function validate(ExecutionContext $context) { $context->addViolation('My message', array('{{ value }}' => 'foobar'), 'invalidValue'); return false; } public static function validateStatic($object, ExecutionContext $context) { $context->addViolation('Static message', array('{{ value }}' => 'baz'), 'otherInvalidValue'); return false; } } class CallbackValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new CallbackValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Callback(array('foo'))); } public function testSingleMethod() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback('validate'); $this->context->expects($this->once()) ->method('addViolation') ->with('My message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } public function testSingleMethodExplicitName() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array('callback' => 'validate')); $this->context->expects($this->once()) ->method('addViolation') ->with('My message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } public function testSingleStaticMethod() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback('validateStatic'); $this->context->expects($this->once()) ->method('addViolation') ->with('Static message', array( '{{ value }}' => 'baz', )); $this->validator->validate($object, $constraint); } public function testClosure() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(function ($object, ExecutionContext $context) { $context->addViolation('My message', array('{{ value }}' => 'foobar'), 'invalidValue'); return false; }); $this->context->expects($this->once()) ->method('addViolation') ->with('My message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } public function testClosureExplicitName() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array( 'callback' => function ($object, ExecutionContext $context) { $context->addViolation('My message', array('{{ value }}' => 'foobar'), 'invalidValue'); return false; }, )); $this->context->expects($this->once()) ->method('addViolation') ->with('My message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } public function testArrayCallable() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array(__CLASS__.'_Class', 'validateCallback')); $this->context->expects($this->once()) ->method('addViolation') ->with('Callback message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } public function testArrayCallableExplicitName() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array( 'callback' => array(__CLASS__.'_Class', 'validateCallback'), )); $this->context->expects($this->once()) ->method('addViolation') ->with('Callback message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } // BC with Symfony < 2.4 public function testSingleMethodBc() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array('validate')); $this->context->expects($this->once()) ->method('addViolation') ->with('My message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } // BC with Symfony < 2.4 public function testSingleMethodBcExplicitName() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array('methods' => array('validate'))); $this->context->expects($this->once()) ->method('addViolation') ->with('My message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } // BC with Symfony < 2.4 public function testMultipleMethodsBc() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array('validate', 'validateStatic')); $this->context->expects($this->at(0)) ->method('addViolation') ->with('My message', array( '{{ value }}' => 'foobar', )); $this->context->expects($this->at(1)) ->method('addViolation') ->with('Static message', array( '{{ value }}' => 'baz', )); $this->validator->validate($object, $constraint); } // BC with Symfony < 2.4 public function testMultipleMethodsBcExplicitName() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array( 'methods' => array('validate', 'validateStatic'), )); $this->context->expects($this->at(0)) ->method('addViolation') ->with('My message', array( '{{ value }}' => 'foobar', )); $this->context->expects($this->at(1)) ->method('addViolation') ->with('Static message', array( '{{ value }}' => 'baz', )); $this->validator->validate($object, $constraint); } // BC with Symfony < 2.4 public function testSingleStaticMethodBc() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array( array(__CLASS__.'_Class', 'validateCallback') )); $this->context->expects($this->once()) ->method('addViolation') ->with('Callback message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } // BC with Symfony < 2.4 public function testSingleStaticMethodBcExplicitName() { $object = new CallbackValidatorTest_Object(); $constraint = new Callback(array( 'methods' => array(array(__CLASS__.'_Class', 'validateCallback')), )); $this->context->expects($this->once()) ->method('addViolation') ->with('Callback message', array( '{{ value }}' => 'foobar', )); $this->validator->validate($object, $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testExpectValidMethods() { $object = new CallbackValidatorTest_Object(); $this->validator->validate($object, new Callback(array('foobar'))); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testExpectValidCallbacks() { $object = new CallbackValidatorTest_Object(); $this->validator->validate($object, new Callback(array(array('foo', 'bar')))); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testExpectEitherCallbackOrMethods() { $object = new CallbackValidatorTest_Object(); $this->validator->validate($object, new Callback(array( 'callback' => 'validate', 'methods' => array('validateStatic'), ))); } public function testConstraintGetTargets() { $constraint = new Callback(array('foo')); $this->assertEquals('class', $constraint->getTargets()); } // Should succeed. Needed when defining constraints as annotations. public function testNoConstructorArguments() { new Callback(); } public function testAnnotationInvocationSingleValued() { $constraint = new Callback(array('value' => 'validateStatic')); $this->assertEquals(new Callback('validateStatic'), $constraint); } public function testAnnotationInvocationMultiValued() { $constraint = new Callback(array('value' => array(__CLASS__.'_Class', 'validateCallback'))); $this->assertEquals(new Callback(array(__CLASS__.'_Class', 'validateCallback')), $constraint); } } PK!@*VH H Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Date; use Symfony\Component\Validator\Constraints\DateValidator; class DateValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new DateValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Date()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Date()); } public function testDateTimeClassIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(new \DateTime(), new Date()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Date()); } /** * @dataProvider getValidDates */ public function testValidDates($date) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($date, new Date()); } public function getValidDates() { return array( array('2010-01-01'), array('1955-12-12'), array('2030-05-31'), ); } /** * @dataProvider getInvalidDates */ public function testInvalidDates($date) { $constraint = new Date(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $date, )); $this->validator->validate($date, $constraint); } public function getInvalidDates() { return array( array('foobar'), array('foobar 2010-13-01'), array('2010-13-01 foobar'), array('2010-13-01'), array('2010-04-32'), array('2010-02-29'), ); } } PK! BT T Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Time; use Symfony\Component\Validator\Constraints\TimeValidator; class TimeValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new TimeValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Time()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Time()); } public function testDateTimeClassIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(new \DateTime(), new Time()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Time()); } /** * @dataProvider getValidTimes */ public function testValidTimes($time) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($time, new Time()); } public function getValidTimes() { return array( array('01:02:03'), array('00:00:00'), array('23:59:59'), ); } /** * @dataProvider getInvalidTimes */ public function testInvalidTimes($time) { $constraint = new Time(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $time, )); $this->validator->validate($time, $constraint); } public function getInvalidTimes() { return array( array('foobar'), array('foobar 12:34:56'), array('12:34:56 foobar'), array('00:00'), array('24:00:00'), array('00:60:00'), array('00:00:60'), ); } } PK!iKKStest/Validator/Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\False; use Symfony\Component\Validator\Constraints\FalseValidator; class FalseValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new FalseValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new False()); } public function testFalseIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(false, new False()); } public function testTrueIsInvalid() { $constraint = new False(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array()); $this->validator->validate(true, $constraint); } } PK!ϏRXtest/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; /** * @author Bernhard Schussek */ class CountValidatorArrayTest extends CountValidatorTest { protected function createCollection(array $content) { return $content; } } PK!qC Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\Validator\Constraints\Language; use Symfony\Component\Validator\Constraints\LanguageValidator; class LanguageValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { IntlTestHelper::requireIntl($this); $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new LanguageValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Language()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Language()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new Language()); } /** * @dataProvider getValidLanguages */ public function testValidLanguages($language) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($language, new Language()); } public function getValidLanguages() { return array( array('en'), array('en_US'), array('my'), ); } /** * @dataProvider getInvalidLanguages */ public function testInvalidLanguages($language) { $constraint = new Language(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $language, )); $this->validator->validate($language, $constraint); } public function getInvalidLanguages() { return array( array('EN'), array('foobar'), ); } public function testValidateUsingCountrySpecificLocale() { \Locale::setDefault('fr_FR'); $existingLanguage = 'en'; $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($existingLanguage, new Language(array( 'message' => 'aMessage' ))); } } PK!ֆStest/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Count; use Symfony\Component\Validator\Constraints\CountValidator; /** * @author Bernhard Schussek */ abstract class CountValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new CountValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } abstract protected function createCollection(array $content); public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Count(6)); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsCountableType() { $this->validator->validate(new \stdClass(), new Count(5)); } public function getThreeOrLessElements() { return array( array($this->createCollection(array(1))), array($this->createCollection(array(1, 2))), array($this->createCollection(array(1, 2, 3))), array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3))), ); } public function getFourElements() { return array( array($this->createCollection(array(1, 2, 3, 4))), array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4))), ); } public function getNotFourElements() { return array_merge( $this->getThreeOrLessElements(), $this->getFiveOrMoreElements() ); } public function getFiveOrMoreElements() { return array( array($this->createCollection(array(1, 2, 3, 4, 5))), array($this->createCollection(array(1, 2, 3, 4, 5, 6))), array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5))), ); } /** * @dataProvider getThreeOrLessElements */ public function testValidValuesMax($value) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Count(array('max' => 3)); $this->validator->validate($value, $constraint); } /** * @dataProvider getFiveOrMoreElements */ public function testValidValuesMin($value) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Count(array('min' => 5)); $this->validator->validate($value, $constraint); } /** * @dataProvider getFourElements */ public function testValidValuesExact($value) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Count(4); $this->validator->validate($value, $constraint); } /** * @dataProvider getFiveOrMoreElements */ public function testInvalidValuesMax($value) { $constraint = new Count(array( 'max' => 4, 'maxMessage' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', $this->identicalTo(array( '{{ count }}' => count($value), '{{ limit }}' => 4, )), $value, 4); $this->validator->validate($value, $constraint); } /** * @dataProvider getThreeOrLessElements */ public function testInvalidValuesMin($value) { $constraint = new Count(array( 'min' => 4, 'minMessage' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', $this->identicalTo(array( '{{ count }}' => count($value), '{{ limit }}' => 4, )), $value, 4); $this->validator->validate($value, $constraint); } /** * @dataProvider getNotFourElements */ public function testInvalidValuesExact($value) { $constraint = new Count(array( 'min' => 4, 'max' => 4, 'exactMessage' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', $this->identicalTo(array( '{{ count }}' => count($value), '{{ limit }}' => 4, )), $value, 4); $this->validator->validate($value, $constraint); } public function testDefaultOption() { $constraint = new Count(5); $this->assertEquals(5, $constraint->min); $this->assertEquals(5, $constraint->max); } } PK!LwwYtest/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\GreaterThan; use Symfony\Component\Validator\Constraints\GreaterThanValidator; /** * @author Daniel Holmes */ class GreaterThanValidatorTest extends AbstractComparisonValidatorTestCase { protected function createValidator() { return new GreaterThanValidator(); } protected function createConstraint(array $options) { return new GreaterThan($options); } /** * {@inheritDoc} */ public function provideValidComparisons() { return array( array(2, 1), array(new \DateTime('2005/01/01'), new \DateTime('2001/01/01')), array(new ComparisonTest_Class(5), new ComparisonTest_Class(4)), array('333', '22'), array(null, 1), ); } /** * {@inheritDoc} */ public function provideInvalidComparisons() { return array( array(1, 2, '2', 'integer'), array(2, 2, '2', 'integer'), array(new \DateTime('2000/01/01'), new \DateTime('2005/01/01'), '2005-01-01 00:00:00', 'DateTime'), array(new \DateTime('2000/01/01'), new \DateTime('2000/01/01'), '2000-01-01 00:00:00', 'DateTime'), array(new ComparisonTest_Class(4), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'), array(new ComparisonTest_Class(5), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'), array('22', '333', "'333'", 'string'), array('22', '22', "'22'", 'string') ); } } PK!kkVtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\File; class FileValidatorPathTest extends FileValidatorTest { protected function getFile($filename) { return $filename; } public function testFileNotFound() { $constraint = new File(array( 'notFoundMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ file }}' => 'foobar', )); $this->validator->validate('foobar', $constraint); } } PK!׫  `test/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; use Symfony\Component\Validator\Constraints\GreaterThanOrEqualValidator; /** * @author Daniel Holmes */ class GreaterThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCase { protected function createValidator() { return new GreaterThanOrEqualValidator(); } protected function createConstraint(array $options) { return new GreaterThanOrEqual($options); } /** * {@inheritDoc} */ public function provideValidComparisons() { return array( array(3, 2), array(1, 1), array(new \DateTime('2010/01/01'), new \DateTime('2000/01/01')), array(new \DateTime('2000/01/01'), new \DateTime('2000/01/01')), array('a', 'a'), array('z', 'a'), array(null, 1), ); } /** * {@inheritDoc} */ public function provideInvalidComparisons() { return array( array(1, 2, '2', 'integer'), array(new \DateTime('2000/01/01'), new \DateTime('2005/01/01'), '2005-01-01 00:00:00', 'DateTime'), array('b', 'c', "'c'", 'string') ); } } PK!W@ Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Iban; use Symfony\Component\Validator\Constraints\IbanValidator; class IbanValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new IbanValidator(); $this->validator->initialize($this->context); } public function testNullIsValid() { $this->context->expects($this->never())->method('addViolation'); $this->validator->validate(null, new Iban()); } public function testEmptyStringIsValid() { $this->context->expects($this->never())->method('addViolation'); $this->validator->validate('', new Iban()); } /** * @dataProvider getValidIbans */ public function testValidIbans($iban) { $this->context->expects($this->never())->method('addViolation'); $this->validator->validate($iban, new Iban()); } public function getValidIbans() { return array( array('CH9300762011623852957'), // Switzerland without spaces //Country list //http://www.rbs.co.uk/corporate/international/g0/guide-to-international-business/regulatory-information/iban/iban-example.ashx array('AL47 2121 1009 0000 0002 3569 8741'), //Albania array('AD12 0001 2030 2003 5910 0100'), //Andorra array('AT61 1904 3002 3457 3201'), //Austria array('AZ21 NABZ 0000 0000 1370 1000 1944'), //Azerbaijan array('BH67 BMAG 0000 1299 1234 56'), //Bahrain array('BE62 5100 0754 7061'), //Belgium array('BA39 1290 0794 0102 8494'), //Bosnia and Herzegovina array('BG80 BNBG 9661 1020 3456 78'), //Bulgaria array('HR12 1001 0051 8630 0016 0'), //Croatia array('CY17 0020 0128 0000 0012 0052 7600'), //Cyprus array('CZ65 0800 0000 1920 0014 5399'), //Czech Republic array('DK50 0040 0440 1162 43'), //Denmark array('EE38 2200 2210 2014 5685'), //Estonia array('FO97 5432 0388 8999 44'), //Faroe Islands array('FI21 1234 5600 0007 85'), //Finland array('FR14 2004 1010 0505 0001 3M02 606'), //France array('GE29 NB00 0000 0101 9049 17'), //Georgia array('DE89 3704 0044 0532 0130 00'), //Germany array('GI75 NWBK 0000 0000 7099 453'), //Gibraltar array('GR16 0110 1250 0000 0001 2300 695'), //Greece array('GL56 0444 9876 5432 10'), //Greenland array('HU42 1177 3016 1111 1018 0000 0000'), //Hungary array('IS14 0159 2600 7654 5510 7303 39'), //Iceland array('IE29 AIBK 9311 5212 3456 78'), //Ireland array('IL62 0108 0000 0009 9999 999'), //Israel array('IT40 S054 2811 1010 0000 0123 456'), //Italy array('LV80 BANK 0000 4351 9500 1'), //Latvia array('LB62 0999 0000 0001 0019 0122 9114'), //Lebanon array('LI21 0881 0000 2324 013A A'), //Liechtenstein array('LT12 1000 0111 0100 1000'), //Lithuania array('LU28 0019 4006 4475 0000'), //Luxembourg array('MK072 5012 0000 0589 84'), //Macedonia array('MT84 MALT 0110 0001 2345 MTLC AST0 01S'), //Malta array('MU17 BOMM 0101 1010 3030 0200 000M UR'), //Mauritius array('MD24 AG00 0225 1000 1310 4168'), //Moldova array('MC93 2005 2222 1001 1223 3M44 555'), //Monaco array('ME25 5050 0001 2345 6789 51'), //Montenegro array('NL39 RABO 0300 0652 64'), //Netherlands array('NO93 8601 1117 947'), //Norway array('PK36 SCBL 0000 0011 2345 6702'), //Pakistan array('PL60 1020 1026 0000 0422 7020 1111'), //Poland array('PT50 0002 0123 1234 5678 9015 4'), //Portugal array('RO49 AAAA 1B31 0075 9384 0000'), //Romania array('SM86 U032 2509 8000 0000 0270 100'), //San Marino array('SA03 8000 0000 6080 1016 7519'), //Saudi Arabia array('RS35 2600 0560 1001 6113 79'), //Serbia array('SK31 1200 0000 1987 4263 7541'), //Slovak Republic array('SI56 1910 0000 0123 438'), //Slovenia array('ES80 2310 0001 1800 0001 2345'), //Spain array('SE35 5000 0000 0549 1000 0003'), //Sweden array('CH93 0076 2011 6238 5295 7'), //Switzerland array('TN59 1000 6035 1835 9847 8831'), //Tunisia array('TR33 0006 1005 1978 6457 8413 26'), //Turkey array('AE07 0331 2345 6789 0123 456'), //UAE array('GB 12 CPBK 0892 9965 0449 91'), //United Kingdom //Extended country list //http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html array('AO06000600000100037131174'), //Angola array('AZ21NABZ00000000137010001944'), //Azerbaijan array('BH29BMAG1299123456BH00'), //Bahrain array('BJ11B00610100400271101192591'), //Benin array('VG96VPVG0000012345678901'), //British Virgin Islands array('BF1030134020015400945000643'), //Burkina Faso array('BI43201011067444'), //Burundi array('CM2110003001000500000605306'), //Cameroon array('CV64000300004547069110176'), //Cape Verde array('FR7630007000110009970004942'), //Central African Republic array('CG5230011000202151234567890'), //Congo array('CR0515202001026284066'), //Costa Rica array('DO28BAGR00000001212453611324'), //Dominican Republic array('GT82TRAJ01020000001210029690'), //Guatemala array('IR580540105180021273113007'), //Iran array('IL620108000000099999999'), //Israel array('CI05A00060174100178530011852'), //Ivory Coast array('KZ176010251000042993'), //Kazakhstan array('KW74NBOK0000000000001000372151'), //Kuwait array('LB30099900000001001925579115'), //Lebanon array('MG4600005030010101914016056'), //Madagascar array('ML03D00890170001002120000447'), //Mali array('MR1300012000010000002037372'), //Mauritania array('MU17BOMM0101101030300200000MUR'), //Mauritius array('MZ59000100000011834194157'), //Mozambique array('PS92PALS000000000400123456702'), //Palestinian Territory array('PT50000200000163099310355'), //Sao Tome and Principe array('SA0380000000608010167519'), //Saudi Arabia array('SN12K00100152000025690007542'), //Senegal array('TN5914207207100707129648'), //Tunisia array('TR330006100519786457841326'), //Turkey array('AE260211000000230064016'), //United Arab Emirates ); } /** * @dataProvider getInvalidIbans */ public function testInvalidIbans($iban) { $constraint = new Iban(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $iban, )); $this->validator->validate($iban, $constraint); } public function getInvalidIbans() { return array( array('CH93 0076 2011 6238 5295'), array('CH930076201162385295'), array('GB29 RBOS 6016 1331 9268 19'), array('CH930072011623852957'), array('NL39 RASO 0300 0652 64'), array('NO93 8601117 947'), array('CY170020 128 0000 0012 0052 7600'), array('foo'), array('123'), array('0750447346'), //Ibans with lower case values are invalid array('Ae260211000000230064016'), array('ae260211000000230064016') ); } } PK!y7{==Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\TypeValidator; class TypeValidatorTest extends \PHPUnit_Framework_TestCase { protected static $file; protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new TypeValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Type(array('type' => 'integer'))); } public function testEmptyIsValidIfString() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Type(array('type' => 'string'))); } public function testEmptyIsInvalidIfNoString() { $this->context->expects($this->once()) ->method('addViolation'); $this->validator->validate('', new Type(array('type' => 'integer'))); } /** * @dataProvider getValidValues */ public function testValidValues($value, $type) { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Type(array('type' => $type)); $this->validator->validate($value, $constraint); } public function getValidValues() { $object = new \stdClass(); $file = $this->createFile(); return array( array(true, 'Boolean'), array(false, 'Boolean'), array(true, 'boolean'), array(false, 'boolean'), array(true, 'bool'), array(false, 'bool'), array(0, 'numeric'), array('0', 'numeric'), array(1.5, 'numeric'), array('1.5', 'numeric'), array(0, 'integer'), array(1.5, 'float'), array('12345', 'string'), array(array(), 'array'), array($object, 'object'), array($object, 'stdClass'), array($file, 'resource'), array('12345', 'digit'), array('12a34', 'alnum'), array('abcde', 'alpha'), array("\n\r\t", 'cntrl'), array('arf12', 'graph'), array('abcde', 'lower'), array('ABCDE', 'upper'), array('arf12', 'print'), array('*&$()', 'punct'), array("\n\r\t", 'space'), array('AB10BC99', 'xdigit'), ); } /** * @dataProvider getInvalidValues */ public function testInvalidValues($value, $type, $valueAsString) { $constraint = new Type(array( 'type' => $type, 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $valueAsString, '{{ type }}' => $type, )); $this->validator->validate($value, $constraint); } public function getInvalidValues() { $object = new \stdClass(); $file = $this->createFile(); return array( array('foobar', 'numeric', 'foobar'), array('foobar', 'boolean', 'foobar'), array('0', 'integer', '0'), array('1.5', 'float', '1.5'), array(12345, 'string', '12345'), array($object, 'boolean', 'stdClass'), array($object, 'numeric', 'stdClass'), array($object, 'integer', 'stdClass'), array($object, 'float', 'stdClass'), array($object, 'string', 'stdClass'), array($object, 'resource', 'stdClass'), array($file, 'boolean', (string) $file), array($file, 'numeric', (string) $file), array($file, 'integer', (string) $file), array($file, 'float', (string) $file), array($file, 'string', (string) $file), array($file, 'object', (string) $file), array('12a34', 'digit', '12a34'), array('1a#23', 'alnum', '1a#23'), array('abcd1', 'alpha', 'abcd1'), array("\nabc", 'cntrl', "\nabc"), array("abc\n", 'graph', "abc\n"), array('abCDE', 'lower', 'abCDE'), array('ABcde', 'upper', 'ABcde'), array("\nabc", 'print', "\nabc"), array('abc&$!', 'punct', 'abc&$!'), array("\nabc", 'space', "\nabc"), array('AR1012', 'xdigit', 'AR1012'), ); } protected function createFile() { if (!self::$file) { self::$file = fopen(__FILE__, 'r'); } return self::$file; } public static function tearDownAfterClass() { if (self::$file) { fclose(self::$file); } } } PK!\z?++Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Required; use Symfony\Component\Validator\Constraints\Optional; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\CollectionValidator; abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new CollectionValidator(); $this->validator->initialize($this->context); $this->context->expects($this->any()) ->method('getGroup') ->will($this->returnValue('MyGroup')); } protected function tearDown() { $this->context = null; $this->validator = null; } abstract protected function prepareTestData(array $contents); public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate(null, new Collection(array('fields' => array( 'foo' => new Range(array('min' => 4)), )))); } public function testFieldsAsDefaultOption() { $data = $this->prepareTestData(array('foo' => 'foobar')); $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate($data, new Collection(array( 'foo' => new Range(array('min' => 4)), ))); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testThrowsExceptionIfNotTraversable() { $this->validator->validate('foobar', new Collection(array('fields' => array( 'foo' => new Range(array('min' => 4)), )))); } public function testWalkSingleConstraint() { $constraint = new Range(array('min' => 4)); $array = array( 'foo' => 3, 'bar' => 5, ); $i = 1; foreach ($array as $key => $value) { $this->context->expects($this->at($i++)) ->method('validateValue') ->with($value, $constraint, '['.$key.']', 'MyGroup'); } $data = $this->prepareTestData($array); $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate($data, new Collection(array( 'fields' => array( 'foo' => $constraint, 'bar' => $constraint, ), ))); } public function testWalkMultipleConstraints() { $constraints = array( new Range(array('min' => 4)), new NotNull(), ); $array = array( 'foo' => 3, 'bar' => 5, ); $i = 1; foreach ($array as $key => $value) { foreach ($constraints as $constraint) { $this->context->expects($this->at($i++)) ->method('validateValue') ->with($value, $constraint, '['.$key.']', 'MyGroup'); } } $data = $this->prepareTestData($array); $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate($data, new Collection(array( 'fields' => array( 'foo' => $constraints, 'bar' => $constraints, ) ))); } public function testExtraFieldsDisallowed() { $data = $this->prepareTestData(array( 'foo' => 5, 'baz' => 6, )); $this->context->expects($this->once()) ->method('addViolationAt') ->with('[baz]', 'myMessage', array( '{{ field }}' => 'baz' )); $this->validator->validate($data, new Collection(array( 'fields' => array( 'foo' => new Range(array('min' => 4)), ), 'extraFieldsMessage' => 'myMessage', ))); } // bug fix public function testNullNotConsideredExtraField() { $data = $this->prepareTestData(array( 'foo' => null, )); $constraint = new Collection(array( 'fields' => array( 'foo' => new Range(array('min' => 4)), ), )); $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate($data, $constraint); } public function testExtraFieldsAllowed() { $data = $this->prepareTestData(array( 'foo' => 5, 'bar' => 6, )); $constraint = new Collection(array( 'fields' => array( 'foo' => new Range(array('min' => 4)), ), 'allowExtraFields' => true, )); $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate($data, $constraint); } public function testMissingFieldsDisallowed() { $data = $this->prepareTestData(array()); $constraint = new Collection(array( 'fields' => array( 'foo' => new Range(array('min' => 4)), ), 'missingFieldsMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolationAt') ->with('[foo]', 'myMessage', array( '{{ field }}' => 'foo', )); $this->validator->validate($data, $constraint); } public function testMissingFieldsAllowed() { $data = $this->prepareTestData(array()); $constraint = new Collection(array( 'fields' => array( 'foo' => new Range(array('min' => 4)), ), 'allowMissingFields' => true, )); $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate($data, $constraint); } public function testOptionalFieldPresent() { $data = $this->prepareTestData(array( 'foo' => null, )); $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate($data, new Collection(array( 'foo' => new Optional(), ))); } public function testOptionalFieldNotPresent() { $data = $this->prepareTestData(array()); $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate($data, new Collection(array( 'foo' => new Optional(), ))); } public function testOptionalFieldSingleConstraint() { $array = array( 'foo' => 5, ); $constraint = new Range(array('min' => 4)); $this->context->expects($this->once()) ->method('validateValue') ->with($array['foo'], $constraint, '[foo]', 'MyGroup'); $this->context->expects($this->never()) ->method('addViolationAt'); $data = $this->prepareTestData($array); $this->validator->validate($data, new Collection(array( 'foo' => new Optional($constraint), ))); } public function testOptionalFieldMultipleConstraints() { $array = array( 'foo' => 5, ); $constraints = array( new NotNull(), new Range(array('min' => 4)), ); $i = 1; foreach ($constraints as $constraint) { $this->context->expects($this->at($i++)) ->method('validateValue') ->with($array['foo'], $constraint, '[foo]', 'MyGroup'); } $this->context->expects($this->never()) ->method('addViolationAt'); $data = $this->prepareTestData($array); $this->validator->validate($data, new Collection(array( 'foo' => new Optional($constraints), ))); } public function testRequiredFieldPresent() { $data = $this->prepareTestData(array( 'foo' => null, )); $this->context->expects($this->never()) ->method('addViolationAt'); $this->validator->validate($data, new Collection(array( 'foo' => new Required(), ))); } public function testRequiredFieldNotPresent() { $data = $this->prepareTestData(array()); $this->context->expects($this->once()) ->method('addViolationAt') ->with('[foo]', 'myMessage', array( '{{ field }}' => 'foo', )); $this->validator->validate($data, new Collection(array( 'fields' => array( 'foo' => new Required(), ), 'missingFieldsMessage' => 'myMessage', ))); } public function testRequiredFieldSingleConstraint() { $array = array( 'foo' => 5, ); $constraint = new Range(array('min' => 4)); $this->context->expects($this->once()) ->method('validateValue') ->with($array['foo'], $constraint, '[foo]', 'MyGroup'); $this->context->expects($this->never()) ->method('addViolationAt'); $data = $this->prepareTestData($array); $this->validator->validate($data, new Collection(array( 'foo' => new Required($constraint), ))); } public function testRequiredFieldMultipleConstraints() { $array = array( 'foo' => 5, ); $constraints = array( new NotNull(), new Range(array('min' => 4)), ); $i = 1; foreach ($constraints as $constraint) { $this->context->expects($this->at($i++)) ->method('validateValue') ->with($array['foo'], $constraint, '[foo]', 'MyGroup'); } $this->context->expects($this->never()) ->method('addViolationAt'); $data = $this->prepareTestData($array); $this->validator->validate($array, new Collection(array( 'foo' => new Required($constraints), ))); } public function testObjectShouldBeLeftUnchanged() { $value = new \ArrayObject(array( 'foo' => 3 )); $this->validator->validate($value, new Collection(array( 'fields' => array( 'foo' => new Range(array('min' => 2)), ) ))); $this->assertEquals(array( 'foo' => 3 ), (array) $value); } } PK!C77Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\LessThan; use Symfony\Component\Validator\Constraints\LessThanValidator; /** * @author Daniel Holmes */ class LessThanValidatorTest extends AbstractComparisonValidatorTestCase { protected function createValidator() { return new LessThanValidator(); } protected function createConstraint(array $options) { return new LessThan($options); } /** * {@inheritDoc} */ public function provideValidComparisons() { return array( array(1, 2), array(new \DateTime('2000-01-01'), new \DateTime('2010-01-01')), array(new ComparisonTest_Class(4), new ComparisonTest_Class(5)), array('22', '333'), array(null, 1), ); } /** * {@inheritDoc} */ public function provideInvalidComparisons() { return array( array(3, 2, '2', 'integer'), array(2, 2, '2', 'integer'), array(new \DateTime('2010-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'), array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'), array(new ComparisonTest_Class(5), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'), array(new ComparisonTest_Class(6), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'), array('333', '22', "'22'", 'string'), ); } } PK!bg g Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\DateTime; use Symfony\Component\Validator\Constraints\DateTimeValidator; class DateTimeValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new DateTimeValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new DateTime()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new DateTime()); } public function testDateTimeClassIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(new \DateTime(), new DateTime()); } /** * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException */ public function testExpectsStringCompatibleType() { $this->validator->validate(new \stdClass(), new DateTime()); } /** * @dataProvider getValidDateTimes */ public function testValidDateTimes($dateTime) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($dateTime, new DateTime()); } public function getValidDateTimes() { return array( array('2010-01-01 01:02:03'), array('1955-12-12 00:00:00'), array('2030-05-31 23:59:59'), ); } /** * @dataProvider getInvalidDateTimes */ public function testInvalidDateTimes($dateTime) { $constraint = new DateTime(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $dateTime, )); $this->validator->validate($dateTime, $constraint); } public function getInvalidDateTimes() { return array( array('foobar'), array('2010-01-01'), array('00:00:00'), array('2010-01-01 00:00'), array('2010-13-01 00:00:00'), array('2010-04-32 00:00:00'), array('2010-02-29 00:00:00'), array('2010-01-01 24:00:00'), array('2010-01-01 00:60:00'), array('2010-01-01 00:00:60'), ); } } PK!;,,Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\Validator\Constraints\Expression; use Symfony\Component\Validator\Constraints\ExpressionValidator; class ExpressionValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new ExpressionValidator(PropertyAccess::createPropertyAccessor()); $this->validator->initialize($this->context); $this->context->expects($this->any()) ->method('getClassName') ->will($this->returnValue(__CLASS__)); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Expression('value == 1')); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Expression('value == 1')); } public function testSucceedingExpressionAtObjectLevel() { $constraint = new Expression('this.property == 1'); $object = (object) array('property' => '1'); $this->context->expects($this->any()) ->method('getPropertyName') ->will($this->returnValue(null)); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($object, $constraint); } public function testFailingExpressionAtObjectLevel() { $constraint = new Expression(array( 'expression' => 'this.property == 1', 'message' => 'myMessage', )); $object = (object) array('property' => '2'); $this->context->expects($this->any()) ->method('getPropertyName') ->will($this->returnValue(null)); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage'); $this->validator->validate($object, $constraint); } public function testSucceedingExpressionAtPropertyLevel() { $constraint = new Expression('value == this.expected'); $object = (object) array('expected' => '1'); $this->context->expects($this->any()) ->method('getPropertyName') ->will($this->returnValue('property')); $this->context->expects($this->any()) ->method('getPropertyPath') ->will($this->returnValue('property')); $this->context->expects($this->any()) ->method('getRoot') ->will($this->returnValue($object)); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('1', $constraint); } public function testFailingExpressionAtPropertyLevel() { $constraint = new Expression(array( 'expression' => 'value == this.expected', 'message' => 'myMessage', )); $object = (object) array('expected' => '1'); $this->context->expects($this->any()) ->method('getPropertyName') ->will($this->returnValue('property')); $this->context->expects($this->any()) ->method('getPropertyPath') ->will($this->returnValue('property')); $this->context->expects($this->any()) ->method('getRoot') ->will($this->returnValue($object)); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage'); $this->validator->validate('2', $constraint); } public function testSucceedingExpressionAtNestedPropertyLevel() { $constraint = new Expression('value == this.expected'); $object = (object) array('expected' => '1'); $root = (object) array('nested' => $object); $this->context->expects($this->any()) ->method('getPropertyName') ->will($this->returnValue('property')); $this->context->expects($this->any()) ->method('getPropertyPath') ->will($this->returnValue('nested.property')); $this->context->expects($this->any()) ->method('getRoot') ->will($this->returnValue($root)); $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('1', $constraint); } public function testFailingExpressionAtNestedPropertyLevel() { $constraint = new Expression(array( 'expression' => 'value == this.expected', 'message' => 'myMessage', )); $object = (object) array('expected' => '1'); $root = (object) array('nested' => $object); $this->context->expects($this->any()) ->method('getPropertyName') ->will($this->returnValue('property')); $this->context->expects($this->any()) ->method('getPropertyPath') ->will($this->returnValue('nested.property')); $this->context->expects($this->any()) ->method('getRoot') ->will($this->returnValue($root)); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage'); $this->validator->validate('2', $constraint); } } PK!Zf^ ^ Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotBlankValidator; class NotBlankValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new NotBlankValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } /** * @dataProvider getValidValues */ public function testValidValues($date) { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($date, new NotBlank()); } public function getValidValues() { return array( array('foobar'), array(0), array(0.0), array('0'), array(1234), ); } public function testNullIsInvalid() { $constraint = new NotBlank(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage'); $this->validator->validate(null, $constraint); } public function testBlankIsInvalid() { $constraint = new NotBlank(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage'); $this->validator->validate('', $constraint); } public function testFalseIsInvalid() { $constraint = new NotBlank(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage'); $this->validator->validate(false, $constraint); } public function testEmptyArrayIsInvalid() { $constraint = new NotBlank(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage'); $this->validator->validate(array(), $constraint); } } PK!}mW]test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; class CollectionValidatorArrayTest extends CollectionValidatorTest { public function prepareTestData(array $contents) { return $contents; } } PK!r3UURtest/Validator/Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Null; use Symfony\Component\Validator\Constraints\NullValidator; class NullValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new NullValidator(); $this->validator->initialize($this->context); } protected function tearDown() { $this->context = null; $this->validator = null; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Null()); } /** * @dataProvider getInvalidValues */ public function testInvalidValues($value, $readableValue) { $constraint = new Null(array( 'message' => 'myMessage' )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ value }}' => $readableValue, )); $this->validator->validate($value, $constraint); } public function getInvalidValues() { return array( array(0, 0), array(false, false), array(true, true), array('', ''), array('foo bar', 'foo bar'), array(new \DateTime(), 'DateTime'), array(array(), 'Array'), ); } } PK!0h'Stest/Validator/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\Validator\Constraints\Image; use Symfony\Component\Validator\Constraints\ImageValidator; class ImageValidatorTest extends \PHPUnit_Framework_TestCase { protected $context; protected $validator; protected $path; protected $image; protected $imageLandscape; protected $imagePortrait; protected function setUp() { $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false); $this->validator = new ImageValidator(); $this->validator->initialize($this->context); $this->image = __DIR__.'/Fixtures/test.gif'; $this->imageLandscape = __DIR__.'/Fixtures/test_landscape.gif'; $this->imagePortrait = __DIR__.'/Fixtures/test_portrait.gif'; } public function testNullIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate(null, new Image()); } public function testEmptyStringIsValid() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate('', new Image()); } public function testValidImage() { $this->context->expects($this->never()) ->method('addViolation'); $this->validator->validate($this->image, new Image()); } public function testValidSize() { $this->context->expects($this->never()) ->method('addViolation'); $constraint = new Image(array( 'minWidth' => 1, 'maxWidth' => 2, 'minHeight' => 1, 'maxHeight' => 2, )); $this->validator->validate($this->image, $constraint); } public function testWidthTooSmall() { $constraint = new Image(array( 'minWidth' => 3, 'minWidthMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ width }}' => '2', '{{ min_width }}' => '3', )); $this->validator->validate($this->image, $constraint); } public function testWidthTooBig() { $constraint = new Image(array( 'maxWidth' => 1, 'maxWidthMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ width }}' => '2', '{{ max_width }}' => '1', )); $this->validator->validate($this->image, $constraint); } public function testHeightTooSmall() { $constraint = new Image(array( 'minHeight' => 3, 'minHeightMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ height }}' => '2', '{{ min_height }}' => '3', )); $this->validator->validate($this->image, $constraint); } public function testHeightTooBig() { $constraint = new Image(array( 'maxHeight' => 1, 'maxHeightMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ height }}' => '2', '{{ max_height }}' => '1', )); $this->validator->validate($this->image, $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testInvalidMinWidth() { $constraint = new Image(array( 'minWidth' => '1abc', )); $this->validator->validate($this->image, $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testInvalidMaxWidth() { $constraint = new Image(array( 'maxWidth' => '1abc', )); $this->validator->validate($this->image, $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testInvalidMinHeight() { $constraint = new Image(array( 'minHeight' => '1abc', )); $this->validator->validate($this->image, $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testInvalidMaxHeight() { $constraint = new Image(array( 'maxHeight' => '1abc', )); $this->validator->validate($this->image, $constraint); } public function testRatioTooSmall() { $constraint = new Image(array( 'minRatio' => 2, 'minRatioMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ ratio }}' => 1, '{{ min_ratio }}' => 2, )); $this->validator->validate($this->image, $constraint); } public function testRatioTooBig() { $constraint = new Image(array( 'maxRatio' => 0.5, 'maxRatioMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ ratio }}' => 1, '{{ max_ratio }}' => 0.5, )); $this->validator->validate($this->image, $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testInvalidMinRatio() { $constraint = new Image(array( 'minRatio' => '1abc', )); $this->validator->validate($this->image, $constraint); } /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ public function testInvalidMaxRatio() { $constraint = new Image(array( 'maxRatio' => '1abc', )); $this->validator->validate($this->image, $constraint); } public function testSquareNotAllowed() { $constraint = new Image(array( 'allowSquare' => false, 'allowSquareMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ width }}' => 2, '{{ height }}' => 2, )); $this->validator->validate($this->image, $constraint); } public function testLandscapeNotAllowed() { $constraint = new Image(array( 'allowLandscape' => false, 'allowLandscapeMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ width }}' => 2, '{{ height }}' => 1, )); $this->validator->validate($this->imageLandscape, $constraint); } public function testPortraitNotAllowed() { $constraint = new Image(array( 'allowPortrait' => false, 'allowPortraitMessage' => 'myMessage', )); $this->context->expects($this->once()) ->method('addViolation') ->with('myMessage', array( '{{ width }}' => 1, '{{ height }}' => 2, )); $this->validator->validate($this->imagePortrait, $constraint); } } PK!d..Ctest/Validator/Symfony/Component/Validator/Tests/ConstraintTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Tests; use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Tests\Fixtures\ConstraintC; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValue; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValueAsDefault; class ConstraintTest extends \PHPUnit_Framework_TestCase { public function testSetProperties() { $constraint = new ConstraintA(array( 'property1' => 'foo', 'property2' => 'bar', )); $this->assertEquals('foo', $constraint->property1); $this->assertEquals('bar', $constraint->property2); } public function testSetNotExistingPropertyThrowsException() { $this->setExpectedException('Symfony\Component\Validator\Exception\InvalidOptionsException'); new ConstraintA(array( 'foo' => 'bar', )); } public function testMagicPropertiesAreNotAllowed() { $constraint = new ConstraintA(); $this->setExpectedException('Symfony\Component\Validator\Exception\InvalidOptionsException'); $constraint->foo = 'bar'; } public function testInvalidAndRequiredOptionsPassed() { $this->setExpectedException('Symfony\Component\Validator\Exception\InvalidOptionsException'); new ConstraintC(array( 'option1' => 'default', 'foo' => 'bar' )); } public function testSetDefaultProperty() { $constraint = new ConstraintA('foo'); $this->assertEquals('foo', $constraint->property2); } public function testSetDefaultPropertyDoctrineStyle() { $constraint = new ConstraintA(array('value' => 'foo')); $this->assertEquals('foo', $constraint->property2); } public function testSetDefaultPropertyDoctrineStylePlusOtherProperty() { $constraint = new ConstraintA(array('value' => 'foo', 'property1' => 'bar')); $this->assertEquals('foo', $constraint->property2); $this->assertEquals('bar', $constraint->property1); } public function testSetDefaultPropertyDoctrineStyleWhenDefaultPropertyIsNamedValue() { $constraint = new ConstraintWithValueAsDefault(array('value' => 'foo')); $this->assertEquals('foo', $constraint->value); $this->assertNull($constraint->property); } public function testDontSetDefaultPropertyIfValuePropertyExists() { $constraint = new ConstraintWithValue(array('value' => 'foo')); $this->assertEquals('foo', $constraint->value); $this->assertNull($constraint->property); } public function testSetUndefinedDefaultProperty() { $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); new ConstraintB('foo'); } public function testRequiredOptionsMustBeDefined() { $this->setExpectedException('Symfony\Component\Validator\Exception\MissingOptionsException'); new ConstraintC(); } public function testRequiredOptionsPassed() { new ConstraintC(array('option1' => 'default')); } public function testGroupsAreConvertedToArray() { $constraint = new ConstraintA(array('groups' => 'Foo')); $this->assertEquals(array('Foo'), $constraint->groups); } public function testAddDefaultGroupAddsGroup() { $constraint = new ConstraintA(array('groups' => 'Default')); $constraint->addImplicitGroupName('Foo'); $this->assertEquals(array('Default', 'Foo'), $constraint->groups); } public function testAllowsSettingZeroRequiredPropertyValue() { $constraint = new ConstraintA(0); $this->assertEquals(0, $constraint->property2); } public function testCanCreateConstraintWithNoDefaultOptionAndEmptyArray() { new ConstraintB(array()); } public function testGetTargetsCanBeString() { $constraint = new ClassConstraint(); $this->assertEquals('class', $constraint->getTargets()); } public function testGetTargetsCanBeArray() { $constraint = new ConstraintA(); $this->assertEquals(array('property', 'class'), $constraint->getTargets()); } } PK!,Q88;test/Validator/Symfony/Component/Validator/phpunit.xml.distnu[ ./Tests/ ./ ./vendor ./Tests PK!Ktest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Logger; use Symfony\Bridge\Doctrine\Logger\DbalLogger; class DbalLoggerTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getLogFixtures */ public function testLog($sql, $params, $logParams) { $logger = $this->getMock('Psr\\Log\\LoggerInterface'); $dbalLogger = $this ->getMockBuilder('Symfony\\Bridge\\Doctrine\\Logger\\DbalLogger') ->setConstructorArgs(array($logger, null)) ->setMethods(array('log')) ->getMock() ; $dbalLogger ->expects($this->once()) ->method('log') ->with($sql, $logParams) ; $dbalLogger->startQuery($sql, $params); } public function getLogFixtures() { return array( array('SQL', null, array()), array('SQL', array(), array()), array('SQL', array('foo' => 'bar'), array('foo' => 'bar')) ); } public function testLogNonUtf8() { $logger = $this->getMock('Psr\\Log\\LoggerInterface'); $dbalLogger = $this ->getMockBuilder('Symfony\\Bridge\\Doctrine\\Logger\\DbalLogger') ->setConstructorArgs(array($logger, null)) ->setMethods(array('log')) ->getMock() ; $dbalLogger ->expects($this->once()) ->method('log') ->with('SQL', array('utf8' => 'foo', 'nonutf8' => DbalLogger::BINARY_DATA_VALUE)) ; $dbalLogger->startQuery('SQL', array( 'utf8' => 'foo', 'nonutf8' => "\x7F\xFF", )); } public function testLogLongString() { $logger = $this->getMock('Symfony\\Component\\HttpKernel\\Log\\LoggerInterface'); $dbalLogger = $this ->getMockBuilder('Symfony\\Bridge\\Doctrine\\Logger\\DbalLogger') ->setConstructorArgs(array($logger, null)) ->setMethods(array('log')) ->getMock() ; $testString = 'abc'; $shortString = str_pad('', DbalLogger::MAX_STRING_LENGTH, $testString); $longString = str_pad('', DbalLogger::MAX_STRING_LENGTH+1, $testString); $dbalLogger ->expects($this->once()) ->method('log') ->with('SQL', array('short' => $shortString, 'long' => substr($longString, 0, DbalLogger::MAX_STRING_LENGTH - 6).' [...]')) ; $dbalLogger->startQuery('SQL', array( 'short' => $shortString, 'long' => $longString, )); } public function testLogUTF8LongString() { if (!function_exists('mb_detect_encoding')) { $this->markTestSkipped('Testing log shortening of utf8 charsets requires the mb_detect_encoding() function.'); } $logger = $this->getMock('Symfony\\Component\\HttpKernel\\Log\\LoggerInterface'); $dbalLogger = $this ->getMockBuilder('Symfony\\Bridge\\Doctrine\\Logger\\DbalLogger') ->setConstructorArgs(array($logger, null)) ->setMethods(array('log')) ->getMock() ; $testStringArray = array('é', 'á', 'ű', 'ő', 'ú', 'ö', 'ü', 'ó', 'í'); $testStringCount = count($testStringArray); $shortString = ''; $longString = ''; for ($i = 1; $i <= DbalLogger::MAX_STRING_LENGTH; $i++) { $shortString .= $testStringArray[$i % $testStringCount]; $longString .= $testStringArray[$i % $testStringCount]; } $longString .= $testStringArray[$i % $testStringCount]; $dbalLogger ->expects($this->once()) ->method('log') ->with('SQL', array('short' => $shortString, 'long' => mb_substr($longString, 0, DbalLogger::MAX_STRING_LENGTH - 6, mb_detect_encoding($longString)).' [...]')) ; $dbalLogger->startQuery('SQL', array( 'short' => $shortString, 'long' => $longString, )); } } PK!l;?test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/bootstrap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ $loader = require __DIR__.'/../vendor/autoload.php'; Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(array($loader, 'loadClass')); PK!1gPtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; /** @Entity */ class SingleIntIdEntity { /** @Id @Column(type="integer") */ protected $id; /** @Column(type="string", nullable=true) */ public $name; public function __construct($id, $name) { $this->id = $id; $this->name = $name; } public function __toString() { return (string) $this->name; } } PK!I>[Ztest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdNoToStringEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; /** @Entity */ class SingleIntIdNoToStringEntity { /** @Id @Column(type="integer") */ protected $id; /** @Column(type="string", nullable=true) */ public $name; public function __construct($id, $name) { $this->id = $id; $this->name = $name; } } PK! +88Stest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeIntIdEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; /** @Entity */ class CompositeIntIdEntity { /** @Id @Column(type="integer") */ protected $id1; /** @Id @Column(type="integer") */ protected $id2; /** @Column(type="string") */ public $name; public function __construct($id1, $id2, $name) { $this->id1 = $id1; $this->id2 = $id2; $this->name = $name; } public function __toString() { return $this->name; } } PK!ͭPtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/AssociationEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class AssociationEntity { /** * @var int * @ORM\Id @ORM\GeneratedValue * @ORM\Column(type="integer") */ private $id; /** * @ORM\ManyToOne(targetEntity="SingleIntIdEntity") * @var \Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity */ public $single; /** * @ORM\ManyToOne(targetEntity="CompositeIntIdEntity") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="composite_id1", referencedColumnName="id1"), * @ORM\JoinColumn(name="composite_id2", referencedColumnName="id2") * }) * @var \Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity */ public $composite; } PK!3Ntest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/GroupableEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; /** @Entity */ class GroupableEntity { /** @Id @Column(type="integer") */ protected $id; /** @Column(type="string", nullable=true) */ public $name; /** @Column(type="string", nullable=true) */ public $groupName; public function __construct($id, $name, $groupName) { $this->id = $id; $this->name = $name; $this->groupName = $groupName; } } PK!!Stest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleStringIdEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; /** @Entity */ class SingleStringIdEntity { /** @Id @Column(type="string") */ protected $id; /** @Column(type="string") */ public $name; public function __construct($id, $name) { $this->id = $id; $this->name = $name; } public function __toString() { return $this->name; } } PK!6i+**Ttest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/ContainerAwareFixture.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\Common\DataFixtures\FixtureInterface; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerAwareInterface; class ContainerAwareFixture implements FixtureInterface, ContainerAwareInterface { public $container; public function setContainer(ContainerInterface $container = null) { $this->container = $container; } public function load(ObjectManager $manager) { } } PK!ИmOtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/DoubleNameEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; /** @Entity */ class DoubleNameEntity { /** @Id @Column(type="integer") */ protected $id; /** @Column(type="string") */ public $name; /** @Column(type="string", nullable=true) */ public $name2; public function __construct($id, $name, $name2) { $this->id = $id; $this->name = $name; $this->name2 = $name2; } } PK!%b99Vtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeStringIdEntity.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; /** @Entity */ class CompositeStringIdEntity { /** @Id @Column(type="string") */ protected $id1; /** @Id @Column(type="string") */ protected $id2; /** @Column(type="string") */ public $name; public function __construct($id1, $id2, $name) { $this->id1 = $id1; $this->id2 = $id2; $this->name = $name; } public function __toString() { return $this->name; } } PK!'N|qqCtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/User.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; use Symfony\Component\Security\Core\User\UserInterface; /** @Entity */ class User implements UserInterface { /** @Id @Column(type="integer") */ protected $id1; /** @Id @Column(type="integer") */ protected $id2; /** @Column(type="string") */ public $name; public function __construct($id1, $id2, $name) { $this->id1 = $id1; $this->id2 = $id2; $this->name = $name; } public function getRoles() { } public function getPassword() { } public function getSalt() { } public function getUsername() { return $this->name; } public function eraseCredentials() { } public function equals(UserInterface $user) { } } PK!.Itest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DoctrineOrmTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests; use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; /** * Class DoctrineOrmTestCase * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. * Use {@link DoctrineTestHelper} instead. */ abstract class DoctrineOrmTestCase extends \PHPUnit_Framework_TestCase { /** * @return \Doctrine\ORM\EntityManager */ public static function createTestEntityManager() { return DoctrineTestHelper::createTestEntityManager(); } } PK!۵Utest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form; use Doctrine\Common\Persistence\Mapping\ClassMetadata; use Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\ValueGuess; class DoctrineOrmTypeGuesserTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider requiredProvider */ public function testRequiredGuesser($classMetadata, $expected) { $this->assertEquals($expected, $this->getGuesser($classMetadata)->guessRequired('TestEntity', 'field')); } public function requiredProvider() { $return = array(); // Simple field, not nullable $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(true)); $classMetadata->expects($this->once())->method('isNullable')->with('field')->will($this->returnValue(false)); $return[] = array($classMetadata, new ValueGuess(true, Guess::HIGH_CONFIDENCE)); // Simple field, nullable $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(true)); $classMetadata->expects($this->once())->method('isNullable')->with('field')->will($this->returnValue(true)); $return[] = array($classMetadata, new ValueGuess(false, Guess::MEDIUM_CONFIDENCE)); // One-to-one, nullable (by default) $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true)); $mapping = array('joinColumns' => array(array())); $classMetadata->expects($this->once())->method('getAssociationMapping')->with('field')->will($this->returnValue($mapping)); $return[] = array($classMetadata, new ValueGuess(false, Guess::HIGH_CONFIDENCE)); // One-to-one, nullable (explicit) $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true)); $mapping = array('joinColumns' => array(array('nullable'=>true))); $classMetadata->expects($this->once())->method('getAssociationMapping')->with('field')->will($this->returnValue($mapping)); $return[] = array($classMetadata, new ValueGuess(false, Guess::HIGH_CONFIDENCE)); // One-to-one, not nullable $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true)); $mapping = array('joinColumns' => array(array('nullable'=>false))); $classMetadata->expects($this->once())->method('getAssociationMapping')->with('field')->will($this->returnValue($mapping)); $return[] = array($classMetadata, new ValueGuess(true, Guess::HIGH_CONFIDENCE)); // One-to-many, no clue $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(false)); $return[] = array($classMetadata, null); return $return; } private function getGuesser(ClassMetadata $classMetadata) { $em = $this->getMock('Doctrine\Common\Persistence\ObjectManager'); $em->expects($this->once())->method('getClassMetaData')->with('TestEntity')->will($this->returnValue($classMetadata)); $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry'); $registry->expects($this->once())->method('getManagers')->will($this->returnValue(array($em))); return new DoctrineOrmTypeGuesser($registry); } } PK!`Հptest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; /** * @author Bernhard Schussek */ class UnloadedEntityChoiceListSingleStringIdTest extends AbstractEntityChoiceListSingleStringIdTest { public function testGetIndicesForValuesIgnoresNonExistingValues() { $this->markTestSkipped('Non-existing values are not detected for unloaded choice lists.'); } } PK!';!!atest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/GenericEntityChoiceListTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; use Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity; use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Doctrine\ORM\Tools\SchemaTool; class GenericEntityChoiceListTest extends \PHPUnit_Framework_TestCase { const SINGLE_INT_ID_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; const SINGLE_STRING_ID_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity'; const COMPOSITE_ID_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity'; const GROUPABLE_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity'; /** * @var \Doctrine\ORM\EntityManager */ private $em; protected function setUp() { if (!class_exists('Symfony\Component\Form\Form')) { $this->markTestSkipped('The "Form" component is not available'); } if (!class_exists('Doctrine\DBAL\Platforms\MySqlPlatform')) { $this->markTestSkipped('Doctrine DBAL is not available.'); } if (!class_exists('Doctrine\Common\Version')) { $this->markTestSkipped('Doctrine Common is not available.'); } if (!class_exists('Doctrine\ORM\EntityManager')) { $this->markTestSkipped('Doctrine ORM is not available.'); } $this->em = DoctrineTestHelper::createTestEntityManager(); $schemaTool = new SchemaTool($this->em); $classes = array( $this->em->getClassMetadata(self::SINGLE_INT_ID_CLASS), $this->em->getClassMetadata(self::SINGLE_STRING_ID_CLASS), $this->em->getClassMetadata(self::COMPOSITE_ID_CLASS), $this->em->getClassMetadata(self::GROUPABLE_CLASS), ); try { $schemaTool->dropSchema($classes); } catch (\Exception $e) { } try { $schemaTool->createSchema($classes); } catch (\Exception $e) { } parent::setUp(); } protected function tearDown() { parent::tearDown(); $this->em = null; } /** * @expectedException \Symfony\Component\Form\Exception\StringCastException * @expectedMessage Entity "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity" passed to the choice field must have a "__toString()" method defined (or you can also override the "property" option). */ public function testEntitiesMustHaveAToStringMethod() { $entity1 = new SingleIntIdNoToStringEntity(1, 'Foo'); $entity2 = new SingleIntIdNoToStringEntity(2, 'Bar'); // Persist for managed state $this->em->persist($entity1); $this->em->persist($entity2); $choiceList = new EntityChoiceList( $this->em, self::SINGLE_INT_ID_CLASS, null, null, array( $entity1, $entity2, ) ); $choiceList->getValues(); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testChoicesMustBeManaged() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); // no persist here! $choiceList = new EntityChoiceList( $this->em, self::SINGLE_INT_ID_CLASS, 'name', null, array( $entity1, $entity2, ) ); // triggers loading -> exception $choiceList->getChoices(); } public function testInitExplicitChoices() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); // Persist for managed state $this->em->persist($entity1); $this->em->persist($entity2); $choiceList = new EntityChoiceList( $this->em, self::SINGLE_INT_ID_CLASS, 'name', null, array( $entity1, $entity2, ) ); $this->assertSame(array(1 => $entity1, 2 => $entity2), $choiceList->getChoices()); } public function testInitEmptyChoices() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); // Persist for managed state $this->em->persist($entity1); $this->em->persist($entity2); $choiceList = new EntityChoiceList( $this->em, self::SINGLE_INT_ID_CLASS, 'name', null, array() ); $this->assertSame(array(), $choiceList->getChoices()); } public function testInitNestedChoices() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); // Oh yeah, we're persisting with fire now! $this->em->persist($entity1); $this->em->persist($entity2); $choiceList = new EntityChoiceList( $this->em, self::SINGLE_INT_ID_CLASS, 'name', null, array( 'group1' => array($entity1), 'group2' => array($entity2), ), array() ); $this->assertSame(array(1 => $entity1, 2 => $entity2), $choiceList->getChoices()); $this->assertEquals(array( 'group1' => array(1 => new ChoiceView($entity1, '1', 'Foo')), 'group2' => array(2 => new ChoiceView($entity2, '2', 'Bar')) ), $choiceList->getRemainingViews()); } public function testGroupByPropertyPath() { $item1 = new GroupableEntity(1, 'Foo', 'Group1'); $item2 = new GroupableEntity(2, 'Bar', 'Group1'); $item3 = new GroupableEntity(3, 'Baz', 'Group2'); $item4 = new GroupableEntity(4, 'Boo!', null); $this->em->persist($item1); $this->em->persist($item2); $this->em->persist($item3); $this->em->persist($item4); $choiceList = new EntityChoiceList( $this->em, self::GROUPABLE_CLASS, 'name', null, array( $item1, $item2, $item3, $item4, ), array(), 'groupName' ); $this->assertEquals(array(1 => $item1, 2 => $item2, 3 => $item3, 4 => $item4), $choiceList->getChoices()); $this->assertEquals(array( 'Group1' => array(1 => new ChoiceView($item1, '1', 'Foo'), 2 => new ChoiceView($item2, '2', 'Bar')), 'Group2' => array(3 => new ChoiceView($item3, '3', 'Baz')), 4 => new ChoiceView($item4, '4', 'Boo!') ), $choiceList->getRemainingViews()); } public function testGroupByInvalidPropertyPathReturnsFlatChoices() { $item1 = new GroupableEntity(1, 'Foo', 'Group1'); $item2 = new GroupableEntity(2, 'Bar', 'Group1'); $this->em->persist($item1); $this->em->persist($item2); $choiceList = new EntityChoiceList( $this->em, self::GROUPABLE_CLASS, 'name', null, array( $item1, $item2, ), array(), 'child.that.does.not.exist' ); $this->assertEquals(array( 1 => $item1, 2 => $item2 ), $choiceList->getChoices()); } public function testInitShorthandEntityName() { $item1 = new SingleIntIdEntity(1, 'Foo'); $item2 = new SingleIntIdEntity(2, 'Bar'); $this->em->persist($item1); $this->em->persist($item2); $choiceList = new EntityChoiceList( $this->em, 'SymfonyTestsDoctrine:SingleIntIdEntity' ); $this->assertEquals(array(1, 2), $choiceList->getValuesForChoices(array($item1, $item2))); $this->assertEquals(array(1, 2), $choiceList->getIndicesForChoices(array($item1, $item2))); } } PK!9&test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; /** * @author Bernhard Schussek */ class UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest extends UnloadedEntityChoiceListSingleStringIdTest { /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { $qb = $this->em->createQueryBuilder()->select('s')->from($this->getEntityClass(), 's'); $loader = new ORMQueryBuilderLoader($qb); return new EntityChoiceList($this->em, $this->getEntityClass(), null, $loader); } } PK!b#mtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleIntIdTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity; /** * @author Bernhard Schussek */ abstract class AbstractEntityChoiceListSingleIntIdTest extends AbstractEntityChoiceListTest { protected function getEntityClass() { return 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createObjects() { return array( new SingleIntIdEntity(-10, 'A'), new SingleIntIdEntity(10, 'B'), new SingleIntIdEntity(20, 'C'), new SingleIntIdEntity(30, 'D'), ); } protected function getChoices() { return array('_10' => $this->obj1, 10 => $this->obj2, 20 => $this->obj3, 30 => $this->obj4); } protected function getLabels() { return array('_10' => 'A', 10 => 'B', 20 => 'C', 30 => 'D'); } protected function getValues() { return array('_10' => '-10', 10 => '10', 20 => '20', 30 => '30'); } protected function getIndices() { return array('_10', 10, 20, 30); } } PK!AGA}test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; /** * @author Bernhard Schussek */ class UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest extends UnloadedEntityChoiceListSingleIntIdTest { /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { $qb = $this->em->createQueryBuilder()->select('s')->from($this->getEntityClass(), 's'); $loader = new ORMQueryBuilderLoader($qb); return new EntityChoiceList($this->em, $this->getEntityClass(), null, $loader); } } PK!~h}test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; /** * @author Bernhard Schussek */ class UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest extends UnloadedEntityChoiceListCompositeIdTest { /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { $qb = $this->em->createQueryBuilder()->select('s')->from($this->getEntityClass(), 's'); $loader = new ORMQueryBuilderLoader($qb); return new EntityChoiceList($this->em, $this->getEntityClass(), null, $loader); } } PK!'jntest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleStringIdTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; /** * @author Bernhard Schussek */ class LoadedEntityChoiceListSingleStringIdTest extends AbstractEntityChoiceListSingleStringIdTest { /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { $list = parent::createChoiceList(); // load list $list->getChoices(); return $list; } } PK!0ektest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleIntIdTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; /** * @author Bernhard Schussek */ class LoadedEntityChoiceListSingleIntIdTest extends AbstractEntityChoiceListSingleIntIdTest { /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { $list = parent::createChoiceList(); // load list $list->getChoices(); return $list; } } PK!V zzmtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; /** * @author Bernhard Schussek */ class UnloadedEntityChoiceListCompositeIdTest extends AbstractEntityChoiceListCompositeIdTest { public function testGetIndicesForValuesIgnoresNonExistingValues() { $this->markTestSkipped('Non-existing values are not detected for unloaded choice lists.'); } } PK!*mtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListCompositeIdTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity; /** * @author Bernhard Schussek */ abstract class AbstractEntityChoiceListCompositeIdTest extends AbstractEntityChoiceListTest { protected function getEntityClass() { return 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity'; } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createObjects() { return array( new CompositeIntIdEntity(10, 11, 'A'), new CompositeIntIdEntity(20, 21, 'B'), new CompositeIntIdEntity(30, 31, 'C'), new CompositeIntIdEntity(40, 41, 'D'), ); } protected function getChoices() { return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); } protected function getIndices() { return array(0, 1, 2, 3); } } PK!n<- - _test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase; use Doctrine\DBAL\Connection; class ORMQueryBuilderLoaderTest extends DoctrineOrmTestCase { /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testItOnlyWorksWithQueryBuilderOrClosure() { new ORMQueryBuilderLoader(new \stdClass()); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testClosureRequiresTheEntityManager() { $closure = function () {}; new ORMQueryBuilderLoader($closure); } public function testIdentifierTypeIsStringArray() { $this->checkIdentifierType('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity', Connection::PARAM_STR_ARRAY); } public function testIdentifierTypeIsIntegerArray() { $this->checkIdentifierType('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity', Connection::PARAM_INT_ARRAY); } protected function checkIdentifierType($classname, $expectedType) { $em = $this->createTestEntityManager(); $query = $this->getMockBuilder('QueryMock') ->setMethods(array('setParameter', 'getResult', 'getSql', '_doExecute')) ->getMock(); $query->expects($this->once()) ->method('setParameter') ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', array(), $expectedType) ->will($this->returnValue($query)); $qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder') ->setConstructorArgs(array($em)) ->setMethods(array('getQuery')) ->getMock(); $qb->expects($this->once()) ->method('getQuery') ->will($this->returnValue($query)); $qb->select('e') ->from($classname, 'e'); $loader = new ORMQueryBuilderLoader($qb); $loader->getEntitiesByIds('id', array()); } } PK!-1 1 btest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList; use Doctrine\ORM\Tools\SchemaTool; use Symfony\Component\Form\Tests\Extension\Core\ChoiceList\AbstractChoiceListTest; /** * @author Bernhard Schussek */ abstract class AbstractEntityChoiceListTest extends AbstractChoiceListTest { /** * @var \Doctrine\ORM\EntityManager */ protected $em; protected $obj1; protected $obj2; protected $obj3; protected $obj4; protected function setUp() { if (!class_exists('Symfony\Component\Form\Form')) { $this->markTestSkipped('The "Form" component is not available'); } if (!class_exists('Doctrine\DBAL\Platforms\MySqlPlatform')) { $this->markTestSkipped('Doctrine DBAL is not available.'); } if (!class_exists('Doctrine\Common\Version')) { $this->markTestSkipped('Doctrine Common is not available.'); } if (!class_exists('Doctrine\ORM\EntityManager')) { $this->markTestSkipped('Doctrine ORM is not available.'); } $this->em = DoctrineTestHelper::createTestEntityManager(); $schemaTool = new SchemaTool($this->em); $classes = array($this->em->getClassMetadata($this->getEntityClass())); try { $schemaTool->dropSchema($classes); } catch (\Exception $e) { } try { $schemaTool->createSchema($classes); } catch (\Exception $e) { } list($this->obj1, $this->obj2, $this->obj3, $this->obj4) = $this->createObjects(); $this->em->persist($this->obj1); $this->em->persist($this->obj2); $this->em->persist($this->obj3); $this->em->persist($this->obj4); $this->em->flush(); parent::setUp(); } protected function tearDown() { parent::tearDown(); $this->em = null; } abstract protected function getEntityClass(); abstract protected function createObjects(); /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { return new EntityChoiceList($this->em, $this->getEntityClass()); } } PK!c&zzmtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; /** * @author Bernhard Schussek */ class UnloadedEntityChoiceListSingleIntIdTest extends AbstractEntityChoiceListSingleIntIdTest { public function testGetIndicesForValuesIgnoresNonExistingValues() { $this->markTestSkipped('Non-existing values are not detected for unloaded choice lists.'); } } PK!ǜ"ktest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListCompositeIdTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; /** * @author Bernhard Schussek */ class LoadedEntityChoiceListCompositeIdTest extends AbstractEntityChoiceListCompositeIdTest { /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { $list = parent::createChoiceList(); // load list $list->getChoices(); return $list; } } PK!_UNFptest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleStringIdTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity; /** * @author Bernhard Schussek */ abstract class AbstractEntityChoiceListSingleStringIdTest extends AbstractEntityChoiceListTest { protected function getEntityClass() { return 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity'; } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createObjects() { return array( new SingleStringIdEntity('a', 'A'), new SingleStringIdEntity('b', 'B'), new SingleStringIdEntity('c', 'C'), new SingleStringIdEntity('d', 'D'), ); } protected function getChoices() { return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); } protected function getIndices() { return array(0, 1, 2, 3); } } PK!Yv:B B ktest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DataTransformer/CollectionToArrayTransformerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\DataTransformer; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer; /** * @author Bernhard Schussek */ class CollectionToArrayTransformerTest extends \PHPUnit_Framework_TestCase { /** * @var CollectionToArrayTransformer */ private $transformer; protected function setUp() { $this->transformer = new CollectionToArrayTransformer(); } public function testTransform() { $array = array( 2 => 'foo', 3 => 'bar', ); $this->assertSame($array, $this->transformer->transform(new ArrayCollection($array))); } /** * This test is needed for cases when getXxxs() in the entity returns the * result of $collection->toArray(), in order to prevent modifications of * the inner collection. * * See https://github.com/symfony/symfony/pull/9308 */ public function testTransformArray() { $array = array( 2 => 'foo', 3 => 'bar', ); $this->assertSame($array, $this->transformer->transform($array)); } public function testTransformNull() { $this->assertSame(array(), $this->transformer->transform(null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformExpectsArrayOrCollection() { $this->transformer->transform('Foo'); } public function testReverseTransform() { $array = array( 2 => 'foo', 3 => 'bar', ); $this->assertEquals(new ArrayCollection($array), $this->transformer->reverseTransform($array)); } public function testReverseTransformEmpty() { $this->assertEquals(new ArrayCollection(), $this->transformer->reverseTransform('')); } public function testReverseTransformNull() { $this->assertEquals(new ArrayCollection(), $this->transformer->reverseTransform(null)); } } PK!(iiNtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\Type; use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeStringIdEntity; use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class EntityTypeTest extends TypeTestCase { const ITEM_GROUP_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\GroupableEntity'; const SINGLE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; const SINGLE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity'; const COMPOSITE_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity'; const COMPOSITE_STRING_IDENT_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeStringIdEntity'; /** * @var \Doctrine\ORM\EntityManager */ private $em; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $emRegistry; protected function setUp() { if (!class_exists('Symfony\Component\Form\Form')) { $this->markTestSkipped('The "Form" component is not available'); } if (!class_exists('Doctrine\DBAL\Platforms\MySqlPlatform')) { $this->markTestSkipped('Doctrine DBAL is not available.'); } if (!class_exists('Doctrine\Common\Version')) { $this->markTestSkipped('Doctrine Common is not available.'); } if (!class_exists('Doctrine\ORM\EntityManager')) { $this->markTestSkipped('Doctrine ORM is not available.'); } $this->em = DoctrineTestHelper::createTestEntityManager(); $this->emRegistry = $this->createRegistryMock('default', $this->em); parent::setUp(); $schemaTool = new SchemaTool($this->em); $classes = array( $this->em->getClassMetadata(self::ITEM_GROUP_CLASS), $this->em->getClassMetadata(self::SINGLE_IDENT_CLASS), $this->em->getClassMetadata(self::SINGLE_STRING_IDENT_CLASS), $this->em->getClassMetadata(self::COMPOSITE_IDENT_CLASS), $this->em->getClassMetadata(self::COMPOSITE_STRING_IDENT_CLASS), ); try { $schemaTool->dropSchema($classes); } catch (\Exception $e) { } try { $schemaTool->createSchema($classes); } catch (\Exception $e) { } } protected function tearDown() { parent::tearDown(); $this->em = null; $this->emRegistry = null; } protected function getExtensions() { return array_merge(parent::getExtensions(), array( new DoctrineOrmExtension($this->emRegistry), )); } protected function persist(array $entities) { foreach ($entities as $entity) { $this->em->persist($entity); } $this->em->flush(); // no clear, because entities managed by the choice field must // be managed! } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException */ public function testClassOptionIsRequired() { $this->factory->createNamed('name', 'entity'); } public function testSetDataToUninitializedEntityWithNonRequired() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $this->persist(array($entity1, $entity2)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'required' => false, 'property' => 'name' )); $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']); } public function testSetDataToUninitializedEntityWithNonRequiredToString() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $this->persist(array($entity1, $entity2)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'required' => false, )); $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']); } public function testSetDataToUninitializedEntityWithNonRequiredQueryBuilder() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $this->persist(array($entity1, $entity2)); $qb = $this->em->createQueryBuilder()->select('e')->from(self::SINGLE_IDENT_CLASS, 'e'); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'required' => false, 'property' => 'name', 'query_builder' => $qb )); $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testConfigureQueryBuilderWithNonQueryBuilderAndNonClosure() { $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'query_builder' => new \stdClass(), )); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testConfigureQueryBuilderWithClosureReturningNonQueryBuilder() { $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'query_builder' => function () { return new \stdClass(); }, )); $field->submit('2'); } public function testSetDataSingleNull() { $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => false, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, )); $field->setData(null); $this->assertNull($field->getData()); $this->assertSame('', $field->getViewData()); } public function testSetDataMultipleExpandedNull() { $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => true, 'expanded' => true, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, )); $field->setData(null); $this->assertNull($field->getData()); $this->assertSame(array(), $field->getViewData()); } public function testSetDataMultipleNonExpandedNull() { $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => true, 'expanded' => false, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, )); $field->setData(null); $this->assertNull($field->getData()); $this->assertSame(array(), $field->getViewData()); } public function testSubmitSingleExpandedNull() { $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => false, 'expanded' => true, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, )); $field->submit(null); $this->assertNull($field->getData()); $this->assertSame(array(), $field->getViewData()); } public function testSubmitSingleNonExpandedNull() { $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => false, 'expanded' => false, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, )); $field->submit(null); $this->assertNull($field->getData()); $this->assertSame('', $field->getViewData()); } public function testSubmitMultipleNull() { $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => true, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, )); $field->submit(null); $this->assertEquals(new ArrayCollection(), $field->getData()); $this->assertSame(array(), $field->getViewData()); } public function testSubmitSingleNonExpandedSingleIdentifier() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $this->persist(array($entity1, $entity2)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => false, 'expanded' => false, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'property' => 'name', )); $field->submit('2'); $this->assertTrue($field->isSynchronized()); $this->assertSame($entity2, $field->getData()); $this->assertSame('2', $field->getViewData()); } public function testSubmitSingleNonExpandedCompositeIdentifier() { $entity1 = new CompositeIntIdEntity(10, 20, 'Foo'); $entity2 = new CompositeIntIdEntity(30, 40, 'Bar'); $this->persist(array($entity1, $entity2)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => false, 'expanded' => false, 'em' => 'default', 'class' => self::COMPOSITE_IDENT_CLASS, 'property' => 'name', )); // the collection key is used here $field->submit('1'); $this->assertTrue($field->isSynchronized()); $this->assertSame($entity2, $field->getData()); $this->assertSame('1', $field->getViewData()); } public function testSubmitMultipleNonExpandedSingleIdentifier() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $entity3 = new SingleIntIdEntity(3, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => true, 'expanded' => false, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'property' => 'name', )); $field->submit(array('1', '3')); $expected = new ArrayCollection(array($entity1, $entity3)); $this->assertTrue($field->isSynchronized()); $this->assertEquals($expected, $field->getData()); $this->assertSame(array('1', '3'), $field->getViewData()); } public function testSubmitMultipleNonExpandedSingleIdentifierForExistingData() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $entity3 = new SingleIntIdEntity(3, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => true, 'expanded' => false, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'property' => 'name', )); $existing = new ArrayCollection(array(0 => $entity2)); $field->setData($existing); $field->submit(array('1', '3')); // entry with index 0 ($entity2) was replaced $expected = new ArrayCollection(array(0 => $entity1, 1 => $entity3)); $this->assertTrue($field->isSynchronized()); $this->assertEquals($expected, $field->getData()); // same object still, useful if it is a PersistentCollection $this->assertSame($existing, $field->getData()); $this->assertSame(array('1', '3'), $field->getViewData()); } public function testSubmitMultipleNonExpandedCompositeIdentifier() { $entity1 = new CompositeIntIdEntity(10, 20, 'Foo'); $entity2 = new CompositeIntIdEntity(30, 40, 'Bar'); $entity3 = new CompositeIntIdEntity(50, 60, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => true, 'expanded' => false, 'em' => 'default', 'class' => self::COMPOSITE_IDENT_CLASS, 'property' => 'name', )); // because of the composite key collection keys are used $field->submit(array('0', '2')); $expected = new ArrayCollection(array($entity1, $entity3)); $this->assertTrue($field->isSynchronized()); $this->assertEquals($expected, $field->getData()); $this->assertSame(array('0', '2'), $field->getViewData()); } public function testSubmitMultipleNonExpandedCompositeIdentifierExistingData() { $entity1 = new CompositeIntIdEntity(10, 20, 'Foo'); $entity2 = new CompositeIntIdEntity(30, 40, 'Bar'); $entity3 = new CompositeIntIdEntity(50, 60, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => true, 'expanded' => false, 'em' => 'default', 'class' => self::COMPOSITE_IDENT_CLASS, 'property' => 'name', )); $existing = new ArrayCollection(array(0 => $entity2)); $field->setData($existing); $field->submit(array('0', '2')); // entry with index 0 ($entity2) was replaced $expected = new ArrayCollection(array(0 => $entity1, 1 => $entity3)); $this->assertTrue($field->isSynchronized()); $this->assertEquals($expected, $field->getData()); // same object still, useful if it is a PersistentCollection $this->assertSame($existing, $field->getData()); $this->assertSame(array('0', '2'), $field->getViewData()); } public function testSubmitSingleExpanded() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $this->persist(array($entity1, $entity2)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => false, 'expanded' => true, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'property' => 'name', )); $field->submit('2'); $this->assertTrue($field->isSynchronized()); $this->assertSame($entity2, $field->getData()); $this->assertFalse($field['1']->getData()); $this->assertTrue($field['2']->getData()); $this->assertNull($field['1']->getViewData()); $this->assertSame('2', $field['2']->getViewData()); } public function testSubmitMultipleExpanded() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $entity3 = new SingleIntIdEntity(3, 'Bar'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => true, 'expanded' => true, 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'property' => 'name', )); $field->submit(array('1', '3')); $expected = new ArrayCollection(array($entity1, $entity3)); $this->assertTrue($field->isSynchronized()); $this->assertEquals($expected, $field->getData()); $this->assertTrue($field['1']->getData()); $this->assertFalse($field['2']->getData()); $this->assertTrue($field['3']->getData()); $this->assertSame('1', $field['1']->getViewData()); $this->assertNull($field['2']->getViewData()); $this->assertSame('3', $field['3']->getViewData()); } public function testOverrideChoices() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $entity3 = new SingleIntIdEntity(3, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, // not all persisted entities should be displayed 'choices' => array($entity1, $entity2), 'property' => 'name', )); $field->submit('2'); $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']); $this->assertTrue($field->isSynchronized()); $this->assertSame($entity2, $field->getData()); $this->assertSame('2', $field->getViewData()); } public function testGroupByChoices() { $item1 = new GroupableEntity(1, 'Foo', 'Group1'); $item2 = new GroupableEntity(2, 'Bar', 'Group1'); $item3 = new GroupableEntity(3, 'Baz', 'Group2'); $item4 = new GroupableEntity(4, 'Boo!', null); $this->persist(array($item1, $item2, $item3, $item4)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::ITEM_GROUP_CLASS, 'choices' => array($item1, $item2, $item3, $item4), 'property' => 'name', 'group_by' => 'groupName', )); $field->submit('2'); $this->assertSame('2', $field->getViewData()); $this->assertEquals(array( 'Group1' => array(1 => new ChoiceView($item1, '1', 'Foo'), 2 => new ChoiceView($item2, '2', 'Bar')), 'Group2' => array(3 => new ChoiceView($item3, '3', 'Baz')), '4' => new ChoiceView($item4, '4', 'Boo!') ), $field->createView()->vars['choices']); } public function testPreferredChoices() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $entity3 = new SingleIntIdEntity(3, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'preferred_choices' => array($entity3, $entity2), 'property' => 'name', )); $this->assertEquals(array(3 => new ChoiceView($entity3, '3', 'Baz'), 2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['preferred_choices']); $this->assertEquals(array(1 => new ChoiceView($entity1, '1', 'Foo')), $field->createView()->vars['choices']); } public function testOverrideChoicesWithPreferredChoices() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $entity3 = new SingleIntIdEntity(3, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'choices' => array($entity2, $entity3), 'preferred_choices' => array($entity3), 'property' => 'name', )); $this->assertEquals(array(3 => new ChoiceView($entity3, '3', 'Baz')), $field->createView()->vars['preferred_choices']); $this->assertEquals(array(2 => new ChoiceView($entity2, '2', 'Bar')), $field->createView()->vars['choices']); } public function testDisallowChoicesThatAreNotIncludedChoicesSingleIdentifier() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $entity3 = new SingleIntIdEntity(3, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'choices' => array($entity1, $entity2), 'property' => 'name', )); $field->submit('3'); $this->assertFalse($field->isSynchronized()); $this->assertNull($field->getData()); } public function testDisallowChoicesThatAreNotIncludedChoicesCompositeIdentifier() { $entity1 = new CompositeIntIdEntity(10, 20, 'Foo'); $entity2 = new CompositeIntIdEntity(30, 40, 'Bar'); $entity3 = new CompositeIntIdEntity(50, 60, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::COMPOSITE_IDENT_CLASS, 'choices' => array($entity1, $entity2), 'property' => 'name', )); $field->submit('2'); $this->assertFalse($field->isSynchronized()); $this->assertNull($field->getData()); } public function testDisallowChoicesThatAreNotIncludedQueryBuilderSingleIdentifier() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $entity3 = new SingleIntIdEntity(3, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $repository = $this->em->getRepository(self::SINGLE_IDENT_CLASS); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'query_builder' => $repository->createQueryBuilder('e') ->where('e.id IN (1, 2)'), 'property' => 'name', )); $field->submit('3'); $this->assertFalse($field->isSynchronized()); $this->assertNull($field->getData()); } public function testDisallowChoicesThatAreNotIncludedQueryBuilderAsClosureSingleIdentifier() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); $entity3 = new SingleIntIdEntity(3, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::SINGLE_IDENT_CLASS, 'query_builder' => function ($repository) { return $repository->createQueryBuilder('e') ->where('e.id IN (1, 2)'); }, 'property' => 'name', )); $field->submit('3'); $this->assertFalse($field->isSynchronized()); $this->assertNull($field->getData()); } public function testDisallowChoicesThatAreNotIncludedQueryBuilderAsClosureCompositeIdentifier() { $entity1 = new CompositeIntIdEntity(10, 20, 'Foo'); $entity2 = new CompositeIntIdEntity(30, 40, 'Bar'); $entity3 = new CompositeIntIdEntity(50, 60, 'Baz'); $this->persist(array($entity1, $entity2, $entity3)); $field = $this->factory->createNamed('name', 'entity', null, array( 'em' => 'default', 'class' => self::COMPOSITE_IDENT_CLASS, 'query_builder' => function ($repository) { return $repository->createQueryBuilder('e') ->where('e.id1 IN (10, 50)'); }, 'property' => 'name', )); $field->submit('2'); $this->assertFalse($field->isSynchronized()); $this->assertNull($field->getData()); } public function testSubmitSingleStringIdentifier() { $entity1 = new SingleStringIdEntity('foo', 'Foo'); $this->persist(array($entity1)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => false, 'expanded' => false, 'em' => 'default', 'class' => self::SINGLE_STRING_IDENT_CLASS, 'property' => 'name', )); $field->submit('foo'); $this->assertTrue($field->isSynchronized()); $this->assertSame($entity1, $field->getData()); $this->assertSame('foo', $field->getViewData()); } public function testSubmitCompositeStringIdentifier() { $entity1 = new CompositeStringIdEntity('foo1', 'foo2', 'Foo'); $this->persist(array($entity1)); $field = $this->factory->createNamed('name', 'entity', null, array( 'multiple' => false, 'expanded' => false, 'em' => 'default', 'class' => self::COMPOSITE_STRING_IDENT_CLASS, 'property' => 'name', )); // the collection key is used here $field->submit('0'); $this->assertTrue($field->isSynchronized()); $this->assertSame($entity1, $field->getData()); $this->assertSame('0', $field->getViewData()); } public function testGetManagerForClassIfNoEm() { $this->emRegistry->expects($this->never()) ->method('getManager'); $this->emRegistry->expects($this->once()) ->method('getManagerForClass') ->with(self::SINGLE_IDENT_CLASS) ->will($this->returnValue($this->em)); $this->factory->createNamed('name', 'entity', null, array( 'class' => self::SINGLE_IDENT_CLASS, 'required' => false, 'property' => 'name' )); } protected function createRegistryMock($name, $em) { $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry'); $registry->expects($this->any()) ->method('getManager') ->with($this->equalTo($name)) ->will($this->returnValue($em)); return $registry; } } PK!ImYtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Form\Type; use Symfony\Component\Form\Tests\FormPerformanceTestCase; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity; use Doctrine\ORM\Tools\SchemaTool; use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase; use Symfony\Component\Form\Extension\Core\CoreExtension; use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension; /** * @author Bernhard Schussek */ class EntityTypePerformanceTest extends FormPerformanceTestCase { const ENTITY_CLASS = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; /** * @var \Doctrine\ORM\EntityManager */ private $em; protected function getExtensions() { $manager = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry'); $manager->expects($this->any()) ->method('getManager') ->will($this->returnValue($this->em)); $manager->expects($this->any()) ->method('getManagerForClass') ->will($this->returnValue($this->em)); return array( new CoreExtension(), new DoctrineOrmExtension($manager) ); } protected function setUp() { $this->em = DoctrineOrmTestCase::createTestEntityManager(); parent::setUp(); $schemaTool = new SchemaTool($this->em); $classes = array( $this->em->getClassMetadata(self::ENTITY_CLASS), ); try { $schemaTool->dropSchema($classes); } catch (\Exception $e) { } try { $schemaTool->createSchema($classes); } catch (\Exception $e) { } $ids = range(1, 300); foreach ($ids as $id) { $name = 65 + chr($id % 57); $this->em->persist(new SingleIntIdEntity($id, $name)); } $this->em->flush(); } /** * This test case is realistic in collection forms where each * row contains the same entity field. * * @group benchmark */ public function testCollapsedEntityField() { $this->setMaxRunningTime(1); for ($i = 0; $i < 40; ++$i) { $form = $this->factory->create('entity', null, array( 'class' => self::ENTITY_CLASS, )); // force loading of the choice list $form->createView(); } } /** * @group benchmark */ public function testCollapsedEntityFieldWithChoices() { $choices = $this->em->createQuery('SELECT c FROM '.self::ENTITY_CLASS.' c')->getResult(); $this->setMaxRunningTime(1); for ($i = 0; $i < 40; ++$i) { $form = $this->factory->create('entity', null, array( 'class' => self::ENTITY_CLASS, 'choices' => $choices, )); // force loading of the choice list $form->createView(); } } /** * @group benchmark */ public function testCollapsedEntityFieldWithPreferredChoices() { $choices = $this->em->createQuery('SELECT c FROM '.self::ENTITY_CLASS.' c')->getResult(); $this->setMaxRunningTime(1); for ($i = 0; $i < 40; ++$i) { $form = $this->factory->create('entity', null, array( 'class' => self::ENTITY_CLASS, 'preferred_choices' => $choices, )); // force loading of the choice list $form->createView(); } } } PK!; Ztest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Security\User; use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; use Symfony\Bridge\Doctrine\Tests\Fixtures\User; use Symfony\Bridge\Doctrine\Security\User\EntityUserProvider; use Doctrine\ORM\Tools\SchemaTool; class EntityUserProviderTest extends \PHPUnit_Framework_TestCase { public function testRefreshUserGetsUserByPrimaryKey() { $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $user1 = new User(1, 1, 'user1'); $user2 = new User(1, 2, 'user2'); $em->persist($user1); $em->persist($user2); $em->flush(); $provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name'); // try to change the user identity $user1->name = 'user2'; $this->assertSame($user1, $provider->refreshUser($user1)); } public function testRefreshUserRequiresId() { $em = DoctrineTestHelper::createTestEntityManager(); $user1 = new User(null, null, 'user1'); $provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name'); $this->setExpectedException( 'InvalidArgumentException', 'You cannot refresh a user from the EntityUserProvider that does not contain an identifier. The user object has to be serialized with its own identifier mapped by Doctrine' ); $provider->refreshUser($user1); } public function testRefreshInvalidUser() { $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $user1 = new User(1, 1, 'user1'); $em->persist($user1); $em->flush(); $provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name'); $user2 = new User(1, 2, 'user2'); $this->setExpectedException( 'Symfony\Component\Security\Core\Exception\UsernameNotFoundException', 'User with id {"id1":1,"id2":2} not found' ); $provider->refreshUser($user2); } public function testSupportProxy() { $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $user1 = new User(1, 1, 'user1'); $em->persist($user1); $em->flush(); $em->clear(); $provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name'); $user2 = $em->getReference('Symfony\Bridge\Doctrine\Tests\Fixtures\User', array('id1' => 1, 'id2' => 1)); $this->assertTrue($provider->supportsClass(get_class($user2))); } private function getManager($em, $name = null) { $manager = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry'); $manager->expects($this->once()) ->method('getManager') ->with($this->equalTo($name)) ->will($this->returnValue($em)); return $manager; } private function createSchema($em) { $schemaTool = new SchemaTool($em); $schemaTool->createSchema(array( $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\User'), )); } } PK!}u>u>_test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\Validator\Constraints; use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; use Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity; use Symfony\Component\Validator\DefaultTranslator; use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Validator; use Doctrine\ORM\Tools\SchemaTool; class UniqueValidatorTest extends \PHPUnit_Framework_TestCase { protected function createRegistryMock($entityManagerName, $em) { $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry'); $registry->expects($this->any()) ->method('getManager') ->with($this->equalTo($entityManagerName)) ->will($this->returnValue($em)); return $registry; } protected function createRepositoryMock() { $repository = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectRepository') ->setMethods(array('findByCustom', 'find', 'findAll', 'findOneBy', 'findBy', 'getClassName')) ->getMock() ; return $repository; } protected function createEntityManagerMock($repositoryMock) { $em = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectManager') ->getMock() ; $em->expects($this->any()) ->method('getRepository') ->will($this->returnValue($repositoryMock)) ; $classMetadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); $classMetadata ->expects($this->any()) ->method('hasField') ->will($this->returnValue(true)) ; $refl = $this->getMockBuilder('Doctrine\Common\Reflection\StaticReflectionProperty') ->disableOriginalConstructor() ->setMethods(array('getValue')) ->getMock() ; $refl ->expects($this->any()) ->method('getValue') ->will($this->returnValue(true)) ; $classMetadata->reflFields = array('name' => $refl); $em->expects($this->any()) ->method('getClassMetadata') ->will($this->returnValue($classMetadata)) ; return $em; } protected function createValidatorFactory($uniqueValidator) { $validatorFactory = $this->getMock('Symfony\Component\Validator\ConstraintValidatorFactoryInterface'); $validatorFactory->expects($this->any()) ->method('getInstance') ->with($this->isInstanceOf('Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity')) ->will($this->returnValue($uniqueValidator)); return $validatorFactory; } public function createValidator($entityManagerName, $em, $validateClass = null, $uniqueFields = null, $errorPath = null, $repositoryMethod = 'findBy', $ignoreNull = true) { if (!$validateClass) { $validateClass = 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'; } if (!$uniqueFields) { $uniqueFields = array('name'); } $registry = $this->createRegistryMock($entityManagerName, $em); $uniqueValidator = new UniqueEntityValidator($registry); $metadata = new ClassMetadata($validateClass); $constraint = new UniqueEntity(array( 'fields' => $uniqueFields, 'em' => $entityManagerName, 'errorPath' => $errorPath, 'repositoryMethod' => $repositoryMethod, 'ignoreNull' => $ignoreNull )); $metadata->addConstraint($constraint); $metadataFactory = new FakeMetadataFactory(); $metadataFactory->addMetadata($metadata); $validatorFactory = $this->createValidatorFactory($uniqueValidator); return new Validator($metadataFactory, $validatorFactory, new DefaultTranslator()); } private function createSchema($em) { $schemaTool = new SchemaTool($em); $schemaTool->createSchema(array( $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity'), $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity'), $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeIntIdEntity'), $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity'), )); } /** * This is a functional test as there is a large integration necessary to get the validator working. */ public function testValidateUniqueness() { $entityManagerName = "foo"; $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $validator = $this->createValidator($entityManagerName, $em); $entity1 = new SingleIntIdEntity(1, 'Foo'); $violationsList = $validator->validate($entity1); $this->assertEquals(0, $violationsList->count(), "No violations found on entity before it is saved to the database."); $em->persist($entity1); $em->flush(); $violationsList = $validator->validate($entity1); $this->assertEquals(0, $violationsList->count(), "No violations found on entity after it was saved to the database."); $entity2 = new SingleIntIdEntity(2, 'Foo'); $violationsList = $validator->validate($entity2); $this->assertEquals(1, $violationsList->count(), "Violation found on entity with conflicting entity existing in the database."); $violation = $violationsList[0]; $this->assertEquals('This value is already used.', $violation->getMessage()); $this->assertEquals('name', $violation->getPropertyPath()); $this->assertEquals('Foo', $violation->getInvalidValue()); } public function testValidateCustomErrorPath() { $entityManagerName = "foo"; $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $validator = $this->createValidator($entityManagerName, $em, null, null, 'bar'); $entity1 = new SingleIntIdEntity(1, 'Foo'); $em->persist($entity1); $em->flush(); $entity2 = new SingleIntIdEntity(2, 'Foo'); $violationsList = $validator->validate($entity2); $this->assertEquals(1, $violationsList->count(), "Violation found on entity with conflicting entity existing in the database."); $violation = $violationsList[0]; $this->assertEquals('This value is already used.', $violation->getMessage()); $this->assertEquals('bar', $violation->getPropertyPath()); $this->assertEquals('Foo', $violation->getInvalidValue()); } public function testValidateUniquenessWithNull() { $entityManagerName = "foo"; $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $validator = $this->createValidator($entityManagerName, $em); $entity1 = new SingleIntIdEntity(1, null); $entity2 = new SingleIntIdEntity(2, null); $em->persist($entity1); $em->persist($entity2); $em->flush(); $violationsList = $validator->validate($entity1); $this->assertEquals(0, $violationsList->count(), "No violations found on entity having a null value."); } public function testValidateUniquenessWithIgnoreNull() { $entityManagerName = "foo"; $validateClass = 'Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity'; $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $validator = $this->createValidator($entityManagerName, $em, $validateClass, array('name', 'name2'), 'bar', 'findby', false); $entity1 = new DoubleNameEntity(1, 'Foo', null); $violationsList = $validator->validate($entity1); $this->assertEquals(0, $violationsList->count(), "No violations found on entity before it is saved to the database."); $em->persist($entity1); $em->flush(); $violationsList = $validator->validate($entity1); $this->assertEquals(0, $violationsList->count(), "No violations found on entity after it was saved to the database."); $entity2 = new DoubleNameEntity(2, 'Foo', null); $violationsList = $validator->validate($entity2); $this->assertEquals(1, $violationsList->count(), "Violation found on entity with conflicting entity existing in the database."); $violation = $violationsList[0]; $this->assertEquals('This value is already used.', $violation->getMessage()); $this->assertEquals('bar', $violation->getPropertyPath()); $this->assertEquals('Foo', $violation->getInvalidValue()); } public function testValidateUniquenessAfterConsideringMultipleQueryResults() { $entityManagerName = "foo"; $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $validator = $this->createValidator($entityManagerName, $em); $entity1 = new SingleIntIdEntity(1, 'foo'); $entity2 = new SingleIntIdEntity(2, 'foo'); $em->persist($entity1); $em->persist($entity2); $em->flush(); $violationsList = $validator->validate($entity1); $this->assertEquals(1, $violationsList->count(), 'Violation found on entity with conflicting entity existing in the database.'); $violationsList = $validator->validate($entity2); $this->assertEquals(1, $violationsList->count(), 'Violation found on entity with conflicting entity existing in the database.'); } public function testValidateUniquenessUsingCustomRepositoryMethod() { $entityManagerName = 'foo'; $repository = $this->createRepositoryMock(); $repository->expects($this->once()) ->method('findByCustom') ->will($this->returnValue(array())) ; $em = $this->createEntityManagerMock($repository); $validator = $this->createValidator($entityManagerName, $em, null, array(), null, 'findByCustom'); $entity1 = new SingleIntIdEntity(1, 'foo'); $violationsList = $validator->validate($entity1); $this->assertEquals(0, $violationsList->count(), 'Violation is using custom repository method.'); } public function testValidateUniquenessWithUnrewoundArray() { $entity = new SingleIntIdEntity(1, 'foo'); $entityManagerName = 'foo'; $repository = $this->createRepositoryMock(); $repository->expects($this->once()) ->method('findByCustom') ->will( $this->returnCallback(function () use ($entity) { $returnValue = array( $entity, ); next($returnValue); return $returnValue; }) ) ; $em = $this->createEntityManagerMock($repository); $validator = $this->createValidator($entityManagerName, $em, null, array(), null, 'findByCustom'); $violationsList = $validator->validate($entity); $this->assertCount(0, $violationsList, 'Violation is using unrewound array as return value in the repository method.'); } /** * @group GH-1635 */ public function testAssociatedEntity() { $entityManagerName = "foo"; $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $validator = $this->createValidator($entityManagerName, $em, 'Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity', array('single')); $entity1 = new SingleIntIdEntity(1, 'foo'); $associated = new AssociationEntity(); $associated->single = $entity1; $em->persist($entity1); $em->persist($associated); $em->flush(); $violationsList = $validator->validate($associated); $this->assertEquals(0, $violationsList->count()); $associated2 = new AssociationEntity(); $associated2->single = $entity1; $em->persist($associated2); $em->flush(); $violationsList = $validator->validate($associated2); $this->assertEquals(1, $violationsList->count()); } public function testAssociatedEntityWithNull() { $entityManagerName = "foo"; $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $validator = $this->createValidator($entityManagerName, $em, 'Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity', array('single'), null, 'findBy', false); $associated = new AssociationEntity(); $associated->single = null; $em->persist($associated); $em->flush(); $violationsList = $validator->validate($associated); $this->assertEquals(0, $violationsList->count()); } /** * @group GH-1635 */ public function testAssociatedCompositeEntity() { $entityManagerName = "foo"; $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); $validator = $this->createValidator($entityManagerName, $em, 'Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity', array('composite')); $composite = new CompositeIntIdEntity(1, 1, "test"); $associated = new AssociationEntity(); $associated->composite = $composite; $em->persist($composite); $em->persist($associated); $em->flush(); $this->setExpectedException( 'Symfony\Component\Validator\Exception\ConstraintDefinitionException', 'Associated entities are not allowed to have more than one identifier field' ); $violationsList = $validator->validate($associated); } public function testDedicatedEntityManagerNullObject() { $uniqueFields = array('name'); $entityManagerName = 'foo'; $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry'); $constraint = new UniqueEntity(array( 'fields' => $uniqueFields, 'em' => $entityManagerName, )); $uniqueValidator = new UniqueEntityValidator($registry); $entity = new SingleIntIdEntity(1, null); $this->setExpectedException( 'Symfony\Component\Validator\Exception\ConstraintDefinitionException', 'Object manager "foo" does not exist.' ); $uniqueValidator->validate($entity, $constraint); } public function testEntityManagerNullObject() { $uniqueFields = array('name'); $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry'); $constraint = new UniqueEntity(array( 'fields' => $uniqueFields, )); $uniqueValidator = new UniqueEntityValidator($registry); $entity = new SingleIntIdEntity(1, null); $this->setExpectedException( 'Symfony\Component\Validator\Exception\ConstraintDefinitionException', 'Unable to find the object manager associated with an entity of class "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity"' ); $uniqueValidator->validate($entity, $constraint); } } PK!,`test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\ExpressionLanguage; use Symfony\Bridge\Doctrine\ExpressionLanguage\DoctrineParserCache; class DoctrineParserCacheTest extends \PHPUnit_Framework_TestCase { public function testFetch() { $doctrineCacheMock = $this->getMock('Doctrine\Common\Cache\Cache'); $parserCache = new DoctrineParserCache($doctrineCacheMock); $doctrineCacheMock->expects($this->once()) ->method('fetch') ->will($this->returnValue('bar')); $result = $parserCache->fetch('foo'); $this->assertEquals('bar', $result); } public function testFetchUnexisting() { $doctrineCacheMock = $this->getMock('Doctrine\Common\Cache\Cache'); $parserCache = new DoctrineParserCache($doctrineCacheMock); $doctrineCacheMock ->expects($this->once()) ->method('fetch') ->will($this->returnValue(false)); $this->assertNull($parserCache->fetch('')); } public function testSave() { $doctrineCacheMock = $this->getMock('Doctrine\Common\Cache\Cache'); $parserCache = new DoctrineParserCache($doctrineCacheMock); $expression = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParsedExpression') ->disableOriginalConstructor() ->getMock(); $doctrineCacheMock->expects($this->once()) ->method('save') ->with('foo', $expression); $parserCache->save('foo', $expression); } } PK!$KBBTtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests; use Symfony\Bridge\Doctrine\ContainerAwareEventManager; use Symfony\Component\DependencyInjection\Container; class ContainerAwareEventManagerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { $this->container = new Container(); $this->evm = new ContainerAwareEventManager($this->container); } public function testDispatchEvent() { $this->container->set('foobar', $listener1 = new MyListener()); $this->evm->addEventListener('foo', 'foobar'); $this->evm->addEventListener('foo', $listener2 = new MyListener()); $this->evm->dispatchEvent('foo'); $this->assertTrue($listener1->called); $this->assertTrue($listener2->called); } public function testRemoveEventListener() { $this->evm->addEventListener('foo', 'bar'); $this->evm->addEventListener('foo', $listener = new MyListener()); $listeners = array('foo' => array('_service_bar' => 'bar', spl_object_hash($listener) => $listener)); $this->assertSame($listeners, $this->evm->getListeners()); $this->assertSame($listeners['foo'], $this->evm->getListeners('foo')); $this->evm->removeEventListener('foo', $listener); $this->assertSame(array('_service_bar' => 'bar'), $this->evm->getListeners('foo')); $this->evm->removeEventListener('foo', 'bar'); $this->assertSame(array(), $this->evm->getListeners('foo')); } } class MyListener { public $called = false; public function foo() { $this->called = true; } } PK!9qq[test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataFixtures/ContainerAwareLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\DataFixtures; use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader; use Symfony\Bridge\Doctrine\Tests\Fixtures\ContainerAwareFixture; class ContainerAwareLoaderTest extends \PHPUnit_Framework_TestCase { public function testShouldSetContainerOnContainerAwareFixture() { $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); $loader = new ContainerAwareLoader($container); $fixture = new ContainerAwareFixture(); $loader->addFixture($fixture); $this->assertSame($container, $fixture->container); } } PK!CII[test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\HttpFoundation; use Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler; /** * Test class for DbalSessionHandler. * * @author Drak */ class DbalSessionHandlerTest extends \PHPUnit_Framework_TestCase { public function testConstruct() { $this->connection = $this->getMock('Doctrine\DBAL\Driver\Connection'); $mock = $this->getMockBuilder('Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler'); $mock->setConstructorArgs(array($this->connection)); $this->driver = $mock->getMock(); } } PK!l]test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\DataCollector; use Doctrine\DBAL\Platforms\MySqlPlatform; use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class DoctrineDataCollectorTest extends \PHPUnit_Framework_TestCase { public function testCollectConnections() { $c = $this->createCollector(array()); $c->collect(new Request(), new Response()); $this->assertEquals(array('default' => 'doctrine.dbal.default_connection'), $c->getConnections()); } public function testCollectManagers() { $c = $this->createCollector(array()); $c->collect(new Request(), new Response()); $this->assertEquals(array('default' => 'doctrine.orm.default_entity_manager'), $c->getManagers()); } public function testCollectQueryCount() { $c = $this->createCollector(array()); $c->collect(new Request(), new Response()); $this->assertEquals(0, $c->getQueryCount()); $queries = array( array('sql' => "SELECT * FROM table1", 'params' => array(), 'types' => array(), 'executionMS' => 0) ); $c = $this->createCollector($queries); $c->collect(new Request(), new Response()); $this->assertEquals(1, $c->getQueryCount()); } public function testCollectTime() { $c = $this->createCollector(array()); $c->collect(new Request(), new Response()); $this->assertEquals(0, $c->getTime()); $queries = array( array('sql' => "SELECT * FROM table1", 'params' => array(), 'types' => array(), 'executionMS' => 1) ); $c = $this->createCollector($queries); $c->collect(new Request(), new Response()); $this->assertEquals(1, $c->getTime()); $queries = array( array('sql' => "SELECT * FROM table1", 'params' => array(), 'types' => array(), 'executionMS' => 1), array('sql' => "SELECT * FROM table2", 'params' => array(), 'types' => array(), 'executionMS' => 2) ); $c = $this->createCollector($queries); $c->collect(new Request(), new Response()); $this->assertEquals(3, $c->getTime()); } /** * @dataProvider paramProvider */ public function testCollectQueries($param, $types, $expected, $explainable) { $queries = array( array('sql' => "SELECT * FROM table1 WHERE field1 = ?1", 'params' => array($param), 'types' => $types, 'executionMS' => 1) ); $c = $this->createCollector($queries); $c->collect(new Request(), new Response()); $collected_queries = $c->getQueries(); $this->assertEquals($expected, $collected_queries['default'][0]['params'][0]); $this->assertEquals($explainable, $collected_queries['default'][0]['explainable']); } /** * @dataProvider paramProvider */ public function testSerialization($param, $types, $expected, $explainable) { $queries = array( array('sql' => "SELECT * FROM table1 WHERE field1 = ?1", 'params' => array($param), 'types' => $types, 'executionMS' => 1) ); $c = $this->createCollector($queries); $c->collect(new Request(), new Response()); $c = unserialize(serialize($c)); $collected_queries = $c->getQueries(); $this->assertEquals($expected, $collected_queries['default'][0]['params'][0]); $this->assertEquals($explainable, $collected_queries['default'][0]['explainable']); } public function paramProvider() { return array( array('some value', array(), 'some value', true), array(1, array(), 1, true), array(true, array(), true, true), array(null, array(), null, true), array(new \DateTime('2011-09-11'), array('date'), '2011-09-11', true), array(fopen(__FILE__, 'r'), array(), 'Resource(stream)', false), array(new \SplFileInfo(__FILE__), array(), 'Object(SplFileInfo)', false), ); } private function createCollector($queries) { $connection = $this->getMockBuilder('Doctrine\DBAL\Connection') ->disableOriginalConstructor() ->getMock(); $connection->expects($this->any()) ->method('getDatabasePlatform') ->will($this->returnValue(new MySqlPlatform())); $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry'); $registry ->expects($this->any()) ->method('getConnectionNames') ->will($this->returnValue(array('default' => 'doctrine.dbal.default_connection'))); $registry ->expects($this->any()) ->method('getManagerNames') ->will($this->returnValue(array('default' => 'doctrine.orm.default_entity_manager'))); $registry->expects($this->any()) ->method('getConnection') ->will($this->returnValue($connection)); $logger = $this->getMock('Doctrine\DBAL\Logging\DebugStack'); $logger->queries = $queries; $collector = new DoctrineDataCollector($registry); $collector->addLogger('default', $logger); return $collector; } } PK!Otest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Tests\DependencyInjection\CompilerPass; use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass; use Symfony\Component\DependencyInjection\ContainerBuilder; class RegisterEventListenersAndSubscribersPassTest extends \PHPUnit_Framework_TestCase { public function testProcessEventListenersWithPriorities() { $container = $this->createBuilder(); $container ->register('a', 'stdClass') ->addTag('doctrine.event_listener', array( 'event' => 'foo', 'priority' => -5, )) ->addTag('doctrine.event_listener', array( 'event' => 'bar', )) ; $container ->register('b', 'stdClass') ->addTag('doctrine.event_listener', array( 'event' => 'foo', )) ; $this->process($container); $this->assertEquals(array('b', 'a'), $this->getServiceOrder($container, 'addEventListener')); $calls = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls(); $this->assertEquals(array('foo', 'bar'), $calls[1][1][0]); } public function testProcessEventListenersWithMultipleConnections() { $container = $this->createBuilder(true); $container ->register('a', 'stdClass') ->addTag('doctrine.event_listener', array( 'event' => 'onFlush', )) ; $this->process($container); $callsDefault = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls(); $this->assertEquals('addEventListener', $callsDefault[0][0]); $this->assertEquals(array('onFlush'), $callsDefault[0][1][0]); $callsSecond = $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls(); $this->assertEquals($callsDefault, $callsSecond); } public function testProcessEventSubscribersWithPriorities() { $container = $this->createBuilder(); $container ->register('a', 'stdClass') ->addTag('doctrine.event_subscriber') ; $container ->register('b', 'stdClass') ->addTag('doctrine.event_subscriber', array( 'priority' => 5, )) ; $container ->register('c', 'stdClass') ->addTag('doctrine.event_subscriber', array( 'priority' => 10, )) ; $container ->register('d', 'stdClass') ->addTag('doctrine.event_subscriber', array( 'priority' => 10, )) ; $container ->register('e', 'stdClass') ->addTag('doctrine.event_subscriber', array( 'priority' => 10, )) ; $this->process($container); $this->assertEquals(array('c', 'd', 'e', 'b', 'a'), $this->getServiceOrder($container, 'addEventSubscriber')); } public function testProcessNoTaggedServices() { $container = $this->createBuilder(true); $this->process($container); $this->assertEquals(array(), $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls()); $this->assertEquals(array(), $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls()); } private function process(ContainerBuilder $container) { $pass = new RegisterEventListenersAndSubscribersPass('doctrine.connections', 'doctrine.dbal.%s_connection.event_manager', 'doctrine'); $pass->process($container); } private function getServiceOrder(ContainerBuilder $container, $method) { $order = array(); foreach ($container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls() as $call) { list($name, $arguments) = $call; if ($method !== $name) { continue; } if ('addEventListener' === $name) { $order[] = (string) $arguments[1]; continue; } $order[] = (string) $arguments[0]; } return $order; } private function createBuilder($multipleConnections = false) { $container = new ContainerBuilder(); $connections = array('default' => 'doctrine.dbal.default_connection'); $container->register('doctrine.dbal.default_connection.event_manager', 'stdClass'); $container->register('doctrine.dbal.default_connection', 'stdClass'); if ($multipleConnections) { $container->register('doctrine.dbal.second_connection.event_manager', 'stdClass'); $container->register('doctrine.dbal.second_connection', 'stdClass'); $connections['second'] = 'doctrine.dbal.second_connection'; } $container->setParameter('doctrine.connections', $connections); return $container; } } PK!ޠ77<test/DoctrineBridge/Symfony/Bridge/Doctrine/phpunit.xml.distnu[ ./Tests/ ./ ./Resources ./Tests PK!&ǦGGNtest/MonologBridge/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog\Tests\Handler; use Monolog\Logger; use Symfony\Bridge\Monolog\Handler\ConsoleHandler; use Symfony\Component\Console\Output\OutputInterface; /** * Tests the ConsoleHandler and also the ConsoleFormatter. * * @author Tobias Schultze */ class ConsoleHandlerTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $handler = new ConsoleHandler(null, false); $this->assertFalse($handler->getBubble(), 'the bubble parameter gets propagated'); } public function testIsHandling() { $handler = new ConsoleHandler(); $this->assertFalse($handler->isHandling(array()), '->isHandling returns false when no output is set'); } /** * @dataProvider provideVerbosityMappingTests */ public function testVerbosityMapping($verbosity, $level, $isHandling, array $map = array()) { $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); $output ->expects($this->atLeastOnce()) ->method('getVerbosity') ->will($this->returnValue($verbosity)) ; $handler = new ConsoleHandler($output, true, $map); $this->assertSame($isHandling, $handler->isHandling(array('level' => $level)), '->isHandling returns correct value depending on console verbosity and log level' ); } public function provideVerbosityMappingTests() { return array( array(OutputInterface::VERBOSITY_QUIET, Logger::ERROR, false), array(OutputInterface::VERBOSITY_NORMAL, Logger::WARNING, true), array(OutputInterface::VERBOSITY_NORMAL, Logger::NOTICE, false), array(OutputInterface::VERBOSITY_VERBOSE, Logger::NOTICE, true), array(OutputInterface::VERBOSITY_VERBOSE, Logger::INFO, false), array(OutputInterface::VERBOSITY_VERY_VERBOSE, Logger::INFO, true), array(OutputInterface::VERBOSITY_VERY_VERBOSE, Logger::DEBUG, false), array(OutputInterface::VERBOSITY_DEBUG, Logger::DEBUG, true), array(OutputInterface::VERBOSITY_DEBUG, Logger::EMERGENCY, true), array(OutputInterface::VERBOSITY_NORMAL, Logger::NOTICE, true, array( OutputInterface::VERBOSITY_NORMAL => Logger::NOTICE )), array(OutputInterface::VERBOSITY_DEBUG, Logger::NOTICE, true, array( OutputInterface::VERBOSITY_NORMAL => Logger::NOTICE )), ); } public function testVerbosityChanged() { $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); $output ->expects($this->at(0)) ->method('getVerbosity') ->will($this->returnValue(OutputInterface::VERBOSITY_QUIET)) ; $output ->expects($this->at(1)) ->method('getVerbosity') ->will($this->returnValue(OutputInterface::VERBOSITY_DEBUG)) ; $handler = new ConsoleHandler($output); $this->assertFalse($handler->isHandling(array('level' => Logger::NOTICE)), 'when verbosity is set to quiet, the handler does not handle the log' ); $this->assertTrue($handler->isHandling(array('level' => Logger::NOTICE)), 'since the verbosity of the output increased externally, the handler is now handling the log' ); } public function testGetFormatter() { $handler = new ConsoleHandler(); $this->assertInstanceOf('Symfony\Bridge\Monolog\Formatter\ConsoleFormatter', $handler->getFormatter(), '-getFormatter returns ConsoleFormatter by default' ); } public function testWritingAndFormatting() { $output = $this->getMock('Symfony\Component\Console\Output\ConsoleOutputInterface'); $output ->expects($this->any()) ->method('getVerbosity') ->will($this->returnValue(OutputInterface::VERBOSITY_DEBUG)) ; $output ->expects($this->once()) ->method('write') ->with('[2013-05-29 16:21:54] app.INFO: My info message [] []'."\n") ; $errorOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); $errorOutput ->expects($this->once()) ->method('write') ->with('[2013-05-29 16:21:54] app.ERROR: My error message [] []'."\n") ; $output ->expects($this->any()) ->method('getErrorOutput') ->will($this->returnValue($errorOutput)) ; $handler = new ConsoleHandler(null, false); $handler->setOutput($output); $infoRecord = array( 'message' => 'My info message', 'context' => array(), 'level' => Logger::INFO, 'level_name' => Logger::getLevelName(Logger::INFO), 'channel' => 'app', 'datetime' => new \DateTime('2013-05-29 16:21:54'), 'extra' => array(), ); $this->assertTrue($handler->handle($infoRecord), 'The handler finished handling the log as bubble is false.'); $errorRecord = array( 'message' => 'My error message', 'context' => array(), 'level' => Logger::ERROR, 'level_name' => Logger::getLevelName(Logger::ERROR), 'channel' => 'app', 'datetime' => new \DateTime('2013-05-29 16:21:54'), 'extra' => array(), ); $this->assertTrue($handler->handle($errorRecord), 'The handler finished handling the log as bubble is false.'); } } PK!o.Ntest/MonologBridge/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Monolog\Tests\Processor; use Monolog\Logger; use Symfony\Bridge\Monolog\Processor\WebProcessor; use Symfony\Component\HttpFoundation\Request; class WebProcessorTest extends \PHPUnit_Framework_TestCase { public function testUsesRequestServerData() { $server = array( 'REQUEST_URI' => 'A', 'REMOTE_ADDR' => 'B', 'REQUEST_METHOD' => 'C', 'SERVER_NAME' => 'D', 'HTTP_REFERER' => 'E' ); $request = new Request(); $request->server->replace($server); $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') ->disableOriginalConstructor() ->getMock(); $event->expects($this->any()) ->method('isMasterRequest') ->will($this->returnValue(true)); $event->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)); $processor = new WebProcessor(); $processor->onKernelRequest($event); $record = $processor($this->getRecord()); $this->assertEquals($server['REQUEST_URI'], $record['extra']['url']); $this->assertEquals($server['REMOTE_ADDR'], $record['extra']['ip']); $this->assertEquals($server['REQUEST_METHOD'], $record['extra']['http_method']); $this->assertEquals($server['SERVER_NAME'], $record['extra']['server']); $this->assertEquals($server['HTTP_REFERER'], $record['extra']['referrer']); } /** * @param integer $level * @param string $message * * @return array Record */ protected function getRecord($level = Logger::WARNING, $message = 'test') { return array( 'message' => $message, 'context' => array(), 'level' => $level, 'level_name' => Logger::getLevelName($level), 'channel' => 'test', 'datetime' => new \DateTime(), 'extra' => array(), ); } } PK!Ki66:test/MonologBridge/Symfony/Bridge/Monolog/phpunit.xml.distnu[ ./Tests/ ./ ./Resources ./Tests PK!}/66Mtest/Templating/Symfony/Component/Templating/Tests/TemplateNameParserTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests; use Symfony\Component\Templating\TemplateNameParser; use Symfony\Component\Templating\TemplateReference; class TemplateNameParserTest extends \PHPUnit_Framework_TestCase { protected $parser; protected function setUp() { $this->parser = new TemplateNameParser(); } protected function tearDown() { $this->parser = null; } /** * @dataProvider getLogicalNameToTemplateProvider */ public function testParse($name, $ref) { $template = $this->parser->parse($name); $this->assertEquals($template->getLogicalName(), $ref->getLogicalName()); $this->assertEquals($template->getLogicalName(), $name); } public function getLogicalNameToTemplateProvider() { return array( array('/path/to/section/name.engine', new TemplateReference('/path/to/section/name.engine', 'engine')), array('name.engine', new TemplateReference('name.engine', 'engine')), array('name', new TemplateReference('name')), ); } } PK!xxLtest/Templating/Symfony/Component/Templating/Tests/Fixtures/SimpleHelper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Fixtures; use Symfony\Component\Templating\Helper\Helper; class SimpleHelper extends Helper { protected $value = ''; public function __construct($value) { $this->value = $value; } public function __toString() { return $this->value; } public function getName() { return 'foo'; } } PK!`2Mtest/Templating/Symfony/Component/Templating/Tests/Fixtures/templates/foo.phpnu[ PK!=DNtest/Templating/Symfony/Component/Templating/Tests/Storage/FileStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Storage; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\Storage\FileStorage; class FileStorageTest extends \PHPUnit_Framework_TestCase { public function testGetContent() { $storage = new FileStorage('foo'); $this->assertInstanceOf('Symfony\Component\Templating\Storage\Storage', $storage, 'FileStorage is an instance of Storage'); $storage = new FileStorage(__DIR__.'/../Fixtures/templates/foo.php'); $this->assertEquals(''."\n", $storage->getContent(), '->getContent() returns the content of the template'); } } PK!` 7SSPtest/Templating/Symfony/Component/Templating/Tests/Storage/StringStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Storage; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\Storage\StringStorage; class StringStorageTest extends \PHPUnit_Framework_TestCase { public function testGetContent() { $storage = new StringStorage('foo'); $this->assertInstanceOf('Symfony\Component\Templating\Storage\Storage', $storage, 'StringStorage is an instance of Storage'); $storage = new StringStorage('foo'); $this->assertEquals('foo', $storage->getContent(), '->getContent() returns the content of the template'); } } PK!S ٦Jtest/Templating/Symfony/Component/Templating/Tests/Storage/StorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Storage; use Symfony\Component\Templating\Storage\Storage; class StorageTest extends \PHPUnit_Framework_TestCase { public function testMagicToString() { $storage = new TestStorage('foo'); $this->assertEquals('foo', (string) $storage, '__toString() returns the template name'); } } class TestStorage extends Storage { public function getContent() { } } PK!7Htest/Templating/Symfony/Component/Templating/Tests/Loader/LoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Loader; use Symfony\Component\Templating\Loader\Loader; use Symfony\Component\Templating\TemplateReferenceInterface; class LoaderTest extends \PHPUnit_Framework_TestCase { public function testGetSetLogger() { $loader = new ProjectTemplateLoader4(); $logger = $this->getMock('Psr\Log\LoggerInterface'); $loader->setLogger($logger); $this->assertSame($logger, $loader->getLogger(), '->setLogger() sets the logger instance'); } public function testGetSetDebugger() { $loader = new ProjectTemplateLoader4(); $debugger = $this->getMock('Symfony\Component\Templating\DebuggerInterface'); $loader->setDebugger($debugger); $this->assertSame($debugger, $loader->getDebugger(), '->setDebugger() sets the debugger instance'); } } class ProjectTemplateLoader4 extends Loader { public function load(TemplateReferenceInterface $template) { } public function getLogger() { return $this->logger; } public function getDebugger() { return $this->debugger; } public function isFresh(TemplateReferenceInterface $template, $time) { return false; } } PK!Wl‡Rtest/Templating/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Loader; use Symfony\Component\Templating\Loader\FilesystemLoader; use Symfony\Component\Templating\Storage\FileStorage; use Symfony\Component\Templating\TemplateReference; class FilesystemLoaderTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; public static function setUpBeforeClass() { self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); } public function testConstructor() { $pathPattern = self::$fixturesPath.'/templates/%name%.%engine%'; $path = self::$fixturesPath.'/templates'; $loader = new ProjectTemplateLoader2($pathPattern); $this->assertEquals(array($pathPattern), $loader->getTemplatePathPatterns(), '__construct() takes a path as its second argument'); $loader = new ProjectTemplateLoader2(array($pathPattern)); $this->assertEquals(array($pathPattern), $loader->getTemplatePathPatterns(), '__construct() takes an array of paths as its second argument'); } public function testIsAbsolutePath() { $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('/foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path'); $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('c:\\\\foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path'); $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('c:/foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path'); $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('\\server\\foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path'); $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('https://server/foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path'); $this->assertTrue(ProjectTemplateLoader2::isAbsolutePath('phar://server/foo.xml'), '->isAbsolutePath() returns true if the path is an absolute path'); } public function testLoad() { $pathPattern = self::$fixturesPath.'/templates/%name%'; $path = self::$fixturesPath.'/templates'; $loader = new ProjectTemplateLoader2($pathPattern); $storage = $loader->load(new TemplateReference($path.'/foo.php', 'php')); $this->assertInstanceOf('Symfony\Component\Templating\Storage\FileStorage', $storage, '->load() returns a FileStorage if you pass an absolute path'); $this->assertEquals($path.'/foo.php', (string) $storage, '->load() returns a FileStorage pointing to the passed absolute path'); $this->assertFalse($loader->load(new TemplateReference('bar', 'php')), '->load() returns false if the template is not found'); $storage = $loader->load(new TemplateReference('foo.php', 'php')); $this->assertInstanceOf('Symfony\Component\Templating\Storage\FileStorage', $storage, '->load() returns a FileStorage if you pass a relative template that exists'); $this->assertEquals($path.'/foo.php', (string) $storage, '->load() returns a FileStorage pointing to the absolute path of the template'); $logger = $this->getMock('Psr\Log\LoggerInterface'); $logger->expects($this->exactly(2))->method('debug'); $loader = new ProjectTemplateLoader2($pathPattern); $loader->setLogger($logger); $this->assertFalse($loader->load(new TemplateReference('foo.xml', 'php')), '->load() returns false if the template does not exist for the given engine'); $loader = new ProjectTemplateLoader2(array(self::$fixturesPath.'/null/%name%', $pathPattern)); $loader->setLogger($logger); $loader->load(new TemplateReference('foo.php', 'php')); } } class ProjectTemplateLoader2 extends FilesystemLoader { public function getTemplatePathPatterns() { return $this->templatePathPatterns; } public static function isAbsolutePath($path) { return parent::isAbsolutePath($path); } } PK! Mtest/Templating/Symfony/Component/Templating/Tests/Loader/CacheLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Loader; use Symfony\Component\Templating\Loader\Loader; use Symfony\Component\Templating\Loader\CacheLoader; use Symfony\Component\Templating\Storage\StringStorage; use Symfony\Component\Templating\TemplateReferenceInterface; use Symfony\Component\Templating\TemplateReference; class CacheLoaderTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $loader = new ProjectTemplateLoader($varLoader = new ProjectTemplateLoaderVar(), sys_get_temp_dir()); $this->assertTrue($loader->getLoader() === $varLoader, '__construct() takes a template loader as its first argument'); $this->assertEquals(sys_get_temp_dir(), $loader->getDir(), '__construct() takes a directory where to store the cache as its second argument'); } public function testLoad() { $dir = sys_get_temp_dir().DIRECTORY_SEPARATOR.rand(111111, 999999); mkdir($dir, 0777, true); $loader = new ProjectTemplateLoader($varLoader = new ProjectTemplateLoaderVar(), $dir); $this->assertFalse($loader->load(new TemplateReference('foo', 'php')), '->load() returns false if the embed loader is not able to load the template'); $logger = $this->getMock('Psr\Log\LoggerInterface'); $logger->expects($this->once())->method('debug')->with('Storing template "index" in cache'); $loader->setLogger($logger); $loader->load(new TemplateReference('index')); $logger = $this->getMock('Psr\Log\LoggerInterface'); $logger->expects($this->once())->method('debug')->with('Fetching template "index" from cache'); $loader->setLogger($logger); $loader->load(new TemplateReference('index')); } } class ProjectTemplateLoader extends CacheLoader { public function getDir() { return $this->dir; } public function getLoader() { return $this->loader; } } class ProjectTemplateLoaderVar extends Loader { public function getIndexTemplate() { return 'Hello World'; } public function getSpecialTemplate() { return 'Hello {{ name }}'; } public function load(TemplateReferenceInterface $template) { if (method_exists($this, $method = 'get'.ucfirst($template->get('name')).'Template')) { return new StringStorage($this->$method()); } return false; } public function isFresh(TemplateReferenceInterface $template, $time) { return false; } } PK!ˡA`Mtest/Templating/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Loader; use Symfony\Component\Templating\Loader\ChainLoader; use Symfony\Component\Templating\Loader\FilesystemLoader; use Symfony\Component\Templating\Storage\FileStorage; use Symfony\Component\Templating\TemplateReference; class ChainLoaderTest extends \PHPUnit_Framework_TestCase { protected $loader1; protected $loader2; protected function setUp() { $fixturesPath = realpath(__DIR__.'/../Fixtures/'); $this->loader1 = new FilesystemLoader($fixturesPath.'/null/%name%'); $this->loader2 = new FilesystemLoader($fixturesPath.'/templates/%name%'); } public function testConstructor() { $loader = new ProjectTemplateLoader1(array($this->loader1, $this->loader2)); $this->assertEquals(array($this->loader1, $this->loader2), $loader->getLoaders(), '__construct() takes an array of template loaders as its second argument'); } public function testAddLoader() { $loader = new ProjectTemplateLoader1(array($this->loader1)); $loader->addLoader($this->loader2); $this->assertEquals(array($this->loader1, $this->loader2), $loader->getLoaders(), '->addLoader() adds a template loader at the end of the loaders'); } public function testLoad() { $loader = new ProjectTemplateLoader1(array($this->loader1, $this->loader2)); $this->assertFalse($loader->load(new TemplateReference('bar', 'php')), '->load() returns false if the template is not found'); $this->assertFalse($loader->load(new TemplateReference('foo', 'php')), '->load() returns false if the template does not exist for the given renderer'); $this->assertInstanceOf( 'Symfony\Component\Templating\Storage\FileStorage', $loader->load(new TemplateReference('foo.php', 'php')), '->load() returns a FileStorage if the template exists' ); } } class ProjectTemplateLoader1 extends ChainLoader { public function getLoaders() { return $this->loaders; } } PK!`n} Ntest/Templating/Symfony/Component/Templating/Tests/Helper/AssetsHelperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Helper; use Symfony\Component\Templating\Helper\AssetsHelper; class AssetsHelperTest extends \PHPUnit_Framework_TestCase { public function testGetVersion() { $helper = new AssetsHelper(null, array(), 'foo'); $this->assertEquals('foo', $helper->getVersion(), '->getVersion() returns the version'); } public function testGetUrl() { $helper = new AssetsHelper(); $this->assertEquals('http://example.com/foo.js', $helper->getUrl('http://example.com/foo.js'), '->getUrl() does nothing if an absolute URL is given'); $helper = new AssetsHelper(); $this->assertEquals('/foo.js', $helper->getUrl('foo.js'), '->getUrl() appends a / on relative paths'); $this->assertEquals('/foo.js', $helper->getUrl('/foo.js'), '->getUrl() does nothing on absolute paths'); $helper = new AssetsHelper('/foo'); $this->assertEquals('/foo/foo.js', $helper->getUrl('foo.js'), '->getUrl() appends the basePath on relative paths'); $this->assertEquals('/foo.js', $helper->getUrl('/foo.js'), '->getUrl() does not append the basePath on absolute paths'); $helper = new AssetsHelper(null, 'http://assets.example.com/'); $this->assertEquals('http://assets.example.com/foo.js', $helper->getUrl('foo.js'), '->getUrl() prepends the base URL'); $this->assertEquals('http://assets.example.com/foo.js', $helper->getUrl('/foo.js'), '->getUrl() prepends the base URL'); $helper = new AssetsHelper(null, 'http://www.example.com/foo'); $this->assertEquals('http://www.example.com/foo/foo.js', $helper->getUrl('foo.js'), '->getUrl() prepends the base URL with a path'); $this->assertEquals('http://www.example.com/foo/foo.js', $helper->getUrl('/foo.js'), '->getUrl() prepends the base URL with a path'); $helper = new AssetsHelper('/foo', 'http://www.example.com/'); $this->assertEquals('http://www.example.com/foo.js', $helper->getUrl('foo.js'), '->getUrl() prepends the base URL and the base path if defined'); $this->assertEquals('http://www.example.com/foo.js', $helper->getUrl('/foo.js'), '->getUrl() prepends the base URL but not the base path on absolute paths'); $helper = new AssetsHelper('/bar', 'http://www.example.com/foo'); $this->assertEquals('http://www.example.com/foo/foo.js', $helper->getUrl('foo.js'), '->getUrl() prepends the base URL and the base path if defined'); $this->assertEquals('http://www.example.com/foo/foo.js', $helper->getUrl('/foo.js'), '->getUrl() prepends the base URL but not the base path on absolute paths'); $helper = new AssetsHelper('/bar', 'http://www.example.com/foo', 'abcd'); $this->assertEquals('http://www.example.com/foo/foo.js?abcd', $helper->getUrl('foo.js'), '->getUrl() appends the version if defined'); $helper = new AssetsHelper(); $this->assertEquals('/', $helper->getUrl(''), '->getUrl() with empty arg returns the prefix alone'); } public function testGetUrlLeavesProtocolRelativePathsUntouched() { $helper = new AssetsHelper(null, 'http://foo.com'); $this->assertEquals('//bar.com/asset', $helper->getUrl('//bar.com/asset')); } } PK!q=R  Htest/Templating/Symfony/Component/Templating/Tests/Helper/HelperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Helper; use Symfony\Component\Templating\Helper\Helper; class HelperTest extends \PHPUnit_Framework_TestCase { public function testGetSetCharset() { $helper = new ProjectTemplateHelper(); $helper->setCharset('ISO-8859-1'); $this->assertTrue('ISO-8859-1' === $helper->getCharset(), '->setCharset() sets the charset set related to this helper'); } } class ProjectTemplateHelper extends Helper { public function getName() { return 'foo'; } } PK!M<Rtest/Templating/Symfony/Component/Templating/Tests/Helper/CoreAssetsHelperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Helper; use Symfony\Component\Templating\Helper\CoreAssetsHelper; class CoreAssetsHelperTest extends \PHPUnit_Framework_TestCase { protected $package; protected function setUp() { $this->package = $this->getMock('Symfony\Component\Templating\Asset\PackageInterface'); } protected function tearDown() { $this->package = null; } public function testAddGetPackage() { $helper = new CoreAssetsHelper($this->package); $helper->addPackage('foo', $this->package); $this->assertSame($this->package, $helper->getPackage('foo')); } public function testGetNonexistingPackage() { $helper = new CoreAssetsHelper($this->package); $this->setExpectedException('\InvalidArgumentException'); $helper->getPackage('foo'); } public function testGetHelperName() { $helper = new CoreAssetsHelper($this->package); $this->assertEquals('assets', $helper->getName()); } } PK!0nl  Mtest/Templating/Symfony/Component/Templating/Tests/Helper/SlotsHelperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests\Helper; use Symfony\Component\Templating\Helper\SlotsHelper; class SlotsHelperTest extends \PHPUnit_Framework_TestCase { public function testHasGetSet() { $helper = new SlotsHelper(); $helper->set('foo', 'bar'); $this->assertEquals('bar', $helper->get('foo'), '->set() sets a slot value'); $this->assertEquals('bar', $helper->get('bar', 'bar'), '->get() takes a default value to return if the slot does not exist'); $this->assertTrue($helper->has('foo'), '->has() returns true if the slot exists'); $this->assertFalse($helper->has('bar'), '->has() returns false if the slot does not exist'); } public function testOutput() { $helper = new SlotsHelper(); $helper->set('foo', 'bar'); ob_start(); $ret = $helper->output('foo'); $output = ob_get_clean(); $this->assertEquals('bar', $output, '->output() outputs the content of a slot'); $this->assertTrue($ret, '->output() returns true if the slot exists'); ob_start(); $ret = $helper->output('bar', 'bar'); $output = ob_get_clean(); $this->assertEquals('bar', $output, '->output() takes a default value to return if the slot does not exist'); $this->assertTrue($ret, '->output() returns true if the slot does not exist but a default value is provided'); ob_start(); $ret = $helper->output('bar'); $output = ob_get_clean(); $this->assertEquals('', $output, '->output() outputs nothing if the slot does not exist'); $this->assertFalse($ret, '->output() returns false if the slot does not exist'); } public function testStartStop() { $helper = new SlotsHelper(); $helper->start('bar'); echo 'foo'; $helper->stop(); $this->assertEquals('foo', $helper->get('bar'), '->start() starts a slot'); $this->assertTrue($helper->has('bar'), '->starts() starts a slot'); $helper->start('bar'); try { $helper->start('bar'); $helper->stop(); $this->fail('->start() throws an InvalidArgumentException if a slot with the same name is already started'); } catch (\Exception $e) { $helper->stop(); $this->assertInstanceOf('\InvalidArgumentException', $e, '->start() throws an InvalidArgumentException if a slot with the same name is already started'); $this->assertEquals('A slot named "bar" is already started.', $e->getMessage(), '->start() throws an InvalidArgumentException if a slot with the same name is already started'); } try { $helper->stop(); $this->fail('->stop() throws an LogicException if no slot is started'); } catch (\Exception $e) { $this->assertInstanceOf('\LogicException', $e, '->stop() throws an LogicException if no slot is started'); $this->assertEquals('No slot started.', $e->getMessage(), '->stop() throws an LogicException if no slot is started'); } } } PK! `#`#Dtest/Templating/Symfony/Component/Templating/Tests/PhpEngineTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests; use Symfony\Component\Templating\PhpEngine; use Symfony\Component\Templating\Loader\Loader; use Symfony\Component\Templating\Storage\Storage; use Symfony\Component\Templating\Storage\StringStorage; use Symfony\Component\Templating\Helper\SlotsHelper; use Symfony\Component\Templating\TemplateNameParser; use Symfony\Component\Templating\TemplateReferenceInterface; use Symfony\Component\Templating\TemplateReference; class PhpEngineTest extends \PHPUnit_Framework_TestCase { protected $loader; protected function setUp() { $this->loader = new ProjectTemplateLoader(); } protected function tearDown() { $this->loader = null; } public function testConstructor() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $this->assertEquals($this->loader, $engine->getLoader(), '__construct() takes a loader instance as its second first argument'); } public function testOffsetGet() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $engine->set($helper = new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('bar'), 'foo'); $this->assertEquals($helper, $engine['foo'], '->offsetGet() returns the value of a helper'); try { $engine['bar']; $this->fail('->offsetGet() throws an InvalidArgumentException if the helper is not defined'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->offsetGet() throws an InvalidArgumentException if the helper is not defined'); $this->assertEquals('The helper "bar" is not defined.', $e->getMessage(), '->offsetGet() throws an InvalidArgumentException if the helper is not defined'); } } public function testGetSetHas() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $foo = new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('foo'); $engine->set($foo); $this->assertEquals($foo, $engine->get('foo'), '->set() sets a helper'); $engine[$foo] = 'bar'; $this->assertEquals($foo, $engine->get('bar'), '->set() takes an alias as a second argument'); $this->assertTrue(isset($engine['bar'])); try { $engine->get('foobar'); $this->fail('->get() throws an InvalidArgumentException if the helper is not defined'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws an InvalidArgumentException if the helper is not defined'); $this->assertEquals('The helper "foobar" is not defined.', $e->getMessage(), '->get() throws an InvalidArgumentException if the helper is not defined'); } $this->assertTrue(isset($engine['bar'])); $this->assertTrue($engine->has('foo'), '->has() returns true if the helper exists'); $this->assertFalse($engine->has('foobar'), '->has() returns false if the helper does not exist'); } public function testUnsetHelper() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $foo = new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('foo'); $engine->set($foo); $this->setExpectedException('\LogicException'); unset($engine['foo']); } public function testExtendRender() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader, array(), array(new SlotsHelper())); try { $engine->render('name'); $this->fail('->render() throws an InvalidArgumentException if the template does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->render() throws an InvalidArgumentException if the template does not exist'); $this->assertEquals('The template "name" does not exist.', $e->getMessage(), '->render() throws an InvalidArgumentException if the template does not exist'); } $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader, array(new SlotsHelper())); $engine->set(new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('bar')); $this->loader->setTemplate('foo.php', 'extend("layout.php"); echo $view[\'foo\'].$foo ?>'); $this->loader->setTemplate('layout.php', '-get("_content") ?>-'); $this->assertEquals('-barfoo-', $engine->render('foo.php', array('foo' => 'foo')), '->render() uses the decorator to decorate the template'); $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader, array(new SlotsHelper())); $engine->set(new \Symfony\Component\Templating\Tests\Fixtures\SimpleHelper('bar')); $this->loader->setTemplate('bar.php', 'bar'); $this->loader->setTemplate('foo.php', 'extend("layout.php"); echo $foo ?>'); $this->loader->setTemplate('layout.php', 'render("bar.php") ?>-get("_content") ?>-'); $this->assertEquals('bar-foo-', $engine->render('foo.php', array('foo' => 'foo', 'bar' => 'bar')), '->render() supports render() calls in templates'); } public function testRenderParameter() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $this->loader->setTemplate('foo.php', ''); $this->assertEquals('foobar', $engine->render('foo.php', array('template' => 'foo', 'parameters' => 'bar')), '->render() extract variables'); } /** * @expectedException \InvalidArgumentException * @dataProvider forbiddenParameterNames */ public function testRenderForbiddenParameter($name) { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $this->loader->setTemplate('foo.php', 'bar'); $engine->render('foo.php', array($name => 'foo')); } public function forbiddenParameterNames() { return array( array('this'), array('view'), ); } public function testEscape() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $this->assertEquals('<br />', $engine->escape('
'), '->escape() escapes strings'); $foo = new \stdClass(); $this->assertEquals($foo, $engine->escape($foo), '->escape() does nothing on non strings'); } public function testGetSetCharset() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $this->assertEquals('UTF-8', $engine->getCharset(), '->getCharset() returns UTF-8 by default'); $engine->setCharset('ISO-8859-1'); $this->assertEquals('ISO-8859-1', $engine->getCharset(), '->setCharset() changes the default charset to use'); } public function testGlobalVariables() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $engine->addGlobal('global_variable', 'lorem ipsum'); $this->assertEquals(array( 'global_variable' => 'lorem ipsum', ), $engine->getGlobals()); } public function testGlobalsGetPassedToTemplate() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $engine->addGlobal('global', 'global variable'); $this->loader->setTemplate('global.php', ''); $this->assertEquals($engine->render('global.php'), 'global variable'); $this->assertEquals($engine->render('global.php', array('global' => 'overwritten')), 'overwritten'); } public function testGetLoader() { $engine = new ProjectTemplateEngine(new TemplateNameParser(), $this->loader); $this->assertSame($this->loader, $engine->getLoader()); } } class ProjectTemplateEngine extends PhpEngine { public function getLoader() { return $this->loader; } } class ProjectTemplateLoader extends Loader { public $templates = array(); public function setTemplate($name, $content) { $template = new TemplateReference($name, 'php'); $this->templates[$template->getLogicalName()] = $content; } public function load(TemplateReferenceInterface $template) { if (isset($this->templates[$template->getLogicalName()])) { return new StringStorage($this->templates[$template->getLogicalName()]); } return false; } public function isFresh(TemplateReferenceInterface $template, $time) { return false; } } PK!氵Ktest/Templating/Symfony/Component/Templating/Tests/DelegatingEngineTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Templating\Tests; use Symfony\Component\Templating\DelegatingEngine; use Symfony\Component\Templating\StreamingEngineInterface; use Symfony\Component\Templating\EngineInterface; class DelegatingEngineTest extends \PHPUnit_Framework_TestCase { public function testRenderDelegatesToSupportedEngine() { $firstEngine = $this->getEngineMock('template.php', false); $secondEngine = $this->getEngineMock('template.php', true); $secondEngine->expects($this->once()) ->method('render') ->with('template.php', array('foo' => 'bar')) ->will($this->returnValue('')); $delegatingEngine = new DelegatingEngine(array($firstEngine, $secondEngine)); $result = $delegatingEngine->render('template.php', array('foo' => 'bar')); $this->assertSame('', $result); } /** * @expectedException \RuntimeException * @expectedExceptionMessage No engine is able to work with the template "template.php" */ public function testRenderWithNoSupportedEngine() { $firstEngine = $this->getEngineMock('template.php', false); $secondEngine = $this->getEngineMock('template.php', false); $delegatingEngine = new DelegatingEngine(array($firstEngine, $secondEngine)); $delegatingEngine->render('template.php', array('foo' => 'bar')); } public function testStreamDelegatesToSupportedEngine() { $streamingEngine = $this->getStreamingEngineMock('template.php', true); $streamingEngine->expects($this->once()) ->method('stream') ->with('template.php', array('foo' => 'bar')) ->will($this->returnValue('')); $delegatingEngine = new DelegatingEngine(array($streamingEngine)); $result = $delegatingEngine->stream('template.php', array('foo' => 'bar')); $this->assertNull($result); } /** * @expectedException \LogicException * @expectedExceptionMessage Template "template.php" cannot be streamed as the engine supporting it does not implement StreamingEngineInterface */ public function testStreamRequiresStreamingEngine() { $engine = $this->getEngineMock('template.php', true); $engine->expects($this->never())->method('stream'); $delegatingEngine = new DelegatingEngine(array($engine)); $delegatingEngine->stream('template.php', array('foo' => 'bar')); } public function testExists() { $engine = $this->getEngineMock('template.php', true); $engine->expects($this->once()) ->method('exists') ->with('template.php') ->will($this->returnValue(true)); $delegatingEngine = new DelegatingEngine(array($engine)); $this->assertTrue($delegatingEngine->exists('template.php')); } public function testSupports() { $engine = $this->getEngineMock('template.php', true); $delegatingEngine = new DelegatingEngine(array($engine)); $this->assertTrue($delegatingEngine->supports('template.php')); } public function testSupportsWithNoSupportedEngine() { $engine = $this->getEngineMock('template.php', false); $delegatingEngine = new DelegatingEngine(array($engine)); $this->assertFalse($delegatingEngine->supports('template.php')); } public function testGetExistingEngine() { $firstEngine = $this->getEngineMock('template.php', false); $secondEngine = $this->getEngineMock('template.php', true); $delegatingEngine = new DelegatingEngine(array($firstEngine, $secondEngine)); $this->assertSame($secondEngine, $delegatingEngine->getEngine('template.php')); } /** * @expectedException \RuntimeException * @expectedExceptionMessage No engine is able to work with the template "template.php" */ public function testGetInvalidEngine() { $firstEngine = $this->getEngineMock('template.php', false); $secondEngine = $this->getEngineMock('template.php', false); $delegatingEngine = new DelegatingEngine(array($firstEngine, $secondEngine)); $delegatingEngine->getEngine('template.php', array('foo' => 'bar')); } private function getEngineMock($template, $supports) { $engine = $this->getMock('Symfony\Component\Templating\EngineInterface'); $engine->expects($this->once()) ->method('supports') ->with($template) ->will($this->returnValue($supports)); return $engine; } private function getStreamingEngineMock($template, $supports) { $engine = $this->getMockForAbstractClass('Symfony\Component\Templating\Tests\MyStreamingEngine'); $engine->expects($this->once()) ->method('supports') ->with($template) ->will($this->returnValue($supports)); return $engine; } } interface MyStreamingEngine extends StreamingEngineInterface, EngineInterface { } PK!%D99=test/Templating/Symfony/Component/Templating/phpunit.xml.distnu[ ./Tests/ ./ ./vendor ./Tests PK!Q5test/Yaml/Symfony/Component/Yaml/Tests/DumperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Tests; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Parser; use Symfony\Component\Yaml\Dumper; class DumperTest extends \PHPUnit_Framework_TestCase { protected $parser; protected $dumper; protected $path; protected $array = array( '' => 'bar', 'foo' => '#bar', 'foo\'bar' => array(), 'bar' => array(1, 'foo'), 'foobar' => array( 'foo' => 'bar', 'bar' => array(1, 'foo'), 'foobar' => array( 'foo' => 'bar', 'bar' => array(1, 'foo'), ), ), ); protected function setUp() { $this->parser = new Parser(); $this->dumper = new Dumper(); $this->path = __DIR__.'/Fixtures'; } protected function tearDown() { $this->parser = null; $this->dumper = null; $this->path = null; $this->array = null; } public function testSetIndentation() { $this->dumper->setIndentation(7); $expected = <<assertEquals($expected, $this->dumper->dump($this->array, 4, 0)); } public function testSpecifications() { $files = $this->parser->parse(file_get_contents($this->path.'/index.yml')); foreach ($files as $file) { $yamls = file_get_contents($this->path.'/'.$file.'.yml'); // split YAMLs documents foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) { if (!$yaml) { continue; } $test = $this->parser->parse($yaml); if (isset($test['dump_skip']) && $test['dump_skip']) { continue; } elseif (isset($test['todo']) && $test['todo']) { // TODO } else { eval('$expected = '.trim($test['php']).';'); $this->assertEquals($expected, $this->parser->parse($this->dumper->dump($expected, 10)), $test['test']); } } } } public function testInlineLevel() { $expected = <<assertEquals($expected, $this->dumper->dump($this->array, -10), '->dump() takes an inline level argument'); $this->assertEquals($expected, $this->dumper->dump($this->array, 0), '->dump() takes an inline level argument'); $expected = <<assertEquals($expected, $this->dumper->dump($this->array, 1), '->dump() takes an inline level argument'); $expected = <<assertEquals($expected, $this->dumper->dump($this->array, 2), '->dump() takes an inline level argument'); $expected = <<assertEquals($expected, $this->dumper->dump($this->array, 3), '->dump() takes an inline level argument'); $expected = <<assertEquals($expected, $this->dumper->dump($this->array, 4), '->dump() takes an inline level argument'); $this->assertEquals($expected, $this->dumper->dump($this->array, 10), '->dump() takes an inline level argument'); } public function testObjectSupportEnabled() { $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, false, true); $this->assertEquals('{ foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects'); } public function testObjectSupportDisabledButNoExceptions() { $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1)); $this->assertEquals('{ foo: null, bar: 1 }', $dump, '->dump() does not dump objects when disabled'); } /** * @expectedException \Symfony\Component\Yaml\Exception\DumpException */ public function testObjectSupportDisabledWithExceptions() { $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, true, false); } } class A { public $a = 'foo'; } PK!Ctest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.ymlnu[--- test: One Element Mapping brief: | A mapping with one key/value pair yaml: | foo: bar php: | array('foo' => 'bar') --- test: Multi Element Mapping brief: | More than one key/value pair yaml: | red: baron white: walls blue: berries php: | array( 'red' => 'baron', 'white' => 'walls', 'blue' => 'berries', ) --- test: Values aligned brief: | Often times human editors of documents will align the values even though YAML emitters generally don't. yaml: | red: baron white: walls blue: berries php: | array( 'red' => 'baron', 'white' => 'walls', 'blue' => 'berries', ) --- test: Colons aligned brief: | Spaces can come before the ': ' key/value separator. yaml: | red : baron white : walls blue : berries php: | array( 'red' => 'baron', 'white' => 'walls', 'blue' => 'berries', ) PK!U U =test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfCompact.ymlnu[--- %YAML:1.0 test: Compact notation brief: | Compact notation for sets of mappings with single element yaml: | --- # products purchased - item : Super Hoop - item : Basketball quantity: 1 - item: name: Big Shoes nick: Biggies quantity: 1 php: | array ( array ( 'item' => 'Super Hoop', ), array ( 'item' => 'Basketball', 'quantity' => 1, ), array ( 'item' => array( 'name' => 'Big Shoes', 'nick' => 'Biggies' ), 'quantity' => 1 ) ) --- test: Compact notation combined with inline notation brief: | Combinations of compact and inline notation are allowed yaml: | --- items: - { item: Super Hoop, quantity: 1 } - [ Basketball, Big Shoes ] php: | array ( 'items' => array ( array ( 'item' => 'Super Hoop', 'quantity' => 1, ), array ( 'Basketball', 'Big Shoes' ) ) ) --- %YAML:1.0 test: Compact notation brief: | Compact notation for sets of mappings with single element yaml: | --- # products purchased - item : Super Hoop - item : Basketball quantity: 1 - item: name: Big Shoes nick: Biggies quantity: 1 php: | array ( array ( 'item' => 'Super Hoop', ), array ( 'item' => 'Basketball', 'quantity' => 1, ), array ( 'item' => array( 'name' => 'Big Shoes', 'nick' => 'Biggies' ), 'quantity' => 1 ) ) --- test: Compact notation combined with inline notation brief: | Combinations of compact and inline notation are allowed yaml: | --- items: - { item: Super Hoop, quantity: 1 } - [ Basketball, Big Shoes ] php: | array ( 'items' => array ( array ( 'item' => 'Super Hoop', 'quantity' => 1, ), array ( 'Basketball', 'Big Shoes' ) ) ) --- %YAML:1.0 test: Compact notation brief: | Compact notation for sets of mappings with single element yaml: | --- # products purchased - item : Super Hoop - item : Basketball quantity: 1 - item: name: Big Shoes nick: Biggies quantity: 1 php: | array ( array ( 'item' => 'Super Hoop', ), array ( 'item' => 'Basketball', 'quantity' => 1, ), array ( 'item' => array( 'name' => 'Big Shoes', 'nick' => 'Biggies' ), 'quantity' => 1 ) ) --- test: Compact notation combined with inline notation brief: | Combinations of compact and inline notation are allowed yaml: | --- items: - { item: Super Hoop, quantity: 1 } - [ Basketball, Big Shoes ] php: | array ( 'items' => array ( array ( 'item' => 'Super Hoop', 'quantity' => 1, ), array ( 'Basketball', 'Big Shoes' ) ) ) PK!5R[[Btest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.ymlnu[--- %YAML:1.0 test: Simple Alias Example brief: > If you need to refer to the same item of data twice, you can give that item an alias. The alias is a plain string, starting with an ampersand. The item may then be referred to by the alias throughout your document by using an asterisk before the name of the alias. This is called an anchor. yaml: | - &showell Steve - Clark - Brian - Oren - *showell php: | array('Steve', 'Clark', 'Brian', 'Oren', 'Steve') --- test: Alias of a Mapping brief: > An alias can be used on any item of data, including sequences, mappings, and other complex data types. yaml: | - &hello Meat: pork Starch: potato - banana - *hello php: | array(array('Meat'=>'pork', 'Starch'=>'potato'), 'banana', array('Meat'=>'pork', 'Starch'=>'potato')) PK!U;test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfTests.ymlnu[--- %YAML:1.0 test: Multiple quoted string on one line brief: > Multiple quoted string on one line yaml: | stripped_title: { name: "foo bar", help: "bar foo" } php: | array('stripped_title' => array('name' => 'foo bar', 'help' => 'bar foo')) --- test: Empty sequence yaml: | foo: [ ] php: | array('foo' => array()) --- test: Empty value yaml: | foo: php: | array('foo' => null) --- test: Inline string parsing brief: > Inline string parsing yaml: | test: ['complex: string', 'another [string]'] php: | array('test' => array('complex: string', 'another [string]')) --- test: Boolean brief: > Boolean yaml: | - false - true - null - ~ - 'false' - 'true' - 'null' - '~' php: | array( false, true, null, null, 'false', 'true', 'null', '~', ) --- test: Empty lines in folded blocks brief: > Empty lines in folded blocks yaml: | foo: bar: | foo bar php: | array('foo' => array('bar' => "foo\n\n\n \nbar\n")) --- test: IP addresses brief: > IP addresses yaml: | foo: 10.0.0.2 php: | array('foo' => '10.0.0.2') --- test: A sequence with an embedded mapping brief: > A sequence with an embedded mapping yaml: | - foo - bar: { bar: foo } php: | array('foo', array('bar' => array('bar' => 'foo'))) --- test: A sequence with an unordered array brief: > A sequence with an unordered array yaml: | 1: foo 0: bar php: | array(1 => 'foo', 0 => 'bar') --- test: Octal brief: as in spec example 2.19, octal value is converted yaml: | foo: 0123 php: | array('foo' => 83) --- test: Octal strings brief: Octal notation in a string must remain a string yaml: | foo: "0123" php: | array('foo' => '0123') --- test: Octal strings brief: Octal notation in a string must remain a string yaml: | foo: '0123' php: | array('foo' => '0123') --- test: Octal strings brief: Octal notation in a string must remain a string yaml: | foo: | 0123 php: | array('foo' => "0123\n") --- test: Document as a simple hash brief: Document as a simple hash yaml: | { foo: bar } php: | array('foo' => 'bar') --- test: Document as a simple array brief: Document as a simple array yaml: | [ foo, bar ] php: | array('foo', 'bar') PK!@UU>test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfComments.ymlnu[--- %YAML:1.0 test: Comments at the end of a line brief: > Comments at the end of a line yaml: | ex1: "foo # bar" ex2: "foo # bar" # comment ex3: 'foo # bar' # comment ex4: foo # comment php: | array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo') --- test: Comments in the middle brief: > Comments in the middle yaml: | foo: # some comment # some comment bar: foo # some comment # some comment php: | array('foo' => array('bar' => 'foo')) --- test: Comments on a hash line brief: > Comments on a hash line yaml: | foo: # a comment foo: bar # a comment php: | array('foo' => array('foo' => 'bar')) --- test: 'Value starting with a #' brief: > 'Value starting with a #' yaml: | foo: '#bar' php: | array('foo' => '#bar') --- test: Document starting with a comment and a separator brief: > Commenting before document start is allowed yaml: | # document comment --- foo: bar # a comment php: | array('foo' => 'bar') --- test: Comment containing a colon on a hash line brief: > Comment containing a colon on a scalar line yaml: 'foo # comment: this is also part of the comment' php: | 'foo' --- test: 'Hash key containing a #' brief: > 'Hash key containing a #' yaml: 'foo#bar: baz' php: | array('foo#bar' => 'baz') PK!Ç--Itest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.ymlnu[--- %YAML:1.0 test: Unindented collection brief: > Unindented collection yaml: | collection: - item1 - item2 - item3 php: | array('collection' => array('item1', 'item2', 'item3')) --- test: Nested unindented collection (two levels) brief: > Nested unindented collection yaml: | collection: key: - a - b - c php: | array('collection' => array('key' => array('a', 'b', 'c'))) --- test: Nested unindented collection (three levels) brief: > Nested unindented collection yaml: | collection: key: subkey: - one - two - three php: | array('collection' => array('key' => array('subkey' => array('one', 'two', 'three')))) --- test: Key/value after unindented collection (1) brief: > Key/value after unindented collection (1) yaml: | collection: key: - a - b - c foo: bar php: | array('collection' => array('key' => array('a', 'b', 'c')), 'foo' => 'bar') --- test: Key/value after unindented collection (at the same level) brief: > Key/value after unindented collection yaml: | collection: key: - a - b - c foo: bar php: | array('collection' => array('key' => array('a', 'b', 'c'), 'foo' => 'bar')) PK!>;Ftest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.ymlnu[--- %YAML:1.0 test: Empty Sequence brief: > You can represent the empty sequence with an empty inline sequence. yaml: | empty: [] php: | array('empty' => array()) --- test: Empty Mapping brief: > You can represent the empty mapping with an empty inline mapping. yaml: | empty: {} php: | array('empty' => array()) --- test: Empty Sequence as Entire Document yaml: | [] php: | array() --- test: Empty Mapping as Entire Document yaml: | {} php: | array() --- test: Null as Document yaml: | ~ php: | null --- test: Empty String brief: > You can represent an empty string with a pair of quotes. yaml: | '' php: | '' PK!trqqAtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.ymlnu[--- test: Missing value for hash item todo: true brief: | Third item in this hash doesn't have a value yaml: | okay: value also okay: ~ causes error because no value specified last key: value okay here too python-error: causes error because no value specified --- test: Not indenting enough brief: | There was a bug in PyYaml where it was off by one in the indentation check. It was allowing the YAML below. # This is actually valid YAML now. Someone should tell showell. yaml: | foo: firstline: 1 secondline: 2 php: | array('foo' => null, 'firstline' => 1, 'secondline' => 2) PK!Z{kXXFtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.ymlnu[--- test: Simple Inline Array brief: > Sequences can be contained on a single line, using the inline syntax. Separate each entry with commas and enclose in square brackets. yaml: | seq: [ a, b, c ] php: | array('seq' => array('a', 'b', 'c')) --- test: Simple Inline Hash brief: > Mapping can also be contained on a single line, using the inline syntax. Each key-value pair is separated by a colon, with a comma between each entry in the mapping. Enclose with curly braces. yaml: | hash: { name: Steve, foo: bar } php: | array('hash' => array('name' => 'Steve', 'foo' => 'bar')) --- test: Multi-line Inline Collections todo: true brief: > Both inline sequences and inline mappings can span multiple lines, provided that you indent the additional lines. yaml: | languages: [ Ruby, Perl, Python ] websites: { YAML: yaml.org, Ruby: ruby-lang.org, Python: python.org, Perl: use.perl.org } php: | array( 'languages' => array('Ruby', 'Perl', 'Python'), 'websites' => array( 'YAML' => 'yaml.org', 'Ruby' => 'ruby-lang.org', 'Python' => 'python.org', 'Perl' => 'use.perl.org' ) ) --- test: Commas in Values (not in the spec!) todo: true brief: > List items in collections are delimited by commas, but there must be a space after each comma. This allows you to add numbers without quoting. yaml: | attendances: [ 45,123, 70,000, 17,222 ] php: | array('attendances' => array(45123, 70000, 17222)) PK!*Etest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.ymlnu[test: outside double quotes yaml: | \0 \ \a \b \n php: | "\\0 \\ \\a \\b \\n" --- test: null yaml: | "\0" php: | "\x00" --- test: bell yaml: | "\a" php: | "\x07" --- test: backspace yaml: | "\b" php: | "\x08" --- test: horizontal tab (1) yaml: | "\t" php: | "\x09" --- test: horizontal tab (2) yaml: | "\ " php: | "\x09" --- test: line feed yaml: | "\n" php: | "\x0a" --- test: vertical tab yaml: | "\v" php: | "\x0b" --- test: form feed yaml: | "\f" php: | "\x0c" --- test: carriage return yaml: | "\r" php: | "\x0d" --- test: escape yaml: | "\e" php: | "\x1b" --- test: space yaml: | "\ " php: | "\x20" --- test: slash yaml: | "\/" php: | "\x2f" --- test: backslash yaml: | "\\" php: | "\\" --- test: Unicode next line yaml: | "\N" php: | "\xc2\x85" --- test: Unicode non-breaking space yaml: | "\_" php: | "\xc2\xa0" --- test: Unicode line separator yaml: | "\L" php: | "\xe2\x80\xa8" --- test: Unicode paragraph separator yaml: | "\P" php: | "\xe2\x80\xa9" --- test: Escaped 8-bit Unicode yaml: | "\x42" php: | "B" --- test: Escaped 16-bit Unicode yaml: | "\u20ac" php: | "\xe2\x82\xac" --- test: Escaped 32-bit Unicode yaml: | "\U00000043" php: | "C" --- test: Example 5.13 Escaped Characters note: | Currently throws an error parsing first line. Maybe Symfony Yaml doesn't support continuation of string across multiple lines? Keeping test here but disabled. todo: true yaml: | "Fun with \\ \" \a \b \e \f \ \n \r \t \v \0 \ \ \_ \N \L \P \ \x41 \u0041 \U00000041" php: | "Fun with \x5C\n\x22 \x07 \x08 \x1B \x0C\n\x0A \x0D \x09 \x0B \x00\n\x20 \xA0 \x85 \xe2\x80\xa8 \xe2\x80\xa9\nA A A" --- test: Double quotes with a line feed yaml: | { double: "some value\n \"some quoted string\" and 'some single quotes one'" } php: | array( 'double' => "some value\n \"some quoted string\" and 'some single quotes one'" ) PK!֋OAtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.ymlnu[--- %YAML:1.0 test: Simple Sequence brief: | You can specify a list in YAML by placing each member of the list on a new line with an opening dash. These lists are called sequences. yaml: | - apple - banana - carrot php: | array('apple', 'banana', 'carrot') --- test: Nested Sequences brief: | You can include a sequence within another sequence by giving the sequence an empty dash, followed by an indented list. yaml: | - - foo - bar - baz php: | array(array('foo', 'bar', 'baz')) --- test: Mixed Sequences brief: | Sequences can contain any YAML data, including strings and other sequences. yaml: | - apple - - foo - bar - x123 - banana - carrot php: | array('apple', array('foo', 'bar', 'x123'), 'banana', 'carrot') --- test: Deeply Nested Sequences brief: | Sequences can be nested even deeper, with each level of indentation representing a level of depth. yaml: | - - - uno - dos php: | array(array(array('uno', 'dos'))) --- test: Simple Mapping brief: | You can add a keyed list (also known as a dictionary or hash) to your document by placing each member of the list on a new line, with a colon separating the key from its value. In YAML, this type of list is called a mapping. yaml: | foo: whatever bar: stuff php: | array('foo' => 'whatever', 'bar' => 'stuff') --- test: Sequence in a Mapping brief: | A value in a mapping can be a sequence. yaml: | foo: whatever bar: - uno - dos php: | array('foo' => 'whatever', 'bar' => array('uno', 'dos')) --- test: Nested Mappings brief: | A value in a mapping can be another mapping. yaml: | foo: whatever bar: fruit: apple name: steve sport: baseball php: | array( 'foo' => 'whatever', 'bar' => array( 'fruit' => 'apple', 'name' => 'steve', 'sport' => 'baseball' ) ) --- test: Mixed Mapping brief: | A mapping can contain any assortment of mappings and sequences as values. yaml: | foo: whatever bar: - fruit: apple name: steve sport: baseball - more - python: rocks perl: papers ruby: scissorses php: | array( 'foo' => 'whatever', 'bar' => array( array( 'fruit' => 'apple', 'name' => 'steve', 'sport' => 'baseball' ), 'more', array( 'python' => 'rocks', 'perl' => 'papers', 'ruby' => 'scissorses' ) ) ) --- test: Mapping-in-Sequence Shortcut todo: true brief: | If you are adding a mapping to a sequence, you can place the mapping on the same line as the dash as a shortcut. yaml: | - work on YAML.py: - work on Store php: | array(array('work on YAML.py' => array('work on Store'))) --- test: Sequence-in-Mapping Shortcut todo: true brief: | The dash in a sequence counts as indentation, so you can add a sequence inside of a mapping without needing spaces as indentation. yaml: | allow: - 'localhost' - '%.sourceforge.net' - '%.freepan.org' php: | array('allow' => array('localhost', '%.sourceforge.net', '%.freepan.org')) --- todo: true test: Merge key brief: | A merge key ('<<') can be used in a mapping to insert other mappings. If the value associated with the merge key is a mapping, each of its key/value pairs is inserted into the current mapping. yaml: | mapping: name: Joe job: Accountant <<: age: 38 php: | array( 'mapping' => array( 'name' => 'Joe', 'job' => 'Accountant', 'age' => 38 ) ) PK!ګغzzDtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.ymlnu[--- %YAML:1.0 test: Single ending newline brief: > A pipe character, followed by an indented block of text is treated as a literal block, in which newlines are preserved throughout the block, including the final newline. yaml: | --- this: | Foo Bar php: | array('this' => "Foo\nBar\n") --- test: The '+' indicator brief: > The '+' indicator says to keep newlines at the end of text blocks. yaml: | normal: | extra new lines not kept preserving: |+ extra new lines are kept dummy: value php: | array( 'normal' => "extra new lines not kept\n", 'preserving' => "extra new lines are kept\n\n\n", 'dummy' => 'value' ) --- test: Three trailing newlines in literals brief: > To give you more control over how space is preserved in text blocks, YAML has the keep '+' and chomp '-' indicators. The keep indicator will preserve all ending newlines, while the chomp indicator will strip all ending newlines. yaml: | clipped: | This has one newline. same as "clipped" above: "This has one newline.\n" stripped: |- This has no newline. same as "stripped" above: "This has no newline." kept: |+ This has four newlines. same as "kept" above: "This has four newlines.\n\n\n\n" php: | array( 'clipped' => "This has one newline.\n", 'same as "clipped" above' => "This has one newline.\n", 'stripped' => 'This has no newline.', 'same as "stripped" above' => 'This has no newline.', 'kept' => "This has four newlines.\n\n\n\n", 'same as "kept" above' => "This has four newlines.\n\n\n\n" ) --- test: Extra trailing newlines with spaces todo: true brief: > Normally, only a single newline is kept from the end of a literal block, unless the keep '+' character is used in combination with the pipe. The following example will preserve all ending whitespace since the last line of both literal blocks contains spaces which extend past the indentation level. yaml: | --- this: | Foo kept: |+ Foo php: | array('this' => "Foo\n\n \n", 'kept' => "Foo\n\n \n" ) --- test: Folded Block in a Sequence brief: > A greater-then character, followed by an indented block of text is treated as a folded block, in which lines of text separated by a single newline are concatenated as a single line. yaml: | --- - apple - banana - > can't you see the beauty of yaml? hmm - dog php: | array( 'apple', 'banana', "can't you see the beauty of yaml? hmm\n", 'dog' ) --- test: Folded Block as a Mapping Value brief: > Both literal and folded blocks can be used in collections, as values in a sequence or a mapping. yaml: | --- quote: > Mark McGwire's year was crippled by a knee injury. source: espn php: | array( 'quote' => "Mark McGwire's year was crippled by a knee injury.\n", 'source' => 'espn' ) --- test: Three trailing newlines in folded blocks brief: > The keep and chomp indicators can also be applied to folded blocks. yaml: | clipped: > This has one newline. same as "clipped" above: "This has one newline.\n" stripped: >- This has no newline. same as "stripped" above: "This has no newline." kept: >+ This has four newlines. same as "kept" above: "This has four newlines.\n\n\n\n" php: | array( 'clipped' => "This has one newline.\n", 'same as "clipped" above' => "This has one newline.\n", 'stripped' => 'This has no newline.', 'same as "stripped" above' => 'This has no newline.', 'kept' => "This has four newlines.\n\n\n\n", 'same as "kept" above' => "This has four newlines.\n\n\n\n" ) PK!889test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/index.ymlnu[- escapedCharacters - sfComments - sfCompact - sfTests - sfObjects - sfMergeKey - sfQuotes - YtsAnchorAlias - YtsBasicTests - YtsBlockMapping - YtsDocumentSeparator - YtsErrorTests - YtsFlowCollections - YtsFoldedScalars - YtsNullsAndEmpties - YtsSpecificationExamples - YtsTypeTransfers - unindentedCollections PK!%MCHtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.ymlnu[--- %YAML:1.0 test: Trailing Document Separator todo: true brief: > You can separate YAML documents with a string of three dashes. yaml: | - foo: 1 bar: 2 --- more: stuff python: | [ [ { 'foo': 1, 'bar': 2 } ], { 'more': 'stuff' } ] ruby: | [ { 'foo' => 1, 'bar' => 2 } ] --- test: Leading Document Separator todo: true brief: > You can explicity give an opening document separator to your YAML stream. yaml: | --- - foo: 1 bar: 2 --- more: stuff python: | [ [ {'foo': 1, 'bar': 2}], {'more': 'stuff'} ] ruby: | [ { 'foo' => 1, 'bar' => 2 } ] --- test: YAML Header todo: true brief: > The opening separator can contain directives to the YAML parser, such as the version number. yaml: | --- %YAML:1.0 foo: 1 bar: 2 php: | array('foo' => 1, 'bar' => 2) documents: 1 --- test: Red Herring Document Separator brief: > Separators included in blocks or strings are treated as blocks or strings, as the document separator should have no indentation preceding it. yaml: | foo: | --- php: | array('foo' => "---\n") --- test: Multiple Document Separators in Block brief: > This technique allows you to embed other YAML documents within literal blocks. yaml: | foo: | --- foo: bar --- yo: baz bar: | fooness php: | array( 'foo' => "---\nfoo: bar\n---\nyo: baz\n", 'bar' => "fooness\n" ) PK!;:QJJ>test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.ymlnu[--- %YAML:1.0 test: Simple In Place Substitution brief: > If you want to reuse an entire alias, only overwriting what is different you can use a << in place substitution. This is not part of the official YAML spec, but a widely implemented extension. See the following URL for details: http://yaml.org/type/merge.html yaml: | foo: &foo a: Steve b: Clark c: Brian bar: &bar <<: *foo x: Oren foo2: &foo2 a: Ballmer ding: &dong [ fi, fei, fo, fam] check: <<: - *foo - *dong isit: tested head: <<: [ *foo , *dong , *foo2 ] php: | array('foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian'), 'bar' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'x' => 'Oren'), 'foo2' => array('a' => 'Ballmer'), 'ding' => array('fi', 'fei', 'fo', 'fam'), 'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'), 'head' => array('a' => 'Ballmer', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam')) PK!Z>test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/embededPhp.ymlnu[value: PK!<=test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfObjects.ymlnu[--- %YAML:1.0 test: Objects brief: > Comments at the end of a line yaml: | ex1: "foo # bar" ex2: "foo # bar" # comment ex3: 'foo # bar' # comment ex4: foo # comment php: | array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo') PK!$RDtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.ymlnu[--- %YAML:1.0 test: Strings brief: > Any group of characters beginning with an alphabetic or numeric character is a string, unless it belongs to one of the groups below (such as an Integer or Time). yaml: | String php: | 'String' --- test: String characters brief: > A string can contain any alphabetic or numeric character, along with many punctuation characters, including the period, dash, space, quotes, exclamation, and question mark. yaml: | - What's Yaml? - It's for writing data structures in plain text. - And? - And what? That's not good enough for you? - No, I mean, "And what about Yaml?" - Oh, oh yeah. Uh.. Yaml for Ruby. php: | array( "What's Yaml?", "It's for writing data structures in plain text.", "And?", "And what? That's not good enough for you?", "No, I mean, \"And what about Yaml?\"", "Oh, oh yeah. Uh.. Yaml for Ruby." ) --- test: Indicators in Strings brief: > Be careful using indicators in strings. In particular, the comma, colon, and pound sign must be used carefully. yaml: | the colon followed by space is an indicator: but is a string:right here same for the pound sign: here we have it#in a string the comma can, honestly, be used in most cases: [ but not in, inline collections ] php: | array( 'the colon followed by space is an indicator' => 'but is a string:right here', 'same for the pound sign' => 'here we have it#in a string', 'the comma can, honestly, be used in most cases' => array('but not in', 'inline collections') ) --- test: Forcing Strings brief: > Any YAML type can be forced into a string using the explicit !str method. yaml: | date string: !str 2001-08-01 number string: !str 192 php: | array( 'date string' => '2001-08-01', 'number string' => '192' ) --- test: Single-quoted Strings brief: > You can also enclose your strings within single quotes, which allows use of slashes, colons, and other indicators freely. Inside single quotes, you can represent a single quote in your string by using two single quotes next to each other. yaml: | all my favorite symbols: '#:!/%.)' a few i hate: '&(*' why do i hate them?: 'it''s very hard to explain' entities: '£ me' php: | array( 'all my favorite symbols' => '#:!/%.)', 'a few i hate' => '&(*', 'why do i hate them?' => 'it\'s very hard to explain', 'entities' => '£ me' ) --- test: Double-quoted Strings brief: > Enclosing strings in double quotes allows you to use escapings to represent ASCII and Unicode characters. yaml: | i know where i want my line breaks: "one here\nand another here\n" php: | array( 'i know where i want my line breaks' => "one here\nand another here\n" ) --- test: Multi-line Quoted Strings todo: true brief: > Both single- and double-quoted strings may be carried on to new lines in your YAML document. They must be indented a step and indentation is interpreted as a single space. yaml: | i want a long string: "so i'm going to let it go on and on to other lines until i end it with a quote." php: | array('i want a long string' => "so i'm going to ". "let it go on and on to other lines ". "until i end it with a quote." ) --- test: Plain scalars todo: true brief: > Unquoted strings may also span multiple lines, if they are free of YAML space indicators and indented. yaml: | - My little toe is broken in two places; - I'm crazy to have skied this way; - I'm not the craziest he's seen, since there was always the German guy who skied for 3 hours on a broken shin bone (just below the kneecap); - Nevertheless, second place is respectable, and he doesn't recommend going for the record; - He's going to put my foot in plaster for a month; - This would impair my skiing ability somewhat for the duration, as can be imagined. php: | array( "My little toe is broken in two places;", "I'm crazy to have skied this way;", "I'm not the craziest he's seen, since there was always ". "the German guy who skied for 3 hours on a broken shin ". "bone (just below the kneecap);", "Nevertheless, second place is respectable, and he doesn't ". "recommend going for the record;", "He's going to put my foot in plaster for a month;", "This would impair my skiing ability somewhat for the duration, ". "as can be imagined." ) --- test: 'Null' brief: > You can use the tilde '~' character for a null value. yaml: | name: Mr. Show hosted by: Bob and David date of next season: ~ php: | array( 'name' => 'Mr. Show', 'hosted by' => 'Bob and David', 'date of next season' => null ) --- test: Boolean brief: > You can use 'true' and 'false' for Boolean values. yaml: | Is Gus a Liar?: true Do I rely on Gus for Sustenance?: false php: | array( 'Is Gus a Liar?' => true, 'Do I rely on Gus for Sustenance?' => false ) --- test: Integers dump_skip: true brief: > An integer is a series of numbers, optionally starting with a positive or negative sign. Integers may also contain commas for readability. yaml: | zero: 0 simple: 12 one-thousand: 1,000 negative one-thousand: -1,000 php: | array( 'zero' => 0, 'simple' => 12, 'one-thousand' => 1000, 'negative one-thousand' => -1000 ) --- test: Integers as Map Keys brief: > An integer can be used a dictionary key. yaml: | 1: one 2: two 3: three php: | array( 1 => 'one', 2 => 'two', 3 => 'three' ) --- test: Floats dump_skip: true brief: > Floats are represented by numbers with decimals, allowing for scientific notation, as well as positive and negative infinity and "not a number." yaml: | a simple float: 2.00 larger float: 1,000.09 scientific notation: 1.00009e+3 php: | array( 'a simple float' => 2.0, 'larger float' => 1000.09, 'scientific notation' => 1000.09 ) --- test: Time todo: true brief: > You can represent timestamps by using ISO8601 format, or a variation which allows spaces between the date, time and time zone. yaml: | iso8601: 2001-12-14t21:59:43.10-05:00 space separated: 2001-12-14 21:59:43.10 -05:00 php: | array( 'iso8601' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'space separated' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ) ) --- test: Date todo: true brief: > A date can be represented by its year, month and day in ISO8601 order. yaml: | 1976-07-31 php: | date( 1976, 7, 31 ) PK!<test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.ymlnu[--- %YAML:1.0 test: Some characters at the beginning of a string must be escaped brief: > Some characters at the beginning of a string must be escaped yaml: | foo: | bar php: | array('foo' => '| bar') --- test: A key can be a quoted string brief: > A key can be a quoted string yaml: | "foo1": bar 'foo2': bar "foo \" bar": bar 'foo '' bar': bar 'foo3: ': bar "foo4: ": bar foo5: { "foo \" bar: ": bar, 'foo '' bar: ': bar } php: | array( 'foo1' => 'bar', 'foo2' => 'bar', 'foo " bar' => 'bar', 'foo \' bar' => 'bar', 'foo3: ' => 'bar', 'foo4: ' => 'bar', 'foo5' => array( 'foo " bar: ' => 'bar', 'foo \' bar: ' => 'bar', ), ) PK!ܷU11Ltest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.ymlnu[--- %YAML:1.0 test: Sequence of scalars spec: 2.1 yaml: | - Mark McGwire - Sammy Sosa - Ken Griffey php: | array('Mark McGwire', 'Sammy Sosa', 'Ken Griffey') --- test: Mapping of scalars to scalars spec: 2.2 yaml: | hr: 65 avg: 0.278 rbi: 147 php: | array('hr' => 65, 'avg' => 0.278, 'rbi' => 147) --- test: Mapping of scalars to sequences spec: 2.3 yaml: | american: - Boston Red Sox - Detroit Tigers - New York Yankees national: - New York Mets - Chicago Cubs - Atlanta Braves php: | array('american' => array( 'Boston Red Sox', 'Detroit Tigers', 'New York Yankees' ), 'national' => array( 'New York Mets', 'Chicago Cubs', 'Atlanta Braves' ) ) --- test: Sequence of mappings spec: 2.4 yaml: | - name: Mark McGwire hr: 65 avg: 0.278 - name: Sammy Sosa hr: 63 avg: 0.288 php: | array( array('name' => 'Mark McGwire', 'hr' => 65, 'avg' => 0.278), array('name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288) ) --- test: Legacy A5 todo: true spec: legacy_A5 yaml: | ? - New York Yankees - Atlanta Braves : - 2001-07-02 - 2001-08-12 - 2001-08-14 ? - Detroit Tigers - Chicago Cubs : - 2001-07-23 perl-busted: > YAML.pm will be able to emulate this behavior soon. In this regard it may be somewhat more correct than Python's native behaviour which can only use tuples as mapping keys. PyYAML will also need to figure out some clever way to roundtrip structured keys. python: | [ { ('New York Yankees', 'Atlanta Braves'): [yaml.timestamp('2001-07-02'), yaml.timestamp('2001-08-12'), yaml.timestamp('2001-08-14')], ('Detroit Tigers', 'Chicago Cubs'): [yaml.timestamp('2001-07-23')] } ] ruby: | { [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ], [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ] } syck: | struct test_node seq1[] = { { T_STR, 0, "New York Yankees" }, { T_STR, 0, "Atlanta Braves" }, end_node }; struct test_node seq2[] = { { T_STR, 0, "2001-07-02" }, { T_STR, 0, "2001-08-12" }, { T_STR, 0, "2001-08-14" }, end_node }; struct test_node seq3[] = { { T_STR, 0, "Detroit Tigers" }, { T_STR, 0, "Chicago Cubs" }, end_node }; struct test_node seq4[] = { { T_STR, 0, "2001-07-23" }, end_node }; struct test_node map[] = { { T_SEQ, 0, 0, seq1 }, { T_SEQ, 0, 0, seq2 }, { T_SEQ, 0, 0, seq3 }, { T_SEQ, 0, 0, seq4 }, end_node }; struct test_node stream[] = { { T_MAP, 0, 0, map }, end_node }; --- test: Sequence of sequences spec: 2.5 yaml: | - [ name , hr , avg ] - [ Mark McGwire , 65 , 0.278 ] - [ Sammy Sosa , 63 , 0.288 ] php: | array( array( 'name', 'hr', 'avg' ), array( 'Mark McGwire', 65, 0.278 ), array( 'Sammy Sosa', 63, 0.288 ) ) --- test: Mapping of mappings todo: true spec: 2.6 yaml: | Mark McGwire: {hr: 65, avg: 0.278} Sammy Sosa: { hr: 63, avg: 0.288 } php: | array( 'Mark McGwire' => array( 'hr' => 65, 'avg' => 0.278 ), 'Sammy Sosa' => array( 'hr' => 63, 'avg' => 0.288 ) ) --- test: Two documents in a stream each with a leading comment todo: true spec: 2.7 yaml: | # Ranking of 1998 home runs --- - Mark McGwire - Sammy Sosa - Ken Griffey # Team ranking --- - Chicago Cubs - St Louis Cardinals ruby: | y = YAML::Stream.new y.add( [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ] ) y.add( [ 'Chicago Cubs', 'St Louis Cardinals' ] ) documents: 2 --- test: Play by play feed from a game todo: true spec: 2.8 yaml: | --- time: 20:03:20 player: Sammy Sosa action: strike (miss) ... --- time: 20:03:47 player: Sammy Sosa action: grand slam ... perl: | [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ] documents: 2 --- test: Single document with two comments spec: 2.9 yaml: | hr: # 1998 hr ranking - Mark McGwire - Sammy Sosa rbi: # 1998 rbi ranking - Sammy Sosa - Ken Griffey php: | array( 'hr' => array( 'Mark McGwire', 'Sammy Sosa' ), 'rbi' => array( 'Sammy Sosa', 'Ken Griffey' ) ) --- test: Node for Sammy Sosa appears twice in this document spec: 2.10 yaml: | --- hr: - Mark McGwire # Following node labeled SS - &SS Sammy Sosa rbi: - *SS # Subsequent occurrence - Ken Griffey php: | array( 'hr' => array('Mark McGwire', 'Sammy Sosa'), 'rbi' => array('Sammy Sosa', 'Ken Griffey') ) --- test: Mapping between sequences todo: true spec: 2.11 yaml: | ? # PLAY SCHEDULE - Detroit Tigers - Chicago Cubs : - 2001-07-23 ? [ New York Yankees, Atlanta Braves ] : [ 2001-07-02, 2001-08-12, 2001-08-14 ] ruby: | { [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ], [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ] } syck: | struct test_node seq1[] = { { T_STR, 0, "New York Yankees" }, { T_STR, 0, "Atlanta Braves" }, end_node }; struct test_node seq2[] = { { T_STR, 0, "2001-07-02" }, { T_STR, 0, "2001-08-12" }, { T_STR, 0, "2001-08-14" }, end_node }; struct test_node seq3[] = { { T_STR, 0, "Detroit Tigers" }, { T_STR, 0, "Chicago Cubs" }, end_node }; struct test_node seq4[] = { { T_STR, 0, "2001-07-23" }, end_node }; struct test_node map[] = { { T_SEQ, 0, 0, seq3 }, { T_SEQ, 0, 0, seq4 }, { T_SEQ, 0, 0, seq1 }, { T_SEQ, 0, 0, seq2 }, end_node }; struct test_node stream[] = { { T_MAP, 0, 0, map }, end_node }; --- test: Sequence key shortcut spec: 2.12 yaml: | --- # products purchased - item : Super Hoop quantity: 1 - item : Basketball quantity: 4 - item : Big Shoes quantity: 1 php: | array ( array ( 'item' => 'Super Hoop', 'quantity' => 1, ), array ( 'item' => 'Basketball', 'quantity' => 4, ), array ( 'item' => 'Big Shoes', 'quantity' => 1, ) ) perl: | [ { item => 'Super Hoop', quantity => 1 }, { item => 'Basketball', quantity => 4 }, { item => 'Big Shoes', quantity => 1 } ] ruby: | [ { 'item' => 'Super Hoop', 'quantity' => 1 }, { 'item' => 'Basketball', 'quantity' => 4 }, { 'item' => 'Big Shoes', 'quantity' => 1 } ] python: | [ { 'item': 'Super Hoop', 'quantity': 1 }, { 'item': 'Basketball', 'quantity': 4 }, { 'item': 'Big Shoes', 'quantity': 1 } ] syck: | struct test_node map1[] = { { T_STR, 0, "item" }, { T_STR, 0, "Super Hoop" }, { T_STR, 0, "quantity" }, { T_STR, 0, "1" }, end_node }; struct test_node map2[] = { { T_STR, 0, "item" }, { T_STR, 0, "Basketball" }, { T_STR, 0, "quantity" }, { T_STR, 0, "4" }, end_node }; struct test_node map3[] = { { T_STR, 0, "item" }, { T_STR, 0, "Big Shoes" }, { T_STR, 0, "quantity" }, { T_STR, 0, "1" }, end_node }; struct test_node seq[] = { { T_MAP, 0, 0, map1 }, { T_MAP, 0, 0, map2 }, { T_MAP, 0, 0, map3 }, end_node }; struct test_node stream[] = { { T_SEQ, 0, 0, seq }, end_node }; --- test: Literal perserves newlines todo: true spec: 2.13 yaml: | # ASCII Art --- | \//||\/|| // || ||_ perl: | "\\//||\\/||\n// || ||_\n" ruby: | "\\//||\\/||\n// || ||_\n" python: | [ flushLeft( """ \//||\/|| // || ||_ """ ) ] syck: | struct test_node stream[] = { { T_STR, 0, "\\//||\\/||\n// || ||_\n" }, end_node }; --- test: Folded treats newlines as a space todo: true spec: 2.14 yaml: | --- Mark McGwire's year was crippled by a knee injury. perl: | "Mark McGwire's year was crippled by a knee injury." ruby: | "Mark McGwire's year was crippled by a knee injury." python: | [ "Mark McGwire's year was crippled by a knee injury." ] syck: | struct test_node stream[] = { { T_STR, 0, "Mark McGwire's year was crippled by a knee injury." }, end_node }; --- test: Newlines preserved for indented and blank lines todo: true spec: 2.15 yaml: | --- > Sammy Sosa completed another fine season with great stats. 63 Home Runs 0.288 Batting Average What a year! perl: | "Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!\n" ruby: | "Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!\n" python: | [ flushLeft( """ Sammy Sosa completed another fine season with great stats. 63 Home Runs 0.288 Batting Average What a year! """ ) ] syck: | struct test_node stream[] = { { T_STR, 0, "Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!\n" }, end_node }; --- test: Indentation determines scope spec: 2.16 yaml: | name: Mark McGwire accomplishment: > Mark set a major league home run record in 1998. stats: | 65 Home Runs 0.278 Batting Average php: | array( 'name' => 'Mark McGwire', 'accomplishment' => "Mark set a major league home run record in 1998.\n", 'stats' => "65 Home Runs\n0.278 Batting Average\n" ) --- test: Quoted scalars todo: true spec: 2.17 yaml: | unicode: "Sosa did fine.\u263A" control: "\b1998\t1999\t2000\n" hexesc: "\x0D\x0A is \r\n" single: '"Howdy!" he cried.' quoted: ' # not a ''comment''.' tie-fighter: '|\-*-/|' ruby: | { "tie-fighter" => "|\\-*-/|", "control"=>"\0101998\t1999\t2000\n", "unicode"=>"Sosa did fine." + ["263A".hex ].pack('U*'), "quoted"=>" # not a 'comment'.", "single"=>"\"Howdy!\" he cried.", "hexesc"=>"\r\n is \r\n" } --- test: Multiline flow scalars todo: true spec: 2.18 yaml: | plain: This unquoted scalar spans many lines. quoted: "So does this quoted scalar.\n" ruby: | { 'plain' => 'This unquoted scalar spans many lines.', 'quoted' => "So does this quoted scalar.\n" } --- test: Integers spec: 2.19 yaml: | canonical: 12345 decimal: +12,345 octal: 014 hexadecimal: 0xC php: | array( 'canonical' => 12345, 'decimal' => 12345, 'octal' => 014, 'hexadecimal' => 0xC ) --- # FIX: spec shows parens around -inf and NaN test: Floating point spec: 2.20 yaml: | canonical: 1.23015e+3 exponential: 12.3015e+02 fixed: 1,230.15 negative infinity: -.inf not a number: .NaN php: | array( 'canonical' => 1230.15, 'exponential' => 1230.15, 'fixed' => 1230.15, 'negative infinity' => log(0), 'not a number' => -log(0), ) --- test: Miscellaneous spec: 2.21 yaml: | null: ~ true: true false: false string: '12345' php: | array( '' => null, 1 => true, 0 => false, 'string' => '12345' ) --- test: Timestamps todo: true spec: 2.22 yaml: | canonical: 2001-12-15T02:59:43.1Z iso8601: 2001-12-14t21:59:43.10-05:00 spaced: 2001-12-14 21:59:43.10 -05:00 date: 2002-12-14 # Time is noon UTC php: | array( 'canonical' => YAML::mktime( 2001, 12, 15, 2, 59, 43, 0.10 ), 'iso8601' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'spaced' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'date' => Date.new( 2002, 12, 14 ) ) --- test: legacy Timestamps test todo: true spec: legacy D4 yaml: | canonical: 2001-12-15T02:59:43.00Z iso8601: 2001-02-28t21:59:43.00-05:00 spaced: 2001-12-14 21:59:43.00 -05:00 date: 2002-12-14 php: | array( 'canonical' => Time::utc( 2001, 12, 15, 2, 59, 43, 0 ), 'iso8601' => YAML::mktime( 2001, 2, 28, 21, 59, 43, 0, "-05:00" ), 'spaced' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0, "-05:00" ), 'date' => Date.new( 2002, 12, 14 ) ) --- test: Various explicit families todo: true spec: 2.23 yaml: | not-date: !str 2002-04-28 picture: !binary | R0lGODlhDAAMAIQAAP//9/X 17unp5WZmZgAAAOfn515eXv Pz7Y6OjuDg4J+fn5OTk6enp 56enmleECcgggoBADs= application specific tag: !!something | The semantics of the tag above may be different for different documents. ruby-setup: | YAML.add_private_type( "something" ) do |type, val| "SOMETHING: #{val}" end ruby: | { 'not-date' => '2002-04-28', 'picture' => "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236i^\020' \202\n\001\000;", 'application specific tag' => "SOMETHING: The semantics of the tag\nabove may be different for\ndifferent documents.\n" } --- test: Application specific family todo: true spec: 2.24 yaml: | # Establish a tag prefix --- !clarkevans.com,2002/graph/^shape # Use the prefix: shorthand for # !clarkevans.com,2002/graph/circle - !^circle center: &ORIGIN {x: 73, 'y': 129} radius: 7 - !^line # !clarkevans.com,2002/graph/line start: *ORIGIN finish: { x: 89, 'y': 102 } - !^label start: *ORIGIN color: 0xFFEEBB value: Pretty vector drawing. ruby-setup: | YAML.add_domain_type( "clarkevans.com,2002", 'graph/shape' ) { |type, val| if Array === val val << "Shape Container" val else raise YAML::Error, "Invalid graph of class #{ val.class }: " + val.inspect end } one_shape_proc = Proc.new { |type, val| scheme, domain, type = type.split( /:/, 3 ) if val.is_a? ::Hash val['TYPE'] = "Shape: #{type}" val else raise YAML::Error, "Invalid graph of class #{ val.class }: " + val.inspect end } YAML.add_domain_type( "clarkevans.com,2002", 'graph/circle', &one_shape_proc ) YAML.add_domain_type( "clarkevans.com,2002", 'graph/line', &one_shape_proc ) YAML.add_domain_type( "clarkevans.com,2002", 'graph/label', &one_shape_proc ) ruby: | [ { "radius" => 7, "center"=> { "x" => 73, "y" => 129 }, "TYPE" => "Shape: graph/circle" }, { "finish" => { "x" => 89, "y" => 102 }, "TYPE" => "Shape: graph/line", "start" => { "x" => 73, "y" => 129 } }, { "TYPE" => "Shape: graph/label", "value" => "Pretty vector drawing.", "start" => { "x" => 73, "y" => 129 }, "color" => 16772795 }, "Shape Container" ] # --- # test: Unordered set # spec: 2.25 # yaml: | # # sets are represented as a # # mapping where each key is # # associated with the empty string # --- !set # ? Mark McGwire # ? Sammy Sosa # ? Ken Griff --- test: Ordered mappings todo: true spec: 2.26 yaml: | # ordered maps are represented as # a sequence of mappings, with # each mapping having one key --- !omap - Mark McGwire: 65 - Sammy Sosa: 63 - Ken Griffy: 58 ruby: | YAML::Omap[ 'Mark McGwire', 65, 'Sammy Sosa', 63, 'Ken Griffy', 58 ] --- test: Invoice dump_skip: true spec: 2.27 yaml: | --- !clarkevans.com,2002/^invoice invoice: 34843 date : 2001-01-23 bill-to: &id001 given : Chris family : Dumars address: lines: | 458 Walkman Dr. Suite #292 city : Royal Oak state : MI postal : 48046 ship-to: *id001 product: - sku : BL394D quantity : 4 description : Basketball price : 450.00 - sku : BL4438H quantity : 1 description : Super Hoop price : 2392.00 tax : 251.42 total: 4443.52 comments: > Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338. php: | array( 'invoice' => 34843, 'date' => mktime(0, 0, 0, 1, 23, 2001), 'bill-to' => array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) ) , 'ship-to' => array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) ) , 'product' => array( array( 'sku' => 'BL394D', 'quantity' => 4, 'description' => 'Basketball', 'price' => 450.00 ), array( 'sku' => 'BL4438H', 'quantity' => 1, 'description' => 'Super Hoop', 'price' => 2392.00 ) ), 'tax' => 251.42, 'total' => 4443.52, 'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n" ) --- test: Log file todo: true spec: 2.28 yaml: | --- Time: 2001-11-23 15:01:42 -05:00 User: ed Warning: > This is an error message for the log file --- Time: 2001-11-23 15:02:31 -05:00 User: ed Warning: > A slightly different error message. --- Date: 2001-11-23 15:03:17 -05:00 User: ed Fatal: > Unknown variable "bar" Stack: - file: TopClass.py line: 23 code: | x = MoreObject("345\n") - file: MoreClass.py line: 58 code: |- foo = bar ruby: | y = YAML::Stream.new y.add( { 'Time' => YAML::mktime( 2001, 11, 23, 15, 01, 42, 00, "-05:00" ), 'User' => 'ed', 'Warning' => "This is an error message for the log file\n" } ) y.add( { 'Time' => YAML::mktime( 2001, 11, 23, 15, 02, 31, 00, "-05:00" ), 'User' => 'ed', 'Warning' => "A slightly different error message.\n" } ) y.add( { 'Date' => YAML::mktime( 2001, 11, 23, 15, 03, 17, 00, "-05:00" ), 'User' => 'ed', 'Fatal' => "Unknown variable \"bar\"\n", 'Stack' => [ { 'file' => 'TopClass.py', 'line' => 23, 'code' => "x = MoreObject(\"345\\n\")\n" }, { 'file' => 'MoreClass.py', 'line' => 58, 'code' => "foo = bar" } ] } ) documents: 3 --- test: Throwaway comments yaml: | ### These are four throwaway comment ### ### lines (the second line is empty). ### this: | # Comments may trail lines. contains three lines of text. The third one starts with a # character. This isn't a comment. # These are three throwaway comment # lines (the first line is empty). php: | array( 'this' => "contains three lines of text.\nThe third one starts with a\n# character. This isn't a comment.\n" ) --- test: Document with a single value todo: true yaml: | --- > This YAML stream contains a single text value. The next stream is a log file - a sequence of log entries. Adding an entry to the log is a simple matter of appending it at the end. ruby: | "This YAML stream contains a single text value. The next stream is a log file - a sequence of log entries. Adding an entry to the log is a simple matter of appending it at the end.\n" --- test: Document stream todo: true yaml: | --- at: 2001-08-12 09:25:00.00 Z type: GET HTTP: '1.0' url: '/index.html' --- at: 2001-08-12 09:25:10.00 Z type: GET HTTP: '1.0' url: '/toc.html' ruby: | y = YAML::Stream.new y.add( { 'at' => Time::utc( 2001, 8, 12, 9, 25, 00 ), 'type' => 'GET', 'HTTP' => '1.0', 'url' => '/index.html' } ) y.add( { 'at' => Time::utc( 2001, 8, 12, 9, 25, 10 ), 'type' => 'GET', 'HTTP' => '1.0', 'url' => '/toc.html' } ) documents: 2 --- test: Top level mapping yaml: | # This stream is an example of a top-level mapping. invoice : 34843 date : 2001-01-23 total : 4443.52 php: | array( 'invoice' => 34843, 'date' => mktime(0, 0, 0, 1, 23, 2001), 'total' => 4443.52 ) --- test: Single-line documents todo: true yaml: | # The following is a sequence of three documents. # The first contains an empty mapping, the second # an empty sequence, and the last an empty string. --- {} --- [ ] --- '' ruby: | y = YAML::Stream.new y.add( {} ) y.add( [] ) y.add( '' ) documents: 3 --- test: Document with pause todo: true yaml: | # A communication channel based on a YAML stream. --- sent at: 2002-06-06 11:46:25.10 Z payload: Whatever # Receiver can process this as soon as the following is sent: ... # Even if the next message is sent long after: --- sent at: 2002-06-06 12:05:53.47 Z payload: Whatever ... ruby: | y = YAML::Stream.new y.add( { 'sent at' => YAML::mktime( 2002, 6, 6, 11, 46, 25, 0.10 ), 'payload' => 'Whatever' } ) y.add( { "payload" => "Whatever", "sent at" => YAML::mktime( 2002, 6, 6, 12, 5, 53, 0.47 ) } ) documents: 2 --- test: Explicit typing yaml: | integer: 12 also int: ! "12" string: !str 12 php: | array( 'integer' => 12, 'also int' => 12, 'string' => '12' ) --- test: Private types todo: true yaml: | # Both examples below make use of the 'x-private:ball' # type family URI, but with different semantics. --- pool: !!ball number: 8 color: black --- bearing: !!ball material: steel ruby: | y = YAML::Stream.new y.add( { 'pool' => YAML::PrivateType.new( 'ball', { 'number' => 8, 'color' => 'black' } ) } ) y.add( { 'bearing' => YAML::PrivateType.new( 'ball', { 'material' => 'steel' } ) } ) documents: 2 --- test: Type family under yaml.org yaml: | # The URI is 'tag:yaml.org,2002:str' - !str a Unicode string php: | array( 'a Unicode string' ) --- test: Type family under perl.yaml.org todo: true yaml: | # The URI is 'tag:perl.yaml.org,2002:Text::Tabs' - !perl/Text::Tabs {} ruby: | [ YAML::DomainType.new( 'perl.yaml.org,2002', 'Text::Tabs', {} ) ] --- test: Type family under clarkevans.com todo: true yaml: | # The URI is 'tag:clarkevans.com,2003-02:timesheet' - !clarkevans.com,2003-02/timesheet {} ruby: | [ YAML::DomainType.new( 'clarkevans.com,2003-02', 'timesheet', {} ) ] --- test: URI Escaping todo: true yaml: | same: - !domain.tld,2002/type\x30 value - !domain.tld,2002/type0 value different: # As far as the YAML parser is concerned - !domain.tld,2002/type%30 value - !domain.tld,2002/type0 value ruby-setup: | YAML.add_domain_type( "domain.tld,2002", "type0" ) { |type, val| "ONE: #{val}" } YAML.add_domain_type( "domain.tld,2002", "type%30" ) { |type, val| "TWO: #{val}" } ruby: | { 'same' => [ 'ONE: value', 'ONE: value' ], 'different' => [ 'TWO: value', 'ONE: value' ] } --- test: URI Prefixing todo: true yaml: | # 'tag:domain.tld,2002:invoice' is some type family. invoice: !domain.tld,2002/^invoice # 'seq' is shorthand for 'tag:yaml.org,2002:seq'. # This does not effect '^customer' below # because it is does not specify a prefix. customers: !seq # '^customer' is shorthand for the full # notation 'tag:domain.tld,2002:customer'. - !^customer given : Chris family : Dumars ruby-setup: | YAML.add_domain_type( "domain.tld,2002", /(invoice|customer)/ ) { |type, val| if val.is_a? ::Hash scheme, domain, type = type.split( /:/, 3 ) val['type'] = "domain #{type}" val else raise YAML::Error, "Not a Hash in domain.tld/invoice: " + val.inspect end } ruby: | { "invoice"=> { "customers"=> [ { "given"=>"Chris", "type"=>"domain customer", "family"=>"Dumars" } ], "type"=>"domain invoice" } } --- test: Overriding anchors yaml: | anchor : &A001 This scalar has an anchor. override : &A001 > The alias node below is a repeated use of this value. alias : *A001 php: | array( 'anchor' => 'This scalar has an anchor.', 'override' => "The alias node below is a repeated use of this value.\n", 'alias' => "The alias node below is a repeated use of this value.\n" ) --- test: Flow and block formatting todo: true yaml: | empty: [] flow: [ one, two, three # May span lines, , four, # indentation is five ] # mostly ignored. block: - First item in top sequence - - Subordinate sequence entry - > A folded sequence entry - Sixth item in top sequence ruby: | { 'empty' => [], 'flow' => [ 'one', 'two', 'three', 'four', 'five' ], 'block' => [ 'First item in top sequence', [ 'Subordinate sequence entry' ], "A folded sequence entry\n", 'Sixth item in top sequence' ] } --- test: Complete mapping test todo: true yaml: | empty: {} flow: { one: 1, two: 2 } spanning: { one: 1, two: 2 } block: first : First entry second: key: Subordinate mapping third: - Subordinate sequence - { } - Previous mapping is empty. - A key: value pair in a sequence. A second: key:value pair. - The previous entry is equal to the following one. - A key: value pair in a sequence. A second: key:value pair. !float 12 : This key is a float. ? > ? : This key had to be protected. "\a" : This key had to be escaped. ? > This is a multi-line folded key : Whose value is also multi-line. ? this also works as a key : with a value at the next line. ? - This key - is a sequence : - With a sequence value. ? This: key is a: mapping : with a: mapping value. ruby: | { 'empty' => {}, 'flow' => { 'one' => 1, 'two' => 2 }, 'spanning' => { 'one' => 1, 'two' => 2 }, 'block' => { 'first' => 'First entry', 'second' => { 'key' => 'Subordinate mapping' }, 'third' => [ 'Subordinate sequence', {}, 'Previous mapping is empty.', { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' }, 'The previous entry is equal to the following one.', { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' } ], 12.0 => 'This key is a float.', "?\n" => 'This key had to be protected.', "\a" => 'This key had to be escaped.', "This is a multi-line folded key\n" => "Whose value is also multi-line.", 'this also works as a key' => 'with a value at the next line.', [ 'This key', 'is a sequence' ] => [ 'With a sequence value.' ] } } # Couldn't recreate map exactly, so we'll do a detailed check to be sure it's entact obj_y['block'].keys.each { |k| if Hash === k v = obj_y['block'][k] if k['This'] == 'key' and k['is a'] == 'mapping' and v['with a'] == 'mapping value.' obj_r['block'][k] = v end end } --- test: Literal explicit indentation yaml: | # Explicit indentation must # be given in all the three # following cases. leading spaces: |2 This value starts with four spaces. leading line break: |2 This value starts with a line break. leading comment indicator: |2 # first line starts with a # character. # Explicit indentation may # also be given when it is # not required. redundant: |2 This value is indented 2 spaces. php: | array( 'leading spaces' => " This value starts with four spaces.\n", 'leading line break' => "\nThis value starts with a line break.\n", 'leading comment indicator' => "# first line starts with a\n# character.\n", 'redundant' => "This value is indented 2 spaces.\n" ) --- test: Chomping and keep modifiers yaml: | clipped: | This has one newline. same as "clipped" above: "This has one newline.\n" stripped: |- This has no newline. same as "stripped" above: "This has no newline." kept: |+ This has two newlines. same as "kept" above: "This has two newlines.\n\n" php: | array( 'clipped' => "This has one newline.\n", 'same as "clipped" above' => "This has one newline.\n", 'stripped' => 'This has no newline.', 'same as "stripped" above' => 'This has no newline.', 'kept' => "This has two newlines.\n\n", 'same as "kept" above' => "This has two newlines.\n\n" ) --- test: Literal combinations todo: true yaml: | empty: | literal: | The \ ' " characters may be freely used. Leading white space is significant. Line breaks are significant. Thus this value contains one empty line and ends with a single line break, but does not start with one. is equal to: "The \\ ' \" characters may \ be\nfreely used. Leading white\n space \ is significant.\n\nLine breaks are \ significant.\nThus this value contains \ one\nempty line and ends with a\nsingle \ line break, but does\nnot start with one.\n" # Comments may follow a block # scalar value. They must be # less indented. # Modifiers may be combined in any order. indented and chomped: |2- This has no newline. also written as: |-2 This has no newline. both are equal to: " This has no newline." php: | array( 'empty' => '', 'literal' => "The \\ ' \" characters may be\nfreely used. Leading white\n space " + "is significant.\n\nLine breaks are significant.\nThus this value contains one\n" + "empty line and ends with a\nsingle line break, but does\nnot start with one.\n", 'is equal to' => "The \\ ' \" characters may be\nfreely used. Leading white\n space " + "is significant.\n\nLine breaks are significant.\nThus this value contains one\n" + "empty line and ends with a\nsingle line break, but does\nnot start with one.\n", 'indented and chomped' => ' This has no newline.', 'also written as' => ' This has no newline.', 'both are equal to' => ' This has no newline.' ) --- test: Folded combinations todo: true yaml: | empty: > one paragraph: > Line feeds are converted to spaces, so this value contains no line breaks except for the final one. multiple paragraphs: >2 An empty line, either at the start or in the value: Is interpreted as a line break. Thus this value contains three line breaks. indented text: > This is a folded paragraph followed by a list: * first entry * second entry Followed by another folded paragraph, another list: * first entry * second entry And a final folded paragraph. above is equal to: | This is a folded paragraph followed by a list: * first entry * second entry Followed by another folded paragraph, another list: * first entry * second entry And a final folded paragraph. # Explicit comments may follow # but must be less indented. php: | array( 'empty' => '', 'one paragraph' => 'Line feeds are converted to spaces, so this value'. " contains no line breaks except for the final one.\n", 'multiple paragraphs' => "\nAn empty line, either at the start or in the value:\n". "Is interpreted as a line break. Thus this value contains three line breaks.\n", 'indented text' => "This is a folded paragraph followed by a list:\n". " * first entry\n * second entry\nFollowed by another folded paragraph, ". "another list:\n\n * first entry\n\n * second entry\n\nAnd a final folded paragraph.\n", 'above is equal to' => "This is a folded paragraph followed by a list:\n". " * first entry\n * second entry\nFollowed by another folded paragraph, ". "another list:\n\n * first entry\n\n * second entry\n\nAnd a final folded paragraph.\n" ) --- test: Single quotes todo: true yaml: | empty: '' second: '! : \ etc. can be used freely.' third: 'a single quote '' must be escaped.' span: 'this contains six spaces and one line break' is same as: "this contains six spaces\nand one line break" php: | array( 'empty' => '', 'second' => '! : \\ etc. can be used freely.', 'third' => "a single quote ' must be escaped.", 'span' => "this contains six spaces\nand one line break", 'is same as' => "this contains six spaces\nand one line break" ) --- test: Double quotes todo: true yaml: | empty: "" second: "! : etc. can be used freely." third: "a \" or a \\ must be escaped." fourth: "this value ends with an LF.\n" span: "this contains four \ spaces" is equal to: "this contains four spaces" php: | array( 'empty' => '', 'second' => '! : etc. can be used freely.', 'third' => 'a " or a \\ must be escaped.', 'fourth' => "this value ends with an LF.\n", 'span' => "this contains four spaces", 'is equal to' => "this contains four spaces" ) --- test: Unquoted strings todo: true yaml: | first: There is no unquoted empty string. second: 12 ## This is an integer. third: !str 12 ## This is a string. span: this contains six spaces and one line break indicators: this has no comments. #:foo and bar# are both text. flow: [ can span lines, # comment like this ] note: { one-line keys: but multi-line values } php: | array( 'first' => 'There is no unquoted empty string.', 'second' => 12, 'third' => '12', 'span' => "this contains six spaces\nand one line break", 'indicators' => "this has no comments. #:foo and bar# are both text.", 'flow' => [ 'can span lines', 'like this' ], 'note' => { 'one-line keys' => 'but multi-line values' } ) --- test: Spanning sequences todo: true yaml: | # The following are equal seqs # with different identities. flow: [ one, two ] spanning: [ one, two ] block: - one - two php: | array( 'flow' => [ 'one', 'two' ], 'spanning' => [ 'one', 'two' ], 'block' => [ 'one', 'two' ] ) --- test: Flow mappings yaml: | # The following are equal maps # with different identities. flow: { one: 1, two: 2 } block: one: 1 two: 2 php: | array( 'flow' => array( 'one' => 1, 'two' => 2 ), 'block' => array( 'one' => 1, 'two' => 2 ) ) --- test: Representations of 12 todo: true yaml: | - 12 # An integer # The following scalars # are loaded to the # string value '1' '2'. - !str 12 - '12' - "12" - "\ 1\ 2\ " # Strings containing paths and regexps can be unquoted: - /foo/bar - d:/foo/bar - foo/bar - /a.*b/ php: | array( 12, '12', '12', '12', '12', '/foo/bar', 'd:/foo/bar', 'foo/bar', '/a.*b/' ) --- test: "Null" todo: true yaml: | canonical: ~ english: null # This sequence has five # entries, two with values. sparse: - ~ - 2nd entry - Null - 4th entry - four: This mapping has five keys, only two with values. php: | array ( 'canonical' => null, 'english' => null, 'sparse' => array( null, '2nd entry', null, '4th entry', null ]), 'four' => 'This mapping has five keys, only two with values.' ) --- test: Omap todo: true yaml: | # Explicitly typed dictionary. Bestiary: !omap - aardvark: African pig-like ant eater. Ugly. - anteater: South-American ant eater. Two species. - anaconda: South-American constrictor snake. Scary. # Etc. ruby: | { 'Bestiary' => YAML::Omap[ 'aardvark', 'African pig-like ant eater. Ugly.', 'anteater', 'South-American ant eater. Two species.', 'anaconda', 'South-American constrictor snake. Scary.' ] } --- test: Pairs todo: true yaml: | # Explicitly typed pairs. tasks: !pairs - meeting: with team. - meeting: with boss. - break: lunch. - meeting: with client. ruby: | { 'tasks' => YAML::Pairs[ 'meeting', 'with team.', 'meeting', 'with boss.', 'break', 'lunch.', 'meeting', 'with client.' ] } --- test: Set todo: true yaml: | # Explicitly typed set. baseball players: !set Mark McGwire: Sammy Sosa: Ken Griffey: ruby: | { 'baseball players' => YAML::Set[ 'Mark McGwire', nil, 'Sammy Sosa', nil, 'Ken Griffey', nil ] } --- test: Boolean yaml: | false: used as key logical: true answer: false php: | array( false => 'used as key', 'logical' => true, 'answer' => false ) --- test: Integer yaml: | canonical: 12345 decimal: +12,345 octal: 014 hexadecimal: 0xC php: | array( 'canonical' => 12345, 'decimal' => 12345, 'octal' => 12, 'hexadecimal' => 12 ) --- test: Float yaml: | canonical: 1.23015e+3 exponential: 12.3015e+02 fixed: 1,230.15 negative infinity: -.inf not a number: .NaN php: | array( 'canonical' => 1230.15, 'exponential' => 1230.15, 'fixed' => 1230.15, 'negative infinity' => log(0), 'not a number' => -log(0) ) --- test: Timestamp todo: true yaml: | canonical: 2001-12-15T02:59:43.1Z valid iso8601: 2001-12-14t21:59:43.10-05:00 space separated: 2001-12-14 21:59:43.10 -05:00 date (noon UTC): 2002-12-14 ruby: | array( 'canonical' => YAML::mktime( 2001, 12, 15, 2, 59, 43, 0.10 ), 'valid iso8601' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'space separated' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'date (noon UTC)' => Date.new( 2002, 12, 14 ) ) --- test: Binary todo: true yaml: | canonical: !binary "\ R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\ OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\ +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\ AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=" base64: !binary | R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= description: > The binary value above is a tiny arrow encoded as a gif image. ruby-setup: | arrow_gif = "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236iiiccc\243\243\243\204\204\204\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371!\376\016Made with GIMP\000,\000\000\000\000\f\000\f\000\000\005, \216\2010\236\343@\024\350i\020\304\321\212\010\034\317\200M$z\357\3770\205p\270\2601f\r\e\316\001\303\001\036\020' \202\n\001\000;" ruby: | { 'canonical' => arrow_gif, 'base64' => arrow_gif, 'description' => "The binary value above is a tiny arrow encoded as a gif image.\n" } --- test: Merge key todo: true yaml: | --- - &CENTER { x: 1, y: 2 } - &LEFT { x: 0, y: 2 } - &BIG { r: 10 } - &SMALL { r: 1 } # All the following maps are equal: - # Explicit keys x: 1 y: 2 r: 10 label: center/big - # Merge one map << : *CENTER r: 10 label: center/big - # Merge multiple maps << : [ *CENTER, *BIG ] label: center/big - # Override << : [ *BIG, *LEFT, *SMALL ] x: 1 label: center/big ruby-setup: | center = { 'x' => 1, 'y' => 2 } left = { 'x' => 0, 'y' => 2 } big = { 'r' => 10 } small = { 'r' => 1 } node1 = { 'x' => 1, 'y' => 2, 'r' => 10, 'label' => 'center/big' } node2 = center.dup node2.update( { 'r' => 10, 'label' => 'center/big' } ) node3 = big.dup node3.update( center ) node3.update( { 'label' => 'center/big' } ) node4 = small.dup node4.update( left ) node4.update( big ) node4.update( { 'x' => 1, 'label' => 'center/big' } ) ruby: | [ center, left, big, small, node1, node2, node3, node4 ] --- test: Default key todo: true yaml: | --- # Old schema link with: - library1.dll - library2.dll --- # New schema link with: - = : library1.dll version: 1.2 - = : library2.dll version: 2.3 ruby: | y = YAML::Stream.new y.add( { 'link with' => [ 'library1.dll', 'library2.dll' ] } ) obj_h = Hash[ 'version' => 1.2 ] obj_h.default = 'library1.dll' obj_h2 = Hash[ 'version' => 2.3 ] obj_h2.default = 'library2.dll' y.add( { 'link with' => [ obj_h, obj_h2 ] } ) documents: 2 --- test: Special keys todo: true yaml: | "!": These three keys "&": had to be quoted "=": and are normal strings. # NOTE: the following node should NOT be serialized this way. encoded node : !special '!' : '!type' !special|canonical '&' : 12 = : value # The proper way to serialize the above node is as follows: node : !!type &12 value ruby: | { '!' => 'These three keys', '&' => 'had to be quoted', '=' => 'and are normal strings.', 'encoded node' => YAML::PrivateType.new( 'type', 'value' ), 'node' => YAML::PrivateType.new( 'type', 'value' ) } PK!~;p2p25test/Yaml/Symfony/Component/Yaml/Tests/ParserTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Tests; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Parser; class ParserTest extends \PHPUnit_Framework_TestCase { protected $parser; protected function setUp() { $this->parser = new Parser(); } protected function tearDown() { $this->parser = null; } /** * @dataProvider getDataFormSpecifications */ public function testSpecifications($file, $expected, $yaml, $comment) { if ('escapedCharacters' == $file) { if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) { $this->markTestSkipped('The iconv and mbstring extensions are not available.'); } } $this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment); } public function getDataFormSpecifications() { $parser = new Parser(); $path = __DIR__.'/Fixtures'; $tests = array(); $files = $parser->parse(file_get_contents($path.'/index.yml')); foreach ($files as $file) { $yamls = file_get_contents($path.'/'.$file.'.yml'); // split YAMLs documents foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) { if (!$yaml) { continue; } $test = $parser->parse($yaml); if (isset($test['todo']) && $test['todo']) { // TODO } else { eval('$expected = '.trim($test['php']).';'); $tests[] = array($file, var_export($expected, true), $test['yaml'], $test['test']); } } } return $tests; } public function testTabsInYaml() { // test tabs in YAML $yamls = array( "foo:\n bar", "foo:\n bar", "foo:\n bar", "foo:\n bar", ); foreach ($yamls as $yaml) { try { $content = $this->parser->parse($yaml); $this->fail('YAML files must not contain tabs'); } catch (\Exception $e) { $this->assertInstanceOf('\Exception', $e, 'YAML files must not contain tabs'); $this->assertEquals('A YAML file cannot contain tabs as indentation at line 2 (near "'.strpbrk($yaml, "\t").'").', $e->getMessage(), 'YAML files must not contain tabs'); } } } public function testEndOfTheDocumentMarker() { $yaml = <<assertEquals('foo', $this->parser->parse($yaml)); } public function getBlockChompingTests() { $tests = array(); $yaml = <<<'EOF' foo: |- one two bar: |- one two EOF; $expected = array( 'foo' => "one\ntwo", 'bar' => "one\ntwo", ); $tests['Literal block chomping strip with single trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: |- one two bar: |- one two EOF; $expected = array( 'foo' => "one\ntwo", 'bar' => "one\ntwo", ); $tests['Literal block chomping strip with multiple trailing newlines'] = array($expected, $yaml); $yaml = <<<'EOF' foo: |- one two bar: |- one two EOF; $expected = array( 'foo' => "one\ntwo", 'bar' => "one\ntwo", ); $tests['Literal block chomping strip without trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: | one two bar: | one two EOF; $expected = array( 'foo' => "one\ntwo\n", 'bar' => "one\ntwo\n", ); $tests['Literal block chomping clip with single trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: | one two bar: | one two EOF; $expected = array( 'foo' => "one\ntwo\n", 'bar' => "one\ntwo\n", ); $tests['Literal block chomping clip with multiple trailing newlines'] = array($expected, $yaml); $yaml = <<<'EOF' foo: | one two bar: | one two EOF; $expected = array( 'foo' => "one\ntwo\n", 'bar' => "one\ntwo", ); $tests['Literal block chomping clip without trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: |+ one two bar: |+ one two EOF; $expected = array( 'foo' => "one\ntwo\n", 'bar' => "one\ntwo\n", ); $tests['Literal block chomping keep with single trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: |+ one two bar: |+ one two EOF; $expected = array( 'foo' => "one\ntwo\n\n", 'bar' => "one\ntwo\n\n", ); $tests['Literal block chomping keep with multiple trailing newlines'] = array($expected, $yaml); $yaml = <<<'EOF' foo: |+ one two bar: |+ one two EOF; $expected = array( 'foo' => "one\ntwo\n", 'bar' => "one\ntwo", ); $tests['Literal block chomping keep without trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: >- one two bar: >- one two EOF; $expected = array( 'foo' => "one two", 'bar' => "one two", ); $tests['Folded block chomping strip with single trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: >- one two bar: >- one two EOF; $expected = array( 'foo' => "one two", 'bar' => "one two", ); $tests['Folded block chomping strip with multiple trailing newlines'] = array($expected, $yaml); $yaml = <<<'EOF' foo: >- one two bar: >- one two EOF; $expected = array( 'foo' => "one two", 'bar' => "one two", ); $tests['Folded block chomping strip without trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: > one two bar: > one two EOF; $expected = array( 'foo' => "one two\n", 'bar' => "one two\n", ); $tests['Folded block chomping clip with single trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: > one two bar: > one two EOF; $expected = array( 'foo' => "one two\n", 'bar' => "one two\n", ); $tests['Folded block chomping clip with multiple trailing newlines'] = array($expected, $yaml); $yaml = <<<'EOF' foo: > one two bar: > one two EOF; $expected = array( 'foo' => "one two\n", 'bar' => "one two", ); $tests['Folded block chomping clip without trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: >+ one two bar: >+ one two EOF; $expected = array( 'foo' => "one two\n", 'bar' => "one two\n", ); $tests['Folded block chomping keep with single trailing newline'] = array($expected, $yaml); $yaml = <<<'EOF' foo: >+ one two bar: >+ one two EOF; $expected = array( 'foo' => "one two\n\n", 'bar' => "one two\n\n", ); $tests['Folded block chomping keep with multiple trailing newlines'] = array($expected, $yaml); $yaml = <<<'EOF' foo: >+ one two bar: >+ one two EOF; $expected = array( 'foo' => "one two\n", 'bar' => "one two", ); $tests['Folded block chomping keep without trailing newline'] = array($expected, $yaml); return $tests; } /** * @dataProvider getBlockChompingTests */ public function testBlockChomping($expected, $yaml) { $this->assertSame($expected, $this->parser->parse($yaml)); } /** * Regression test for issue #7989. * * @see https://github.com/symfony/symfony/issues/7989 */ public function testBlockLiteralWithLeadingNewlines() { $yaml = <<<'EOF' foo: |- bar EOF; $expected = array( 'foo' => "\n\nbar" ); $this->assertSame($expected, $this->parser->parse($yaml)); } public function testObjectSupportEnabled() { $input = <<assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects'); } public function testObjectSupportDisabledButNoExceptions() { $input = <<assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects'); } /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testObjectsSupportDisabledWithExceptions() { $this->parser->parse('foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}', true, false); } public function testNonUtf8Exception() { if (!function_exists('mb_detect_encoding') || !function_exists('iconv')) { $this->markTestSkipped('Exceptions for non-utf8 charsets require the mb_detect_encoding() and iconv() functions.'); return; } $yamls = array( iconv("UTF-8", "ISO-8859-1", "foo: 'äöüß'"), iconv("UTF-8", "ISO-8859-15", "euro: '€'"), iconv("UTF-8", "CP1252", "cp1252: '©ÉÇáñ'") ); foreach ($yamls as $yaml) { try { $this->parser->parse($yaml); $this->fail('charsets other than UTF-8 are rejected.'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\Yaml\Exception\ParseException', $e, 'charsets other than UTF-8 are rejected.'); } } } /** * * @expectedException \Symfony\Component\Yaml\Exception\ParseException * */ public function testUnindentedCollectionException() { $yaml = <<parser->parse($yaml); } /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testSequenceInAMapping() { Yaml::parse(<<assertEquals(array('hash' => null), Yaml::parse($input)); } public function testStringBlockWithComments() { $this->assertEquals(array('content' => <<

title

footer # comment3 EOT ), Yaml::parse(<<

title

footer # comment3 EOF )); } public function testFoldedStringBlockWithComments() { $this->assertEquals(array(array('content' => <<

title

footer # comment3 EOT )), Yaml::parse(<<

title

footer # comment3 EOF )); } public function testNestedFoldedStringBlockWithComments() { $this->assertEquals(array(array( 'title' => 'some title', 'content' => <<

title

footer # comment3 EOT )), Yaml::parse(<<

title

footer # comment3 EOF )); } } class B { public $b = 'foo'; } PK!=ao[%[%5test/Yaml/Symfony/Component/Yaml/Tests/InlineTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Tests; use Symfony\Component\Yaml\Inline; class InlineTest extends \PHPUnit_Framework_TestCase { public function testParse() { foreach ($this->getTestsForParse() as $yaml => $value) { $this->assertSame($value, Inline::parse($yaml), sprintf('::parse() converts an inline YAML to a PHP structure (%s)', $yaml)); } } public function testDump() { $testsForDump = $this->getTestsForDump(); foreach ($testsForDump as $yaml => $value) { $this->assertEquals($yaml, Inline::dump($value), sprintf('::dump() converts a PHP structure to an inline YAML (%s)', $yaml)); } foreach ($this->getTestsForParse() as $value) { $this->assertEquals($value, Inline::parse(Inline::dump($value)), 'check consistency'); } foreach ($testsForDump as $value) { $this->assertEquals($value, Inline::parse(Inline::dump($value)), 'check consistency'); } } public function testDumpNumericValueWithLocale() { $locale = setlocale(LC_NUMERIC, 0); if (false === $locale) { $this->markTestSkipped('Your platform does not support locales.'); } $required_locales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252'); if (false === setlocale(LC_ALL, $required_locales)) { $this->markTestSkipped('Could not set any of required locales: '.implode(", ", $required_locales)); } $this->assertEquals('1.2', Inline::dump(1.2)); $this->assertContains('fr', strtolower(setlocale(LC_NUMERIC, 0))); setlocale(LC_ALL, $locale); } public function testHashStringsResemblingExponentialNumericsShouldNotBeChangedToINF() { $value = '686e444'; $this->assertSame($value, Inline::parse(Inline::dump($value))); } /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testParseScalarWithIncorrectlyQuotedStringShouldThrowException() { $value = "'don't do somthin' like that'"; Inline::parse($value); } /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testParseScalarWithIncorrectlyDoubleQuotedStringShouldThrowException() { $value = '"don"t do somthin" like that"'; Inline::parse($value); } /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testParseInvalidMappingKeyShouldThrowException() { $value = '{ "foo " bar": "bar" }'; Inline::parse($value); } /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testParseInvalidMappingShouldThrowException() { Inline::parse('[foo] bar'); } /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testParseInvalidSequenceShouldThrowException() { Inline::parse('{ foo: bar } bar'); } public function testParseScalarWithCorrectlyQuotedStringShouldReturnString() { $value = "'don''t do somthin'' like that'"; $expect = "don't do somthin' like that"; $this->assertSame($expect, Inline::parseScalar($value)); } protected function getTestsForParse() { return array( '' => '', 'null' => null, 'false' => false, 'true' => true, '12' => 12, '-12' => -12, '"quoted string"' => 'quoted string', "'quoted string'" => 'quoted string', '12.30e+02' => 12.30e+02, '0x4D2' => 0x4D2, '02333' => 02333, '.Inf' => -log(0), '-.Inf' => log(0), "'686e444'" => '686e444', '686e444' => 646e444, '123456789123456789123456789123456789' => '123456789123456789123456789123456789', '"foo\r\nbar"' => "foo\r\nbar", "'foo#bar'" => 'foo#bar', "'foo # bar'" => 'foo # bar', "'#cfcfcf'" => '#cfcfcf', '::form_base.html.twig' => '::form_base.html.twig', '2007-10-30' => mktime(0, 0, 0, 10, 30, 2007), '2007-10-30T02:59:43Z' => gmmktime(2, 59, 43, 10, 30, 2007), '2007-10-30 02:59:43 Z' => gmmktime(2, 59, 43, 10, 30, 2007), '1960-10-30 02:59:43 Z' => gmmktime(2, 59, 43, 10, 30, 1960), '1730-10-30T02:59:43Z' => gmmktime(2, 59, 43, 10, 30, 1730), '"a \\"string\\" with \'quoted strings inside\'"' => 'a "string" with \'quoted strings inside\'', "'a \"string\" with ''quoted strings inside'''" => 'a "string" with \'quoted strings inside\'', // sequences // urls are no key value mapping. see #3609. Valid yaml "key: value" mappings require a space after the colon '[foo, http://urls.are/no/mappings, false, null, 12]' => array('foo', 'http://urls.are/no/mappings', false, null, 12), '[ foo , bar , false , null , 12 ]' => array('foo', 'bar', false, null, 12), '[\'foo,bar\', \'foo bar\']' => array('foo,bar', 'foo bar'), // mappings '{foo:bar,bar:foo,false:false,null:null,integer:12}' => array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), '{ foo : bar, bar : foo, false : false, null : null, integer : 12 }' => array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), '{foo: \'bar\', bar: \'foo: bar\'}' => array('foo' => 'bar', 'bar' => 'foo: bar'), '{\'foo\': \'bar\', "bar": \'foo: bar\'}' => array('foo' => 'bar', 'bar' => 'foo: bar'), '{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}' => array('foo\'' => 'bar', "bar\"" => 'foo: bar'), '{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}' => array('foo: ' => 'bar', "bar: " => 'foo: bar'), // nested sequences and mappings '[foo, [bar, foo]]' => array('foo', array('bar', 'foo')), '[foo, {bar: foo}]' => array('foo', array('bar' => 'foo')), '{ foo: {bar: foo} }' => array('foo' => array('bar' => 'foo')), '{ foo: [bar, foo] }' => array('foo' => array('bar', 'foo')), '[ foo, [ bar, foo ] ]' => array('foo', array('bar', 'foo')), '[{ foo: {bar: foo} }]' => array(array('foo' => array('bar' => 'foo'))), '[foo, [bar, [foo, [bar, foo]], foo]]' => array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo')), '[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]' => array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo'))), '[foo, bar: { foo: bar }]' => array('foo', '1' => array('bar' => array('foo' => 'bar'))), '[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']' => array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%',), true, '@service_container',), ); } protected function getTestsForDump() { return array( 'null' => null, 'false' => false, 'true' => true, '12' => 12, "'quoted string'" => 'quoted string', '12.30e+02' => 12.30e+02, '1234' => 0x4D2, '1243' => 02333, '.Inf' => -log(0), '-.Inf' => log(0), "'686e444'" => '686e444', '"foo\r\nbar"' => "foo\r\nbar", "'foo#bar'" => 'foo#bar', "'foo # bar'" => 'foo # bar', "'#cfcfcf'" => '#cfcfcf', "'a \"string\" with ''quoted strings inside'''" => 'a "string" with \'quoted strings inside\'', "'-dash'" => '-dash', "'-'" => '-', // sequences '[foo, bar, false, null, 12]' => array('foo', 'bar', false, null, 12), '[\'foo,bar\', \'foo bar\']' => array('foo,bar', 'foo bar'), // mappings '{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }' => array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), '{ foo: bar, bar: \'foo: bar\' }' => array('foo' => 'bar', 'bar' => 'foo: bar'), // nested sequences and mappings '[foo, [bar, foo]]' => array('foo', array('bar', 'foo')), '[foo, [bar, [foo, [bar, foo]], foo]]' => array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo')), '{ foo: { bar: foo } }' => array('foo' => array('bar' => 'foo')), '[foo, { bar: foo }]' => array('foo', array('bar' => 'foo')), '[foo, { bar: foo, foo: [foo, { bar: foo }] }, [foo, { bar: foo }]]' => array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo'))), '[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']' => array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%',), true, '@service_container',), ); } } PK!`@ee3test/Yaml/Symfony/Component/Yaml/Tests/YamlTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Tests; use Symfony\Component\Yaml\Yaml; class YamlTest extends \PHPUnit_Framework_TestCase { public function testParseAndDump() { $data = array('lorem' => 'ipsum', 'dolor' => 'sit'); $yml = Yaml::dump($data); $parsed = Yaml::parse($yml); $this->assertEquals($data, $parsed); $filename = __DIR__.'/Fixtures/index.yml'; $contents = file_get_contents($filename); $parsedByFilename = Yaml::parse($filename); $parsedByContents = Yaml::parse($contents); $this->assertEquals($parsedByFilename, $parsedByContents); } } PK!?o=test/Yaml/Symfony/Component/Yaml/Tests/ParseExceptionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Tests; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Yaml; class ParseExceptionTest extends \PHPUnit_Framework_TestCase { public function testGetMessage() { $exception = new ParseException('Error message', 42, 'foo: bar', '/var/www/app/config.yml'); if (version_compare(PHP_VERSION, '5.4.0', '>=')) { $message = 'Error message in "/var/www/app/config.yml" at line 42 (near "foo: bar")'; } else { $message = 'Error message in "\\/var\\/www\\/app\\/config.yml" at line 42 (near "foo: bar")'; } $this->assertEquals($message, $exception->getMessage()); } } PK!>[331test/Yaml/Symfony/Component/Yaml/phpunit.xml.distnu[ ./Tests/ ./ ./vendor ./Tests PK!mg Jtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\IpUtils; class IpUtilsTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider testIpv4Provider */ public function testIpv4($matches, $remoteAddr, $cidr) { $this->assertSame($matches, IpUtils::checkIp($remoteAddr, $cidr)); } public function testIpv4Provider() { return array( array(true, '192.168.1.1', '192.168.1.1'), array(true, '192.168.1.1', '192.168.1.1/1'), array(true, '192.168.1.1', '192.168.1.0/24'), array(false, '192.168.1.1', '1.2.3.4/1'), array(false, '192.168.1.1', '192.168.1/33'), array(true, '192.168.1.1', array('1.2.3.4/1', '192.168.1.0/24')), array(true, '192.168.1.1', array('192.168.1.0/24', '1.2.3.4/1')), array(false, '192.168.1.1', array('1.2.3.4/1', '4.3.2.1/1')), ); } /** * @dataProvider testIpv6Provider */ public function testIpv6($matches, $remoteAddr, $cidr) { if (!defined('AF_INET6')) { $this->markTestSkipped('Only works when PHP is compiled without the option "disable-ipv6".'); } $this->assertSame($matches, IpUtils::checkIp($remoteAddr, $cidr)); } public function testIpv6Provider() { return array( array(true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'), array(false, '2a00:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'), array(false, '2a01:198:603:0:396e:4789:8e99:890f', '::1'), array(true, '0:0:0:0:0:0:0:1', '::1'), array(false, '0:0:603:0:396e:4789:8e99:0001', '::1'), array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '2a01:198:603:0::/65')), array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('2a01:198:603:0::/65', '::1')), array(false, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '1a01:198:603:0::/65')), ); } /** * @expectedException \RuntimeException */ public function testAnIpv6WithOptionDisabledIpv6() { if (!extension_loaded('sockets')) { $this->markTestSkipped('Only works when the socket extension is enabled'); } if (defined('AF_INET6')) { $this->markTestSkipped('Only works when PHP is compiled with the option "disable-ipv6".'); } IpUtils::checkIp('2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'); } } PK!Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestStackTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; class RequestStackTest extends \PHPUnit_Framework_TestCase { public function testGetCurrentRequest() { $requestStack = new RequestStack(); $this->assertNull($requestStack->getCurrentRequest()); $request = Request::create('/foo'); $requestStack->push($request); $this->assertSame($request, $requestStack->getCurrentRequest()); $this->assertSame($request, $requestStack->pop()); $this->assertNull($requestStack->getCurrentRequest()); $this->assertNull($requestStack->pop()); } public function testGetMasterRequest() { $requestStack = new RequestStack(); $this->assertNull($requestStack->getMasterRequest()); $masterRequest = Request::create('/foo'); $subRequest = Request::create('/bar'); $requestStack->push($masterRequest); $requestStack->push($subRequest); $this->assertSame($masterRequest, $requestStack->getMasterRequest()); } public function testGetParentRequest() { $requestStack = new RequestStack(); $this->assertNull($requestStack->getParentRequest()); $masterRequest = Request::create('/foo'); $requestStack->push($masterRequest); $this->assertNull($requestStack->getParentRequest()); $firstSubRequest = Request::create('/bar'); $requestStack->push($firstSubRequest); $this->assertSame($masterRequest, $requestStack->getParentRequest()); $secondSubRequest = Request::create('/baz'); $requestStack->push($secondSubRequest); $this->assertSame($firstSubRequest, $requestStack->getParentRequest()); } } PK!lOD D Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\Request; abstract class ResponseTestCase extends \PHPUnit_Framework_TestCase { public function testNoCacheControlHeaderOnAttachmentUsingHTTPSAndMSIE() { // Check for HTTPS and IE 8 $request = new Request(); $request->server->set('HTTPS', true); $request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'); $response = $this->provideResponse(); $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); $response->prepare($request); $this->assertFalse($response->headers->has('Cache-Control')); // Check for IE 10 and HTTPS $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)'); $response = $this->provideResponse(); $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); $response->prepare($request); $this->assertTrue($response->headers->has('Cache-Control')); // Check for IE 9 and HTTPS $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)'); $response = $this->provideResponse(); $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); $response->prepare($request); $this->assertTrue($response->headers->has('Cache-Control')); // Check for IE 9 and HTTP $request->server->set('HTTPS', false); $response = $this->provideResponse(); $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); $response->prepare($request); $this->assertTrue($response->headers->has('Cache-Control')); // Check for IE 8 and HTTP $request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'); $response = $this->provideResponse(); $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); $response->prepare($request); $this->assertTrue($response->headers->has('Cache-Control')); // Check for non-IE and HTTPS $request->server->set('HTTPS', true); $request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17'); $response = $this->provideResponse(); $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); $response->prepare($request); $this->assertTrue($response->headers->has('Cache-Control')); // Check for non-IE and HTTP $request->server->set('HTTPS', false); $response = $this->provideResponse(); $response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"'); $response->prepare($request); $this->assertTrue($response->headers->has('Cache-Control')); } abstract protected function provideResponse(); } PK!F9bbItest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/CookieTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\Cookie; /** * CookieTest * * @author John Kary * @author Hugo Hamon */ class CookieTest extends \PHPUnit_Framework_TestCase { public function invalidNames() { return array( array(''), array(",MyName"), array(";MyName"), array(" MyName"), array("\tMyName"), array("\rMyName"), array("\nMyName"), array("\013MyName"), array("\014MyName"), ); } /** * @dataProvider invalidNames * @expectedException \InvalidArgumentException * @covers Symfony\Component\HttpFoundation\Cookie::__construct */ public function testInstantiationThrowsExceptionIfCookieNameContainsInvalidCharacters($name) { new Cookie($name); } /** * @expectedException \InvalidArgumentException */ public function testInvalidExpiration() { $cookie = new Cookie('MyCookie', 'foo', 'bar'); } /** * @covers Symfony\Component\HttpFoundation\Cookie::getValue */ public function testGetValue() { $value = 'MyValue'; $cookie = new Cookie('MyCookie', $value); $this->assertSame($value, $cookie->getValue(), '->getValue() returns the proper value'); } public function testGetPath() { $cookie = new Cookie('foo', 'bar'); $this->assertSame('/', $cookie->getPath(), '->getPath() returns / as the default path'); } public function testGetExpiresTime() { $cookie = new Cookie('foo', 'bar', 3600); $this->assertEquals(3600, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date'); } public function testConstructorWithDateTime() { $expire = new \DateTime(); $cookie = new Cookie('foo', 'bar', $expire); $this->assertEquals($expire->format('U'), $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date'); } public function testGetExpiresTimeWithStringValue() { $value = "+1 day"; $cookie = new Cookie('foo', 'bar', $value); $expire = strtotime($value); $this->assertEquals($expire, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date'); } public function testGetDomain() { $cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com'); $this->assertEquals('.myfoodomain.com', $cookie->getDomain(), '->getDomain() returns the domain name on which the cookie is valid'); } public function testIsSecure() { $cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com', true); $this->assertTrue($cookie->isSecure(), '->isSecure() returns whether the cookie is transmitted over HTTPS'); } public function testIsHttpOnly() { $cookie = new Cookie('foo', 'bar', 3600, '/', '.myfoodomain.com', false, true); $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns whether the cookie is only transmitted over HTTP'); } public function testCookieIsNotCleared() { $cookie = new Cookie('foo', 'bar', time()+3600*24); $this->assertFalse($cookie->isCleared(), '->isCleared() returns false if the cookie did not expire yet'); } public function testCookieIsCleared() { $cookie = new Cookie('foo', 'bar', time()-20); $this->assertTrue($cookie->isCleared(), '->isCleared() returns true if the cookie has expired'); } public function testToString() { $cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', $cookie->__toString(), '->__toString() returns string representation of the cookie'); $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com'); $this->assertEquals('foo=deleted; expires='.gmdate("D, d-M-Y H:i:s T", time()-31536001).'; path=/admin/; domain=.myfoodomain.com; httponly', $cookie->__toString(), '->__toString() returns string representation of a cleared cookie if value is NULL'); $cookie = new Cookie('foo', 'bar', 0, '/', ''); $this->assertEquals('foo=bar; path=/; httponly', $cookie->__toString()); } } PK!qHStest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\RedirectResponse; class RedirectResponseTest extends \PHPUnit_Framework_TestCase { public function testGenerateMetaRedirect() { $response = new RedirectResponse('foo.bar'); $this->assertEquals(1, preg_match( '##', preg_replace(array('/\s+/', '/\'/'), array(' ', '"'), $response->getContent()) )); } /** * @expectedException \InvalidArgumentException */ public function testRedirectResponseConstructorNullUrl() { $response = new RedirectResponse(null); } /** * @expectedException \InvalidArgumentException */ public function testRedirectResponseConstructorWrongStatusCode() { $response = new RedirectResponse('foo.bar', 404); } public function testGenerateLocationHeader() { $response = new RedirectResponse('foo.bar'); $this->assertTrue($response->headers->has('Location')); $this->assertEquals('foo.bar', $response->headers->get('Location')); } public function testGetTargetUrl() { $response = new RedirectResponse('foo.bar'); $this->assertEquals('foo.bar', $response->getTargetUrl()); } public function testSetTargetUrl() { $response = new RedirectResponse('foo.bar'); $response->setTargetUrl('baz.beep'); $this->assertEquals('baz.beep', $response->getTargetUrl()); } /** * @expectedException \InvalidArgumentException */ public function testSetTargetUrlNull() { $response = new RedirectResponse('foo.bar'); $response->setTargetUrl(null); } public function testCreate() { $response = RedirectResponse::create('foo', 301); $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response); $this->assertEquals(301, $response->getStatusCode()); } } PK!qr [test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ExpressionRequestMatcherTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\HttpFoundation\ExpressionRequestMatcher; use Symfony\Component\HttpFoundation\Request; class ExpressionRequestMatcherTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \LogicException */ public function testWhenNoExpressionIsSet() { $expressionRequestMatcher = new ExpressionRequestMatcher(); $expressionRequestMatcher->matches(new Request()); } /** * @dataProvider provideExpressions */ public function testMatchesWhenParentMatchesIsTrue($expression, $expected) { $request = Request::create('/foo'); $expressionRequestMatcher = new ExpressionRequestMatcher(); $expressionRequestMatcher->setExpression(new ExpressionLanguage(), $expression); $this->assertSame($expected, $expressionRequestMatcher->matches($request)); } /** * @dataProvider provideExpressions */ public function testMatchesWhenParentMatchesIsFalse($expression) { $request = Request::create('/foo'); $request->attributes->set('foo', 'foo'); $expressionRequestMatcher = new ExpressionRequestMatcher(); $expressionRequestMatcher->matchAttribute('foo', 'bar'); $expressionRequestMatcher->setExpression(new ExpressionLanguage(), $expression); $this->assertFalse($expressionRequestMatcher->matches($request)); } public function provideExpressions() { return array( array('request.getMethod() == method', true), array('request.getPathInfo() == path', true), array('request.getHost() == host', true), array('request.getClientIp() == ip', true), array('request.attributes.all() == attributes', true), array('request.getMethod() == method && request.getPathInfo() == path && request.getHost() == host && request.getClientIp() == ip && request.attributes.all() == attributes', true), array('request.getMethod() != method', false), array('request.getMethod() != method && request.getPathInfo() == path && request.getHost() == host && request.getClientIp() == ip && request.attributes.all() == attributes', false), ); } } PK!_|Utest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\ResponseHeaderBag; class BinaryFileResponseTest extends ResponseTestCase { public function testConstruction() { $response = new BinaryFileResponse('README.md', 404, array('X-Header' => 'Foo'), true, null, true, true); $this->assertEquals(404, $response->getStatusCode()); $this->assertEquals('Foo', $response->headers->get('X-Header')); $this->assertTrue($response->headers->has('ETag')); $this->assertTrue($response->headers->has('Last-Modified')); $this->assertFalse($response->headers->has('Content-Disposition')); $response = BinaryFileResponse::create('README.md', 404, array(), true, ResponseHeaderBag::DISPOSITION_INLINE); $this->assertEquals(404, $response->getStatusCode()); $this->assertFalse($response->headers->has('ETag')); $this->assertEquals('inline; filename="README.md"', $response->headers->get('Content-Disposition')); } /** * @expectedException \LogicException */ public function testSetContent() { $response = new BinaryFileResponse('README.md'); $response->setContent('foo'); } public function testGetContent() { $response = new BinaryFileResponse('README.md'); $this->assertFalse($response->getContent()); } /** * @dataProvider provideRanges */ public function testRequests($requestRange, $offset, $length, $responseRange) { $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag(); // do a request to get the ETag $request = Request::create('/'); $response->prepare($request); $etag = $response->headers->get('ETag'); // prepare a request for a range of the testing file $request = Request::create('/'); $request->headers->set('If-Range', $etag); $request->headers->set('Range', $requestRange); $file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r'); fseek($file, $offset); $data = fread($file, $length); fclose($file); $this->expectOutputString($data); $response = clone $response; $response->prepare($request); $response->sendContent(); $this->assertEquals(206, $response->getStatusCode()); $this->assertEquals('binary', $response->headers->get('Content-Transfer-Encoding')); $this->assertEquals($responseRange, $response->headers->get('Content-Range')); } public function provideRanges() { return array( array('bytes=1-4', 1, 4, 'bytes 1-4/35'), array('bytes=-5', 30, 5, 'bytes 30-34/35'), array('bytes=30-', 30, 5, 'bytes 30-34/35'), array('bytes=30-30', 30, 1, 'bytes 30-30/35'), array('bytes=30-34', 30, 5, 'bytes 30-34/35'), ); } /** * @dataProvider provideFullFileRanges */ public function testFullFileRequests($requestRange) { $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag(); // prepare a request for a range of the testing file $request = Request::create('/'); $request->headers->set('Range', $requestRange); $file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r'); $data = fread($file, 35); fclose($file); $this->expectOutputString($data); $response = clone $response; $response->prepare($request); $response->sendContent(); $this->assertEquals(200, $response->getStatusCode()); $this->assertEquals('binary', $response->headers->get('Content-Transfer-Encoding')); } public function provideFullFileRanges() { return array( array('bytes=0-'), array('bytes=0-34'), array('bytes=-35'), // Syntactical invalid range-request should also return the full resource array('bytes=20-10'), array('bytes=50-40'), ); } /** * @dataProvider provideInvalidRanges */ public function testInvalidRequests($requestRange) { $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag(); // prepare a request for a range of the testing file $request = Request::create('/'); $request->headers->set('Range', $requestRange); $response = clone $response; $response->prepare($request); $response->sendContent(); $this->assertEquals(416, $response->getStatusCode()); $this->assertEquals('binary', $response->headers->get('Content-Transfer-Encoding')); #$this->assertEquals('', $response->headers->get('Content-Range')); } public function provideInvalidRanges() { return array( array('bytes=-40'), array('bytes=30-40') ); } public function testXSendfile() { $request = Request::create('/'); $request->headers->set('X-Sendfile-Type', 'X-Sendfile'); BinaryFileResponse::trustXSendfileTypeHeader(); $response = BinaryFileResponse::create('README.md'); $response->prepare($request); $this->expectOutputString(''); $response->sendContent(); $this->assertContains('README.md', $response->headers->get('X-Sendfile')); } /** * @dataProvider getSampleXAccelMappings */ public function testXAccelMapping($realpath, $mapping, $virtual) { $request = Request::create('/'); $request->headers->set('X-Sendfile-Type', 'X-Accel-Redirect'); $request->headers->set('X-Accel-Mapping', $mapping); $file = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File') ->disableOriginalConstructor() ->getMock(); $file->expects($this->any()) ->method('getRealPath') ->will($this->returnValue($realpath)); $file->expects($this->any()) ->method('isReadable') ->will($this->returnValue(true)); BinaryFileResponse::trustXSendFileTypeHeader(); $response = new BinaryFileResponse('README.md'); $reflection = new \ReflectionObject($response); $property = $reflection->getProperty('file'); $property->setAccessible(true); $property->setValue($response, $file); $response->prepare($request); $this->assertEquals($virtual, $response->headers->get('X-Accel-Redirect')); } public function getSampleXAccelMappings() { return array( array('/var/www/var/www/files/foo.txt', '/files/=/var/www/', '/files/var/www/files/foo.txt'), array('/home/foo/bar.txt', '/files/=/var/www/,/baz/=/home/foo/', '/baz/bar.txt'), ); } protected function provideResponse() { return new BinaryFileResponse('README.md'); } } PK!@LLJtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/FileBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\FileBag; /** * FileBagTest. * * @author Fabien Potencier * @author Bulat Shakirzyanov */ class FileBagTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \InvalidArgumentException */ public function testFileMustBeAnArrayOrUploadedFile() { new FileBag(array('file' => 'foo')); } public function testShouldConvertsUploadedFiles() { $tmpFile = $this->createTempFile(); $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); $bag = new FileBag(array('file' => array( 'name' => basename($tmpFile), 'type' => 'text/plain', 'tmp_name' => $tmpFile, 'error' => 0, 'size' => 100 ))); $this->assertEquals($file, $bag->get('file')); } public function testShouldSetEmptyUploadedFilesToNull() { $bag = new FileBag(array('file' => array( 'name' => '', 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_NO_FILE, 'size' => 0 ))); $this->assertNull($bag->get('file')); } public function testShouldConvertUploadedFilesWithPhpBug() { $tmpFile = $this->createTempFile(); $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); $bag = new FileBag(array( 'child' => array( 'name' => array( 'file' => basename($tmpFile), ), 'type' => array( 'file' => 'text/plain', ), 'tmp_name' => array( 'file' => $tmpFile, ), 'error' => array( 'file' => 0, ), 'size' => array( 'file' => 100, ), ) )); $files = $bag->all(); $this->assertEquals($file, $files['child']['file']); } public function testShouldConvertNestedUploadedFilesWithPhpBug() { $tmpFile = $this->createTempFile(); $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); $bag = new FileBag(array( 'child' => array( 'name' => array( 'sub' => array('file' => basename($tmpFile)) ), 'type' => array( 'sub' => array('file' => 'text/plain') ), 'tmp_name' => array( 'sub' => array('file' => $tmpFile) ), 'error' => array( 'sub' => array('file' => 0) ), 'size' => array( 'sub' => array('file' => 100) ), ) )); $files = $bag->all(); $this->assertEquals($file, $files['child']['sub']['file']); } public function testShouldNotConvertNestedUploadedFiles() { $tmpFile = $this->createTempFile(); $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); $bag = new FileBag(array('image' => array('file' => $file))); $files = $bag->all(); $this->assertEquals($file, $files['image']['file']); } protected function createTempFile() { return tempnam(sys_get_temp_dir().'/form_test', 'FormTest'); } protected function setUp() { mkdir(sys_get_temp_dir().'/form_test', 0777, true); } protected function tearDown() { foreach (glob(sys_get_temp_dir().'/form_test/*') as $file) { unlink($file); } rmdir(sys_get_temp_dir().'/form_test'); } } PK!m..Ltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/HeaderBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\HeaderBag; class HeaderBagTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\HttpFoundation\HeaderBag::__construct */ public function testConstructor() { $bag = new HeaderBag(array('foo' => 'bar')); $this->assertTrue($bag->has('foo')); } public function testToStringNull() { $bag = new HeaderBag(); $this->assertEquals('', $bag->__toString()); } public function testToStringNotNull() { $bag = new HeaderBag(array('foo' => 'bar')); $this->assertEquals("Foo: bar\r\n", $bag->__toString()); } public function testKeys() { $bag = new HeaderBag(array('foo' => 'bar')); $keys = $bag->keys(); $this->assertEquals("foo", $keys[0]); } public function testGetDate() { $bag = new HeaderBag(array('foo' => 'Tue, 4 Sep 2012 20:00:00 +0200')); $headerDate = $bag->getDate('foo'); $this->assertInstanceOf('DateTime', $headerDate); } /** * @expectedException \RuntimeException */ public function testGetDateException() { $bag = new HeaderBag(array('foo' => 'Tue')); $headerDate = $bag->getDate('foo'); } public function testGetCacheControlHeader() { $bag = new HeaderBag(); $bag->addCacheControlDirective('public', '#a'); $this->assertTrue($bag->hasCacheControlDirective('public')); $this->assertEquals('#a', $bag->getCacheControlDirective('public')); } /** * @covers Symfony\Component\HttpFoundation\HeaderBag::all */ public function testAll() { $bag = new HeaderBag(array('foo' => 'bar')); $this->assertEquals(array('foo' => array('bar')), $bag->all(), '->all() gets all the input'); $bag = new HeaderBag(array('FOO' => 'BAR')); $this->assertEquals(array('foo' => array('BAR')), $bag->all(), '->all() gets all the input key are lower case'); } /** * @covers Symfony\Component\HttpFoundation\HeaderBag::replace */ public function testReplace() { $bag = new HeaderBag(array('foo' => 'bar')); $bag->replace(array('NOPE' => 'BAR')); $this->assertEquals(array('nope' => array('BAR')), $bag->all(), '->replace() replaces the input with the argument'); $this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input'); } /** * @covers Symfony\Component\HttpFoundation\HeaderBag::get */ public function testGet() { $bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz')); $this->assertEquals( 'bar', $bag->get('foo'), '->get return current value'); $this->assertEquals( 'bar', $bag->get('FoO'), '->get key in case insensitive'); $this->assertEquals( array('bar'), $bag->get('foo', 'nope', false), '->get return the value as array'); // defaults $this->assertNull($bag->get('none'), '->get unknown values returns null'); $this->assertEquals( 'default', $bag->get('none', 'default'), '->get unknown values returns default'); $this->assertEquals( array('default'), $bag->get('none', 'default', false), '->get unknown values returns default as array'); $bag->set('foo', 'bor', false); $this->assertEquals( 'bar', $bag->get('foo'), '->get return first value'); $this->assertEquals( array('bar', 'bor'), $bag->get('foo', 'nope', false), '->get return all values as array'); } public function testSetAssociativeArray() { $bag = new HeaderBag(); $bag->set('foo', array('bad-assoc-index' => 'value')); $this->assertSame('value', $bag->get('foo')); $this->assertEquals(array('value'), $bag->get('foo', 'nope', false), 'assoc indices of multi-valued headers are ignored'); } /** * @covers Symfony\Component\HttpFoundation\HeaderBag::contains */ public function testContains() { $bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz')); $this->assertTrue( $bag->contains('foo', 'bar'), '->contains first value'); $this->assertTrue( $bag->contains('fuzz', 'bizz'), '->contains second value'); $this->assertFalse( $bag->contains('nope', 'nope'), '->contains unknown value'); $this->assertFalse( $bag->contains('foo', 'nope'), '->contains unknown value'); // Multiple values $bag->set('foo', 'bor', false); $this->assertTrue( $bag->contains('foo', 'bar'), '->contains first value'); $this->assertTrue( $bag->contains('foo', 'bor'), '->contains second value'); $this->assertFalse( $bag->contains('foo', 'nope'), '->contains unknown value'); } public function testCacheControlDirectiveAccessors() { $bag = new HeaderBag(); $bag->addCacheControlDirective('public'); $this->assertTrue($bag->hasCacheControlDirective('public')); $this->assertTrue($bag->getCacheControlDirective('public')); $this->assertEquals('public', $bag->get('cache-control')); $bag->addCacheControlDirective('max-age', 10); $this->assertTrue($bag->hasCacheControlDirective('max-age')); $this->assertEquals(10, $bag->getCacheControlDirective('max-age')); $this->assertEquals('max-age=10, public', $bag->get('cache-control')); $bag->removeCacheControlDirective('max-age'); $this->assertFalse($bag->hasCacheControlDirective('max-age')); } public function testCacheControlDirectiveParsing() { $bag = new HeaderBag(array('cache-control' => 'public, max-age=10')); $this->assertTrue($bag->hasCacheControlDirective('public')); $this->assertTrue($bag->getCacheControlDirective('public')); $this->assertTrue($bag->hasCacheControlDirective('max-age')); $this->assertEquals(10, $bag->getCacheControlDirective('max-age')); $bag->addCacheControlDirective('s-maxage', 100); $this->assertEquals('max-age=10, public, s-maxage=100', $bag->get('cache-control')); } public function testCacheControlDirectiveParsingQuotedZero() { $bag = new HeaderBag(array('cache-control' => 'max-age="0"')); $this->assertTrue($bag->hasCacheControlDirective('max-age')); $this->assertEquals(0, $bag->getCacheControlDirective('max-age')); } public function testCacheControlDirectiveOverrideWithReplace() { $bag = new HeaderBag(array('cache-control' => 'private, max-age=100')); $bag->replace(array('cache-control' => 'public, max-age=10')); $this->assertTrue($bag->hasCacheControlDirective('public')); $this->assertTrue($bag->getCacheControlDirective('public')); $this->assertTrue($bag->hasCacheControlDirective('max-age')); $this->assertEquals(10, $bag->getCacheControlDirective('max-age')); } /** * @covers Symfony\Component\HttpFoundation\HeaderBag::getIterator */ public function testGetIterator() { $headers = array('foo' => 'bar', 'hello' => 'world', 'third' => 'charm'); $headerBag = new HeaderBag($headers); $i = 0; foreach ($headerBag as $key => $val) { $i++; $this->assertEquals(array($headers[$key]), $val); } $this->assertEquals(count($headers), $i); } /** * @covers Symfony\Component\HttpFoundation\HeaderBag::count */ public function testCount() { $headers = array('foo' => 'bar', 'HELLO' => 'WORLD'); $headerBag = new HeaderBag($headers); $this->assertEquals(count($headers), count($headerBag)); } } PK!܏##Qtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gifnu[GIF87a,D;PK!+vZtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextensionnu[fPK!Ytest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.emptynu[PK!܏##Mtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/testnu[GIF87a,D;PK!~rM;;Ytest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\File\MimeType; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; use Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; class MimeTypeTest extends \PHPUnit_Framework_TestCase { protected $path; public function testGuessImageWithoutExtension() { if (extension_loaded('fileinfo')) { $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test')); } else { $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test')); } } public function testGuessImageWithDirectory() { $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/directory'); } public function testGuessImageWithFileBinaryMimeTypeGuesser() { $guesser = MimeTypeGuesser::getInstance(); $guesser->register(new FileBinaryMimeTypeGuesser()); if (extension_loaded('fileinfo')) { $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test')); } else { $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test')); } } public function testGuessImageWithKnownExtension() { if (extension_loaded('fileinfo')) { $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test.gif')); } else { $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test.gif')); } } public function testGuessFileWithUnknownExtension() { if (extension_loaded('fileinfo')) { $this->assertEquals('application/octet-stream', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/.unknownextension')); } else { $this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/.unknownextension')); } } public function testGuessWithIncorrectPath() { $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/not_here'); } public function testGuessWithNonReadablePath() { if (defined('PHP_WINDOWS_VERSION_BUILD')) { $this->markTestSkipped('Can not verify chmod operations on Windows'); } if (in_array(get_current_user(), array('root'))) { $this->markTestSkipped('This test will fail if run under superuser'); } $path = __DIR__.'/../Fixtures/to_delete'; touch($path); @chmod($path, 0333); if (get_current_user() != 'root' && substr(sprintf('%o', fileperms($path)), -4) == '0333') { $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException'); MimeTypeGuesser::getInstance()->guess($path); } else { $this->markTestSkipped('Can not verify chmod operations, change of file permissions failed'); } } public static function tearDownAfterClass() { $path = __DIR__.'/../Fixtures/to_delete'; if (file_exists($path)) { @chmod($path, 0666); @unlink($path); } } } PK! ##Ltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/FileTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\File; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; class FileTest extends \PHPUnit_Framework_TestCase { protected $file; public function testGetMimeTypeUsesMimeTypeGuessers() { $file = new File(__DIR__.'/Fixtures/test.gif'); $guesser = $this->createMockGuesser($file->getPathname(), 'image/gif'); MimeTypeGuesser::getInstance()->register($guesser); $this->assertEquals('image/gif', $file->getMimeType()); } public function testGuessExtensionWithoutGuesser() { $file = new File(__DIR__.'/Fixtures/directory/.empty'); $this->assertNull($file->guessExtension()); } public function testGuessExtensionIsBasedOnMimeType() { $file = new File(__DIR__.'/Fixtures/test'); $guesser = $this->createMockGuesser($file->getPathname(), 'image/gif'); MimeTypeGuesser::getInstance()->register($guesser); $this->assertEquals('gif', $file->guessExtension()); } public function testConstructWhenFileNotExists() { $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); new File(__DIR__.'/Fixtures/not_here'); } public function testMove() { $path = __DIR__.'/Fixtures/test.copy.gif'; $targetDir = __DIR__.'/Fixtures/directory'; $targetPath = $targetDir.'/test.copy.gif'; @unlink($path); @unlink($targetPath); copy(__DIR__.'/Fixtures/test.gif', $path); $file = new File($path); $movedFile = $file->move($targetDir); $this->assertInstanceOf('Symfony\Component\HttpFoundation\File\File', $movedFile); $this->assertTrue(file_exists($targetPath)); $this->assertFalse(file_exists($path)); $this->assertEquals(realpath($targetPath), $movedFile->getRealPath()); @unlink($targetPath); } public function testMoveWithNewName() { $path = __DIR__.'/Fixtures/test.copy.gif'; $targetDir = __DIR__.'/Fixtures/directory'; $targetPath = $targetDir.'/test.newname.gif'; @unlink($path); @unlink($targetPath); copy(__DIR__.'/Fixtures/test.gif', $path); $file = new File($path); $movedFile = $file->move($targetDir, 'test.newname.gif'); $this->assertTrue(file_exists($targetPath)); $this->assertFalse(file_exists($path)); $this->assertEquals(realpath($targetPath), $movedFile->getRealPath()); @unlink($targetPath); } public function getFilenameFixtures() { return array( array('original.gif', 'original.gif'), array('..\\..\\original.gif', 'original.gif'), array('../../original.gif', 'original.gif'), array('файлfile.gif', 'файлfile.gif'), array('..\\..\\файлfile.gif', 'файлfile.gif'), array('../../файлfile.gif', 'файлfile.gif'), ); } /** * @dataProvider getFilenameFixtures */ public function testMoveWithNonLatinName($filename, $sanitizedFilename) { $path = __DIR__.'/Fixtures/'.$sanitizedFilename; $targetDir = __DIR__.'/Fixtures/directory/'; $targetPath = $targetDir.$sanitizedFilename; @unlink($path); @unlink($targetPath); copy(__DIR__.'/Fixtures/test.gif', $path); $file = new File($path); $movedFile = $file->move($targetDir,$filename); $this->assertInstanceOf('Symfony\Component\HttpFoundation\File\File', $movedFile); $this->assertTrue(file_exists($targetPath)); $this->assertFalse(file_exists($path)); $this->assertEquals(realpath($targetPath), $movedFile->getRealPath()); @unlink($targetPath); } public function testMoveToAnUnexistentDirectory() { $sourcePath = __DIR__.'/Fixtures/test.copy.gif'; $targetDir = __DIR__.'/Fixtures/directory/sub'; $targetPath = $targetDir.'/test.copy.gif'; @unlink($sourcePath); @unlink($targetPath); @rmdir($targetDir); copy(__DIR__.'/Fixtures/test.gif', $sourcePath); $file = new File($sourcePath); $movedFile = $file->move($targetDir); $this->assertFileExists($targetPath); $this->assertFileNotExists($sourcePath); $this->assertEquals(realpath($targetPath), $movedFile->getRealPath()); @unlink($sourcePath); @unlink($targetPath); @rmdir($targetDir); } public function testGetExtension() { $file = new File(__DIR__.'/Fixtures/test.gif'); $this->assertEquals('gif', $file->getExtension()); } protected function createMockGuesser($path, $mimeType) { $guesser = $this->getMock('Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface'); $guesser ->expects($this->once()) ->method('guess') ->with($this->equalTo($path)) ->will($this->returnValue($mimeType)) ; return $guesser; } } PK!tAATtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\File; use Symfony\Component\HttpFoundation\File\UploadedFile; class UploadedFileTest extends \PHPUnit_Framework_TestCase { protected function setUp() { if (!ini_get('file_uploads')) { $this->markTestSkipped('file_uploads is disabled in php.ini'); } } public function testConstructWhenFileNotExists() { $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); new UploadedFile( __DIR__.'/Fixtures/not_here', 'original.gif', null ); } public function testFileUploadsWithNoMimeType() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', null, filesize(__DIR__.'/Fixtures/test.gif'), UPLOAD_ERR_OK ); $this->assertEquals('application/octet-stream', $file->getClientMimeType()); if (extension_loaded('fileinfo')) { $this->assertEquals('image/gif', $file->getMimeType()); } } public function testFileUploadsWithUnknownMimeType() { $file = new UploadedFile( __DIR__.'/Fixtures/.unknownextension', 'original.gif', null, filesize(__DIR__.'/Fixtures/.unknownextension'), UPLOAD_ERR_OK ); $this->assertEquals('application/octet-stream', $file->getClientMimeType()); } public function testGuessClientExtension() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', filesize(__DIR__.'/Fixtures/test.gif'), null ); $this->assertEquals('gif', $file->guessClientExtension()); } public function testGuessClientExtensionWithIncorrectMimeType() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/jpeg', filesize(__DIR__.'/Fixtures/test.gif'), null ); $this->assertEquals('jpeg', $file->guessClientExtension()); } public function testErrorIsOkByDefault() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', filesize(__DIR__.'/Fixtures/test.gif'), null ); $this->assertEquals(UPLOAD_ERR_OK, $file->getError()); } public function testGetClientOriginalName() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', filesize(__DIR__.'/Fixtures/test.gif'), null ); $this->assertEquals('original.gif', $file->getClientOriginalName()); } public function testGetClientOriginalExtension() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', filesize(__DIR__.'/Fixtures/test.gif'), null ); $this->assertEquals('gif', $file->getClientOriginalExtension()); } /** * @expectedException \Symfony\Component\HttpFoundation\File\Exception\FileException */ public function testMoveLocalFileIsNotAllowed() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', filesize(__DIR__.'/Fixtures/test.gif'), UPLOAD_ERR_OK ); $movedFile = $file->move(__DIR__.'/Fixtures/directory'); } public function testMoveLocalFileIsAllowedInTestMode() { $path = __DIR__.'/Fixtures/test.copy.gif'; $targetDir = __DIR__.'/Fixtures/directory'; $targetPath = $targetDir.'/test.copy.gif'; @unlink($path); @unlink($targetPath); copy(__DIR__.'/Fixtures/test.gif', $path); $file = new UploadedFile( $path, 'original.gif', 'image/gif', filesize($path), UPLOAD_ERR_OK, true ); $movedFile = $file->move(__DIR__.'/Fixtures/directory'); $this->assertTrue(file_exists($targetPath)); $this->assertFalse(file_exists($path)); $this->assertEquals(realpath($targetPath), $movedFile->getRealPath()); @unlink($targetPath); } public function testGetClientOriginalNameSanitizeFilename() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', '../../original.gif', 'image/gif', filesize(__DIR__.'/Fixtures/test.gif'), null ); $this->assertEquals('original.gif', $file->getClientOriginalName()); } public function testGetSize() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', filesize(__DIR__.'/Fixtures/test.gif'), null ); $this->assertEquals(filesize(__DIR__.'/Fixtures/test.gif'), $file->getSize()); $file = new UploadedFile( __DIR__.'/Fixtures/test', 'original.gif', 'image/gif' ); $this->assertEquals(filesize(__DIR__.'/Fixtures/test'), $file->getSize()); } public function testGetExtension() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', null ); $this->assertEquals('gif', $file->getExtension()); } public function testIsValid() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', null, filesize(__DIR__.'/Fixtures/test.gif'), UPLOAD_ERR_OK, true ); $this->assertTrue($file->isValid()); } /** * @dataProvider uploadedFileErrorProvider */ public function testIsInvalidOnUploadError($error) { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', null, filesize(__DIR__.'/Fixtures/test.gif'), $error ); $this->assertFalse($file->isValid()); } public function uploadedFileErrorProvider() { return array( array(UPLOAD_ERR_INI_SIZE), array(UPLOAD_ERR_FORM_SIZE), array(UPLOAD_ERR_PARTIAL), array(UPLOAD_ERR_NO_TMP_DIR), array(UPLOAD_ERR_EXTENSION), ); } public function testIsInvalidIfNotHttpUpload() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', null, filesize(__DIR__.'/Fixtures/test.gif'), UPLOAD_ERR_OK ); $this->assertFalse($file->isValid()); } } PK!ʾV Stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\StreamedResponse; class StreamedResponseTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $response = new StreamedResponse(function () { echo 'foo'; }, 404, array('Content-Type' => 'text/plain')); $this->assertEquals(404, $response->getStatusCode()); $this->assertEquals('text/plain', $response->headers->get('Content-Type')); } public function testPrepareWith11Protocol() { $response = new StreamedResponse(function () { echo 'foo'; }); $request = Request::create('/'); $request->server->set('SERVER_PROTOCOL', 'HTTP/1.1'); $response->prepare($request); $this->assertEquals('1.1', $response->getProtocolVersion()); $this->assertNotEquals('chunked', $response->headers->get('Transfer-Encoding'), 'Apache assumes responses with a Transfer-Encoding header set to chunked to already be encoded.'); $this->assertEquals('no-cache, private', $response->headers->get('Cache-Control')); } public function testPrepareWith10Protocol() { $response = new StreamedResponse(function () { echo 'foo'; }); $request = Request::create('/'); $request->server->set('SERVER_PROTOCOL', 'HTTP/1.0'); $response->prepare($request); $this->assertEquals('1.0', $response->getProtocolVersion()); $this->assertNull($response->headers->get('Transfer-Encoding')); $this->assertEquals('no-cache, private', $response->headers->get('Cache-Control')); } public function testPrepareWithHeadRequest() { $response = new StreamedResponse(function () { echo 'foo'; }); $request = Request::create('/', 'HEAD'); $response->prepare($request); } public function testSendContent() { $called = 0; $response = new StreamedResponse(function () use (&$called) { ++$called; }); $response->sendContent(); $this->assertEquals(1, $called); $response->sendContent(); $this->assertEquals(1, $called); } /** * @expectedException \LogicException */ public function testSendContentWithNonCallable() { $response = new StreamedResponse(null); $response->sendContent(); } /** * @expectedException \LogicException */ public function testSetCallbackNonCallable() { $response = new StreamedResponse(null); $response->setCallback(null); } /** * @expectedException \LogicException */ public function testSetContent() { $response = new StreamedResponse(function () { echo 'foo'; }); $response->setContent('foo'); } public function testGetContent() { $response = new StreamedResponse(function () { echo 'foo'; }); $this->assertFalse($response->getContent()); } public function testCreate() { $response = StreamedResponse::create(function () {}, 204); $this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response); $this->assertEquals(204, $response->getStatusCode()); } } PK!M{ctest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Flash; use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag as FlashBag; /** * AutoExpireFlashBagTest * * @author Drak */ class AutoExpireFlashBagTest extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag */ private $bag; /** * @var array */ protected $array = array(); protected function setUp() { parent::setUp(); $this->bag = new FlashBag(); $this->array = array('new' => array('notice' => array('A previous flash message'))); $this->bag->initialize($this->array); } public function tearDown() { $this->bag = null; parent::tearDown(); } public function testInitialize() { $bag = new FlashBag(); $array = array('new' => array('notice' => array('A previous flash message'))); $bag->initialize($array); $this->assertEquals(array('A previous flash message'), $bag->peek('notice')); $array = array('new' => array( 'notice' => array('Something else'), 'error' => array('a'), )); $bag->initialize($array); $this->assertEquals(array('Something else'), $bag->peek('notice')); $this->assertEquals(array('a'), $bag->peek('error')); } public function testGetStorageKey() { $this->assertEquals('_sf2_flashes', $this->bag->getStorageKey()); $attributeBag = new FlashBag('test'); $this->assertEquals('test', $attributeBag->getStorageKey()); } public function testGetSetName() { $this->assertEquals('flashes', $this->bag->getName()); $this->bag->setName('foo'); $this->assertEquals('foo', $this->bag->getName()); } public function testPeek() { $this->assertEquals(array(), $this->bag->peek('non_existing')); $this->assertEquals(array('default'), $this->bag->peek('non_existing', array('default'))); $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); } public function testSet() { $this->bag->set('notice', 'Foo'); $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); } public function testHas() { $this->assertFalse($this->bag->has('nothing')); $this->assertTrue($this->bag->has('notice')); } public function testKeys() { $this->assertEquals(array('notice'), $this->bag->keys()); } public function testPeekAll() { $array = array( 'new' => array( 'notice' => 'Foo', 'error' => 'Bar', ), ); $this->bag->initialize($array); $this->assertEquals(array( 'notice' => 'Foo', 'error' => 'Bar', ), $this->bag->peekAll() ); $this->assertEquals(array( 'notice' => 'Foo', 'error' => 'Bar', ), $this->bag->peekAll() ); } public function testGet() { $this->assertEquals(array(), $this->bag->get('non_existing')); $this->assertEquals(array('default'), $this->bag->get('non_existing', array('default'))); $this->assertEquals(array('A previous flash message'), $this->bag->get('notice')); $this->assertEquals(array(), $this->bag->get('notice')); } public function testSetAll() { $this->bag->setAll(array('a' => 'first', 'b' => 'second')); $this->assertFalse($this->bag->has('a')); $this->assertFalse($this->bag->has('b')); } public function testAll() { $this->bag->set('notice', 'Foo'); $this->bag->set('error', 'Bar'); $this->assertEquals(array( 'notice' => array('A previous flash message'), ), $this->bag->all() ); $this->assertEquals(array(), $this->bag->all()); } public function testClear() { $this->assertEquals(array('notice' => array('A previous flash message')), $this->bag->clear()); } } PK!ƒYtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Flash; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; /** * FlashBagTest * * @author Drak */ class FlashBagTest extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\HttpFoundation\SessionFlash\FlashBagInterface */ private $bag; /** * @var array */ protected $array = array(); protected function setUp() { parent::setUp(); $this->bag = new FlashBag(); $this->array = array('notice' => array('A previous flash message')); $this->bag->initialize($this->array); } public function tearDown() { $this->bag = null; parent::tearDown(); } public function testInitialize() { $bag = new FlashBag(); $bag->initialize($this->array); $this->assertEquals($this->array, $bag->peekAll()); $array = array('should' => array('change')); $bag->initialize($array); $this->assertEquals($array, $bag->peekAll()); } public function testGetStorageKey() { $this->assertEquals('_sf2_flashes', $this->bag->getStorageKey()); $attributeBag = new FlashBag('test'); $this->assertEquals('test', $attributeBag->getStorageKey()); } public function testGetSetName() { $this->assertEquals('flashes', $this->bag->getName()); $this->bag->setName('foo'); $this->assertEquals('foo', $this->bag->getName()); } public function testPeek() { $this->assertEquals(array(), $this->bag->peek('non_existing')); $this->assertEquals(array('default'), $this->bag->peek('not_existing', array('default'))); $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); } public function testGet() { $this->assertEquals(array(), $this->bag->get('non_existing')); $this->assertEquals(array('default'), $this->bag->get('not_existing', array('default'))); $this->assertEquals(array('A previous flash message'), $this->bag->get('notice')); $this->assertEquals(array(), $this->bag->get('notice')); } public function testAll() { $this->bag->set('notice', 'Foo'); $this->bag->set('error', 'Bar'); $this->assertEquals(array( 'notice' => array('Foo'), 'error' => array('Bar')), $this->bag->all() ); $this->assertEquals(array(), $this->bag->all()); } public function testSet() { $this->bag->set('notice', 'Foo'); $this->bag->set('notice', 'Bar'); $this->assertEquals(array('Bar'), $this->bag->peek('notice')); } public function testHas() { $this->assertFalse($this->bag->has('nothing')); $this->assertTrue($this->bag->has('notice')); } public function testKeys() { $this->assertEquals(array('notice'), $this->bag->keys()); } public function testPeekAll() { $this->bag->set('notice', 'Foo'); $this->bag->set('error', 'Bar'); $this->assertEquals(array( 'notice' => array('Foo'), 'error' => array('Bar'), ), $this->bag->peekAll() ); $this->assertTrue($this->bag->has('notice')); $this->assertTrue($this->bag->has('error')); $this->assertEquals(array( 'notice' => array('Foo'), 'error' => array('Bar'), ), $this->bag->peekAll() ); } /** * @covers Symfony\Component\HttpFoundation\Session\Flash\FlashBag::getIterator */ public function testGetIterator() { $flashes = array('hello' => 'world', 'beep' => 'boop', 'notice' => 'nope'); foreach ($flashes as $key => $val) { $this->bag->set($key, $val); } $i = 0; foreach ($this->bag as $key => $val) { $this->assertEquals(array($flashes[$key]), $val); $i++; } $this->assertEquals(count($flashes), $i); $this->assertCount(0, $this->bag->all()); } } PK!0atest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Attribute; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; /** * Tests AttributeBag * * @author Drak */ class AttributeBagTest extends \PHPUnit_Framework_TestCase { /** * @var array */ private $array; /** * @var AttributeBag */ private $bag; protected function setUp() { $this->array = array( 'hello' => 'world', 'always' => 'be happy', 'user.login' => 'drak', 'csrf.token' => array( 'a' => '1234', 'b' => '4321', ), 'category' => array( 'fishing' => array( 'first' => 'cod', 'second' => 'sole') ), ); $this->bag = new AttributeBag('_sf2'); $this->bag->initialize($this->array); } protected function tearDown() { $this->bag = null; $this->array = array(); } public function testInitialize() { $bag = new AttributeBag(); $bag->initialize($this->array); $this->assertEquals($this->array, $bag->all()); $array = array('should' => 'change'); $bag->initialize($array); $this->assertEquals($array, $bag->all()); } public function testGetStorageKey() { $this->assertEquals('_sf2', $this->bag->getStorageKey()); $attributeBag = new AttributeBag('test'); $this->assertEquals('test', $attributeBag->getStorageKey()); } public function testGetSetName() { $this->assertEquals('attributes', $this->bag->getName()); $this->bag->setName('foo'); $this->assertEquals('foo', $this->bag->getName()); } /** * @dataProvider attributesProvider */ public function testHas($key, $value, $exists) { $this->assertEquals($exists, $this->bag->has($key)); } /** * @dataProvider attributesProvider */ public function testGet($key, $value, $expected) { $this->assertEquals($value, $this->bag->get($key)); } public function testGetDefaults() { $this->assertNull($this->bag->get('user2.login')); $this->assertEquals('default', $this->bag->get('user2.login', 'default')); } /** * @dataProvider attributesProvider */ public function testSet($key, $value, $expected) { $this->bag->set($key, $value); $this->assertEquals($value, $this->bag->get($key)); } public function testAll() { $this->assertEquals($this->array, $this->bag->all()); $this->bag->set('hello', 'fabien'); $array = $this->array; $array['hello'] = 'fabien'; $this->assertEquals($array, $this->bag->all()); } public function testReplace() { $array = array(); $array['name'] = 'jack'; $array['foo.bar'] = 'beep'; $this->bag->replace($array); $this->assertEquals($array, $this->bag->all()); $this->assertNull($this->bag->get('hello')); $this->assertNull($this->bag->get('always')); $this->assertNull($this->bag->get('user.login')); } public function testRemove() { $this->assertEquals('world', $this->bag->get('hello')); $this->bag->remove('hello'); $this->assertNull($this->bag->get('hello')); $this->assertEquals('be happy', $this->bag->get('always')); $this->bag->remove('always'); $this->assertNull($this->bag->get('always')); $this->assertEquals('drak', $this->bag->get('user.login')); $this->bag->remove('user.login'); $this->assertNull($this->bag->get('user.login')); } public function testClear() { $this->bag->clear(); $this->assertEquals(array(), $this->bag->all()); } public function attributesProvider() { return array( array('hello', 'world', true), array('always', 'be happy', true), array('user.login', 'drak', true), array('csrf.token', array('a' => '1234', 'b' => '4321'), true), array('category', array('fishing' => array('first' => 'cod', 'second' => 'sole')), true), array('user2.login', null, false), array('never', null, false), array('bye', null, false), array('bye/for/now', null, false), ); } /** * @covers Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag::getIterator */ public function testGetIterator() { $i = 0; foreach ($this->bag as $key => $val) { $this->assertEquals($this->array[$key], $val); $i++; } $this->assertEquals(count($this->array), $i); } /** * @covers Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag::count */ public function testCount() { $this->assertEquals(count($this->array), count($this->bag)); } } PK!)ktest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Attribute; use Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag; /** * Tests NamespacedAttributeBag * * @author Drak */ class NamespacedAttributeBagTest extends \PHPUnit_Framework_TestCase { /** * @var array */ private $array; /** * @var NamespacedAttributeBag */ private $bag; protected function setUp() { $this->array = array( 'hello' => 'world', 'always' => 'be happy', 'user.login' => 'drak', 'csrf.token' => array( 'a' => '1234', 'b' => '4321', ), 'category' => array( 'fishing' => array( 'first' => 'cod', 'second' => 'sole') ), ); $this->bag = new NamespacedAttributeBag('_sf2', '/'); $this->bag->initialize($this->array); } protected function tearDown() { $this->bag = null; $this->array = array(); } public function testInitialize() { $bag = new NamespacedAttributeBag(); $bag->initialize($this->array); $this->assertEquals($this->array, $this->bag->all()); $array = array('should' => 'not stick'); $bag->initialize($array); // should have remained the same $this->assertEquals($this->array, $this->bag->all()); } public function testGetStorageKey() { $this->assertEquals('_sf2', $this->bag->getStorageKey()); $attributeBag = new NamespacedAttributeBag('test'); $this->assertEquals('test', $attributeBag->getStorageKey()); } /** * @dataProvider attributesProvider */ public function testHas($key, $value, $exists) { $this->assertEquals($exists, $this->bag->has($key)); } /** * @dataProvider attributesProvider */ public function testGet($key, $value, $expected) { $this->assertEquals($value, $this->bag->get($key)); } public function testGetDefaults() { $this->assertNull($this->bag->get('user2.login')); $this->assertEquals('default', $this->bag->get('user2.login', 'default')); } /** * @dataProvider attributesProvider */ public function testSet($key, $value, $expected) { $this->bag->set($key, $value); $this->assertEquals($value, $this->bag->get($key)); } public function testAll() { $this->assertEquals($this->array, $this->bag->all()); $this->bag->set('hello', 'fabien'); $array = $this->array; $array['hello'] = 'fabien'; $this->assertEquals($array, $this->bag->all()); } public function testReplace() { $array = array(); $array['name'] = 'jack'; $array['foo.bar'] = 'beep'; $this->bag->replace($array); $this->assertEquals($array, $this->bag->all()); $this->assertNull($this->bag->get('hello')); $this->assertNull($this->bag->get('always')); $this->assertNull($this->bag->get('user.login')); } public function testRemove() { $this->assertEquals('world', $this->bag->get('hello')); $this->bag->remove('hello'); $this->assertNull($this->bag->get('hello')); $this->assertEquals('be happy', $this->bag->get('always')); $this->bag->remove('always'); $this->assertNull($this->bag->get('always')); $this->assertEquals('drak', $this->bag->get('user.login')); $this->bag->remove('user.login'); $this->assertNull($this->bag->get('user.login')); } public function testRemoveExistingNamespacedAttribute() { $this->assertSame('cod', $this->bag->remove('category/fishing/first')); } public function testRemoveNonexistingNamespacedAttribute() { $this->assertNull($this->bag->remove('foo/bar/baz')); } public function testClear() { $this->bag->clear(); $this->assertEquals(array(), $this->bag->all()); } public function attributesProvider() { return array( array('hello', 'world', true), array('always', 'be happy', true), array('user.login', 'drak', true), array('csrf.token', array('a' => '1234', 'b' => '4321'), true), array('csrf.token/a', '1234', true), array('csrf.token/b', '4321', true), array('category', array('fishing' => array('first' => 'cod', 'second' => 'sole')), true), array('category/fishing', array('first' => 'cod', 'second' => 'sole'), true), array('category/fishing/missing/first', null, false), array('category/fishing/first', 'cod', true), array('category/fishing/second', 'sole', true), array('category/fishing/missing/second', null, false), array('user2.login', null, false), array('never', null, false), array('bye', null, false), array('bye/for/now', null, false), ); } } PK!ppRtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * SessionTest * * @author Fabien Potencier * @author Robert Schönthal * @author Drak */ class SessionTest extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface */ protected $storage; /** * @var \Symfony\Component\HttpFoundation\Session\SessionInterface */ protected $session; protected function setUp() { $this->storage = new MockArraySessionStorage(); $this->session = new Session($this->storage, new AttributeBag(), new FlashBag()); } protected function tearDown() { $this->storage = null; $this->session = null; } public function testStart() { $this->assertEquals('', $this->session->getId()); $this->assertTrue($this->session->start()); $this->assertNotEquals('', $this->session->getId()); } public function testIsStarted() { $this->assertFalse($this->session->isStarted()); $this->session->start(); $this->assertTrue($this->session->isStarted()); } public function testSetId() { $this->assertEquals('', $this->session->getId()); $this->session->setId('0123456789abcdef'); $this->session->start(); $this->assertEquals('0123456789abcdef', $this->session->getId()); } public function testSetName() { $this->assertEquals('MOCKSESSID', $this->session->getName()); $this->session->setName('session.test.com'); $this->session->start(); $this->assertEquals('session.test.com', $this->session->getName()); } public function testGet() { // tests defaults $this->assertNull($this->session->get('foo')); $this->assertEquals(1, $this->session->get('foo', 1)); } /** * @dataProvider setProvider */ public function testSet($key, $value) { $this->session->set($key, $value); $this->assertEquals($value, $this->session->get($key)); } /** * @dataProvider setProvider */ public function testHas($key, $value) { $this->session->set($key, $value); $this->assertTrue($this->session->has($key)); $this->assertFalse($this->session->has($key.'non_value')); } public function testReplace() { $this->session->replace(array('happiness' => 'be good', 'symfony' => 'awesome')); $this->assertEquals(array('happiness' => 'be good', 'symfony' => 'awesome'), $this->session->all()); $this->session->replace(array()); $this->assertEquals(array(), $this->session->all()); } /** * @dataProvider setProvider */ public function testAll($key, $value, $result) { $this->session->set($key, $value); $this->assertEquals($result, $this->session->all()); } /** * @dataProvider setProvider */ public function testClear($key, $value) { $this->session->set('hi', 'fabien'); $this->session->set($key, $value); $this->session->clear(); $this->assertEquals(array(), $this->session->all()); } public function setProvider() { return array( array('foo', 'bar', array('foo' => 'bar')), array('foo.bar', 'too much beer', array('foo.bar' => 'too much beer')), array('great', 'symfony2 is great', array('great' => 'symfony2 is great')), ); } /** * @dataProvider setProvider */ public function testRemove($key, $value) { $this->session->set('hi.world', 'have a nice day'); $this->session->set($key, $value); $this->session->remove($key); $this->assertEquals(array('hi.world' => 'have a nice day'), $this->session->all()); } public function testInvalidate() { $this->session->set('invalidate', 123); $this->session->invalidate(); $this->assertEquals(array(), $this->session->all()); } public function testMigrate() { $this->session->set('migrate', 321); $this->session->migrate(); $this->assertEquals(321, $this->session->get('migrate')); } public function testMigrateDestroy() { $this->session->set('migrate', 333); $this->session->migrate(true); $this->assertEquals(333, $this->session->get('migrate')); } public function testSave() { $this->session->start(); $this->session->save(); } public function testGetId() { $this->assertEquals('', $this->session->getId()); $this->session->start(); $this->assertNotEquals('', $this->session->getId()); } public function testGetFlashBag() { $this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface', $this->session->getFlashBag()); } /** * @covers Symfony\Component\HttpFoundation\Session\Session::getIterator */ public function testGetIterator() { $attributes = array('hello' => 'world', 'symfony2' => 'rocks'); foreach ($attributes as $key => $val) { $this->session->set($key, $val); } $i = 0; foreach ($this->session as $key => $val) { $this->assertEquals($attributes[$key], $val); $i++; } $this->assertEquals(count($attributes), $i); } /** * @covers \Symfony\Component\HttpFoundation\Session\Session::count */ public function testGetCount() { $this->session->set('hello', 'world'); $this->session->set('symfony2', 'rocks'); $this->assertCount(2, $this->session); } public function testGetMeta() { $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\MetadataBag', $this->session->getMetadataBag()); } } PK!>*itest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; /** * Test class for MockFileSessionStorage. * * @author Drak */ class MockFileSessionStorageTest extends \PHPUnit_Framework_TestCase { /** * @var string */ private $sessionDir; /** * @var FileMockSessionStorage */ protected $storage; protected function setUp() { $this->sessionDir = sys_get_temp_dir().'/sf2test'; $this->storage = $this->getStorage(); } protected function tearDown() { $this->sessionDir = null; $this->storage = null; array_map('unlink', glob($this->sessionDir.'/*.session')); if (is_dir($this->sessionDir)) { rmdir($this->sessionDir); } } public function testStart() { $this->assertEquals('', $this->storage->getId()); $this->assertTrue($this->storage->start()); $id = $this->storage->getId(); $this->assertNotEquals('', $this->storage->getId()); $this->assertTrue($this->storage->start()); $this->assertEquals($id, $this->storage->getId()); } public function testRegenerate() { $this->storage->start(); $this->storage->getBag('attributes')->set('regenerate', 1234); $this->storage->regenerate(); $this->assertEquals(1234, $this->storage->getBag('attributes')->get('regenerate')); $this->storage->regenerate(true); $this->assertEquals(1234, $this->storage->getBag('attributes')->get('regenerate')); } public function testGetId() { $this->assertEquals('', $this->storage->getId()); $this->storage->start(); $this->assertNotEquals('', $this->storage->getId()); } public function testSave() { $this->storage->start(); $id = $this->storage->getId(); $this->assertNotEquals('108', $this->storage->getBag('attributes')->get('new')); $this->assertFalse($this->storage->getBag('flashes')->has('newkey')); $this->storage->getBag('attributes')->set('new', '108'); $this->storage->getBag('flashes')->set('newkey', 'test'); $this->storage->save(); $storage = $this->getStorage(); $storage->setId($id); $storage->start(); $this->assertEquals('108', $storage->getBag('attributes')->get('new')); $this->assertTrue($storage->getBag('flashes')->has('newkey')); $this->assertEquals(array('test'), $storage->getBag('flashes')->peek('newkey')); } public function testMultipleInstances() { $storage1 = $this->getStorage(); $storage1->start(); $storage1->getBag('attributes')->set('foo', 'bar'); $storage1->save(); $storage2 = $this->getStorage(); $storage2->setId($storage1->getId()); $storage2->start(); $this->assertEquals('bar', $storage2->getBag('attributes')->get('foo'), 'values persist between instances'); } /** * @expectedException \RuntimeException */ public function testSaveWithoutStart() { $storage1 = $this->getStorage(); $storage1->save(); } private function getStorage() { $storage = new MockFileSessionStorage($this->sessionDir); $storage->registerBag(new FlashBag()); $storage->registerBag(new AttributeBag()); return $storage; } } PK!5hotest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; /** * Test class for NativeSessionHandler. * * @author Drak * * @runTestsInSeparateProcesses */ class NativeSessionHandlerTest extends \PHPUnit_Framework_TestCase { public function testConstruct() { $handler = new NativeSessionHandler(); // note for PHPUnit optimisers - the use of assertTrue/False // here is deliberate since the tests do not require the classes to exist - drak if (version_compare(phpversion(), '5.4.0', '<')) { $this->assertFalse($handler instanceof \SessionHandler); $this->assertTrue($handler instanceof NativeSessionHandler); } else { $this->assertTrue($handler instanceof \SessionHandler); $this->assertTrue($handler instanceof NativeSessionHandler); } } } PK!1Mf f qtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler; class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase { const PREFIX = 'prefix_'; const TTL = 1000; /** * @var MemcacheSessionHandler */ protected $storage; protected $memcache; protected function setUp() { if (!class_exists('Memcache')) { $this->markTestSkipped('Skipped tests Memcache class is not present'); } $this->memcache = $this->getMock('Memcache'); $this->storage = new MemcacheSessionHandler( $this->memcache, array('prefix' => self::PREFIX, 'expiretime' => self::TTL) ); } protected function tearDown() { $this->memcache = null; $this->storage = null; } public function testOpenSession() { $this->assertTrue($this->storage->open('', '')); } public function testCloseSession() { $this->memcache ->expects($this->once()) ->method('close') ->will($this->returnValue(true)) ; $this->assertTrue($this->storage->close()); } public function testReadSession() { $this->memcache ->expects($this->once()) ->method('get') ->with(self::PREFIX.'id') ; $this->assertEquals('', $this->storage->read('id')); } public function testWriteSession() { $this->memcache ->expects($this->once()) ->method('set') ->with(self::PREFIX.'id', 'data', 0, $this->equalTo(time() + self::TTL, 2)) ->will($this->returnValue(true)) ; $this->assertTrue($this->storage->write('id', 'data')); } public function testDestroySession() { $this->memcache ->expects($this->once()) ->method('delete') ->with(self::PREFIX.'id') ->will($this->returnValue(true)) ; $this->assertTrue($this->storage->destroy('id')); } public function testGcSession() { $this->assertTrue($this->storage->gc(123)); } /** * @dataProvider getOptionFixtures */ public function testSupportedOptions($options, $supported) { try { new MemcacheSessionHandler($this->memcache, $options); $this->assertTrue($supported); } catch (\InvalidArgumentException $e) { $this->assertFalse($supported); } } public function getOptionFixtures() { return array( array(array('prefix' => 'session'), true), array(array('expiretime' => 100), true), array(array('prefix' => 'session', 'expiretime' => 200), true), array(array('expiretime' => 100, 'foo' => 'bar'), false), ); } public function testGetConnection() { $method = new \ReflectionMethod($this->storage, 'getMemcache'); $method->setAccessible(true); $this->assertInstanceOf('\Memcache', $method->invoke($this->storage)); } } PK!+?  stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; /** * Test class for NativeFileSessionHandler. * * @author Drak * * @runTestsInSeparateProcesses */ class NativeFileSessionHandlerTest extends \PHPUnit_Framework_TestCase { public function testConstruct() { $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler(sys_get_temp_dir())); if (version_compare(phpversion(), '5.4.0', '<')) { $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); $this->assertEquals('files', ini_get('session.save_handler')); } else { $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); $this->assertEquals('user', ini_get('session.save_handler')); } $this->assertEquals(sys_get_temp_dir(), ini_get('session.save_path')); $this->assertEquals('TESTING', ini_get('session.name')); } /** * @dataProvider savePathDataProvider */ public function testConstructSavePath($savePath, $expectedSavePath, $path) { $handler = new NativeFileSessionHandler($savePath); $this->assertEquals($expectedSavePath, ini_get('session.save_path')); $this->assertTrue(is_dir(realpath($path))); rmdir($path); } public function savePathDataProvider() { $base = sys_get_temp_dir(); return array( array("$base/foo", "$base/foo", "$base/foo"), array("5;$base/foo", "5;$base/foo", "$base/foo"), array("5;0600;$base/foo", "5;0600;$base/foo", "$base/foo"), ); } /** * @expectedException \InvalidArgumentException */ public function testConstructException() { $handler = new NativeFileSessionHandler('something;invalid;with;too-many-args'); } public function testConstructDefault() { $path = ini_get('session.save_path'); $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler()); $this->assertEquals($path, ini_get('session.save_path')); } } PK!>$$ptest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler; /** * @author Markus Bachmann */ class MongoDbSessionHandlerTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $mongo; private $storage; public $options; protected function setUp() { if (!extension_loaded('mongo')) { $this->markTestSkipped('MongoDbSessionHandler requires the PHP "mongo" extension.'); } $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? 'Mongo' : 'MongoClient'; $this->mongo = $this->getMockBuilder($mongoClass) ->disableOriginalConstructor() ->getMock(); $this->options = array( 'id_field' => '_id', 'data_field' => 'data', 'time_field' => 'time', 'database' => 'sf2-test', 'collection' => 'session-test' ); $this->storage = new MongoDbSessionHandler($this->mongo, $this->options); } /** * @expectedException \InvalidArgumentException */ public function testConstructorShouldThrowExceptionForInvalidMongo() { new MongoDbSessionHandler(new \stdClass(), $this->options); } /** * @expectedException \InvalidArgumentException */ public function testConstructorShouldThrowExceptionForMissingOptions() { new MongoDbSessionHandler($this->mongo, array()); } public function testOpenMethodAlwaysReturnTrue() { $this->assertTrue($this->storage->open('test', 'test'), 'The "open" method should always return true'); } public function testCloseMethodAlwaysReturnTrue() { $this->assertTrue($this->storage->close(), 'The "close" method should always return true'); } public function testWrite() { $collection = $this->getMockBuilder('MongoCollection') ->disableOriginalConstructor() ->getMock(); $this->mongo->expects($this->once()) ->method('selectCollection') ->with($this->options['database'], $this->options['collection']) ->will($this->returnValue($collection)); $that = $this; $data = array(); $collection->expects($this->once()) ->method('update') ->will($this->returnCallback(function ($criteria, $updateData, $options) use ($that, &$data) { $that->assertEquals(array($that->options['id_field'] => 'foo'), $criteria); $that->assertEquals(array('upsert' => true, 'multiple' => false), $options); $data = $updateData['$set']; })); $this->assertTrue($this->storage->write('foo', 'bar')); $this->assertEquals('bar', $data[$this->options['data_field']]->bin); $that->assertInstanceOf('MongoDate', $data[$this->options['time_field']]); } public function testReplaceSessionData() { $collection = $this->getMockBuilder('MongoCollection') ->disableOriginalConstructor() ->getMock(); $this->mongo->expects($this->once()) ->method('selectCollection') ->with($this->options['database'], $this->options['collection']) ->will($this->returnValue($collection)); $data = array(); $collection->expects($this->exactly(2)) ->method('update') ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) { $data = $updateData; })); $this->storage->write('foo', 'bar'); $this->storage->write('foo', 'foobar'); $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->bin); } public function testDestroy() { $collection = $this->getMockBuilder('MongoCollection') ->disableOriginalConstructor() ->getMock(); $this->mongo->expects($this->once()) ->method('selectCollection') ->with($this->options['database'], $this->options['collection']) ->will($this->returnValue($collection)); $collection->expects($this->once()) ->method('remove') ->with(array($this->options['id_field'] => 'foo')); $this->assertTrue($this->storage->destroy('foo')); } public function testGc() { $collection = $this->getMockBuilder('MongoCollection') ->disableOriginalConstructor() ->getMock(); $this->mongo->expects($this->once()) ->method('selectCollection') ->with($this->options['database'], $this->options['collection']) ->will($this->returnValue($collection)); $that = $this; $collection->expects($this->once()) ->method('remove') ->will($this->returnCallback(function ($criteria) use ($that) { $that->assertInstanceOf('MongoDate', $criteria[$that->options['time_field']]['$lt']); $that->assertGreaterThanOrEqual(time() - -1, $criteria[$that->options['time_field']]['$lt']->sec); })); $this->assertTrue($this->storage->gc(-1)); } public function testGetConnection() { $method = new \ReflectionMethod($this->storage, 'getMongo'); $method->setAccessible(true); $mongoClass = (version_compare(phpversion('mongo'), '1.3.0', '<')) ? '\Mongo' : '\MongoClient'; $this->assertInstanceOf($mongoClass, $method->invoke($this->storage)); } } PK!` rtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler; class MemcachedSessionHandlerTest extends \PHPUnit_Framework_TestCase { const PREFIX = 'prefix_'; const TTL = 1000; /** * @var MemcachedSessionHandler */ protected $storage; protected $memcached; protected function setUp() { if (!class_exists('Memcached')) { $this->markTestSkipped('Skipped tests Memcached class is not present'); } $this->memcached = $this->getMock('Memcached'); $this->storage = new MemcachedSessionHandler( $this->memcached, array('prefix' => self::PREFIX, 'expiretime' => self::TTL) ); } protected function tearDown() { $this->memcached = null; $this->storage = null; } public function testOpenSession() { $this->assertTrue($this->storage->open('', '')); } public function testCloseSession() { $this->assertTrue($this->storage->close()); } public function testReadSession() { $this->memcached ->expects($this->once()) ->method('get') ->with(self::PREFIX.'id') ; $this->assertEquals('', $this->storage->read('id')); } public function testWriteSession() { $this->memcached ->expects($this->once()) ->method('set') ->with(self::PREFIX.'id', 'data', $this->equalTo(time() + self::TTL, 2)) ->will($this->returnValue(true)) ; $this->assertTrue($this->storage->write('id', 'data')); } public function testDestroySession() { $this->memcached ->expects($this->once()) ->method('delete') ->with(self::PREFIX.'id') ->will($this->returnValue(true)) ; $this->assertTrue($this->storage->destroy('id')); } public function testGcSession() { $this->assertTrue($this->storage->gc(123)); } /** * @dataProvider getOptionFixtures */ public function testSupportedOptions($options, $supported) { try { new MemcachedSessionHandler($this->memcached, $options); $this->assertTrue($supported); } catch (\InvalidArgumentException $e) { $this->assertFalse($supported); } } public function getOptionFixtures() { return array( array(array('prefix' => 'session'), true), array(array('expiretime' => 100), true), array(array('prefix' => 'session', 'expiretime' => 200), true), array(array('expiretime' => 100, 'foo' => 'bar'), false), ); } public function testGetConnection() { $method = new \ReflectionMethod($this->storage, 'getMemcached'); $method->setAccessible(true); $this->assertInstanceOf('\Memcached', $method->invoke($this->storage)); } } PK!c= stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler; /** * @author Adrien Brault */ class WriteCheckSessionHandlerTest extends \PHPUnit_Framework_TestCase { public function test() { $wrappedSessionHandlerMock = $this->getMock('SessionHandlerInterface'); $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock); $wrappedSessionHandlerMock ->expects($this->once()) ->method('close') ->with() ->will($this->returnValue(true)) ; $this->assertEquals(true, $writeCheckSessionHandler->close()); } public function testWrite() { $wrappedSessionHandlerMock = $this->getMock('SessionHandlerInterface'); $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock); $wrappedSessionHandlerMock ->expects($this->once()) ->method('write') ->with('foo', 'bar') ->will($this->returnValue(true)) ; $this->assertEquals(true, $writeCheckSessionHandler->write('foo', 'bar')); } public function testSkippedWrite() { $wrappedSessionHandlerMock = $this->getMock('SessionHandlerInterface'); $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock); $wrappedSessionHandlerMock ->expects($this->once()) ->method('read') ->with('foo') ->will($this->returnValue('bar')) ; $wrappedSessionHandlerMock ->expects($this->never()) ->method('write') ; $this->assertEquals('bar', $writeCheckSessionHandler->read('foo')); $this->assertEquals(true, $writeCheckSessionHandler->write('foo', 'bar')); } public function testNonSkippedWrite() { $wrappedSessionHandlerMock = $this->getMock('SessionHandlerInterface'); $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock); $wrappedSessionHandlerMock ->expects($this->once()) ->method('read') ->with('foo') ->will($this->returnValue('bar')) ; $wrappedSessionHandlerMock ->expects($this->once()) ->method('write') ->with('foo', 'baZZZ') ->will($this->returnValue(true)) ; $this->assertEquals('bar', $writeCheckSessionHandler->read('foo')); $this->assertEquals(true, $writeCheckSessionHandler->write('foo', 'baZZZ')); } } PK!Qttltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler; class PdoSessionHandlerTest extends \PHPUnit_Framework_TestCase { private $pdo; protected function setUp() { if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) { $this->markTestSkipped('This test requires SQLite support in your environment'); } $this->pdo = new \PDO("sqlite::memory:"); $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $sql = "CREATE TABLE sessions (sess_id VARCHAR(255) PRIMARY KEY, sess_data TEXT, sess_time INTEGER)"; $this->pdo->exec($sql); } public function testIncompleteOptions() { $this->setExpectedException('InvalidArgumentException'); $storage = new PdoSessionHandler($this->pdo, array(), array()); } public function testWrongPdoErrMode() { $pdo = new \PDO("sqlite::memory:"); $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_SILENT); $pdo->exec("CREATE TABLE sessions (sess_id VARCHAR(255) PRIMARY KEY, sess_data TEXT, sess_time INTEGER)"); $this->setExpectedException('InvalidArgumentException'); $storage = new PdoSessionHandler($pdo, array('db_table' => 'sessions'), array()); } public function testWrongTableOptionsWrite() { $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'bad_name'), array()); $this->setExpectedException('RuntimeException'); $storage->write('foo', 'bar'); } public function testWrongTableOptionsRead() { $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'bad_name'), array()); $this->setExpectedException('RuntimeException'); $storage->read('foo', 'bar'); } public function testWriteRead() { $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $storage->write('foo', 'bar'); $this->assertEquals('bar', $storage->read('foo'), 'written value can be read back correctly'); } public function testMultipleInstances() { $storage1 = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $storage1->write('foo', 'bar'); $storage2 = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $this->assertEquals('bar', $storage2->read('foo'), 'values persist between instances'); } public function testSessionDestroy() { $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $storage->write('foo', 'bar'); $this->assertCount(1, $this->pdo->query('SELECT * FROM sessions')->fetchAll()); $storage->destroy('foo'); $this->assertCount(0, $this->pdo->query('SELECT * FROM sessions')->fetchAll()); } public function testSessionGC() { $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $storage->write('foo', 'bar'); $storage->write('baz', 'bar'); $this->assertCount(2, $this->pdo->query('SELECT * FROM sessions')->fetchAll()); $storage->gc(-1); $this->assertCount(0, $this->pdo->query('SELECT * FROM sessions')->fetchAll()); } public function testGetConnection() { $storage = new PdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array()); $method = new \ReflectionMethod($storage, 'getConnection'); $method->setAccessible(true); $this->assertInstanceOf('\PDO', $method->invoke($storage)); } } PK!+ɠmtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; use Symfony\Component\HttpFoundation\Session\Session; /** * Test class for NullSessionHandler. * * @author Drak * * @runTestsInSeparateProcesses */ class NullSessionHandlerTest extends \PHPUnit_Framework_TestCase { public function testSaveHandlers() { $storage = $this->getStorage(); $this->assertEquals('user', ini_get('session.save_handler')); } public function testSession() { session_id('nullsessionstorage'); $storage = $this->getStorage(); $session = new Session($storage); $this->assertNull($session->get('something')); $session->set('something', 'unique'); $this->assertEquals('unique', $session->get('something')); } public function testNothingIsPersisted() { session_id('nullsessionstorage'); $storage = $this->getStorage(); $session = new Session($storage); $session->start(); $this->assertEquals('nullsessionstorage', $session->getId()); $this->assertNull($session->get('something')); } public function getStorage() { return new NativeSessionStorage(array(), new NullSessionHandler()); } } PK!x..jtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; /** * Test class for PhpSessionStorage. * * @author Drak * * These tests require separate processes. * * @runTestsInSeparateProcesses */ class PhpBridgeSessionStorageTest extends \PHPUnit_Framework_TestCase { private $savePath; protected function setUp() { ini_set('session.save_handler', 'files'); ini_set('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test'); if (!is_dir($this->savePath)) { mkdir($this->savePath); } } protected function tearDown() { session_write_close(); array_map('unlink', glob($this->savePath.'/*')); if (is_dir($this->savePath)) { rmdir($this->savePath); } $this->savePath = null; } /** * @return PhpBridgeSessionStorage */ protected function getStorage() { $storage = new PhpBridgeSessionStorage(); $storage->registerBag(new AttributeBag()); return $storage; } public function testPhpSession53() { if (version_compare(phpversion(), '5.4.0', '>=')) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } $storage = $this->getStorage(); $this->assertFalse(isset($_SESSION)); $this->assertFalse($storage->getSaveHandler()->isActive()); session_start(); $this->assertTrue(isset($_SESSION)); // in PHP 5.3 we cannot reliably tell if a session has started $this->assertFalse($storage->getSaveHandler()->isActive()); // PHP session might have started, but the storage driver has not, so false is correct here $this->assertFalse($storage->isStarted()); $key = $storage->getMetadataBag()->getStorageKey(); $this->assertFalse(isset($_SESSION[$key])); $storage->start(); $this->assertTrue(isset($_SESSION[$key])); } public function testPhpSession54() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->markTestSkipped('Test skipped, for PHP 5.4 only.'); } $storage = $this->getStorage(); $this->assertFalse(isset($_SESSION)); $this->assertFalse($storage->getSaveHandler()->isActive()); $this->assertFalse($storage->isStarted()); session_start(); $this->assertTrue(isset($_SESSION)); // in PHP 5.4 we can reliably detect a session started $this->assertTrue($storage->getSaveHandler()->isActive()); // PHP session might have started, but the storage driver has not, so false is correct here $this->assertFalse($storage->isStarted()); $key = $storage->getMetadataBag()->getStorageKey(); $this->assertFalse(isset($_SESSION[$key])); $storage->start(); $this->assertTrue(isset($_SESSION[$key])); } public function testClear() { $storage = $this->getStorage(); session_start(); $_SESSION['drak'] = 'loves symfony'; $storage->getBag('attributes')->set('symfony', 'greatness'); $key = $storage->getBag('attributes')->getStorageKey(); $this->assertEquals($_SESSION[$key], array('symfony' => 'greatness')); $this->assertEquals($_SESSION['drak'], 'loves symfony'); $storage->clear(); $this->assertEquals($_SESSION[$key], array()); $this->assertEquals($_SESSION['drak'], 'loves symfony'); } } PK! jtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; /** * Test class for MockArraySessionStorage. * * @author Drak */ class MockArraySessionStorageTest extends \PHPUnit_Framework_TestCase { /** * @var MockArraySessionStorage */ private $storage; /** * @var AttributeBag */ private $attributes; /** * @var FlashBag */ private $flashes; private $data; protected function setUp() { $this->attributes = new AttributeBag(); $this->flashes = new FlashBag(); $this->data = array( $this->attributes->getStorageKey() => array('foo' => 'bar'), $this->flashes->getStorageKey() => array('notice' => 'hello'), ); $this->storage = new MockArraySessionStorage(); $this->storage->registerBag($this->flashes); $this->storage->registerBag($this->attributes); $this->storage->setSessionData($this->data); } protected function tearDown() { $this->data = null; $this->flashes = null; $this->attributes = null; $this->storage = null; } public function testStart() { $this->assertEquals('', $this->storage->getId()); $this->storage->start(); $id = $this->storage->getId(); $this->assertNotEquals('', $id); $this->storage->start(); $this->assertEquals($id, $this->storage->getId()); } public function testRegenerate() { $this->storage->start(); $id = $this->storage->getId(); $this->storage->regenerate(); $this->assertNotEquals($id, $this->storage->getId()); $this->assertEquals(array('foo' => 'bar'), $this->storage->getBag('attributes')->all()); $this->assertEquals(array('notice' => 'hello'), $this->storage->getBag('flashes')->peekAll()); $id = $this->storage->getId(); $this->storage->regenerate(true); $this->assertNotEquals($id, $this->storage->getId()); $this->assertEquals(array('foo' => 'bar'), $this->storage->getBag('attributes')->all()); $this->assertEquals(array('notice' => 'hello'), $this->storage->getBag('flashes')->peekAll()); } public function testGetId() { $this->assertEquals('', $this->storage->getId()); $this->storage->start(); $this->assertNotEquals('', $this->storage->getId()); } /** * @expectedException \RuntimeException */ public function testUnstartedSave() { $this->storage->save(); } } PK!t䪑$$gtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; /** * Test class for NativeSessionStorage. * * @author Drak * * These tests require separate processes. * * @runTestsInSeparateProcesses */ class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase { private $savePath; protected function setUp() { ini_set('session.save_handler', 'files'); ini_set('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test'); if (!is_dir($this->savePath)) { mkdir($this->savePath); } } protected function tearDown() { session_write_close(); array_map('unlink', glob($this->savePath.'/*')); if (is_dir($this->savePath)) { rmdir($this->savePath); } $this->savePath = null; } /** * @param array $options * * @return NativeSessionStorage */ protected function getStorage(array $options = array()) { $storage = new NativeSessionStorage($options); $storage->registerBag(new AttributeBag()); return $storage; } public function testBag() { $storage = $this->getStorage(); $bag = new FlashBag(); $storage->registerBag($bag); $this->assertSame($bag, $storage->getBag($bag->getName())); } /** * @expectedException \InvalidArgumentException */ public function testRegisterBagException() { $storage = $this->getStorage(); $storage->getBag('non_existing'); } public function testGetId() { $storage = $this->getStorage(); $this->assertEquals('', $storage->getId()); $storage->start(); $this->assertNotEquals('', $storage->getId()); $storage->save(); $this->assertNotEquals('', $storage->getId()); } public function testRegenerate() { $storage = $this->getStorage(); $storage->start(); $id = $storage->getId(); $storage->getBag('attributes')->set('lucky', 7); $storage->regenerate(); $this->assertNotEquals($id, $storage->getId()); $this->assertEquals(7, $storage->getBag('attributes')->get('lucky')); } public function testRegenerateDestroy() { $storage = $this->getStorage(); $storage->start(); $id = $storage->getId(); $storage->getBag('attributes')->set('legs', 11); $storage->regenerate(true); $this->assertNotEquals($id, $storage->getId()); $this->assertEquals(11, $storage->getBag('attributes')->get('legs')); } public function testDefaultSessionCacheLimiter() { ini_set('session.cache_limiter', 'nocache'); $storage = new NativeSessionStorage(); $this->assertEquals('', ini_get('session.cache_limiter')); } public function testExplicitSessionCacheLimiter() { ini_set('session.cache_limiter', 'nocache'); $storage = new NativeSessionStorage(array('cache_limiter' => 'public')); $this->assertEquals('public', ini_get('session.cache_limiter')); } public function testCookieOptions() { $options = array( 'cookie_lifetime' => 123456, 'cookie_path' => '/my/cookie/path', 'cookie_domain' => 'symfony2.example.com', 'cookie_secure' => true, 'cookie_httponly' => false, ); $this->getStorage($options); $temp = session_get_cookie_params(); $gco = array(); foreach ($temp as $key => $value) { $gco['cookie_'.$key] = $value; } $this->assertEquals($options, $gco); } /** * @expectedException \InvalidArgumentException */ public function testSetSaveHandlerException() { $storage = $this->getStorage(); $storage->setSaveHandler(new \stdClass()); } public function testSetSaveHandler53() { if (version_compare(phpversion(), '5.4.0', '>=')) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } ini_set('session.save_handler', 'files'); $storage = $this->getStorage(); $storage->setSaveHandler(); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler()); $storage->setSaveHandler(null); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler()); $storage->setSaveHandler(new NativeSessionHandler()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler()); $storage->setSaveHandler(new SessionHandlerProxy(new SessionHandler())); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); $storage->setSaveHandler(new SessionHandler()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); $storage->setSaveHandler(new NativeProxy()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler()); } public function testSetSaveHandler54() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->markTestSkipped('Test skipped, for PHP 5.4 only.'); } ini_set('session.save_handler', 'files'); $storage = $this->getStorage(); $storage->setSaveHandler(); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); $storage->setSaveHandler(null); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); $storage->setSaveHandler(new SessionHandlerProxy(new NativeSessionHandler())); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); $storage->setSaveHandler(new NativeSessionHandler()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); $storage->setSaveHandler(new SessionHandlerProxy(new SessionHandler())); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); $storage->setSaveHandler(new SessionHandler()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); } /** * @expectedException \RuntimeException */ public function testStartedOutside53() { if (version_compare(phpversion(), '5.4.0', '>=')) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } $storage = $this->getStorage(); $this->assertFalse(isset($_SESSION)); session_start(); $this->assertTrue(isset($_SESSION)); // PHP session might have started, but the storage driver has not, so false is correct here $this->assertFalse($storage->isStarted()); $key = $storage->getMetadataBag()->getStorageKey(); $this->assertFalse(isset($_SESSION[$key])); $storage->start(); } /** * @expectedException \RuntimeException */ public function testCanStartOutside54() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->markTestSkipped('Test skipped, for PHP 5.4 only.'); } $storage = $this->getStorage(); $this->assertFalse(isset($_SESSION)); $this->assertFalse($storage->getSaveHandler()->isActive()); $this->assertFalse($storage->isStarted()); session_start(); $this->assertTrue(isset($_SESSION)); $this->assertTrue($storage->getSaveHandler()->isActive()); // PHP session might have started, but the storage driver has not, so false is correct here $this->assertFalse($storage->isStarted()); $key = $storage->getMetadataBag()->getStorageKey(); $this->assertFalse(isset($_SESSION[$key])); $storage->start(); } } class SessionHandler implements \SessionHandlerInterface { public function open($savePath, $sessionName) { } public function close() { } public function read($id) { } public function write($id, $data) { } public function destroy($id) { } public function gc($maxlifetime) { } } PK!@|B``dtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; /** * Test class for NativeProxy. * * @author Drak */ class NativeProxyTest extends \PHPUnit_Framework_TestCase { public function testIsWrapper() { $proxy = new NativeProxy(); $this->assertFalse($proxy->isWrapper()); } public function testGetSaveHandlerName() { $name = ini_get('session.save_handler'); $proxy = new NativeProxy(); $this->assertEquals($name, $proxy->getSaveHandlerName()); } } PK!F++ftest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; // Note until PHPUnit_Mock_Objects 1.2 is released you cannot mock abstracts due to // https://github.com/sebastianbergmann/phpunit-mock-objects/issues/73 class ConcreteProxy extends AbstractProxy { } class ConcreteSessionHandlerInterfaceProxy extends AbstractProxy implements \SessionHandlerInterface { public function open($savePath, $sessionName) { } public function close() { } public function read($id) { } public function write($id, $data) { } public function destroy($id) { } public function gc($maxlifetime) { } } /** * Test class for AbstractProxy. * * @author Drak */ class AbstractProxyTest extends \PHPUnit_Framework_TestCase { /** * @var AbstractProxy */ protected $proxy; protected function setUp() { $this->proxy = new ConcreteProxy(); } protected function tearDown() { $this->proxy = null; } public function testGetSaveHandlerName() { $this->assertNull($this->proxy->getSaveHandlerName()); } public function testIsSessionHandlerInterface() { $this->assertFalse($this->proxy->isSessionHandlerInterface()); $sh = new ConcreteSessionHandlerInterfaceProxy(); $this->assertTrue($sh->isSessionHandlerInterface()); } public function testIsWrapper() { $this->assertFalse($this->proxy->isWrapper()); } public function testIsActivePhp53() { if (version_compare(phpversion(), '5.4.0', '>=')) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } $this->assertFalse($this->proxy->isActive()); } /** * @runInSeparateProcess */ public function testIsActivePhp54() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->markTestSkipped('Test skipped, for PHP 5.4 only.'); } $this->assertFalse($this->proxy->isActive()); session_start(); $this->assertTrue($this->proxy->isActive()); } public function testSetActivePhp53() { if (version_compare(phpversion(), '5.4.0', '>=')) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } $this->proxy->setActive(true); $this->assertTrue($this->proxy->isActive()); $this->proxy->setActive(false); $this->assertFalse($this->proxy->isActive()); } /** * @runInSeparateProcess * @expectedException \LogicException */ public function testSetActivePhp54() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->markTestSkipped('Test skipped, for PHP 5.4 only.'); } $this->proxy->setActive(true); } /** * @runInSeparateProcess */ public function testName() { $this->assertEquals(session_name(), $this->proxy->getName()); $this->proxy->setName('foo'); $this->assertEquals('foo', $this->proxy->getName()); $this->assertEquals(session_name(), $this->proxy->getName()); } /** * @expectedException \LogicException */ public function testNameExceptionPhp53() { if (version_compare(phpversion(), '5.4.0', '>=')) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } $this->proxy->setActive(true); $this->proxy->setName('foo'); } /** * @runInSeparateProcess * @expectedException \LogicException */ public function testNameExceptionPhp54() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->markTestSkipped('Test skipped, for PHP 5.4 only.'); } session_start(); $this->proxy->setName('foo'); } /** * @runInSeparateProcess */ public function testId() { $this->assertEquals(session_id(), $this->proxy->getId()); $this->proxy->setId('foo'); $this->assertEquals('foo', $this->proxy->getId()); $this->assertEquals(session_id(), $this->proxy->getId()); } /** * @expectedException \LogicException */ public function testIdExceptionPhp53() { if (version_compare(phpversion(), '5.4.0', '>=')) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } $this->proxy->setActive(true); $this->proxy->setId('foo'); } /** * @runInSeparateProcess * @expectedException \LogicException */ public function testIdExceptionPhp54() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->markTestSkipped('Test skipped, for PHP 5.4 only.'); } session_start(); $this->proxy->setId('foo'); } } PK!Č# ltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; /** * Tests for SessionHandlerProxy class. * * @author Drak * * @runTestsInSeparateProcesses */ class SessionHandlerProxyTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_Matcher */ private $mock; /** * @var SessionHandlerProxy */ private $proxy; protected function setUp() { $this->mock = $this->getMock('SessionHandlerInterface'); $this->proxy = new SessionHandlerProxy($this->mock); } protected function tearDown() { $this->mock = null; $this->proxy = null; } public function testOpen() { $this->mock->expects($this->once()) ->method('open') ->will($this->returnValue(true)); $this->assertFalse($this->proxy->isActive()); $this->proxy->open('name', 'id'); if (version_compare(phpversion(), '5.4.0', '<')) { $this->assertTrue($this->proxy->isActive()); } else { $this->assertFalse($this->proxy->isActive()); } } public function testOpenFalse() { $this->mock->expects($this->once()) ->method('open') ->will($this->returnValue(false)); $this->assertFalse($this->proxy->isActive()); $this->proxy->open('name', 'id'); $this->assertFalse($this->proxy->isActive()); } public function testClose() { $this->mock->expects($this->once()) ->method('close') ->will($this->returnValue(true)); $this->assertFalse($this->proxy->isActive()); $this->proxy->close(); $this->assertFalse($this->proxy->isActive()); } public function testCloseFalse() { $this->mock->expects($this->once()) ->method('close') ->will($this->returnValue(false)); $this->assertFalse($this->proxy->isActive()); $this->proxy->close(); $this->assertFalse($this->proxy->isActive()); } public function testRead() { $this->mock->expects($this->once()) ->method('read'); $this->proxy->read('id'); } public function testWrite() { $this->mock->expects($this->once()) ->method('write'); $this->proxy->write('id', 'data'); } public function testDestroy() { $this->mock->expects($this->once()) ->method('destroy'); $this->proxy->destroy('id'); } public function testGc() { $this->mock->expects($this->once()) ->method('gc'); $this->proxy->gc(86400); } } PK!T S^test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; /** * Test class for MetadataBag. */ class MetadataBagTest extends \PHPUnit_Framework_TestCase { /** * @var MetadataBag */ protected $bag; /** * @var array */ protected $array = array(); protected function setUp() { $this->bag = new MetadataBag(); $this->array = array(MetadataBag::CREATED => 1234567, MetadataBag::UPDATED => 12345678, MetadataBag::LIFETIME => 0); $this->bag->initialize($this->array); } protected function tearDown() { $this->array = array(); $this->bag = null; } public function testInitialize() { $sessionMetadata = array(); $bag1 = new MetadataBag(); $bag1->initialize($sessionMetadata); $this->assertGreaterThanOrEqual(time(), $bag1->getCreated()); $this->assertEquals($bag1->getCreated(), $bag1->getLastUsed()); sleep(1); $bag2 = new MetadataBag(); $bag2->initialize($sessionMetadata); $this->assertEquals($bag1->getCreated(), $bag2->getCreated()); $this->assertEquals($bag1->getLastUsed(), $bag2->getLastUsed()); $this->assertEquals($bag2->getCreated(), $bag2->getLastUsed()); sleep(1); $bag3 = new MetadataBag(); $bag3->initialize($sessionMetadata); $this->assertEquals($bag1->getCreated(), $bag3->getCreated()); $this->assertGreaterThan($bag2->getLastUsed(), $bag3->getLastUsed()); $this->assertNotEquals($bag3->getCreated(), $bag3->getLastUsed()); } public function testGetSetName() { $this->assertEquals('__metadata', $this->bag->getName()); $this->bag->setName('foo'); $this->assertEquals('foo', $this->bag->getName()); } public function testGetStorageKey() { $this->assertEquals('_sf2_meta', $this->bag->getStorageKey()); } public function testGetLifetime() { $bag = new MetadataBag(); $array = array(MetadataBag::CREATED => 1234567, MetadataBag::UPDATED => 12345678, MetadataBag::LIFETIME => 1000); $bag->initialize($array); $this->assertEquals(1000, $bag->getLifetime()); } public function testGetCreated() { $this->assertEquals(1234567, $this->bag->getCreated()); } public function testGetLastUsed() { $this->assertLessThanOrEqual(time(), $this->bag->getLastUsed()); } public function testClear() { $this->bag->clear(); } public function testSkipLastUsedUpdate() { $bag = new MetadataBag('', 30); $timeStamp = time(); $created = $timeStamp - 15; $sessionMetadata = array( MetadataBag::CREATED => $created, MetadataBag::UPDATED => $created, MetadataBag::LIFETIME => 1000 ); $bag->initialize($sessionMetadata); $this->assertEquals($created, $sessionMetadata[MetadataBag::UPDATED]); } public function testDoesNotSkipLastUsedUpdate() { $bag = new MetadataBag('', 30); $timeStamp = time(); $created = $timeStamp - 45; $sessionMetadata = array( MetadataBag::CREATED => $created, MetadataBag::UPDATED => $created, MetadataBag::LIFETIME => 1000 ); $bag->initialize($sessionMetadata); $this->assertEquals($timeStamp, $sessionMetadata[MetadataBag::UPDATED]); } } PK!7 Stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderItemTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\AcceptHeaderItem; class AcceptHeaderItemTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider provideFromStringData */ public function testFromString($string, $value, array $attributes) { $item = AcceptHeaderItem::fromString($string); $this->assertEquals($value, $item->getValue()); $this->assertEquals($attributes, $item->getAttributes()); } public function provideFromStringData() { return array( array( 'text/html', 'text/html', array() ), array( '"this;should,not=matter"', 'this;should,not=matter', array() ), array( "text/plain; charset=utf-8;param=\"this;should,not=matter\";\tfootnotes=true", 'text/plain', array('charset' => 'utf-8', 'param' => 'this;should,not=matter', 'footnotes' => 'true') ), array( '"this;should,not=matter";charset=utf-8', 'this;should,not=matter', array('charset' => 'utf-8') ), ); } /** * @dataProvider provideToStringData */ public function testToString($value, array $attributes, $string) { $item = new AcceptHeaderItem($value, $attributes); $this->assertEquals($string, (string) $item); } public function provideToStringData() { return array( array( 'text/html', array(), 'text/html' ), array( 'text/plain', array('charset' => 'utf-8', 'param' => 'this;should,not=matter', 'footnotes' => 'true'), 'text/plain;charset=utf-8;param="this;should,not=matter";footnotes=true' ), ); } public function testValue() { $item = new AcceptHeaderItem('value', array()); $this->assertEquals('value', $item->getValue()); $item->setValue('new value'); $this->assertEquals('new value', $item->getValue()); $item->setValue(1); $this->assertEquals('1', $item->getValue()); } public function testQuality() { $item = new AcceptHeaderItem('value', array()); $this->assertEquals(1.0, $item->getQuality()); $item->setQuality(0.5); $this->assertEquals(0.5, $item->getQuality()); $item->setAttribute('q', 0.75); $this->assertEquals(0.75, $item->getQuality()); $this->assertFalse($item->hasAttribute('q')); } public function testAttribute() { $item = new AcceptHeaderItem('value', array()); $this->assertEquals(array(), $item->getAttributes()); $this->assertFalse($item->hasAttribute('test')); $this->assertNull($item->getAttribute('test')); $this->assertEquals('default', $item->getAttribute('test', 'default')); $item->setAttribute('test', 'value'); $this->assertEquals(array('test' => 'value'), $item->getAttributes()); $this->assertTrue($item->hasAttribute('test')); $this->assertEquals('value', $item->getAttribute('test')); $this->assertEquals('value', $item->getAttribute('test', 'default')); } } PK!`k Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\JsonResponse; class JsonResponseTest extends \PHPUnit_Framework_TestCase { public function testConstructorEmptyCreatesJsonObject() { $response = new JsonResponse(); $this->assertSame('{}', $response->getContent()); } public function testConstructorWithArrayCreatesJsonArray() { $response = new JsonResponse(array(0, 1, 2, 3)); $this->assertSame('[0,1,2,3]', $response->getContent()); } public function testConstructorWithAssocArrayCreatesJsonObject() { $response = new JsonResponse(array('foo' => 'bar')); $this->assertSame('{"foo":"bar"}', $response->getContent()); } public function testConstructorWithSimpleTypes() { $response = new JsonResponse('foo'); $this->assertSame('"foo"', $response->getContent()); $response = new JsonResponse(0); $this->assertSame('0', $response->getContent()); $response = new JsonResponse(0.1); $this->assertSame('0.1', $response->getContent()); $response = new JsonResponse(true); $this->assertSame('true', $response->getContent()); } public function testConstructorWithCustomStatus() { $response = new JsonResponse(array(), 202); $this->assertSame(202, $response->getStatusCode()); } public function testConstructorAddsContentTypeHeader() { $response = new JsonResponse(); $this->assertSame('application/json', $response->headers->get('Content-Type')); } public function testConstructorWithCustomHeaders() { $response = new JsonResponse(array(), 200, array('ETag' => 'foo')); $this->assertSame('application/json', $response->headers->get('Content-Type')); $this->assertSame('foo', $response->headers->get('ETag')); } public function testConstructorWithCustomContentType() { $headers = array('Content-Type' => 'application/vnd.acme.blog-v1+json'); $response = new JsonResponse(array(), 200, $headers); $this->assertSame('application/vnd.acme.blog-v1+json', $response->headers->get('Content-Type')); } public function testCreate() { $response = JsonResponse::create(array('foo' => 'bar'), 204); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertEquals('{"foo":"bar"}', $response->getContent()); $this->assertEquals(204, $response->getStatusCode()); } public function testStaticCreateEmptyJsonObject() { $response = JsonResponse::create(); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertSame('{}', $response->getContent()); } public function testStaticCreateJsonArray() { $response = JsonResponse::create(array(0, 1, 2, 3)); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertSame('[0,1,2,3]', $response->getContent()); } public function testStaticCreateJsonObject() { $response = JsonResponse::create(array('foo' => 'bar')); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertSame('{"foo":"bar"}', $response->getContent()); } public function testStaticCreateWithSimpleTypes() { $response = JsonResponse::create('foo'); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertSame('"foo"', $response->getContent()); $response = JsonResponse::create(0); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertSame('0', $response->getContent()); $response = JsonResponse::create(0.1); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertSame('0.1', $response->getContent()); $response = JsonResponse::create(true); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertSame('true', $response->getContent()); } public function testStaticCreateWithCustomStatus() { $response = JsonResponse::create(array(), 202); $this->assertSame(202, $response->getStatusCode()); } public function testStaticCreateAddsContentTypeHeader() { $response = JsonResponse::create(); $this->assertSame('application/json', $response->headers->get('Content-Type')); } public function testStaticCreateWithCustomHeaders() { $response = JsonResponse::create(array(), 200, array('ETag' => 'foo')); $this->assertSame('application/json', $response->headers->get('Content-Type')); $this->assertSame('foo', $response->headers->get('ETag')); } public function testStaticCreateWithCustomContentType() { $headers = array('Content-Type' => 'application/vnd.acme.blog-v1+json'); $response = JsonResponse::create(array(), 200, $headers); $this->assertSame('application/vnd.acme.blog-v1+json', $response->headers->get('Content-Type')); } public function testSetCallback() { $response = JsonResponse::create(array('foo' => 'bar'))->setCallback('callback'); $this->assertEquals('callback({"foo":"bar"});', $response->getContent()); $this->assertEquals('text/javascript', $response->headers->get('Content-Type')); } public function testJsonEncodeFlags() { $response = new JsonResponse('<>\'&"'); $this->assertEquals('"\u003C\u003E\u0027\u0026\u0022"', $response->getContent()); } /** * @expectedException \InvalidArgumentException */ public function testSetCallbackInvalidIdentifier() { $response = new JsonResponse('foo'); $response->setCallback('+invalid'); } /** * @expectedException \InvalidArgumentException */ public function testSetContent() { JsonResponse::create("\xB1\x31"); } } PK!EQtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\RequestMatcher; use Symfony\Component\HttpFoundation\Request; class RequestMatcherTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider testMethodFixtures */ public function testMethod($requestMethod, $matcherMethod, $isMatch) { $matcher = new RequestMatcher(); $matcher->matchMethod($matcherMethod); $request = Request::create('', $requestMethod); $this->assertSame($isMatch, $matcher->matches($request)); $matcher = new RequestMatcher(null, null, $matcherMethod); $request = Request::create('', $requestMethod); $this->assertSame($isMatch, $matcher->matches($request)); } public function testMethodFixtures() { return array( array('get', 'get', true), array('get', array('get', 'post'), true), array('get', 'post', false), array('get', 'GET', true), array('get', array('GET', 'POST'), true), array('get', 'POST', false), ); } /** * @dataProvider testHostFixture */ public function testHost($pattern, $isMatch) { $matcher = new RequestMatcher(); $request = Request::create('', 'get', array(), array(), array(), array('HTTP_HOST' => 'foo.example.com')); $matcher->matchHost($pattern); $this->assertSame($isMatch, $matcher->matches($request)); $matcher= new RequestMatcher(null, $pattern); $this->assertSame($isMatch, $matcher->matches($request)); } public function testHostFixture() { return array( array('.*\.example\.com', true), array('\.example\.com$', true), array('^.*\.example\.com$', true), array('.*\.sensio\.com', false), array('.*\.example\.COM', true), array('\.example\.COM$', true), array('^.*\.example\.COM$', true), array('.*\.sensio\.COM', false), ); } public function testPath() { $matcher = new RequestMatcher(); $request = Request::create('/admin/foo'); $matcher->matchPath('/admin/.*'); $this->assertTrue($matcher->matches($request)); $matcher->matchPath('/admin'); $this->assertTrue($matcher->matches($request)); $matcher->matchPath('^/admin/.*$'); $this->assertTrue($matcher->matches($request)); $matcher->matchMethod('/blog/.*'); $this->assertFalse($matcher->matches($request)); } public function testPathWithLocaleIsNotSupported() { $matcher = new RequestMatcher(); $request = Request::create('/en/login'); $request->setLocale('en'); $matcher->matchPath('^/{_locale}/login$'); $this->assertFalse($matcher->matches($request)); } public function testPathWithEncodedCharacters() { $matcher = new RequestMatcher(); $request = Request::create('/admin/fo%20o'); $matcher->matchPath('^/admin/fo o*$'); $this->assertTrue($matcher->matches($request)); } public function testAttributes() { $matcher = new RequestMatcher(); $request = Request::create('/admin/foo'); $request->attributes->set('foo', 'foo_bar'); $matcher->matchAttribute('foo', 'foo_.*'); $this->assertTrue($matcher->matches($request)); $matcher->matchAttribute('foo', 'foo'); $this->assertTrue($matcher->matches($request)); $matcher->matchAttribute('foo', '^foo_bar$'); $this->assertTrue($matcher->matches($request)); $matcher->matchAttribute('foo', 'babar'); $this->assertFalse($matcher->matches($request)); } } PK!,,Ttest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\HttpFoundation\Cookie; class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\HttpFoundation\ResponseHeaderBag::allPreserveCase * @dataProvider provideAllPreserveCase */ public function testAllPreserveCase($headers, $expected) { $bag = new ResponseHeaderBag($headers); $this->assertEquals($expected, $bag->allPreserveCase(), '->allPreserveCase() gets all input keys in original case'); } public function provideAllPreserveCase() { return array( array( array('fOo' => 'BAR'), array('fOo' => array('BAR'), 'Cache-Control' => array('no-cache')) ), array( array('ETag' => 'xyzzy'), array('ETag' => array('xyzzy'), 'Cache-Control' => array('private, must-revalidate')) ), array( array('Content-MD5' => 'Q2hlY2sgSW50ZWdyaXR5IQ=='), array('Content-MD5' => array('Q2hlY2sgSW50ZWdyaXR5IQ=='), 'Cache-Control' => array('no-cache')) ), array( array('P3P' => 'CP="CAO PSA OUR"'), array('P3P' => array('CP="CAO PSA OUR"'), 'Cache-Control' => array('no-cache')) ), array( array('WWW-Authenticate' => 'Basic realm="WallyWorld"'), array('WWW-Authenticate' => array('Basic realm="WallyWorld"'), 'Cache-Control' => array('no-cache')) ), array( array('X-UA-Compatible' => 'IE=edge,chrome=1'), array('X-UA-Compatible' => array('IE=edge,chrome=1'), 'Cache-Control' => array('no-cache')) ), array( array('X-XSS-Protection' => '1; mode=block'), array('X-XSS-Protection' => array('1; mode=block'), 'Cache-Control' => array('no-cache')) ), ); } public function testCacheControlHeader() { $bag = new ResponseHeaderBag(array()); $this->assertEquals('no-cache', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('no-cache')); $bag = new ResponseHeaderBag(array('Cache-Control' => 'public')); $this->assertEquals('public', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('public')); $bag = new ResponseHeaderBag(array('ETag' => 'abcde')); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('private')); $this->assertTrue($bag->hasCacheControlDirective('must-revalidate')); $this->assertFalse($bag->hasCacheControlDirective('max-age')); $bag = new ResponseHeaderBag(array('Expires' => 'Wed, 16 Feb 2011 14:17:43 GMT')); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(array( 'Expires' => 'Wed, 16 Feb 2011 14:17:43 GMT', 'Cache-Control' => 'max-age=3600' )); $this->assertEquals('max-age=3600, private', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(array('Last-Modified' => 'abcde')); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(array('Etag' => 'abcde', 'Last-Modified' => 'abcde')); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(array('cache-control' => 'max-age=100')); $this->assertEquals('max-age=100, private', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(array('cache-control' => 's-maxage=100')); $this->assertEquals('s-maxage=100', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(array('cache-control' => 'private, max-age=100')); $this->assertEquals('max-age=100, private', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(array('cache-control' => 'public, max-age=100')); $this->assertEquals('max-age=100, public', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(); $bag->set('Last-Modified', 'abcde'); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); } public function testToStringIncludesCookieHeaders() { $bag = new ResponseHeaderBag(array()); $bag->setCookie(new Cookie('foo', 'bar')); $this->assertContains("Set-Cookie: foo=bar; path=/; httponly", explode("\r\n", $bag->__toString())); $bag->clearCookie('foo'); $this->assertContains("Set-Cookie: foo=deleted; expires=".gmdate("D, d-M-Y H:i:s T", time() - 31536001)."; path=/; httponly", explode("\r\n", $bag->__toString())); } public function testReplace() { $bag = new ResponseHeaderBag(array()); $this->assertEquals('no-cache', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('no-cache')); $bag->replace(array('Cache-Control' => 'public')); $this->assertEquals('public', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('public')); } public function testReplaceWithRemove() { $bag = new ResponseHeaderBag(array()); $this->assertEquals('no-cache', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('no-cache')); $bag->remove('Cache-Control'); $bag->replace(array()); $this->assertEquals('no-cache', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('no-cache')); } public function testCookiesWithSameNames() { $bag = new ResponseHeaderBag(); $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar')); $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'foo.bar')); $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'bar.foo')); $bag->setCookie(new Cookie('foo', 'bar')); $this->assertCount(4, $bag->getCookies()); $headers = explode("\r\n", $bag->__toString()); $this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers); $this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers); $this->assertContains("Set-Cookie: foo=bar; path=/path/bar; domain=bar.foo; httponly", $headers); $this->assertContains("Set-Cookie: foo=bar; path=/; httponly", $headers); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertTrue(isset($cookies['foo.bar']['/path/foo']['foo'])); $this->assertTrue(isset($cookies['foo.bar']['/path/bar']['foo'])); $this->assertTrue(isset($cookies['bar.foo']['/path/bar']['foo'])); $this->assertTrue(isset($cookies['']['/']['foo'])); } public function testRemoveCookie() { $bag = new ResponseHeaderBag(); $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar')); $bag->setCookie(new Cookie('bar', 'foo', 0, '/path/bar', 'foo.bar')); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertTrue(isset($cookies['foo.bar']['/path/foo'])); $bag->removeCookie('foo', '/path/foo', 'foo.bar'); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertFalse(isset($cookies['foo.bar']['/path/foo'])); $bag->removeCookie('bar', '/path/bar', 'foo.bar'); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertFalse(isset($cookies['foo.bar'])); } public function testRemoveCookieWithNullRemove() { $bag = new ResponseHeaderBag(); $bag->setCookie(new Cookie('foo', 'bar', 0)); $bag->setCookie(new Cookie('bar', 'foo', 0)); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertTrue(isset($cookies['']['/'])); $bag->removeCookie('foo', null); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertFalse(isset($cookies['']['/']['foo'])); $bag->removeCookie('bar', null); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertFalse(isset($cookies['']['/']['bar'])); } /** * @expectedException \InvalidArgumentException */ public function testGetCookiesWithInvalidArgument() { $bag = new ResponseHeaderBag(); $cookies = $bag->getCookies('invalid_argument'); } /** * @expectedException \InvalidArgumentException */ public function testMakeDispositionInvalidDisposition() { $headers = new ResponseHeaderBag(); $headers->makeDisposition('invalid', 'foo.html'); } /** * @dataProvider provideMakeDisposition */ public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected) { $headers = new ResponseHeaderBag(); $this->assertEquals($expected, $headers->makeDisposition($disposition, $filename, $filenameFallback)); } public function testToStringDoesntMessUpHeaders() { $headers = new ResponseHeaderBag(); $headers->set('Location', 'http://www.symfony.com'); $headers->set('Content-type', 'text/html'); (string) $headers; $allHeaders = $headers->allPreserveCase(); $this->assertEquals(array('http://www.symfony.com'), $allHeaders['Location']); $this->assertEquals(array('text/html'), $allHeaders['Content-type']); } public function provideMakeDisposition() { return array( array('attachment', 'foo.html', 'foo.html', 'attachment; filename="foo.html"'), array('attachment', 'foo.html', '', 'attachment; filename="foo.html"'), array('attachment', 'foo bar.html', '', 'attachment; filename="foo bar.html"'), array('attachment', 'foo "bar".html', '', 'attachment; filename="foo \\"bar\\".html"'), array('attachment', 'foo%20bar.html', 'foo bar.html', 'attachment; filename="foo bar.html"; filename*=utf-8\'\'foo%2520bar.html'), array('attachment', 'föö.html', 'foo.html', 'attachment; filename="foo.html"; filename*=utf-8\'\'f%C3%B6%C3%B6.html'), ); } /** * @dataProvider provideMakeDispositionFail * @expectedException \InvalidArgumentException */ public function testMakeDispositionFail($disposition, $filename) { $headers = new ResponseHeaderBag(); $headers->makeDisposition($disposition, $filename); } public function provideMakeDispositionFail() { return array( array('attachment', 'foo%20bar.html'), array('attachment', 'foo/bar.html'), array('attachment', '/foo.html'), array('attachment', 'foo\bar.html'), array('attachment', '\foo.html'), array('attachment', 'föö.html'), ); } } PK!k\BrrKtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class ResponseTest extends ResponseTestCase { public function testCreate() { $response = Response::create('foo', 301, array('Foo' => 'bar')); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); $this->assertEquals(301, $response->getStatusCode()); $this->assertEquals('bar', $response->headers->get('foo')); } public function testToString() { $response = new Response(); $response = explode("\r\n", $response); $this->assertEquals("HTTP/1.0 200 OK", $response[0]); $this->assertEquals("Cache-Control: no-cache", $response[1]); } public function testClone() { $response = new Response(); $responseClone = clone $response; $this->assertEquals($response, $responseClone); } public function testSendHeaders() { $response = new Response(); $headers = $response->sendHeaders(); $this->assertObjectHasAttribute('headers', $headers); $this->assertObjectHasAttribute('content', $headers); $this->assertObjectHasAttribute('version', $headers); $this->assertObjectHasAttribute('statusCode', $headers); $this->assertObjectHasAttribute('statusText', $headers); $this->assertObjectHasAttribute('charset', $headers); } public function testSend() { $response = new Response(); $responseSend = $response->send(); $this->assertObjectHasAttribute('headers', $responseSend); $this->assertObjectHasAttribute('content', $responseSend); $this->assertObjectHasAttribute('version', $responseSend); $this->assertObjectHasAttribute('statusCode', $responseSend); $this->assertObjectHasAttribute('statusText', $responseSend); $this->assertObjectHasAttribute('charset', $responseSend); } public function testGetCharset() { $response = new Response(); $charsetOrigin = 'UTF-8'; $response->setCharset($charsetOrigin); $charset = $response->getCharset(); $this->assertEquals($charsetOrigin, $charset); } public function testIsCacheable() { $response = new Response(); $this->assertFalse($response->isCacheable()); } public function testIsCacheableWithErrorCode() { $response = new Response('', 500); $this->assertFalse($response->isCacheable()); } public function testIsCacheableWithNoStoreDirective() { $response = new Response(); $response->headers->set('cache-control', 'private'); $this->assertFalse($response->isCacheable()); } public function testIsCacheableWithSetTtl() { $response = new Response(); $response->setTtl(10); $this->assertTrue($response->isCacheable()); } public function testMustRevalidate() { $response = new Response(); $this->assertFalse($response->mustRevalidate()); } public function testSetNotModified() { $response = new Response(); $modified = $response->setNotModified(); $this->assertObjectHasAttribute('headers', $modified); $this->assertObjectHasAttribute('content', $modified); $this->assertObjectHasAttribute('version', $modified); $this->assertObjectHasAttribute('statusCode', $modified); $this->assertObjectHasAttribute('statusText', $modified); $this->assertObjectHasAttribute('charset', $modified); $this->assertEquals(304, $modified->getStatusCode()); } public function testIsSuccessful() { $response = new Response(); $this->assertTrue($response->isSuccessful()); } public function testIsNotModified() { $response = new Response(); $modified = $response->isNotModified(new Request()); $this->assertFalse($modified); } public function testIsNotModifiedNotSafe() { $request = Request::create('/homepage', 'POST'); $response = new Response(); $this->assertFalse($response->isNotModified($request)); } public function testIsNotModifiedLastModified() { $modified = 'Sun, 25 Aug 2013 18:33:31 GMT'; $request = new Request(); $request->headers->set('If-Modified-Since', $modified); $response = new Response(); $response->headers->set('Last-Modified', $modified); $this->assertTrue($response->isNotModified($request)); $response->headers->set('Last-Modified', ''); $this->assertFalse($response->isNotModified($request)); } public function testIsNotModifiedEtag() { $etagOne = 'randomly_generated_etag'; $etagTwo = 'randomly_generated_etag_2'; $request = new Request(); $request->headers->set('if_none_match', sprintf('%s, %s, %s', $etagOne, $etagTwo, 'etagThree')); $response = new Response(); $response->headers->set('ETag', $etagOne); $this->assertTrue($response->isNotModified($request)); $response->headers->set('ETag', $etagTwo); $this->assertTrue($response->isNotModified($request)); $response->headers->set('ETag', ''); $this->assertFalse($response->isNotModified($request)); } public function testIsValidateable() { $response = new Response('', 200, array('Last-Modified' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822))); $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if Last-Modified is present'); $response = new Response('', 200, array('ETag' => '"12345"')); $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if ETag is present'); $response = new Response(); $this->assertFalse($response->isValidateable(), '->isValidateable() returns false when no validator is present'); } public function testGetDate() { $response = new Response('', 200, array('Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822))); $this->assertEquals(0, $this->createDateTimeOneHourAgo()->diff($response->getDate())->format('%s'), '->getDate() returns the Date header if present'); $response = new Response(); $date = $response->getDate(); $this->assertLessThan(1, $date->diff(new \DateTime(), true)->format('%s'), '->getDate() returns the current Date if no Date header present'); $response = new Response('', 200, array('Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822))); $now = $this->createDateTimeNow(); $response->headers->set('Date', $now->format(DATE_RFC2822)); $this->assertEquals(0, $now->diff($response->getDate())->format('%s'), '->getDate() returns the date when the header has been modified'); $response = new Response('', 200); $response->headers->remove('Date'); $this->assertInstanceOf('\DateTime', $response->getDate()); } public function testGetMaxAge() { $response = new Response(); $response->headers->set('Cache-Control', 's-maxage=600, max-age=0'); $this->assertEquals(600, $response->getMaxAge(), '->getMaxAge() uses s-maxage cache control directive when present'); $response = new Response(); $response->headers->set('Cache-Control', 'max-age=600'); $this->assertEquals(600, $response->getMaxAge(), '->getMaxAge() falls back to max-age when no s-maxage directive present'); $response = new Response(); $response->headers->set('Cache-Control', 'must-revalidate'); $response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822)); $this->assertEquals(3600, $response->getMaxAge(), '->getMaxAge() falls back to Expires when no max-age or s-maxage directive present'); $response = new Response(); $response->headers->set('Cache-Control', 'must-revalidate'); $response->headers->set('Expires', -1); $this->assertEquals('Sat, 01 Jan 00 00:00:00 +0000', $response->getExpires()->format(DATE_RFC822)); $response = new Response(); $this->assertNull($response->getMaxAge(), '->getMaxAge() returns null if no freshness information available'); } public function testSetSharedMaxAge() { $response = new Response(); $response->setSharedMaxAge(20); $cacheControl = $response->headers->get('Cache-Control'); $this->assertEquals('public, s-maxage=20', $cacheControl); } public function testIsPrivate() { $response = new Response(); $response->headers->set('Cache-Control', 'max-age=100'); $response->setPrivate(); $this->assertEquals(100, $response->headers->getCacheControlDirective('max-age'), '->isPrivate() adds the private Cache-Control directive when set to true'); $this->assertTrue($response->headers->getCacheControlDirective('private'), '->isPrivate() adds the private Cache-Control directive when set to true'); $response = new Response(); $response->headers->set('Cache-Control', 'public, max-age=100'); $response->setPrivate(); $this->assertEquals(100, $response->headers->getCacheControlDirective('max-age'), '->isPrivate() adds the private Cache-Control directive when set to true'); $this->assertTrue($response->headers->getCacheControlDirective('private'), '->isPrivate() adds the private Cache-Control directive when set to true'); $this->assertFalse($response->headers->hasCacheControlDirective('public'), '->isPrivate() removes the public Cache-Control directive'); } public function testExpire() { $response = new Response(); $response->headers->set('Cache-Control', 'max-age=100'); $response->expire(); $this->assertEquals(100, $response->headers->get('Age'), '->expire() sets the Age to max-age when present'); $response = new Response(); $response->headers->set('Cache-Control', 'max-age=100, s-maxage=500'); $response->expire(); $this->assertEquals(500, $response->headers->get('Age'), '->expire() sets the Age to s-maxage when both max-age and s-maxage are present'); $response = new Response(); $response->headers->set('Cache-Control', 'max-age=5, s-maxage=500'); $response->headers->set('Age', '1000'); $response->expire(); $this->assertEquals(1000, $response->headers->get('Age'), '->expire() does nothing when the response is already stale/expired'); $response = new Response(); $response->expire(); $this->assertFalse($response->headers->has('Age'), '->expire() does nothing when the response does not include freshness information'); $response = new Response(); $response->headers->set('Expires', -1); $response->expire(); $this->assertNull($response->headers->get('Age'), '->expire() does not set the Age when the response is expired'); } public function testGetTtl() { $response = new Response(); $this->assertNull($response->getTtl(), '->getTtl() returns null when no Expires or Cache-Control headers are present'); $response = new Response(); $response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822)); $this->assertLessThan(1, 3600 - $response->getTtl(), '->getTtl() uses the Expires header when no max-age is present'); $response = new Response(); $response->headers->set('Expires', $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)); $this->assertLessThan(0, $response->getTtl(), '->getTtl() returns negative values when Expires is in past'); $response = new Response(); $response->headers->set('Expires', $response->getDate()->format(DATE_RFC2822)); $response->headers->set('Age', 0); $this->assertSame(0, $response->getTtl(), '->getTtl() correctly handles zero'); $response = new Response(); $response->headers->set('Cache-Control', 'max-age=60'); $this->assertLessThan(1, 60 - $response->getTtl(), '->getTtl() uses Cache-Control max-age when present'); } public function testSetClientTtl() { $response = new Response(); $response->setClientTtl(10); $this->assertEquals($response->getMaxAge(), $response->getAge() + 10); } public function testGetSetProtocolVersion() { $response = new Response(); $this->assertEquals('1.0', $response->getProtocolVersion()); $response->setProtocolVersion('1.1'); $this->assertEquals('1.1', $response->getProtocolVersion()); } public function testGetVary() { $response = new Response(); $this->assertEquals(array(), $response->getVary(), '->getVary() returns an empty array if no Vary header is present'); $response = new Response(); $response->headers->set('Vary', 'Accept-Language'); $this->assertEquals(array('Accept-Language'), $response->getVary(), '->getVary() parses a single header name value'); $response = new Response(); $response->headers->set('Vary', 'Accept-Language User-Agent X-Foo'); $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by spaces'); $response = new Response(); $response->headers->set('Vary', 'Accept-Language,User-Agent, X-Foo'); $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by commas'); $vary = array('Accept-Language', 'User-Agent', 'X-foo'); $response = new Response(); $response->headers->set('Vary', $vary); $this->assertEquals($vary, $response->getVary(), '->getVary() parses multiple header name values in arrays'); $response = new Response(); $response->headers->set('Vary', 'Accept-Language, User-Agent, X-foo'); $this->assertEquals($vary, $response->getVary(), '->getVary() parses multiple header name values in arrays'); } public function testSetVary() { $response = new Response(); $response->setVary('Accept-Language'); $this->assertEquals(array('Accept-Language'), $response->getVary()); $response->setVary('Accept-Language, User-Agent'); $this->assertEquals(array('Accept-Language', 'User-Agent'), $response->getVary(), '->setVary() replace the vary header by default'); $response->setVary('X-Foo', false); $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->setVary() doesn\'t wipe out earlier Vary headers if replace is set to false'); } public function testDefaultContentType() { $headerMock = $this->getMock('Symfony\Component\HttpFoundation\ResponseHeaderBag', array('set')); $headerMock->expects($this->at(0)) ->method('set') ->with('Content-Type', 'text/html'); $headerMock->expects($this->at(1)) ->method('set') ->with('Content-Type', 'text/html; charset=UTF-8'); $response = new Response('foo'); $response->headers = $headerMock; $response->prepare(new Request()); } public function testContentTypeCharset() { $response = new Response(); $response->headers->set('Content-Type', 'text/css'); // force fixContentType() to be called $response->prepare(new Request()); $this->assertEquals('text/css; charset=UTF-8', $response->headers->get('Content-Type')); } public function testPrepareDoesNothingIfContentTypeIsSet() { $response = new Response('foo'); $response->headers->set('Content-Type', 'text/plain'); $response->prepare(new Request()); $this->assertEquals('text/plain; charset=UTF-8', $response->headers->get('content-type')); } public function testPrepareDoesNothingIfRequestFormatIsNotDefined() { $response = new Response('foo'); $response->prepare(new Request()); $this->assertEquals('text/html; charset=UTF-8', $response->headers->get('content-type')); } public function testPrepareSetContentType() { $response = new Response('foo'); $request = Request::create('/'); $request->setRequestFormat('json'); $response->prepare($request); $this->assertEquals('application/json', $response->headers->get('content-type')); } public function testPrepareRemovesContentForHeadRequests() { $response = new Response('foo'); $request = Request::create('/', 'HEAD'); $length = 12345; $response->headers->set('Content-Length', $length); $response->prepare($request); $this->assertEquals('', $response->getContent()); $this->assertEquals($length, $response->headers->get('Content-Length'), 'Content-Length should be as if it was GET; see RFC2616 14.13'); } public function testPrepareRemovesContentForInformationalResponse() { $response = new Response('foo'); $request = Request::create('/'); $response->setContent('content'); $response->setStatusCode(101); $response->prepare($request); $this->assertEquals('', $response->getContent()); $response->setContent('content'); $response->setStatusCode(304); $response->prepare($request); $this->assertEquals('', $response->getContent()); } public function testPrepareRemovesContentLength() { $response = new Response('foo'); $request = Request::create('/'); $response->headers->set('Content-Length', 12345); $response->prepare($request); $this->assertEquals(12345, $response->headers->get('Content-Length')); $response->headers->set('Transfer-Encoding', 'chunked'); $response->prepare($request); $this->assertFalse($response->headers->has('Content-Length')); } public function testPrepareSetsPragmaOnHttp10Only() { $request = Request::create('/', 'GET'); $request->server->set('SERVER_PROTOCOL', 'HTTP/1.0'); $response = new Response('foo'); $response->prepare($request); $this->assertEquals('no-cache', $response->headers->get('pragma')); $this->assertEquals('-1', $response->headers->get('expires')); $request->server->set('SERVER_PROTOCOL', 'HTTP/1.1'); $response = new Response('foo'); $response->prepare($request); $this->assertFalse($response->headers->has('pragma')); $this->assertFalse($response->headers->has('expires')); } public function testSetCache() { $response = new Response(); //array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public') try { $response->setCache(array("wrong option" => "value")); $this->fail('->setCache() throws an InvalidArgumentException if an option is not supported'); } catch (\Exception $e) { $this->assertInstanceOf('InvalidArgumentException', $e, '->setCache() throws an InvalidArgumentException if an option is not supported'); $this->assertContains('"wrong option"', $e->getMessage()); } $options = array('etag' => '"whatever"'); $response->setCache($options); $this->assertEquals($response->getEtag(), '"whatever"'); $now = new \DateTime(); $options = array('last_modified' => $now); $response->setCache($options); $this->assertEquals($response->getLastModified()->getTimestamp(), $now->getTimestamp()); $options = array('max_age' => 100); $response->setCache($options); $this->assertEquals($response->getMaxAge(), 100); $options = array('s_maxage' => 200); $response->setCache($options); $this->assertEquals($response->getMaxAge(), 200); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); $response->setCache(array('public' => true)); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); $response->setCache(array('public' => false)); $this->assertFalse($response->headers->hasCacheControlDirective('public')); $this->assertTrue($response->headers->hasCacheControlDirective('private')); $response->setCache(array('private' => true)); $this->assertFalse($response->headers->hasCacheControlDirective('public')); $this->assertTrue($response->headers->hasCacheControlDirective('private')); $response->setCache(array('private' => false)); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); } public function testSendContent() { $response = new Response('test response rendering', 200); ob_start(); $response->sendContent(); $string = ob_get_clean(); $this->assertContains('test response rendering', $string); } public function testSetPublic() { $response = new Response(); $response->setPublic(); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); } public function testSetExpires() { $response = new Response(); $response->setExpires(null); $this->assertNull($response->getExpires(), '->setExpires() remove the header when passed null'); $now = new \DateTime(); $response->setExpires($now); $this->assertEquals($response->getExpires()->getTimestamp(), $now->getTimestamp()); } public function testSetLastModified() { $response = new Response(); $response->setLastModified(new \DateTime()); $this->assertNotNull($response->getLastModified()); $response->setLastModified(null); $this->assertNull($response->getLastModified()); } public function testIsInvalid() { $response = new Response(); try { $response->setStatusCode(99); $this->fail(); } catch (\InvalidArgumentException $e) { $this->assertTrue($response->isInvalid()); } try { $response->setStatusCode(650); $this->fail(); } catch (\InvalidArgumentException $e) { $this->assertTrue($response->isInvalid()); } $response = new Response('', 200); $this->assertFalse($response->isInvalid()); } /** * @dataProvider getStatusCodeFixtures */ public function testSetStatusCode($code, $text, $expectedText) { $response = new Response(); $response->setStatusCode($code, $text); $statusText = new \ReflectionProperty($response, 'statusText'); $statusText->setAccessible(true); $this->assertEquals($expectedText, $statusText->getValue($response)); } public function getStatusCodeFixtures() { return array( array('200', null, 'OK'), array('200', false, ''), array('200', 'foo', 'foo'), array('199', null, ''), array('199', false, ''), array('199', 'foo', 'foo') ); } public function testIsInformational() { $response = new Response('', 100); $this->assertTrue($response->isInformational()); $response = new Response('', 200); $this->assertFalse($response->isInformational()); } public function testIsRedirectRedirection() { foreach (array(301, 302, 303, 307) as $code) { $response = new Response('', $code); $this->assertTrue($response->isRedirection()); $this->assertTrue($response->isRedirect()); } $response = new Response('', 304); $this->assertTrue($response->isRedirection()); $this->assertFalse($response->isRedirect()); $response = new Response('', 200); $this->assertFalse($response->isRedirection()); $this->assertFalse($response->isRedirect()); $response = new Response('', 404); $this->assertFalse($response->isRedirection()); $this->assertFalse($response->isRedirect()); $response = new Response('', 301, array('Location' => '/good-uri')); $this->assertFalse($response->isRedirect('/bad-uri')); $this->assertTrue($response->isRedirect('/good-uri')); } public function testIsNotFound() { $response = new Response('', 404); $this->assertTrue($response->isNotFound()); $response = new Response('', 200); $this->assertFalse($response->isNotFound()); } public function testIsEmpty() { foreach (array(201, 204, 304) as $code) { $response = new Response('', $code); $this->assertTrue($response->isEmpty()); } $response = new Response('', 200); $this->assertFalse($response->isEmpty()); } public function testIsForbidden() { $response = new Response('', 403); $this->assertTrue($response->isForbidden()); $response = new Response('', 200); $this->assertFalse($response->isForbidden()); } public function testIsOk() { $response = new Response('', 200); $this->assertTrue($response->isOk()); $response = new Response('', 404); $this->assertFalse($response->isOk()); } public function testIsServerOrClientError() { $response = new Response('', 404); $this->assertTrue($response->isClientError()); $this->assertFalse($response->isServerError()); $response = new Response('', 500); $this->assertFalse($response->isClientError()); $this->assertTrue($response->isServerError()); } public function testHasVary() { $response = new Response(); $this->assertFalse($response->hasVary()); $response->setVary('User-Agent'); $this->assertTrue($response->hasVary()); } public function testSetEtag() { $response = new Response('', 200, array('ETag' => '"12345"')); $response->setEtag(); $this->assertNull($response->headers->get('Etag'), '->setEtag() removes Etags when call with null'); } /** * @dataProvider validContentProvider */ public function testSetContent($content) { $response = new Response(); $response->setContent($content); $this->assertEquals((string) $content, $response->getContent()); } /** * @expectedException \UnexpectedValueException * @dataProvider invalidContentProvider */ public function testSetContentInvalid($content) { $response = new Response(); $response->setContent($content); } public function testSettersAreChainable() { $response = new Response(); $setters = array( 'setProtocolVersion' => '1.0', 'setCharset' => 'UTF-8', 'setPublic' => null, 'setPrivate' => null, 'setDate' => new \DateTime(), 'expire' => null, 'setMaxAge' => 1, 'setSharedMaxAge' => 1, 'setTtl' => 1, 'setClientTtl' => 1, ); foreach ($setters as $setter => $arg) { $this->assertEquals($response, $response->{$setter}($arg)); } } public function validContentProvider() { return array( 'obj' => array(new StringableObject()), 'string' => array('Foo'), 'int' => array(2), ); } public function invalidContentProvider() { return array( 'obj' => array(new \stdClass), 'array' => array(array()), 'bool' => array(true, '1'), ); } protected function createDateTimeOneHourAgo() { $date = new \DateTime(); return $date->sub(new \DateInterval('PT1H')); } protected function createDateTimeOneHourLater() { $date = new \DateTime(); return $date->add(new \DateInterval('PT1H')); } protected function createDateTimeNow() { return new \DateTime(); } protected function provideResponse() { return new Response(); } } class StringableObject { public function __toString() { return 'Foo'; } } PK!AkB#B#Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\ParameterBag; class ParameterBagTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\HttpFoundation\ParameterBag::__construct */ public function testConstructor() { $this->testAll(); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::all */ public function testAll() { $bag = new ParameterBag(array('foo' => 'bar')); $this->assertEquals(array('foo' => 'bar'), $bag->all(), '->all() gets all the input'); } public function testKeys() { $bag = new ParameterBag(array('foo' => 'bar')); $this->assertEquals(array('foo'), $bag->keys()); } public function testAdd() { $bag = new ParameterBag(array('foo' => 'bar')); $bag->add(array('bar' => 'bas')); $this->assertEquals(array('foo' => 'bar', 'bar' => 'bas'), $bag->all()); } public function testRemove() { $bag = new ParameterBag(array('foo' => 'bar')); $bag->add(array('bar' => 'bas')); $this->assertEquals(array('foo' => 'bar', 'bar' => 'bas'), $bag->all()); $bag->remove('bar'); $this->assertEquals(array('foo' => 'bar'), $bag->all()); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::replace */ public function testReplace() { $bag = new ParameterBag(array('foo' => 'bar')); $bag->replace(array('FOO' => 'BAR')); $this->assertEquals(array('FOO' => 'BAR'), $bag->all(), '->replace() replaces the input with the argument'); $this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input'); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::get */ public function testGet() { $bag = new ParameterBag(array('foo' => 'bar', 'null' => null)); $this->assertEquals('bar', $bag->get('foo'), '->get() gets the value of a parameter'); $this->assertEquals('default', $bag->get('unknown', 'default'), '->get() returns second argument as default if a parameter is not defined'); $this->assertNull($bag->get('null', 'default'), '->get() returns null if null is set'); } public function testGetDoesNotUseDeepByDefault() { $bag = new ParameterBag(array('foo' => array('bar' => 'moo'))); $this->assertNull($bag->get('foo[bar]')); } /** * @dataProvider getInvalidPaths * @expectedException \InvalidArgumentException */ public function testGetDeepWithInvalidPaths($path) { $bag = new ParameterBag(array('foo' => array('bar' => 'moo'))); $bag->get($path, null, true); } public function getInvalidPaths() { return array( array('foo[['), array('foo[d'), array('foo[bar]]'), array('foo[bar]d'), ); } public function testGetDeep() { $bag = new ParameterBag(array('foo' => array('bar' => array('moo' => 'boo')))); $this->assertEquals(array('moo' => 'boo'), $bag->get('foo[bar]', null, true)); $this->assertEquals('boo', $bag->get('foo[bar][moo]', null, true)); $this->assertEquals('default', $bag->get('foo[bar][foo]', 'default', true)); $this->assertEquals('default', $bag->get('bar[moo][foo]', 'default', true)); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::set */ public function testSet() { $bag = new ParameterBag(array()); $bag->set('foo', 'bar'); $this->assertEquals('bar', $bag->get('foo'), '->set() sets the value of parameter'); $bag->set('foo', 'baz'); $this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter'); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::has */ public function testHas() { $bag = new ParameterBag(array('foo' => 'bar')); $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined'); $this->assertFalse($bag->has('unknown'), '->has() return false if a parameter is not defined'); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::getAlpha */ public function testGetAlpha() { $bag = new ParameterBag(array('word' => 'foo_BAR_012')); $this->assertEquals('fooBAR', $bag->getAlpha('word'), '->getAlpha() gets only alphabetic characters'); $this->assertEquals('', $bag->getAlpha('unknown'), '->getAlpha() returns empty string if a parameter is not defined'); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::getAlnum */ public function testGetAlnum() { $bag = new ParameterBag(array('word' => 'foo_BAR_012')); $this->assertEquals('fooBAR012', $bag->getAlnum('word'), '->getAlnum() gets only alphanumeric characters'); $this->assertEquals('', $bag->getAlnum('unknown'), '->getAlnum() returns empty string if a parameter is not defined'); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::getDigits */ public function testGetDigits() { $bag = new ParameterBag(array('word' => 'foo_BAR_012')); $this->assertEquals('012', $bag->getDigits('word'), '->getDigits() gets only digits as string'); $this->assertEquals('', $bag->getDigits('unknown'), '->getDigits() returns empty string if a parameter is not defined'); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::getInt */ public function testGetInt() { $bag = new ParameterBag(array('digits' => '0123')); $this->assertEquals(123, $bag->getInt('digits'), '->getInt() gets a value of parameter as integer'); $this->assertEquals(0, $bag->getInt('unknown'), '->getInt() returns zero if a parameter is not defined'); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::filter */ public function testFilter() { $bag = new ParameterBag(array( 'digits' => '0123ab', 'email' => 'example@example.com', 'url' => 'http://example.com/foo', 'dec' => '256', 'hex' => '0x100', 'array' => array('bang'), )); $this->assertEmpty($bag->filter('nokey'), '->filter() should return empty by default if no key is found'); $this->assertEquals('0123', $bag->filter('digits', '', false, FILTER_SANITIZE_NUMBER_INT), '->filter() gets a value of parameter as integer filtering out invalid characters'); $this->assertEquals('example@example.com', $bag->filter('email', '', false, FILTER_VALIDATE_EMAIL), '->filter() gets a value of parameter as email'); $this->assertEquals('http://example.com/foo', $bag->filter('url', '', false, FILTER_VALIDATE_URL, array('flags' => FILTER_FLAG_PATH_REQUIRED)), '->filter() gets a value of parameter as URL with a path'); // This test is repeated for code-coverage $this->assertEquals('http://example.com/foo', $bag->filter('url', '', false, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED), '->filter() gets a value of parameter as URL with a path'); $this->assertFalse($bag->filter('dec', '', false, FILTER_VALIDATE_INT, array( 'flags' => FILTER_FLAG_ALLOW_HEX, 'options' => array('min_range' => 1, 'max_range' => 0xff)) ), '->filter() gets a value of parameter as integer between boundaries'); $this->assertFalse($bag->filter('hex', '', false, FILTER_VALIDATE_INT, array( 'flags' => FILTER_FLAG_ALLOW_HEX, 'options' => array('min_range' => 1, 'max_range' => 0xff)) ), '->filter() gets a value of parameter as integer between boundaries'); $this->assertEquals(array('bang'), $bag->filter('array', '', false), '->filter() gets a value of parameter as an array'); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::getIterator */ public function testGetIterator() { $parameters = array('foo' => 'bar', 'hello' => 'world'); $bag = new ParameterBag($parameters); $i = 0; foreach ($bag as $key => $val) { $i++; $this->assertEquals($parameters[$key], $val); } $this->assertEquals(count($parameters), $i); } /** * @covers Symfony\Component\HttpFoundation\ParameterBag::count */ public function testCount() { $parameters = array('foo' => 'bar', 'hello' => 'world'); $bag = new ParameterBag($parameters); $this->assertEquals(count($parameters), count($bag)); } } PK!qJtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Request; class RequestTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\HttpFoundation\Request::__construct */ public function testConstructor() { $this->testInitialize(); } /** * @covers Symfony\Component\HttpFoundation\Request::initialize */ public function testInitialize() { $request = new Request(); $request->initialize(array('foo' => 'bar')); $this->assertEquals('bar', $request->query->get('foo'), '->initialize() takes an array of query parameters as its first argument'); $request->initialize(array(), array('foo' => 'bar')); $this->assertEquals('bar', $request->request->get('foo'), '->initialize() takes an array of request parameters as its second argument'); $request->initialize(array(), array(), array('foo' => 'bar')); $this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its third argument'); $request->initialize(array(), array(), array(), array(), array(), array('HTTP_FOO' => 'bar')); $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its fourth argument'); } public function testGetLocale() { $request = new Request(); $request->setLocale('pl'); $locale = $request->getLocale(); $this->assertEquals('pl', $locale); } public function testGetUser() { $request = Request::create('http://user_test:password_test@test.com/'); $user = $request->getUser(); $this->assertEquals('user_test', $user); } public function testGetPassword() { $request = Request::create('http://user_test:password_test@test.com/'); $password = $request->getPassword(); $this->assertEquals('password_test', $password); } public function testIsNoCache() { $request = new Request(); $isNoCache = $request->isNoCache(); $this->assertFalse($isNoCache); } public function testGetContentType() { $request = new Request(); $contentType = $request->getContentType(); $this->assertNull($contentType); } public function testSetDefaultLocale() { $request = new Request(); $request->setDefaultLocale('pl'); $locale = $request->getLocale(); $this->assertEquals('pl', $locale); } /** * @covers Symfony\Component\HttpFoundation\Request::create */ public function testCreate() { $request = Request::create('http://test.com/foo?bar=baz'); $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('bar=baz', $request->getQueryString()); $this->assertEquals(80, $request->getPort()); $this->assertEquals('test.com', $request->getHttpHost()); $this->assertFalse($request->isSecure()); $request = Request::create('http://test.com/foo', 'GET', array('bar' => 'baz')); $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('bar=baz', $request->getQueryString()); $this->assertEquals(80, $request->getPort()); $this->assertEquals('test.com', $request->getHttpHost()); $this->assertFalse($request->isSecure()); $request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz')); $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('bar=baz', $request->getQueryString()); $this->assertEquals(80, $request->getPort()); $this->assertEquals('test.com', $request->getHttpHost()); $this->assertFalse($request->isSecure()); $request = Request::create('https://test.com/foo?bar=baz'); $this->assertEquals('https://test.com/foo?bar=baz', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('bar=baz', $request->getQueryString()); $this->assertEquals(443, $request->getPort()); $this->assertEquals('test.com', $request->getHttpHost()); $this->assertTrue($request->isSecure()); $request = Request::create('test.com:90/foo'); $this->assertEquals('http://test.com:90/foo', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('test.com', $request->getHost()); $this->assertEquals('test.com:90', $request->getHttpHost()); $this->assertEquals(90, $request->getPort()); $this->assertFalse($request->isSecure()); $request = Request::create('https://test.com:90/foo'); $this->assertEquals('https://test.com:90/foo', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('test.com', $request->getHost()); $this->assertEquals('test.com:90', $request->getHttpHost()); $this->assertEquals(90, $request->getPort()); $this->assertTrue($request->isSecure()); $request = Request::create('https://127.0.0.1:90/foo'); $this->assertEquals('https://127.0.0.1:90/foo', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('127.0.0.1', $request->getHost()); $this->assertEquals('127.0.0.1:90', $request->getHttpHost()); $this->assertEquals(90, $request->getPort()); $this->assertTrue($request->isSecure()); $request = Request::create('https://[::1]:90/foo'); $this->assertEquals('https://[::1]:90/foo', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('[::1]', $request->getHost()); $this->assertEquals('[::1]:90', $request->getHttpHost()); $this->assertEquals(90, $request->getPort()); $this->assertTrue($request->isSecure()); $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}'; $request = Request::create('http://example.com/jsonrpc', 'POST', array(), array(), array(), array(), $json); $this->assertEquals($json, $request->getContent()); $this->assertFalse($request->isSecure()); $request = Request::create('http://test.com'); $this->assertEquals('http://test.com/', $request->getUri()); $this->assertEquals('/', $request->getPathInfo()); $this->assertEquals('', $request->getQueryString()); $this->assertEquals(80, $request->getPort()); $this->assertEquals('test.com', $request->getHttpHost()); $this->assertFalse($request->isSecure()); $request = Request::create('http://test.com?test=1'); $this->assertEquals('http://test.com/?test=1', $request->getUri()); $this->assertEquals('/', $request->getPathInfo()); $this->assertEquals('test=1', $request->getQueryString()); $this->assertEquals(80, $request->getPort()); $this->assertEquals('test.com', $request->getHttpHost()); $this->assertFalse($request->isSecure()); $request = Request::create('http://test.com:90/?test=1'); $this->assertEquals('http://test.com:90/?test=1', $request->getUri()); $this->assertEquals('/', $request->getPathInfo()); $this->assertEquals('test=1', $request->getQueryString()); $this->assertEquals(90, $request->getPort()); $this->assertEquals('test.com:90', $request->getHttpHost()); $this->assertFalse($request->isSecure()); $request = Request::create('http://test:test@test.com'); $this->assertEquals('http://test.com/', $request->getUri()); $this->assertEquals('/', $request->getPathInfo()); $this->assertEquals('', $request->getQueryString()); $this->assertEquals(80, $request->getPort()); $this->assertEquals('test.com', $request->getHttpHost()); $this->assertEquals('test', $request->getUser()); $this->assertEquals('test', $request->getPassword()); $this->assertFalse($request->isSecure()); $request = Request::create('http://testnopass@test.com'); $this->assertEquals('http://test.com/', $request->getUri()); $this->assertEquals('/', $request->getPathInfo()); $this->assertEquals('', $request->getQueryString()); $this->assertEquals(80, $request->getPort()); $this->assertEquals('test.com', $request->getHttpHost()); $this->assertEquals('testnopass', $request->getUser()); $this->assertNull($request->getPassword()); $this->assertFalse($request->isSecure()); $request = Request::create('http://test.com/?foo'); $this->assertEquals('/?foo', $request->getRequestUri()); $this->assertEquals(array('foo' => ''), $request->query->all()); } /** * @covers Symfony\Component\HttpFoundation\Request::create */ public function testCreateCheckPrecedence() { // server is used by default $request = Request::create('/', 'DELETE', array(), array(), array(), array( 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on', 'SERVER_PORT' => 443, 'PHP_AUTH_USER' => 'fabien', 'PHP_AUTH_PW' => 'pa$$', 'QUERY_STRING' => 'foo=bar', 'CONTENT_TYPE' => 'application/json', )); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(443, $request->getPort()); $this->assertTrue($request->isSecure()); $this->assertEquals('fabien', $request->getUser()); $this->assertEquals('pa$$', $request->getPassword()); $this->assertEquals('', $request->getQueryString()); $this->assertEquals('application/json', $request->headers->get('CONTENT_TYPE')); // URI has precedence over server $request = Request::create('http://thomas:pokemon@example.net:8080/?foo=bar', 'GET', array(), array(), array(), array( 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on', 'SERVER_PORT' => 443, )); $this->assertEquals('example.net', $request->getHost()); $this->assertEquals(8080, $request->getPort()); $this->assertFalse($request->isSecure()); $this->assertEquals('thomas', $request->getUser()); $this->assertEquals('pokemon', $request->getPassword()); $this->assertEquals('foo=bar', $request->getQueryString()); } public function testDuplicate() { $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar')); $dup = $request->duplicate(); $this->assertEquals($request->query->all(), $dup->query->all(), '->duplicate() duplicates a request an copy the current query parameters'); $this->assertEquals($request->request->all(), $dup->request->all(), '->duplicate() duplicates a request an copy the current request parameters'); $this->assertEquals($request->attributes->all(), $dup->attributes->all(), '->duplicate() duplicates a request an copy the current attributes'); $this->assertEquals($request->headers->all(), $dup->headers->all(), '->duplicate() duplicates a request an copy the current HTTP headers'); $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar')); $this->assertEquals(array('foo' => 'foobar'), $dup->query->all(), '->duplicate() overrides the query parameters if provided'); $this->assertEquals(array('foo' => 'foobar'), $dup->request->all(), '->duplicate() overrides the request parameters if provided'); $this->assertEquals(array('foo' => 'foobar'), $dup->attributes->all(), '->duplicate() overrides the attributes if provided'); $this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided'); } public function testDuplicateWithFormat() { $request = new Request(array(), array(), array('_format' => 'json')); $dup = $request->duplicate(); $this->assertEquals('json', $dup->getRequestFormat()); $this->assertEquals('json', $dup->attributes->get('_format')); $request = new Request(); $request->setRequestFormat('xml'); $dup = $request->duplicate(); $this->assertEquals('xml', $dup->getRequestFormat()); } /** * @covers Symfony\Component\HttpFoundation\Request::getFormat * @covers Symfony\Component\HttpFoundation\Request::setFormat * @dataProvider getFormatToMimeTypeMapProvider */ public function testGetFormatFromMimeType($format, $mimeTypes) { $request = new Request(); foreach ($mimeTypes as $mime) { $this->assertEquals($format, $request->getFormat($mime)); } $request->setFormat($format, $mimeTypes); foreach ($mimeTypes as $mime) { $this->assertEquals($format, $request->getFormat($mime)); } } /** * @covers Symfony\Component\HttpFoundation\Request::getFormat */ public function testGetFormatFromMimeTypeWithParameters() { $request = new Request(); $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8')); } /** * @covers Symfony\Component\HttpFoundation\Request::getMimeType * @dataProvider getFormatToMimeTypeMapProvider */ public function testGetMimeTypeFromFormat($format, $mimeTypes) { if (null !== $format) { $request = new Request(); $this->assertEquals($mimeTypes[0], $request->getMimeType($format)); } } public function getFormatToMimeTypeMapProvider() { return array( array(null, array(null, 'unexistent-mime-type')), array('txt', array('text/plain')), array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')), array('css', array('text/css')), array('json', array('application/json', 'application/x-json')), array('xml', array('text/xml', 'application/xml', 'application/x-xml')), array('rdf', array('application/rdf+xml')), array('atom',array('application/atom+xml')), ); } /** * @covers Symfony\Component\HttpFoundation\Request::getUri */ public function testGetUri() { $server = array(); // Standard Request on non default PORT // http://host:8080/index.php/path/info?query=string $server['HTTP_HOST'] = 'host:8080'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '8080'; $server['QUERY_STRING'] = 'query=string'; $server['REQUEST_URI'] = '/index.php/path/info?query=string'; $server['SCRIPT_NAME'] = '/index.php'; $server['PATH_INFO'] = '/path/info'; $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info'; $server['PHP_SELF'] = '/index_dev.php/path/info'; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $request = new Request(); $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://host:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port'); // Use std port number $server['HTTP_HOST'] = 'host'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://host/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port'); // Without HOST HEADER unset($server['HTTP_HOST']); $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER'); // Request with URL REWRITING (hide index.php) // RewriteCond %{REQUEST_FILENAME} !-f // RewriteRule ^(.*)$ index.php [QSA,L] // http://host:8080/path/info?query=string $server = array(); $server['HTTP_HOST'] = 'host:8080'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '8080'; $server['REDIRECT_QUERY_STRING'] = 'query=string'; $server['REDIRECT_URL'] = '/path/info'; $server['SCRIPT_NAME'] = '/index.php'; $server['QUERY_STRING'] = 'query=string'; $server['REQUEST_URI'] = '/path/info?toto=test&1=1'; $server['SCRIPT_NAME'] = '/index.php'; $server['PHP_SELF'] = '/index.php'; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://host:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite'); // Use std port number // http://host/path/info?query=string $server['HTTP_HOST'] = 'host'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://host/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port'); // Without HOST HEADER unset($server['HTTP_HOST']); $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER'); // With encoded characters $server = array( 'HTTP_HOST' => 'host:8080', 'SERVER_NAME' => 'servername', 'SERVER_PORT' => '8080', 'QUERY_STRING' => 'query=string', 'REQUEST_URI' => '/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', 'SCRIPT_NAME' => '/ba se/index_dev.php', 'PATH_TRANSLATED' => 'redirect:/index.php/foo bar/in+fo', 'PHP_SELF' => '/ba se/index_dev.php/path/info', 'SCRIPT_FILENAME' => '/some/where/ba se/index_dev.php', ); $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals( 'http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri() ); // with user info $server['PHP_AUTH_USER'] = 'fabien'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri()); $server['PHP_AUTH_PW'] = 'symfony'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri()); } /** * @covers Symfony\Component\HttpFoundation\Request::getUriForPath */ public function testGetUriForPath() { $request = Request::create('http://test.com/foo?bar=baz'); $this->assertEquals('http://test.com/some/path', $request->getUriForPath('/some/path')); $request = Request::create('http://test.com:90/foo?bar=baz'); $this->assertEquals('http://test.com:90/some/path', $request->getUriForPath('/some/path')); $request = Request::create('https://test.com/foo?bar=baz'); $this->assertEquals('https://test.com/some/path', $request->getUriForPath('/some/path')); $request = Request::create('https://test.com:90/foo?bar=baz'); $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path')); $server = array(); // Standard Request on non default PORT // http://host:8080/index.php/path/info?query=string $server['HTTP_HOST'] = 'host:8080'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '8080'; $server['QUERY_STRING'] = 'query=string'; $server['REQUEST_URI'] = '/index.php/path/info?query=string'; $server['SCRIPT_NAME'] = '/index.php'; $server['PATH_INFO'] = '/path/info'; $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info'; $server['PHP_SELF'] = '/index_dev.php/path/info'; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $request = new Request(); $request->initialize(array(), array(), array(), array(), array(),$server); $this->assertEquals('http://host:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port'); // Use std port number $server['HTTP_HOST'] = 'host'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://host/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port'); // Without HOST HEADER unset($server['HTTP_HOST']); $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER'); // Request with URL REWRITING (hide index.php) // RewriteCond %{REQUEST_FILENAME} !-f // RewriteRule ^(.*)$ index.php [QSA,L] // http://host:8080/path/info?query=string $server = array(); $server['HTTP_HOST'] = 'host:8080'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '8080'; $server['REDIRECT_QUERY_STRING'] = 'query=string'; $server['REDIRECT_URL'] = '/path/info'; $server['SCRIPT_NAME'] = '/index.php'; $server['QUERY_STRING'] = 'query=string'; $server['REQUEST_URI'] = '/path/info?toto=test&1=1'; $server['SCRIPT_NAME'] = '/index.php'; $server['PHP_SELF'] = '/index.php'; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://host:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite'); // Use std port number // http://host/path/info?query=string $server['HTTP_HOST'] = 'host'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://host/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port'); // Without HOST HEADER unset($server['HTTP_HOST']); $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite, default port without HOST_HEADER'); $this->assertEquals('servername', $request->getHttpHost()); // with user info $server['PHP_AUTH_USER'] = 'fabien'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path')); $server['PHP_AUTH_PW'] = 'symfony'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path')); } /** * @covers Symfony\Component\HttpFoundation\Request::getUserInfo */ public function testGetUserInfo() { $request = new Request(); $server['PHP_AUTH_USER'] = 'fabien'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('fabien', $request->getUserInfo()); $server['PHP_AUTH_USER'] = '0'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('0', $request->getUserInfo()); $server['PHP_AUTH_PW'] = '0'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('0:0', $request->getUserInfo()); } /** * @covers Symfony\Component\HttpFoundation\Request::getSchemeAndHttpHost */ public function testGetSchemeAndHttpHost() { $request = new Request(); $server = array(); $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '90'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); $server['PHP_AUTH_USER'] = 'fabien'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); $server['PHP_AUTH_USER'] = '0'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); $server['PHP_AUTH_PW'] = '0'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); } /** * @covers Symfony\Component\HttpFoundation\Request::getQueryString * @covers Symfony\Component\HttpFoundation\Request::normalizeQueryString * @dataProvider getQueryStringNormalizationData */ public function testGetQueryString($query, $expectedQuery, $msg) { $request = new Request(); $request->server->set('QUERY_STRING', $query); $this->assertSame($expectedQuery, $request->getQueryString(), $msg); } public function getQueryStringNormalizationData() { return array( array('foo', 'foo', 'works with valueless parameters'), array('foo=', 'foo=', 'includes a dangling equal sign'), array('bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'), array('foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'), // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded). // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str. array('him=John%20Doe&her=Jane+Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'), array('foo[]=1&foo[]=2', 'foo%5B%5D=1&foo%5B%5D=2', 'allows array notation'), array('foo=1&foo=2', 'foo=1&foo=2', 'allows repeated parameters'), array('pa%3Dram=foo%26bar%3Dbaz&test=test', 'pa%3Dram=foo%26bar%3Dbaz&test=test', 'works with encoded delimiters'), array('0', '0', 'allows "0"'), array('Jane Doe&John%20Doe', 'Jane%20Doe&John%20Doe', 'normalizes encoding in keys'), array('her=Jane Doe&him=John%20Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes encoding in values'), array('foo=bar&&&test&&', 'foo=bar&test', 'removes unneeded delimiters'), array('formula=e=m*c^2', 'formula=e%3Dm%2Ac%5E2', 'correctly treats only the first "=" as delimiter and the next as value'), // Ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway. // PHP also does not include them when building _GET. array('foo=bar&=a=b&=x=y', 'foo=bar', 'removes params with empty key'), ); } public function testGetQueryStringReturnsNull() { $request = new Request(); $this->assertNull($request->getQueryString(), '->getQueryString() returns null for non-existent query string'); $request->server->set('QUERY_STRING', ''); $this->assertNull($request->getQueryString(), '->getQueryString() returns null for empty query string'); } public function testGetHost() { $request = new Request(); $request->initialize(array('foo' => 'bar')); $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized'); $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com')); $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header'); // Host header with port number $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com:8080')); $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header with port number'); // Server values $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com')); $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from server name'); $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com', 'HTTP_HOST' => 'www.host.com')); $this->assertEquals('www.host.com', $request->getHost(), '->getHost() value from Host header has priority over SERVER_NAME '); } public function testGetPort() { $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'https', 'HTTP_X_FORWARDED_PORT' => '443' )); $port = $request->getPort(); $this->assertEquals(80, $port, 'Without trusted proxies FORWARDED_PROTO and FORWARDED_PORT are ignored.'); Request::setTrustedProxies(array('1.1.1.1')); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'https', 'HTTP_X_FORWARDED_PORT' => '8443' )); $port = $request->getPort(); $this->assertEquals(8443, $port, 'With PROTO and PORT set PORT takes precedence.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'https' )); $port = $request->getPort(); $this->assertEquals(443, $port, 'With only PROTO set getPort() defaults to 443.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'http' )); $port = $request->getPort(); $this->assertEquals(80, $port, 'If X_FORWARDED_PROTO is set to HTTP return 80.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'On' )); $port = $request->getPort(); $this->assertEquals(443, $port, 'With only PROTO set and value is On, getPort() defaults to 443.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => '1' )); $port = $request->getPort(); $this->assertEquals(443, $port, 'With only PROTO set and value is 1, getPort() defaults to 443.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'something-else' )); $port = $request->getPort(); $this->assertEquals(80, $port, 'With only PROTO set and value is not recognized, getPort() defaults to 80.'); Request::setTrustedProxies(array()); } /** * @expectedException \RuntimeException */ public function testGetHostWithFakeHttpHostValue() { $request = new Request(); $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.host.com?query=string')); $request->getHost(); } /** * @covers Symfony\Component\HttpFoundation\Request::setMethod * @covers Symfony\Component\HttpFoundation\Request::getMethod */ public function testGetSetMethod() { $request = new Request(); $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns GET if no method is defined'); $request->setMethod('get'); $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns an uppercased string'); $request->setMethod('PURGE'); $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method even if it is not a standard one'); $request->setMethod('POST'); $this->assertEquals('POST', $request->getMethod(), '->getMethod() returns the method POST if no _method is defined'); $request->setMethod('POST'); $request->request->set('_method', 'purge'); $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled'); $request = new Request(); $request->setMethod('POST'); $request->request->set('_method', 'purge'); $this->assertFalse(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be disabled by default'); Request::enableHttpMethodParameterOverride(); $this->assertTrue(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be enabled now but it is not'); $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST'); $this->disableHttpMethodParameterOverride(); $request = new Request(); $request->setMethod('POST'); $request->query->set('_method', 'purge'); $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled'); $request = new Request(); $request->setMethod('POST'); $request->query->set('_method', 'purge'); Request::enableHttpMethodParameterOverride(); $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST'); $this->disableHttpMethodParameterOverride(); $request = new Request(); $request->setMethod('POST'); $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete'); $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override even though _method is set if defined and POST'); $request = new Request(); $request->setMethod('POST'); $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete'); $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override if defined and POST'); } /** * @dataProvider testGetClientIpsProvider */ public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trustedProxies) { $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies); $this->assertEquals($expected[0], $request->getClientIp()); Request::setTrustedProxies(array()); } /** * @dataProvider testGetClientIpsProvider */ public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $trustedProxies) { $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies); $this->assertEquals($expected, $request->getClientIps()); Request::setTrustedProxies(array()); } public function testGetClientIpsProvider() { // $expected $remoteAddr $httpForwardedFor $trustedProxies return array( // simple IPv4 array(array('88.88.88.88'), '88.88.88.88', null, null), // trust the IPv4 remote addr array(array('88.88.88.88'), '88.88.88.88', null, array('88.88.88.88')), // simple IPv6 array(array('::1'), '::1', null, null), // trust the IPv6 remote addr array(array('::1'), '::1', null, array('::1')), // forwarded for with remote IPv4 addr not trusted array(array('127.0.0.1'), '127.0.0.1', '88.88.88.88', null), // forwarded for with remote IPv4 addr trusted array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88', array('127.0.0.1')), // forwarded for with remote IPv4 and all FF addrs trusted array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88', array('127.0.0.1', '88.88.88.88')), // forwarded for with remote IPv4 range trusted array(array('88.88.88.88'), '123.45.67.89', '88.88.88.88', array('123.45.67.0/24')), // forwarded for with remote IPv6 addr not trusted array(array('1620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', null), // forwarded for with remote IPv6 addr trusted array(array('2620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3')), // forwarded for with remote IPv6 range trusted array(array('88.88.88.88'), '2a01:198:603:0:396e:4789:8e99:890f', '88.88.88.88', array('2a01:198:603:0::/65')), // multiple forwarded for with remote IPv4 addr trusted array(array('88.88.88.88', '87.65.43.21', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89')), // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted array(array('87.65.43.21', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')), // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle array(array('88.88.88.88', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21')), // multiple forwarded for with remote IPv4 addr and all reverse proxies trusted array(array('127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21', '88.88.88.88', '127.0.0.1')), // multiple forwarded for with remote IPv6 addr trusted array(array('2620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3')), // multiple forwarded for with remote IPv6 addr and some reverse proxies trusted array(array('3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3')), // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle array(array('2620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3,3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3')), ); } public function testGetContentWorksTwiceInDefaultMode() { $req = new Request(); $this->assertEquals('', $req->getContent()); $this->assertEquals('', $req->getContent()); } public function testGetContentReturnsResource() { $req = new Request(); $retval = $req->getContent(true); $this->assertInternalType('resource', $retval); $this->assertEquals("", fread($retval, 1)); $this->assertTrue(feof($retval)); } /** * @expectedException \LogicException * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider */ public function testGetContentCantBeCalledTwiceWithResources($first, $second) { $req = new Request(); $req->getContent($first); $req->getContent($second); } public function getContentCantBeCalledTwiceWithResourcesProvider() { return array( 'Resource then fetch' => array(true, false), 'Resource then resource' => array(true, true), 'Fetch then resource' => array(false, true), ); } public function provideOverloadedMethods() { return array( array('PUT'), array('DELETE'), array('PATCH'), array('put'), array('delete'), array('patch'), ); } /** * @dataProvider provideOverloadedMethods */ public function testCreateFromGlobals($method) { $normalizedMethod = strtoupper($method); $_GET['foo1'] = 'bar1'; $_POST['foo2'] = 'bar2'; $_COOKIE['foo3'] = 'bar3'; $_FILES['foo4'] = array('bar4'); $_SERVER['foo5'] = 'bar5'; $request = Request::createFromGlobals(); $this->assertEquals('bar1', $request->query->get('foo1'), '::fromGlobals() uses values from $_GET'); $this->assertEquals('bar2', $request->request->get('foo2'), '::fromGlobals() uses values from $_POST'); $this->assertEquals('bar3', $request->cookies->get('foo3'), '::fromGlobals() uses values from $_COOKIE'); $this->assertEquals(array('bar4'), $request->files->get('foo4'), '::fromGlobals() uses values from $_FILES'); $this->assertEquals('bar5', $request->server->get('foo5'), '::fromGlobals() uses values from $_SERVER'); unset($_GET['foo1'], $_POST['foo2'], $_COOKIE['foo3'], $_FILES['foo4'], $_SERVER['foo5']); $_SERVER['REQUEST_METHOD'] = $method; $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; $request = RequestContentProxy::createFromGlobals(); $this->assertEquals($normalizedMethod, $request->getMethod()); $this->assertEquals('mycontent', $request->request->get('content')); unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']); Request::createFromGlobals(); Request::enableHttpMethodParameterOverride(); $_POST['_method'] = $method; $_POST['foo6'] = 'bar6'; $_SERVER['REQUEST_METHOD'] = 'PoSt'; $request = Request::createFromGlobals(); $this->assertEquals($normalizedMethod, $request->getMethod()); $this->assertEquals('POST', $request->getRealMethod()); $this->assertEquals('bar6', $request->request->get('foo6')); unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']); $this->disableHttpMethodParameterOverride(); } public function testOverrideGlobals() { $request = new Request(); $request->initialize(array('foo' => 'bar')); // as the Request::overrideGlobals really work, it erase $_SERVER, so we must backup it $server = $_SERVER; $request->overrideGlobals(); $this->assertEquals(array('foo' => 'bar'), $_GET); $request->initialize(array(), array('foo' => 'bar')); $request->overrideGlobals(); $this->assertEquals(array('foo' => 'bar'), $_POST); $this->assertArrayNotHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER); $request->headers->set('X_FORWARDED_PROTO', 'https'); Request::setTrustedProxies(array('1.1.1.1')); $this->assertTrue($request->isSecure()); Request::setTrustedProxies(array()); $request->overrideGlobals(); $this->assertArrayHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER); $request->headers->set('CONTENT_TYPE', 'multipart/form-data'); $request->headers->set('CONTENT_LENGTH', 12345); $request->overrideGlobals(); $this->assertArrayHasKey('CONTENT_TYPE', $_SERVER); $this->assertArrayHasKey('CONTENT_LENGTH', $_SERVER); // restore initial $_SERVER array $_SERVER = $server; } public function testGetScriptName() { $request = new Request(); $this->assertEquals('', $request->getScriptName()); $server = array(); $server['SCRIPT_NAME'] = '/index.php'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('/index.php', $request->getScriptName()); $server = array(); $server['ORIG_SCRIPT_NAME'] = '/frontend.php'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('/frontend.php', $request->getScriptName()); $server = array(); $server['SCRIPT_NAME'] = '/index.php'; $server['ORIG_SCRIPT_NAME'] = '/frontend.php'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('/index.php', $request->getScriptName()); } public function testGetBasePath() { $request = new Request(); $this->assertEquals('', $request->getBasePath()); $server = array(); $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('', $request->getBasePath()); $server = array(); $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $server['SCRIPT_NAME'] = '/index.php'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('', $request->getBasePath()); $server = array(); $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $server['PHP_SELF'] = '/index.php'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('', $request->getBasePath()); $server = array(); $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $server['ORIG_SCRIPT_NAME'] = '/index.php'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('', $request->getBasePath()); } public function testGetPathInfo() { $request = new Request(); $this->assertEquals('/', $request->getPathInfo()); $server = array(); $server['REQUEST_URI'] = '/path/info'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('/path/info', $request->getPathInfo()); $server = array(); $server['REQUEST_URI'] = '/path%20test/info'; $request->initialize(array(), array(), array(), array(), array(), $server); $this->assertEquals('/path%20test/info', $request->getPathInfo()); } public function testGetPreferredLanguage() { $request = new Request(); $this->assertNull($request->getPreferredLanguage()); $this->assertNull($request->getPreferredLanguage(array())); $this->assertEquals('fr', $request->getPreferredLanguage(array('fr'))); $this->assertEquals('fr', $request->getPreferredLanguage(array('fr', 'en'))); $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'fr'))); $this->assertEquals('fr-ch', $request->getPreferredLanguage(array('fr-ch', 'fr-fr'))); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'en-us'))); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8'); $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8, fr-fr; q=0.6, fr; q=0.5'); $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); } public function testIsXmlHttpRequest() { $request = new Request(); $this->assertFalse($request->isXmlHttpRequest()); $request->headers->set('X-Requested-With', 'XMLHttpRequest'); $this->assertTrue($request->isXmlHttpRequest()); $request->headers->remove('X-Requested-With'); $this->assertFalse($request->isXmlHttpRequest()); } public function testIntlLocale() { if (!extension_loaded('intl')) { $this->markTestSkipped('The intl extension is needed to run this test.'); } $request = new Request(); $request->setDefaultLocale('fr'); $this->assertEquals('fr', $request->getLocale()); $this->assertEquals('fr', \Locale::getDefault()); $request->setLocale('en'); $this->assertEquals('en', $request->getLocale()); $this->assertEquals('en', \Locale::getDefault()); $request->setDefaultLocale('de'); $this->assertEquals('en', $request->getLocale()); $this->assertEquals('en', \Locale::getDefault()); } public function testGetCharsets() { $request = new Request(); $this->assertEquals(array(), $request->getCharsets()); $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6'); $this->assertEquals(array(), $request->getCharsets()); // testing caching $request = new Request(); $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6'); $this->assertEquals(array('ISO-8859-1', 'US-ASCII', 'UTF-8', 'ISO-10646-UCS-2'), $request->getCharsets()); $request = new Request(); $request->headers->set('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7'); $this->assertEquals(array('ISO-8859-1', 'utf-8', '*'), $request->getCharsets()); } public function testGetEncodings() { $request = new Request(); $this->assertEquals(array(), $request->getEncodings()); $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch'); $this->assertEquals(array(), $request->getEncodings()); // testing caching $request = new Request(); $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch'); $this->assertEquals(array('gzip', 'deflate', 'sdch'), $request->getEncodings()); $request = new Request(); $request->headers->set('Accept-Encoding', 'gzip;q=0.4,deflate;q=0.9,compress;q=0.7'); $this->assertEquals(array('deflate', 'compress', 'gzip'), $request->getEncodings()); } public function testGetAcceptableContentTypes() { $request = new Request(); $this->assertEquals(array(), $request->getAcceptableContentTypes()); $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*'); $this->assertEquals(array(), $request->getAcceptableContentTypes()); // testing caching $request = new Request(); $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*'); $this->assertEquals(array('application/vnd.wap.wmlscriptc', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml', 'application/xhtml+xml', 'text/html', 'multipart/mixed', '*/*'), $request->getAcceptableContentTypes()); } public function testGetLanguages() { $request = new Request(); $this->assertEquals(array(), $request->getLanguages()); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages()); $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages()); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.6, en; q=0.8'); $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test out of order qvalues $request = new Request(); $request->headers->set('Accept-language', 'zh, en, en-us'); $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test equal weighting without qvalues $request = new Request(); $request->headers->set('Accept-language', 'zh; q=0.6, en, en-us; q=0.6'); $this->assertEquals(array('en', 'zh', 'en_US'), $request->getLanguages()); // Test equal weighting with qvalues $request = new Request(); $request->headers->set('Accept-language', 'zh, i-cherokee; q=0.6'); $this->assertEquals(array('zh', 'cherokee'), $request->getLanguages()); } public function testGetRequestFormat() { $request = new Request(); $this->assertEquals('html', $request->getRequestFormat()); $request = new Request(); $this->assertNull($request->getRequestFormat(null)); $request = new Request(); $this->assertNull($request->setRequestFormat('foo')); $this->assertEquals('foo', $request->getRequestFormat(null)); } public function testHasSession() { $request = new Request(); $this->assertFalse($request->hasSession()); $request->setSession(new Session(new MockArraySessionStorage())); $this->assertTrue($request->hasSession()); } public function testGetSession() { $request = new Request(); $request->setSession(new Session(new MockArraySessionStorage())); $this->assertTrue($request->hasSession()); $session = $request->getSession(); $this->assertObjectHasAttribute('storage', $session); $this->assertObjectHasAttribute('flashName', $session); $this->assertObjectHasAttribute('attributeName', $session); } public function testHasPreviousSession() { $request = new Request(); $this->assertFalse($request->hasPreviousSession()); $request->cookies->set('MOCKSESSID', 'foo'); $this->assertFalse($request->hasPreviousSession()); $request->setSession(new Session(new MockArraySessionStorage())); $this->assertTrue($request->hasPreviousSession()); } public function testToString() { $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $request->__toString()); } public function testIsMethod() { $request = new Request(); $request->setMethod('POST'); $this->assertTrue($request->isMethod('POST')); $this->assertTrue($request->isMethod('post')); $this->assertFalse($request->isMethod('GET')); $this->assertFalse($request->isMethod('get')); $request->setMethod('GET'); $this->assertTrue($request->isMethod('GET')); $this->assertTrue($request->isMethod('get')); $this->assertFalse($request->isMethod('POST')); $this->assertFalse($request->isMethod('post')); } /** * @dataProvider getBaseUrlData */ public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo) { $request = Request::create($uri, 'GET', array(), array(), array(), $server); $this->assertSame($expectedBaseUrl, $request->getBaseUrl(), 'baseUrl'); $this->assertSame($expectedPathInfo, $request->getPathInfo(), 'pathInfo'); } public function getBaseUrlData() { return array( array( '/foo%20bar', array( 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 'SCRIPT_NAME' => '/foo bar/app.php', 'PHP_SELF' => '/foo bar/app.php', ), '/foo%20bar', '/', ), array( '/foo%20bar/home', array( 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 'SCRIPT_NAME' => '/foo bar/app.php', 'PHP_SELF' => '/foo bar/app.php', ), '/foo%20bar', '/home', ), array( '/foo%20bar/app.php/home', array( 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 'SCRIPT_NAME' => '/foo bar/app.php', 'PHP_SELF' => '/foo bar/app.php', ), '/foo%20bar/app.php', '/home', ), array( '/foo%20bar/app.php/home%3Dbaz', array( 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 'SCRIPT_NAME' => '/foo bar/app.php', 'PHP_SELF' => '/foo bar/app.php', ), '/foo%20bar/app.php', '/home%3Dbaz', ), array( '/foo/bar+baz', array( 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo/app.php', 'SCRIPT_NAME' => '/foo/app.php', 'PHP_SELF' => '/foo/app.php', ), '/foo', '/bar+baz', ), ); } /** * @dataProvider urlencodedStringPrefixData */ public function testUrlencodedStringPrefix($string, $prefix, $expect) { $request = new Request(); $me = new \ReflectionMethod($request, 'getUrlencodedPrefix'); $me->setAccessible(true); $this->assertSame($expect, $me->invoke($request, $string, $prefix)); } public function urlencodedStringPrefixData() { return array( array('foo', 'foo', 'foo'), array('fo%6f', 'foo', 'fo%6f'), array('foo/bar', 'foo', 'foo'), array('fo%6f/bar', 'foo', 'fo%6f'), array('f%6f%6f/bar', 'foo', 'f%6f%6f'), array('%66%6F%6F/bar', 'foo', '%66%6F%6F'), array('fo+o/bar', 'fo+o', 'fo+o'), array('fo%2Bo/bar', 'fo+o', 'fo%2Bo'), ); } private function disableHttpMethodParameterOverride() { $class = new \ReflectionClass('Symfony\\Component\\HttpFoundation\\Request'); $property = $class->getProperty('httpMethodParameterOverride'); $property->setAccessible(true); $property->setValue(false); } private function getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies) { $request = new Request(); $server = array('REMOTE_ADDR' => $remoteAddr); if (null !== $httpForwardedFor) { $server['HTTP_X_FORWARDED_FOR'] = $httpForwardedFor; } if ($trustedProxies) { Request::setTrustedProxies($trustedProxies); } $request->initialize(array(), array(), array(), array(), array(), $server); return $request; } public function testTrustedProxies() { $request = Request::create('http://example.com/'); $request->server->set('REMOTE_ADDR', '3.3.3.3'); $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2'); $request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080'); $request->headers->set('X_FORWARDED_PROTO', 'https'); $request->headers->set('X_FORWARDED_PORT', 443); $request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4'); $request->headers->set('X_MY_HOST', 'my.example.com'); $request->headers->set('X_MY_PROTO', 'http'); $request->headers->set('X_MY_PORT', 81); // no trusted proxies $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // disabling proxy trusting Request::setTrustedProxies(array()); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // trusted proxy via setTrustedProxies() Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2')); $this->assertEquals('1.1.1.1', $request->getClientIp()); $this->assertEquals('real.example.com', $request->getHost()); $this->assertEquals(443, $request->getPort()); $this->assertTrue($request->isSecure()); // check various X_FORWARDED_PROTO header values $request->headers->set('X_FORWARDED_PROTO', 'ssl'); $this->assertTrue($request->isSecure()); $request->headers->set('X_FORWARDED_PROTO', 'https, http'); $this->assertTrue($request->isSecure()); // custom header names Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_MY_FOR'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_MY_HOST'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_MY_PORT'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_MY_PROTO'); $this->assertEquals('4.4.4.4', $request->getClientIp()); $this->assertEquals('my.example.com', $request->getHost()); $this->assertEquals(81, $request->getPort()); $this->assertFalse($request->isSecure()); // disabling via empty header names Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, null); Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, null); Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, null); Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, null); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // reset Request::setTrustedProxies(array()); Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO'); } /** * @expectedException \InvalidArgumentException */ public function testSetTrustedProxiesInvalidHeaderName() { Request::create('http://example.com/'); Request::setTrustedHeaderName('bogus name', 'X_MY_FOR'); } /** * @expectedException \InvalidArgumentException */ public function testGetTrustedProxiesInvalidHeaderName() { Request::create('http://example.com/'); Request::getTrustedHeaderName('bogus name'); } /** * @dataProvider iisRequestUriProvider */ public function testIISRequestUri($headers, $server, $expectedRequestUri) { $request = new Request(); $request->headers->replace($headers); $request->server->replace($server); $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct'); $subRequestUri = '/bar/foo'; $subRequest = Request::create($subRequestUri, 'get', array(), array(), array(), $request->server->all()); $this->assertEquals($subRequestUri, $subRequest->getRequestUri(), '->getRequestUri() is correct in sub request'); } public function iisRequestUriProvider() { return array( array( array( 'X_ORIGINAL_URL' => '/foo/bar', ), array(), '/foo/bar' ), array( array( 'X_REWRITE_URL' => '/foo/bar', ), array(), '/foo/bar' ), array( array(), array( 'IIS_WasUrlRewritten' => '1', 'UNENCODED_URL' => '/foo/bar' ), '/foo/bar' ), array( array( 'X_ORIGINAL_URL' => '/foo/bar', ), array( 'HTTP_X_ORIGINAL_URL' => '/foo/bar' ), '/foo/bar' ), array( array( 'X_ORIGINAL_URL' => '/foo/bar', ), array( 'IIS_WasUrlRewritten' => '1', 'UNENCODED_URL' => '/foo/bar' ), '/foo/bar' ), array( array( 'X_ORIGINAL_URL' => '/foo/bar', ), array( 'HTTP_X_ORIGINAL_URL' => '/foo/bar', 'IIS_WasUrlRewritten' => '1', 'UNENCODED_URL' => '/foo/bar' ), '/foo/bar' ), array( array(), array( 'ORIG_PATH_INFO' => '/foo/bar', ), '/foo/bar' ), array( array(), array( 'ORIG_PATH_INFO' => '/foo/bar', 'QUERY_STRING' => 'foo=bar', ), '/foo/bar?foo=bar' ) ); } public function testTrustedHosts() { // create a request $request = Request::create('/'); // no trusted host set -> no host check $request->headers->set('host', 'evil.com'); $this->assertEquals('evil.com', $request->getHost()); // add a trusted domain and all its subdomains Request::setTrustedHosts(array('.*\.?trusted.com$')); // untrusted host $request->headers->set('host', 'evil.com'); try { $request->getHost(); $this->fail('Request::getHost() should throw an exception when host is not trusted.'); } catch (\UnexpectedValueException $e) { $this->assertEquals('Untrusted Host "evil.com"', $e->getMessage()); } // trusted hosts $request->headers->set('host', 'trusted.com'); $this->assertEquals('trusted.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $request->server->set('HTTPS', true); $request->headers->set('host', 'trusted.com'); $this->assertEquals('trusted.com', $request->getHost()); $this->assertEquals(443, $request->getPort()); $request->server->set('HTTPS', false); $request->headers->set('host', 'trusted.com:8000'); $this->assertEquals('trusted.com', $request->getHost()); $this->assertEquals(8000, $request->getPort()); $request->headers->set('host', 'subdomain.trusted.com'); $this->assertEquals('subdomain.trusted.com', $request->getHost()); // reset request for following tests Request::setTrustedHosts(array()); } public function testFactory() { Request::setFactory(function (array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { return new NewRequest(); }); $this->assertEquals('foo', Request::create('/')->getFoo()); Request::setFactory(null); } } class RequestContentProxy extends Request { public function getContent($asResource = false) { return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent')); } } class NewRequest extends Request { public function getFoo() { return 'foo'; } } PK!%bD Ptest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\ApacheRequest; class ApacheRequestTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider provideServerVars */ public function testUriMethods($server, $expectedRequestUri, $expectedBaseUrl, $expectedPathInfo) { $request = new ApacheRequest(); $request->server->replace($server); $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct'); $this->assertEquals($expectedBaseUrl, $request->getBaseUrl(), '->getBaseUrl() is correct'); $this->assertEquals($expectedPathInfo, $request->getPathInfo(), '->getPathInfo() is correct'); } public function provideServerVars() { return array( array( array( 'REQUEST_URI' => '/foo/app_dev.php/bar', 'SCRIPT_NAME' => '/foo/app_dev.php', 'PATH_INFO' => '/bar', ), '/foo/app_dev.php/bar', '/foo/app_dev.php', '/bar' ), array( array( 'REQUEST_URI' => '/foo/bar', 'SCRIPT_NAME' => '/foo/app_dev.php', ), '/foo/bar', '/foo', '/bar', ), array( array( 'REQUEST_URI' => '/app_dev.php/foo/bar', 'SCRIPT_NAME' => '/app_dev.php', 'PATH_INFO' => '/foo/bar', ), '/app_dev.php/foo/bar', '/app_dev.php', '/foo/bar', ), array( array( 'REQUEST_URI' => '/foo/bar', 'SCRIPT_NAME' => '/app_dev.php', ), '/foo/bar', '', '/foo/bar', ), array( array( 'REQUEST_URI' => '/app_dev.php', 'SCRIPT_NAME' => '/app_dev.php', ), '/app_dev.php', '/app_dev.php', '/', ), array( array( 'REQUEST_URI' => '/', 'SCRIPT_NAME' => '/app_dev.php', ), '/', '', '/', ), ); } } PK!1r Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\AcceptHeader; use Symfony\Component\HttpFoundation\AcceptHeaderItem; class AcceptHeaderTest extends \PHPUnit_Framework_TestCase { public function testFirst() { $header = AcceptHeader::fromString('text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c'); $this->assertSame('text/html', $header->first()->getValue()); } /** * @dataProvider provideFromStringData */ public function testFromString($string, array $items) { $header = AcceptHeader::fromString($string); $parsed = array_values($header->all()); // reset index since the fixtures don't have them set foreach ($parsed as $item) { $item->setIndex(0); } $this->assertEquals($items, $parsed); } public function provideFromStringData() { return array( array('', array()), array('gzip', array(new AcceptHeaderItem('gzip'))), array('gzip,deflate,sdch', array(new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch'))), array("gzip, deflate\t,sdch", array(new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch'))), array('"this;should,not=matter"', array(new AcceptHeaderItem('this;should,not=matter'))), ); } /** * @dataProvider provideToStringData */ public function testToString(array $items, $string) { $header = new AcceptHeader($items); $this->assertEquals($string, (string) $header); } public function provideToStringData() { return array( array(array(), ''), array(array(new AcceptHeaderItem('gzip')), 'gzip'), array(array(new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch')), 'gzip,deflate,sdch'), array(array(new AcceptHeaderItem('this;should,not=matter')), 'this;should,not=matter'), ); } /** * @dataProvider provideFilterData */ public function testFilter($string, $filter, array $values) { $header = AcceptHeader::fromString($string)->filter($filter); $this->assertEquals($values, array_keys($header->all())); } public function provideFilterData() { return array( array('fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4', '/fr.*/', array('fr-FR', 'fr')), ); } /** * @dataProvider provideSortingData */ public function testSorting($string, array $values) { $header = AcceptHeader::fromString($string); $this->assertEquals($values, array_keys($header->all())); } public function provideSortingData() { return array( 'quality has priority' => array('*;q=0.3,ISO-8859-1,utf-8;q=0.7', array('ISO-8859-1', 'utf-8', '*')), 'order matters when q is equal' => array('*;q=0.3,ISO-8859-1;q=0.7,utf-8;q=0.7', array('ISO-8859-1', 'utf-8', '*')), 'order matters when q is equal2' => array('*;q=0.3,utf-8;q=0.7,ISO-8859-1;q=0.7', array('utf-8', 'ISO-8859-1', '*')), ); } } PK!?Ltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ServerBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\ServerBag; /** * ServerBagTest * * @author Bulat Shakirzyanov */ class ServerBagTest extends \PHPUnit_Framework_TestCase { public function testShouldExtractHeadersFromServerArray() { $server = array( 'SOME_SERVER_VARIABLE' => 'value', 'SOME_SERVER_VARIABLE2' => 'value', 'ROOT' => 'value', 'HTTP_CONTENT_TYPE' => 'text/html', 'HTTP_CONTENT_LENGTH' => '0', 'HTTP_ETAG' => 'asdf', 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar', ); $bag = new ServerBag($server); $this->assertEquals(array( 'CONTENT_TYPE' => 'text/html', 'CONTENT_LENGTH' => '0', 'ETAG' => 'asdf', 'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'), 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar', ), $bag->getHeaders()); } public function testHttpPasswordIsOptional() { $bag = new ServerBag(array('PHP_AUTH_USER' => 'foo')); $this->assertEquals(array( 'AUTHORIZATION' => 'Basic '.base64_encode('foo:'), 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => '' ), $bag->getHeaders()); } public function testHttpBasicAuthWithPhpCgi() { $bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'))); $this->assertEquals(array( 'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'), 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar' ), $bag->getHeaders()); } public function testHttpBasicAuthWithPhpCgiRedirect() { $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'))); $this->assertEquals(array( 'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'), 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar' ), $bag->getHeaders()); } public function testHttpBasicAuthWithPhpCgiEmptyPassword() { $bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:'))); $this->assertEquals(array( 'AUTHORIZATION' => 'Basic '.base64_encode('foo:'), 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => '' ), $bag->getHeaders()); } public function testHttpDigestAuthWithPhpCgi() { $digest = 'Digest username="foo", realm="acme", nonce="'.md5('secret').'", uri="/protected, qop="auth"'; $bag = new ServerBag(array('HTTP_AUTHORIZATION' => $digest)); $this->assertEquals(array( 'AUTHORIZATION' => $digest, 'PHP_AUTH_DIGEST' => $digest, ), $bag->getHeaders()); } public function testHttpDigestAuthWithPhpCgiRedirect() { $digest = 'Digest username="foo", realm="acme", nonce="'.md5('secret').'", uri="/protected, qop="auth"'; $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => $digest)); $this->assertEquals(array( 'AUTHORIZATION' => $digest, 'PHP_AUTH_DIGEST' => $digest, ), $bag->getHeaders()); } public function testOAuthBearerAuth() { $headerContent = 'Bearer L-yLEOr9zhmUYRkzN1jwwxwQ-PBNiKDc8dgfB4hTfvo'; $bag = new ServerBag(array('HTTP_AUTHORIZATION' => $headerContent)); $this->assertEquals(array( 'AUTHORIZATION' => $headerContent, ), $bag->getHeaders()); } } PK!bppEtest/HttpFoundation/Symfony/Component/HttpFoundation/phpunit.xml.distnu[ ./Tests/ ./ ./Resources ./Tests ./vendor PK!J=''Dtest/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieJarTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit\Tests; use Symfony\Component\BrowserKit\CookieJar; use Symfony\Component\BrowserKit\Cookie; use Symfony\Component\BrowserKit\Response; class CookieJarTest extends \PHPUnit_Framework_TestCase { public function testSetGet() { $cookieJar = new CookieJar(); $cookieJar->set($cookie = new Cookie('foo', 'bar')); $this->assertEquals($cookie, $cookieJar->get('foo'), '->set() sets a cookie'); $this->assertNull($cookieJar->get('foobar'), '->get() returns null if the cookie does not exist'); $cookieJar->set($cookie = new Cookie('foo', 'bar', time() - 86400)); $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired'); } public function testExpire() { $cookieJar = new CookieJar(); $cookieJar->set($cookie = new Cookie('foo', 'bar')); $cookieJar->expire('foo'); $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired'); } public function testAll() { $cookieJar = new CookieJar(); $cookieJar->set($cookie1 = new Cookie('foo', 'bar')); $cookieJar->set($cookie2 = new Cookie('bar', 'foo')); $this->assertEquals(array($cookie1, $cookie2), $cookieJar->all(), '->all() returns all cookies in the jar'); } public function testClear() { $cookieJar = new CookieJar(); $cookieJar->set($cookie1 = new Cookie('foo', 'bar')); $cookieJar->set($cookie2 = new Cookie('bar', 'foo')); $cookieJar->clear(); $this->assertEquals(array(), $cookieJar->all(), '->clear() expires all cookies'); } public function testUpdateFromResponse() { $response = new Response('', 200, array('Set-Cookie' => 'foo=foo')); $cookieJar = new CookieJar(); $cookieJar->updateFromResponse($response); $this->assertEquals('foo', $cookieJar->get('foo')->getValue(), '->updateFromResponse() updates cookies from a Response objects'); } public function testUpdateFromSetCookie() { $setCookies = array('foo=foo'); $cookieJar = new CookieJar(); $cookieJar->set(new Cookie('bar', 'bar')); $cookieJar->updateFromSetCookie($setCookies); $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $cookieJar->get('foo')); $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $cookieJar->get('bar')); $this->assertEquals('foo', $cookieJar->get('foo')->getValue(), '->updateFromSetCookie() updates cookies from a Set-Cookie header'); $this->assertEquals('bar', $cookieJar->get('bar')->getValue(), '->updateFromSetCookie() keeps existing cookies'); } public function testUpdateFromEmptySetCookie() { $cookieJar = new CookieJar(); $cookieJar->updateFromSetCookie(array('')); $this->assertEquals(array(), $cookieJar->all()); } public function testUpdateFromSetCookieWithMultipleCookies() { $timestamp = time() + 3600; $date = gmdate('D, d M Y H:i:s \G\M\T', $timestamp); $setCookies = array(sprintf('foo=foo; expires=%s; domain=.symfony.com; path=/, bar=bar; domain=.blog.symfony.com, PHPSESSID=id; expires=%s', $date, $date)); $cookieJar = new CookieJar(); $cookieJar->updateFromSetCookie($setCookies); $fooCookie = $cookieJar->get('foo', '/', '.symfony.com'); $barCookie = $cookieJar->get('bar', '/', '.blog.symfony.com'); $phpCookie = $cookieJar->get('PHPSESSID'); $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $fooCookie); $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $barCookie); $this->assertInstanceOf('Symfony\Component\BrowserKit\Cookie', $phpCookie); $this->assertEquals('foo', $fooCookie->getValue()); $this->assertEquals('bar', $barCookie->getValue()); $this->assertEquals('id', $phpCookie->getValue()); $this->assertEquals($timestamp, $fooCookie->getExpiresTime()); $this->assertNull($barCookie->getExpiresTime()); $this->assertEquals($timestamp, $phpCookie->getExpiresTime()); } /** * @dataProvider provideAllValuesValues */ public function testAllValues($uri, $values) { $cookieJar = new CookieJar(); $cookieJar->set($cookie1 = new Cookie('foo_nothing', 'foo')); $cookieJar->set($cookie2 = new Cookie('foo_expired', 'foo', time() - 86400)); $cookieJar->set($cookie3 = new Cookie('foo_path', 'foo', null, '/foo')); $cookieJar->set($cookie4 = new Cookie('foo_domain', 'foo', null, '/', '.example.com')); $cookieJar->set($cookie4 = new Cookie('foo_strict_domain', 'foo', null, '/', '.www4.example.com')); $cookieJar->set($cookie5 = new Cookie('foo_secure', 'foo', null, '/', '', true)); $this->assertEquals($values, array_keys($cookieJar->allValues($uri)), '->allValues() returns the cookie for a given URI'); } public function provideAllValuesValues() { return array( array('http://www.example.com', array('foo_nothing', 'foo_domain')), array('http://www.example.com/', array('foo_nothing', 'foo_domain')), array('http://foo.example.com/', array('foo_nothing', 'foo_domain')), array('http://foo.example1.com/', array('foo_nothing')), array('https://foo.example.com/', array('foo_nothing', 'foo_secure', 'foo_domain')), array('http://www.example.com/foo/bar', array('foo_nothing', 'foo_path', 'foo_domain')), array('http://www4.example.com/', array('foo_nothing', 'foo_domain', 'foo_strict_domain')), ); } public function testEncodedValues() { $cookieJar = new CookieJar(); $cookieJar->set($cookie = new Cookie('foo', 'bar%3Dbaz', null, '/', '', false, true, true)); $this->assertEquals(array('foo' => 'bar=baz'), $cookieJar->allValues('/')); $this->assertEquals(array('foo' => 'bar%3Dbaz'), $cookieJar->allRawValues('/')); } public function testCookieExpireWithSameNameButDifferentPaths() { $cookieJar = new CookieJar(); $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/foo')); $cookieJar->set($cookie2 = new Cookie('foo', 'bar2', null, '/bar')); $cookieJar->expire('foo', '/foo'); $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired'); $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/'))); $this->assertEquals(array(), $cookieJar->allValues('http://example.com/foo')); $this->assertEquals(array('foo' => 'bar2'), $cookieJar->allValues('http://example.com/bar')); } public function testCookieExpireWithNullPaths() { $cookieJar = new CookieJar(); $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/')); $cookieJar->expire('foo', null); $this->assertNull($cookieJar->get('foo'), '->get() returns null if the cookie is expired'); $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/'))); } public function testCookieWithSameNameButDifferentPaths() { $cookieJar = new CookieJar(); $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/foo')); $cookieJar->set($cookie2 = new Cookie('foo', 'bar2', null, '/bar')); $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/'))); $this->assertEquals(array('foo' => 'bar1'), $cookieJar->allValues('http://example.com/foo')); $this->assertEquals(array('foo' => 'bar2'), $cookieJar->allValues('http://example.com/bar')); } public function testCookieWithSameNameButDifferentDomains() { $cookieJar = new CookieJar(); $cookieJar->set($cookie1 = new Cookie('foo', 'bar1', null, '/', 'foo.example.com')); $cookieJar->set($cookie2 = new Cookie('foo', 'bar2', null, '/', 'bar.example.com')); $this->assertEquals(array(), array_keys($cookieJar->allValues('http://example.com/'))); $this->assertEquals(array('foo' => 'bar1'), $cookieJar->allValues('http://foo.example.com/')); $this->assertEquals(array('foo' => 'bar2'), $cookieJar->allValues('http://bar.example.com/')); } public function testCookieGetWithSubdomain() { $cookieJar = new CookieJar(); $cookieJar->set($cookie1 = new Cookie('foo', 'bar', null, '/', '.example.com')); $cookieJar->set($cookie2 = new Cookie('foo1', 'bar', null, '/', 'test.example.com')); $this->assertEquals($cookie1, $cookieJar->get('foo','/','foo.example.com')); $this->assertEquals($cookie1, $cookieJar->get('foo','/','example.com')); $this->assertEquals($cookie2, $cookieJar->get('foo1','/','test.example.com')); } public function testCookieGetWithSubdirectory() { $cookieJar = new CookieJar(); $cookieJar->set($cookie1 = new Cookie('foo', 'bar', null, '/test', '.example.com')); $cookieJar->set($cookie2 = new Cookie('foo1', 'bar1', null, '/', '.example.com')); $this->assertNull($cookieJar->get('foo','/','.example.com')); $this->assertNull($cookieJar->get('foo','/bar','.example.com')); $this->assertEquals($cookie1, $cookieJar->get('foo','/test','example.com')); $this->assertEquals($cookie2, $cookieJar->get('foo1','/','example.com')); $this->assertEquals($cookie2, $cookieJar->get('foo1','/bar','example.com')); } public function testCookieWithWildcardDomain() { $cookieJar = new CookieJar(); $cookieJar->set(new Cookie('foo', 'bar', null, '/', '.example.com')); $this->assertEquals(array('foo' => 'bar'), $cookieJar->allValues('http://www.example.com')); $this->assertEmpty($cookieJar->allValues('http://wwwexample.com')); } } PK!N4ZccAtest/BrowserKit/Symfony/Component/BrowserKit/Tests/ClientTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit\Tests; use Symfony\Component\BrowserKit\Client; use Symfony\Component\BrowserKit\History; use Symfony\Component\BrowserKit\CookieJar; use Symfony\Component\BrowserKit\Request; use Symfony\Component\BrowserKit\Response; class SpecialResponse extends Response { } class TestClient extends Client { protected $nextResponse = null; protected $nextScript = null; public function setNextResponse(Response $response) { $this->nextResponse = $response; } public function setNextScript($script) { $this->nextScript = $script; } protected function doRequest($request) { if (null === $this->nextResponse) { return new Response(); } $response = $this->nextResponse; $this->nextResponse = null; return $response; } protected function filterResponse($response) { if ($response instanceof SpecialResponse) { return new Response($response->getContent(), $response->getStatus(), $response->getHeaders()); } return $response; } protected function getScript($request) { $r = new \ReflectionClass('Symfony\Component\BrowserKit\Response'); $path = $r->getFileName(); return <<nextScript); EOF; } } class ClientTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\BrowserKit\Client::getHistory */ public function testGetHistory() { $client = new TestClient(array(), $history = new History()); $this->assertSame($history, $client->getHistory(), '->getHistory() returns the History'); } /** * @covers Symfony\Component\BrowserKit\Client::getCookieJar */ public function testGetCookieJar() { $client = new TestClient(array(), null, $cookieJar = new CookieJar()); $this->assertSame($cookieJar, $client->getCookieJar(), '->getCookieJar() returns the CookieJar'); } /** * @covers Symfony\Component\BrowserKit\Client::getRequest */ public function testGetRequest() { $client = new TestClient(); $client->request('GET', 'http://example.com/'); $this->assertEquals('http://example.com/', $client->getRequest()->getUri(), '->getCrawler() returns the Request of the last request'); } public function testGetResponse() { $client = new TestClient(); $client->setNextResponse(new Response('foo')); $client->request('GET', 'http://example.com/'); $this->assertEquals('foo', $client->getResponse()->getContent(), '->getCrawler() returns the Response of the last request'); $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getResponse(), '->getCrawler() returns the Response of the last request'); } public function testGetInternalResponse() { $client = new TestClient(); $client->setNextResponse(new SpecialResponse('foo')); $client->request('GET', 'http://example.com/'); $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getInternalResponse()); $this->assertNotInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialResponse', $client->getInternalResponse()); $this->assertInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialResponse', $client->getResponse()); } public function testGetContent() { $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}'; $client = new TestClient(); $client->request('POST', 'http://example.com/jsonrpc', array(), array(), array(), $json); $this->assertEquals($json, $client->getRequest()->getContent()); } /** * @covers Symfony\Component\BrowserKit\Client::getCrawler */ public function testGetCrawler() { $client = new TestClient(); $client->setNextResponse(new Response('foo')); $crawler = $client->request('GET', 'http://example.com/'); $this->assertSame($crawler, $client->getCrawler(), '->getCrawler() returns the Crawler of the last request'); } public function testRequestHttpHeaders() { $client = new TestClient(); $client->request('GET', '/'); $headers = $client->getRequest()->getServer(); $this->assertEquals('localhost', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header'); $client = new TestClient(); $client->request('GET', 'http://www.example.com'); $headers = $client->getRequest()->getServer(); $this->assertEquals('www.example.com', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header'); $client->request('GET', 'https://www.example.com'); $headers = $client->getRequest()->getServer(); $this->assertTrue($headers['HTTPS'], '->request() sets the HTTPS header'); $client = new TestClient(); $client->request('GET', 'http://www.example.com:8080'); $headers = $client->getRequest()->getServer(); $this->assertEquals('www.example.com:8080', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header with port'); } public function testRequestURIConversion() { $client = new TestClient(); $client->request('GET', '/foo'); $this->assertEquals('http://localhost/foo', $client->getRequest()->getUri(), '->request() converts the URI to an absolute one'); $client = new TestClient(); $client->request('GET', 'http://www.example.com'); $this->assertEquals('http://www.example.com', $client->getRequest()->getUri(), '->request() does not change absolute URIs'); $client = new TestClient(); $client->request('GET', 'http://www.example.com/'); $client->request('GET', '/foo'); $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs'); $client = new TestClient(); $client->request('GET', 'http://www.example.com/foo'); $client->request('GET', '#'); $this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #'); $client->request('GET', '#'); $this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #'); $client->request('GET', '#foo'); $this->assertEquals('http://www.example.com/foo#foo', $client->getRequest()->getUri(), '->request() uses the previous request for #'); $client = new TestClient(); $client->request('GET', 'http://www.example.com/foo/'); $client->request('GET', 'bar'); $this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs'); $client = new TestClient(); $client->request('GET', 'http://www.example.com/foo/foobar'); $client->request('GET', 'bar'); $this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs'); } public function testRequestReferer() { $client = new TestClient(); $client->request('GET', 'http://www.example.com/foo/foobar'); $client->request('GET', 'bar'); $server = $client->getRequest()->getServer(); $this->assertEquals('http://www.example.com/foo/foobar', $server['HTTP_REFERER'], '->request() sets the referer'); } public function testRequestHistory() { $client = new TestClient(); $client->request('GET', 'http://www.example.com/foo/foobar'); $client->request('GET', 'bar'); $this->assertEquals('http://www.example.com/foo/bar', $client->getHistory()->current()->getUri(), '->request() updates the History'); $this->assertEquals('http://www.example.com/foo/foobar', $client->getHistory()->back()->getUri(), '->request() updates the History'); } public function testRequestCookies() { $client = new TestClient(); $client->setNextResponse(new Response('foo', 200, array('Set-Cookie' => 'foo=bar'))); $client->request('GET', 'http://www.example.com/foo/foobar'); $this->assertEquals(array('foo' => 'bar'), $client->getCookieJar()->allValues('http://www.example.com/foo/foobar'), '->request() updates the CookieJar'); $client->request('GET', 'bar'); $this->assertEquals(array('foo' => 'bar'), $client->getCookieJar()->allValues('http://www.example.com/foo/foobar'), '->request() updates the CookieJar'); } public function testRequestSecureCookies() { $client = new TestClient(); $client->setNextResponse(new Response('foo', 200, array('Set-Cookie' => 'foo=bar; path=/; secure'))); $client->request('GET', 'https://www.example.com/foo/foobar'); $this->assertTrue($client->getCookieJar()->get('foo', '/', 'www.example.com')->isSecure()); } public function testClick() { $client = new TestClient(); $client->setNextResponse(new Response('foo')); $crawler = $client->request('GET', 'http://www.example.com/foo/foobar'); $client->click($crawler->filter('a')->link()); $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() clicks on links'); } public function testClickForm() { $client = new TestClient(); $client->setNextResponse(new Response('
')); $crawler = $client->request('GET', 'http://www.example.com/foo/foobar'); $client->click($crawler->filter('input')->form()); $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() Form submit forms'); } public function testSubmit() { $client = new TestClient(); $client->setNextResponse(new Response('
')); $crawler = $client->request('GET', 'http://www.example.com/foo/foobar'); $client->submit($crawler->filter('input')->form()); $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms'); } public function testSubmitPreserveAuth() { $client = new TestClient(array('PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar')); $client->setNextResponse(new Response('
')); $crawler = $client->request('GET', 'http://www.example.com/foo/foobar'); $server = $client->getRequest()->getServer(); $this->assertArrayHasKey('PHP_AUTH_USER', $server); $this->assertEquals('foo', $server['PHP_AUTH_USER']); $this->assertArrayHasKey('PHP_AUTH_PW', $server); $this->assertEquals('bar', $server['PHP_AUTH_PW']); $client->submit($crawler->filter('input')->form()); $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms'); $server = $client->getRequest()->getServer(); $this->assertArrayHasKey('PHP_AUTH_USER', $server); $this->assertEquals('foo', $server['PHP_AUTH_USER']); $this->assertArrayHasKey('PHP_AUTH_PW', $server); $this->assertEquals('bar', $server['PHP_AUTH_PW']); } public function testFollowRedirect() { $client = new TestClient(); $client->followRedirects(false); $client->request('GET', 'http://www.example.com/foo/foobar'); try { $client->followRedirect(); $this->fail('->followRedirect() throws a \LogicException if the request was not redirected'); } catch (\Exception $e) { $this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request was not redirected'); } $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected'))); $client->request('GET', 'http://www.example.com/foo/foobar'); $client->followRedirect(); $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any'); $client = new TestClient(); $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected'))); $client->request('GET', 'http://www.example.com/foo/foobar'); $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() automatically follows redirects if followRedirects is true'); $client = new TestClient(); $client->setNextResponse(new Response('', 201, array('Location' => 'http://www.example.com/redirected'))); $client->request('GET', 'http://www.example.com/foo/foobar'); $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->followRedirect() does not follow redirect if HTTP Code is not 30x'); $client = new TestClient(); $client->setNextResponse(new Response('', 201, array('Location' => 'http://www.example.com/redirected'))); $client->followRedirects(false); $client->request('GET', 'http://www.example.com/foo/foobar'); try { $client->followRedirect(); $this->fail('->followRedirect() throws a \LogicException if the request did not respond with 30x HTTP Code'); } catch (\Exception $e) { $this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request did not respond with 30x HTTP Code'); } } public function testFollowRedirectWithMaxRedirects() { $client = new TestClient(); $client->setMaxRedirects(1); $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected'))); $client->request('GET', 'http://www.example.com/foo/foobar'); $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any'); $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected2'))); try { $client->followRedirect(); $this->fail('->followRedirect() throws a \LogicException if the request was redirected and limit of redirections was reached'); } catch (\Exception $e) { $this->assertInstanceof('LogicException', $e, '->followRedirect() throws a \LogicException if the request was redirected and limit of redirections was reached'); } $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected'))); $client->request('GET', 'http://www.example.com/foo/foobar'); $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any'); $client->setNextResponse(new Response('', 302, array('Location' => '/redirected'))); $client->request('GET', 'http://www.example.com/foo/foobar'); $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows relative URLs'); $client = new TestClient(); $client->setNextResponse(new Response('', 302, array('Location' => '//www.example.org/'))); $client->request('GET', 'https://www.example.com/'); $this->assertEquals('https://www.example.org/', $client->getRequest()->getUri(), '->followRedirect() follows protocol-relative URLs'); $client = new TestClient(); $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected'))); $client->request('POST', 'http://www.example.com/foo/foobar', array('name' => 'bar')); $this->assertEquals('get', $client->getRequest()->getMethod(), '->followRedirect() uses a get for 302'); $this->assertEquals(array(), $client->getRequest()->getParameters(), '->followRedirect() does not submit parameters when changing the method'); } public function testFollowRedirectWithCookies() { $client = new TestClient(); $client->followRedirects(false); $client->setNextResponse(new Response('', 302, array( 'Location' => 'http://www.example.com/redirected', 'Set-Cookie' => 'foo=bar', ))); $client->request('GET', 'http://www.example.com/'); $this->assertEquals(array(), $client->getRequest()->getCookies()); $client->followRedirect(); $this->assertEquals(array('foo' => 'bar'), $client->getRequest()->getCookies()); } public function testFollowRedirectWithHeaders() { $headers = array( 'HTTP_HOST' => 'www.example.com', 'HTTP_USER_AGENT' => 'Symfony2 BrowserKit', 'CONTENT_TYPE' => 'application/vnd.custom+xml', 'HTTPS' => false, ); $client = new TestClient(); $client->followRedirects(false); $client->setNextResponse(new Response('', 302, array( 'Location' => 'http://www.example.com/redirected', ))); $client->request('GET', 'http://www.example.com/', array(), array(), array( 'CONTENT_TYPE' => 'application/vnd.custom+xml', )); $this->assertEquals($headers, $client->getRequest()->getServer()); $client->followRedirect(); $headers['HTTP_REFERER'] = 'http://www.example.com/'; $this->assertEquals($headers, $client->getRequest()->getServer()); } public function testFollowRedirectWithPort() { $headers = array( 'HTTP_HOST' => 'www.example.com:8080', 'HTTP_USER_AGENT' => 'Symfony2 BrowserKit', 'HTTPS' => false ); $client = new TestClient(); $client->followRedirects(false); $client->setNextResponse(new Response('', 302, array( 'Location' => 'http://www.example.com:8080/redirected', ))); $client->request('GET', 'http://www.example.com:8080/'); $this->assertEquals($headers, $client->getRequest()->getServer()); } public function testBack() { $client = new TestClient(); $parameters = array('foo' => 'bar'); $files = array('myfile.foo' => 'baz'); $server = array('X_TEST_FOO' => 'bazbar'); $content = 'foobarbaz'; $client->request('GET', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content); $client->request('GET', 'http://www.example.com/foo'); $client->back(); $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->back() goes back in the history'); $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->back() keeps parameters'); $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->back() keeps files'); $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->back() keeps $_SERVER'); $this->assertEquals($content, $client->getRequest()->getContent(), '->back() keeps content'); } public function testForward() { $client = new TestClient(); $parameters = array('foo' => 'bar'); $files = array('myfile.foo' => 'baz'); $server = array('X_TEST_FOO' => 'bazbar'); $content = 'foobarbaz'; $client->request('GET', 'http://www.example.com/foo/foobar'); $client->request('GET', 'http://www.example.com/foo', $parameters, $files, $server, $content); $client->back(); $client->forward(); $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->forward() goes forward in the history'); $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->forward() keeps parameters'); $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->forward() keeps files'); $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->forward() keeps $_SERVER'); $this->assertEquals($content, $client->getRequest()->getContent(), '->forward() keeps content'); } public function testReload() { $client = new TestClient(); $parameters = array('foo' => 'bar'); $files = array('myfile.foo' => 'baz'); $server = array('X_TEST_FOO' => 'bazbar'); $content = 'foobarbaz'; $client->request('GET', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content); $client->reload(); $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->reload() reloads the current page'); $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->reload() keeps parameters'); $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->reload() keeps files'); $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->reload() keeps $_SERVER'); $this->assertEquals($content, $client->getRequest()->getContent(), '->reload() keeps content'); } public function testRestart() { $client = new TestClient(); $client->request('GET', 'http://www.example.com/foo/foobar'); $client->restart(); $this->assertTrue($client->getHistory()->isEmpty(), '->restart() clears the history'); $this->assertEquals(array(), $client->getCookieJar()->all(), '->restart() clears the cookies'); } public function testInsulatedRequests() { $client = new TestClient(); $client->insulate(); $client->setNextScript("new Symfony\Component\BrowserKit\Response('foobar')"); $client->request('GET', 'http://www.example.com/foo/foobar'); $this->assertEquals('foobar', $client->getResponse()->getContent(), '->insulate() process the request in a forked process'); $client->setNextScript("new Symfony\Component\BrowserKit\Response('foobar)"); try { $client->request('GET', 'http://www.example.com/foo/foobar'); $this->fail('->request() throws a \RuntimeException if the script has an error'); } catch (\Exception $e) { $this->assertInstanceof('RuntimeException', $e, '->request() throws a \RuntimeException if the script has an error'); } } public function testGetServerParameter() { $client = new TestClient(); $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST')); $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT')); $this->assertEquals('testvalue', $client->getServerParameter('testkey', 'testvalue')); } public function testSetServerParameter() { $client = new TestClient(); $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST')); $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT')); $client->setServerParameter('HTTP_HOST', 'testhost'); $this->assertEquals('testhost', $client->getServerParameter('HTTP_HOST')); $client->setServerParameter('HTTP_USER_AGENT', 'testua'); $this->assertEquals('testua', $client->getServerParameter('HTTP_USER_AGENT')); } public function testSetServerParameterInRequest() { $client = new TestClient(); $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST')); $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT')); $client->request('GET', 'https://www.example.com/https/www.example.com', array(), array(), array( 'HTTP_HOST' => 'testhost', 'HTTP_USER_AGENT' => 'testua', 'HTTPS' => false, 'NEW_SERVER_KEY' => 'new-server-key-value' )); $this->assertEquals('localhost', $client->getServerParameter('HTTP_HOST')); $this->assertEquals('Symfony2 BrowserKit', $client->getServerParameter('HTTP_USER_AGENT')); $this->assertEquals('http://testhost/https/www.example.com', $client->getRequest()->getUri()); $server = $client->getRequest()->getServer(); $this->assertArrayHasKey('HTTP_USER_AGENT', $server); $this->assertEquals('testua', $server['HTTP_USER_AGENT']); $this->assertArrayHasKey('HTTP_HOST', $server); $this->assertEquals('testhost', $server['HTTP_HOST']); $this->assertArrayHasKey('NEW_SERVER_KEY', $server); $this->assertEquals('new-server-key-value', $server['NEW_SERVER_KEY']); $this->assertArrayHasKey('HTTPS', $server); $this->assertFalse($server['HTTPS']); } } PK!ɹ(RRAtest/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit\Tests; use Symfony\Component\BrowserKit\Cookie; class CookieTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getTestsForToFromString */ public function testToFromString($cookie, $url = null) { $this->assertEquals($cookie, (string) Cookie::fromString($cookie, $url)); } public function getTestsForToFromString() { return array( array('foo=bar; path=/'), array('foo=bar; path=/foo'), array('foo=bar; domain=google.com; path=/'), array('foo=bar; domain=example.com; path=/; secure', 'https://example.com/'), array('foo=bar; path=/; httponly'), array('foo=bar; domain=google.com; path=/foo; secure; httponly', 'https://google.com/'), array('foo=bar=baz; path=/'), array('foo=bar%3Dbaz; path=/'), ); } public function testFromStringIgnoreSecureFlag() { $this->assertFalse(Cookie::fromString('foo=bar; secure')->isSecure()); $this->assertFalse(Cookie::fromString('foo=bar; secure', 'http://example.com/')->isSecure()); } /** * @dataProvider getExpireCookieStrings */ public function testFromStringAcceptsSeveralExpiresDateFormats($cookie) { $this->assertEquals(1596185377, Cookie::fromString($cookie)->getExpiresTime()); } public function getExpireCookieStrings() { return array( array('foo=bar; expires=Fri, 31-Jul-2020 08:49:37 GMT'), array('foo=bar; expires=Fri, 31 Jul 2020 08:49:37 GMT'), array('foo=bar; expires=Fri, 31-07-2020 08:49:37 GMT'), array('foo=bar; expires=Fri, 31-07-20 08:49:37 GMT'), array('foo=bar; expires=Friday, 31-Jul-20 08:49:37 GMT'), array('foo=bar; expires=Fri Jul 31 08:49:37 2020'), array('foo=bar; expires=\'Fri Jul 31 08:49:37 2020\''), array('foo=bar; expires=Friday July 31st 2020, 08:49:37 GMT'), ); } public function testFromStringWithCapitalization() { $this->assertEquals('Foo=Bar; path=/', (string) Cookie::fromString('Foo=Bar')); $this->assertEquals('foo=bar; expires=Fri, 31 Dec 2010 23:59:59 GMT; path=/', (string) Cookie::fromString('foo=bar; Expires=Fri, 31 Dec 2010 23:59:59 GMT')); $this->assertEquals('foo=bar; domain=www.example.org; path=/; httponly', (string) Cookie::fromString('foo=bar; DOMAIN=www.example.org; HttpOnly')); } public function testFromStringWithUrl() { $this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar', 'http://www.example.com/')); $this->assertEquals('foo=bar; domain=www.example.com; path=/foo', (string) Cookie::FromString('foo=bar', 'http://www.example.com/foo/bar')); $this->assertEquals('foo=bar; domain=www.example.com; path=/', (string) Cookie::FromString('foo=bar; path=/', 'http://www.example.com/foo/bar')); $this->assertEquals('foo=bar; domain=www.myotherexample.com; path=/', (string) Cookie::FromString('foo=bar; domain=www.myotherexample.com', 'http://www.example.com/')); } public function testFromStringThrowsAnExceptionIfCookieIsNotValid() { $this->setExpectedException('InvalidArgumentException'); Cookie::FromString('foo'); } public function testFromStringThrowsAnExceptionIfCookieDateIsNotValid() { $this->setExpectedException('InvalidArgumentException'); Cookie::FromString('foo=bar; expires=Flursday July 31st 2020, 08:49:37 GMT'); } public function testFromStringThrowsAnExceptionIfUrlIsNotValid() { $this->setExpectedException('InvalidArgumentException'); Cookie::FromString('foo=bar', 'foobar'); } public function testGetName() { $cookie = new Cookie('foo', 'bar'); $this->assertEquals('foo', $cookie->getName(), '->getName() returns the cookie name'); } public function testGetValue() { $cookie = new Cookie('foo', 'bar'); $this->assertEquals('bar', $cookie->getValue(), '->getValue() returns the cookie value'); $cookie = new Cookie('foo', 'bar%3Dbaz', null, '/', '', false, true, true); // raw value $this->assertEquals('bar=baz', $cookie->getValue(), '->getValue() returns the urldecoded cookie value'); } public function testGetRawValue() { $cookie = new Cookie('foo', 'bar=baz'); // decoded value $this->assertEquals('bar%3Dbaz', $cookie->getRawValue(), '->getRawValue() returns the urlencoded cookie value'); $cookie = new Cookie('foo', 'bar%3Dbaz', null, '/', '', false, true, true); // raw value $this->assertEquals('bar%3Dbaz', $cookie->getRawValue(), '->getRawValue() returns the non-urldecoded cookie value'); } public function testGetPath() { $cookie = new Cookie('foo', 'bar', 0); $this->assertEquals('/', $cookie->getPath(), '->getPath() returns / is no path is defined'); $cookie = new Cookie('foo', 'bar', 0, '/foo'); $this->assertEquals('/foo', $cookie->getPath(), '->getPath() returns the cookie path'); } public function testGetDomain() { $cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com'); $this->assertEquals('foo.com', $cookie->getDomain(), '->getDomain() returns the cookie domain'); } public function testIsSecure() { $cookie = new Cookie('foo', 'bar'); $this->assertFalse($cookie->isSecure(), '->isSecure() returns false if not defined'); $cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com', true); $this->assertTrue($cookie->isSecure(), '->isSecure() returns the cookie secure flag'); } public function testIsHttponly() { $cookie = new Cookie('foo', 'bar'); $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns false if not defined'); $cookie = new Cookie('foo', 'bar', 0, '/', 'foo.com', false, true); $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns the cookie httponly flag'); } public function testGetExpiresTime() { $cookie = new Cookie('foo', 'bar'); $this->assertNull($cookie->getExpiresTime(), '->getExpiresTime() returns the expires time'); $cookie = new Cookie('foo', 'bar', $time = time() - 86400); $this->assertEquals($time, $cookie->getExpiresTime(), '->getExpiresTime() returns the expires time'); } public function testIsExpired() { $cookie = new Cookie('foo', 'bar'); $this->assertFalse($cookie->isExpired(), '->isExpired() returns false when the cookie never expires (null as expires time)'); $cookie = new Cookie('foo', 'bar', time() - 86400); $this->assertTrue($cookie->isExpired(), '->isExpired() returns true when the cookie is expired'); $cookie = new Cookie('foo', 'bar', 0); $this->assertFalse($cookie->isExpired()); } } PK!KBtest/BrowserKit/Symfony/Component/BrowserKit/Tests/HistoryTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit\Tests; use Symfony\Component\BrowserKit\History; use Symfony\Component\BrowserKit\Request; class HistoryTest extends \PHPUnit_Framework_TestCase { public function testAdd() { $history = new History(); $history->add(new Request('http://www.example1.com/', 'get')); $this->assertSame('http://www.example1.com/', $history->current()->getUri(), '->add() adds a request to the history'); $history->add(new Request('http://www.example2.com/', 'get')); $this->assertSame('http://www.example2.com/', $history->current()->getUri(), '->add() adds a request to the history'); $history->add(new Request('http://www.example3.com/', 'get')); $history->back(); $history->add(new Request('http://www.example4.com/', 'get')); $this->assertSame('http://www.example4.com/', $history->current()->getUri(), '->add() adds a request to the history'); $history->back(); $this->assertSame('http://www.example2.com/', $history->current()->getUri(), '->add() adds a request to the history'); } public function testClearIsEmpty() { $history = new History(); $history->add(new Request('http://www.example.com/', 'get')); $this->assertFalse($history->isEmpty(), '->isEmpty() returns false if the history is not empty'); $history->clear(); $this->assertTrue($history->isEmpty(), '->isEmpty() true if the history is empty'); } public function testCurrent() { $history = new History(); try { $history->current(); $this->fail('->current() throws a \LogicException if the history is empty'); } catch (\Exception $e) { $this->assertInstanceof('LogicException', $e, '->current() throws a \LogicException if the history is empty'); } $history->add(new Request('http://www.example.com/', 'get')); $this->assertSame('http://www.example.com/', $history->current()->getUri(), '->current() returns the current request in the history'); } public function testBack() { $history = new History(); $history->add(new Request('http://www.example.com/', 'get')); try { $history->back(); $this->fail('->back() throws a \LogicException if the history is already on the first page'); } catch (\Exception $e) { $this->assertInstanceof('LogicException', $e, '->current() throws a \LogicException if the history is already on the first page'); } $history->add(new Request('http://www.example1.com/', 'get')); $history->back(); $this->assertSame('http://www.example.com/', $history->current()->getUri(), '->back() returns the previous request in the history'); } public function testForward() { $history = new History(); $history->add(new Request('http://www.example.com/', 'get')); $history->add(new Request('http://www.example1.com/', 'get')); try { $history->forward(); $this->fail('->forward() throws a \LogicException if the history is already on the last page'); } catch (\Exception $e) { $this->assertInstanceof('LogicException', $e, '->forward() throws a \LogicException if the history is already on the last page'); } $history->back(); $history->forward(); $this->assertSame('http://www.example1.com/', $history->current()->getUri(), '->forward() returns the next request in the history'); } } PK!{2w  Ctest/BrowserKit/Symfony/Component/BrowserKit/Tests/ResponseTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit\Tests; use Symfony\Component\BrowserKit\Response; class ResponseTest extends \PHPUnit_Framework_TestCase { public function testGetUri() { $response = new Response('foo'); $this->assertEquals('foo', $response->getContent(), '->getContent() returns the content of the response'); } public function testGetStatus() { $response = new Response('foo', 304); $this->assertEquals('304', $response->getStatus(), '->getStatus() returns the status of the response'); } public function testGetHeaders() { $response = new Response('foo', 200, array('foo' => 'bar')); $this->assertEquals(array('foo' => 'bar'), $response->getHeaders(), '->getHeaders() returns the headers of the response'); } public function testGetHeader() { $response = new Response('foo', 200, array( 'Content-Type' => 'text/html', 'Set-Cookie' => array('foo=bar', 'bar=foo'), )); $this->assertEquals('text/html', $response->getHeader('Content-Type'), '->getHeader() returns a header of the response'); $this->assertEquals('text/html', $response->getHeader('content-type'), '->getHeader() returns a header of the response'); $this->assertEquals('text/html', $response->getHeader('content_type'), '->getHeader() returns a header of the response'); $this->assertEquals('foo=bar', $response->getHeader('Set-Cookie'), '->getHeader() returns the first header value'); $this->assertEquals(array('foo=bar', 'bar=foo'), $response->getHeader('Set-Cookie', false), '->getHeader() returns all header values if first is false'); $this->assertNull($response->getHeader('foo'), '->getHeader() returns null if the header is not defined'); $this->assertEquals(array(), $response->getHeader('foo', false), '->getHeader() returns an empty array if the header is not defined and first is set to false'); } public function testMagicToString() { $response = new Response('foo', 304, array('foo' => 'bar')); $this->assertEquals("foo: bar\n\nfoo", $response->__toString(), '->__toString() returns the headers and the content as a string'); } public function testMagicToStringWithMultipleSetCookieHeader() { $headers = array( 'content-type' => 'text/html; charset=utf-8', 'set-cookie' => array('foo=bar', 'bar=foo') ); $expected = 'content-type: text/html; charset=utf-8'."\n"; $expected.= 'set-cookie: foo=bar'."\n"; $expected.= 'set-cookie: bar=foo'."\n\n"; $expected.= 'foo'; $response = new Response('foo', 304, $headers); $this->assertEquals($expected, $response->__toString(), '->__toString() returns the headers and the content as a string'); } } PK!|Btest/BrowserKit/Symfony/Component/BrowserKit/Tests/RequestTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit\Tests; use Symfony\Component\BrowserKit\Request; class RequestTest extends \PHPUnit_Framework_TestCase { public function testGetUri() { $request = new Request('http://www.example.com/', 'get'); $this->assertEquals('http://www.example.com/', $request->getUri(), '->getUri() returns the URI of the request'); } public function testGetMethod() { $request = new Request('http://www.example.com/', 'get'); $this->assertEquals('get', $request->getMethod(), '->getMethod() returns the method of the request'); } public function testGetParameters() { $request = new Request('http://www.example.com/', 'get', array('foo' => 'bar')); $this->assertEquals(array('foo' => 'bar'), $request->getParameters(), '->getParameters() returns the parameters of the request'); } public function testGetFiles() { $request = new Request('http://www.example.com/', 'get', array(), array('foo' => 'bar')); $this->assertEquals(array('foo' => 'bar'), $request->getFiles(), '->getFiles() returns the uploaded files of the request'); } public function testGetCookies() { $request = new Request('http://www.example.com/', 'get', array(), array(), array('foo' => 'bar')); $this->assertEquals(array('foo' => 'bar'), $request->getCookies(), '->getCookies() returns the cookies of the request'); } public function testGetServer() { $request = new Request('http://www.example.com/', 'get', array(), array(), array(), array('foo' => 'bar')); $this->assertEquals(array('foo' => 'bar'), $request->getServer(), '->getServer() returns the server parameters of the request'); } } PK!p6ll=test/BrowserKit/Symfony/Component/BrowserKit/phpunit.xml.distnu[ ./Tests/ ./ ./Resources ./Tests ./vendor PK!w۴Mtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.htmlnu[

PK!xHtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/no-extensionnu[Test PK!l#8Btest/DomCrawler/Symfony/Component/DomCrawler/Tests/CrawlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DomCrawler\Tests; use Symfony\Component\CssSelector\CssSelector; use Symfony\Component\DomCrawler\Crawler; class CrawlerTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $crawler = new Crawler(); $this->assertCount(0, $crawler, '__construct() returns an empty crawler'); $crawler = new Crawler(new \DOMNode()); $this->assertCount(1, $crawler, '__construct() takes a node as a first argument'); } /** * @covers Symfony\Component\DomCrawler\Crawler::add */ public function testAdd() { $crawler = new Crawler(); $crawler->add($this->createDomDocument()); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMDocument'); $crawler = new Crawler(); $crawler->add($this->createNodeList()); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMNodeList'); foreach ($this->createNodeList() as $node) { $list[] = $node; } $crawler = new Crawler(); $crawler->add($list); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from an array of nodes'); $crawler = new Crawler(); $crawler->add($this->createNodeList()->item(0)); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from an \DOMNode'); $crawler = new Crawler(); $crawler->add('Foo'); $this->assertEquals('Foo', $crawler->filterXPath('//body')->text(), '->add() adds nodes from a string'); } /** * @expectedException \InvalidArgumentException */ public function testAddInvalidNode() { $crawler = new Crawler(); $crawler->add(1); } /** * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent */ public function testAddHtmlContent() { $crawler = new Crawler(); $crawler->addHtmlContent('
', 'UTF-8'); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addHtmlContent() adds nodes from an HTML string'); $crawler->addHtmlContent('', 'UTF-8'); $this->assertEquals('http://symfony.com', $crawler->filterXPath('//base')->attr('href'), '->addHtmlContent() adds nodes from an HTML string'); $this->assertEquals('http://symfony.com/contact', $crawler->filterXPath('//a')->link()->getUri(), '->addHtmlContent() adds nodes from an HTML string'); } /** * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent */ public function testAddHtmlContentCharset() { $crawler = new Crawler(); $crawler->addHtmlContent('
Tiếng Việt', 'UTF-8'); $this->assertEquals('Tiếng Việt', $crawler->filterXPath('//div')->text()); } /** * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent */ public function testAddHtmlContentInvalidBaseTag() { $crawler = new Crawler(null, 'http://symfony.com'); $crawler->addHtmlContent('', 'UTF-8'); $this->assertEquals('http://symfony.com/contact', current($crawler->filterXPath('//a')->links())->getUri(), '->addHtmlContent() correctly handles a non-existent base tag href attribute'); } /** * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent */ public function testAddHtmlContentUnsupportedCharset() { $crawler = new Crawler(); $crawler->addHtmlContent(file_get_contents(__DIR__.'/Fixtures/windows-1250.html'), 'Windows-1250'); $this->assertEquals('Žťčýů', $crawler->filterXPath('//p')->text()); } /** * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent */ public function testAddHtmlContentCharsetGbk() { $crawler = new Crawler(); //gbk encode of

中文

$crawler->addHtmlContent(base64_decode('PGh0bWw+PHA+1tDOxDwvcD48L2h0bWw+'), 'gbk'); $this->assertEquals('中文', $crawler->filterXPath('//p')->text()); } /** * @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent */ public function testAddHtmlContentWithErrors() { $internalErrors = libxml_use_internal_errors(true); $crawler = new Crawler(); $crawler->addHtmlContent(<< EOF , 'UTF-8'); $errors = libxml_get_errors(); $this->assertCount(1, $errors); $this->assertEquals("Tag nav invalid\n", $errors[0]->message); libxml_clear_errors(); libxml_use_internal_errors($internalErrors); } /** * @covers Symfony\Component\DomCrawler\Crawler::addXmlContent */ public function testAddXmlContent() { $crawler = new Crawler(); $crawler->addXmlContent('
', 'UTF-8'); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addXmlContent() adds nodes from an XML string'); } /** * @covers Symfony\Component\DomCrawler\Crawler::addXmlContent */ public function testAddXmlContentCharset() { $crawler = new Crawler(); $crawler->addXmlContent('
Tiếng Việt
', 'UTF-8'); $this->assertEquals('Tiếng Việt', $crawler->filterXPath('//div')->text()); } /** * @covers Symfony\Component\DomCrawler\Crawler::addXmlContent */ public function testAddXmlContentWithErrors() { $internalErrors = libxml_use_internal_errors(true); $crawler = new Crawler(); $crawler->addXmlContent(<<
EOF , 'UTF-8'); $this->assertTrue(count(libxml_get_errors()) > 1); libxml_clear_errors(); libxml_use_internal_errors($internalErrors); } /** * @covers Symfony\Component\DomCrawler\Crawler::addContent */ public function testAddContent() { $crawler = new Crawler(); $crawler->addContent('
', 'text/html; charset=UTF-8'); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an HTML string'); $crawler = new Crawler(); $crawler->addContent('
', 'text/html; charset=UTF-8; dir=RTL'); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an HTML string with extended content type'); $crawler = new Crawler(); $crawler->addContent('
'); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() uses text/html as the default type'); $crawler = new Crawler(); $crawler->addContent('
', 'text/xml; charset=UTF-8'); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an XML string'); $crawler = new Crawler(); $crawler->addContent('
', 'text/xml'); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an XML string'); $crawler = new Crawler(); $crawler->addContent('foo bar', 'text/plain'); $this->assertCount(0, $crawler, '->addContent() does nothing if the type is not (x|ht)ml'); $crawler = new Crawler(); $crawler->addContent('中文'); $this->assertEquals('中文', $crawler->filterXPath('//span')->text(), '->addContent() guess wrong charset'); } /** * @covers Symfony\Component\DomCrawler\Crawler::addDocument */ public function testAddDocument() { $crawler = new Crawler(); $crawler->addDocument($this->createDomDocument()); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addDocument() adds nodes from a \DOMDocument'); } /** * @covers Symfony\Component\DomCrawler\Crawler::addNodeList */ public function testAddNodeList() { $crawler = new Crawler(); $crawler->addNodeList($this->createNodeList()); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNodeList() adds nodes from a \DOMNodeList'); } /** * @covers Symfony\Component\DomCrawler\Crawler::addNodes */ public function testAddNodes() { foreach ($this->createNodeList() as $node) { $list[] = $node; } $crawler = new Crawler(); $crawler->addNodes($list); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNodes() adds nodes from an array of nodes'); } /** * @covers Symfony\Component\DomCrawler\Crawler::addNode */ public function testAddNode() { $crawler = new Crawler(); $crawler->addNode($this->createNodeList()->item(0)); $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNode() adds nodes from an \DOMNode'); } public function testClear() { $crawler = new Crawler(new \DOMNode()); $crawler->clear(); $this->assertCount(0, $crawler, '->clear() removes all the nodes from the crawler'); } public function testEq() { $crawler = $this->createTestCrawler()->filterXPath('//li'); $this->assertNotSame($crawler, $crawler->eq(0), '->eq() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->eq() returns a new instance of a crawler'); $this->assertEquals('Two', $crawler->eq(1)->text(), '->eq() returns the nth node of the list'); $this->assertCount(0, $crawler->eq(100), '->eq() returns an empty crawler if the nth node does not exist'); } public function testEach() { $data = $this->createTestCrawler()->filterXPath('//ul[1]/li')->each(function ($node, $i) { return $i.'-'.$node->text(); }); $this->assertEquals(array('0-One', '1-Two', '2-Three'), $data, '->each() executes an anonymous function on each node of the list'); } public function testReduce() { $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li'); $nodes = $crawler->reduce(function ($node, $i) { return $i == 1 ? false : true; }); $this->assertNotSame($nodes, $crawler, '->reduce() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $nodes, '->reduce() returns a new instance of a crawler'); $this->assertCount(2, $nodes, '->reduce() filters the nodes in the list'); } public function testAttr() { $this->assertEquals('first', $this->createTestCrawler()->filterXPath('//li')->attr('class'), '->attr() returns the attribute of the first element of the node list'); try { $this->createTestCrawler()->filterXPath('//ol')->attr('class'); $this->fail('->attr() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->attr() throws an \InvalidArgumentException if the node list is empty'); } } public function testMissingAttrValueIsNull() { $crawler = new Crawler(); $crawler->addContent('
', 'text/html; charset=UTF-8'); $div = $crawler->filterXPath('//div'); $this->assertEquals('sample value', $div->attr('non-empty-attr'), '->attr() reads non-empty attributes correctly'); $this->assertEquals('', $div->attr('empty-attr'), '->attr() reads empty attributes correctly'); $this->assertNull($div->attr('missing-attr'), '->attr() reads missing attributes correctly'); } public function testText() { $this->assertEquals('One', $this->createTestCrawler()->filterXPath('//li')->text(), '->text() returns the node value of the first element of the node list'); try { $this->createTestCrawler()->filterXPath('//ol')->text(); $this->fail('->text() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->text() throws an \InvalidArgumentException if the node list is empty'); } } public function testHtml() { $this->assertEquals('Bar', $this->createTestCrawler()->filterXPath('//a[5]')->html()); $this->assertEquals('' , trim($this->createTestCrawler()->filterXPath('//form[@id="FooFormId"]')->html())); try { $this->createTestCrawler()->filterXPath('//ol')->html(); $this->fail('->html() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->html() throws an \InvalidArgumentException if the node list is empty'); } } public function testExtract() { $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li'); $this->assertEquals(array('One', 'Two', 'Three'), $crawler->extract('_text'), '->extract() returns an array of extracted data from the node list'); $this->assertEquals(array(array('One', 'first'), array('Two', ''), array('Three', '')), $crawler->extract(array('_text', 'class')), '->extract() returns an array of extracted data from the node list'); $this->assertEquals(array(), $this->createTestCrawler()->filterXPath('//ol')->extract('_text'), '->extract() returns an empty array if the node list is empty'); } /** * @covers Symfony\Component\DomCrawler\Crawler::filterXPath */ public function testFilterXPath() { $crawler = $this->createTestCrawler(); $this->assertNotSame($crawler, $crawler->filterXPath('//li'), '->filterXPath() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->filterXPath() returns a new instance of a crawler'); $crawler = $this->createTestCrawler()->filterXPath('//ul'); $this->assertCount(6, $crawler->filterXPath('//li'), '->filterXPath() filters the node list with the XPath expression'); } public function testFilterXPathWithDefaultNamespace() { $crawler = $this->createTestXmlCrawler()->filterXPath('//default:entry/default:id'); $this->assertCount(1, $crawler, '->filterXPath() automatically registers a namespace'); $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text()); } public function testFilterXPathWithCustomDefaultNamespace() { $crawler = $this->createTestXmlCrawler(); $crawler->setDefaultNamespacePrefix('x'); $crawler = $crawler->filterXPath('//x:entry/x:id'); $this->assertCount(1, $crawler, '->filterXPath() lets to override the default namespace prefix'); $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text()); } public function testFilterXPathWithNamespace() { $crawler = $this->createTestXmlCrawler()->filterXPath('//yt:accessControl'); $this->assertCount(2, $crawler, '->filterXPath() automatically registers a namespace'); } public function testFilterXPathWithMultipleNamespaces() { $crawler = $this->createTestXmlCrawler()->filterXPath('//media:group/yt:aspectRatio'); $this->assertCount(1, $crawler, '->filterXPath() automatically registers multiple namespaces'); $this->assertSame('widescreen', $crawler->text()); } public function testFilterXPathWithManuallyRegisteredNamespace() { $crawler = $this->createTestXmlCrawler(); $crawler->registerNamespace('m', 'http://search.yahoo.com/mrss/'); $crawler = $crawler->filterXPath('//m:group/yt:aspectRatio'); $this->assertCount(1, $crawler, '->filterXPath() uses manually registered namespace'); $this->assertSame('widescreen', $crawler->text()); } public function testFilterXPathWithAnUrl() { $crawler = $this->createTestXmlCrawler(); $crawler = $crawler->filterXPath('//media:category[@scheme="http://gdata.youtube.com/schemas/2007/categories.cat"]'); $this->assertCount(1, $crawler); $this->assertSame('Music', $crawler->text()); } /** * @covers Symfony\Component\DomCrawler\Crawler::filter */ public function testFilter() { $crawler = $this->createTestCrawler(); $this->assertNotSame($crawler, $crawler->filter('li'), '->filter() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->filter() returns a new instance of a crawler'); $crawler = $this->createTestCrawler()->filter('ul'); $this->assertCount(6, $crawler->filter('li'), '->filter() filters the node list with the CSS selector'); } public function testFilterWithDefaultNamespace() { $crawler = $this->createTestXmlCrawler()->filter('default|entry default|id'); $this->assertCount(1, $crawler, '->filter() automatically registers namespaces'); $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text()); } public function testFilterWithNamespace() { CssSelector::disableHtmlExtension(); $crawler = $this->createTestXmlCrawler()->filter('yt|accessControl'); $this->assertCount(2, $crawler, '->filter() automatically registers namespaces'); } public function testFilterWithMultipleNamespaces() { CssSelector::disableHtmlExtension(); $crawler = $this->createTestXmlCrawler()->filter('media|group yt|aspectRatio'); $this->assertCount(1, $crawler, '->filter() automatically registers namespaces'); $this->assertSame('widescreen', $crawler->text()); } public function testFilterWithDefaultNamespaceOnly() { $crawler = new Crawler(' http://localhost/foo weekly 0.5 2012-11-16 http://localhost/bar weekly 0.5 2012-11-16 '); $this->assertEquals(2, $crawler->filter('url')->count()); } public function testSelectLink() { $crawler = $this->createTestCrawler(); $this->assertNotSame($crawler, $crawler->selectLink('Foo'), '->selectLink() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->selectLink() returns a new instance of a crawler'); $this->assertCount(1, $crawler->selectLink('Fabien\'s Foo'), '->selectLink() selects links by the node values'); $this->assertCount(1, $crawler->selectLink('Fabien\'s Bar'), '->selectLink() selects links by the alt attribute of a clickable image'); $this->assertCount(2, $crawler->selectLink('Fabien"s Foo'), '->selectLink() selects links by the node values'); $this->assertCount(2, $crawler->selectLink('Fabien"s Bar'), '->selectLink() selects links by the alt attribute of a clickable image'); $this->assertCount(1, $crawler->selectLink('\' Fabien"s Foo'), '->selectLink() selects links by the node values'); $this->assertCount(1, $crawler->selectLink('\' Fabien"s Bar'), '->selectLink() selects links by the alt attribute of a clickable image'); $this->assertCount(4, $crawler->selectLink('Foo'), '->selectLink() selects links by the node values'); $this->assertCount(4, $crawler->selectLink('Bar'), '->selectLink() selects links by the node values'); } public function testSelectButton() { $crawler = $this->createTestCrawler(); $this->assertNotSame($crawler, $crawler->selectButton('FooValue'), '->selectButton() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->selectButton() returns a new instance of a crawler'); $this->assertEquals(1, $crawler->selectButton('FooValue')->count(), '->selectButton() selects buttons'); $this->assertEquals(1, $crawler->selectButton('FooName')->count(), '->selectButton() selects buttons'); $this->assertEquals(1, $crawler->selectButton('FooId')->count(), '->selectButton() selects buttons'); $this->assertEquals(1, $crawler->selectButton('BarValue')->count(), '->selectButton() selects buttons'); $this->assertEquals(1, $crawler->selectButton('BarName')->count(), '->selectButton() selects buttons'); $this->assertEquals(1, $crawler->selectButton('BarId')->count(), '->selectButton() selects buttons'); $this->assertEquals(1, $crawler->selectButton('FooBarValue')->count(), '->selectButton() selects buttons with form attribute too'); $this->assertEquals(1, $crawler->selectButton('FooBarName')->count(), '->selectButton() selects buttons with form attribute too'); } public function testLink() { $crawler = $this->createTestCrawler('http://example.com/bar/')->selectLink('Foo'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Link', $crawler->link(), '->link() returns a Link instance'); $this->assertEquals('POST', $crawler->link('post')->getMethod(), '->link() takes a method as its argument'); $crawler = $this->createTestCrawler('http://example.com/bar')->selectLink('GetLink'); $this->assertEquals('http://example.com/bar?get=param', $crawler->link()->getUri(), '->link() returns a Link instance'); try { $this->createTestCrawler()->filterXPath('//ol')->link(); $this->fail('->link() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->link() throws an \InvalidArgumentException if the node list is empty'); } } public function testLinks() { $crawler = $this->createTestCrawler('http://example.com/bar/')->selectLink('Foo'); $this->assertInternalType('array', $crawler->links(), '->links() returns an array'); $this->assertCount(4, $crawler->links(), '->links() returns an array'); $links = $crawler->links(); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Link', $links[0], '->links() returns an array of Link instances'); $this->assertEquals(array(), $this->createTestCrawler()->filterXPath('//ol')->links(), '->links() returns an empty array if the node selection is empty'); } public function testForm() { $testCrawler = $this->createTestCrawler('http://example.com/bar/'); $crawler = $testCrawler->selectButton('FooValue'); $crawler2 = $testCrawler->selectButton('FooBarValue'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Form', $crawler->form(), '->form() returns a Form instance'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Form', $crawler2->form(), '->form() returns a Form instance'); $this->assertEquals($crawler->form()->getFormNode()->getAttribute('id'), $crawler2->form()->getFormNode()->getAttribute('id'), '->form() works on elements with form attribute'); $this->assertEquals(array('FooName' => 'FooBar', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'), $crawler->form(array('FooName' => 'FooBar'))->getValues(), '->form() takes an array of values to submit as its first argument'); $this->assertEquals(array('FooName' => 'FooValue', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'), $crawler->form()->getValues(), '->getValues() returns correct form values'); $this->assertEquals(array('FooBarName' => 'FooBarValue', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'), $crawler2->form()->getValues(), '->getValues() returns correct form values'); try { $this->createTestCrawler()->filterXPath('//ol')->form(); $this->fail('->form() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->form() throws an \InvalidArgumentException if the node list is empty'); } } public function testLast() { $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li'); $this->assertNotSame($crawler, $crawler->last(), '->last() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->last() returns a new instance of a crawler'); $this->assertEquals('Three', $crawler->last()->text()); } public function testFirst() { $crawler = $this->createTestCrawler()->filterXPath('//li'); $this->assertNotSame($crawler, $crawler->first(), '->first() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->first() returns a new instance of a crawler'); $this->assertEquals('One', $crawler->first()->text()); } public function testSiblings() { $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(1); $this->assertNotSame($crawler, $crawler->siblings(), '->siblings() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->siblings() returns a new instance of a crawler'); $nodes = $crawler->siblings(); $this->assertEquals(2, $nodes->count()); $this->assertEquals('One', $nodes->eq(0)->text()); $this->assertEquals('Three', $nodes->eq(1)->text()); $nodes = $this->createTestCrawler()->filterXPath('//li')->eq(0)->siblings(); $this->assertEquals(2, $nodes->count()); $this->assertEquals('Two', $nodes->eq(0)->text()); $this->assertEquals('Three', $nodes->eq(1)->text()); try { $this->createTestCrawler()->filterXPath('//ol')->siblings(); $this->fail('->siblings() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->siblings() throws an \InvalidArgumentException if the node list is empty'); } } public function testNextAll() { $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(1); $this->assertNotSame($crawler, $crawler->nextAll(), '->nextAll() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->nextAll() returns a new instance of a crawler'); $nodes = $crawler->nextAll(); $this->assertEquals(1, $nodes->count()); $this->assertEquals('Three', $nodes->eq(0)->text()); try { $this->createTestCrawler()->filterXPath('//ol')->nextAll(); $this->fail('->nextAll() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->nextAll() throws an \InvalidArgumentException if the node list is empty'); } } public function testPreviousAll() { $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(2); $this->assertNotSame($crawler, $crawler->previousAll(), '->previousAll() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->previousAll() returns a new instance of a crawler'); $nodes = $crawler->previousAll(); $this->assertEquals(2, $nodes->count()); $this->assertEquals('Two', $nodes->eq(0)->text()); try { $this->createTestCrawler()->filterXPath('//ol')->previousAll(); $this->fail('->previousAll() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->previousAll() throws an \InvalidArgumentException if the node list is empty'); } } public function testChildren() { $crawler = $this->createTestCrawler()->filterXPath('//ul'); $this->assertNotSame($crawler, $crawler->children(), '->children() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->children() returns a new instance of a crawler'); $nodes = $crawler->children(); $this->assertEquals(3, $nodes->count()); $this->assertEquals('One', $nodes->eq(0)->text()); $this->assertEquals('Two', $nodes->eq(1)->text()); $this->assertEquals('Three', $nodes->eq(2)->text()); try { $this->createTestCrawler()->filterXPath('//ol')->children(); $this->fail('->children() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->children() throws an \InvalidArgumentException if the node list is empty'); } try { $crawler = new Crawler('

'); $crawler->filter('p')->children(); $this->assertTrue(true, '->children() does not trigger a notice if the node has no children'); } catch (\PHPUnit_Framework_Error_Notice $e) { $this->fail('->children() does not trigger a notice if the node has no children'); } } public function testParents() { $crawler = $this->createTestCrawler()->filterXPath('//li[1]'); $this->assertNotSame($crawler, $crawler->parents(), '->parents() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->parents() returns a new instance of a crawler'); $nodes = $crawler->parents(); $this->assertEquals(3, $nodes->count()); $nodes = $this->createTestCrawler()->filterXPath('//html')->parents(); $this->assertEquals(0, $nodes->count()); try { $this->createTestCrawler()->filterXPath('//ol')->parents(); $this->fail('->parents() throws an \InvalidArgumentException if the node list is empty'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->parents() throws an \InvalidArgumentException if the node list is empty'); } } public function testBaseTag() { $crawler = new Crawler('
'); $this->assertEquals('http://base.com/link', $crawler->filterXPath('//a')->link()->getUri()); $crawler = new Crawler('', 'https://domain.com'); $this->assertEquals('https://base.com/link', $crawler->filterXPath('//a')->link()->getUri(), ' tag can use a schema-less URL'); $crawler = new Crawler('', 'https://domain.com'); $this->assertEquals('https://domain.com/path/link', $crawler->filterXPath('//a')->link()->getUri(), ' tag can set a path'); } public function createTestCrawler($uri = null) { $dom = new \DOMDocument(); $dom->loadHTML(' Foo Fabien\'s Foo Fabien"s Foo \' Fabien"s Foo Bar    Fabien\'s Bar   Fabien"s Bar \' Fabien"s Bar GetLink
', array('bar' => array('InputFormField', 'bar')), ), array( 'appends the submitted button value but not other submit buttons', ' ', array('foobar' => array('InputFormField', 'foobar')), ), array( 'turns an image input into x and y fields', '', array('bar.x' => array('InputFormField', '0'), 'bar.y' => array('InputFormField', '0')), ), array( 'returns textareas', ' ', array('foo' => array('TextareaFormField', 'foo')), ), array( 'returns inputs', ' ', array('foo' => array('InputFormField', 'foo')), ), array( 'returns checkboxes', ' ', array('foo' => array('ChoiceFormField', 'foo')), ), array( 'returns not-checked checkboxes', ' ', array('foo' => array('ChoiceFormField', false)), ), array( 'returns radio buttons', ' ', array('foo' => array('ChoiceFormField', 'bar')), ), array( 'returns file inputs', ' ', array('foo' => array('FileFormField', array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))), ), ); } public function testGetFormNode() { $dom = new \DOMDocument(); $dom->loadHTML('
'); $form = new Form($dom->getElementsByTagName('input')->item(0), 'http://example.com'); $this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form'); } public function testGetFormNodeFromNamedForm() { $dom = new \DOMDocument(); $dom->loadHTML('
'); $form = new Form($dom->getElementsByTagName('form')->item(0), 'http://example.com'); $this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form'); } public function testGetMethod() { $form = $this->createForm('
'); $this->assertEquals('GET', $form->getMethod(), '->getMethod() returns get if no method is defined'); $form = $this->createForm('
'); $this->assertEquals('POST', $form->getMethod(), '->getMethod() returns the method attribute value of the form'); $form = $this->createForm('
', 'put'); $this->assertEquals('PUT', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided'); $form = $this->createForm('
', 'delete'); $this->assertEquals('DELETE', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided'); $form = $this->createForm('
', 'patch'); $this->assertEquals('PATCH', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided'); } public function testGetSetValue() { $form = $this->createForm('
'); $this->assertEquals('foo', $form['foo']->getValue(), '->offsetGet() returns the value of a form field'); $form['foo'] = 'bar'; $this->assertEquals('bar', $form['foo']->getValue(), '->offsetSet() changes the value of a form field'); try { $form['foobar'] = 'bar'; $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the field does not exist'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the field does not exist'); } try { $form['foobar']; $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the field does not exist'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the field does not exist'); } } public function testSetValueOnMultiValuedFieldsWithMalformedName() { $form = $this->createForm('
'); try { $form['foo[bar'] = 'bar'; $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the name is malformed.'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the name is malformed.'); } } public function testDisableValidation() { $form = $this->createForm('
'); $form->disableValidation(); $form['foo[bar]']->select('foo'); $form['foo[baz]']->select('bar'); $this->assertEquals('foo', $form['foo[bar]']->getValue(), '->disableValidation() disables validation of all ChoiceFormField.'); $this->assertEquals('bar', $form['foo[baz]']->getValue(), '->disableValidation() disables validation of all ChoiceFormField.'); } public function testOffsetUnset() { $form = $this->createForm('
'); unset($form['foo']); $this->assertFalse(isset($form['foo']), '->offsetUnset() removes a field'); } public function testOffsetExists() { $form = $this->createForm('
'); $this->assertTrue(isset($form['foo']), '->offsetExists() return true if the field exists'); $this->assertFalse(isset($form['bar']), '->offsetExists() return false if the field does not exist'); } public function testGetValues() { $form = $this->createForm('
'); $this->assertEquals(array('foo[bar]' => 'foo', 'bar' => 'bar'), $form->getValues(), '->getValues() returns all form field values'); $form = $this->createForm('
'); $this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include not-checked checkboxes'); $form = $this->createForm('
'); $this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include file input fields'); $form = $this->createForm('
'); $this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include disabled fields'); } public function testSetValues() { $form = $this->createForm('
'); $form->setValues(array('foo' => false, 'bar' => 'foo')); $this->assertEquals(array('bar' => 'foo'), $form->getValues(), '->setValues() sets the values of fields'); } public function testMultiselectSetValues() { $form = $this->createForm('
'); $form->setValues(array('multi' => array("foo", "bar"))); $this->assertEquals(array('multi' => array('foo', 'bar')), $form->getValues(), '->setValue() sets the values of select'); } public function testGetPhpValues() { $form = $this->createForm('
'); $this->assertEquals(array('foo' => array('bar' => 'foo'), 'bar' => 'bar'), $form->getPhpValues(), '->getPhpValues() converts keys with [] to arrays'); $form = $this->createForm('
'); $this->assertEquals(array('fo.o' => array('ba.r' => 'foo'), 'ba r' => 'bar'), $form->getPhpValues(), '->getPhpValues() preserves periods and spaces in names'); $form = $this->createForm('
'); $this->assertEquals(array('fo.o' => array('ba.r' => array('foo', 'ba.z' => 'bar'))), $form->getPhpValues(), '->getPhpValues() preserves periods and spaces in names recursively'); } public function testGetFiles() { $form = $this->createForm('
'); $this->assertEquals(array(), $form->getFiles(), '->getFiles() returns an empty array if method is get'); $form = $this->createForm('
'); $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for POST'); $form = $this->createForm('
', 'put'); $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for PUT'); $form = $this->createForm('
', 'delete'); $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for DELETE'); $form = $this->createForm('
', 'patch'); $this->assertEquals(array('foo[bar]' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)), $form->getFiles(), '->getFiles() only returns file fields for PATCH'); $form = $this->createForm('
'); $this->assertEquals(array(), $form->getFiles(), '->getFiles() does not include disabled file fields'); } public function testGetPhpFiles() { $form = $this->createForm('
'); $this->assertEquals(array('foo' => array('bar' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))), $form->getPhpFiles(), '->getPhpFiles() converts keys with [] to arrays'); $form = $this->createForm('
'); $this->assertEquals(array('f.o o' => array('bar' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))), $form->getPhpFiles(), '->getPhpFiles() preserves periods and spaces in names'); $form = $this->createForm('
'); $this->assertEquals(array('f.o o' => array('bar' => array('ba.z' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0), array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)))), $form->getPhpFiles(), '->getPhpFiles() preserves periods and spaces in names recursively'); } /** * @dataProvider provideGetUriValues */ public function testGetUri($message, $form, $values, $uri, $method = null) { $form = $this->createForm($form, $method); $form->setValues($values); $this->assertEquals('http://example.com'.$uri, $form->getUri(), '->getUri() '.$message); } public function testGetBaseUri() { $dom = new \DOMDocument(); $dom->loadHTML('
'); $nodes = $dom->getElementsByTagName('input'); $form = new Form($nodes->item($nodes->length - 1), 'http://www.foo.com/'); $this->assertEquals('http://www.foo.com/foo.php', $form->getUri()); } public function testGetUriWithAnchor() { $form = $this->createForm('
', null, 'http://example.com/id/123'); $this->assertEquals('http://example.com/id/123#foo', $form->getUri()); } public function testGetUriActionAbsolute() { $formHtml='
'; $form = $this->createForm($formHtml); $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); $form = $this->createForm($formHtml, null, 'https://login.foo.com'); $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); $form = $this->createForm($formHtml, null, 'https://login.foo.com/bar/'); $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); // The action URI haven't the same domain Host have an another domain as Host $form = $this->createForm($formHtml, null, 'https://www.foo.com'); $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); $form = $this->createForm($formHtml, null, 'https://www.foo.com/bar/'); $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); } public function testGetUriAbsolute() { $form = $this->createForm('
', null, 'http://localhost/foo/'); $this->assertEquals('http://localhost/foo/foo', $form->getUri(), '->getUri() returns absolute URIs'); $form = $this->createForm('
', null, 'http://localhost/foo/'); $this->assertEquals('http://localhost/foo', $form->getUri(), '->getUri() returns absolute URIs'); } public function testGetUriWithOnlyQueryString() { $form = $this->createForm('
', null, 'http://localhost/foo/bar'); $this->assertEquals('http://localhost/foo/bar?get=param', $form->getUri(), '->getUri() returns absolute URIs only if the host has been defined in the constructor'); } public function testGetUriWithoutAction() { $form = $this->createForm('
', null, 'http://localhost/foo/bar'); $this->assertEquals('http://localhost/foo/bar', $form->getUri(), '->getUri() returns path if no action defined'); } public function provideGetUriValues() { return array( array( 'returns the URI of the form', '
', array(), '/foo' ), array( 'appends the form values if the method is get', '
', array(), '/foo?foo=foo' ), array( 'appends the form values and merges the submitted values', '
', array('foo' => 'bar'), '/foo?foo=bar' ), array( 'does not append values if the method is post', '
', array(), '/foo' ), array( 'does not append values if the method is patch', '
', array(), '/foo', 'PUT' ), array( 'does not append values if the method is delete', '
', array(), '/foo', 'DELETE' ), array( 'does not append values if the method is put', '
', array(), '/foo', 'PATCH' ), array( 'appends the form values to an existing query string', '
', array(), '/foo?bar=bar&foo=foo' ), array( 'returns an empty URI if the action is empty', '
', array(), '/', ), array( 'appends the form values even if the action is empty', '
', array(), '/?foo=foo', ), array( 'chooses the path if the action attribute value is a sharp (#)', '
', array(), '/#', ), ); } public function testHas() { $form = $this->createForm('
'); $this->assertFalse($form->has('foo'), '->has() returns false if a field is not in the form'); $this->assertTrue($form->has('bar'), '->has() returns true if a field is in the form'); } public function testRemove() { $form = $this->createForm('
'); $form->remove('bar'); $this->assertFalse($form->has('bar'), '->remove() removes a field'); } public function testGet() { $form = $this->createForm('
'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Field\\InputFormField', $form->get('bar'), '->get() returns the field object associated with the given name'); try { $form->get('foo'); $this->fail('->get() throws an \InvalidArgumentException if the field does not exist'); } catch (\InvalidArgumentException $e) { $this->assertTrue(true, '->get() throws an \InvalidArgumentException if the field does not exist'); } } public function testAll() { $form = $this->createForm('
'); $fields = $form->all(); $this->assertCount(1, $fields, '->all() return an array of form field objects'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Field\\InputFormField', $fields['bar'], '->all() return an array of form field objects'); } public function testSubmitWithoutAFormButton() { $dom = new \DOMDocument(); $dom->loadHTML('
'); $nodes = $dom->getElementsByTagName('form'); $form = new Form($nodes->item(0), 'http://example.com'); $this->assertSame($nodes->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form'); } /** * @expectedException \InvalidArgumentException */ public function testFormFieldRegistryAddThrowAnExceptionWhenTheNameIsMalformed() { $registry = new FormFieldRegistry(); $registry->add($this->getFormFieldMock('[foo]')); } /** * @expectedException \InvalidArgumentException */ public function testFormFieldRegistryRemoveThrowAnExceptionWhenTheNameIsMalformed() { $registry = new FormFieldRegistry(); $registry->remove('[foo]'); } /** * @expectedException \InvalidArgumentException */ public function testFormFieldRegistryGetThrowAnExceptionWhenTheNameIsMalformed() { $registry = new FormFieldRegistry(); $registry->get('[foo]'); } /** * @expectedException \InvalidArgumentException */ public function testFormFieldRegistryGetThrowAnExceptionWhenTheFieldDoesNotExist() { $registry = new FormFieldRegistry(); $registry->get('foo'); } /** * @expectedException \InvalidArgumentException */ public function testFormFieldRegistrySetThrowAnExceptionWhenTheNameIsMalformed() { $registry = new FormFieldRegistry(); $registry->set('[foo]', null); } /** * @expectedException \InvalidArgumentException */ public function testFormFieldRegistrySetThrowAnExceptionWhenTheFieldDoesNotExist() { $registry = new FormFieldRegistry(); $registry->set('foo', null); } public function testFormFieldRegistryHasReturnsTrueWhenTheFQNExists() { $registry = new FormFieldRegistry(); $registry->add($this->getFormFieldMock('foo[bar]')); $this->assertTrue($registry->has('foo')); $this->assertTrue($registry->has('foo[bar]')); $this->assertFalse($registry->has('bar')); $this->assertFalse($registry->has('foo[foo]')); } public function testFormRegistryFieldsCanBeRemoved() { $registry = new FormFieldRegistry(); $registry->add($this->getFormFieldMock('foo')); $registry->remove('foo'); $this->assertFalse($registry->has('foo')); } public function testFormRegistrySupportsMultivaluedFields() { $registry = new FormFieldRegistry(); $registry->add($this->getFormFieldMock('foo[]')); $registry->add($this->getFormFieldMock('foo[]')); $registry->add($this->getFormFieldMock('bar[5]')); $registry->add($this->getFormFieldMock('bar[]')); $registry->add($this->getFormFieldMock('bar[baz]')); $this->assertEquals( array('foo[0]', 'foo[1]', 'bar[5]', 'bar[6]', 'bar[baz]'), array_keys($registry->all()) ); } public function testFormRegistrySetValues() { $registry = new FormFieldRegistry(); $registry->add($f2 = $this->getFormFieldMock('foo[2]')); $registry->add($f3 = $this->getFormFieldMock('foo[3]')); $registry->add($fbb = $this->getFormFieldMock('foo[bar][baz]')); $f2 ->expects($this->exactly(2)) ->method('setValue') ->with(2) ; $f3 ->expects($this->exactly(2)) ->method('setValue') ->with(3) ; $fbb ->expects($this->exactly(2)) ->method('setValue') ->with('fbb') ; $registry->set('foo[2]', 2); $registry->set('foo[3]', 3); $registry->set('foo[bar][baz]', 'fbb'); $registry->set('foo', array( 2 => 2, 3 => 3, 'bar' => array( 'baz' => 'fbb' ) )); } protected function getFormFieldMock($name, $value = null) { $field = $this ->getMockBuilder('Symfony\\Component\\DomCrawler\\Field\\FormField') ->setMethods(array('getName', 'getValue', 'setValue', 'initialize')) ->disableOriginalConstructor() ->getMock() ; $field ->expects($this->any()) ->method('getName') ->will($this->returnValue($name)) ; $field ->expects($this->any()) ->method('getValue') ->will($this->returnValue($value)) ; return $field; } protected function createForm($form, $method = null, $currentUri = null) { $dom = new \DOMDocument(); $dom->loadHTML(''.$form.''); $nodes = $dom->getElementsByTagName('input'); $xPath = new \DOMXPath($dom); $nodes = $xPath->query('//input | //button'); if (null === $currentUri) { $currentUri = 'http://example.com/'; } return new Form($nodes->item($nodes->length - 1), $currentUri, $method); } protected function createTestHtml5Form() { $dom = new \DOMDocument(); $dom->loadHTML('

Hello form

array( array('ISBN', 'Title', 'Author'), array( array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), ), TableHelper::LAYOUT_DEFAULT, <<
array( array('ISBN', 'Title', 'Author'), array( array('99921-58-10-700', 'Divine Com', 'Dante Alighieri'), array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), ), TableHelper::LAYOUT_DEFAULT, <<
99921-58-10-700 | Divine Com | Dante Alighieri | | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | +----------------------------------+----------------------+-----------------+ TABLE ), ); } public function testRenderMultiByte() { if (!function_exists('mb_strlen')) { $this->markTestSkipped('The "mbstring" extension is not available'); } $table = new TableHelper(); $table ->setHeaders(array('■■')) ->setRows(array(array(1234))) ->setLayout(TableHelper::LAYOUT_DEFAULT) ; $table->render($output = $this->getOutputStream()); $expected = <<
assertEquals($expected, $this->getOutputContent($output)); } protected function getOutputStream() { return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, false); } protected function getOutputContent(StreamOutput $output) { rewind($output->getStream()); return str_replace(PHP_EOL, "\n", stream_get_contents($output->getStream())); } } PK!" UJtest/Console/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tests\Helper; use Symfony\Component\Console\Helper\ProgressHelper; use Symfony\Component\Console\Output\StreamOutput; class ProgressHelperTest extends \PHPUnit_Framework_TestCase { public function testAdvance() { $progress = new ProgressHelper(); $progress->start($output = $this->getOutputStream()); $progress->advance(); rewind($output->getStream()); $this->assertEquals($this->generateOutput(' 1 [->--------------------------]'), stream_get_contents($output->getStream())); } public function testAdvanceWithStep() { $progress = new ProgressHelper(); $progress->start($output = $this->getOutputStream()); $progress->advance(5); rewind($output->getStream()); $this->assertEquals($this->generateOutput(' 5 [----->----------------------]'), stream_get_contents($output->getStream())); } public function testAdvanceMultipleTimes() { $progress = new ProgressHelper(); $progress->start($output = $this->getOutputStream()); $progress->advance(3); $progress->advance(2); rewind($output->getStream()); $this->assertEquals($this->generateOutput(' 3 [--->------------------------]').$this->generateOutput(' 5 [----->----------------------]'), stream_get_contents($output->getStream())); } public function testCustomizations() { $progress = new ProgressHelper(); $progress->setBarWidth(10); $progress->setBarCharacter('_'); $progress->setEmptyBarCharacter(' '); $progress->setProgressCharacter('/'); $progress->setFormat(' %current%/%max% [%bar%] %percent%%'); $progress->start($output = $this->getOutputStream(), 10); $progress->advance(); rewind($output->getStream()); $this->assertEquals($this->generateOutput(' 1/10 [_/ ] 10%'), stream_get_contents($output->getStream())); } public function testPercent() { $progress = new ProgressHelper(); $progress->start($output = $this->getOutputStream(), 50); $progress->display(); $progress->advance(); $progress->advance(); rewind($output->getStream()); $this->assertEquals($this->generateOutput(' 0/50 [>---------------------------] 0%').$this->generateOutput(' 1/50 [>---------------------------] 2%').$this->generateOutput(' 2/50 [=>--------------------------] 4%'), stream_get_contents($output->getStream())); } public function testOverwriteWithShorterLine() { $progress = new ProgressHelper(); $progress->setFormat(' %current%/%max% [%bar%] %percent%%'); $progress->start($output = $this->getOutputStream(), 50); $progress->display(); $progress->advance(); // set shorter format $progress->setFormat(' %current%/%max% [%bar%]'); $progress->advance(); rewind($output->getStream()); $this->assertEquals( $this->generateOutput(' 0/50 [>---------------------------] 0%') . $this->generateOutput(' 1/50 [>---------------------------] 2%') . $this->generateOutput(' 2/50 [=>--------------------------] '), stream_get_contents($output->getStream()) ); } public function testSetCurrentProgress() { $progress = new ProgressHelper(); $progress->start($output = $this->getOutputStream(), 50); $progress->display(); $progress->advance(); $progress->setCurrent(15); $progress->setCurrent(25); rewind($output->getStream()); $this->assertEquals( $this->generateOutput(' 0/50 [>---------------------------] 0%') . $this->generateOutput(' 1/50 [>---------------------------] 2%') . $this->generateOutput(' 15/50 [========>-------------------] 30%') . $this->generateOutput(' 25/50 [==============>-------------] 50%'), stream_get_contents($output->getStream()) ); } /** * @expectedException \LogicException * @expectedExceptionMessage You must start the progress bar */ public function testSetCurrentBeforeStarting() { $progress = new ProgressHelper(); $progress->setCurrent(15); } /** * @expectedException \LogicException * @expectedExceptionMessage You can't regress the progress bar */ public function testRegressProgress() { $progress = new ProgressHelper(); $progress->start($output = $this->getOutputStream(), 50); $progress->setCurrent(15); $progress->setCurrent(10); } public function testRedrawFrequency() { $progress = $this->getMock('Symfony\Component\Console\Helper\ProgressHelper', array('display')); $progress->expects($this->exactly(4)) ->method('display'); $progress->setRedrawFrequency(2); $progress->start($output = $this->getOutputStream(), 6); $progress->setCurrent(1); $progress->advance(2); $progress->advance(2); $progress->advance(1); } public function testMultiByteSupport() { if (!function_exists('mb_strlen') || (false === $encoding = mb_detect_encoding('■'))) { $this->markTestSkipped('The mbstring extension is needed for multi-byte support'); } $progress = new ProgressHelper(); $progress->start($output = $this->getOutputStream()); $progress->setBarCharacter('■'); $progress->advance(3); rewind($output->getStream()); $this->assertEquals($this->generateOutput(' 3 [■■■>------------------------]'), stream_get_contents($output->getStream())); } public function testClear() { $progress = new ProgressHelper(); $progress->start($output = $this->getOutputStream(), 50); $progress->setCurrent(25); $progress->clear(); rewind($output->getStream()); $this->assertEquals( $this->generateOutput(' 25/50 [==============>-------------] 50%') . $this->generateOutput(''), stream_get_contents($output->getStream()) ); } public function testPercentNotHundredBeforeComplete() { $progress = new ProgressHelper(); $progress->start($output = $this->getOutputStream(), 200); $progress->display(); $progress->advance(199); $progress->advance(); rewind($output->getStream()); $this->assertEquals($this->generateOutput(' 0/200 [>---------------------------] 0%').$this->generateOutput(' 199/200 [===========================>] 99%').$this->generateOutput(' 200/200 [============================] 100%'), stream_get_contents($output->getStream())); } protected function getOutputStream() { return new StreamOutput(fopen('php://memory', 'r+', false)); } protected $lastMessagesLength; protected function generateOutput($expected) { $expectedout = $expected; if ($this->lastMessagesLength !== null) { $expectedout = str_pad($expected, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); } $this->lastMessagesLength = strlen($expectedout); return "\x0D".$expectedout; } } PK!K 99Ntest/Console/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tests\Descriptor; use Symfony\Component\Console\Descriptor\TextDescriptor; class TextDescriptorTest extends AbstractDescriptorTest { protected function getDescriptor() { return new TextDescriptor(); } protected function getFormat() { return 'txt'; } } PK!1HDDDRtest/Console/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tests\Descriptor; use Symfony\Component\Console\Descriptor\MarkdownDescriptor; class MarkdownDescriptorTest extends AbstractDescriptorTest { protected function getDescriptor() { return new MarkdownDescriptor(); } protected function getFormat() { return 'md'; } } PK!oW::Ntest/Console/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tests\Descriptor; use Symfony\Component\Console\Descriptor\JsonDescriptor; class JsonDescriptorTest extends AbstractDescriptorTest { protected function getDescriptor() { return new JsonDescriptor(); } protected function getFormat() { return 'json'; } } PK!66Mtest/Console/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tests\Descriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; class XmlDescriptorTest extends AbstractDescriptorTest { protected function getDescriptor() { return new XmlDescriptor(); } protected function getFormat() { return 'xml'; } } PK!ž_J J Ktest/Console/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tests\Descriptor; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication1; use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication2; use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand1; use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand2; /** * @author Jean-François Simon */ class ObjectsProvider { public static function getInputArguments() { return array( 'input_argument_1' => new InputArgument('argument_name', InputArgument::REQUIRED), 'input_argument_2' => new InputArgument('argument_name', InputArgument::IS_ARRAY, 'argument description'), 'input_argument_3' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'default_value'), ); } public static function getInputOptions() { return array( 'input_option_1' => new InputOption('option_name', 'o', InputOption::VALUE_NONE), 'input_option_2' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', 'default_value'), 'input_option_3' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description'), 'input_option_4' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'option description', array()), ); } public static function getInputDefinitions() { return array( 'input_definition_1' => new InputDefinition(), 'input_definition_2' => new InputDefinition(array(new InputArgument('argument_name', InputArgument::REQUIRED))), 'input_definition_3' => new InputDefinition(array(new InputOption('option_name', 'o', InputOption::VALUE_NONE))), 'input_definition_4' => new InputDefinition(array( new InputArgument('argument_name', InputArgument::REQUIRED), new InputOption('option_name', 'o', InputOption::VALUE_NONE), )), ); } public static function getCommands() { return array( 'command_1' => new DescriptorCommand1(), 'command_2' => new DescriptorCommand2(), ); } public static function getApplications() { return array( 'application_1' => new DescriptorApplication1(), 'application_2' => new DescriptorApplication2(), ); } } PK!} Rtest/Console/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tests\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\BufferedOutput; abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase { /** @dataProvider getDescribeInputArgumentTestData */ public function testDescribeInputArgument(InputArgument $argument, $expectedDescription) { $this->assertDescription($expectedDescription, $argument); } /** @dataProvider getDescribeInputOptionTestData */ public function testDescribeInputOption(InputOption $option, $expectedDescription) { $this->assertDescription($expectedDescription, $option); } /** @dataProvider getDescribeInputDefinitionTestData */ public function testDescribeInputDefinition(InputDefinition $definition, $expectedDescription) { $this->assertDescription($expectedDescription, $definition); } /** @dataProvider getDescribeCommandTestData */ public function testDescribeCommand(Command $command, $expectedDescription) { $this->assertDescription($expectedDescription, $command); } /** @dataProvider getDescribeApplicationTestData */ public function testDescribeApplication(Application $application, $expectedDescription) { // Replaces the dynamic placeholders of the command help text with a static version. // The placeholder %command.full_name% includes the script path that is not predictable // and can not be tested against. foreach ($application->all() as $command) { $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp())); } $this->assertDescription($expectedDescription, $application); } public function getDescribeInputArgumentTestData() { return $this->getDescriptionTestData(ObjectsProvider::getInputArguments()); } public function getDescribeInputOptionTestData() { return $this->getDescriptionTestData(ObjectsProvider::getInputOptions()); } public function getDescribeInputDefinitionTestData() { return $this->getDescriptionTestData(ObjectsProvider::getInputDefinitions()); } public function getDescribeCommandTestData() { return $this->getDescriptionTestData(ObjectsProvider::getCommands()); } public function getDescribeApplicationTestData() { return $this->getDescriptionTestData(ObjectsProvider::getApplications()); } abstract protected function getDescriptor(); abstract protected function getFormat(); private function getDescriptionTestData(array $objects) { $data = array(); foreach ($objects as $name => $object) { $description = file_get_contents(sprintf('%s/../Fixtures/%s.%s', __DIR__, $name, $this->getFormat())); $data[] = array($object, $description); } return $data; } private function assertDescription($expectedDescription, $describedObject) { $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); $this->getDescriptor()->describe($output, $describedObject, array('raw_output' => true)); $this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $output->fetch()))); } } PK!?UHii7test/Console/Symfony/Component/Console/phpunit.xml.distnu[ ./Tests/ ./ ./Resources ./Tests ./vendor PK!F1yAATtest/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Tests; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\Options; class OptionsResolverTest extends \PHPUnit_Framework_TestCase { /** * @var OptionsResolver */ private $resolver; protected function setUp() { $this->resolver = new OptionsResolver(); } public function testResolve() { $this->resolver->setDefaults(array( 'one' => '1', 'two' => '2', )); $options = array( 'two' => '20', ); $this->assertEquals(array( 'one' => '1', 'two' => '20', ), $this->resolver->resolve($options)); } public function testResolveLazy() { $this->resolver->setDefaults(array( 'one' => '1', 'two' => function (Options $options) { return '20'; }, )); $this->assertEquals(array( 'one' => '1', 'two' => '20', ), $this->resolver->resolve(array())); } public function testResolveLazyDependencyOnOptional() { $this->resolver->setDefaults(array( 'one' => '1', 'two' => function (Options $options) { return $options['one'].'2'; }, )); $options = array( 'one' => '10', ); $this->assertEquals(array( 'one' => '10', 'two' => '102', ), $this->resolver->resolve($options)); } public function testResolveLazyDependencyOnMissingOptionalWithoutDefault() { $test = $this; $this->resolver->setOptional(array( 'one', )); $this->resolver->setDefaults(array( 'two' => function (Options $options) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertFalse(isset($options['one'])); return '2'; }, )); $options = array( ); $this->assertEquals(array( 'two' => '2', ), $this->resolver->resolve($options)); } public function testResolveLazyDependencyOnOptionalWithoutDefault() { $test = $this; $this->resolver->setOptional(array( 'one', )); $this->resolver->setDefaults(array( 'two' => function (Options $options) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertTrue(isset($options['one'])); return $options['one'].'2'; }, )); $options = array( 'one' => '10', ); $this->assertEquals(array( 'one' => '10', 'two' => '102', ), $this->resolver->resolve($options)); } public function testResolveLazyDependencyOnRequired() { $this->resolver->setRequired(array( 'one', )); $this->resolver->setDefaults(array( 'two' => function (Options $options) { return $options['one'].'2'; }, )); $options = array( 'one' => '10', ); $this->assertEquals(array( 'one' => '10', 'two' => '102', ), $this->resolver->resolve($options)); } public function testResolveLazyReplaceDefaults() { $test = $this; $this->resolver->setDefaults(array( 'one' => function (Options $options) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->fail('Previous closure should not be executed'); }, )); $this->resolver->replaceDefaults(array( 'one' => function (Options $options, $previousValue) { return '1'; }, )); $this->assertEquals(array( 'one' => '1', ), $this->resolver->resolve(array())); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testResolveFailsIfNonExistingOption() { $this->resolver->setDefaults(array( 'one' => '1', )); $this->resolver->setRequired(array( 'two', )); $this->resolver->setOptional(array( 'three', )); $this->resolver->resolve(array( 'foo' => 'bar', )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException */ public function testResolveFailsIfMissingRequiredOption() { $this->resolver->setRequired(array( 'one', )); $this->resolver->setDefaults(array( 'two' => '2', )); $this->resolver->resolve(array( 'two' => '20', )); } public function testResolveSucceedsIfOptionValueAllowed() { $this->resolver->setDefaults(array( 'one' => '1', )); $this->resolver->setAllowedValues(array( 'one' => array('1', 'one'), )); $options = array( 'one' => 'one', ); $this->assertEquals(array( 'one' => 'one', ), $this->resolver->resolve($options)); } public function testResolveSucceedsIfOptionValueAllowed2() { $this->resolver->setDefaults(array( 'one' => '1', 'two' => '2', )); $this->resolver->setAllowedValues(array( 'one' => '1', 'two' => '2', )); $this->resolver->addAllowedValues(array( 'one' => 'one', 'two' => 'two', )); $options = array( 'one' => '1', 'two' => 'two', ); $this->assertEquals(array( 'one' => '1', 'two' => 'two', ), $this->resolver->resolve($options)); } public function testResolveSucceedsIfOptionalWithAllowedValuesNotSet() { $this->resolver->setRequired(array( 'one', )); $this->resolver->setOptional(array( 'two', )); $this->resolver->setAllowedValues(array( 'one' => array('1', 'one'), 'two' => array('2', 'two'), )); $options = array( 'one' => '1', ); $this->assertEquals(array( 'one' => '1', ), $this->resolver->resolve($options)); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testResolveFailsIfOptionValueNotAllowed() { $this->resolver->setDefaults(array( 'one' => '1', )); $this->resolver->setAllowedValues(array( 'one' => array('1', 'one'), )); $this->resolver->resolve(array( 'one' => '2', )); } public function testResolveSucceedsIfOptionTypeAllowed() { $this->resolver->setDefaults(array( 'one' => '1', )); $this->resolver->setAllowedTypes(array( 'one' => 'string', )); $options = array( 'one' => 'one', ); $this->assertEquals(array( 'one' => 'one', ), $this->resolver->resolve($options)); } public function testResolveSucceedsIfOptionTypeAllowedPassArray() { $this->resolver->setDefaults(array( 'one' => '1', )); $this->resolver->setAllowedTypes(array( 'one' => array('string', 'bool'), )); $options = array( 'one' => true, ); $this->assertEquals(array( 'one' => true, ), $this->resolver->resolve($options)); } public function testResolveSucceedsIfOptionTypeAllowedPassObject() { $this->resolver->setDefaults(array( 'one' => '1', )); $this->resolver->setAllowedTypes(array( 'one' => 'object', )); $object = new \stdClass(); $options = array( 'one' => $object, ); $this->assertEquals(array( 'one' => $object, ), $this->resolver->resolve($options)); } public function testResolveSucceedsIfOptionTypeAllowedPassClass() { $this->resolver->setDefaults(array( 'one' => '1', )); $this->resolver->setAllowedTypes(array( 'one' => '\stdClass', )); $object = new \stdClass(); $options = array( 'one' => $object, ); $this->assertEquals(array( 'one' => $object, ), $this->resolver->resolve($options)); } public function testResolveSucceedsIfOptionTypeAllowedAddTypes() { $this->resolver->setDefaults(array( 'one' => '1', 'two' => '2', )); $this->resolver->setAllowedTypes(array( 'one' => 'string', 'two' => 'bool', )); $this->resolver->addAllowedTypes(array( 'one' => 'float', 'two' => 'integer', )); $options = array( 'one' => 1.23, 'two' => false, ); $this->assertEquals(array( 'one' => 1.23, 'two' => false, ), $this->resolver->resolve($options)); } public function testResolveSucceedsIfOptionalWithTypeAndWithoutValue() { $this->resolver->setOptional(array( 'one', 'two', )); $this->resolver->setAllowedTypes(array( 'one' => 'string', 'two' => 'int', )); $options = array( 'two' => 1, ); $this->assertEquals(array( 'two' => 1, ), $this->resolver->resolve($options)); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testResolveFailsIfOptionTypeNotAllowed() { $this->resolver->setDefaults(array( 'one' => '1', )); $this->resolver->setAllowedTypes(array( 'one' => array('string', 'bool'), )); $this->resolver->resolve(array( 'one' => 1.23, )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testResolveFailsIfOptionTypeNotAllowedMultipleOptions() { $this->resolver->setDefaults(array( 'one' => '1', 'two' => '2', )); $this->resolver->setAllowedTypes(array( 'one' => 'string', 'two' => 'bool', )); $this->resolver->resolve(array( 'one' => 'foo', 'two' => 1.23, )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testResolveFailsIfOptionTypeNotAllowedAddTypes() { $this->resolver->setDefaults(array( 'one' => '1', )); $this->resolver->setAllowedTypes(array( 'one' => 'string', )); $this->resolver->addAllowedTypes(array( 'one' => 'bool', )); $this->resolver->resolve(array( 'one' => 1.23, )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testSetRequiredFailsIfDefaultIsPassed() { $this->resolver->setRequired(array( 'one' => '1', )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testSetOptionalFailsIfDefaultIsPassed() { $this->resolver->setOptional(array( 'one' => '1', )); } public function testFluidInterface() { $this->resolver->setDefaults(array('one' => '1')) ->replaceDefaults(array('one' => '2')) ->setAllowedValues(array('one' => array('1', '2'))) ->addAllowedValues(array('one' => array('3'))) ->setRequired(array('two')) ->setOptional(array('three')); $options = array( 'two' => '2', ); $this->assertEquals(array( 'one' => '2', 'two' => '2', ), $this->resolver->resolve($options)); } public function testKnownIfDefaultWasSet() { $this->assertFalse($this->resolver->isKnown('foo')); $this->resolver->setDefaults(array( 'foo' => 'bar', )); $this->assertTrue($this->resolver->isKnown('foo')); } public function testKnownIfRequired() { $this->assertFalse($this->resolver->isKnown('foo')); $this->resolver->setRequired(array( 'foo', )); $this->assertTrue($this->resolver->isKnown('foo')); } public function testKnownIfOptional() { $this->assertFalse($this->resolver->isKnown('foo')); $this->resolver->setOptional(array( 'foo', )); $this->assertTrue($this->resolver->isKnown('foo')); } public function testRequiredIfRequired() { $this->assertFalse($this->resolver->isRequired('foo')); $this->resolver->setRequired(array( 'foo', )); $this->assertTrue($this->resolver->isRequired('foo')); } public function testNotRequiredIfRequiredAndDefaultValue() { $this->assertFalse($this->resolver->isRequired('foo')); $this->resolver->setRequired(array( 'foo', )); $this->resolver->setDefaults(array( 'foo' => 'bar', )); $this->assertFalse($this->resolver->isRequired('foo')); } public function testNormalizersTransformFinalOptions() { $this->resolver->setDefaults(array( 'foo' => 'bar', 'bam' => 'baz', )); $this->resolver->setNormalizers(array( 'foo' => function (Options $options, $value) { return $options['bam'].'['.$value.']'; }, )); $expected = array( 'foo' => 'baz[bar]', 'bam' => 'baz', ); $this->assertEquals($expected, $this->resolver->resolve(array())); $expected = array( 'foo' => 'boo[custom]', 'bam' => 'boo', ); $this->assertEquals($expected, $this->resolver->resolve(array( 'foo' => 'custom', 'bam' => 'boo', ))); } public function testResolveWithoutOptionSucceedsIfRequiredAndDefaultValue() { $this->resolver->setRequired(array( 'foo', )); $this->resolver->setDefaults(array( 'foo' => 'bar', )); $this->assertEquals(array( 'foo' => 'bar' ), $this->resolver->resolve(array())); } public function testResolveWithoutOptionSucceedsIfDefaultValueAndRequired() { $this->resolver->setDefaults(array( 'foo' => 'bar', )); $this->resolver->setRequired(array( 'foo', )); $this->assertEquals(array( 'foo' => 'bar' ), $this->resolver->resolve(array())); } public function testResolveSucceedsIfOptionRequiredAndValueAllowed() { $this->resolver->setRequired(array( 'one', 'two', )); $this->resolver->setAllowedValues(array( 'two' => array('2'), )); $options = array( 'one' => '1', 'two' => '2' ); $this->assertEquals($options, $this->resolver->resolve($options)); } public function testClone() { $this->resolver->setDefaults(array('one' => '1')); $clone = clone $this->resolver; // Changes after cloning don't affect each other $this->resolver->setDefaults(array('two' => '2')); $clone->setDefaults(array('three' => '3')); $this->assertEquals(array( 'one' => '1', 'two' => '2', ), $this->resolver->resolve()); $this->assertEquals(array( 'one' => '1', 'three' => '3', ), $clone->resolve()); } } PK!ν3;3;Ltest/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\OptionsResolver\Tests; use Symfony\Component\OptionsResolver\Options; class OptionsTest extends \PHPUnit_Framework_TestCase { /** * @var Options */ private $options; protected function setUp() { $this->options = new Options(); } public function testArrayAccess() { $this->assertFalse(isset($this->options['foo'])); $this->assertFalse(isset($this->options['bar'])); $this->options['foo'] = 0; $this->options['bar'] = 1; $this->assertTrue(isset($this->options['foo'])); $this->assertTrue(isset($this->options['bar'])); unset($this->options['bar']); $this->assertTrue(isset($this->options['foo'])); $this->assertFalse(isset($this->options['bar'])); $this->assertEquals(0, $this->options['foo']); } public function testCountable() { $this->options->set('foo', 0); $this->options->set('bar', 1); $this->assertCount(2, $this->options); } /** * @expectedException \OutOfBoundsException */ public function testGetNonExisting() { $this->options->get('foo'); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testSetNotSupportedAfterGet() { $this->options->set('foo', 'bar'); $this->options->get('foo'); $this->options->set('foo', 'baz'); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testRemoveNotSupportedAfterGet() { $this->options->set('foo', 'bar'); $this->options->get('foo'); $this->options->remove('foo'); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testSetNormalizerNotSupportedAfterGet() { $this->options->set('foo', 'bar'); $this->options->get('foo'); $this->options->setNormalizer('foo', function () {}); } public function testSetLazyOption() { $test = $this; $this->options->set('foo', function (Options $options) use ($test) { return 'dynamic'; }); $this->assertEquals('dynamic', $this->options->get('foo')); } public function testSetDiscardsPreviousValue() { $test = $this; // defined by superclass $this->options->set('foo', 'bar'); // defined by subclass $this->options->set('foo', function (Options $options, $previousValue) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertNull($previousValue); return 'dynamic'; }); $this->assertEquals('dynamic', $this->options->get('foo')); } public function testOverloadKeepsPreviousValue() { $test = $this; // defined by superclass $this->options->set('foo', 'bar'); // defined by subclass $this->options->overload('foo', function (Options $options, $previousValue) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals('bar', $previousValue); return 'dynamic'; }); $this->assertEquals('dynamic', $this->options->get('foo')); } public function testPreviousValueIsEvaluatedIfLazy() { $test = $this; // defined by superclass $this->options->set('foo', function (Options $options) { return 'bar'; }); // defined by subclass $this->options->overload('foo', function (Options $options, $previousValue) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals('bar', $previousValue); return 'dynamic'; }); $this->assertEquals('dynamic', $this->options->get('foo')); } public function testPreviousValueIsNotEvaluatedIfNoSecondArgument() { $test = $this; // defined by superclass $this->options->set('foo', function (Options $options) use ($test) { $test->fail('Should not be called'); }); // defined by subclass, no $previousValue argument defined! $this->options->overload('foo', function (Options $options) use ($test) { return 'dynamic'; }); $this->assertEquals('dynamic', $this->options->get('foo')); } public function testLazyOptionCanAccessOtherOptions() { $test = $this; $this->options->set('foo', 'bar'); $this->options->set('bam', function (Options $options) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals('bar', $options->get('foo')); return 'dynamic'; }); $this->assertEquals('bar', $this->options->get('foo')); $this->assertEquals('dynamic', $this->options->get('bam')); } public function testLazyOptionCanAccessOtherLazyOptions() { $test = $this; $this->options->set('foo', function (Options $options) { return 'bar'; }); $this->options->set('bam', function (Options $options) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals('bar', $options->get('foo')); return 'dynamic'; }); $this->assertEquals('bar', $this->options->get('foo')); $this->assertEquals('dynamic', $this->options->get('bam')); } public function testNormalizer() { $this->options->set('foo', 'bar'); $this->options->setNormalizer('foo', function () { return 'normalized'; }); $this->assertEquals('normalized', $this->options->get('foo')); } public function testNormalizerReceivesUnnormalizedValue() { $this->options->set('foo', 'bar'); $this->options->setNormalizer('foo', function (Options $options, $value) { return 'normalized['.$value.']'; }); $this->assertEquals('normalized[bar]', $this->options->get('foo')); } public function testNormalizerCanAccessOtherOptions() { $test = $this; $this->options->set('foo', 'bar'); $this->options->set('bam', 'baz'); $this->options->setNormalizer('bam', function (Options $options) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals('bar', $options->get('foo')); return 'normalized'; }); $this->assertEquals('bar', $this->options->get('foo')); $this->assertEquals('normalized', $this->options->get('bam')); } public function testNormalizerCanAccessOtherLazyOptions() { $test = $this; $this->options->set('foo', function (Options $options) { return 'bar'; }); $this->options->set('bam', 'baz'); $this->options->setNormalizer('bam', function (Options $options) use ($test) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals('bar', $options->get('foo')); return 'normalized'; }); $this->assertEquals('bar', $this->options->get('foo')); $this->assertEquals('normalized', $this->options->get('bam')); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testFailForCyclicDependencies() { $this->options->set('foo', function (Options $options) { $options->get('bam'); }); $this->options->set('bam', function (Options $options) { $options->get('foo'); }); $this->options->get('foo'); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testFailForCyclicDependenciesBetweenNormalizers() { $this->options->set('foo', 'bar'); $this->options->set('bam', 'baz'); $this->options->setNormalizer('foo', function (Options $options) { $options->get('bam'); }); $this->options->setNormalizer('bam', function (Options $options) { $options->get('foo'); }); $this->options->get('foo'); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testFailForCyclicDependenciesBetweenNormalizerAndLazyOption() { $this->options->set('foo', function (Options $options) { $options->get('bam'); }); $this->options->set('bam', 'baz'); $this->options->setNormalizer('bam', function (Options $options) { $options->get('foo'); }); $this->options->get('foo'); } public function testAllInvokesEachLazyOptionOnlyOnce() { $test = $this; $i = 1; $this->options->set('foo', function (Options $options) use ($test, &$i) { $test->assertSame(1, $i); ++$i; // Implicitly invoke lazy option for "bam" $options->get('bam'); }); $this->options->set('bam', function (Options $options) use ($test, &$i) { $test->assertSame(2, $i); ++$i; }); $this->options->all(); } public function testAllInvokesEachNormalizerOnlyOnce() { $test = $this; $i = 1; $this->options->set('foo', 'bar'); $this->options->set('bam', 'baz'); $this->options->setNormalizer('foo', function (Options $options) use ($test, &$i) { $test->assertSame(1, $i); ++$i; // Implicitly invoke normalizer for "bam" $options->get('bam'); }); $this->options->setNormalizer('bam', function (Options $options) use ($test, &$i) { $test->assertSame(2, $i); ++$i; }); $this->options->all(); } public function testReplaceClearsAndSets() { $this->options->set('one', '1'); $this->options->replace(array( 'two' => '2', 'three' => function (Options $options) { return '2' === $options['two'] ? '3' : 'foo'; } )); $this->assertEquals(array( 'two' => '2', 'three' => '3', ), $this->options->all()); } public function testClearRemovesAllOptions() { $this->options->set('one', 1); $this->options->set('two', 2); $this->options->clear(); $this->assertEmpty($this->options->all()); } /** * @covers Symfony\Component\OptionsResolver\Options::replace * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testCannotReplaceAfterOptionWasRead() { $this->options->set('one', 1); $this->options->all(); $this->options->replace(array( 'two' => '2', )); } /** * @covers Symfony\Component\OptionsResolver\Options::overload * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testCannotOverloadAfterOptionWasRead() { $this->options->set('one', 1); $this->options->all(); $this->options->overload('one', 2); } /** * @covers Symfony\Component\OptionsResolver\Options::clear * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException */ public function testCannotClearAfterOptionWasRead() { $this->options->set('one', 1); $this->options->all(); $this->options->clear(); } public function testOverloadCannotBeEvaluatedLazilyWithoutExpectedClosureParams() { $this->options->set('foo', 'bar'); $this->options->overload('foo', function () { return 'test'; }); $this->assertNotEquals('test', $this->options->get('foo')); $this->assertTrue(is_callable($this->options->get('foo'))); } public function testOverloadCannotBeEvaluatedLazilyWithoutFirstParamTypeHint() { $this->options->set('foo', 'bar'); $this->options->overload('foo', function ($object) { return 'test'; }); $this->assertNotEquals('test', $this->options->get('foo')); $this->assertTrue(is_callable($this->options->get('foo'))); } public function testOptionsIteration() { $this->options->set('foo', 'bar'); $this->options->set('foo1', 'bar1'); $expectedResult = array('foo' => 'bar', 'foo1' => 'bar1'); $this->assertEquals($expectedResult, iterator_to_array($this->options, true)); } public function testHasWithNullValue() { $this->options->set('foo', null); $this->assertTrue($this->options->has('foo')); } public function testRemoveOptionAndNormalizer() { $this->options->set('foo1', 'bar'); $this->options->setNormalizer('foo1', function (Options $options) { return ''; }); $this->options->set('foo2', 'bar'); $this->options->setNormalizer('foo2', function (Options $options) { return ''; }); $this->options->remove('foo2'); $this->assertEquals(array('foo1' => ''), $this->options->all()); } public function testReplaceOptionAndNormalizer() { $this->options->set('foo1', 'bar'); $this->options->setNormalizer('foo1', function (Options $options) { return ''; }); $this->options->set('foo2', 'bar'); $this->options->setNormalizer('foo2', function (Options $options) { return ''; }); $this->options->replace(array('foo1' => 'new')); $this->assertEquals(array('foo1' => 'new'), $this->options->all()); } public function testClearOptionAndNormalizer() { $this->options->set('foo1', 'bar'); $this->options->setNormalizer('foo1', function (Options $options) { return ''; }); $this->options->set('foo2', 'bar'); $this->options->setNormalizer('foo2', function (Options $options) { return ''; }); $this->options->clear(); $this->assertEmpty($this->options->all()); } public function testNormalizerWithoutCorrespondingOption() { $test = $this; $this->options->setNormalizer('foo', function (Options $options, $previousValue) use ($test) { $test->assertNull($previousValue); return ''; }); $this->assertEquals(array('foo' => ''), $this->options->all()); } } PK!*/AAGtest/OptionsResolver/Symfony/Component/OptionsResolver/phpunit.xml.distnu[ ./Tests/ ./ ./Resources ./Tests PK!iHFtest/Config/Symfony/Component/Config/Tests/Definition/EnumNodeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\EnumNode; class EnumNodeTest extends \PHPUnit_Framework_TestCase { public function testFinalizeValue() { $node = new EnumNode('foo', null, array('foo', 'bar')); $this->assertSame('foo', $node->finalize('foo')); } /** * @expectedException \InvalidArgumentException */ public function testConstructionWithOneValue() { new EnumNode('foo', null, array('foo', 'foo')); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedExceptionMessage The value "foobar" is not allowed for path "foo". Permissible values: "foo", "bar" */ public function testFinalizeWithInvalidValue() { $node = new EnumNode('foo', null, array('foo', 'bar')); $node->finalize('foobar'); } } PK!hͼKtest/Config/Symfony/Component/Config/Tests/Definition/NormalizationTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\Builder\TreeBuilder; class NormalizationTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getEncoderTests */ public function testNormalizeEncoders($denormalized) { $tb = new TreeBuilder(); $tree = $tb ->root('root_name', 'array') ->fixXmlConfig('encoder') ->children() ->node('encoders', 'array') ->useAttributeAsKey('class') ->prototype('array') ->beforeNormalization()->ifString()->then(function ($v) { return array('algorithm' => $v); })->end() ->children() ->node('algorithm', 'scalar')->end() ->end() ->end() ->end() ->end() ->end() ->buildTree() ; $normalized = array( 'encoders' => array( 'foo' => array('algorithm' => 'plaintext'), ), ); $this->assertNormalized($tree, $denormalized, $normalized); } public function getEncoderTests() { $configs = array(); // XML $configs[] = array( 'encoder' => array( array('class' => 'foo', 'algorithm' => 'plaintext'), ), ); // XML when only one element of this type $configs[] = array( 'encoder' => array('class' => 'foo', 'algorithm' => 'plaintext'), ); // YAML/PHP $configs[] = array( 'encoders' => array( array('class' => 'foo', 'algorithm' => 'plaintext'), ), ); // YAML/PHP $configs[] = array( 'encoders' => array( 'foo' => 'plaintext', ), ); // YAML/PHP $configs[] = array( 'encoders' => array( 'foo' => array('algorithm' => 'plaintext'), ), ); return array_map(function ($v) { return array($v); }, $configs); } /** * @dataProvider getAnonymousKeysTests */ public function testAnonymousKeysArray($denormalized) { $tb = new TreeBuilder(); $tree = $tb ->root('root', 'array') ->children() ->node('logout', 'array') ->fixXmlConfig('handler') ->children() ->node('handlers', 'array') ->prototype('scalar')->end() ->end() ->end() ->end() ->end() ->end() ->buildTree() ; $normalized = array('logout' => array('handlers' => array('a', 'b', 'c'))); $this->assertNormalized($tree, $denormalized, $normalized); } public function getAnonymousKeysTests() { $configs = array(); $configs[] = array( 'logout' => array( 'handlers' => array('a', 'b', 'c'), ), ); $configs[] = array( 'logout' => array( 'handler' => array('a', 'b', 'c'), ), ); return array_map(function ($v) { return array($v); }, $configs); } /** * @dataProvider getNumericKeysTests */ public function testNumericKeysAsAttributes($denormalized) { $normalized = array( 'thing' => array(42 => array('foo', 'bar'), 1337 => array('baz', 'qux')), ); $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, $normalized); } public function getNumericKeysTests() { $configs = array(); $configs[] = array( 'thing' => array( 42 => array('foo', 'bar'), 1337 => array('baz', 'qux'), ), ); $configs[] = array( 'thing' => array( array('foo', 'bar', 'id' => 42), array('baz', 'qux', 'id' => 1337), ), ); return array_map(function ($v) { return array($v); }, $configs); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedExceptionMessage The attribute "id" must be set for path "root.thing". */ public function testNonAssociativeArrayThrowsExceptionIfAttributeNotSet() { $denormalized = array( 'thing' => array( array('foo', 'bar'), array('baz', 'qux') ) ); $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, array()); } public function testAssociativeArrayPreserveKeys() { $tb = new TreeBuilder(); $tree = $tb ->root('root', 'array') ->prototype('array') ->children() ->node('foo', 'scalar')->end() ->end() ->end() ->end() ->buildTree() ; $data = array('first' => array('foo' => 'bar')); $this->assertNormalized($tree, $data, $data); } public static function assertNormalized(NodeInterface $tree, $denormalized, $normalized) { self::assertSame($normalized, $tree->normalize($denormalized)); } private function getNumericKeysTestTree() { $tb = new TreeBuilder(); $tree = $tb ->root('root', 'array') ->children() ->node('thing', 'array') ->useAttributeAsKey('id') ->prototype('array') ->prototype('scalar')->end() ->end() ->end() ->end() ->end() ->buildTree() ; return $tree; } } PK!hE --Gtest/Config/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\ScalarNode; class ArrayNodeTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException */ public function testNormalizeThrowsExceptionWhenFalseIsNotAllowed() { $node = new ArrayNode('root'); $node->normalize(false); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedExceptionMessage Unrecognized options "foo" under "root" */ public function testExceptionThrownOnUnrecognizedChild() { $node = new ArrayNode('root'); $node->normalize(array('foo' => 'bar')); } /** * Tests that no exception is thrown for an unrecognized child if the * ignoreExtraKeys option is set to true. * * Related to testExceptionThrownOnUnrecognizedChild */ public function testIgnoreExtraKeysNoException() { $node = new ArrayNode('roo'); $node->setIgnoreExtraKeys(true); $node->normalize(array('foo' => 'bar')); $this->assertTrue(true, 'No exception was thrown when setIgnoreExtraKeys is true'); } /** * @dataProvider getPreNormalizationTests */ public function testPreNormalize($denormalized, $normalized) { $node = new ArrayNode('foo'); $r = new \ReflectionMethod($node, 'preNormalize'); $r->setAccessible(true); $this->assertSame($normalized, $r->invoke($node, $denormalized)); } public function getPreNormalizationTests() { return array( array( array('foo-bar' => 'foo'), array('foo_bar' => 'foo'), ), array( array('foo-bar_moo' => 'foo'), array('foo-bar_moo' => 'foo'), ), array( array('foo-bar' => null, 'foo_bar' => 'foo'), array('foo-bar' => null, 'foo_bar' => 'foo'), ) ); } /** * @dataProvider getZeroNamedNodeExamplesData */ public function testNodeNameCanBeZero($denormalized, $normalized) { $zeroNode = new ArrayNode(0); $zeroNode->addChild(new ScalarNode('name')); $fiveNode = new ArrayNode(5); $fiveNode->addChild(new ScalarNode(0)); $fiveNode->addChild(new ScalarNode('new_key')); $rootNode = new ArrayNode('root'); $rootNode->addChild($zeroNode); $rootNode->addChild($fiveNode); $rootNode->addChild(new ScalarNode('string_key')); $r = new \ReflectionMethod($rootNode, 'normalizeValue'); $r->setAccessible(true); $this->assertSame($normalized, $r->invoke($rootNode, $denormalized)); } public function getZeroNamedNodeExamplesData() { return array( array( array( 0 => array( 'name' => 'something', ), 5 => array( 0 => 'this won\'t work too', 'new_key' => 'some other value', ), 'string_key' => 'just value', ), array( 0 => array ( 'name' => 'something', ), 5 => array ( 0 => 'this won\'t work too', 'new_key' => 'some other value', ), 'string_key' => 'just value', ), ), ); } /** * @dataProvider getPreNormalizedNormalizedOrderedData */ public function testChildrenOrderIsMaintainedOnNormalizeValue($prenormalized, $normalized) { $scalar1 = new ScalarNode('1'); $scalar2 = new ScalarNode('2'); $scalar3 = new ScalarNode('3'); $node = new ArrayNode('foo'); $node->addChild($scalar1); $node->addChild($scalar3); $node->addChild($scalar2); $r = new \ReflectionMethod($node, 'normalizeValue'); $r->setAccessible(true); $this->assertSame($normalized, $r->invoke($node, $prenormalized)); } public function getPreNormalizedNormalizedOrderedData() { return array( array( array('2' => 'two', '1' => 'one', '3' => 'three'), array('2' => 'two', '1' => 'one', '3' => 'three'), ), ); } } PK!Itest/Config/Symfony/Component/Config/Tests/Definition/IntegerNodeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\IntegerNode; class IntegerNodeTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getValidValues */ public function testNormalize($value) { $node = new IntegerNode('test'); $this->assertSame($value, $node->normalize($value)); } public function getValidValues() { return array( array(1798), array(-678), array(0), ); } /** * @dataProvider getInvalidValues * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException */ public function testNormalizeThrowsExceptionOnInvalidValues($value) { $node = new IntegerNode('test'); $node->normalize($value); } public function getInvalidValues() { return array( array(null), array(''), array('foo'), array(true), array(false), array(0.0), array(0.1), array(array()), array(array('foo' => 'bar')), array(new \stdClass()), ); } } PK!&]Gtest/Config/Symfony/Component/Config/Tests/Definition/FloatNodeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\FloatNode; class FloatNodeTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getValidValues */ public function testNormalize($value) { $node = new FloatNode('test'); $this->assertSame($value, $node->normalize($value)); } public function getValidValues() { return array( array(1798.0), array(-678.987), array(12.56E45), array(0.0), // Integer are accepted too, they will be cast array(17), array(-10), array(0) ); } /** * @dataProvider getInvalidValues * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException */ public function testNormalizeThrowsExceptionOnInvalidValues($value) { $node = new FloatNode('test'); $node->normalize($value); } public function getInvalidValues() { return array( array(null), array(''), array('foo'), array(true), array(false), array(array()), array(array('foo' => 'bar')), array(new \stdClass()), ); } } PK!-1Qtest/Config/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Definition\Builder\TreeBuilder; class ExprBuilderTest extends \PHPUnit_Framework_TestCase { public function testAlwaysExpression() { $test = $this->getTestBuilder() ->always($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('new_value', $test); } public function testIfTrueExpression() { $test = $this->getTestBuilder() ->ifTrue() ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('new_value', $test, array('key'=>true)); $test = $this->getTestBuilder() ->ifTrue( function ($v) { return true; }) ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('new_value', $test); $test = $this->getTestBuilder() ->ifTrue( function ($v) { return false; }) ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('value',$test); } public function testIfStringExpression() { $test = $this->getTestBuilder() ->ifString() ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('new_value', $test); $test = $this->getTestBuilder() ->ifString() ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs(45, $test, array('key'=>45)); } public function testIfNullExpression() { $test = $this->getTestBuilder() ->ifNull() ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('new_value', $test, array('key'=>null)); $test = $this->getTestBuilder() ->ifNull() ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('value', $test); } public function testIfArrayExpression() { $test = $this->getTestBuilder() ->ifArray() ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('new_value', $test, array('key'=>array())); $test = $this->getTestBuilder() ->ifArray() ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('value', $test); } public function testIfInArrayExpression() { $test = $this->getTestBuilder() ->ifInArray(array('foo', 'bar', 'value')) ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('new_value', $test); $test = $this->getTestBuilder() ->ifInArray(array('foo', 'bar')) ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('value', $test); } public function testIfNotInArrayExpression() { $test = $this->getTestBuilder() ->ifNotInArray(array('foo', 'bar')) ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('new_value', $test); $test = $this->getTestBuilder() ->ifNotInArray(array('foo', 'bar', 'value_from_config' )) ->then($this->returnClosure('new_value')) ->end(); $this->assertFinalizedValueIs('new_value', $test); } public function testThenEmptyArrayExpression() { $test = $this->getTestBuilder() ->ifString() ->thenEmptyArray() ->end(); $this->assertFinalizedValueIs(array(), $test); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException */ public function testThenInvalid() { $test = $this->getTestBuilder() ->ifString() ->thenInvalid('Invalid value') ->end(); $this->finalizeTestBuilder($test); } public function testThenUnsetExpression() { $test = $this->getTestBuilder() ->ifString() ->thenUnset() ->end(); $this->assertEquals(array(), $this->finalizeTestBuilder($test)); } /** * Create a test treebuilder with a variable node, and init the validation * @return TreeBuilder */ protected function getTestBuilder() { $builder = new TreeBuilder(); return $builder ->root('test') ->children() ->variableNode('key') ->validate() ; } /** * Close the validation process and finalize with the given config * @param TreeBuilder $testBuilder The tree builder to finalize * @param array $config The config you want to use for the finalization, if nothing provided * a simple array('key'=>'value') will be used * @return array The finalized config values */ protected function finalizeTestBuilder($testBuilder, $config = null) { return $testBuilder ->end() ->end() ->end() ->buildTree() ->finalize($config === null ? array('key'=>'value') : $config) ; } /** * Return a closure that will return the given value * @param $val The value that the closure must return * @return Closure */ protected function returnClosure($val) { return function ($v) use ($val) { return $val; }; } /** * Assert that the given test builder, will return the given value * * @param mixed $value The value to test * @param TreeBuilder $treeBuilder The tree builder to finalize * @param mixed $config The config values that new to be finalized */ protected function assertFinalizedValueIs($value, $treeBuilder, $config = null) { $this->assertEquals(array('key'=>$value), $this->finalizeTestBuilder($treeBuilder, $config)); } } PK!<CXtest/Config/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Definition\Builder\EnumNodeDefinition; class EnumNodeDefinitionTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage ->values() must be called with at least two distinct values. */ public function testNoDistinctValues() { $def = new EnumNodeDefinition('foo'); $def->values(array('foo', 'foo')); } /** * @expectedException \RuntimeException * @expectedExceptionMessage You must call ->values() on enum nodes. */ public function testNoValuesPassed() { $def = new EnumNodeDefinition('foo'); $def->getNode(); } public function testGetNode() { $def = new EnumNodeDefinition('foo'); $def->values(array('foo', 'bar')); $node = $def->getNode(); $this->assertEquals(array('foo', 'bar'), $node->getValues()); } } PK!wX Ytest/Config/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition; use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; class ArrayNodeDefinitionTest extends \PHPUnit_Framework_TestCase { public function testAppendingSomeNode() { $parent = new ArrayNodeDefinition('root'); $child = new ScalarNodeDefinition('child'); $parent ->children() ->scalarNode('foo')->end() ->scalarNode('bar')->end() ->end() ->append($child); $this->assertCount(3, $this->getField($parent, 'children')); $this->assertTrue(in_array($child, $this->getField($parent, 'children'))); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException * @dataProvider providePrototypeNodeSpecificCalls */ public function testPrototypeNodeSpecificOption($method, $args) { $node = new ArrayNodeDefinition('root'); call_user_func_array(array($node, $method), $args); $node->getNode(); } public function providePrototypeNodeSpecificCalls() { return array( array('defaultValue', array(array())), array('addDefaultChildrenIfNoneSet', array()), array('requiresAtLeastOneElement', array()), array('useAttributeAsKey', array('foo')) ); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException */ public function testConcreteNodeSpecificOption() { $node = new ArrayNodeDefinition('root'); $node ->addDefaultsIfNotSet() ->prototype('array') ; $node->getNode(); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException */ public function testPrototypeNodesCantHaveADefaultValueWhenUsingDefaultChildren() { $node = new ArrayNodeDefinition('root'); $node ->defaultValue(array()) ->addDefaultChildrenIfNoneSet('foo') ->prototype('array') ; $node->getNode(); } public function testPrototypedArrayNodeDefaultWhenUsingDefaultChildren() { $node = new ArrayNodeDefinition('root'); $node ->addDefaultChildrenIfNoneSet() ->prototype('array') ; $tree = $node->getNode(); $this->assertEquals(array(array()), $tree->getDefaultValue()); } /** * @dataProvider providePrototypedArrayNodeDefaults */ public function testPrototypedArrayNodeDefault($args, $shouldThrowWhenUsingAttrAsKey, $shouldThrowWhenNotUsingAttrAsKey, $defaults) { $node = new ArrayNodeDefinition('root'); $node ->addDefaultChildrenIfNoneSet($args) ->prototype('array') ; try { $tree = $node->getNode(); $this->assertFalse($shouldThrowWhenNotUsingAttrAsKey); $this->assertEquals($defaults, $tree->getDefaultValue()); } catch (InvalidDefinitionException $e) { $this->assertTrue($shouldThrowWhenNotUsingAttrAsKey); } $node = new ArrayNodeDefinition('root'); $node ->useAttributeAsKey('attr') ->addDefaultChildrenIfNoneSet($args) ->prototype('array') ; try { $tree = $node->getNode(); $this->assertFalse($shouldThrowWhenUsingAttrAsKey); $this->assertEquals($defaults, $tree->getDefaultValue()); } catch (InvalidDefinitionException $e) { $this->assertTrue($shouldThrowWhenUsingAttrAsKey); } } public function providePrototypedArrayNodeDefaults() { return array( array(null, true, false, array(array())), array(2, true, false, array(array(), array())), array('2', false, true, array('2' => array())), array('foo', false, true, array('foo' => array())), array(array('foo'), false, true, array('foo' => array())), array(array('foo', 'bar'), false, true, array('foo' => array(), 'bar' => array())), ); } public function testNestedPrototypedArrayNodes() { $node = new ArrayNodeDefinition('root'); $node ->addDefaultChildrenIfNoneSet() ->prototype('array') ->prototype('array') ; $node->getNode(); } public function testEnabledNodeDefaults() { $node = new ArrayNodeDefinition('root'); $node ->canBeEnabled() ->children() ->scalarNode('foo')->defaultValue('bar')->end() ; $this->assertEquals(array('enabled' => false, 'foo' => 'bar'), $node->getNode()->getDefaultValue()); } /** * @dataProvider getEnableableNodeFixtures */ public function testTrueEnableEnabledNode($expected, $config, $message) { $processor = new Processor(); $node = new ArrayNodeDefinition('root'); $node ->canBeEnabled() ->children() ->scalarNode('foo')->defaultValue('bar')->end() ; $this->assertEquals( $expected, $processor->process($node->getNode(), $config), $message ); } public function getEnableableNodeFixtures() { return array( array(array('enabled' => true, 'foo' => 'bar'), array(true), 'true enables an enableable node'), array(array('enabled' => true, 'foo' => 'bar'), array(null), 'null enables an enableable node'), array(array('enabled' => true, 'foo' => 'bar'), array(array('enabled' => true)), 'An enableable node can be enabled'), array(array('enabled' => true, 'foo' => 'baz'), array(array('foo' => 'baz')), 'any configuration enables an enableable node'), array(array('enabled' => false, 'foo' => 'baz'), array(array('foo' => 'baz', 'enabled' => false)), 'An enableable node can be disabled'), array(array('enabled' => false, 'foo' => 'bar'), array(false), 'false disables an enableable node'), ); } protected function getField($object, $field) { $reflection = new \ReflectionProperty($object, $field); $reflection->setAccessible(true); return $reflection->getValue($object); } } PK! Kmޮ Qtest/Config/Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Definition\Builder\NodeBuilder as BaseNodeBuilder; use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition as BaseVariableNodeDefinition; class NodeBuilderTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \RuntimeException */ public function testThrowsAnExceptionWhenTryingToCreateANonRegisteredNodeType() { $builder = new BaseNodeBuilder(); $builder->node('', 'foobar'); } /** * @expectedException \RuntimeException */ public function testThrowsAnExceptionWhenTheNodeClassIsNotFound() { $builder = new BaseNodeBuilder(); $builder ->setNodeClass('noclasstype', '\\foo\\bar\\noclass') ->node('', 'noclasstype'); } public function testAddingANewNodeType() { $class = __NAMESPACE__.'\\SomeNodeDefinition'; $builder = new BaseNodeBuilder(); $node = $builder ->setNodeClass('newtype', $class) ->node('', 'newtype'); $this->assertInstanceOf($class, $node); } public function testOverridingAnExistingNodeType() { $class = __NAMESPACE__.'\\SomeNodeDefinition'; $builder = new BaseNodeBuilder(); $node = $builder ->setNodeClass('variable', $class) ->node('', 'variable'); $this->assertInstanceOf($class, $node); } public function testNodeTypesAreNotCaseSensitive() { $builder = new BaseNodeBuilder(); $node1 = $builder->node('', 'VaRiAbLe'); $node2 = $builder->node('', 'variable'); $this->assertInstanceOf(get_class($node1), $node2); $builder->setNodeClass('CuStOm', __NAMESPACE__.'\\SomeNodeDefinition'); $node1 = $builder->node('', 'CUSTOM'); $node2 = $builder->node('', 'custom'); $this->assertInstanceOf(get_class($node1), $node2); } public function testNumericNodeCreation() { $builder = new NodeBuilder(); $node = $builder->integerNode('foo')->min(3)->max(5); $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition', $node); $node = $builder->floatNode('bar')->min(3.0)->max(5.0); $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\FloatNodeDefinition', $node); } } class SomeNodeDefinition extends BaseVariableNodeDefinition { } PK!Qtest/Config/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder as CustomNodeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\NodeBuilder; require __DIR__.'/../../Fixtures/Builder/NodeBuilder.php'; require __DIR__.'/../../Fixtures/Builder/BarNodeDefinition.php'; require __DIR__.'/../../Fixtures/Builder/VariableNodeDefinition.php'; class TreeBuilderTest extends \PHPUnit_Framework_TestCase { public function testUsingACustomNodeBuilder() { $builder = new TreeBuilder(); $root = $builder->root('custom', 'array', new CustomNodeBuilder()); $nodeBuilder = $root->children(); $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder', $nodeBuilder); $nodeBuilder = $nodeBuilder->arrayNode('deeper')->children(); $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder', $nodeBuilder); } public function testOverrideABuiltInNodeType() { $builder = new TreeBuilder(); $root = $builder->root('override', 'array', new CustomNodeBuilder()); $definition = $root->children()->variableNode('variable'); $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\VariableNodeDefinition', $definition); } public function testAddANodeType() { $builder = new TreeBuilder(); $root = $builder->root('override', 'array', new CustomNodeBuilder()); $definition = $root->children()->barNode('variable'); $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\BarNodeDefinition', $definition); } public function testCreateABuiltInNodeTypeWithACustomNodeBuilder() { $builder = new TreeBuilder(); $root = $builder->root('builtin', 'array', new CustomNodeBuilder()); $definition = $root->children()->booleanNode('boolean'); $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition', $definition); } public function testPrototypedArrayNodeUseTheCustomNodeBuilder() { $builder = new TreeBuilder(); $root = $builder->root('override', 'array', new CustomNodeBuilder()); $root->prototype('bar')->end(); } public function testAnExtendedNodeBuilderGetsPropagatedToTheChildren() { $builder = new TreeBuilder(); $builder->root('propagation') ->children() ->setNodeClass('extended', 'Symfony\Component\Config\Tests\Definition\Builder\VariableNodeDefinition') ->node('foo', 'extended')->end() ->arrayNode('child') ->children() ->node('foo', 'extended') ->end() ->end() ->end() ->end(); } public function testDefinitionInfoGetsTransferredToNode() { $builder = new TreeBuilder(); $builder->root('test')->info('root info') ->children() ->node('child', 'variable')->info('child info')->defaultValue('default') ->end() ->end(); $tree = $builder->buildTree(); $children = $tree->getChildren(); $this->assertEquals('root info', $tree->getInfo()); $this->assertEquals('child info', $children['child']->getInfo()); } public function testDefinitionExampleGetsTransferredToNode() { $builder = new TreeBuilder(); $builder->root('test') ->example(array('key' => 'value')) ->children() ->node('child', 'variable')->info('child info')->defaultValue('default')->example('example') ->end() ->end(); $tree = $builder->buildTree(); $children = $tree->getChildren(); $this->assertTrue(is_array($tree->getExample())); $this->assertEquals('example', $children['child']->getExample()); } } PK!Ej~j j [test/Config/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition as NumericNodeDefinition; use Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition; use Symfony\Component\Config\Definition\Builder\FloatNodeDefinition; class NumericNodeDefinitionTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage You cannot define a min(4) as you already have a max(3) */ public function testIncoherentMinAssertion() { $def = new NumericNodeDefinition('foo'); $def->max(3)->min(4); } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage You cannot define a max(2) as you already have a min(3) */ public function testIncoherentMaxAssertion() { $node = new NumericNodeDefinition('foo'); $node->min(3)->max(2); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedExceptionMessage The value 4 is too small for path "foo". Should be greater than or equal to 5 */ public function testIntegerMinAssertion() { $def = new IntegerNodeDefinition('foo'); $def->min(5)->getNode()->finalize(4); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedExceptionMessage The value 4 is too big for path "foo". Should be less than or equal to 3 */ public function testIntegerMaxAssertion() { $def = new IntegerNodeDefinition('foo'); $def->max(3)->getNode()->finalize(4); } public function testIntegerValidMinMaxAssertion() { $def = new IntegerNodeDefinition('foo'); $node = $def->min(3)->max(7)->getNode(); $this->assertEquals(4, $node->finalize(4)); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedExceptionMessage The value 400 is too small for path "foo". Should be greater than or equal to 500 */ public function testFloatMinAssertion() { $def = new FloatNodeDefinition('foo'); $def->min(5E2)->getNode()->finalize(4e2); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedExceptionMessage The value 4.3 is too big for path "foo". Should be less than or equal to 0.3 */ public function testFloatMaxAssertion() { $def = new FloatNodeDefinition('foo'); $def->max(0.3)->getNode()->finalize(4.3); } public function testFloatValidMinMaxAssertion() { $def = new FloatNodeDefinition('foo'); $node = $def->min(3.0)->max(7e2)->getNode(); $this->assertEquals(4.5, $node->finalize(4.5)); } } PK!jO灃Htest/Config/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\ScalarNode; class ScalarNodeTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getValidValues */ public function testNormalize($value) { $node = new ScalarNode('test'); $this->assertSame($value, $node->normalize($value)); } public function getValidValues() { return array( array(false), array(true), array(null), array(''), array('foo'), array(0), array(1), array(0.0), array(0.1), ); } /** * @dataProvider getInvalidValues * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException */ public function testNormalizeThrowsExceptionOnInvalidValues($value) { $node = new ScalarNode('test'); $node->normalize($value); } public function getInvalidValues() { return array( array(array()), array(array('foo' => 'bar')), array(new \stdClass()), ); } } PK!yXtest/Config/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Dumper; use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper; use Symfony\Component\Config\Tests\Fixtures\Configuration\ExampleConfiguration; class YamlReferenceDumperTest extends \PHPUnit_Framework_TestCase { public function testDumper() { $configuration = new ExampleConfiguration(); $dumper = new YamlReferenceDumper(); $this->markTestIncomplete('The Yaml Dumper currently does not support prototyped arrays'); $this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration)); } private function getConfigurationAsString() { return << * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Dumper; use Symfony\Component\Config\Definition\Dumper\XmlReferenceDumper; use Symfony\Component\Config\Tests\Fixtures\Configuration\ExampleConfiguration; class XmlReferenceDumperTest extends \PHPUnit_Framework_TestCase { public function testDumper() { $configuration = new ExampleConfiguration(); $dumper = new XmlReferenceDumper(); $this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration)); } public function testNamespaceDumper() { $configuration = new ExampleConfiguration(); $dumper = new XmlReferenceDumper(); $this->assertEquals(str_replace('http://example.org/schema/dic/acme_root', 'http://symfony.com/schema/dic/symfony', $this->getConfigurationAsString()), $dumper->dump($configuration, 'http://symfony.com/schema/dic/symfony')); } private function getConfigurationAsString() { return << scalar value EOL; } } PK!D99Ctest/Config/Symfony/Component/Config/Tests/Definition/MergeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\Builder\TreeBuilder; class MergeTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException */ public function testForbiddenOverwrite() { $tb = new TreeBuilder(); $tree = $tb ->root('root', 'array') ->children() ->node('foo', 'scalar') ->cannotBeOverwritten() ->end() ->end() ->end() ->buildTree() ; $a = array( 'foo' => 'bar', ); $b = array( 'foo' => 'moo', ); $tree->merge($a, $b); } public function testUnsetKey() { $tb = new TreeBuilder(); $tree = $tb ->root('root', 'array') ->children() ->node('foo', 'scalar')->end() ->node('bar', 'scalar')->end() ->node('unsettable', 'array') ->canBeUnset() ->children() ->node('foo', 'scalar')->end() ->node('bar', 'scalar')->end() ->end() ->end() ->node('unsetted', 'array') ->canBeUnset() ->prototype('scalar')->end() ->end() ->end() ->end() ->buildTree() ; $a = array( 'foo' => 'bar', 'unsettable' => array( 'foo' => 'a', 'bar' => 'b', ), 'unsetted' => false, ); $b = array( 'foo' => 'moo', 'bar' => 'b', 'unsettable' => false, 'unsetted' => array('a', 'b'), ); $this->assertEquals(array( 'foo' => 'moo', 'bar' => 'b', 'unsettable' => false, 'unsetted' => array('a', 'b'), ), $tree->merge($a, $b)); } /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException */ public function testDoesNotAllowNewKeysInSubsequentConfigs() { $tb = new TreeBuilder(); $tree = $tb ->root('config', 'array') ->children() ->node('test', 'array') ->disallowNewKeysInSubsequentConfigs() ->useAttributeAsKey('key') ->prototype('array') ->children() ->node('value', 'scalar')->end() ->end() ->end() ->end() ->end() ->end() ->buildTree(); $a = array( 'test' => array( 'a' => array('value' => 'foo') ) ); $b = array( 'test' => array( 'b' => array('value' => 'foo') ) ); $tree->merge($a, $b); } public function testPerformsNoDeepMerging() { $tb = new TreeBuilder(); $tree = $tb ->root('config', 'array') ->children() ->node('no_deep_merging', 'array') ->performNoDeepMerging() ->children() ->node('foo', 'scalar')->end() ->node('bar', 'scalar')->end() ->end() ->end() ->end() ->end() ->buildTree() ; $a = array( 'no_deep_merging' => array( 'foo' => 'a', 'bar' => 'b', ), ); $b = array( 'no_deep_merging' => array( 'c' => 'd', ) ); $this->assertEquals(array( 'no_deep_merging' => array( 'c' => 'd', ) ), $tree->merge($a, $b)); } public function testPrototypeWithoutAKeyAttribute() { $tb = new TreeBuilder(); $tree = $tb ->root('config', 'array') ->children() ->arrayNode('append_elements') ->prototype('scalar')->end() ->end() ->end() ->end() ->buildTree() ; $a = array( 'append_elements' => array('a', 'b'), ); $b = array( 'append_elements' => array('c', 'd'), ); $this->assertEquals(array('append_elements' => array('a', 'b', 'c', 'd')), $tree->merge($a, $b)); } } PK!ARRJtest/Config/Symfony/Component/Config/Tests/Definition/FinalizationTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Config\Definition\NodeInterface; class FinalizationTest extends \PHPUnit_Framework_TestCase { public function testUnsetKeyWithDeepHierarchy() { $tb = new TreeBuilder(); $tree = $tb ->root('config', 'array') ->children() ->node('level1', 'array') ->canBeUnset() ->children() ->node('level2', 'array') ->canBeUnset() ->children() ->node('somevalue', 'scalar')->end() ->node('anothervalue', 'scalar')->end() ->end() ->end() ->node('level1_scalar', 'scalar')->end() ->end() ->end() ->end() ->end() ->buildTree() ; $a = array( 'level1' => array( 'level2' => array( 'somevalue' => 'foo', 'anothervalue' => 'bar', ), 'level1_scalar' => 'foo', ), ); $b = array( 'level1' => array( 'level2' => false, ), ); $this->assertEquals(array( 'level1' => array( 'level1_scalar' => 'foo', ), ), $this->process($tree, array($a, $b))); } protected function process(NodeInterface $tree, array $configs) { $processor = new Processor(); return $processor->process($tree, $configs); } } PK!{Itest/Config/Symfony/Component/Config/Tests/Definition/BooleanNodeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\BooleanNode; class BooleanNodeTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getValidValues */ public function testNormalize($value) { $node = new BooleanNode('test'); $this->assertSame($value, $node->normalize($value)); } public function getValidValues() { return array( array(false), array(true), ); } /** * @dataProvider getInvalidValues * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException */ public function testNormalizeThrowsExceptionOnInvalidValues($value) { $node = new BooleanNode('test'); $node->normalize($value); } public function getInvalidValues() { return array( array(null), array(''), array('foo'), array(0), array(1), array(0.0), array(0.1), array(array()), array(array('foo' => 'bar')), array(new \stdClass()), ); } } PK!%JbxQtest/Config/Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition; use Symfony\Component\Config\Definition\PrototypedArrayNode; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\ScalarNode; class PrototypedArrayNodeTest extends \PHPUnit_Framework_TestCase { public function testGetDefaultValueReturnsAnEmptyArrayForPrototypes() { $node = new PrototypedArrayNode('root'); $prototype = new ArrayNode(null, $node); $node->setPrototype($prototype); $this->assertEmpty($node->getDefaultValue()); } public function testGetDefaultValueReturnsDefaultValueForPrototypes() { $node = new PrototypedArrayNode('root'); $prototype = new ArrayNode(null, $node); $node->setPrototype($prototype); $node->setDefaultValue(array('test')); $this->assertEquals(array('test'), $node->getDefaultValue()); } // a remapped key (e.g. "mapping" -> "mappings") should be unset after being used public function testRemappedKeysAreUnset() { $node = new ArrayNode('root'); $mappingsNode = new PrototypedArrayNode('mappings'); $node->addChild($mappingsNode); // each item under mappings is just a scalar $prototype = new ScalarNode(null, $mappingsNode); $mappingsNode->setPrototype($prototype); $remappings = array(); $remappings[] = array('mapping', 'mappings'); $node->setXmlRemappings($remappings); $normalized = $node->normalize(array('mapping' => array('foo', 'bar'))); $this->assertEquals(array('mappings' => array('foo', 'bar')), $normalized); } /** * Tests that when a key attribute is mapped, that key is removed from the array: * * * * * The above should finally be mapped to an array that looks like this * (because "id" is the key attribute). * * array( * 'things' => array( * 'option1' => 'foo', * 'option2' => 'bar', * ) * ) */ public function testMappedAttributeKeyIsRemoved() { $node = new PrototypedArrayNode('root'); $node->setKeyAttribute('id', true); // each item under the root is an array, with one scalar item $prototype = new ArrayNode(null, $node); $prototype->addChild(new ScalarNode('foo')); $node->setPrototype($prototype); $children = array(); $children[] = array('id' => 'item_name', 'foo' => 'bar'); $normalized = $node->normalize($children); $expected = array(); $expected['item_name'] = array('foo' => 'bar'); $this->assertEquals($expected, $normalized); } /** * Tests the opposite of the testMappedAttributeKeyIsRemoved because * the removal can be toggled with an option. */ public function testMappedAttributeKeyNotRemoved() { $node = new PrototypedArrayNode('root'); $node->setKeyAttribute('id', false); // each item under the root is an array, with two scalar items $prototype = new ArrayNode(null, $node); $prototype->addChild(new ScalarNode('foo')); $prototype->addChild(new ScalarNode('id')); // the key attribute will remain $node->setPrototype($prototype); $children = array(); $children[] = array('id' => 'item_name', 'foo' => 'bar'); $normalized = $node->normalize($children); $expected = array(); $expected['item_name'] = array('id' => 'item_name', 'foo' => 'bar'); $this->assertEquals($expected, $normalized); } public function testAddDefaultChildren() { $node = $this->getPrototypeNodeWithDefaultChildren(); $node->setAddChildrenIfNoneSet(); $this->assertTrue($node->hasDefaultValue()); $this->assertEquals(array(array('foo' => 'bar')), $node->getDefaultValue()); $node = $this->getPrototypeNodeWithDefaultChildren(); $node->setKeyAttribute('foobar'); $node->setAddChildrenIfNoneSet(); $this->assertTrue($node->hasDefaultValue()); $this->assertEquals(array('defaults' => array('foo' => 'bar')), $node->getDefaultValue()); $node = $this->getPrototypeNodeWithDefaultChildren(); $node->setKeyAttribute('foobar'); $node->setAddChildrenIfNoneSet('defaultkey'); $this->assertTrue($node->hasDefaultValue()); $this->assertEquals(array('defaultkey' => array('foo' => 'bar')), $node->getDefaultValue()); $node = $this->getPrototypeNodeWithDefaultChildren(); $node->setKeyAttribute('foobar'); $node->setAddChildrenIfNoneSet(array('defaultkey')); $this->assertTrue($node->hasDefaultValue()); $this->assertEquals(array('defaultkey' => array('foo' => 'bar')), $node->getDefaultValue()); $node = $this->getPrototypeNodeWithDefaultChildren(); $node->setKeyAttribute('foobar'); $node->setAddChildrenIfNoneSet(array('dk1', 'dk2')); $this->assertTrue($node->hasDefaultValue()); $this->assertEquals(array('dk1' => array('foo' => 'bar'), 'dk2' => array('foo' => 'bar')), $node->getDefaultValue()); $node = $this->getPrototypeNodeWithDefaultChildren(); $node->setAddChildrenIfNoneSet(array(5, 6)); $this->assertTrue($node->hasDefaultValue()); $this->assertEquals(array(0 => array('foo' => 'bar'), 1 => array('foo' => 'bar')), $node->getDefaultValue()); $node = $this->getPrototypeNodeWithDefaultChildren(); $node->setAddChildrenIfNoneSet(2); $this->assertTrue($node->hasDefaultValue()); $this->assertEquals(array(array('foo' => 'bar'), array('foo' => 'bar')), $node->getDefaultValue()); } public function testDefaultChildrenWinsOverDefaultValue() { $node = $this->getPrototypeNodeWithDefaultChildren(); $node->setAddChildrenIfNoneSet(); $node->setDefaultValue(array('bar' => 'foo')); $this->assertTrue($node->hasDefaultValue()); $this->assertEquals(array(array('foo' => 'bar')), $node->getDefaultValue()); } protected function getPrototypeNodeWithDefaultChildren() { $node = new PrototypedArrayNode('root'); $prototype = new ArrayNode(null, $node); $child = new ScalarNode('foo'); $child->setDefaultValue('bar'); $prototype->addChild($child); $prototype->setAddIfNotSet(true); $node->setPrototype($prototype); return $node; } } PK!b..Dtest/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid.xmlnu[ PK!c=Jtest/Config/Symfony/Component/Config/Tests/Fixtures/Util/document_type.xmlnu[ ]> PK!GɩSSKtest/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid_schema.xmlnu[ PK!\ XXBtest/Config/Symfony/Component/Config/Tests/Fixtures/Util/valid.xmlnu[ PK!&Ctest/Config/Symfony/Component/Config/Tests/Fixtures/Util/schema.xsdnu[ PK!r_Qtest/Config/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Definition\Builder\NodeDefinition; class BarNodeDefinition extends NodeDefinition { protected function createNode() { } } PK!@Vtest/Config/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition as BaseVariableNodeDefinition; class VariableNodeDefinition extends BaseVariableNodeDefinition { } PK!u;ssKtest/Config/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Definition\Builder; use Symfony\Component\Config\Definition\Builder\NodeBuilder as BaseNodeBuilder; class NodeBuilder extends BaseNodeBuilder { public function barNode($name) { return $this->node($name, 'bar'); } protected function getNodeClass($type) { switch ($type) { case 'variable': return __NAMESPACE__.'\\'.ucfirst($type).'NodeDefinition'; case 'bar': return __NAMESPACE__.'\\'.ucfirst($type).'NodeDefinition'; default: return parent::getNodeClass($type); } } } PK! Ztest/Config/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Fixtures\Configuration; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; class ExampleConfiguration implements ConfigurationInterface { public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('acme_root'); $rootNode ->fixXmlConfig('parameter') ->fixXmlConfig('connection') ->children() ->booleanNode('boolean')->defaultTrue()->end() ->scalarNode('scalar_empty')->end() ->scalarNode('scalar_null')->defaultNull()->end() ->scalarNode('scalar_true')->defaultTrue()->end() ->scalarNode('scalar_false')->defaultFalse()->end() ->scalarNode('scalar_default')->defaultValue('default')->end() ->scalarNode('scalar_array_empty')->defaultValue(array())->end() ->scalarNode('scalar_array_defaults')->defaultValue(array('elem1', 'elem2'))->end() ->scalarNode('scalar_required')->isRequired()->end() ->enumNode('enum')->values(array('this', 'that'))->end() ->arrayNode('array') ->info('some info') ->canBeUnset() ->children() ->scalarNode('child1')->end() ->scalarNode('child2')->end() ->scalarNode('child3') ->info( "this is a long\n". "multi-line info text\n". "which should be indented" ) ->example('example setting') ->end() ->end() ->end() ->arrayNode('parameters') ->useAttributeAsKey('name') ->prototype('scalar')->end() ->end() ->arrayNode('connections') ->prototype('array') ->children() ->scalarNode('user')->end() ->scalarNode('pass')->end() ->end() ->end() ->end() ->end() ; return $treeBuilder; } } PK!Atest/Config/Symfony/Component/Config/Tests/Fixtures/Again/foo.xmlnu[PK!;test/Config/Symfony/Component/Config/Tests/Fixtures/foo.xmlnu[PK!Mtest/Config/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Resource; use Symfony\Component\Config\Resource\DirectoryResource; class DirectoryResourceTest extends \PHPUnit_Framework_TestCase { protected $directory; protected function setUp() { $this->directory = sys_get_temp_dir().'/symfonyDirectoryIterator'; if (!file_exists($this->directory)) { mkdir($this->directory); } touch($this->directory.'/tmp.xml'); } protected function tearDown() { if (!is_dir($this->directory)) { return; } $this->removeDirectory($this->directory); } protected function removeDirectory($directory) { $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory), \RecursiveIteratorIterator::CHILD_FIRST); foreach ($iterator as $path) { if (preg_match('#[/\\\\]\.\.?$#', $path->__toString())) { continue; } if ($path->isDir()) { rmdir($path->__toString()); } else { unlink($path->__toString()); } } rmdir($directory); } public function testGetResource() { $resource = new DirectoryResource($this->directory); $this->assertSame($this->directory, $resource->getResource(), '->getResource() returns the path to the resource'); $this->assertSame($this->directory, (string) $resource, '->__toString() returns the path to the resource'); } public function testGetPattern() { $resource = new DirectoryResource('foo', 'bar'); $this->assertEquals('bar', $resource->getPattern()); } public function testIsFresh() { $resource = new DirectoryResource($this->directory); $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if the resource has not changed'); $this->assertFalse($resource->isFresh(time() - 86400), '->isFresh() returns false if the resource has been updated'); $resource = new DirectoryResource('/____foo/foobar'.rand(1, 999999)); $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the resource does not exist'); } public function testIsFreshUpdateFile() { $resource = new DirectoryResource($this->directory); touch($this->directory.'/tmp.xml', time() + 20); $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if an existing file is modified'); } public function testIsFreshNewFile() { $resource = new DirectoryResource($this->directory); touch($this->directory.'/new.xml', time() + 20); $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a new file is added'); } public function testIsFreshDeleteFile() { $resource = new DirectoryResource($this->directory); unlink($this->directory.'/tmp.xml'); $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if an existing file is removed'); } public function testIsFreshDeleteDirectory() { $resource = new DirectoryResource($this->directory); $this->removeDirectory($this->directory); $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the whole resource is removed'); } public function testIsFreshCreateFileInSubdirectory() { $subdirectory = $this->directory.'/subdirectory'; mkdir($subdirectory); $resource = new DirectoryResource($this->directory); $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if an unmodified subdirectory exists'); touch($subdirectory.'/newfile.xml', time() + 20); $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a new file in a subdirectory is added'); } public function testIsFreshModifySubdirectory() { $resource = new DirectoryResource($this->directory); $subdirectory = $this->directory.'/subdirectory'; mkdir($subdirectory); touch($subdirectory, time() + 20); $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a subdirectory is modified (e.g. a file gets deleted)'); } public function testFilterRegexListNoMatch() { $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/'); touch($this->directory.'/new.bar', time() + 20); $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if a new file not matching the filter regex is created'); } public function testFilterRegexListMatch() { $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/'); touch($this->directory.'/new.xml', time() + 20); $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if an new file matching the filter regex is created '); } public function testSerializeUnserialize() { $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/'); $unserialized = unserialize(serialize($resource)); $this->assertSame($this->directory, $resource->getResource()); $this->assertSame('/\.(foo|xml)$/', $resource->getPattern()); } } PK!D-Htest/Config/Symfony/Component/Config/Tests/Resource/FileResourceTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Resource; use Symfony\Component\Config\Resource\FileResource; class FileResourceTest extends \PHPUnit_Framework_TestCase { protected $resource; protected $file; protected function setUp() { $this->file = realpath(sys_get_temp_dir()).'/tmp.xml'; touch($this->file); $this->resource = new FileResource($this->file); } protected function tearDown() { unlink($this->file); } public function testGetResource() { $this->assertSame(realpath($this->file), $this->resource->getResource(), '->getResource() returns the path to the resource'); } public function testToString() { $this->assertSame(realpath($this->file), (string) $this->resource); } public function testIsFresh() { $this->assertTrue($this->resource->isFresh(time() + 10), '->isFresh() returns true if the resource has not changed'); $this->assertFalse($this->resource->isFresh(time() - 86400), '->isFresh() returns false if the resource has been updated'); $resource = new FileResource('/____foo/foobar'.rand(1, 999999)); $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the resource does not exist'); } public function testSerializeUnserialize() { $unserialized = unserialize(serialize($this->resource)); $this->assertSame(realpath($this->file), $this->resource->getResource()); } } PK!s@test/Config/Symfony/Component/Config/Tests/Util/XmlUtilsTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Loader; use Symfony\Component\Config\Util\XmlUtils; class XmlUtilsTest extends \PHPUnit_Framework_TestCase { public function testLoadFile() { $fixtures = __DIR__.'/../Fixtures/Util/'; try { XmlUtils::loadFile($fixtures.'invalid.xml'); $this->fail(); } catch (\InvalidArgumentException $e) { $this->assertContains('ERROR 77', $e->getMessage()); } try { XmlUtils::loadFile($fixtures.'document_type.xml'); $this->fail(); } catch (\InvalidArgumentException $e) { $this->assertContains('Document types are not allowed', $e->getMessage()); } try { XmlUtils::loadFile($fixtures.'invalid_schema.xml', $fixtures.'schema.xsd'); $this->fail(); } catch (\InvalidArgumentException $e) { $this->assertContains('ERROR 1845', $e->getMessage()); } try { XmlUtils::loadFile($fixtures.'invalid_schema.xml', 'invalid_callback_or_file'); $this->fail(); } catch (\InvalidArgumentException $e) { $this->assertContains('XSD file or callable', $e->getMessage()); } $mock = $this->getMock(__NAMESPACE__.'\Validator'); $mock->expects($this->exactly(2))->method('validate')->will($this->onConsecutiveCalls(false, true)); try { XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate')); $this->fail(); } catch (\InvalidArgumentException $e) { $this->assertContains('is not valid', $e->getMessage()); } $this->assertInstanceOf('DOMDocument', XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate'))); } /** * @dataProvider getDataForConvertDomToArray */ public function testConvertDomToArray($expected, $xml, $root = false, $checkPrefix = true) { $dom = new \DOMDocument(); $dom->loadXML($root ? $xml : ''.$xml.''); $this->assertSame($expected, XmlUtils::convertDomElementToArray($dom->documentElement, $checkPrefix)); } public function getDataForConvertDomToArray() { return array( array(null, ''), array('bar', 'bar'), array(array('bar' => 'foobar'), '', true), array(array('foo' => null), ''), array(array('foo' => 'bar'), 'bar'), array(array('foo' => array('foo' => 'bar')), ''), array(array('foo' => array('foo' => 0)), '0'), array(array('foo' => array('foo' => 'bar')), 'bar'), array(array('foo' => array('foo' => 'bar', 'value' => 'text')), 'text'), array(array('foo' => array('attr' => 'bar', 'foo' => 'text')), 'text'), array(array('foo' => array('bar', 'text')), 'bartext'), array(array('foo' => array(array('foo' => 'bar'), array('foo' => 'text'))), ''), array(array('foo' => array('foo' => array('bar', 'text'))), 'text'), array(array('foo' => 'bar'), 'bar'), array(array('foo' => 'text'), 'text'), array(array('foo' => array('bar' => 'bar', 'value' => 'text')), 'text', false, false), array(array('attr' => 1, 'b' => 'hello'), 'hello2', true), ); } /** * @dataProvider getDataForPhpize */ public function testPhpize($expected, $value) { $this->assertSame($expected, XmlUtils::phpize($value)); } public function getDataForPhpize() { return array( array('', ''), array(null, 'null'), array(true, 'true'), array(false, 'false'), array(null, 'Null'), array(true, 'True'), array(false, 'False'), array(0, '0'), array(1, '1'), array(-1, '-1'), array(0777, '0777'), array(255, '0xFF'), array(100.0, '1e2'), array(-120.0, '-1.2E2'), array(-10100.1, '-10100.1'), array('-10,100.1', '-10,100.1'), array('1234 5678 9101 1121 3141', '1234 5678 9101 1121 3141'), array('1,2,3,4', '1,2,3,4'), array('11,22,33,44', '11,22,33,44'), array('11,222,333,4', '11,222,333,4'), array('1,222,333,444', '1,222,333,444'), array('11,222,333,444', '11,222,333,444'), array('111,222,333,444', '111,222,333,444'), array('1111,2222,3333,4444,5555', '1111,2222,3333,4444,5555'), array('foo', 'foo'), array(6, '0b0110'), ); } public function testLoadEmptyXmlFile() { $file = __DIR__.'/../Fixtures/foo.xml'; $this->setExpectedException('InvalidArgumentException', 'File '.$file.' does not contain valid XML, it is empty.'); XmlUtils::loadFile($file); } // test for issue https://github.com/symfony/symfony/issues/9731 public function testLoadWrongEmptyXMLWithErrorHandler() { $originalDisableEntities = libxml_disable_entity_loader(false); $errorReporting = error_reporting(-1); set_error_handler(function ($errno, $errstr) { throw new \Exception($errstr, $errno); }); $file = __DIR__.'/../Fixtures/foo.xml'; try { XmlUtils::loadFile($file); $this->fail('An exception should have been raised'); } catch (\InvalidArgumentException $e) { $this->assertEquals(sprintf('File %s does not contain valid XML, it is empty.', $file), $e->getMessage()); } restore_error_handler(); error_reporting($errorReporting); $disableEntities = libxml_disable_entity_loader(true); libxml_disable_entity_loader($disableEntities); libxml_disable_entity_loader($originalDisableEntities); $this->assertFalse($disableEntities); // should not throw an exception XmlUtils::loadFile(__DIR__.'/../Fixtures/Util/valid.xml', __DIR__.'/../Fixtures/Util/schema.xsd'); } } interface Validator { public function validate(); } PK! Z^^>test/Config/Symfony/Component/Config/Tests/ConfigCacheTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests; use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\Resource\FileResource; class ConfigCacheTest extends \PHPUnit_Framework_TestCase { private $resourceFile = null; private $cacheFile = null; private $metaFile = null; public function setUp() { $this->resourceFile = tempnam(sys_get_temp_dir(), '_resource'); $this->cacheFile = tempnam(sys_get_temp_dir(), 'config_'); $this->metaFile = $this->cacheFile.'.meta'; $this->makeCacheFresh(); $this->generateMetaFile(); } public function tearDown() { $files = array($this->cacheFile, $this->metaFile, $this->resourceFile); foreach ($files as $file) { if (file_exists($file)) { unlink($file); } } } public function testToString() { $cache = new ConfigCache($this->cacheFile, true); $this->assertSame($this->cacheFile, (string) $cache); } public function testCacheIsNotFreshIfFileDoesNotExist() { unlink($this->cacheFile); $cache = new ConfigCache($this->cacheFile, false); $this->assertFalse($cache->isFresh()); } public function testCacheIsAlwaysFreshIfFileExistsWithDebugDisabled() { $this->makeCacheStale(); $cache = new ConfigCache($this->cacheFile, false); $this->assertTrue($cache->isFresh()); } public function testCacheIsNotFreshWithoutMetaFile() { unlink($this->metaFile); $cache = new ConfigCache($this->cacheFile, true); $this->assertFalse($cache->isFresh()); } public function testCacheIsFreshIfResourceIsFresh() { $cache = new ConfigCache($this->cacheFile, true); $this->assertTrue($cache->isFresh()); } public function testCacheIsNotFreshIfOneOfTheResourcesIsNotFresh() { $this->makeCacheStale(); $cache = new ConfigCache($this->cacheFile, true); $this->assertFalse($cache->isFresh()); } public function testWriteDumpsFile() { unlink($this->cacheFile); unlink($this->metaFile); $cache = new ConfigCache($this->cacheFile, false); $cache->write('FOOBAR'); $this->assertFileExists($this->cacheFile, 'Cache file is created'); $this->assertSame('FOOBAR', file_get_contents($this->cacheFile)); $this->assertFileNotExists($this->metaFile, 'Meta file is not created'); } public function testWriteDumpsMetaFileWithDebugEnabled() { unlink($this->cacheFile); unlink($this->metaFile); $metadata = array(new FileResource($this->resourceFile)); $cache = new ConfigCache($this->cacheFile, true); $cache->write('FOOBAR', $metadata); $this->assertFileExists($this->cacheFile, 'Cache file is created'); $this->assertFileExists($this->metaFile, 'Meta file is created'); $this->assertSame(serialize($metadata), file_get_contents($this->metaFile)); } private function makeCacheFresh() { touch($this->resourceFile, filemtime($this->cacheFile) - 3600); } private function makeCacheStale() { touch($this->cacheFile, time() - 3600); } private function generateMetaFile() { file_put_contents($this->metaFile, serialize(array(new FileResource($this->resourceFile)))); } } PK!KOCC>test/Config/Symfony/Component/Config/Tests/FileLocatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests; use Symfony\Component\Config\FileLocator; class FileLocatorTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getIsAbsolutePathTests */ public function testIsAbsolutePath($path) { $loader = new FileLocator(array()); $r = new \ReflectionObject($loader); $m = $r->getMethod('isAbsolutePath'); $m->setAccessible(true); $this->assertTrue($m->invoke($loader, $path), '->isAbsolutePath() returns true for an absolute path'); } public function getIsAbsolutePathTests() { return array( array('/foo.xml'), array('c:\\\\foo.xml'), array('c:/foo.xml'), array('\\server\\foo.xml'), array('https://server/foo.xml'), array('phar://server/foo.xml'), ); } public function testLocate() { $loader = new FileLocator(__DIR__.'/Fixtures'); $this->assertEquals( __DIR__.DIRECTORY_SEPARATOR.'FileLocatorTest.php', $loader->locate('FileLocatorTest.php', __DIR__), '->locate() returns the absolute filename if the file exists in the given path' ); $this->assertEquals( __DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', $loader->locate('foo.xml', __DIR__), '->locate() returns the absolute filename if the file exists in one of the paths given in the constructor' ); $this->assertEquals( __DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', $loader->locate(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__), '->locate() returns the absolute filename if the file exists in one of the paths given in the constructor' ); $loader = new FileLocator(array(__DIR__.'/Fixtures', __DIR__.'/Fixtures/Again')); $this->assertEquals( array(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.DIRECTORY_SEPARATOR.'foo.xml'), $loader->locate('foo.xml', __DIR__, false), '->locate() returns an array of absolute filenames' ); $this->assertEquals( array(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.DIRECTORY_SEPARATOR.'foo.xml'), $loader->locate('foo.xml', __DIR__.'/Fixtures', false), '->locate() returns an array of absolute filenames' ); $loader = new FileLocator(__DIR__.'/Fixtures/Again'); $this->assertEquals( array(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.DIRECTORY_SEPARATOR.'foo.xml'), $loader->locate('foo.xml', __DIR__.'/Fixtures', false), '->locate() returns an array of absolute filenames' ); } /** * @expectedException \InvalidArgumentException */ public function testLocateThrowsAnExceptionIfTheFileDoesNotExists() { $loader = new FileLocator(array(__DIR__.'/Fixtures')); $loader->locate('foobar.xml', __DIR__); } /** * @expectedException \InvalidArgumentException */ public function testLocateThrowsAnExceptionIfTheFileDoesNotExistsInAbsolutePath() { $loader = new FileLocator(array(__DIR__.'/Fixtures')); $loader->locate(__DIR__.'/Fixtures/foobar.xml', __DIR__); } } PK!L{Dtest/Config/Symfony/Component/Config/Tests/Loader/FileLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Loader; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException; class FileLoaderTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\Config\Loader\FileLoader */ public function testImportWithFileLocatorDelegation() { $locatorMock = $this->getMock('Symfony\Component\Config\FileLocatorInterface'); $locatorMockForAdditionalLoader = $this->getMock('Symfony\Component\Config\FileLocatorInterface'); $locatorMockForAdditionalLoader->expects($this->any())->method('locate')->will($this->onConsecutiveCalls( array('path/to/file1'), // Default array('path/to/file1', 'path/to/file2'), // First is imported array('path/to/file1', 'path/to/file2'), // Second is imported array('path/to/file1'), // Exception array('path/to/file1', 'path/to/file2') // Exception )); $fileLoader = new TestFileLoader($locatorMock); $fileLoader->setSupports(false); $fileLoader->setCurrentDir('.'); $additionalLoader = new TestFileLoader($locatorMockForAdditionalLoader); $additionalLoader->setCurrentDir('.'); $fileLoader->setResolver($loaderResolver = new LoaderResolver(array($fileLoader, $additionalLoader))); // Default case $this->assertSame('path/to/file1', $fileLoader->import('my_resource')); // Check first file is imported if not already loading $this->assertSame('path/to/file1', $fileLoader->import('my_resource')); // Check second file is imported if first is already loading $fileLoader->addLoading('path/to/file1'); $this->assertSame('path/to/file2', $fileLoader->import('my_resource')); // Check exception throws if first (and only available) file is already loading try { $fileLoader->import('my_resource'); $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading'); } // Check exception throws if all files are already loading try { $fileLoader->addLoading('path/to/file2'); $fileLoader->import('my_resource'); $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading'); } } } class TestFileLoader extends FileLoader { private $supports = true; public function load($resource, $type = null) { return $resource; } public function supports($resource, $type = null) { return $this->supports; } public function addLoading($resource) { self::$loading[$resource] = true; } public function removeLoading($resource) { unset(self::$loading[$resource]); } public function clearLoading() { self::$loading = array(); } public function setSupports($supports) { $this->supports = $supports; } } PK!5bc@@@test/Config/Symfony/Component/Config/Tests/Loader/LoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Loader; use Symfony\Component\Config\Loader\Loader; class LoaderTest extends \PHPUnit_Framework_TestCase { public function testGetSetResolver() { $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface'); $loader = new ProjectLoader1(); $loader->setResolver($resolver); $this->assertSame($resolver, $loader->getResolver(), '->setResolver() sets the resolver loader'); } public function testResolve() { $resolvedLoader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface'); $resolver->expects($this->once()) ->method('resolve') ->with('foo.xml') ->will($this->returnValue($resolvedLoader)); $loader = new ProjectLoader1(); $loader->setResolver($resolver); $this->assertSame($loader, $loader->resolve('foo.foo'), '->resolve() finds a loader'); $this->assertSame($resolvedLoader, $loader->resolve('foo.xml'), '->resolve() finds a loader'); } /** * @expectedException \Symfony\Component\Config\Exception\FileLoaderLoadException */ public function testResolveWhenResolverCannotFindLoader() { $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface'); $resolver->expects($this->once()) ->method('resolve') ->with('FOOBAR') ->will($this->returnValue(false)); $loader = new ProjectLoader1(); $loader->setResolver($resolver); $loader->resolve('FOOBAR'); } public function testImport() { $resolvedLoader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); $resolvedLoader->expects($this->once()) ->method('load') ->with('foo') ->will($this->returnValue('yes')); $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface'); $resolver->expects($this->once()) ->method('resolve') ->with('foo') ->will($this->returnValue($resolvedLoader)); $loader = new ProjectLoader1(); $loader->setResolver($resolver); $this->assertEquals('yes', $loader->import('foo')); } public function testImportWithType() { $resolvedLoader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); $resolvedLoader->expects($this->once()) ->method('load') ->with('foo', 'bar') ->will($this->returnValue('yes')); $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface'); $resolver->expects($this->once()) ->method('resolve') ->with('foo', 'bar') ->will($this->returnValue($resolvedLoader)); $loader = new ProjectLoader1(); $loader->setResolver($resolver); $this->assertEquals('yes', $loader->import('foo', 'bar')); } } class ProjectLoader1 extends Loader { public function load($resource, $type = null) { } public function supports($resource, $type = null) { return is_string($resource) && 'foo' === pathinfo($resource, PATHINFO_EXTENSION); } public function getType() { } } PK!oq*, Jtest/Config/Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Loader; use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\Loader\DelegatingLoader; class DelegatingLoaderTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\Config\Loader\DelegatingLoader::__construct */ public function testConstructor() { $loader = new DelegatingLoader($resolver = new LoaderResolver()); $this->assertTrue(true, '__construct() takes a loader resolver as its first argument'); } /** * @covers Symfony\Component\Config\Loader\DelegatingLoader::getResolver * @covers Symfony\Component\Config\Loader\DelegatingLoader::setResolver */ public function testGetSetResolver() { $resolver = new LoaderResolver(); $loader = new DelegatingLoader($resolver); $this->assertSame($resolver, $loader->getResolver(), '->getResolver() gets the resolver loader'); $loader->setResolver($resolver = new LoaderResolver()); $this->assertSame($resolver, $loader->getResolver(), '->setResolver() sets the resolver loader'); } /** * @covers Symfony\Component\Config\Loader\DelegatingLoader::supports */ public function testSupports() { $loader1 = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); $loader1->expects($this->once())->method('supports')->will($this->returnValue(true)); $loader = new DelegatingLoader(new LoaderResolver(array($loader1))); $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable'); $loader1 = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); $loader1->expects($this->once())->method('supports')->will($this->returnValue(false)); $loader = new DelegatingLoader(new LoaderResolver(array($loader1))); $this->assertFalse($loader->supports('foo.foo'), '->supports() returns false if the resource is not loadable'); } /** * @covers Symfony\Component\Config\Loader\DelegatingLoader::load */ public function testLoad() { $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); $loader->expects($this->once())->method('supports')->will($this->returnValue(true)); $loader->expects($this->once())->method('load'); $resolver = new LoaderResolver(array($loader)); $loader = new DelegatingLoader($resolver); $loader->load('foo'); } /** * @expectedException \Symfony\Component\Config\Exception\FileLoaderLoadException */ public function testLoadThrowsAnExceptionIfTheResourceCannotBeLoaded() { $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); $loader->expects($this->once())->method('supports')->will($this->returnValue(false)); $resolver = new LoaderResolver(array($loader)); $loader = new DelegatingLoader($resolver); $loader->load('foo'); } } PK!Y  Htest/Config/Symfony/Component/Config/Tests/Loader/LoaderResolverTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Tests\Loader; use Symfony\Component\Config\Loader\LoaderResolver; class LoaderResolverTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\Config\Loader\LoaderResolver::__construct */ public function testConstructor() { $resolver = new LoaderResolver(array( $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'), )); $this->assertEquals(array($loader), $resolver->getLoaders(), '__construct() takes an array of loaders as its first argument'); } /** * @covers Symfony\Component\Config\Loader\LoaderResolver::resolve */ public function testResolve() { $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); $resolver = new LoaderResolver(array($loader)); $this->assertFalse($resolver->resolve('foo.foo'), '->resolve() returns false if no loader is able to load the resource'); $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); $loader->expects($this->once())->method('supports')->will($this->returnValue(true)); $resolver = new LoaderResolver(array($loader)); $this->assertEquals($loader, $resolver->resolve(function () {}), '->resolve() returns the loader for the given resource'); } /** * @covers Symfony\Component\Config\Loader\LoaderResolver::getLoaders * @covers Symfony\Component\Config\Loader\LoaderResolver::addLoader */ public function testLoaders() { $resolver = new LoaderResolver(); $resolver->addLoader($loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface')); $this->assertEquals(array($loader), $resolver->getLoaders(), 'addLoader() adds a loader'); } } PK!Yhh5test/Config/Symfony/Component/Config/phpunit.xml.distnu[ ./Tests/ ./ ./Resources ./Tests ./vendor PK!?7|ffAtest/HttpKernel/Symfony/Component/HttpKernel/Tests/KernelTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest; use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForOverrideName; use Symfony\Component\HttpKernel\Tests\Fixtures\FooBarBundle; class KernelTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $env = 'test_env'; $debug = true; $kernel = new KernelForTest($env, $debug); $this->assertEquals($env, $kernel->getEnvironment()); $this->assertEquals($debug, $kernel->isDebug()); $this->assertFalse($kernel->isBooted()); $this->assertLessThanOrEqual(microtime(true), $kernel->getStartTime()); $this->assertNull($kernel->getContainer()); } public function testClone() { $env = 'test_env'; $debug = true; $kernel = new KernelForTest($env, $debug); $clone = clone $kernel; $this->assertEquals($env, $clone->getEnvironment()); $this->assertEquals($debug, $clone->isDebug()); $this->assertFalse($clone->isBooted()); $this->assertLessThanOrEqual(microtime(true), $clone->getStartTime()); $this->assertNull($clone->getContainer()); } public function testBootInitializesBundlesAndContainer() { $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer')); $kernel->expects($this->once()) ->method('initializeBundles'); $kernel->expects($this->once()) ->method('initializeContainer'); $kernel->boot(); } public function testBootSetsTheContainerToTheBundles() { $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); $bundle->expects($this->once()) ->method('setContainer'); $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'getBundles')); $kernel->expects($this->once()) ->method('getBundles') ->will($this->returnValue(array($bundle))); $kernel->boot(); } public function testBootSetsTheBootedFlagToTrue() { // use test kernel to access isBooted() $kernel = $this->getKernelForTest(array('initializeBundles', 'initializeContainer')); $kernel->boot(); $this->assertTrue($kernel->isBooted()); } public function testClassCacheIsLoaded() { $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache')); $kernel->loadClassCache('name', '.extension'); $kernel->expects($this->once()) ->method('doLoadClassCache') ->with('name', '.extension'); $kernel->boot(); } public function testClassCacheIsNotLoadedByDefault() { $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer')); $kernel->expects($this->never()) ->method('doLoadClassCache'); $kernel->boot(); } public function testClassCacheIsNotLoadedWhenKernelIsNotBooted() { $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache')); $kernel->loadClassCache(); $kernel->expects($this->never()) ->method('doLoadClassCache'); } public function testBootKernelSeveralTimesOnlyInitializesBundlesOnce() { $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer')); $kernel->expects($this->once()) ->method('initializeBundles'); $kernel->boot(); $kernel->boot(); } public function testShutdownCallsShutdownOnAllBundles() { $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); $bundle->expects($this->once()) ->method('shutdown'); $kernel = $this->getKernel(array(), array($bundle)); $kernel->boot(); $kernel->shutdown(); } public function testShutdownGivesNullContainerToAllBundles() { $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); $bundle->expects($this->at(3)) ->method('setContainer') ->with(null); $kernel = $this->getKernel(array('getBundles')); $kernel->expects($this->any()) ->method('getBundles') ->will($this->returnValue(array($bundle))); $kernel->boot(); $kernel->shutdown(); } public function testHandleCallsHandleOnHttpKernel() { $type = HttpKernelInterface::MASTER_REQUEST; $catch = true; $request = new Request(); $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel') ->disableOriginalConstructor() ->getMock(); $httpKernelMock ->expects($this->once()) ->method('handle') ->with($request, $type, $catch); $kernel = $this->getKernel(array('getHttpKernel')); $kernel->expects($this->once()) ->method('getHttpKernel') ->will($this->returnValue($httpKernelMock)); $kernel->handle($request, $type, $catch); } public function testHandleBootsTheKernel() { $type = HttpKernelInterface::MASTER_REQUEST; $catch = true; $request = new Request(); $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel') ->disableOriginalConstructor() ->getMock(); $kernel = $this->getKernel(array('getHttpKernel', 'boot')); $kernel->expects($this->once()) ->method('getHttpKernel') ->will($this->returnValue($httpKernelMock)); $kernel->expects($this->once()) ->method('boot'); $kernel->handle($request, $type, $catch); } public function testStripComments() { if (!function_exists('token_get_all')) { $this->markTestSkipped('The function token_get_all() is not available.'); return; } $source = <<<'EOF' assertEquals($expected, $output); } public function testIsClassInActiveBundleFalse() { $kernel = $this->getKernelMockForIsClassInActiveBundleTest(); $this->assertFalse($kernel->isClassInActiveBundle('Not\In\Active\Bundle')); } public function testIsClassInActiveBundleFalseNoNamespace() { $kernel = $this->getKernelMockForIsClassInActiveBundleTest(); $this->assertFalse($kernel->isClassInActiveBundle('NotNamespacedClass')); } public function testIsClassInActiveBundleTrue() { $kernel = $this->getKernelMockForIsClassInActiveBundleTest(); $this->assertTrue($kernel->isClassInActiveBundle(__NAMESPACE__.'\Fixtures\FooBarBundle\SomeClass')); } protected function getKernelMockForIsClassInActiveBundleTest() { $bundle = new FooBarBundle(); $kernel = $this->getKernel(array('getBundles')); $kernel->expects($this->once()) ->method('getBundles') ->will($this->returnValue(array($bundle))); return $kernel; } public function testGetRootDir() { $kernel = new KernelForTest('test', true); $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures', realpath($kernel->getRootDir())); } public function testGetName() { $kernel = new KernelForTest('test', true); $this->assertEquals('Fixtures', $kernel->getName()); } public function testOverrideGetName() { $kernel = new KernelForOverrideName('test', true); $this->assertEquals('overridden', $kernel->getName()); } public function testSerialize() { $env = 'test_env'; $debug = true; $kernel = new KernelForTest($env, $debug); $expected = serialize(array($env, $debug)); $this->assertEquals($expected, $kernel->serialize()); } /** * @expectedException \InvalidArgumentException */ public function testLocateResourceThrowsExceptionWhenNameIsNotValid() { $this->getKernel()->locateResource('Foo'); } /** * @expectedException \RuntimeException */ public function testLocateResourceThrowsExceptionWhenNameIsUnsafe() { $this->getKernel()->locateResource('@FooBundle/../bar'); } /** * @expectedException \InvalidArgumentException */ public function testLocateResourceThrowsExceptionWhenBundleDoesNotExist() { $this->getKernel()->locateResource('@FooBundle/config/routing.xml'); } /** * @expectedException \InvalidArgumentException */ public function testLocateResourceThrowsExceptionWhenResourceDoesNotExist() { $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->once()) ->method('getBundle') ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) ; $kernel->locateResource('@Bundle1Bundle/config/routing.xml'); } public function testLocateResourceReturnsTheFirstThatMatches() { $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->once()) ->method('getBundle') ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) ; $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt')); } public function testLocateResourceReturnsTheFirstThatMatchesWithParent() { $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle'); $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->exactly(2)) ->method('getBundle') ->will($this->returnValue(array($child, $parent))) ; $this->assertEquals(__DIR__.'/Fixtures/Bundle2Bundle/foo.txt', $kernel->locateResource('@ParentAABundle/foo.txt')); $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/bar.txt', $kernel->locateResource('@ParentAABundle/bar.txt')); } public function testLocateResourceReturnsAllMatches() { $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle'); $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->once()) ->method('getBundle') ->will($this->returnValue(array($child, $parent))) ; $this->assertEquals(array( __DIR__.'/Fixtures/Bundle2Bundle/foo.txt', __DIR__.'/Fixtures/Bundle1Bundle/foo.txt'), $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false)); } public function testLocateResourceReturnsAllMatchesBis() { $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->once()) ->method('getBundle') ->will($this->returnValue(array( $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'), $this->getBundle(__DIR__.'/Foobar') ))) ; $this->assertEquals( array(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt'), $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false) ); } public function testLocateResourceIgnoresDirOnNonResource() { $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->once()) ->method('getBundle') ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) ; $this->assertEquals( __DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt', __DIR__.'/Fixtures') ); } public function testLocateResourceReturnsTheDirOneForResources() { $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->once()) ->method('getBundle') ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))) ; $this->assertEquals( __DIR__.'/Fixtures/Resources/FooBundle/foo.txt', $kernel->locateResource('@FooBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources') ); } public function testLocateResourceReturnsTheDirOneForResourcesAndBundleOnes() { $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->once()) ->method('getBundle') ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')))) ; $this->assertEquals(array( __DIR__.'/Fixtures/Resources/Bundle1Bundle/foo.txt', __DIR__.'/Fixtures/Bundle1Bundle/Resources/foo.txt'), $kernel->locateResource('@Bundle1Bundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false) ); } public function testLocateResourceOverrideBundleAndResourcesFolders() { $parent = $this->getBundle(__DIR__.'/Fixtures/BaseBundle', null, 'BaseBundle', 'BaseBundle'); $child = $this->getBundle(__DIR__.'/Fixtures/ChildBundle', 'ParentBundle', 'ChildBundle', 'ChildBundle'); $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->exactly(4)) ->method('getBundle') ->will($this->returnValue(array($child, $parent))) ; $this->assertEquals(array( __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt', __DIR__.'/Fixtures/ChildBundle/Resources/foo.txt', __DIR__.'/Fixtures/BaseBundle/Resources/foo.txt', ), $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false) ); $this->assertEquals( __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt', $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources') ); try { $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', false); $this->fail('Hidden resources should raise an exception when returning an array of matching paths'); } catch (\RuntimeException $e) { } try { $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', true); $this->fail('Hidden resources should raise an exception when returning the first matching path'); } catch (\RuntimeException $e) { } } public function testLocateResourceOnDirectories() { $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->exactly(2)) ->method('getBundle') ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))) ; $this->assertEquals( __DIR__.'/Fixtures/Resources/FooBundle/', $kernel->locateResource('@FooBundle/Resources/', __DIR__.'/Fixtures/Resources') ); $this->assertEquals( __DIR__.'/Fixtures/Resources/FooBundle', $kernel->locateResource('@FooBundle/Resources', __DIR__.'/Fixtures/Resources') ); $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->exactly(2)) ->method('getBundle') ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')))) ; $this->assertEquals( __DIR__.'/Fixtures/Bundle1Bundle/Resources/', $kernel->locateResource('@Bundle1Bundle/Resources/') ); $this->assertEquals( __DIR__.'/Fixtures/Bundle1Bundle/Resources', $kernel->locateResource('@Bundle1Bundle/Resources') ); } public function testInitializeBundles() { $parent = $this->getBundle(null, null, 'ParentABundle'); $child = $this->getBundle(null, 'ParentABundle', 'ChildABundle'); // use test kernel so we can access getBundleMap() $kernel = $this->getKernelForTest(array('registerBundles')); $kernel ->expects($this->once()) ->method('registerBundles') ->will($this->returnValue(array($parent, $child))) ; $kernel->boot(); $map = $kernel->getBundleMap(); $this->assertEquals(array($child, $parent), $map['ParentABundle']); } public function testInitializeBundlesSupportInheritanceCascade() { $grandparent = $this->getBundle(null, null, 'GrandParentBBundle'); $parent = $this->getBundle(null, 'GrandParentBBundle', 'ParentBBundle'); $child = $this->getBundle(null, 'ParentBBundle', 'ChildBBundle'); // use test kernel so we can access getBundleMap() $kernel = $this->getKernelForTest(array('registerBundles')); $kernel ->expects($this->once()) ->method('registerBundles') ->will($this->returnValue(array($grandparent, $parent, $child))) ; $kernel->boot(); $map = $kernel->getBundleMap(); $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentBBundle']); $this->assertEquals(array($child, $parent), $map['ParentBBundle']); $this->assertEquals(array($child), $map['ChildBBundle']); } /** * @expectedException \LogicException * @expectedExceptionMessage Bundle "ChildCBundle" extends bundle "FooBar", which is not registered. */ public function testInitializeBundlesThrowsExceptionWhenAParentDoesNotExists() { $child = $this->getBundle(null, 'FooBar', 'ChildCBundle'); $kernel = $this->getKernel(array(), array($child)); $kernel->boot(); } public function testInitializeBundlesSupportsArbitraryBundleRegistrationOrder() { $grandparent = $this->getBundle(null, null, 'GrandParentCBundle'); $parent = $this->getBundle(null, 'GrandParentCBundle', 'ParentCBundle'); $child = $this->getBundle(null, 'ParentCBundle', 'ChildCBundle'); // use test kernel so we can access getBundleMap() $kernel = $this->getKernelForTest(array('registerBundles')); $kernel ->expects($this->once()) ->method('registerBundles') ->will($this->returnValue(array($parent, $grandparent, $child))) ; $kernel->boot(); $map = $kernel->getBundleMap(); $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentCBundle']); $this->assertEquals(array($child, $parent), $map['ParentCBundle']); $this->assertEquals(array($child), $map['ChildCBundle']); } /** * @expectedException \LogicException * @expectedExceptionMessage Bundle "ParentCBundle" is directly extended by two bundles "ChildC2Bundle" and "ChildC1Bundle". */ public function testInitializeBundlesThrowsExceptionWhenABundleIsDirectlyExtendedByTwoBundles() { $parent = $this->getBundle(null, null, 'ParentCBundle'); $child1 = $this->getBundle(null, 'ParentCBundle', 'ChildC1Bundle'); $child2 = $this->getBundle(null, 'ParentCBundle', 'ChildC2Bundle'); $kernel = $this->getKernel(array(), array($parent, $child1, $child2)); $kernel->boot(); } /** * @expectedException \LogicException * @expectedExceptionMessage Trying to register two bundles with the same name "DuplicateName" */ public function testInitializeBundleThrowsExceptionWhenRegisteringTwoBundlesWithTheSameName() { $fooBundle = $this->getBundle(null, null, 'FooBundle', 'DuplicateName'); $barBundle = $this->getBundle(null, null, 'BarBundle', 'DuplicateName'); $kernel = $this->getKernel(array(), array($fooBundle, $barBundle)); $kernel->boot(); } /** * @expectedException \LogicException * @expectedExceptionMessage Bundle "CircularRefBundle" can not extend itself. */ public function testInitializeBundleThrowsExceptionWhenABundleExtendsItself() { $circularRef = $this->getBundle(null, 'CircularRefBundle', 'CircularRefBundle'); $kernel = $this->getKernel(array(), array($circularRef)); $kernel->boot(); } public function testTerminateReturnsSilentlyIfKernelIsNotBooted() { $kernel = $this->getKernel(array('getHttpKernel')); $kernel->expects($this->never()) ->method('getHttpKernel'); $kernel->terminate(Request::create('/'), new Response()); } public function testTerminateDelegatesTerminationOnlyForTerminableInterface() { // does not implement TerminableInterface $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface') ->disableOriginalConstructor() ->getMock(); $httpKernelMock ->expects($this->never()) ->method('terminate'); $kernel = $this->getKernel(array('getHttpKernel')); $kernel->expects($this->once()) ->method('getHttpKernel') ->will($this->returnValue($httpKernelMock)); $kernel->boot(); $kernel->terminate(Request::create('/'), new Response()); // implements TerminableInterface $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel') ->disableOriginalConstructor() ->setMethods(array('terminate')) ->getMock(); $httpKernelMock ->expects($this->once()) ->method('terminate'); $kernel = $this->getKernel(array('getHttpKernel')); $kernel->expects($this->exactly(2)) ->method('getHttpKernel') ->will($this->returnValue($httpKernelMock)); $kernel->boot(); $kernel->terminate(Request::create('/'), new Response()); } /** * Returns a mock for the BundleInterface * * @return BundleInterface */ protected function getBundle($dir = null, $parent = null, $className = null, $bundleName = null) { $bundle = $this ->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface') ->setMethods(array('getPath', 'getParent', 'getName')) ->disableOriginalConstructor() ; if ($className) { $bundle->setMockClassName($className); } $bundle = $bundle->getMockForAbstractClass(); $bundle ->expects($this->any()) ->method('getName') ->will($this->returnValue(null === $bundleName ? get_class($bundle) : $bundleName)) ; $bundle ->expects($this->any()) ->method('getPath') ->will($this->returnValue($dir)) ; $bundle ->expects($this->any()) ->method('getParent') ->will($this->returnValue($parent)) ; return $bundle; } /** * Returns a mock for the abstract kernel. * * @param array $methods Additional methods to mock (besides the abstract ones) * @param array $bundles Bundles to register * * @return Kernel */ protected function getKernel(array $methods = array(), array $bundles = array()) { $methods[] = 'registerBundles'; $kernel = $this ->getMockBuilder('Symfony\Component\HttpKernel\Kernel') ->setMethods($methods) ->setConstructorArgs(array('test', false)) ->getMockForAbstractClass() ; $kernel->expects($this->any()) ->method('registerBundles') ->will($this->returnValue($bundles)) ; $p = new \ReflectionProperty($kernel, 'rootDir'); $p->setAccessible(true); $p->setValue($kernel, __DIR__.'/Fixtures'); return $kernel; } protected function getKernelForTest(array $methods = array()) { $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') ->setConstructorArgs(array('test', false)) ->setMethods($methods) ->getMock(); $p = new \ReflectionProperty($kernel, 'rootDir'); $p->setAccessible(true); $p->setValue($kernel, __DIR__.'/Fixtures'); return $kernel; } } PK!6^PYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\CacheClearer; use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; use Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer; class ChainCacheClearerTest extends \PHPUnit_Framework_TestCase { protected static $cacheDir; public static function setUpBeforeClass() { self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_clearer_dir'); } public static function tearDownAfterClass() { @unlink(self::$cacheDir); } public function testInjectClearersInConstructor() { $clearer = $this->getMockClearer(); $clearer ->expects($this->once()) ->method('clear'); $chainClearer = new ChainCacheClearer(array($clearer)); $chainClearer->clear(self::$cacheDir); } public function testInjectClearerUsingAdd() { $clearer = $this->getMockClearer(); $clearer ->expects($this->once()) ->method('clear'); $chainClearer = new ChainCacheClearer(); $chainClearer->add($clearer); $chainClearer->clear(self::$cacheDir); } protected function getMockClearer() { return $this->getMock('Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface'); } } PK!32ETStest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures; use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcher; class TestEventDispatcher extends EventDispatcher implements TraceableEventDispatcherInterface { public function getCalledListeners() { return array('foo'); } public function getNotCalledListeners() { return array('bar'); } } PK!g&ktest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionAbsentBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class ExtensionAbsentBundle extends Bundle { } PK!xitest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command; use Symfony\Component\Console\Command\Command; class FooCommand extends Command { protected function configure() { $this->setName('foo'); } } PK!`Aļmtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class ExtensionPresentBundle extends Bundle { } PK!OgVVtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\DependencyInjection\Extension; class ExtensionPresentExtension extends Extension { public function load(array $configs, ContainerBuilder $container) { } } PK!GQ>` ` itest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/MockObjectTestProjectContainer.phpnu[parameters = $this->getDefaultParameters(); $this->services = $this->scopedServices = $this->scopeStacks = array(); $this->set('service_container', $this); $this->scopes = array(); $this->scopeChildren = array(); $this->aliases = array(); } public function getParameter($name) { $name = strtolower($name); if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } return $this->parameters[$name]; } public function hasParameter($name) { $name = strtolower($name); return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters); } public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } public function getParameterBag() { if (null === $this->parameterBag) { $this->parameterBag = new FrozenParameterBag($this->parameters); } return $this->parameterBag; } protected function getDefaultParameters() { return array( 'kernel.root_dir' => '/Users/fabien/Code/github/symfony/symfony/src/Symfony/Component/HttpKernel/Tests/Fixtures', 'kernel.environment' => 'test', 'kernel.debug' => false, 'kernel.name' => 'MockObject', 'kernel.cache_dir' => '/Users/fabien/Code/github/symfony/symfony/src/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test', 'kernel.logs_dir' => '/Users/fabien/Code/github/symfony/symfony/src/Symfony/Component/HttpKernel/Tests/Fixtures/logs', 'kernel.bundles' => array( 'Mock_Bundle_7fc4ae26' => 'Mock_Bundle_7fc4ae26', ), 'kernel.charset' => 'UTF-8', 'kernel.container_class' => 'MockObjectTestProjectContainer', ); } } PK!#Rtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/classes.mapnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Config\Loader\LoaderInterface; class KernelForOverrideName extends Kernel { protected $name = 'overridden'; public function registerBundles() { } public function registerContainerConfiguration(LoaderInterface $loader) { } } PK!Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txtnu[PK!Ztest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txtnu[PK!Qtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txtnu[PK!Qtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txtnu[PK![test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txtnu[PK!Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txtnu[PK!Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txtnu[PK![test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txtnu[PK!Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txtnu[PK!Xtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txtnu[PK!Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txtnu[PK!&#Jtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures; use Symfony\Component\HttpKernel\Client; class TestClient extends Client { protected function getScript($request) { $script = parent::getScript($request); $autoload = file_exists(__DIR__.'/../../vendor/autoload.php') ? __DIR__.'/../../vendor/autoload.php' : __DIR__.'/../../../../../../vendor/autoload.php' ; $script = preg_replace('/(\->register\(\);)/', "$0\nrequire_once '$autoload';\n", $script); return $script; } } PK!yhMtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Config\Loader\LoaderInterface; class KernelForTest extends Kernel { public function getBundleMap() { return $this->bundleMap; } public function registerBundles() { return array(); } public function registerContainerConfiguration(LoaderInterface $loader) { } public function isBooted() { return $this->booted; } } PK!0Ltest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures; use Symfony\Component\HttpKernel\Bundle\Bundle; class FooBarBundle extends Bundle { // We need a full namespaced bundle instance to test isClassInActiveBundle } PK!?ɜktest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionLoadedBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class ExtensionLoadedBundle extends Bundle { } PK!_TTtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionLoadedBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\DependencyInjection\Extension; class ExtensionLoadedExtension extends Extension { public function load(array $configs, ContainerBuilder $container) { } } PK!S [test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\CacheWarmer; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer; class CacheWarmerAggregateTest extends \PHPUnit_Framework_TestCase { protected static $cacheDir; public static function setUpBeforeClass() { self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir'); } public static function tearDownAfterClass() { @unlink(self::$cacheDir); } public function testInjectWarmersUsingConstructor() { $warmer = $this->getCacheWarmerMock(); $warmer ->expects($this->once()) ->method('warmUp'); $aggregate = new CacheWarmerAggregate(array($warmer)); $aggregate->warmUp(self::$cacheDir); } public function testInjectWarmersUsingAdd() { $warmer = $this->getCacheWarmerMock(); $warmer ->expects($this->once()) ->method('warmUp'); $aggregate = new CacheWarmerAggregate(); $aggregate->add($warmer); $aggregate->warmUp(self::$cacheDir); } public function testInjectWarmersUsingSetWarmers() { $warmer = $this->getCacheWarmerMock(); $warmer ->expects($this->once()) ->method('warmUp'); $aggregate = new CacheWarmerAggregate(); $aggregate->setWarmers(array($warmer)); $aggregate->warmUp(self::$cacheDir); } public function testWarmupDoesCallWarmupOnOptionalWarmersWhenEnableOptionalWarmersIsEnabled() { $warmer = $this->getCacheWarmerMock(); $warmer ->expects($this->never()) ->method('isOptional'); $warmer ->expects($this->once()) ->method('warmUp'); $aggregate = new CacheWarmerAggregate(array($warmer)); $aggregate->enableOptionalWarmers(); $aggregate->warmUp(self::$cacheDir); } public function testWarmupDoesNotCallWarmupOnOptionalWarmersWhenEnableOptionalWarmersIsNotEnabled() { $warmer = $this->getCacheWarmerMock(); $warmer ->expects($this->once()) ->method('isOptional') ->will($this->returnValue(true)); $warmer ->expects($this->never()) ->method('warmUp'); $aggregate = new CacheWarmerAggregate(array($warmer)); $aggregate->warmUp(self::$cacheDir); } protected function getCacheWarmerMock() { $warmer = $this->getMockBuilder('Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface') ->disableOriginalConstructor() ->getMock(); return $warmer; } } PK!,%%Rtest/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\CacheWarmer; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer; class CacheWarmerTest extends \PHPUnit_Framework_TestCase { protected static $cacheFile; public static function setUpBeforeClass() { self::$cacheFile = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir'); } public static function tearDownAfterClass() { @unlink(self::$cacheFile); } public function testWriteCacheFileCreatesTheFile() { $warmer = new TestCacheWarmer(self::$cacheFile); $warmer->warmUp(dirname(self::$cacheFile)); $this->assertTrue(file_exists(self::$cacheFile)); } /** * @expectedException \RuntimeException */ public function testWriteNonWritableCacheFileThrowsARuntimeException() { $nonWritableFile = '/this/file/is/very/probably/not/writable'; $warmer = new TestCacheWarmer($nonWritableFile); $warmer->warmUp(dirname($nonWritableFile)); } } class TestCacheWarmer extends CacheWarmer { protected $file; public function __construct($file) { $this->file = $file; } public function warmUp($cacheDir) { $this->writeCacheFile($this->file, 'content'); } public function isOptional() { return false; } } PK!0GGEtest/HttpKernel/Symfony/Component/HttpKernel/Tests/TestHttpKernel.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcher; class TestHttpKernel extends HttpKernel implements ControllerResolverInterface { public function __construct() { parent::__construct(new EventDispatcher(), $this); } public function getController(Request $request) { return array($this, 'callController'); } public function getArguments(Request $request, $controller) { return array($request); } public function callController(Request $request) { return new Response('Request: '.$request->getRequestUri()); } } PK!qAtest/HttpKernel/Symfony/Component/HttpKernel/Tests/ClientTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests; use Symfony\Component\HttpKernel\Client; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpKernel\Tests\Fixtures\TestClient; class ClientTest extends \PHPUnit_Framework_TestCase { public function testDoRequest() { $client = new Client(new TestHttpKernel()); $client->request('GET', '/'); $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->doRequest() uses the request handler to make the request'); $this->assertInstanceOf('Symfony\Component\BrowserKit\Request', $client->getInternalRequest()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Request', $client->getRequest()); $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getInternalResponse()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $client->getResponse()); $client->request('GET', 'http://www.example.com/'); $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->doRequest() uses the request handler to make the request'); $this->assertEquals('www.example.com', $client->getRequest()->getHost(), '->doRequest() uses the request handler to make the request'); $client->request('GET', 'http://www.example.com/?parameter=http://google.com'); $this->assertEquals('http://www.example.com/?parameter='.urlencode('http://google.com'), $client->getRequest()->getUri(), '->doRequest() uses the request handler to make the request'); } public function testGetScript() { $client = new TestClient(new TestHttpKernel()); $client->insulate(); $client->request('GET', '/'); $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->getScript() returns a script that uses the request handler to make the request'); } public function testFilterResponseConvertsCookies() { $client = new Client(new TestHttpKernel()); $r = new \ReflectionObject($client); $m = $r->getMethod('filterResponse'); $m->setAccessible(true); $expected = array( 'foo=bar; expires=Sun, 15 Feb 2009 20:00:00 GMT; domain=http://example.com; path=/foo; secure; httponly', 'foo1=bar1; expires=Sun, 15 Feb 2009 20:00:00 GMT; domain=http://example.com; path=/foo; secure; httponly' ); $response = new Response(); $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); $domResponse = $m->invoke($client, $response); $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie')); $response = new Response(); $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); $response->headers->setCookie(new Cookie('foo1', 'bar1', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); $domResponse = $m->invoke($client, $response); $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie')); $this->assertEquals($expected, $domResponse->getHeader('Set-Cookie', false)); } public function testFilterResponseSupportsStreamedResponses() { $client = new Client(new TestHttpKernel()); $r = new \ReflectionObject($client); $m = $r->getMethod('filterResponse'); $m->setAccessible(true); $response = new StreamedResponse(function () { echo 'foo'; }); $domResponse = $m->invoke($client, $response); $this->assertEquals('foo', $domResponse->getContent()); } public function testUploadedFile() { $source = tempnam(sys_get_temp_dir(), 'source'); $target = sys_get_temp_dir().'/sf.moved.file'; @unlink($target); $kernel = new TestHttpKernel(); $client = new Client($kernel); $files = array( array('tmp_name' => $source, 'name' => 'original', 'type' => 'mime/original', 'size' => 123, 'error' => UPLOAD_ERR_OK), new UploadedFile($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK, true), ); $file = null; foreach ($files as $file) { $client->request('POST', '/', array(), array('foo' => $file)); $files = $client->getRequest()->files->all(); $this->assertCount(1, $files); $file = $files['foo']; $this->assertEquals('original', $file->getClientOriginalName()); $this->assertEquals('mime/original', $file->getClientMimeType()); $this->assertEquals('123', $file->getClientSize()); $this->assertTrue($file->isValid()); } $file->move(dirname($target), basename($target)); $this->assertFileExists($target); unlink($target); } public function testUploadedFileWhenSizeExceedsUploadMaxFileSize() { $source = tempnam(sys_get_temp_dir(), 'source'); $kernel = new TestHttpKernel(); $client = new Client($kernel); $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') ->setConstructorArgs(array($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK, true)) ->setMethods(array('getSize')) ->getMock() ; $file->expects($this->once()) ->method('getSize') ->will($this->returnValue(INF)) ; $client->request('POST', '/', array(), array($file)); $files = $client->getRequest()->files->all(); $this->assertCount(1, $files); $file = $files[0]; $this->assertFalse($file->isValid()); $this->assertEquals(UPLOAD_ERR_INI_SIZE, $file->getError()); $this->assertEquals('mime/original', $file->getClientMimeType()); $this->assertEquals('original', $file->getClientOriginalName()); $this->assertEquals(0, $file->getClientSize()); unlink($source); } } PK!݂($$Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Debug; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Stopwatch\Stopwatch; class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase { public function testAddRemoveListener() { $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); $tdispatcher->addListener('foo', $listener = function () { ; }); $listeners = $dispatcher->getListeners('foo'); $this->assertCount(1, $listeners); $this->assertSame($listener, $listeners[0]); $tdispatcher->removeListener('foo', $listener); $this->assertCount(0, $dispatcher->getListeners('foo')); } public function testGetListeners() { $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); $tdispatcher->addListener('foo', $listener = function () { ; }); $this->assertSame($dispatcher->getListeners('foo'), $tdispatcher->getListeners('foo')); } public function testHasListeners() { $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); $this->assertFalse($dispatcher->hasListeners('foo')); $this->assertFalse($tdispatcher->hasListeners('foo')); $tdispatcher->addListener('foo', $listener = function () { ; }); $this->assertTrue($dispatcher->hasListeners('foo')); $this->assertTrue($tdispatcher->hasListeners('foo')); } public function testAddRemoveSubscriber() { $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); $subscriber = new EventSubscriber(); $tdispatcher->addSubscriber($subscriber); $listeners = $dispatcher->getListeners('foo'); $this->assertCount(1, $listeners); $this->assertSame(array($subscriber, 'call'), $listeners[0]); $tdispatcher->removeSubscriber($subscriber); $this->assertCount(0, $dispatcher->getListeners('foo')); } public function testGetCalledListeners() { $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); $tdispatcher->addListener('foo', $listener = function () { ; }); $this->assertEquals(array(), $tdispatcher->getCalledListeners()); $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'type' => 'Closure', 'pretty' => 'closure')), $tdispatcher->getNotCalledListeners()); $tdispatcher->dispatch('foo'); $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'type' => 'Closure', 'pretty' => 'closure')), $tdispatcher->getCalledListeners()); $this->assertEquals(array(), $tdispatcher->getNotCalledListeners()); } public function testLogger() { $logger = $this->getMock('Psr\Log\LoggerInterface'); $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger); $tdispatcher->addListener('foo', $listener1 = function () { ; }); $tdispatcher->addListener('foo', $listener2 = function () { ; }); $logger->expects($this->at(0))->method('debug')->with("Notified event \"foo\" to listener \"closure\"."); $logger->expects($this->at(1))->method('debug')->with("Notified event \"foo\" to listener \"closure\"."); $tdispatcher->dispatch('foo'); } public function testLoggerWithStoppedEvent() { $logger = $this->getMock('Psr\Log\LoggerInterface'); $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger); $tdispatcher->addListener('foo', $listener1 = function (Event $event) { $event->stopPropagation(); }); $tdispatcher->addListener('foo', $listener2 = function () { ; }); $logger->expects($this->at(0))->method('debug')->with("Notified event \"foo\" to listener \"closure\"."); $logger->expects($this->at(1))->method('debug')->with("Listener \"closure\" stopped propagation of the event \"foo\"."); $logger->expects($this->at(2))->method('debug')->with("Listener \"closure\" was not called for event \"foo\"."); $tdispatcher->dispatch('foo'); } public function testDispatchCallListeners() { $called = array(); $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); $tdispatcher->addListener('foo', $listener1 = function () use (&$called) { $called[] = 'foo1'; }); $tdispatcher->addListener('foo', $listener2 = function () use (&$called) { $called[] = 'foo2'; }); $tdispatcher->dispatch('foo'); $this->assertEquals(array('foo1', 'foo2'), $called); } public function testDispatchNested() { $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); $loop = 1; $dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) { ++$loop; if (2 == $loop) { $dispatcher->dispatch('foo'); } }); $dispatcher->dispatch('foo'); } public function testDispatchReusedEventNested() { $nestedCall = false; $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); $dispatcher->addListener('foo', function (Event $e) use ($dispatcher) { $dispatcher->dispatch('bar', $e); }); $dispatcher->addListener('bar', function (Event $e) use (&$nestedCall) { $nestedCall = true; }); $this->assertFalse($nestedCall); $dispatcher->dispatch('foo'); $this->assertTrue($nestedCall); } public function testStopwatchSections() { $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch = new Stopwatch()); $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); }); $request = Request::create('/'); $response = $kernel->handle($request); $kernel->terminate($request, $response); $events = $stopwatch->getSectionEvents($response->headers->get('X-Debug-Token')); $this->assertEquals(array( '__section__', 'kernel.request', 'kernel.request.loading', 'kernel.controller', 'kernel.controller.loading', 'controller', 'kernel.response', 'kernel.response.loading', 'kernel.terminate', 'kernel.terminate.loading', ), array_keys($events)); } public function testStopwatchCheckControllerOnRequestEvent() { $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch') ->setMethods(array('isStarted')) ->getMock(); $stopwatch->expects($this->once()) ->method('isStarted') ->will($this->returnValue(false)); $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch); $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); }); $request = Request::create('/'); $kernel->handle($request); } public function testStopwatchStopControllerOnRequestEvent() { $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch') ->setMethods(array('isStarted', 'stop', 'stopSection')) ->getMock(); $stopwatch->expects($this->once()) ->method('isStarted') ->will($this->returnValue(true)); $stopwatch->expects($this->once()) ->method('stop'); $stopwatch->expects($this->once()) ->method('stopSection'); $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch); $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); }); $request = Request::create('/'); $kernel->handle($request); } protected function getHttpKernel($dispatcher, $controller) { $resolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface'); $resolver->expects($this->once())->method('getController')->will($this->returnValue($controller)); $resolver->expects($this->once())->method('getArguments')->will($this->returnValue(array())); return new HttpKernel($dispatcher, $resolver); } } class EventSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents() { return array('foo' => 'call'); } } PK!!/ / Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/FragmentListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\EventListener; use Symfony\Component\HttpKernel\EventListener\FragmentListener; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\UriSigner; class FragmentListenerTest extends \PHPUnit_Framework_TestCase { public function testOnlyTriggeredOnFragmentRoute() { $request = Request::create('http://example.com/foo?_path=foo%3Dbar%26_controller%3Dfoo'); $listener = new FragmentListener(new UriSigner('foo')); $event = $this->createGetResponseEvent($request); $expected = $request->attributes->all(); $listener->onKernelRequest($event); $this->assertEquals($expected, $request->attributes->all()); $this->assertTrue($request->query->has('_path')); } /** * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException */ public function testAccessDeniedWithNonSafeMethods() { $request = Request::create('http://example.com/_fragment', 'POST'); $listener = new FragmentListener(new UriSigner('foo')); $event = $this->createGetResponseEvent($request); $listener->onKernelRequest($event); } /** * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException */ public function testAccessDeniedWithNonLocalIps() { $request = Request::create('http://example.com/_fragment', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1')); $listener = new FragmentListener(new UriSigner('foo')); $event = $this->createGetResponseEvent($request); $listener->onKernelRequest($event); } /** * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException */ public function testAccessDeniedWithWrongSignature() { $request = Request::create('http://example.com/_fragment', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1')); $listener = new FragmentListener(new UriSigner('foo')); $event = $this->createGetResponseEvent($request); $listener->onKernelRequest($event); } public function testWithSignature() { $signer = new UriSigner('foo'); $request = Request::create($signer->sign('http://example.com/_fragment?_path=foo%3Dbar%26_controller%3Dfoo'), 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1')); $listener = new FragmentListener($signer); $event = $this->createGetResponseEvent($request); $listener->onKernelRequest($event); $this->assertEquals(array('foo' => 'bar', '_controller' => 'foo'), $request->attributes->get('_route_params')); $this->assertFalse($request->query->has('_path')); } private function createGetResponseEvent(Request $request) { return new GetResponseEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST); } } PK!W:ttZtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\EventListener; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\EventListener\ExceptionListener; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Tests\Logger; /** * ExceptionListenerTest * * @author Robert Schönthal */ class ExceptionListenerTest extends \PHPUnit_Framework_TestCase { public function testConstruct() { $logger = new TestLogger(); $l = new ExceptionListener('foo', $logger); $_logger = new \ReflectionProperty(get_class($l), 'logger'); $_logger->setAccessible(true); $_controller = new \ReflectionProperty(get_class($l), 'controller'); $_controller->setAccessible(true); $this->assertSame($logger, $_logger->getValue($l)); $this->assertSame('foo', $_controller->getValue($l)); } /** * @dataProvider provider */ public function testHandleWithoutLogger($event, $event2) { // store the current error_log, and disable it temporarily $errorLog = ini_set('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul'); $l = new ExceptionListener('foo'); $l->onKernelException($event); $this->assertEquals(new Response('foo'), $event->getResponse()); try { $l->onKernelException($event2); } catch (\Exception $e) { $this->assertSame('foo', $e->getMessage()); } // restore the old error_log ini_set('error_log', $errorLog); } /** * @dataProvider provider */ public function testHandleWithLogger($event, $event2) { $logger = new TestLogger(); $l = new ExceptionListener('foo', $logger); $l->onKernelException($event); $this->assertEquals(new Response('foo'), $event->getResponse()); try { $l->onKernelException($event2); } catch (\Exception $e) { $this->assertSame('foo', $e->getMessage()); } $this->assertEquals(3, $logger->countErrors()); $this->assertCount(3, $logger->getLogs('critical')); } public function provider() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { return array(array(null, null)); } $request = new Request(); $exception = new \Exception('foo'); $event = new GetResponseForExceptionEvent(new TestKernel(), $request, 'foo', $exception); $event2 = new GetResponseForExceptionEvent(new TestKernelThatThrowsException(), $request, 'foo', $exception); return array( array($event, $event2) ); } public function testSubRequestFormat() { $listener = new ExceptionListener('foo', $this->getMock('Psr\Log\LoggerInterface')); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { return new Response($request->getRequestFormat()); })); $request = Request::create('/'); $request->setRequestFormat('xml'); $event = new GetResponseForExceptionEvent($kernel, $request, 'foo', new \Exception('foo')); $listener->onKernelException($event); $response = $event->getResponse(); $this->assertEquals('xml', $response->getContent()); } } class TestLogger extends Logger implements DebugLoggerInterface { public function countErrors() { return count($this->logs['critical']); } } class TestKernel implements HttpKernelInterface { public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) { return new Response('foo'); } } class TestKernelThatThrowsException implements HttpKernelInterface { public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) { throw new \Exception('bar'); } } PK!(kkYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\EventListener; use Symfony\Component\HttpKernel\EventListener\ProfilerListener; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\PostResponseEvent; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Kernel; class ProfilerListenerTest extends \PHPUnit_Framework_TestCase { /** * Test to ensure BC without RequestStack * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function testEventsWithoutRequestStack() { $profile = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profile') ->disableOriginalConstructor() ->getMock(); $profiler = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler') ->disableOriginalConstructor() ->getMock(); $profiler->expects($this->once()) ->method('collect') ->will($this->returnValue($profile)); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request') ->disableOriginalConstructor() ->getMock(); $response = $this->getMockBuilder('Symfony\Component\HttpFoundation\Response') ->disableOriginalConstructor() ->getMock(); $listener = new ProfilerListener($profiler); $listener->onKernelRequest(new GetResponseEvent($kernel, $request, Kernel::MASTER_REQUEST)); $listener->onKernelResponse(new FilterResponseEvent($kernel, $request, Kernel::MASTER_REQUEST, $response)); $listener->onKernelTerminate(new PostResponseEvent($kernel, $request, $response)); } /** * Test a master and sub request with an exception and `onlyException` profiler option enabled. */ public function testKernelTerminate() { $profile = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profile') ->disableOriginalConstructor() ->getMock(); $profiler = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler') ->disableOriginalConstructor() ->getMock(); $profiler->expects($this->once()) ->method('collect') ->will($this->returnValue($profile)); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $masterRequest = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request') ->disableOriginalConstructor() ->getMock(); $subRequest = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request') ->disableOriginalConstructor() ->getMock(); $response = $this->getMockBuilder('Symfony\Component\HttpFoundation\Response') ->disableOriginalConstructor() ->getMock(); $onlyException = true; $listener = new ProfilerListener($profiler, null, $onlyException); // master request $listener->onKernelRequest(new GetResponseEvent($kernel, $masterRequest, Kernel::MASTER_REQUEST)); $listener->onKernelResponse(new FilterResponseEvent($kernel, $masterRequest, Kernel::MASTER_REQUEST, $response)); // sub request $listener->onKernelRequest(new GetResponseEvent($kernel, $subRequest, Kernel::SUB_REQUEST)); $listener->onKernelException(new GetResponseForExceptionEvent($kernel, $subRequest, Kernel::SUB_REQUEST, new HttpException(404))); $listener->onKernelResponse(new FilterResponseEvent($kernel, $subRequest, Kernel::SUB_REQUEST, $response)); $listener->onKernelTerminate(new PostResponseEvent($kernel, $masterRequest, $response)); } } PK!=v? Ttest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\EventListener; use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\HttpKernel\EventListener\EsiListener; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcher; class EsiListenerTest extends \PHPUnit_Framework_TestCase { public function testFilterDoesNothingForSubRequests() { $dispatcher = new EventDispatcher(); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $response = new Response('foo '); $listener = new EsiListener(new Esi()); $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control')); } public function testFilterWhenThereIsSomeEsiIncludes() { $dispatcher = new EventDispatcher(); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $response = new Response('foo '); $listener = new EsiListener(new Esi()); $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->assertEquals('content="ESI/1.0"', $event->getResponse()->headers->get('Surrogate-Control')); } public function testFilterWhenThereIsNoEsiIncludes() { $dispatcher = new EventDispatcher(); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $response = new Response('foo'); $listener = new EsiListener(new Esi()); $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control')); } } PK!p66Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\EventListener; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\EventListener\RouterListener; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Routing\RequestContext; class RouterListenerTest extends \PHPUnit_Framework_TestCase { private $requestStack; public function setUp() { $this->requestStack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array(), array(), '', false); } /** * @dataProvider getPortData */ public function testPort($defaultHttpPort, $defaultHttpsPort, $uri, $expectedHttpPort, $expectedHttpsPort) { $urlMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface') ->disableOriginalConstructor() ->getMock(); $context = new RequestContext(); $context->setHttpPort($defaultHttpPort); $context->setHttpsPort($defaultHttpsPort); $urlMatcher->expects($this->any()) ->method('getContext') ->will($this->returnValue($context)); $listener = new RouterListener($urlMatcher, null, null, $this->requestStack); $event = $this->createGetResponseEventForUri($uri); $listener->onKernelRequest($event); $this->assertEquals($expectedHttpPort, $context->getHttpPort()); $this->assertEquals($expectedHttpsPort, $context->getHttpsPort()); $this->assertEquals(0 === strpos($uri, 'https') ? 'https' : 'http', $context->getScheme()); } public function getPortData() { return array( array(80, 443, 'http://localhost/', 80, 443), array(80, 443, 'http://localhost:90/', 90, 443), array(80, 443, 'https://localhost/', 80, 443), array(80, 443, 'https://localhost:90/', 80, 90), ); } /** * @param string $uri * * @return GetResponseEvent */ private function createGetResponseEventForUri($uri) { $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $request = Request::create($uri); $request->attributes->set('_controller', null); // Prevents going in to routing process return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); } /** * @expectedException \InvalidArgumentException */ public function testInvalidMatcher() { new RouterListener(new \stdClass(), null, null, $this->requestStack); } public function testRequestMatcher() { $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $request = Request::create('http://localhost/'); $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); $requestMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface'); $requestMatcher->expects($this->once()) ->method('matchRequest') ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) ->will($this->returnValue(array())); $listener = new RouterListener($requestMatcher, new RequestContext(), null, $this->requestStack); $listener->onKernelRequest($event); } public function testSubRequestWithDifferentMethod() { $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $request = Request::create('http://localhost/', 'post'); $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); $requestMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface'); $requestMatcher->expects($this->any()) ->method('matchRequest') ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) ->will($this->returnValue(array())); $context = new RequestContext(); $requestMatcher->expects($this->any()) ->method('getContext') ->will($this->returnValue($context)); $listener = new RouterListener($requestMatcher, new RequestContext(), null, $this->requestStack); $listener->onKernelRequest($event); // sub-request with another HTTP method $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $request = Request::create('http://localhost/', 'get'); $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST); $listener->onKernelRequest($event); $this->assertEquals('GET', $context->getMethod()); } } PK!uu\test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\EventListener; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * SessionListenerTest. * * Tests SessionListener. * * @author Bulat Shakirzyanov */ class TestSessionListenerTest extends \PHPUnit_Framework_TestCase { /** * @var TestSessionListener */ private $listener; /** * @var SessionInterface */ private $session; protected function setUp() { $this->listener = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\EventListener\TestSessionListener'); $this->session = $this->getSession(); } public function testShouldSaveMasterRequestSession() { $this->sessionHasBeenStarted(); $this->sessionMustBeSaved(); $this->filterResponse(new Request()); } public function testShouldNotSaveSubRequestSession() { $this->sessionMustNotBeSaved(); $this->filterResponse(new Request(), HttpKernelInterface::SUB_REQUEST); } public function testDoesNotDeleteCookieIfUsingSessionLifetime() { $this->sessionHasBeenStarted(); $params = session_get_cookie_params(); session_set_cookie_params(0, $params['path'], $params['domain'], $params['secure'], $params['httponly']); $response = $this->filterResponse(new Request(), HttpKernelInterface::MASTER_REQUEST); $cookies = $response->headers->getCookies(); $this->assertEquals(0, reset($cookies)->getExpiresTime()); } public function testUnstartedSessionIsNotSave() { $this->sessionHasNotBeenStarted(); $this->sessionMustNotBeSaved(); $this->filterResponse(new Request()); } private function filterResponse(Request $request, $type = HttpKernelInterface::MASTER_REQUEST) { $request->setSession($this->session); $response = new Response(); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $event = new FilterResponseEvent($kernel, $request, $type, $response); $this->listener->onKernelResponse($event); $this->assertSame($response, $event->getResponse()); return $response; } private function sessionMustNotBeSaved() { $this->session->expects($this->never()) ->method('save'); } private function sessionMustBeSaved() { $this->session->expects($this->once()) ->method('save'); } private function sessionHasBeenStarted() { $this->session->expects($this->once()) ->method('isStarted') ->will($this->returnValue(true)); } private function sessionHasNotBeenStarted() { $this->session->expects($this->once()) ->method('isStarted') ->will($this->returnValue(false)); } private function getSession() { $mock = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session') ->disableOriginalConstructor() ->getMock(); // set return value for getName() $mock->expects($this->any())->method('getName')->will($this->returnValue('MOCKSESSID')); return $mock; } } PK!,ph h Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\EventListener; use Symfony\Component\HttpKernel\EventListener\ResponseListener; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventDispatcher; class ResponseListenerTest extends \PHPUnit_Framework_TestCase { private $dispatcher; private $kernel; protected function setUp() { $this->dispatcher = new EventDispatcher(); $listener = new ResponseListener('UTF-8'); $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); $this->kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); } protected function tearDown() { $this->dispatcher = null; $this->kernel = null; } public function testFilterDoesNothingForSubRequests() { $response = new Response('foo'); $event = new FilterResponseEvent($this->kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response); $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->assertEquals('', $event->getResponse()->headers->get('content-type')); } public function testFilterSetsNonDefaultCharsetIfNotOverridden() { $listener = new ResponseListener('ISO-8859-15'); $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1); $response = new Response('foo'); $event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response); $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->assertEquals('ISO-8859-15', $response->getCharset()); } public function testFilterDoesNothingIfCharsetIsOverridden() { $listener = new ResponseListener('ISO-8859-15'); $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1); $response = new Response('foo'); $response->setCharset('ISO-8859-1'); $event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response); $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->assertEquals('ISO-8859-1', $response->getCharset()); } public function testFiltersSetsNonDefaultCharsetIfNotOverriddenOnNonTextContentType() { $listener = new ResponseListener('ISO-8859-15'); $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1); $response = new Response('foo'); $request = Request::create('/'); $request->setRequestFormat('application/json'); $event = new FilterResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->assertEquals('ISO-8859-15', $response->getCharset()); } } PK!K(^Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\EventListener; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\EventListener\LocaleListener; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; class LocaleListenerTest extends \PHPUnit_Framework_TestCase { private $requestStack; protected function setUp() { $this->requestStack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array(), array(), '', false); } public function testDefaultLocaleWithoutSession() { $listener = new LocaleListener('fr', null, $this->requestStack); $event = $this->getEvent($request = Request::create('/')); $listener->onKernelRequest($event); $this->assertEquals('fr', $request->getLocale()); } public function testLocaleFromRequestAttribute() { $request = Request::create('/'); session_name('foo'); $request->cookies->set('foo', 'value'); $request->attributes->set('_locale', 'es'); $listener = new LocaleListener('fr', null, $this->requestStack); $event = $this->getEvent($request); $listener->onKernelRequest($event); $this->assertEquals('es', $request->getLocale()); } public function testLocaleSetForRoutingContext() { // the request context is updated $context = $this->getMock('Symfony\Component\Routing\RequestContext'); $context->expects($this->once())->method('setParameter')->with('_locale', 'es'); $router = $this->getMock('Symfony\Component\Routing\Router', array('getContext'), array(), '', false); $router->expects($this->once())->method('getContext')->will($this->returnValue($context)); $request = Request::create('/'); $request->attributes->set('_locale', 'es'); $listener = new LocaleListener('fr', $router, $this->requestStack); $listener->onKernelRequest($this->getEvent($request)); } public function testRouterResetWithParentRequestOnKernelFinishRequest() { if (!class_exists('Symfony\Component\Routing\Router')) { $this->markTestSkipped('The "Routing" component is not available'); } // the request context is updated $context = $this->getMock('Symfony\Component\Routing\RequestContext'); $context->expects($this->once())->method('setParameter')->with('_locale', 'es'); $router = $this->getMock('Symfony\Component\Routing\Router', array('getContext'), array(), '', false); $router->expects($this->once())->method('getContext')->will($this->returnValue($context)); $parentRequest = Request::create('/'); $parentRequest->setLocale('es'); $this->requestStack->expects($this->once())->method('getParentRequest')->will($this->returnValue($parentRequest)); $event = $this->getMock('Symfony\Component\HttpKernel\Event\FinishRequestEvent', array(), array(), '', false); $listener = new LocaleListener('fr', $router, $this->requestStack); $listener->onKernelFinishRequest($event); } public function testRequestLocaleIsNotOverridden() { $request = Request::create('/'); $request->setLocale('de'); $listener = new LocaleListener('fr', null, $this->requestStack); $event = $this->getEvent($request); $listener->onKernelRequest($event); $this->assertEquals('de', $request->getLocale()); } private function getEvent(Request $request) { return new GetResponseEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST); } } PK!oM\test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fragment; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\Fragment\HIncludeFragmentRenderer; use Symfony\Component\HttpKernel\UriSigner; use Symfony\Component\HttpFoundation\Request; class HIncludeFragmentRendererTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \LogicException */ public function testRenderExceptionWhenControllerAndNoSigner() { $strategy = new HIncludeFragmentRenderer(); $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/')); } public function testRenderWithControllerAndSigner() { $strategy = new HIncludeFragmentRenderer(null, new UriSigner('foo')); $this->assertEquals('', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent()); } public function testRenderWithUri() { $strategy = new HIncludeFragmentRenderer(); $this->assertEquals('', $strategy->render('/foo', Request::create('/'))->getContent()); $strategy = new HIncludeFragmentRenderer(null, new UriSigner('foo')); $this->assertEquals('', $strategy->render('/foo', Request::create('/'))->getContent()); } public function testRenderWithDefault() { // only default $strategy = new HIncludeFragmentRenderer(); $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent()); // only global default $strategy = new HIncludeFragmentRenderer(null, null, 'global_default'); $this->assertEquals('global_default', $strategy->render('/foo', Request::create('/'), array())->getContent()); // global default and default $strategy = new HIncludeFragmentRenderer(null, null, 'global_default'); $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent()); } public function testRenderWithAttributesOptions() { // with id $strategy = new HIncludeFragmentRenderer(); $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'id' => 'bar'))->getContent()); // with attributes $strategy = new HIncludeFragmentRenderer(); $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'attributes' => array('p1' => 'v1', 'p2' => 'v2')))->getContent()); // with id & attributes $strategy = new HIncludeFragmentRenderer(); $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'id' => 'bar', 'attributes' => array('p1' => 'v1', 'p2' => 'v2')))->getContent()); } public function testRenderWithDefaultText() { $engine = $this->getMock('Symfony\\Component\\Templating\\EngineInterface'); $engine->expects($this->once()) ->method('exists') ->with('default') ->will($this->throwException(new \InvalidArgumentException())); // only default $strategy = new HIncludeFragmentRenderer($engine); $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent()); } } PK! ((\test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerReference; class RoutableFragmentRendererTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getGenerateFragmentUriData */ public function testGenerateFragmentUri($uri, $controller) { $this->assertEquals($uri, $this->callGenerateFragmentUriMethod($controller, Request::create('/'))); } /** * @dataProvider getGenerateFragmentUriData */ public function testGenerateAbsoluteFragmentUri($uri, $controller) { $this->assertEquals('http://localhost'.$uri, $this->callGenerateFragmentUriMethod($controller, Request::create('/'), true)); } public function getGenerateFragmentUriData() { return array( array('/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array(), array())), array('/_fragment?_path=_format%3Dxml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('_format' => 'xml'), array())), array('/_fragment?_path=foo%3Dfoo%26_format%3Djson%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => 'foo', '_format' => 'json'), array())), array('/_fragment?bar=bar&_path=foo%3Dfoo%26_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => 'foo'), array('bar' => 'bar'))), array('/_fragment?foo=foo&_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array(), array('foo' => 'foo'))), array('/_fragment?_path=foo%255B0%255D%3Dfoo%26foo%255B1%255D%3Dbar%26_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => array('foo', 'bar')), array())), ); } public function testGenerateFragmentUriWithARequest() { $request = Request::create('/'); $request->attributes->set('_format', 'json'); $request->setLocale('fr'); $controller = new ControllerReference('controller', array(), array()); $this->assertEquals('/_fragment?_path=_format%3Djson%26_locale%3Dfr%26_controller%3Dcontroller', $this->callGenerateFragmentUriMethod($controller, $request)); } /** * @expectedException LogicException * @dataProvider getGenerateFragmentUriDataWithNonScalar */ public function testGenerateFragmentUriWithNonScalar($controller) { $this->callGenerateFragmentUriMethod($controller, Request::create('/')); } public function getGenerateFragmentUriDataWithNonScalar() { return array( array(new ControllerReference('controller', array('foo' => new Foo(), 'bar' => 'bar'), array())), array(new ControllerReference('controller', array('foo' => array('foo' => 'foo'), 'bar' => array('bar' => new Foo())), array())), ); } private function callGenerateFragmentUriMethod(ControllerReference $reference, Request $request, $absolute = false) { $renderer = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\Fragment\RoutableFragmentRenderer'); $r = new \ReflectionObject($renderer); $m = $r->getMethod('generateFragmentUri'); $m->setAccessible(true); return $m->invoke($renderer, $reference, $request, $absolute); } } class Foo { public $foo; public function getFoo() { return $this->foo; } } PK!vZtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fragment; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\EventDispatcher\EventDispatcher; class InlineFragmentRendererTest extends \PHPUnit_Framework_TestCase { public function testRender() { $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo')))); $this->assertEquals('foo', $strategy->render('/', Request::create('/'))->getContent()); } public function testRenderWithControllerReference() { $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo')))); $this->assertEquals('foo', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent()); } public function testRenderWithObjectsAsAttributes() { $object = new \stdClass(); $subRequest = Request::create('/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dmain_controller'); $subRequest->attributes->replace(array('object' => $object, '_format' => 'html', '_controller' => 'main_controller', '_locale' => 'en')); $subRequest->headers->set('x-forwarded-for', array('127.0.0.1')); $subRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($subRequest)); $strategy->render(new ControllerReference('main_controller', array('object' => $object), array()), Request::create('/')); } public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheController() { $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver', array('getController')); $resolver ->expects($this->once()) ->method('getController') ->will($this->returnValue(function (\stdClass $object, Bar $object1) { return new Response($object1->getBar()); })) ; $kernel = new HttpKernel(new EventDispatcher(), $resolver); $renderer = new InlineFragmentRenderer($kernel); $response = $renderer->render(new ControllerReference('main_controller', array('object' => new \stdClass(), 'object1' => new Bar()), array()), Request::create('/')); $this->assertEquals('bar', $response->getContent()); } public function testRenderWithTrustedHeaderDisabled() { $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP); Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, ''); $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest(Request::create('/'))); $strategy->render('/', Request::create('/')); Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, $trustedHeaderName); } /** * @expectedException \RuntimeException */ public function testRenderExceptionNoIgnoreErrors() { $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $dispatcher->expects($this->never())->method('dispatch'); $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher); $this->assertEquals('foo', $strategy->render('/', Request::create('/'))->getContent()); } public function testRenderExceptionIgnoreErrors() { $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $dispatcher->expects($this->once())->method('dispatch')->with(KernelEvents::EXCEPTION); $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher); $this->assertEmpty($strategy->render('/', Request::create('/'), array('ignore_errors' => true))->getContent()); } public function testRenderExceptionIgnoreErrorsWithAlt() { $strategy = new InlineFragmentRenderer($this->getKernel($this->onConsecutiveCalls( $this->throwException(new \RuntimeException('foo')), $this->returnValue(new Response('bar')) ))); $this->assertEquals('bar', $strategy->render('/', Request::create('/'), array('ignore_errors' => true, 'alt' => '/foo'))->getContent()); } private function getKernel($returnValue) { $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $kernel ->expects($this->any()) ->method('handle') ->will($returnValue) ; return $kernel; } /** * Creates a Kernel expecting a request equals to $request * Allows delta in comparison in case REQUEST_TIME changed by 1 second */ private function getKernelExpectingRequest(Request $request) { $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $kernel ->expects($this->any()) ->method('handle') ->with($this->equalTo($request, 1)) ; return $kernel; } public function testExceptionInSubRequestsDoesNotMangleOutputBuffers() { $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface'); $resolver ->expects($this->once()) ->method('getController') ->will($this->returnValue(function () { ob_start(); echo 'bar'; throw new \RuntimeException(); })) ; $resolver ->expects($this->once()) ->method('getArguments') ->will($this->returnValue(array())) ; $kernel = new HttpKernel(new EventDispatcher(), $resolver); $renderer = new InlineFragmentRenderer($kernel); // simulate a main request with output buffering ob_start(); echo 'Foo'; // simulate a sub-request with output buffering and an exception $renderer->render('/', Request::create('/'), array('ignore_errors' => true)); $this->assertEquals('Foo', ob_get_clean()); } public function testESIHeaderIsKeptInSubrequest() { $expectedSubRequest = Request::create('/'); $expectedSubRequest->headers->set('Surrogate-Capability', 'abc="ESI/1.0"'); if (Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)) { $expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1')); $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); } $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest)); $request = Request::create('/'); $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"'); $strategy->render('/', $request); } public function testESIHeaderIsKeptInSubrequestWithTrustedHeaderDisabled() { $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP); Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, ''); $this->testESIHeaderIsKeptInSubrequest(); Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, $trustedHeaderName); } } class Bar { public $bar = 'bar'; public function getBar() { return $this->bar; } } PK!; Stest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fragment; use Symfony\Component\HttpKernel\Fragment\FragmentHandler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class FragmentHandlerTest extends \PHPUnit_Framework_TestCase { private $requestStack; public function setUp() { $this->requestStack = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\RequestStack') ->disableOriginalConstructor() ->getMock() ; $this->requestStack ->expects($this->any()) ->method('getCurrentRequest') ->will($this->returnValue(Request::create('/'))) ; } /** * @expectedException \InvalidArgumentException */ public function testRenderWhenRendererDoesNotExist() { $handler = new FragmentHandler(array(), null, $this->requestStack); $handler->render('/', 'foo'); } /** * @expectedException \InvalidArgumentException */ public function testRenderWithUnknownRenderer() { $handler = $this->getHandler($this->returnValue(new Response('foo'))); $handler->render('/', 'bar'); } /** * @expectedException \RuntimeException * @expectedExceptionMessage Error when rendering "http://localhost/" (Status code is 404). */ public function testDeliverWithUnsuccessfulResponse() { $handler = $this->getHandler($this->returnValue(new Response('foo', 404))); $handler->render('/', 'foo'); } public function testRender() { $handler = $this->getHandler($this->returnValue(new Response('foo')), array('/', Request::create('/'), array('foo' => 'foo', 'ignore_errors' => true))); $this->assertEquals('foo', $handler->render('/', 'foo', array('foo' => 'foo'))); } protected function getHandler($returnValue, $arguments = array()) { $renderer = $this->getMock('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface'); $renderer ->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')) ; $e = $renderer ->expects($this->any()) ->method('render') ->will($returnValue) ; if ($arguments) { call_user_func_array(array($e, 'with'), $arguments); } $handler = new FragmentHandler(array(), null, $this->requestStack); $handler->addRenderer($renderer); return $handler; } } PK!҃ Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Fragment; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer; use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\HttpFoundation\Request; class EsiFragmentRendererTest extends \PHPUnit_Framework_TestCase { public function testRenderFallbackToInlineStrategyIfNoRequest() { $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(true)); $strategy->render('/', Request::create('/')); } public function testRenderFallbackToInlineStrategyIfEsiNotSupported() { $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(true)); $strategy->render('/', Request::create('/')); } public function testRender() { $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy()); $request = Request::create('/'); $request->setLocale('fr'); $request->headers->set('Surrogate-Capability', 'ESI/1.0'); $this->assertEquals('', $strategy->render('/', $request)->getContent()); $this->assertEquals("\n", $strategy->render('/', $request, array('comment' => 'This is a comment'))->getContent()); $this->assertEquals('', $strategy->render('/', $request, array('alt' => 'foo'))->getContent()); $this->assertEquals('', $strategy->render(new ControllerReference('main_controller', array(), array()), $request, array('alt' => new ControllerReference('alt_controller', array(), array())))->getContent()); } private function getInlineStrategy($called = false) { $inline = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer')->disableOriginalConstructor()->getMock(); if ($called) { $inline->expects($this->once())->method('render'); } return $inline; } } PK!p =test/HttpKernel/Symfony/Component/HttpKernel/Tests/Logger.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests; use Psr\Log\LoggerInterface; class Logger implements LoggerInterface { protected $logs; public function __construct() { $this->clear(); } public function getLogs($level = false) { return false === $level ? $this->logs : $this->logs[$level]; } public function clear() { $this->logs = array( 'emergency' => array(), 'alert' => array(), 'critical' => array(), 'error' => array(), 'warning' => array(), 'notice' => array(), 'info' => array(), 'debug' => array(), ); } public function log($level, $message, array $context = array()) { $this->logs[$level][] = $message; } public function emergency($message, array $context = array()) { $this->log('emergency', $message, $context); } public function alert($message, array $context = array()) { $this->log('alert', $message, $context); } public function critical($message, array $context = array()) { $this->log('critical', $message, $context); } public function error($message, array $context = array()) { $this->log('error', $message, $context); } public function warning($message, array $context = array()) { $this->log('warning', $message, $context); } public function notice($message, array $context = array()) { $this->log('notice', $message, $context); } public function info($message, array $context = array()) { $this->log('info', $message, $context); } public function debug($message, array $context = array()) { $this->log('debug', $message, $context); } /** * @deprecated */ public function emerg($message, array $context = array()) { trigger_error('Use emergency() which is PSR-3 compatible', E_USER_DEPRECATED); $this->log('emergency', $message, $context); } /** * @deprecated */ public function crit($message, array $context = array()) { trigger_error('Use critical() which is PSR-3 compatible', E_USER_DEPRECATED); $this->log('critical', $message, $context); } /** * @deprecated */ public function err($message, array $context = array()) { trigger_error('Use error() which is PSR-3 compatible', E_USER_DEPRECATED); $this->log('error', $message, $context); } /** * @deprecated */ public function warn($message, array $context = array()) { trigger_error('Use warning() which is PSR-3 compatible', E_USER_DEPRECATED); $this->log('warning', $message, $context); } } PK!m*Ntest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\HttpCache; use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\StoreInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class HttpCacheTest extends HttpCacheTestCase { public function testTerminateDelegatesTerminationOnlyForTerminableInterface() { $storeMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface') ->disableOriginalConstructor() ->getMock(); // does not implement TerminableInterface $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\HttpKernelInterface') ->disableOriginalConstructor() ->getMock(); $kernelMock->expects($this->never()) ->method('terminate'); $kernel = new HttpCache($kernelMock, $storeMock); $kernel->terminate(Request::create('/'), new Response()); // implements TerminableInterface $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Kernel') ->disableOriginalConstructor() ->setMethods(array('terminate', 'registerBundles', 'registerContainerConfiguration')) ->getMock(); $kernelMock->expects($this->once()) ->method('terminate'); $kernel = new HttpCache($kernelMock, $storeMock); $kernel->terminate(Request::create('/'), new Response()); } public function testPassesOnNonGetHeadRequests() { $this->setNextResponse(200); $this->request('POST', '/'); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); $this->assertTraceContains('pass'); $this->assertFalse($this->response->headers->has('Age')); } public function testInvalidatesOnPostPutDeleteRequests() { foreach (array('post', 'put', 'delete') as $method) { $this->setNextResponse(200); $this->request($method, '/'); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); $this->assertTraceContains('invalidate'); $this->assertTraceContains('pass'); } } public function testDoesNotCacheWithAuthorizationRequestHeaderAndNonPublicResponse() { $this->setNextResponse(200, array('ETag' => '"Foo"')); $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz')); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); $this->assertEquals('private', $this->response->headers->get('Cache-Control')); $this->assertTraceContains('miss'); $this->assertTraceNotContains('store'); $this->assertFalse($this->response->headers->has('Age')); } public function testDoesCacheWithAuthorizationRequestHeaderAndPublicResponse() { $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"Foo"')); $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz')); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertTrue($this->response->headers->has('Age')); $this->assertEquals('public', $this->response->headers->get('Cache-Control')); } public function testDoesNotCacheWithCookieHeaderAndNonPublicResponse() { $this->setNextResponse(200, array('ETag' => '"Foo"')); $this->request('GET', '/', array(), array('foo' => 'bar')); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); $this->assertEquals('private', $this->response->headers->get('Cache-Control')); $this->assertTraceContains('miss'); $this->assertTraceNotContains('store'); $this->assertFalse($this->response->headers->has('Age')); } public function testDoesNotCacheRequestsWithACookieHeader() { $this->setNextResponse(200); $this->request('GET', '/', array(), array('foo' => 'bar')); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); $this->assertEquals('private', $this->response->headers->get('Cache-Control')); $this->assertTraceContains('miss'); $this->assertTraceNotContains('store'); $this->assertFalse($this->response->headers->has('Age')); } public function testRespondsWith304WhenIfModifiedSinceMatchesLastModified() { $time = new \DateTime(); $this->setNextResponse(200, array('Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822), 'Content-Type' => 'text/plain'), 'Hello World'); $this->request('GET', '/', array('HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); $this->assertHttpKernelIsCalled(); $this->assertEquals(304, $this->response->getStatusCode()); $this->assertEquals('', $this->response->headers->get('Content-Type')); $this->assertEmpty($this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); } public function testRespondsWith304WhenIfNoneMatchMatchesETag() { $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '12345', 'Content-Type' => 'text/plain'), 'Hello World'); $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345')); $this->assertHttpKernelIsCalled(); $this->assertEquals(304, $this->response->getStatusCode()); $this->assertEquals('', $this->response->headers->get('Content-Type')); $this->assertTrue($this->response->headers->has('ETag')); $this->assertEmpty($this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); } public function testRespondsWith304OnlyIfIfNoneMatchAndIfModifiedSinceBothMatch() { $time = new \DateTime(); $this->setNextResponse(200, array(), '', function ($request, $response) use ($time) { $response->setStatusCode(200); $response->headers->set('ETag', '12345'); $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); $response->headers->set('Content-Type', 'text/plain'); $response->setContent('Hello World'); }); // only ETag matches $t = \DateTime::createFromFormat('U', time() - 3600); $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $t->format(DATE_RFC2822))); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); // only Last-Modified matches $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '1234', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); // Both matches $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); $this->assertHttpKernelIsCalled(); $this->assertEquals(304, $this->response->getStatusCode()); } public function testValidatesPrivateResponsesCachedOnTheClient() { $this->setNextResponse(200, array(), '', function ($request, $response) { $etags = preg_split('/\s*,\s*/', $request->headers->get('IF_NONE_MATCH')); if ($request->cookies->has('authenticated')) { $response->headers->set('Cache-Control', 'private, no-store'); $response->setETag('"private tag"'); if (in_array('"private tag"', $etags)) { $response->setStatusCode(304); } else { $response->setStatusCode(200); $response->headers->set('Content-Type', 'text/plain'); $response->setContent('private data'); } } else { $response->headers->set('Cache-Control', 'public'); $response->setETag('"public tag"'); if (in_array('"public tag"', $etags)) { $response->setStatusCode(304); } else { $response->setStatusCode(200); $response->headers->set('Content-Type', 'text/plain'); $response->setContent('public data'); } } }); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('"public tag"', $this->response->headers->get('ETag')); $this->assertEquals('public data', $this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->request('GET', '/', array(), array('authenticated' => '')); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('"private tag"', $this->response->headers->get('ETag')); $this->assertEquals('private data', $this->response->getContent()); $this->assertTraceContains('stale'); $this->assertTraceContains('invalid'); $this->assertTraceNotContains('store'); } public function testStoresResponsesWhenNoCacheRequestDirectivePresent() { $time = \DateTime::createFromFormat('U', time() + 5); $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); $this->assertHttpKernelIsCalled(); $this->assertTraceContains('store'); $this->assertTrue($this->response->headers->has('Age')); } public function testReloadsResponsesWhenCacheHitsButNoCacheRequestDirectivePresentWhenAllowReloadIsSetTrue() { $count = 0; $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) { ++$count; $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); }); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('store'); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('fresh'); $this->cacheConfig['allow_reload'] = true; $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Goodbye World', $this->response->getContent()); $this->assertTraceContains('reload'); $this->assertTraceContains('store'); } public function testDoesNotReloadResponsesWhenAllowReloadIsSetFalseDefault() { $count = 0; $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) { ++$count; $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); }); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('store'); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('fresh'); $this->cacheConfig['allow_reload'] = false; $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceNotContains('reload'); $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceNotContains('reload'); } public function testRevalidatesFreshCacheEntryWhenMaxAgeRequestDirectiveIsExceededWhenAllowRevalidateOptionIsSetTrue() { $count = 0; $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) { ++$count; $response->headers->set('Cache-Control', 'public, max-age=10000'); $response->setETag($count); $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); }); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('store'); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('fresh'); $this->cacheConfig['allow_revalidate'] = true; $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Goodbye World', $this->response->getContent()); $this->assertTraceContains('stale'); $this->assertTraceContains('invalid'); $this->assertTraceContains('store'); } public function testDoesNotRevalidateFreshCacheEntryWhenEnableRevalidateOptionIsSetFalseDefault() { $count = 0; $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) { ++$count; $response->headers->set('Cache-Control', 'public, max-age=10000'); $response->setETag($count); $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); }); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('store'); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('fresh'); $this->cacheConfig['allow_revalidate'] = false; $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceNotContains('stale'); $this->assertTraceNotContains('invalid'); $this->assertTraceContains('fresh'); $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceNotContains('stale'); $this->assertTraceNotContains('invalid'); $this->assertTraceContains('fresh'); } public function testFetchesResponseFromBackendWhenCacheMisses() { $time = \DateTime::createFromFormat('U', time() + 5); $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTraceContains('miss'); $this->assertTrue($this->response->headers->has('Age')); } public function testDoesNotCacheSomeStatusCodeResponses() { foreach (array_merge(range(201, 202), range(204, 206), range(303, 305), range(400, 403), range(405, 409), range(411, 417), range(500, 505)) as $code) { $time = \DateTime::createFromFormat('U', time() + 5); $this->setNextResponse($code, array('Expires' => $time->format(DATE_RFC2822))); $this->request('GET', '/'); $this->assertEquals($code, $this->response->getStatusCode()); $this->assertTraceNotContains('store'); $this->assertFalse($this->response->headers->has('Age')); } } public function testDoesNotCacheResponsesWithExplicitNoStoreDirective() { $time = \DateTime::createFromFormat('U', time() + 5); $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'no-store')); $this->request('GET', '/'); $this->assertTraceNotContains('store'); $this->assertFalse($this->response->headers->has('Age')); } public function testDoesNotCacheResponsesWithoutFreshnessInformationOrAValidator() { $this->setNextResponse(); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTraceNotContains('store'); } public function testCachesResponsesWithExplicitNoCacheDirective() { $time = \DateTime::createFromFormat('U', time() + 5); $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, no-cache')); $this->request('GET', '/'); $this->assertTraceContains('store'); $this->assertTrue($this->response->headers->has('Age')); } public function testCachesResponsesWithAnExpirationHeader() { $time = \DateTime::createFromFormat('U', time() + 5); $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertNotNull($this->response->headers->get('Date')); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $values = $this->getMetaStorageValues(); $this->assertCount(1, $values); } public function testCachesResponsesWithAMaxAgeDirective() { $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=5')); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertNotNull($this->response->headers->get('Date')); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $values = $this->getMetaStorageValues(); $this->assertCount(1, $values); } public function testCachesResponsesWithASMaxAgeDirective() { $this->setNextResponse(200, array('Cache-Control' => 's-maxage=5')); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertNotNull($this->response->headers->get('Date')); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $values = $this->getMetaStorageValues(); $this->assertCount(1, $values); } public function testCachesResponsesWithALastModifiedValidatorButNoFreshnessInformation() { $time = \DateTime::createFromFormat('U', time()); $this->setNextResponse(200, array('Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822))); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); } public function testCachesResponsesWithAnETagValidatorButNoFreshnessInformation() { $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"123456"')); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); } public function testHitsCachedResponsesWithExpiresHeader() { $time1 = \DateTime::createFromFormat('U', time() - 5); $time2 = \DateTime::createFromFormat('U', time() + 5); $this->setNextResponse(200, array('Cache-Control' => 'public', 'Date' => $time1->format(DATE_RFC2822), 'Expires' => $time2->format(DATE_RFC2822))); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertNotNull($this->response->headers->get('Date')); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); $this->request('GET', '/'); $this->assertHttpKernelIsNotCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2); $this->assertTrue($this->response->headers->get('Age') > 0); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertTraceContains('fresh'); $this->assertTraceNotContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); } public function testHitsCachedResponseWithMaxAgeDirective() { $time = \DateTime::createFromFormat('U', time() - 5); $this->setNextResponse(200, array('Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, max-age=10')); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertNotNull($this->response->headers->get('Date')); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); $this->request('GET', '/'); $this->assertHttpKernelIsNotCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2); $this->assertTrue($this->response->headers->get('Age') > 0); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertTraceContains('fresh'); $this->assertTraceNotContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); } public function testHitsCachedResponseWithSMaxAgeDirective() { $time = \DateTime::createFromFormat('U', time() - 5); $this->setNextResponse(200, array('Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 's-maxage=10, max-age=0')); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertNotNull($this->response->headers->get('Date')); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); $this->request('GET', '/'); $this->assertHttpKernelIsNotCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2); $this->assertTrue($this->response->headers->get('Age') > 0); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertTraceContains('fresh'); $this->assertTraceNotContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); } public function testAssignsDefaultTtlWhenResponseHasNoFreshnessInformation() { $this->setNextResponse(); $this->cacheConfig['default_ttl'] = 10; $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertRegExp('/s-maxage=10/', $this->response->headers->get('Cache-Control')); $this->cacheConfig['default_ttl'] = 10; $this->request('GET', '/'); $this->assertHttpKernelIsNotCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTraceContains('fresh'); $this->assertTraceNotContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); } public function testDoesNotAssignDefaultTtlWhenResponseHasMustRevalidateDirective() { $this->setNextResponse(200, array('Cache-Control' => 'must-revalidate')); $this->cacheConfig['default_ttl'] = 10; $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTraceContains('miss'); $this->assertTraceNotContains('store'); $this->assertNotRegExp('/s-maxage/', $this->response->headers->get('Cache-Control')); $this->assertEquals('Hello World', $this->response->getContent()); } public function testFetchesFullResponseWhenCacheStaleAndNoValidatorsPresent() { $time = \DateTime::createFromFormat('U', time() + 5); $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); // build initial request $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertNotNull($this->response->headers->get('Date')); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertNotNull($this->response->headers->get('Age')); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); # go in and play around with the cached metadata directly ... $values = $this->getMetaStorageValues(); $this->assertCount(1, $values); $tmp = unserialize($values[0]); $time = \DateTime::createFromFormat('U', time()); $tmp[0][1]['expires'] = $time->format(DATE_RFC2822); $r = new \ReflectionObject($this->store); $m = $r->getMethod('save'); $m->setAccessible(true); $m->invoke($this->store, 'md'.hash('sha256', 'http://localhost/'), serialize($tmp)); // build subsequent request; should be found but miss due to freshness $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTrue($this->response->headers->get('Age') <= 1); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertTraceContains('stale'); $this->assertTraceNotContains('fresh'); $this->assertTraceNotContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); } public function testValidatesCachedResponsesWithLastModifiedAndNoFreshnessInformation() { $time = \DateTime::createFromFormat('U', time()); $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($time) { $response->headers->set('Cache-Control', 'public'); $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); if ($time->format(DATE_RFC2822) == $request->headers->get('IF_MODIFIED_SINCE')) { $response->setStatusCode(304); $response->setContent(''); } }); // build initial request $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertNotNull($this->response->headers->get('Last-Modified')); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertTraceNotContains('stale'); // build subsequent request; should be found but miss due to freshness $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertNotNull($this->response->headers->get('Last-Modified')); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertTrue($this->response->headers->get('Age') <= 1); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('stale'); $this->assertTraceContains('valid'); $this->assertTraceContains('store'); $this->assertTraceNotContains('miss'); } public function testValidatesCachedResponsesWithETagAndNoFreshnessInformation() { $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) { $response->headers->set('Cache-Control', 'public'); $response->headers->set('ETag', '"12345"'); if ($response->getETag() == $request->headers->get('IF_NONE_MATCH')) { $response->setStatusCode(304); $response->setContent(''); } }); // build initial request $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertNotNull($this->response->headers->get('ETag')); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); // build subsequent request; should be found but miss due to freshness $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertNotNull($this->response->headers->get('ETag')); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $this->assertTrue($this->response->headers->get('Age') <= 1); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('stale'); $this->assertTraceContains('valid'); $this->assertTraceContains('store'); $this->assertTraceNotContains('miss'); } public function testReplacesCachedResponsesWhenValidationResultsInNon304Response() { $time = \DateTime::createFromFormat('U', time()); $count = 0; $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($time, &$count) { $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); $response->headers->set('Cache-Control', 'public'); switch (++$count) { case 1: $response->setContent('first response'); break; case 2: $response->setContent('second response'); break; case 3: $response->setContent(''); $response->setStatusCode(304); break; } }); // first request should fetch from backend and store in cache $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('first response', $this->response->getContent()); // second request is validated, is invalid, and replaces cached entry $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('second response', $this->response->getContent()); // third response is validated, valid, and returns cached entry $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('second response', $this->response->getContent()); $this->assertEquals(3, $count); } public function testPassesHeadRequestsThroughDirectlyOnPass() { $that = $this; $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($that) { $response->setContent(''); $response->setStatusCode(200); $that->assertEquals('HEAD', $request->getMethod()); }); $this->request('HEAD', '/', array('HTTP_EXPECT' => 'something ...')); $this->assertHttpKernelIsCalled(); $this->assertEquals('', $this->response->getContent()); } public function testUsesCacheToRespondToHeadRequestsWhenFresh() { $that = $this; $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($that) { $response->headers->set('Cache-Control', 'public, max-age=10'); $response->setContent('Hello World'); $response->setStatusCode(200); $that->assertNotEquals('HEAD', $request->getMethod()); }); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals('Hello World', $this->response->getContent()); $this->request('HEAD', '/'); $this->assertHttpKernelIsNotCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('', $this->response->getContent()); $this->assertEquals(strlen('Hello World'), $this->response->headers->get('Content-Length')); } public function testSendsNoContentWhenFresh() { $time = \DateTime::createFromFormat('U', time()); $that = $this; $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($that, $time) { $response->headers->set('Cache-Control', 'public, max-age=10'); $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); }); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals('Hello World', $this->response->getContent()); $this->request('GET', '/', array('HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); $this->assertHttpKernelIsNotCalled(); $this->assertEquals(304, $this->response->getStatusCode()); $this->assertEquals('', $this->response->getContent()); } public function testInvalidatesCachedResponsesOnPost() { $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) { if ('GET' == $request->getMethod()) { $response->setStatusCode(200); $response->headers->set('Cache-Control', 'public, max-age=500'); $response->setContent('Hello World'); } elseif ('POST' == $request->getMethod()) { $response->setStatusCode(303); $response->headers->set('Location', '/'); $response->headers->remove('Cache-Control'); $response->setContent(''); } }); // build initial request to enter into the cache $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); // make sure it is valid $this->request('GET', '/'); $this->assertHttpKernelIsNotCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('fresh'); // now POST to same URL $this->request('POST', '/helloworld'); $this->assertHttpKernelIsCalled(); $this->assertEquals('/', $this->response->headers->get('Location')); $this->assertTraceContains('invalidate'); $this->assertTraceContains('pass'); $this->assertEquals('', $this->response->getContent()); // now make sure it was actually invalidated $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceContains('stale'); $this->assertTraceContains('invalid'); $this->assertTraceContains('store'); } public function testServesFromCacheWhenHeadersMatch() { $count = 0; $this->setNextResponse(200, array('Cache-Control' => 'max-age=10000'), '', function ($request, $response) use (&$count) { $response->headers->set('Vary', 'Accept User-Agent Foo'); $response->headers->set('Cache-Control', 'public, max-age=10'); $response->headers->set('X-Response-Count', ++$count); $response->setContent($request->headers->get('USER_AGENT')); }); $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Bob/1.0', $this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Bob/1.0', $this->response->getContent()); $this->assertTraceContains('fresh'); $this->assertTraceNotContains('store'); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); } public function testStoresMultipleResponsesWhenHeadersDiffer() { $count = 0; $this->setNextResponse(200, array('Cache-Control' => 'max-age=10000'), '', function ($request, $response) use (&$count) { $response->headers->set('Vary', 'Accept User-Agent Foo'); $response->headers->set('Cache-Control', 'public, max-age=10'); $response->headers->set('X-Response-Count', ++$count); $response->setContent($request->headers->get('USER_AGENT')); }); $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Bob/1.0', $this->response->getContent()); $this->assertEquals(1, $this->response->headers->get('X-Response-Count')); $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0')); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Bob/2.0', $this->response->getContent()); $this->assertEquals(2, $this->response->headers->get('X-Response-Count')); $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); $this->assertTraceContains('fresh'); $this->assertEquals('Bob/1.0', $this->response->getContent()); $this->assertEquals(1, $this->response->headers->get('X-Response-Count')); $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0')); $this->assertTraceContains('fresh'); $this->assertEquals('Bob/2.0', $this->response->getContent()); $this->assertEquals(2, $this->response->headers->get('X-Response-Count')); $this->request('GET', '/', array('HTTP_USER_AGENT' => 'Bob/2.0')); $this->assertTraceContains('miss'); $this->assertEquals('Bob/2.0', $this->response->getContent()); $this->assertEquals(3, $this->response->headers->get('X-Response-Count')); } public function testShouldCatchExceptions() { $this->catchExceptions(); $this->setNextResponse(); $this->request('GET', '/'); $this->assertExceptionsAreCaught(); } public function testShouldCatchExceptionsWhenReloadingAndNoCacheRequest() { $this->catchExceptions(); $this->setNextResponse(); $this->cacheConfig['allow_reload'] = true; $this->request('GET', '/', array(), array(), false, array('Pragma' => 'no-cache')); $this->assertExceptionsAreCaught(); } public function testShouldNotCatchExceptions() { $this->catchExceptions(false); $this->setNextResponse(); $this->request('GET', '/'); $this->assertExceptionsAreNotCaught(); } public function testEsiCacheSendsTheLowestTtl() { $responses = array( array( 'status' => 200, 'body' => ' ', 'headers' => array( 'Cache-Control' => 's-maxage=300', 'Surrogate-Control' => 'content="ESI/1.0"', ), ), array( 'status' => 200, 'body' => 'Hello World!', 'headers' => array('Cache-Control' => 's-maxage=300'), ), array( 'status' => 200, 'body' => 'My name is Bobby.', 'headers' => array('Cache-Control' => 's-maxage=100'), ), ); $this->setNextResponses($responses); $this->request('GET', '/', array(), array(), true); $this->assertEquals("Hello World! My name is Bobby.", $this->response->getContent()); // check for 100 or 99 as the test can be executed after a second change $this->assertTrue(in_array($this->response->getTtl(), array(99, 100))); } public function testEsiCacheForceValidation() { $responses = array( array( 'status' => 200, 'body' => ' ', 'headers' => array( 'Cache-Control' => 's-maxage=300', 'Surrogate-Control' => 'content="ESI/1.0"', ), ), array( 'status' => 200, 'body' => 'Hello World!', 'headers' => array('ETag' => 'foobar'), ), array( 'status' => 200, 'body' => 'My name is Bobby.', 'headers' => array('Cache-Control' => 's-maxage=100'), ), ); $this->setNextResponses($responses); $this->request('GET', '/', array(), array(), true); $this->assertEquals('Hello World! My name is Bobby.', $this->response->getContent()); $this->assertNull($this->response->getTtl()); $this->assertTrue($this->response->mustRevalidate()); $this->assertTrue($this->response->headers->hasCacheControlDirective('private')); $this->assertTrue($this->response->headers->hasCacheControlDirective('no-cache')); } public function testEsiRecalculateContentLengthHeader() { $responses = array( array( 'status' => 200, 'body' => '', 'headers' => array( 'Content-Length' => 26, 'Cache-Control' => 's-maxage=300', 'Surrogate-Control' => 'content="ESI/1.0"', ), ), array( 'status' => 200, 'body' => 'Hello World!', 'headers' => array(), ), ); $this->setNextResponses($responses); $this->request('GET', '/', array(), array(), true); $this->assertEquals('Hello World!', $this->response->getContent()); $this->assertEquals(12, $this->response->headers->get('Content-Length')); } public function testClientIpIsAlwaysLocalhostForForwardedRequests() { $this->setNextResponse(); $this->request('GET', '/', array('REMOTE_ADDR' => '10.0.0.1')); $this->assertEquals('127.0.0.1', $this->kernel->getBackendRequest()->server->get('REMOTE_ADDR')); } /** * @dataProvider getXForwardedForData */ public function testXForwarderForHeaderForForwardedRequests($xForwardedFor, $expected) { $this->setNextResponse(); $server = array('REMOTE_ADDR' => '10.0.0.1'); if (false !== $xForwardedFor) { $server['HTTP_X_FORWARDED_FOR'] = $xForwardedFor; } $this->request('GET', '/', $server); $this->assertEquals($expected, $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For')); } public function getXForwardedForData() { return array( array(false, '10.0.0.1'), array('10.0.0.2', '10.0.0.2, 10.0.0.1'), array('10.0.0.2, 10.0.0.3', '10.0.0.2, 10.0.0.3, 10.0.0.1'), ); } public function testXForwarderForHeaderForPassRequests() { $this->setNextResponse(); $server = array('REMOTE_ADDR' => '10.0.0.1'); $this->request('POST', '/', $server); $this->assertEquals('10.0.0.1', $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For')); } public function testEsiCacheRemoveValidationHeadersIfEmbeddedResponses() { $time = new \DateTime; $responses = array( array( 'status' => 200, 'body' => '', 'headers' => array( 'Surrogate-Control' => 'content="ESI/1.0"', 'ETag' => 'hey', 'Last-Modified' => $time->format(DATE_RFC2822), ), ), array( 'status' => 200, 'body' => 'Hey!', 'headers' => array(), ), ); $this->setNextResponses($responses); $this->request('GET', '/', array(), array(), true); $this->assertNull($this->response->getETag()); $this->assertNull($this->response->getLastModified()); } } PK!t~ Otest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\HttpCache; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcher; class TestHttpKernel extends HttpKernel implements ControllerResolverInterface { protected $body; protected $status; protected $headers; protected $called = false; protected $customizer; protected $catch = false; protected $backendRequest; public function __construct($body, $status, $headers, \Closure $customizer = null) { $this->body = $body; $this->status = $status; $this->headers = $headers; $this->customizer = $customizer; parent::__construct(new EventDispatcher(), $this); } public function getBackendRequest() { return $this->backendRequest; } public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = false) { $this->catch = $catch; $this->backendRequest = $request; return parent::handle($request, $type, $catch); } public function isCatchingExceptions() { return $this->catch; } public function getController(Request $request) { return array($this, 'callController'); } public function getArguments(Request $request, $controller) { return array($request); } public function callController(Request $request) { $this->called = true; $response = new Response($this->body, $this->status, $this->headers); if (null !== $this->customizer) { call_user_func($this->customizer, $request, $response); } return $response; } public function hasBeenCalled() { return $this->called; } public function reset() { $this->called = false; } } PK!`uNNHtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\HttpCache; use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class EsiTest extends \PHPUnit_Framework_TestCase { public function testHasSurrogateEsiCapability() { $esi = new Esi(); $request = Request::create('/'); $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"'); $this->assertTrue($esi->hasSurrogateEsiCapability($request)); $request = Request::create('/'); $request->headers->set('Surrogate-Capability', 'foobar'); $this->assertFalse($esi->hasSurrogateEsiCapability($request)); $request = Request::create('/'); $this->assertFalse($esi->hasSurrogateEsiCapability($request)); } public function testAddSurrogateEsiCapability() { $esi = new Esi(); $request = Request::create('/'); $esi->addSurrogateEsiCapability($request); $this->assertEquals('symfony2="ESI/1.0"', $request->headers->get('Surrogate-Capability')); $esi->addSurrogateEsiCapability($request); $this->assertEquals('symfony2="ESI/1.0", symfony2="ESI/1.0"', $request->headers->get('Surrogate-Capability')); } public function testAddSurrogateControl() { $esi = new Esi(); $response = new Response('foo '); $esi->addSurrogateControl($response); $this->assertEquals('content="ESI/1.0"', $response->headers->get('Surrogate-Control')); $response = new Response('foo'); $esi->addSurrogateControl($response); $this->assertEquals('', $response->headers->get('Surrogate-Control')); } public function testNeedsEsiParsing() { $esi = new Esi(); $response = new Response(); $response->headers->set('Surrogate-Control', 'content="ESI/1.0"'); $this->assertTrue($esi->needsEsiParsing($response)); $response = new Response(); $this->assertFalse($esi->needsEsiParsing($response)); } public function testRenderIncludeTag() { $esi = new Esi(); $this->assertEquals('', $esi->renderIncludeTag('/', '/alt', true)); $this->assertEquals('', $esi->renderIncludeTag('/', '/alt', false)); $this->assertEquals('', $esi->renderIncludeTag('/')); $this->assertEquals(''."\n".'', $esi->renderIncludeTag('/', '/alt', true, 'some comment')); } public function testProcessDoesNothingIfContentTypeIsNotHtml() { $esi = new Esi(); $request = Request::create('/'); $response = new Response(); $response->headers->set('Content-Type', 'text/plain'); $esi->process($request, $response); $this->assertFalse($response->headers->has('x-body-eval')); } public function testProcess() { $esi = new Esi(); $request = Request::create('/'); $response = new Response('foo '); $esi->process($request, $response); $this->assertEquals('foo esi->handle($this, \'...\', \'alt\', true) ?>'."\n", $response->getContent()); $this->assertEquals('ESI', $response->headers->get('x-body-eval')); $response = new Response('foo '); $esi->process($request, $response); $this->assertEquals('foo esi->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent()); $response = new Response('foo '); $esi->process($request, $response); $this->assertEquals('foo esi->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent()); } public function testProcessEscapesPhpTags() { $esi = new Esi(); $request = Request::create('/'); $response = new Response('foo <%= "lala" %>'); $esi->process($request, $response); $this->assertEquals('foo php die("foo"); ?>= "lala" %>', $response->getContent()); } /** * @expectedException \RuntimeException */ public function testProcessWhenNoSrcInAnEsi() { $esi = new Esi(); $request = Request::create('/'); $response = new Response('foo '); $esi->process($request, $response); } public function testProcessRemoveSurrogateControlHeader() { $esi = new Esi(); $request = Request::create('/'); $response = new Response('foo '); $response->headers->set('Surrogate-Control', 'content="ESI/1.0"'); $esi->process($request, $response); $this->assertEquals('ESI', $response->headers->get('x-body-eval')); $response->headers->set('Surrogate-Control', 'no-store, content="ESI/1.0"'); $esi->process($request, $response); $this->assertEquals('ESI', $response->headers->get('x-body-eval')); $this->assertEquals('no-store', $response->headers->get('surrogate-control')); $response->headers->set('Surrogate-Control', 'content="ESI/1.0", no-store'); $esi->process($request, $response); $this->assertEquals('ESI', $response->headers->get('x-body-eval')); $this->assertEquals('no-store', $response->headers->get('surrogate-control')); } public function testHandle() { $esi = new Esi(); $cache = $this->getCache(Request::create('/'), new Response('foo')); $this->assertEquals('foo', $esi->handle($cache, '/', '/alt', true)); } /** * @expectedException \RuntimeException */ public function testHandleWhenResponseIsNot200() { $esi = new Esi(); $response = new Response('foo'); $response->setStatusCode(404); $cache = $this->getCache(Request::create('/'), $response); $esi->handle($cache, '/', '/alt', false); } public function testHandleWhenResponseIsNot200AndErrorsAreIgnored() { $esi = new Esi(); $response = new Response('foo'); $response->setStatusCode(404); $cache = $this->getCache(Request::create('/'), $response); $this->assertEquals('', $esi->handle($cache, '/', '/alt', true)); } public function testHandleWhenResponseIsNot200AndAltIsPresent() { $esi = new Esi(); $response1 = new Response('foo'); $response1->setStatusCode(404); $response2 = new Response('bar'); $cache = $this->getCache(Request::create('/'), array($response1, $response2)); $this->assertEquals('bar', $esi->handle($cache, '/', '/alt', false)); } protected function getCache($request, $response) { $cache = $this->getMock('Symfony\Component\HttpKernel\HttpCache\HttpCache', array('getRequest', 'handle'), array(), '', false); $cache->expects($this->any()) ->method('getRequest') ->will($this->returnValue($request)) ; if (is_array($response)) { $cache->expects($this->any()) ->method('handle') ->will(call_user_func_array(array($this, 'onConsecutiveCalls'), $response)) ; } else { $cache->expects($this->any()) ->method('handle') ->will($this->returnValue($response)) ; } return $cache; } } PK!JJWtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\HttpCache; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcher; class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInterface { protected $bodies = array(); protected $statuses = array(); protected $headers = array(); protected $call = false; protected $backendRequest; public function __construct($responses) { foreach ($responses as $response) { $this->bodies[] = $response['body']; $this->statuses[] = $response['status']; $this->headers[] = $response['headers']; } parent::__construct(new EventDispatcher(), $this); } public function getBackendRequest() { return $this->backendRequest; } public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = false) { $this->backendRequest = $request; return parent::handle($request, $type, $catch); } public function getController(Request $request) { return array($this, 'callController'); } public function getArguments(Request $request, $controller) { return array($request); } public function callController(Request $request) { $this->called = true; $response = new Response(array_shift($this->bodies), array_shift($this->statuses), array_shift($this->headers)); return $response; } public function hasBeenCalled() { return $this->called; } public function reset() { $this->call = false; } } PK!VPRtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\Store; use Symfony\Component\HttpKernel\HttpKernelInterface; class HttpCacheTestCase extends \PHPUnit_Framework_TestCase { protected $kernel; protected $cache; protected $caches; protected $cacheConfig; protected $request; protected $response; protected $responses; protected $catch; protected $esi; protected function setUp() { $this->kernel = null; $this->cache = null; $this->esi = null; $this->caches = array(); $this->cacheConfig = array(); $this->request = null; $this->response = null; $this->responses = array(); $this->catch = false; $this->clearDirectory(sys_get_temp_dir().'/http_cache'); } protected function tearDown() { $this->kernel = null; $this->cache = null; $this->caches = null; $this->request = null; $this->response = null; $this->responses = null; $this->cacheConfig = null; $this->catch = null; $this->esi = null; $this->clearDirectory(sys_get_temp_dir().'/http_cache'); } public function assertHttpKernelIsCalled() { $this->assertTrue($this->kernel->hasBeenCalled()); } public function assertHttpKernelIsNotCalled() { $this->assertFalse($this->kernel->hasBeenCalled()); } public function assertResponseOk() { $this->assertEquals(200, $this->response->getStatusCode()); } public function assertTraceContains($trace) { $traces = $this->cache->getTraces(); $traces = current($traces); $this->assertRegExp('/'.$trace.'/', implode(', ', $traces)); } public function assertTraceNotContains($trace) { $traces = $this->cache->getTraces(); $traces = current($traces); $this->assertNotRegExp('/'.$trace.'/', implode(', ', $traces)); } public function assertExceptionsAreCaught() { $this->assertTrue($this->kernel->isCatchingExceptions()); } public function assertExceptionsAreNotCaught() { $this->assertFalse($this->kernel->isCatchingExceptions()); } public function request($method, $uri = '/', $server = array(), $cookies = array(), $esi = false, $headers = array()) { if (null === $this->kernel) { throw new \LogicException('You must call setNextResponse() before calling request().'); } $this->kernel->reset(); $this->store = new Store(sys_get_temp_dir().'/http_cache'); $this->cacheConfig['debug'] = true; $this->esi = $esi ? new Esi() : null; $this->cache = new HttpCache($this->kernel, $this->store, $this->esi, $this->cacheConfig); $this->request = Request::create($uri, $method, array(), $cookies, array(), $server); $this->request->headers->add($headers); $this->response = $this->cache->handle($this->request, HttpKernelInterface::MASTER_REQUEST, $this->catch); $this->responses[] = $this->response; } public function getMetaStorageValues() { $values = array(); foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(sys_get_temp_dir().'/http_cache/md', \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { $values[] = file_get_contents($file); } return $values; } // A basic response with 200 status code and a tiny body. public function setNextResponse($statusCode = 200, array $headers = array(), $body = 'Hello World', \Closure $customizer = null) { $this->kernel = new TestHttpKernel($body, $statusCode, $headers, $customizer); } public function setNextResponses($responses) { $this->kernel = new TestMultipleHttpKernel($responses); } public function catchExceptions($catch = true) { $this->catch = $catch; } public static function clearDirectory($directory) { if (!is_dir($directory)) { return; } $fp = opendir($directory); while (false !== $file = readdir($fp)) { if (!in_array($file, array('.', '..'))) { if (is_link($directory.'/'.$file)) { unlink($directory.'/'.$file); } elseif (is_dir($directory.'/'.$file)) { self::clearDirectory($directory.'/'.$file); rmdir($directory.'/'.$file); } else { unlink($directory.'/'.$file); } } } closedir($fp); } } PK!Z&Z&Jtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpCache\Store; class StoreTest extends \PHPUnit_Framework_TestCase { protected $request; protected $response; protected $store; protected function setUp() { $this->request = Request::create('/'); $this->response = new Response('hello world', 200, array()); HttpCacheTestCase::clearDirectory(sys_get_temp_dir().'/http_cache'); $this->store = new Store(sys_get_temp_dir().'/http_cache'); } protected function tearDown() { $this->store = null; $this->request = null; $this->response = null; HttpCacheTestCase::clearDirectory(sys_get_temp_dir().'/http_cache'); } public function testReadsAnEmptyArrayWithReadWhenNothingCachedAtKey() { $this->assertEmpty($this->getStoreMetadata('/nothing')); } public function testUnlockFileThatDoesExist() { $cacheKey = $this->storeSimpleEntry(); $this->store->lock($this->request); $this->assertTrue($this->store->unlock($this->request)); } public function testUnlockFileThatDoesNotExist() { $this->assertFalse($this->store->unlock($this->request)); } public function testRemovesEntriesForKeyWithPurge() { $request = Request::create('/foo'); $this->store->write($request, new Response('foo')); $metadata = $this->getStoreMetadata($request); $this->assertNotEmpty($metadata); $this->assertTrue($this->store->purge('/foo')); $this->assertEmpty($this->getStoreMetadata($request)); // cached content should be kept after purging $path = $this->store->getPath($metadata[0][1]['x-content-digest'][0]); $this->assertTrue(is_file($path)); $this->assertFalse($this->store->purge('/bar')); } public function testStoresACacheEntry() { $cacheKey = $this->storeSimpleEntry(); $this->assertNotEmpty($this->getStoreMetadata($cacheKey)); } public function testSetsTheXContentDigestResponseHeaderBeforeStoring() { $cacheKey = $this->storeSimpleEntry(); $entries = $this->getStoreMetadata($cacheKey); list ($req, $res) = $entries[0]; $this->assertEquals('en9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', $res['x-content-digest'][0]); } public function testFindsAStoredEntryWithLookup() { $this->storeSimpleEntry(); $response = $this->store->lookup($this->request); $this->assertNotNull($response); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); } public function testDoesNotFindAnEntryWithLookupWhenNoneExists() { $request = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); $this->assertNull($this->store->lookup($request)); } public function testCanonizesUrlsForCacheKeys() { $this->storeSimpleEntry($path = '/test?x=y&p=q'); $hitsReq = Request::create($path); $missReq = Request::create('/test?p=x'); $this->assertNotNull($this->store->lookup($hitsReq)); $this->assertNull($this->store->lookup($missReq)); } public function testDoesNotFindAnEntryWithLookupWhenTheBodyDoesNotExist() { $this->storeSimpleEntry(); $this->assertNotNull($this->response->headers->get('X-Content-Digest')); $path = $this->getStorePath($this->response->headers->get('X-Content-Digest')); @unlink($path); $this->assertNull($this->store->lookup($this->request)); } public function testRestoresResponseHeadersProperlyWithLookup() { $this->storeSimpleEntry(); $response = $this->store->lookup($this->request); $this->assertEquals($response->headers->all(), array_merge(array('content-length' => 4, 'x-body-file' => array($this->getStorePath($response->headers->get('X-Content-Digest')))), $this->response->headers->all())); } public function testRestoresResponseContentFromEntityStoreWithLookup() { $this->storeSimpleEntry(); $response = $this->store->lookup($this->request); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test')), $response->getContent()); } public function testInvalidatesMetaAndEntityStoreEntriesWithInvalidate() { $this->storeSimpleEntry(); $this->store->invalidate($this->request); $response = $this->store->lookup($this->request); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); $this->assertFalse($response->isFresh()); } public function testSucceedsQuietlyWhenInvalidateCalledWithNoMatchingEntries() { $req = Request::create('/test'); $this->store->invalidate($req); $this->assertNull($this->store->lookup($this->request)); } public function testDoesNotReturnEntriesThatVaryWithLookup() { $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam')); $res = new Response('test', 200, array('Vary' => 'Foo Bar')); $this->store->write($req1, $res); $this->assertNull($this->store->lookup($req2)); } public function testStoresMultipleResponsesForEachVaryCombination() { $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); $res1 = new Response('test 1', 200, array('Vary' => 'Foo Bar')); $key = $this->store->write($req1, $res1); $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam')); $res2 = new Response('test 2', 200, array('Vary' => 'Foo Bar')); $this->store->write($req2, $res2); $req3 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Baz', 'HTTP_BAR' => 'Boom')); $res3 = new Response('test 3', 200, array('Vary' => 'Foo Bar')); $this->store->write($req3, $res3); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 3')), $this->store->lookup($req3)->getContent()); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 2')), $this->store->lookup($req2)->getContent()); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 1')), $this->store->lookup($req1)->getContent()); $this->assertCount(3, $this->getStoreMetadata($key)); } public function testOverwritesNonVaryingResponseWithStore() { $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); $res1 = new Response('test 1', 200, array('Vary' => 'Foo Bar')); $key = $this->store->write($req1, $res1); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 1')), $this->store->lookup($req1)->getContent()); $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam')); $res2 = new Response('test 2', 200, array('Vary' => 'Foo Bar')); $this->store->write($req2, $res2); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 2')), $this->store->lookup($req2)->getContent()); $req3 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); $res3 = new Response('test 3', 200, array('Vary' => 'Foo Bar')); $key = $this->store->write($req3, $res3); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 3')), $this->store->lookup($req3)->getContent()); $this->assertCount(2, $this->getStoreMetadata($key)); } public function testLocking() { $req = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); $this->assertTrue($this->store->lock($req)); $path = $this->store->lock($req); $this->assertTrue($this->store->isLocked($req)); $this->store->unlock($req); $this->assertFalse($this->store->isLocked($req)); } protected function storeSimpleEntry($path = null, $headers = array()) { if (null === $path) { $path = '/test'; } $this->request = Request::create($path, 'get', array(), array(), array(), $headers); $this->response = new Response('test', 200, array('Cache-Control' => 'max-age=420')); return $this->store->write($this->request, $this->response); } protected function getStoreMetadata($key) { $r = new \ReflectionObject($this->store); $m = $r->getMethod('getMetadata'); $m->setAccessible(true); if ($key instanceof Request) { $m1 = $r->getMethod('getCacheKey'); $m1->setAccessible(true); $key = $m1->invoke($this->store, $key); } return $m->invoke($this->store, $key); } protected function getStorePath($key) { $r = new \ReflectionObject($this->store); $m = $r->getMethod('getPath'); $m->setAccessible(true); return $m->invoke($this->store, $key); } } PK!`1Mtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Config/FileLocatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Config; use Symfony\Component\HttpKernel\Config\FileLocator; class FileLocatorTest extends \PHPUnit_Framework_TestCase { public function testLocate() { $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface'); $kernel ->expects($this->atLeastOnce()) ->method('locateResource') ->with('@BundleName/some/path', null, true) ->will($this->returnValue('/bundle-name/some/path')); $locator = new FileLocator($kernel); $this->assertEquals('/bundle-name/some/path', $locator->locate('@BundleName/some/path')); $kernel ->expects($this->never()) ->method('locateResource'); $this->setExpectedException('LogicException'); $locator->locate('/some/path'); } public function testLocateWithGlobalResourcePath() { $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface'); $kernel ->expects($this->atLeastOnce()) ->method('locateResource') ->with('@BundleName/some/path', '/global/resource/path', false); $locator = new FileLocator($kernel, '/global/resource/path'); $locator->locate('@BundleName/some/path', null, false); } } PK!KwHtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Bundle; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionAbsentBundle\ExtensionAbsentBundle; use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand; use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\ExtensionPresentBundle; class BundleTest extends \PHPUnit_Framework_TestCase { public function testRegisterCommands() { $cmd = new FooCommand(); $app = $this->getMock('Symfony\Component\Console\Application'); $app->expects($this->once())->method('add')->with($this->equalTo($cmd)); $bundle = new ExtensionPresentBundle(); $bundle->registerCommands($app); $bundle2 = new ExtensionAbsentBundle(); $this->assertNull($bundle2->registerCommands($app)); } public function testRegisterCommandsIngoreCommandAsAService() { $container = new ContainerBuilder(); $container->addCompilerPass(new AddConsoleCommandPass()); $definition = new Definition('Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand'); $definition->addTag('console.command'); $container->setDefinition('my-command', $definition); $container->compile(); $application = $this->getMock('Symfony\Component\Console\Application'); // Never called, because it's the // Symfony\Bundle\FrameworkBundle\Console\Application that register // commands as a service $application->expects($this->never())->method('add'); $bundle = new ExtensionPresentBundle(); $bundle->setContainer($container); $bundle->registerCommands($application); } } PK!!g[test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler; use Symfony\Component\HttpKernel\Profiler\MemcacheProfilerStorage; use Symfony\Component\HttpKernel\Tests\Profiler\Mock\MemcacheMock; class MemcacheProfilerStorageTest extends AbstractProfilerStorageTest { protected static $storage; protected function setUp() { $memcacheMock = new MemcacheMock(); $memcacheMock->addServer('127.0.0.1', 11211); self::$storage = new MemcacheProfilerStorage('memcache://127.0.0.1:11211', '', '', 86400); self::$storage->setMemcache($memcacheMock); if (self::$storage) { self::$storage->purge(); } } protected function tearDown() { if (self::$storage) { self::$storage->purge(); self::$storage = false; } } /** * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface */ protected function getStorage() { return self::$storage; } } PK![\test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler; use Symfony\Component\HttpKernel\Profiler\MemcachedProfilerStorage; use Symfony\Component\HttpKernel\Tests\Profiler\Mock\MemcachedMock; class MemcachedProfilerStorageTest extends AbstractProfilerStorageTest { protected static $storage; protected function setUp() { $memcachedMock = new MemcachedMock(); $memcachedMock->addServer('127.0.0.1', 11211); self::$storage = new MemcachedProfilerStorage('memcached://127.0.0.1:11211', '', '', 86400); self::$storage->setMemcached($memcachedMock); if (self::$storage) { self::$storage->purge(); } } protected function tearDown() { if (self::$storage) { self::$storage->purge(); self::$storage = false; } } /** * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface */ protected function getStorage() { return self::$storage; } } PK!T Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler; use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage; use Symfony\Component\HttpKernel\Profiler\Profile; class FileProfilerStorageTest extends AbstractProfilerStorageTest { protected static $tmpDir; protected static $storage; protected static function cleanDir() { $flags = \FilesystemIterator::SKIP_DOTS; $iterator = new \RecursiveDirectoryIterator(self::$tmpDir, $flags); $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $file) { if (is_file($file)) { unlink($file); } } } public static function setUpBeforeClass() { self::$tmpDir = sys_get_temp_dir().'/sf2_profiler_file_storage'; if (is_dir(self::$tmpDir)) { self::cleanDir(); } self::$storage = new FileProfilerStorage('file:'.self::$tmpDir); } public static function tearDownAfterClass() { self::cleanDir(); } protected function setUp() { self::$storage->purge(); } /** * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface */ protected function getStorage() { return self::$storage; } public function testMultiRowIndexFile() { $iteration = 3; for ($i = 0; $i < $iteration; $i++) { $profile = new Profile('token'.$i); $profile->setIp('127.0.0.'.$i); $profile->setUrl('http://foo.bar/'.$i); $storage = $this->getStorage(); $storage->write($profile); $storage->write($profile); $storage->write($profile); } $handle = fopen(self::$tmpDir.'/index.csv', 'r'); for ($i = 0; $i < $iteration; $i++) { $row = fgetcsv($handle); $this->assertEquals('token'.$i, $row[0]); $this->assertEquals('127.0.0.'.$i, $row[1]); $this->assertEquals('http://foo.bar/'.$i, $row[3]); } $this->assertFalse(fgetcsv($handle)); } public function testReadLineFromFile() { $r = new \ReflectionMethod(self::$storage, 'readLineFromFile'); $r->setAccessible(true); $h = tmpfile(); fwrite($h, "line1\n\n\nline2\n"); fseek($h, 0, SEEK_END); $this->assertEquals("line2", $r->invoke(self::$storage, $h)); $this->assertEquals("line1", $r->invoke(self::$storage, $h)); } } PK!,))[test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler; use Symfony\Component\HttpKernel\Profiler\Profile; abstract class AbstractProfilerStorageTest extends \PHPUnit_Framework_TestCase { public function testStore() { for ($i = 0; $i < 10; $i ++) { $profile = new Profile('token_'.$i); $profile->setIp('127.0.0.1'); $profile->setUrl('http://foo.bar'); $profile->setMethod('GET'); $this->getStorage()->write($profile); } $this->assertCount(10, $this->getStorage()->find('127.0.0.1', 'http://foo.bar', 20, 'GET'), '->write() stores data in the storage'); } public function testChildren() { $parentProfile = new Profile('token_parent'); $parentProfile->setIp('127.0.0.1'); $parentProfile->setUrl('http://foo.bar/parent'); $childProfile = new Profile('token_child'); $childProfile->setIp('127.0.0.1'); $childProfile->setUrl('http://foo.bar/child'); $parentProfile->addChild($childProfile); $this->getStorage()->write($parentProfile); $this->getStorage()->write($childProfile); // Load them from storage $parentProfile = $this->getStorage()->read('token_parent'); $childProfile = $this->getStorage()->read('token_child'); // Check child has link to parent $this->assertNotNull($childProfile->getParent()); $this->assertEquals($parentProfile->getToken(), $childProfile->getParentToken()); // Check parent has child $children = $parentProfile->getChildren(); $this->assertCount(1, $children); $this->assertEquals($childProfile->getToken(), $children[0]->getToken()); } public function testStoreSpecialCharsInUrl() { // The storage accepts special characters in URLs (Even though URLs are not // supposed to contain them) $profile = new Profile('simple_quote'); $profile->setUrl('http://foo.bar/\''); $this->getStorage()->write($profile); $this->assertTrue(false !== $this->getStorage()->read('simple_quote'), '->write() accepts single quotes in URL'); $profile = new Profile('double_quote'); $profile->setUrl('http://foo.bar/"'); $this->getStorage()->write($profile); $this->assertTrue(false !== $this->getStorage()->read('double_quote'), '->write() accepts double quotes in URL'); $profile = new Profile('backslash'); $profile->setUrl('http://foo.bar/\\'); $this->getStorage()->write($profile); $this->assertTrue(false !== $this->getStorage()->read('backslash'), '->write() accepts backslash in URL'); $profile = new Profile('comma'); $profile->setUrl('http://foo.bar/,'); $this->getStorage()->write($profile); $this->assertTrue(false !== $this->getStorage()->read('comma'), '->write() accepts comma in URL'); } public function testStoreDuplicateToken() { $profile = new Profile('token'); $profile->setUrl('http://example.com/'); $this->assertTrue($this->getStorage()->write($profile), '->write() returns true when the token is unique'); $profile->setUrl('http://example.net/'); $this->assertTrue($this->getStorage()->write($profile), '->write() returns true when the token is already present in the storage'); $this->assertEquals('http://example.net/', $this->getStorage()->read('token')->getUrl(), '->write() overwrites the current profile data'); $this->assertCount(1, $this->getStorage()->find('', '', 1000, ''), '->find() does not return the same profile twice'); } public function testRetrieveByIp() { $profile = new Profile('token'); $profile->setIp('127.0.0.1'); $profile->setMethod('GET'); $this->getStorage()->write($profile); $this->assertCount(1, $this->getStorage()->find('127.0.0.1', '', 10, 'GET'), '->find() retrieve a record by IP'); $this->assertCount(0, $this->getStorage()->find('127.0.%.1', '', 10, 'GET'), '->find() does not interpret a "%" as a wildcard in the IP'); $this->assertCount(0, $this->getStorage()->find('127.0._.1', '', 10, 'GET'), '->find() does not interpret a "_" as a wildcard in the IP'); } public function testRetrieveByUrl() { $profile = new Profile('simple_quote'); $profile->setIp('127.0.0.1'); $profile->setUrl('http://foo.bar/\''); $profile->setMethod('GET'); $this->getStorage()->write($profile); $profile = new Profile('double_quote'); $profile->setIp('127.0.0.1'); $profile->setUrl('http://foo.bar/"'); $profile->setMethod('GET'); $this->getStorage()->write($profile); $profile = new Profile('backslash'); $profile->setIp('127.0.0.1'); $profile->setUrl('http://foo\\bar/'); $profile->setMethod('GET'); $this->getStorage()->write($profile); $profile = new Profile('percent'); $profile->setIp('127.0.0.1'); $profile->setUrl('http://foo.bar/%'); $profile->setMethod('GET'); $this->getStorage()->write($profile); $profile = new Profile('underscore'); $profile->setIp('127.0.0.1'); $profile->setUrl('http://foo.bar/_'); $profile->setMethod('GET'); $this->getStorage()->write($profile); $profile = new Profile('semicolon'); $profile->setIp('127.0.0.1'); $profile->setUrl('http://foo.bar/;'); $profile->setMethod('GET'); $this->getStorage()->write($profile); $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/\'', 10, 'GET'), '->find() accepts single quotes in URLs'); $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/"', 10, 'GET'), '->find() accepts double quotes in URLs'); $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo\\bar/', 10, 'GET'), '->find() accepts backslash in URLs'); $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/;', 10, 'GET'), '->find() accepts semicolon in URLs'); $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/%', 10, 'GET'), '->find() does not interpret a "%" as a wildcard in the URL'); $this->assertCount(1, $this->getStorage()->find('127.0.0.1', 'http://foo.bar/_', 10, 'GET'), '->find() does not interpret a "_" as a wildcard in the URL'); } public function testStoreTime() { $dt = new \DateTime('now'); $start = $dt->getTimestamp(); for ($i = 0; $i < 3; $i++) { $dt->modify('+1 minute'); $profile = new Profile('time_'.$i); $profile->setIp('127.0.0.1'); $profile->setUrl('http://foo.bar'); $profile->setTime($dt->getTimestamp()); $profile->setMethod('GET'); $this->getStorage()->write($profile); } $records = $this->getStorage()->find('', '', 3, 'GET', $start, time() + 3 * 60); $this->assertCount(3, $records, '->find() returns all previously added records'); $this->assertEquals($records[0]['token'], 'time_2', '->find() returns records ordered by time in descendant order'); $this->assertEquals($records[1]['token'], 'time_1', '->find() returns records ordered by time in descendant order'); $this->assertEquals($records[2]['token'], 'time_0', '->find() returns records ordered by time in descendant order'); $records = $this->getStorage()->find('', '', 3, 'GET', $start, time() + 2 * 60); $this->assertCount(2, $records, '->find() should return only first two of the previously added records'); } public function testRetrieveByEmptyUrlAndIp() { for ($i = 0; $i < 5; $i++) { $profile = new Profile('token_'.$i); $profile->setMethod('GET'); $this->getStorage()->write($profile); } $this->assertCount(5, $this->getStorage()->find('', '', 10, 'GET'), '->find() returns all previously added records'); $this->getStorage()->purge(); } public function testRetrieveByMethodAndLimit() { foreach (array('POST', 'GET') as $method) { for ($i = 0; $i < 5; $i++) { $profile = new Profile('token_'.$i.$method); $profile->setMethod($method); $this->getStorage()->write($profile); } } $this->assertCount(5, $this->getStorage()->find('', '', 5, 'POST')); $this->getStorage()->purge(); } public function testPurge() { $profile = new Profile('token1'); $profile->setIp('127.0.0.1'); $profile->setUrl('http://example.com/'); $profile->setMethod('GET'); $this->getStorage()->write($profile); $this->assertTrue(false !== $this->getStorage()->read('token1')); $this->assertCount(1, $this->getStorage()->find('127.0.0.1', '', 10, 'GET')); $profile = new Profile('token2'); $profile->setIp('127.0.0.1'); $profile->setUrl('http://example.net/'); $profile->setMethod('GET'); $this->getStorage()->write($profile); $this->assertTrue(false !== $this->getStorage()->read('token2')); $this->assertCount(2, $this->getStorage()->find('127.0.0.1', '', 10, 'GET')); $this->getStorage()->purge(); $this->assertEmpty($this->getStorage()->read('token'), '->purge() removes all data stored by profiler'); $this->assertCount(0, $this->getStorage()->find('127.0.0.1', '', 10, 'GET'), '->purge() removes all items from index'); } public function testDuplicates() { for ($i = 1; $i <= 5; $i++) { $profile = new Profile('foo'.$i); $profile->setIp('127.0.0.1'); $profile->setUrl('http://example.net/'); $profile->setMethod('GET'); ///three duplicates $this->getStorage()->write($profile); $this->getStorage()->write($profile); $this->getStorage()->write($profile); } $this->assertCount(3, $this->getStorage()->find('127.0.0.1', 'http://example.net/', 3, 'GET'), '->find() method returns incorrect number of entries'); } /** * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface */ abstract protected function getStorage(); } PK!.\Rtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcachedMock.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler\Mock; /** * MemcachedMock for simulating Memcached extension in tests. * * @author Andrej Hudec */ class MemcachedMock { private $connected = false; private $storage = array(); /** * Set a Memcached option * * @param integer $option * @param mixed $value * * @return boolean */ public function setOption($option, $value) { return true; } /** * Add a memcached server to connection pool * * @param string $host * @param integer $port * @param integer $weight * * @return boolean */ public function addServer($host, $port = 11211, $weight = 0) { if ('127.0.0.1' == $host && 11211 == $port) { $this->connected = true; return true; } return false; } /** * Add an item to the server only if such key doesn't exist at the server yet. * * @param string $key * @param mixed $value * @param integer $expiration * * @return boolean */ public function add($key, $value, $expiration = 0) { if (!$this->connected) { return false; } if (!isset($this->storage[$key])) { $this->storeData($key, $value); return true; } return false; } /** * Store data at the server. * * @param string $key * @param mixed $value * @param integer $expiration * * @return boolean */ public function set($key, $value, $expiration = null) { if (!$this->connected) { return false; } $this->storeData($key, $value); return true; } /** * Replace value of the existing item. * * @param string $key * @param mixed $value * @param integer $expiration * * @return boolean */ public function replace($key, $value, $expiration = null) { if (!$this->connected) { return false; } if (isset($this->storage[$key])) { $this->storeData($key, $value); return true; } return false; } /** * Retrieve item from the server. * * @param string $key * @param callable $cache_cb * @param float $cas_token * * @return boolean */ public function get($key, $cache_cb = null, &$cas_token = null) { if (!$this->connected) { return false; } return $this->getData($key); } /** * Append data to an existing item * * @param string $key * @param string $value * * @return boolean */ public function append($key, $value) { if (!$this->connected) { return false; } if (isset($this->storage[$key])) { $this->storeData($key, $this->getData($key).$value); return true; } return false; } /** * Delete item from the server * * @param string $key * * @return boolean */ public function delete($key) { if (!$this->connected) { return false; } if (isset($this->storage[$key])) { unset($this->storage[$key]); return true; } return false; } /** * Flush all existing items at the server * * @return boolean */ public function flush() { if (!$this->connected) { return false; } $this->storage = array(); return true; } private function getData($key) { if (isset($this->storage[$key])) { return unserialize($this->storage[$key]); } return false; } private function storeData($key, $value) { $this->storage[$key] = serialize($value); return true; } } PK!i]Qtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcacheMock.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler\Mock; /** * MemcacheMock for simulating Memcache extension in tests. * * @author Andrej Hudec */ class MemcacheMock { private $connected = false; private $storage = array(); /** * Open memcached server connection * * @param string $host * @param integer $port * @param integer $timeout * * @return boolean */ public function connect($host, $port = null, $timeout = null) { if ('127.0.0.1' == $host && 11211 == $port) { $this->connected = true; return true; } return false; } /** * Open memcached server persistent connection * * @param string $host * @param integer $port * @param integer $timeout * * @return boolean */ public function pconnect($host, $port = null, $timeout = null) { if ('127.0.0.1' == $host && 11211 == $port) { $this->connected = true; return true; } return false; } /** * Add a memcached server to connection pool * * @param string $host * @param integer $port * @param boolean $persistent * @param integer $weight * @param integer $timeout * @param integer $retry_interval * @param boolean $status * @param callable $failure_callback * @param integer $timeoutms * * @return boolean */ public function addServer($host, $port = 11211, $persistent = null, $weight = null, $timeout = null, $retry_interval = null, $status = null, $failure_callback = null, $timeoutms = null) { if ('127.0.0.1' == $host && 11211 == $port) { $this->connected = true; return true; } return false; } /** * Add an item to the server only if such key doesn't exist at the server yet. * * @param string $key * @param mixed $var * @param integer $flag * @param integer $expire * * @return boolean */ public function add($key, $var, $flag = null, $expire = null) { if (!$this->connected) { return false; } if (!isset($this->storage[$key])) { $this->storeData($key, $var); return true; } return false; } /** * Store data at the server. * * @param string $key * @param string $var * @param integer $flag * @param integer $expire * * @return boolean */ public function set($key, $var, $flag = null, $expire = null) { if (!$this->connected) { return false; } $this->storeData($key, $var); return true; } /** * Replace value of the existing item. * * @param string $key * @param mixed $var * @param integer $flag * @param integer $expire * * @return boolean */ public function replace($key, $var, $flag = null, $expire = null) { if (!$this->connected) { return false; } if (isset($this->storage[$key])) { $this->storeData($key, $var); return true; } return false; } /** * Retrieve item from the server. * * @param string|array $key * @param integer|array $flags * * @return mixed */ public function get($key, &$flags = null) { if (!$this->connected) { return false; } if (is_array($key)) { $result = array(); foreach ($key as $k) { if (isset($this->storage[$k])) { $result[] = $this->getData($k); } } return $result; } return $this->getData($key); } /** * Delete item from the server * * @param string $key * * @return boolean */ public function delete($key) { if (!$this->connected) { return false; } if (isset($this->storage[$key])) { unset($this->storage[$key]); return true; } return false; } /** * Flush all existing items at the server * * @return boolean */ public function flush() { if (!$this->connected) { return false; } $this->storage = array(); return true; } /** * Close memcached server connection * * @return boolean */ public function close() { $this->connected = false; return true; } private function getData($key) { if (isset($this->storage[$key])) { return unserialize($this->storage[$key]); } return false; } private function storeData($key, $value) { $this->storage[$key] = serialize($value); return true; } } PK!eK  Ntest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/RedisMock.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler\Mock; /** * RedisMock for simulating Redis extension in tests. * * @author Andrej Hudec */ class RedisMock { private $connected = false; private $storage = array(); /** * Add a server to connection pool * * @param string $host * @param integer $port * @param float $timeout * * @return boolean */ public function connect($host, $port = 6379, $timeout = 0) { if ('127.0.0.1' == $host && 6379 == $port) { $this->connected = true; return true; } return false; } /** * Set client option. * * @param integer $name * @param integer $value * * @return boolean */ public function setOption($name, $value) { if (!$this->connected) { return false; } return true; } /** * Verify if the specified key exists. * * @param string $key * * @return boolean */ public function exists($key) { if (!$this->connected) { return false; } return isset($this->storage[$key]); } /** * Store data at the server with expiration time. * * @param string $key * @param integer $ttl * @param mixed $value * * @return boolean */ public function setex($key, $ttl, $value) { if (!$this->connected) { return false; } $this->storeData($key, $value); return true; } /** * Sets an expiration time on an item. * * @param string $key * @param integer $ttl * * @return boolean */ public function setTimeout($key, $ttl) { if (!$this->connected) { return false; } if (isset($this->storage[$key])) { return true; } return false; } /** * Retrieve item from the server. * * @param string $key * * @return boolean */ public function get($key) { if (!$this->connected) { return false; } return $this->getData($key); } /** * Append data to an existing item * * @param string $key * @param string $value * * @return integer Size of the value after the append. */ public function append($key, $value) { if (!$this->connected) { return false; } if (isset($this->storage[$key])) { $this->storeData($key, $this->getData($key).$value); return strlen($this->storage[$key]); } return false; } /** * Remove specified keys. * * @param string|array $key * * @return integer */ public function delete($key) { if (!$this->connected) { return false; } if (is_array($key)) { $result = 0; foreach ($key as $k) { if (isset($this->storage[$k])) { unset($this->storage[$k]); ++$result; } } return $result; } if (isset($this->storage[$key])) { unset($this->storage[$key]); return 1; } return 0; } /** * Flush all existing items from all databases at the server. * * @return boolean */ public function flushAll() { if (!$this->connected) { return false; } $this->storage = array(); return true; } /** * Close Redis server connection * * @return boolean */ public function close() { $this->connected = false; return true; } private function getData($key) { if (isset($this->storage[$key])) { return unserialize($this->storage[$key]); } return false; } private function storeData($key, $value) { $this->storage[$key] = serialize($value); return true; } public function select($dbnum) { if (!$this->connected) { return false; } if (0 > $dbnum) { return false; } return true; } } PK!`ejZtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler; use Symfony\Component\HttpKernel\Profiler\MongoDbProfilerStorage; use Symfony\Component\HttpKernel\Profiler\Profile; use Symfony\Component\HttpKernel\DataCollector\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class DummyMongoDbProfilerStorage extends MongoDbProfilerStorage { public function getMongo() { return parent::getMongo(); } } class MongoDbProfilerStorageTestDataCollector extends DataCollector { public function setData($data) { $this->data = $data; } public function getData() { return $this->data; } public function collect(Request $request, Response $response, \Exception $exception = null) { } public function getName() { return 'test_data_collector'; } } class MongoDbProfilerStorageTest extends AbstractProfilerStorageTest { protected static $storage; public static function setUpBeforeClass() { if (extension_loaded('mongo')) { self::$storage = new DummyMongoDbProfilerStorage('mongodb://localhost/symfony_tests/profiler_data', '', '', 86400); try { self::$storage->getMongo(); } catch (\MongoConnectionException $e) { self::$storage = null; } } } public static function tearDownAfterClass() { if (self::$storage) { self::$storage->purge(); self::$storage = null; } } public function getDsns() { return array( array('mongodb://localhost/symfony_tests/profiler_data', array( 'mongodb://localhost/symfony_tests', 'symfony_tests', 'profiler_data' )), array('mongodb://user:password@localhost/symfony_tests/profiler_data', array( 'mongodb://user:password@localhost/symfony_tests', 'symfony_tests', 'profiler_data' )), array('mongodb://user:password@localhost/admin/symfony_tests/profiler_data', array( 'mongodb://user:password@localhost/admin', 'symfony_tests', 'profiler_data' )), array('mongodb://user:password@localhost:27009,localhost:27010/?replicaSet=rs-name&authSource=admin/symfony_tests/profiler_data', array( 'mongodb://user:password@localhost:27009,localhost:27010/?replicaSet=rs-name&authSource=admin', 'symfony_tests', 'profiler_data' )) ); } public function testCleanup() { $dt = new \DateTime('-2 day'); for ($i = 0; $i < 3; $i++) { $dt->modify('-1 day'); $profile = new Profile('time_'.$i); $profile->setTime($dt->getTimestamp()); $profile->setMethod('GET'); self::$storage->write($profile); } $records = self::$storage->find('', '', 3, 'GET'); $this->assertCount(1, $records, '->find() returns only one record'); $this->assertEquals($records[0]['token'], 'time_2', '->find() returns the latest added record'); self::$storage->purge(); } /** * @dataProvider getDsns */ public function testDsnParser($dsn, $expected) { $m = new \ReflectionMethod(self::$storage, 'parseDsn'); $m->setAccessible(true); $this->assertEquals($expected, $m->invoke(self::$storage, $dsn)); } public function testUtf8() { $profile = new Profile('utf8_test_profile'); $data = 'HЁʃʃϿ, ϢorЃd!'; $nonUtf8Data = mb_convert_encoding($data, 'UCS-2'); $collector = new MongoDbProfilerStorageTestDataCollector(); $collector->setData($nonUtf8Data); $profile->setCollectors(array($collector)); self::$storage->write($profile); $readProfile = self::$storage->read('utf8_test_profile'); $collectors = $readProfile->getCollectors(); $this->assertCount(1, $collectors); $this->assertArrayHasKey('test_data_collector', $collectors); $this->assertEquals($nonUtf8Data, $collectors['test_data_collector']->getData(), 'Non-UTF8 data is properly encoded/decoded'); } /** * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface */ protected function getStorage() { return self::$storage; } protected function setUp() { if (self::$storage) { self::$storage->purge(); } else { $this->markTestSkipped('MongoDbProfilerStorageTest requires the mongo PHP extension and a MongoDB server on localhost'); } } } PK!p3h NNYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler; use Symfony\Component\HttpKernel\Profiler\SqliteProfilerStorage; class SqliteProfilerStorageTest extends AbstractProfilerStorageTest { protected static $dbFile; protected static $storage; public static function setUpBeforeClass() { self::$dbFile = tempnam(sys_get_temp_dir(), 'sf2_sqlite_storage'); if (file_exists(self::$dbFile)) { @unlink(self::$dbFile); } self::$storage = new SqliteProfilerStorage('sqlite:'.self::$dbFile); } public static function tearDownAfterClass() { @unlink(self::$dbFile); } protected function setUp() { if (!class_exists('SQLite3') && (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers()))) { $this->markTestSkipped('This test requires SQLite support in your environment'); } self::$storage->purge(); } /** * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface */ protected function getStorage() { return self::$storage; } } PK!FEXtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler; use Symfony\Component\HttpKernel\Profiler\RedisProfilerStorage; use Symfony\Component\HttpKernel\Tests\Profiler\Mock\RedisMock; class RedisProfilerStorageTest extends AbstractProfilerStorageTest { protected static $storage; protected function setUp() { $redisMock = new RedisMock(); $redisMock->connect('127.0.0.1', 6379); self::$storage = new RedisProfilerStorage('redis://127.0.0.1:6379', '', '', 86400); self::$storage->setRedis($redisMock); if (self::$storage) { self::$storage->purge(); } } protected function tearDown() { if (self::$storage) { self::$storage->purge(); self::$storage = false; } } /** * @return \Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface */ protected function getStorage() { return self::$storage; } } PK!&2TTLtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Profiler; use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; use Symfony\Component\HttpKernel\Profiler\SqliteProfilerStorage; use Symfony\Component\HttpKernel\Profiler\Profiler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class ProfilerTest extends \PHPUnit_Framework_TestCase { public function testCollect() { if (!class_exists('SQLite3') && (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers()))) { $this->markTestSkipped('This test requires SQLite support in your environment'); } $request = new Request(); $request->query->set('foo', 'bar'); $response = new Response(); $collector = new RequestDataCollector(); $tmp = tempnam(sys_get_temp_dir(), 'sf2_profiler'); if (file_exists($tmp)) { @unlink($tmp); } $storage = new SqliteProfilerStorage('sqlite:'.$tmp); $storage->purge(); $profiler = new Profiler($storage); $profiler->add($collector); $profile = $profiler->collect($request, $response); $profile = $profiler->loadProfile($profile->getToken()); $this->assertEquals(array('foo' => 'bar'), $profiler->get('request')->getRequestQuery()->all()); @unlink($tmp); } } PK!Uu֝Dtest/HttpKernel/Symfony/Component/HttpKernel/Tests/UriSignerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests; use Symfony\Component\HttpKernel\UriSigner; class UriSignerTest extends \PHPUnit_Framework_TestCase { public function testSign() { $signer = new UriSigner('foobar'); $this->assertContains('?_hash=', $signer->sign('http://example.com/foo')); $this->assertContains('&_hash=', $signer->sign('http://example.com/foo?foo=bar')); } public function testCheck() { $signer = new UriSigner('foobar'); $this->assertFalse($signer->check('http://example.com/foo?_hash=foo')); $this->assertFalse($signer->check('http://example.com/foo?foo=bar&_hash=foo')); $this->assertFalse($signer->check('http://example.com/foo?foo=bar&_hash=foo&bar=foo')); $this->assertTrue($signer->check($signer->sign('http://example.com/foo'))); $this->assertTrue($signer->check($signer->sign('http://example.com/foo?foo=bar'))); } } PK!bҏ^^\test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use Symfony\Component\HttpKernel\DataCollector\MemoryDataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class MemoryDataCollectorTest extends \PHPUnit_Framework_TestCase { public function testCollect() { $collector = new MemoryDataCollector(); $collector->collect(new Request(), new Response()); $this->assertInternalType('integer', $collector->getMemory()); $this->assertInternalType('integer', $collector->getMemoryLimit()); $this->assertSame('memory', $collector->getName()); } /** @dataProvider getBytesConversionTestData */ public function testBytesConversion($limit, $bytes) { $collector = new MemoryDataCollector(); $method = new \ReflectionMethod($collector, 'convertToBytes'); $method->setAccessible(true); $this->assertEquals($bytes, $method->invoke($collector, $limit)); } public function getBytesConversionTestData() { return array( array('2k', 2048), array('2 k', 2048), array('8m', 8 * 1024 * 1024), array('+2 k', 2048), array('+2???k', 2048), array('0x10', 16), array('0xf', 15), array('010', 8), array('+0x10 k', 16 * 1024), array('1g', 1024 * 1024 * 1024), array('1G', 1024 * 1024 * 1024), array('-1', -1), array('0', 0), array('2mk', 2048), // the unit must be the last char, so in this case 'k', not 'm' ); } } PK!CZtest/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/TimeDataCollectorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use Symfony\Component\HttpKernel\DataCollector\TimeDataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class TimeDataCollectorTest extends \PHPUnit_Framework_TestCase { public function testCollect() { $c = new TimeDataCollector(); $request = new Request(); $request->server->set('REQUEST_TIME', 1); $c->collect($request, new Response()); $this->assertEquals(1000, $c->getStartTime()); $request->server->set('REQUEST_TIME_FLOAT', 2); $c->collect($request, new Response()); $this->assertEquals(2000, $c->getStartTime()); $request = new Request(); $c->collect($request, new Response()); $this->assertEquals(0, $c->getStartTime()); $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface'); $kernel->expects($this->once())->method('getStartTime')->will($this->returnValue(123456)); $c = new TimeDataCollector($kernel); $request = new Request(); $request->server->set('REQUEST_TIME', 1); $c->collect($request, new Response()); $this->assertEquals(123456000, $c->getStartTime()); } } PK! \test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class ConfigDataCollectorTest extends \PHPUnit_Framework_TestCase { public function testCollect() { $kernel = new KernelForTest('test', true); $c = new ConfigDataCollector(); $c->setKernel($kernel); $c->collect(new Request(), new Response()); $this->assertSame('test',$c->getEnv()); $this->assertTrue($c->isDebug()); $this->assertSame('config',$c->getName()); $this->assertSame('testkernel',$c->getAppName()); $this->assertSame(PHP_VERSION,$c->getPhpVersion()); $this->assertSame(Kernel::VERSION,$c->getSymfonyVersion()); $this->assertNull($c->getToken()); // if else clause because we don't know it if (extension_loaded('xdebug')) { $this->assertTrue($c->hasXdebug()); } else { $this->assertFalse($c->hasXdebug()); } // if else clause because we don't know it if (((extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) || (extension_loaded('apc') && ini_get('apc.enabled')) || (extension_loaded('Zend OPcache') && ini_get('opcache.enable')) || (extension_loaded('xcache') && ini_get('xcache.cacher')) || (extension_loaded('wincache') && ini_get('wincache.ocenabled')))) { $this->assertTrue($c->hasAccelerator()); } else { $this->assertFalse($c->hasAccelerator()); } } } class KernelForTest extends Kernel { public function getName() { return 'testkernel'; } public function registerBundles() { } public function init() { } public function getBundles() { return array(); } public function registerContainerConfiguration(LoaderInterface $loader) { } } PK!}#_test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector; use Symfony\Component\HttpKernel\Exception\FlattenException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class ExceptionDataCollectorTest extends \PHPUnit_Framework_TestCase { public function testCollect() { $e = new \Exception('foo',500); $c = new ExceptionDataCollector(); $flattened = FlattenException::create($e); $trace = $flattened->getTrace(); $this->assertFalse($c->hasException()); $c->collect(new Request(), new Response(),$e); $this->assertTrue($c->hasException()); $this->assertEquals($flattened,$c->getException()); $this->assertSame('foo',$c->getMessage()); $this->assertSame(500,$c->getCode()); $this->assertSame('exception',$c->getName()); $this->assertSame($trace,$c->getTrace()); } } PK!J֌]test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\EventDispatcher\EventDispatcher; class RequestDataCollectorTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider provider */ public function testCollect(Request $request, Response $response) { $c = new RequestDataCollector(); $c->collect($request, $response); $this->assertSame('request', $c->getName()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\HeaderBag', $c->getRequestHeaders()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestServer()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestCookies()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestAttributes()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestRequest()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestQuery()); $this->assertSame('html', $c->getFormat()); $this->assertSame('foobar', $c->getRoute()); $this->assertSame(array('name' => 'foo'), $c->getRouteParams()); $this->assertSame(array(), $c->getSessionAttributes()); $this->assertSame('en', $c->getLocale()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\HeaderBag', $c->getResponseHeaders()); $this->assertSame('OK', $c->getStatusText()); $this->assertSame(200, $c->getStatusCode()); $this->assertSame('application/json', $c->getContentType()); } /** * Test various types of controller callables. * * @dataProvider provider */ public function testControllerInspection(Request $request, Response $response) { // make sure we always match the line number $r1 = new \ReflectionMethod($this, 'testControllerInspection'); $r2 = new \ReflectionMethod($this, 'staticControllerMethod'); // test name, callable, expected $controllerTests = array( array( '"Regular" callable', array($this, 'testControllerInspection'), array( 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'testControllerInspection', 'file' => __FILE__, 'line' => $r1->getStartLine() ), ), array( 'Closure', function () { return 'foo'; }, array( 'class' => __NAMESPACE__.'\{closure}', 'method' => null, 'file' => __FILE__, 'line' => __LINE__ - 5, ), ), array( 'Static callback as string', 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest::staticControllerMethod', 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest::staticControllerMethod', ), array( 'Static callable with instance', array($this, 'staticControllerMethod'), array( 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'staticControllerMethod', 'file' => __FILE__, 'line' => $r2->getStartLine() ), ), array( 'Static callable with class name', array('Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'staticControllerMethod'), array( 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'staticControllerMethod', 'file' => __FILE__, 'line' => $r2->getStartLine() ), ), array( 'Callable with instance depending on __call()', array($this, 'magicMethod'), array( 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'magicMethod', 'file' => 'n/a', 'line' => 'n/a' ), ), array( 'Callable with class name depending on __callStatic()', array('Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'magicMethod'), array( 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'magicMethod', 'file' => 'n/a', 'line' => 'n/a' ), ), ); $c = new RequestDataCollector(); foreach ($controllerTests as $controllerTest) { $this->injectController($c, $controllerTest[1], $request); $c->collect($request, $response); $this->assertSame($controllerTest[2], $c->getController(), sprintf('Testing: %s', $controllerTest[0])); } } public function provider() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { return array(array(null, null)); } $request = Request::create('http://test.com/foo?bar=baz'); $request->attributes->set('foo', 'bar'); $request->attributes->set('_route', 'foobar'); $request->attributes->set('_route_params', array('name' => 'foo')); $response = new Response(); $response->setStatusCode(200); $response->headers->set('Content-Type', 'application/json'); $response->headers->setCookie(new Cookie('foo','bar',1,'/foo','localhost',true,true)); $response->headers->setCookie(new Cookie('bar','foo',new \DateTime('@946684800'))); $response->headers->setCookie(new Cookie('bazz','foo','2000-12-12')); return array( array($request, $response) ); } /** * Inject the given controller callable into the data collector. */ protected function injectController($collector, $controller, $request) { $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface'); $httpKernel = new HttpKernel(new EventDispatcher(), $resolver); $event = new FilterControllerEvent($httpKernel, $controller, $request, HttpKernelInterface::MASTER_REQUEST); $collector->onKernelController($event); } /** * Dummy method used as controller callable */ public static function staticControllerMethod() { throw new \LogicException('Unexpected method call'); } /** * Magic method to allow non existing methods to be called and delegated. */ public function __call($method, $args) { throw new \LogicException('Unexpected method call'); } /** * Magic method to allow non existing methods to be called and delegated. */ public static function __callStatic($method, $args) { throw new \LogicException('Unexpected method call'); } } PK!i i \test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector; use Symfony\Component\HttpKernel\Debug\ErrorHandler; class LoggerDataCollectorTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getCollectTestData */ public function testCollect($nb, $logs, $expectedLogs, $expectedDeprecationCount) { $logger = $this->getMock('Symfony\Component\HttpKernel\Log\DebugLoggerInterface'); $logger->expects($this->once())->method('countErrors')->will($this->returnValue($nb)); $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue($logs)); $c = new LoggerDataCollector($logger); $c->lateCollect(); $this->assertSame('logger', $c->getName()); $this->assertSame($nb, $c->countErrors()); $this->assertSame($expectedLogs ? $expectedLogs : $logs, $c->getLogs()); $this->assertSame($expectedDeprecationCount, $c->countDeprecations()); } public function getCollectTestData() { return array( array( 1, array(array('message' => 'foo', 'context' => array())), null, 0 ), array( 1, array(array('message' => 'foo', 'context' => array('foo' => fopen(__FILE__, 'r')))), array(array('message' => 'foo', 'context' => array('foo' => 'Resource(stream)'))), 0 ), array( 1, array(array('message' => 'foo', 'context' => array('foo' => new \stdClass()))), array(array('message' => 'foo', 'context' => array('foo' => 'Object(stdClass)'))), 0 ), array( 1, array( array('message' => 'foo', 'context' => array('type' => ErrorHandler::TYPE_DEPRECATION)), array('message' => 'foo2', 'context' => array('type' => ErrorHandler::TYPE_DEPRECATION)) ), null, 2 ), ); } } PK!g]>*>*Etest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpKernelTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\EventDispatcher\EventDispatcher; class HttpKernelTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \RuntimeException */ public function testHandleWhenControllerThrowsAnExceptionAndRawIsTrue() { $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); })); $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true); } /** * @expectedException \RuntimeException */ public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalseAndNoListenerIsRegistered() { $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); })); $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false); } public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalse() { $dispatcher = new EventDispatcher(); $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) { $event->setResponse(new Response($event->getException()->getMessage())); }); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); })); $response = $kernel->handle(new Request()); $this->assertEquals('500', $response->getStatusCode()); $this->assertEquals('foo', $response->getContent()); } public function testHandleExceptionWithARedirectionResponse() { $dispatcher = new EventDispatcher(); $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) { $event->setResponse(new RedirectResponse('/login', 301)); }); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new AccessDeniedHttpException(); })); $response = $kernel->handle(new Request()); $this->assertEquals('301', $response->getStatusCode()); $this->assertEquals('/login', $response->headers->get('Location')); } public function testHandleHttpException() { $dispatcher = new EventDispatcher(); $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) { $event->setResponse(new Response($event->getException()->getMessage())); }); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new MethodNotAllowedHttpException(array('POST')); })); $response = $kernel->handle(new Request()); $this->assertEquals('405', $response->getStatusCode()); $this->assertEquals('POST', $response->headers->get('Allow')); } /** * @dataProvider getStatusCodes */ public function testHandleWhenAnExceptionIsHandledWithASpecificStatusCode($responseStatusCode, $expectedStatusCode) { $dispatcher = new EventDispatcher(); $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) use ($responseStatusCode, $expectedStatusCode) { $event->setResponse(new Response('', $responseStatusCode, array('X-Status-Code' => $expectedStatusCode))); }); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException(); })); $response = $kernel->handle(new Request()); $this->assertEquals($expectedStatusCode, $response->getStatusCode()); $this->assertFalse($response->headers->has('X-Status-Code')); } public function getStatusCodes() { return array( array(200, 404), array(404, 200), array(301, 200), array(500, 200), ); } public function testHandleWhenAListenerReturnsAResponse() { $dispatcher = new EventDispatcher(); $dispatcher->addListener(KernelEvents::REQUEST, function ($event) { $event->setResponse(new Response('hello')); }); $kernel = new HttpKernel($dispatcher, $this->getResolver()); $this->assertEquals('hello', $kernel->handle(new Request())->getContent()); } /** * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function testHandleWhenNoControllerIsFound() { $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver(false)); $kernel->handle(new Request()); } /** * @expectedException \LogicException */ public function testHandleWhenTheControllerIsNotACallable() { $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver('foobar')); $kernel->handle(new Request()); } public function testHandleWhenTheControllerIsAClosure() { $response = new Response('foo'); $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () use ($response) { return $response; })); $this->assertSame($response, $kernel->handle(new Request())); } public function testHandleWhenTheControllerIsAnObjectWithInvoke() { $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver(new Controller())); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } public function testHandleWhenTheControllerIsAFunction() { $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver('Symfony\Component\HttpKernel\Tests\controller_func')); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } public function testHandleWhenTheControllerIsAnArray() { $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver(array(new Controller(), 'controller'))); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } public function testHandleWhenTheControllerIsAStaticArray() { $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver(array('Symfony\Component\HttpKernel\Tests\Controller', 'staticcontroller'))); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } /** * @expectedException \LogicException */ public function testHandleWhenTheControllerDoesNotReturnAResponse() { $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); $kernel->handle(new Request()); } public function testHandleWhenTheControllerDoesNotReturnAResponseButAViewIsRegistered() { $dispatcher = new EventDispatcher(); $dispatcher->addListener(KernelEvents::VIEW, function ($event) { $event->setResponse(new Response($event->getControllerResult())); }); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); } public function testHandleWithAResponseListener() { $dispatcher = new EventDispatcher(); $dispatcher->addListener(KernelEvents::RESPONSE, function ($event) { $event->setResponse(new Response('foo')); }); $kernel = new HttpKernel($dispatcher, $this->getResolver()); $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); } public function testTerminate() { $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver()); $dispatcher->addListener(KernelEvents::TERMINATE, function ($event) use (&$called, &$capturedKernel, &$capturedRequest, &$capturedResponse) { $called = true; $capturedKernel = $event->getKernel(); $capturedRequest = $event->getRequest(); $capturedResponse = $event->getResponse(); }); $kernel->terminate($request = Request::create('/'), $response = new Response()); $this->assertTrue($called); $this->assertEquals($kernel, $capturedKernel); $this->assertEquals($request, $capturedRequest); $this->assertEquals($response, $capturedResponse); } public function testVerifyRequestStackPushPopDuringHandle() { $request = new Request(); $stack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array('push', 'pop')); $stack->expects($this->at(0))->method('push')->with($this->equalTo($request)); $stack->expects($this->at(1))->method('pop'); $dispatcher = new EventDispatcher(); $kernel = new HttpKernel($dispatcher, $this->getResolver(), $stack); $kernel->handle($request, HttpKernelInterface::MASTER_REQUEST); } protected function getResolver($controller = null) { if (null === $controller) { $controller = function () { return new Response('Hello'); }; } $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface'); $resolver->expects($this->any()) ->method('getController') ->will($this->returnValue($controller)); $resolver->expects($this->any()) ->method('getArguments') ->will($this->returnValue(array())); return $resolver; } protected function assertResponseEquals(Response $expected, Response $actual) { $expected->setDate($actual->getDate()); $this->assertEquals($expected, $actual); } } class Controller { public function __invoke() { return new Response('foo'); } public function controller() { return new Response('foo'); } public static function staticController() { return new Response('foo'); } } function controller_func() { return new Response('foo'); } PK!z*V%%Xtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Controller; use Symfony\Component\HttpKernel\Controller\ControllerResolver; use Symfony\Component\HttpKernel\Tests\Logger; use Symfony\Component\HttpFoundation\Request; class ControllerResolverTest extends \PHPUnit_Framework_TestCase { public function testGetControllerWithoutControllerParameter() { $logger = $this->getMock('Psr\Log\LoggerInterface'); $logger->expects($this->once())->method('warning')->with('Unable to look for the controller as the "_controller" parameter is missing'); $resolver = new ControllerResolver($logger); $request = Request::create('/'); $this->assertFalse($resolver->getController($request), '->getController() returns false when the request has no _controller attribute'); } public function testGetControllerWithLambda() { $resolver = new ControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', $lambda = function () {}); $controller = $resolver->getController($request); $this->assertSame($lambda, $controller); } public function testGetControllerWithObjectAndInvokeMethod() { $resolver = new ControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', $this); $controller = $resolver->getController($request); $this->assertSame($this, $controller); } public function testGetControllerWithObjectAndMethod() { $resolver = new ControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', array($this, 'controllerMethod1')); $controller = $resolver->getController($request); $this->assertSame(array($this, 'controllerMethod1'), $controller); } public function testGetControllerWithClassAndMethod() { $resolver = new ControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4')); $controller = $resolver->getController($request); $this->assertSame(array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4'), $controller); } public function testGetControllerWithObjectAndMethodAsString() { $resolver = new ControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::controllerMethod1'); $controller = $resolver->getController($request); $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller[0], '->getController() returns a PHP callable'); } public function testGetControllerWithClassAndInvokeMethod() { $resolver = new ControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest'); $controller = $resolver->getController($request); $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller); } /** * @expectedException \InvalidArgumentException */ public function testGetControllerOnObjectWithoutInvokeMethod() { $resolver = new ControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', new \stdClass()); $resolver->getController($request); } public function testGetControllerWithFunction() { $resolver = new ControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'); $controller = $resolver->getController($request); $this->assertSame('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function', $controller); } /** * @dataProvider getUndefinedControllers * @expectedException \InvalidArgumentException */ public function testGetControllerOnNonUndefinedFunction($controller) { $resolver = new ControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', $controller); $resolver->getController($request); } public function getUndefinedControllers() { return array( array('foo'), array('foo::bar'), array('stdClass'), array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar'), ); } public function testGetArguments() { $resolver = new ControllerResolver(); $request = Request::create('/'); $controller = array(new self(), 'testGetArguments'); $this->assertEquals(array(), $resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments'); $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $controller = array(new self(), 'controllerMethod1'); $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method'); $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $controller = array(new self(), 'controllerMethod2'); $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller), '->getArguments() uses default values if present'); $request->attributes->set('bar', 'bar'); $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes'); $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $controller = function ($foo) {}; $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller)); $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $controller = function ($foo, $bar = 'bar') {}; $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller)); $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $controller = new self(); $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller)); $request->attributes->set('bar', 'bar'); $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller)); $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $request->attributes->set('foobar', 'foobar'); $controller = 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'; $this->assertEquals(array('foo', 'foobar'), $resolver->getArguments($request, $controller)); $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $request->attributes->set('foobar', 'foobar'); $controller = array(new self(), 'controllerMethod3'); if (version_compare(PHP_VERSION, '5.3.16', '==')) { $this->markTestSkipped('PHP 5.3.16 has a major bug in the Reflection sub-system'); } else { try { $resolver->getArguments($request, $controller); $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); } catch (\Exception $e) { $this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); } } $request = Request::create('/'); $controller = array(new self(), 'controllerMethod5'); $this->assertEquals(array($request), $resolver->getArguments($request, $controller), '->getArguments() injects the request'); } public function testCreateControllerCanReturnAnyCallable() { $mock = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolver', array('createController')); $mock->expects($this->once())->method('createController')->will($this->returnValue('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function')); $request = Request::create('/'); $request->attributes->set('_controller', 'foobar'); $mock->getController($request); } public function __invoke($foo, $bar = null) { } public function controllerMethod1($foo) { } protected function controllerMethod2($foo, $bar = null) { } protected function controllerMethod3($foo, $bar = null, $foobar) { } protected static function controllerMethod4() { } protected function controllerMethod5(Request $request) { } } function some_controller_function($foo, $foobar) { } PK!e ֮ntest/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; class MergeExtensionConfigurationPassTest extends \PHPUnit_Framework_TestCase { public function testAutoloadMainExtension() { $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder'); $params = $this->getMock('Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag'); $container->expects($this->at(0)) ->method('getExtensionConfig') ->with('loaded') ->will($this->returnValue(array(array()))); $container->expects($this->at(1)) ->method('getExtensionConfig') ->with('notloaded') ->will($this->returnValue(array())); $container->expects($this->once()) ->method('loadFromExtension') ->with('notloaded', array()); $container->expects($this->any()) ->method('getParameterBag') ->will($this->returnValue($params)); $params->expects($this->any()) ->method('all') ->will($this->returnValue(array())); $container->expects($this->any()) ->method('getDefinitions') ->will($this->returnValue(array())); $container->expects($this->any()) ->method('getAliases') ->will($this->returnValue(array())); $container->expects($this->any()) ->method('getExtensions') ->will($this->returnValue(array())); $configPass = new MergeExtensionConfigurationPass(array('loaded', 'notloaded')); $configPass->process($container); } } PK!V^^dtest/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterListenersPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass; class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase { /** * Tests that event subscribers not implementing EventSubscriberInterface * trigger an exception. * * @expectedException \InvalidArgumentException */ public function testEventSubscriberWithoutInterface() { // one service, not implementing any interface $services = array( 'my_event_subscriber' => array(0 => array()), ); $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); $definition->expects($this->atLeastOnce()) ->method('isPublic') ->will($this->returnValue(true)); $definition->expects($this->atLeastOnce()) ->method('getClass') ->will($this->returnValue('stdClass')); $builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder'); $builder->expects($this->any()) ->method('hasDefinition') ->will($this->returnValue(true)); // We don't test kernel.event_listener here $builder->expects($this->atLeastOnce()) ->method('findTaggedServiceIds') ->will($this->onConsecutiveCalls(array(), $services)); $builder->expects($this->atLeastOnce()) ->method('getDefinition') ->will($this->returnValue($definition)); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($builder); } public function testValidEventSubscriber() { $services = array( 'my_event_subscriber' => array(0 => array()), ); $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); $definition->expects($this->atLeastOnce()) ->method('isPublic') ->will($this->returnValue(true)); $definition->expects($this->atLeastOnce()) ->method('getClass') ->will($this->returnValue('Symfony\Component\HttpKernel\Tests\DependencyInjection\SubscriberService')); $builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder'); $builder->expects($this->any()) ->method('hasDefinition') ->will($this->returnValue(true)); // We don't test kernel.event_listener here $builder->expects($this->atLeastOnce()) ->method('findTaggedServiceIds') ->will($this->onConsecutiveCalls(array(), $services)); $builder->expects($this->atLeastOnce()) ->method('getDefinition') ->will($this->returnValue($definition)); $builder->expects($this->atLeastOnce()) ->method('findDefinition') ->will($this->returnValue($definition)); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($builder); } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage The service "foo" must be public as event listeners are lazy-loaded. */ public function testPrivateEventListener() { $container = new ContainerBuilder(); $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_listener', array()); $container->register('event_dispatcher', 'stdClass'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($container); } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage The service "foo" must be public as event subscribers are lazy-loaded. */ public function testPrivateEventSubscriber() { $container = new ContainerBuilder(); $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_subscriber', array()); $container->register('event_dispatcher', 'stdClass'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($container); } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage The service "foo" must not be abstract as event listeners are lazy-loaded. */ public function testAbstractEventListener() { $container = new ContainerBuilder(); $container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_listener', array()); $container->register('event_dispatcher', 'stdClass'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($container); } } class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface { public static function getSubscribedEvents() {} } PK!Chhgtest/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcher; class ContainerAwareHttpKernelTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getProviderTypes */ public function testHandle($type) { $request = new Request(); $expected = new Response(); $controller = function () use ($expected) { return $expected; }; $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); $this ->expectsEnterScopeOnce($container) ->expectsLeaveScopeOnce($container) ->expectsSetRequestWithAt($container, $request, 3) ->expectsSetRequestWithAt($container, null, 4) ; $dispatcher = new EventDispatcher(); $resolver = $this->getResolverMockFor($controller, $request); $stack = new RequestStack(); $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack); $actual = $kernel->handle($request, $type); $this->assertSame($expected, $actual, '->handle() returns the response'); } /** * @dataProvider getProviderTypes */ public function testVerifyRequestStackPushPopDuringHandle($type) { $request = new Request(); $expected = new Response(); $controller = function () use ($expected) { return $expected; }; $stack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array('push', 'pop')); $stack->expects($this->at(0))->method('push')->with($this->equalTo($request)); $stack->expects($this->at(1))->method('pop'); $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); $dispatcher = new EventDispatcher(); $resolver = $this->getResolverMockFor($controller, $request); $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack); $kernel->handle($request, $type); } /** * @dataProvider getProviderTypes */ public function testHandleRestoresThePreviousRequestOnException($type) { $request = new Request(); $expected = new \Exception(); $controller = function () use ($expected) { throw $expected; }; $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); $this ->expectsEnterScopeOnce($container) ->expectsLeaveScopeOnce($container) ->expectsSetRequestWithAt($container, $request, 3) ->expectsSetRequestWithAt($container, null, 4) ; $dispatcher = new EventDispatcher(); $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface'); $resolver = $this->getResolverMockFor($controller, $request); $stack = new RequestStack(); $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack); try { $kernel->handle($request, $type); $this->fail('->handle() suppresses the controller exception'); } catch (\PHPUnit_Framework_Exception $exception) { throw $exception; } catch (\Exception $actual) { $this->assertSame($expected, $actual, '->handle() throws the controller exception'); } } public function getProviderTypes() { return array( array(HttpKernelInterface::MASTER_REQUEST), array(HttpKernelInterface::SUB_REQUEST), ); } private function getResolverMockFor($controller, $request) { $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface'); $resolver->expects($this->once()) ->method('getController') ->with($request) ->will($this->returnValue($controller)); $resolver->expects($this->once()) ->method('getArguments') ->with($request, $controller) ->will($this->returnValue(array())); return $resolver; } private function expectsSetRequestWithAt($container, $with, $at) { $container ->expects($this->at($at)) ->method('set') ->with($this->equalTo('request'), $this->equalTo($with), $this->equalTo('request')) ; return $this; } private function expectsEnterScopeOnce($container) { $container ->expects($this->once()) ->method('enterScope') ->with($this->equalTo('request')) ; return $this; } private function expectsLeaveScopeOnce($container) { $container ->expects($this->once()) ->method('leaveScope') ->with($this->equalTo('request')) ; return $this; } } PK!x99=test/HttpKernel/Symfony/Component/HttpKernel/phpunit.xml.distnu[ ./Tests/ ./ ./Tests ./vendor PK!]Q Rtest/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader\Tests; use Symfony\Component\ClassLoader\ClassCollectionLoader; require_once __DIR__.'/Fixtures/ClassesWithParents/GInterface.php'; require_once __DIR__.'/Fixtures/ClassesWithParents/CInterface.php'; require_once __DIR__.'/Fixtures/ClassesWithParents/B.php'; require_once __DIR__.'/Fixtures/ClassesWithParents/A.php'; class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase { public function testTraitDependencies() { if (version_compare(phpversion(), '5.4', '<')) { $this->markTestSkipped('Requires PHP > 5.4'); return; } require_once __DIR__.'/Fixtures/deps/traits.php'; $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader'); $m = $r->getMethod('getOrderedClasses'); $m->setAccessible(true); $ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', array('CTFoo')); $this->assertEquals( array('TD', 'TC', 'TB', 'TA', 'TZ', 'CTFoo'), array_map(function ($class) { return $class->getName(); }, $ordered) ); $ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', array('CTBar')); $this->assertEquals( array('TD', 'TZ', 'TC', 'TB', 'TA', 'CTBar'), array_map(function ($class) { return $class->getName(); }, $ordered) ); } /** * @dataProvider getDifferentOrders */ public function testClassReordering(array $classes) { $expected = array( 'ClassesWithParents\\GInterface', 'ClassesWithParents\\CInterface', 'ClassesWithParents\\B', 'ClassesWithParents\\A', ); $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader'); $m = $r->getMethod('getOrderedClasses'); $m->setAccessible(true); $ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', $classes); $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered)); } public function getDifferentOrders() { return array( array(array( 'ClassesWithParents\\A', 'ClassesWithParents\\CInterface', 'ClassesWithParents\\GInterface', 'ClassesWithParents\\B', )), array(array( 'ClassesWithParents\\B', 'ClassesWithParents\\A', 'ClassesWithParents\\CInterface', )), array(array( 'ClassesWithParents\\CInterface', 'ClassesWithParents\\B', 'ClassesWithParents\\A', )), array(array( 'ClassesWithParents\\A', )), ); } /** * @dataProvider getDifferentOrdersForTraits */ public function testClassWithTraitsReordering(array $classes) { if (version_compare(phpversion(), '5.4', '<')) { $this->markTestSkipped('Requires PHP > 5.4'); return; } require_once __DIR__.'/Fixtures/ClassesWithParents/ATrait.php'; require_once __DIR__.'/Fixtures/ClassesWithParents/BTrait.php'; require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php'; require_once __DIR__.'/Fixtures/ClassesWithParents/D.php'; require_once __DIR__.'/Fixtures/ClassesWithParents/E.php'; $expected = array( 'ClassesWithParents\\GInterface', 'ClassesWithParents\\CInterface', 'ClassesWithParents\\ATrait', 'ClassesWithParents\\BTrait', 'ClassesWithParents\\CTrait', 'ClassesWithParents\\B', 'ClassesWithParents\\A', 'ClassesWithParents\\D', 'ClassesWithParents\\E', ); $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader'); $m = $r->getMethod('getOrderedClasses'); $m->setAccessible(true); $ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', $classes); $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered)); } public function getDifferentOrdersForTraits() { return array( array(array( 'ClassesWithParents\\E', 'ClassesWithParents\\ATrait', )), array(array( 'ClassesWithParents\\E', )), ); } /** * @dataProvider getFixNamespaceDeclarationsData */ public function testFixNamespaceDeclarations($source, $expected) { $this->assertEquals('assertEquals('assertEquals(<< * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace ClassMap; abstract class SomeParent { } PK!֡Z  Xtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace ClassMap; interface SomeInterface { } PK!KG9ՈUtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Foo\Bar; class A {} class B {} PK!.~oDDTtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeClass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace ClassMap; class SomeClass extends SomeParent implements SomeInterface { } PK!RTtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notPhpFile.mdnu[This file should be skipped. PK!iTtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notAClass.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace NamespaceCollision\A\B; class Bar { public static $loaded = true; } PK!AAatest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace NamespaceCollision\A\B; class Foo { public static $loaded = true; } PK!@OOQtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Namespaced; class Bar { public static $loaded = true; } PK!ᒟ55Ptest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Namespaced; class Baz { public static $loaded = true; } PK!R55Ptest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Namespaced; class Foo { public static $loaded = true; } PK!UXYtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Namespaced; class WithComments { /** @Boolean */ public static $loaded = true; } $string = 'string shoult not be modified {$string}'; $heredoc = (<< * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class Pearlike_WithComments { /** @Boolean */ public static $loaded = true; } PK!>XMtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/deps/traits.phpnu[XX`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace NamespaceCollision\A; class Bar { public static $loaded = true; } PK!i??`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace NamespaceCollision\A; class Foo { public static $loaded = true; } PK!nDD[test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2/FooBar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Namespaced; class FooBar { public static $loaded = true; } PK!xwCCZtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike/FooBar.phpnu[\oNNitest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Apc\NamespaceCollision\A\B; class Bar { public static $loaded = true; } PK!][EEitest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Apc\NamespaceCollision\A\B; class Foo { public static $loaded = true; } PK!/5<<Wtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Apc\Namespaced; class FooBar { public static $loaded = true; } PK!ے99Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Apc\Namespaced; class Bar { public static $loaded = true; } PK!$y99Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Apc\Namespaced; class Baz { public static $loaded = true; } PK!0- +99Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Apc\Namespaced; class Foo { public static $loaded = true; } PK!yQUmDDRtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Apc\NamespaceCollision\A; class Bar { public static $loaded = true; } PK!qoCChtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Apc\NamespaceCollision\A; class Foo { public static $loaded = true; } PK!/5<<`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced/FooBar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Apc\Namespaced; class FooBar { public static $loaded = true; } PK!GGbtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader\Tests; use Symfony\Component\ClassLoader\ClassLoader; class ClassLoaderTest extends \PHPUnit_Framework_TestCase { public function testGetPrefixes() { $loader = new ClassLoader(); $loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->addPrefix('Bar', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->addPrefix('Bas', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $prefixes = $loader->getPrefixes(); $this->assertArrayHasKey('Foo', $prefixes); $this->assertArrayNotHasKey('Foo1', $prefixes); $this->assertArrayHasKey('Bar', $prefixes); $this->assertArrayHasKey('Bas', $prefixes); } public function testGetFallbackDirs() { $loader = new ClassLoader(); $loader->addPrefix(null, __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->addPrefix(null, __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $fallback_dirs = $loader->getFallbackDirs(); $this->assertCount(2, $fallback_dirs); } /** * @dataProvider getLoadClassTests */ public function testLoadClass($className, $testClassName, $message) { $loader = new ClassLoader(); $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->loadClass($testClassName); $this->assertTrue(class_exists($className), $message); } public function getLoadClassTests() { return array( array('\\Namespaced2\\Foo', 'Namespaced2\\Foo', '->loadClass() loads Namespaced2\Foo class'), array('\\Pearlike2_Foo', 'Pearlike2_Foo', '->loadClass() loads Pearlike2_Foo class'), ); } /** * @dataProvider getLoadNonexistentClassTests */ public function testLoadNonexistentClass($className, $testClassName, $message) { $loader = new ClassLoader(); $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->loadClass($testClassName); $this->assertFalse(class_exists($className), $message); } public function getLoadNonexistentClassTests() { return array( array('\\Pearlike3_Bar', '\\Pearlike3_Bar', '->loadClass() loads non existing Pearlike3_Bar class with a leading slash'), ); } public function testAddPrefix() { $loader = new ClassLoader(); $loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $prefixes = $loader->getPrefixes(); $this->assertArrayHasKey('Foo', $prefixes); $this->assertCount(2, $prefixes['Foo']); } public function testUseIncludePath() { $loader = new ClassLoader(); $this->assertFalse($loader->getUseIncludePath()); $this->assertNull($loader->findFile('Foo')); $includePath = get_include_path(); $loader->setUseIncludePath(true); $this->assertTrue($loader->getUseIncludePath()); set_include_path(__DIR__.'/Fixtures/includepath'.PATH_SEPARATOR.$includePath); $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'includepath'.DIRECTORY_SEPARATOR.'Foo.php', $loader->findFile('Foo')); set_include_path($includePath); } /** * @dataProvider getLoadClassFromFallbackTests */ public function testLoadClassFromFallback($className, $testClassName, $message) { $loader = new ClassLoader(); $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->addPrefix('', array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback')); $loader->loadClass($testClassName); $this->assertTrue(class_exists($className), $message); } public function getLoadClassFromFallbackTests() { return array( array('\\Namespaced2\\Baz', 'Namespaced2\\Baz', '->loadClass() loads Namespaced2\Baz class'), array('\\Pearlike2_Baz', 'Pearlike2_Baz', '->loadClass() loads Pearlike2_Baz class'), array('\\Namespaced2\\FooBar', 'Namespaced2\\FooBar', '->loadClass() loads Namespaced2\Baz class from fallback dir'), array('\\Pearlike2_FooBar', 'Pearlike2_FooBar', '->loadClass() loads Pearlike2_Baz class from fallback dir'), ); } /** * @dataProvider getLoadClassNamespaceCollisionTests */ public function testLoadClassNamespaceCollision($namespaces, $className, $message) { $loader = new ClassLoader(); $loader->addPrefixes($namespaces); $loader->loadClass($className); $this->assertTrue(class_exists($className), $message); } public function getLoadClassNamespaceCollisionTests() { return array( array( array( 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', ), 'NamespaceCollision\C\Foo', '->loadClass() loads NamespaceCollision\C\Foo from alpha.', ), array( array( 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', ), 'NamespaceCollision\C\Bar', '->loadClass() loads NamespaceCollision\C\Bar from alpha.', ), array( array( 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', ), 'NamespaceCollision\C\B\Foo', '->loadClass() loads NamespaceCollision\C\B\Foo from beta.', ), array( array( 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', ), 'NamespaceCollision\C\B\Bar', '->loadClass() loads NamespaceCollision\C\B\Bar from beta.', ), array( array( 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', ), 'PrefixCollision_C_Foo', '->loadClass() loads PrefixCollision_C_Foo from alpha.', ), array( array( 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', ), 'PrefixCollision_C_Bar', '->loadClass() loads PrefixCollision_C_Bar from alpha.', ), array( array( 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', ), 'PrefixCollision_C_B_Foo', '->loadClass() loads PrefixCollision_C_B_Foo from beta.', ), array( array( 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', ), 'PrefixCollision_C_B_Bar', '->loadClass() loads PrefixCollision_C_B_Bar from beta.', ), ); } } PK!e:{aTtest/ClassLoader/Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader\Tests; use Symfony\Component\ClassLoader\ApcUniversalClassLoader; class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase { protected function setUp() { if (!extension_loaded('apc')) { $this->markTestSkipped('The apc extension is not available.'); } if (!(ini_get('apc.enabled') && ini_get('apc.enable_cli'))) { $this->markTestSkipped('The apc extension is available, but not enabled.'); } else { apc_clear_cache('user'); } } protected function tearDown() { if (ini_get('apc.enabled') && ini_get('apc.enable_cli')) { apc_clear_cache('user'); } } public function testConstructor() { $loader = new ApcUniversalClassLoader('test.prefix.'); $loader->registerNamespace('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $this->assertEquals($loader->findFile('\Apc\Namespaced\FooBar'), apc_fetch('test.prefix.\Apc\Namespaced\FooBar'), '__construct() takes a prefix as its first argument'); } /** * @dataProvider getLoadClassTests */ public function testLoadClass($className, $testClassName, $message) { $loader = new ApcUniversalClassLoader('test.prefix.'); $loader->registerNamespace('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerPrefix('Apc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->loadClass($testClassName); $this->assertTrue(class_exists($className), $message); } public function getLoadClassTests() { return array( array('\\Apc\\Namespaced\\Foo', '\\Apc\\Namespaced\\Foo', '->loadClass() loads Apc\Namespaced\Foo class'), array('Apc_Pearlike_Foo', 'Apc_Pearlike_Foo', '->loadClass() loads Apc_Pearlike_Foo class'), array('\\Apc\\Namespaced\\Bar', '\\Apc\\Namespaced\\Bar', '->loadClass() loads Apc\Namespaced\Bar class with a leading slash'), array('Apc_Pearlike_Bar', '\\Apc_Pearlike_Bar', '->loadClass() loads Apc_Pearlike_Bar class with a leading slash'), ); } /** * @dataProvider getLoadClassFromFallbackTests */ public function testLoadClassFromFallback($className, $testClassName, $message) { $loader = new ApcUniversalClassLoader('test.prefix.fallback'); $loader->registerNamespace('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerPrefix('Apc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerNamespaceFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/fallback')); $loader->registerPrefixFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/fallback')); $loader->loadClass($testClassName); $this->assertTrue(class_exists($className), $message); } public function getLoadClassFromFallbackTests() { return array( array('\\Apc\\Namespaced\\Baz', '\\Apc\\Namespaced\\Baz', '->loadClass() loads Apc\Namespaced\Baz class'), array('Apc_Pearlike_Baz', 'Apc_Pearlike_Baz', '->loadClass() loads Apc_Pearlike_Baz class'), array('\\Apc\\Namespaced\\FooBar', '\\Apc\\Namespaced\\FooBar', '->loadClass() loads Apc\Namespaced\Baz class from fallback dir'), array('Apc_Pearlike_FooBar', 'Apc_Pearlike_FooBar', '->loadClass() loads Apc_Pearlike_Baz class from fallback dir'), ); } /** * @dataProvider getLoadClassNamespaceCollisionTests */ public function testLoadClassNamespaceCollision($namespaces, $className, $message) { $loader = new ApcUniversalClassLoader('test.prefix.collision.'); $loader->registerNamespaces($namespaces); $loader->loadClass($className); $this->assertTrue(class_exists($className), $message); } public function getLoadClassNamespaceCollisionTests() { return array( array( array( 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', ), '\Apc\NamespaceCollision\A\Foo', '->loadClass() loads NamespaceCollision\A\Foo from alpha.', ), array( array( 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', ), '\Apc\NamespaceCollision\A\Bar', '->loadClass() loads NamespaceCollision\A\Bar from alpha.', ), array( array( 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', ), '\Apc\NamespaceCollision\A\B\Foo', '->loadClass() loads NamespaceCollision\A\B\Foo from beta.', ), array( array( 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', ), '\Apc\NamespaceCollision\A\B\Bar', '->loadClass() loads NamespaceCollision\A\B\Bar from beta.', ), ); } /** * @dataProvider getLoadClassPrefixCollisionTests */ public function testLoadClassPrefixCollision($prefixes, $className, $message) { $loader = new ApcUniversalClassLoader('test.prefix.collision.'); $loader->registerPrefixes($prefixes); $loader->loadClass($className); $this->assertTrue(class_exists($className), $message); } public function getLoadClassPrefixCollisionTests() { return array( array( array( 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', ), 'ApcPrefixCollision_A_Foo', '->loadClass() loads ApcPrefixCollision_A_Foo from alpha.', ), array( array( 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', ), 'ApcPrefixCollision_A_Bar', '->loadClass() loads ApcPrefixCollision_A_Bar from alpha.', ), array( array( 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', ), 'ApcPrefixCollision_A_B_Foo', '->loadClass() loads ApcPrefixCollision_A_B_Foo from beta.', ), array( array( 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', ), 'ApcPrefixCollision_A_B_Bar', '->loadClass() loads ApcPrefixCollision_A_B_Bar from beta.', ), ); } } PK!8`##Qtest/ClassLoader/Symfony/Component/ClassLoader/Tests/UniversalClassLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader\Tests; use Symfony\Component\ClassLoader\UniversalClassLoader; class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getLoadClassTests */ public function testLoadClass($className, $testClassName, $message) { $loader = new UniversalClassLoader(); $loader->registerNamespace('Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $this->assertTrue($loader->loadClass($testClassName)); $this->assertTrue(class_exists($className), $message); } public function getLoadClassTests() { return array( array('\\Namespaced\\Foo', 'Namespaced\\Foo', '->loadClass() loads Namespaced\Foo class'), array('\\Pearlike_Foo', 'Pearlike_Foo', '->loadClass() loads Pearlike_Foo class'), ); } public function testUseIncludePath() { $loader = new UniversalClassLoader(); $this->assertFalse($loader->getUseIncludePath()); $this->assertNull($loader->findFile('Foo')); $includePath = get_include_path(); $loader->useIncludePath(true); $this->assertTrue($loader->getUseIncludePath()); set_include_path(__DIR__.'/Fixtures/includepath'.PATH_SEPARATOR.$includePath); $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'includepath'.DIRECTORY_SEPARATOR.'Foo.php', $loader->findFile('Foo')); set_include_path($includePath); } public function testGetNamespaces() { $loader = new UniversalClassLoader(); $loader->registerNamespace('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerNamespace('Bar', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerNamespace('Bas', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $namespaces = $loader->getNamespaces(); $this->assertArrayHasKey('Foo', $namespaces); $this->assertArrayNotHasKey('Foo1', $namespaces); $this->assertArrayHasKey('Bar', $namespaces); $this->assertArrayHasKey('Bas', $namespaces); } public function testGetPrefixes() { $loader = new UniversalClassLoader(); $loader->registerPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerPrefix('Bar', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerPrefix('Bas', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $prefixes = $loader->getPrefixes(); $this->assertArrayHasKey('Foo', $prefixes); $this->assertArrayNotHasKey('Foo1', $prefixes); $this->assertArrayHasKey('Bar', $prefixes); $this->assertArrayHasKey('Bas', $prefixes); } /** * @dataProvider getLoadClassFromFallbackTests */ public function testLoadClassFromFallback($className, $testClassName, $message) { $loader = new UniversalClassLoader(); $loader->registerNamespace('Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); $loader->registerNamespaceFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback')); $loader->registerPrefixFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback')); $this->assertTrue($loader->loadClass($testClassName)); $this->assertTrue(class_exists($className), $message); } public function getLoadClassFromFallbackTests() { return array( array('\\Namespaced\\Baz', 'Namespaced\\Baz', '->loadClass() loads Namespaced\Baz class'), array('\\Pearlike_Baz', 'Pearlike_Baz', '->loadClass() loads Pearlike_Baz class'), array('\\Namespaced\\FooBar', 'Namespaced\\FooBar', '->loadClass() loads Namespaced\Baz class from fallback dir'), array('\\Pearlike_FooBar', 'Pearlike_FooBar', '->loadClass() loads Pearlike_Baz class from fallback dir'), ); } public function testRegisterPrefixFallback() { $loader = new UniversalClassLoader(); $loader->registerPrefixFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'); $this->assertEquals(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'), $loader->getPrefixFallbacks()); } public function testRegisterNamespaceFallback() { $loader = new UniversalClassLoader(); $loader->registerNamespaceFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Namespaced/fallback'); $this->assertEquals(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Namespaced/fallback'), $loader->getNamespaceFallbacks()); } /** * @dataProvider getLoadClassNamespaceCollisionTests */ public function testLoadClassNamespaceCollision($namespaces, $className, $message) { $loader = new UniversalClassLoader(); $loader->registerNamespaces($namespaces); $this->assertTrue($loader->loadClass($className)); $this->assertTrue(class_exists($className), $message); } public function getLoadClassNamespaceCollisionTests() { return array( array( array( 'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', 'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', ), 'NamespaceCollision\A\Foo', '->loadClass() loads NamespaceCollision\A\Foo from alpha.', ), array( array( 'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', 'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', ), 'NamespaceCollision\A\Bar', '->loadClass() loads NamespaceCollision\A\Bar from alpha.', ), array( array( 'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', 'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', ), 'NamespaceCollision\A\B\Foo', '->loadClass() loads NamespaceCollision\A\B\Foo from beta.', ), array( array( 'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', 'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', ), 'NamespaceCollision\A\B\Bar', '->loadClass() loads NamespaceCollision\A\B\Bar from beta.', ), ); } /** * @dataProvider getLoadClassPrefixCollisionTests */ public function testLoadClassPrefixCollision($prefixes, $className, $message) { $loader = new UniversalClassLoader(); $loader->registerPrefixes($prefixes); $this->assertTrue($loader->loadClass($className)); $this->assertTrue(class_exists($className), $message); } public function getLoadClassPrefixCollisionTests() { return array( array( array( 'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', 'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', ), 'PrefixCollision_A_Foo', '->loadClass() loads PrefixCollision_A_Foo from alpha.', ), array( array( 'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', 'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', ), 'PrefixCollision_A_Bar', '->loadClass() loads PrefixCollision_A_Bar from alpha.', ), array( array( 'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', 'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', ), 'PrefixCollision_A_B_Foo', '->loadClass() loads PrefixCollision_A_B_Foo from beta.', ), array( array( 'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', 'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', ), 'PrefixCollision_A_B_Bar', '->loadClass() loads PrefixCollision_A_B_Bar from beta.', ), ); } } PK!\|Ntest/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader\Tests; use Symfony\Component\ClassLoader\ClassMapGenerator; class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase { /** * @var string $workspace */ private $workspace = null; public function prepare_workspace() { $this->workspace = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.time().rand(0, 1000); mkdir($this->workspace, 0777, true); $this->workspace = realpath($this->workspace); } /** * @param string $file */ private function clean($file) { if (is_dir($file) && !is_link($file)) { $dir = new \FilesystemIterator($file); foreach ($dir as $childFile) { $this->clean($childFile); } rmdir($file); } else { unlink($file); } } /** * @dataProvider getTestCreateMapTests */ public function testDump($directory, $expected) { $this->prepare_workspace(); $file = $this->workspace.'/file'; $generator = new ClassMapGenerator(); $generator->dump($directory, $file); $this->assertFileExists($file); $this->clean($this->workspace); } /** * @dataProvider getTestCreateMapTests */ public function testCreateMap($directory, $expected) { $this->assertEqualsNormalized($expected, ClassMapGenerator::createMap($directory)); } public function getTestCreateMapTests() { $data = array( array(__DIR__.'/Fixtures/Namespaced', array( 'Namespaced\\Bar' => realpath(__DIR__).'/Fixtures/Namespaced/Bar.php', 'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php', 'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php', 'Namespaced\\WithComments' => realpath(__DIR__).'/Fixtures/Namespaced/WithComments.php', ) ), array(__DIR__.'/Fixtures/beta/NamespaceCollision', array( 'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php', 'NamespaceCollision\\A\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Foo.php', 'NamespaceCollision\\C\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Bar.php', 'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php', )), array(__DIR__.'/Fixtures/Pearlike', array( 'Pearlike_Foo' => realpath(__DIR__).'/Fixtures/Pearlike/Foo.php', 'Pearlike_Bar' => realpath(__DIR__).'/Fixtures/Pearlike/Bar.php', 'Pearlike_Baz' => realpath(__DIR__).'/Fixtures/Pearlike/Baz.php', 'Pearlike_WithComments' => realpath(__DIR__).'/Fixtures/Pearlike/WithComments.php', )), array(__DIR__.'/Fixtures/classmap', array( 'Foo\\Bar\\A' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php', 'Foo\\Bar\\B' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php', 'A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', 'Alpha\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', 'Alpha\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', 'Beta\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', 'Beta\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', 'ClassMap\\SomeInterface' => realpath(__DIR__).'/Fixtures/classmap/SomeInterface.php', 'ClassMap\\SomeParent' => realpath(__DIR__).'/Fixtures/classmap/SomeParent.php', 'ClassMap\\SomeClass' => realpath(__DIR__).'/Fixtures/classmap/SomeClass.php', )), ); if (version_compare(PHP_VERSION, '5.4', '>=')) { $data[] = array(__DIR__.'/Fixtures/php5.4', array( 'TFoo' => __DIR__.'/Fixtures/php5.4/traits.php', 'CFoo' => __DIR__.'/Fixtures/php5.4/traits.php', 'Foo\\TBar' => __DIR__.'/Fixtures/php5.4/traits.php', 'Foo\\IBar' => __DIR__.'/Fixtures/php5.4/traits.php', 'Foo\\TFooBar' => __DIR__.'/Fixtures/php5.4/traits.php', 'Foo\\CBar' => __DIR__.'/Fixtures/php5.4/traits.php', )); } return $data; } public function testCreateMapFinderSupport() { $finder = new \Symfony\Component\Finder\Finder(); $finder->files()->in(__DIR__.'/Fixtures/beta/NamespaceCollision'); $this->assertEqualsNormalized(array( 'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php', 'NamespaceCollision\\A\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Foo.php', 'NamespaceCollision\\C\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Bar.php', 'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php', ), ClassMapGenerator::createMap($finder)); } protected function assertEqualsNormalized($expected, $actual, $message = null) { foreach ($expected as $ns => $path) { $expected[$ns] = strtr($path, '\\', '/'); } foreach ($actual as $ns => $path) { $actual[$ns] = strtr($path, '\\', '/'); } $this->assertEquals($expected, $actual, $message); } } PK!)mm?test/ClassLoader/Symfony/Component/ClassLoader/phpunit.xml.distnu[ ./Tests/ ./ ./Resources ./Tests ./vendor PK!yMV]test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests; require_once __DIR__.'/Fixtures/includes/classes.php'; require_once __DIR__.'/Fixtures/includes/ProjectExtension.php'; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Scope; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\ExpressionLanguage\Expression; class ContainerBuilderTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinitions * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinitions * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinition * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinition */ public function testDefinitions() { $builder = new ContainerBuilder(); $definitions = array( 'foo' => new Definition('FooClass'), 'bar' => new Definition('BarClass'), ); $builder->setDefinitions($definitions); $this->assertEquals($definitions, $builder->getDefinitions(), '->setDefinitions() sets the service definitions'); $this->assertTrue($builder->hasDefinition('foo'), '->hasDefinition() returns true if a service definition exists'); $this->assertFalse($builder->hasDefinition('foobar'), '->hasDefinition() returns false if a service definition does not exist'); $builder->setDefinition('foobar', $foo = new Definition('FooBarClass')); $this->assertEquals($foo, $builder->getDefinition('foobar'), '->getDefinition() returns a service definition if defined'); $this->assertTrue($builder->setDefinition('foobar', $foo = new Definition('FooBarClass')) === $foo, '->setDefinition() implements a fluid interface by returning the service reference'); $builder->addDefinitions($defs = array('foobar' => new Definition('FooBarClass'))); $this->assertEquals(array_merge($definitions, $defs), $builder->getDefinitions(), '->addDefinitions() adds the service definitions'); try { $builder->getDefinition('baz'); $this->fail('->getDefinition() throws an InvalidArgumentException if the service definition does not exist'); } catch (\InvalidArgumentException $e) { $this->assertEquals('The service definition "baz" does not exist.', $e->getMessage(), '->getDefinition() throws an InvalidArgumentException if the service definition does not exist'); } } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::register */ public function testRegister() { $builder = new ContainerBuilder(); $builder->register('foo', 'FooClass'); $this->assertTrue($builder->hasDefinition('foo'), '->register() registers a new service definition'); $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $builder->getDefinition('foo'), '->register() returns the newly created Definition instance'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::has */ public function testHas() { $builder = new ContainerBuilder(); $this->assertFalse($builder->has('foo'), '->has() returns false if the service does not exist'); $builder->register('foo', 'FooClass'); $this->assertTrue($builder->has('foo'), '->has() returns true if a service definition exists'); $builder->set('bar', new \stdClass()); $this->assertTrue($builder->has('bar'), '->has() returns true if a service exists'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get */ public function testGet() { $builder = new ContainerBuilder(); try { $builder->get('foo'); $this->fail('->get() throws an InvalidArgumentException if the service does not exist'); } catch (\InvalidArgumentException $e) { $this->assertEquals('The service definition "foo" does not exist.', $e->getMessage(), '->get() throws an InvalidArgumentException if the service does not exist'); } $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service does not exist and NULL_ON_INVALID_REFERENCE is passed as a second argument'); $builder->register('foo', 'stdClass'); $this->assertInternalType('object', $builder->get('foo'), '->get() returns the service definition associated with the id'); $builder->set('bar', $bar = new \stdClass()); $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id'); $builder->register('bar', 'stdClass'); $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id even if a definition has been defined'); $builder->register('baz', 'stdClass')->setArguments(array(new Reference('baz'))); try { @$builder->get('baz'); $this->fail('->get() throws a ServiceCircularReferenceException if the service has a circular reference to itself'); } catch (\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException $e) { $this->assertEquals('Circular reference detected for service "baz", path: "baz".', $e->getMessage(), '->get() throws a LogicException if the service has a circular reference to itself'); } $builder->register('foobar', 'stdClass')->setScope('container'); $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared'); } /** * @covers \Symfony\Component\DependencyInjection\ContainerBuilder::get * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException * @expectedExceptionMessage You have requested a synthetic service ("foo"). The DIC does not know how to construct this service. */ public function testGetUnsetLoadingServiceWhenCreateServiceThrowsAnException() { $builder = new ContainerBuilder(); $builder->register('foo', 'stdClass')->setSynthetic(true); // we expect a RuntimeException here as foo is synthetic try { $builder->get('foo'); } catch (RuntimeException $e) { } // we must also have the same RuntimeException here $builder->get('foo'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get */ public function testGetReturnsNullOnInactiveScope() { $builder = new ContainerBuilder(); $builder->register('foo', 'stdClass')->setScope('request'); $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get */ public function testGetReturnsNullOnInactiveScopeWhenServiceIsCreatedByAMethod() { $builder = new ProjectContainer(); $this->assertNull($builder->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getServiceIds */ public function testGetServiceIds() { $builder = new ContainerBuilder(); $builder->register('foo', 'stdClass'); $builder->bar = $bar = new \stdClass(); $builder->register('bar', 'stdClass'); $this->assertEquals(array('foo', 'bar', 'service_container'), $builder->getServiceIds(), '->getServiceIds() returns all defined service ids'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAlias * @covers Symfony\Component\DependencyInjection\ContainerBuilder::hasAlias * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAlias */ public function testAliases() { $builder = new ContainerBuilder(); $builder->register('foo', 'stdClass'); $builder->setAlias('bar', 'foo'); $this->assertTrue($builder->hasAlias('bar'), '->hasAlias() returns true if the alias exists'); $this->assertFalse($builder->hasAlias('foobar'), '->hasAlias() returns false if the alias does not exist'); $this->assertEquals('foo', (string) $builder->getAlias('bar'), '->getAlias() returns the aliased service'); $this->assertTrue($builder->has('bar'), '->setAlias() defines a new service'); $this->assertTrue($builder->get('bar') === $builder->get('foo'), '->setAlias() creates a service that is an alias to another one'); try { $builder->getAlias('foobar'); $this->fail('->getAlias() throws an InvalidArgumentException if the alias does not exist'); } catch (\InvalidArgumentException $e) { $this->assertEquals('The service alias "foobar" does not exist.', $e->getMessage(), '->getAlias() throws an InvalidArgumentException if the alias does not exist'); } } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAliases */ public function testGetAliases() { $builder = new ContainerBuilder(); $builder->setAlias('bar', 'foo'); $builder->setAlias('foobar', 'foo'); $builder->setAlias('moo', new Alias('foo', false)); $aliases = $builder->getAliases(); $this->assertEquals('foo', (string) $aliases['bar']); $this->assertTrue($aliases['bar']->isPublic()); $this->assertEquals('foo', (string) $aliases['foobar']); $this->assertEquals('foo', (string) $aliases['moo']); $this->assertFalse($aliases['moo']->isPublic()); $builder->register('bar', 'stdClass'); $this->assertFalse($builder->hasAlias('bar')); $builder->set('foobar', 'stdClass'); $builder->set('moo', 'stdClass'); $this->assertCount(0, $builder->getAliases(), '->getAliases() does not return aliased services that have been overridden'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAliases */ public function testSetAliases() { $builder = new ContainerBuilder(); $builder->setAliases(array('bar' => 'foo', 'foobar' => 'foo')); $aliases = $builder->getAliases(); $this->assertTrue(isset($aliases['bar'])); $this->assertTrue(isset($aliases['foobar'])); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addAliases */ public function testAddAliases() { $builder = new ContainerBuilder(); $builder->setAliases(array('bar' => 'foo')); $builder->addAliases(array('foobar' => 'foo')); $aliases = $builder->getAliases(); $this->assertTrue(isset($aliases['bar'])); $this->assertTrue(isset($aliases['foobar'])); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addCompilerPass * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getCompilerPassConfig */ public function testAddGetCompilerPass() { $builder = new ContainerBuilder(); $builder->setResourceTracking(false); $builderCompilerPasses = $builder->getCompiler()->getPassConfig()->getPasses(); $builder->addCompilerPass($this->getMock('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface')); $this->assertEquals(sizeof($builderCompilerPasses) + 1, sizeof($builder->getCompiler()->getPassConfig()->getPasses())); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ public function testCreateService() { $builder = new ContainerBuilder(); $builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); $this->assertInstanceOf('\FooClass', $builder->get('foo1'), '->createService() requires the file defined by the service definition'); $builder->register('foo2', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/%file%.php'); $builder->setParameter('file', 'foo'); $this->assertInstanceOf('\FooClass', $builder->get('foo2'), '->createService() replaces parameters in the file provided by the service definition'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ public function testCreateProxyWithRealServiceInstantiator() { $builder = new ContainerBuilder(); $builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); $builder->getDefinition('foo1')->setLazy(true); $foo1 = $builder->get('foo1'); $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls'); $this->assertSame('FooClass', get_class($foo1)); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ public function testCreateServiceClass() { $builder = new ContainerBuilder(); $builder->register('foo1', '%class%'); $builder->setParameter('class', 'stdClass'); $this->assertInstanceOf('\stdClass', $builder->get('foo1'), '->createService() replaces parameters in the class provided by the service definition'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ public function testCreateServiceArguments() { $builder = new ContainerBuilder(); $builder->register('bar', 'stdClass'); $builder->register('foo1', 'FooClass')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'), '%%unescape_it%%')); $builder->setParameter('value', 'bar'); $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar'), '%unescape_it%'), $builder->get('foo1')->arguments, '->createService() replaces parameters and service references in the arguments provided by the service definition'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ public function testCreateServiceFactoryMethod() { $builder = new ContainerBuilder(); $builder->register('bar', 'stdClass'); $builder->register('foo1', 'FooClass')->setFactoryClass('FooClass')->setFactoryMethod('getInstance')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'))); $builder->setParameter('value', 'bar'); $this->assertTrue($builder->get('foo1')->called, '->createService() calls the factory method to create the service instance'); $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar')), $builder->get('foo1')->arguments, '->createService() passes the arguments to the factory method'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ public function testCreateServiceFactoryService() { $builder = new ContainerBuilder(); $builder->register('baz_service')->setFactoryService('baz_factory')->setFactoryMethod('getInstance'); $builder->register('baz_factory', 'BazClass'); $this->assertInstanceOf('BazClass', $builder->get('baz_service')); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ public function testCreateServiceMethodCalls() { $builder = new ContainerBuilder(); $builder->register('bar', 'stdClass'); $builder->register('foo1', 'FooClass')->addMethodCall('setBar', array(array('%value%', new Reference('bar')))); $builder->setParameter('value', 'bar'); $this->assertEquals(array('bar', $builder->get('bar')), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService */ public function testCreateServiceConfigurator() { $builder = new ContainerBuilder(); $builder->register('foo1', 'FooClass')->setConfigurator('sc_configure'); $this->assertTrue($builder->get('foo1')->configured, '->createService() calls the configurator'); $builder->register('foo2', 'FooClass')->setConfigurator(array('%class%', 'configureStatic')); $builder->setParameter('class', 'BazClass'); $this->assertTrue($builder->get('foo2')->configured, '->createService() calls the configurator'); $builder->register('baz', 'BazClass'); $builder->register('foo3', 'FooClass')->setConfigurator(array(new Reference('baz'), 'configure')); $this->assertTrue($builder->get('foo3')->configured, '->createService() calls the configurator'); $builder->register('foo4', 'FooClass')->setConfigurator('foo'); try { $builder->get('foo4'); $this->fail('->createService() throws an InvalidArgumentException if the configure callable is not a valid callable'); } catch (\InvalidArgumentException $e) { $this->assertEquals('The configure callable for class "FooClass" is not a callable.', $e->getMessage(), '->createService() throws an InvalidArgumentException if the configure callable is not a valid callable'); } } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService * @expectedException \RuntimeException */ public function testCreateSyntheticService() { $builder = new ContainerBuilder(); $builder->register('foo', 'FooClass')->setSynthetic(true); $builder->get('foo'); } public function testCreateServiceWithExpression() { $builder = new ContainerBuilder(); $builder->setParameter('bar', 'bar'); $builder->register('bar', 'BarClass'); $builder->register('foo', 'FooClass')->addArgument(array('foo' => new Expression('service("bar").foo ~ parameter("bar")'))); $this->assertEquals('foobar', $builder->get('foo')->arguments['foo']); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::resolveServices */ public function testResolveServices() { $builder = new ContainerBuilder(); $builder->register('foo', 'FooClass'); $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Reference('foo')), '->resolveServices() resolves service references to service instances'); $this->assertEquals(array('foo' => array('foo', $builder->get('foo'))), $builder->resolveServices(array('foo' => array('foo', new Reference('foo')))), '->resolveServices() resolves service references to service instances in nested arrays'); $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Expression('service("foo")')), '->resolveServices() resolves expressions'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge */ public function testMerge() { $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo'))); $container->setResourceTracking(false); $config = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); $container->merge($config); $this->assertEquals(array('bar' => 'foo', 'foo' => 'bar'), $container->getParameterBag()->all(), '->merge() merges current parameters with the loaded ones'); $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo'))); $container->setResourceTracking(false); $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%'))); $container->merge($config); $container->compile(); $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones'); $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo'))); $container->setResourceTracking(false); $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%', 'baz' => '%foo%'))); $container->merge($config); $container->compile(); $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo', 'baz' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones'); $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->register('foo', 'FooClass'); $container->register('bar', 'BarClass'); $config = new ContainerBuilder(); $config->setDefinition('baz', new Definition('BazClass')); $config->setAlias('alias_for_foo', 'foo'); $container->merge($config); $this->assertEquals(array('foo', 'bar', 'baz'), array_keys($container->getDefinitions()), '->merge() merges definitions already defined ones'); $aliases = $container->getAliases(); $this->assertTrue(isset($aliases['alias_for_foo'])); $this->assertEquals('foo', (string) $aliases['alias_for_foo']); $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->register('foo', 'FooClass'); $config->setDefinition('foo', new Definition('BazClass')); $container->merge($config); $this->assertEquals('BazClass', $container->getDefinition('foo')->getClass(), '->merge() overrides already defined services'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge * @expectedException \LogicException */ public function testMergeLogicException() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->compile(); $container->merge(new ContainerBuilder()); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findTaggedServiceIds */ public function testfindTaggedServiceIds() { $builder = new ContainerBuilder(); $builder ->register('foo', 'FooClass') ->addTag('foo', array('foo' => 'foo')) ->addTag('bar', array('bar' => 'bar')) ->addTag('foo', array('foofoo' => 'foofoo')) ; $this->assertEquals($builder->findTaggedServiceIds('foo'), array( 'foo' => array( array('foo' => 'foo'), array('foofoo' => 'foofoo'), ) ), '->findTaggedServiceIds() returns an array of service ids and its tag attributes'); $this->assertEquals(array(), $builder->findTaggedServiceIds('foobar'), '->findTaggedServiceIds() returns an empty array if there is annotated services'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findDefinition */ public function testFindDefinition() { $container = new ContainerBuilder(); $container->setDefinition('foo', $definition = new Definition('FooClass')); $container->setAlias('bar', 'foo'); $container->setAlias('foobar', 'bar'); $this->assertEquals($definition, $container->findDefinition('foobar'), '->findDefinition() returns a Definition'); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addObjectResource */ public function testAddObjectResource() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->addObjectResource(new \BarClass()); $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking'); $container->setResourceTracking(true); $container->addObjectResource(new \BarClass()); $resources = $container->getResources(); $this->assertCount(1, $resources, '1 resource was registered'); /* @var $resource \Symfony\Component\Config\Resource\FileResource */ $resource = end($resources); $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource); $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource())); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addClassResource */ public function testAddClassResource() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->addClassResource(new \ReflectionClass('BarClass')); $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking'); $container->setResourceTracking(true); $container->addClassResource(new \ReflectionClass('BarClass')); $resources = $container->getResources(); $this->assertCount(1, $resources, '1 resource was registered'); /* @var $resource \Symfony\Component\Config\Resource\FileResource */ $resource = end($resources); $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource); $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource())); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::compile */ public function testCompilesClassDefinitionsOfLazyServices() { $container = new ContainerBuilder(); $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking'); $container->register('foo', 'BarClass'); $container->getDefinition('foo')->setLazy(true); $container->compile(); $classesPath = realpath(__DIR__.'/Fixtures/includes/classes.php'); $matchingResources = array_filter( $container->getResources(), function (ResourceInterface $resource) use ($classesPath) { return $resource instanceof FileResource && $classesPath === realpath($resource->getResource()); } ); $this->assertNotEmpty($matchingResources); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getResources * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addResource */ public function testResources() { $container = new ContainerBuilder(); $container->addResource($a = new FileResource(__DIR__.'/Fixtures/xml/services1.xml')); $container->addResource($b = new FileResource(__DIR__.'/Fixtures/xml/services2.xml')); $resources = array(); foreach ($container->getResources() as $resource) { if (false === strpos($resource, '.php')) { $resources[] = $resource; } } $this->assertEquals(array($a, $b), $resources, '->getResources() returns an array of resources read for the current configuration'); $this->assertSame($container, $container->setResources(array())); $this->assertEquals(array(), $container->getResources()); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::registerExtension * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getExtension */ public function testExtension() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->registerExtension($extension = new \ProjectExtension()); $this->assertTrue($container->getExtension('project') === $extension, '->registerExtension() registers an extension'); $this->setExpectedException('LogicException'); $container->getExtension('no_registered'); } public function testRegisteredButNotLoadedExtension() { $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface'); $extension->expects($this->once())->method('getAlias')->will($this->returnValue('project')); $extension->expects($this->never())->method('load'); $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->registerExtension($extension); $container->compile(); } public function testRegisteredAndLoadedExtension() { $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface'); $extension->expects($this->exactly(2))->method('getAlias')->will($this->returnValue('project')); $extension->expects($this->once())->method('load')->with(array(array('foo' => 'bar'))); $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->registerExtension($extension); $container->loadFromExtension('project', array('foo' => 'bar')); $container->compile(); } public function testPrivateServiceUser() { $fooDefinition = new Definition('BarClass'); $fooUserDefinition = new Definition('BarUserClass', array(new Reference('bar'))); $container = new ContainerBuilder(); $container->setResourceTracking(false); $fooDefinition->setPublic(false); $container->addDefinitions(array( 'bar' => $fooDefinition, 'bar_user' => $fooUserDefinition )); $container->compile(); $this->assertInstanceOf('BarClass', $container->get('bar_user')->bar); } /** * @expectedException \BadMethodCallException */ public function testThrowsExceptionWhenSetServiceOnAFrozenContainer() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->setDefinition('a', new Definition('stdClass')); $container->compile(); $container->set('a', new \stdClass()); } /** * @expectedException \BadMethodCallException */ public function testThrowsExceptionWhenAddServiceOnAFrozenContainer() { $container = new ContainerBuilder(); $container->compile(); $container->set('a', new \stdClass()); } public function testNoExceptionWhenSetSyntheticServiceOnAFrozenContainer() { $container = new ContainerBuilder(); $def = new Definition('stdClass'); $def->setSynthetic(true); $container->setDefinition('a', $def); $container->compile(); $container->set('a', $a = new \stdClass()); $this->assertEquals($a, $container->get('a')); } public function testSetOnSynchronizedService() { $container = new ContainerBuilder(); $container->register('baz', 'BazClass') ->setSynchronized(true) ; $container->register('bar', 'BarClass') ->addMethodCall('setBaz', array(new Reference('baz'))) ; $container->set('baz', $baz = new \BazClass()); $this->assertSame($baz, $container->get('bar')->getBaz()); $container->set('baz', $baz = new \BazClass()); $this->assertSame($baz, $container->get('bar')->getBaz()); } public function testSynchronizedServiceWithScopes() { $container = new ContainerBuilder(); $container->addScope(new Scope('foo')); $container->register('baz', 'BazClass') ->setSynthetic(true) ->setSynchronized(true) ->setScope('foo') ; $container->register('bar', 'BarClass') ->addMethodCall('setBaz', array(new Reference('baz', ContainerInterface::NULL_ON_INVALID_REFERENCE, false))) ; $container->compile(); $container->enterScope('foo'); $container->set('baz', $outerBaz = new \BazClass(), 'foo'); $this->assertSame($outerBaz, $container->get('bar')->getBaz()); $container->enterScope('foo'); $container->set('baz', $innerBaz = new \BazClass(), 'foo'); $this->assertSame($innerBaz, $container->get('bar')->getBaz()); $container->leaveScope('foo'); $this->assertNotSame($innerBaz, $container->get('bar')->getBaz()); $this->assertSame($outerBaz, $container->get('bar')->getBaz()); $container->leaveScope('foo'); } /** * @expectedException \BadMethodCallException */ public function testThrowsExceptionWhenSetDefinitionOnAFrozenContainer() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->compile(); $container->setDefinition('a', new Definition()); } /** * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getExtensionConfig * @covers Symfony\Component\DependencyInjection\ContainerBuilder::prependExtensionConfig */ public function testExtensionConfig() { $container = new ContainerBuilder(); $configs = $container->getExtensionConfig('foo'); $this->assertEmpty($configs); $first = array('foo' => 'bar'); $container->prependExtensionConfig('foo', $first); $configs = $container->getExtensionConfig('foo'); $this->assertEquals(array($first), $configs); $second = array('ding' => 'dong'); $container->prependExtensionConfig('foo', $second); $configs = $container->getExtensionConfig('foo'); $this->assertEquals(array($second, $first), $configs); } public function testLazyLoadedService() { $loader = new ClosureLoader($container = new ContainerBuilder()); $loader->load(function (ContainerBuilder $container) { $container->set('a', new \BazClass()); $definition = new Definition('BazClass'); $definition->setLazy(true); $container->setDefinition('a', $definition); } ); $container->setResourceTracking(true); $container->compile(); $class = new \BazClass(); $reflectionClass = new \ReflectionClass($class); $r = new \ReflectionProperty($container, 'resources'); $r->setAccessible(true); $resources = $r->getValue($container); $classInList = false; foreach ($resources as $resource) { if ($resource->getResource() === $reflectionClass->getFileName()) { $classInList = true; break; } } $this->assertTrue($classInList); } } class FooClass {} class ProjectContainer extends ContainerBuilder { public function getFoobazService() { throw new InactiveScopeException('foo', 'request'); } } PK![Vtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests; use Symfony\Component\DependencyInjection\Parameter; class ParameterTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\DependencyInjection\Parameter::__construct */ public function testConstructor() { $ref = new Parameter('foo'); $this->assertEquals('foo', (string) $ref, '__construct() sets the id of the parameter, which is used for the __toString() method'); } } PK!~O99ktest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\LazyProxy\PhpDumper; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; /** * Tests for {@see \Symfony\Component\DependencyInjection\PhpDumper\NullDumper} * * @author Marco Pivetta * * @covers \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper */ class NullDumperTest extends \PHPUnit_Framework_TestCase { public function testNullDumper() { $dumper = new NullDumper(); $definition = new Definition('stdClass'); $this->assertFalse($dumper->isProxyCandidate($definition)); $this->assertSame('', $dumper->getProxyFactoryCode($definition, 'foo')); $this->assertSame('', $dumper->getProxyCode($definition)); } } PK!I8i{test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\LazyProxy\Instantiator; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; /** * Tests for {@see \Symfony\Component\DependencyInjection\Instantiator\RealServiceInstantiator} * * @author Marco Pivetta * * @covers \Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator */ class RealServiceInstantiatorTest extends \PHPUnit_Framework_TestCase { public function testInstantiateProxy() { $instantiator = new RealServiceInstantiator(); $instance = new \stdClass(); $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); $callback = function () use ($instance) { return $instance; }; $this->assertSame($instance, $instantiator->instantiateProxy($container, new Definition(), 'foo', $callback)); } } PK!//\test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.phpnu[setParameter('foo', 'foo'); PK!G3G@ `test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.phpnu[parameters = $this->getDefaultParameters(); $this->services = $this->scopedServices = $this->scopeStacks = array(); $this->set('service_container', $this); $this->scopes = array(); $this->scopeChildren = array(); $this->methodMap = array( 'test' => 'getTestService', ); $this->aliases = array(); } /** * Gets the 'test' service. * * This service is shared. * This method always returns the same instance of the service. * * @return stdClass A stdClass instance. */ protected function getTestService() { return $this->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end')); } /** * {@inheritdoc} */ public function getParameter($name) { $name = strtolower($name); if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } return $this->parameters[$name]; } /** * {@inheritdoc} */ public function hasParameter($name) { $name = strtolower($name); return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters); } /** * {@inheritdoc} */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } /** * {@inheritDoc} */ public function getParameterBag() { if (null === $this->parameterBag) { $this->parameterBag = new FrozenParameterBag($this->parameters); } return $this->parameterBag; } /** * Gets the default parameters. * * @return array An array of the default parameters */ protected function getDefaultParameters() { return array( 'empty_value' => '', 'some_string' => '-', ); } } PK!E))atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.phpnu[getDefaultParameters())); $this->methodMap = array( 'bar' => 'getBarService', 'baz' => 'getBazService', 'depends_on_request' => 'getDependsOnRequestService', 'factory_service' => 'getFactoryServiceService', 'foo' => 'getFooService', 'foo.baz' => 'getFoo_BazService', 'foo_bar' => 'getFooBarService', 'foo_with_inline' => 'getFooWithInlineService', 'inlined' => 'getInlinedService', 'method_call1' => 'getMethodCall1Service', 'request' => 'getRequestService', ); $this->aliases = array( 'alias_for_alias' => 'foo', 'alias_for_foo' => 'foo', ); } /** * Gets the 'bar' service. * * This service is shared. * This method always returns the same instance of the service. * * @return FooClass A FooClass instance. */ protected function getBarService() { $this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar')); $this->get('foo.baz')->configure($instance); return $instance; } /** * Gets the 'baz' service. * * This service is shared. * This method always returns the same instance of the service. * * @return Baz A Baz instance. */ protected function getBazService() { $this->services['baz'] = $instance = new \Baz(); $instance->setFoo($this->get('foo_with_inline')); return $instance; } /** * Gets the 'depends_on_request' service. * * This service is shared. * This method always returns the same instance of the service. * * @return stdClass A stdClass instance. */ protected function getDependsOnRequestService() { $this->services['depends_on_request'] = $instance = new \stdClass(); $instance->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE)); return $instance; } /** * Gets the 'factory_service' service. * * This service is shared. * This method always returns the same instance of the service. * * @return Bar A Bar instance. */ protected function getFactoryServiceService() { return $this->services['factory_service'] = $this->get('foo.baz')->getInstance(); } /** * Gets the 'foo' service. * * This service is shared. * This method always returns the same instance of the service. * * @return FooClass A FooClass instance. */ protected function getFooService() { $a = $this->get('foo.baz'); $this->services['foo'] = $instance = call_user_func(array('FooClass', 'getInstance'), 'foo', $a, array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')), true, $this); $instance->setBar($this->get('bar')); $instance->initialize(); $instance->foo = 'bar'; $instance->moo = $a; $instance->qux = array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')); sc_configure($instance); return $instance; } /** * Gets the 'foo.baz' service. * * This service is shared. * This method always returns the same instance of the service. * * @return object A %baz_class% instance. */ protected function getFoo_BazService() { $this->services['foo.baz'] = $instance = call_user_func(array($this->getParameter('baz_class'), 'getInstance')); call_user_func(array($this->getParameter('baz_class'), 'configureStatic1'), $instance); return $instance; } /** * Gets the 'foo_bar' service. * * @return object A %foo_class% instance. */ protected function getFooBarService() { $class = $this->getParameter('foo_class'); return new $class(); } /** * Gets the 'foo_with_inline' service. * * This service is shared. * This method always returns the same instance of the service. * * @return Foo A Foo instance. */ protected function getFooWithInlineService() { $this->services['foo_with_inline'] = $instance = new \Foo(); $instance->setBar($this->get('inlined')); return $instance; } /** * Gets the 'method_call1' service. * * This service is shared. * This method always returns the same instance of the service. * * @return FooClass A FooClass instance. */ protected function getMethodCall1Service() { require_once '%path%foo.php'; $this->services['method_call1'] = $instance = new \FooClass(); $instance->setBar($this->get('foo')); $instance->setBar($this->get('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)); if ($this->has('foo3')) { $instance->setBar($this->get('foo3', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } if ($this->has('foobaz')) { $instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } $instance->setBar(($this->get("foo")->foo() . $this->getParameter("foo"))); return $instance; } /** * Gets the 'request' service. * * This service is shared. * This method always returns the same instance of the service. * * @throws RuntimeException always since this service is expected to be injected dynamically */ protected function getRequestService() { throw new RuntimeException('You have requested a synthetic service ("request"). The DIC does not know how to construct this service.'); } /** * Updates the 'request' service. */ protected function synchronizeRequestService() { if ($this->initialized('depends_on_request')) { $this->get('depends_on_request')->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } } /** * Gets the 'inlined' service. * * This service is shared. * This method always returns the same instance of the service. * * This service is private. * If you want to be able to request this service from the container directly, * make it public, otherwise you might end up with broken code. * * @return Bar A Bar instance. */ protected function getInlinedService() { $this->services['inlined'] = $instance = new \Bar(); $instance->setBaz($this->get('baz')); $instance->pub = 'pub'; return $instance; } /** * Gets the default parameters. * * @return array An array of the default parameters */ protected function getDefaultParameters() { return array( 'baz_class' => 'BazClass', 'foo_class' => 'FooClass', 'foo' => 'bar', ); } } PK!$oyy`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.phpnu[services = $this->scopedServices = $this->scopeStacks = array(); $this->set('service_container', $this); $this->scopes = array(); $this->scopeChildren = array(); $this->methodMap = array( 'foo' => 'getFooService', ); $this->aliases = array(); } /** * Gets the 'foo' service. * * This service is shared. * This method always returns the same instance of the service. * * @return stdClass A stdClass instance. */ protected function getFooService() { return $this->services['foo'] = new \stdClass(); } } PK!:A!!htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.phpnu[parameters = $this->getDefaultParameters(); $this->services = $this->scopedServices = $this->scopeStacks = array(); $this->set('service_container', $this); $this->scopes = array(); $this->scopeChildren = array(); $this->methodMap = array( 'bar' => 'getBarService', 'baz' => 'getBazService', 'depends_on_request' => 'getDependsOnRequestService', 'factory_service' => 'getFactoryServiceService', 'foo' => 'getFooService', 'foo.baz' => 'getFoo_BazService', 'foo_bar' => 'getFooBarService', 'foo_with_inline' => 'getFooWithInlineService', 'method_call1' => 'getMethodCall1Service', 'request' => 'getRequestService', ); $this->aliases = array( 'alias_for_alias' => 'foo', 'alias_for_foo' => 'foo', ); } /** * Gets the 'bar' service. * * This service is shared. * This method always returns the same instance of the service. * * @return FooClass A FooClass instance. */ protected function getBarService() { $this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar')); $this->get('foo.baz')->configure($instance); return $instance; } /** * Gets the 'baz' service. * * This service is shared. * This method always returns the same instance of the service. * * @return Baz A Baz instance. */ protected function getBazService() { $this->services['baz'] = $instance = new \Baz(); $instance->setFoo($this->get('foo_with_inline')); return $instance; } /** * Gets the 'depends_on_request' service. * * This service is shared. * This method always returns the same instance of the service. * * @return stdClass A stdClass instance. */ protected function getDependsOnRequestService() { $this->services['depends_on_request'] = $instance = new \stdClass(); $instance->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE)); return $instance; } /** * Gets the 'factory_service' service. * * This service is shared. * This method always returns the same instance of the service. * * @return Bar A Bar instance. */ protected function getFactoryServiceService() { return $this->services['factory_service'] = $this->get('foo.baz')->getInstance(); } /** * Gets the 'foo' service. * * This service is shared. * This method always returns the same instance of the service. * * @return FooClass A FooClass instance. */ protected function getFooService() { $a = $this->get('foo.baz'); $this->services['foo'] = $instance = call_user_func(array('FooClass', 'getInstance'), 'foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this); $instance->setBar($this->get('bar')); $instance->initialize(); $instance->foo = 'bar'; $instance->moo = $a; $instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar'); sc_configure($instance); return $instance; } /** * Gets the 'foo.baz' service. * * This service is shared. * This method always returns the same instance of the service. * * @return BazClass A BazClass instance. */ protected function getFoo_BazService() { $this->services['foo.baz'] = $instance = call_user_func(array('BazClass', 'getInstance')); call_user_func(array('BazClass', 'configureStatic1'), $instance); return $instance; } /** * Gets the 'foo_bar' service. * * @return FooClass A FooClass instance. */ protected function getFooBarService() { return new \FooClass(); } /** * Gets the 'foo_with_inline' service. * * This service is shared. * This method always returns the same instance of the service. * * @return Foo A Foo instance. */ protected function getFooWithInlineService() { $a = new \Bar(); $this->services['foo_with_inline'] = $instance = new \Foo(); $a->setBaz($this->get('baz')); $a->pub = 'pub'; $instance->setBar($a); return $instance; } /** * Gets the 'method_call1' service. * * This service is shared. * This method always returns the same instance of the service. * * @return FooClass A FooClass instance. */ protected function getMethodCall1Service() { require_once '%path%foo.php'; $this->services['method_call1'] = $instance = new \FooClass(); $instance->setBar($this->get('foo')); $instance->setBar(NULL); $instance->setBar(($this->get("foo")->foo() . $this->getParameter("foo"))); return $instance; } /** * Gets the 'request' service. * * This service is shared. * This method always returns the same instance of the service. * * @throws RuntimeException always since this service is expected to be injected dynamically */ protected function getRequestService() { throw new RuntimeException('You have requested a synthetic service ("request"). The DIC does not know how to construct this service.'); } /** * Updates the 'request' service. */ protected function synchronizeRequestService() { if ($this->initialized('depends_on_request')) { $this->get('depends_on_request')->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } } /** * {@inheritdoc} */ public function getParameter($name) { $name = strtolower($name); if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } return $this->parameters[$name]; } /** * {@inheritdoc} */ public function hasParameter($name) { $name = strtolower($name); return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters); } /** * {@inheritdoc} */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } /** * {@inheritDoc} */ public function getParameterBag() { if (null === $this->parameterBag) { $this->parameterBag = new FrozenParameterBag($this->parameters); } return $this->parameterBag; } /** * Gets the default parameters. * * @return array An array of the default parameters */ protected function getDefaultParameters() { return array( 'baz_class' => 'BazClass', 'foo_class' => 'FooClass', 'foo' => 'bar', ); } } PK!7/_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.phpnu[getDefaultParameters())); } /** * Gets the default parameters. * * @return array An array of the default parameters */ protected function getDefaultParameters() { return array( 'foo' => '%baz%', 'baz' => 'bar', 'bar' => 'foo is %%foo bar', 'escape' => '@escapeme', 'values' => array( 0 => true, 1 => false, 2 => NULL, 3 => 0, 4 => 1000.3, 5 => 'true', 6 => 'false', 7 => 'null', ), ); } } PK!(]  _test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xmlnu[ PK!ibĤ_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xmlnu[ PK!![  `test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services10.xmlnu[ PK!u  _test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xmlnu[ PK!_+WW_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xmlnu[ PK!x' 11atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/withdoctype.xmlnu[ PK!wzhh_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xmlnu[ %baz% bar foo is %%foo bar @escapeme true false null 0 1000.3 true false null PK! true PK!pԠ_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xmlnu[ %path%/foo.php foo true false service("foo").foo() ~ parameter("foo") foo true false PK!˕n%%^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xmlnu[ PK!Pggjtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xmlnu[ PK!\__test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xmlnu[ foo true false PK!]2 itest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xmlnu[ PK! _test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xmlnu[ a string bar 0 4 null true true false on off 1.3 1000.3 a string foo bar value PHP_EOL PK!itest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xmlnu[ PK!BX  _test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xmlnu[ BazClass FooClass bar foo foo is %foo% %foo% true bar foo is %foo% %foo% foo %foo_bar% %path%foo.php service("foo").foo() ~ parameter("foo") pub PK!^jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xmlnu[ BAR %project.parameter.foo% PK!Ńjtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xmlnu[ PK!җ'yjtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xmlnu[ PK! jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xmlnu[ PK!ixCjtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xmlnu[ PK!>Ujtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xmlnu[ BAR PK!}jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xmlnu[ BAR PK!33etest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dotnu[digraph sc { ratio="compress" node [fontsize="11" fontname="Arial" shape="record"]; edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"]; node_foo [label="foo\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"]; node_bar [label="bar\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foo -> node_bar [label="" style="filled"]; } PK!h dtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dotnu[digraph sc { ratio="compress" node [fontsize="11" fontname="Arial" shape="record"]; edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"]; node_foo [label="foo (alias_for_foo)\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_bar [label="bar\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_foo_baz [label="foo.baz\nBazClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_foo_bar [label="foo_bar\nFooClass\n", shape=record, fillcolor="#eeeeee", style="dotted"]; node_method_call1 [label="method_call1\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_factory_service [label="factory_service\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_foo_with_inline [label="foo_with_inline\nFoo\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_inlined [label="inlined\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_baz [label="baz\nBaz\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_request [label="request\nRequest\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_depends_on_request [label="depends_on_request\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"]; node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foo -> node_foo_baz [label="" style="filled"]; node_foo -> node_service_container [label="" style="filled"]; node_foo -> node_foo_baz [label="" style="dashed"]; node_foo -> node_bar [label="setBar()" style="dashed"]; node_bar -> node_foo_baz [label="" style="filled"]; node_method_call1 -> node_foo [label="setBar()" style="dashed"]; node_method_call1 -> node_foo2 [label="setBar()" style="dashed"]; node_method_call1 -> node_foo3 [label="setBar()" style="dashed"]; node_method_call1 -> node_foobaz [label="setBar()" style="dashed"]; node_foo_with_inline -> node_inlined [label="setBar()" style="dashed"]; node_inlined -> node_baz [label="setBaz()" style="dashed"]; node_baz -> node_foo_with_inline [label="setFoo()" style="dashed"]; node_depends_on_request -> node_request [label="setRequest()" style="dashed"]; } PK!Ձ1*,,gtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dotnu[digraph sc { ratio="normal" node [fontsize="13" fontname="Verdana" shape="square"]; edge [fontsize="12" fontname="Verdana" color="white" arrowhead="closed" arrowsize="1"]; node_foo [label="foo\nFooClass\n", shape=square, fillcolor="grey", style="filled"]; node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=square, fillcolor="green", style="empty"]; node_bar [label="bar\n\n", shape=square, fillcolor="red", style="empty"]; node_foo -> node_bar [label="" style="filled"]; } PK!&WWdtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dotnu[digraph sc { ratio="compress" node [fontsize="11" fontname="Arial" shape="record"]; edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"]; node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"]; } PK!ŏD;;etest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services13.dotnu[digraph sc { ratio="compress" node [fontsize="11" fontname="Arial" shape="record"]; edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"]; node_foo [label="foo\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_bar [label="bar\nBarClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"]; node_foo -> node_bar [label="" style="filled"]; } PK!8BBetest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services14.dotnu[digraph sc { ratio="compress" node [fontsize="11" fontname="Arial" shape="record"]; edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"]; node_service_container [label="service_container\nContainer14\\ProjectServiceContainer\n", shape=record, fillcolor="#9999ff", style="filled"]; } PK!N{rrytest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtensionInPhar.pharnu[ "ProjectWithXsdExtensionInPhar.phar!ProjectWithXsdExtensionInPhar.php~akM~ schema/project-1.0.xsdakMQp W]ʯ`5,,) EYGBMBPK! ^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.phpnu[arguments = $arguments; } public static function getInstance($arguments = array()) { $obj = new self($arguments); $obj->called = true; return $obj; } public function initialize() { $this->initialized = true; } public function configure() { $this->configured = true; } public function setBar($value = null) { $this->bar = $value; } } PK!]etest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.phpnu[addFromString('ProjectWithXsdExtensionInPhar.php',<<addFromString('schema/project-1.0.xsd', << EOT ); $phar->setStub(''); PK!.Y<ҿktest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.phpnu[setDefinition('project.service.bar', new Definition('FooClass')); $configuration->setParameter('project.parameter.bar', isset($config['foo']) ? $config['foo'] : 'foobar'); $configuration->setDefinition('project.service.foo', new Definition('FooClass')); $configuration->setParameter('project.parameter.foo', isset($config['foo']) ? $config['foo'] : 'foobar'); return $configuration; } public function getXsdValidationBasePath() { return false; } public function getNamespace() { return 'http://www.example.com/schema/project'; } public function getAlias() { return 'project'; } public function getConfiguration(array $config, ContainerBuilder $container) { return null; } } PK!Aov:ZZbtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.phpnu[configure(); } class BarClass { protected $baz; public $foo = 'foo'; public function setBaz(BazClass $baz) { $this->baz = $baz; } public function getBaz() { return $this->baz; } } class BazClass { protected $foo; public function setFoo(Foo $foo) { $this->foo = $foo; } public function configure($instance) { $instance->configure(); } public static function getInstance() { return new self(); } public static function configureStatic($instance) { $instance->configure(); } public static function configureStatic1() { } } class BarUserClass { public $bar; public function __construct(BarClass $bar) { $this->bar = $bar; } } PK!RK:mtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsdnu[ PK![[rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.phpnu[^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.ymlnu[services: foo_service: class: FooClass tags: # tag is missing the name key foo_tag: { foo: bar } PK!:Ʋ`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.ymlnu[parameters: FOO: bar values: - true - false - 0 - 1000.3 bar: foo escape: @@escapeme foo_bar: @foo_bar MixedCase: MixedCaseKey: value PK!W%`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.ymlnu[false PK!|w`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.ymlnu[parameters: baz_class: BazClass foo_class: FooClass foo: bar services: foo: class: FooClass tags: - { name: foo, foo: foo } - { name: foo, bar: bar } factory_class: FooClass factory_method: getInstance arguments: [foo, '@foo.baz', { '%foo%': 'foo is %foo%', foobar: '%foo%' }, true, '@service_container'] properties: { foo: bar, moo: '@foo.baz', qux: { '%foo%': 'foo is %foo%', foobar: '%foo%' } } calls: - [setBar, ['@bar']] - [initialize, { }] configurator: sc_configure bar: class: FooClass arguments: [foo, '@foo.baz', '%foo_bar%'] configurator: ['@foo.baz', configure] foo.baz: class: %baz_class% factory_class: %baz_class% factory_method: getInstance configurator: ['%baz_class%', configureStatic1] foo_bar: class: %foo_class% scope: prototype method_call1: class: FooClass file: %path%foo.php calls: - [setBar, ['@foo']] - [setBar, ['@?foo2']] - [setBar, ['@?foo3']] - [setBar, ['@?foobaz']] - [setBar, ['@=service("foo").foo() ~ parameter("foo")']] factory_service: class: Bar factory_method: getInstance factory_service: foo.baz foo_with_inline: class: Foo calls: - [setBar, ['@inlined']] inlined: class: Bar public: false properties: { pub: pub } calls: - [setBaz, ['@baz']] baz: class: Baz calls: - [setFoo, ['@foo_with_inline']] request: class: Request synthetic: true synchronized: true depends_on_request: class: stdClass calls: - [setRequest, ['@?request']] alias_for_foo: @foo alias_for_alias: @foo PK!GGatest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.ymlnu[# used to test imports in XML parameters: imported_from_yaml: true PK!۴)++^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ininu[{NOT AN INI FILE} {JUST A PLAIN TEXT FILE} PK!pu((atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ininu[[parameters] imported_from_ini = true PK!s4''`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ininu[[parameters] foo = bar bar = %foo% PK!5l%%atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ininu[[parameters] FOO = foo baz = baz PK!Fmhtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.phpnu[setDefinition('barFactory', $factoryDefinition); $definition = new Definition(); $definition->setFactoryService('barFactory'); $definition->setFactoryMethod('createBarClass'); $container->setDefinition('bar', $definition); return $container; class BarClass { public $foo; public function setBar($foo) { $this->foo = $foo; } } class BarClassFactory { public function createBarClass() { return new BarClass(); } } PK!4hgtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.phpnu[ '%baz%', 'baz' => 'bar', 'bar' => 'foo is %%foo bar', 'escape' => '@escapeme', 'values' => array(true, false, null, 0, 1000.3, 'true', 'false', 'null'), ))); return $container; PK! Z gtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.phpnu[ register('foo', 'FooClass')-> addTag('foo', array('foo' => 'foo'))-> addTag('foo', array('bar' => 'bar'))-> setFactoryClass('FooClass')-> setFactoryMethod('getInstance')-> setArguments(array('foo', new Reference('foo.baz'), array('%foo%' => 'foo is %foo%', 'foobar' => '%foo%'), true, new Reference('service_container')))-> setProperties(array('foo' => 'bar', 'moo' => new Reference('foo.baz'), 'qux' => array('%foo%' => 'foo is %foo%', 'foobar' => '%foo%')))-> addMethodCall('setBar', array(new Reference('bar')))-> addMethodCall('initialize')-> setConfigurator('sc_configure') ; $container-> register('bar', 'FooClass')-> setArguments(array('foo', new Reference('foo.baz'), new Parameter('foo_bar')))-> setScope('container')-> setConfigurator(array(new Reference('foo.baz'), 'configure')) ; $container-> register('foo.baz', '%baz_class%')-> setFactoryClass('%baz_class%')-> setFactoryMethod('getInstance')-> setConfigurator(array('%baz_class%', 'configureStatic1')) ; $container-> register('foo_bar', '%foo_class%')-> setScope('prototype') ; $container->getParameterBag()->clear(); $container->getParameterBag()->add(array( 'baz_class' => 'BazClass', 'foo_class' => 'FooClass', 'foo' => 'bar', )); $container->setAlias('alias_for_foo', 'foo'); $container->setAlias('alias_for_alias', 'alias_for_foo'); $container-> register('method_call1', 'FooClass')-> setFile(realpath(__DIR__.'/../includes/foo.php'))-> addMethodCall('setBar', array(new Reference('foo')))-> addMethodCall('setBar', array(new Reference('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)))-> addMethodCall('setBar', array(new Reference('foo3', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))-> addMethodCall('setBar', array(new Reference('foobaz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))-> addMethodCall('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")'))) ; $container-> register('factory_service', 'Bar')-> setFactoryService('foo.baz')-> setFactoryMethod('getInstance') ; $container ->register('foo_with_inline', 'Foo') ->addMethodCall('setBar', array(new Reference('inlined'))) ; $container ->register('inlined', 'Bar') ->setProperty('pub', 'pub') ->addMethodCall('setBaz', array(new Reference('baz'))) ->setPublic(false) ; $container ->register('baz', 'Baz') ->addMethodCall('setFoo', array(new Reference('foo_with_inline'))) ; $container ->register('request', 'Request') ->setSynthetic(true) ->setSynchronized(true) ; $container ->register('depends_on_request', 'stdClass') ->addMethodCall('setRequest', array(new Reference('request', ContainerInterface::NULL_ON_INVALID_REFERENCE, false))) ; return $container; PK!33htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.phpnu[ register('foo', 'FooClass')-> addArgument(new Definition('BarClass', array(new Definition('BazClass')))) ; return $container; PK! |htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.phpnu[setParameter('cla', 'Fo'); $container->setParameter('ss', 'Class'); $definition = new Definition('%cla%o%ss%'); $container->setDefinition('foo', $definition); return $container; if (!class_exists('FooClass')) { class FooClass { public $bar; public function setBar($bar) { $this->bar = $bar; } } } PK!Cݲ;;htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.phpnu[ register('foo', 'FooClass')-> addArgument(new Reference('bar')) ; return $container; PK!BreOOhtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.phpnu[ register('foo', 'FooClass')-> addArgument(new Reference('bar')) ; $container-> register('bar', 'BarClass') ; $container->compile(); return $container; PK!*EEhtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.phpnu[ register('foo', 'FooClass\\Foo')-> addArgument('foo<>&bar')-> addTag('foo"bar\\bar', array('foo' => 'foo"barřž€')) ; return $container; PK!1vhtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; class FrozenParameterBagTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::__construct */ public function testConstructor() { $parameters = array( 'foo' => 'foo', 'bar' => 'bar', ); $bag = new FrozenParameterBag($parameters); $this->assertEquals($parameters, $bag->all(), '__construct() takes an array of parameters as its first argument'); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::clear * @expectedException \LogicException */ public function testClear() { $bag = new FrozenParameterBag(array()); $bag->clear(); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::set * @expectedException \LogicException */ public function testSet() { $bag = new FrozenParameterBag(array()); $bag->set('foo', 'bar'); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::add * @expectedException \LogicException */ public function testAdd() { $bag = new FrozenParameterBag(array()); $bag->add(array()); } } PK!$99ftest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; class ParameterBagTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::__construct */ public function testConstructor() { $bag = new ParameterBag($parameters = array( 'foo' => 'foo', 'bar' => 'bar', )); $this->assertEquals($parameters, $bag->all(), '__construct() takes an array of parameters as its first argument'); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::clear */ public function testClear() { $bag = new ParameterBag($parameters = array( 'foo' => 'foo', 'bar' => 'bar', )); $bag->clear(); $this->assertEquals(array(), $bag->all(), '->clear() removes all parameters'); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::remove */ public function testRemove() { $bag = new ParameterBag(array( 'foo' => 'foo', 'bar' => 'bar', )); $bag->remove('foo'); $this->assertEquals(array('bar' => 'bar'), $bag->all(), '->remove() removes a parameter'); $bag->remove('BAR'); $this->assertEquals(array(), $bag->all(), '->remove() converts key to lowercase before removing'); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::get * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::set */ public function testGetSet() { $bag = new ParameterBag(array('foo' => 'bar')); $bag->set('bar', 'foo'); $this->assertEquals('foo', $bag->get('bar'), '->set() sets the value of a new parameter'); $bag->set('foo', 'baz'); $this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter'); $bag->set('Foo', 'baz1'); $this->assertEquals('baz1', $bag->get('foo'), '->set() converts the key to lowercase'); $this->assertEquals('baz1', $bag->get('FOO'), '->get() converts the key to lowercase'); try { $bag->get('baba'); $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); } } public function testGetThrowParameterNotFoundException() { $bag = new ParameterBag(array( 'foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz', )); try { $bag->get('foo1'); $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); $this->assertEquals('You have requested a non-existent parameter "foo1". Did you mean this: "foo"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices'); } try { $bag->get('bag'); $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); $this->assertEquals('You have requested a non-existent parameter "bag". Did you mean one of these: "bar", "baz"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices'); } try { $bag->get(''); $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); $this->assertEquals('You have requested a non-existent parameter "".', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices'); } } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::has */ public function testHas() { $bag = new ParameterBag(array('foo' => 'bar')); $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined'); $this->assertTrue($bag->has('Foo'), '->has() converts the key to lowercase'); $this->assertFalse($bag->has('bar'), '->has() returns false if a parameter is not defined'); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolveValue */ public function testResolveValue() { $bag = new ParameterBag(array()); $this->assertEquals('foo', $bag->resolveValue('foo'), '->resolveValue() returns its argument unmodified if no placeholders are found'); $bag = new ParameterBag(array('foo' => 'bar')); $this->assertEquals('I\'m a bar', $bag->resolveValue('I\'m a %foo%'), '->resolveValue() replaces placeholders by their values'); $this->assertEquals(array('bar' => 'bar'), $bag->resolveValue(array('%foo%' => '%foo%')), '->resolveValue() replaces placeholders in keys and values of arrays'); $this->assertEquals(array('bar' => array('bar' => array('bar' => 'bar'))), $bag->resolveValue(array('%foo%' => array('%foo%' => array('%foo%' => '%foo%')))), '->resolveValue() replaces placeholders in nested arrays'); $this->assertEquals('I\'m a %%foo%%', $bag->resolveValue('I\'m a %%foo%%'), '->resolveValue() supports % escaping by doubling it'); $this->assertEquals('I\'m a bar %%foo bar', $bag->resolveValue('I\'m a %foo% %%foo %foo%'), '->resolveValue() supports % escaping by doubling it'); $this->assertEquals(array('foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar'))), $bag->resolveValue(array('foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar')))), '->resolveValue() supports % escaping by doubling it'); $bag = new ParameterBag(array('foo' => true)); $this->assertTrue($bag->resolveValue('%foo%'), '->resolveValue() replaces arguments that are just a placeholder by their value without casting them to strings'); $bag = new ParameterBag(array('foo' => null)); $this->assertNull($bag->resolveValue('%foo%'), '->resolveValue() replaces arguments that are just a placeholder by their value without casting them to strings'); $bag = new ParameterBag(array('foo' => 'bar', 'baz' => '%%%foo% %foo%%% %%foo%% %%%foo%%%')); $this->assertEquals('%%bar bar%% %%foo%% %%bar%%', $bag->resolveValue('%baz%'), '->resolveValue() replaces params placed besides escaped %'); $bag = new ParameterBag(array('baz' => '%%s?%%s')); $this->assertEquals('%%s?%%s', $bag->resolveValue('%baz%'), '->resolveValue() is not replacing greedily'); $bag = new ParameterBag(array()); try { $bag->resolveValue('%foobar%'); $this->fail('->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); } catch (ParameterNotFoundException $e) { $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter'); } try { $bag->resolveValue('foo %foobar% bar'); $this->fail('->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter'); } catch (ParameterNotFoundException $e) { $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter'); } $bag = new ParameterBag(array('foo' => 'a %bar%', 'bar' => array())); try { $bag->resolveValue('%foo%'); $this->fail('->resolveValue() throws a RuntimeException when a parameter embeds another non-string parameter'); } catch (RuntimeException $e) { $this->assertEquals('A string value must be composed of strings and/or numbers, but found parameter "bar" of type array inside string value "a %bar%".', $e->getMessage(), '->resolveValue() throws a RuntimeException when a parameter embeds another non-string parameter'); } $bag = new ParameterBag(array('foo' => '%bar%', 'bar' => '%foobar%', 'foobar' => '%foo%')); try { $bag->resolveValue('%foo%'); $this->fail('->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference'); } catch (ParameterCircularReferenceException $e) { $this->assertEquals('Circular reference detected for parameter "foo" ("foo" > "bar" > "foobar" > "foo").', $e->getMessage(), '->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference'); } $bag = new ParameterBag(array('foo' => 'a %bar%', 'bar' => 'a %foobar%', 'foobar' => 'a %foo%')); try { $bag->resolveValue('%foo%'); $this->fail('->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference'); } catch (ParameterCircularReferenceException $e) { $this->assertEquals('Circular reference detected for parameter "foo" ("foo" > "bar" > "foobar" > "foo").', $e->getMessage(), '->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference'); } $bag = new ParameterBag(array('host' => 'foo.bar', 'port' => 1337)); $this->assertEquals('foo.bar:1337', $bag->resolveValue('%host%:%port%')); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve */ public function testResolveIndicatesWhyAParameterIsNeeded() { $bag = new ParameterBag(array('foo' => '%bar%')); try { $bag->resolve(); } catch (ParameterNotFoundException $e) { $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage()); } $bag = new ParameterBag(array('foo' => '%bar%')); try { $bag->resolve(); } catch (ParameterNotFoundException $e) { $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage()); } } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve */ public function testResolveUnescapesValue() { $bag = new ParameterBag(array( 'foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar')), 'bar' => 'I\'m a %%foo%%', )); $bag->resolve(); $this->assertEquals('I\'m a %foo%', $bag->get('bar'), '->resolveValue() supports % escaping by doubling it'); $this->assertEquals(array('bar' => array('ding' => 'I\'m a bar %foo %bar')), $bag->get('foo'), '->resolveValue() supports % escaping by doubling it'); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::escapeValue */ public function testEscapeValue() { $bag = new ParameterBag(); $bag->add(array( 'foo' => $bag->escapeValue(array('bar' => array('ding' => 'I\'m a bar %foo %bar', 'zero' => null))), 'bar' => $bag->escapeValue('I\'m a %foo%'), )); $this->assertEquals('I\'m a %%foo%%', $bag->get('bar'), '->escapeValue() escapes % by doubling it'); $this->assertEquals(array('bar' => array('ding' => 'I\'m a bar %%foo %%bar', 'zero' => null)), $bag->get('foo'), '->escapeValue() escapes % by doubling it'); } /** * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve * @dataProvider stringsWithSpacesProvider */ public function testResolveStringWithSpacesReturnsString($expected, $test, $description) { $bag = new ParameterBag(array('foo' => 'bar')); try { $this->assertEquals($expected, $bag->resolveString($test), $description); } catch (ParameterNotFoundException $e) { $this->fail(sprintf('%s - "%s"', $description, $expected)); } } public function stringsWithSpacesProvider() { return array( array('bar', '%foo%', 'Parameters must be wrapped by %.'), array('% foo %', '% foo %', 'Parameters should not have spaces.'), array('{% set my_template = "foo" %}', '{% set my_template = "foo" %}', 'Twig-like strings are not parameters.'), array('50% is less than 100%', '50% is less than 100%', 'Text between % signs is allowed, if there are spaces.'), ); } } PK! Wtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; class CrossCheckTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; public static function setUpBeforeClass() { self::$fixturesPath = __DIR__.'/Fixtures/'; require_once self::$fixturesPath.'/includes/classes.php'; require_once self::$fixturesPath.'/includes/foo.php'; } /** * @dataProvider crossCheckLoadersDumpers */ public function testCrossCheck($fixture, $type) { $loaderClass = 'Symfony\\Component\\DependencyInjection\\Loader\\'.ucfirst($type).'FileLoader'; $dumperClass = 'Symfony\\Component\\DependencyInjection\\Dumper\\'.ucfirst($type).'Dumper'; $tmp = tempnam('sf_service_container', 'sf'); file_put_contents($tmp, file_get_contents(self::$fixturesPath.'/'.$type.'/'.$fixture)); $container1 = new ContainerBuilder(); $loader1 = new $loaderClass($container1, new FileLocator()); $loader1->load($tmp); $dumper = new $dumperClass($container1); file_put_contents($tmp, $dumper->dump()); $container2 = new ContainerBuilder(); $loader2 = new $loaderClass($container2, new FileLocator()); $loader2->load($tmp); unlink($tmp); $this->assertEquals($container2->getAliases(), $container1->getAliases(), 'loading a dump from a previously loaded container returns the same container'); $this->assertEquals($container2->getDefinitions(), $container1->getDefinitions(), 'loading a dump from a previously loaded container returns the same container'); $this->assertEquals($container2->getParameterBag()->all(), $container1->getParameterBag()->all(), '->getParameterBag() returns the same value for both containers'); $this->assertEquals(serialize($container2), serialize($container1), 'loading a dump from a previously loaded container returns the same container'); $services1 = array(); foreach ($container1 as $id => $service) { $services1[$id] = serialize($service); } $services2 = array(); foreach ($container2 as $id => $service) { $services2[$id] = serialize($service); } unset($services1['service_container'], $services2['service_container']); $this->assertEquals($services2, $services1, 'Iterator on the containers returns the same services'); } public function crossCheckLoadersDumpers() { $tests = array( array('services1.xml', 'xml'), array('services2.xml', 'xml'), array('services6.xml', 'xml'), array('services8.xml', 'xml'), array('services9.xml', 'xml'), ); if (class_exists('Symfony\Component\Yaml\Yaml')) { $tests = array_merge($tests, array( array('services1.yml', 'yaml'), array('services2.yml', 'yaml'), array('services6.yml', 'yaml'), array('services8.yml', 'yaml'), array('services9.yml', 'yaml'), )); } return $tests; } } PK!2+` ^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Dumper; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\YamlDumper; class YamlDumperTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; public static function setUpBeforeClass() { self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); } public function testDump() { $dumper = new YamlDumper($container = new ContainerBuilder()); $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services1.yml', $dumper->dump(), '->dump() dumps an empty container as an empty YAML file'); $container = new ContainerBuilder(); $dumper = new YamlDumper($container); } public function testAddParameters() { $container = include self::$fixturesPath.'/containers/container8.php'; $dumper = new YamlDumper($container); $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services8.yml', $dumper->dump(), '->dump() dumps parameters'); } public function testAddService() { $container = include self::$fixturesPath.'/containers/container9.php'; $dumper = new YamlDumper($container); $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/yaml/services9.yml')), $dumper->dump(), '->dump() dumps services'); $dumper = new YamlDumper($container = new ContainerBuilder()); $container->register('foo', 'FooClass')->addArgument(new \stdClass()); try { $dumper->dump(); $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); } catch (\Exception $e) { $this->assertInstanceOf('\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); } } } PK!v  btest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Dumper; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\GraphvizDumper; class GraphvizDumperTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; public static function setUpBeforeClass() { self::$fixturesPath = __DIR__.'/../Fixtures/'; } public function testDump() { $dumper = new GraphvizDumper($container = new ContainerBuilder()); $this->assertStringEqualsFile(self::$fixturesPath.'/graphviz/services1.dot', $dumper->dump(), '->dump() dumps an empty container as an empty dot file'); $container = include self::$fixturesPath.'/containers/container9.php'; $dumper = new GraphvizDumper($container); $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services9.dot')), $dumper->dump(), '->dump() dumps services'); $container = include self::$fixturesPath.'/containers/container10.php'; $dumper = new GraphvizDumper($container); $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services10.dot')), $dumper->dump(), '->dump() dumps services'); $container = include self::$fixturesPath.'/containers/container10.php'; $dumper = new GraphvizDumper($container); $this->assertEquals($dumper->dump(array( 'graph' => array('ratio' => 'normal'), 'node' => array('fontsize' => 13, 'fontname' => 'Verdana', 'shape' => 'square'), 'edge' => array('fontsize' => 12, 'fontname' => 'Verdana', 'color' => 'white', 'arrowhead' => 'closed', 'arrowsize' => 1), 'node.instance' => array('fillcolor' => 'green', 'style' => 'empty'), 'node.definition' => array('fillcolor' => 'grey'), 'node.missing' => array('fillcolor' => 'red', 'style' => 'empty'), )), str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services10-1.dot')), '->dump() dumps services'); } public function testDumpWithFrozenContainer() { $container = include self::$fixturesPath.'/containers/container13.php'; $dumper = new GraphvizDumper($container); $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services13.dot')), $dumper->dump(), '->dump() dumps services'); } public function testDumpWithFrozenCustomClassContainer() { $container = include self::$fixturesPath.'/containers/container14.php'; $dumper = new GraphvizDumper($container); $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services14.dot')), $dumper->dump(), '->dump() dumps services'); } } PK!)]test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Dumper; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\XmlDumper; class XmlDumperTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; public static function setUpBeforeClass() { self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); } public function testDump() { $dumper = new XmlDumper($container = new ContainerBuilder()); $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services1.xml', $dumper->dump(), '->dump() dumps an empty container as an empty XML file'); $container = new ContainerBuilder(); $dumper = new XmlDumper($container); } public function testExportParameters() { $container = include self::$fixturesPath.'//containers/container8.php'; $dumper = new XmlDumper($container); $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services8.xml', $dumper->dump(), '->dump() dumps parameters'); } public function testAddParameters() { $container = include self::$fixturesPath.'//containers/container8.php'; $dumper = new XmlDumper($container); $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services8.xml', $dumper->dump(), '->dump() dumps parameters'); } public function testAddService() { $container = include self::$fixturesPath.'/containers/container9.php'; $dumper = new XmlDumper($container); $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/xml/services9.xml')), $dumper->dump(), '->dump() dumps services'); $dumper = new XmlDumper($container = new ContainerBuilder()); $container->register('foo', 'FooClass')->addArgument(new \stdClass()); try { $dumper->dump(); $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); } catch (\Exception $e) { $this->assertInstanceOf('\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); } } public function testDumpAnonymousServices() { include self::$fixturesPath.'/containers/container11.php'; $dumper = new XmlDumper($container); $this->assertEquals(" ", $dumper->dump()); } public function testDumpEntities() { include self::$fixturesPath.'/containers/container12.php'; $dumper = new XmlDumper($container); $this->assertEquals(" foo<>&bar ", $dumper->dump()); } } PK!"."."]test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Dumper; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Definition; class PhpDumperTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; public static function setUpBeforeClass() { self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); } public function testDump() { $dumper = new PhpDumper($container = new ContainerBuilder()); $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class'); $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1-1.php', $dumper->dump(array('class' => 'Container', 'base_class' => 'AbstractContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Dump')), '->dump() takes a class and a base_class options'); $container = new ContainerBuilder(); new PhpDumper($container); } public function testDumpFrozenContainerWithNoParameter() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->register('foo', 'stdClass'); $container->compile(); $dumper = new PhpDumper($container); $dumpedString = $dumper->dump(); $this->assertStringEqualsFile(self::$fixturesPath.'/php/services11.php', $dumpedString, '->dump() does not add getDefaultParameters() method call if container have no parameters.'); $this->assertNotRegexp("/function getDefaultParameters\(/", $dumpedString, '->dump() does not add getDefaultParameters() method definition.'); } public function testDumpOptimizationString() { $definition = new Definition(); $definition->setClass('stdClass'); $definition->addArgument(array( 'only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' =>'concatenation from the start key', 'optimize concatenation' => "string1%some_string%string2", 'optimize concatenation with empty string' => "string1%empty_value%string2", 'optimize concatenation from the start' => '%empty_value%start', 'optimize concatenation at the end' => 'end%empty_value%', )); $container = new ContainerBuilder(); $container->setResourceTracking(false); $container->setDefinition('test', $definition); $container->setParameter('empty_value', ''); $container->setParameter('some_string', '-'); $container->compile(); $dumper = new PhpDumper($container); $this->assertStringEqualsFile(self::$fixturesPath.'/php/services10.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class'); } /** * @expectedException \InvalidArgumentException */ public function testExportParameters() { $dumper = new PhpDumper(new ContainerBuilder(new ParameterBag(array('foo' => new Reference('foo'))))); $dumper->dump(); } public function testAddParameters() { $container = include self::$fixturesPath.'/containers/container8.php'; $dumper = new PhpDumper($container); $this->assertStringEqualsFile(self::$fixturesPath.'/php/services8.php', $dumper->dump(), '->dump() dumps parameters'); } public function testAddService() { // without compilation $container = include self::$fixturesPath.'/containers/container9.php'; $dumper = new PhpDumper($container); $this->assertEquals(str_replace('%path%', str_replace('\\','\\\\',self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9.php')), $dumper->dump(), '->dump() dumps services'); // with compilation $container = include self::$fixturesPath.'/containers/container9.php'; $container->compile(); $dumper = new PhpDumper($container); $this->assertEquals(str_replace('%path%', str_replace('\\','\\\\',self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9_compiled.php')), $dumper->dump(), '->dump() dumps services'); $dumper = new PhpDumper($container = new ContainerBuilder()); $container->register('foo', 'FooClass')->addArgument(new \stdClass()); try { $dumper->dump(); $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); } catch (\Exception $e) { $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); } } /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage Service id "bar$" cannot be converted to a valid PHP method name. */ public function testAddServiceInvalidServiceId() { $container = new ContainerBuilder(); $container->register('bar$', 'FooClass'); $dumper = new PhpDumper($container); $dumper->dump(); } public function testAliases() { $container = include self::$fixturesPath.'/containers/container9.php'; $container->compile(); $dumper = new PhpDumper($container); eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Aliases'))); $container = new \Symfony_DI_PhpDumper_Test_Aliases(); $container->set('foo', $foo = new \stdClass); $this->assertSame($foo, $container->get('foo')); $this->assertSame($foo, $container->get('alias_for_foo')); $this->assertSame($foo, $container->get('alias_for_alias')); } public function testFrozenContainerWithoutAliases() { $container = new ContainerBuilder(); $container->compile(); $dumper = new PhpDumper($container); eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Frozen_No_Aliases'))); $container = new \Symfony_DI_PhpDumper_Test_Frozen_No_Aliases(); $this->assertFalse($container->has('foo')); } public function testOverrideServiceWhenUsingADumpedContainer() { require_once self::$fixturesPath.'/php/services9.php'; require_once self::$fixturesPath.'/includes/foo.php'; $container = new \ProjectServiceContainer(); $container->set('bar', $bar = new \stdClass()); $container->setParameter('foo_bar', 'foo_bar'); $this->assertEquals($bar, $container->get('bar'), '->set() overrides an already defined service'); } public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFromAnotherOne() { require_once self::$fixturesPath.'/php/services9.php'; require_once self::$fixturesPath.'/includes/foo.php'; require_once self::$fixturesPath.'/includes/classes.php'; $container = new \ProjectServiceContainer(); $container->set('bar', $bar = new \stdClass()); $this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service'); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException */ public function testCircularReference() { $container = new ContainerBuilder(); $container->register('foo', 'stdClass')->addArgument(new Reference('bar')); $container->register('bar', 'stdClass')->setPublic(false)->addMethodCall('setA', array(new Reference('baz'))); $container->register('baz', 'stdClass')->addMethodCall('setA', array(new Reference('foo'))); $container->compile(); $dumper = new PhpDumper($container); $dumper->dump(); } } PK!Vtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ReferenceTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests; use Symfony\Component\DependencyInjection\Reference; class ReferenceTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\DependencyInjection\Reference::__construct */ public function testConstructor() { $ref = new Reference('foo'); $this->assertEquals('foo', (string) $ref, '__construct() sets the id of the reference, which is used for the __toString() method'); } public function testCaseInsensitive() { $ref = new Reference('FooBar'); $this->assertEquals('foobar', (string) $ref, 'the id is lowercased as the container is case insensitive'); } } PK!ł``atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; class ClosureLoaderTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\DependencyInjection\Loader\ClosureLoader::supports */ public function testSupports() { $loader = new ClosureLoader(new ContainerBuilder()); $this->assertTrue($loader->supports(function ($container) {}), '->supports() returns true if the resource is loadable'); $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); } /** * @covers Symfony\Component\DependencyInjection\Loader\ClosureLoader::load */ public function testLoad() { $loader = new ClosureLoader($container = new ContainerBuilder()); $loader->load(function ($container) { $container->setParameter('foo', 'foo'); }); $this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a \Closure resource'); } } PK!SRatest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\Config\FileLocator; class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\DependencyInjection\Loader\PhpFileLoader::supports */ public function testSupports() { $loader = new PhpFileLoader(new ContainerBuilder(), new FileLocator()); $this->assertTrue($loader->supports('foo.php'), '->supports() returns true if the resource is loadable'); $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); } /** * @covers Symfony\Component\DependencyInjection\Loader\PhpFileLoader::load */ public function testLoad() { $loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator()); $loader->load(__DIR__.'/../Fixtures/php/simple.php'); $this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a PHP file resource'); } } PK!kV00btest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\Loader\IniFileLoader; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\FileLocator; use Symfony\Component\ExpressionLanguage\Expression; class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; public static function setUpBeforeClass() { self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); require_once self::$fixturesPath.'/includes/foo.php'; require_once self::$fixturesPath.'/includes/ProjectExtension.php'; } public function testLoadFile() { $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini')); $r = new \ReflectionObject($loader); $m = $r->getMethod('loadFile'); $m->setAccessible(true); try { $m->invoke($loader, 'foo.yml'); $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist'); $this->assertEquals('The service file "foo.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist'); } try { $m->invoke($loader, 'parameters.ini'); $this->fail('->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file'); $this->assertEquals('The service file "parameters.ini" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file'); } $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); foreach (array('nonvalid1', 'nonvalid2') as $fixture) { try { $m->invoke($loader, $fixture.'.yml'); $this->fail('->load() throws an InvalidArgumentException if the loaded file does not validate'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not validate'); $this->assertStringMatchesFormat('The service file "nonvalid%d.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not validate'); } } } public function testLoadParameters() { $container = new ContainerBuilder(); $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('services2.yml'); $this->assertEquals(array('foo' => 'bar', 'mixedcase' => array('MixedCaseKey' => 'value'), 'values' => array(true, false, 0, 1000.3), 'bar' => 'foo', 'escape' => '@escapeme', 'foo_bar' => new Reference('foo_bar')), $container->getParameterBag()->all(), '->load() converts YAML keys to lowercase'); } public function testLoadImports() { $container = new ContainerBuilder(); $resolver = new LoaderResolver(array( new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')), new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')), new PhpFileLoader($container, new FileLocator(self::$fixturesPath.'/php')), $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')), )); $loader->setResolver($resolver); $loader->load('services4.yml'); $actual = $container->getParameterBag()->all(); $expected = array('foo' => 'bar', 'values' => array(true, false), 'bar' => '%foo%', 'escape' => '@escapeme', 'foo_bar' => new Reference('foo_bar'), 'mixedcase' => array('MixedCaseKey' => 'value'), 'imported_from_ini' => true, 'imported_from_xml' => true); $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files'); // Bad import throws no exception due to ignore_errors value. $loader->load('services4_bad_import.yml'); } public function testLoadServices() { $container = new ContainerBuilder(); $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('services6.yml'); $services = $container->getDefinitions(); $this->assertTrue(isset($services['foo']), '->load() parses service elements'); $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Definition', $services['foo'], '->load() converts service element to Definition instances'); $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute'); $this->assertEquals('container', $services['scope.container']->getScope()); $this->assertEquals('custom', $services['scope.custom']->getScope()); $this->assertEquals('prototype', $services['scope.prototype']->getScope()); $this->assertEquals('getInstance', $services['constructor']->getFactoryMethod(), '->load() parses the factory_method attribute'); $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag'); $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags'); $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array(new Reference('baz'), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array(array('setBar', array()), array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag'); $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag'); $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService()); $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag'); $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag'); $this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag'); $aliases = $container->getAliases(); $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses aliases'); $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases'); $this->assertTrue($aliases['alias_for_foo']->isPublic()); $this->assertTrue(isset($aliases['another_alias_for_foo'])); $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']); $this->assertFalse($aliases['another_alias_for_foo']->isPublic()); } public function testExtensions() { $container = new ContainerBuilder(); $container->registerExtension(new \ProjectExtension()); $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('services10.yml'); $container->compile(); $services = $container->getDefinitions(); $parameters = $container->getParameterBag()->all(); $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements'); $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements'); $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements'); $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements'); try { $loader->load('services11.yml'); $this->fail('->load() throws an InvalidArgumentException if the tag is not valid'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid'); $this->assertStringStartsWith('There is no extension able to load the configuration for "foobarfoobar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid'); } } /** * @covers Symfony\Component\DependencyInjection\Loader\YamlFileLoader::supports */ public function testSupports() { $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator()); $this->assertTrue($loader->supports('foo.yml'), '->supports() returns true if the resource is loadable'); $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); } public function testNonArrayTagThrowsException() { $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); try { $loader->load('badtag1.yml'); $this->fail('->load() should throw an exception when the tags key of a service is not an array'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tags key is not an array'); $this->assertStringStartsWith('Parameter "tags" must be an array for service', $e->getMessage(), '->load() throws an InvalidArgumentException if the tags key is not an array'); } } public function testTagWithoutNameThrowsException() { $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); try { $loader->load('badtag2.yml'); $this->fail('->load() should throw an exception when a tag is missing the name key'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag is missing the name key'); $this->assertStringStartsWith('A "tags" entry is missing a "name" key for service ', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag is missing the name key'); } } public function testTagWithAttributeArrayThrowsException() { $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); try { $loader->load('badtag3.yml'); $this->fail('->load() should throw an exception when a tag-attribute is not a scalar'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar'); $this->assertStringStartsWith('A "tags" attribute must be of a scalar-type for service "foo_service", tag "foo", attribute "bar"', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar'); } } } PK!Q&I8a8aatest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Loader; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\Loader\IniFileLoader; use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\FileLocator; use Symfony\Component\ExpressionLanguage\Expression; class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; public static function setUpBeforeClass() { self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); require_once self::$fixturesPath.'/includes/foo.php'; require_once self::$fixturesPath.'/includes/ProjectExtension.php'; require_once self::$fixturesPath.'/includes/ProjectWithXsdExtension.php'; } public function testLoad() { $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini')); try { $loader->load('foo.xml'); $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist'); $this->assertStringStartsWith('The file "foo.xml" does not exist (in:', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist'); } } public function testParseFile() { $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini')); $r = new \ReflectionObject($loader); $m = $r->getMethod('parseFile'); $m->setAccessible(true); try { $m->invoke($loader, self::$fixturesPath.'/ini/parameters.ini'); $this->fail('->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file'); $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'parameters.ini'), $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file'); $e = $e->getPrevious(); $this->assertInstanceOf('InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file'); $this->assertStringStartsWith('[ERROR 4] Start tag expected, \'<\' not found (in', $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file'); } $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/xml')); try { $m->invoke($loader, self::$fixturesPath.'/xml/nonvalid.xml'); $this->fail('->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD'); $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'nonvalid.xml'), $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file'); $e = $e->getPrevious(); $this->assertInstanceOf('InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD'); $this->assertStringStartsWith('[ERROR 1845] Element \'nonvalid\': No matching global declaration available for the validation root. (in', $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD'); } $xml = $m->invoke($loader, self::$fixturesPath.'/xml/services1.xml'); $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\SimpleXMLElement', $xml, '->parseFile() returns an SimpleXMLElement object'); } public function testLoadParameters() { $container = new ContainerBuilder(); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $loader->load('services2.xml'); $actual = $container->getParameterBag()->all(); $expected = array( 'a string', 'foo' => 'bar', 'values' => array( 0, 'integer' => 4, 100 => null, 'true', true, false, 'on', 'off', 'float' => 1.3, 1000.3, 'a string', array('foo', 'bar'), ), 'foo_bar' => new Reference('foo_bar'), 'mixedcase' => array('MixedCaseKey' => 'value'), 'constant' => PHP_EOL, ); $this->assertEquals($expected, $actual, '->load() converts XML values to PHP ones'); } public function testLoadImports() { $container = new ContainerBuilder(); $resolver = new LoaderResolver(array( new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')), )); $loader->setResolver($resolver); $loader->load('services4.xml'); $actual = $container->getParameterBag()->all(); $expected = array( 'a string', 'foo' => 'bar', 'values' => array( 0, 'integer' => 4, 100 => null, 'true', true, false, 'on', 'off', 'float' => 1.3, 1000.3, 'a string', array('foo', 'bar'), ), 'foo_bar' => new Reference('foo_bar'), 'mixedcase' => array('MixedCaseKey' => 'value'), 'constant' => PHP_EOL, 'bar' => '%foo%', 'imported_from_ini' => true, 'imported_from_yaml' => true ); $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files'); // Bad import throws no exception due to ignore_errors value. $loader->load('services4_bad_import.xml'); } public function testLoadAnonymousServices() { $container = new ContainerBuilder(); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $loader->load('services5.xml'); $services = $container->getDefinitions(); $this->assertCount(4, $services, '->load() attributes unique ids to anonymous services'); // anonymous service as an argument $args = $services['foo']->getArguments(); $this->assertCount(1, $args, '->load() references anonymous services as "normal" ones'); $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $args[0], '->load() converts anonymous services to references to "normal" services'); $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones'); $inner = $services[(string) $args[0]]; $this->assertEquals('BarClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones'); // inner anonymous services $args = $inner->getArguments(); $this->assertCount(1, $args, '->load() references anonymous services as "normal" ones'); $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $args[0], '->load() converts anonymous services to references to "normal" services'); $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones'); $inner = $services[(string) $args[0]]; $this->assertEquals('BazClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones'); // anonymous service as a property $properties = $services['foo']->getProperties(); $property = $properties['p']; $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $property, '->load() converts anonymous services to references to "normal" services'); $this->assertTrue(isset($services[(string) $property]), '->load() makes a reference to the created ones'); $inner = $services[(string) $property]; $this->assertEquals('BazClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones'); } public function testLoadServices() { $container = new ContainerBuilder(); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $loader->load('services6.xml'); $services = $container->getDefinitions(); $this->assertTrue(isset($services['foo']), '->load() parses elements'); $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Definition', $services['foo'], '->load() converts element to Definition instances'); $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute'); $this->assertEquals('container', $services['scope.container']->getScope()); $this->assertEquals('custom', $services['scope.custom']->getScope()); $this->assertEquals('prototype', $services['scope.prototype']->getScope()); $this->assertEquals('getInstance', $services['constructor']->getFactoryMethod(), '->load() parses the factory-method attribute'); $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag'); $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags'); $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array(new Reference('baz', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array(array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag'); $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag'); $this->assertNull($services['factory_service']->getClass()); $this->assertEquals('getInstance', $services['factory_service']->getFactoryMethod()); $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService()); $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag'); $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag'); $this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag'); $aliases = $container->getAliases(); $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses elements'); $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases'); $this->assertTrue($aliases['alias_for_foo']->isPublic()); $this->assertTrue(isset($aliases['another_alias_for_foo'])); $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']); $this->assertFalse($aliases['another_alias_for_foo']->isPublic()); } public function testParsesTags() { $container = new ContainerBuilder(); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $loader->load('services10.xml'); $services = $container->findTaggedServiceIds('foo_tag'); $this->assertCount(1, $services); foreach ($services as $id => $tagAttributes) { foreach ($tagAttributes as $attributes) { $this->assertArrayHasKey('other_option', $attributes); $this->assertEquals('lorem', $attributes['other_option']); $this->assertArrayHasKey('other-option', $attributes, 'unnormalized tag attributes should not be removed'); $this->assertEquals('ciz', $attributes['some_option'], 'no overriding should be done when normalizing'); $this->assertEquals('cat', $attributes['some-option']); $this->assertArrayNotHasKey('an_other_option', $attributes, 'normalization should not be done when an underscore is already found'); } } } public function testConvertDomElementToArray() { $doc = new \DOMDocument("1.0"); $doc->loadXML('bar'); $this->assertEquals('bar', XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); $doc = new \DOMDocument("1.0"); $doc->loadXML(''); $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); $doc = new \DOMDocument("1.0"); $doc->loadXML('bar'); $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); $doc = new \DOMDocument("1.0"); $doc->loadXML('barbar'); $this->assertEquals(array('foo' => array('value' => 'bar', 'foo' => 'bar')), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); $doc = new \DOMDocument("1.0"); $doc->loadXML(''); $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); $doc = new \DOMDocument("1.0"); $doc->loadXML(''); $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); $doc = new \DOMDocument("1.0"); $doc->loadXML(''); $this->assertEquals(array('foo' => array(array('foo' => 'bar'), array('foo' => 'bar'))), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array'); } public function testExtensions() { $container = new ContainerBuilder(); $container->registerExtension(new \ProjectExtension()); $container->registerExtension(new \ProjectWithXsdExtension()); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); // extension without an XSD $loader->load('extensions/services1.xml'); $container->compile(); $services = $container->getDefinitions(); $parameters = $container->getParameterBag()->all(); $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements'); $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements'); $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements'); $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements'); // extension with an XSD $container = new ContainerBuilder(); $container->registerExtension(new \ProjectExtension()); $container->registerExtension(new \ProjectWithXsdExtension()); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $loader->load('extensions/services2.xml'); $container->compile(); $services = $container->getDefinitions(); $parameters = $container->getParameterBag()->all(); $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements'); $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements'); $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements'); $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements'); $container = new ContainerBuilder(); $container->registerExtension(new \ProjectExtension()); $container->registerExtension(new \ProjectWithXsdExtension()); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); // extension with an XSD (does not validate) try { $loader->load('extensions/services3.xml'); $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services3.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); $e = $e->getPrevious(); $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); $this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); } // non-registered extension try { $loader->load('extensions/services4.xml'); $this->fail('->load() throws an InvalidArgumentException if the tag is not valid'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid'); $this->assertStringStartsWith('There is no extension able to load the configuration for "project:bar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid'); } } public function testExtensionInPhar() { if (extension_loaded('suhosin') && false === strpos(ini_get('suhosin.executor.include.whitelist'), 'phar')) { $this->markTestSkipped('To run this test, add "phar" to the "suhosin.executor.include.whitelist" settings in your php.ini file.'); } require_once self::$fixturesPath.'/includes/ProjectWithXsdExtensionInPhar.phar'; // extension with an XSD in PHAR archive $container = new ContainerBuilder(); $container->registerExtension(new \ProjectWithXsdExtensionInPhar()); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $loader->load('extensions/services6.xml'); // extension with an XSD in PHAR archive (does not validate) try { $loader->load('extensions/services7.xml'); $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services7.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); $e = $e->getPrevious(); $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); $this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD'); } } /** * @covers Symfony\Component\DependencyInjection\Loader\XmlFileLoader::supports */ public function testSupports() { $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator()); $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable'); $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); } public function testNoNamingConflictsForAnonymousServices() { $container = new ContainerBuilder(); $loader1 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension1')); $loader1->load('services.xml'); $services = $container->getDefinitions(); $this->assertCount(2, $services, '->load() attributes unique ids to anonymous services'); $loader2 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension2')); $loader2->load('services.xml'); $services = $container->getDefinitions(); $this->assertCount(4, $services, '->load() attributes unique ids to anonymous services'); $services = $container->getDefinitions(); $args1 = $services['extension1.foo']->getArguments(); $inner1 = $services[(string) $args1[0]]; $this->assertEquals('BarClass1', $inner1->getClass(), '->load() uses the same configuration as for the anonymous ones'); $args2 = $services['extension2.foo']->getArguments(); $inner2 = $services[(string) $args2[0]]; $this->assertEquals('BarClass2', $inner2->getClass(), '->load() uses the same configuration as for the anonymous ones'); } public function testDocTypeIsNotAllowed() { $container = new ContainerBuilder(); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); // document types are not allowed. try { $loader->load('withdoctype.xml'); $this->fail('->load() throws an InvalidArgumentException if the configuration contains a document type'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type'); $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'withdoctype.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type'); $e = $e->getPrevious(); $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type'); $this->assertSame('Document types are not allowed.', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type'); } } } PK! atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\IniFileLoader; use Symfony\Component\Config\FileLocator; class IniFileLoaderTest extends \PHPUnit_Framework_TestCase { protected static $fixturesPath; protected $container; protected $loader; public static function setUpBeforeClass() { self::$fixturesPath = realpath(__DIR__.'/../Fixtures/'); } protected function setUp() { $this->container = new ContainerBuilder(); $this->loader = new IniFileLoader($this->container, new FileLocator(self::$fixturesPath.'/ini')); } /** * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load */ public function testIniFileCanBeLoaded() { $this->loader->load('parameters.ini'); $this->assertEquals(array('foo' => 'bar', 'bar' => '%foo%'), $this->container->getParameterBag()->all(), '->load() takes a single file name as its first argument'); } /** * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load * * @expectedException \InvalidArgumentException * @expectedExceptionMessage The file "foo.ini" does not exist (in: */ public function testExceptionIsRaisedWhenIniFileDoesNotExist() { $this->loader->load('foo.ini'); } /** * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load * * @expectedException \InvalidArgumentException * @expectedExceptionMessage The "nonvalid.ini" file is not valid. */ public function testExceptionIsRaisedWhenIniFileCannotBeParsed() { @$this->loader->load('nonvalid.ini'); } /** * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::supports */ public function testSupports() { $loader = new IniFileLoader(new ContainerBuilder(), new FileLocator()); $this->assertTrue($loader->supports('foo.ini'), '->supports() returns true if the resource is loadable'); $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); } } PK!' rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Compiler\ResolveInvalidReferencesPass; use Symfony\Component\DependencyInjection\ContainerBuilder; class ResolveInvalidReferencesPassTest extends \PHPUnit_Framework_TestCase { public function testProcess() { $container = new ContainerBuilder(); $def = $container ->register('foo') ->setArguments(array(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE))) ->addMethodCall('foo', array(new Reference('moo', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))) ; $this->process($container); $arguments = $def->getArguments(); $this->assertNull($arguments[0]); $this->assertCount(0, $def->getMethodCalls()); } public function testProcessIgnoreNonExistentServices() { $container = new ContainerBuilder(); $def = $container ->register('foo') ->setArguments(array(new Reference('bar'))) ; $this->process($container); $arguments = $def->getArguments(); $this->assertEquals('bar', (string) $arguments[0]); } public function testProcessRemovesPropertiesOnInvalid() { $container = new ContainerBuilder(); $def = $container ->register('foo') ->setProperty('foo', new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)) ; $this->process($container); $this->assertEquals(array(), $def->getProperties()); } public function testStrictFlagIsPreserved() { $container = new ContainerBuilder(); $container->register('bar'); $def = $container ->register('foo') ->addArgument(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)) ; $this->process($container); $this->assertFalse($def->getArgument(0)->isStrict()); } protected function process(ContainerBuilder $container) { $pass = new ResolveInvalidReferencesPass(); $pass->process($container); } } PK!'{ { qtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass; use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; class CheckCircularReferencesPassTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException */ public function testProcess() { $container = new ContainerBuilder(); $container->register('a')->addArgument(new Reference('b')); $container->register('b')->addArgument(new Reference('a')); $this->process($container); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException */ public function testProcessWithAliases() { $container = new ContainerBuilder(); $container->register('a')->addArgument(new Reference('b')); $container->setAlias('b', 'c'); $container->setAlias('c', 'a'); $this->process($container); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException */ public function testProcessDetectsIndirectCircularReference() { $container = new ContainerBuilder(); $container->register('a')->addArgument(new Reference('b')); $container->register('b')->addArgument(new Reference('c')); $container->register('c')->addArgument(new Reference('a')); $this->process($container); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException */ public function testDeepCircularReference() { $container = new ContainerBuilder(); $container->register('a')->addArgument(new Reference('b')); $container->register('b')->addArgument(new Reference('c')); $container->register('c')->addArgument(new Reference('b')); $this->process($container); } public function testProcessIgnoresMethodCalls() { $container = new ContainerBuilder(); $container->register('a')->addArgument(new Reference('b')); $container->register('b')->addMethodCall('setA', array(new Reference('a'))); $this->process($container); } protected function process(ContainerBuilder $container) { $compiler = new Compiler(); $passConfig = $compiler->getPassConfig(); $passConfig->setOptimizationPasses(array( new AnalyzeServiceReferencesPass(true), new CheckCircularReferencesPass(), )); $passConfig->setRemovingPasses(array()); $compiler->compile($container); } } PK!>" ptest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Scope; use Symfony\Component\DependencyInjection\Compiler\CheckReferenceValidityPass; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; class CheckReferenceValidityPassTest extends \PHPUnit_Framework_TestCase { public function testProcessIgnoresScopeWideningIfNonStrictReference() { $container = new ContainerBuilder(); $container->register('a')->addArgument(new Reference('b', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false)); $container->register('b')->setScope('prototype'); $this->process($container); } /** * @expectedException \RuntimeException */ public function testProcessDetectsScopeWidening() { $container = new ContainerBuilder(); $container->register('a')->addArgument(new Reference('b')); $container->register('b')->setScope('prototype'); $this->process($container); } public function testProcessIgnoresCrossScopeHierarchyReferenceIfNotStrict() { $container = new ContainerBuilder(); $container->addScope(new Scope('a')); $container->addScope(new Scope('b')); $container->register('a')->setScope('a')->addArgument(new Reference('b', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false)); $container->register('b')->setScope('b'); $this->process($container); } /** * @expectedException \RuntimeException */ public function testProcessDetectsCrossScopeHierarchyReference() { $container = new ContainerBuilder(); $container->addScope(new Scope('a')); $container->addScope(new Scope('b')); $container->register('a')->setScope('a')->addArgument(new Reference('b')); $container->register('b')->setScope('b'); $this->process($container); } /** * @expectedException \RuntimeException */ public function testProcessDetectsReferenceToAbstractDefinition() { $container = new ContainerBuilder(); $container->register('a')->setAbstract(true); $container->register('b')->addArgument(new Reference('a')); $this->process($container); } public function testProcess() { $container = new ContainerBuilder(); $container->register('a')->addArgument(new Reference('b')); $container->register('b'); $this->process($container); } protected function process(ContainerBuilder $container) { $pass = new CheckReferenceValidityPass(); $pass->process($container); } } PK!]ttest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass; use Symfony\Component\DependencyInjection\ContainerBuilder; class ResolveDefinitionTemplatesPassTest extends \PHPUnit_Framework_TestCase { public function testProcess() { $container = new ContainerBuilder(); $container->register('parent', 'foo')->setArguments(array('moo', 'b'))->setProperty('foo', 'moo'); $container->setDefinition('child', new DefinitionDecorator('parent')) ->replaceArgument(0, 'a') ->setProperty('foo', 'bar') ->setClass('bar') ; $this->process($container); $def = $container->getDefinition('child'); $this->assertNotInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $def); $this->assertEquals('bar', $def->getClass()); $this->assertEquals(array('a', 'b'), $def->getArguments()); $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); } public function testProcessAppendsMethodCallsAlways() { $container = new ContainerBuilder(); $container ->register('parent') ->addMethodCall('foo', array('bar')) ; $container ->setDefinition('child', new DefinitionDecorator('parent')) ->addMethodCall('bar', array('foo')) ; $this->process($container); $def = $container->getDefinition('child'); $this->assertEquals(array( array('foo', array('bar')), array('bar', array('foo')), ), $def->getMethodCalls()); } public function testProcessDoesNotCopyAbstract() { $container = new ContainerBuilder(); $container ->register('parent') ->setAbstract(true) ; $container ->setDefinition('child', new DefinitionDecorator('parent')) ; $this->process($container); $def = $container->getDefinition('child'); $this->assertFalse($def->isAbstract()); } public function testProcessDoesNotCopyScope() { $container = new ContainerBuilder(); $container ->register('parent') ->setScope('foo') ; $container ->setDefinition('child', new DefinitionDecorator('parent')) ; $this->process($container); $def = $container->getDefinition('child'); $this->assertEquals(ContainerInterface::SCOPE_CONTAINER, $def->getScope()); } public function testProcessDoesNotCopyTags() { $container = new ContainerBuilder(); $container ->register('parent') ->addTag('foo') ; $container ->setDefinition('child', new DefinitionDecorator('parent')) ; $this->process($container); $def = $container->getDefinition('child'); $this->assertEquals(array(), $def->getTags()); } public function testProcessHandlesMultipleInheritance() { $container = new ContainerBuilder(); $container ->register('parent', 'foo') ->setArguments(array('foo', 'bar', 'c')) ; $container ->setDefinition('child2', new DefinitionDecorator('child1')) ->replaceArgument(1, 'b') ; $container ->setDefinition('child1', new DefinitionDecorator('parent')) ->replaceArgument(0, 'a') ; $this->process($container); $def = $container->getDefinition('child2'); $this->assertEquals(array('a', 'b', 'c'), $def->getArguments()); $this->assertEquals('foo', $def->getClass()); } public function testSetLazyOnServiceHasParent() { $container = new ContainerBuilder(); $container->register('parent','stdClass'); $container->setDefinition('child1',new DefinitionDecorator('parent')) ->setLazy(true) ; $this->process($container); $this->assertTrue($container->getDefinition('child1')->isLazy()); } public function testSetLazyOnServiceIsParent() { $container = new ContainerBuilder(); $container->register('parent','stdClass') ->setLazy(true) ; $container->setDefinition('child1',new DefinitionDecorator('parent')); $this->process($container); $this->assertTrue($container->getDefinition('child1')->isLazy()); } protected function process(ContainerBuilder $container) { $pass = new ResolveDefinitionTemplatesPass(); $pass->process($container); } } PK!}1H@@xtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Compiler\ReplaceAliasByActualDefinitionPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; class ReplaceAliasByActualDefinitionPassTest extends \PHPUnit_Framework_TestCase { public function testProcess() { $container = new ContainerBuilder(); $container->register('a', '\stdClass'); $bDefinition = new Definition('\stdClass'); $bDefinition->setPublic(false); $container->setDefinition('b', $bDefinition); $container->setAlias('a_alias', 'a'); $container->setAlias('b_alias', 'b'); $this->process($container); $this->assertTrue($container->has('a'), '->process() does nothing to public definitions.'); $this->assertTrue($container->hasAlias('a_alias')); $this->assertFalse($container->has('b'), '->process() removes non-public definitions.'); $this->assertTrue( $container->has('b_alias') && !$container->hasAlias('b_alias'), '->process() replaces alias to actual.' ); } /** * @expectedException \InvalidArgumentException */ public function testProcessWithInvalidAlias() { $container = new ContainerBuilder(); $container->setAlias('a_alias', 'a'); $this->process($container); } protected function process(ContainerBuilder $container) { $pass = new ReplaceAliasByActualDefinitionPass(); $pass->process($container); } } PK!f00rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Scope; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; use Symfony\Component\DependencyInjection\Compiler\RepeatedPass; use Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; class InlineServiceDefinitionsPassTest extends \PHPUnit_Framework_TestCase { public function testProcess() { $container = new ContainerBuilder(); $container ->register('inlinable.service') ->setPublic(false) ; $container ->register('service') ->setArguments(array(new Reference('inlinable.service'))) ; $this->process($container); $arguments = $container->getDefinition('service')->getArguments(); $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $arguments[0]); $this->assertSame($container->getDefinition('inlinable.service'), $arguments[0]); } public function testProcessDoesNotInlineWhenAliasedServiceIsNotOfPrototypeScope() { $container = new ContainerBuilder(); $container ->register('foo') ->setPublic(false) ; $container->setAlias('moo', 'foo'); $container ->register('service') ->setArguments(array($ref = new Reference('foo'))) ; $this->process($container); $arguments = $container->getDefinition('service')->getArguments(); $this->assertSame($ref, $arguments[0]); } public function testProcessDoesInlineServiceOfPrototypeScope() { $container = new ContainerBuilder(); $container ->register('foo') ->setScope('prototype') ; $container ->register('bar') ->setPublic(false) ->setScope('prototype') ; $container->setAlias('moo', 'bar'); $container ->register('service') ->setArguments(array(new Reference('foo'), $ref = new Reference('moo'), new Reference('bar'))) ; $this->process($container); $arguments = $container->getDefinition('service')->getArguments(); $this->assertEquals($container->getDefinition('foo'), $arguments[0]); $this->assertNotSame($container->getDefinition('foo'), $arguments[0]); $this->assertSame($ref, $arguments[1]); $this->assertEquals($container->getDefinition('bar'), $arguments[2]); $this->assertNotSame($container->getDefinition('bar'), $arguments[2]); } public function testProcessInlinesIfMultipleReferencesButAllFromTheSameDefinition() { $container = new ContainerBuilder(); $a = $container->register('a')->setPublic(false); $b = $container ->register('b') ->addArgument(new Reference('a')) ->addArgument(new Definition(null, array(new Reference('a')))) ; $this->process($container); $arguments = $b->getArguments(); $this->assertSame($a, $arguments[0]); $inlinedArguments = $arguments[1]->getArguments(); $this->assertSame($a, $inlinedArguments[0]); } public function testProcessInlinesOnlyIfSameScope() { $container = new ContainerBuilder(); $container->addScope(new Scope('foo')); $a = $container->register('a')->setPublic(false)->setScope('foo'); $b = $container->register('b')->addArgument(new Reference('a')); $this->process($container); $arguments = $b->getArguments(); $this->assertEquals(new Reference('a'), $arguments[0]); $this->assertTrue($container->hasDefinition('a')); } public function testProcessDoesNotInlineWhenServiceIsPrivateButLazy() { $container = new ContainerBuilder(); $container ->register('foo') ->setPublic(false) ->setLazy(true) ; $container ->register('service') ->setArguments(array($ref = new Reference('foo'))) ; $this->process($container); $arguments = $container->getDefinition('service')->getArguments(); $this->assertSame($ref, $arguments[0]); } public function testProcessDoesNotInlineWhenServiceReferencesItself() { $container = new ContainerBuilder(); $container ->register('foo') ->setPublic(false) ->addMethodCall('foo', array($ref = new Reference('foo'))) ; $this->process($container); $calls = $container->getDefinition('foo')->getMethodCalls(); $this->assertSame($ref, $calls[0][1][0]); } protected function process(ContainerBuilder $container) { $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass())); $repeatedPass->process($container); } } PK!O atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * This class tests the integration of the different compiler passes */ class IntegrationTest extends \PHPUnit_Framework_TestCase { /** * This tests that the following dependencies are correctly processed: * * A is public, B/C are private * A -> C * B -> C */ public function testProcessRemovesAndInlinesRecursively() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $a = $container ->register('a', '\stdClass') ->addArgument(new Reference('c')) ; $b = $container ->register('b', '\stdClass') ->addArgument(new Reference('c')) ->setPublic(false) ; $c = $container ->register('c', '\stdClass') ->setPublic(false) ; $container->compile(); $this->assertTrue($container->hasDefinition('a')); $arguments = $a->getArguments(); $this->assertSame($c, $arguments[0]); $this->assertFalse($container->hasDefinition('b')); $this->assertFalse($container->hasDefinition('c')); } public function testProcessInlinesReferencesToAliases() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $a = $container ->register('a', '\stdClass') ->addArgument(new Reference('b')) ; $container->setAlias('b', new Alias('c', false)); $c = $container ->register('c', '\stdClass') ->setPublic(false) ; $container->compile(); $this->assertTrue($container->hasDefinition('a')); $arguments = $a->getArguments(); $this->assertSame($c, $arguments[0]); $this->assertFalse($container->hasAlias('b')); $this->assertFalse($container->hasDefinition('c')); } public function testProcessInlinesWhenThereAreMultipleReferencesButFromTheSameDefinition() { $container = new ContainerBuilder(); $container->setResourceTracking(false); $container ->register('a', '\stdClass') ->addArgument(new Reference('b')) ->addMethodCall('setC', array(new Reference('c'))) ; $container ->register('b', '\stdClass') ->addArgument(new Reference('c')) ->setPublic(false) ; $container ->register('c', '\stdClass') ->setPublic(false) ; $container->compile(); $this->assertTrue($container->hasDefinition('a')); $this->assertFalse($container->hasDefinition('b')); $this->assertFalse($container->hasDefinition('c'), 'Service C was not inlined.'); } } PK!@|޵test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Compiler\CheckExceptionOnInvalidReferenceBehaviorPass; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; class CheckExceptionOnInvalidReferenceBehaviorPassTest extends \PHPUnit_Framework_TestCase { public function testProcess() { $container = new ContainerBuilder(); $container ->register('a', '\stdClass') ->addArgument(new Reference('b')) ; $container->register('b', '\stdClass'); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException */ public function testProcessThrowsExceptionOnInvalidReference() { $container = new ContainerBuilder(); $container ->register('a', '\stdClass') ->addArgument(new Reference('b')) ; $this->process($container); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException */ public function testProcessThrowsExceptionOnInvalidReferenceFromInlinedDefinition() { $container = new ContainerBuilder(); $def = new Definition(); $def->addArgument(new Reference('b')); $container ->register('a', '\stdClass') ->addArgument($def) ; $this->process($container); } private function process(ContainerBuilder $container) { $pass = new CheckExceptionOnInvalidReferenceBehaviorPass(); $pass->process($container); } } PK!@w qtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Compiler\CheckDefinitionValidityPass; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; class CheckDefinitionValidityPassTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException */ public function testProcessDetectsSyntheticNonPublicDefinitions() { $container = new ContainerBuilder(); $container->register('a')->setSynthetic(true)->setPublic(false); $this->process($container); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException */ public function testProcessDetectsSyntheticPrototypeDefinitions() { $container = new ContainerBuilder(); $container->register('a')->setSynthetic(true)->setScope(ContainerInterface::SCOPE_PROTOTYPE); $this->process($container); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException */ public function testProcessDetectsNonSyntheticNonAbstractDefinitionWithoutClass() { $container = new ContainerBuilder(); $container->register('a')->setSynthetic(false)->setAbstract(false); $this->process($container); } public function testProcess() { $container = new ContainerBuilder(); $container->register('a', 'class'); $container->register('b', 'class')->setSynthetic(true)->setPublic(true); $container->register('c', 'class')->setAbstract(true); $container->register('d', 'class')->setSynthetic(true); $this->process($container); } public function testValidTags() { $container = new ContainerBuilder(); $container->register('a', 'class')->addTag('foo', array('bar' => 'baz')); $container->register('b', 'class')->addTag('foo', array('bar' => null)); $container->register('c', 'class')->addTag('foo', array('bar' => 1)); $container->register('d', 'class')->addTag('foo', array('bar' => 1.1)); $this->process($container); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException */ public function testInvalidTags() { $container = new ContainerBuilder(); $container->register('a', 'class')->addTag('foo', array('bar' => array('baz' => 'baz'))); $this->process($container); } protected function process(ContainerBuilder $container) { $pass = new CheckDefinitionValidityPass(); $pass->process($container); } } PK!~ ` ` rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; use Symfony\Component\DependencyInjection\Compiler\RepeatedPass; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; class AnalyzeServiceReferencesPassTest extends \PHPUnit_Framework_TestCase { public function testProcess() { $container = new ContainerBuilder(); $a = $container ->register('a') ->addArgument($ref1 = new Reference('b')) ; $b = $container ->register('b') ->addMethodCall('setA', array($ref2 = new Reference('a'))) ; $c = $container ->register('c') ->addArgument($ref3 = new Reference('a')) ->addArgument($ref4 = new Reference('b')) ; $d = $container ->register('d') ->setProperty('foo', $ref5 = new Reference('b')) ; $e = $container ->register('e') ->setConfigurator(array($ref6 = new Reference('b'), 'methodName')) ; $graph = $this->process($container); $this->assertCount(4, $edges = $graph->getNode('b')->getInEdges()); $this->assertSame($ref1, $edges[0]->getValue()); $this->assertSame($ref4, $edges[1]->getValue()); $this->assertSame($ref5, $edges[2]->getValue()); $this->assertSame($ref6, $edges[3]->getValue()); } public function testProcessDetectsReferencesFromInlinedDefinitions() { $container = new ContainerBuilder(); $container ->register('a') ; $container ->register('b') ->addArgument(new Definition(null, array($ref = new Reference('a')))) ; $graph = $this->process($container); $this->assertCount(1, $refs = $graph->getNode('a')->getInEdges()); $this->assertSame($ref, $refs[0]->getValue()); } public function testProcessDoesNotSaveDuplicateReferences() { $container = new ContainerBuilder(); $container ->register('a') ; $container ->register('b') ->addArgument(new Definition(null, array($ref1 = new Reference('a')))) ->addArgument(new Definition(null, array($ref2 = new Reference('a')))) ; $graph = $this->process($container); $this->assertCount(2, $graph->getNode('a')->getInEdges()); } protected function process(ContainerBuilder $container) { $pass = new RepeatedPass(array(new AnalyzeServiceReferencesPass())); $pass->process($container); return $container->getCompiler()->getServiceReferenceGraph(); } } PK!I qtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\RepeatedPass; use Symfony\Component\DependencyInjection\Compiler\RemoveUnusedDefinitionsPass; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; class RemoveUnusedDefinitionsPassTest extends \PHPUnit_Framework_TestCase { public function testProcess() { $container = new ContainerBuilder(); $container ->register('foo') ->setPublic(false) ; $container ->register('bar') ->setPublic(false) ; $container ->register('moo') ->setArguments(array(new Reference('bar'))) ; $this->process($container); $this->assertFalse($container->hasDefinition('foo')); $this->assertTrue($container->hasDefinition('bar')); $this->assertTrue($container->hasDefinition('moo')); } public function testProcessRemovesUnusedDefinitionsRecursively() { $container = new ContainerBuilder(); $container ->register('foo') ->setPublic(false) ; $container ->register('bar') ->setArguments(array(new Reference('foo'))) ->setPublic(false) ; $this->process($container); $this->assertFalse($container->hasDefinition('foo')); $this->assertFalse($container->hasDefinition('bar')); } public function testProcessWorksWithInlinedDefinitions() { $container = new ContainerBuilder(); $container ->register('foo') ->setPublic(false) ; $container ->register('bar') ->setArguments(array(new Definition(null, array(new Reference('foo'))))) ; $this->process($container); $this->assertTrue($container->hasDefinition('foo')); $this->assertTrue($container->hasDefinition('bar')); } protected function process(ContainerBuilder $container) { $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new RemoveUnusedDefinitionsPass())); $repeatedPass->process($container); } } PK! T^??ttest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Compiler\ResolveReferencesToAliasesPass; use Symfony\Component\DependencyInjection\ContainerBuilder; class ResolveReferencesToAliasesPassTest extends \PHPUnit_Framework_TestCase { public function testProcess() { $container = new ContainerBuilder(); $container->setAlias('bar', 'foo'); $def = $container ->register('moo') ->setArguments(array(new Reference('bar'))) ; $this->process($container); $arguments = $def->getArguments(); $this->assertEquals('foo', (string) $arguments[0]); } public function testProcessRecursively() { $container = new ContainerBuilder(); $container->setAlias('bar', 'foo'); $container->setAlias('moo', 'bar'); $def = $container ->register('foobar') ->setArguments(array(new Reference('moo'))) ; $this->process($container); $arguments = $def->getArguments(); $this->assertEquals('foo', (string) $arguments[0]); } protected function process(ContainerBuilder $container) { $pass = new ResolveReferencesToAliasesPass(); $pass->process($container); } } PK!e55Wtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests; use Symfony\Component\DependencyInjection\Definition; class DefinitionTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\DependencyInjection\Definition::__construct */ public function testConstructor() { $def = new Definition('stdClass'); $this->assertEquals('stdClass', $def->getClass(), '__construct() takes the class name as its first argument'); $def = new Definition('stdClass', array('foo')); $this->assertEquals(array('foo'), $def->getArguments(), '__construct() takes an optional array of arguments as its second argument'); } public function testSetGetFactoryClass() { $def = new Definition('stdClass'); $this->assertNull($def->getFactoryClass()); $this->assertSame($def, $def->setFactoryClass('stdClass2'), "->setFactoryClass() implements a fluent interface."); $this->assertEquals('stdClass2', $def->getFactoryClass(), "->getFactoryClass() returns current class to construct this service."); } public function testSetGetFactoryMethod() { $def = new Definition('stdClass'); $this->assertNull($def->getFactoryMethod()); $this->assertSame($def, $def->setFactoryMethod('foo'), '->setFactoryMethod() implements a fluent interface'); $this->assertEquals('foo', $def->getFactoryMethod(), '->getFactoryMethod() returns the factory method name'); } public function testSetGetFactoryService() { $def = new Definition('stdClass'); $this->assertNull($def->getFactoryService()); $this->assertSame($def, $def->setFactoryService('foo.bar'), "->setFactoryService() implements a fluent interface."); $this->assertEquals('foo.bar', $def->getFactoryService(), "->getFactoryService() returns current service to construct this service."); } /** * @covers Symfony\Component\DependencyInjection\Definition::setClass * @covers Symfony\Component\DependencyInjection\Definition::getClass */ public function testSetGetClass() { $def = new Definition('stdClass'); $this->assertSame($def, $def->setClass('foo'), '->setClass() implements a fluent interface'); $this->assertEquals('foo', $def->getClass(), '->getClass() returns the class name'); } /** * @covers Symfony\Component\DependencyInjection\Definition::setArguments * @covers Symfony\Component\DependencyInjection\Definition::getArguments * @covers Symfony\Component\DependencyInjection\Definition::addArgument */ public function testArguments() { $def = new Definition('stdClass'); $this->assertSame($def, $def->setArguments(array('foo')), '->setArguments() implements a fluent interface'); $this->assertEquals(array('foo'), $def->getArguments(), '->getArguments() returns the arguments'); $this->assertSame($def, $def->addArgument('bar'), '->addArgument() implements a fluent interface'); $this->assertEquals(array('foo', 'bar'), $def->getArguments(), '->addArgument() adds an argument'); } /** * @covers Symfony\Component\DependencyInjection\Definition::setMethodCalls * @covers Symfony\Component\DependencyInjection\Definition::addMethodCall * @covers Symfony\Component\DependencyInjection\Definition::hasMethodCall * @covers Symfony\Component\DependencyInjection\Definition::removeMethodCall */ public function testMethodCalls() { $def = new Definition('stdClass'); $this->assertSame($def, $def->setMethodCalls(array(array('foo', array('foo')))), '->setMethodCalls() implements a fluent interface'); $this->assertEquals(array(array('foo', array('foo'))), $def->getMethodCalls(), '->getMethodCalls() returns the methods to call'); $this->assertSame($def, $def->addMethodCall('bar', array('bar')), '->addMethodCall() implements a fluent interface'); $this->assertEquals(array(array('foo', array('foo')), array('bar', array('bar'))), $def->getMethodCalls(), '->addMethodCall() adds a method to call'); $this->assertTrue($def->hasMethodCall('bar'), '->hasMethodCall() returns true if first argument is a method to call registered'); $this->assertFalse($def->hasMethodCall('no_registered'), '->hasMethodCall() returns false if first argument is not a method to call registered'); $this->assertSame($def, $def->removeMethodCall('bar'), '->removeMethodCall() implements a fluent interface'); $this->assertEquals(array(array('foo', array('foo'))), $def->getMethodCalls(), '->removeMethodCall() removes a method to call'); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException * @expectedExceptionMessage Method name cannot be empty. */ public function testExceptionOnEmptyMethodCall() { $def = new Definition('stdClass'); $def->addMethodCall(''); } /** * @covers Symfony\Component\DependencyInjection\Definition::setFile * @covers Symfony\Component\DependencyInjection\Definition::getFile */ public function testSetGetFile() { $def = new Definition('stdClass'); $this->assertSame($def, $def->setFile('foo'), '->setFile() implements a fluent interface'); $this->assertEquals('foo', $def->getFile(), '->getFile() returns the file to include'); } /** * @covers Symfony\Component\DependencyInjection\Definition::setScope * @covers Symfony\Component\DependencyInjection\Definition::getScope */ public function testSetGetScope() { $def = new Definition('stdClass'); $this->assertEquals('container', $def->getScope()); $this->assertSame($def, $def->setScope('foo')); $this->assertEquals('foo', $def->getScope()); } /** * @covers Symfony\Component\DependencyInjection\Definition::setPublic * @covers Symfony\Component\DependencyInjection\Definition::isPublic */ public function testSetIsPublic() { $def = new Definition('stdClass'); $this->assertTrue($def->isPublic(), '->isPublic() returns true by default'); $this->assertSame($def, $def->setPublic(false), '->setPublic() implements a fluent interface'); $this->assertFalse($def->isPublic(), '->isPublic() returns false if the instance must not be public.'); } /** * @covers Symfony\Component\DependencyInjection\Definition::setSynthetic * @covers Symfony\Component\DependencyInjection\Definition::isSynthetic */ public function testSetIsSynthetic() { $def = new Definition('stdClass'); $this->assertFalse($def->isSynthetic(), '->isSynthetic() returns false by default'); $this->assertSame($def, $def->setSynthetic(true), '->setSynthetic() implements a fluent interface'); $this->assertTrue($def->isSynthetic(), '->isSynthetic() returns true if the service is synthetic.'); } /** * @covers Symfony\Component\DependencyInjection\Definition::setSynchronized * @covers Symfony\Component\DependencyInjection\Definition::isSynchronized */ public function testSetIsSynchronized() { $def = new Definition('stdClass'); $this->assertFalse($def->isSynchronized(), '->isSynchronized() returns false by default'); $this->assertSame($def, $def->setSynchronized(true), '->setSynchronized() implements a fluent interface'); $this->assertTrue($def->isSynchronized(), '->isSynchronized() returns true if the service is synchronized.'); } /** * @covers Symfony\Component\DependencyInjection\Definition::setLazy * @covers Symfony\Component\DependencyInjection\Definition::isLazy */ public function testSetIsLazy() { $def = new Definition('stdClass'); $this->assertFalse($def->isLazy(), '->isLazy() returns false by default'); $this->assertSame($def, $def->setLazy(true), '->setLazy() implements a fluent interface'); $this->assertTrue($def->isLazy(), '->isLazy() returns true if the service is lazy.'); } /** * @covers Symfony\Component\DependencyInjection\Definition::setAbstract * @covers Symfony\Component\DependencyInjection\Definition::isAbstract */ public function testSetIsAbstract() { $def = new Definition('stdClass'); $this->assertFalse($def->isAbstract(), '->isAbstract() returns false by default'); $this->assertSame($def, $def->setAbstract(true), '->setAbstract() implements a fluent interface'); $this->assertTrue($def->isAbstract(), '->isAbstract() returns true if the instance must not be public.'); } /** * @covers Symfony\Component\DependencyInjection\Definition::setConfigurator * @covers Symfony\Component\DependencyInjection\Definition::getConfigurator */ public function testSetGetConfigurator() { $def = new Definition('stdClass'); $this->assertSame($def, $def->setConfigurator('foo'), '->setConfigurator() implements a fluent interface'); $this->assertEquals('foo', $def->getConfigurator(), '->getConfigurator() returns the configurator'); } /** * @covers Symfony\Component\DependencyInjection\Definition::clearTags */ public function testClearTags() { $def = new Definition('stdClass'); $this->assertSame($def, $def->clearTags(), '->clearTags() implements a fluent interface'); $def->addTag('foo', array('foo' => 'bar')); $def->clearTags(); $this->assertEquals(array(), $def->getTags(), '->clearTags() removes all current tags'); } /** * @covers Symfony\Component\DependencyInjection\Definition::clearTags */ public function testClearTag() { $def = new Definition('stdClass'); $this->assertSame($def, $def->clearTags(), '->clearTags() implements a fluent interface'); $def->addTag('1foo1', array('foo1' => 'bar1')); $def->addTag('2foo2', array('foo2' => 'bar2')); $def->addTag('3foo3', array('foo3' => 'bar3')); $def->clearTag('2foo2'); $this->assertTrue($def->hasTag('1foo1')); $this->assertFalse($def->hasTag('2foo2')); $this->assertTrue($def->hasTag('3foo3')); $def->clearTag('1foo1'); $this->assertFalse($def->hasTag('1foo1')); $this->assertTrue($def->hasTag('3foo3')); } /** * @covers Symfony\Component\DependencyInjection\Definition::addTag * @covers Symfony\Component\DependencyInjection\Definition::getTag * @covers Symfony\Component\DependencyInjection\Definition::getTags * @covers Symfony\Component\DependencyInjection\Definition::hasTag */ public function testTags() { $def = new Definition('stdClass'); $this->assertEquals(array(), $def->getTag('foo'), '->getTag() returns an empty array if the tag is not defined'); $this->assertFalse($def->hasTag('foo')); $this->assertSame($def, $def->addTag('foo'), '->addTag() implements a fluent interface'); $this->assertTrue($def->hasTag('foo')); $this->assertEquals(array(array()), $def->getTag('foo'), '->getTag() returns attributes for a tag name'); $def->addTag('foo', array('foo' => 'bar')); $this->assertEquals(array(array(), array('foo' => 'bar')), $def->getTag('foo'), '->addTag() can adds the same tag several times'); $def->addTag('bar', array('bar' => 'bar')); $this->assertEquals($def->getTags(), array( 'foo' => array(array(), array('foo' => 'bar')), 'bar' => array(array('bar' => 'bar')), ), '->getTags() returns all tags'); } /** * @covers Symfony\Component\DependencyInjection\Definition::replaceArgument */ public function testSetArgument() { $def = new Definition('stdClass'); $def->addArgument('foo'); $this->assertSame(array('foo'), $def->getArguments()); $this->assertSame($def, $def->replaceArgument(0, 'moo')); $this->assertSame(array('moo'), $def->getArguments()); $def->addArgument('moo'); $def ->replaceArgument(0, 'foo') ->replaceArgument(1, 'bar') ; $this->assertSame(array('foo', 'bar'), $def->getArguments()); } /** * @expectedException \OutOfBoundsException */ public function testGetArgumentShouldCheckBounds() { $def = new Definition('stdClass'); $def->addArgument('foo'); $def->getArgument(1); } /** * @expectedException \OutOfBoundsException */ public function testReplaceArgumentShouldCheckBounds() { $def = new Definition('stdClass'); $def->addArgument('foo'); $def->replaceArgument(1, 'bar'); } public function testSetGetProperties() { $def = new Definition('stdClass'); $this->assertEquals(array(), $def->getProperties()); $this->assertSame($def, $def->setProperties(array('foo' => 'bar'))); $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); } public function testSetProperty() { $def = new Definition('stdClass'); $this->assertEquals(array(), $def->getProperties()); $this->assertSame($def, $def->setProperty('foo', 'bar')); $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); } } PK!+E `test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests; use Symfony\Component\DependencyInjection\DefinitionDecorator; class DefinitionDecoratorTest extends \PHPUnit_Framework_TestCase { public function testConstructor() { $def = new DefinitionDecorator('foo'); $this->assertEquals('foo', $def->getParent()); $this->assertEquals(array(), $def->getChanges()); } /** * @dataProvider getPropertyTests */ public function testSetProperty($property, $changeKey) { $def = new DefinitionDecorator('foo'); $getter = 'get'.ucfirst($property); $setter = 'set'.ucfirst($property); $this->assertNull($def->$getter()); $this->assertSame($def, $def->$setter('foo')); $this->assertEquals('foo', $def->$getter()); $this->assertEquals(array($changeKey => true), $def->getChanges()); } public function getPropertyTests() { return array( array('class', 'class'), array('factoryClass', 'factory_class'), array('factoryMethod', 'factory_method'), array('factoryService', 'factory_service'), array('configurator', 'configurator'), array('file', 'file'), ); } public function testSetPublic() { $def = new DefinitionDecorator('foo'); $this->assertTrue($def->isPublic()); $this->assertSame($def, $def->setPublic(false)); $this->assertFalse($def->isPublic()); $this->assertEquals(array('public' => true), $def->getChanges()); } public function testSetLazy() { $def = new DefinitionDecorator('foo'); $this->assertFalse($def->isLazy()); $this->assertSame($def, $def->setLazy(false)); $this->assertFalse($def->isLazy()); $this->assertEquals(array('lazy' => true), $def->getChanges()); } public function testSetArgument() { $def = new DefinitionDecorator('foo'); $this->assertEquals(array(), $def->getArguments()); $this->assertSame($def, $def->replaceArgument(0, 'foo')); $this->assertEquals(array('index_0' => 'foo'), $def->getArguments()); } /** * @expectedException \InvalidArgumentException */ public function testReplaceArgumentShouldRequireIntegerIndex() { $def = new DefinitionDecorator('foo'); $def->replaceArgument('0', 'foo'); } public function testReplaceArgument() { $def = new DefinitionDecorator('foo'); $def->setArguments(array(0 => 'foo', 1 => 'bar')); $this->assertEquals('foo', $def->getArgument(0)); $this->assertEquals('bar', $def->getArgument(1)); $this->assertSame($def, $def->replaceArgument(1, 'baz')); $this->assertEquals('foo', $def->getArgument(0)); $this->assertEquals('baz', $def->getArgument(1)); $this->assertEquals(array(0 => 'foo', 1 => 'bar', 'index_1' => 'baz'), $def->getArguments()); } /** * @expectedException \OutOfBoundsException */ public function testGetArgumentShouldCheckBounds() { $def = new DefinitionDecorator('foo'); $def->setArguments(array(0 => 'foo')); $def->replaceArgument(0, 'foo'); $def->getArgument(1); } } PK!K5WWVtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests; use Symfony\Component\DependencyInjection\Scope; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; class ContainerTest extends \PHPUnit_Framework_TestCase { /** * @covers Symfony\Component\DependencyInjection\Container::__construct */ public function testConstructor() { $sc = new Container(); $this->assertSame($sc, $sc->get('service_container'), '__construct() automatically registers itself as a service'); $sc = new Container(new ParameterBag(array('foo' => 'bar'))); $this->assertEquals(array('foo' => 'bar'), $sc->getParameterBag()->all(), '__construct() takes an array of parameters as its first argument'); } /** * @dataProvider dataForTestCamelize */ public function testCamelize($id, $expected) { $this->assertEquals($expected, Container::camelize($id), sprintf('Container::camelize("%s")', $id)); } public function dataForTestCamelize() { return array( array('foo_bar', 'FooBar'), array('foo.bar', 'Foo_Bar'), array('foo.bar_baz', 'Foo_BarBaz'), array('foo._bar', 'Foo_Bar'), array('foo_.bar', 'Foo_Bar'), array('_foo', 'Foo'), array('.foo', '_Foo'), array('foo_', 'Foo'), array('foo.', 'Foo_'), array('foo\bar', 'Foo_Bar'), ); } /** * @covers Symfony\Component\DependencyInjection\Container::compile */ public function testCompile() { $sc = new Container(new ParameterBag(array('foo' => 'bar'))); $sc->compile(); $this->assertInstanceOf('Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag', $sc->getParameterBag(), '->compile() changes the parameter bag to a FrozenParameterBag instance'); $this->assertEquals(array('foo' => 'bar'), $sc->getParameterBag()->all(), '->compile() copies the current parameters to the new parameter bag'); } /** * @covers Symfony\Component\DependencyInjection\Container::isFrozen */ public function testIsFrozen() { $sc = new Container(new ParameterBag(array('foo' => 'bar'))); $this->assertFalse($sc->isFrozen(), '->isFrozen() returns false if the parameters are not frozen'); $sc->compile(); $this->assertTrue($sc->isFrozen(), '->isFrozen() returns true if the parameters are frozen'); } /** * @covers Symfony\Component\DependencyInjection\Container::getParameterBag */ public function testGetParameterBag() { $sc = new Container(); $this->assertEquals(array(), $sc->getParameterBag()->all(), '->getParameterBag() returns an empty array if no parameter has been defined'); } /** * @covers Symfony\Component\DependencyInjection\Container::setParameter * @covers Symfony\Component\DependencyInjection\Container::getParameter */ public function testGetSetParameter() { $sc = new Container(new ParameterBag(array('foo' => 'bar'))); $sc->setParameter('bar', 'foo'); $this->assertEquals('foo', $sc->getParameter('bar'), '->setParameter() sets the value of a new parameter'); $sc->setParameter('foo', 'baz'); $this->assertEquals('baz', $sc->getParameter('foo'), '->setParameter() overrides previously set parameter'); $sc->setParameter('Foo', 'baz1'); $this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase'); $this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase'); try { $sc->getParameter('baba'); $this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->getParameter() thrown an \InvalidArgumentException if the key does not exist'); $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->getParameter() thrown an \InvalidArgumentException if the key does not exist'); } } /** * @covers Symfony\Component\DependencyInjection\Container::getServiceIds */ public function testGetServiceIds() { $sc = new Container(); $sc->set('foo', $obj = new \stdClass()); $sc->set('bar', $obj = new \stdClass()); $this->assertEquals(array('service_container', 'foo', 'bar'), $sc->getServiceIds(), '->getServiceIds() returns all defined service ids'); $sc = new ProjectServiceContainer(); $this->assertEquals(array('scoped', 'scoped_foo', 'inactive', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'service_container'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods'); } /** * @covers Symfony\Component\DependencyInjection\Container::set */ public function testSet() { $sc = new Container(); $sc->set('foo', $foo = new \stdClass()); $this->assertEquals($foo, $sc->get('foo'), '->set() sets a service'); } /** * @covers Symfony\Component\DependencyInjection\Container::set */ public function testSetWithNullResetTheService() { $sc = new Container(); $sc->set('foo', null); $this->assertFalse($sc->has('foo')); } /** * @expectedException \InvalidArgumentException */ public function testSetDoesNotAllowPrototypeScope() { $c = new Container(); $c->set('foo', new \stdClass(), 'prototype'); } /** * @expectedException \RuntimeException */ public function testSetDoesNotAllowInactiveScope() { $c = new Container(); $c->addScope(new Scope('foo')); $c->set('foo', new \stdClass(), 'foo'); } public function testSetAlsoSetsScopedService() { $c = new Container(); $c->addScope(new Scope('foo')); $c->enterScope('foo'); $c->set('foo', $foo = new \stdClass(), 'foo'); $services = $this->getField($c, 'scopedServices'); $this->assertTrue(isset($services['foo']['foo'])); $this->assertSame($foo, $services['foo']['foo']); } /** * @covers Symfony\Component\DependencyInjection\Container::get */ public function testGet() { $sc = new ProjectServiceContainer(); $sc->set('foo', $foo = new \stdClass()); $this->assertEquals($foo, $sc->get('foo'), '->get() returns the service for the given id'); $this->assertEquals($sc->__bar, $sc->get('bar'), '->get() returns the service for the given id'); $this->assertEquals($sc->__foo_bar, $sc->get('foo_bar'), '->get() returns the service if a get*Method() is defined'); $this->assertEquals($sc->__foo_baz, $sc->get('foo.baz'), '->get() returns the service if a get*Method() is defined'); $this->assertEquals($sc->__foo_baz, $sc->get('foo\\baz'), '->get() returns the service if a get*Method() is defined'); $sc->set('bar', $bar = new \stdClass()); $this->assertEquals($bar, $sc->get('bar'), '->get() prefers to return a service defined with set() than one defined with a getXXXMethod()'); try { $sc->get(''); $this->fail('->get() throws a \InvalidArgumentException exception if the service is empty'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws a ServiceNotFoundException exception if the service is empty'); } $this->assertNull($sc->get('', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } public function testGetThrowServiceNotFoundException() { $sc = new ProjectServiceContainer(); $sc->set('foo', $foo = new \stdClass()); $sc->set('bar', $foo = new \stdClass()); $sc->set('baz', $foo = new \stdClass()); try { $sc->get('foo1'); $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist'); $this->assertEquals('You have requested a non-existent service "foo1". Did you mean this: "foo"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException with some advices'); } try { $sc->get('bag'); $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist'); $this->assertEquals('You have requested a non-existent service "bag". Did you mean one of these: "bar", "baz"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException with some advices'); } } public function testGetCircularReference() { $sc = new ProjectServiceContainer(); try { $sc->get('circular'); $this->fail('->get() throws a ServiceCircularReferenceException if it contains circular reference'); } catch (\Exception $e) { $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException', $e, '->get() throws a ServiceCircularReferenceException if it contains circular reference'); $this->assertStringStartsWith('Circular reference detected for service "circular"', $e->getMessage(), '->get() throws a \LogicException if it contains circular reference'); } } /** * @covers Symfony\Component\DependencyInjection\Container::get */ public function testGetReturnsNullOnInactiveScope() { $sc = new ProjectServiceContainer(); $this->assertNull($sc->get('inactive', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } /** * @covers Symfony\Component\DependencyInjection\Container::has */ public function testHas() { $sc = new ProjectServiceContainer(); $sc->set('foo', new \stdClass()); $this->assertFalse($sc->has('foo1'), '->has() returns false if the service does not exist'); $this->assertTrue($sc->has('foo'), '->has() returns true if the service exists'); $this->assertTrue($sc->has('bar'), '->has() returns true if a get*Method() is defined'); $this->assertTrue($sc->has('foo_bar'), '->has() returns true if a get*Method() is defined'); $this->assertTrue($sc->has('foo.baz'), '->has() returns true if a get*Method() is defined'); $this->assertTrue($sc->has('foo\\baz'), '->has() returns true if a get*Method() is defined'); } /** * @covers Symfony\Component\DependencyInjection\Container::initialized */ public function testInitialized() { $sc = new ProjectServiceContainer(); $sc->set('foo', new \stdClass()); $this->assertTrue($sc->initialized('foo'), '->initialized() returns true if service is loaded'); $this->assertFalse($sc->initialized('foo1'), '->initialized() returns false if service is not loaded'); $this->assertFalse($sc->initialized('bar'), '->initialized() returns false if a service is defined, but not currently loaded'); } public function testEnterLeaveCurrentScope() { $container = new ProjectServiceContainer(); $container->addScope(new Scope('foo')); $container->enterScope('foo'); $scoped1 = $container->get('scoped'); $scopedFoo1 = $container->get('scoped_foo'); $container->enterScope('foo'); $scoped2 = $container->get('scoped'); $scoped3 = $container->get('scoped'); $scopedFoo2 = $container->get('scoped_foo'); $container->leaveScope('foo'); $scoped4 = $container->get('scoped'); $scopedFoo3 = $container->get('scoped_foo'); $this->assertNotSame($scoped1, $scoped2); $this->assertSame($scoped2, $scoped3); $this->assertSame($scoped1, $scoped4); $this->assertNotSame($scopedFoo1, $scopedFoo2); $this->assertSame($scopedFoo1, $scopedFoo3); } public function testEnterLeaveScopeWithChildScopes() { $container = new Container(); $container->addScope(new Scope('foo')); $container->addScope(new Scope('bar', 'foo')); $this->assertFalse($container->isScopeActive('foo')); $container->enterScope('foo'); $container->enterScope('bar'); $this->assertTrue($container->isScopeActive('foo')); $this->assertFalse($container->has('a')); $a = new \stdClass(); $container->set('a', $a, 'bar'); $services = $this->getField($container, 'scopedServices'); $this->assertTrue(isset($services['bar']['a'])); $this->assertSame($a, $services['bar']['a']); $this->assertTrue($container->has('a')); $container->leaveScope('foo'); $services = $this->getField($container, 'scopedServices'); $this->assertFalse(isset($services['bar'])); $this->assertFalse($container->isScopeActive('foo')); $this->assertFalse($container->has('a')); } public function testEnterScopeRecursivelyWithInactiveChildScopes() { $container = new Container(); $container->addScope(new Scope('foo')); $container->addScope(new Scope('bar', 'foo')); $this->assertFalse($container->isScopeActive('foo')); $container->enterScope('foo'); $this->assertTrue($container->isScopeActive('foo')); $this->assertFalse($container->isScopeActive('bar')); $this->assertFalse($container->has('a')); $a = new \stdClass(); $container->set('a', $a, 'foo'); $services = $this->getField($container, 'scopedServices'); $this->assertTrue(isset($services['foo']['a'])); $this->assertSame($a, $services['foo']['a']); $this->assertTrue($container->has('a')); $container->enterScope('foo'); $services = $this->getField($container, 'scopedServices'); $this->assertFalse(isset($services['a'])); $this->assertTrue($container->isScopeActive('foo')); $this->assertFalse($container->isScopeActive('bar')); $this->assertFalse($container->has('a')); } public function testLeaveScopeNotActive() { $container = new Container(); $container->addScope(new Scope('foo')); try { $container->leaveScope('foo'); $this->fail('->leaveScope() throws a \LogicException if the scope is not active yet'); } catch (\Exception $e) { $this->assertInstanceOf('\LogicException', $e, '->leaveScope() throws a \LogicException if the scope is not active yet'); $this->assertEquals('The scope "foo" is not active.', $e->getMessage(), '->leaveScope() throws a \LogicException if the scope is not active yet'); } try { $container->leaveScope('bar'); $this->fail('->leaveScope() throws a \LogicException if the scope does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('\LogicException', $e, '->leaveScope() throws a \LogicException if the scope does not exist'); $this->assertEquals('The scope "bar" is not active.', $e->getMessage(), '->leaveScope() throws a \LogicException if the scope does not exist'); } } /** * @expectedException \InvalidArgumentException * @dataProvider getBuiltInScopes */ public function testAddScopeDoesNotAllowBuiltInScopes($scope) { $container = new Container(); $container->addScope(new Scope($scope)); } /** * @expectedException \InvalidArgumentException */ public function testAddScopeDoesNotAllowExistingScope() { $container = new Container(); $container->addScope(new Scope('foo')); $container->addScope(new Scope('foo')); } /** * @expectedException \InvalidArgumentException * @dataProvider getInvalidParentScopes */ public function testAddScopeDoesNotAllowInvalidParentScope($scope) { $c = new Container(); $c->addScope(new Scope('foo', $scope)); } public function testAddScope() { $c = new Container(); $c->addScope(new Scope('foo')); $c->addScope(new Scope('bar', 'foo')); $this->assertSame(array('foo' => 'container', 'bar' => 'foo'), $this->getField($c, 'scopes')); $this->assertSame(array('foo' => array('bar'), 'bar' => array()), $this->getField($c, 'scopeChildren')); } public function testHasScope() { $c = new Container(); $this->assertFalse($c->hasScope('foo')); $c->addScope(new Scope('foo')); $this->assertTrue($c->hasScope('foo')); } public function testIsScopeActive() { $c = new Container(); $this->assertFalse($c->isScopeActive('foo')); $c->addScope(new Scope('foo')); $this->assertFalse($c->isScopeActive('foo')); $c->enterScope('foo'); $this->assertTrue($c->isScopeActive('foo')); $c->leaveScope('foo'); $this->assertFalse($c->isScopeActive('foo')); } public function testGetThrowsException() { $c = new ProjectServiceContainer(); try { $c->get('throw_exception'); $this->fail(); } catch (\Exception $e) { $this->assertEquals('Something went terribly wrong!', $e->getMessage()); } try { $c->get('throw_exception'); $this->fail(); } catch (\Exception $e) { $this->assertEquals('Something went terribly wrong!', $e->getMessage()); } } public function testGetThrowsExceptionOnServiceConfiguration() { $c = new ProjectServiceContainer(); try { $c->get('throws_exception_on_service_configuration'); $this->fail('The container can not contain invalid service!'); } catch (\Exception $e) { $this->assertEquals('Something was terribly wrong while trying to configure the service!', $e->getMessage()); } $this->assertFalse($c->initialized('throws_exception_on_service_configuration')); try { $c->get('throws_exception_on_service_configuration'); $this->fail('The container can not contain invalid service!'); } catch (\Exception $e) { $this->assertEquals('Something was terribly wrong while trying to configure the service!', $e->getMessage()); } $this->assertFalse($c->initialized('throws_exception_on_service_configuration')); } public function getInvalidParentScopes() { return array( array(ContainerInterface::SCOPE_PROTOTYPE), array('bar'), ); } public function getBuiltInScopes() { return array( array(ContainerInterface::SCOPE_CONTAINER), array(ContainerInterface::SCOPE_PROTOTYPE), ); } protected function getField($obj, $field) { $reflection = new \ReflectionProperty($obj, $field); $reflection->setAccessible(true); return $reflection->getValue($obj); } public function testAlias() { $c = new ProjectServiceContainer(); $this->assertTrue($c->has('alias')); $this->assertSame($c->get('alias'), $c->get('bar')); } } class ProjectServiceContainer extends Container { public $__bar, $__foo_bar, $__foo_baz; public function __construct() { parent::__construct(); $this->__bar = new \stdClass(); $this->__foo_bar = new \stdClass(); $this->__foo_baz = new \stdClass(); $this->aliases = array('alias' => 'bar'); } protected function getScopedService() { if (!isset($this->scopedServices['foo'])) { throw new \RuntimeException('Invalid call'); } return $this->services['scoped'] = $this->scopedServices['foo']['scoped'] = new \stdClass(); } protected function getScopedFooService() { if (!isset($this->scopedServices['foo'])) { throw new \RuntimeException('invalid call'); } return $this->services['scoped_foo'] = $this->scopedServices['foo']['scoped_foo'] = new \stdClass(); } protected function getInactiveService() { throw new InactiveScopeException('request', 'request'); } protected function getBarService() { return $this->__bar; } protected function getFooBarService() { return $this->__foo_bar; } protected function getFoo_BazService() { return $this->__foo_baz; } protected function getCircularService() { return $this->get('circular'); } protected function getThrowExceptionService() { throw new \Exception('Something went terribly wrong!'); } protected function getThrowsExceptionOnServiceConfigurationService() { $this->services['throws_exception_on_service_configuration'] = $instance = new \stdClass(); throw new \Exception('Something was terribly wrong while trying to configure the service!'); } } PK!`= `test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Tests\Extension; class ExtensionTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider getResolvedEnabledFixtures */ public function testIsConfigEnabledReturnsTheResolvedValue($enabled) { $pb = $this->getMockBuilder('Symfony\Component\DependencyInjection\ParameterBag\ParameterBag') ->setMethods(array('resolveValue')) ->getMock() ; $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder') ->setMethods(array('getParameterBag')) ->getMock() ; $pb->expects($this->once()) ->method('resolveValue') ->with($this->equalTo($enabled)) ->will($this->returnValue($enabled)) ; $container->expects($this->once()) ->method('getParameterBag') ->will($this->returnValue($pb)) ; $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension') ->setMethods(array()) ->getMockForAbstractClass() ; $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled'); $r->setAccessible(true); $r->invoke($extension, $container, array('enabled' => $enabled)); } public function getResolvedEnabledFixtures() { return array( array(true), array(false) ); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException * @expectedExceptionMessage The config array has no 'enabled' key. */ public function testIsConfigEnabledOnNonEnableableConfig() { $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder') ->getMock() ; $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension') ->setMethods(array()) ->getMockForAbstractClass() ; $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled'); $r->setAccessible(true); $r->invoke($extension, $container, array()); } } PK!uuOtest/DependencyInjection/Symfony/Component/DependencyInjection/phpunit.xml.distnu[ ./Tests/ ./ ./Resources ./Tests ./vendor PK!jdata/Base/design/design.txtnu[Base ==== Purpose ------- This is the base package of the eZ publish components, offering the basic support that all Components need. In the first version this will be the autoload support. PK!u+SS"data/Base/design/class_diagram.pngnu[PNG  IHDR|bKGD IDATxy|MWd4s S|%Um5I[EiiS\T!⪡U&14*1D( R "|srN"C~>^{>k >{-0 DDDDDDDDD$#_(Y&""""""""re"""""""""w(Y&""""""""re"""""""""w(Y&""""""""re"""""""""w(Y&""""""""re"""""""""w(Y&""""""""rݻ;G"""<@ 0Ƚ@n+VDDDDDbdeh0DӫW/{!"""""Y&""""""""r,Akh2) %DȃXDDDDD(,Ck<شFY&""""""""re"""""""""w(Y&""""""""re"`Hʕiڴ)ӦM#==ޡ}F2ի޽#FвeKRSSG,?-0,>\x+WRvmɓG, gggz!tŋXhe"RdgΜԭ[WWWիY?5Ųr[nTV <==5jׯ_/T< .\:iѢUTɉU+uV%&&TT ___>#^jΛ<0 {!r988F``cɿ۷Ӿ}{]fu͍UV`Qn+]ҥ-[p!onݲO}vʖ-k~^ܹ͛Ӹqc:d.ONNUVڼHڷoo.ۻw/mڴ!995c׮]ck Frr2#11 RSSٲe 5|GE7  Xg`3aÆy$::prr2cĈFiƫju޽{ WE9pORQFYaƾ}%&&QLr7770Z]gF͚5e5ob),,Zc|ث'D֮] !Cl۷/6lȵ$zIff&ڵcʔ)7mA0 N:U `߾}[>}0HKK(S/y{{cϟ7ǼHpw"2-Dg\ߟӧOҥKqtt8qxgX*++k׮qaf͚Exx8޽ Z]Iٳgw6=z4}!::hvM6tЁb_&""""""%C2)4[_MDD˗orVuL]+WQT)*U?xxx0eFŚ5k/_ѣ9ydݻ7+VdҤI~,X dÆ ԯ_(Hk"Rh(^js~. 888d5jgYq1b[l1ӣGNΜ9Chh(AAA4h'N0tP1fDDDDDDd)Y&"Ν; t]zz:=z 55>;Zz7n0mrΜ9$$$0aرmYYY6۪[.}!$$GuVsΛ<%D^z%v)33|DDX>ҹsgƎg?<!!!Vppp^zѢEzh5^u׫W ;o""""""R,B4h+VdǎKٳtl€xqrrbk"##5k?8-!>+goyfz^3,2339y$1#Gw1[.p;oq-y76m˗_nݺqFRRR$..@d77ۺ888fNd̙3Y|9aꫯҠA4ibDDDDDD%D!d~Wm۶[[(d`ZZƍk׮йsgƎˊ+(]t'""""""5Drg,ZsDze1cF_us%za.ٳ'.]bvLDDDDDDSL%''g+дiSڷo׭ӪU+siӦjQL06mرcƘ1c3fǨQ,DIjj*3f̠cǎ4k֌:_aўXZnMppE4h>,mڴaʔ)j"lYlO=իW7רQÜ|MNN.EDDDDDH.L;v@<<ի3zh6mdڌ 9|… ̙3)U27矓l<0`IIIj*3f *iIMMߪÆ ҥ=]DDDDDDr'D"b]ѢE^d qƄ{n"""hҤ {!22*c䖇Wfǎe˖Ua 2;v裏Zc*3RL. )3fqy'=z47o6ٻw/5bݺu||lnݺѣG퍳3>>>0Rxꩧ $66z}ѣG~<۸q#'OA8::R~}Ə`j'kUȑ#[. k׮wJZA|Qv"0zYk"ԩS:uxĉL8sU'x¢'_5 6v 0}9qm ;;<ݻws!ׯo}kΞ= @ǎm?~U)I *e.\8v,Ș\~z/'Sؗe"XďԩSIHHN:lOOO޽E=S2(gRɾė_;88X\4e/5V,ELL ߟƍ`yaܹy^_fMN>́xg\k.BCC\2899QNN>>,]{똞2g;rn|\,ew*i#<3g1ꈈ}2<%YoyfΞ=kѤnݺeZ"**>>#Gk?ѣG߿|vl&bLcLL Ɍ?2e0a?~<={?d/_ʕ+s:w;~-{f֭~cȑԬY*ȑ#t| ÇVZ8::@r %00wwwPZbT~窤dڵL2l߾ݪ۷S\9^|{q""hX͙3֬YCZ;vԉзo_;G W^rC,|MjԨAXX,,, www8EDDDDD~,J.㉌… \pHƏ;=ˠA6mZ_DDDDDDK2{(00Pk㉈JܡdZL+Vl0DVXaDDDDDO@2;֬YÚ5kؑe"aADDDDDDDJݻww"RL"""<,:֭#Қe"""""R,#,,@{!"N^.]G沞={tRϟϠA8991}t{!o;|QL%''3w\6o˗Z*[+W΢?+8rTZVZ1h ʔ)cwef͚ŶmHKKu֌=ȱgTBBBظq#;UV_o߾X{ٲe3v,K,4nܘѣGə3gǏSNDEEeGêzYa&Rڥ<,EΧNԩS'Ndĉ'LJ>O>$?`ذa$$$Xcso9Mql@pY\;|qW\&TGDHSLDDTJcYYYVeSN%!!:uвeK<=={L 4DIgNٟspp0aTGDDDDDD~dH.bbb4nܘ os5kri83$]ta޼yܸqޡHnaÆ4mڔ OeLŲeh۶m1ETc,"""zL$EIl޼gdqnݺeZ"**>ΖGߟ^{~GҿvLL޽{uV_͎;pnnnԭ[^x޽{[<mRy˯_~#GX>Mdʕ+yWy&Czz֚[Ç77 bcƌ֭[m6=ʲe|W7++[wyTovs!>>~IHH`ժU<_~iqͤIHIIGl޼GOxx8^^^;w?EoxNJӧOn:~g-i#zgٿp.g,͚5#22#G~zڶmKzz:Cʕ+w"""+%DDggѳgO{#"Kre Ę1cՕ'|ɓ'ӻwoYdI߿ӧЯ_?:vh>NFF 'Nv899SO_fzzzZ|~a2dS>777\\\hҤ }p{L_'''xg9s&`gq[v;vӧЧObsȐ!4hЀrCjܶG&w5jԈ 퍳3^^^|s|mP <<}G}"k""""-[̯ꫯs]D?99Cr-Zh#,رڍ=XwV4 8y?cԮ]ݝӧO믿O?;?UEַo_ڴiSl}>Ve-цIa]vѢ~sNl8LEDD;(%DDDD8~8M6ͳӧs=7fΝ;k8s >h˙h?~ŋI׮]Yz/±caQoРA9~vߟ6mкukcrruuF<tڕ͛[/jVv-ц-w?$In+'J慩|r֮]Kٲe;w.+V P/s*U*Tjժٳ:uźgk׮7Kҥ ˗g̙/\`^nݺ,Z:uEMgWqRmdW{]rl/_QyyP)Y&rG^GAED.]ׯssB!?ĉqpp?+>RRRHMM-pwӯ_?fϞͮ]e 6 /Lڵ\2^^^6f׶m[ڶm˯Ν;!&&SNqY&Nܹsc*VIYqdP{gصkP]cǽ}gH| $,,a䋒e"h ㉍e˖ƍ1l0^x<8|0ǎ׷8¶az֬Ysn}ì,Jf͚tڕ]yfg+EIqtEw 6f۷o 4k 2<)" J-[$>>YfZ7vZyZlIhh|ʔ)9rvuMra"""eǎ_VZy.`iN:Y>t-Z|u ;oEQ}tՆaX% syꩧppp0ݺu9s5ǽ}i 3kdн{w{ "$EkxbG޽>|8 6d|Z GGGnfӦM,^ 2m4Ą-zbɒ%\jժѻwoʖ-ˁ裏^׭[_dƌ5k̙3L2wyʕ+sI+sr իK3gC aܸqʉ'2e SF*> :jL2~zڶmKVV΅w0l0yԩCbb"SLaԬY3_?ފ,#,,@{!"5cz!sN:wlUg„ 4j|lJP9r{,׶M׫W &3{lfϞmQ'$88fvW_305B w}ӧ9x 5k`lڴǏ[$Lz!Feq\y+賠.67nݻ2dĉw}ᇼ{|ߘ3ge˖s,xy]x5j;"C8jժ}ݺu'''ʗ/ϳ>… gϞ-pݺucҥlْ *쌧'Ḻ-j׮M?>'O8ߣGMFFpqq\r4oޜaÆ4kʕ+ʕ+8p ^^^與}ᆪVZtފCqYqGSNE)SGGGN sΌ3ɉ5jЫW/֮]wVJ͏#+WiӦL6t{Z 0f~<ό3݋yY _T''''*W̓O>9uT n[XXYYYoqk{|@RR͓)nɝU/I"1=Yfg-uu҅LO`at,"%ӓӧӱcGqHHAAAvh ?O?4[l(z\vԉo|\q}/>1o<^{b^sάX%Vq4lؐ]vQb+sgb@ХK3/{9sdw營_'+{={=@%"""R@aX|222x"+Wvٳ7n87ni&<<olڴ:oڵkjr0 n޼Ʌ ={6e˖e|W5OƑ Zj9r';T)%D!..ڂqvn̜9#F0|pf̘ٙz.]xb-Zd . ׯ纳֭[IIIy ~m3իWM6DFF2rH `ܸq5`fΜ ܹsU9::RfMX|9~SL$rKd{!&&۷)7n]vݝ5kҹsgƎKZZZ#"""RΜ9C[y^zqaZ)bbb֭ժUOOOF 3< Υ3}tZhA*Uprrjժ+lݺf{八+*Uח>WڼfbJnɲغO2e >>>?+WZ+HG׮]l߂~/&NXϜ9/e˖CGӦMۛ$r/7z7pwwٙ~/﫢FaksεMnj31cF&t=z0ٓK2| dDDDDi߾=׮]3]xpV^ͪU Sҥ-.\[oŭ[e'OO?eÆ l߾=_;f~K%''ӪU+bcc-/_LTT֭#22ۛݻ6mڐl. 66X,X]x衇2oZL2]k׮͍֭[:o(U o߾DFFׂ*~Kz7on]AEQ 2_[?7QQQ67Wck׮?~CpAQ:o=Y&RLLpҺukRSS1c;vYftЁ/: .]bر<u ֭[s)222b|7++?+W);XOۛ~Tٵk͚50 >ck Frr2#11 RSSٲe 5|GE7WWWZnMbb"8y$-[uもoG&[a笠}YJA8L gCagbb""))>,_߸qDoX|HZZ*Gƍ߿_|1ױ]a~dH.Ld && РA~$''9pB~W" :b{WҧO{IKKcL6W8[A^~=[Ojj*6l(XEDDD뫯ҥK=?///hڴ)w%))Yfή]1bsƍ̞=zs=ҥKNGGGUFn8|ƍݻI&ٳH-~N:,\hfΜEQ8NQw>jՎTGDDDĞL!C<߷o_<їDϞ=̤]vL2Ml.Ca:u}(?}4acuXeJ/b>a?\VfJ}w㼒ev2}J2)S{'rMZwU{Q8[l빼)S-Z0o<6nh:S1;'''쿨,.kb>޸q#'Of͚DԩQQQt @ѣ7mڔ#G2rbWQ,nѣ6WE{2-g f׿N>K.x' _Wk׮]̚5pٽ{ep{]xݻ;lwӇh 6mСCڷoosiq̛l߾dʗ/ORR;v+kw *%% *ܓ~=777j׮O?M>}x,^&NSr77k ?`Z s}^%!!___6 (6o%Dr騩S2uTĉ8q"ūٳgر~L?=6[/(Jʕ+/_ުTGDDDĞ/]z_5/_oʕ+[1vY\zGRT)S5jk֬1[|9GɓjwTXI&_X` ,ӓ 6P~}fo6nHΝ̼v2==3QS$ {/gnk@j %66:wO?]cMQbZT~I~AdH1[1? ٷvtt$33'aι %VMc-U-rSEDrRlY]իWXbMHHw%KШQ\HNNnF)Sزe,<<ܼpyÆ ֭գjժ<4hf[??ٳg駟駟8v'N`С濗2oٙek׮sZ87) ~ȩ0^YB/^L-سgƍO>XLOQ&%%)L2\Kiܸ1 , ::~Νv9s ~]iWG%66bCYupp0 RRR̿I⎳*UpE~+d#"7|_|a%4i!ܹؕ_~9ץӣGRSS0aBOxzzrh޼yqm%:X̙À,e%/++/7֭K>}ӧp{ :=PygB [0X~=e˖JտIQnnݺeIߒ-y <3fΝ;[$.ލQFDGGk.;5?3-/.o?1c8rn|lۮ];&Mľ}$..I&Ykz ͚5qI(8[A~G8sU;2S{z饗̴:hܹՎz9~ :em/zh_ξV?sWV6w8/ċ/ȅ ҥKnWW<+lr"_9+c۷/r-nݝ,}]gX'p-Mf3saFXXX&#F0|}}uakVu}}} ___dK.?͛779b{ O>V㏭Vv\8jǖPWZe .g…f͚|%.aaaFr_WΝ;'N0N8atG{>}`"+ȿ7Ν3*VhF6mݻwiii͛...~5|?qs1߸x񢑒b~5c͛7'N&M2\\\ Xd4.^hdffqqq믿nqϜ9cfԨQ`<Ɔ ׯ7o4:dknݺirWHH7cw/_+V7o4nܸQ9>ݼy_Hm۶`8;;۶mW~808,YbͽKRRnFv7n0nݺߊ>700 >00mp%֬YCڵyz*QQQT^ݢiC[ _v-[p%ʖ-V;񤧧3o<֭[_5kƇ~H6m,OKK/`ƍǸq̏̚匫̫C~NII_Ga޼y׏Dt Lݙt0XtBff&ӧO`ذac)L> '!!!9)7QQQt5קXKh>c߾}w#{f ͚5c͸ k߾}-~7oYwܸq,[DV\I.]?5mԼK_Njbǎt޲+<\pZjΜ9Cݺu󼦰?-̜enʕ+ŋv/l%5LV{QRqw-Z`Ԯ]GZ^e׮]\zEoKqŴZXXLed ɩ?9sš5k;?N:1`k,(Y&bJcǎ駟qF.^H2ex1b+Wܜr}vLBtt4ԯ_^z1bJ¸NӦMy7ͯfeh"ONBB< :W^yŋo /qF5III||7:u7oR^=jժi޲+yY]SO>پ};7nܠF/*UAmۖ`z!u oI(?^1Tr IDATDǡC!33q1a„{>g2i$;~w~aƍGϞ=^2?%liiitޝ{#G0uT~'""",~s*JIn,%DDAKi7Ly.]?e""ӧ `xIsAqOĈ܍e"@eРA\:u*111DDDW}'$$g}a >zѰa{<ؔ,y@Kk""F(ә1cm۶5{ /?\OHw""""ݻӽ{w{!f\B@@, +Wf;F&""""=Y&"""r|2K.eRV-:vH-,ꥤb vիW\2< ݺuئޔ6m .رc8;;ӬY3^uSWYYYX;wDݺuyiӦE[ٿ0=~xM~ElmܹBTT7oNժU&**:PlقRLDDD>ѣk.;{,3g$++VZʸq8wڵk9t&Mzp\~7nqF à"##3339vǎ#--5 B*UJdܶرt4ibuI&:t;w^DDD%Dٻr|çĆ|g1rmfÚ9-a Y s K2>u]u])ۭ~_wz{_kHY!DQ]m߾wbooϴihР/DFF*A;vpu6mvvv\tUVq5mưa궱aʔ)4jԈH"##ߔ`/7*İ~z0`,2mImmmYx15k,qj?N^{{{˄B/ ;!Sҕ;kkk{=%ĉiٲ% ._~%FlJ 22*MMM䧟~tܙ}ҷo_?`e|2P ,JuLUF!B,BT[? d988S*W^^rlѬYDٲe o6D7iDrE;nmݻ5'ꘪB!>$X&PZWtDOG_Eը>m8;;Ӷm[~wϹs c׮] >\ef+mhq^]sw1ς9B17 _ R !ԅJAQ5jԈ[nq5%ߖ6VVVܸqgҶm[ٳg,UuԡgϞٓK.qQoΆ JZj瓕y5r[듖FFFW;tMV)!6mZ]Л˄wyGr QHLTy:w&003fPn]BBBqƬ\N:q 6m\tбcG۞:u*L0ݻӬY3nݺhJ'%%E/9c߾}曤)},͸ݼysҸyFP͛J!B}IL!xL}6mڨ}~W˵ݏ?ݻ8px6nXք?+?͛DFFZCe:t(-[:sB!aeeŌ3J,WNƍǸq-+*_Yq5O055e„ L0[[۵jբDFFPٳ 2SSbB!(Ls !]2rb'$$(dz}v^u>|5'̋}:|06mɉL>S4#++y1x`ݝs)|aaa]cvҒT`τBQ2!tж???UXjUXXzu4i§~ʰa*K ZbxyyqyvY2l0ټy3ywχZj-镞)SL᫯b8p>  Kߔjբe˖?B.MQIII=KKK~'W=G$//777RRRCO{=&6D2!H^^֭ݝ.]н{wƎuwLVZ+]taYǏ+e ?8::j}ѦYfܻwO}4i=zɉ7ߐV?d''' W^+VЫW/VXapiii̟?^zѥK<==ٳgqsQfMƌ@LLrhǏW^J ԩ 8::FFFA}BQz[fذa5 Ebb"3f >>{VZnoСCŖUmbggeϚ*m'|̙3Yj'Nn Q2!tP9<#FYflݺӧO3fZlIhhRח`sNNNԩS<|PyPy1&M"))I)B@@O׷ط_%r 5R]rn",,_iiiJ/2|>>ddd(Lo^gϞ=xxx!D 3*ӿ>)=`swˎ;ܹb`l۶ݻ,?<eEӆJڐjժL!DU#3˄(AdGFFK3∉alٲE)i&xW ~#<<ώ;/P}hr-Z@.]s7o`>|#Gw۰aiiinݚHbbbxڮ!!!ٱj* j3$$ׯcccC@@qqq2aÆ_%J888hUSB!0dVZ56lȴi]=zzv>|XEpa`jju IMM%00{&D&3˄(x!!!$''ӣGݻ%K`ccb.\ȠAbРAzM9ǏW>Đϙ3gؽ{7.\J94O>DIsΜ9̙3Gk;>>>bnnի1777(vСsUT,nCAxx8;v`̘1TVM.Unaۢ:MRԃ?~<ʱ[nJ||<  $X&D۷/NNNl߾D֬YæM2e%T8PMYW%7e8s ޞ6mhS$#F 22l֭[m/RjժIJ$aTu)xvvAnnnEwC!/SN1w\RSSNK퍽=W^eɒ%JZAP2m\]]լY3.\K/?8p@ lܸ7n`kkŋiٲ%Nb%֭i׮;vLmǏڵk888(Rʳb,ҥKٲe`Ypp04i҄E@RRŋi^}7m˄$9˄!!!??? ?YBBV f=~077jA$Ռ;wա׮]Sr=8Crr T6lH׮] oaɒ%ԯ_+WPQȑ#ŋ]V (oɥKꫯXhZ̙3|Wmrty.\`ڵ\p&MЯ_?Co% nիA1R} !-///*B_>|~oooo߿{W_Ϫyyy1rSUZӇos}͹>N:jρESu蛚(ՒvکWUJϒ6Dғ`0$XŒ%KXt)K.U;WAg̘1믜 so\}+(˗ <Per%ܹr\WZWsN ʊjT>|/TP0d?|^]ҌݝoСCپ};Fબ*5+III۷ 63XfccÕ+W8qߕ'NPfFq-ݻB҆Q< Qy ~b˫KbnnG}G}Tl}ҷo_&W[.K,zhWek[m&Clذ쳔,,,Ԏ{tktQvmF?7nܠI&@'N0qD-IL啖yyy\~]yЦMjöm %%Ec%!f,Y_|A۶m9w_~eז&-GӦMԩСvvvO]wQf)Gd-ZD֭IJJR fł $X&Pݻw'33ٳgӷo_ԩիWrWT///~'BBB5kPZcB!.啖RUԬYSm=zɊ+Xbڌ0Cyzzo>Ν;_~JGҦ >>e˖hVں 75ϵk7nڹMjӇ d7L!DRXt)zsμ;$$$РA޺<ժU cRRRHIIaǎ,\BQ+Wh=J@@ӧOgȑxyy1k,"""UP,[e˖]&u QUE0UZ WWWׯO5hٲ9#F###͕Ig ͜9&M`ddTbJ5j`iiI^i߾r?dԫWccc7o^1~~~ < `ll̛oɜ9sJ֐֣G5j_EÆ ٳg];ϧUVcll=cƌ?y]ݺu dȐ!XYYaddÇ'((HIo~affFll9I"D嗔PPj aĈZ?g'//0v˗y1/]ta„ XYYUtKʱcǀ7ÇBCC9rg 77WYZPs-[Վ_r :KKK-ZDÆ i`(o|fΜ7ZzzEaooR͐LMJJ F6&n:ٶmZڐA1qD&LP=/#G+q}ddBU^#FT@eU5$((,ڶm'撜LPP/_&44S[٬Z}bii @>}Xr%>>>2V"rZ QI!JGa !Bh1d RL>͛cdd ̘1ǏWdl۶tM\\\BuU9-$m#3˄B!JݻpqMI~]xcvv6[n%..t4ho;ZgUΝ;ܽ{uZ9z(?3/_ѣG4hЀN:1|pLMMV1<|(^}UeY(nܦM8p k6 5kM6i)DձcG&O7|)Sl@!2!Beee1|O˗@Ya999|\tI9vm"##ps̡z'{xx… ݻ7:tEԨ\XXjؽ{7>Tpjc>LvvZrps)9"I(yHK!*7%a$X&EDDBT-ٵk'VVVL6 ;;;Ο?ʕ+IOOW+sN.]D-xwiڴ)7oϏSNqzMxxl.>}`ff͛پ};۷of͚+tܙ޽{+aꉊ`„ уjժq.\lRZ}`ggq2,B!De%2!k۶mGE!^`=N||<-[uL4%K 򍩖RSL> 66V 4ggg9yI]> IDAT$III={ӧO?3o*:CǠ򰩎iOBTu<)EDDTy,:zw*'BҒeYjܸ18wrܹse---y&WHJJbϞ= 6Lj[Ii/ׯ+}`mmMNNIII)hGĉt҅ׯvZWk CIKK͛A1U`yOq\uFn*B!ʐ˄B! Կ:č73gNe OΙ|677޽{L>KKKV^MΝquueǎDGGц %/u\|k֐1tЁ.^H֭^x;{τJeBgĈTt7"2!B-Ufjj… %!!Llmm0`ԬYS)kffƢEغu+ܹs333:t(M6Uʎ;PQ{zzkg.]_M4 LMMgرrq=zңG8< ,N:.?Vh?ח-[СCiٲ%۷> Qv0aΘqMhժUbî]7nvҒTpB!'2!#sȑ#XYYӵkWիǟIdd$|駬_^mʦh(==+Vƍl|8V`τƍvvvPzu,--ӧ˖-SZnͰa $00Çk$B?XkLM'|Bll,<~'Ob _}c~<~7oɰa8yd9N|Kw^֭ӦMBތ ؿ?w‚^z{QNXUk7YϏ3gbmmiРT!׮]ݝ&M}v222 SNj^7n#aaa5J* C߿Σ,=bFJJZQPxFӣG|2=zO?H_Ռ2YQuHL2vZ%Wʭ[ |@A dܸqܸqC)Ç54S]t]6Ǐ/qԩS:u*o-K~~>|iFǏ4iIIIʱ8}4jA#Z .fggʼn'شi 3]222֭]v% _~}*ebbbc?3Zx;;;Ϟ={лB!Э,9+K3j333֬YÚ5kXvmdbbBVX|9^^^?;wR瀮7o&00ɓ'W`Da S2yffϞÇ9r}J7r lmmٰaqqqq: ){4iL U#&&ٳgeZHNׯ{Ȉw}WMHJJW_%44~pڷoO||<;vШСC\8͛lڴI)Lrr2M4! 8ŋ= ?('$$( iWΎÇ_0rH4ʩeoP0A>1U!B4ϟO^ҥ ٳGkLVZ+]taYǏ+ebW}w5ᅬ [ LJS˲e޽;zbݺuܻwooouFϞ=Y``=?[nՋ瓖_CuE&OLnݻ7_}YYYc}(I͚53f gO{YVs_|{ٙs璙uɂ ӧNNN 6(/yyy[wwwtB;vz_ij'3˄(/!??3gΰ{n.\E̒С}ӧOWאFFF>W^孷vZx1'''Ϫ/vکU7o>u1]UpKӓ-[3Gɓ't҅5 OOOКLuLUFQTTofEwC! ذxb8us%55UlYsU,Y̪4hZ3KE@RRSf}wi6oLffݺu,]-[uV7n̆ Ә9[ ЩS'Μ9ܹsJӯf͚pB^z% JE{o~hذ!r4^A}ŋiٲ%Nbc-7l@ZZ[fXXX|r~Gt KU&ҥKٲe,we* Q_f}-[3g`kk?iӦFnUp P-۶m[_Α#Gt3vXڴi?FFFG߾}qrr_e$&&f6mĔ)S-9ˋ гgOHAfhžf*n`M ÃPN>,U-mm̪c6Sy|PB< Ymfy;w.ӦMS+_Yv5BifϞ=-Z0b֭[ǣGVf5 ???evPr5ʬYhڴ)#G$ +KsK6l؀ZHrڴjՊQFĒ%Kر2UښWsNeGz./m1nCVʔG?0/2U˄(cqqqӇdeH(XRذaCf,Y_|A۶m9w_~F]ҥ :t3SҥKLMM9<}Gk׮z*innnܸqٳgB-$#Uѷ\qƏ޽{q~~~̜9S9׳gO3gf͢E_lڴ7$U/YhZԩS,Y~)ez-ZD֭IJJ⫯givժU#??k׮)o i8?Ov_rW^֭[\zU#(z`7BbÆ / ///?o YRtƼYޥU_XYFP). dbb>W~>+{\RuqJy(qfUMY_߅!}wZ$X&DѣQQQ̟?_g쌧'ܹs{~)A C,]K.iM۳gO-ZT_ˋ%KtR.]V[P}VZ,X'2 l̘1믜C6l,Һuks5ƍViӦjJ; ;ܹӠvK2zh""" [׮]9x Oj梾9!'NKEwEԟ-.]"11Ν;+5ʖfV}a]PV Q <ʊ!+eʣ^z?\x֭[}}gZ$X&{'Kll,OsVӐP &<<_~˗/SZ5P{zqSF Õexyy)[$:t`Ȑ!lٲo___ԩC@@ׯ*>N4_~Y.,XѣG~&LPUn]_s5w޼jKAK;ƙ3gzjnݺlAmH%]s׏+VѣRNxRL!YTTTEwx7t_}2̙3 Um{iW#wCj}fBI.ty.\`ڵ\p&MVVǸ Y)Swڕ0,YBYr%?jΐDVvT-K_(sZj0b󩴻UU|4k֌[j_nl۶Mƍ 4'2a„gȑ#iE?JpL5TeB/{{{/_ߠYҕQio{bԨQ\rE5jԠe˖J³UG5FFF+3 L9s&M4H[0}tڴikצwެYZ 7}Ȑ!XYYaddÇW H%uF5bѬ[Nj!X_~ӬY3 ͛e><ƭZ)3x`4h1o(ˣFH߾}[.5kt ݝӪU+166ޞ1c+뇙S}ae$3^L/̲o([lƍu&=vӧOWr;\R|r,TeW\Q/,55]vHZZ5jॗ^SN[j;WPќuB}Xr%>>>K?ug .jժ… >}*eǎ\R+Y&BŐ!C2dHEw0}t7o&&&8880c ?^]Tm6rζm*gBT^f⣏>SSSW5(˵UdfB!򈈈ȑ#ܾ}5jдiSzI޽fgguVHOOAxxx([ʩ~^zܹswRn]r%sQ~g._̣GhР:ubᘚ{>cx!QQQ4lP9naaA6mbԮ]۠-z2ӻe5 r+?Y&BaPnJJJ dggsy;vڥ?g۷dҥؖ .$$$3gΐkP7|lڷoQOȑ#]!YeBȑ#9B/x{{ꫯKLL ׯ'::sN.]D-xwiڴ)7oϏSNqzMxxl.>}`ff͛پ};۷of͚+tܙ޽{+tգe8azAjոp .رc^4R7,B!(o,!xOVxxx8dffO?qu:wL߾}۷Zٸ8 ߘǔ)SX3$''sI8{,Of޼yj &??dbccz*O 33ض ˗ѨGuLUF!`B!F͚5kHLL$11-[oӿLLLr)))NE]v͠v찳cРAm6""" ?yݻwINN8_l޽{Zs񼉈.!D;SЛ˄@l!DS?Х,c]"`W IDAT۶mٿ?Ν#,,]v1|peaIK5zhYṉ5kFDD@rr27SN/G{cVP(1U!7<) _!!!#UXhhT:uٳ'={ҥK=z۷a%Xfii͛7Yz5aggGRR{aذao޼ hN -^sss_ FFFZ5d '-- ׯv.##C)#DvB˄B! 4uTRSS0aݻwYfܺu 5xչsgmƿ/ƏOf͸>vbǎiӆ 3III̤O>X[[CRRAAAJ;*Q9q]t]V9իZCмysҸyFPLk޼~!*CrʊBTzݺucڴi HL!@ Ϗ׳~zs[V+sy>Sr&&&xyy)͹wӧOҒիWӹsg\]]ٱcDGGkOO뉉___:._L^k:t@BB/^T/^cǎ:Uѵkת\.!x"""ݻ Q;wW^yT:::P]*9z(NNNCQ)Sr>}022"::ZYظqc:v숛ŘEuVsfff8880tP6m;v,^cϞ=\t ###4i...[رc⣏>%͢ReB}ٳg‚=z0ydݹ /T|FF~~~߿;w`aaA^xSN3Z}pV^ʢW^x{{km;,,N:)r Ǐ#aaa5uBTz[fذaʋÇk$B?]i=233={6GQ;~INS֯_k{|*`l۶`ُ?{g7h@IAZI?(Ja QF6o ٳ9|0G 66֠ 9%$$(INNI&?666\x urcٸq#7n֖ 6.\h888hSSB!xTt"66 iذ!FFF0uT&Mē'OXfMEwկ_?j׮ÇIKKZ&==LMMۗETV2Lbz)zӧЬY35o\B!ċ&--+Wr!gJz/S333g޽ܾ} z-&L1δ;w`ԨQj1 :t(jJ)=T=zvE52d&M޽{|PfMwάY]fҥݻcccuƴiӰx~ɓ'111O>̘1Cm>X:u.Oxx8;wdر]vgâbAEWt%QQKKK![\[ " qc#l ++1(vQTl(Z(wof|[9s}98PNUm6mi֬i&>Lrr2XZZ2d"M:2A(#=bܹ$$$S(eR4ݱM6J۶m {\M_˟  ߓ'O~IۤcAA%L(66.]zLj՘4iҶYz5AAA[lA*) %&&___LLLJܮS*o>Xp!P>.LuN@@!!!888ٕ]^^^uֱsNyNNƒ1cԶ}vM8yJOC$$$ƽ{*I5jĒ%K_>[nLJ09ikZfaҒ6mpE~whܹs-Z ]M4Gu&/׮]5999޽{ G?kE˄ ePF"""vJO^rssGGGBAFF<\ann۷SN9)fi4lؐ7oD(..N:up}RSSS>S a„ ӧ!wy5;myKѮ];ܘ5kGsssU@dɒ% :PI~zzz|R뇭%IBӦMۛ/^*7n6m<_ٺuk.\W_}EXX\WI쌅cƌLJ4yI2 3|p.^RbiTYI5vXUVٳgqMz聝R=G?4-Lӻwon޼fZZԮ]'O~Nrr2*HA;w2=z`|rZlI||߿ORRJP,))I>F}G PTڵS9Ν; Sҥ)K.)MMpmѮ 5`\]e.ѣر//BG?4-LԨQwwwL"\\\)۷/}U)f͚8;;\d{4=WVKTV {{{nݻw夲w%&&S#PΝ^Ԯz'@>}qVb4oޜ9]F~={d,\ggg6mJJJ ڵ kkki=:wLv툎3gҹsgTµk駟K.JyJV\)Gll4h6})uBbaaA]FvTɖE ݻwqqqa4mڔ?P VPyH"DL 3a<̌cVrAx[uڕ]Vv3A 5f~n߾C:88pq.]J*̝;W]ʕ;l08pL>7nRGϞ=Y| &p1ܹt %ejj-[dԨQ.mXS] ÉbjE&L;*y^Ys.]8qqqq*u4-Be9A0,YINN&$$%KPTAM.GؘM61x`jժ>͚5Xʟwz`oozzz#ę?> 4@OOONP;wdٴjՊURZ5>6l/fRJ#GR^=W_|۷o/2HIyyyѵkWWǏ[?ʣ] =zPNRRR055gϞҮaÆxb7o!XZZҥK =<_~TZSNiZʦ(.K ttt^B^-_Tr?cƌ]ABE~$''3h ߩR oooonҴ :S2yJnPVƌYRO<}4?cY4FxtڕYfUv3Jfoo/  {dffB߾}^:IIIxzzжmJn Ex]z;w ,o@"##+  Z8p *X^ر##FԮ][e%Ax[4-UQ[Jf)  _СCܺulׯOΝXAAPn0E3MQ&ޯ    Y&TvA(#  IAIyDLСCߨ (yA ׵kW1KAA`P*߯f#FG2AAAJ6\ZWW>9s&UT֕j:6oތ3O>-:AAMs7*W Beϯw>XV.\`ݺu8991|֮]KLLLe7KAA#e000~ >]vsJn T?gΜ233Y`ϟ?& YhvvvannΰapssHAAAK,KJJbʔ)XXX`ddcƌ!>>^:::tyF{g!ٳSN$''~{ԩS}}}֭˧~ՖȴiӰȈZjѾ}{.]JJJssѫW/]6&** {QmcmmvȈ͛?ЬY3qnl۶2zhy_|Çٶm[%LAvUmwڂ?]tޞVBKVէ:vH>}prrx0`yyyEǠA&::LDE_͛ǼyĊB`٩Shݺ57o?:Ӿ}{BCC.X;v`cc=zDNN7oӓݻu.\yJҥ ԩSaժU*#?~̲eO͍L8::Bjj*/,\P򨿸UF FşoT޽;+ڪ֖L>OA_q)7Ο?Ç8p u!uϢm۶ddd(ݟÇ" aʭ-T5)HPa~ꊗVVVTR6oٳIMMeEŋprr^͋/5j7nqЭ[7v GN==={=Fݻwqqq/T:GZtΝtcccԩ߬`իWceeC:\VP K.TZ?͛7pY^ٱc=e˖qI>s|||T):uJȆ}}}?ߟH裏"$$uxyyG&MXvV+(M֦ӧO?ܻw__RۨQ#8s *}k.޽KÆ ٱclڴI)WkrƌCժUپ}RR[n9s-ZC&# Byy2|*5o]]]4h WK~VgΜQ;^==y$UTPF IDATO?-T&D,Ϝ9Sɓ'9"55/\ǪUK#0f̘r5 [nivB˗߾}BvhwvÆ 8p ~~~VZP({,MJe[ǎF $(j4 V… 9t'o&M`ll,b?~,?r4k ===4i’%KXj[~zLLLꗗ/__J\\\֭[#JROz}-tuuUVЮ];ʣ~MW͚5ڵkr;==/RZ5QF*hܸ1  =zŋի;wfر>|XmM꾻j"77@m>bmR<|777zInpww';;w{tt4zbڴi%j69"}KMMUW\MS駟Bgҷo_jԨU֧yyyx{{3l0:wLݙ8q7u2==O?>3TkD *~ )Yǩ!2e oʊݻw_JئMWp a^^iiidz~z%22R%w͛7|2QQQDFF ĉ s5lؐO>Agahh(_ʶjժ0RP޽{|ԬYP{)՞?u>l>}{ァyCv%jFwizYr---K}+ߺukڶmRVyԯ;v,{e۶mrY^|IΝ@'O/CIۤcAAx=edd0yd@W\UX)EDqqq[]]D( gff&t^-$JLL wÇ@HH*AM)egguH uS999KFFFy={ƤIyMʽ얩SǬ,G^^P$QQQ>|X*%Ua2MG+vܖ-[F+ݤKtKKZ֖Fj*\\\"{U@QY&+VW&?ؾ};۷oҒÇӤIV*Uhu{Iڮ?(Nq9?Ѷn{{{[)&n6`\F*`S^kzLMM>|8q))RX.T+eȑATf͢k׮ AЊ'X-Z>T:6WWW,--IJJ]N1tPΟ?_wWfzzz*)h4^y 6dŊ4k֌]_4iZvO!366VN\YO;wV9FJbffٳgaaa*2)EIHHHMNQ"͞M6\x]FGGsZhA˖-T t]kkkrrr Ã{,۹s'7oޤA,_-ZϢE~:۷oW֨Q#,YBٺu+>>>2MS`PZ6 S6i#M/!!ٳg:ݼ<=ߟѣGsM7o΢Eغu+\vв>s~wёf͚p ̙JoBŪ_>~QIH 8|UJ&ZҺ͛''?yғ#zQJ V1Hӡ .rlyԯ7nݻgϢK.]KuCmp o@+P)m%:AЖ6<{ Һuk9EJ%I)===ڶmUiԫ.免Jp,;V!tiYXj_?ƍG||<&&&L4IүH4IQ'yHʴI>FӧOjJԽ۴i#,,,8q"'N^/4hGJoBҥ {ݝZj?@Æ +JϞ=پ}; .ٙM/voo=fBCC~:7ndڵEŋ$&&qFiР+Q{%+Wd4oޜXyҖ[aYl[ի*זW\{!CBA6mU>$%%Œcw8#i7]0%%IQiYZZӧO'))qV!S^LQDvj0zzzҾ}{KsK"$E @޽9viiiѣG^w钼_ 9sXt)DDDqF/rƒ4`$I~ť3)HRaʕ+ӧtFŀҥKREٳ'111lݺU%X?5j$'׆4G;t˸qT?ƍD\\JuKoAGGBQh0]3qD9¥KϔƮ ?ΥK;vҾ*U0wRխ+&M"<</|64OOOڴWbjjҶ-[2jԨR[crQ^*WA:jy֯?~ 6m6}fϞM5`֬Y*7EΝ;޽e˖aׯ_g|ԭ[+Wɮ]?~,˾ <<<1bȈ+W4߿TVQWNzz:AAA :^:>>>lٲ0>|(8m4'T%u|q"GHbffFΝ7n<$xyy)gJ[CCC6mڵk9z(|,\_ԯ8^/@ݕ׏5kp)ƏԩST^>}hF!r o;Lx4lؐ7npEyz/kffFRR(v0m4oޜqƱ}vi߾Ҋ۸qc^JttҀXcrҤ5Ѧ 6͛*T"\tIa%aÆGpp0F"88@%pUVѣر//Beܾ}:u$o+I{ԩIMMUU!Re‚e 4;;;=Eay) .]Td~)Z޴iS6lɓYjdQҹsg\\\ԖIyJ 2e 7ndƍJ.Z={ȹs簰^W&!!}ѠA)mUsqF!o+ܼea7uMLL7o+]]]UVZiD«ak֬)rjժ74A5^rF?$ժUޞ[r]4hԩSUV-ҨmZD}ƍZJNQr?ڥQwܑG2i$9ݻwٴi0_zիWYb˗/M6\r+VYvm|8xxx+j69*&)J$tA^ڵkkNbY2dwŅҴiS@y$XA=z˗/e˖~)HRa2'GTZ;2ƍZHӦMYjdffҤIƌFFFedd666L0Ai.edd?@BBFFFtؑ9s駟ҴiSƏm711!<<OOOu9994nܘ!C`{R[EٶmӧOԩSxR!oL?͛S&Laff2uTx7fJLcƌ_~΄&E6lfff8pȲo:u* >\դMG͟۹M6rEңGXfU]zMiNmRsTMR7|pXz5_R)E&L;*Luyw1ܹ> m)HRቦ5k֭[s٤paOSPn ӧxB^vW]ruwV IƏυ "55#G駟nl f͚se233!11N%PV~4^7n̡Cx999*| Nׯ4k֌A=ؘ%KBrr2Ʉdɒ" Pq166fӦM 3s璞Η_~35"77H+Yt)6l(q?~CjridF⧟~~cʕ*]]]a͚5|GܸqoƎKbb"^Թ>G 2+WҴiSYp!9x}0`_5m۶ܹsL47nb y.TwE,N5~?cƌ)b7_Ax}(MTGΔ)S}6VVV޽===ׯ_! Eyyy֖H7or͛7|2QQQDFF\WWW&NHxx84lؐO>Agahh(_~Z*Ϟ=#==5kj))).ޡCUrگ.5.Je[jՀW2?m n fޤ@,9cAVlB@@5j 88ڵk3`6tuuUҨQ#VZJ{Օ7ojT5kdŊDGG}voߎ%W,I5k֌hܹ/Y2nIunbb%PhpFddd_JJ M[L߼sU>m?D_~4oޜ>}pu>իWr k;M  ""X0ժU#--F;$$$0{lttt-4WjHOOٳgZQ'''VZEXX-͛3b7nLݺuiѢ͚5S[Ν;w8z(O\v7n0gBBBפmӇh I9> WiDZZ45jBjj*!+-m B޴@'l}ו/Ϻ?~̙3ga֭jٲe >>>9sǏ\puYv|1TWnkkky$˜;w.}GGG|}}i A]䵨y7ob^N8VmnnNddk^^ԯ_TWf,Z;;;077gذan߿?*? }\tI~gϞjqqqиq_Z2@Hʟ5n8㽼?ָqcttt|9*JoVVV̜9,_֨(Hvv6ӧO/tD˗xzz0|p}:::@ZR(|ԛ66*ȻDݽfY{nMl_yr}xmennnAvv6=MɬYprrԩS}:FFFl۶ WWW]t!99=z IBCC5jW\{|g>}*#ҤuAAA撝]hӧOF1l0&>>aÆqqV̙3 -CS^AN#uGy›rvƍo^ۢTh rYիҥ 5ksN,X-[?QmQgK,)UGh@KʣG9}4ϟ?Ғ (d֭9rԭ[0ydyկO~ Qt̞={ҥKѻwo̙#_<6mÇINNKKK СCѣr[.=z`ƌTZU>ԩAAA9sFi4ũcǎjԔEeffǩR 端H>&==M6q1?~LݺuիSLQIZc֯_ω'x9z}~ٳ:P^=yᅬ5{aܸqrmA( 4;;;=60a>#e˖>oJ/8ٴiS6lɓYjVR:sθ-@ޘٙ)SqF6nܨtEسg;wN}7@߾}UhР׿~׶ 9x ,`ڵrzu={6J `ԩ*O}UoߞǏ+U*:o~~~1`GF m6*M~](RxTȲFH1kkktuu_%O>ͩS055e 4SSS077g̙L6/_aÆroOy &OLhh(iiiplMƎ;w999$''Ü9s4"SSʣRSSٷouֱeܹCNNƲbŊbݸq# ,<{\߿Ϟ={к:t@WWW%ӧѡcǎ*UJff&O<ߟgϞ1i$v̓ɓ̔MOOёRSS_~a…*dff^dkkKff&5Bi 8iذ!ԬY>}paOt7ё'N0`jժ!͛7g儅ij7f:t͛7+/ٱc}FFFлwo~g-[ƢEW9$&&&7вeKʊ .7!?W\kkkLLLӣVZt 777YfM2x5X[[O&Mprr"66V m߿?ժUC__oE?h ;v,fffcffppJr MT3^A(4Ȳ":tzR$<`Æ 9sgϞѸqcƏEQ'Rq)oԨQ( 7o]**ԍt???OYb-Z 66777>|t/|ᇸbiiIRRDEEСC iԨK,~lݺMPPk׮ښBCC`޽3кw 4 4bcc:u*NҺLLLh޼9 <~:u#R [YӧO ̌׳g];w͛4hЀ˗ӢE Yhׯ_g̘1]vq]6lȊ+h֬,^X3gТE }Ҷ3gΨЬYB(ӧ%[ntMc 餩3~xƍ6Y͚5qwwW:Ym +++#Ju֜;wNc7n̡C+[lɮ]4nOqׯ%6)}EYP#xyy?ȑ#6mxzzrI ޽;jgΜÃ#G`hhH׮]5ku-UO!5-mi_U!^`Ya$6i4I\\֭CWrOGu;x-[$(('OiɩS3 AZU|||g֭ˣU jԨIJ؛-~޴i'Q~^IJJm۶J۵kr;w͏?Hxx8>>>s=|}}Kծ4ԴLMﻴm&׼8s gϞ姟~j6}VŎ;Dr}&`YZuj2?hf͚'&WB899aaaAժUYp!ϟҨcccK@y-===@%+8Z@p1sBFFFS#JS4 1mՀ$J:BKb``Pd}СC,^6mڐņ 8p +իW@Æ ;v,~m}nӦ!22R~oSVWҼ~Km*6}}5Q7VڦIrsAA^_FOӧOJqqqiӦ+վxWWW5j<]AU|[[[ hݺ<*|X3gΜai0M|||8z(;v` TEc:88ʗ\  bdddPZZkLTӧ9tΖPkuɓ'tB ۹sg.^իWܹsʛB!w̜9%KKnn.1SL! @QSGP[!)hX95X;=Lc̓34˔kref͚űc3e)c%*DKdeЩ$Fjua~#F;wj^m21Obgyh (//ȑ#81ܹs+Whvca̘1h46l@YY{0fs-?XOݔF4AӍPZ~~>端vojr{y*o6kmJB{OeeeBB4ДN-g*m 'gi1׼v~2VBt*$]v7?>,[l!%%QFWQQUSäMV17S$4|ל>}Z놄{n y]v̚5K}@qq1~~~8;;Q"88(bbbyN;P^^^lٲH'=?~`κ( -5sNΞ=Pt],((;vp 5_ȑ#ņ FVVzQJ$' !e2f@sl;=x ղݰXaXɮ ݕ kh唘KrEn޼{gFQbС 4_233)--|̜9\ sʠ)*fJD@[[[uָhG*ّH@@X[[coo::g\]]֭[f???"##۷/666FHHK,s퍭-666#.^Ftܙ$ؿ?7o $$z^Ț5kHOOoԩSXYYرcu:*hO>ݻws:wSO=K/bnJS\\{ڵkՋ "##uFɲe_ԹD>|8eee̟?ooo8szdW_}EJJޛ!*007ZBqO3eG֭IOOWu֍'x`e>oAnn.o#44Tg2ei,Cs͆257ܹs)//';;;wлwo8u[Ψ2SJUb v_JDD۶mӹ+EsdU ?CQQGEhUVƍu_|}} #44k*G"|lIVVV^W\111lذs$''c(f̘7n˗/7x:T߳[GB4ӧ\7Q'XB Wn^0 Ym gjDo޼ytޝ[r)nݺE׮]:t(899Y.3x`Yt), iXB!$Jb=fԨQlذ^xPms̘1I&i&/_Nv횬AVOIgF469]tI&w?WF1~!h|}}e1AHX!WD1~!hƍǸq, ! U&ɼR4,!B!B!Y&'r!ĽҥK5os닓[lt 'NO>w]![B!D˄@NBܻ xu?C_'++"ۈjkűn:*++0a 8)B4bҢX~B\Me{]VV]7Xh8;;… Y~=MM!G!jmLD~^h9*++-݅F+'>>^}b VX!BIII\t^xA-8q"9III[wBܻBf_,-Ds"?B4cw_Xr%999\v={/2j(zdzsN\B.]x'y嗱S) iiiƒO۶my駙9suUQQA||<ѦM3f :://O:>>9sΪUth3T^}vii)iii 2'''ߏF!--I&ѱcG^!DG!Z/ݻ˗zǙ>}!Bh?@=/((( $$wwwRSSseHܹѣvSNɓj/ʁHLL}: իܼy/ """c͚5j۷os9׍ZxTgʜmȶm(++S9OOO8@ff&cǎ5OBB92Ϟ=+P'ot7BԠz2Nzj._L`Ϟ= 11QfN<+߿\\\(,,$99Y=z ##L]322gϞ=̟?u`yyyzcz"''7|]S999OJRG4d#uknLN|N8A>}tjmz}h{7שUVtԉ`2!ybɶ>h~c׮]L:gϚ| scܹ̙3+VpС]S;4 M6{hx뭷:… u.ȟ?Z #\G=P9s&m۶%77> &͛78e*cېb9ɔ2B!Y,.uO][ mjLJ{yyy8p/Gyׯ駟|7Xh8;;₟ .ƍ MʪA߯U]6mjmۛ[ɀy&+WdԨQ|F_STn{ IDAT!|oVoᔲB!Ľ.նa׮]̚5 ooo<==2e k׮UMԶә={6gϖpj,:CVpuuE'%%q%^xlĉ\t&h~򈏏b  @ܘv T% ^ٹ^CBBk֬!88bccu=ej{3 ܹ3zx6L#w#Knm !Ų81}tΝKvv6ܺu|-[Ƙ1cؽ{ww."[DFFO2tP4VVVƊ+aС=+WD!),,$<<zh VZCeL<7;6m^^^xxxϳtRLSS Eii)>=zX]V1/(++#22ÇMll,}1d~4 iii ZK'6lK.ŋܼyS$ **|'::'xnjFaÆ ѻwoQilvpp`ƍܸq'OS6Զu̙3zU곽S!ݚ^D@B-%մ)""}+°aԩ Y|/i^[^]kZwׯʹsԲǏ`nbڴi=zT-+**"11 n1VXXsM ***qqqYFm9‘#G~zob>ct.^HZZ%%%F g\vSrIkri߾5Fu9}4a{?>RSS)//g޼yl۶2<==ӓرcq&Oy^RfΝ={V=Rѽ{w2cELLނ֠Aԯ(..ggg6o\5`ٲe,[ 缾maÆEAAN?װ>B"2B"# ٻw/8::ѣqtt^{5MƝ;wXrkaRRR8w...$&&~uk׮ѣ ;;ۨ{c͚5 4i &PYYI߾}uw9~87oޤK.xyyR2ʢ]v >W^yE/m/\]FϞ=yull26mڄ3g4jkפI Ւմzy^^? TE',\ӧ߾};PHӫW//^/[l7ży޽;PuDobb"%%%۷ڵkpI߿kٳJ;֭[ )`^{5vIxx5Fj9gԩf 0IKKʕ+J e6d>Kǖ-[t7釋 QQQuԩS,kRӢr|||j7Fakkjo}jCquuN =taaa&7B JKKgΝ\r.]O/cggSK~~>m۶駟f̙jԕ1si̙3wwwVZSGe$ˌmkGbHt&`ޭbP5W> .++cƍ&%%E6 jB"##sG6؇>|A^~e@v+G)M?S$>I_+ڧ͜9%KKnn.1SL! vz˗/3k,; pu1ujU dڔ… zSGGGK/X_wI_ߴ)eJ!DW_}EJJx3AAAR4FPRZZZc`CC !jb2`۷oebbbXnU{ڂ pss̙3DEE|}}u>AP>5ѣGceeő#G 3i˙ĉ| 8cǎh"Ο?g}+bRWߟ~.]D1ƒJ^Xb[($"JTgjdUuSkÃݻw_raV\ڵkyWk}{=;Fn_> Ǐ7Nmj[kDD髡GS4 }fKfkkŋ1c&M`ӦM,_<-soѣ,ZHM_Q="G,^]@bb"vRˌ4OSՋ: kj[@BX|` ݶfmm͝;wfέbPY6d~a"""g׮]bmݻs"""jLP,Gx] ׭[7~'>̣>>|X3gΜa:IM^݂tQvի Ann.oڟLӺuZuti:c=+5jҹsg.^իWo+V/B<&<`ժUTVVsϩW۪fΜ7-//7i,{-| cڵ+`|2ٳg ٣sXl&[`WakkK||<>>>w}nwww5H 쌵5j'cskkkoϏH틍 666’%Kjm{ܹx{{ckk > ֺuꃱ1;vHRRǏ kkk8q":[9&#G}s&fggcgg3<B!D5i 6J ECW33Huuн:'&s !DM,` ݶ6tP w}GHHC]v|'2l0{͵쭷7ߤO>;OaHKKcҥDEEq}|r֭׿Ȗ-[(,,?fŊl2GGG"##uʊҥN=gfٵ^ooorCojz#f\Wfj;v$**`}eQP{C}0t?:ub޼yp51eL}ck{2TޡCHHH%ϟСC`%BعAc0G(..fƍ;"bbb}߆ږ9&_, &**?~BBBؽ{mMmk͛-g ? ,ˈ#x뭷tBmزe z PQ5߿?!!!:e}9N6'OשK/lښ 0uTÇ0`Æ #++8Ç퍝gΜw!DCW_.QLVB< ٹs'gϞKUQjEFF˖-cٲe]޷e$hݺ5qݺu'P*>SvťKС bڴi<j9sGqE-NYtN:;VCܹs)//';;;wлwo8u[ΤŲ PYYɮ]Rm6;wLRRqqq߿7oSO=Uc~a̪U9r$˖-#;;_|Ql2ΨQذa7 :EB4-/fƌL4 M6|r{ƍٸq!;7PW|'޽+Wйsgz)^zz0vNW<͐YfѪU+o΍7h4,ZHMc}j[@BXUHG-?ǪUHHH`ƍ:[|}} #44Ԥ)r)))[))))bGEEiiilݺSNq-vСC \{=h4L8=,9 \Ͽh Mb9°y}Y& 4Mw GGG̙c,ܛm۶ۗ>www~W6oln5Zx%,س#//O_]卩R籡MTwڵZW٪[LT !Bh05թnu)// OiWbbbؾ};666.]\xvɕ+Wҥ O>$/2vvvj ̤6mƘ1ctPiom`l3g9wdddLϞ=|uw6m aٳGͫUΪULz]~V\INN׮]gϞ⋌5JsWC?^N-wt֍~Ç裏̙֫3gؼymhΝ;sE^JΝuzZG!B,LTTVVr.] >v}]6o͛7)))a˖-L2εkט:u*9 \xTBCC)++S駟rYn߾MYYG&%%Ť5]Ell,1aΝ;7|SgϞ= >(y~:*}PLy] 櫯/YgT[CK{J)}7S < P^^Α#G֫;b*ǹsW\?D0m4AuPP~jS,uB!bf}[bb"'>>"n|3p@T7֨ꔭ!C0rH233楗^Wٿ?p֮]Yf 'OU\\\(,,$99Y+ؿ?{a[4ի999Ҿ}{zbO]v̚5KT=z4Æ @J)B!2!jU}k[ꧺiF=խ:SݱVOuزeKlmm#Ο?OOOڴi?LDDt Pvܩm߾=Po?yyyjcJ uk`N~`߾}@ÇӡCIkrZ{wve޽̝;ݻӾ}{"""_W6t 1ƾrje4e2-p}ѺukY=;;; kkk"99Y'*lΜ9bmmͭ[9r$۷';;[٩nB!&9˄05f5޽{@6mj/C`JӟĘ1c)))/ w_SPP̙3quuc(xK.ŋܼy{F&^N-w̛7ٳgӯ_?ڵkGVpvvϏu9 ,L9}4!!! an V\\l޼ko;vfJ GGG߿?&LPsNΞ=˔)Stv],88($MX )_d@F5EֺWS^ɓ'}vyuj~U6, ~&¦טI[jE@@ֆ!hS!B4Y& j;-)OuˠA?~>LhӦ nnn3___PVVFBB۷o_K.<쳄bccӏ}*--%--!Cֹh41i$:v8$B!,B˄BqWc͚5۷os9PcݺuiӦqQnQQGV5o۶2<==dff2v߻B!{6L!B222XbgϞ=̟?u֙\oڵ=zzT[8p `ӦMn}Ք[m۶у@{Fȑ#۷/}ۛx@Naa!8qǏm66JOO'779Ax5 ^ޔI۷oϵkHIIɓxyym߾(\\\ի/ח-[mv z\Ϟ=u!BC˄˽dee=ax7kʕ+䐓?Ltt^O?o`$..uQYYɄ pwwg3gdrss?fʔ)Ю];={ڟb9ɔ2B!h9dwZW )2335j}YSt[***t+**oڵk>nܸEXp!7nܰth4vUٺu+ 07orJF_|arZۻvZ[YYk)uB!D!eB@ԸunȜ9s8vXAII G)ϧ{IQIII\t^xA-8q".]"))ɂ=doo Y`JJJ537o[s\zU9L#B!ZY,Œ._Ldd$O>$C%((LleeeXѣYr%nRh) u~CMר^<.,,$<<zhVbXDG5R}{9<<vpp???ټy3Æ #++O4즅B!]G"˄0Ν; ߿x%ڵk9z(=|3p@8M Nh4 2#G5/RGdddÔ)Sصk^={{{ˉ'r Pe?=k֬ɓ㕐 $''u?3Ο?OnXz:?u[#_~zQʪG RY"GYu~~~DFFҷo_lll͍,Ybr=;;; kkk"99Y'*lΜ9bmmF9ۓlxgqDB!%Hdicc=z}1zhGeee ׀X`;wTv  hA3f\ה=qP(X]Ϟ=u!✏OW֧=gfٵ[Cquu:t05V!BX&(ky[w85M nWl+p}YD~moowG%))IgL)7DR9`re.\)[[Eu2tQRBܛꫯHIIa޼y@U$N!B2b,@նURq$Tg(}]YhDGG&6ԾүIi'6t @۶m|ibam -)U}Zf*d(?RV} 5 i,[[[/^̌34i6mbk½B!A˄0nݺO?qahÇuvv̙3l޼gggo߾L4dMHHHuCBBؽ{7z9oڵkǬY燳37oڶ~zƎ˟gj*##e˖l2HR._ؐ`vٳgՓ6ݻw) bǎ8q_~Y-9rB)c;l0(((ЋQִB!B|Y& j%>>>Zn;o&PMQaggGbb"8;;cmm=^^^$''D3͙3WWWk/mРA?;wfߟN:acc'-PԻwonǎIJJb899amm'N$99Yg < z5elGIֻNvv6vvvjĠB!B{Ue]ٰhHII! cs***bѸi&__4̪UHHH`ƍU'uFhh{(J``zC&ϻB!AlLNYY;;;Μ9û #} >Nnn.O!B2!x"//O﹃Ǻu먬d„ 3p@ T%PڮX<#Ba S!-FVV7nh"qvv???.\ȍ7B|}}4h!BXD %DKҒ";F0$%%q%^xlĉ|$%%n shtYK_Z B!EbB@@!T;TTTOff&EEEi777ƌNݲ2ؾ};+]tg%44?(--%--!Cֹh41i$:vw-B!v S!ǧ~ٳg}6eee9r~ޭ[6mW… ܾ}"9s&m6{ӓ2233~iU*ʊ۷oGGG"##r /:t`JJJƍL<:ȤI(**?׮]c}EuJQ ֵ*1D JԈK԰bd7j(2TTh쉱E F1H(" :yy̹r{iҤ &&&@zzzYy뭷Vua„ <~X>jCNr{ܹhWN׮]Yn]B!x2!BTV\ݻEuVeM8{,m۶e4mڔ+W`bccٵk "..NrHZj-221yd?hҤ W/3sqƍs~6mĉ:uZj3==^zi}=p.i%W^ܹsG9ڵkyyKyAtt4<|ӧ{B񲑙eB'''%@%96777,X78Z]L2իWsE}.^ի2e eCianL>ӧNB#˃9 ><<{A\\vR:t `ooM4aݻqΟ?kvvvZ}D˙3gx ~)'NȈsΑƼyؽ{{a߾}<}H|2K,w%KG.]8}4OtޝJUfqd-Z/F@@jZyI߿OիBQHLTFF7n ""ÇPݹsHT*z[JEddӧ d̙̘1+W_a !:u*&&&DGGl2 JY:vUܴyf%5޽ &MGT>V]v2uT gwԯ-Z`ff̙3۶zj~mqqqQFhPyf:t@*Uhݺ2CmӦMegIZr%͛7̌iӦ XXXtRIIIa„ j~B!^6,ŕz99∌dӦM8;;G}ē'O(S(;;ׯ_1ԓ'Oݙ3gswBLr+зo_ܹsi߾=^~c_a;>z55.E&(V^;vTΝ0mӦuj=o߾Zϻw1.\I&J/5k@bbbYڶm|meePhŋcff_ʂ HKK+8!e$2!y,K011e˖,[ {{{Cʚ3>uBBtҥc(RRR>|IJJN !ċ777ٸqR|ҥJkkk gYd^\\Qvmfffzۍt|*%~5I/,{qd,PDù~:*nݺ)K8򗿰v"C!xYHL2_ݟ/2qDwN>}Xpaf9UZ___;ZZZ+W͍]2`V^MFFtSN=ԩ׮]S40MAl(:w\,Y;ҥKs~)}Ņ9s®1[lSNԫWOioРNNNlٲTc!*qrrbѼys큜}z s3ܹ×_~ǏWj>knBN}&)zMGN<\o #44._*XjĉGq=)/ґdϏXy;vК1Q:t\j95Əφ qܼyJԩSΦq899qUg \~Ν;ӨQ#SN*1'N```7Y#ƌ͛uYYY$''رca=]v222ؿR`8\ƁHKKE<...qn95j-GtU]Ύ|||ҥ |ט*5ewBwww @nHJJ҉A믗`ܸqĐǕ䬧gǼxyyq)ř3gb``@޽,Kt_MbGcM IDAT``5kHMM}oО&BT,Add$G~(94D߿mڴgҶm[ˆ!<<:$7x` g74yxxh[ZZҲeKΟ?}6.\YfJ,mܸK.ѰaCT*'O$88.^믹~:5bÆ =rgϦM6TZ뜷py '9?>B6m"**(nɓuvd޽>ŋ"}o!&&9EѽJׯ7пVJÆ 9s&4cjԨATTSN֖*U`eeŠA*_Z1֗_~I&MR<#88LMM155m۶a?ΚweΝeseW!Q.Bhڴ򵥥%Px1޼n߾ /9 ݻ7QQQ5 @ }sk:Ѵi!^ML8ŋxb&MT?S8q={b 6mJ׮]Ybe6VHH(˟ k``GvFl߾޽{SfMeʔ)szjGGGe˔jGGGu?:33SvwwEӧ?=Վ?P5Qys߄x;P)~xyy癙}GTVTxlP9sFVէOV^{M_sj̙1bZV͛ZxPO2&''R~O%55իWrbBQ8I Q σfyټyN2JaiiIϞ=Y~=-ZꟻF{7oS UV^:!!! :zaddDzd ÃZjall[oE@@yssq?~ zY!(gϞq=޽˥Ktg>s-Z?L0???u5vX6m<,4n333 BDDn>#""͙2e iiiE䎯Vfz1c2ySSSΦSN2sL&O h[0agΜa߾}ܿH,--y7J={Sͱ ((Zͅ /<<͛7ӡCTB֭Y~=6mRZXXtRIIIa„ j~bBQ8ue000 44///iڵsN6l9h ;vlG(SXXL_MJJb N8Azz,~;GIDD?|߱c֮ЖZ;\bkk7>?f׮]l޼`ddDN7n֩7oޤFrOmee600Pw]j*uJJJpttT}}}߾}j@䤴i޿kPZ&%%)sotu[mee644TYfj@[(z-Z˗ Oll>Rj33RBC !*GGG&NŋYx1&M¨W\Yb\-={$::._Ǚ8q"u-iժzҢE HHH(8['==SN)KLݻ|mccØ1c ݻtڕ:u*~0uT^JZZ'O͛+߻ N"++dfΜ{V6m֬YCjj*۷}@N-BQ8Y)tÓ3tЊArн{ㅥU닧'[.k .A400>`ҤIT*eg8p 6mbȑ9RSNi՘5kd%%;DEEakk޼yEΝ;Q9K,Ѻ3qD&N7E'p2L!Ķmƶm*: !Ŷm۸zjEB/Q(DYFFXYYM`6j(j֬Ihh(kʕ 6jժajjJΝٺu+W^-N (u 4ɓ 65kbll#۶mӪZ~5j **SbkkK*UbРADGGӱcG888`jj)m۶ߟ 6B2!0EeUb꯲%cccn߾]ժUZ*V˯f͚lٲEkgliDFFТE e `ggo %WV--[Ʋe ;zhF]fBLeB!BJ!55Ǐ駟0cƌ H!HeB7;w0%$K B^~١C|}}+.!/-I  2CB '::gggA_ܹC^ꫯRE>!(>Cr> !xu>}@n݊ZfذaӡCMQ ׮]BT,),De_qh!>c<<|͛ aĉB!x$Y& 2Dj ̔dY9$ҢYt)~-UTaС?s1VJ=5kժUSΑFpp0?N:ocرČ3gڵܾ}+Vp /^?sq2xBMRR7o֖7vZ-Z=;vAlذ ;i&Ξ=K۶m={6M6ʕ+,XXvŠAjҤ *J ?iժ̙3c3^dd$Zҹ^M[dd$˄B!^!wBT?oo") ѣܹsHT*z[JEdd$w)xJJ̙31c+W$>>999i= ky+5>}ٳĄ#FC`122I&̟?{㣵\~ vQjU3gαNB!x52!^`%Ψ{.˗/g޽|׼666Đ*;;ׯϭ[=(ܳ\͕6m|ի=ŋu4*+WбcGvRw]54m>B! 3˄(}3-^$VVV̘1ÇILLjOHH 55.]<8J"RRR Ȅ(qqqZ!g>yV |ѣG:mgt.R9^5h!B!*/Y&D&((rMVJӦM8pN-ҖwY6WVV.sm<߲e K.%!!|MN3kK.DDDI(:w̮]tLMM%((ÇsԩC޽7nZ}ܹêU8z(O۷K.jevYTTj:zevk߾J#G0{lڴi]缲%_R,XXXR###,--ٳ'ׯ/-333pssf͚TR{{{>S@YqsuuܜǏyq,,,YmB! 5˄(#SNO>!::h֬YѣTW]`C&L+WV& %;w&$$( ULׯh8?wqЮ];}s(%ъniiә>}zƂMLΝvMԩSU\~ 9S!BT~2Lg}o>ΝKIOOg׏;v(ǖdWXZZ… .7~FFFV|]Np۷Ąh233Qfd&޼J\'DգGؾ};>$;;~O>П@/QFѠAX[[S؅B!Ef Q,--qss͍g߳a.]N-[2b֯_ς pttTfANGVceb+1>^kf||<}iԨ.]ԩSZYh-zVZ7633cL2#Fk.VX1!BQy2!Yiii4o{{{@{Vqvil,/,̘1chذ!#((HZjsNpfeHH@z KHH ++eWŴ~mS⧟~>9'D5k,ONV055kkk UO#'Nd,^I&{vB!dfedԨQ,X@﬇|}}9r䈲K[nywiUwkkkv]` fff̛7???my׀UDD˗/gZ3JK}s}FÇzӦFƍ|||9WWWDWqmn8z(III:ejllLPPԪU cccz-t+; !B!(-ua  Uf}.^ k׮%88;wj7h ;vlG(#,, oooe_MJ]! Nf !^YB!Bf%;W7B!/ IDATI !^iwd_| 4 99EQ^=fϞ])ͱ -- sY& h~۷oҠA~W^]ygׯ 8uo߾2(˜J$fllL:upvv -?ߊNtt4β+"dyڵ}̞=ɓ'sa&NX8y\t={၇VC`I&̟?Aw^eթS' e̘1$&&IΝK}=9NB!(>Y& ?ZӺukeH'NPUO?iU7`n|/oE8}4̜93frJ+4&~: ˭cǎܸq:u*&&&DGGl2 J"==]իWpssӚ I]xcjfs{5i$5kFbb"M4zJsݻw$Ӵi!Bd/Gj=oӦ PpL|oO}pBMofܹݛ]Z*;vL'\gQ7[n1o<|M>|8{'Jx{{o0h ?W^ɉ*clٲN:Q^=_ prrb˖-ފʯgϞ@NHHH`…%>qrrbѼys큜[^z9uΝ;dzgϸs_~%NNNZ?YU%0:tJ͛7ף/Ƣsx5m] Q!e&(#lܸQyIbb"<~XYfݼyJERRzԨQ ru]FF?u ݻsaN8 /_&-- jԨ,[3f .]RHNN&,,XT*Z1,]TKn˖-#446m0nܸ2 "==;vM@@?fر1Νc7?:t… {y޽˨Q}ŋ̝;gϞ1`|-{ҽ{wuJᆪo߾JMG8p4#7bcc9x .^oԨQ>|W2zh7nVs/XEh"}}}9r h355eڴiZjq]ݱ֙MZX=..Tϟ9~)UTaxzz2oBϟ׳gR_}y8&I9sLs){RF <<<ظq#QQQʙ3gV2 @N2/;;;>B@֬Y5kV}K憛[絴dL>~}՚YY|g|g:(ד_E9Zjxyyiذ!ki||<~~~B!BOf QFN ,[aÆRHOOꧩOԜrrrR-/^,p34ݻk<׼O?i9 '[ǎqDJ^aaa@N-{x M6U$rģwQQiE֪Uоy8澕fPY'>>>(Ex]vUwлLӦ#x5 bmmLU!B$˄(@ j۷/cܹoߞtV^M~رcrZ.p̼Ejٲ%;wle\Aɲ,.\ewy-Ye^^^VYvmcbg-ȩS{XY8$%%)Kr0Ĩ>vܼ͛y]v1|LMM+:.,--ϵEUСC$$$;h}e9m۶InݺqQtf$%%=F!"?s!DE2dH!2!ݩR \t YF3j(*u?R8~xef3Xjddd(7&gggTBVV,^:!!!|W9r;wPvm_-j׮.Y133#((@;ƣGhҤ >>>̝;7icmmM׮]1b/Q,yj׮MHH͛7K=of͚Ž{J}.}222zѧO&MkV&cB_d'eiΜ9:uJy~ڇ~ѣGj>c:\zW7߰pB^2uVj5Æ ޞ:h,!";;CLL ۶m~ܼC+dǾ}矉ȷyotqƕ3߿O||}G_ǯIE(eBOhh_!y<Њ5Rd3K.ѣGZ4I7N:)kfڵӵkWz{Ν;ubHKKcʕѵkW ի {''';Pxzz$r_~jժNMMe˖-tԉz)}4h[l!555ߘB<W\aܸq4nٳz+..!CPn]iڴ):U.]JOOgٲeуڵkSJԩC9r]pӬY3LLLY&|'ܿ_1Žow]/?E?{}*=+ پ}k2eB!(УG3f .]Rڒ #66JU(lܸQyIbb"ޝxH!b&iגnډЈ"֪[*- QDhBS""ZJREId7ϝdlzEs䙙3RRRԍW2228qޛ݄eʕXXPbW^y~|GziE{߾}Ү];cڵĉ߿6!#<<}i_vZ 6o]|O?Nj UǩShܸ^zrr2zqCܹÞ={ػw/W=/Э[7/s2228y$'O$ H}YxQՕU{n>swJ*tdq3g ‚ɓ'3vXBCC;]oIF- 4*/>>> x{{=qbŊ {zf͚ _@W^:2{l2@_ ]xQUWREXP4sMvEQUV)Yd(_~9Y.s,III1(5'E EV xw巺>|ό38rw%++#qs IDATG0}t>;ͩSXr%3gdŊDGGu(nܸ@_yn޼ivӧOrDFF3x`IOOw5x`... 0< ~zXԺ޽ @ iӴyB-mlS=>vXo3tPի-;O?EQ vEQ_9{^+WP-[`g^xx#,((H^BQϸio=[(~]YaURxy-~WLDXX rlll;v,]vgDFFf~G*Udg(uǎx)--yၝ̝;[āB-߸9a={M6>|;wriVZE`` SLQx):_0dF͛7駟?~1ScUԺAv5Ӧ ,iSjoVA]Ǐʕ+4lؐoKKK/Yr U_rrrHJJ"..͛7Ӯ];?n E;{,'NϹ˝3goDDD&кuF~۷ޮ1nNNNKLչ>ǎQF4lQ)JIIֶT-~W2Y&c,::={`kk^ڵkӧOڴiÐ!Cسge~znݺb:t(~-ׯ7͜xs՝MV~oLckknnnq6l؀:YfggիWٵkYk.6nHy饗3uשSD߿O:uݿ_#7'7|CHHիWgΝԪU K,,,Y&ڵ]v899h"fϞtpp0s۬'/GF|'jLׯ@@@ 4`ԯ_(iӇ%K??@VVV~]Үtpp(zK܆)rrrXf mۖN:[o ib h۶-cժUzMbsNFi2(uڵ>|8}A9>?Ctڕs|Vrr2˖-_M6___Us3nb*7YV\k;fqa^}4Q^2!̰rJ6nܨə3g8s )))j &N. G;ʕ+ޖui:ug{:tu}ڵ tCtt4&~mo$[18qi&LHOOg |Gjj*ڵ3hWv8qWW!רQ8x ׮]c̘1z [/fztk=Ç~AUJkժݻwqwwN{TX`6nܨw /;rG۷',,X!@&B rI~gz]2d|G۠A}lqY &ݝ2''gGGGz-z-Q ~=`֡Clmmٻw/o>UFΝ<*';;uЯ_Qha;vb """8r*88XH\\͚5c?~Zh' DEE_@8=ܺuѣGY|9coo͛7 ̳6n˗qppߟ'>>sرcǎS?L~Uq>>l۶MvӢݫW/VJxxAñGfBk& PBN3g$&&Fe???cTP]%~M#MzZ;@իG  6 ~mVbEzABB7o֭[tڕʕ+ykWjΘܹs9{, 6o߾EQǞB}=W<=Jp'JQod^Zqqqѻ_a˞l|Q^F tM9~DR%00P=ްaCP&M$&&*YYYJll2b\@zzٳ@iҤ~JffrW^ 4Hf_~~~ ԯ__իW{W^][*ÇL͛JhhҳgOP*U3Ǔ}B)؋vGGk߾}Jv+~~~JZZ^ytŠ>]}U4MK.)Fqss3(/%%E/o^kնm[E(Fk۶|999fc֭F^u=|Р?$e+Mjjҷo_O?U>S_~l߾]ͧ o~A=_y8g>qm~]+&.-{s/եVAQ{6kӌ/ kkk,X@hh( $$$ʂ RJY7O!>}͘1cxT5jԠG߿I&tR3f aaaݛ5kbeeEƍ9tP^*WLz2d{믿;>n86l@-\2tޝ|G̛7xJ֖>6m5+VaÆ:u '''z ;n٩k^z% t9_^{jժQbE59c+3Ю];,X@||< 0gnՏS{lmmqss͍88 UqUvڕo1cȞ={X~=;vaÆy.\&0vR ?Bޞ+W'::?):uꐘS r !F0yd.] )S  !x<8;;)fmV;v,/} #G2rHFa4U5ǧft~BcNc޽F3fE}̭!$f߿?...l۶T5jnJۛsΑ͝;w/qqqaĉj^ʨk׮i͛7_'55cDzyfOHLL$00qƑkF- ںpBbccԩS]^;7WWW|||!++-Z[AQ<իehtl !ӓe˖l2ZB!F2!0j(|||Xx1/;J`>|J*xyyתUwvM=|~ ___]Kt.ͭvڌ=Z/iӦ <8ߺs\vMR :۷',,XUyuB!B!DnL33|7nVVV4hЀѣGlll;;;,--ՕP3gKKK222t+++/^/;vf͚XXXPV-:uꄯ/K,1/:tbŊԭ[#Gf[WY~=o&uҒu2tP-qիUV%<<ܠplllѣGB!B!reBIg+?̘13f䙯gϞN:ѩSBF|X̶5j0k,f͚gyK/8VV OOOqܸqh&L@ժU,C!B!(,B<Fݻ R'낂3Uo֭zqB!d`mm͂ 6mcKhh(˗//B<{nB!O,B<14 'OfҥL2 B_qla.B!D&˄(L {yzzYou(Q:t(f!2!ۺu+ *QnʀʺB$f$i,B!ʹ Y)ʥ *uyB'L !B!(V3S$2!߰a/!`% [!#13%$$˔2!X>BwuK,ĉdffԩSM/߼y@"##ILLRJD !=)(iLV3B;w.'OT}vw%,,`W .0n8RRRԴ Ο?ٵk~~~ԭ[8u+W$88EQ>>ڲaƍGΝ4i!!!dddu;v &M6MG!e*fY֝;3--[)Dɒ2!)WC_RJ4oޜ9spAۡ]DHH7DEEQ?#>>>8;;ciiIY`{)P}={gӦML:bcc䯿*:ϟ?zBU!2֭[_ [&D0B7nмysW^y7o]$22իW3f<==Rڵk-'>>P6i҄&M0zh222`ݺu,Y>X{.јd4m!?dժU;vP^=FI>}6f-[%&&ʕ+ӽ{wO~\Xbajn:fΜ3k֬1I-q8xD&˄BPAP'''ٳ'mڴܹӧOj*2eKQǎ㣏>*~KN!2!Bx+&&,bbbXhhՖ ۶m#55F Ke.]GqΝ;Gvv6w/Ņ'yQ£*%K'##p{=z_|D.m6B<- 3=z{GGGV7QQQ|wj>sbvΚ5 GGG*WKJJR4Vg^U)6rB!4j(<ȵkoɵ [/fzZl>|J*xyyתUwvK.1M6ӦNپ}{ˆ @ll,PF! sbv6h@-:󢝜*)6L!FoЪ^:ׯ7ߤnݺXZZRn]J@@a̟?ƍcee 4`|j>KKKlmmquu% @̙3qppҒ 5}ڴi\WWW`aaL4M6QVbW^TZp~cccC=;!x徥=Pxy]m={w^ϟOIOOgժUdL*ӍW{ Jp,B!DjԨY5kVyM}1frI]̘13f䙯gϞ6mЦM|*:U'~~~ܸqJh&L`Z!D{g~:4md>{{{\Btt4[VӋS͍88 5+@~ PuNc;6ԩSD߿ooSpHV !BQFsagggpkBѾ}{.]Jbb"|gdbv4VXhWEqeB&˄B!J5 , 44 eM#x[ԩSK `ܸqjQFȍ73f mڴa̘1ܼy옝F`tԉm Nӯ_jYXo兇5jʊv1o<-q8eB!%OOϲnBgooO 0: X,LSuX[[3{lfϞo[p !+˄B!B)&L!B!cťD-[>miӦ1bBCCY|L !B!"_q8)-,B!ʹaÆ1lذnBQ`%q8@&˄BrL%U֭˺ B!(g$B}# IDAT!B!OV !؛oYMD@B!(V2Y&Bs2 ʫ *uyB'L !B!(V3S$eB!B!B?YY&Bbu-,Y‰'ӓSL/ ϟ_Twqq **9SrAWHHiFb !;r]BEQL,B!D;w.'OT}vw%,,챙2G^}8u+W$88EQ۷Tڵklj'ؿ?,~ !DyUؖiii>}ӧrJ^}Rhahڴ)M4~ѣtdǏ@KmI P S!yڸq#/_"""ޞxԼ?H"##Yz5cƌӓ*U]rҒl233Tt5_n 4Pokk }/)[֭c̙8;;f͚468K PQ2YVou3swwge݌}ANgϞiӆÇsNN>ͪU dʔ)"Y΃<^F ޽˭[ppp08MwrB emiӌO!T)));?CM;wɣm|roF/'Ɍ3F ~ %%%߲ Bhh(G6xޢQ貵|}}INNV' 37s7TL=%VXQMBr˫Pr ѴnZMήH憛qqq8p 6뫾Qիڵˬׯݻw=zq 6|lPN>u;P;]!dAAA'ФIΜ9ܹsu^^ݸs̡A\z5.vh6B?~|Ă xgߟC86mƍ |'8;;sϟo?ͯߓ'Or54iBӦM ]VWWtqq!33={xbMNMiҤ qqq̛7O:yBsAcdM&˞})&!DEU^1M6%..EбcG߿?7n`ӇFqu@EW.]ۛYfѨQ#ݻG`` 6mŅ5kVW)µkpttGDEEvZ,--yר]6w|7km^|EzիW 9sx饗G6mZe|zc ]UfNÇ׻=jժ|;wPNuƸq7pwwbŊH^x:vȨQ|6667p!nݺEjhٲ%'NԻ}r̙|W$&&< _c~.]Djj*6664k :uXW^|3rH6cccC=Bsbfh,>cQBRZ5vJÆ qww`LQMk1!w_*Vc{aoeeE~ d޽ <{o7e*,7TL=$BiҡF̚5YfSX_eƌ̘1#|={4z% bРA֕W{FU'~~~ܸqCݨƍDGG3a B${tOW_UO>mq!uQv>-)))¬`^˜>>|G˜? {naHV/\@˖-_~έ=s+TL !B|8z;oK105p@N8g}`4e*h|OcwT* &]!P 8h4LSN:ep\+4o_!wxzzu3ծ]%$$35e^ cmmٳ={v&fj.eiiɾ}WвÂ4v~At%(YY&X999$%%ŋ:t(iiieݬBscƌas%$11~coOq1c?< ;;g}LTҼ>m !lu mFRR999JW^y[(TF#((HMB,O+LwQQQ|ǜ>}իWꛔtm<<<~:>,cƌՕKKK_޽{Yv-flڴ KK2iﯿ ڵkҥ j|qOysaS/o+Bӧ۶m3VZzq( *#eUbEy^{5jժ';vxb&f͚iݺ5k֬1߾~L2=z0x`?NPP#G,feeЭ[7*TPfvB!0k,ٻw/;<쳴mۖcRnݲnx$#e7Xjaaaܾ}5kҶm[LBÆ )+*3gΰvZ"##INNΎ>}0uTo޼9n28Cؿ?/^$99իӢE ƏO֭ ιr | ǎ#!!*UH=z@_~0j׮ͪU L̬Y;w.e.]bܹs:uо}{LBz ӍƤ\2Zbʔ)xq5_*>>+V?3ӧO[nfǪ#G0i$._L۶m믁=rY\ҏG~-Oրysqqq]//|ۛd…@֬YٳgiԨ .䥗^‚8>N:ŪU>'0dƏYYY>}-7, wytw̙3WW\aҥOf߾}0(ߧsΌ;Mٳv+W%1IIIL>]m{g/^dѢEER;?W\a޽۫}z< (s 0sgZƞGOnSNi@ *(JA!0oΝ;L<ooo\2 >>>=d,ԩS|7No{͛7믿?OŊiժ_~%[4hӨQ#\\\:u*''NdȐ!zܹe˖hR VVVhтe˖p9sbccG NNNTX*UкukV\ O?Tqy& jƍҦMV^MFT5bմiӆi&ꫬ^F5[V'N}:tԉ{OcnE!66/ҨQ#5ȑ#&ynʕ+3#Fꫯbgg@F hθi4'>ѣG0aL0H>l2ޗ_~@5s8pd,--4iR^ꫯ<((טc]]kz=3>M6;v0\pӧOsi5Y[!&O̬Y8uNMk׎nݺѵkW*U7glllHJJ"%%ի|ML;999i'rrrjօ l[I~4σz||SRc+kMQg=gL<$y=BdPt|޽jժn:jԨa'55(ڊ*- lmmiٲ%-[իWgvZ5ݻYd ׯ_/Pz\R 𝐐wttdƍ yę3gt-Z(z8J&lllHKK3zrھjې[^`}xkJIVA5E=A%F(OvZjř3g/d΀֭TV$׶|PE`ٱ}xc(ܵ񐞞N.]Mq\N8}`ժUΝ;ȵkטN!JJIl#eBٳg9y$;w.y>dڴiE#.. .h222W.֭[srr ၇dܸqzr[߾}'((1c}myޛGGGbccSNDGGJ3QQQ9s;1y999@vY) ǣ4ZcLXlQQQl???5kƅ 0a?;5kawȑ#9pF"))m۶QV-/`tPkhݺ5k֬1Y_|y.\… ɲKre6lHPP-Z 22h E9?]t!##M61ydVX!e7`<==˺Brj%Q&˄sΜ={:ڽ{7;w_M_hΝW^L2%:ڴiC\\!!!e.\w888,ܔЏ5`}HOOW'f:uč76 㱶͛ӡC=ʿo++믱{ީS'bccYv-:tЛ믿}F-I={$** ???:t7ɧ( |smmmw111 h}#(J&x\鿹c\֘{=B<>pU^KKK*VܰaCŮ]兯/:t 22iӦ9[Ƿ~?OuhXB}… {z\}ڵf!:ubռzep}|}}9{, `ҤIL4ɬ1q3h ]&(1%6Yf\>|8իW_eќ>}7.̜9S=租~bӦM4nܘKzذ! IDATaXYYm6.]۷IKK#""wyx3~:_}/`ԨQq{{{ч۷oŋ9s:ynׯSNѣͅ tW3n .VZѻwo6m&== ._ӿoL78l0UFdd$&M">>L4iǏn%iȐ!<쳄3uT">>ɓ''9sÇ\v hV{yb۷l233M8?*L*ܿK!ŋ/SB*T~}>>>_"22M RGYcâ:ڇA`-ذD XP#FA%$.y,nh"#(h0 "H QD sEvܟ3ά[fgmcchol0uYNj/PB۷ԩSy9^B?dfP;|3'NеkW2_~%m///.]D:u ^[ɲRJ||Z4hȑ#^CYՋ.]δiOرcٱc7oٳQFq^5xwԺml3j(n޼ٳ> k/WK.eر8phoeeҥK{ݼTH`Ϟ=ٳG 2e>/ܺu^zi7w\Mft<< ɓ';vz,뮬W?Le7sS] !^۹i$S갲ʶeg)wVݛ?[MHHӦMc̛7g"!ċ?^>LPP.\ɓ'ԨQVZѥKɅzfVVV.]&Magׁ3//;5Q&MٳKWY&hт;vУGlmmhѢ4k֌uѯ_?ѣ7n>XbXZZRJ>sʊw};f͛u޽Yx1XYYammMӦMYz5&LPs_5jUV`(P+2l0vء3al)ؽ{7s͍ebaaFޣO>l߾]gLѺukoLٲe)Pe˖O>am6m6lȎ;OتUOǎvSԩS͛7ӦM/%gۤXLy,Z777 .L(W\a cmS֘RjT:;uС餤h:u*ΝQF\p/"uܼyt֑ͬ)%2;ͬdɒ <ǏΔ)Sx+"9 !!q1i$%99gҥK9~ }{.;}:*T`piȟUJ*\~+Vп4 [lo߾/^B333ԄYoJ ͖0a-[QFѴiS/?C`` zlg3'%%q /_NXXeʔ!00mUY<}=zЮ];5=ҥK9x 7o6O}_zD2!DUUT͛z/B!DfԨQSNмys$%%#<<<(Z(ׯҒuQhQ 8)SRQq 6l%,^… 7ĉiРo>ʊƍ$h=bŊhԁW-.{َ?Npp0666]N:accCcر9TVXᾕ4 5j`ҥ888p}oߞa\fݻO>ܻw5kKL2X&u?& 7od…@ BO9qǏG`nn 1W~} 6 ///uRJxyyqF w}Gʕ ))I+baaF [pFE2eh4S}lĈx{{D)X kӓu֙xBAbbb9s&ZŅo>l xyyѹsg\\\ԩ+V 99Y-P] @ٲeҫW/FE7N&Mر#K,ɓ'ZRRRtZbʕ@FĩSҬY3ZlɬY9?))9sЬY3Zj̙3щظ͸5kF֭?>O>5szMC}}111_Z8{7RCK:/V+VЙ}!C2dHu 񶊏gذaܹsG=v%NS699#GLJϳ|r Qvmڴ2EaСZǞu7"3˄VZ޽kmP\9:v͛1bD~)5ȅ թSPquu"q!44UVa"##]6Re2!D(WӧOg޽\p˗/w}gҲ!o:u/_`{=8zh>E()eYW]+_MFݺuɉӧ\w̛7 (@ʕ\YeU@ c1X^=uIHfTV +++5OaRRSNbŊh4 z+ԭ[W-y0Ĕ&OL h4꬟Wߔ6~5M ˙_N2/ԩSUַs^q&MD (\0ӦM#""_UzĢ\# ҽ{w"""Քo*VS^A)22L!BJS6p-Zкdɒl߾ŋӢE .B^nݺC 3n߾ @Ν^իUlYܹCTT+W[&==xc2:%gBݻ:ש^w楐UTQn&MhV$f^jJ\W f<4wMS)K,B-q+ׯ[y&EJg~.1?9sFXX?C o߾,XP- @ѢEuSʼL2L!BlmmYjƍ_>Ӳe|Rr |fff:5WP5}Vʠʼn' p-[CdHvBFrey6Urr~vqYZZV?RvJQz̔rҖykfvx~S˜Xڵkݻ9s +VСCl٢r,7;9%3˄B!+N:jn_2qD`ٔ/_>#Bs5}S֖[n}vlmm룏>b׮]ѡC5'B/==wwwu٦7o̙3ZW9sF+={Vk ӧxcy׋qnyZM/'m|\~SNi%ח3/w믿z*9>X+FΝܹ3x.\`񄅅ѴiSwﮞ ̛7gϒٳg7o̝;WmӧO3o<><˘6)}}aHRRϟg\r{{{lJ|9i˼x۷2ԩSpΝS6/Wv}]x1$&&h"DK.]pvv_~!!!jժh|S*ˮ3S\47̲T5B!g(W"oԮ]+VPV-Vݻ/B7S~سg7o#۲9rgҿ ,Ȅ %K$66]bkkہ)GŵkDlْJkIؠA8toVwTTPAXniGGGzꕧq9e/g}eVX1.\5bJ|9i˼xΧ1Hu(/Be]^ :? e0ggg!VSK.ez!^?YeVP!VZ9vO>>;w]EDDp!\“'O(RiFzϞ==Fcʾ7oRR%ٳgPn]ڷo!B!AkgٲeDFF>|/99˗u%""\]]3f -Zr/^ߟot&NHJQF>D*ٓfB$9ʄ#e0sLIMMe̘1UέZ0 .Lnhܸ1K&..?N8cǎ51Dh׮eʔM6,[%KnfBW0BQ&',ze|HMMVZannܥK8v|W۫/^777իĉ9vڵ!#6֭[C:k.nJ޽1:!Or !۞lͯJ !myvm,&y7n$$$`ooOΝqss*͛9y$=dɒ4nܘ=zPpa28xb֭[˗Ņrz2 =|???N:Ebb"˗K.|Ze f=ܞ={6/bŊ̚5 ȘMeBCCdɒ4oޜnݺi}@8t;w(ˬxtԉ 6pD~'~74 Ջ%Jݘ2Ϯ]]6666jҥKSV-vEN(R.B![n} ',F{1SNvm/_NZZ-Z !!3fp\LL ;wܹs|:KfϞ͓'OHJJb3|pb|)3gQݸqC({֭#>>RJ3̙õk2'00+W0m4u9:ذa/^Թ2<ȹsXhdfĘ'$$Dׯs_9w'Nm۶>~!e\r@M!!dLm۶m<|*U0n8J,/ 00PL Ν;-[qQre]oֻ$Ύ1cPT) ɓ`YdYرG˗/l2bcc_/_Z}v]FjOPweժU;wÇӺuk.]::y޸q3gRF _βe˸wAAA8cNP?>}ʕ+PJ !ċ133{ܜbŊQzuwرc_\ڒQQQZsO?ɓsm o^ՁwE9|0W^%>>E@۶m6lݰ_Dv}񪷫Еy%B䥼H${ygϞZewԩS <[[[ , `ٲe1,,,^:~)'OԉcСbeeEǎR>|Z##G4ZYuQkbhh(}*Uܜw}Wt 88X- EA}GAڵ#F{cNW7nY)ǔ2B!r_ZZ=ɓL4>$frr27n̓zΣGگDƌCڵo8u/PF/jҺo%YcNWǏIS!xqYTy?~μy)Bӭ]ڵk_ݯ_7oߞGbiiI۷/NNN,YSNYx1;w|) eFϏ}wB7:,ex~r -ȩ2ϸzz@UvLOOWҬ-/5k'<',,L-UǠ_@3&iw\};*r_Bgii;Cn(U-[,;<;KfŊر.\&LѣTR͛7ӠAmllhӦ mڴaرtܙ3e,YOQ !yCa E IDAT)3Fҧlٲ\tIrL2y]%1P_6oӧ=̔ߦMԲJ_`7o$((@#իWnGFFd טsڿ(;rܧ˼kB.nݺéP[[[맾geffG)S+++T7n ovqf,]777J*Kݝ#Gޕ+W9r$UVEPD 6lȜ9s .3֭O>)RDɩP׸t +++ʕ+>})3p@lmmZj|w_xUVammuʲjذ:lٲe\~]fL2Ջ,vvӦoѪU+ *Dɒ%ܹ<BdLMfbbbHJJLJ={2n8\FXj/_&55˗/zj V^quu2^rE~)[X1hf$UfˋB[.?DGGOÆ ٵk,TuѤI~bbbxׯ_g…St%{I\\M6?'88XRSSyvUVرC~ ?r5y1Nb4h@'햚ʆ %aRSSn Sܹ'''|}}{.Ϟ=ݻ[ p<)k.X~=ѤpUƏς ƶf9rd0ԯ_!C2ǐ!Cx")))؍"sI8|0s>%JpeF̀سgݻwWu[[[ݻӧӧO޽{f EcooOtt4ӦMS뎎) _Shcoo˗2e {fh4hV#FBBB֭cԨQӇѣG~z>}op3*U0m4ٳRJ/cNWd2NNNrT!r[ll,ݻw'.. &p>}Jhh(Æ #99}JOOo޼yq#F 55#Gr 9vUV,\0G񦥥/C 8uj$$$HXX...3w\s&L@\\~)W\!99>#7ovسgԬYSBҸqcb޽9jQ%mXtt4{ӧt҅ϓҥ SgL)t}ӧOի.]"))I݉:ky2K?6 {`pPjԩ4i҄0p;w&))s}}ϋϐ!C裏8~89r*Ulx՛(!!q1i$u:99gҥKlgu e GGG5mdz=ɓDEEQre;ț,_I&1qD8sL~֐23?~u˜9s&&MJxrJի?*UҒ͛;@_^u.,PeʔGxzzP+iӦ*TFCƍٳZ(-jժXZZRP!Zh~^ضm[ZǕyˋ'OвeKUVVVԪU@ZlÇY|y\˔~y1:t`ӦMT^+++ׯϮ]S%FQz|kԨChܸ1GGG~WZlǏYrQeF`` M6p| 'Nh5/^}G{|ڴi8qe2k,ɓ' Ã'O0eΝ;#~senݺul_ڵkf@DDy^ӧO1cݻw;;;vӵc.[˼|||:t(׮] (( &6g̘1-[6Gn_Giii333~^?L`` ^^^j޺{={oB&LҥKlٲ%?9 FdYf !**JonHjժEF :z1͛|ܹSkS r)=DvrYmڴaҥ9NfffZK`r ...37772>|-ܼy *ݺu{+++(YÛ~ݻwӾ}{ݻ#z-C aaa8p@om۶2W@HMMջI!)))XZZR@RRRJQoƍM2s9j׮uN||<֘k-517;333/6DA2 SEƆ 6c3aŊ4jԈ~&O>}$&&sNJ.sNll,:t‚ݻw*ub ֮]ˎ;btt4;wÃѣGse7L!!3iٓ}Ҹs+Vt)={ƍ7uK..]Z+Ɏ;(SLKEU$՛_.ùy&UVeƍ:+ԕY:Ⱥ355B>}ؿ?:(_ۙ1cڵVnfSN 44SB*T $99YqFhѢ@@ŊHJJژ&()y?RK=i?]x0P~… 7Ɏj>@q%eNhVZUX"Eݝۍ}̙3iժ...ߟ};wŅN:b >|Nkl߾ȘŪo 25koݝ&MбcG,YAR_JJ -͍VZ,?~ԩSi֬-[d֬YZ9+󓒒3g͚5UV̜9xի=f͚Ѻukϟ3)'mkB Njj'YرڵkשShժ(--+WҵkW\\\pssc:3=rشi5z.+Wggg6m$^@ƾ}XzNbŊMvZ@ʕ% 2fϟON$_|&_bBS/TnPhQmۦ3 P?LFzsssJ(+TXfԩ:ADk׮eڵTR}=Ξ[v-FQR/^\l`굌'C,rppԩSDFF⒣@U~}3ByOM^Q= 6;w.]`fȑ#vۍLJϳ|lgN*K+6mjL"E:tֱ'O0tPf&ҊE^z5l޼Y_YennάY_p:Ȯ]8s 6lel\#FulBZZӦMLk]Snݺ.~)Mkɒ%ũQ˗/WC$sq9渃i{7}+۷OV1Y&HC aРAT\F9eʔM6,ZEX5?-GGGz͚5kXf }1:B &=қ?󌮬.^g}6l0:"L4 |Rӻwo_N51cl۶`)֭[0dvǏyLƴ[dd$[Wxx:*+}K/st̔ MVʬ*Lchm۶FﴶyfK>sZy%J0rr˜=~~~ܹs;;;||| eժUz?oذHj׮?'O$ NPP2s`oooT\~{{{5Foooz<ϟgƍ8qBٴ` (-[ a;vLǏl2BCCΎw; WŊ $$$!C9m^P_TRz_,M?uoߦf͚)qU\KuˋP;'@mCBBYι1;2X&H渻`֯_ϦM>|8666^2e 7ndѢE:W^6www&OɓСC"RjeM<ݛ̙CΝ R )$%%+;"\/_2d:w5-R4ۛ?Sݐy8Smݺu@ؔOJy2k !!AڦjUP.'OjkOy2SfEe5l0 (ʕ+s<>>_2MϔNJc/,E˺Mqeaڴiԭ[KKK>}u PrefϞ ]KY"o}1֫WOv!s<==VVVVjN$NJŊh4&===quuҒu32ɓPFIy)mkb(ѿ_Ufj\ MG@@>{DDDlSE;@ƠZVlJwdL!%qܹs+033Q`ĉ={Vݹ*;-[[cffrN)KJ2J(96 RTT 333.\se"ƶ[jj:#Bٹ%f)K\ '?X.4/^ U2tdP7Q'U2vXi߾sӡC5j:*oFXjj* .YBd/yc"ܺu  hwrr){m:w5ljl(eufL߀ݻwuSzuK2*T`Y֯_@k)qe_YΙߗ)mkҦM/ΡCԁbmmWǣh cҥ L΋v/W)eDޑ2!BFM }Ç1b ‚ySn]|}}sQh4YS?Cݻ73)RRR~:se7N_y}: 6L+12?P\9,,,]6ׯgƌjþ j֬ŋi׮XZZRN݋=gr)9]ƌ~Qfe3}t ,իWi޼9 jժ,]e˖sd=TľhضmjBPV-mۆFO2L)TX1)Q{~h4j֬͛o heeΝ;?~={dyO@@f͚h4իǞ={(W۶mIo/rMMe_hzPwݾ}[DD%>Xo֎[bzz:M;;; cirfm%ܤl8}4z,/z66V׮]133c۶mJͭ+FΝחAj*/YٌE\嘡 [D0R;!xmڵ+TҡCΜ9… ٿ?.\I&2dժUc@ʕׯ&M2j7aF-M4aРA:3^>S4 K.ŋh4}Ə;ժUc\RBRX1BCCYp!۶mƍ<{J*ѥKLB2eLjGDRԙtӷo_&MĶmx%J̙ٙCpp04hЀ3f&j͚55`(Wz_N8uܿ2eжm[<==&_6kOSu$7-YYf ۷gذaZq9e/-ZTRIJetvyCpZUVB!xKK[&OL ؽ{77n 99wy Fٲe;D!LÆ =z4/`̘1899sTo,B!B177o߾yu$>?B!B! ,B!B!2!B!B!?Y&B? 6ׯ0h2X&Bڸq; !B Bd S!B!BOf !⭶l2Y)3}/xz!!~M,B![m2+[o{.??:g"o,B!B!2!B!B!?Y)B!^ȟI_ I&CI쬷FbŊww^)1GDD[}ܜŋS~}FAժU"##8p eʔaΝF.]bժU899p9Hr !Bѣ/K@N>}4˗/&==^z@_zBW[III\|Yfamm|x!&<ܻw5kcdB^V&Nŋ9׃9L2ȘՕW>C)BHH111zr1 ,--ޗdB!+aŊ*UY8VZšCxKUV >kkktӦM,YgϢhhӦ ǏPB@UVo>J*t҅?XZP^j'N+Wۢشi5lٲjr̦M0`E5#"&&e˖qq>}J*U8p SN_7fܿҥKG1l0ïϓ}9Wq=-[FHH)))|GL8WWWXrziv_c|=GӧjJmscTXǏm p ,H3f F뱄`ߏ͚5cܸq.]B N@@۷og:uر:t蠾= iN'3/s=[r !Bbcc4h/W^e̙ҩS'n}KBB33WWWٷolGꊏgذaܹsG=v%6Ɍ9HXTT>>>?˗gݐtbccoU>z?e)'g\\C Vٳxy&Jҹӓ'NW0ydr .d@ծ]8s 6lXb@R̀ThvPdmSS'=[r,B!xE[ رc|'|}}~:7vvv\zk\bŊ!C8|zˋP;'?3+,+W&$$/2CBBYucJ!īϏ;w`ggZJ vsI_>݂- y|LWdAUhB%v%*vڢPb j%ھTRVbMR{"DVDGi&3IfFbc2{kΜsգuر[[[hQZɊ+d߿?L'ל8WZ\d ϟ7ǏsiN @ ߬_fiEDD0w\"## L2ܸqիWx{{SV-~79իWZ*ժU3=jSS=[}O:˄B!a)cy!""?///\\\?~<0?5kbooOZt/vmP1cQwRRn[0֯_M`` F?DӫW/=yƜ={wOF˗#x̹խ[ &sNBBBTTPɓ'}vcN:,XoN{`ܸqT^{{{ FRߧnݺ|'֙ӻwoN:AO> *LHH07vX6l=5kԍܱBvTM-O=[}Oa !BS7nrNU^z:u[vKzz.mĈL2(o߿?AAA899?2{.uYi}j׮[o_|ݻIJJ͍$vڅ+[%sZz̋{rt !Ba"yB0C>zZj?{e˖-?~ zj fҺ'Y*SJLMM54ǭDڴmW!,*Μ''NO>L>wwwZhaq<~`;?tJ9qj'4uqzyڷoի駟֭?zXd77Ǝ˘r}2 S!"z嗁GD)ScǎkFnnntRV\I>}HJJbΜ9zEmvicO^Ӧ[hZxzzpqܶmtke|XC*Uݻ7J)BBB[vdґ#G8qA^/MeNvg||?8GW_5۩S'lllزe Wb}2/r}2LXիWvBˋ[; ! QF]ٳgBbŘ;w.ׯSKY|9!!!L:jժq)O@&M̮C\~cҶm[*V~íիxyye[;wetܙ7o2c Xݕ+W֭[\rvJ%;^˖-pӧOgԩTRӧOmhт˗3~xƌCŊwWfժUh"Ν;~:K,aۺukΞ=g}ԩSUgΜ>3륩̉f…駟RfMΞ=˴i,iL6MwO8AHH޴J-///ի{s[.*TgN{ddfyqϖ{_2aU&=z^ ((0k!x׏;wGve|"[>}ؽ{7W^=%K }!$$3f|@˸^]N`۶mYټys6mW_}W_}`15jľ}7XH;*’"BggϞ\|}fo߾ݻ8zꥷɉ#Gޛspvvilܾg˽/4L/(%| ʴS3%Jl2ZjE"Ejժ̜9m)Re˖ѵkWJ*-JG,_\9:uĤIR 888M߾}2e.ѣ)[,93rH)Z(4lؐ'Z|nݺ5...8pJ˖-n!D̒%KXbQR%>S@ )WWWBCC [[[tx21纥Un]vJZZ_|E:88pBCRiӦFz4q.Y@qppe˖P>ks̡qQT){=-Zg͛7Dܻwŋ3GVLOfl>T+ ٳ'k(;HY&DY?-bҥl޼eO>ֱcG̀xQHt_0f~n޼I)S [nM"2'bBLa&YL! >}?Ƙ1c'mWӦMh4;VZʕ+W9s&uԱrBr]Y&YL'Fos|n9ggg&Oݻ7[neܹ899Y9:!ڶmƍ /:.,L&BQ2tPfϞ aò]pY3///~'.]Djj*/2 4`*U! Ƚ/HgB!S`WPP+W ..No~ Yfヽ=4o\.Ė-[݆LB_:t(իWhѢ4oޜqƱ{nQ\0a5j͍eZ\<ݹB!B!22Q ?1}ر#2ѣ?uL>]o СC C)ťK̎])oɓ'/_RuꫯtOOOڶmKXXn[QJqu]fccìYcԨQ߿Ͼ}>}:o&+Wf&Cf͚5h?c !ٳYn[~=FbԨQ@ª{2ȑ#iժ 6^ZoY{_rb߾}l;z(gݺu(֭*UvVT!,h;v,K#..P&MDͭs(\Ӓ{o$#DqqzK}w_"Ee hjy_B(V 6$,,O>$Ǝoݺux{{M@@};wΝ;F۷/6m|r:wLjոxnӶ[FŊUVL0~[n1`RRR8qIdb>Ys'ϻ}M'N$00ʔ)CN0aHg!xbcc-?~<TR;v ::[ҷo_߿_N8QñaTV-:/?  {\x*U0qD.]ʖ-[8w\eo\rPOJp#F08&s]1)R"""leUb4o^;!zVHeٲeܾ}ݻz۷Yl#B<(^8˗/}/^[[[ʔ)IKKc…Z{o%0EÑ#G8tmڴ1ywFO?% ˼;vx5jaxiӦO2ZuzmΜ93-_<666 hذA%ַo_Lb4̴Ihܸ^ f.٘mF=MB̟?W#4 'N>=U 55`VX7x7o$44#Fx_h4F% 6Dd!xL&jVf%j…yܿY(L IDAT5kcnݺExx8 @3k,֯_F!))m۶cRRRHNNdϜ9m۶BRR۷ozˤX!%%D{7r*9i97o/ܿ_nk׮eƌ&hN[%''ӿnJbb"ό?ޠ\oY& CRhQZj8;;cgg}G\rznd*/?L޽\2...*T777ׯϔ)S8w/[~… cgg+brqApww?0p,3=MB1GGG/֭}OOO5k7իWk׮fhN[if'ywY&B@@@Nb׮]X9s>$xxxpmۆu(Q[nH%%&&!rMlӦ ۷o',,mRxq2YhJ)y]GY2e|2ǎ~ǎ89=zW_}Uq=}Y2|8իWŅ… opB>s@)Re˖ѵkWJ*-JG,_\}n3g7ΎRJ{h"4.s2vyZscuǴj ggg^:ӧOub[Τi+,YB``ae-[dʽ7QOBO!<<={@^kٳ'aaaF ! .6nѢE,]͛7SlY:v0`#y7666dgƈGO'bedB!O>.]ZC|XXNBޛɚeB!O!Srӳmɓ>|8{`̝֭;`B!{/,B!2tPfϞ a B!D{o$e"_ڰaC/ 6ХKk!(fd!!c۽C<?Y&]Z;!B!BL+ң.B!Bk2DDD0w\k!7?vB!B!!,իWe(/lذ{{{k!xF6l@ǎ9V?%Kyֹt|iAziУGdL!e7ofC!&eB!xf0⹢vBaB@!B!BBF ={ʕ+ݶ~ziBB d2!5ѱcGlْ!B!B=Y&6m7n$))t.]Ĕ)SSNקOJ.MXX.-,, `۲eCB!B2\˓rccci۶-7ndƌ̘1Co; :%%&M}[o/BBwիWY&8qŋ2@VD 8%Kp=|}}x^v?'ßѶ/r\O!B! XY&f/~=zGqI7n̯Jhh(ŊcŊ$%%{F>}HJJb帻u +tM#ʕ+s94 Ǐnٳx">>>DGGCG\\AY… 7o^.B!B?Y&fZ~=k֬vQZ5/_իuyx Fɾ}hܸ1{?䭷ʵ:͛GŊqvvfȑܽ{W},^_6m7|cP+saܾ}!CҥK4B!BHY&f:<*TЭfcc'NkFTTժU3x@DnPF 麴 ״iSfϞ3;v࣏>^#$$FcB!BQIgȗ2vK^xgʘlMaI֣yM@{{{ݻw넆ҨQ#W^yEt B!BQY;!2jܸne4|={˗/S\7n'N^z>|O>/2}̭+Vɓ߿~[e4;_~>|3g2j(s%&!B!oddBw ((#Gcnݺ o.ݻ/iܸ1iӦ|޽[G; ܹsa=z0x`ϣGayo!99ZjQV-@B!BE!BXXX !,Šg4L8@<<<ԩ&L`Æ 8;;?0RRR9s&ѣԩSD4 < 11,믥L!cǎaVdt般e˸}6ݻwץу5kְl2SEİaXh7wfѸ쌛8;;SH)3otڕwyڇsU9S~}FtB.]B!H:˄0Qzz:K,aǎܼy{{{С;v˫hXt);wΝ;,Y6m0`;2Krr2k׮^z*UJtvZzM"EQ s,Y7n0|ƌÇYj`jԨ34g !DniHB!盧L͟?+W?z'Np ]Bjj*:uJ͛)T(/h46lhaÆİc:wG'r |M6GԩSΠS5-[ۑ J)k xN5 ZBE2!Li&͛=b̘1u:V^ͩSQƍۛ+WBLL [ncǎNzAVj6YVԪUXλː!C3gNNNzΜ9Å x"/^^уBfBKeBlY& SK5\\\>aaa\x͛H``^;wB2eP'Ocǎl߾=FgϞ\rʗ/G...|nݚr֬YC5ty~GJ,ɵk3f IIIꫯRV-^{5ׯO&Mځ&k !,(ˉa&BxL1)SETT| '((HoիW0Zm=w0)MG`` գgϞ̙3`wy˗p%8qqqq]O?[[[ԩCӦMi֬M4a&LCB!DA#e@}1cM6A?uۗG^_>[fժU8991rH]^zS:u}4jxiM4Ƀ#Z%f͚5O]#F_~!!!m۶믳j*6lHR ",,;wBBš#Ie0RJʭ[ظq# 111X;Le>^B! ,vJԩS'&MD*Upppooo˔)St\]] %((lmmqssy,_\oTѣ)[,кuk\\\8pA Օ-[gF;7|åK8}4ƍ?L1cjZ~-RWDDjժ舧'$ΜXsLOޞ_~Ν;j*V\i娄B,,^Cq!֭['W1j(mFtt4wfkժ[l!::_~… ıcǸ~.9vz%V<7TG}Į]HHH`d۷i۶-M4̙3TgΜQSNUEQj֬z k)u*,,,MAט+777rrrR?>f|9;;_|5N:FjԨ֭el666j۶mzFʗ/nݺkf s3;Ɵvmo[n% x'B2\˓׳ɓٺu+7o͛lݺɓ'y#SDVŋi֬'O䣏>Zj8;;@ʕ0aXb۷EY;l!{.$''3rHΟ?σdd0zKY_+a}K.1x`ҥK~|||8z(3g4)t/6nH̘1#GPzu"""h4E PJ1m4}FIrr2󤦦hسgժUzKhXn>sAeZ'Miϟĉ$&&_X|l/!x&I'=r7O^FFíNjHFYye5p@TҥUPP:y0X}Vdɒ^UPAUYFegggjΜ9I&xV(QBmVٳhyΝSVA-ZTխ[WM}sx3.](@ :h| P*U26śYHHGʎ92ZN?6fDZ֍Ȕk}Bرc ,Wof P...zNNN 0z͍Wd䨖fq۰>K!ctP/6fɱ{ ~=wX:˄U=ӼI:?cONR5(/u!~Gl4ӧkРA P'N4)ޔuC~!˺ .vܙ屛z|(7ݹsG*UJt_vM+;;;cr6΂aśYFn޼itɓ'իeS˗Wjݺzvuq߾}&Ǖӵ^{Mmٲ7ǏͨbŊ P 4PWVW^ͶK͔2)!ctPgΜ1fɱ{ ~='eºLWYfgBBȑ#ՃTdd0`*T*ZqFjʋ/*GGG`u%߯|||vrd4uad<ƍS^PF(ՠA(}Ο?RSSFQ{QժUS2dS۳,oUVM*""B?j޽[m۶zܾ}[-ZT/gΜQ>TGU-[TFҞ(WJ7oСW>TC P$-9άL)ꫯ:U˖-&OlRݙ-M)VXetUGݽ{`޽{&ǕݵVTAAA PnnnF˹pںu0ajٲz饗l2cT}UAfiϓSOY?ʱ{ ~='eºLWYfߧLy"OɸoNi-`w6rԩ w.=zHٙ… +@%&&=fSh;Y[h-Zdng2i;,1͛m flmmԪUTĩSX`4lؐhTbŋ9y$111DGGs17~Idd$更oߞv햹ܔb1H+\0|fti|}}o4͍{LѢE-Stsfgv,=ŋgJ8|*Udrz|||8rM6&Bh4|dۛcǎOF{wU.(@"KbK.(*WBQDKE?Bn KZLTLD1 4l"9132 uu993e?ג'<رnnnRJ?Q2255Ō30c /#GܹsbUT鯪AMMM#??_{B(REDT$%%0a „ гgOuQodggWݏ?0ȑ#hѢL\@&MThjjyppp@pp0.]lxzzJ;p,,,`aaQF믿FDDo>}::[[[q۟]vaܸqDjj׭&յ5jpۜZ]2Qp_EEEr.oMS^^ʌ"U#GĀo6͛W-1Q6lM F!}HHHرc| ߿? @f_RR444`ffR{ GԩSeoܸQŋfff7dqpp٦uS*r@CCvɿ2+rA˽qqqRb_SvʎMU'D kQeTױYņ k֬-KXX&MÇĉveS]:9III޽;:t+US$^̐$tMRTn.VѣG#:::tL;???ǽ{|~~~ŋCŕ+Wa 2DvPqq:L%)V )R-YoɓsN~9ݫPߤ^#Fkװ~zDDD 33xd %K@OOOsz'1k,aӦMu{aѩS'L6 ;vqqܻw/_F/mڴu*eS:@PPΝH?h׮QQQXj"##w}+V~ٳgT_DD5MCj:0Q%.^͛7; "W,xY,^ѭ[7<ڵkaeehb׮](..F\\lllGѣaeeK..Ν;޽;,]_| ?7nʕ+##"/梢"|8LMMKܽ{+!շx QƚeDD$ePR|̙BYfSNɴ-o"_/\ >\h޼+W_}%ȴzzz0yrK޽[M  ~AqeРAR<{LXt`ii) BǎE ?u+=.U(;!UclZZ0k,Hv*(tނ_6l`dd$5:w, ƍط0m4͛J &4nX|M޿ɓ' yܹaĉ ->X%'DZ0?;wVwT)ID$O}KCoQz-X;wɓNdQaÆQw(DDDDDDDu'ˈM6;"""""":eD Pqq1ЩS'YNdQC`hӦ <<<Q2ݻwy7n樈O[Qs6m7xcƌ#>>ZZZpvv ""Z2ݻ077߼y3m6|gj SwDTS!8YFSN]t ɓ'M6jpu@DDDDDTc8YF`ĈRۼw^,[ ?"`ĉV󎈪"88NNNT2(55;v֤IlذSNUNNN58eT 8YF_͕,)S`ǎp%#OR.^͛7; "g>sWa)LSQ{.Bf6oތڵ#WFDJ ǃR{.abbիWqf͛3\t8"RW(+NR >>^͑@R Zݾ}]tQիQ8YFܼy/^ \;wZBϞ=1qDΎeDDDV-4xUlݺ 4i:w j^',#j`$0Ϟ='ϟӧcʕj\Ο?_~_x+V`022;˗/Gxx8t~""z=qٹs'BCC۷ׯ_WSDD GuDLO"BI҂cLdX:u ƍSiDDTwD~VVVT-~WyI?FPP##z}޽YYYġCp|rۿ?ɨ(\t ;wDFF:زe qxzz8t$^Xjb\yyyAӦM[xJWt,QQQ]/&iCDDTWЬY3\~}Uw8D*Q4)''8s 2e {rJ<{m@daff&Ն4NT̄uAEӜrss' 55Ul"00P$ϟ O?XE:R6n܈I eWeLO"3f@DDGI5kV9::ĉd888k׮/|}}ڊ_+ڮVK^)SrJ8p@hO>رcaddcǎ)|l>}py$%%Ɍ1)) W8F""jҥ Sh1|oddR՝$]ӓZZBPP CCCk׮X~zK[d }}}[nXnfϞ ߚcǎ7~mBWW>}:VZ%OvţG!~?R6ŋZZZ =vС000@ddLhҤ ؉ŕeD$bPaڵh޼96oތ0o^]vaڵꫯ`ii7obݺuT[a0zh#F@N]&5t+LMM3gW^9s&/OT+C޽@6(YQPwYo>&N͛3|055Ńܹ &GiǓ'Oرc^zgЧODŽ ;;[OOO?/,,DLL bbb pHY\Vw999Ia ,#jǣgϞ℔=lmmOѼys޽ ´ipi";;D- t};?&Gi]t]ob͚5Xf ~gqر#acc141Bݻزe 'ˈ\8| ""Z4L.,, ~ :::pvv۷Ol;`,XϟG߾}q9|4hR}hkkvCb˖-ԩ`ӧO_\v܉{ׯo.s&M6n܈[ǘ;w.A{NDDL0&LPwDTM0TĕeD ܝ;wR-ZHLLھvZDDD &&U};#~ݲeK%$RRR{:_~2̙3q):u +VϟJ'"I"""jX8YF+]խIgtOёi;yd :F@@???]sQhTBNDT󎈪"885A)N5pfff}6߿:(IW ˖-Cbb"z聸8,]6mRԩnܸ .`ذa[h3f`ƌO?c…,SP߾}ʂֳgOuP%cƌ/D';"N5p1|}}-[ o&233̙33g`ӦM۷/Μ9Aȑ#1`%:w\nYYYo'ՇL˗ {E޽qUɴ@jj*mX[[iWźeDDD 'ˈ8OOO>|.]>===|7gϞa044޽{ݻwHLLDѦM<~]tAp 000PŋO?իSL۷zxx`Μ9pwwԾR.^(>HQLC"""eD \fp%^?3ѴiS.'v 333%[l+^^^x ׯV^ݻ+Ν;OOO:>>9d[e3vmtE]h[Ǘf͚nnnرJ.{T5,,L,}ѫW/keD-Z`ӦMRdžG߇ $$DiӦaڴi'OɓC&bmoڴ)mۆm۶Uv̙9sf}Մ˗Rc4ۢEpz5W]gϞEll, SSSQիغu+8A0i$t666*deccǏ; ""z/!!}v١>>>2tyuPJ߷bdddW^ŏ?իW+u^/^`Ŋ?~<cǎ}}*TwDT7Y[[֭[b*%QCT]]짺b … pB>HI;455pR&LLL/_c,)S xj 'ˈH.+++5E Ou(IYd /^-[ڵkU>/Iמѣ} 6)))pwwG߾}1p@[/^:'Ozj 8X|9q )nǖ-[0j(#GĶmPXX(sGaʕ4hzɓ'Qބcӧ1g8::W^裏'cŊׯ O<(3fyСR+]?qF? 44=z@۶mڵ=BCC82a\]t>_.'jHj+է*TGL![IO(.. 3g"==]<~C^^^իWaڢ]v̄/ڶme˖ 1g?edd 00IIIغu+45K&SJiKII7^z#GV9۷# @j[ff&BCC-H%DF\\ѤI}(3Tv+s}@Vm^y<==q%%%$$EEEc@``WWk`{zz"** .]Ν;@+ؾ};c޽̘+S=.OQQnݺ лwoq"נ?!22R7t\QQQ]&&iCDTqeZ,JLTNBFFttt`aaѣGc̘1Rmhݺ5O?T#T6UP8"1Uӧduptt; *2e {=MDD`ڵ066cƌ'Ϲ/,Y"KUTpA[믿Ν;ʴB=򂻻;Ξ=sC1W{\ZyﵦMO>WȳtRf͚PTILIhifffRm;NQ?; Jmݺ{%3<5J)))5%++ ,[d 5<ʌ2hiie˖ìYy@k Oǎů5k&ӧO@P$$m;NQS<|o!*סC[l=^|'N'J,[ HKKڵk41c >>^eT^?iF $&&M*FޱP}~~~DAA6l{{{?qxRSS+d䳮h"99˗/W_!)) /_ĕ+Wk7hРr2cVʮAEׯ2Tڴ4}m5nKDT*"TLGRԐ!CЫW/;wGױm6۷3b*4G1pqqӧqm̞=[>tP=8>>999񁁁V^ mmm`ʔ)Xr%8CCCL>ΝCBB\\\ӨQ#,X@~ƌ@BB>#fvttġCo[hObر022±c'N2$''KӧOjӥK kI*3fuPȻ~ӧΟ?$J퓬l|6":+ˈBָ~ TӦM1j(`Ϟ=puuEvv66n(;v 2ZI4ȑ#{2cHgJcJ $?_AWW?~tuuѭ[7[NL|(n{`oo/j QǕeDT!z 7nPw(DruuP*_~ݻʢtaff&C޽{eh$sƎ+:c׏#pqq!\ʌQRKH^apQYh׮m022IO%"8YFD277G&MXVHcǎ7~mBWW>}:VZ%S&**T"y*3F2ャG"##8z(|||ШQ#uGDTmX*ݻ?yF¨Q*m״iS,\ .ݐ!C0dȐI^?Xv zclܸ1tq5sQbggwww͛'S🈨dUE^_8~8)5DDT1'''899; "2"5BBB 444S5rJT&NC IJ_|S=͛73$NQ㭷Rw8DT͘RCDDDD/NQwMMM\veJeRCDDDDTeDT&M Q  ""Z2"R Qsa>|XaQ-d){ؽ{ ""5 ;"""RNBlllボ;R';"Z;"?}UwDMu@DA`*ffjj &; "G&LSSSup; "uAD*2"R5kׯ/d T߾}y bHi+ˈHa666HHHPwDDDDDDD5+ˈHaVVV|àZƚ=DDDDDԐpfmm@z ZZZjkQu5۷oK.RƝ={Gō7~ ѣ_Ut+Sq*Bzu\!&&ЫW/A52"R5򐒒jDT+ IDAT~a2"kѢE8||xzzҥKR@x{{Q=Vr8^[&MBΝaccЈp֭[7hii,#""Rϫ;ZK.m۶;w.f͚ѣG8tك/?#wp[&Q_/^+0~xƎ˗#<<j ѥK'""*^8Rŋ-[b׮]9r$Zl ---9sիWضmåPPP?~ɓ'ۦLǏ#((HQM2"R]0ꍬ,l޼/^ċ/`aaiӦaٲeW # Ѻuk >~)tuuH׭RMLL 6n܈_~ژ8q"̙ϟcptttЯ_?xxxq9N>p$''[#a``PcccǎNmI ~m999Ǚ3gn ٳѤIk7"!!zzz4hϟƍCq!G B_,^;wFU兓'Ob1b~1h P^Gm6DEE!77fff6mT]z{EcEo׭[ϣQFׯΝVZUx}sNNBCCѣG_v`ooPL:GqbmmͿ)(//~)>|(nKNN'J+,,Ĝ9spMq[FF[BSSĐ 6HM011AxxgAA?MMM\}vH+33իkt>};ƍO>ږO>Rq 662/nnnxx-~' CBBc={}*Ǎ7"''@UxzzիذalmmѮ];dffm۶2>}ۦ^ȑ#7 ///DFF(;|0,5!Z2c>y$ sԩS7n\MDu 0H)666?SuBDDTÇ066F`` /wRd߾}y&y bccqQҫu^uҥK3gZZZ駟ٳg.\ ~%/QQQtv $EM>>Q':u]]]899,[ :tN *d,.._waJVoIXJW^<⊪3gSSS pttD˖-/_mۢ_~JME&ݱ:NNN'ʕ+XXX[n8q=V+++<|.]*wƍ1cu놀qJVTݻw_~p hjjb̘1*M&V)Jx]-9Pc}I2Yωdׅ>NՐݻ~Te!-- ǎQmY%5ZhRE󋊊]cc>|8N8`1-[_\\;v@|$1߿k׮gϞb{SUի .>VXZZ͛غu+.\(W&7xxhhhȬSte77nHfr (3VZ!33ϟ?y¦$]'oQÚeDDDDD5du!)) EEEHLLĺud@I dz O}:N:|7n>}Ec@I]!!!AW:7^QXX(էc+Ou߸8R'!33ذaBIÇŋHMMR&W_!)) /_ĕ+WfAʽ.ʌYr*I3.M&RH=5\|Yaժ={Ta߿ӧWv8w"QFX`}-S;FFF8vXMdĉd888XvΝ;w ֿ|WRp8s RTf}m?FVѩ26y*etW6|||0e\RΘ1HHHG}$v֬Y׎8t[|ƩMR֥K (3>}HJJ@W"8YxbP'մj[nŅ  sss[VU&MgϞǏѸqcbΜ9رvp-(U-YEEEīWЩS'޽{ǁPcc-[bϞ= _ܻwիƍ'3a_ Ν;q9 %O[3f 駟S'DTY8x Q\\{aժU UkHcڵCpp-88FFF2iDz`ffD:b2"FWy-0{l5EVXaׇ L:pQl޼5RstDT8Y@DuLMM믿޽{(,,o޽{O?E۶mbiHc̛7O?>8Y@.V&"K455 &Xa`2""""""""2""""""""2"233BkODDDDD '˨АB-ЫW/@ݡ*qihh@[[-Zsu[+$/~@׮]Q*./^{Uz_{"\|_^DT?[x._˗/#<<gϞCW^ٳg#<<111h֬Cu1{x5\v =~;4kODT]c={TwD",zCWaa!233qA曈ڵkʎK!==hӦ W_;'}$#ȑ#QPPiӦKDDDDDDǕeTo7qЪU+{_ЪLKK Ƙ9s&z- 0aaaSwh m_bÆ pssݻw'NTwDTIa da055쌛7omJ~||<&L6m@WWDnnJ1K8gdd+((MЯ_?j hݺ5>C;wNܹ9scǎCaggUVٳgrQ)W^/ XZZBGGmڴITn,puu tuuabbӧΝ;r+{KVSI٘$HKK7n#G"..ܹn߾ i^[HOOweq{NUEppU|_,e/… BӦM2F Ǐ9F^/}}}v}w\HTT@xwggg Ʀ!;vLXаc̄jn9xoYUwÆ rӓ& 򋠯/ƍ UIE)Uc*}_O4IAx뭷ޝUU<]9`jɩP ˛`8SڽMCh-55n `zJKHie@ ޽pxBT}"} =,rXYY)ӦMS~GƍJBB2n8ZiРr;788Xp? J͚5@4i?+m*2gc5QTTʆ gggP̜9SN:)T|%11Q޽(ݺuۧG ?^%//Oo;*WdW~eJ:u@5k^F֭+'NP<==@iРremK.)uUKIMMUn޼*^^^ 4jHtXVOTxǕ,(J``( .48ڞ9 )Ҷm[m,NK>٫.}_r1* DQY5,{Й3XpQM6F3fm 0!:r6㨤f@clRo`ۏ?Jڵkժʵk IMMUI+Li]q=?m+**Rʂ ruбO>JQQQcrss~k8-+WZuǕQ!De~*UenU? ~SO[޽l2N'ƾ0/ʴiӔiӦ)f{>B9"9˄F}Joatqعsgbȑҿ.\sի;/?BΜ9CPPv=WQ~TfbǎqU6oތ7i_M^^nnnqss#//\B ͋/`2K!..+++PӧO'%%E[_>}n-55+++ZjeQk׮yԜIG6_bdVZaeeeMKN}])..74ȭV~eEEE,Zkn_d,...맕ۏeQIJגL.ܼy3>Pegĉmۖ_~BDz䳷gA{!JQQQ?'''"""HHH ,,LoƊjݺuL\\]t!))[Mg9t&M $$5jqF0a ۃ1:tO>/L{ IDAT>… 8;;f|Zr-[i&\`g`/kfzu>իqԙXի%((bmyTŚ5k̤cǎlڴ+ae)L~N>ʕ+IHH ""͛s>2mNСq2v)(\}IϟW4hJ~Ç+7nP٣L0ASlllGjlٲE'|R~5k*o+Jnn{nSN ̝;Wo̘oݺOʻᆱ)n:m{۶m@yו PIMMUFPΞ=J;w*ׯ_Wnݺ?~\߿(CPݩ]uiJ2 (Æ SN:ܼyS_|QG}TqㆶϯԫWO///ĉ͛7'N(^^^ Ԯ][_,DzD= )7o޴8&S]Q'(YYYFu[n)/^Tnݪxxx(bkk۷Ϥc%%?{սKW. >quu5韢(ʈ#WWW%11QzJֽp^_UquuUƏoCY+ﵲ\~X9qWYx2tPUtWv[jCRR^+oO:Oe}+(3<[uw*~~~d􅷷ꪤNm4V^V=S_ÊueE>^zIquuU233 T\]]#4Li޼9 2ݻwYb]t/X+ծ];VXqXp! .ԫ׽{w*Sa7NqL0+WrJs!&&#GТE ~ml©S08G͵/{sT|'8p@^y-9zEĉ+o֬[lVZZ_W:t([lj֬ITT-[Dzw^)bQL>|8Ǐn/,[.}K+J䳷g~{!Ξ= `{pTΝ(3EYO6U%Rrټeff2m4N:eM)1^|ǏӺukm7/.^w*/Uh`9mz*g֒2%0p1qvv֖  /sN^u?g߾}K4l;;;{1yA;Y&ZbĈر?zǏϚ5kҥ 5k֤~<|,X@K&C t{{{lllh۶-oG50ccc 6TCe޽t:lllhݺ53f<w}ǨQpttGGGƌѣG4h^}KјH^|Eԩ _-r@l M6͍yq̙ S%?{k !ݦ.!+r0O,JCZj֬iں,^SN̨Q;wͶU[c>&Kgkkܙ7f=zTm%͜0%m~I=g5Lcm6sI.U!|2Lpqq1Șk׮Yt^z|1p?nw2fƌctѣ3kР|s LoO<[*%=9r;v,7Di>iժ;v쨴LwIVVVTY1L9%9?{ս~O?4ޠ#gϞe۶m8::0˥>'""Fm/,,枷ٙt;|fSv|r!ѣGs:vɓ'Y|9?#<¯,VVV(Bnnԙ~T'NЛ=>ٹs&MAVVM4ۦ> t#3˄ ťyH !$/ .$55B?n|ˬYHKK+WG鴤uyٽ@AAiiizu^[ˢ>&88BN8= WZE?/xyyW_O:uh+~7prrɉ._2/4iBdd$ԫW[[[:tEN6!CРApss3zXR͜9cggGƍ>|8aaae3vZ8@ݺuYBR wD+{Qw-ZpUXj'!Ҿ"** TɥK8p NNNlݺҏ_z(˗/'66EQ>|8...t)B!BdL3۷ڝƍ̙3!C7gfÆ 0BQNmتr}i/^ȺuHLL$##[[[׿s1bׯcdUae]Iә|%Vdd$/_fĈZȑ#|2UB!4oU=?0rH8wriUf*VW5̘1ӧl2;v#BGfj~cŊsuZjŘ1c0`^سgW\iӦۗ &Pn]:Chh()))ԬYSj cΝ\t [[[ڴi ;V배0O V*N;sO?VYft:bbb=z43B!2g]U,{cՌ>\}Y|MZnMaa!N> --˗`{Ͻ 3Y&W2vXK 9s AAAl۶Mwu^{5֯_oFaa!DGG3n8 =qD'++7m_|9~)Ν֭[qq}]L?44Al1_5yyylsss#//;wB!#3|))){`ccCZxꩧU=#,ƚ5k̤cǎlڴ+[v-4oޜɉ3gΰzjclْM6?|}ӦM,[O`` d;[&>>;sСCej!BT<ݻ7rM:wfҤIӭ[7^~e,Yw#UVMݻ7*7oP|fBӱ}v NG``LXltޝb w&OLϞ=ׯ .ƍf@eNN|ߴ~ иqc233 E$''gϞr2Vy&ϧgϞۗ sSג~۷/&M*6eUCNNA,Bqe(;l9]7c Zhܾp5k^=uk֬Y<tܙ3gog&OO@@vL___"""ֶ׮]ׯEzz: 2!CQ3զۘӧOKkժ^!BT@:XV\Ixx>Đ݌[|9k׮ܺuǏsqrss-'ѣGYx1]vYfddd3g[PPI8yVv%"""HMMeX[ߣ8q"YYYqFK۩@HOOIIIDDDPvmb7n&LW^gϞ<ޱoMh"mEA~~>۷oرc[ԵLY%qU IIIܹ[BQM2Qm\xOWpp{zJ8%iF{^DkeSNf͚$&&ÇA~~S2\zhN2L#Bs58p|,9t| 24ufz1|rss s璛˼y_~3׭[ɓ'yljѥKغuAL1ߘW^!88fƏs=믿N\\ :s3x t:,^~rj+=hgj]KUAexG_9s ;v, ǎgUO1Wӓ'O{n֬YChhESɭP\ gΜ1gjiҤ deeѤImrB!ڶmnР/33iӦq)}Kx:u*'11DV\?>>>ԪU͹9e>iݺ5Ϲs4)m'ܝuЁ:GAAW&,,ŋ_yuK.?ޢ)$dUa!3DѣG,YBFF,^N%pwwn߽LII.\@^>:?<ڵk `|VzQXFyfnܸAzz:!!!عեgϞ58ZfN!B͒wxbN:3Fbܹԫ`1ý_REV N˗ 1vX iF-~0%jB<,dLT*M4!%%_~={jrcҢE .\?ݺuߟ/ҢE -ׄ9ԋzMݵ)]v` 8cz~!zbذa4lv;:Жjp\̒C!B[@KDDSN5(,,^Yv-cǎ%;; kY|Qgo۶`099$bNNN+TY*kNAYrI0ʌͰS?z(>EuF?+ %ɪ!ăD˄Q"GYiM4!22ի-:t`ѢE 0@W^="##6lԨQFի d oooxǰΎ6mzӧOyԨQ㎉\MƐ!ChРvvv1gmvzUnݺ fB!FBB1{l\͡elxK9rhtBDD]ve9rDcl{>}(**ʕ+|Gt:&Mdv,n@9r$p{ ̙3puό3?L_azHMMG ֳܾnejB<$gV?iРRրr5_Yy<<<0jOn*)6v:uCxx8.\y<ǎcĉB!D "((`{ZZnnn;`BBB _JΆ/JKNN&''yQvm,X cȑ̝;XիGFz*8::m6ػw/)))5JصjbڴifSoϞ=;w`+ѣψ54Ζ-[C{ΦMpss+7Ocǎ >ܢ>=zo>RSS >Y x2!scǎYfDEEieQQQ8::\ !Uƌ3fၽ=vvvtԉ 2am ~# @[D@@/_t[.H5_>^ڢFn@x7Y|9/;;;\\\xϴd` Uhh(={ƌêU3nejB<̬;eh|}}䢥ߛNw&-u|>h[|M6lСCYtiw^xPXYYBa*}"5ڔkasMV"<<͛7j4h'NdܸqU_u!O%2!L<%KdL"eB!ɪ!@r T,Q6S%B!*{{{͛Ǜoѣغu+K.VZUBT,B!BaY x`B!BTsVmTA eB!B!B,{HYYYUuB!B!Վ =dzI\\\U!gB!,B! 6lֶB!=$e[a!D$Bbl޼B!=$e)EQ:!QqBp2!B!6lXU gϞUUB!ц ذaCU!mذsUuB 2;}4۷kC IDAT穬HLL[nrG\! ɉ(&e[oo>y*+ƣG|rbccQÇB.]*t\!B!a"0m߾}<73gC '''={67nܨB!B,Ft:>#KTH._̈##G~z"##kjСAjZG!OәQT/e|2UB&3PvNwN_ڵ~:QQQΐ!C2d^]v[f޼y 4۷,ۼ1~EԩSر#Gpr5Oe˖iժ^!BT&&PRRRY&?Ic!<2X&S2|ILLdʕCZzΝqΜ9sc2&33iӦq)m9mz*ы9L#BȡCg")"*ĉ ??7R\\̬Ycǎ%33S̙3QTTM>yHOO222&))m0$B2LrŲvAPP;w&??+V0`6nܨջ@ӝfmݍYx1NٙQF1w\L:9m0M-S!j\v88-ooV.-"ZlɦMߠ=k֬!33;i&+@DD`zʌkגN͉ !!p8s W6;>Ic!<2LT+OOON<ݻYf ڝ=GGGΞ=˶m۴dU1##""hԨBll&MAVVM4ۦQ-].BYߦu?\m75}CERDTZh/dggk<3zffvC5kO>$;wf̙ٳɓ'BQY& ///t:9yyyklmmz}n_0QTTĕ+W裏tL4IΨR5ޭ;OBB1{l\`39ml߾=gϞ58ZB!Dh۶AcLƌØ1cxwnq>uTj֬Ibb">|8y+*c@6m7hŋʹpp{zJ\'i,BGfjcرBHH޶]jػw/)))5J^Z6mQF\zoooٶm]yپ};AAA;-- 777=zo>RSSbHMMW^f[!eS|c=f =mڴSN 6Lݺuc޽lٲ+Vn:LR[h7 ʬgaI"DLOX!0Ff EҼ ;;;ڴiխ[|||pttFԯ_wwwV^ws4oޜ5j{Wјgƌxxx`oo:ub…L03}ic]^>Ձ[./mB!ĽS2}ԩS j]cǒMhhWrss<4G1T;W$-BMYQB!3Dd<#88h}uMmc:u!<< .мyscǎ1qD'D !zJHH'==]{&Nиqcp 0v믿̥t߼y3ҥKѣGbbbXd 4lؐK3ۃtp9-Xi`y:vɓ'Yp!` ۓٳg $BY&`ر4k֌(,** GGGeB!~ ͍QF?hҀBBBݻ7ݻwגN`?CzŰahذ{WiҤ )))S{*zC fөƎK-pt .^H-]G)+J4B!df0KE3^{Ӝ2Ԋg޼y曌=[tRjժU !ʸf1c8p"ڵkǨQ #66777!..N{3z,1m4ٵk7n@1g^z%פI"##Y|9 Ӷm[ׯVo|ddd2^zDFF'w^\B&MׯǏ|8p1cm4B!dL+'Ofɒ%L2BwBQqe .75}œA<{{{ ,n+M*c(APLOX!( O|||: !Bjoر|DEEipB!H2!B!CHMcuV.]ĥKغu+͓4B񐓙eB!BBa !B!ZB!Di2X6lXU B!BQHβL-:thU!fСhѢB!B< dfCgϞٳB!B!dL!B2[a!(B!0O\\\U =UB'9ʄa&B!YeB!BǧBX@˄B!(gWa ++AQ S!B!B2!B!B!Ga !Bqt:s | [nĉ\~{}Ez:Juiڷoot[\\tMr !D%2!B!}#//@:WBJJ ^5Vz}|8...tҥ "B,B!B7f͚šCppp`ܹܹÇuV~:׿8~xUZ)gƍ̙3!C舓̞=7n("eB!BTNӖ<8pƍzjHƍQNNNL4"VXQU\|#Fhe#GDFFVadBqeB!Beyyyw^jժŋ/Ȕ)SYVglذ4iڴ)L<ڵkP\\LXX;wҥKҦM4hP /ƆaÆ1i$Xh֖޽{@:ů 33KrAnܸA6m3f 3gsή]iڴ)/ƍNm6F6>EQxsrr cϞ=\rMҷo_&L@ݺu (&&PRRRY&?> ,KNNСC2B`B!fPsUVV9oM֭g?p{@ȑ#tؑ;vGh"(:)**8]Ɛ!CHNN6:R@ڵk>>>ܼy3gҲeKj֬ѣUĩ*͚5'|[[[vٳ bٵkPF Znͼy?jԨ^jctYg}hѢ5kfeggNƍٵkn]v@޽njԨQz39}4p{@VZBa>Y)B!]ֶm[u LMƩS UE{=uTϟObb"\|||Uo^{]ra6mٳgxꩧt`si43gh8<.]uF+Bnn^ .йsgj|/^48Nɾ_>gfcc8p}r!0a6gNT`Wy^ `4'ZBa>Y&B!p%ŕWqŋ9uΌ5sgPÃ;vDΝgŊ 07܆(t,KT@cJXSߌ9q}Ϗr] 5[[[_y/۳Ĭ`NTw祖Y!idfB!U,115jۗOOON<ݻYf w=q:;;O?3hۿ{c:::rYmۆc饗ؾ};QQQ 0ƍm/..fժU(7m ǎg;vL\NNNt֍xRSSٿ?=^^6sf&MAVVM4ۦ.-].t2L!Bj"!!{t|Ѯ];\\\PU /… IMMǏpBcO,--"\G}N@н{wv;w$''[nq NJbb"=zВcp;wXJJ hˢ~ח_~??r޽{IIIaԨQzjժŴiBBBx駟%ӇwyGoرcٳgΝӞljѢAzꅃ/_Yo%m3QF\zoooٶm=z`߾}|ZlB!,#3˄B!c95c <<<ΎN:pB&L@ll,caggmڴϏW-=aaaxzzҰaCl;)JDfLh,ŸBm"H)dX6اaP&2nCѐJ"eI{>?3wݺG}9{;}?ZZĪUjذ! ###hjjسg f͚a߾}бcG4hׯqF5jݻwc̘1044& 1n8ٳ(e...Rqm,χ 455QPP4h4hhѰaC~v!iNB!ЀP(I奤`ذa066FxxSر8rLLL9|pL6 ^^^jǍOif!B!Dj())'Oo_}kXyxxO?P(ӄB!$,#B!#b޽;Fx4mڔl(OOO+WDxx8RRRp\R1TB!B!Zp!pI|8KQؘ1c]BH%T`x ({9BCC !j mmmuWʌ=g! ,#RLfBԋoB!2RRSS駟VWA!eeeʮJ/-ظq#PXXWWW| ˗/q?B4X֫W/0j(|_~5NyFFFꫯW_a̘1ܹs޺u !!!qnܸJsN,\ (mܸq?{n̜9S%U=uW&'|#G۷O͵R#%s瑓GGjjhkkCxx8.\M>zDE455allI&hPBH푛˗uʙ3g0}tCŦMSRR;v666ĉ^ VVV(**† `ggرooo }Ŋ+p=G /_ |$g֭prr ???iiiXj[[[,]TNѣG9s&z~aڵ_gu+++ÇGIIXϟ?YYY8puCCC~O?VVV8pwO1 IDAT+B!S`ٳg0uTAWWFFF?~<޽+s _1zhl:::hݺ5/^lܣG+?? мyshiiE2dΟ?/3bhӦ tuuѤIxc77vq۹-_:O֮]]˗8t6EUw;͟g aÆ/SSSL<>TY]5GeQlے0aA[[m۶Ŗ-[*߁SB!5ŋq ݻwE!>>(**Bjj*8um۶ vQXX\ܾ}?#BٰaBBBLڵ ǎ!""fq[ϜxyyĉDaa!-UL>{ūWPXXaΜ9RIdeeaҤIGFF p)iӦ!..Ç+owiرxot&ͅTEDDDC!X% B& _>;~1}g)s߯egg̿<111 /333Y׮]ˬ;v1qqqQFeӪU+~g 4`m۶6 V~}Sf_(R~yJ>Wvbؘ1c4E˭vۮرcy:}JRtI?+(۶Ǐ3===Ǭ]V%%~)r>>RS2WW20PXeL ͍=~沍72@k~޽{3@BCCY~~>gӇ v%VPPrrrXhh(lذa֋K7n{۹s'֖yzzO|o1@'waح[XAAv!Wufٻw0j(deeaܹx! ///UjcLf~]._ 0O?3w\deeaʔ)x! sΡCx)~JGWWxԬ{!99})sEG)gի6hnGe!n߾ RΝ \v >|ݻw1baܸqx >|ÇqFxxxgEyرc>ƍ0`@}QrEU*k&&6m kkklڴ ꮪB䙭^uyH=^'1;YdXXX@OOSLP '** W^EpIlٲf}2^  Azz:Fx݆ŋm۶с+ҿ077.>h=ϝ;AN]bҥRuYԄV\ 8qDf{{{cǎ|yK,QIy .gs֫"7ƨQ\t @,[nA__]vܿ`nn.GV!nS5k#sܹsΉeZZZ [`ض 9ի2gDܫ^zlRy32<|` 4K_>ӥILLd1lqug1???/blܸ`[l:FROnh>.W:.~lllXaaض֯_?^ZeuQ4]=;^2m[z5),,d666UY*r>V[{ݻuWWn|HMhfٿ*zyp޼y͋1N>lmm={@Mϗ^\\zlw^^Ծ۷oʓlWNNN =zٟ1&6>~BjYoenrqPTTAaڵb۹ecee>srLMM oر#cx%~_b+SE3Eկ_窺ܪnGeӧO@KK|A\ ,Xx8ghРsNDFF癣{Uq̛7O---,ZHf,UtN LbfwAARSSq!|gJѵdz:xWE*\pÆ wLMM+V\f8y$/_Ν;#??~~~pttÇnz@zr$?3fbV'0d^:ʖ٤͚5ȑ#q $&&"::лwo2e.fBHB\j##r++8L:O>E6m@SSSlG;wV~8KJJwb-\vI;w ..W\͛7e퍉'"66JaÆaСbT7ssstBFmmڴ)XU_yLQܪMRnU2se (] (}DWUuQ۷o1c >|*^m\p ~SBJ͛7G߾}o>!˗AAAhڴ)ҿK"~NNNprrݻwqݻ9rd)?~[n{[nIiddgϞرc,)quk*)Oq!_~vBHH5jGEqw6l|E^zhҤ lmm! ddffbbZl ggg:u &Mۿ +4nB!W3ߣq {=|wѡC2BvveTdXv- ڵѣѪU+h۷/^$1#Fq\x/^ăc̙3Z~舍7pqq hLUs3EpTuUݎοZul29ʼWi733##͚5lTE!::C(MMMEpp0p %w^L<|Zrr2֯_DGGC___2nܸR`oo/ Pĉ8y$1tP~իWѯ_?~0 pu\~{˗'۫T&׍L8q/_˗KmOJJ-<<>>R;x ,>k,rí&7qDmofX:\j_@J`ӹIKKcXF4eMVF3lذal ԪJYYue kӦX}-WTVÆ <2kkk(`FFF 2Ueڶn:ݛIϒmuȺ^Z)Tu-KtYi:5I*իWL H]Ƣ@ `...23+++ >ŋʊܹID'jWuŋq ׯr cgϞeSNe:::LKKݸq?ѣ ԩS1%KTΜ9:v+VS?޿?M6 1cKMMeEEE,11]p?{?i߾=`٬ݾ} 4`GTծ@YXX0߿c-QF eRYy穰z2L[[]pAl?eUu;$.UMqƱ$vu֯_?*e1~WȘrUe&:h7h vMv=6zh֬Y3~hLޞ={2,%%E;w0[ne{֪U+=)9۵kW@{< &ihhȼS"XQm۶e ۿ?{y(o1XsZ`G޽@ `,##d6m4&]#''}3@O没CiׯgÆ cyyyU]"'>!V2;~8+Ol@m`` ?Hecc#D g///cwٲeCc222X<Ą=}R&.Q^y7)^yR9O 6ylnX֫W/:[B!B!B=I!BH-˗/iQB!DT>XvE?^BcLU R nܸm۶`aرD.]]5B!Ve!T`YA!<,[ FK.Ehh(\CB!0 !)!U+44V`ee2wލׯ_oƍ?w̙3.BH]CeB333=Z =z4zj*YYYٳg-ZSNEÆ JJJ@[[[3.߁Э[7~)pQFNB!߿/B,(JOOe.\(w;71tl۶ عs'w^U2#Gď?#GήObSu(`}!!!!u ~*AVz||<Ν;AN;w7[={E J IDAT/֠AdggC("995jF%Ruhժ>BQU^h֬fϞpܹsGUA_~ALL ޾}-ZH;DEE~2djY(.!u-#j9rDUU^| tLW_}x6g|2._ L4 _>߻w@fL2.ۇB!3޾}_/^D^^Zn & [nn.7oޠE*gC纬Gtuuannש9ܹsllkpvvV&IEse7UO>͛7Vra!8prr޽3g`޽Q7oTdddybsBB_ / Pfqߏw/Dpp0\tqqq ~/ʊ 0ǎNZ#,, 1114i+˗/ajj{}ay~hݺ5:wvX>ׯ_Ѿ}{tA9UV"pg K-11бcG߿K.]s!''xmVT>XbE7\̞= ,@tt4޽{$$$`pvv]Mo=`͚5HHH@QQvZ@޽}aeeC!77m۶%@[[ߏ[ٳgRqiB!D~6X&:%Hdd TmmmtK.722@%455aaa+Wle$%% (c…033.?*33]{{{cǎ|{,YRaފ#)o /@Vuss{<% t5 28\0\8{13%V`;'!!8x{{ypq8::(RWTGҥK044Ċ++W𳬳h"ܾ}JQSI.|cll/| 033˗/1i$X[[cҤIx|ܾn:Ɔ!/JyϞ==&K#Bbjc1.)G"s̼=z$w999r ~gx{{#33Sj%"ynݚx qSn$deQ?g"33ę3gаaC 4H鼁8H0\NELp z1 [n֭[EEEb7ԥYf?>N8{:ŋf͚aϞ=b3ԍߢA󃟟X[oTAFapyyׯL_+tkii!$$Eajj޽{i@M7oFtt4&L V^tt46lBǣ˔ ]VR}$egg[E1ppp@6m@2_26_^$ۢUQ:::6lߏ'Obر8y$ 0b,eVJyKV0\NELp !\֭ҿSZE7'{JXbbbVZa„ 5ɻMew ȑ#ajj?/^BXXLMMnc2C9رcCvϜ9P$%%!??-Z=fΜ)3"Xv-.\3f̐)%oCY6oތp899aΜ9M5jܸ1.\ V/%Bȿj2SSS<~nB[nIkddgϞرcRRU[uQq> 0ƐoWd$SSS$''beML]\\  qQ;G+U.||| tȑ#z*B!!oʞ_~B;vc7?P BM͵#Bj6vZ$&&o۷/ Ѥ$#-- [lOݍ/,OII ?իWiӦJ~!99֭S_ 46QTT;wয়~XE133CnDDDڵ+,,,*$yJR$(.!/`eg1QUh,nݺaРA&L""ݻo߾E(1Tnʣ]Ǐs1݊7-- Y7?/FLL .]~ A/EܿEPPLLLKs9P(n8oj7===\HIIAJJ ñrrC]B!b5rfq)<}#!!A.Z1w\MݻwpqqxGVltPG4f=°yfl޼dޕΜ99h ;i#G"..6lؔ[֬YuI (ʊA'zٳgsʫgϞpʦ`mWP+((\ |wrN:aڴiRDc166~1Çĉ/^,X?NYwΆP(Drr21jԨrcۣYf󡭭"DFFvvv WSS>/KTTcwN<ի ?۩S'`̙8wf̘PC___۷oE ~3gĦMf*B!Q`Yywm۶!** ٰ/_.vAްaCa׮]8w^~ }}}tӧOG6m}ϟ۷#55c@iM?&L 6`ܹW"##+++,[ V/ttt[̙3A>}ӧO{"eoo͛#-- ͚5g"oQH0\yQ0\B>>K6loիʬXU puČ33 > YEɓabbt~b,ܪ6mBjj*aXYYA/d.@iLbxzz@*Ι"A׮]xzz"""YYY(,,ĝ;w0g\|={O-66HJJҥKtˊ^(,,ĵk߿˔?~<:ߟOo!BdarO<'O| lll%vEQ0\B>.,.b L6 9r$>s-2qDDFF"!!CWt.d.@B+x5LMMѽ{w.>n:̘1?Ty}ի7lj'|rPtAj/ǏWLyϡ(MMMx{{cɈŭ[йsgZFNǏ;WBj`Yz(X)R"!98=WeYER׮]1fڴiOOO׏߯ ( >FY@@\\\bf)LfͰo>Ɠ'Okkk9Rj0(]i(..F۶m'O Th1;w_Lf̙ULyϡN:aĈ ?vA !$$DU b=zPw!J`,$"88ǏJN!z|l[{ ;v@`` 9"1m4xyyIͲJ^ihh@(7BCC\#BHm֣G~!h5rf!Bz8~8B!4-|/eW@%48FH-FeB!)np믴?eH .U6XFw!zBe7B!T>XfffѣG:[B!^BhB!|W^ի%B!_˗/B!qBQZ BHE{\pRnܸm۶`aرD.]PSB!UY̲ʚB 8r䈺A!p<,[ FK.Ehh(BZT`!UXXHejt' dҪmvލׯ_oƍ?w̙3X;B!zT`!WRpi?>,--c@nn.7oޠE^"yriVj-#GV3!,++inn./^K.'$$ !!AAAX|9u[yAe%իW éSm6tԩjI&rE!^zaFbaa ~vq]|F֭3Yqqqgn +++ĉXn<ɛg||c111K՟K2B!u^ٷ꠲ҥK044Ċ++W <<ƢEpjqUֹ󯘘߿ŢEWM58q}_$AE=R BCCquWC^أ5kʕ+'NmР@("$$5jTܿ`nn.UVbB!ufՔG.^h4k {`llo 4~tuuѮ];/p1zT ¤*j̄T-nQ 7y9I=3g~\|/_?&MWWWԯ__X~= ;;;,\b`ݺuD-*U E1g @+Oehkkވ,S~*IKKq_K!&&hժ&LGGrϋSaB!u<3+1Vn5Ο?G֭[1k,HEECCd5Ҹ}!F /^Ӓd(T6)heϞ=G__'OKɓ̧"88qqq s6lǜ]v|qqԫW+V;~^~~>N87ob000P^ӦMCFFÇQRRqEy*cC>MӗU,L4 /_9urrrZ{x-̣G|rcذa2zjSaB!3###<{ ǎQ NNN{.Μ9{ח[h7oTdddyb۸ tB!.1˄B!^xccc!662g~2 ƕ+W.]L;}&&& q߾}HNN _@ѣGسg1?p%L>n:hjjÈԩSQQQRsccccccz TL4 @ʠyX<:h֬<}v/_{ۢUY޽{[taaaˆ#AAAe"u B(,^pA~?yRɊ[TSl!LܫgϞpuuU2$VA W1`,Xʣ`޼y7o=\C@iܤ$#-- [lΰ¡Cm@{efqnW)T}V'Bj,S$*Ͻ:ummmtK.ʷL555>:Yuܹ3?ٳR,^m۶\]]>|7͡ www޽<ԩ?[Ht0Dz-\fffgdffەTVqq1@KIOv?퍎;%KHU_x`AA||XbETlJJJsabRE{U,Xc֭yf$VZ!!!nnnѣ ܹs}=<<d ҵkWlڴ)ŅY=i(U_.wުB!Farw+tыNeŋHII}c=F׹sg}:zJ*;qBnݚY4$kkk߹GEWU^s *,AOӗUn.N:'^]BLA QUbI~6oތ'NG>}TV|f͚s=V!nSoeB\T_A2֭ Gro_k׮]V]OuB7ֻj4WSiːW/:5T'O [0˺ܟ:E]!"RJёP,m۶[;Ǐ{$uqppPoR&mM6% kג)ӄԾB!E re ?#gΜgQ9sFmm 2$:tZKQVVի)//gذaD3/^Km`J_ju S_n~KII xyyM!.BVV'O*lv8??̅ ҥ"RDX4T$ݻm۶STTD֭bƌ2ij"muۍWuĆ֤?]c:6۷ogԨQh(|}}r ۷olCݼrڼWʹ\d g̙9I b3w\B6m0a{'BԏY_Y޽xb233)--ٳ,^Xmm ݛ=zoLrr22k,۷/ɚH222(--%##Cc]sxq)"##%u/cαU?d֬Ym۶Zc6˺?T?'Oo{Om]_EtRrss)**>]-O]!"¢!RcwAii$|'[8q[nQZZJnn.[laɒ%޿L/vÆ \r5v֬YJ_^^Yt)]v51j36+\| 222g,CqE@9FRRܸq>cR INN6x`ooϢEعs'999sN-ZUNA!5ȕeǏ端ŋW688L5+dz hӦɒ%KxWB;Cu<((}qe5uPꪳuG.]3fL˘sl EU)_Z.ϐsY0a{j)TLU4ˤ /ԩS|1} "22%K§Ywo߾z/L-mL\0\{PQ<7,,񝝝NٟKa{5fϞ}u&~E^^ .]bȐ!zW&6cdcc/֭x{{sQn޼ɴiڤMۆCGGG~iNUL6l޼9#B!ie0|||h֬.]R>S74>ŅСCvѣ} kjZ[~)ǪNMX`AAA,^-[qڌ_| 6_MRRVVVZUWC/c<5 HB!idСC,YYYj]M%+!(;v`ԨQhHɸ˗/ T٬_pΝ?MOqwwg5{ɤMll,s8)cgԨQ=zT {L6ƣOǎҥK:b:ldzcKwC!ANYYY@@@ ZKs0wPERR:5{So߾hUfh%+ޞ ¶m5j_ڥfl'''^ ̝;wxǙ0a?lݺU䖡={6VVVpmY`C vl+44+WBSRo׬Yz*M6GL>]|Mzѣٺu+˖-#&&ǨQjS˜>ƣL8Q9I6Lbb B hTnL ?^-[Bq}oWfڵرC+uxȑ0e9~x"EYFWW;K6*h>B4h'deB!=JRkoȑ˭h5 !:,۶m[]Z!+LRk綾^eB!}&d&]!$uX!8f,T;!BEry:vh\¦MHKK#77[[[ 0c`9Uv}]bb"iiixxx"!f,;r˗/7nBHۄBX›o,RL:u[qq1ϟڵkd.uN:ELL [n1cƓO>i !=;|B ضm| !˖-^z@ZZG':u"''3N8aD!n߾͂ M68;;}vW!GuVLV6!DJHH`BwLNhޣESOGd-jݺu\zcǪƍ͛Yn3f̰`RgeB!%4j]' WVVFll,`kkKeȑj&*oWdRRRӓ^{֭[֐Ʋo>_N֭fڴi4kLgo>:~GGG~W]N)\]]c /вeKoߎn|2~~~mۖ/BKZZQQQ|0zhO͛7y9tߟsҴiӪ*U^mٲ(222hܸ1>,f޾}EGGsNFYg˖-S6GywwwlB`` >BK&˄B<==eU]kİqFqII gϞٳ"g׮]ӧٴiN|C޺uɓ'.77ӉI&Z"??bƌʔ){L6_|OOOx lmm2fܡC߿k>o߮>^f m۶e۶m;wN=7wʊ V9&cpM9eeemGO׮]6m_5G}>}HOO'99QFBq?3{ͲU>~fϞ}aҤIlڴzCy/Ν;;C ה1|p9yd}t2\˿BqS&hVXc8taaalݺ*Zǎ#..ggg5IҔ7n$++mDZcXv-\p}]kef.c/6l`ԩ 0W^yDնǏI&:R&맵=33͛7sQO%K?'55URa.ڵc2i$}}XBLMMs:Q)mB}B8z 222#""//zMҥ ;wȑ#:W5?~ڷoO=GR0͑#Gf$ xKwbVy'hҤ n">>,߿V} SWu֍pfΜujWV [ntޝyꫯo>N0;;ji}||}ϙ3ghڴİ0qի?7oڵ 00Xu̝;W]9~xiEBB\RkrY髦G}TBڻVUѣGqrrb…$''sqvIpp0n⭷ٳ{WBY2cǎj_ ??X:H!)GB^yy?H2̚5ƍG}>XTTTzxxh=V./&*&4=S\rEg$MuLΝ fݻiӦqE>C̈́ hܸ1֭ѣܹs޽{cc&cǎ5o'СjՆ1 0}wS$$$5~wnܸ&Mi#,6YV߷Uȑ#>|GGG֯_qttggg^}UOΝ;wXj{~իW'(((ԯpttdԨQ:uL>ƍ!砶4kUB<@yy9WzNy*$F!̧,vx{{ӻwo&L@rrIBVX#ݻ7ÇgժUZ_04_i```Inj+„ l2 /QQQܺuKrR>C̛͛7OOO… )((yo'DDDX2_.\`ƌxzz2h /^ɐsl> 6;wIe_~%WЌɓ'VkUzjݻ7_Yߝϳ!)GR?O!8880b֮]ƍ "//(2ѡ… U3##CS_bR[gggN>VyܦM*RCƯ7p%@w(00;;;nѣGo߾&Ւx iJ@V"lS!9YVPP)SHJJ"//{͛Ӷӧa\BII 9991k֬ +VVCiӦLD c͚5ڵ$''STTD~~>wfҥ:W#))I&i<0_!!!STT͛7ϵrkڧ>ʭ;wԺP&rjSLL k֬˔PXXٳgywR繦B;B2 _O߾} `ݖYjt X닻;}<㸹+Zl T|߹}6YYY,Y{dffRZZʩS*VVIFFdddxb@jʔ ˗/=qLJ~ȅ (..֭[:t9s0p@c>CW_ѢEP?{ O>DݮFLjRij*vdY||< jOllޕ_6mܹs<$$$pqy'IOOgΝU&\~mGSjSWIF5%z gUE޽;?3wI._LΝҥLm*AycggLiܸ1%JdS$4nXM\f9iUпR_39ɔ~UNmR Ǔ?'N;٦,)GBcUСCO-;󩏐 XQݿQ???"""ԩvvvѡCyvgߟ͛cggG>}X`Anj8q"W[G̐> ֭c899ammƍcZɌU m۶X[[%1 ?믿NLL ^^^㣳ݐ+<<,;VJUcC> ig9Rs˸kPKKKzU Y|2={O}}}ٳ'?Q㕀!N\~ yiF'L!D4ȕe...㏜9sgyFݮ\5ԦM.]Į]LJ2dIII3tPWȗ3l0Mggg.^ӧիAU壪$#sX~~~_0f h_JBӈ#8w{eÆ DEEօv IDATSQUVrM4#I9~ܸq .;wj i?~@9Ddd$K,щgG]}rA233u-)GBO8#G3g@ń!*өqjH̙3ٿ?3f̠yqF=J>}̙34mԠ_֭!!!: EqvvPCQFIRR#G0<K_ʭ['++ ///~+ptt$%%Plmm)--%%%'''u1㕀q71XQSMA^5,L!DݰʲR퉍eĈh+њ_5kF\\ikkkbZ+q%@$ƍyڵ+M4iӦ 4UV,m6Gb+ɨ2cαz/^^^jՊ?GGGueLB8ϒr$)5}~aHH˄ hܸ1֭*i޹s޽{ԭ,ݷo;v֖!C E\Liz/dqƤGU|}}S?/=͛79rĘJB! WAVDDֶZn7x7x}V* Z cW톞cCY{#je~a M^o,)GBԍתKìmFu!8::2j(T'jZU  bŴlR"1(ƞr5.(xxxp Μ9êUشi3gάF؋/Ȇ /&)) +++u"LSuWVB!4КeWHQVVO?Q q#!,W֧z( z/*غu+Gʊ}N:Hyy9i=i׮]:I'N ==]mkyP& m52%deڵlܸ 򈊊5xxxJff&bZIƌW OQT4IB!A,:t(}:R-[dڴiuKR}e.]Jdd$-Z`$&&¿/vHyt¹s xxwԩgϞCg}Fyy9ݻwEɤMll,sd3w\q6mħ~;W6<('wQ]___ cС<@!+PQѣj-uΌoǎҥK:b"mVG!B[dܹsquueϞ=OӻwoLuX{f )GBԣ_~222xL4%Ðĉٶm`\= .$$$m۶1j(u1(///oNttZ&@ 10!+Pq^z*...<3Z3^ Xٱc;vt7BQdhד./Dݩ3UV[;FQQ= 4Hm|\~VZ1h N7#** #?|'jGVo5վB!ĽAN !"YCC>4pڵkGu"ʜ9s3gvCCQ`ooOXXaaa.BVMVmiC++*Gtw^{ OOOKwCaY_!ru,jGV>۶mSoBcl۶˗/[B2!м͍Ç[7 XUBU. d|8!qrr͛t_!Bu0YIbbw+Bܕ iIJJÞCHB!0B!fqy:vh݁/0Ҧ.{'&&I!Dcɲ#G0~xsV!-!7|Zl2nq)bbbغu+3777|IKwM!V/kBQbB9x𠥻ݾ} O6mcl۶ {{{ P!mB!1r+uk۶mR׭K(֭ի;V6n86o̺u1c{'B!eB! K^z^zYw2bccINN&''[[[:t耯/#GTU5Vy855%KknZ絆'66}quZn7ӦMYf:%44777~k˜}vZRRRhݺ5C aʔ)U;իWWۏׯrJ<۷f޼y:ٲe ={I#Ζ-[ iBad7nLv?~<Æ `;feeEy' v:w'N䡇bXYYUٶ ___rrrG>!=B~鉧!ZbbbظqgrY L}g׮]ӧٴiFu'O&++K}]nn. G&ME~~O}ߘ}3}tΝ;!..LbbbtK264i궯_5G>}Nrr2F2!3U0܃|M~ ,\Pj03yd._\'ҥ ;w~ȑ#ն=~8999o߾&R(vΜ9b N>mn QhԨ?H}Dm߾+Vp1:DXX[n5yGa;v8r 6m2ƍʢm۶q1֮]3.\`:m߾=׺8x q]ߘ}oڴsOILL'$==;wV;|dgg† 8vi @ΝuS)mBX} +nܸAtt4III| 0.gTC/eeeh"N:Ś5kjaQFc_e_@ET_B[bb =M&ʪ+'NФInݺE||N0AF}j;%%HɰE1rHtn4dl`޼yt=z_]h׮~}Q6B!,bewC!TGGGBCCIJJᄈtw VVVmۖzcr:;裏HMMڵk:u7bСC< VZsBBheBԭ;vX wYfoFZZ| &M" xzxxh=~'_LjFؽ{wO=W\ٯ2SComm͝;w())Vg?EEEj;c0b}pIcCeQ7M7n[L٦BaY 6k׮7{f„ $''sծ+V0bzYjjGUJKKhԨsWqUϟׯNy|I>}I~:4h}at4)Wn޼\aa!?uo鉷7\vMmgooϰaøsZ/R|||/!iYYWϏ޽{ӿ^~e_,[aÆ /@TTn .0c <==4h/ZPl~~s#B(jnXvCDDݻwUV1tP>s}]Mac}ͻ @oWcVǐWy@wf}rrrosOaMsߕQ~wޕm~BQmL2Ej7UƔ(//ƍ,[ @]Vmq^~e~WRc*#5(ŋhժsaaa=zJHHsj3QHLLdΝ|P&(jjZS 熄EEE|甕HX!իWIOOV9WC ;p6sKrpp`Ĉ1sαw^6l@TT3QFSPP&O[8u_Ljŋ9}VکRU)` C߾}{nܸAJJ :Pn 2tmڴҥKڵVŅ,N<},33SmV͛:ߑ{; ! reY||< jXi4쬪&e5;={d$''cmmԩSM:.TL_ p!s2UbӘU)--ww:m~w9|zH!h;t@'Ore:wL.]>USS ՚R8]vl߾T&MsP7|OAAZ+Z-EgjGBP%g}Faa!?8nnnZlwmXdI}̤SN T0PQ+##R222Xx1qEK̀'CsO?~;wpU6o̚5kxzl=w|Ǹkݑa,?rQ[[[zuY kkk`'@RR}橧bʕ:W9nŸxxx謤2HkO@iu4?9wLkggg5Ev!JPPK,[NҭLVEGGӯ_?FM-ܯ#xxx0uTrssҥ cƌ1mPPdgg3i$<<<4iW\UhWeϏÇ5#GAII 1C W^ :e˖Q\\ /ט}裏 իO?`5*&Lcǎ2m4<<< SN:m _ul3dRR!Dka*WV*0`gU/yyy+\t!C-Ƙ*Q+\l*#5(5ĉ;|0͚5SW !z,%:% e+xiJΚ888`Xx1-[Tor\kkkJKK *ew$ciLRMƮ 0OC1|p6mĞ={3f {졸_|Qk^}|||9sUVi&fΜit} jB߿¼4/3KyeȠq<̚5 {{{u?ׯ_gʕDdd$K,љWWOu:Er -[Y߾}9x :ǖBBTWwRvS +!P+..N+rp ښnݺRm3\2rH[99s~+L/֭[Ǔz?^^^8::Bhh(ZȘJ!z駙1cK.`̙~BQ,+2bZh nnnk/J΀ڴi5xyy~zU5mkkkуѣGsckggǪU [[[OTTfϞ?͛7Ύ>}`ߟ-[bggs=W_L'6668991qDV^]e3///ZjN90|TϏ:uꄝvvvtЁ`~*_=z4NNNX[[ĸqX~As+#ƌC\\EEEUצ IDAT___ϴGrMF5`x%E܋I$_a-[Ʋe7n# *VEDDhmuZ -YUњD̙39sl7Pj+_mghqךOC tL}joµPr>(jH1Y}m\)+L 1TM!(8cla3 Byٰa_~%$%%aee `x%E!BA,߿Z*//2~'uNMW䅸#nBB4 ...www?>l ?y)..֩sfx%E!BAކL޳g?<ݛ)Sh]aBHX!*s+p_&%% ^x) 15*BIz*...<3Z3^ A0~xƏon!52+++tW]%4!j>?c+Vw^ 0`XԤlݺe˖/d͚5߿WҴiSzy}jՊuñc(**#88AfϞ)))ܾ}www,X!C ꫟666$&&Tܒگ_?}R,66???bƌwDGGsa&N AHLLtw^zY B5*Rn ?~Zpc!~<+Lzj֮]ˎ;BPFIHHSLp>*+VfwF^|ڶm{$ WWW@EѠh+˄B!!((ݻw&K0ѣ-!]L&DŽ{dB!YJ믿N`` ;wd" " !LQRger%N!.$~"B!a2WWW^z%sV!D WIB!0'<==4nB! رIuwwjN(6]m_HZZrB>Y ! IBQ|Mpz9N]Oݾ} O6mcl۶ {{:=B&ˤvBԯ,Ck۶my➱n:^رcmƍcͬ[3fXwB!,&˄BK:3BK)++#66drrrC2rH]U*oWdRRRӓ^{֭[֐Ʋo>_N֭fڴi4kLgo>:~cTuNlBTT4nܘg}YfU,::;w2bf͚E~~>[lgϞ899yٲe <&]!ݫANZSٹs'~-nݢSNx{{+?ꀾxM=!eV_)&+HڡbbbظqgrY Lk.HJJlڴ ޺uɓ'.77ӉI&Z"??_kRƯOHH7oTSVVFxx}tڕiӦ_SXXH>}tӇt5j- 'j0==## ∈2Y\\V a^Gaeж}vVX;%%%$%%dnjdֳgO;ϟϕ+Wشimݸq#YYYmۖwyΝ;s9,X X~~۷oO\\vvv{1ƯOvXh?0k׮%..,"!!۳b u"055Ν;Fٖ*eBqt9qɓ=z'''.\Hrr2ǏgΝs-z-Ξ=k^߿kC;vmT.&}']RLzm6?nn4H$L||F!b+▷#GpaY~2qggg^}U4iªUXj|َ-1uGҘ[\t7RjRΚ5~4O4i<&C뱲 _~1mvv6ݻwjSOpck:>H"PCbQShCBk(ڢ#5gQ%AƖXCIPs"g\;ɽ/]8)y~kJ,iݔ{ŸPq[nQ@㵛7oX-bf#""ϗrfDBM:ud=vOr̶[t߾}L<ד-[6ٳ'ofܹggg֭ˠAș3U|Ֆb,\-[?~4io-L- P['w~+Wrqbbbȟ??գW^58cqfbǎܿ &b"""&oooؾ};| f,]޽{[,狏$yld7%-361k&f$5^Νɓ-voLے;*O<Ysƍq 9Ç9x cƌqƩkjt5f"""x!;:uxWϟ3Z(UYS7bӶt\/Òe(Ni{B urrBnMj2ҥK₿?7Cx⸺ҩS'L%?=Tt˖-ʔ)%J`ȑlܸcFJ|;w/_M61m4Ə>>f?Y4H阶>sk_NΝܹ39+V0=*Vhv ӳJHdE^Oҍoyi.ebg|7T\{` MI2|pʕ+ ...,Y@>3c\~hӦ /...ԬYaÆ%yɓ'Svmeˆ;wfܹV26w,Z???<<%J"ʨ⫉ʕ`)TNNNS^=ThVI̭{x{{憋 *T`رt7)+ϟO6mȓ'...[F/!XэW?-[W? Ulwd[HM崐N` ԩ{Ң/J(ݺu0[N4hP>m۶p{ꅫq(ϛ7۷s GÆ ֭[]뇣#[lxzz2l04ib6n̚5+W5L݃,Xm۸v9sJ*Ӭ~j 8k.(]4;vٳ̟?+VPfM٪qL:]vѹsgԩ!H&pTBCCСQ7""1z%͝; fNŭZG41$$Y!!!-"iN/"YJfNjH%V\^++dԩXTLDҋjd-,KC u*~F@:$ODDD2,#"""|Kdُ?""b#͌I=Ǵ>U7GD$\R""""""O(jifH CHn2!DDDDDDDD2eO>aǎ?U>x 3gdŊӮ];ʔ)CJ2>>Cy))-""":@.-ڵkor5-ZgzfիW={6wݻ+tܙMblݺ7n?~4h@ɕ+1˗3yd"""puuQFטu#ϟ͛|2Δ,Y-[ҪU+c%{xx3`ʔ)ܹs$dm{JםԹX|9ժUS`A<==Y|9:u"w=,Mݼy_nl;uÇ'..-Zp]{=Μ9cr ߿`rav=zpmbbbXj="((3gW_ccc__wM&OLTTY*-ۚhj֬iZ͚5ٿ?7ouv$""YGTruuxtЁf͚epT'҃*Y IDAT爈d 2ŋsuʗ/իٹs'Ƹ3gPHٻw/ .pœ:u/ŋg޽]m6իW0c Ν;2d+V(!D޽QFu'uݻw⸦m1""|9q#FԚYy0`3fСCX&~GHbȑ#AAAgJrQbEy:t([n8A(V,;wfƭ[hӦ ]֦;v숋K]58+b6FDDmSL6ol,_dI&Gv}`7)\cɓ5kp}Μ9øqR}mZ[״-5;EDMV.]Jdd$OQR%o#GXl{1f;7'''VZݻ޽;;w4)afhi&ձy jժѸqc6oތݺu3k9lmc̖f;=UMu҅|Aͩ]6aaaf?PX1.^H׮]k׮\tbŊ.L\S̛ĸYgklٲѲeKܹcoٳ۷oӪU+R;K֭[)[,4ij1{$hNzS5z2fYf)\0cƌIq /A4hP㒪fm^Yrnnn 2XBx[ڹs̉? .ŋ)RxۡCѣ/|""YAIS'z$lb~BVǦT,)ϼ;,^ӠA6n܈Ş;Æ # cǒ'Oׯo6ƞs(&>>'?3oooؾ};| f,]޽{'Y#,署爈d=tL  1!!!*T;frt""PB[.Ս_leO… ݻ9r;w74뺘+WN:_2fVj6ڞsڈ6IMj#"""d2bꏤ#Gdڵ\|˗/vZFI3;<LaIljƍL6 OOOZL֭#00E:{"Ep-ϟsڈ6Iَ5iyO6lHn,Ϙi͟?___Wi{*UcŊL43g}S#3gw^bbb(U4lׯ_?ٲe ӓaÆѤIb%[lq-J:uII{ڸqcNʮ]ܹq,cf """"""""2 @xxկS/1WWW/Nh֬YFl/i!,,}兟_SD' 0DD;JdA7'N`Ĉʕ7|3CR<̙3Ybk׎2ePRM$ՒjHH\(Qo6;w5K4Z8}t:D/_9x`t7OD$+SLDD$ H<͛L:7dɒg&Y3߿ϰahӦ חO?+W1dGq:ġCشi!!! DD[Js%#y2`6nȱc2;,eѢE\v}]-[ƢEիW&F'z!=Ç3gIf6HFQy}Wxzzh}xzze>>>xzzyf~zIzyL8h:u* 4`ԩ6!EGG3c |||Q-Z`>7o2i$*T`ٳ'ƶ˗/̑#G9s&pucS>|8qqqh¦3׭[G߾}yWYnnnnfksYݩY&}L2Vwi̙Þ={qVZݛW^yb\;w>̙3ԨQ[Zg:Y%af̘ٳgɟ??uԡgϞVLNF=Ke""+T?СCY[[nёݻw#Gx7ȑ#˖-`Ȑ!޽={0o<ve'OLHH%J`ƌV6͸Zj4nܘ͛7Dn.]H^{5BCC駟 RJ߿kc/^)_f;^z5[fӦMܺur͛Gv잽 Iĉ{Ѷm[ 8_E\\۷oCI|||Xlϟ'66(=ʴihѢY"%eԨQ˗~'L3j'OC\ʕ+i֬߷ cHFSLDDi L֖ fjOܹs-[Ï?/YV~}P|y6mĴi?~<wM1ɓ';fͲ: '''*W̬Y,G32eD%9r$Ku 8bŊ#G?MXӱcG\\\M ¸umڴ!<<,Pzț7/[l!66xܲe ԭ[(^L3*LcD_ѻwoݻG׮]ٺu+|״k׎Xk1{ `>vX.\ ((8ٱc˗/xDFF#̝;GRti8z(ǎcժUT\xfϞmν{h߾=[n~ѣRT)O-ѣgFr1>>Aqmc6s\2Vرc|w4jԈпn޼i?裏QF|?~oF͇~ȟi5sαi&>LPPo$HݳJ?F]ǏwMLL }5dhJ5Hm޼WWWzꅳ3=8Yh$j_NΝܹ39+V̙3_R gN||mQ_Hn*T]7peҥKsiclK#FÃ+&L&M2bY#=z0{5ѣ{K}Zou=yV %־$YRD$y{{s!/^̽{]6kf̛7wK0|بs81ݫW/ 9x c͚5iذ! 4-u_?{F#Gꫯ&ORMK6brN_S3M,RmyoO""O3, ht2%jժ`,MWž{?~O?~ΝۡCk؜9slޣH"ܺu盽fJqqqӦMӓ={cM6qD\BLL &L(5kp}Μ9øqle˖xzz_Mҥr uȃ^rSkTyR0q+V`Æ ̙ /X1JMqwwJ*L2>w2aq6l^zԫWݻ3k,~$&nݚ9sp|2VW^x{{s'oOaÆԨQx2Q&L˵6Wwk>`m)ꟘZGJuƜ9sk׮5,Y&M/'OJ*EÆ ooo.]Ğ={gϞ=H?}{R߿x<+lV?0I꾛>IZΜ9sQQQI5}V&)]-f2Yd,Jey{{ ,K0qIooopqqB ;ݻgآbŊL.[gUR???⌢x@pp0*T'''ݩW_~̩|h"ɝ;7`4mׯ_?ڴi / 5kdذa6 )W...BIDATPdIeQIIXע=۸qcraή]ȕ+U$)n]|ܿ}ҨQqĉug͚<yfG۶miԨGY=V…iӦ ƍ7YB.I'g46:tS<1rӄc+#|Mcǎ4n8.&^^^DFFFժU^;qM4H"ܹ 23L^CLLnݺ\xoҥKcmhjۓ7ngΜy|,_QF}АЂ e&qqq̛7~^n]9¼y]YGCӲw[jE>z옩yVZjf<MfKdֳ(Y&"""ϕ ,HHH-$$B Y<(Xǎɝ;7?3>|}'|Ygɒ%+W'uC_3qD_ٻw/}@1… ̚5X `^paqBqI `${/-Zw4u ĉ27|ۓڵkK.套^bԨQ& .̚5kزeoG}ӧShQڶmkС9sd߾}|:uXN:|O?[u3%;∍R _~9sX"## .\??cˌg)"4LDDD+nnn9?uڵL>ٳgrtKL:޽{gQGeavƌ:?<+¨Q׿Ŝ9s,gW\٬yEB:\&֮];Zli|ݽ{w 1K$d9wF>ԩSf7^zl6jjerin߾?~H!gΜ7>SUfQklƌ|lذl{7oƶ 2eo SL1f^㧟~O>fוgЈ#߿?֭3۞7o^ΝKΜ9SIN3DDDSjUzĉ8q"{NрHBcmۖB -[6rMڵYx1:t0yѶm[-[ƛo;Δ,YjI /2͛7gѢEK۷oĉ)_<...ʕZj`g$lBCC}r_|@RȞ=;NNN/^[$oOb\z;ZԡU\~jsM?O(Z(ݺucӦMV;6lؐuѪU+<<>>>Whh(:tm,">Lf$:+spp`ʔ)Fm%K}->5 ?I?,Y ҵkLLDp,/%DDDDDDDDDK2R7Ly\2Cy\mfv""""F2yev""Ee""?,N5DDDDDDDDDK3DD$KS2̥f"""QLDD4(ddIQ&"_~/ d3fDi*UDDR2+>A6e|||2;  J$A̋%Kfv""I2LRLDDDDDDDD俴 SDDDDD8wS}o%""+o?1ED٠e"""""„ 4hS}رcҥK O|\y6(Y&"""""?Icbb1c(P5jӉy㋈H֧d/Y7oҴiSc[ӦMy&k֬DDie"""""ỴGXr%{?$[l+VӰaC111Z{rMC:uhݺ5f><γo>;Ξ=M3N>m?Yz5'O$((GǴYlbkL,_իWm~:6m޽{'}ݻwCJ,SR%~W[oeuȳG2,`Сk<|;w`[#1n:N>Mҥ֭ŊҥK̟?_m۶ѰaCR=̞:ƍxWCvel3c櫯">>3gΰk.~w9@tttsgϞp1m3痒e"""""YLΝ={6ìXwyf͚j|2@ϟ?1Ys-Əϙ3g,^Ov_{VkƈK2;$1Sf͚TXuV~7/_ywe)%R1Y̙3g(X ժUhѢ*Ux^{j66y~)Y&""""ʕS~}N>;}oXx*P.]b֬Y(PੈɚÇa}_|ׯŋ/hZTT1FDDoiFDDDDD2L>}cPxq^yeoӦMٳ~$M\tܦm1""2,UV̟? `ʗ/o68qsuu% ݝ۷oS@f͚.1Y;oΝ;9s&3gδ8ٳgT}*UΩSb8uUVED٣e"""""O ,,,C4jԈ>W_}ggg)Z(ZwƸ9r0zh5kFptt$W\TV/lU.]ёtytB͚5ɞ=;Δ*U}Ҷm[6mڔ\cZȞ=;?E?39rf͚v_<[S)""""ppp`ʔ)PdIٰb V^͌3ڵk|ѺuLWɒ%Yp!]vDD2ynlْ~zc)P͛7DDie"""""/]QK>?>ٳӻwoƎK-ضm׿puuDDid 0. The dialog implementation is responsible for calling fixup() as it thinks is appropriate (e.g. always before calling validate(), only if validate() fails, never). Dialog implementations ====================== The new feature set comes with a collection of basic dialog implementations, which will be described in this section. ezcConsoleQuestionDialog ------------------------ The ezcConsoleQuestionDialog is the most basic imaginable dialog. It asks the user a simply question and expects a certain answer. A typical output from an ezcConsoleQuestionDialog object could look like this: :: Do you want to continue? (y/n) This dialog implementation provides a set of rudimentary options, which can be used to customize its appearance and enhance its capabilities. For this purpose, it comes with a custom options class ezcConsoleQuestionDialogOptions, that accepts the following options in addition to those provided by ezcConsoleDialogOptions: text This option defines the main "question" text, displayed to the user. validator The validator is an instance of ezcConsoleQuestionDialogValidator. For implementation details, see further below. showResults If this boolean option is set to true, the dialog will display the possible result values behind the question text itself (retrieved from the validator). If a default value is provided, it will also indicate, which one this is. For example: :: Do you want to continue? (y/n) [y] While here "y" and "n" are valid results and "y" is the default result, which is selected when simply skipping this question by hitting just . ezcConsoleQuestionDialogValidator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The interface if ezcConsoleQuestionValidator inherits from ezcConsoleDialogValidator and adds the following methods: getResultString() This method returns the result string to be displayed if the option "showResults" is true in the ezcConsoleQuestionDialogOptions object. Concrete implementations of these interface are: ezcConsoleQuestionDialogTypeValidator This validator checks the result to be of a given type (e.g. int, float). It optionally checks if the result is in a given range (e.g. [0-100]). ezcConsoleQuestionDialogCollectionValidator This validator checks the result against a given collection of pre-defined values (e.g. "y" and "n"). Beside that, it can perform basic operations on the result before checking it (like strtolower()). ezcConsoleQuestionDialogRegexValidator This validator checks the result against a given regex (e.g. "/([0-2]?[0-9])[:.]([0-6]?[0-9])/" for validation of a time value). In addition it can perform a manipulation using this regex with a given (e.g. "\1:\2" to unify the time value given). ezcConsoleMenuDialog -------------------- The second dialog implementation shipped with ConsoleTools is the menu dialog, which is an enhanced version of the question dialog. The menu dialog will display an ordered set of options and let the user select one of these. A typical menu can look like this: :: You can choose one of the following actions. 1) Create something new 2) Edit something 3) Delete something 4) Do something else Please choose an action: The menu dialog also comes with its own set of options, the ezcConsoleMenuDialogOptions: text The text displayed before the menu. selectionText The text displayed after the menu to indicate to the user that he should make a selection. markerChar The marker character used to divide the marker of a menu entry (e.g. the number) from the menu value (the text of a menu entry). validator The validator must be an instance of ezcConsoleMenuDialogValidator. ezcConsoleMenuDialogValidator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In contrast to ezcConsoleQuestionDialogValidator, this is not an interface, but a concrete implementation of ezcConsoleDialogValidator. The menu validator offers 2 properties to determine the menu entries: $entries An array of entries shown as the menu. The keys of this array represent the markers of the menu entries, the values represent the text shown. In addition, the validator can be configured to perform a manipulation on the result like the ezcConsoleQuestionDialogCollectionValidator (e.g. strtolower()). ============================== Enhanced handling of arguments ============================== Design overview =============== The current functionality for handling options and arguments for a console based application in eZ Components (mainly the class ezcConsoleInput) has only rudimentary support for dealing with arguments. The current possibility is to either switch arguments on or off and does not allow to specify the following things: - How many arguments are possible - Which arguments are mandatory/optional - Names and types for the arguments. The goal of this design section is to provide these 3 features for argument handling. Clarification of terms ---------------------- Parameter ^^^^^^^^^ The term parameter is a generic term, which covers options and arguments together. Option ^^^^^^ An option for a console based application is specified using a short or a long name and can (optionally) carry a value of a given type. Short names are built using "-" syntax, long names use "--". Options are already handled by the ezcConsoleInput class, using objects of ezcConsoleOption. Example: :: foo.php --save "bar.txt" -a "--save" is a long name and the parameter carries a string value "bar.txt". "-a" is a short name of an option, while this option does not carry any value. Argument ^^^^^^^^ In contrast to an option, an argument is not specified using a specific name, but by by the order of submission to the program. Arguments can only be given to a program, after all options have been specified. Example: :: foo.php --save "bar.txt" -a -- "baz" 23 "baz" is the value of the first argument, 23 the value of the second one. Arguments separator ^^^^^^^^^^^^^^^^^^^ In some cases the semantic for specifying parameters on the console is not deterministic. Since the algorithm used to parse parameters cannot handle nondeterministic semantics, a separator must be used to determine the border between options and arguments. The separator used is "-- ", which indicates that anything following it is an argument and does not belong to the option before it. The seperator is not mandatory and must only be used in cases where the parsing would not be deterministic. Example: :: foo.php --save "bar.txt" -a "baz" 23 foo.php --save "bar.txt" -a -- "baz" 23 In the first line, it is not possible to determine if "baz" is the value for the parameter "-a" or if it is an argument. The second line clarifies this. Basic design ------------ The core of the new functionality is built upon 2 classes: - ezcConsoleArguments - ezcConsoleArgument The first one is a collection class, which takes care of holding all arguments. The second one is a struct class, which handles 1 specific argument. Class design ============ ezcConsoleArgument ------------------ This struct class represents a single argument and defines the following properties: name A descriptive name for the argument. This name is used for 2 purposes: - Displaying it in the help text generated by ezcConsoleInput. - Identifying and retrieving the object from the argument collection. This property is mandatory and may not be left out. type The data type of the argument. The type is used for validation purposes when the parameter string of the console application is parsed and is indicated to the user in the help text generated by ezcConsoleInput. The default for this property will be ezcConsoleInput::TYPE_STRING. ezcConsoleInput::TYPE_NONE will not be allowed. shorthelp A short help text, which is used by ezcConsoleInput when generating a short help output. A sensible default will be set for this property. longhelp A long help text, which is used by ezcConsoleInput when generating a long help output. A sensible default will be set for this property. mandatory This boolean flag specifies if an argument is mandatory or optional. Since ezcConsoleArguments is an ordered collection, all arguments following an optional argument will be handled as optional, too. The default value for this property is true. default This property carries the default value for optional arguments. If these are not submitted, the default value will be used as the value property. If no default value was explicitly defined, it is null and therefore the value property will be null, if the argument was not submitted. multiple This booloan property determines, if an argument can carry multiple values. The default here is false. If this is set to true, no more arguments may follow the current argument, since multiple defines the number of values to be undefined. If arguments would follow, the parameter string would be non-deterministic. Therefore all following arguments are silently ignored. For arguments with this property true, the returned value is an array. The default value may be an array, too. value This property is not meant to be set by the developer directly, but by ezcConsoleInput while parsing the parameter string of the application. It will contain the value submitted for the argument after parsing. If this argument was not submitted, the value of the default property will be set here. ezcConsoleArguments ------------------- This collection class carries the arguments for an application. It keeps track of the order of the ezcConsoleArgument objects and offers 2 access methods for them: - By their order (using numeric identification) - By their name For these purpose, the ArrayAccess and Iterator interfaces provided by PHP will be implemented in this class. ArrayAccess will be used for both variants of access, while Iterator will iterate of the numeric order of the arguments. Argument names must be unique. The registration of new arguments is only allowed by number. The retrival is also allowed by name. The class does not offer any additional methods to deal with arguments and purely relies on the given interfaces. Integration aspects =================== The current design of ezcConsoleInput is not designed to handle arguments in the planned way. Therefore its API must be changed slightly. Naturally this will be done maintaining BC. The following changes are planned: Property $argumentDefinition ---------------------------- Since ezcConsoleInput already has a property $arguments, which carries the values of submitted arguments in an array, a new property will be introduced to carry the instance of ezcConsoleArguments. By default, this property will be null, which indicates, that the old manor of handling arguments is used. If ezcConsoleArguments is used, the preferred way of retrieving argument values is, to use the ezcConsoleArgument struct of the specific argument. The $arguments property of ezcConsoleInput will still be set and contain the values of the provided arguments. Switching arguments on/off -------------------------- The ezcConsoleOption class allows to switch arguments on or off for a console call to the application using its property $arguments. This behaviour will not be changed. If an option defines that arguments are not allowed, if it is submitted, all defined arguments will not be allowed. It is possible, that this behaviour will be enhanced in the future, so that options can define a filter rule for arguments instead of a boolean on/off switch. But this feature is not in scope of the design given here. Usage example ============= The following example shows the basic of the newly created API. Using arguments --------------- :: $input = new ezcConsoleInput(); $input->argumentDefinition = new ezcConsoleArguments(); // First argument $input->argumentDefinition[] = new ezcConsoleArgument( "infile", ezcConsoleInput::TYPE_STRING, "The file to read from.", "The input file, from which the content to process is read.", ); // Second argument $input->argumentDefinition[1] = new ezcConsoleArgument( "outfile" ); $input->argumentDefinition[1]->shorthelp = "Output file."; $input->argumentDefinition[1]->longhelp = "File to output generated content to. Output will be printed to STDOUT if left out."; $input->argumentDefinition[1]->mandatory = false; $input->argumentDefinition[1]->default = "php://output; try { $input->process(); } catch ( ezcConsoleMissingArgumentException $e ) { // Only the first argument will possibly trigger this die( "Argument {$e->argument->name} missing!" ); } // The first argument is always present if no exception occured $inFile = fopen( $input->argumentDefinition["infile"]->value, "r" ); // The second one is optional, but has a default $outFile = fopen( $input->argumentDefinition["infile"]->value, "w" ); Generating help --------------- :: $input = new ezcConsoleInput(); $input->argumentDefinition = new ezcConsoleArguments(); // First argument $input->argumentDefinition[] = new ezcConsoleArgument( "file", ezcConsoleInput::TYPE_STRING, "Output file.", "File to output generated ); // Second argument $input->argumentDefinition[] = new ezcConsoleArgument( "bytes", ezcConsoleInput::TYPE_INT, "Bytes to write.", "The number of bytes written to the output file. If left out, everything will be written.", false, -1 ); echo $input->getHelpiText( "Some example program." ); Generates: :: Usage: test.php [--] [] Some example program Arguments: Output file. = -1 Bytes to write. Open issues =========== - The access of arguments by number and name is comfortable, but (as described above) not reliable, if 2 parameters have the same name. It also makes implementation more complex (if a parameter is removed, namesake has to come in place. So, do we want this or not? - The property name $argumentsDefinition is OK for the definition part, but does actually not make sense, if you access it later to retrieve the value. Any better naming solution? - It is sometimes sensible to allow that for 1 argument multiple values are submitted (e.g. if you expect an undefined number of file names). To resolve this, we need to invent a property "multiple" for the ezcConsoleArgument struct. If multiple is defined for 1 argument, no more arguments must follow, since the algorithm could not determine easily where the multiple values for the argument end. Do we need this functionality (now)? .. Local Variables: mode: rst fill-column: 79 End: vim: et syn=rst tw=79 PK!>5AA$data/ConsoleTools/design/console.pngnu[PNG  IHDRHg 3X IDATxˑ6ФA1t@1AȄƁ!8l?A3?fx`Ӷ jvo7+5M=S4McXK`TO`TO`Tov`4MCkvtj8&<.դ>k1XJw ' šBKAomqpj MIg$s863ּ U|7MLE}?)e xVuL6sOgueΥQ \J"s))ʏ.ZcfEf.%}]my MӸA<g6+cQ \ӳ5D5pY"24Q \/|_^.@LE'''''''''''''''q`_ j߶mg8*γU1` nya.ol2I~vae7}&r#gIKw o+ij`gg%c㢑~JSцJ5k)) `&Hڔ/Ih{\@6 dgŵ23^9LM۶MӴm{HHiܠ P76@6@v l&w u|d6V(:ŋ3g:b*ZmwB#(3P'Hf(el {u8]&Y/?ZUv2ؾt/uAvu0&h6kǼP]m5O0:2Sф(%g]gY| ve&HK$'Y]II} AmFm~}ivL_״m4M۶g`iܠޖMrM5_ݿ+ Xi垇XV&&3Y[9Hd 1v@}0bbQ TgMG򂖮Yؼ qf`xYy$D;kbxWPWE8qG`TO`TO`TO`Toq.>Yqd\zM3qz__-~ @E6lS+c̰V|fr^e8mxܟ(tO)<|ll-DXzvvn |׫ l?-;]ϛLEIn .O~XNr67̔/iV+\U8LWjO S2Ԓ@4g gZ;ޠ↧x,~ieX"g֜) ϳSњ?9VlLùC}Y&$WiwcVaA~S鶓Ǫύ(D5 2|%x$2Vd`??w_~[BS2 sISG5+%T4r&}\E`}SU)l'_Bi۶i5-!/_̪4 p81b080X}l lꙊE9{mY`= V.o'V ~^*p`;,| 4 6!G+L\+{Ҕ ~5MTL ؖN{1 K3՝ 8>L^?Qu'px<8Yߤ8BiZPjVxXk}a#񔶹KuTJ`՟oxڝ%kN\3ʽw=ٗ#6Lz [ZD5p$ <3a29O,^0`ٹ0_~-.Ό!`ha48LӶm4VЇi, g>ʀ+[y4 p81""'V%cߓ[#`FY3Gc`4~dֺ7c9{l%ȽY|rfiۙxIRhӱ/w K!ۙU3k(O &(ö7˚ps/y&Iłg^cbAf{wllye7#n> i398*6yؕ|m}.%N֍0+O܁Cxcdd0s+|>H.B`ԡ$Gyiֵ.9 1I>Hxd=8ߤ8ro܏d8xJ۬eXF`T`x.I,e62+ߗ|W 31}+yK|b ^\8#Gņ3LZ+Kɗ_ca;d25<3-Bt-lU='à%yP`0`0L*Ɩ+⠫|}vG.xvrǚ2|6M#c/N~l c~9{k lt6ovVfWT 2]syVPg6n{5^Iv'y8$[V=f,¸g%p6IlIdz㻪w.x/>= i"1<{_LUWp$ @_ayֽ)Qvf],>?pTC<+dQɗf]2 Y}# ł| GD*cCJ;o2ՁzP`_bdr#~$wX|?sl,' &X c.x †Yٞp@ؼRE@a*/|iY_؂ed˶e ҀzV`\X^?p aL8M۶MӴm}M6a&gkv?>5Mu3ۚjXil嗳U^2;k0_M:WO693;H ,dT7qGY#mxmKpY6ZS{H 咼l&d#ȴ̺HfxGX!a*Tzx|E_$WAZ38lU׮q!%PB`+賦Q%= N LΧM>k.1`"6P x~;glw\keiu|k%CZ@ fHV Ww\_f0ޟĥpmۦiڶݾ馉WE&o_)$([e 5|6MsC>S):%Q>\6֔̌ߚqn*uY=? [63 l]}U4`CoܔĪheT4zzzzzfMI p_/R^/dS[ߣYXVvo`cMI6wbtxp&7;9k?~υs _{ ΃ϧAj5"鰑V;g+D6u+|tp'Y%ݣ"=qr|9egr:p0-'dI46%3ھIMc㟜ӏX̺!MU&?72;X0vA/9o^V{DR:䧮[*/ۏ(똀{ߙ71/'ʼnWJbdlю\4zNNZVq8xbXGɄRJV N&dyzc# ڴ&*ZƤ9eb_m֜?*tJI{ ]U*ڮ%ISc9}$:?\pc'~]j` [~/䒋}GW%JH/>f ;ހۻ򉾅X"&8'+ &jb +yE+6yla/x8.Yd,s7 uOgc%we/n o@\| L2D%%ǐMxnf$LL |’IqfJ->3+4& ;u?pSp¬ign7Oa.OpW>ޑ_{:roPӗ{sfqSwcv0+{Tm/\9R#F7HɩceJJ I6!ɫd㗒1\P9gPrO-Q4V+x&{86xbWͿE+X0mwl'%Lìgc)L8VZpr'cZ2\_ SX],KL -GI -%fHPˤ#JI~V\aUY"oa򙱮'ԏʥvÁőXXTJ"x$2fe ꫢH~L2okwUұe#9KSWE{?Jcx>U~~DY{]iw{xaVmRZ~U0G IDATTS Q rt`ۯugW2Hq-u]vPLyC.H0+T'; ;.Y`FlK//8|XᰅȲ܃#PFcjr`c;ɰpr os.&@ql~eKsddTg^^e#plUO%R k-Ϫ.99:v<Ґw1Wr{S )>Â:T♙Xd#GO\md>-_pYaeil' \՗{N~]ĕvcw]yW~`ӗ{wnN ҕC{~F|/r<4^kqijL*˻۰vVv+;y||#>ҩT ?B~J63oT/Zlphn ,XsgؚdF"6hsK&_*Y19ahlm8zIVLvZ򮓽ۉ i'7h}UIɗƞ| ;}UY]BZ\,rU}36o'dBBakC%2Żs;6}z_ &NtfS~땜T0q8Z88Wc`Ա ɎZ1 ?7;ԩ({X MT##F}&ǡ2_dqO~~9{iF @Ew^Z◾X#hn 00JN*+l '-1K.ȁs_sx6W;&]=޷Q8sha426)^*Z&<k5Q \kC%|~H_f M<{pi_!Ul. ϯ!SѸ .nP_^p 8 W6R7г\ߺ뛊K7;Z*z*жiiQPsƒ$_7^jm%]  qdqA$0,m闸x)Nɽۈc m &iby.J[ttXXc#3`'džً|aEHװVm)YBut• lO@KtLLW,,86ʽ6T;s&>ƶ'IyN ᔰ` bc'e˜x[__X8hLj^&9M`C!Zrj.g=΁MX6ܐE̹=9u v1􁞌 d9n$2Bp3Z̙qi_.nry9.JgF򹔠䜴Cqɖ33c`̆&=f6"?w%6{ /ټm*"6c 3}kD2hqdfтsFJ5NxzG;ࣛן+9}QgYuA@k?,/t& 6>"83q 4M?ޚ*};`486жgʧk#͈mk# l`KbQk6/p{?kܵ8vх4n/c|pؗ/v\[!pcs p?l[Q p؝.[(F`Gb P;s A/86@D5 lPbF]YT\& 8KnZHpN8;xׯ|@LK3:8dF8Q P)% ,> l*,'ȇP;SZLK'n@`#SKT܀HllࢺFxD \WM؜ \ؐj@6&\Tܘ V :}lGIw^kWO !LE!*mIQ6P+ 0ƚ*f9 &IݒBjmπMmɺFT<Cl$QtCTб*Mw\nϢC26pO ]I6pgbk:q \8 i2dlR7P5Q @BlLm:.($g@E PN`68Y6D%` <.E5 l6p5k=|}l N`= z}F c8;Miip0Q V6O6pQ 6@Hl{3\c$XN#؃ LC%؉VL?ؕ FT 0MlkH@`b %8UрRə4(diA#%\Tp0 0$6'@5`>q! dlKn%8XKl l mx,\؆؆3ult[qo `{qc\؅؆[,  7#2;cTa p}`_v^*4*%8؆t7eB`GlC- P p.pe55GpMJ lsmTM`FluvLb@ܠ8Y8x=N+}krw"N!fZ,ޮv}EMG~CZ=gxP=Ɨ_ yfJ+=x{ן5F`D肄a#x&E #|;s;,=np 8`8ədzI|#Q6K )\3 ldQɗSkIL.D&,%٘LJJ^Ó/ Wдm4M۶gi>eo>/_:k}l lt 5sN`T|OFk, ^`'ţx*RS8垁Ki K&kUr}d;iLd0 P$6(Ȑ̒-36 \$)c׷.^X؜Q2|&OLF. c h`&?s@HӶm4m۞=4MsNGm4Mcg['1?>}v_~9u,4=36{73vd>JlrNP/_l8tS26ny/u8ydX~Q+SM, P= P= P= P= P= P=u͹ Ƭp3zӼtK}ɒ Po?+p?/+Y@-6(1,{TO~;xO0[8{؜&yeE5_~ힹY]e){vqz}Ա_47ؼYOiJj]q,CC 69JR \߿Q !ad#qF"hyV|dAWY%cT\26#5]HsX6~?*6GzT4j%1M6~E8@o[] Wx_I5 ]ٝ0*sbƦ\tޭu9e-p_LEvܡrx;n;f$wUngwi|-No@tY~ ap PҰpKIY%'cg}~$y2Y%h6$w٣øbĵF CF•K뵬͗TKn)3 g`܉/36]}/׏m¡qo/_:kFm/ nHHO@6@6@\coeu˫[WnIjx3y^p#6dlŷެ3()|Hb'y_α8(ҟ=mE{kf^ "|G,MG}HjgEb X#ެ6, p8%)- N424:6 n#?(Y+Q|UL> C䔹ngiڶmm۳G\K4?Ql,ygSpM%7ulg-A'PJIDAT= P= P= P=?@ sG0T4zzM۶MsN4 P= P= P= P= P= P= P= P= P= P= P= P= P= P= Pm*> ̺vIENDB`PK!_x!!/data/ConsoleTools/design/console_parameters.pngnu[PNG  IHDR IDATxݱՆ:םA`GvT!L$/&I8`O.4,@ԩ%X6@q hl*^^]mA]V.+Pz^ƓU(k,Ē6Շ{=Nrgh_69?3H.%VKrHQi A]Xl *fJL%8mLu?("*|؃#9][Rvhڏ uEatVի:+npR>o%Wz)UZKr3J1%B,]cC |AZ{Hk{Wע ' z]/+H9? @]V.+P `uX@]V.+P `uXX]SМ\_q h@[asTwE^&~{~fJly*m59=cWpnvkK|ee_<|Gva/kpB `uXhJkϛ?74^4Გ "sEsKnT]Az0+<bz<>rċ31W8+^ )_`sL5TY{/ .^p@]V.+P2j<0r1!5YqHqZ a>j_zW>^V5%>EUәF|ޫѽr_٫x՜N(ݞ{?yov 荢ʖ^1iH'u9f߸"{ҪDT]1CuPj#vn?Q.Kfv`oj+5t}P=({EXҪޫ:u9x A]V.+P .*w̾gU.^ɞwEoϪB GKziX;.VZ\ UsxwiooCzxysyq6du5(9\x;.Txg"<\ ].+P `uX@]V.+P `uX@]V.+P fo }^BC ZFۧ5ٙX1{燿}[i^.+P &g0f\w\ح<_F]0 o>p[.3{*HYZ'N|54┩\͚0@%oǜ#oIsS `F'`Y)`h&NR@]0zG\'fLi.6wX`&C]V.+P `wrJxRև_fFn^nVX]-~ v[4.積ɌUg^i.^EX`EjK\3z酭 .rLQ_UX\tAp:/-͈mr#0.ާ\bK];@]V.+P `uXQx/lF `uXx~&ˍ2[Sun"ꚶx~], k"t]*nq_q~8S*E8|) T5պ$%ĢTG ㆴ}]XQ;vt燿}ؚ\`uX@]V.+P &3ڴux}=eze!ݮsU.Q(az9ãPKrN7aOuţ=C.d8<+b1Plc\~UCT!=RQeP3FXmե'⮢럢LΜE%2RċxcθJ]5/ګ'焙ۼ>>>^׽_? ov~d+P `uX oXl `uX|W~>ROSŶL L{uw]@`.ecił-BRpL;3t#gT_?}>~2/8qco3}jBŀJw^1"-#F/.x+M\.-W5Bjuā̙KO/A82PsK%XP !I aCu%IwluX1wBh@ xWaINe0nƤ3\}ic#' \,/ҡdT:t֮<맼p:8t奋|/L.^X \ L¤6uX{Hb^-C,S\bD<- M]<hM/ZO=}祐A.n<.ˌ >AIg͹}~{̥d< oiqЇxf9kܬyӠxa%p/L†BK0 OYuXDP*eR: {4nF#f[}oQ3JَDP`$ONBTmz1{թ5WבxH0R2 #oal! F#ĩΔ2ޮ!WGxƕ+'2.ʼnkj=3 L3C'9y/~:p W3K/Gj}e̉<AqsS ]9]9b78spst<u\Sxcdj){DS\]ˢu#zҺ̞:bEqbalMsx3^%X<ܤ' }nw7">gȯClc>3xK2.i8v]/W9C|RV %B_6?Uqvpfa*CxFvyZ]:Fk^yXK]y5uXXL]}i\rE oT-zdiV[ t;< 2ޫ r u4<8J]2=rs6rlL?6-o ƿcH.S\n˥4։ 93MCb.-MZrfARA./H xғg>&@\>-޿doЇɡzGxvT=28[ӛ٢Y %NҰ+!ZNu̷4;:2 b-u-X`bCuzƷ5{/`e.d1o5W|_E{xwE*twhHU4-qhb}978>oh$ҟ)\1E6V]KWŐzH]siBMMY*As9lbT379bɱf/P帜Z׭IMOꌟRj/O q2~eM5Qw]RǮTv2}AlrŘ*+n=;汱 w&?zP]9Ow[:[.x]p[:&uXnxŔ^nuY\?n(j gj %d ݺ8kW(ȭv-p ݸn]n03RL]<-@]n ک{{XPXَvfwBP]j%}mQ0vql`\x^[飭RNf& \swź"]B jV=Ū-?GWW;T[,1ni9v9Ld- rD|w+p_B_ .0U]bE +|]JUxSv+|/hPz.ހylE52+FȿBtfFkjR[92ڎw~pB]<9Ʌ<5 Nň}#Ea삕` % fbEX.>T.ͶK0ޫ!|Ut3WLD ́slhS7u{y{YůGRJq5ReX+*ǷP)v|~P|ɌiX|$E>ڇ375DģGx'uiG :Pw1NYR7?v('@gPkweŶ eevVd={ƛwja/L1]1㺴ަ._8fp}+s~|,UdWl1X~Ȥ.^ef%WҗNҚw|r3l,{G]J뮢]zze nzb} Pw' +0- ;;&qfh .8UP+XC]/_;LK)wl L^Jٍ?sqMRF̻h9vQ4ɝ-~? D"8K 8$ĥ)+,8Hksξ2u2ܕ)f1JPw7f%osoњ3[ggVxv)Ʈל"l "&`WK\%2AAJ W*-bn*Ou8H*lz.^Qf6"z.&鏦|>\|Lq`Hf'YIDATcԥ[WR >P8fR'T}j%i%.|8& % 5HE$\L 8o2였!)GKޭSw~/D[cPD9@*/hN}Mra#[5H*0u^,cDf>S c:x! u\Y0 N.yTN2:x+ Yk쪽zIUJ]n{l.]A]VTj@)VvuX@]V.+P `uX@]V.+P 0BfQeIENDB`PK!YǾ$data/ConsoleTools/design/console.xmlnu[ Enterprise Architect 2.5 Package PK!>'J J *data/ConsoleTools/design/class_diagram.pngnu[PNG  IHDR \ R)bKGD IDATx{t/pPk lEAvUUQ[x*HD+:]֭V;:UP@B1(83 iZ-D(JՊ `@JƐp(׵VߝIeeeeִ 46 .6`# .6`# .6`# .6`# .6Ҽ |^̞=;~{fN .e˖eʔ)NަLlD _>k&MC: hTt؈ dٹ &@YlYLR4j2eO:\40Ahl&MC: ht؈ ([oU5\> /ر\Pٳs{iӦMZl+oB4i$M4⋹ꪫrae]wMӡCq1bD^{gu]޽{]_˥oΠ1=;Y4/t4˗/裏֚{L߾}_*۷/@]k׮͕W^1cdÆ 5̛7/-ܒ.,FJ-\pv[jL|_p@QGG}4:uʭޚ^x!WG}^z)?Ү]<#ׯ_֯__?3֮]O>9wyg5koyDz|[.nf̘Ç2zkodݺuN`*++!( Ir9dɒ%W^x!W^yez֭[(p@Fwm2k֬3if\~5kVvg}6sON:| _Hww93a„<ԩSf̘N`@.] . ]tI˖-S\\Cf…u7id?+++ˠA/|!EEEڵk暬ZFO?G}4_2un̻gϞ曓$wuW^z)g}v:wt9Çŋ7{]I>_Һut!˼ym}.]4vXve|߬31cdO-K[.7pCk{0aB]6?O|%;vLͳFfΜYgnrl[> 5[`4iR~r)j͵j*>`[c|K_HoݺuV^]}|=׊=COg]vI\x;vlFniG}/zm 5k:g]vC=?;wn铵k֘/**̙3sQGU??dʕu>dܹ]r]}O~*?O̹.]tQ~_k-浩ͽw6V\˖-SN^3mJçy_O$Iɓ'טuc=_:uj='OW\2}:oҤIMV}t峐t{ 80+W_ŋg͚5ygry祢"C ɛoYZ?Fׯj.|ǹ袋ꫯ"O=ToJyyyN=|9[oչ瞛={v>̜93]vMEEEF_+WŋSQQիW'L=kon}Ҷ<ߪ[Q6V~/_{9#3wܬ]6/B뗏>(Æ _K}}x,X +Vȿ˿Ԛ/~ &oSN9%93ceYre-[N:)IrXotA={vV^kfܹ9ꨣRYYYfK`)~_fksmeKVrG殻ʥ^+Vfי;wn$ 2zn̘1裏2xkgh"{l~_%IK.Mt};ȪUrqeԩ9蠃RTT:(SNq=zt+_ԩSsGM6W+IF$ư~Eiݺu$o~'m[xqG$\><0O>#FgϞi߾}:w\k~>|xvuEK^~sI۶m^{?yd5֘8qb{G֭[e˖9#r&Iϟ`)~&I9y%IO5VX3<3ׯI'G5:"\|ŵ-))Ieee^}5k$Iڶm[+iƌI:MM~GK.ؗ$|Pc|J7'NUtAormy~U[\ڷo$Yre4F֭[=>~]cqܭ[1&^{TVVW^$y,[Op$IqqqJ?]r^~_Wi֬Y_~9tHؒ|$6V5^oZcKdÆ 5Ư$3`)Iwyk׮gիWoL~6۵k$IyyV}g$I_K׿|&Ms޼yuֈ^ts9'ƍˢE'IfΜ m;ҬY3f?ǧiӦ9sk5m_zu^y啭Ϋ.;wnaWރ0I2f̘⋹馛r_~5:lذkogz .vO>9߾x~Z󥥥iҤI[c3`1b{wqIq՚+//O&M>T}_ 'z+U^ziڴiN:)I֗7lؐ[o5ɦ5>&M^5׻wZc3my~_fڵ9SVV=͛}"wTСCuƏu d6e5[nIvi;,ڑm/'I:Zsv[5kԘgz .v/8k̙O>9ڵkO /Yg͛gԨQL6-//}){ouw-[f„ kogy'Y >9cǎG}4={/~,Y$ׯϚ5kR^^')));3#Fv|'ڵ˓O>d…… 3`̜93mڴwO}<$ɠA2cƌ|Y~}3dȐ$Ssۖo޽{sw;d>|x>ӧOsL .ٳvڼ++rwn2 SNSQQQ+GK/")ٳgkuh\kGU.]^x! Bw߭qަW}? kRYYYY$>&MCa7>Gy$WywS}\RR?[{?>w^uQy'ҪU0`@/^=5k뮻.7xc~8 G}Tke˖EiժUu /0=\Io~33lذy)..η*EEEO^z)\sMJJJҾ}4k,[8∌1"/~:-̙3'KRTT#8"?yO0!'|rve4o<Z1 ̙3SRR͛g},XVEC-v{p[{r!e˖i߾}?{n馌92I2f̘m~mg::\l'bN?BPÔ)S 4z .H.]2hРBPMe .1c9i@@4iRZ46)@:&Mzi@ 4)԰n:M @c@/_I_=%%%۷o3k<-Z(.--W\+";0+vN`gU^^$9蠃jٳ`95&W^yef͚Fs=ѣGOeeenݺCypt(M\Tf͚^fMF8:uʀ2bĈYfg @CRpT{IcǦ$'ONq))))dl„ |qcgyf/_ &03NxswfΜ9YjUg|N߾}kĭ\2cǎO`3|t-&Mj<{|}yw^~\o~3Ijժ?c,YR[oeҤI7o^Ə6mX /̊+$k׮̓> 6K=G[. ,Ȃ fС[nʕ+k>l?իWw޵zye9SB'3*//Oٳv=wI=2uZcOڵk'I6lP=vee˖;wn~ӟf?~|֮]W8^w]{$IvjUU٧`'ԤIOu' (6֢Es'G_>8k׮͝wޙ}ܪ7ݢuEEEOsU6mZګ>}PpeرI={,wqGW^)++iH_$/f:u$ykWo۷O~2nܸ{9nۦ >걺mk.;vLX\XU } .v$+xG8裓$zkz뭬]6?SRRo}[q}I5*3G?J{SOMIIIx^:u떤˖-:tHOdٲe9skuҥ83jԨ|͵"zUCy2`}ԩS,?ϒ${]G}tf͚y& I l^xбcL0!'xbڵk-Z{[ҷove„ 9ӳ{Yfc=rgNrLQQQҵk ><7xcuUW]Ν;Yf욗_~y]w5EEEݻwF]'tRڴi~ֺO?tڶmN8ƩIeeee<4iRϾ1cdܸqy衇ҹs$o /yW a}[l>;{g&NX=6qgذa yn%%% nYYY3hݺun\z9묳$ӦMߞVZ8;'PvX.zIK.$z*pVlo .)(!CdȐ!NԴ 46 .6~d IDAT`# ݔ)S @ ~/)h`~zSI@2dH R4m̞=;~{ؤBVB'ylٲL2i2e` th`}]l .vB'N믿N:eyg2v(w}YpazI&gMiii9̛7/ӦMKUSVVV}d˗$I^2bĈ?S3f$IFN:%Iwp ߿y{-Z(I{ךg}j@c`'t$ɡZcW^b-[$ׯ_k˛Kk׮\XU 4 .v;WTuhȎRYYYI&[تU6;_fӦMkUյ/ ^{W^y%ӟ/zOS,]4?pWǎ[oeŊرc+VT@cRχw '$I~<ׯς Vq$K/?λロ)))E]T[թbٲecp@dҥ֮B СCc^7;|̜93ϰaj̵j*_~yq{e)..?>:fJyyyzU$ɱ}. . ,eee;t֭[gرׯ_vm4o<ݺuM7ݔ$)**m۶mƏ!C8͚5KӧO}5S\uUܹs5k$I'6m駟O?mVwB 믯1o&Iv}۷W\+bkx9k.2dHƍ7x#;wNysM6r``'|%%%%ydÆ yWs7&I=g=3'N8qb3lذl:\4R%%% nYYYx 7|sn:t\]lݺun\z9묳$ӦMߞVZm׽`{PpӥK@]6W4N$;3䩧5\$w}e…ٳg&Mg}69C2o޼L6-tبz]u\tEձU*-[V=v$I.]Z+תh:\>;F7ߜo\^7|̜93ϰajĵj*_~yq{e)..?>:fJyyyux`RTT]f׶mی?>C Iqqq5kۧO>ktꪫҹs4k,IN:)mڴO?]+ק~:m۶ 'Ѐw; <~mܭk߾}\q;s'e]2dȐ7.oF:w$y7 /L6ml+.h>瞙8qbĉS\\aÆ03v:\4R%%% n]-֭[nȥ^:+I2mڴ~iժUNa/8zkK.I^ ;gEC2dH R44-t (HB'yw:LRSp@tA: Zn-Sp@9s1N .ȤI2tBIN- )0iҤ=zt6m}^:{5׻w̛7/ӧOi>M[SNMqygSOkIqw_.\={fҤIygSZZC9$˴iӒE9s$Iw^+hLtJJJjE [6mjժL81K,I>}2p 8F܌3$FJN$on?5b1Qp{<A@Ek 6H AM*UbAxCjb``bʉ\D:p6ZP% DaYa{gYkX̳_8 ]uUKfҥ\~婪J֭}VJ :tXbY~}CMj =М8?dy ?y+2eJfΜ+2_W$gƍ\/++KhѢZC;fС:th^{3cƌL48pQQQ+W'HEE?sYvm6lؐΝ;7Z۰aC!!KPȣ>|3$iժU3L?>znݚwy'{o BƎ[m8bժUZ޽$+Wl͉.CGĉsw;h֯_K/4?ꫯfԨQZnxݩS_>ÇOEEEx≜viy|F&˓$ o>6'\XMMMjjj3[o5#8"GqD;\z]k߾}MTTT<;vgz]w]wlٲ%Ir9m۶Ypa .L3x`905t :t};v5\kf}C ɐ!CڵkL:5WNݓ$W/1cƤm۶{&`?qѣӵk̚5X5kV***2jԨ&s@3U(˾555eߝiӦM&Lۿ%\$?~ᄡnf)q;L\yׯ_ShI[UUUJ>؎ ,uCܹsK?` \g#F(u`ORUUU^0p,Z(w_cԜ9sJpZjUΝ[M̝;' '\g>Ahn3rRf 1p7H޽w6gΜ,]4Iҿ1@Fbks=&k/R&OGy$ sǧo߾%H ]RsiӦr- RQQnݺe曳iӦ + ) M>=֭E]T]|Yn]O^d{-K]o)Sdٸqcz왯}kҗԨ6,N>O欳W\;jjjݿ}zٙ4iR^}y9sUWM6E̞=;zjtRڵk BfϞK.$:tW&ا \4cׯѣok+Vȭޚ[sMlܸ1_o֮],[,ӦMK۶m*Ø1caÆ$͛8۶mwzϓO>TVV6Y̲eSO+_^eEs3foN8!???I2mڴb?7|3ݻwϴi /dԩ֭[VXzh3{챙7o^/^/}4ٯ͑ P(4U}ѢEI믿>=zH۶m3~6 @?>'tRZj}s馛$?: 7ܐ=z#ȑ#$.y7~Xc{={l͑ f쭷J{}WN|skT?7;;&Im۶{֯_$СCZC4G-KpSSS4IRVV[li_V8OC_M?qONh>O'IVX˾nݺ%I^~F늊ba+vܹsdÆ Mj =hN;$ɝwޙkfwB?wg$I&NW_}5~a^}~IA{;u$yDziӦ曹;:cǪU޽{'IV\٤͑ f.KΝꫯ_r9s$I/7z#W_/[o=z//6 gs=4hPFO|{ac9s˛7p%VSSu9ӧOϐ!CҡCj*}w|K_*u!ӧOψ#ҥKK.Ccǎޫ:\pA:q-ܲt=ٲeKsI۶mp& .L3x~&oep(ȑ#k7>`N{,ݻwO^:Æ ˘1co| ./F]f֬YڬYRQQQF0잁 6md„ ?~֬Y5kd0aBZn]xK-KC)q;L\yׯ_S`JUUUciQ͍ NR8ԕ: \'̜9sJ -Jq~hѢ91v2pf6ѢiY~x{ksҥK$ψ#d4Hbks=&k/R&OGy$ sǧo߾%H EpxyvXߴiSn\pHn2||ٴiN @  R(ӧgݺu袋/8֭K Ñ fmoNsEezv6}e:묌;v$ߟCf9s3eʔlٲeZbEƍ_bn ;ʒ$={vN=tҥӵk ̞=;{-=ֲعgy+V[o֭[sվ&MJmmmշlْc^+Y&ӦM3yhƌ 6$I6ZI# IDAToޜٶm[ƏdRYYd2˖-SO=|+{~`O91cF~p 7o^IiӦzŋsm>s̼k9S]]_|1sI߾}lٲ̟?{l͛ŋ/O}4ٯ.B555YhQO=$ǏiŨQrGO'I&Nnݺ%PƄ 2lذ,X Æ k 7P:rL6-.I~?={6@3[o%IzOmb]}ժUICŊMjw\uǎ$۶me'I:td uדl/޳e˖tw76jժokѢEڞ~/0pЌ}ӟdŊ9vWVV{i߾}>***r<LΝvlذ!;wnaÆb(M?fNKyYvm6oޜ~) 9}:uJ}|'_җ}W_}u.uQ9#RYY[ncgk߾}MTTT<;vgzhNҽ{g˖-Is9'm۶… /\0۷?!9rd~ 5fԩyҽ{$ի3lذ3&7J~^9faڵkf͚U͚5+5jT p82p@ЦML0!Ϛ5kf͚̟??&LH֭KLRrJƍ;3IrW_~%NJUUUJ\Rhn \lvZ:nĈܹsK=I=կ~1 v~2p 81``?ȑ#K`K-ٜ9sJ|xnlڴ`3pPbB!B1>}z֭[.X⋳nݺL>0pp{rYg{)rgС0`@=L2%[lI3lذl۶~VJPyW={vN=tҥ׵k ̞=;@8}ݙ9sf9\qI-[dر1cFz|YfMM*۶mKr??34O~I'|2uuul婧JAbҤI5kVz?m۶M̜93ZNڪU$C+V(5jTyL>=YdInݚe yI:4٫*\PUUU͛͛7̤Ik|ƍ>|+_Iuuu/_ &I T)++KhѢ^ 8T8\s5'?/?|^{p I\2OOOӼg?O|޽{'IV\$CCU.v^Ș1cruו:J<7tS /W^I\zٳg^}Ռ5*_r9?aZn^_R__$4hP./_來x뭷|'}Ieee^x|3ٯϬIMMG=餓r'S.ڷoiӦ*)//Oǎsg䡇iڵ+>s9i۶m.\侅 }= .LEEE.\z饥D \+2?pwyO~s9'奎d \>:v[F.]:p3p2vhܹЈK{./76lX#F: \ֆ 2sL>=/2`jࢪ*UUU@R__{.?2o޼$Ʌ^I&eРA%Ng-Z1vjΜ9͖ Y2dHy|=ܓ /0GuTcUVeܹWZ(̝;3p4+73iҤ|-u}'MuuuFYЬ>Ңƍ?7pC.j~G}4|Aկf۶mi5woFzõ9sdҥIgĈ2w.}nݺu>}zz衼۷onTUU裏.u<>k6=\jjjK}z֭[.X⋋s1N:G1VXqeo=6mj[WW?C̀rfʔ)ٲeKg) Y`A{ӟP(ol4 ={vN=tҥӵk ̞=; v_^zRGHȘ1cҷol۶q+cƌɲe˲ylذ!?3iҤ-[2v̘1#oV>Y&ӦMUW]UӥK|ڵk$k׮wܑ.]䦛ni'|2uuulVYYM5z`ײ84ח:!/s,Y)Sd޼y)//ψ#0`@IJ G 7ܐ=z$IFiӦw-?I'[nI^ze„ 6lX,XaÆ%IN=TUUe֬Y׿_W~x$^Ϟ=C?xVX{'UUUi߾}#֎;;&ImVZ*I2t޿bŊFW^ye^|WJ^77Ͱ~$?%c{ 8ص(uMeee)++krooұc}ѹ[$N.袴k.:uѣ}z6me]v裏%\5k6ƍs7W^9#ӳgό?>7oa͹7կ~]v'?{Wt۶m[ӻwyСC ^|T,]4W\qa}IҪU?`wlܸchW e.8:w^zeʔ)$I]]]~h"ӧOorC=T9sf-Z_ԩyy晍}ʕ8qb-['|mνy֙gwy>[6zn[lҥKtҼkvzo~;'w޲_'L***r<m<+VNkɓ'MΝvlذ!;wnaÆb plٲ+ٴiSn$ɸqR^^_=uuuַ$y'OO?ŋӳg7]wݵgu]K3dڴi,CgV|ݮ]?dȐFLۿN$իWʊ_'*<O,>裓$۶mI;3mڴSO=k6g3q5O~ʜtIy'rueժUy2tД9555X{o>ӦMKUUU***R^^;3C=TRVV$iu;6mJ֭}^ڷo6m uyw<~>ɹ?wy2u,^8O%8qbƎ$??_z<^9rdjC>SKݓ$Wΰa2f̘|(qB8~^ */B>IҧOӳg$o~7j:u.,-ʲeo~3r5{2k֬uY-'F]f֬YڬYRQQQF0[.8\qyd…œ.s'/|Yvm嬳gdz%_X;RVVk6>}sI#8bر6md„ ?~֬Y5kd0aBg`ײ`O|ӟN BzxyDzdɒr)ڶmkԧ>u֥w9cdɒxy73iҤL4Qs)dܸq;$W^yeWTo9??GZjݻ~]~QG%K䪫ʱ-[裏ΰaòtҜ|,xֽޛ??Nyyy֮]=zdɒ%2dHN8ᄴn:[Ή'o13fgv*wuW]0+'\_zo;wO~=zvt)w}w=wOY[￟ 4(W\qE# 6mܹs3u,\0sL>ݻ`( I9st$I3bĈ}\.`ԩSS]] 6, ,Ȑ!CҢaoKϧm۶;qf޼yYxq.$ɳ>[\իWcɌ3 /{^~_7kI>}4Yk5f￟ٳggg>Sk_Z~_ggQ BՓdԨQ9#O?tdĉ9S^^^ze„ I $I񔋚$ɋ/w}7w^6oޜE%3///opm؂AfO?mIق`6믿?hp^x! ̙3'Iv}92 Ȍ3>,uv^˘1cҽ{7gə6mZ_zצMV7kB`4eʔ\uUرc~_;/&Mg}> \sMr'w}S^^?I [NK렃J\z3fLjkk3a„\r% o>I76lXޜp k޼y:th~Neee=vaEGeNȰa2v۷޵G?{sΩIӦM$oM74of:t'e,}fС?׍x [gܹskOc=:, '\™9sf~e-~;7xcz 0 :u*:",,=Zʭޚ޽{g6*Z+{wn'CpIv1ČբEtMիW]wݴh";s}2cϿo1rK|l&Iz+={I'O<`9䐢Av}EKGy'欳7lEǂ&aӧO1T*, J~rEe=HYYYqI_tz|Ф)\TWth>#3w\ Ei3gN뮻(9zFn-sq h$UUUI^{1"Iҵks1p@> <8̘1cҡCuY9Fhž\~Rc=6nmկ 93iҤ+]w]w^t$`9X-ȬYrW^u嬣:*~޴lٲ1b@!ʋ@n;8p*UUUEXl{w;nF{ 8d.vmVZӥKuQ ~GK.y7$C';]v͡+"|BXP>O޽{?1}s=ҥKڴiS7*sOO$MBEXvFn-׿?8blRUUQFeرԩSݵc歷ʮv7MnzO<9sO>?]=Ooy뭷Ɔ 3g6׿5|O޽{FG}4_Iq@3o/OǎSUU<{wJRр4#$իWNs9yg2| 0 ISO-~wqGz뭴k. ʳ>n)/r`~kZjc=67|suVt4si|ĈYoc3ȪR'/K^~5*I2cƌE5lذ$ɹ瞛;&I:w~zs&I6|lH$wyg8∴lٲDҪG橧J=2|L6-*$y('Nlno&I:uTo|wn0?L ?VD MEE}\szl$9#3hРOJ=?9ٳgݜ_8qbڵk+[mU:vc9fr/g|$Ys`E'>|x8E?gΜ7 ([@k׮yg2~~s_$ɴi\?6`9{dzn'Ȱaþpѣsꩧf7΁y-@=}YN8|ի=O3iҤu"sA%I.Ҍ3&0aB.s۷o$y\?6.x zh铪\} {ꪫҩSTUUYg#F8VR{G݉ڵKuuu{w'?Iw}楗^>iҤEڧo߾i߾}&Ok׮ׯ_:t`nd_c=i_hD`9;rGrwǼ+usN;l馹ӭ[ ><'Ng6۬TSS^///OϞ=$GuT]?3se˖iѢE:v옟߿w"hѢEn+뮻nZh?w^x`V_}}dǰx㍹[fM6I[ٳgN:餜x'fe{% eK.)ueN3u$I޽ӧOe `Я_lᆹ뮻lF۷o`)\,#R)g}v~ng`ηTTTo. !iٲe.}z9 2d[or-ٳrN`={C=%b~bQ]s=veEGhtNfw2dH6d 80nΝ^{-sNN>:#F(:j䡇*:RSSSt e  =#9CӦM=:ni9^zi;#C- e}Ks.w}w?L>=EhTNfnKy ,[$)g9O:5?fE|8ӦM7E_7.Xcn:w3s̺9 K=:~3f4{ƌ۷o\sʹm6w2y/9lYmղ[ٳ^Xu%?QtF hڵk7|3&LoM6-ݻwϋ/ڎ;gy&kf_|~;M7ݴFT\Y`o~q衇OSy[neƌ^{fϞ=#555 o׿5 T*uֹ袋rꩧQt:|+_Y~__̖[nÇgΜ9y駳[dܸq˖8SK/O>y睗$y/mJW_}un'|ٳg'Hl?CfΜ9>|xr˼k++LMMMvu<;wn&Lw=?xn%~fhrSNEGhtNf2sɌ3k,}o}&N{,_><0:tĉ, GNΝ$|AZn|g_^Tѣ /dر &,ͫw#<}ku>ӱcnj?~N;vl^{zW_}5[ouk 6lA:jƏ;.pNT^ne˖={v>䓴lٲn|֬YY}ճjeIp1gΜhѢZyyzN;찌=z.IW_=fZIz>Xuy*/:w$2dB92뮻nv$ ?IbA9s,tEK_SOѣ[O3a„UTT,/z$6m"e h$կ~{y'?IJR?BW$O?]o[lEr\76nܸ{$_$ÇW\N8^cܹ5aÆ%If1T*53\.:^{N׮]s=dԩO3rzyG}-wٳgOγ>sf9䓓$zh6m$In̜93&L_x饗 2$gΘ1c$IG[Os=O?4Æ I'$իB=#${Θ1cR[[ɓ'3LYYYzJ ;Xo2~^?#swfW:ujvuzf?޶mۺ86|_7y }ƿ/9蠃ݻw\o;gy&-[\ӦMK׮]3iҤ믾y駳;/4<9mfȑ/ꬹYkҫWM(\|(\|fΜYtp;l0dΜ9_x̝;wYO?KE(_ѣG2dH~_}}ǏO=2}eXBm]jjjT.B92J.z7tS=^:tO?:d:*2v̞=(KL($/B͛W7޶m$g{wy$oݻ祗^ZIեK̝;7?.>~{y7SO%IfϞ)Sv<  6H6mrM6޽{F<[ou]w݌5(KLXgɹկ~^{-~r!9R[[5va;ݻg}?<XTUU(KLX]v%۷O޽s}eܹyW$[neꪼT_ IDAT˹Ǝ;gW<>}䨣ʍ7޸<X9KLX̙?{Ns1裏裏_oVZemɏ~\xᅙ2eJu~)JYeUrM7'?I .HTZޏ]E;wnQHYɧ rW^y7'IclfYgu2nܸ|;vlz{z꩙7o^k6,Ǐooy뮻w]64[ r6z7޺u#SLiPHk6/Bnz;cƍ6tt1/b7C+ `,^z)?sa`(\M\)S[nܹsr|I'޻nlĈm2hРw̕W^+"NQdM2%#G!r)'f_E1lذ>v`Xye OgϞO{K/4-Zg4TUU5(EhS[[žwu]A'XEѪUta=(dmi۶G?<'|rfϞEU]] `p4iyg믿>OEEE#.쒚J,2 I[otMs+\@3uԼEGXd @뮻_ɓ,N:3jVtEp4i]tIYYYFYt` UVV旿e6|,2 0-[9묳N+:ƍ#8"g.: RVJeee0`@ƍ믿8RXmgرEGR  a̙9 /4ښm]>y7m]`f:9rdQPuY'oik?y'5ù瞛M6$wyg 4TVV=(_ѿ{V3<_QK.y衇p0v腋$UUUeҤI1cFQ¨k)SXB]tɼyRSSSt/p0SVV{(j׮]6pÌ=(_HXazj2jԨKaȐ!9*8v#FX ;SB RYY;ҭ[l|/)+JC4%J֭cHrV^t"7tS ;8@pvZL81[.:)\,ӳve}͠A,GEh\s\wu;2tТ@S[[O? p<~wٳgYfeu#hQpP7<]v۾}âKK.裏+ `T]]$NN;UW]5F*: @  i 6Ȗ[n4`VYYN:( (\+1Ν[\5kV1PVXՅ}#<v!3f(dh.7):@  k׮Ywu3eʔn?^xrX.Vn3lr߻M6/~k&cƌYVYT*`ET*>d9rdVYe# K, Ȅ r5hD K}9ss_/:HJR+9sdw+8@#PhoF6x㬲*EGO?TUU tM3p$Iʋ~ <RҥKFYt :  &}ԩS,.]dҤI1cFQ(\ԩS.첥^:R)FjT@2o޼  lb-sXBڵˆnp4 @Ν(TUUeȑVc:th^~c K.Ms`pO>iuu#F4Za޼y9묳rI'T*VUUU=zt1(\D׮]3eʔ+EGIgy'3hР C 'y@h:w-Z4S.r)3Ȕ)SM. . ~(PBeee.tС(g?K˖-(bP38#UUUEǨg5_;3?xqETV*JEh:ꨌ7.ƍKeeeq/ Kn2s̢  Q{'gyf1ФL2%zkJRQЬ̛7/G}t{챢K:~a^}բ+1 Y)//ϋ/'x(7w@C;S***2jԨ+1 0;S׭s=6aÆewΌ3MJeee:upJ(ZkLڵkF>lX:v7|3~QɩJMMM1t53f㋎6`\qB)|Nuuuƌ @p4;;CZj{(__~s=ӿ̜93/bQ쬲*ȑ#r7fĉ꫋MFǎ3rtС(JJh3bĈc,m6w^._*:4 ҥKV]uբ+) Pd6l2Y{Y8묳?iQ$EVn3g\&mvh"=P{u5JB8TT, ,E% h/v"e)ұ,JWt@Ltp2KHHr'㜜 a 4Hl6ΤΆ PpZffQpֆ tQTk:~e{naaaJHH*C=>}hȑ4JujɓB0ϯR ѣGR)Uw}W:u(T 0t B*c j۶V?뛎Sf7p֯_o:. Pծ][ c*blC8:\\ PpP㏺;f: .''GVMG. *oԞ={c: fo߾ڸq(Pp\ƩS4m4RnիiӦi֬Y7 VZ)!!t,6f:@eHIIQ``6lؠ]Snl6v]rww7 Y(pWPPmf:JX,={ۧzt*TXXo߮ϛ9 .1=zPdddJݳ2k„ 4i>l:j*##C{1Ts\Ү];%&&Q!ոqc7t*LHH|}}s<(.m۶:y^xA'N0r3~x-^t PMQp&MZjiѦPnvܩkך) .>|^~e1*fΜ%KhP.”h:(.+??_|{z4rHeffU ӡCtiQ@5DpY۷WRRΟ?o:JywTN/p$.BPpT=oZdc*[``ԼysQj^{5jxQ@5DpY!!!W\\(p*em۶\P)!!t P Qp@5fXdX\n׶mۮh;*8 (_mȑ#ȸ^z)44R+[ot P *f3=:s|}}/9oՕ8:\ybСCzGj: N 1"R8//OS;w7dl6;Vofs4m439gjȐ!Uxx8p wEիV^]mgA \P||~'eee饗^$9Rnnnڻw233Mvb [N999UPP=iӦiӔviǎݻթS'}7 8&gYj֬߯LHV\)1m6䫯RNN4k,IK|,եKEEE)//t g*իMGZXI.bccաCIRZZjժ%I駟ԪU+IRFF_|zm믿}ݧ͛kϞ=nݺvܩÇo=t萂uwjӦM咳,{%%%)44Tt)իWO5jޏ$x_u}W^ԸqK=%Njժ&Mcǚ@eee[v?8 :\ڴicf͚[liϯw_N:I$$5nX,IڵkW,^!!!֭+I*(((~$iԩц snkKsVrbbb4i$>|t@5W㼼<=3U֭'J _~S@@ "}}}!COuo]6OzzƍƍKAAAQvveYvڥ]Oӈ#a1-((ĉլY3yyyf͚j߾ϟTc%ut8++Ky]&|||VNNNYܔ_.9˲WVV֭ۧ[_/̙3Zj,XXIR@@^{5 > *77WmڴQ&MfqXI?k sh"͚5K EEY?dX m߾]VΝX,ޫ׫F咳,{]s͖u) IDAT5:uTO=Ν[࢐fرco;'IӦMӘ1cC Pj۶m+rK7o^⚠ IѣGeي}@j*YRwА!Ce^Й3g===Giɦ\T||~'eee饗^$9Rnnnڻw233Mvb׬Yu)''G ѣG5mڴ6mծ];رCyyyڽ{:uoF .,e٫Yfڿ233#IZrŠH|WQZZf͚%I>}z .@ 6L?yf{'G$EDDhWJJeXtw[|6-okҤ,{=uv?-44T-Z0fΜVZ[FG'9sYfQtt$ I< OOOu^xbŊ\l$O>џ'Ez%Iq,^ӧO-"=ZtG%Iof̘'NhĈl:r%?XlFa@\|\Ҽ˭رbcc̵Zڼy=wõwb9}}}eiӦ\ru@=Zcǎ-v믿^'N$5jHG՜9s&ٳV^(L/77ˮ'5o<,S999*++ĬuֵM\mβ앓c/lQ{wKjС|}}QF׷իս{wyxxAƍԮ][[nըQԨQ#KS\\<8ګnݺի%j߾{wոqc߬ (44TVHHƍ>WraÅ.,b۷9.((9%9w\,^v*,~_… ձcGeff*&&F7xfϞ}E\:Lȑ#k.m޼\wL~[(T{Չ]"u֩[n URRõzۧGQF]J~GKHHoG.<<\)))c: yf >\Կ?#m߾]JIIQtt,rV{\߿>֤IY,{JKKS֭պukIE;f\"==]uҥKէOqJzzRSSu 7&*Eǎj͛ps{-[M6咳"u IRFtQ͙3^lr={jtӿ 0܊m(WV (::Z7n[8RvmmݺUFRFuW^@wUƍIRTT,XPy{{[!!!7n>r3:\cJ:hks=`gX$I  .P*zݻk.y{{@a:3f(??_w6RRR|r1@G Z~~M5k֨W^:sj׮m:ppͦI&)..tEmV6M* X,}'Zv( ׯ Pp oߞTaaaaJHH0TazSIR߾} ' BO/Lǫ4Ee¼yԼys1ULΝեK1(3 . I:q℺uΝ;kڻwcǎiѣwTqQ gϚerqEFFѣ* j߾֭[nASNݻݻW/j֬/R={T~~T*f:(ڵkkٲe3T1\@C ÇuwjzԢE S͚5Ӌ/[N:4{lӱ4ӦMSNLeVZ)!!tPPp`/aÆaÆR``"##g-e.}k4iq)==ȼ͛7kݺukb թS!!!%)_nѢEjѢ<<O<ۦMm޼Y~~~(͝;W&LK/t999JHHP۶mi/Էo_eee[UV{ux_qqq뮻]伧6mڤt=(--a /l|v5*_nʔ);vl^^^ԣG+QK/+.YD:znf}w;LǩΟ?Tp1Ә1ctY:\TӧOO>JKKѣueeei۶mz'oElb_9rDQQQ:#G(77Wc$uK:u*Rl~)++K?d=c=:t|AmٲEڴi4i\+E=Ziiizꩧt*33S~ZhGjҤIBe}.4+<<\qqqݻճgOh:ydr\pEAAA_LGH1.j*==]3T!\T9sĉ?~z-[7o}Y;wN3gμu4qDIRttt gVNNq{ :wO>DG/͛OtuE+VP˖-驖-[jŊҥΜ93f8\whŊر|}}uwj޼y[$𐏏.-[Lzrvz/t뭷jƍj׮ԢE \R]tѹs4{R&OFqEڷoOU1b+-]txQ@B@%/$IO?O>$iÆ %^ܹs߿u_/ro$9Z*ͦ#GDz$IkIرcUFїjԨ^xAn:k۶$)55M7$I֭/^?s-[fӯZn.Tϟ# M0A>>>E.¼Ѯ];%$$QuYO%)_^z h ,3+,0 ڶmZjEխ[WoΝXq.$$$D7T!\T7={V6į[?gb-Z\r+}}Ν%Iׯ5\ Ν;pٳgdZ<򈒒/h…:t6m*I:tFU!ٮ%=DžTNm6[ n:ӧեKQw}6lL! .*Qa7[j]vvLM4I={,qn&M$IWt~I{={7KYrRSSeXp?Pd^yiذ  h߾}Zv$iӦM_EIJJr8'Ijݺu5x9033ؚCs:LG6fΜ[8 .*< IzW_edXԭ["?vܩ޽{_`b璓eXdk۶v=ߌ_رc:ujԨ>~KL"k 4uTI=sW"((HEw.vC3[Y2mڴbcϟo!IzG d…%SX\sߩ4in[8 .*ȑ#UvmP||***J^{55kh̙jժ>"%1bh"?^ǏWff6nhf1x"kΝziݺu ̙3ua+++Kz7eZ_,=aĈY[[{Qnn٣޽{kӦMO?}Տa%I}_ +99YWQU/R?ݫ\ܹS=zЖ-[t7kСEwI4l0mٲE:tƌYf$iŊWnnna: YblCdXxb/>KGYYYϚ5K#F[V%%%]̳pB=rOqFy{{ONNV޽upssSLL&MTڵkշo_;奥KW^E GJzTvAUF*$[iK],e3g9_~}mذAv[DuY;w p.]hӦMEƪˊK,Qdd.>:pPɺuQCM7$ծ][]vՆ YСCcСN:ԭު_~Y~mb I Ѯ]4w\= մiSEEEiǎ-$顇5`];v+h(Zji۶m?hB>>>rwwWpp{9رHEyg+WM6j]7VttvUBx'66V={T@@<==ծ];}zꩧJgѢEz'wwwxy[PLGU.1Z댁Pr-zg׿tpP Z~Ν;g: (ƍ+11t PPpP zߛRiҤI6PmV c* R[6m8QgjԩzWMGTc~߯TQڷoOE馛K/iʔ)MTSaaa*((PRR(QpT16M6t pi኏MGv׿*$$DQQQT (00 pY\c,Y:u꘎QjJOO CpssӼyuV͟?t@5x1Zl)___TKzg /v)33t (F;wtRswwjնmLG&M$3t@54~x}c'n:"##j*1O?tUO<ϛQmk޼y:q(Ep}5!?tj7(Ncٲe#H8b:Hl6 8^z)""t .jɒ%ZjW}5ˣd[Tt4LGT?MN Pe8qBVU{$رcZ֭dc߾}Ne4f3F˖-Tyi::u&Nh:pR\*#99YԲe"!!!29{؛/;4c EGG?VrB*λᆱwyt kʕZf(j ,,LIIIc'E2J*( 7ܠ޽{_TVVV%b9rD.k׮O?tqUjÇYVׇ~(I;wV.]*I>}Vɘ(Et >ֿ8qB-2 ~I~[zMGTqmڴ;].C\\Ǐo^_~/KKKӴiԽ{wGz뭷}sa!5rHuIs^" 4{l[۷wܡ!ChժUEuu/~5|bse*}wZZ.]0]wu9׷̤]jW~~MGq]wL3fZhxQr7R @~EDDQFZ|5x`5mTK,O֠A<'z衇$Iz'ta-YDZp|}}\;**JΝ$e8; IDATggk*((PLL$iƌ]vi׮]Pdde[JKK+RP땙:;סCkÆ zGK g+>>^wq8.cС裏4l0ݝMXX.CtUBrr$)$$qE→EZb{=# }:|4h j۶mZ`n}mۦ^ƍ$"윘X쓞7nXK~%+Ij޼y/B^|XUmV?.bhΜ9t@fZQT -[tx\Ѷl"IVÆ 뫘%&&jʕy111jժ<<<Ժuk?^qb;v6l(///{TŽ/ֲetGZf0`<==+ٷo? J.TdU]vg:i֬w֭['u֬Yԭ[7-_/f[w5U8v+΢}JJJRMG儂 5w\IRHH5}tIRhh_믗$L[ԴiSIc5$IVRVV>ɓ'ݬY3I/R캅cst%bȐ!믵sNѣȹzAqFСCkذa+1h k}vT4a„2߷~jŮyfk׮~<.%??_sQ^^(*blCdXxbEDD8J֬Y65kҢ'hĈڰa8*ԩS5k&O̿Y$:\~9rNS/BCCMBlڴIuɓ'MGqi3g?6PE)//O;w48 :\jN+""BcPZj%ͦ8=C㸴:(**Jcƌу>kt$ V:;?>D%@󐘉xT$5S%nV^bv2ZyCCРǙҜSo"!~\TPdCytk 9]jҤq@S>>>3: $M4I%J[oet@1`2dXsN" ԬY3 .GyD3f̐QńbQ||1@A@jڴvܩL@Rn4j(cƍСCrQ@dt-]T%J0:ҥKQpKJzap+C _JJʒd2:)QQQ 2:Ttt<233;CY7: s0:P`mܸ(" c:ѣG5d5o\_5i$n L͞=[]vUfԲeKO+WuW^L=*Yyeff.)))6m{9mr$iX,۷oeXql:ubц 򵆒t%?^_1cd9ŋոqcyyy}Q{QPJJ=ϡYf3:OVU;w6: g rNF*I:|TjU-_\ ۷|||m'hΜ98w/^d?>۹ӧ+%%իWSN$&&j}/SLъ+ǟ~*VK4}rpp;#IJOOנA}$ٳTBBf͚%쟫1p@%%%\|233v|fͲ""Iׯ_~]zUsYYY/$I;vGŋfd2ym\o:~ܹsV||"##նm[͘1CTjj\]]%^Pi&mVte9sFfY͛7:}sHW_}T8xmذAݺuZ\Ge EEbG}dt ` vBBB$7cEIFXm۶M%I[n1n5k/ĈҩSTBEFFj튈ȶ{âEm6'O/_X 0@eu .ԁhQ UVՊ+KI+bۊAfΜ۷k˖-5j$iɒ%߱cΜ9#ժUK#9s&y`?~\+V9sTB=zT͓ի7nhϞ= }rppPllk-IM4k>ӧUre͟?=pȑccc%Iuqfx85mT?@aXt)?( \b}ݺus=ٲevء'xB֭Ӈ~{O(*$$Df~l+J SUD k̘1}FRZd6$I5zhUZUݻ$w7J&N(9::F;v$iڵ99rT"gggwg(w.՚vl¦sΒUV}Anۺw%ɾ~Prr:w4}ѺukI[oV4zhխ[=9r:tH.VZ>SU|ySFd2wbXO2ESLzw%ŋ5|pQ${{Ĵi4mڴc}7rJ.}9mN>-In:9sFO>?a9;;kȐ!/i&=JHHZl))kx)IRsr˗/Kʔ)㜭'Ojժںu7ont" @۷o7:'իWOgϞ5: 0;\?)S\BBB;(&&ofgLێqssvvε?ɭPfQD ;eYvn:OiiiաC-_owO鏝;֯_y"///)11Q/_ַ~MC 6T8p@ 4895u^p@1w^.@fZk. 0@7oo߮^{M0cddaǏgddMʕu1ݻWM4ݻ7G_ɤ,]zվCnM/ooo8qBk֬w3777uI:uҁyf͟?_ӧOWn$IW$͘1C9ضmիW{yB 矵g5m޾gIvڵӞ={4|]zi͛7W||ʕ+jݺaʕuqڵ+%$$[lY;wNIII*[lsIII>[Ν7n8ȣ/B>,_3x(lz۷+==]3f=99smV4i$%$$(##CפIrt\R׮]5y|Y ”7nҥKeX4hР|iuɓΝ;bhٲeJMMUZ#;f9rDTլY\n֬Vȑ#yӪU+Iĉo>eddh߾}uoѢ_W988wݰ\<䓒EeS>3,vRFF~GM0!GڵkKN8㜭[~1O?[n5kQy)=d@󉉉w+88XժU/}* @/r۹Eٳ}wӷo_UVMSHH6m>1m"]vUǎ%I}$M}TJ>}ZW@@3gΨJ*߿oٲeﯴ4ծ][^^^URJ?m'aHHj׮si P>}m+m ["x^F1c@Á PZ`?f;[ovکdɒ2ͪ[&MH,YrǹJ,uIrrrƏ/I2ÇW#l6+00Po-J.H[rssSV4o޼{A7TŊtI_llV͚5շo_7Nׯ_׺u{?*S֭[ׯ5O2e4w\S^^^rtt^z%͛7OnnnkNRbn-lfY޽<<}裏***%ooo w6mڨw:t(d\ܤCɓ'M6jҤz!* 0(jJ,cj:{Ξ=իWkرrqq1:y>EִikFGڴi.]dtPȜP9RUTѺuO?)==]_ԬY3(5j!ChԩW_}U\r>}㕕%dt$@!3(&&F]v5:(D\AAAA 2: owrJ}/|ݻzmt AJ.ڵkjRpCggg}_qƲZF BдiSL&SFsNcBF@!㍎qƺ|;ftPp`hڴ~c|󓓓vܩ5k .@ctI& Sff؈dɒՎ;ԳgOBOad2_P())I4: ӬY4tPc Qhh ;\"OPTdee\]]cխ[8ʕСCգGh8Bꫯ2 .@ cxHEGG+88Ĝt!UT(Oz҂ 4p@޽[FG0WRP(uI{FG<\897jժ)<<\&MÇ(`+(6.\:]6mҩSԥKyyyiڵFǻCv=Ζ-[rJ%$$(99YeʔQzԵkW5o޼sZ,Ij̙3Zpt9(QB*USO=^zg0BAqLL$Iٳgdw7bEGGkРAڼyL&ё Pl$$$H֭װLyoᄏwk=и IDATj˖-ڲeڶmql6^>|X^joKOOסCt!YFs̑Wg+vޭYfiɒ%ҋ/(5hh/׮]3:pO@XBݺu3:Pp\؎ǘ0a6oެҥK+44Tmڴ_%%%)..NgƍUD ?rVŴitU5mTjԨ #- #'''aÆ8q$72b4w\]pAzKpΝk`2ȟ,/mڴu0mذS_sy}NJՕ+WTZ5С@#""Bo|||4{lIRjj̙7_Ur*44Tf9\7oҥK4+WNZҐ!Cꚭ޶A^Yj$_VjrgOOOhƌU~lsjڸqf7oC\rݚ̒}׺tʕ+6mh*]tq/^ӧk߾}rvvO?aÆe}SϟŋުTb?%%E?<<>>>teG_~~7eddѣ ך5kr?}tXOOOנA4|9sFׯ_ٳgaÆ)33~'|Zr222t9-^X'O}g{JZly17o.Iڽ{ws֬Y4%''kڵ߿8歮\oZhΟ?oh*5555T||Ҕ˗kJ 3gjݺ~zʔ)_|QNҦM۲et򲞳fҧ~'OJMMSQQQ]^W_)55U9 Tjj* EXZZjԨa/Ňbю; XHHH$zl3|]xQO/&N(777͟?_z) Y,FG؝`%)S4eᆱw}W;39sFTv Ht}޽[TzfM $I{n;W~ԩSGn[p I9 z-٬%Kh۶mrppГO>nnnԩ̙ O>JNN)/ו-[Vz[hzT|lET^u5JgϞ5:5nE($QplO:UΝSZZL"Ţ^xsnZDݸqC.]҇~(ŢAfJOOWbbƌcoONN]NUV$I'NԾ}}iҤIran^z%I:zumٲEoV5)_:w+99YՓ{翗{zvYE˖-Sjjjժ%IwݸU^]fEam߾x@Ǝ+www 6(6d͞=s2:_~ڸqۧ>۹W^ysW~ۧl\\\4|pqVvZ+<<3-YDK,ѧjժ:th_~YK.toҽS^ֳO>8q&Oɓ'g.]h 58a`~lz1]&M<gϞOzGeoBBB Lnɓ'رc@1dt Zli㣎;8%KرcۋNV^3ftf .Pxyy)))IEaaartt4:a5j!ChԩW_}U⏂ ?1jtbڵ[T3((HAAAFRVVL&1@0oft{ү_?(QBFGv_}"##| . m6M4 7n(55(p2:͂rJcxH-]R?~~W/_8($111JHH㍎G5RFFݫf͚0vEF=ԣGcx4mTdZ N”'*>>({TF yzzjǎFG;\"#&&c=8=FA!ӧ,XjɉQFڵk1Om@a2,#xhF@!2LO_z7EV2:x(EJ.]dt h\R SffBRvm=ZcǎUUZ5#b(22R2F PC=z0:) PjU >>jРIRЫW[j 6}c///5jHݻwWFԨQ#;vL[V͚5 L rmv~mu]ޒ]j̘1ZtJ,Y1ײeKIUr}֯_ҥKG-x9 ,,1s… >^҅ 4w\Pfg2d2r_~]pIҥKԫW/*UJӧs\5OJzg5ϕ+W4j(ըQCΪV”k{y/s߿_m۶URT\9 l }*S[`~lz1{g%00P>>>ഴ4h"׿?ꫯgي'ʖ-K.e+("""[MVVF?LӦMӈ# /ڷo .j1۹=zH.]jD4P@P\zU:uꔽ-11^lqt 4H={VJHHЬY櫯Rjjs T||6lؠnݺ]PbbbSf{۴idZմiS͞=[:|M6)22RƩ]͛J*i„ 0a>sEDD(++^tqsdDD$ijݺgiȐ!9s& Ň~+""Bvȑ#zg J ySNB ?:uh3f.\… ujѪYN8'*>>^WV.]dZsݭ#66VTN9lm\%ۧ=yw [QբETzuIO\&L˗8gҥӧT.]4x<kСzճgO-[~رcY@AG)%n7|#I SUD k̘19nܸQ4qDQ5jرc%Ik׮\$UZ5ǹjժe%G$ըQC&z$Iq$)33L:U%KԆ o^z8qRSS V O;wNW\@A N8!Ijذav}O<)IԩS.]H=zǹl[Llmw_lcūxknIII9fd!zӧ'|R SJ4{<M̙c߽5j02(NF 6,nm/ YYYَs{ >rtpY>@QctyԳgϻV:9 ~iǎZ|{=1B zs^z%͞=[mۦcǎE*U2:O\Aʕu1ݻWM4ݻ7G_ooo8qBk֬w*[Ν;$-[69'@qգG#(@/&O ͜9Sŋ5m4M:U[_1M&taHj֬Ǐ?VHH(PL&f̘!Ţ ȑ#Y&@ΏI@m۶$M4I 5iҤ}[n-I SbbnܸK.?bi/NiӦj߾>3h]cǎ'|Rcl[[- #h۶m6lV*'''yzzK.SÆ =~5jI$i3g"jԨQ?~Aɻᆱׯ/TZ رZZ:gɒ%N:]NNN%If޷tҊTPP(777jJ˶;śo+Q钤U[n͑c֭*]} P{+S\]]ʕ+{/WhL&}#ZxXF)<<\III2gaxWC|~g]~].]ze뗕{cǎ:{ڹs]k׮wsww/)[J<== N  OOOgk=U\lnnn1bFq1۵kvek+U4g>}Z+V$>}Z{z… ۷֭[ܩSt)-_\:tТEf@JG7n(m IDATo]vi׮]Zt# O М9sԸqcyвeKY,-[LO?qI6lXG>mQQQVHHHj֭֬[ *hԩ]zwUL]V:uRFFѱlRe˖ʕ+{N~]_d|}}e6Ureo+Rh{Hܹsiٲe2Lj׮]c>|XڱcG;v(ɤe˖׽@qg*.bd2)w5] "QU4Ek[DbZmͭtPmR%%$Bj֥DAsyܳ>f?{EE)000cxآ$M=yھ}^u]v͢A˗/Wڳ+L ,?Oݾ}"~ھ}%ITxx<\oܸQ/M}vt1Zj^}l+..N-[TFFYnݪƍ~G+JII6?wwwũB ۽0?^9͝-[j9믿|_l1QV(P(si{-_\rwwӧr{UBݸqC.]YСC5sLG7~ʕ+ŋŋrtt4;~$a Pd\|YJIIш#t k0`233ϛ3 ɓ'̙czi 8Po֠Atieff<==uM2cI?\C%ԬY3b .( @ԩu %&&SN~uk;vںuUL}Gf#FPJJx 8qBJKKӖ-[TV-9sF&M*[!!!ڿj׮;v(--MSƍe08~Ĉjݺۧ7n())I;wVzzz*x 8qB~#I 2urtt233~zy\ HǥK7lؠ [ Pd̞=[/^￯>LrppPF7hذaz &HƌcYfƍ޽kN͛7ŋ%I-2'''Kj֬ UjjZj+VvڲWڵb jJ²ߢE XBM6o$ڵ,v߾}SSvvvrttT˖-#IZzuv~9$-\PM6J( j…Ç8~Z~4h {{{լYS˗/+˗/kم~666/yyywղeK?l\^S@@$)66loFׯ_Wǎs޽? xQpN+H\zU=zЭ[Ԯ];}'f6m$ 2b N>mjKOO$,Y2gbnƍwyG}]Il:Ԣ_$]vͬg$uAQQQ_L}kז`йs ,3g`0A}=^7n/nfcc1cH藺I-Z7|7?ש]v*S֭[۷oKn߾09::?keee׮]RJ]vyG,[LvvvNjٲeNx%%%Iwĉ|M9sFZx+fII /\]]uTRS"{ۍӢYL7ׯvޭݻwKS+cǎzeoo_`ݭ _n:uJG޽{g}D$G(RVZUVY; `%֐׸9s(&&F...Zzʔ)c*);Vxzz*>>^GUÆ s5֭[f;)HR...ׯgnӷo_*UJ}/I_4|͟?_ժUӆ Q ^Xt}:u*c]]]۞9 mllO+""BO?$???ر#\͝;Wj֬>sIR.]$I]vU||XIRsu}pa0xūHXq׆+Wc' 6L666TZA7o.IZ~}?e˪gϞ6W^v̕+Wr:w})99Y߿$I?^( ЩS+88XsիuϱtU-ݫlsZj *h͚5ڿv-{{{uQԭ[7IҦM?+66VO=^}\;vE/k<<==~ڵKZedd( @iiicljtA%&&iӦ; @3f_#Fn|ʕ+u5ؘo>ݻW۷gS\AR~I֮];j֭[~_n}ǒYfif}ϟ7ʒs:-ZXڵKTNPشiS :TO秗_~,&?שXbW_}M6Iڴic] 6Ԟ={'NhO"vEƲe˴l2k !7ǺuELLlllԡCѣGFV$IsεKLLMm/ڴi .{JKKq_UӦMFmjo׮$iԩ2iӦI^yё#G,4ibVɓ'%IzLӳ?m4nݺO>D[cTXGMYYY6lENNo߽{wI… ͎ V"10ǏJ(adx .\0\~?j׮mdm6ӆr${9CXX6ܼyӐfHHH0L:PB$Ä /$CN G1ܸqpCN NNN3gΘtC; PfMÆ  7o ڵ3H2tڵPry Aa .nݺeHLL44F!999ʔ)cѣѣ7noxW UT1\vA`0"##Mqf}NYYYg}PX1$ʗ/ouV;'pqEEE)000cxآdz//__̜֭9S6{{{k߾}"""4`loܸ6o,Dĉ9QX17N&M[fv7nX(QBK,YEv5j~)1+WΝ;UjB-/%I||lkɒ%:qℾ[ubHbO?^ 4U9]K-Zhzgt1999s;;L>]m۶-7o;vh9sf;'[tA_>TT)iF6l׶mktҲ??P[l(:u(!!Aj߾dgg'yyyi:p@ԱcG߿_={/.777[Fpuuݻ{VZrttTQFf[^_^Z`ի%JU֮]>@Yfe;>((H111U3h:tE񫯾R믿*$$Ĭ/) @mp;\y-Ir&w;vL5jȶ/&&FqqqF[n35@ x=J@nЁT~}kT$@ތ5J۶m˶ ҥKe0Խ{wyyy^zVGV^mPkZ;GA|||b۶mٶ+88XrssSJ+==!g gO-oookQ̛7O/^T@@Gx͛gxPp ydeei֬YSƍբE OV28IJKKShh|||ԸqcuQ3gTffY唒%K襗^RM1+V,Y<xؘ855UcǎJ(!www7Nsh۶m*[Znmoպuk.]ZZ  >\UT19r^@v0-\t|M%$$(!!Aׯ_WPPP2335h %%%bϟ?%&&*,,L9?;cJKKS&M,4i{jÆ ҥ_>w$jժMmɚ#g/ԟi{]zUM65ٳg5c mڴI;w}b IRhhvޭ;v$iҥyTRRԩhٳG111WݫXI2#>>tsNIR͚5-r5c%`x<}tǫaÆ:pn޼#GYfڴi""",UҴh"I.I9sҔ-[H֬YsN$yxxh׮]qv!www%$$($$a Py{{bTEEEԩSjٲ7J&OJ*I<<<4qDjݺu1cǎIVjnr/&&Fxb=s4̟?_Ԁƌ=Z㔔 ۷OQQQ:|6o,rJIٳոqcIRӦM5{lkN+V|@PpÇפI8}߿nhmٳg%I>>>ٮwseIErĉ<!; m5j0;>:v}Y޽EvN>-Nݚ7on@Pp{w0l0wW۶mըQ#mݺUW֡C4sLEFFjСҥKtsEjj}mll$I}6c ȽgCŽK[ڷo<==թS'թSG/j׮sbw *())I?,X>TH8777%''k͚5rsss.e˖Յ tU-[֬xǽ]ǎә3gTj|ͱ~zIҮ]OK9bysѣڱcڴicj߱c)?P8(ȇN:ܹs;v:tի_~$$rתU+͟?_ƍ;Cիʕ+ԢEYfIsc`ٳgUJIR5t%''[V$''b(*5kk 6lhP}qyyyI:w*44TuեK4}tM6MZ͛8$}ڵԿSgBBB4h EFF[? $Iz lO>hB7ָq$I 4s\߾}ÇgϞjذڵkEA#F0Ŗ)SF秎;J6m*IJLLּy9yS'jԨa9bرzk.⋲M&'''M>vIԻwo9::_ԡCLqw}W^^^:uꔚ4i"{{{5mTgΜQMg.#'>>)OŋWLLN:%IzgռysSE^J,͙3G[lŋ hРA4Ŏ=Z_}.\LIRvkݻY۷oWɒ%զMB<ȫ;v(((iȣ(Z; (4_|ƍgƍRJi׮]rJ;wNjѢ>o{༡y֮]۷onݺ5j~'M8Qj߾}.]ZvĉrJoXt & `0X; d1acͬY4w\ZJ+W$;wN8p ` /::ZAAA2cwO[k'ѧOUXQQQQ(gϞV GOqk'PP eB9::jĉ6lz%I՗_~)+g ȋ/!ChڴiCAV x:tҥKkӦM_kݺuNH8vjԨQ֎Q\\$QF֭L Cxl<*;Q@Z; DIRڵ͎ԩcQFi۶mV~k8p@aaaZt w.///իW _ekSIm۶"vzz/777UTI~~~?~ru\"Zp$)<<\Zd$)44TL97o.^S[=tE͛7ϊ?ŭ@Qoi̙ڹsRSS޽{Cfq))) ͛\rjݺ|M,Yg,Yd>3>|X%JЫÇQpmذAϟUN:lǛއkҬYb];SRRdK*_)bŊ^z%o+)AAA v 7?~\Z/_DW^^^.<._>}ҥK'Oj„ }:v(IJMM?O:uwEGGk޽իW%IZ|4n8IRXXiwIy٥. IDATׯ>L)))fyY~ԤI&Mh޽ڰat钧& .@c@(ISNDžmtjժ>Hʕӌ3rJEDD .\SNrUfM%%%)88X'O5dV'B ;w"""eSŊ+$I͛7n:hҥ 2]+$C/i;wJj֬i1mΝ\)Nnڵkg{\v!I3fT"'''7NZr)n˖-qƩnݺ /_yfyURE%J0Vq5SqG(?{bwv;&NAɽb((:}٣+Vh.@ѭ[7k$`'qSjԩ?P~wv(($I5jԸoܹs$I/Y{[jL]]]%IYYYÇkҤIS\\k_rppUyg˒$>c1deeĉt.]]ҥKҥK0߼ys}wV<(EJTT'Ttt\666i:m۶UFuV^Z̙3CK.\?- iLrƱ xڪs駟$)NPʕ+rMO?mj;|{=+Zvm rVpIR:uPIR oz *HNc1yw%IǏիWuqڵK'|#Gw޺u&M=z?QpDIw .;~6m*I6m.\ M:Uܹ)e˖ɓ'úu>O>DԼy<ݩS'y{{oUZZW.///IqYLIҪUSN)$$$5jԐ$%''[kl3p?=zг>k*ITTt颾}jѢEf?' Vtرbbb4rH9R1111+(\Oe˖Ç믫Yfo)O>RΝ;QF߿J*߿ӧ$)$$D-ZPƍ5n8Iwv02QcǎX矫y֭J.nmczؖ^o̙lcf͚޽{kȑ9s+O .dԨQ ʶ Ә1c4zh9C{ ,9bv0-[VS۶m";;;լYSSLQLq...7ou˫Xb*_z5ki„ zeoo/{{{UVM}դILqGVʕUX1effw#F_J4i|wvkkNNNNھ}ż۷oWɒ%զM<'˗u hΜ9SLѐ!Chʔ) t%$$ O&EEE)000ǝ$)>>ެ===]]vU۶moKf̘~A˖-CxRDGG+((H?{ z͚5KsժUTreIҹs뫁jVՓ;µsN͞=[˖-VT.#T87o.^S[=tE͛7ϊO>XLmQQQrssSϞ=;}Zh$}:wVXdXBACէ~ Jŕ+W4zhyyyiΝ8p`m0Mxv,kÆ :TZ5uIfiii;w6nܨ]ʕk^ F"%%EK,K/˛b*V(ooo-YDzC8k@A$dg͵ Ka_޻rQ'N԰aԫW/IRllK988X9;@Qs)))I5j0yzzcǎ2eVZoV˖-SΝ t[n)<<\Mmz l;wo֬Y  o޼%$$ $effjРAJJJ2Ş?^JLLTXXlmsttJKKS&M,4i{jÆ ҥK@x5dM6M4tP5hYw[ >\ZR||6nܨW_}@5j(>>6E'O:/_$Xی1Glll,o޼zKzꩧ4aI9;;L2ӧ]f1>==]z)Kϟ`>;v<<
xdffe˖zꩧ4~xGO?^{M4n8;V%K W&Mի 988ZpPpK񑏏?hLnnnJNN֚5k5ʖ- .ի*[YիWM1޽{u!yyyO?Մ 4d :zT)ShҤIZfNԺuk+((HgΜGe j֬YS?jӦMЀ $OZ~~~ҭ[^qqqVZzP;7b/jժUo tkftM#Gڵk_gDXԩ*--MիW$תU+IwyQݾ}[ y{{kРAX (gϞ5ըQCҝf<+խ[W>|$)==]gV51cH3gTeoo&MvXbEkH/^zxUiӸV6mRv@ѵkWURi(<==T$yyy~SzԸqcY̛7OIttZn+*V֭[+::@.rO>+!!4h"<̙3 ͛7駟Z;<+_6oެ nZݷ [+Wn:͚5ˢ/00P ҕ+WTt[>>vzAijذF3g(99Y͚53۵ ,^X:tE:tŋ_~.(X\1}w}(;(gϞVPԼ曊T AIzΝ;+$$D Uݺuu%M>]ӦMSVyϸƍڵkΟ?'NEN_ԹsgOݻlSj֭ѣ|MӿTݻK-ZT]pA7nTnݴlٲlcqF]pA+V,@<6 eB7'8q ^zI$/R5@WB5jȬ[׿r3vXZJvҋ/hӧX~ƵΟ?_`s(zBBBd=zTeʔv:gS)0ԩBCCMmݺuSJԫW/zK.tg'tR 6@ ҋ/!Chڴi6m X;-@zj*W1ch-+UvڥÇjժ*^z)*..N/k 6رc9hȑ9ro'FSU^*+::ZŊ3ko֬9R76l ٫_~z,)hc x;Q@Z; @1 =o{ٲev<-Ieʔь34cƌswj֬Sp7n(&&F;vٳNIIIy(km۲mOOOWppJ*OǏWzzCȿmVTff:uJyԟ+pqqQjjyD(m4 ռytEz衋/j޼yV Ȼ3g̙36mShoիվ}{U^]/od)>q)tD=.] &ujܸz 6d[PqرfΜi=GJJ,Y^zI˗7TXQZdRRR l`}:yX#GTΝe0̙3 S{b999)--i<*nUVY; Oe˖Y; Sxl]~] Яjj;z}L 4HIII+""B mϿZ~ԤI&Mh޽ڰat xxF={ҥKv:[o} N2E3fSk׮Y; Gp]k׮NC$)**J*U޽[f;PEFF*))IuQtt٣իWO{Ull$)>>4&>>tsNIR͚5-6cGV\FY;UZ'bΜ9zTdIk-WWW]~iDu'X0>n8=zTo/B4h)xCٳgMm5jԐt 2c4h`4]QQQJNN֤I(6m5k;\ұcr133S۷׵k^9G>܊Q\\$QF֭[A$)((HΜ9}7o߾ںu>={988hĈ2e󓛛֬YMj۶mJLL711QԼy91Ο?ݻkΜ9v:iw k[zS$+WNݻwvEV2e`ksp FRPPP[nյk$I׮]֭[Rf}qi̘1=zBCCuP+>>pt*^HYQeɒ%@XbruuU˖-5|"ѣGr*V233%IڵonUdIӎ駟ֵk4h I7nPTTٮG(z(ȅm۶ݷ_][9=9>Hzz/777UTI~~~?~ (KzJ&LЦMhկ__ҝ'U#GԚ5kgm޼YӦMY\۶mzjٳGׯ$9;;+00PԹsLΝճgO999x ׶m۴pBkX͛7[oMYeʔQ>}LEwOOOW~쬧zJzOjjƎ+(QB7n222;ygiF*WׯbL4aըQC%J7n9s<ٳg5n8URE}{wVUq 䀙e9\gMRoNhh9\s@s( +fbU -5(S8%ipj" 0E IDAT?|8yd<)5dw.xTp!"""""""'''aϏ?H 2e O<5:#g$$$пSۀHHH`&GIqrr/ڵkdffrYfϞ `*(.rڂpttdРA:Zhѣ4i.]2:ccرܹsYf ݺucƍ$''sU֭[;35k֐A`` mڴ?sTٳ'=z 33re.gggvErr2/_fL0!8uTΝ˩SHKK:t~ ;6++;wSV-1bgϞeGGrr2o?QDDDDDDDTp!"""""""K.ӱcGZn͠A ˵P#99___\]]iݺ5=zߟ4Sv233֭tڕ\w?ӱcGFUy/##>ӱcG/_@bb"ӦMm۶8;;Vu-}_ڶmwϟoy"kd帹ѺukڷoСCٲeIIIlذ^zJ*+W6l )))}GS%;vEۗ*T#Z5k!!!GHHfήX1'L4(p=JJJ s+++N8Arr2|9o۶;vpM8@͚59w ,s A˖-9r?m۶ڵbYׯϩSHNNf|WlYYY+V믿͛$%%o"66 йsg.]D`` ̝;g}6qbaeooϦM5: .DDDDDDDr ۹v8qiӦ蛖ƨQXv-;s] NYYYG롐 d*(L裏&99k׮rJBCC?IXX$%%m6|||LrFIxx8$&&_uW???V\IOO'99H͛g7|Crr2mڴq6mڐLXX=)[&Oĉiذ!vvvXZZ舛AAATZl޼9Ø1ch֬Y#b4/^̺uؽ{q K.iӦ1~xRRRO_>{\|9xv튍 mڴ1l޼99y(U5b͚5[΢Kݺu7lqʕ<lٲr~~~$$$0zh8{lUGe߾}|s}m۶%11((<J@DDDDDDD8qT¼yhذ!̘1DGGӸqcMFڵӓpBBBի#""?S^=֭ @zWN"""^z)GZj`zЦ0 +**?5jn:/_/rʬ]+VܮF̚5gyUVݻ>}z1A-___HOOgxyyqFhذakn;p{%"";N.N^bsƈ9EЧOw;ѣGM!KxMߗ+Ws=gL2yܹmp̙<ǜ>}'7Ŗ(s5nO> pׂ{ FXXaaa̜9ӧ3~xJ.8KKKϟ%oG͍ݻ`t{V|yn޼it )p!"""""""<'''ڳWɝ>}:M6ښf͚1cƌݹs'ԫW+++jժŬYؾ}]ngϞlݺ5q 2[մ0 kԩԭ[C7odڴiԨQ[[[|MCr&OLձ5J\v-|'A>}0_'O:TfM>""""`[t)6lP}`ookUƗ*e_vaB~VNEYn,Vŋ _&99ӧSJg$)^+]ty<2^ADDDDDDD A;\#%660_Yf9?WW\믿;WRR} ,`9޽ׯSlY.뛾}ڵkᦢܟϙ?~""""`V~Mwml5kɓ;w.ׂt?PCeȐ!,[_:uy袘[nԨQ͛7<ʗ/OFF1DDDDDDDÅ<"""̾e:0sׯ{믿&--->7o믿ў"ɝ[rnirMtΝ;c}yRSSŅ/2r˝x*""""1b&==}1j( _www~g222‚;[+sũSLmk‚~ѠAƌc:vgܛd.۷o|'*^7n0:vGJj8s GEGHll,8::z,YB6mr?x ƍ#$$>}[n qQz WWW\]]oeڵ,\޽{PbEILLbŊfM}DDi&#H>yZjeرc3uTli޼ٱҥK;`Q\O?4 ԯ_5jCjՈ!88/ W^LOLL 駟6:}uK *plB޽˫w,o?u}ٳ'/^dԩPn]~7|njOlllŠXSyFG|lݺFJpwwg̙9|z-۷eҩS{bϒ%K!"4n8ڶm["~: 6,%++UEDDDDDDDD0Yy-!"""""""R,,, 2n}G=R !!!~.)˗/gժUlٲ0ŋի#Gd'g}MZD.kp2)M6Gݻ9vvvvrN)]vuֱl2n޼ɩS4:<@ÅǏ籗nBhҤ vb\p+WiiiFG+p!"""""""ɓ'SzuvٳgIKKgu >J*1Wkn#4o|||3f ͚538cDzn:F޽{K|W y8pk:u- t:t+رqDDDDDDDD yXZZQ am+)INNNDDD䖓'OR~\s!Zjoq?;+++>SZhU>|ёmt._ KyFɗ .DDDDDDDDDDDDP.{͵ȑ#qFׯ^0 Hi֬?2e M ,##R+Yrr2?˗7:}元FG""""""""""""x`vػwo)))̜9>}H*Upsscƌ"oܹTVhC ::1cPjU.]dtßɀaǎ}oΝxzzRJփf͢W^l߾^zɓԨQ#DZ5kyAq@, V%=Q9‹/ht "ӼH!>|M6CDJM8|1DDDD1i&}C!㱵СC,Z~@jjj?WWWL_Eky\@rrn#"dO?GD+WLc7zYfF'B;AAAFb6p@#c$((wwwcc>`ݹsEsG;uܙVZgnѣG'001cлwB۪ׯ_x׹ݖGQ &`yH1z*ëjt$y̕Ç'11ٺuDDDDDDD .DDDDDDDDDDDDWWW\]]oeڵ,\THQ~cTXxXٱ8ly۳~&Lg}ftGǎϏ> +++z-ƌC &ceeetv{yBJ̒%Kؿ1Dڶm˸q㌎!""""""""b={rEN u~ںYf ӧOgԭ[Wqrrb*8<իW~"66GQSlY|}}quuetHRDQQQ<4hoooz-ʕ+gt,Giiiٓot"%*{iiiL8kRT)Ǝ˜9s|2cƌ!44\]]l|rr2ckkkG}tׯ3oc}<<,~!~!_}+V +++n!믿ٙ4֯_*ݻ޽{Ph)))̜9>}H*UpsscƌODDՕ@<ٸq#cǎ\rEĉ |w[tܙ[raʔ); /^4x"  tyKD(UVӓ itCjj*WfFGˋ+Vn::vhttR6mǏn}O_>{]nO׮]M6ƒ͛79gpp09/JQF2-gQnݺۛvrJ O.\ =,Ξ=X#BDDDDDDD:NNN899ぷzj߿m$$$zjȽ}m67+Ǐ3i$7oN)U*Te˖̘1s~) 6XI]΍7>|8۷oڵks S5jk׮'==8?~]6(ۛPRSSv۷ogذa\vo!996mߦM +kyxxxハcƌYfFo4iB̤ytܙWaΝ;nj3TlhҤ +W(~-[0i${<PfM2YYY9222-B :Δ)S?8qb!""""""R\ÅH1KHH`Ȑ!ر#DZ .pK\\\qpp0 +55w}˗xի7ǏkkbĈv.)AAA\p*U0o<6lHdd$3f !!o`` 4nܘiӦQvmbcc$<<zEDDD;[fΙd^z%?Ό3  Fvہݻw>>kߗ|٫Hsrr2ʯ}L>MbmmMf͘1cFܹOOOիjb֬Yl߾د8:u*mڴښM2}tk8y$5j1>{>""""""E1d[3-ȝ.]Ddd$FGy$lݺmrIT;3g.1˗̙3/@3gN<\׿>}:ϟ͛9kkk.]Jtt4uԡ{L2خGDDDDDDh y2bW- 8;YXXNۗ~j׮ԩS~Y}c~i6oޜv7 O?4'N0x`V UVeȐ!>}:ر#TPWWWswiFE:u'y̞=W:SXe˲sNݩyl۶ kkk,YBLLիiԨ<׏<:;ݯSDDDDQauv t{nٯ8ǜJ _?ɾ۲evODDDDDO?1l0Uƈ#] ^bELjոp}QEr-ZĹsHOO|W9 #gqտΜ9Czz:qqqaÆO?BJJ ̟??߱E;\Ck߾}tޝk׮ؼy3_~%...:k?7aaa۷2eQx':א!CxhѢYm۷/)))k_e^}\ya:t@jj*7߰gZnm?$S[ZZ?3?3k֬СC<3ŒN}V^Mff&Fo[x6l| V??6m[ Vk f֭|t޽@s~"""""jժq=jѣ9:::Khh(%_qy139`ybŊǓHŊ'&&M"R222|7n޼ɗ_~/iӦ_bsZjժFGTp!+WЧO0aٺu+oT\99 Fnxwy?3g7o۶m30aIIIL<5jÇ3f ̞=bv{W^'|®]r-6mZbż 9s#$$Aqi~i;ٿT(jNtԉ3g0|ΝK 8~8ٙ5k0}t&OLݺuz*_'''/_<^zfμ|ᇦk.]ԯ_xbccsVƚm۶CD e˖FGȗ8p $%Kɕ+WxW^1:<@M9}tDDDDDDDDu)<>6m .N:ѪU+>SyYti9t>c˗/͛׏e˖QfMi׮9ׯ7~XaÆE.____37oƆ{͛7_۷o͛y)]4 ~)4O?GQNC_rnݺزݮ(ӧhԨQ!(<:u* 4ᆪe˖ҨQ#+ILLCN杻eԬY~!CЪU+o!CY&ǎcРAlْ.]~z0ao pssGEW9O&>>Fѯ_?S_~ڵkWy;~e˖QtiFٳgٸq-Čx{{BDDDDDDDKBJ+;6ÇgѢE1o޼\$&&2`222ҥKNwZ NNNN9v8HIIlٲܹɓ'XuҒ)S{nvؑu3&G[-vY{j8}4...3SZ5{wnW/;=HJJ̙3spٶm3g,Ԝ)""""򸉈󘽽=+VϏׯSV- ᅬoٲe `ʕ޽ʔ)Cf5ju14iK.%>>"g/̜yYp!|'k׮ >ںtŋٷoo}QlY:uTWgFB 2[AӴiS&LyשRёxÇ7:<7n;{^zѤIӈHaBJ8::/{W܌1sQN>s̎_;$܍W^%))Ew~NC9eʔ 33Ӭ}ڴi :~~U=zн{wu5.]ׯ^zȻ&U^z%N8Qt?O1Ov4SO=eĉ8qbܹ3;w6k˯#>3/_ŋ;L2j*.^HժUx" #Gtw/""R\ED\FG(>/wyM6pqqqwȝ; Ƹq:uq 4AFB{OAWϫʕ+ \rlݺ *su;Vd?_322^gWAArqF p߮];?u+V4{%\d֐^OaL gΜa%(_N.5f\=yOjSDDDDDnqqqˋ;ҢE KDD*T`Ĉ'5k!!!GHHfR<ҺuF3f=-z* .^zkdddi&Wnt4yHdddлwo7oN@@CHIQ3|~[fԩfm5k4=\<gf>,AAAۗ[uV㶶QF<uV?NΝsZ*qd+`ccömۘ2e Y5k:%88#Gl^ren݊Y{ٳg}5e7s~<`$$$[ |^Ӊn Hh yh/0l0U5˗SN1zhgΜ)Æ c޽t֍'x4hܹsٽ{w7nLdd$+Vk׮8::bmmcȑ9r$GE=z?3h )U[9r^z:r?ѨQ#)Uuwȑ#9 3[a߿l666,Z'N0uTpppʊ'x-[2c N>ŋ-[;|ٳ'''J*EZxI&9^]RLJ*ų>)"""""""""'33˗F֭i߾=Ce˖-9&''닫+[G펛]4}뤤$6lK/DJL}*W6l ))TDt^͛c= cȐ!FBPWV*P?Hsk׎vj-o6ovlԨׯ/pvX鉧! ݩN:}ЧO~;wӓ*UPV-f͚E^ؾ};zs'OPFj֬iGDGRRL:eٳgҥ ڵcÆ kkkc# 0#FBDDDDDDD.Tp!"""""""7x""E5~xfϞ͡C8t˖-cذacgggwy\]]s=ϯ>D*Vhv,11GDY~=#FWj*|IZ)11*Tm(]ёK*ry\2IDDDDDDDDDDD1ֳgO{>)yإ,m(qgy"_AEMER;JAIS+%4( Ö,H(D?k=.9 g `{s^sFܿ9Mlܸlz!Zn @5,z)8vW^?୷d2kk>"--֦MRSSe0HR VÄ\l7 IDAT0om6֭kt{N)Ǐ[=h2HHH(){oc$˝QTTk׮ 6)1cưpB jLJ={UZj1ydzꑑ;NNNн{wbccINN? гg^ڵߟ@iڴi}U>BBBؽ{7mڴaŌ={{RG$x &N<`tJG]"""""""R:BDDDDDDDN1*Cә6m+W$11X""b;.+)wwwfϞ? 666lΝkgggGhh(899QZ5ݻ7k׮*Ԝ6mM4Zjзo_j׮M\\\ qqqϖE*7n+RL&<<<]6}Geĉ*CթSVZsqqaF R"""|1D4:]%66%r󃩥uDya֬Y :'''DGGckkkpB  ĠAn)S0eʔ"fVN<==Yf OI&>}DƏOڵo"RZjVΛ7vѲeRWDDDDDDDDDʟN2at  >X'ȽORf0:&OOO]DDDDD/^dر:uv1Kōrssȑ#3gJrr2!!!TZƜ/&&&K.m6Yn%ft"##9<ͳ@\\pb˖-|7cggwkޱct-8ݺu#>>;w2dȐSDDnֹsgXt)'NT"rrJ6nHF^dQqqq~FGTp!eFz`[etΩSpvv7ޠm۶>|@Ξ=kwݺu9r:0sLZlIjj* .$>>[2x`<٢$;lw΢ݻ+VХK=J`` +֭ϯY֯_38p UTÌ?RXqǏұcG=ʬY8}4}&L5۷mܶo>\HDQ<==4:/+Vbȑ*RJJ nnn1+VGDDDDDDDBP)<<PvmIa'VFEEEDDDDDDDIbgҿ>>sN:iذ!۶m3:]i殛;**6lXyFJCE:\,PJ[YA'<ܩҘzu_\v U8ϒ%K8z(M6'e˖o߾׻}4ZjQ5/h-涂>K2i$~gnjt[ݝtot$)BZZFP&99[Сa&SN%66ȇСCa>|8[*"""""bM?cYڿ|}HMM%&&v-9N8t>`2ԇR^=NǧȾ>>>ٳ$ժUɓ'[^׫W qrr"&&dԯ_?ڵkKwl۶ٳg3{|׏;Fnݬy6mU%Ys݉%99WWWzYݫG"R \p>9BϞ=(KҶm[fΜIHHH9)={rĉ"O;.ߘ3g}k׮1m۶뗕ſ/{9vʀXl.\g20LG=xgXh׮]cժUOЫW/^xlb5w}O?m>e*ɺ ;++HtBÆ -}7nd"22"qғPh-WfРAw}T^֭[3o<lll,} '''U{fڵV')L6&MPZ5rsso;{I,̲eѣիWaÆ=UVYOо}{-ZĸqذaU3gҷo_lll_>ÇgԬYTܷo_j׮M\\\qⰳb"""T/}0_/0ydxNOCK˗/sa>ŋlٲedeeY> cv55ܹ֭!C(HY_~Μ9\pFL2)S9nnnVm9>ŝ֭o9wqƲg…^3]| J}DƏEDet)aÆD~Wl̙3y饗ptt,G>`ܸq$$$P*""""""""R跂bd:tPp9ڵkoA x7 |ᇜj׮M@@ |ǖ~w Gy5j裏2sL|cB͚5-U?rݼ gxx8QQQ :nZ%.(ɺ rqzA͚7onGDDDDDH 88~{ Wթ rw%(([rΜ9֭[ VZF{[nݚQ"R*zӽDDDDDDD1:Bʕ%Kd3|J˯ @6mwi}QvnqnԲeK\vk1w\8xwy,C#* }k6s# oO?Dnn.5'`ر4lR ;wϏK0qD\]] N%""r{?^e8p]veذaMt5FŨQt>gg2_V233oӧQbt )\HTJ;ըQyڵ+{O>waݺuL8!CrN˳̙|oժ1*"""""RV'FG)ue9ݨ~""RL::t6l@^^Çutр"w?5k;?ƃ>ht,2;?#Ǐf͚FGT?9-RXz5:t !!+WJBB,5j"w,JLLj7vrr4hk֬?d̘1?e˖xB/Z Z[q]GGG:73u0k,θHNNN9%%%1n8xϟπ8v}=z0:Hz*Ço%&&F""""""""PdzEACXt)\t%K`2x-z … IJJʕ+$%%h"zY`2ظq#vH-[FRR5k֤O>kZxVVt҅ Z4nDdd$F޾&{Vݺuoy-FT^(~i㈈TZ*rws?`<8::FHHҥKj yK?{{{xسg<3888xnwwwWNTT'OiӦٓ1cXM6~trsssTZ]vdb֬Y]}e1zhqⰳg-!"""""r3///lbt  "%1c8w-%%ٳgsU x饗,HOO'""xBCC]me?~<\tM6q5 gǎdggqNn݈gΝ 22T4m۶5:+W"%<<3gontJMRmf?7$3 .eunA1hР"sssͭXs2c f̘qYwAsשSOOO֬YӧiҤ O&11$EDDDDD<<< "=$ro8wڵ7ޠA|DŽZ .>CNm۶ȑ#̚5֮]meh֬AAA4jԈ5kݻ  !!3m߾}* lڴ ___[ZZ&M"##_8R\|y3a㈈Tz*b3f ~)p68TQQQFG n՞޽{>}:...;]bݖk<>(3g'_~m\["44yǁ7k޼U(==իWj*Ξ=K/dtiѢ̛7Zhat$@jԨ_M"e`޽XBBZQNvJܚ-AAA꫌5 [b jժep:Tbt "믿ЦM">}^dqN:Ys;Zlik׮yOFF}D*rJ6n܈cǎe„ {?ׯgĉl߾8R8::AHZZFPHΝcҥL8WWWSHE2x`<==!"TDD[l1:Hv9y LN5*˳[h5j8_ժU]3U*Ci&\]]Yj#G7sޣW^DFF2b#HPܵtS?H"RI]|Y"F/Bv ?Lbb"?=11'''K[*UŋRIOO'333.晙>"SL[nFG)5=z`رkۗzIDDDDDDDDDJYDDDDDDDDDDDDݻw`ҥs%,Yd矷ݻ7 .$))+WĢEٳ-[ɓ' *,mmڴ 555_sHE1` UlaxbEDDDDDDDDDʀN)Ǐ[=h2Oi,NVɛߧEEEqvʰaJ}~<^xvERR /[3f _~%iiiV\\\z͛Y|9˗/իGFF899C݉%99WWWɀuܽիʕ+駟"k鉍QDDDDDDDD:BDDDDDDDN1zEO"$$ӧ3m4V\Ibbb9'{MBBB憽=5jԠm۶,^[ưahذ!ժUaÆ9k`;ydJݺu[n̚5O6&MPZ5rss۷/k&..._8xgo{N)_Æ _7:cf͚رc-""""""""rw R0k,mٙ ޲_ݺu߿~̘13fX37fVN<==Yf OI&>}DƏOڵo&7;8""""""""R\H|2Æ 3:T0U< ',,g2bKȑ#Y~=aaaNDD3O?pKHxx8NNNx{{NDD֭[yW b„ FǑr֣G!"""""""% )3ᄇCDDDDDD*sαс IDATb KNN-[d̜9.f͚5ڵ Я_?Ǝ 7~'ř Gpp0vƆ=z0i$4hPfyرcͣ{?3ӧy deeI.]hذOƍ1LDFF2j(o+Ƚ֖ ^}UF\wŊԪUt""R<ȑ#7ns1:cH Bʌ7\xcr)K۱c,7ח#GXΜ9Chh(ɄPjRWs.^.]ĶmHLLdݺu888I3fp!,Y+7&==`6l̙3 .nc֭[kݺu#>>;w2dȐeu???.] ĉquu58H>}XrqDDDDDDDDJ|8[cǎ$}Y~G-Zy9z(-bڵC=_źu裏0LZ ~C^^iiivY Xva.\@߾}47|CDD;vdժU~zzI.]ߧ6mڐNjjjŠTK1TT-Z`Μ9̙3ÇCIDDDDDDDDDJH"(66f͚СC-Htt4SDDDDDB>ǧȾ>>>ٳ$ժUɓ'[^׫W qrr"&&dԯ_?ڵk,OVVAAAԮ]yQzu9r$saÆ >uޝXquu#99={8<==4:He>L^^DDDDDDB g2 < ٳ16rH֯_OXX~~~^+.\@-fXݻ9{,u___Zje;m4~mͽ%0˖-cΜ98pcZo1w\pvvߟ9ŝ |ˉcVaggdz>[""roۻw/+V0:ФIѣ15jޣ{ڵ 777#I/g\e.)ZDD[l1:2\Hu9VX޽{ɡe˖=3gdggfvN ׯ,‘OHH ++HtBÆ -}7nd"22QFaoo_ׯٳΜ9@ 2e SL)rL77|GgwƯ[.˗/y,X ?s|wwwdɒrC?KE/_VH .^رc9uꔥرcbˑ#G,mgΜ!44dBBBZjsرluZn݈gΝ 2W%""""""z";;3f憝,^vkcƌO?%<<qrrt""b(#H1UR,[TlNtܙuQZ5#H)))q ,<ڶmolsܹO?c= ԫWqr%(([rΜ9֭[ VZF-ߟzyflll$""""""""H'\H3Lj޽y\]] dҤIV}w… qvvE1x`mVǏYf5oܪ9\\\ؾ};?4jԈ'xcXl/stR&NDDDDDDnOnn.߿uRڻw/|{%55WҰaCq^x{9# )Dyyyw""""""""""R؞ìY:t(NNN8;;N`` 999RDJΝ;rb c Sp1^[od׼GZZ|{jjjm /"""""""""RٙL&IɕYXXgϞeĈ#GrY L&"ȑ#ߟ>("Œʸqpqqf͚899ő#G _J[~,!!~lllhٲ%3f… Vؾ};?7o+4wwǎc̘14i4i'N(r]| O?4ԫWAY߉'UVԬYΝ;3w\)i+K.oҫW/^: 4cϞ=Æ t6mK/t׭QDDDDDD*7)}?3>>>EaϞ=$%%muVZL<^zddd111tޝXquu?99={DDDDDD*hjԨat  "%o;o>.\@=z41l$$$X{sի6m[fժUdggfvN ׯcǎ7d2ɨQ/wTDCve 0 IPqqq 0[Ӊ`lڴnqZx饗zɓ,^;wG:uXnԯ_sо}{{1O?~W>6nȖ-[ӧOcu_-[VeF\nWyeՄW_qZh7g϶#޽gRN\]]-M6~trss۷/˗/'..ѣG[刋rↈ-[زe1DDD1c8w-%%ٳgsUx[.[,ↂsss9̙3LHHUZ6>~x233gnڴk׮Ph;vMn]ܹ֭!CzE .d˖-L:U']]+##Cɓ 115k'Gr_^^^-Z̙3x-?ǏիӤI8/ȡCXx1`޽s8@DD:uȷSL!&&_tRb 777><Ȏ;S$&&riKӧO7k.Պ/}{|sh׮7o櫯 44mѢ?55(bq\ .SOyfڷo ۷gCw-5k? ));uĎ;puuƆm۲i&y222x _NJW^dgg3c ܰ#55ŋX /J˘1cO ''''Ku.{ٰaÌ "`yIDʟd*V{BBeӧ@@@@EIȅڵ K3p(#((m6l5%?<ǏkܬyV}D2d /=j2:_~+PN#+I ? >vX|MvoQ`LFɕ+W۷/-^ɔ%'';;-NZ*:wfkĉ{1|?כ6mʉ'߿?'NW^4m[ߝfQi|~E y$ խ[R ӧO/O?%00 eF\]?ݩƍ &88zz7n\ikkKPP*F`֭XB8Att4'!7iӦT51ܪ=-- A?%%%_[˖--;88pڵ"ddd`ooGD=o6ڵcѢE̝;8rl_|Q-9SN8Qq?ӪU+֯_Ojլ^>_EVVu-=5I^rVZk3q3g /~\/xg8p  *l7*ϯN<?@||<$11ȓauV`{.]8z--5H夂 ;m߾~\5jO<رciذaٹsgXt)p}WWRGDDDDD^1D"ZBBk<7K"//rOnnn :ݢ pB5jX/n~sw=6m-E\rwz*#Gɓ|FG2ĭNaU(OW^>柗=UV$$$p1bs -04^x%TLJuow/vZ֮]K˖-ٹs'-Z(l7ϯ86l̙39yd5֞}1c""""""RBZTZOOrLj9EDDDDDDDDD*F/Bv WJxa }+NNNs]#dffhu-33GD]& 9_~eTu_%>MѣTRuN:deeq…bѳgOرcG .ХKȺuE ԯ_?=%[ixyIKK/`޽ݻ?㏼klݺԳW7?xxxмys4h@۶miݺux}2CYQDDDDDD$VH""""""""""""ݻtRӹtK,d2[w޲e 999""r,XիY~}OP&_ut#F ;;s2hРBlb=b}]iE9iP9 VJ /k֬gϞ2v_q-XUVqQ͛Nj/ȠAN,vZvz"""""""*)Ǐzbʔ)ѵkW}YL޽{dnɄd*#**)S0em^ 8::Āѣ/l׻wo/_NϞ=6lXvL7oNRR<ۗ>Zj1y޽GEY )jxI3MTH7vL#byfxɼĔ4o%(̂a 505sT/ZZgwr_XO߾}7ֵk … ؾ};/HnSO'_pTR>}O<={ό3JXmїI*UhܸgϞ=zA_>̼y󰱱aɦ^zo[\tyO{Y4nܘ*Uעˢfv_Yw 6lE_DD낂bϟ7oEEEfm.\`Μ9e7X("""""" 2xW h￙:u*!!!l߾SNqF IDAToĉ?IaaM޽(^}U&OIOOZ>""rwIKK#-->WWWbccٙjժѲeKΝk6nҤIPfMb̙7111b0ooo/^|]NL<777lmmM? GGGvacٳ ߏ@ժUٰa/S%SfMRRRxꩧصkΝ㫯bر 6Uf:gڵ|iӆ%K,Q_|{{{bcc>}:;lٲŴȑ#YhuaÆ nݚ>Cq wӓ'N0c ڶmk63_}deeQXXHVVlݺGGG^z~ HNN毿… dffhfv=_y4lŋM!'O,;wā(,,d>СCCzz:s%99Gc=ƫj?\1FEf͘3g| 4i҄ ^}U-iݺ5{eɒ%Z N8- 6{?~1?9sؼy3ǏnݺٓiӦѲerGq\\\o;w.k֬_~4nܘ~1uT֭[a+^x{{{}]ۇ=='N駟Yf > ҿ󃂂cO{ۗ3g}=BDDDDDDD8'N 22;wRPP;ÇgyF~~>$''sqԩC޽=z4vvv <:--ʹ͊-TvmJdd$xINNΎ.]0aԩS9sEeN|x}Æ 3R n8GB*Ldd$ NCDS`` NCDDDD/FÇMm7[\qƑej%&&L)q uVjN]t!22ݻw[͝;up9HOO'..o gϞСCG]윱cǒg>ҥK ]7n$??///񼼼صk6m*vJ}Q7oǏYHE_/"""""""""S 00":tfG``|\x>L oaѢEf;4őE֭IHHoe<#ڵkH?~PjNwǎ۹s'|7РA~7JjK,СC;:: pA/^lqNFXj)))5 ԟP.c1FDDD*G`` ͐!CT^z֭[3vXJ_U_ʯ_|#GX;BDDDDDDDnyfGiƂPڴiCj`ƌMNN ,,͛ckkK&M={6IIIUXX@ժo"jU$iӦEjhӦiw+ ʢn۶ig-[X3e6l=AAA>}ra7nl#"""""7-1_5NRTTĨQXt)[XDDDDDDDDn3kά"6''__buRǪWҰa+Fǎ?#>|ԱKm۶f~8 .]2:u gggsm<<]D*Usgϖ߮];rssټy3=\q7o6_1667gc+ (VZ5=?ƶr1w̙c۽{w/^Lhh(SLYf駟… ˓AɡaÆmۖ~3zhƌO<+'N/?zz˔޽{ W^ƾ7/&,,7xVZe뙔բE =JvvEaEvv)FDDzt҅˗[; )+{j*:udTn[[la3iӦY;MBθTq+رc <6d.]Jll,VNDDDDD_|ȑ#K9r$[neϞ= :ԬzL4VZ:u  ֭ 44/""",޽;3g,6ڵk[٪U+ tͱ4blBNNF2kذE[Ytܙm۶Y_ff&p}"""""R~>So<3̟?کmDrWҥK,ZM6Kjpww_~+k@~~>$''sqԩC޽=z4vvvfy\ә3gHLL}ԫWS~}<==ILLdذa8;;W$"""""r+hE9{,M4aС̚5 ɉW_q1jԨƍiӦɓ'pQ Mvvv}v>sӧY&?0~~~t֭|#""׿Ejj*k橧2XWrvv&66>[rI\]]y'xpqq)s{^z{cnַcٳg+""sNS||>>%w֭ŠԬY{cWtRfML”)SJ^I+WרQ@9rnnn9rtƎcc\KQQS2RS$$$`4DDDDDDDDX*VZ$%%βeLe#++֭[3}t&,,]vvZHKKm %%-[ZjlKIIQH1uF~~>ӦM''';w.ڵr#F~zM +"""""bE&LiTp!X`pV۬={x:7\W\rr2aaa4h&M0{lHJJ*QF}76s}aʕnWV-ƌcnO̞=_~aÆvZ"##^8*&NkFjj*,XQFh6yq999;KԩS8;;[ی1""""""bnʔ)4lؐ 6/PXXȽKN=z4ճvG}`͛rV"""peZ|9tؑZ%{8p-ZX; H\)M tWǗC LJ;uV֬YCFF~!qqq?+Z@9{lUTƢfs666hTJevxNEDD*ݻbٲe1h 7o#MDDD ֭#--صkWggl3ƈH*((`̙`0hР̘1k'"wGyg}`Ν;gtn L: .D~ʕ+ϧYf4ojժ;{~.^ɓ'ydܸqXN9996۴= <==M;%*bcc9v6 2cǎkDnΛoiTn˖-5S/Z;CB1bt֍N: GFIƍٳgCCՋO?ի3i$SlZo߾tL\m]v97/"""""""""ryѣ-??KN۷/~!9s???.]dv<==ׯ)611S^=S\$113gToYYYNj݋? ,,H;p@}˗/'$$/_^YȝJbuiiiY5f͚Ń>vvv3rH^{r999C`` [[[\\\ffSL<777lmmM׫W/ٱcE;vɉ={V3""""""b=AAATRE:rYǠ܀w}8~ƌ@aa!ƍO>~ĉt 4Ç_]st 7^^^iӦ S M67"kSJLL UTvJR^yg߽{7QQQL<瓞^ȝ <|}}esqq1R|||jԨA`` 9r7779Bzz:cǎ9n\hҤ 7 5..,Znqww';;0vڵk#((D/^l7[cqᔔZli-%%WGc?o*ݻ7Z ;;;k$l۶mŶ0sL0 f̘+ppp4EDDDDDD.DnQ#F~Ǜ1 :ԊTOOOZb >\\\L}ѼyslmmiҤ g )) 5k?_ 3gȠFxxxp5jd{ƍbDD*&L(v;M˖-IJJf͚NU{&66cǎ1x`Sې!C8vVLDDDDDDDnwBnYGv9880{l^~e ڵkzVNDDDDDb 8)PTTdDu5sM_:e˖_5/^SNTzTN:ŵm;`kkk4*}ڵkĉDFFsN pwwgL>0|INNԩS޽{3zh%Wbqi߾=3ԯ_OOO6lX""""""""ע [أ>Jpp0`UDDDDDDTZ; K%$$d4DjW/sʒj*Ν;… 0]ٳk׮MIHH 33ӴR|׮]M1UTrqc1FD2mrk믿=z46߿TlqBƍGVV-77233*}hƍeŮ]شi .uDQ5HDDDDDDDDD!!!ԩSHoNVVZ`0ͺu0 ׼ְaXr%˖-믿ƆΝ;]]]9z(yyygsa4hoI˖-ٻw/3fرcfqqqdeeѺukO;لk.֮]iiibвeKo ڶmȑ#ٺu+{aСfT^I&Y\kX]uܙm۶i񾗙Y9"""wcbvڋ̘o:x`c:u ggg>c1FDDDDDDDÅH+YL:oΩSp۷ogĉ]QZjE˖-9~8;w,5o%77&MV{nxW}ر#&))ڴicˡW^p ԩcs)oNy駭˱c& 2KKppʔOAA1Æ +6nĈ_xL@||<CVZ""wϓO>YǏӻwo4iҥKvJRF={fΜ9<۷9sXvޝŋʔ)Sh֬'qqq|xzzpBNEEEҢE =JvvEaEvv)FDDDDDDDzB*̄ 0aP;w$((im&>>^;U'NΝ;)((ݝÇVP#??h9~8uԡwތ=;;;W~ƚ5k>|Yŕj׮СC?7\Bxx8ѥK&L` U9sEeNEEE:tQC*_ѣIJJӜ?-TXXȸqO8<0qD.]TXtݻw[͝;uq9N>MRRFeeΞ=?ҥK߹pG%!!ѣGoqرcٵkΝ#//>SH]z5,XSٳgM9$&&^)Ny^(g޽Ǜ6nH~~>^^^yyyϦMn8w=ԫW{{{:w{WJ>(̛7y1~xI""Ldd$K,a֭N ''' 6Pn]kt[KKK"Xhs=TZ͛;99C`` [[[\\\ffSL<777lmm),,.Ȏ;,رcNNNٳXDDDDDDDTB*Tj&1A""""r;4hЀ7|-[w^f̘cbʢuL>www c׮]]??w8~8Ԝ>nIoߞ}1c ~7.q-YCoA˖-b̙>)Sd0 :%"""""""w\D;wNA"b!>>^+Wlr򆇇ElNN^U^=rss-ȑ#u#<ÇK1ڶmkn|~7sM_p%'|lٲӧOӧټy3NNN{ &Mľ},*ؤzM8^{TRSSY`F"00իN:mUÆ ={6 2͛[;UR7|iJZFѧOV\Ixx8fjb̘17uLfϞ/̰aXv-fEDDDDDDDK"7сhѢE}˗/'55חN:ѷo_>C M1ƢgΜ!11S^=SL$113gTΝ;yhٲ%s뭝^Ri%e0ӧdddAhh(}`0ܔ+Z*jբ]vL<_~׸Yȝ+--}-Z/sUVyٙb!00-...x{{xb &Of '""]r=`ccCZ֭;oDD]tjժԫWÇpBvvv3rH^{5S\^pttdǎر'''Ӯ)""rs%$$;:n#!!?>?NjjS)vRTTK,1=><{e޽_PXXȸq2Cff&QQQؔ\qF]ˋ]vi&NDDD|;ȑ#ٰaEÇ9|0}}aҥ7?buzv;,PNvBBB )>>>߭[7uV\k֬iաikkƍK3aaa.iӦ1mڴkS __RcjԨA`` 9r7779Bzz:cǎc[|S28pS;Daa!:t8`ŊNADDDDDD* .d6|<==9}Xr%ᄇժUlٳy6lk׮%22ի[9;B>}HKKYf2?V\Ɇ x+e;Մ 0aX;k8q"2h bbb8wY\NNxzzcKԩS8;;[ی1"""rwf̘14l{{{ AAAdee_JkWKKKcԭ[;;;ݙ6mgϞ5۱c6lnݺZʢJ[6MZ-ψ#pss777FO?T}|wjժ/v*~qѴiS{xGy?=Q>}X~}vcz璾-sÃ#Grk^ܹst WWWVJ:uxٺukǿ, BzÃu֕Xה)S e˖T^ f裏̼y7oǏi-t/_NHH!!!,_):/Vx|GУGJNTСrh tW\a٢"w;vd֭Y >C?~<\=ij?X6ǎ;xg8}ѣ$$$j*>kNO>/:ܹsٴi;vF0n8j׮}ͱFC=c=f־~z @AA~O>aʕ^][MΝcݺulܸ[ҩS'Sw}O<3gLm,^TޛnёZ_ի:F/\lllfѬ]cϜ97?Yɓ'IJJbÆ ]gyLc_Drr23;g׏%Ki\\666hTJUln5+l۶ݻwŲe(**bРA4oޜGy jժ,\Ν;СC+lO|P|UF||.[zLrrqq___ؼy3|  @vv6֭`0{ WWW=J^^f}yyy:uΜ9äI#==hbbb d߾}fwW:gOS/رcx"ƍcԩʨQؽ{7s_`Ν:D^pttә4i| oV .{?$00tNXXM6/j*""""m۶^PP̙3 0nό3XbEѼȭcǎ;W^y>}iaѼysY&0` v"?^""""""w eEӓ+WOfh޼9pyݻx"'Oӓqƙb;UZh@vvE6c>#;ӉiӦT^;/|PuRSS5k* .fРA,XƍSZ5vҥKOMGZly5|Ξ=KYj=vvvck~MRZ5fYvwMnt<ϕ..Q K,s888`ooOLKٳLc^̉'ѣVUVѮ]; Zn}=/""""i)V˱c~R߉G===e!BdXٳ'}eZX~={ 27qrřc><(;#w2Hjj*tڕ (u5j> Ϭv|wxxx( ,*Z+W 燽=.B!B!jz@r ===q_^d yPReN8Arr25kԔӧӲeKܹsٰaIII vZΜ IDAT9Ä 4b8s ׯX!q]VྩSrMZlΝ;RX:uTwԮ]XyJf͚deeiϛ7I&qyΟ?|۷/C O>b˭,޿f͚Ѿ}{Μ9Cjj*j"%%`Zj(KrÇq+\pu|i~'ԉ]v{x7n{uBWCB´iHIIѣG޽,e O|HLLDR+WёpV\)5")) WWW4hyd9BZZZ %00Ç?+ nl۶͛7ӳgO]#D/9uTqssc׮]dgg3zhZnMΝuB!B!*"I, ,,,gddhRӿ5kbmm 4i"""6m5j(I!QU eUSV@Whٲ%aaa\|nݺ'Oazvւ6jժԫĉ]6| /^?`֭lݺiѢEĖ۳jo%((+++>̓'O ]ݢ,/u./Vԟ k.͛$KVi~'״Đ^{bF8wHSfpvvaÆxxxR8qℒpELL :t`޼y ߿KKKjժŋc…l޼ECV\aaaʌݹ m۶Z˂%BQyyyXW ]LWSN[΂ 1b2щߟիgB!B!$B֖퍃cccBQ^j֬w^Wߘ5k*UˋvGjj*<(Vz",,#G+իtڕ!C<~=RRR[1Sb+ Æ cذas1Ξ=ٳgz*ׯ_g߿c{/7uJyy_RTTIѣGeɓ'WPaܸq[9͛S~}ڶmK֭gi~'ܻwziEY???] BS'3UAN6m 䬖R4pqqqhggg,-- Yooo>S;vl]\$ռys:BQQ7^.,*W\ш_OOO3fR6vXv܉'vvv:N!B!$\ jϪH^:̚5~֭[W!gB!ѲeK.^ȹs4hP{cƌ!--%KB DGGӣG"3f }6mbΜ9&&&/2p@c.\+KM6eҤIL4 ~!C(ul}ٳ'FFF:tl9B͚5ʥ\2YYYi%\~) 2к˖-`L6Mc_bb8swC={_~EkE;I>B+ٺAQ?éW'R SjlϘ1 .E-ϋݻe:B29s&իWgպEP$, $11}}}LLL:tXziiixxxM4hSL@#1K׮]iРRQFT!B!/?It;;;VZܬ355qTB!(Oŋ,[~QϏѣG3h s,e_>}VEtt4o6͚5͛@#((ѣG5j[Xj+WfܹJ_Xr%x=++Kӷoߢ/R7oN\\Ѵo^cV_^zzz׏ݻwCrr2C jժqթS;wJ>}4Tgn믴lْO>к˹YFy^j%6lgϞeO# ;;[9F-KKKu޽{uIř[___y_gQIT<(IR_"LK/;ٳgC۷oW333"***+^FFӧO'&&FJ"::77B'8riii~hnnNhh( >]!B!/6I6S<0$Bذa 8:ve֭~6l@ǎپ}{fƍxzzҨQ#f͚EZ /`ĉǸӵkW:D/4hM6%33ׯs!V^۷Yp!:us8q+++\\\hٲ%̛7'ORF fΜpر2rH{ͩZ*/_V@rZP+ٽ{7 .T˳ٳ'cԩxzzbffFBB6l`ӦM%nɓ'߄F`` xxxh%մiSbcc;w.-~\|+Vcޝ;wL(g}ƚ5k dȑ,]-[r5ϟK|=DFȑ#u) BYÆ Ү];bbbpss޾cիGRR)))ԫWOc_JJRG!^V6mɉ7Jx5p֯_ʮ]D"&&:0owwwNZE%c"cqpp`ԩlڴI+cr5~g6mZh[Uvb޽ݻwkR>>tܙ͛7cggΝ;ի]vr>fgg|mӦ IIIi%V)ue~>sp^ys5jq{fĈ1TUU7n @-pvvҒ,-- ʕ+~7ؼys:B!B!xB!L <&Oo>kצ_~j݌~z~%K`ḢwGDDD0a1c9WCa[>}{{{Oׯ={mffVC4燽=:!YyDFFbccCn0`;vZj̙3TQK,AOOO^hԩS+++ |n_]7Y!^ǎ#44.\`رL:Uk!fϞMժU cѨT*=zTzXXX(c333廝B{.3F^2u!B!Bd !B!Q֭(VT}իTZ>Tk׎;vzU]6...$/755Z8kc„ L0!Ǐg%-[d۶mZ(cc'^L_~%NҚ,\cǎi?>}ӧOӯ_?/^A]фƮ]fѴnݺVBj*T*l‰'HNNf͚2}tZl +/Vfnܸ1,ZWWW-[ܹsٰaIIIddd0`֮]˙3g>9sCCC"o%!!/͛ 2>(BW޿d}])ՓGGGTŋ ,,,رcl۶5k(ŭgllL\\(D#))ի/%%E#B!B! dԨQC!B!J[n}uVpppUVܻw///v؁7orV&>>MЦMJS!B!BH…xnuB!BQjWo߾ӷo_*UՕ޽{pPofݺu={tLLL0a45 ((3h Lܯطo&LHȭnݺذn:~G%BNpp0a``@Ϟ=/_~}t;ǏΝ;ԯ_?SbhhՎ/k֬!22UG1{le5, $11}}}LLL:tƊҵkW4h7j333|}}?~dʔ)ܺuK)|l[FFӧO'&&F)KLLDR+W.K.SϞ=YnZVXxDDD兑Q'˃OqRT*jԨq̴iHIIQ޽{7YYY899ەDEEÇ7nG!-- sss %00Ç|BU.]cժU̘1CAN!x?ЫW/|}}5VWBOO???eoЫW/lmmK\JŖ-[8qԬYSSSON˖-seÆ $%%Xv-gΜa„ 9sCCCܮB!B!^p! .ȑ#u5eB!x|wC7nݢq|7mۖ(ϟOrrF]///bbbСĄ8\\\ eXZZ q1Z={uѵkW~7ϟϟvvv۹qM4aҥmۖ,X@ll,[nNf͚LÆ @Rq %bϞ=_333233 Օ]v) mV+.uYpp$\!xeX[[cmm0Lу)S`ooytZXX`aaQŭgdd=߿?(Y&xxx@&MHHH ""iӦiMZ B!BW$\ooo]!(!CSB!BTꄃ8qNNNtYdZBƍhѢXZZeqg++l訬 ѱcG1c'NJ(L~ݩS'̙͛39~V{4mT*߿Q<ۛ7nлwoF#4ڹr W5!B!^LSe,$ċ֖퍃31666:N!B!$\!B!;CQnjjU7>>3ccc A$&&$.'!!AW5;w [ >:uQ1&&&k###ٳgxbBBB aӦML<kkkUԻ{.jC]#B!x߿se Ua3V$իWٙYf1~x w}ݺuc^!B!B$B!B!^އ5G$*UTd|ƱŬ.˯}!B!Dwqƌĉ[Lu;;;VZ3A!B!.I/|8xzzҫW/ZlUիl߾KKKcp|Ҹqcn޼IDDݺuS#""Ju~򅅅p1mƚ5kzꑔDJJ 8>%%E#BGOBQqEEEaeeE~X~eE}غu+NNN888ЪU+ݻ;v̌͛79+4dggOӦMԩ1dʔ)L:}R^=n߾ѣG?8p`e˖)qFEE:W޽ٺu+...,]vw^J|-JBB ͛78qbu'Nɓ'Fc_j՘3g]N޽8p'''?~ѣGYf k֬O>,X ֭gv=zt}fkkljg6mUVꊫ>SSSu=8u@>Bd$WJJ N:ٳ5j:$!B!B!tB.Ι/֒UV孷֖Wr$991c(ecǎeΝxzzbggB Ξ=˺ut/ٳx6^:qi}(߿Oڵy/05kְh"BBB[}/ IDAT.dʔ)qwnjӓ~'OrիG߾}022*ֵ ===qozV7`֮]˙3g0aFgΜА~!/7? bͫaȑ??ڵkY?++ʕ+CdB!B!B/Iޱcb+=zÇ,Iܹ3׮]S222>}:111JYbb"*hܴfYbѣG2 iiڝ6m)))Jw&++ ''_ݻw1,\O2dFJѣ>}@yȑ#ann92|pB!DYuB B(?>iii8::ҿ cŊ/ԃ3/[[[<퍱1666:N!DE&'!^2yu :Dqrr9ET>,--ٷo_&}aÆR7n5j`֭m.zжm[8e:B!Bpuu?weȑQNN_NիWٙHbb"ٙjժ:SL޳p9Rq!r:!B!ρ$\rNa7}V\oo| ۷׺19͞SqEz-> {uW'%T\W^8o%ve~e[.ÇLJhΜ9@^}eO!x^:tYLɗ_~ɩStra}Ʈ]fѴnZIB!Bϟ| P1OqE2b9s&ҥKiѢ7nTVOKKcT\OOOnݪٳ\xQc"2֭[W_pBɷpqq!44#Gh)m=O>^W>}s͛yFy9::*/`mmNcBaܸqC!B!D~*Y D=Jb 2Dc'Ox74n`̭$u{V38p0P"##5x7ݢz<6l:F^Ǐ]vq9*WL= %%EXuB+%\_uNp}`F17ʊ瓞^Q !B!{M6ʼy -/kEy5OIXC Qqr%Yd vvvTR˗/E͚5{?yŅ/~W-[VIDGG3{l]F&M0`O>899qe>}ʝ;w133cZm.[ho6_}\\V?2u!<)?۷ornԚ ܜU%*OOO3fR6vXf~B!B=x,'133rZ.JNPBT6lcǎTVٳg9IQ?ueذa(>qFJ={ Sĉt===ڵkU8۴iCꫯ`ΝkjՊի3g޽[fHNN7+B!B!^|z@ݛ.\… _|ssslll8vW\aԩh=|_tCȈ+VM8'OFjժ)_Vn]&NQ֮];FL$y?i$O>gi՟0aKc_=8uјjS!U_qFy͛7g„ CNd}Fe͚5DFFRjU>#fϞMݝ@ĄCbiiVaaakwwwΝK֭ټyF+/ ;55___vJ :5RfƏOZJF! 1BA(k׮#oyq1jiiixxxM4hSLQ7 wGaɒ%cÇ3|>#\]]xqYqXyu|MѣG5ͭ={y5\g6+qW-Wur},̪U||xʭ$u b``1ǏaÆ QTlٲ'NL͚5155elR5kְh"BBB[.ԸWvs.Žϣz鉛ϟѣGlْ'ҷo_P5 0kr&L̙3*7BsUi֬w&::'Һuk|||{w֖۷o+e,\O2d睟#G>sssBCC d%IQ{w^]!B@i/UqLFFӧO'&&FJ"::777*W. gʕҨQ#puuA̛7Y1z"lllqΝ_WiJV'&TRcJ^PT8 맴}VRBW3f  `޽xxxVťT+/9uTqssc׮]dgg3zhZnMΝuB!B!^&p!*Zjܫ1@΃8::j[If1Y{{bկ]6k׮-v Yqy]t f͚iXTfM !!&M@DDӦMBz%Lzym۶qmڵk7|CQTJ۹qM4aҥmۖ,X@ll,[nNf͚LÆ @Rq %bϞ=_333233 Օ]v1n8eТE T*ƍ:m۶Z˂a!!PvvCB! $㗂>T^q 111tЁyabbB\\...~,--@+->VZ,^;;;.\͛Yh>dʕ{ˊ{-d %ċѣ?~ȉΟ?O>}ӧO?ּys\͛7i֬Y\S&MbҤI޽+V`oo/ ԩS`F1VVV̟?zB!B!C./4?Əo=[[[<7x{{cllM+BG`Ѿ}|g95m'''%)Bĉʾ;ЩS'̙͛39~V…qPTܿ__F S;v,3ϳ+c(!^ ;w[nE֛:u*^^^$;c +֬_;rmV^ͪUӧǏ/x}UTl^J֭011ƍlܸ:uDll,@҅^t$''3flرܹOORB!B!IB }u֭^:̚5KIؿ?֭ZjBWއV\ʕ+KtR?hӦMr{w4DyM5++K)={6/&$$6mɓ.h9%UݻwdR!ʆ?#Gq$BW!!ċ4*8&>> |Q?[%Θ1 .E- ,+c(!^ {WÆ ޽F3g,GGG˹sҥƾ5jz\}_"996mЬY3n޼ӧON>e;$&& CJDLKKà oׯϠA2eԒ; $ҵkW4hiԨfff2~|6 !B!B$\!^ 4 %%333RJut邝VrnwE^ӿwɓ'ٷo.]bƍxyy1c ^dY[}lʕ˞ !y{{cmm0(ƍ0xM:(ͬ܅_By3Re\Vce %e߾}H f&iծ]sαd~G022s|JB\Y(%Ko'''y1ӦMC__ 6@˖-OSfqsscvff&QQQDEEC3wFFӧOW-@bb"*hv077gnnNhh(Q!B!"?3!(aaa/e) `{i bmmիYzuK[ !!,, www:t@XXׯT>>\p???:wLhh(4/s @۶mbP!B!B$\!BQC=XjIIInӦ qqqZuB!y_Ԋ;ӧNNN\|Or{̘>}R$cйsgT*ܹ'{T֭ݻW4~*jԨb?È# S([J*hggg gR\rf͚ik޼F!B!BuB!B *BŤI "22O>Dcg}3ydzM6*+[[[\\\puuJ055U^שSwbee1(޽{g֮]ڵk077תWί=zp)5sʕ|?"$$$y3f FFF:S?,4@5jT&'""H"##n?d„ ݻ ļƍ{o޼9/_ggglB^طoYYYdeeЧO{}{"""""""Q…7K.%11a2 $$$X; :_$00ŋdׯ_gҤI;wTvIS튋y뭷8~… ƒETTYbDE&M `ĈݛN: kFll,_~%^^^зo_k&OLAA7n`ƍܼyP]oAvv隼<9t4iĬυ eS)))#QQQ^tMII dffruƌS᳨u۷oOOO><==9t;v`ȑ#"""uP"?f…YX;*{nkHf,>>>4lؐu֙۷O>g}ƞ={ϧiӦtڕz'|v|Q\\ 裏HMMef1booϠAjEDDDDDDa `[T)tEe00 CD!!!sѶm[͛;o6>>ǏөS'f̘+999DDDp!6o9|iF#FiӦ,_UVj*lmmҥ gᦓ2ƌCRR+W0O<f͢u˞={L W&;;v1w\9~83gӬ\@>8ҥK֭'N ,,oji&-[%%%Irrrs^ZhU,--M """0͡DjOBBRx{{6mӦM\iӦ bbbͥ]v撞ɓ-6"h<<<^UٳP:w ]v%,,̢ߝ;w 4cǎ̚5 jΚ5kxw ++Ea0h֬||W\zcǎv]pp0...4jȴpʕ+K.<*56$$OOOlllܹ)y`Zu駟l޼PN:J()CfmDDDDDr~-'N&$$X?mڴ10!!gggƎkDDDDDDDa.DDDDDDD䡒 /`V^>ٳy;&L+W_-ZرcINN&..OOO+~gzIÆoոvtt͛\tbvϟ?oc=̾8wlԩ̞=rAVXĉ1 4nܸu/_cT͍M61dk"74j_;;;f͚Ŕ)S7n7ofҥUaEDDDDDDDC 3QX7*j[75._޺u8x pkϨQje\y𕟷Tg>SVVf}z~My׮]O>Y-DGGB-Z`ȑ$&&Ejjlll2'eW>ض~=ˋ=zw^ ;ˉ'((#GVwu3cjr"""""W^y!X݋/H`` / ((DDDDDDDDjJ "R+=JTTɔkfIUDDaE""Ӿ}{Μ9ñcok*?vE[gggrrrزe 5ݝ#GqF~mzi ƍdž HNN櫯~իmۖtwn*OOO22268z(9::퍷7Ǐg׮]Z%KTpQZlI^^lSy4h$""b}f00 CDDDDDDD2J G{***b̙뱳8DDDjC޽Yn:r 43gΰ`Ν3<É'X`ErJBCC 橧7Y>bв2Ξ= ~~~9rX]ƈ#pqq#Gƹݯ~+ Ɔ (++K.,Ǐ7kEf̟?\233`6Æ #77 SO=Q^u{#''"˜OyȃE'7r?l2hР1Q…XqW͇1An#??ѣGXv-qqqZ1:y،3m۶w1a„*N0{رc7n{gy\|ٲe gܸqYd-x'xw-Ǐ끊#ߟݻwsY&NhVbQТE kAdd$fmvZe<չW^۷,;&"""""i޼96mbŊ;GDDDDDDDDD RڵsInܸAVׯ4iҥK|۷" 3*&mk"44۷3g b*߶maaaK'?˗/'--k׮ѡCƏov]y%/y&ر .`cc+Æ cUwUٽ{7.]UV 0-MJJbɒ%dddШQ#^z%Nj:ի$%%ѭ[7L׷i7n}"""uځ3f:&!!`0*U%MTTڵktؑc=|gٳ|6mJ׮]y뭷x'MmOL^^Ŧ)Sн{w6l?.]DÆ СljԴiS}@\\~){ҥKlْohq͒%KiѢ/2&M2{.>>>4lؐu֑ @ӧSG}Djj*Ǐ7#55{{{ tGDDD?<4l:vh0g}>PFAv VXALLYY^^III\r9sO8\Sm۶qu>kҶBBB8z(-k׮iӆ<"##qrr2%u\|.^hӄ?3tл#**իW/))!33L_^釘׮]70-[;11CkHhp 6n͛7 `i1'bǎ9YDD)++v"RGԫW!3ׯ_gѢEEWZŋyg7oZ+߈넋M6l2<<<())!%%H+MXz5ٴk׎sǙ9s&Ofʕ]O0k,ZnMLL ٳǔpxƲ4%\=ӷo_ {{{rrrXp!/U+,,/ƍj6nV|r{wN{O R*K\(_~aOYY'N`֭on`w^f̘s=@׮]ӟĔ)SI;ѭ[7  dffo[S@hh)In5i҄k׮@vv6__*۳g)Ν;ХKf̘;ݻ-.M0fbccr助ԩSČ:t`FDDDDD^2d6l 22H͛`n۷k77NP1k,LbJ:ټy3K.qVNDDDDnؾ};'N#où\wޡ4m!#N R]x{'NX~sLIFZZ3bQAAA|dffұcG?՟?~}ԩS={6X'b0\ J㾝k 7o4]|uGy2cyp:uҿm֭[ѣFDdL ߺu+׿(..uٓI&d(((ÃP4h`x_$00ŋ]vrT""0/ ;SiPȑ#|?RVV3={d̘1mH_ëJDDé5_qww'""[;:mҥ$&&Z; ) """"""S…Ժ Ɠ-*JhXh'N}wՕ{߸h񚴽_իwWח(..Gݻ/cǎ|r bȑ5lllL_Wt_Ʋ[yu۷¿=JTTɔk?oHEQQ~} ڡT(%%*d#TDDƑ#GL_x{Sii)g˖-ל={g_`sODӧO3tPzMll#YJ֭Y~=:uv(@BB 111cX; ,W@!ݴbcc:u*C5/--}fdeeYYw?⣏>Ӣ?DFFZ$dtڵٽ{7gϞeĉfu...eѫW/GVVSE$CDDDŋYt)WWWƏoڽæİsN~GZj1i$F2~m())nݺdjӦM<<֭pkRY͛7fǎ\p\]]6lÇ7nO7n ???:uT}N///찵cDdlmmח͛ckkˠA &mk*22~`ڶm @۶m &??ߔвeKYp!C {___5k-̜9Ӣ<3bkk+&L`ٕ@\\Fɉ 䄟+Wxò:L&MHMMKMMޞAո_ׯ3i$RRRr %%%x*uؑ9sзo{6n""rw~֭ٳsuN:Ett4cƌ!??y?=z(>OβeHOOvX"""""""RM:B4"""*t MBHHYyE5i[]Mϟ-_y^ymVzomggWQ͚5#88_[QyӦM1 ĐKv%==ɓ'8lZsh۶-ݝL>tԉ3fJNN:t͛73|p`o; -- b9r]y@[!ddggӮ];Ν;Ǐg̙>}+WPM6l2<<<())!%%HM :vt:tPMDD}u~!ׯ_{L2;RZZʉ'9y$QQQ̙3cEEE̜9___[i  IDAT~zj%s:BD;ڴic[BBΌ;֊/{ 44Ν;cccC׮] hsN"""pssAtؑYfRXN'3."2]MOstb:owq֭[O?/fͦvw;2BQ^=\h&" .Ex~nmzFÆ iܸ1/icX3_G~~>G6O\\# "r1k,L¸qؼy3K.qVNDDё /`V޵kWgϞĬӧOW9˗['g,3ݨQeeeAD!77.]=ϟ㾧Nٳ9x dŊL8`Ο8<=;vQ<233ԩSIWJJJѣ X;&Oz*޽K.ѪU+ @@@fhт~/cչRQ٘Ư>}:nnn|'qOJJbɒ%dddШQ#^z%NjvŋYt)WWWƏoJ^֭NNN۴iIII7"""""""Rw(BDjŋ/H`` / ((ŝ"""Gԗ@6_1޽{өS'lllj<%KzYCE&OLAA7n`ƍܼyP_ΤI8w隓'O-n}v СCر7MJZc0hJDDĊڷoϙ3g8voMǎhLNN[lٹclْ< hٲY""""""5նm[;޽<==3sttooo?ή]XjK,1-[laՋ{v%Wh&dСK?<~mV^[oEjjO=ypdggӮ];Ν;Ǐg̙>}+Whj?b6mYjV֖.]пmcuؑXS<̚5֭[Cll,{1%\$$$p9ڶm˼ypww'330JKKbcYZZ.DDDDDDD8-DDDDD4h ,X@VVdff` 44'O?s%?xxx[o?>{駟 ''ǢocȝׯdddPZZJFFiӧO;{ذaxxxa yꩧpss0YnOoƍ,]SNQ\\Lqq1׿X~=ƍ3^u;w!CбcG֮]K ~|||gN0{RymٳgpVΝK.!vmq9k֬wÃ,-Z`cǎd `\\\hԨ+WTy]v%,,̢SN8СYt…#b̘1l۶ &Tv„ ݻ ƎkV׸qc{=͛7̖-[ի#++]]'Temٿ?9YYY\r~C޽SN-~{^nG5V)ߟݻwsY&NhVbQVӾ#""$22ҬyΟ>6lHrr2WfԾ}{BBBؚԾ #[lI&°aprrvHRtŬ^^;&L+W_-Zc~kGGGn޼i*3&$c6*{888XˌmDDDDDDD """QzK{z>|7= 6͍9sfooOll,ggg4h#cʕf|ONvhР <&MjGjj*7DD&ȴiؿ?/_~3uT?~^މߴ˦5=z(>OβeHOOZ<""j@\\Fɉ 䄟+W4->>>3`kk-L0ٳg AL>^}U~_ӨQ#ׯ#"" 6н{{6n"~'oί~+k@={6M6߷v(uwgߡ[ F}Ã|:[[[LnXUtYY5կo,X0-"""""" r_%&&RRRb0D֯_`vAm0DX7ofΝѢE .\@V6mӦMO///ʚ6m` &&\ڵk.==ɓ'kGy(͟?]vaooϤI0`['sNlllL o5o>Z(STT̙35,,cggW+qܮYfm+YYw׹ݫ5w]˗/HMMv8,{{{x)((YfIm۶|w%Luő#Gظq#oE_Ɠ&*Jfڷoϙ3g8voMǎh۲eK(((e˖fu6"""""""R)Bݻ+Bꫯ-wgȐ! 2aY`pT #???9Bll,׮]cĈP\\̑#G߿ck ̙3,Xs3p =駟&// cQHݤ o}]}]k!"""@1. >̐!CذaDFF7oޜ{:fbʔ)7ubҥKiܸ=KD"DFFw^7n/LPPق]v~zN<ɍ7hժ#00д͛7fǎ\p\]]6lÇ7_0~xd۵hтcDztR.?҈dΝһwo}])D=餢WݻtZb`oooORRK,!##FK/1uTөW^%))nݺdM6xxxĸqpppXn"AJlQ5oޜ˗/ン3[lߟݻwsY&NhŬ75k֐LrrO<y3m۶w1a„*Ջ}E׮]겲$p!͘1cHLLv"r  jDgΜv`\\\غu+׿(..uٓI&-W^|EYx1AAA./!!!|WDJKKM;7XkHJJʕ+̙3(V^mjSRRBff&\~1cp1։BUݻ7K.ѣu .4-q)))cڵkdgg[bb""66֔Pb4yd Lcoܸ7o ),,b}:1yyy@\\~){ҥKlْoZ{LBٰa?t 6C 8???mEckvvvDGGv;vdرckkkj;x`>#RSS?~Y?3hР;JF E@cr 4oook!Rgm޼;wZ; ~֯_`ocTcO[ggg>cسg)bڵČCR^=233;w{l.]~?WWW׎|2ˌmDDDDDeΝԔ,RWUݺZې!CذaDFF5oޜ2;;;f͚Ŕ)S7npK """""""u.u)~iTUVу &жm V.Z۱[75V+??μֶ>-Zĉ'h߾=puu瞳xyyѣG_|cX|91rHV2Å صkzڵԾcׯ_T ؘWEXe]'""""(0`پ}ydddm6)"tȭ[bZnMϞ=4iR+xbڵkm."""""""wH Hzٷo_sy6mĶmۈsεԆGErr2eeekvua6mÇe˖<ҿkX+;?9sU^ hڴ)?8;x}-Jױ4olS}ii)ooo9~8vbժU,YĔp1rHRRRO>f'l}^Ç[gddmpQ~_ڶmw}Gzz:ݻw7\ZlI^^lҬFDD4Eaa!Ck9y$!!!xzzһwok@ =hׯ``0;FDDDDDDD{=f߾}U>|JKK#>>=zPXXGj)GoEEE̜9___i۶->>>X6.]bĉk$''snܸAII yyyl۶I&op5kP矹r Ǐ>c|KŅW_}aHꫯb0 Mqq1'O$,,T~ 6lz 777T.]+PXXȤIHLL~ ;;;lmmyX`$''Cxx8< ʄ ={YDFFdc=Fi޼9}eɒ%/QFƴdzMÆ qrrb|'ښL>vѠAJ6ppp ..QFD prrϏ+WX5x`4iBjjE]jj* 4ȣK'z0_X$::kҽ{wkHر#aaa̝;lk#""""""""p!uי4iΝ3˟ɧ~z* 2wy&M}7۷-Z|*幹LXXɌ?"+VW_q%ZlI^ Cי3g`…=zFѭ[7ҥu}}iii\pƍK/Ą *VU|@ZZ?غu+Æ 3;?իWqpp' 3:}4˖-㫯ʕ+1uTXauY;#t:^,|5&]y{{]K߾}ިYf|GUˬ{n֬W_uWӦM1 ĐKv[3yd'EDDK'7{fϞm4Jo$$$֭[}HII`ADDDDDD%\Hsh۶-ݝL7kԩ3fՕ"""8t7of>|tzBMwCmѢk<8ҥK֭'N ,,O``O0k,ZnMLL ٳǔfrssi߾=͍L-~j*.^ȳ>˼yhժ_Flll 5eӦM,[ JJ8G0 IDATJHII!22dSEZZҔp!oaҤI\vT?yfoׯ_lܸ6m"$$T駟Jrridc=ٻ!R229C2ia!aH9<3!bTÖ$ dZdC'9wxo7^뺞{u=оN-r%B3m4ӕ}q1lBnl3""+++?~ d%:ugϲ{n:vԍZ-ɓ'\vk׮w^Kݺu$^5_}NRK)%%1cp53g;})R%GϟgҤIjDGG3i$V^]~_#GtB!Dȑ#(>>>bmmBd$x5jԈh~mM"Uez쉿?FtH/L.]$B D~B!BW$\rJv(ҥKHv011a…̘1C~PPY;99aaaѣGs%jr*)IWvVh׮888$\yall رcÇ3g`}] ~~W̜9S灬U'5jՋ#F0b6oܸd%Z]UG@JJ Ǐښ M`` ̚5'NP^=弼vؼy2}ŊJ#Ϟ=ʊI&ѠA/f̞֭=_RZ޽t ڹ~߽{3fN~;w.M4֭[^'O2}t?Λo/? &ЦM"##?>o eHIIaӰaC>}ʕ+WXx1111_oLbˮ_qmTTTlµkhѢ˗/wEKKh-[Fxx86m*REIÇ5kr_|Aƍ?VXEJtB!tttprrb̙p!֯_+W!Bׅ$[T<ݻwg͚5{党1cFgB!B!lI…V0$n߾ v111޽{Ԯ]TСgm֬򵾾>ϟ?WTWTr_@Vl3?ʼne֬Y,YPBCCټy3ǏJmYfTe:BݻwsQ;vHǎooo9vZ&N}KFFXtR޹sg;,,,8ppm޼ykΝbff͛El޼BCCٵkWڥKVXرc|Z]U"—_~ R ]t͍rI%ᢴeWV_A rXf\Y5k֬O>\~H}?ӦMoΨQ/ŋ2S]^7n{A@@@N|Iy&:ubԩJCt!"JLLdժU6mZ/B~c!.ȡ$$$PjUz->CF, !^]uƎB䐙B!B!I.LJ*Z'䢆/wyTf!ZvV|]=vx^TyEqb177̌3gpA\¦MÇŒJ%GJpNFӓs;aѣG̚5gϞѳgO .\:׹^2ӁcJJͤIr}iii1i$BCC9sLוP%9dhhȭ[?~<666JB-r]_icˮ,޿TV ={6co0%GNʕ+3eԿx}焄;`xx8nnnɨQhٲ* WTVVVXYYi: !.\jZ~c7o2qDRRR nܸ78|0%9S_BjZ*>>>CAgtB!B!ʘ$\ QFo\r_)rJqaemYz䉲BL^Joddh(+}grE\OFtU)W ݋~ЦM"WX2dC !::SNc\]] xj?x@#DyQԒsnݺ1GGGO7n̺u\qծA[.RLzzz<|ja-x d/EpM\•+WRI͛7 -7Zf )))t҅3gҴiS>}ʯʚ5k~:nnnΝeѧ0rHF0d) !B!x^] X(>}իWYbE{&_~gϞw})'OVv.}v1<~(f͚ѰaC P~U/_\Oxx8n0ٙ˗/S]s}w իW@zz:~- 6,СC155eϞ=ҢE Zl ѪU+ Ԫ2U!CQwɯ?GAWWwwwjժNjj*P+T9w(ȳg^Ve/aC͛7*eݻSbnnQfeW(Tׯ_кGW^ {{{6n~,=R]c~!ŊUfjj)xyyѣ1cƐ#B!BhJYThii]`yyQ%|,_-[RJWNǎv,+2x2228xB!B!B3BThcǎرcܺu ;;q"##V;VzufϞ]6CCC>V?w\Rm~qUSNiӦ F*UԩSܸq{{{|^D~)AAADFF8qb'[[[qqqEnUջuFHHQQQV[WѣG]Crr2M"&&KRR%\]]i޼y}Z>:wիW9w:t(}]]]>|ȣGx7rC%`nn9?.]ҥKܾ}K^汕+/U"?R~.6k֌A[oQvm7oN߾}gIQay&:u*?OOO|||?~<?q.B5! **Hz뜈^Y222bĈ1ӧO3qDKYV={ݻ Mظq#˖-c̘1j?VlْK.q<T+v͍;w*S/aaaxzzyϜk,0a/_=Æ {mVmd%DZ`lKKK+D rxx8nnnɨQhٲeB!B!( I^:uXxZY||<uU+gΜ9̙36U+TPGAگJZXn]_y2|ϟ_hѿn8xȐ! 2:XYY;w$w!""I&A%r56nHݩ\#G0c >C<==+Vpu C}M@@@7o2h 6lٳgw>}:7nATBB=ZZZL0A)ٳ'QQQlݺݻ=9=Liٓ;wp1Zhv,N6e[I߿ruuhܸ1})jǢ+mj}s$ܜK.Ap233ٶm[}o>6l؀)O<ѣL*j=oooi۶- ,YfLXXBm.\uֹbU]pA&9rCB/;wKÆ Yt)[&::Eۙ:u*@ck,0l0tuuٴi;v`ǎhkkӾ}{zڂ=2l޼+Wk.Y%ҡC;pD1YƢE1b@l .$00PkB!BQ&$BTh={$55cnnqqq\;j8B2ȑ#0o<|||044Zщ׍5v/vvv̝;wyp>޽{\2sU9y$vwaj2vXٳgo&vvv%Kr=D_|90h >3zꅑO<ۄm6O~ررPL_|AƍcժU\xlllJ}̖-[6m-Ąjժob '2yIII\z]vq9TKdcŊ̘1ڵk֭[ٿR-4$hxxxp9MٳiҤ nb͚5T\ +/ihIԨQd|||W^j^PPдiSѣy&ܸq5&&MB4B!48`i׮Ă 6mOV.B*~W.^˗ _~! ͛7oI2h:qvvV7ޠGL>}M~ /;///=zR6fvލWB!B!N.DGg\\\pqqQ;Vvm5x̙3‡bT^]щMYnOXZZ7ЦM ~:^mo@o͛7yfz;vdjeoL2[ng+Wf̚5KA]iӦqIN>>jǦM?[T&d$HWW 6`ggDZc8v9+W/,4qDYfdBCC e͌?+++¢ֻ}6@;MYfc2U!ī$R!(/AQw,S-_ ԺukZnl߾wwwVZŷ~[&}K>}1c`ookpruuwaŸj: fӦM\pd4i¸q裏=zwwwN>MRRu֥O>۫%\WWW"##Vc֬Y%\f?ѣGѹsgիiРaccgB!B!DqH…͛1?#;ԯ_> &LԩSNe888`bbW^lݺs]ttth߾='N{jU֋cȑ4i҄͛7NZZ :'뜖-[?o>?׹>+W333lllhժU}ۗÇyf~'000[nL<͛:򢧧Ǟ={غu+AAA۷3yd~=ޱcݣM6,[uvZߏpsNbcciذ!K.uDGGh"bbbؾ};SN-Q 7ɉၧ'8::rҥ}Λ7cccUرcxaܸqJȩI&juB!B!JCvB!e}\xӧ`ڷoOj?7Dh-θڝĤ8s X[[ի^:gV^׮]cii![n.@TTPRBG^+_V6Ϟ=ˁÇԬY{KKKw^8oܸ69E܋_x{{JBBUV孷?d뗸ו]@@'!/[[[N>۷?~1cc\emcn޼ĉIIIQ222q7nxxxP^b]u憿?5-[ҡCR]B϶5k֭[9s IIIзo_&NX ̜9.]g]FRRUTI&ۗ1cƨ//!( 2gΜW2"ggAJĈL{9e9iii:*+ !B!B$\,00 M!(@F0/w}m۶q9ODa!5hЀ j: 񒲵ȑ#(|||044s!뫠9+=>4iD9VN>#=z4GeĈkNs@dd$XoPJ:v숳3?L"11ѣG+ecƌaxyy1u2O!xK,wfРABnu놟Wٙ7x@Fؿ?zb8;;tRڴiCtt4+VGJk8pÇKcT%pܾ}cccZjEBBqqq+:B!B!% Ga!BTT0!@GG'''fΜ bT^] !^6pWqppZjju<<< ݻԭ[A1am[… 6ݻwgƌԭ[W{Aƍl]:uf߿_I(j???'䕘#9}4IIIԭ[>}`oo<???\]]Zj׏Yf QNoݻkqCE]ףGsԫWOӠALMMƆ5kyB!/! Y XYYi:!4O?%((H>cc'NTܾ}ǫ366V+իcݺu[]8FU%>|nݺBTT&&&j$!B!B ¬_WB.!uԉSzjr=4B?>?5חO*+8gdd0yds$** 777 cʕ>|t=JDDpzY`[ݻwgHNN>#66V)KHHח0<==Q9&MJ{8::*u&L˱gذatޝmRj<(?~8yNڵ+aaa8qÇ!)ӧ?~<_~$[W^A兛?34o;;;ԫY&^^^lݺ3gΐ}eĉjcٳgEPPiiih" TΝƍIHH ##n:Ν;Ǹq;w===_B!B! \x@FP(!/˲ŋfee%?!7nϏ`%ۛhڶm˂ h֬qqq8;;ơC(ϳ~z:w̯… 믿fԩܽ{CCz뭷HLL,v?fΝ;aÆ,]֭[͢EaJ*7ɉၧ'j Æ CWWM6cv؁6۷wXXXR{u]p֭[FUم $B!(իWdȑ8;;k:!4ȨH jb޼yʸ:?:::̟?竕7~YnnnZ.VVVxxxp6l;w`ҤIB!B!( I/>>>CQLcǎtB!BQM/^wȚR^=㉏Wr~I) U۷W+ر#Ws5k|ǜZnM֭###۷ΪUoPf\Te:B!Bܽ{AѠAۧ ׯÃׯ+ ɉ3gbccCX~=իWptB!B!xUH…BQ6lؠB!^Jwl<&O嵓DvɅƕs U"RֱcG9u~im:uJ_~JU*_o=HKKѣEݝP^G^ׯ*B!DN?*UɓJR-^ݻw石sNM#SNL:իWB!B!īD.kƍjJL5a0M)LT@@2̌O>D !e#00P!!(!qqq>|CC6 VʆѣGGj;oܼyScaaQ~Ȉ[nA.]֭݇[se˔)Srԓ#J{ HHH{RG!AOB駟2rH4ذaѧOM$ +++M!B!BW$\NHHHK>x݄憿?5-[ҡCM& 3}tM K㣏>t"IBQݛ۷ȼyhѢ/ڵ SSSlR`˗/gҥ;\zggg i߾=8r&Lޞ}b``{8y$=iii 801QQTܾ}cc<ի۷oٙKҦMYb[Eq3˗/Irr2Æ ؘ ._̚5kR{ujՊr%V|HZxgϞgܹlܸ222lf͚xyyuVΜ9CRRۗ'_Ļn̙t҅={p5R M4o߾35j(sn:Ν;Ǹqb9wzzz߿D"Io'''3f -[tHB!B!BC$BTxc?45kƸqX`>&55{.ueРAjPT ٿ.DGGG?7|G};v ү_?\\\ٴi.\ 99&M0n8r/ϟ?ݝ'NOժUi֬C¢=z;O&))uҧOնV燫}r~5kEQcy~~~tܙz) 4???lllYfBQܾ}@FPD``oW>saΜ9%jVZ[ȱٳĊsssVZ̛7y^q#fff]Q}^ץܹs p"""4iZBIOB|d|#^'3gŋ>>bmmBxy,㛋/\BG*U^Ϩ'O(B!B!ef bdd'?3j"x{{M۶mŋСC8tK\4*5kdɒ%xb?_MJJ NNNcݻG6mطogϞeذaxzz۷ 6?sYϟܹX6l[aiܸ1… ?brZnUB駟bgg/ׯ_tXB!BtttprrСCϡCprrzO!BhHLL t(Bp>>>dff?'*?!B!BI _tIHv011a…̘1C~PPдiSѣenΝLJ>W2f}/066VG+DiըQd|||W^1#Fx^^},XiӦqiNvμyk;v,<|رܸqJȩI&ju2Ut6l؀9o&cd Yfo޷jeW!Fxx8;vtB!DשS'NիpppDQ !BMgРA4mڔ;vh:!^+"ǫ|N!B!H…rM8k۷2dHm߼vȏ/^ի4mڔӧ믿hժU,YfdBCC e͌?++'!߹sJNuUqgL (;x<رܿ%$'U+Y8p磏>R>#=ʁ=zYXXp*ƍ@hh(fff7!xg22Ja!xI$&&j*x VVVL6-!JQAESd(*0`>L54/ŋ dȑEj:!B!/$\rPQpZɺ:9%''52Wő븹9fff9sr6mڄ7 >XeOȩjժy]WQcQ UYiݻw/ct邽}z97?N`` ?wޥJ*ӻwo}ςxfΜIzpss#%%GҶm[ԩԫ[..Gef2-^UtrḹOff&Fe˖tA !B!,\˗/+ݻW`yY+h q222$11+; :Ga!___Ǝ0B!Bܳ@5j+Ws044V-tRaaa/$ƍ7C6mMxK8HIIQkC__!CΝ;Ç۾jתY\EZm*'U".\Hpp0>O͛7ٺu+?C9sǏٳgYhQIl~~~r5RSSyd۶m2h oeCՃzU2ޅ HOO|HOO租~*/NHHHiii,Z#F`hh,\rR!B!DFFyfX`Ae-1DƁd%((͛k:$!B!B!+D.DֿVXATTO>իX"W޽{yIII|w2yd*ۥ_~ח:鉉JnXz5 bjjʰam[zHKK#66\){!55-ZвeK@}Gz3<}Hѣx7Ն,Ye4hggg|}}qrr{*'O`|}}ٹs'&Lرc_|Yl2իGbbb*G`„ x{{ビ㏩^:P;WuSN@֪M6Ofj֬dS,YBv011aڵ@.-3f̠m۶tؑsJi֬޽:u`ccC|||$''3|6mJjhҤ իT*Uɓ'L>}}}ԩŋHJJbRvm%0;UfΜVWҿ*WLժU2e`}'U}ڝfŴjՊjժQfM>mV///=zR6f`dB!B8Ci=}TiSKK mmE8PhJ|||X~a.]ģGprrF|7TR'''ƌ_?5kO?%((H>cv&Nozb߾}[uеk\lmmqvv%WBIrin߾Վ*+ҭ[7BBBcTTP!^f|I{ڴiĉLHˮzꤦrO}177ϳ %Zl=˖-#,,Lyv;w$33XΝ;G\\򽝚 :t:t@JJ ׯ_GGG6m(Td*[_ cccCؿ?ZZZ|j;99)?x{{sy._$'攞N޽S +ٙ0?zipwwW^/]Mi&%255;wLIOOg_wγ޽{d%RlٲgϞYj:##PBCCy!s?;'N >>UҬY3ZT<<< ݻԭ[A1aeQߙT_~XB IDATOsԫWOӠALMMƆ5k)n!'00r!x5=z;O&))uҧOSetW^^cPi422jժѯ_?f͚ @z022_D)Q.ׯORRCbqF (;pF!B!$BT=P777Ξ=Krr2M6ښŋ\OOOOOmFpp0bbbɓն;w.7n$!!͒%KIFFF̛7/_^^^?Nͱo߾?{l "-- SSS-ZĠAYZZRJQF[[|ۯY&^^^lݺ3gΐ}eĉ5n:Ν;Ǹq8wzzz&Boe֭[zqشiW\ʕ+3l0PZ\۷ow !!!>V\.33Sz;vӡC"""x9:trҸJ`` T*jԨXm?1ԓ6mro$'';vs ]d TZ 6"+=zЧOۛ`5jmڴQB!B!(L.Dgll… 5RRR011(722bܹN:,n5&|reE ĠA47n{z8;;\j666ؔ}ڵk3o<͛Ws$5kbgg/4idΜ9ôi!/4 N$XZZҡC~g>ŋ ~`̘1ZN(Jի4jԈ.]дiSZj\vm޽{|2 ;wV'՟L]GTL/Vu&NȪUaٲelˋ[%K?}||&44؄ Ͷmxׁ]`6mDVJXn:t`,\{*}g,^Xٝ`_@N{ (kҺukhР)))}444$##OOObkkˌ31cF`aaÃ`e? o4v Vc%؂DGGE'ˢeHB!(ɖ-[z*M4aҥ$$$`ٴiŎa+^c'Ѽyshذ!T*"##  !ףG&NȜ9s߿c-b&GY~=,X#055?>۷oWvB!B!(H.D3Ċ+xwtx\ݻ%# SSSu[F~:ϟXqe:+++r 111޽͛7k%\\tv)/\hN(/ٳ,[LytuGD!CpǙ3glSn"33:uhN%[V^dףG<޽;W\)ς:8jժ.V ST_SLQVxnn2a(+WdҤI8p`\]]={vkԨAVV\z={2bFQ/""wwwe'-[憭-ŋ?hBB& !*GqN"22WWW%Ņ3gra%ᢼI̛7f͚0vXT*wy @!ī櫯bϞ=pJ^T~~~1zhl̘1l۶ ??A!B!/gOW^|ᇜ:uu2uTG(Wqss#,,RRR ]'DpCBB="11Rϝ9s&#Gмys塷zwA~-/_ѣG?^[nu!nݺL8'?cVXܹs5Nښ]rvٳgY~=8991|pk)NĩAOO;[]8'BWG@@vvvCR='Н«o?Ϊܥ%ȗCծ]tҊU4%%EWq$##UV1"y7n~~~|'8qBNJJ *x~L6MY&'';v<1KKKbcc9pQ!B!BMvvvvlݺǏl+/;;;kkƌp0BBB )򘾾>/###dڴiۧOf̘믿>4m[[[tԉʕ+cll -x_ĉ}}}Zjٳ5Ynݺa``//B5|8"^...$%%$;_;_ÇgQR%zS(}ݗzʥK2333*U7|Cff&ozkժUվ666esJSSSéSbccK^z@;|uB!I4ni {q=1T˖-(xdd$Z @egg+ N B*UƍټyCy"7o֭[ʱcǔ*mٲ%,Yrh߾=OбcGbcc jy愆ͤI,= L]G!B! YE!xU^ɓ'3ydIE%mXYYaeeU~ qvv.N>j֬ٳN(H;@ƍy4U^AJZZlƅ 9r$eb211a@~b̙3=ٙ]vq PjԨ_svvf˖-ܸqU~}h۶-͛7g޼yL>GGG5en{С$''iݺ5*6mՕyѺukoٺu+lذǵkh֬m۶%55$ 5mۖ{#B!ٓM6ҥK177'!!/=zS>]]]K-,\,p:]Ilٲ%nnnFSb;v,*;wYDQ"hBB!B!DAp!B!''mɇʱc~ׯ[B7|||7n 4i;;;,XPbMڵ9qK,aΝ$''cddϒ%Kx뭷Z|k͍SҼys100 ++k͚5r5M>֭#!!_t|enwww<<<8֩S' 8rΝ^sQ׭[t ){[n=zxv'$Ʉ@׮]9r#B!ڵk}f͚i1%22֬YÚ5kb5\2k֬!44}q144}1B^ų၏S(SEQS+UTsԿREw/V-++K.Me_]OOOO똺 !B!B$BP377g0f͟W%MJu(υMdddܹs;wn(Y&vvvL&MHNN̙3L65jsf̘Pxu֍ V\;uˋ6mΝ;]ٵkÇ'%%'ʊM6ʼyhݺ57lݺ r?OP'\vMyնm[RSSIJJJHJJR!B!B& B!m2p@HKKuh yOH^:nnn|'70000x!^=h<<cDEE1~xQQQҷo'!B!B$B4o\cjjuųfggB?]t̟?7nFݖ-[R]&lիWiҤ K.7$!! ȦM66o̭[077gٲej*v܉JR.IHH}`ffFRRJ ڵkApp7{YEGGoj}eђp!B'&@!ī͍Ν;2c ]S&7ݽ:իWggg3Y}O###ΝܹsKm[[[cmmQVfM%99&M̙3g6mB!B!DAp!B35kчo@www7n 'zakkKxxpQF իٓ#F0b6ZŋIj-ZШ#B![̙3lmm155uHspp`޽0o<055^ !B!{ !2p@]!D$?'qqqk׎-Zk.-[ƵkXxqEff擄,ڵ;pud ?ɢwy7n(em۶-1k׮`ccNHLLTΞ=jժêU5j*6Z/==Zjiť.SB!Bd-ZD:uJݱA<_իW͍0RRRHII!,, 777 tB!B!*(BThJKbY]PժU111k׮L0AYe !&&ȟ\Uxr!tmڵA?^{'N`iiI͚5|xc,ee!B!<\]]}GF[A1a׹sgYr%NNNtIQ !B!" !ܸqPۇ7:tuX;}4ǨQhӦCqʕrշX[ IDATޞD?ѣG `ɒ%TR zA=޽;uI&@O3B& !;wN#륞۸qc~wΜ9)gΜwHRkذ!ۦ)IIIٳGacc :t͛7$R^zHMM%##ziB!tAOB\\\{' 3p@FqqqT^]!;;;]!B!B$\Q?ox{{Nhh ݻǂ 1b2qiذa̟?۷˿P틍 #""oժZb„ $''űcgʕTToTwNHH#x/˗tRx pww(ʢ={dӦMtRIHH/GJnݺʕ+qwwN:xyyBӦMٹs'VVVlڴ WWW͛G֭g֭XXXaJrr2 8֭[]zm۶%55$Ċ$B&LŅcǎi$\dggKDD7oĄ0ydVS'DGGADDUV{̚5 Ay ӓsQZ5ٳ5vz}6֭ѣܻw^zR?dDGGE-?~<$33Sn]BCC5nD_vaÆѤIvMff&AAAt҅ (5jAAA7Zj_W!ˮ^z :Cɉ'[Si;%xy`gg0^*eIdѢE`llL0ũU~~~|9r۷oS^=z͔)S022R֫W???9y$999nK{VRظq#QfM:uiժRwذaTR^ @ӦMѣׯ_?V^MTTǏ׸֨( ۷o!i/'O3S#bd !B!B$\3'N'C͛o;qNjj*AAAܹs%K͖-[:< ..8޽[{;vJ>}: JYJJ *xnX={Cxx8gΜ_8N6 ;v+?tҤI$''+۷wj]?==nݺ… yC aԨQT*])E%ī-00@]!B!BҒ B믿 ԔuDdd2e۶m@~bƐ!CTqqqL6(P֮]< <<˕pall @qqq̌$݉%,,Lk'ǏE.]8<ƍ6o7776l/*H%a֭$''ӴiS-[F6mc…Z,߼y3nܜe˖abbªUعs'*!C0vXشiS =zw x7bWEGGK…ꫯ8uFBI߿75jPvhJ_M^^~)-Z7AB!ϖ{% @O`jjB!d:tmۨ\7k,gtB!B!KsgaaUZ9_|A˖-^:SLcǎ?cnnΏ?Ț5kXbYYYJ=j_1bN:EXXXѣGT򿼥iӦ +We˖Վ3ӡC%!!22ڝ7o͚5ZjJ"ɝ;wGŅvڡON/z?~>f͚QF \]]9u;wW1b.]Rv8ٳԬYN:pE ?ɣ0:B╴3QSv(gTuvZ_> 4O>xyyB!xWaaaBXXnnn:bbbԟB!Ν;ʕ+prrRمBQvbTR2^BQ///usB!B$B333ڵkښ]rvٳgY~=8991|2_ǯ ovnjwȀ%%oiW___y]R%6 ]8gQeE166fOTT=zjLM]VxQ_믿CӦM:t(W45rrrرc'O$==uңG,Oz~/m߾'NpMTBfͰwޥUR]ݻw }+uLLLh׮ 25k=B<Oۛ`5jmڴQQx^Ic1B[cذa̟?۷SzuG(B!XLKBe4jԈ :!B!BQϰ;y$… ̟?_)sC‚lZnM6m?ٳ|2M4_~q+++\]]p=۬Y OˉÇ>}www'n4ݝ_˗k}&V\Ijj*999|WXXXKn:t(Ν;[ԩSG9޶m[Q2?iР˖-#00777Õ+Whݺ5_}AAAxzzoGdd$;DHHHEFԩS$?8x ...e&O }{UuZlu:yD]GgB#UGZZGVƌCZZ~~~:L!BQ'/ !˧y,Zwww._pB!B!D)d Rٳ',\ jp888u:uTd=322bŊ&Lȑ#;w{{{̙3Gccc&LQfnnΨQs!.^ԩS~i%.<'NHDDΝZ~ʔ)ZǏѣƱnݺqQ;v>Gfȑe* !66S*IcL>]IR;y$| 4^ɉ?(zX1Ѷm[FIv_ٻw/ׯ_wkkNJ,~77nuL]#ܾ}uqQݻG^pqqѪ[Ejnn.>>>8p133cСjTZݻ3k,LLLJСCl߾ . ={ёG1x`֭KhhN:׮]cذa4i҄ݻwIPP]tQ>/5jAAA7Zj=7S!BRm|||OiӦ 6l ;;___"""y&&&& 0ɓ'SjUlق۷Wvё/RcKnܸ2>Sq8wժUO>̞=[c'd$^d$%%[s! GGG"""t3sbE;vv">>;wPV-z- Fݟz߅V!!!еkb !B!Bw$BӸgCx[ޞ~ dذaTR^ @ӦMѣSjULMMy7n 68nhhJbƍDFFF͚5ԩӧOUVZmzzzh"bbb066'i,ڵk9tw>Օ?u^zɓ'ɡUVL05kT^իbǢ044x0*ċƍ0s"ۺvZUŒ%KHIIGZw_grY׿ŠAVZ+ @EM]#.dff2i$}qRf˖-G\\weرWX={!<<3gQ}|7jĝ;wXd FBRqAcǎ}~ҒX8Kv!cرZWB!%$33SIL>ӧO'!!AJ">>ooo틗ϟ';;5jp WN}tnܸ$gڴi=vAnn.@{2^/Ç3i$ΝPT7|C x)9zֳ r!cǎq1ŋ5>+ӧOMpp0yyy56mбcG]&B!B$BTh+\^V-U ŋ ~`̘1Z Syyyʵ>xWWWSyٺu+4mڔe˖ѦMɫP֮]< <<?~///t?>7nGG"ضm 2J*Ǵiӈ'KiӦ".ԻOEGGE'ˢeB!(N˖-QTLh߾=...;akk[oE\\gΜҒra􈎎&''e'w}{͛7͍ J"22RI(xOKEO?akkˇ~XB{=Nܹs8p uuHOѣG,_|9Аɓ'ӫW/6lHFF111lذYdS뻢%_ܻw 0bLMM6lgc !B!Bg !D۷7n\hԨJY@@?Xx^5jo]P`ݺuh}=V :666CVVkhhK./dСdeeyf:޽{JYyv(N:@uxZ,,,4J*?r...k}}}:u_|Qj??_1bN:EXXV}ggg,--קC$b8v?3㏬Y+V(kfĈ\t'N?_gϞUvʂ}v5o\-ZhB!B3~RX;""wwwڴiCʕiٲ%nnn( ='aOܹsC ++c7o͚5ZjJ;wxIh2d]tARɂ&B_~^=~w™3gȈM6aooOƍ\2 8M6allLxx8Νuόiii=Z)3f iii02!B!B&;\!*_yݦM Rdի'|$e允sUҒ`;>cZlɕ+WĤ}]vŚ5k裏h޼9w~ ,,vڱh" ?!//e5 6'Nۙ8qc;sLҘ͛7'55V]Ȉ :D߾}u7n,5΢Eܺu7nh%VܸqC#\~:h;;{l/^LLL 111|7L4 ;;"'vUzzu EusZ pcooOpp0~~~XZZr =z{ァ|;.SB;} !sb)>>>|۷ocbbB^:u*ZɹsV}anpRRŘCbkkoPP]tAJyF ((qB!B!I…BkРXXXJʕ۹sgYr%NNNBL INNVV/-?3.]?8VZ5ꄆO>nݺ600ёŋ~kV~mmmaƍZ .]pAn֭[M /IQթS'N:EbbF ;w.m!ʣE=SSO+<ɯ`Rqڵ+Gaݜ={Ç/MD =7ꫯ8̌viM666fOTT=zPW,?u)ī' ;;;]!xE* !t<'“KKRנA~mΝ;Gzz:G[.Ǐ';;:vHݺuKlW___y]X<=/ÇŒ٣1IYQw2ydX.\$[t}ONBBRJ">>ooc IDAT+={ݻӧX={Cxx8gΜ_Iv,,>#^Hll,*JMXmڴiddd(}ر\Y7[lQ?x8{2ؿ?XZZjeiiIll,к+B!B(n:uTEpYf /ű믿믿f̘1!B!BBBدQK.eРAԯ_=== ҥ ˗/XAjĉ4h===C'//~:u(u۶mKjj*IIIZ:B!BQVVVlڴ WWW͛G֭g֭XXXazʕ+ٱcpѭ[7<==ٶm={|3ޓxQTZ^a! PUZSWWW:t@N?>fҨ;7e˖akkKxx8u}| YߡC\]]qrr"22|R47b -dc$FEcc!?#2X_uZe#ZVVzzUdz<xUTyͻ{̝;>Gj\oٴiooo"""SOdd$鸺鉧u.]%pTڰJG!B!'.Bzfر9ÇÇqk׮SNz~:t(VVV8p@i;p< o#|||5&L ___~UIN!!!лwoF͛燓Ǐ';;.];T:jQPP?*;Vp_~jT.jxBSNƭ<BAK/k{/+ύJ˗K76++~jsrrRGܸqkV6FU͛)-,,*?*ӦMq$$$wy ծs5P!B!B$B!g\\\X~=ƍcԨQ̘1~ Fccce׫[nq-eƍ;<PU9{###### $NTà :uꄑFFFǢE4ҷo_5j5cǎ/Ȩ1f͚&&&ѵkW-[Ƅ عsZ&M(UT)cffƀBG}u:Ǖ68~xWSϟ',,Yf1sL֬YÅ B'LUO133#""///lllhذ!i&nnnfEu9uU=y^BQ[V$4hq]m'ϯ*!..~@@:*YP>777~m8@LL*SMܿA`` јy B!꿪fYXX(U၇F̙39sfVv]yI!`kk˕+Wx"zRUgccCFFUÇƍׯ/F-[(3KLLTxyҪU+]ƅ xWv&leaa?B\\7o&44ÇeյͥEj*}B!Bd μ+1Ba!jaĈjo.'&$$[΄ $٢ٳ={6 w8BZ V_& +WrJ&OaBThh(wU1i$6o͛7)..&++MÇsݻ?Q\\LZZlQ0֯_)..$,Y;65yr%SZZZ<[n9wQQQjHt_MAAc9;;SPPÇkB%!ܹsj 噘;͚5QF۳xb333"""Ɔ baa+6mR0sLZnMÆ )**Rڍ !44~ѬY3 ŅPиqc񆆆ҷo_5j5cǎ/P377gƍ9kkk6l5GfӦMXXX~ѩS'022???-Z8p k\#>>333B!B!O*\:ehhXb!ēG-W˫BoߞeŶmHII_dّܹApp0gΜ!&&Fɍ7hժK,s$%%HNNNٳ5kHqq1sN9w*5y={7obooOjC㏜;w={|/w9s2d 4 ))'-eOscN>uQ!xBԼysڲRk`ƌ̘1kVq jڴ)Vmڴ)gfU^R+TI&xyya233iݺ5\p'*$B!Bp!Ԉ#1bB޽{S-66FO"}! /vQKB8rj (KVXp!Æ #66VIf8vͣ[n888Ȕ)SԔ|"##IOOOOO<==gMbl111-T?W'ORZZJjj*䧟~ٳx.]m۶ckNB!BBAAs 333222X|9/#|:W_$|DFFbccB!B!DyS!x̎9,B!uGp_4yeuFFqMƢEHHH !!u1n8066ܚĨRqwѣ||;v|̪۷>}:JKK׺Ν;k\Oզ#B! 4ݻwBHH1KKK&LȞn&&&,\S2flիWWށB!B!/IO4Ni}cW.by?k.prrbȑe\!DW\wB!R]k*V}(MJ ӠA*憓Ǐg߾}\xkײm6&O+=61VC(**:;ҩ+HMM֖W_};;;v|U@c,U.Z!B!ģ={6mڴ\z"}Yz?/ʕ+C} Df}H$P!<666ddd~lllkkk˕+Wx"zR/^XNJJ qqql޼*.jcebbbXz5ǿLBLL $,--HOOWШQL̽EdggK-U!k'!B KߡTI= !B!u !Ԝ;wʯq~}ϟ'666j ~/ē(66X}!iӆ#F; !dĈiFa̛748qdvdWm\B!7y~B!B!B!ēN*\z \\\pss#44]O\\&M'''~mV\IAAÇ|xxxлwo\\\xwٻw#7o<5v>t̙3GiY`oNNN5]Ĕuݽ{O?+/44|^|믿βeԪVܽ{(z쉵޲eKݻU[!oN KKԾo߮_OOT333#""///lllhذ!i& &&&NfhԨ,^##J ((N:addvvvh"̙3iݺ5 61VT\\`Uދ~sss|Ç?ҜB'ծ] 1rH}SU"3f`ƌ^yrs8v옒pc,aȐ!4hЀ$&N[={Xf KHH;wԚj9-" ,X{Xbl޼۷oӥK,Y?CDD#'\f~[l!==֭['йsgRRR?>/_fӦMӶm[.\ȳ>ˆ رcJӧܹxӧOK…Pq-Fr 1͛7gڵT^ Ç|ܺu ҥKj_q>5}kddDVxqqqڏ9\vvi!֭of(jgĈA!#pqq9s憙,_^zI|WDFF*BSJKK9s&ڵSNzT!x 4ݻwBHH1KKKLLLXp!SNe̘1İzjB!BxT}a˖-|XZZjܹs4n=DYMɓ'IOOw85w^ܹàAA޽{5jG}ĉ'tN(Y`fffuaT5Ν;)--wޞ=z!R!D}b``^^^'Y!LIB5CCC"##ؾ};{wB!B!dp! """EӖШQNJJ qqql޼GNϹ|2]t!%%0f̘g)}tՠAJKKwfff\|Yk̯UV\v .+(.\FXUZhAvv6hBXnnGQ{_3gиqcѣՒ믹z*;ٓѣG+>|Htt4| nݢQFiӆ`ll̫ʡC8~849q<Ņ&M<~EڒM~7vٳgyW0aBك _||ܹsKKKՒt_ͣ*w4o\ceeE׮]eȐ!}2'Nxń;wj*bccٺupQټ߿T=A`` ј<0B!LMk#$B!#F0b}!%B!B!B[ Q}F``ҞСCqttdСC qYoN=AYҧOV\Ivv6XGGGUTI${ѯsuu 88DJJJHLLdٲeׯf7ر#Tm>B ɓW_}Ŷm۔QQQ?PPP}6dJ۷_EII _Jp1′j;5:#00cǎOqq1N>olܸ;;;,Z}CII nbϞ=U~N>Maa/{Aaa!|M-ꎣRIռysfΜ @jj7Vf(B!O<!B!B!TOWWWbcc "((HxZZLHHF‚kWA޹s{. .ԔŋӨQ#.\ѣY`;wܜw}#GovW9={j*VZFOuѣG~:ƍS;֦M6]Ӈ'N1vrr2PD! ʊ;vpAΜ9+ 4য়~b…|wu0w\^|EJJJ8y$ׯСC+[[[:vȥKHIIk׮5RRRʢ}J2WgвeKLBv "300k\r:0~xڴi͛7 '))cǎ)+t_k.0Ο?@5Q+I1pmV^ͩS>vvv;s;a9­[⭷_zS4׺ZRRh ˸PV&<<Ç!vvv :aÆUWUV6wEϞ=VlGGG3f !B!ē >[[[٣q|Сܼy={`kkK\\ѤQXX`jju m" 9'NksZyL"BK6`5R*S5y&}k.prr!B!B<=$Bݣ0k,JJJt^Jxx8;w5jĮ]HOO__Z?̢EhժZb,X.]J-ظq#aaa| /,fp߿#筷RWqFqq~Zh믿㱰=8p V">>cǪL QNeoWl/ۛ{; !_TttCBM68::rY֭r,11L^ylmmYn6lP;?;;(XxNc޽{qƑ:t{ig!u}'NS> ~R?0vIii)ZS !B!! Vp w„ j߻^뱵Yt)K.h}Z7 XJ!7=$D1|pΞ=W_}p ;3gC A$%%1qDuo֭dffbkk˒%K'))Ikey&BWw T}ܿ鉍 P^`` ј9B!B!BIB___+"##DHlllstBUY2Csq1͛,rpp 00)S?rJœ۳pB FllPS 6[nL8Q#ΚkjjJ~~>ꊧ.\t mjk׮Z!ē!A秄7oΑ#G9s&pqqqɓ駟8{,PQ?ܹs ㏙:uZ_y&B$O O7èQѣGc6nH@@B!B!D] !D111a…L:1cի166stB<.^%Kƍ(I fffߟsطo7oH x78pG7ѣzlْ7nV~F?<ݻptTxgy&9|TT={Zioٲ%DEE1fB!BQI…NrJ&Ou\p޽{s ֭[ӴiS>rrrŅmے -\Ɔ_|$]F.]xj5~uKTT|tؑW^7|CNNѼʱ^zw^>3{=ڶmK^^ &&]`1`n߾뫍S%o׮o͛7oT'[um[TZU,,,?>,[ KKK_qprr۷/vZmɓ>|ƵUs-**q a BEm߾{; !j͛7s^{5bcc100Pb RSSW_Ύ]*FuUYNm3B޽{m$[WTTĤIHIIQڲ 990jjݺulذA-;;(Xxڱy%QݻgRm_SPPu9s xS!B!OIB9///Y,%Ջ'OFXXWңG Fxx8ׯHҥk0$-j2~u BBB׮]c…J{>}d]E0`$2l0Ξ=ˏ?w7ngϞe֭lݺ@5N3<Ν: 䳵ʕ+\x^z)1ؐ$?CN3f 6m"88_~YVSq-,,pwwݝؼy3{)֤BGy-Z ;;\rss>B'ӈ#1bBEK…HVprr$''sI^}UݧtxII֤lmmIOOW[pWIBܸqVZd:wLRRݶm)))̝;;;;222̙30l0Ν;W;v`Μ9 2 ĉĊ.]ĺuѣ̟?Ln￯u ]pi:wqUӧ%B!B!xJ=B!ڵ]v=5}]166А^xiӦ)<o?!2l0&OڽzYfܽ{M-144dѢEaaa!L8K. 8yfԔO>3```={dҥj#t_cǎ 333 ѣ&M6w}kkk (..ʒK4wjYK_ `ٲe$''SRRBRR˖-諪<1oGQQZ}F``Ҟ8o&|?tRL"Bվj?vP>_n044Aoʑ#G4lؐ+%)LHHFՕ={j*VZS2yӇ'N6l~BQvtR.RB!:t(VVV8p@i;p< o#uܹJ;͚5QF۳xbfffDDD免 6WWW6mڤv̙nݚ RTTS9駟j\ԩFFFagg-RM>OOO6m̟?k?>>333BG}w\;3fɓܹs~WN<ɴiu{M]ƯƬY9s&k֬… zG!Dݩ 66lP2k,011Ȉ]l2%ibΝ:addDxx8XZZbddĀ]˓g!YoheP勇>i>Q+V 55[[[|||X`A-UUgÆ +=&sQ]@syMB!B!A*\:|%?5* !ؘɓ'l2 Ciܸuy;fee`eenaa31cFtssM]g͚ŬY4uvl8̙Ü9sդIذanL.\ĉ1556n!Em98qOK.%..333yxg%!!/#G`hh$ՔWe3|<==cC!ēc„ jU'377'88T{g ][D!D}akk˕+WxZ/j!##+buAU0""KKKӕ%%%4jR~ABw}ͭ25K-&77-ZU!B!$ N3rH}!B<t¨Qظq#GK.zJ 3gnnn><嫯"22ٳg >>>zNǷ>pXXXAvc͛7gРA8991j(bcc[n 6nHNNFRF͎;ظq#zN!(#$B!p-['|BNHMMeٲe}ϦM7ogϦCol۶[_|U|(--iӦV}mG͕?/^LǎILLdҥ^&sر#dddh$Vddd(}B!Bt Qg"##wB!Se $<<Ç!vvv :T:GX<رcՒ-k޼9>>>^?J…ꚧO&$$#G`ddD߾}2eRe%ܽ{p=/&LL:QQQHƍy76mRݻDEEѳgO[l#QQQ3ssssB!y&BQx{{s!]_}8~8ɃL>]Ғ;w၍ 9&WWWb3"i IDATcc Ҩ }.]4bر#\É'HNNAorr2y~B!B!_$Bբ!DZP%={6mڴ\z"}YzRQ_~V\ ɓ5>B|q !uEIB< ibbBxx8aaa>>\zpvܩL8w\JKK9vfff 07n\5Yj;V:ʘB!B!x:I…3fĈEQC; !200 ///}T{)_W퉈Pl۶^|EΝsbbb ܸqVZd:wLRRT9={Xf KHH;wۻj5y޺u *|ԩS^={J`` 7od۶mTE[l!==֭['йsgRRR?>/_fӦMӶm[.\ȳ>ˆ رcJӧܹxӧOK…B'<!x5o\DVVRP‚3f0cƌ*憛[}*{477'88X˟t\4i6l 33֭[Ʌ 8qfB!B!xzH…S^^^DFF; !D UB!Z_]{>>>j;q9r`Zj%+,\aÆ$3;v yѭ[7 )DFF+xzzV;ϚXj[ޜ9sBuƼyB!B!BAAs 333222X|9/#|2W_ٳlllstB!B!Kp!BB!B!6h vMHH!!!j,--*JpBNʘ1ca> !B!~ !1ZfCB!W?*[Tl/|^ɡ|4hРkٷo/^dڵl۶ɓ'3|JϭMK/E\\n׊SWT:*tU>"CCC嵶jMB!BQe\z"}Yz$_~V\ ɓuژA!B!$\QOoXT-BRgddNNNѪU(qyܱڵlڑ#G>q*::Z!!޽|"%SNqsa609ME!ӝp[3 I4?r)jiP"rCuglЖrӕx\]}~EΝ;177/?3Νk׮Jsu-ppp 55i&JM&ƒ8;;MPP=zUV}.^͛prr8̙3ZҤI~WΞ=KnݔgT"''333c999J!$B莞:̕B!B !qqqܼy7o}_PP+WdϞ=ӱcJ_֙3gg֭2bܹC{|ǺAƠAt6!zzƍӓ֭[_̖-[aݺu׏ŋ_Ҷm[Ο?ŋ˼#̞=AѺuk~7@zCaa!XZZjcI:uٽ{7&L`ҤI333_۷0`@ -Zwrr2>>>߿ի7nLJ/ۓc=ʜϢڴiCVViiiiiiJ!$B!B!BJ.xNر{]v WV{. $&&g]CYU}6sE=vذa|DDDXktUVTT3fu&; !D5n8HJJMXZ=z4{_eܸqZ]|}}U;fmm}4iƤ쌅ȕ+W¢ܱDEEC! ,,(&NXsϸq3gj yBB```oʹiӨ_57,, ???Y&.ӧOWp V^͡C}6}aΜ9Ӹ5kHHH //͛3vX 1 Ç `߾}dffO˖-qttI闛KXX]taÆJ{ƍ!,,1cPNbF!Ӊu(B*"""B=xJK011a̙̜9qLMM7oZ[ff&PfU3{{b+7$ٳĊԭ[+VڧnݺxzzYx%Ov###\]]ٰa4m Ξ=ɓ]vB[A!xa:}B!B$B<U0eRSS>?zzzjc,]T-b4mڔe;w{n?>yyy|ʮDhh('N 00KKKlll8y$IIItQ雔DFFݺuB ٵkC - cΝL0jժ=ѹsg~'"sdv gggוs.]ļyx}|Xټy޽{$''̭[=z4{%??;;;q ۇs1 _͛{lϞ=$%%бcG  # uB*߯ggϞ3{l166&--%Ko8—;w&$$DI 777G',RUW!<ݓ[B!B!"{-Z !! Ljj*:t 44ǏNΝ9qQQQc7pQL/իWg۶m$$$0i$6o˗iڴ);v 6ФI.]ƍwVntt4...ɓ\r+++Zn VVV\r\;jKiȜ9r+Wr1iҤ W\!88m֬$$$0~xbcc[l!## 6mıcPK yߴiׯ_}DFFСC ,q޵EtڕSNQ^= CCC"33LVZO!D \]]),,A^055%&&YfaÆٳBȿovA.]ӊz5j#sбcG:u*xxxTx\OOO,--=z4ܼyS99sx?O>Qi\ȑ#|J?///FIv˗ի...Jbʅ TUT}xR%%ݹsUVaooO xwYr%~~~ N!U}/BAA5{L0A(t7Ãe˖0uTuB!DYh 4P~&E\R B!Bb \P- WIOO.]hkӦv-[* 5%Y<7ʕ+GGG8|0}ѣ0i$Wu칹>wy V((Q9`;;;GeڴiDEEUZŽ{ W^[%))Im3gꫯ>Ѹe˜>}ZmRRR4>7jԈ~K.Ѿ}rm,&&&888@jj*`ӦM) fffdee999J|ڴinRcJk׮O?h>/^ŋܾ}{O1;w](ܹsg9z({B<1ggg+o^jw}a*|=8٬XhlRe.:Tl۷;w....{aÆ_Ql56!B!O?* !B!B!x9Tlk!twxyy?nܸaccÔ)S*Z>III,^=zwvv7DO?qy^}ˆwޝf͚O?Dy]RRR>}:?M6ZE9s >>>O}Ei}뭷XlYYYܹsKbccСCKBMGZ0`SNf͚J?ȝ;w_>zÃڵkCطoӲeKqrrАΝ;4ٵkgРAԩS/J 7n`:t۷oӧO̙ݿOlذ]F8p &L@W*>JkX~ѥKh7Ɔ0ƌ̻/9B,EDD:!^jGGaiipΎ Eƍ+}~ JW!ʣe= $&&`kk[KB!B!tE.Uw~zbccz*FFFX[[3eZjUiթS Ǎ7033o߾L8zzz899a4'{cbbRk֬gڴiO޽;cƌQFZ]'11SSS i|/ `ժU8p[n;޽{bffFPP;v;wЪU+ƍWtmb6l5j <<˗/www_Ybfرj;|0O{UCӦMվP*^<;v,kܹ֬s;w[2tP[11UBٳ9z((Y 44 ڵkٰa9YYYqM.\?7oVܻwduGU '**qiپ};R/Knn.Ǐ'##Ci۳gn*dgg|r^{5L2T-33@RRRGOQWeڻw/iĉ۷ggJUە9B!B蚭-zzz;v*L=Xv-FԱ;s m IDATlݺBF;wuhB!B! IUZi&&&̜93gVh m֭,&MRPTYsr]АXw?ݡsRn]VXQij=322b̞=̾OM4GcJcdd+6l ##CYٳgBMZR׭[*mׯ_gر;[re@}ӧSfM1bܹsG.uܼy7or߿/@ǎxR;uNi}}}XlrKzz:BP%Y\tI|UlԩqLզ#ċ.""]!x!!t*BTݻwԩSܿgȐ!|BbŊG}~~>Vݻ3d֬YCAAhwy'''a£ K.4lP׸qclll S6mB!B!5p!/7|-[ԩSqT999qI.^g}vf͚ `_^o+4 999|'4hЀիWcmmͩStڸ7|n\Dʳ\Y[.]caa;C˖-y4v֖8vsXf L:gggk2`{FOAACUK+ˢJ(xXiLLL;w.,^zѻwbQ+rh3_UIg?0kKu~qTm>B BBBpuuuBThh(GuBKB*%??s=3W}ussf͚pQ3gOvv6?$>>ӧ+?*i_/2j(IOO[nq=z4W^̙3駟2k,VZٳguB!9cAJZ(,,T*z<幩)Μ9s]o&RZ5QTm>B!B!VC[hh }9RjԨQo^Q QuQN:WCc^:{-Oy_4Ȉٳg3{2駟駟j(;-Zp}Ο?WM~VpmΝ / IB!B0sLׯʕ+'55U=9iiiܹSR1c߲uV=Ř,rrr033S;7''G#B!BQH…xjMB<,--ux <: !ٽ{7!!!xzz9nnn:Nxv'gϞ%::i޼rԔAakkȑ#Ņ;. HJJ%+ԨQ7x Ƒ#Gtbz*#GTF7|CPP:N!B2=z4\tkײj*zƍӓ֭[_̖-[QѠAo),,SNg76mڐEZZFbEZZG!B!*Ь)B!344ۛ(233$** ooojժx`ccӧӧSLQj*޽;C a͚5hsu͛G>}޽;nnn۷OT>|Ⱥu6lݻwgϞ|l߾]휒/o%;;vZLMMdNc̻w`~müy~z\/_ϏbҥKxxxoӷo_/^۷5bRԩS߿?+VÌ;VÇ166_~ZޥB!B!!.SJaaC6mĉyw?IxxZ5b-:%)+.m^3 kN㘪MG!U˵k8p`ãje ?dŊ8:!^q̙éSXnfbb̙3ٹs'Ǐ,[d {3f͚ѢE cFFFrY222 Ξ=FrB!B!H !1c111C*+::Z!!lll"777 U|||hҤ h7NNNDGGˋ;`mm_|iJv˗ի...yX} j(>j}ٳ ;vˋSGRe^w,XDYv-ǏՕZjz61φ Iff P.U`Us%_5:u֮+WhӲeK幉 >,ڵ]v76nH@@Yti16lԩqLզ#/t5kFRRBCڵ+LQ2XreB!B!%I9QPPy&&&&ٳ8Uvu-me)Z>24~E:pҿ1TzzzW^%P+ϋ=zpm5E pww' @ VT(O\*yͨڊOU[y^kB"{CDl۶M/$ Hu릣ȄB6lHNN666xyyQzxxxl2NZB!B!%I9͛7y&qqq8*QgΜߟ[RXXȈ#RvBbEBQΝ;177/?3Νk׮Jsu-ppp 55i&JM&ƒ8;;MPP=zUV}.^͛prr8^}UbiҤ +gϞU[xxY cv8}4۶mqUJ)/m^3fffdeeڱB̊K2edggcjjJRRg%V*BEttV]]]quu}J!B!B<9I9c{=vETT'\T*۷;w....BaÆ_#Œ3uB<ۄ: !D#;V {fƍxyyI֭믿f˖-ذn:?ŋ/i۶-ϟge^ё fϞ͠Ahݺ5Y%t,--$:ub޽ &0i$틙ׯ_g 0dE)/5zƍ/}*أG2糨QFqicСXZZRPPӧY|2yʹiӆ,4+T #mڴy*q !RXX8p ;vܹsM!B!B!D% s3B$++'OR^=>39‰'?hԨ ի9Ri5j| AAAxxx0:, 2D!ܓBTqGRRnnnjjժŌ3G͞={_7nVqww___|}}ՎY[[+իGvv6Æ ܜ;wjci{.???>{fܹŞojjq۷gĈ_;$==ǫh+޽{3fl֭[ٺuFf͚1m4b}Rڼfz-:DJJk %%X2B! ЪU+8p $[!B!B! J.DJ`֬YXYY);yabbbvgL01c׮]ԨQÇ3errrXd ӳgO<==122R% r ׯO>}4iƤ쌅ȕ+W¢ܱDEEC! ,,(&NXs^{e… 4Hi߳g_|?`͚5$$$G;vyEpSÇo>233קe˖8::Txe}IIIԬYw}ӧ+(Knn.aaat҅ *7Ɔ0ƌC:u>WTTCB[n|ƍԨQ͛ӷo_FEڵIi߿?+VÌ;VmÇcllL~JB!$&&: !B!B!O$\炟ʢLBjj'33@RRRGOOOmK%C_Msvލ //?PY$*Nr Ɔ'ODǎIIIdddЭ[7,,,]v@XX;wd„ TV&g̙3,]kkk7nLVV4lؐ9s;ׯ_WνtO;?7oVw$''s֭"ɓ'C~FI׮]>GO?ҒڵkũS8Ξ!!!©S9*NyҒ5k*7o: .8j޼Z!F`` k׮uB! mРAҧOvϩSW&Mq5chh7QQQdffITTԪUK U%ۺE oV۰I!B!B!ċO*\jqJzz:tF[6m-[Tj@NU;S^r5jHPPO>=z&MDյ=77WIX|9˗/K^^ŎWU:u*Ǐ'99-ZW\O΂ HLL$11k2~x\]]K]RM*x<|PXGUBR!6Zjùp_5ժUuH%r…'11[[[,CBJJ_(((QFtޝ &аaC](f|M<<kZѣ8p`+35=.輊؂1cIHi.\ȅ ~vTdz{n;t]<^}U7oN6m,HY[[mZ!AQ|1WkADDDE| [lQUt"DEEc0DDDDDDn999CBBB->>_>6+7>7bFll,|tl˒ ܜ|YxbiժN"44l_EbL8|6`\aÆqEϟ_h%yJ8ԩS|ˌuDDJ{{{W_}E߾} L6)ow.ʕ+L6AD0`SNʕ+H aٲe^]Z:DJ{R r9.\``ԨQWnȑ#\~#GGйsg$77???}y7 [nlذoo=_aÆLHHH WWB/Wōcǎ޽|1&&&Kx'9z(c޽⋸_el2&L@Yt)YYY,_;vSn]^z%F7nl2oٳgI&׏W6oš5kh׮٪^`0fJ͚5+ ь1I&[oXڵk;wδڲ߉' lݺu+34p!@BBBQaaax{{䄍 t֍r]5f͚3x`ё!CY}kkk K(N999lݺ^~"ӧ5kd֭yo1qDFgĉԩCxx8={f͚ҲeK>cz]hcǎeРA<δi0`ӧO;;;4i3g,QXzꅽ={ƞ={Q/Bx'HJJŅ{舻K(͟?LS"Cvv6FbŊ9sΞ=KXXcƌƍcCCC/8}4999deeqQ>C"##MJfAmFVVV dee}rzEDAフ6mڴYdA 2eNppp1bD%F&"r?~|{:tP}&LE8|p%G("""""""rVZQ7qƕ?L8'ٗȑ#9rd-~mV;w4==Χ$ .gf_~| /򋧂V'OfwK+5QXW7˗/'55gggRSS9|0o&E!"R֭[]6uˋ{իW\\\ 32j*hݺ5SLI&L||<Ѧ 6h" 999lٲ֮]k2m&$$la @˖-o,e*fݺuADDDDvEZ*xjg}YfWd=1{˯\´i4hNNNЦNVZe)""""""".DD*ҰaèWL⑑899kDndQ8|IMeLJgUHCY:3lS9)`ǎӼyslllpqq!((-["##Yn' "!!RY'NШQ|7nlVGDDDDDN222b͖EubccSd:py~JJD x '==///Sِ!CHOO'<<܂ȃJ+\Tjժ{СCO>jժNDe<;v.]mllXl_y뭷HMMe̙]2ŝߟM6gPĘ`tiBW/INN6=3f 3g$..8>S6T6 ryj֬oXGD8lDD%EDriӆUo>ZhapDDJ̘fϟϑ#GR ?i&KOBB[H,̭[K.777vŦM駟Xd Vb 8mĘcm>>CDDvvv)7| ^W_}ō7  ;;QFd:ٳHhh(LcHeQ…]l%y]6ӧOn~~WNZիSvmٳgϥK}:-ZJ*ԬY:_t@?Nnn.Νc… Feۯ_? ʢYf4o[[Ri|-O>m*kѢ)))5눈܍ùvZСw\%RD N'NaÆTRŴۭqw@pp0͛7زenvxyy'o׸qc:""""""""!K """"E{Yl| dggMVVׯzꄅネXj?VZyUwn6XJJ dzm6sw sɒ%8pʕ+&<<}uޝsΙ\t)fnyvv6qqqqEƍWw ???vő#G5WjUL Fpp0!!!uuu-Uj 0'''bbbر#w&11Ѭ]KΝv""'Nn:nnn <2Cܸq!"$$SҠARFǎIOOFHhҤ鱃`8 G'''==z4ѣ;17WɸXGDDDDDDDh \||׭[իyhժ4mڔUV1bĈbg̜9Ӵ:EiZh͚5`ر̞=3ըQ ϟϱc߿?ooVYBQ7X+rxxx:\iٳ'={4+^:,_THMMü1ݻ ,r ӦMcРA8997NVZe)"""@زe L4鮼7 "rqrr"%%EYx1ɴjՊ$BCCxN:A:ueddꈈT&p!}xzzZ: )OOOڷoo0D=3Ƿ.OBdd$ 6,w _~cN< VVViӦ=zDqU^\jݺqڵ 2w\U?~$deeyٰaèWH`d"r?3  KQ.IOOT6d `d"""@B߿OOO<== t8""ݻܹs,\QLu8@TTmڴ!,, WWWV^́Lu+U>}Tf'%%%_Ʋ[W ZB*̻˻k0DDDyjmcc!? 666slb**΢/;;;.!E^ظq#˗/'66@ΝKppR2ժU#(({C'|BժU-<˖-c„ 4oޜKٱc;u套^bĈf_nܸeؾ};gϞ֖&MЯ_?o_qڼ598!!L֬YCv~׫W5k:tY2^rr2}'<<DDt~~~ڵ#Gdjժ;Lg֬Yܹs地 Ra|||f֦M۽XLjANN}}lٲ7n J^^^keUV-?@||<&M?Rrgm۶% s2w\FKQ6|233M ٌ5+Vprrr8{,aaa3, 044/ӧOCVVG?4[ѧ$md۶mdeeo;YYYl߾^Yz5...^[[[K#"R)HHH(S5j ,, ooonݺaZy" IDAT$$~'R~}ׯĉIOO'$$ &쌍 {{{ٓ={PF ^x2HIi PfQDޠd {߭FATTřVr2dHǿ+͢Exꩧ?7osΥ{|wkEeeeE^^?3͛7I&:u%KO?Mrr2`b7ޖCDŅ0UVD֭2e M4!%%`㉎6^a-Z` ''-[ڵkM3̈́-bcc!e 8^%˴i;v,EDPX"FA7 lfϞٳ˼˦={gϞfuW7˗/'55gggRSS9|0o~~HS…T(OOO<==-ƍ-\ ovL<7w^ڶmkޞy[|ף>Jzz:-ZQFL8QF@@@Y]DDT~___;vleŅ ϖ-[L \tHN:En4h 2$mĉ4j(>*P:""[:KTw 5j(6ED| 6͛7ĉ ___ G'""""""""%\.\@Ϟ=ٹs'x{{3m4VZ1?0{e֬Y 55t¬Yx'-k…ri]o-/&)) MҧO&MTn#""wc‚ӧ(q#1c0sL∋O?oooߡ%i ϟf͚ˌuDD$t"r˳tŖƲe˘0af`)jժ{СCO>)򞶈HEQ…]Y\[.nnnfQϽf֭#..777 b}Aa JZnkk``۶mVZ,X z\yY}yyy啯?E!""w/( nww%={Ʈ]شi?K,aժU=͂XYY`mmoXGDA aիW1cݺuK.GDնm[;w.GQȃJ "lΜ9Æ  婧tX:Dhh(k׮%//W_}͛ӦMK&"'2}t~m,Cv""w'''RRR)D<<< ))o+V0|SEIۼ]:uHKK###:u0_ƍWqqqJ)#ooo%ߊ]A "[gmv %..I&aUfʕ+L6A[ 0S~zG"b-"$$ Z:^Æ t"raÆCݻA`` 'NYf\pUV_b0Xt)#55ɓ'ӻwo5kQiʊm&ZhAZZ)))+RRRLuDDtׯt"RIB۶m˥Сic)B,`0 R*U㏳` ?LLLfҾ lȐ!^p,^"2wɓ+=͍ Tj""""""""""Rq-HQ ңGFeڗŢECۗ%K]`ׯ_gΜ9t҅=zf`ʔ)tԉݻ3c ._lFff&_͍>}0|.]ӧi׮ (}:G>Knrr2tԉ{>+W=wfݝSU9WD3f ///l|vJqqO`0Я_?S5kЮ];Mի``͚5dffx^""!//4H G$""R~J_F ֭f+I 0ӧcggM4Ϗ3g &쌍^zaooϞ={ŻgjԨ /PҗGDi?G6mY.?+π$((\, 777_+o)ZB '334=;;QFdsYHLL$44kk|9sa/ggg֯_ojիl޼kkkf̘Kx9uش4',, b08pGᩧ2=roߞ *i'OJLLLuزe fժUi7$##W_}ō7 n&)j:믿ΗRQ?aÆ%$''3}trss۷/*aaa|7TϘҥKmFVVbwww'>>۷3p|EDާwEDE%b8880n8ƍwv<<DDDo޼٬_J  *uE]6.\0~O>}F9s V*S5bÆ Ν;MKRSSiР+V`߾},[,"_bZbÆ |+ヽ62^';w 66-[Xf#"" i0DIÆ -E Fzfu ___ F&"""ry饗pqq!&&;;;aooO?M\\EKuoR.Ϥ}H+\H3 *uFR___/Gv@pp0n&eѿlBڛƕz)=z4;w$ N84LJ0.^hڿk.LO<+?{=*~T/00д?̠AXr%{ݝL~'W+'N0]O2df#""N:ѩS'K!""jժ{СCO>jժNDDDpiiiԫWap% @LLW={6uֵh "`xwyw-}M rO}ӧOQ`|e-Z0=˖&MWV-q$[=39sЯ_?ٳg=z`޽ddd0rHlllJ{Qjժe*+Mnnnf۴i2{7Le,FVѿ(/k׮%<<wwwKnn.:t0%?5k;Xf#"""""rmܹs=z)[DDm?+V~ %%\i߾=Ç_t rm899gϞ5 ,?gĉ矖Ǐsynʣ>jpիCQQQCDnS󊈈e)B*ݭ+Wlq{n_N7(.]J*ֵ.:hW^aŊGlٲkkkUJ{Q<?^>n]!n}}JӮK[ۼ㩨 *+Hڵ8p QQQ$&&g:w)cYq ׮]+T>ooo-tغuk}W_}E޽Yzi)(fՌ=Q=FiL IIIWi0DnܸaH9ӝg'999BLL NNNW_9|0۷7>|˭u܈%11]X!f֭[8r)СC>N<ɨQhڴ)UTGm۶̜9 .xLIc+JI?+V0dWYyAQJJ m۶z׬NRRC ;;;\]]1;voQK.YfҬY3VZܜ)9(( `ggG˖- /~xR4הyڵ+Y^N8RJ4cI[q1n8"""""""RX\BBBQaaa|ܹtWKRfMصkΝN:>>lܸajAJhϞ=Ӈ/҈bÆ |WݻDmVV+x5:u?۷g}# QFQv;OsZ`aÆyf"##8q"p&Hq`&OLLL1 p)>tMnnnQfM,Xŋ...ӧ%v,]k׮ꫯ駟;wիi׮_~)"%%-[-ZĥK޽;6ḻayvIhhhեKXvN=ػwY9s#`kkKnXn[fӦMeVey"""ʴiӈ(reSҺuk*Ɵ9=z0;gyΝ;W91?'ϟg > … y9zYe<)JIéW}C\y&#\~Ԧ)r)p2 2իWN@@yX[:{A.]իIII4oޜ}XZjٳg9{,QjJZDάM8*jЈHIXYYiӦM]ɽ8o]~j۷o/ իW| @ yyy6]r90vĉM4i[n-ѣG+{gxYy ݻ7?1{'#55bUi߿?L3{ :+++? k׮ʌL4)߹=CP*BΝ͞7oxРAf\\\4+/$MQJzM,eff2o<^~eӧ7ddLh׮ya7n`ҥ 0:ХKƍŐŢECۗ%K]`yIb0زeY_``Q),Yvh*W5k@DDDDDDD*V)GGG2220 bccShݶmܹs_TVV""%ֳgO6olD!""bi7Y\D2EEE8LNIII899Yɓ9r$+M6e$''O+&.\@ff&?p),O3c]ӦMU^9VSLa۷}7?sۗ>}P]nUo\vݻӰaC}5k׮ڵ5k[oئ1)V́СCqE:u̞?}}sckk[`e<)JIY/z&m篢 IDAT֥Kx9uꔩ,--( ޾TmrJ=ѣG|)q2;;QF~={0 ͗ Y'OСC̙3WWWիGZZ!!!8::dY)˱۶m#++ ww|m8p`iO_DDDDDDDJH "X:Ap 7wb"rOݻC1a*''G κ_X/uQfM6mDZ1\+6mJBBǏ}:f썳QfM._\ ??!""4iPnU/"";w"MDDD  5P1ZlIRRӦM#99J_ n 6h" 999lٲ֮]kJ2XjIIInݚ)SФIRRR&>>h_h?*j 15kd̙0}t.]ʌ3|2s)oOY_XZlcYll.DDDDDDD*QM!""""""""""R_pB|_ʊUVѪU"0&^IΝ?L:u5222 <… f+?HJJ aaaӼys~ƌS!KJJ:x.߹v]z1EY>$iӦww|e[I߿\VZo]d|^W^`޼yV3[AjժV˪2& ~߹i t%)V|/={uVOO?իWYd {櫯2+h[wV)˱߯d[nMM3ȽcxzzZ: ҝfI~6mO>$::={ҞSI\riӦ1h Lׯ_Oj*<|,^X^|Eyꩧطok֬!""z`1,^z+Wq[oŒ%K^z{ԬY8}]̎Ylڵc֭nݚK/ѰaCrrr_غu+?0 EsN @pp0M6%99)Sk.tPC !$$OOO.\;UT$@򎭤9s g}ȶ;t3<áCرc97`l߾OOO>6mɓ':ujtԉM61rH1 xb>;]Jy(5jɆ ߿?7nή͍ٳg裏Z:|ׯϯÇi߾ܘnÃ$[VX8pbbb_I,^dZjERR7cs>e9N:A:u̎0ʣ P999 I0fH²Ɯ2FrXYaaid 9DԔlmh6}."q?}}s^>.\]]ٷo$A+VЮ];ٳgp)Jgƌ̚5KW_%<<}ve›14jԨ5_}vΜ9Sl] XpM 4cǎ%,,L l޼޽{uVCBB@___/{8:: bܸq\P۷'66VeB?SU[oEvv6'9!ijɉ03g2@k0`Lf믿044T{ cڴix{{ӬY3n޼Ɇ X~=Z xCaa!/^aÆ:v """h׮Vˋ7H5bԴm"##C-"##CYG!B!O>BTp %/y=6"DGfڴiB{{{eBFiϟˋ7|=z0o<ܹVɓtޝ+l2\\\ܹ3gŊX{twww[b\ ZҹsguG}ĶmTڔ^K'}((( ::QʵطoǏ }]-ZD^^VcaӦMtЁz)ׯ=6m"''8'gggCCCj֬IϞ=ٻw/J .h݇o߾ԪU ###^u̙Á^Z֭[BPP}CCCW-$%%%[(ߟ'O%XZZ2b*lga ;Ɨ_~I˖-111>3Ԓ'*26M͛7N:*uqssVZl߾7ojԦk׮$''3bZjT=qqqPvmԩ?#cǎj?Ghh(}Fꫯ}2}}}IBlٲEeb!ċO>aɒ%Vv8B!ըQ#xW&$$%\4i҄ذaiiinݚSҴiS222'!!h \t ++++ZhAJJ \zXlܿ]v͛6lʕ:N&ƒ p ._-͚5M洵ٳ$&&ҡCƍ鑒'jqqqhB/EY\\$\!()wٳZf ۷ڡ !OT͚5ۻ̺%%oT₋K絰`LWWW劮ח-[`bbTBbBprr"**%Kdbwf(QF˩SpwwW9Vzu&M|?l0~'OFU?#Gߟ;;;׵k 8KKKvءUپ};C Q&t޽ Wxw177gܿkӫW/LLL022UV̛7qyf޻woLMM9|Z_LˈB!DeY&-Z >>CB!B!BB<AAAL2[[[VZ@^^?Pn]˘1cT&(ŋ100>`dgg3|:!ݺuۛ5j(ϑCPPڵkԭ[ݻ3n8̸x" ښ(q 0˗/Ʊkkڴiٳٳg,駟wQb }67fĈ*JOjz ˕+W044iӦ 0{uoi&/^̩S066waĉ]+rrrشi:t^zޞM61|p5B!Bg >>>?LI `L≮^z%\@ݺuKR߫W/zskhhȾ}Jm`bbJ|Hu_!00u)߿RRReذaŶZ?>Aӓlۺu+L6 ={G.]ҥ ݻAkB!BQnݺž ϟoQ>FΝ; p,--qwwa۶ml۶Buܙ7 OtBq}>C!B!mVOY&Mclذ4ZnMDDǏ'22vڑ@tt9RSSٸq#Ge֭[Sy!eu֑N  رccee PN߹sJvUю%͙5k̘1fΜInn.~~~XXXvZ_ZlITT $$D;S ;wf̘1Eo///-Z 䨄AoxqDFFVvOL-Y&o߾BTK.UO3B!B" \PLWx"...?ZY͕_*nڴkvE\| @hh({=zlƍαjJY&LIIII&?Q95H'Nd֬Yʕ+ͭUE5E< eׯ_8EB( <WvB!BUnnnJ'Yi˖-UZj?ںCBTǏg˖-$3ExB!B$\%(s۷o[Zj$E'+]ݻk.Uc.W4==r/,,T#??_x^ppp 66۷믿b 6l 4hVw _7.EYqYQV!B!B!pI `ذa7gΜAQŸɎB<#^!B!xH…x.YZZ;|}YYYLNXupp ..T:[oEzj˗/lْ4>>8;;ӬY3/@uGi{5ѼysPKPB aBg|P!!B!B!B!BQH…x.5XN:ʱի3iҤ kȑ߿/raÆjeԫWWbmmMǎ+$v{{RLLL$''???LMM={61tPfΜ͛177磏>"&&SN煮gر%DTTK,aɒ%tEȑ#' @-!ήk{5ѵkW)I ) 86mQ[ B!3Y}FR8y$۷o'99B,--ܹ3Æ -4B!B!D$ G<333BBBXf իԨQ;;;ƏMgnnNhh(}\v:uУGƎJjժ{{j3k,/ f̙0w\ԩChh(;vwbccèQѣG4iժU#&&;w`oo۷Jb``@dd$X[[ȑ#K|#F;|0fffS !B!m۶m۶C!sDFVT޷nZsrIgqA~TDIIIyf ]vB!*ʳΝˎ;\x/}v͛bl=3B!BQuI…x: &Oɓu:65kooRR7nƍ+񸦱gqΝܹsG~Tʬתo|||)3F\\\:?h~55j͍`233iР$''鉩i} !/,ׯ_a!^@BPI 8u+W}#-Z;v`ll;={ښΜ9Æ 8tӦM#**uVXL#B!BTmp!FΝ; W&rcii{%G'OΑ#GXv-G!##R^=:uG}WU)v .\ 88}qYrrr077YfٓѣGӤI iYz5ܸqCؓz|0}}}iܸ1=z`„ kck!DUTvB@ddde `ooVDPPeXlN IaddTj^hh(W^eȐ!ʲCqFBCCBCT 3ٳgٺu+FFF|wjagg_|}غu+ֿ<!B!U$\!<O>|8,]իWrtBQ^ʨQؽ{ڱK.q%n݊37n¢|~ݻwooo)((P9vMN8'?>| ظMi;u=>|͛7INN&99˗zjI9e\ɑ!^TCj!((s5֭K7nfffzE9:tǏ'--MYʕ+J`` ժU)Ă ~dee@z:ujS{!//.]K.$$$w^ x9r/J…Ug$sa޽KI&̞=[}3B!BQU_n__СC+;!x">#y뭷8}4}-[###7o/GVZݻy嗉VZ%ݺukXz~#GҠAhРFܹs ĉtj׮ Ŷ;wǏcccjժE5k7o,Fw111aϞ=}ܹCCCVZrqm?w^,sYR\O3yaggGff&}}+ܽ{onݺQN [.#66Vu1tPիvvvرĘB!#VZ^L66m`hhH۶m<߿_>ɍ7puu%11Q9I &&lmmקI&k.c(Ipssɓ=_~!Cбcryyy8p-[2k֬ (]߾}8pFWaȐ!@V+O\ggR$O3-)ɓ'iժG!//wOΝ),,dܹy&nnn6O޽{w_|'OСC\~p :ĉ/׹'& ?gʔ),[JG(VD.^z{nf̘A۶m{.+Vٙ[*l dXY4Oy*VVM2MTe/2666dO!H*ʋ<=#oYXYc.oL#B!BT}p!%/y=g!3իL:ŋcccCqpp`|dgg|Rό3qssS[j?dʕ4nCCCٸq#ׯWE:kٲeܾ}~(ZjZ"**~7nXlnݺE׮]155孷b=zT/uW{DEEѲeKx7駟hݺ.B<4R>h;w.̌'ٻw/gʊr%B[wa鸺biiWe!!ij%11 ZnMbb"˖-NmbZ2⽥eⱰŅ`֭[ȑ#u/VQc$$$+,_ӲeK5Im:uVk(SrppرcW[ӧOX-4B!B!DgP/^e!QÆ +;!i;wO>)1coػwo:t(('''gΜ9lْ4b:1`233ٙf͚_`hhoƴiYfܼy 6~zYjh%B.^XӜ8qڵkǪUbƍ8::ҡCr5mۼysPXPy:[灃ӦMؕхi H+=cǎeȐ![L UXL#B!BT}p!B4սΝ;WqbccƍW9ACBY,,,y&999ԬYS6%ū8EyI5بըQP߂~ԩ|G;vL5=zUXlEr&;;[rrr055ոMIt[묭і"E$tN>MBBǏWib.C1)n;w,x!RI+oڴŋs)yw8q"&&&*2e yyy?Cݺu۷/cƌQtR9;whڴ)#F`ԩƥx_PP@PP{ʕ+ҴiS \@ѦX8RFlQK/;K.~P&\(G@@111ouq2'' ϵkר[.ݻwgܸq*ߜ6mDW}gӦM >ssb.\$\9sE<<>>ַ<!B!U$\'fҥDDDTvB^atYHپ};kVQA+lllHLL~SNy{$T$Sn 41j(j֬W_}ɓ'믿 #,,Mw^4iR!ĉQ{;%.qk{4?3?hРAu7oԩSIOO/W\*)1VZIQ6OOO{.[niӦ[x1999I?^pBBBHMM%00PRqnn.cƌҥKʺ2٢4*E߿OJJ )))2lذjcI_֭[q,]$cWN{.v"99 6hwmF:++ QKr,ٳIOLTڄ-!#5j֭[ܼyS$Μ9ç~6le˖%۷5ёD٣QٳgСgÆ ?ݼy IDATl^z%67oTV}}.^Ⱦ}8rGٳ\p']rzɉ'J(v'<9,޽[aqvY[O3X&""" <ƍSn]Zh}r=mn޼Y)IB'QF+LHHPKhҤ !!!]!6l@ZZ[fԩ4mڔ IHH ::ZExx8.]ʊ-Z/W^-5(-[=g׮]yf VnX8^}Ubs.]J8s \| 6Ub[n4hЀ9sТE Ҙ>}:ϟ',, ///6e߸8Zh֟,..N.xFڵK?\j5k퍷w.QI...y^ &OɓK׫W/zqř;wn _~S&mkԨdff*333INNӳBv B!D٪3-_|EUTL#B!BT}ʮ"B!XѣZ{.C !//YfM[,C `ʕUK?p->msqzaÆ|G+WVLtcƌ5k{OrssO>ݻիW0tPu… (M*3S@Kj*Μ9ٳEe2z(V__m̈́:!2{{{WYaÆ+U]?ӤII`ڴiiCCC-3>Čp"##q$&&0M%Sjg]SXXߢ|||ҥ iF져.*:mVSڔun7jHmƍU!X#G~*cii{%F&B9yB!B!6IB!A>}G}}R?Ç[x;wٯ.믿V\XXl#xr&AYXX,.ŋGuMPor;;28q"7RHX8ի+WJ+33S~Q*۵k=]tb'~TYM=X"## GFF>~ˋ5kG>}HHHݻ8pOOO6,_6mڰn:%cllLhh(SN&//+w5jJ ֭ݻiݺ5˗/'==pRSSYp!LX177 84IKKcbjj'|RkaĐ˃HMM _AEǦꫯx믿ppp`\v:¸qx!+VҥKԮ]P|MƍǑ#G{..\`ɬX:]xreiii 4cǎxUZU^eN }/344T~]ڿEw}xŹ}Zmzիwfƌmۖwb ٺukmuq*WO*1 ʫ$Xe'!i߾=^^^,ZE1aB!%L#B!BT]<B>jy˗⧟~"006m<(ӐD`` 7o?[[[jBADDDʾ}ԩZ+V|?={6h'ń(&F6k֌+V0f͛ǼyTuƍ+'z;wI̘1Yf꫄3x`oUNFJ_S_~%۷o̙3Kx XpMۖ-[ꫯ7o!!!%Fp VX9sWgΟ?J ƍW!qk{ccc}:6mܹs8qBQ]97owlݺUmtHH*!D(,,$77Wonq;9%رKKRZ[[s~W:v,_5\\\HKKc߾}]ŋ3hР $ b׮]舍Zgϲn:E:uJ%1>)) x6?INNVw099@1֩S,Sʱle!O2!\!y%4B!B!D$;\zqqqlذ/sSTʶO;w>}:XZZbee{, ٙd<<<А5kҳgOR… Z۷/jȈ_9spb#oݺ5)))ѧO,--144zIRRZB9y$XZZb``%#F ))Iرc|嗴l >#))Im~EƦSg̙|W8::RN^:5_~,Z3gbll̼y;Z( kȈN:?2v [J>}Q޽U]*y-V4jP ;!3Oݦf܎a%):~ԀLaϙ å \NРHJC ({7'7q]\>k?|kUy/g*-ZcǎxxxLzzΚ5;w2`ZlO?4o͊+غuE~ :dMf:g߾}m,"Ү];8׹pψ# ֭[\z?ܹsMuy֬YCjj*7oܹs*+2f GyWWW233kce /@aa!3g$&&˗/sMb֬Y\~g}իWٳݘF]eeyzzBJJ 7o$%%t&1ZG ##1cHC_T@;\W䭡e˖WAu۶mKHHiݎ&~eDPPP^y֮]KZZZcnnnv@0ϸkzwΟu>3՝W۾Mƴi*?uTNZXjz?zΝ;˕j2ӓa6lG3}t;FJJ fZjŢEL?kO@@!!!Kqss3n׮¡CjcU__BXXaaa1”VV]w>}x嗫9Bff&3f0;֭[re:t(Ǐ'55~KΝ;Yd 999(""""""""""wvF`0`08s #G4[yM6͐!Cx饗ؼy3EEEfmuV|||2dO>$ (ן%mD%'Nqw믿j* ȑ#Yr%W\nzz:cذa55k֔۩իی5 /_Naaa_|z~www&OL\\\&K?/޽Al*ܹ3ݻw_}?G}ѣG4R4k֌ fX"^U;-Z &жm[4.lllprrӓ;v`oo϶mEo`ggWi?>>>\{ ;;;ٳ'ӧO7۱jɒ%t:5*vvvyh޼9ڵ'$,,-[Vx~XXÆ E8;;3m4njv_V6mdҤI8;;ccc3SLaǎ899Yt=w=z4c}fϞmHE{{{.]ҥK&hTai='''/^ŋ}\ҬҥKtر}///j%;O><+m۶F*SQԶm[ =K}[n/۷o'++]Err2sʾD3nFD^2`Zjӧ-N1!&&aܳp!MB=0|EZZ}eٲeٓ BBBHLL;i& ʞ={Lͤ$ LFSm*ɵ}lܸA˗sE7o^} SNl߾=jJxO⡇wՕsΕ0Pܹ+WЧO}]:v|NDDD  y9up{屲eNR…Tk5g2jԨrǛ5kFhh(w?87O>$,]///'r?mJ䈎+G'"ADFBBilK,XDDDDDDDD~m~Z0 f_Օ- zApp0qqqU(f„ $%%qZY[nE:զߥKၭ-3%$=zNҭ[7ZliJ,_LǏ;exDZ͍jk|Mu놃AAA$%%矗k6Xy9ɓok)"uȑ#oĉIJJ]v \tK.qAiժ; CDDDDDDDDDD$'eff]at j*HHH`˖-̘1___I5i\@vԯN S~WJ ŋjzC|^rsshӦMe:""""y4 c'RTTDN2d3g!ȼyXnQѤI%* ‡~HAAGD7c0Du<#"""""rR…uIIIfY-ӝ[@(((0ݝcǎ_߲yf?>Ǐqu{1SYms ORBٴ6ښ^7k֬qce.OC_Q%b{nd,m"""""ri޼9Z;H)Q{XLLi;n"11#GZ;iB|}}v"3""""""*%\HBFFťNNNx{{MZZfΝ&״͚*..60YkHII1%={Sy衇pgΜTZnCߩS'~Gӧ5CdggG3΃>Hɱv(""""""""""rK4#F (([nqU>C s53f }QXX#<+`BM4\Ym+,\k׮=V^Tn޼ٳg syg ̙3ܼy^\݆С[lnܸڵk1 7裏Q?cHu}YY>}xnu9|0ϟg٦ѣGKZd>#)**2V;;;\\\2dSNSN0z-h߾=>,3gήNVΎm۶i&>̵kxꩧ /uUCDFFӧqzb52zh6lɓ'6mY'Oёgy("SLL 111CDD營x ?^LϞ=Kxx8{존_~WWW `HEDD~|rΜ9czʕ*[eYfq5SYQQϟ:t۷\o}h"""""""%\HVU2/fն퍷w,m //[mۖ 6[]Qy֭Yt)K.nCߥKBBBj^}^Zn/۷o'++]Err2sھD[`cǎv""HD @ͱn1&|^WWWZhAVx'L}ڧh"""""""p!"RK3uT<ƍiժqFbbbHv"u6i$k "@iiCpe6o̩S((({L6ެ^~~>۶mȑ#\z;2rHfϞqbW˖޽0RRRhٲ%O?4 .l{n NΝ1 ޽SҦMM"""r`РAJe%%%l۶K.akkKϞ=3fL پ};Otؑ{3g7*/oߞ˗/sxuVnV>5F(BDȼyXnQH}5FDi֬CWJ kaH% +WYr%n⥗^W_} .eggCbb' IDAT"888*9s搗7())!((sK (wÃD+Ə_DDD֐cpvez_\\̹s8w׮]3;w.iii.]"""Ti޼y}͜9իW3{lƍǰa۷/֯k?4*III"Y~=SLv8""""""""R;wr9qƍ ""To׮]\p]ӧپ};]t!==;v:~s)f̘ѣG]2=Sݻwe:"[;OdSxi&N>͉'Xt){1EZZ}%&&2`9x`7عs'f⩧w]w]MDDDDDD i WU_5o&ݺu M ׯߟe˖pȑZHnhٲiE_~sΟ?N({fuDk֬ ,`߾}EDrc#::X~g&L@RR) >>\]]GgQ^^^8pO>^{ @jj*k׮ח~MDDDDDD4e999<</_cǎ?Ο?ϣ>%!!www&Mt7C8Z`ԲeK~ax4笈4F/^瓬,oVOS={4vrrsrsshӦMc2c7R"" !> .dժU$$$-[1cjT/33oo IOOQ{wL>"vmxYvm1C """"u ?no߾V1y78~U&Vٳg gϞ=/ʀz"""_y뭷ptt䩧vHUsVD̚5kVJ(--5_TTTi=[[c׼y eu6i\ Bhh&&cTj ///9v_|~-7o&**3~xX*U>|8ׯ_'..gggcvvvm6d1C Ҡbbb(..v"RC{a4 %\?~:+V`„ ٻw/w3LrNeÆ '4 =gE1ԩ?#ӧz]t~ 99ʓL$R]#PӡCˣCfLuDO?Dzz:zv8"rا6ۛ4>Ν; 3%\Cj_޽9s }̓#ڧh"""""""-ԓ3qDk!"0qD_9`ڵk۶m`0{n6mdZ5LHrrr>^|Ecf2ȑ#dff2c zݺu3+dlذ 6Q۵kGnn.>>>p!IMMͬqźLƧUVߟj2M!!!KJs\3}t;FJJJ{ZbѢEFԩSOسg{)?l1C;\HYfҗ藟4ZIII$%%CMRR;vT!GsMYr%2+((W_O?ܼylbbb9s&ڞ3gܸq<>3L̤BΝ;ǻKttE񇅅o6!>"_~%N𠰰F񈈈utR(,,$77>C"ΝΝ;x"\t.\HIII6⡇bU^_ii)W^eݺu<5EuZsVD~СxyyѦMlmmݻ7Y\6mdҤI8;;ccc3SLaǎ899.Z &жm[`Ŋɒ%t=z4Eqo.DT5Fا|||Xr%=vvvѳgOOΪULlllprrӓ;vQx _'<<OOO~мyspuuw|iwSc4vekkkKitؑ>?^z%vŅ ڵ+{&--+VΎ;7oY?0tԉ۷ѣG `lڴ @qq1qqqgvy=z ""Jqݕ})z]]c٩S?~|byh? }wѣEZZ}eٲeٓ BBBHLL]j7N8Glڴ ruܩN666f+EMӒ>9+"MC.] ^۶m 4=*cooҥKYtYyٟ*X ///֭[ʢk׮dee̜9s*|H6yzKc|\c퍷w:99xb/^\eKFWW}1C Ҡ&NĉЁH`L0_oҭ[7LIFG5ׯgٲek9r\E``M???"""_L((( :: .Ʉ 0a8,?PRVꈈHP{zYؽ{7W^5 $$.];v,qqqDmLprr⣏>xPǜ9s*Mƨ\}=gEDqGhDh\\\rt" ưaìTAc4.DDDDjDǵkײvZwywy|UpE+NOck\իu۶mg\ff&@o^״o~Sa=/w###{ޒ-fis_YcooOpp0:SNlܸDDDD~i&""""""rP…H-?ܤK'4[c 5ۯXO4=͚5wN.-ֶ~pwwرc||l޼(ϟ-JKKM};^6ۼyrnjeu""rwvu+Vy}~nܸ֭[ +V 5kЮ];FQiU=?+_;羞"" k̛7u0|ܬMc4{.Dj7.~sYٳg˸2`k&"$Μ9ٳ۷/;v7nnnl۶ѩS'~GӧOt?@rr26'''Rۛ4>Ν; (᢬f͚QZZʵkpttW6+ҡCˣCfLuDDqg<*BFFYӾ/^Lǎٸq#'N --{1Nʎ; aݧg],{9+"|}}v""""rDDDDDDDmj?~IIIU~5E-ׯb &L ]tLJ˗suk'"T[aС[lnܸڵk1 7TRRRy&)))YÇ׸1c`0طo<#Ymڵ\~ .Z뮨oT5JDD7K 2 w}ǭ[z*~!s֩o???z-[,W_k׮;-}~:-}9+""""""""""""""%\  Ð&&22&Ol*2e 999DFFZ12_4W^y:‹/ȰaÈ`֬Yzt֍,f̘;3fŋt֍3fԸBCCy'2dAAAfۥ'K/U٦11dÆ >I&+81u'cYmPDDz,}.XjtޝUV,ZN}ذl25kӧoޞzf͚w^YuZsVDDDDDDDDDDDDDD5JF͘qFifaa!6mۛ!CK/yf())a֭0d|I^y8P?Kڼ39."AAA ?c0Xt˼[<Ӹ3yrUYle-?ypww_$,, MOOg޼y 6QFf(,%??ݻw3h M;w`0{n?""uU6CDFFE6mw޼{,HDD`ccرlݯ_?rƤIuׯ7[uZsVDDDDDDDDDDDDDD5-%7M/**bܹ\tRSS yDڵTsq9]_۬K.ٳ]777:wLvv68;;l2rss ʕ+sYr%nݪvXz*((W_… lbbbHLL$""s̙C^^7n>Ĵ2|Q..ꫯ?~|-H&/J]t!$$zm۶%00*%%%Y\퍷wyyyeQ,],鰲\wE}n___oNVV]v ++d̙S%""%υ<㜜Xx1/n-[f|M|M2KuNKzΊHCp7ݻ!4J~)ӟ~w."r񌈈ȽJ;\HУGN:o @TTiiiۗ׿ˀHLLsM8}4'N0MDٳgm9I%))I+*2jӦ Vڵk\z-]Fppi;wr9qi%Ԉ:[KOYv… tڕN>ҥ ر9?0ԩS̘1G8SNлwr}ˌuDDD sDGGʢqqqߊ4}zΊHC8q"'Nv"ҀbnbϞ=ܸqڡH#4x`}iD47i L:DL K.`ƎK\\cǎpL0 &W6ˠA%::W_}s1e~ߚ|Lu@PPiWeL _~ߟe˖kq͛gvN``_~q,ϟn'pս{w:""Vs[[*gooOpp0:SNlܸVZY9:MYi(AD*)**̙3," `k!"""""""rOS…4 IFx{{WX?==z…Zزe 3flGMڬNM&Ο?;w=zf/^>jq5a)+++ dq'x,;ڸGIIIcnRXGDD"d޼y[}aH#ekkKtt4W)B$2228t...wrrooo8|0;w$,,4m֗>tCZZ,^tSN㏦:j֬\v GGG]:,?eu҅~dl*ONN=$:M^^:t0;?//TGDDDDDDDD'NdĉCDHqq&(Vݝ-[X; i4Fi<47_^ 1bAAA|wܺuWb0;w1c0 ۷By\]]jҦq:]7bbb0`駟TgС[lnܸڵk1 7Ҷ۵k~:.\ 44\=KOY͛7IIIa͚5 >f7<dddkXf#""""""""""Ҕ_EDDDDDDDDD侣.I>}:ǎ#%%cZbѢEZ.ͭVmk׎\|||pqqСCf C'%%Opp0۴hт`L[oŞ={hӦ 񤤤/3k֬Jdlذ 6Q9Bff&3f0;֭[re4CrqRSSŘ .CDDDDDDDD9|ƒܞ=iҤԓ׿|}.''D^!6T9Թ4i:p!VW_j9::ѣGɡuָ1w\zeC-… Zd>#)**ureVZE.]ҥ [zj:t@dd$>}7nЫW/OΨQ*mѢE4oޜx_``Ŋ۶mȑ#\z;2rHfϞޝAm6+.]-={d̘1;,KIjÒp׮Ac8K "d 8yn:ϟ{-CDR&Mv"jرJ C@nn.\rTʕ+u/R #??lb\EEEE̝;4SK.Ajj*4oܬ9s搗7())!((xK (wÃD+Ə_{KAA*.\0eggCbb"888Ԫpvez_\\̹s8w׮]8T7޺[נ1H㥄 i|}}5KDĉ8qo+"T\\{Ν;r }wߥcǎ||DDD:GDDDPQQyTTiiiۗe˖ѳgO222 !11[%&88N:}v"""8z(AAAfI߹SݻwXeNd=`׮]\p];лwoXbرyT:|lڴ @qq1qqqgS[w4iff0̾*x7֭ą?1K<>>\]]GW@uF˖-M~*9}fԨQ4k֬N׷裏hՉ%!!wwJ}DD:>'t 8@jj* mڴ?|||6lX}7QQ8j{>˕+W_:wlv,33?tɬNVVcƌ7 ӟ*>3g/HNN槟~ ]tH!]xeW]yff&OOO/WֳgOk'''JJJ'776mڔ;f,3';;'''`fO<1Tm,\UV@BB[laƌҪU+Sڌdccí[(..ֶ7nUxn]p""""""".DDDDP`` o8|0F2;7|= Kxx88;;{7n`ٲe8q¬7| | {nݺ7xǏߵɄe={pCii)/2 0*񈈈ʞ++Wf?3'Nĉ<3ZO>8qr (**ԩSf MT͛^C;Iff&_|k֬a^ԇwJixii霢JUlyiii+s 5o^~kcYcK/tڕ}1n8k#"XMH.^^^s1 [6oLTTg@Iwj۶-еkr/]dWVu㭻u É4^Jw^Ǝk0Dĉ=s̙3 6~z bZڵk-Ν[n5VXXڵkYn];p ={6#Gcǎ\zx$$$l2>z6?^nMl~:+V`„ ٻw/w%\E իWsa9s&#GSN呐֭[֖~/qSȑ#͎.믿.p'콬R֭СClyz!JJJ?ATT'N ((ӱc:4{YNIOO4 nOd+--ڵk8::կHl 2228ts:t@vv6yyytX^^4=NNNݛ%\Hҥ ? GЫWF{ É4^JU\\̤IHj)Sϖ-[x7裏r L2c4hǎѣ1MNN/uDDDУGӱN:1cNɓΑ0ydSٔ)SOd޼yVNDD*L\\NNNDDDн{wӱɓc„ z#F={^yCbb"EEEfʗMO=}vvvo߾fpss8|0}s̩8"ݻYn!!!<lܸXz!>sڵkGnn.`\t:?bvAPP<#&**O>֭[kԦ19$33nݺ裏MFFFIy:"4`0DɎ; wޡO>f:.w̘1deetRyy~G|g*<3$%%?}YڷoիW9|01>lDDDDDDD/%\H&::aX 1c{aܸq۳o>7oβe̶ /,,d{\UUh8Xjij)"9MM-/cxj_'_H8M`&#IwD$/!K$?|sY{>{^lou7!::ڬkXd 94jԈ:3X]a_g#z2VڰҥK,Y-[p9ZnM0a1+;v`^FŒ%KذaG:[Uf_,k[}W\IBB4nܘ{^xҥK\~___c;3 V\ɨQhѢK#""|w$&&˗СGf̙[ω=lEy>>>DEEwc8YYY̟?M6Ahh(SN5V=p3}FWdoJ>|l{rUBCCi֬lٲ}\o9r8bzs?>۶mI&<L2ƍvZ9r`&NHƍܹEyK,aƌt|赭-eo]W={EY~߳i&rssokm배0֭[… Yp!Rcǎe۶meI&L6cGzz:}ah?//YIq޽{GQZZ'"57flB~~>ƍ3ֶm[4G-o8Njn,E/""Fڑ#G9<ׯҘBCCILL4曤ןb *?rU5SNiӦ ?! >xX}˖-dffٓ'OR\\?_ll,vHMMhG 8oߞW_}궄.]d <εWM>U}~dmAVZ̢Eؽ{7W\{aر׿6M6 WWW6m˗ b7Ql$%%[rY7oN`` &M{q3fwߥw… ٹs'G6˿sN<==ykt."<sz!g#"7H-Z 99m۶q9ZjůkƏϪիq۷/cƌ19Nqssfݺu|OOO~Z>DDDDDDD. :g6lC-,"g֭ƊZ7˳b :̙3СN">>{acu;իW`ZѣG駟f|I31/_ǏӦM^{5:w̡C={6ǎcٲeL<gЦMJ9VYՋkR&wus;`ҥ$%%uV3shMLiYYY`("bN>?:;w̚5xFTőg-U @׮])((СC6\233 -*{V^.+Wd֭ lxbۓdRkk/{ږ>?܋j3_iMKllYz [ӕ}{yy1}tO^i { 0,yDDDtR aĉ%"׹sgր 5T:ImA1hР*ko;Z6lv<Ԇi4BTDD)))CD"*[+L-xNif,M oܹ < bfHIIㄅ1tPj3nwwwf͚s=믿NJJ nnnn @\\ݺu{̜9-[8ѯL舺[S111m}ŋGwZYӔGDDf:00YfYӬ:bccYuF\\SLa֭=[U5SN:wΡC8p _5gϞcǎ~wĉk׮Uyi߾=Ǐgʕ;w~5\\\,^y'**ʬ}T0|8r/=$RƌƍIII1:NGTTpuugϞdgg3eg#""Hm8I.DDDDf9[ֱcnj/ dgg{1n8"""hҤuƐ!CXf ~!cǎSPP\Wރ>3go3gpiC5}uJ}ԋ5ԃI^^^/1>Zha):̬u\7uZ?uwI``>UL'0gwΕ+W_“O>ڵk+=s׿ա:e:m۶,'O7o @XX1ʟip[ۭzz0iԨlצ4WW˦)~""R kߥ}2l0VX'Æ 3uqqOOOLU/5{jՊ".\@V̶]p#""灀szi8p"ϓ BFFl˗ן暭~ڵkP,u񌪎)W'͚5pA͎եK|||!''n5kVتNzz:˗/O>6WҨj`Jy\[{R&Ƒ{Q!ADD '""""""Ұh :/YcOӧOgǎ?R{v //\ gM,Zg:ڲ~-ZK/Č3xw1""zGȑ#Ϝ;w~ &Md}g b͚5sұcG|b[O~ػw6*RZZJnn.o}52p@yHMMogϞİgNJqq1?<ƾ-[`\|Ǐ3zӬ6ȑziS,jcȭ7 //R`ҥ\v\\\ &))l?[o[xʕ+W?~<=zJJJ8qiii5ʬ8rmmK[Ƚ(…ܲcń۷cxzzM;p,^M6ѨQ#^}Z>W(..歷޺@|2gfСl̚546mEF1vXmFnn.QQQfۚ4i´iӌcƌ!>>[twXGqqY1cزe 7l[۶m-̙˗ٱc $$$X]weƺuXp! . $$bߺ-[ry#==ݢ\G}aY\<:Ɋ "##O9y$cǎ4#[ω8~' ϼG}ٳg[".]0bĈ*..QHbO>c\Zl *j=]^z wwwVZˍN*  669rmmK[Ƚ(…8]PPAAAA!##///-[FTTÓO>ɲe!##\g\-?0۶mc֭Mi& IDATڒ9{,>6rHΞ=Krr#o߾ZIRR憗aaa,[lp̙}݇tЁc+U/SLHoѢ >___eȑ,[ ///7&!!zpuuLJP̙C`` _/l7m47XZ2c ڴi͕{ 8f͚sNm;wӘ!ZDDִiS,Y Apwwcǎƀt##[ ϟOBB}nՕ-[ү_?Hƍƛ@hh(2zh/^lQHbOtxjs`App01RՀ {2nnn̘1 Fvhܸ1F|| 66,vΝ;.?>v͒%K׿eמ2o>+8t?ٳիWӣGk6~ _Wٳ233ILLd$%%ϙ3gXbEqV|r?N6mHJJb,];Ʋe,뮻XnYYY7[Z=ѣi߾=k֬!//:z裏صk&M`vZ0a;v0s:eeeйsgMi<"""M6eܹlذB ٰasΥI&ODOgϞ 6}ѲeK/"u{Q!qTYY"~6m"))a8{[O,E+\H +=;;6mČ3hԨlڴ ___cՇ;vPVVÇO׿ŗ_~ \_^۶m`̙t@^~e?I6m >>ڷoܹsCc#$&&0DgDDDDDDn.p! ;< ܹk..\ }ӦMpdӧO L|A5)3??AY~1㵯1ˣi5F|e*{f9s>:t0^{yyp5et֍!Cf>CƎkѺԩYfVckڴ~\ТE |4S"""pv""74WWj2Ix#ܿ00l0'G""utBCCyW)**;tv8"{!--Mm$B\HG~>?[oÇ GCtYlamuYՀ4<yf~gF*oZelEF...vپ};_y,;Z7^;rLf혦4{_DDDDDDDDKIIXjj*ҳgO\]]ٽ{78IDD)))CDP{FDDDDDfҠLVVyyyرGyl%lhٲ%Ǐ7Z4QQ@@Ǐ'!!!Fz^^EޚǩSHOOϯҘ BFFۗ{"_Z@v*-"N|SK޽IMMg#"b8zhLHVS* iCV{SFE.+fɒ%1KsN~g^8qK,aժUvu`ɒ%;l޼Gy8>j9c }]())ӓ$uVΞ=K dҤIs=q͟?;vrEy}:ӧOz kW [Ypayi~!&&=נ#FտI:5oޜ.]JAAmڴ&NHf*=4\)))8; [FYYCU/_f :???Ù5kiii4mȍcǎ|k١or*٫9BFI.DDj1cظq#)))ƀrrt"Rdff:; *M:Pg!RcZUJDիW;;ء.99gi#G䣏>"99ɓ';1:ѹX,"RQCl#%EDDDDDD&Wg "r3hڴ)seÆ RXXȆ ;w.M4qvx"R{!--aT*--|g!R+Эe…lby D޽y_BII .]Ga\vx3yW\?;$((+Wrҥz8S.]ğ'z)oKBB?Y c+O?+J3g}]͛73i$Œ^`y={6c;w2j[(""""""pi ZC1yd,X)S trT"R"""HIIqv""68;ZBDD[Tjj*CgRRRڵ+&LI&q!#_aa!IIIh"Zh#HJJ/`F;vЯ_?>3 (?$${3dȐ- OO#Gtv8""""""""bEBB)))oߞwyDb :Ojj*{aу{a"##i֬˖-3;iE߾}s1LyDDDDa?~6mڐݻYt);v̢SLٽ{7IIIsVXQT壏> 66,v` (ѣ{Fmڴ?f-AFL.DDDDDDDDDDdt>"55///}]7m@||<;v͍3w\222fС|ڵ K.q7onzzQ.n<""""ő6֭[+8t֍Fѽ{wfΜ -[j5XBBBhԨݺu#..,cKt'|o͛o \_8~a⶷m j74d@DDDDGҩS'V^Mvv6 >>C7=wŋhтxpBCCklSG\О2jGu}'㏹;Ͷn߸q#wqYynv>q8+Sg'?o ???zMdd$mw +奦H|~ƶ| ducǎXjɄk.~gz_?-ZX˔f#""" t,̙3Z^pp=zpZ-*}ӦM,*5Weq;ҶTQDDDDDDҀ 1/}vϢEXjeee1;YzO̙3͛7ر;v+QeߪtŽ;8tŀL<<<())!++lW_}eǚV߶)--e޼y[쓟O~~>?x7۷o}{CPV^g0ODD֭ʕ+,^cu啟LJ!CJ^^;w0]\\pu\lڔf#"""R[Fڵk6mb3 LXRMʩ[oÇ GCtm6Sf-ni4BTjj1cX"""8ۭ_|ٳg3tPg֬YѴi SDDNzΛ7͛7Itt4;… dggxb6mDFxWk2vj ߿6ӀH̴pq!ֵv[,Xt7nLTT?8\vÇb vA\\֭uc36X3}tZnMbbbԩSʌ55kְj*vڅ+}1jՊ".\@Vp႑GDBBB裏ٳ?'O$''^z999fm"WiGnnj]vZNUL+%%%ѲeK?nl/--5W_~6pmvHåRgNTS۶m :3h9{,>6rH>#>>1%K ȯȑڍ""""""" VZJjj:DN>?:;w̚5gϚ]bg̙tЁSN޽{ٰa9CcْMLiYYY 2NWDDĪ|~Uӯ~+`D~a>̬Y8s +V`6ˮh?~6mkѹsg:ٳ9v˖-cfu]̝;;K֭[3W~[NvJAA" pѧO\\\$&&CnQQU߳zjxwYr%[n5_P[\Y۷'))T۱g5ϩ#ڰR|̙v>}:ӧO븦ywu۷7ּys"""Xt)irrr8q"͚5鈈X&..ӧOmR{x{{ccKӦM%66,b;k 0fYU+[hтxL.*?o<˲mvHåRkNZe' qm!4(:"VLwfغu+qqqt @f͚ԩSnڴ xΝȨ9~QzLLyDDDS}>MeW딲2ˋ5f֭qqqL2[:Թywޝ3gϳeH^Y)W';w?СC 8gұcGnvZj}Ç9qڵrEU^~eYr%Ν3W:TimڥۡQQQf3e5W9uWVZqq1/_+Fo̘1lܸcJJ ~~~DEE["rٳ'nnn޽aÆ9;qڍ""""""" \Hիzrv"""SNZ`РAVuرJ:6vy?CMtuufJVH}>Haa!7o|7o6WTqu SGrk6¤QFzn״N:puuȑ#\v,dff2rHBΝ:ʯʮCYYQUSCq &L`V"{ϥ6bϩ=ڰR|}}pAAAf3C=ɓY`SL:PHDBBB8qℳjRQDDDDDDр T@@9p={48`ϏSNejՊ".\@V̶]p#""R*X!CArr2}5[믿f >VZvEaaaǓKii)y۷ʫԩ- \LtR]FHH...?d-Է-\-[~z._Ǚ?]< :+W0~x9z(%%%p 5j1;v{iu8rϫ +""" ]ZBDDDɧ~ɓ';vlyǎ˶m%**l[&M6me˖?pHOOO>l߾<)""R^}>~/,yG={|||,ҥ #FƌÖ-[gܸqfڶmkVWS[S̞={ӧㅆw^cS߶8rXn .d…K/;VbJ*M콦=6ԔV%ћ6mʒ%K4hvtؑW_}#'IIIDDD燛^^^l2}g̘A6mpss>qfعsE;wӘmXDD>t瓐@߾}puue˖׏?Ҹqc&$$;=ŋiZhArr2Ç777|}}9r$˖-˫Fj/G{k׮kWWWqwe\S߶8rMСCÃslƌ3HIIaذak׎ƍꊯ/aaadzfzM콦=6ԔKYYYi("##HIIFPXXO??6l.^K~zڴi@AAfĉDGGZY"RRR^!o]=+((h6d3{:mT"##1ڴ{֞"rkm~̐D gDDDDDDn.Ug_~ˀԩS|I֬Y?-[2a„Z-iӦ̝;?5 6H&Mj,{PD{^mX Aжm[>N8AII wq{&::__Z/b,X)SX刈CqjD9;‰'xᇝԡDRSSTE.DDDDо}خDDDQgeX2EDDlqQu&QNn>qM{R]GXjj*?/={8;c8; AӻwoOqqCiMO>\zUԐ=zN:YݶzjfܤnNׯP*;\"""""""R]p!"""RTRSS-#22Hg!""R+^|EonYhV#FбcGzHEfӻwosȭLm. ԩSwN-gggϟof| 999X޽gǎ1 -LEDJ@VViaBYj;vߚ\\tgbooO߾}ͣZ-++)Sp{k\bq.\"""""""RlHuyزe L2ݻwJNDDDеkWپ};,Y+Wh" xwr /ffX:t`#"""RڶmKll,K.Vcqug׮]˵kHII'0-(Jig}ƙ3ghժ֭СCY_R%"""""""A .DDDDDDDDDDV2 fJk;w.[^zL._l:nnnҶm[/^ @tt)Gx{{sN1vXx>qpcBڴic#"""R^|||7.kMd¸\|aÆq58wK̽ZmϞ=̟?G};;;wXK5TN@DDDD* jM'N}E ..wwwF]2ݻw}v{yG4hÆ ѱR[['ZBD*WvL_;99PPP`jKKKӳʠ""""TM8w"ۯ^… 9r$...xyy`"##iРAu)""w}}}9x μ+ӇFq9ly?c=VYWL"b ...>}(ϞoɓtؑTV\ɛoY{6mJFF4mXff)FDDDZSyxxĺur }o߾lxyjՊSNqzmjOIIU%"""""""Q""""Rn4YQ+883vXS۸q83qYlEj. Zp!"""RKݺȣիWE^߿?/"[n5{_YrrrOW^ :UVkGQ9eeeqFz聳)E 6nHVVV;Ut<`„ fƌ+Y{VV}=<]dnGaРA(ŵC^s;SOرc6뿸T,|INAAٱ4 Æ 3;%K۷/ bѢE.5k'Nnl6mژňTstݻwKΝK.̟?]vY{{R3'u888KBB_|E85bȑ'OϥKptt8fl3ƈ%-j,8 @zzz*,,$;;۬D.]w gZǸ8~ڷo_lLJz ~:znݺffv /bj+5;] Xx1۷o'==toŋ_;L^HIIoEDtDDDDDDDviH&/na*|W,Z.]p5VZŐ!Cؼys K쯴_שS˒f,e:w `ڹ(=d\~~K)-z IDATj/[]ch&M1b~g{ =5;?̙3Yb+V`֬Y;Twww_N||SvDDDDDDDv-=DDDDDj '''<==$55;wn:1bD\\\8}4QQQ;MAff&M65;i)My1e{g&,,!CФIszj y簵Օ~$ziOJJИiTyϜ>>fq70nܸ1.] ӧ{%%%b{&? ?ŹȻkZ`<]HKKcʔ)f[h+/"111$''ϛžK+bĉDFFŏM4afm;vd̘1F""""ߟ[; ZE;\T-G{{{ڵkɓYdI6lHPP޸`kk $$s̡e˖ڒ xu4lؐWQY9@`<888p=?UVZLHstt$88ѣG쌭-Ό7*{yަMѡC} b+j{u o߾ԭ[ggg&Nի5\ڵe˖NCDDDDDDDDDV""""TQ <<==,esrr77,1{ooo֮]˙3gL?s IIIL>Rs)팇c„ L0}6jԈs2wrVR;}puuϯĘctQxڶm[dLF_Zz%DVǏg֭NCDq7-)p򬝆zFDDDDDN""""Re&Mė_~IXXiRjXX...X9;)MNNW^ʵ02QFY;b>)={jH zFDDDDDΤ""""U`0Ty$ꚠA,^_4AsR~}+g'"""߿k777Zk """RkkNCDDDDDDD䎦""""RqfΜɊ+5kݻwrV"""Rdffb0ֶsP-!"uԱv "RM H1~xíBȝE .DDDDPmىy{{m4DDDKzG >\? D`lݺi:vvvY; AȝJ .DDDDDDDDDD5jFv"RE4AeffҨQ#k!"@5H͡zFDDDDDdcDDDDDDDDDDDDDzL6qY; ZA;\|Ǔ7jUĉo߾cGa۶m$%%q qqqW^?WW*;""8=zm%"/=MDFIľ}غu+)))\|GGG{1۷om0HHHsW&T"""""""\"<<̒%KԾkT"""""""\gϞZl!"5ިQhݺFv "r!1JNNO?'??ʶw"WXATTLJӪU+ 8~8۷___lBf*WpBF ^^^,XH4hPDuBDDqIJeعs' 6dڴi 4͛I\\W&&&;;;.]Zi}״DDDDDDDj-)kkf4DDDNADDj1TΤ:B @:uLOY.:l޼{{{өS'ݻw{ܹ͛73}J?883vXS۸qذa̜9Sn] bԩNGDAeHDtt4NNNѦMӱ&M0d;v,ь9Ν;[-ߪJDDDDDDvт ?pk!"R0mSS)Hb͚5ڵ/ҬY3 /LÆ MqI=znLP,5kְcӱ]v 6Ç吓ڵk… 4k֌g}iӦo$7oLaa!ƍXlqӧS^=:tPi}geeqFz聳)E 6nȄ ptt,6/9/Ul۶ '-Y&M!00/´xXޞ}kv*.ܸq#$''S^=z)fϞmڍQ5H""""#,,ikNAR >\ DjٺuӐ*ԩS9uꔩ-##p B^r%ׯ7رc;v+W0~xrss1ctHIIaʕۏqO?]b>m۶eҥfm7|CNN{8ֻwoٱc#F(17Yb4j鈈UWsQ_b>}%00Dc>QQQ\vh ɩ\pdff޼y3eDDDDDDDj-)ŨQ5jkhkӂ;9u-[wߥCpBN`0Gtt4lڴ4.44T:ui׮OϏxoË'==اBv5XM%zEǎ9{\媫p...%spyc 00=zpq,Xٳg e̙}ԅF</y] vmZpQJDDDDDD)"""""""""""5`0SRݻsѥKϟ]* aaaDDDo1rHؾ}).&&???ܰm۶,^)((N:n[} d[cDkѢǎ+r¯~婑nݒ YXXhߛ͛7޽{cggGΝMu^YU.;w.[^z/_6/}TM%""""""Rh 1s ڷo_䱈pwwgՙPeyhMo>nJJJ /_ё{ ///{翵{Mҙ3gҥY{n8{l={l,YB\\qqq|L2oooׯoKKKӳSkŰPJDDDDDDт 1y뭷ػwoYr%6m1cfHmh"vioo>Yd ꣤:nɭgYtDݝ={m6=ʪU e֬Y1(I7.?ٳgoy͎w/no66gۊyCDDD_yjcuFzz:;w_,6w5⇛ݺ;+>B;;;E}裏WԄiӦdddIӦM͎effbDDD:fĈDGGL~x衇,b~G֯_-'''-*MLL,W.UU>}*Q""""w9`;Ipp0ϟgرqqyH%%%!!!ꊭ-M4aȐ!ФIINNv妺Mx ϏdINNfׯ6l?~a!8___~_ŋ1 ̘1k|qZZcȑ\v^z@N8Ann.?!22 &2n߾=O~c1FDDDjcts=GNNӦM#<xڵk\|hL˗-b2MHXy;egg3uT6l`4pMFNN齗.]bҤI|sI-Zd6i}:\vL6ol6)ʕ+L6h._L^^?i͎= @K̳o߾$&&Z+g_BuȍEM7/l#=ggglmmqvvfܸqT~Xh<Ӯ];&O̒%KLq 6$((ooo\\\ɉb49sвeKlmm52g5j> ggg 9={~iؿ߿ 2x C:%HYO@@{ƆƍӿW^зo_֭3'Ndf(UE]XJDDDDDD""""Ԗ-[O0 ?6mbJN?>ڵ>|xO^C9bcc1bD^HI8@`` =z,Xg̙3b۶mKPPiBFYo:u-[ҡCRSSYp!'O$$$tu믿ұcG{=5k_ :th5DYʣ}:GD',,sZ;c_B4jԈuayj²GT"""""""v``KXXo9on777lmmi۶-/ ::~N8ܘw6mژňX˼yݻ7vvvt4}>>>fOXy;c|}}ܹ3vvvtŴ#î]L3[___/*t e!WvsҺukիgZqnE{,X\Ƨ֭[3H {|%{MDڤIhѢNGaaacDxW9t萵Sk]ÅH-5{l,YB\\qqq|L2oooׯoKKK(Z'O,K.7Y#""RZx$^w_~ƉF+o3gХKnݺpYSQy5DYʣmvݻ[ٙtiݺuy:;;[+g_D5hЀŋ3aoN```zZ;j*E .DDDD*IƉm/^<<6mJFF4mXff)FDDeAcrrN<"cO?DRR={4'%%1j޼9?3'Ocǎv e!WVjժ9z(O<ѣ#F ::`C=d?~znqv>UŽP&"oook!"W^l޼ׯckkktDD,T烎j*ڡr'""""nذa >srrrxqss̟~}Xb\v> /Pk(k Qָ(ϵX|39v7ҥ =999L6pΝ;G~~>K/qUyvjq|ETq/THEMJJSqÅH-5i$[O<={Y\y7L7n̥KŅ(޽{IIILLM4afm;vd̘1j[UŽP&"""ѩS'6lH\\]tv:""""""""""5v վ-G{{{ڵkɓYd)aÆ퍋 8991`BBB̞r@nݬaR&w[uVk!"rGzgTP^^Gv""""""""w,-B'!W~r Xx1:&L`R~jEDDDfC ?c7_Rf֡MTz"0n!"""""""RŴBDDDDg̙XYfѽ{w+g%"""wsҺuk+KիӦM)V;mr'SENAD NCDnzFDDDDD΢""""Uwjx{{[; kﴱN`ccS-5JmUɝ&22QFY9*s)ÇIP=#"""""rg҂ ´H㭝HMXXTψܩlHM""""""""""""""""""""""""kDDDDjHn4DDDY; KEFFZ;!Ο?χ~H||رcqrr>"""ݝѣGWy~w>ck""` !!yT5iH) juVnj4DD.`9bz믿^z-k1䥗^ʕ+\N8'bڵ8;;WZ\M6QXXȘ1cpssk׮8ѢBDj """""""bmZp!"""R0¬]) ~?N~~~m޽EG\r={Ӷm[9~8}?+WdҥիWYp!#G///,X@dd$ 4(w_"R3tR.\}gtD+%Q """"""""5\ 00X; Rki6*%"5EDDS 0 OL ) u޾b\l2^֭Kn˫;vmܸqlذ`fΜYbcc>|JR5RuR """"""""5>Ldd)Qdd$iiiNCRDFFjϡ;[VV}=<mgУG Xz5^^^Ջ/uVrrrOW^ :UV[du&M_-ݺukصkWƍѣΦ-Z`0ظq#YYYHԤI:tCT4z聗WLJ F=عs'3f`:jŊǭu ŋYt)ӟݻ7 ,(ADDDDDDD""""&,,iN:NARm4D.㭝TlNʩSLmOPP:ʕ+Y~u^^ǎرc\rTnn.3f 55NPP)))\4m4-[/ /@߾}ԩvvvEn| 999X޽gǎ1ļEpww'..iHkݺ5d:wl:̙3gٳ'ZO?eڵf`ƍ\|KϬ,L™3gLm_5W\U """"""""5v;9u-[$((CvZ\]]9y$!!!؄k߲e | b߾}̛7M6Jjj*:u"<<ÇA׮]g% /燓֭㥗^'W^!""l׊366:XSc1FD z"!!|k""U̸X/4k`ȑlذyg}ƙ3ghժ֭СCY_ADDDDDDDRi9pVNADDDDDDe0Ԟݻ5=K.̟?W_}]v1s @vv6aaa:u0rH$Epuum۶,^ÇK?Ç9r|wDDD駟r}UJ'N8֦M3s5~:udtDZ#ѤIbbb3gvvv3`߾}rq+w7v+={0|}Qw믛ŪB .>|HFeTDD\ddS;\':*7~Q?z*ODDD,3pe믱vZ5҉'h߾mCHv"u gVܳgfɒ%ǧ~ʔ)S~4<==<ɓ'oС'O&77֬YÇ~|P)}^t GGGc6c:tKhԨS*Vn] Fpp0gРAԩ1c1FD 666Zl!R˕FzXn?4hؘpqZjœO>IvxG˽XZԭk9mA5:!""""VP;OTWpBF xyy`^jDDD*۶m`Lڻwm_H @RRY񵋋m OOO֮]4i/_& c#**ǗGؼysO> OL>6m @ff1c1FDDDjWWW݉%%%}O-4. b :eUV9rĬ=%%"V5BL`` v""*"")H Uީ93 Wn<4Zn r^ur>#S?;8Fd0L$9\M Rh(JNW㔚?Q2ĮQG514牌fidj)Π9rpP?9O{G"ZAf͚rԩ5xԬYm'"""׭[7K޽ٸ} /pIz-cիW)[ly7o[ԫWcǎ;UDDDDDDDD B߲j*zaTDD۪Ul<.]G}Ď;y&ڵcĉ9ܸwQQQlڴ@jܹɒCDD7oё-[2bʗ/g~[laժU=z[nQ|yڴiðaø{./2eʔ!>>dӧOӵkWXv-iiiѸqc*Vqqqww7H QQQ;___iiiDEEuV.]Di׮䜿cϞ=\v G@@I܍7X`7o|K 8GGGc{K ֭[ǽ{x饗pqq_$..u1h hm.^hT͛TV~2~KnP>'$$_|Aɒ%ٳ'Cʕ+̜9;w@֭?~}: yHٳge_}ׯ_w߹sdt>Ç~z̙3Y~=nbÆ Tܹc,9r$M6>~ҥK,Yyzmo=svؑ>]vѯ_?zڵ 777ڷo_—%JK.DEEѵk/7 vݻwQDEEb \8::Ŝ9sزe ׯ_#,,$V}).4BDDD-]gRreO/6;Xv̙lذVXcݻ={67ȑ#L4sαl2 f˗/`„ t ;;;>̐!Cصk}!..EpaIlϞ=ԪU+y e{""YsZ*ƕ,Yɓ'ߦVZ0ydN8EXx1/^vL>f-[FJJ ueĉTVSNYnqK ;Ν;/5j___~Giܸqv61119sJ*1}tjժÇ4i.\k˩R K,aDDDիX"/&**簶m TԩSyꩧX`l۶0ͮai{#p)]4Ǐg`bn偁{\ƌØ1cС_Y5k֌f͚{qRJĂ 8{,^^^={2d"""pwf͚y|i\g:?q{KҌD{={߶m׮]ͤ<{ۜ:uʤ- -G6:+ijՌ]\\rgMۚ;3?K[y0uTFi n:fϞmwSy4O4jԈo&M:y """"""""ŁVݻ4hj'''*WL/m^ OOO}8tP",,<==(C}?jժeDhʫ0h!8H!/:t`ƍL2s-͛G@@W%J{w9r+W&887|+W+[,ݺu$''k.Zje1{5w>Cكde=0 y1{ H{K|g!}6_}U&{}jyd<~\ڶ^CK[y\4jԈaÆ1k,f͚<)|}})[,u*"SDDDDDDDDlM+\dsƍsl;s gΜa|r̘rܹCjj*7ndƍdzjժ|em#Gkoڵk0; <)Xrʜ3nܸA5Lgj6xwHNN&##@ǎ=׾}sGeҤIW?tܙW'x¸f͚:u* e~mڴW'%%ARR3fLWs2 45kܺuw}???^yc\۶m ѣܽ{K.СC-;~8Go͛77[͛SJRRR8~xmӾ}{f̘alÇ( IDAT&+?7orI"""<~AXӶ2@qicEy{n[!"""""""""b3p!ŀ8y$=?:kGGGj֬ɤIػw/O<;v`NPdI*VСC;w.QQQ6kعs۷oqf"`j֬Ijj*Yf3oHHnݚ͛`veҿ5kƠAHMMv+s22e ?=z$_~ƁPY@=jnCY}DDD BBBٳҬY3BCC9wބc @rHJJ_e˖\AIIIӴiS:vҥKqvvf&V{WW_Fn郏} #Чhժ={4XӶ2 ڵ+:u,.ȣ߸H.ĦN: OOOCJJx;;|_%&&ңG|IV&Lڵk&qvbƍ鉽=iӆEx`>t6n܈?/;7n$===8 'dɒ[oѣ޽;K&Oo[˚رc޸Ey5i{{{lmd< AAAAAA~nΝ@s_~csY_...&-ʴ7۠Ak׮c dN<٢޺u+s׮]o6)/2]\\̞TR7oε^ 9sttܻw>twwϵ-|||2SSSXn˗3LkW^UM6.sҥ_.ֶ׳ ֭߰[5j0UVtvvμ~z/y7zv=3333cbbLΓ<:5lԨQkΝ5ڵq_3gegΜO$G g~Ey9w\fF2;udT-x0wK/~3fL?K/gDDDDDD %˗/ӽ{w=z4Æ 駟,X8S#G4X3f`ĉ|!Cp]o rfΜisjD˖-MRSSyWy&;wwޡF?~0֮]KϞ=IIIbŊ9K/믿N x駟>}ɊG&--A1~xTBFF~-Ç'%%iӦ1o޼[V~ǏsaIKK+pOSzu~ƍ?|s5KAim|VNNNk׎/ǏSF #GpI <;Ê&on殧ύ7yqu} /$&&l$88׺uknܸ Сnnn:u3gРAgX<#RV\iDD[}i#FK.NCDDDDDDDV ?.\`ĉDFFRzui֬| #Gʕ+|Gy'!!)S0n8ϟ۷ի1>>>888ЪU+/_ҥKNVZל9svm۶%>>:uH:um۶̝;[&>>-Zs=g|u޽&xw^:ЦM׮]rA]n޼Irr2SLa̘15lI[.xyy~| /^]vSvmiР_}u7os}gcpa9E=fznݚ;/:u2ԩSYnϟ[S\Y0nAvhҤ =z 112e0x`gX<#"""__NCDDDDDDDDD&…؄yٴiӧO7szMFF;vdƌ&ۿ c_??3߼y777*͛?~<%Jg*Qo۶mcƍf5|eM4ի&+W0|pZnMʕSNonY3N_=y{ex7rSdI&NH```y˥ c6>;CS_|/d9E=fzTP+WGXX6jԈaÆ1k, 6,TEDD?~((d)PY%tOJpߘ#,66>}: NPP111NCDPFDDDDDQU"YsOYr%]2e䈹v`=jQ<@FF紴4\lpu۝->w7-_eѢEt֍ڵks[V{233sn޼ljskϐ}x<-xssqU~ǒy?-[Ã7_MRxVsKDDDDDDDrƍs=?sͳ0;v䳟~~~ycILQ^V\ɘ1c3f +W,¬DDDqWĖVHDDDDDDxӀ _|wyW\]ǎKRR]veҤIym۶,X Ƕd15i҄ۓJ^qF>s f͢D;XޱcG}]ݻgϽ{5k?|[;;;~s= z SA+{iOffqk}ƛSdIڷo牍… k''<+yn 8&XK/KQӧOK/W>}lcPI&m6_Ν;wxb믿Á;w.ƍcر̙3q"""eJ}"[I[' aÆGg^|EéW#..EQdIÍ[>zd~'c…TX#GNBB#F&DEEѸqc6nHݺuyy饗&==~7{qELBM9gmF׮] z8q'}v\]]׿umػwo"""ѣ~!899qQ Ã:\V 4H6mD=x^:ǏgҤI۷@}& իW3e<7nnnO.]w"7y1.]: |5m)<QDD$q5jdX#mǎrܢ[n޼ɓ޽;IvVZKQ)"Zd :ٲo>M.&{lٲag5~~뭷 +ԨQy1p@f̘3L7o΄ L|||j?~<ׇ2e ӦM3)駉G]kךlwrr"&&*U䚿kr:tc %\Vb :vիYz>фboooU.iky饗ɓe.{F}vza,,x2 GG}0n8rSn]>̒%KСC\x{{{i۶-Çsvԉ3fe~w|Iڷoτ U0Ã}1sL֮]?Lzz:>>>tܙ7x'|rԯEnݺb~c޼yٳk׮C~rLemAarGEE1vX|}}?~/s[}"\M`bUVjʪ}4h *9k׮ҥK-m/]4ᄇ$7k_~zP[[?իxA>%|zZ[{nLJ7Yn"AAA: \:JDĖbccӧӐBp5^{5JƲ~ 4ܹsYdszz:\~sC%%%{yINNfܹ(Q5ې!Cr nbܻw"_͍7ϱߟi&u@-"Nf͸s"|2!!!\xXv LݻwԩP؃%224O$""""""(܈<\]]f4jԨ(BdN<۷ PR%N8EYg-NLL4~έ<>>9so>vɄ Xbqe˖Bݺuoeʕ<߿uyQJٳgl۶͸g 1"RT^'|RFE$ŋsEj׮M||<;wW^ ::gMAa[UZ={[o=zO$""""""Ӏ yl5m^zuV_NFFǏ7`̙ <ؖiH.L^y ^z888P~}&N֭[ a&昘V\AILL4@ؼy3booOժU:u*6l(p?~<899gzzjرc_Ofc#"O˖-ٷobf7ooo\]] #115k {P}Xh6G}"GI[' "b+?<ϱΎڴiSɉXرcԬYӤ,CFY999QJ?H"|e^+W$!!f͚ѳgORDD!sN>sz*k׮l򾏟m^/k={뛔7hsأFbڴi$$$Lhh(AAA8;;N> @``8q"s]qppȱ֭[ƸUf|{/_=6C!FDf͚: Ƀ?\ؿQ?]T&/ֲO$""""""Ѐ yl5lؐÇ{_/NŊiٲ%#GYfNSD$W:;veo7͍{3,uΝˊ+̤W^ SL2-[ܹ;wҾ}{MVY<ȃ~@· 2+{աC5kYv-b޼y,[Çӭ[7233<εk^ti._̅ ʱƸаY .Q"܆2sHЬY3RSS_ 3nܸA5Lgen۶-aaa=zwr%>C:t10ӧe۷?K.ݻ\p˗駟/:ԬYSNPfŅ_|ggg[""H-5kܺuw}???^yc\a,ØL2|ܼy'OQzO$""""""p """"Eŋ̞=ݻwsMUF~8q"`:؍7X`7o|K 8иy\_ܒ_˻GEEi&Ο?ժUst%߼7zGƍP1bŊG߾}qwwϷ DDb_ٳ6oތ#-[dĈ/_>GlTTcǎחFTT[nҥK/_v1x`lcϞ=\v G@@I܃ZvZ뇏v+[,̞=5kP^=3{mk7.$r IDAT.Hprr^`ԨQU+/ a֭>}Pm9ʬ=vxx89kذ}پ};III9;;3zh2epev튧'ׯK.l۶>C>tԩ֡Eرd$''7EDDDހؼy3III& d|_1K0%iӦ ||爳<ܴ…H!~:dÆ \zt=jl՝;w:t(/ܹssy5j+P\tYfPNwܹ|駜>}tnܸÇ>}:111/?_57n0G-nܸM ""p9s&ׯ֭[\z 6իWsFFFf|Xڵkk,_~ RSSeܸqø˗ /?$##'N0e5 jiܡChݺumֲeK8p_k`Ȑ!߿[nqV^Mddq"\pBzI B ݛEQvڕ)S3舣#ժUL6Ftt4AAAxzzboomڴaѢE&;///s|ᇼԯ_777J(DFF2uTK:v숫+vʑî]pss3!"""rʱpB:t耻;ԪU3gLNP1K0%=z4ݻwt8::ɓ \oDDDDDDDnZB Ull,NCD侭Z)C,&&3gPR%ONZ8|0&M… &˖-#%%u2qDUƩSg[.]:tVYgdv-k 9s#== 6+ӧO*zٳZjPguVsm̞=ƍs&MĹsXlÆ 3Z*U&,Yɓ'ߦVZ0ydN8EXx1/^vL>f3ƽҸOO<駟=-X۶UTaԩ~Inpqqa„ L0!xK>M+\Hiڴ)yA~~~&ʷm@XX 2iҤݼy3booOժU:u*6l(p4hЀ>(` kk#OLL +W?{$&&nݺ痗cǎ=I<&L?ԫWp>UppqE֘Wںu1v7ooo\]] #115k jia̒%g#33YYӞym Ə7NNNA$YWP@DBŊMVhӓ`f&"""Rt'y8h )4#F`ĈNCDDN:@ L6l#u kmիԩSKfW漣Fbڴi$$$Lhh(AAA8;;[5._ |v2C,gΜɱ|gP~}rýܹs25ksa[-Pϟx{{皣*Tȱ͚̋5mkPZ5{ݻg,S@DԩS9r$}`ݺu̞=~y"kCɛD""""""" BӧObccmen_y|p:vmڴ1J|]6))){uV-Z ..YfO<ٳYr%+Wf͚5@[-_>?/8p 矧\r\xoO>7o/=-XӶR@DDDWNzz: p!"""""""""4 )d}᫯_~yߟ۷Dpp6gggFmlеkW<==Y~}vqq7dȐ!Znݺg!!!cE֥۴iC||<||y[Zh;HNNαzrr2P6EDQlڵkӫW| a֭>}Pm&e `$%%/40qm"##Qm2ydmbI{Zm-~9;;ϒ+"""""""""()aux8s ~~~8رc+Wd̘13+WaV""WbbbKE`` O<%Kחz GGGc鉽=١?vQ}M&OLRJtڕI&q"RDѺukϸz*6DݠAgp bŊbbb$88؆HQS@ӣGza4DçEܽ{:VӦMSQFDDDDDѤ.H("**yΜ9̙3&+;H.\ȅ xWe{f,\aÆ0;+ >"""L)S( SNeȑu1{lm% D?+Wu ""O?O?MBBڵu:"#F0b[!"""""""HӀ ylơ7={p5|||ׯ&qiiiDEEuV.]Di׮6Y"0$..Hprr^`ԨQp=شiϟjժѹsgtbr;v,̟?$&+s;sGƍP1bŊG߾}qwwB<Ə77nΝ;Ç~:}7HҬ~@z_s slglڴnݺYDdT jKJ#>X[{_ xҥ͋CyE- ;CÆ QAAA~z#ߎ; e˖8::ҪU+N ۋ]{4lؐjժUdee;bDEE/€HMM%!!\VxEEۚ'N7'ոqc<"""""""""""""""""""""":p!wy3|9s3g`}grY6mZj ZjeަMi 7 &0k,INNf9W^*m˗Yfc4slo5cccINNۛAUY"""roP޸~lVZ55jD@@/RW_h…\>ÇEhhhg믿im;ŎyDD'>,u""8p 6u"Ubj{EĦ9$UN<z*ӧOgxxxP^=6mW^勈)SNMMe˖- UV8&""""""rorǥ7'\X{'tЁ,X@pp0>(/&66 ~z|}}$889sмysә7o:up}%##)SЫW/x w(((̙3esssӿΝ;GHHHZM6>}ĊӧOyDD7ooy`:L&;2n 2d6tP֬YCDDƍat""""OZ4i;vH5{v;npꫯΑ#Gxر1_7 > ȑ#fȑ={ 2r =|pBBBܹ3۷'((ˇ~~~ݻkh":uĠAxG+}СWaL@`gg^zu׿m)R%loI/dd2qvرcc999,Y>}о}{zͲe>d21bk`2غuEz>}0Llٲ(h'Odܸqtؑnݺ1o޼b+_tٳgӭ[7|||6m999-;;ڵkG:u{ DLL ٕ;߿$[!"唓ܹ3=z`ܹ\t"ϭ ۶mcǎooo^~e,X`OSآEڵ+-*=XgggpB^z%#P\Z_ƍX???ڷoOΝyW/k"""""""&p!w\ };ݝ.]ʾ}v?8#F[nF5k'|Ν;tt֍_WW C=Dll,NAtɘ0i$>cΟ?oda'Nޞ[rUL&ӧO_}[+gϞ,Z={0l0ٳw^8::e0DDJ4h [ R뇿TtttQr %;;薛رcIOO7;wpXt)ݻwg;vjԨ-[믍gc/_ٳ899ѱc3f \v?7ndgg3rH222s6o̯ZZ_}999;CJJ [l+Zh$&&:) ܜ<Ϸ~KTT...y+wYrΟ?OLL YYY̞=j|~!QQQhтѣGz/\| ТE W\^35MJJ [t)}q<=ѣG_ _i…qE6^zGaL<|Nӧ})z=zG*ٙ)S0eʔ2羭ʕ+Ƞ~dddp!ƌc<| 8: ^Mpp0)))$$$Я_?~i=ʡC!??۷cooORR׮]zƂ3J}^֨Q#fΜIݺuYr%رØpj*222hРsˋG2cƌb2*߬YbiIII'"7gϦ@;EN8iݺ5ǎcdddj*?Yl `͚5L2޽{cggѣG3f1ᣨPiҤ K,ڟ*{Xai}N~̙3f͚9y$7}udL&yyy$&&ڵk ꯉܻm;c=f{TT02yL&WYƀA[4i҄3g[@ƼyE߾}v{o.]J}4lؐjժ񲲲;w`ԩhGGGڶm_b:qpsGQ7#"r;oߞ˗/:) ڵk#-[4&|رXvͷ~Kٴi}|ps牢̓-\]]quu-888ЦM>b}?=ѲeKiժSN`@z !QQQ/0`RSSIHH0PMDDDDDDޥ.U$]"l̜97|W^y/^Lmܦݩ6(==aÆ/ؾݚ7nзo_Ν;GXXm۶-E"g-oIm~jhԨKe^Nv'NiӦVƒ \@} IDATqРA?Hݻ'--,j֬O?;vmtHamfgΜ(qGړ'Oq[lZj7/4ܹsqxzz?޸qH駟hٲymڴ)v˗/Pfbi<""C֭^:+֞hVZVپŋ8q"ǎ+XZtt4/wZ~ӟӧy{FF{43Ξ= T7af͚Err2,_#Gok""""""".M yg7n ,`+""wNi֬ǎc޽ٿ?ΝI&wypqq瞳uHVڵ҃tR֮]KAAˋ֭[ Ry\~3fm6_~ݻw{nwάY,V*c[IKl*gm_a՗ԩCV8r/_fΝ<쳸ѦMKNNn77RhlggW9=PM7Y+CD899a2ػw/#Fu8"RsXϟϱchР=hѢI[k׮b BCCK-Օӧ3|p͛[ ooovɆ 8|0˖-cՌ?ꯉ4BZw?CDDJѿΝK|||.֯__˪6u._̢EHLLdժUw턋]vYMz*ӧOgxxx7yڴi|'϶mpqqaԨQtڕu뒙Irr2+V`֭8::2{Ja W{,"ӧٸqYQ=zp!>S~Wc;'|•+W=Я4 4ԩS8p#=--X^wwwΟ?Off&233<"rkal|]^>>>|Aȭ)e}ſGY*w24nLP8uq+Bdd$<3aСC}ЧOٶm~)Ƅ DDDDDDD]ŗO 3LV+={ŋ|2wzKw8²ժUI&Xrn 2d6tP.\@DD #ݡCHLLՕHWԪU^zIZHLLȑ#Q{,"a0߸t}&cyu놽=91CY__[^ 88w}_,oӦM8}tc4sۛcǎKӯ_nUɜ9sHKK#//F/܊Gnn.ǏgڴiFzVVV<,_\kQ~}~,e9r|9¼yԩ2}}b2NNNO<^^^fꯉܻÅCHH;wz ?jժymF\\ǏڵkԮ]___ƍG5[eΝ;#ۗ~K/Dll,7nW_-_|A~~>zf͚.(D+]t?]vqUvԩS+\gsrrXr%[nvڼ⋌5bWIQZzcEeggCvSd2+bԻT7))n݊;v7ޠv򆅅1i$Xbل}v.]Dڵڵ+GŢ?,[$\Bƍ6lzWmUymذaÆѸqcVV-Yx1ׯe˖ϒ@kfy|nLL 9rjժ3ac7փc)#FsN9B``űի3qD㽻;m۶%55M/5駟x'\<ٶm'N`FzϞ= Сv"--fHͻK :vȴiӌ91YE67oΈ#,Қ6mJ@@@VKbb"3f`ƌŮuq:u*ôjժԘy3f qqqߟ >۷sFiq^Æ -*>|8bq2DDDDDDD]BDDD2e pe裏˗/w%55+W牉fҥo̙3呓ѣG;w.QQQF>V V0` _lFIBByf}.]Ă hѢ\Ǝ˧~ٳgܹs3anܸa-o}Ub_Ö-[nK"">7r5HLLdȑVW %;;8q^{5֬Y fԨQ^|Ç_|N<Ɍ3ظqvUwa:w\jWNNNxzz2bf͚eSMDDDDDDޥ.䶊X]RD^g>/1111رɓ'ێ|ʔ);;;=ʘ1c,YnK,d2Gbb"!!!]XӓVZqaXD}Μ9Cfh޼y/˪UȠA̝;///=ju WEիIOO穧bԩxzzriIII!!!胔*h֬YsiIIIƤu{eŴk׎cǎ1m4Ξ=ի7nE&Mn2gq)ׯϜ9sh֬L>'Oi\O?ŋ4oޜsRvm>C֯_Oxx8{nO[U|?3@.\p}U5kԨ3gΤnݺ\pva 0.o==Jruu孷⭷*:~~~K4i&M*ܒⰖ3eLRjއ~V\IFF ##C1f̘w-3i^>77zO?z?̞=K.1~x6n܈}aɒ%^9997XUK/]rsKFF0}tW^,Y9[o7|3d<;7n0sL֮]ˏ?O=FoLD*܇x˝j֬IppcwVԩS\wywyX#<ɓgh_O>ӧ몿&""""""r҄ 4hr%M(^ /4i_.]d߽{7;vM6?76QW\!**SNˀ* ߿?&>>"XS˲sNb)ڶm_|r_-[2f̘buVWps̙3ׯ ֊WU9qpshQ7#""Ucʔ)N-[$((dzcǎb;v ((-[ЪU+Nʟgon\c޽A 64+hʛ/77*y*RHݚM<٨ۀ-v(o==y(c0aTT8:۟gŒs̡I&,[xg}=Ώ4^{rܬy5tb߯ {{ˍ+geҥ+''+VoY_Ԕ)S_j%99d5)NDnȽɾ,"EAA^z}?#<7/2l0 ܹsYv-N,BN0jժ̇~ ڵk|yGؾ}1P1++m۶BϞ=+\~Y~'cPY6mJ=/55ToNӦMqtt_:̙3͕L&2\=y򤑷"UU._ \(s9gU֭[k 37nN(v={H3ܴiRcmUyթSsΕ H}ԭyU}փcy8;;3sL8wΝ#!!3gZ>/"U/%%ÇsUfϞ qppp{qblڴׯDƍYpae.\T}Y|8͍.]X-$wH}mggo2_tui<""R53>j^~~ߎڴiùsضmj1l۶_TE2խ.o==3<øqX`Ǐm۶6J OL03fpU>c;ìY,v;5[l/>>>ѣG֭[ܹsi~Nf~мys"##yYz5F8+S֒%Kx'8q"~]]\\$44~??O'"r/QMDDDDDDޣ.ٿ?qqqCDJ3MndÙ0a{8oJ>}Xr%}Ç'++bΎ 6-:Ѡ"嗦A8p"=--\<䓼+la\mѼ3FWJJEԗy寿j^}",v̜f#""eY_ԑ#G,0v(V곰mEȃߟ pBjpD']E?p}ǎ?Y9?M4xwX=zhYz)ZjOX`lٲ~~`rrrJ=OD^ȽE;\mOTTe: y@۷SN1{l#=++Zjѷo_2222e z'7`"YÆ i׮)))lٲmҤIJ_^xe˖ٳiٲ%'N߯P=klݺ ˜4iqK.DFFɓy'իYj&+Vܸ|2ߟsRfvvvp6l@ӦM9s'ѣгg2%22`̙CIOOg޼ytۡCbbbX`<,^X4hV7_Vx饗/5jG[nsEk\z^x֭[W>RUzP{,"""wtr_b_kN+ge*\yw2d={$>>+WDPP;vl#"""""""""R4BDDD.Kbb"3f`ƌŎ?~Npp0!!!&xIIIa 0%00m۶q FmXμ{38o=bvɑ#G 8zL8x_eݺu,ZE~5`ƍtЁ]vVwb2LEDdjbĈi͛7ge;|poΙ3g9rű Zlݺ#G/[}׍oG[U>@PPׯ_믿&44.X]taVϟwΎ]VY|)k$''xM鉝˗/';;VZѪU+rEDDDDDDDDDn[!P8qbLa 4N&" ::frP{&UeŊ\xׯ@FFc̘15Ύ(& '>M[}=wkC~ԿEGGW' c*|eߡC,L&Cխ7Ǐ/g5ػw/mڴ8+SV-ݻ7ͳzͺur5jď?'|R.}aÆ V-[PN>}1šGyoٳg~z222puus̞=~LY|7%^>"((3gpuƌ#1<˼Uv?"<-&"""""""ri…HڵkW2}t ~~~L68d"""r8;;3sL|M^yXxq&DDD=hEX,*鳩|*͍??V4eEDDfptt,v!C0dȐb9#GZOTTv4Bld2X~ ,<:t(k֬!""q0:]yƍǂ ?~]B&\_eԨQOFǍ2vXӍsNZZK.޾IJ+rrr)vLJlBoDDDDDDDDD_QQQ<%r& aHC$''o:?QQQCDPFDDPx IDATDDD~U(qXTT?#<<}fիIOO穧"::K֭III!!!\455x@f͊]ۜf#""""""""""" lm'i0DDDDDDDDDDnv;d2+chٲ%m۶eڴiyn @pp0I&̜9~H~J,ĉ4jԨرƍ[xxx:[ @:}4mڴHo۶mgΜO>VuR˺|25k,v̜f#""wR'׉HՊa*..!=xyј+rna$''͠A$^T?c͉'hڴiUtn**77^x,\]]ټy3NNNeuTSDDDDDDb4BŠnmggWf\Rq53Y+WDDyyyADD'>>aQdҥ][uh""""zٵkM{ܹ,عs'=zqT8MR ?Ç`>|X^N>ƍ+;ϟ'33wwwcF;EEEe0DDDeMz«W2}t `}#""wŋw^[!"R7x;: []Dnkl… 2H:t(k֬!""q0:)oqsswe޽u:<@}Nʲu"@ƍ͈#W_w#Fq9r@}YzɪU^:'N4򺹹7Wݻ7:t --صi:u{~lH8s挭qqqj{EĦ9t9s ڵ}Ү];m;v,x{{/`rrrJ,d2=.]ٳ֭>>>L65]vԩSH0LĐ][)},YB>}h߾={fٲey s~8@׮];vEz~~>ϧstX /33SұcGt{ǯZb<'Odܸqtؑnݺ1o<^Z{/,!!7n/ /7HHH(a-N/2c vJ d˖-'9EDDDDDD*O;\b9gggXt)wʕ+4i҄@f̘Ņpc.\?L۶m;v,?wҤI|ǜ?xֳgO-ZĞ={6lE{ŅݻߙJ'**a!T(m< uR6ldoȑ#l8v222xgiР˗/gʕ?={vfȑdddi7ohW_Oc>>>e_[\z/ҠA["H%77cǒn;wpXt)%XCCCζ0|֭[gF35KyJ1cƐis *{AA_|(_>}aƍ5B~WFO?d?~SVn.R^V"## 駟o>MJJYfŎyDDEÇgCDXeդSOu֤;7^\/55x_ kҤ III&fcIJJb޽zhԨ֭#))#Gcǎ ߻ٷ~ٳg' ///Ξ=[駟WDܓ""""""" @ܹ3&deeq 1k,cEU>|8=QQQxxxXe<(L&ūt___jժ֭[ ??[RN:w Ҽys6mG}|+WΝ;:u*-ZёmX'N7ոqc<"""mP>֭[ 4i̙3M\-Ie ɩX)Sx'prr2vļ~:SNQFTVW^y4'OaÆTV.++ұ'`w0۷/6l(3%hٲ{6mZI}N{U)55^zBBB,+TgggfΜɛoi}sREQ񳧧񳳳sV\>HUn`2n~/… 2H:t(.\ ""†ΡCHLLՕHWԪU^zIZHLL4&UƓO>ɇ~?37n,L& NRHҿ~7FAnnnGnn.ǏgڴiFzVVVywk^ŎӴ"ڷo޽{m"}.]߸t}&cy;#9sRm?cO^}4jԈt~r߽{w͛GZZ=zyU !!~ؼy3?c >Hi ;$44lc^nn.cǎO?ٳq9Ù0a7n0]t)8s yyypQΝKTT"״櫯"''"rrrزeKՈȭSmÇܹs:vظq#׮]#++DFYͮ\kƚ5kC~~>ϟ'::QFS1cƐµk?'44BnbE[W˗ʕ+W!$$B1WyQHޓju1ϯwy=z쌓-Z`޼yƀĵkז+'''0`nnn899ѽ{wٳ'5j`Ϟ=Ŏٳcc{Uǎ֭/_u("Q\\\puuחH&MDqpp 77m{^^6mՕ^zԬYM6Wf΄ѧO}Qz!={6@vTSDDDDDDÅVDGG: B&M7 Yz5Mpp0)))$$$֭[%K0L员HHHk׮% B,i줤$5kV,~sZRRM$""R1w(5… ŎݻŋӮ޽UUHe/eSЎڌt̔f΄ұ3g-5/d(G I3o$ݞͣ.T}g#eھ}bccpBIRll\\\hp:ԧ@-訬,뒤޽{Wk|z('L%Ie?s9sW_UZZҴvZM:U6r%IGu-f@})TX_#۴isܹs…Qu^$I?S.oO=Tv?:]t1$IuV{IմݹsԩS*\ }@}qppвe4{lM4IuVYKh~飏>ʕ+r˜˝n @Pp:fjU]={OM7}[Hw?9O?շ~w}W6m̙35v*o,VVV$kkke6Sٻwo;wN{rٳܿҳc [PښGJufnyUVԩSСyuE=zиq_\\l>#UU ԧ>}(88XW$͜9Snnn@}3Rg 6mZRAAqJ*9buUi9;;ֵkWIRVVE^S A}|ꩧ4rHhڴi?O)77W6mK/k׮S^,kPQQ;pI҈#*wipHZb$iРA?w믿*##Cs?ۗ[z7Raa233fn|$1l٢k׮ٳZr][9Fд1AL+==]%kܹד'OVxxV\i`}Weκtƌ#m۶M PJJ222,ȐTqPS;R]T믿/PDD""", 2DK,)3<)Sh{'4~1ݻWٚ:uje;vh;gḓ^ U9Ҏ;tR-]byff<==奏?Xo|MI]_9Fд1$wwr 1ӧ]yi޼yJJJT8r䈎9Ru-FNNN҆ J#7:p)븸8##(gqift !2ۯ]%KW...nd988gL@2ydm߾]Zp7\\\hp:g#a`Wh>=JKKftl IDAT15 .`8F,[LLΟ? &&Nx(88tA˖-ٳ5i$I֭[f~h% BEnk.;wNҥF]bTEEEi׿|Po5m4ٕQ:S~~Էo_iܧm۶rwwWBB&MVZ 4y}QppV^-I9s N` >}*,,4/P=k֬Q\\1R\\lt@-7_߸qC'NЉ'tUT_aatIss)::ZuyvܩyzzZ,Çk.;@yot y8_Ǐ駟6:pWll1H0QpH%Iou رC+WTbbK۴iN<={*$$D]tQVVuamݺU>>>:rl*I޽EVS[jj*h#z衇J ;Ss-Zʕ+ٳg%___Vݻ%Ij׮$Gղe;vǧ}Z]vH5Vc~ WWWT*֦޿IIIJKKt`pܸq PpzWK"Ç߯O?T~}]mڴI3gرcԯ]rVVV$kkke6S@݋S\\1h2`t u駟6: ZzVXat?RRRهµkjΜ9cDkruuU^ H 0 qrruIٳG|"""̅⢬,m۶M...UҺuk*//O[.,//Pf͚%c]@HJJ2: GUfܾ4,ZH:t̙3R#)))FG(S}W\\ߊ֭[{5VXSڵkZd|}}nj0%''>c 7րѣG+''G-~;=?!Ir!ChÆ … _~ѦM]֭t{beggcǎ]*77WYYYYYY>ׯ_?b(((ЀK/)<<8P<$}'%3geex@f֭[w k„ 涉'*>>^111 60>Yh&O,IZr+44TV~SLQΝ@O#FЇ~({{{͝;Y0F%I0`$)##"mРAsEZr^u޽8P5oVXk׮Uohȑ?]rRFkyUUM_٣ yyy3^|{+!!A}U6m}ڶm+www%$$(??poa !L9:f5kLIII:{$C4hȢ*_ղeK)((H= ;(77ֈ#ozJd=p5lذ:;)..4 0: /jϞ=4i?m D||zOS*''[<.I ɓ'mΝStt222i.((Ku֏P~~~%iժUͯ}o^_~]۷o^y Ì3g^oͺuy$֚5k$ɢʕ+z%)77Wqqq:|բE M]_Ee1T]VQQQ%]|Y˗//7Ν;UPP OOOe:|vڥcVe\I*Koooy{{usrrҼy4o޼ >\Ç/ֲeK+**J999j߾$)''GǏ׌3,ԎYfPc3:P)IIIFG@n:iҤIڹs]h{͵k״xbM2E{}QE:q№.]jwӦM:yz쩐uEYYY ÇuVȑ#Y[裏*::Zvvv%322N:iƍZnV\)WWWm޼Ym۶|/yԩ-[~XQQQ־}.-[ӧO/ѶqF={V۷ןgu]'OԒ%KtmذAT1TK-ZQFJ'NЌ3ts޿ݻ[-55 h"(ɓ'k튍… %IrqqQ``ׯ)PI믿ŋ uXVVVFꍽV\)//z%I!!!ѣ$M/ٳKݽ{$)<<\ڵte˖G;vpX-?.I׺u믿*$$D:u$M4Iׯ7\Q cǎnϺ˗/ڱ)33S+1߾}$Iz'%IO=BBB/k޽M]_Ee1T*..֩Sg~7|# 9}$Ν;h(@U5USV-[ٳgkҤI[j͚578uO>Zj,XgyFFGBYx233'7VVV8qbm{?$7)klIgh(˙3g*QMֵkW-Z0ܥKӝ999Inݺenyիo($$D/_$)''G;?l禮eyB8F^ .hܹ:uŲ K.]$jbQp4`}QppV^-I9s N@ݚ5kltԡmjrC6o򱁻=~~y3*4o޼vkk Q[[[eSc-[jСz4fEEE .sgGiM]_˚nQIuUt)uA\S=b sJbb߿#FP-t8p@6lXa*nH I5V$''K7FРnf۶mх ltֽJII'|Rmu?jϺu-[}hƌ6m:r?f@ׯ ???N VPPEjٲ~ŋZ|uftU4ydm۶DASll\\\h`2@}kft4^fҬYH-_\GF⡇/"kkƉC|riFGPEZlfϞI&Inݪ5ktDL@@⌎)̝;W|&L4xl$(@ck*22RNNNFP }QppV^-I9s No\NږbUqqqڲe1&VݻϟwyHP [nzot (@󓟟1nܸAtY4tP;HP_|m۶i׮]1:jypOUPPM8`V\\ hȑ6lqPCpԢӧOk׮e.KJJRZZ$Cƍh4*JMMĉu5km/ƳҺuԺuk3PKϟ9rbٱcDkruuU^ H AIII:|0zW\\nܸQoPd#>$%%k׮iɒ%$i̘1 Srr3&Fnԭ[7c/4`F h@\pTALLΟ? &&Nx(88t+,,ѣF fҬYШQp&֭[Z~vڥsV]tѣSoAA{n_҃>6m$;>r󕐐}M6>m۶4i$jժajժz쩯 gt P(@7_߸qC'NЉ'tUH=RPPNcIo-wwwݸqC;vʕ+h.شiN<={*$$D]tQVVuamݺU>>>:rH-LRSS%Iݻw`jKMM4y І tubݼyS͚sO~~~@I7nܠꈻ{?wk -Z$*))I#Gh֭~w$U666zGl2IҎ;*ӧ%I:uXֹs}@툋ӥK*uQ޽{ڵkFG@` 4Isѫ4iڵ:uK-I.s;gΜp?9ZXfjʕ+Zx'H{L?itம_EiȐ!rpp0:N;rH?}vZjTT3ԕkRR$.7n\}FPpzWˤNÇ߯O?T~}]mڴI3gرc%ݞ"W\p&d26nP{+///EFFёPꫯ4o<w .^3:ϟ{e;vLJLLTqqƏ/WWWˀ- .d999[:y٣>@ eeei۶mrqq>Zn\u%3p@Z`  777#^x_2:pWZr.\vP)))FG(S}4k״d3FaaaJNNg{4a&`rwwG}=ruu$ښ 2DLݼyS/^[o%wwwf6Wʲ`jkhS,ZHԄ otT^z%cwdZ`Qzk„ 涉'󊉉10u 4I'O$\RV*I%F2e:wt_~1b>CkܹΒn1j(IҀ$ILm #iѦMteq4"銉k-ZJ.^˗gTPPPf߂V5j(*,,4qww/+=zTC5zgj/**ҪU4x` :T֭$)$$DԐ!C+ի1>s挂5p@=Zb]Vc|9r<<<+""BW\"I{QPPV^m~/w]󕐐}M6>m۶(r4:͌11cԬY3%%%ٳ:hРAb IrttTtt}۷OϟW˖-榠 =c ,;C\m#FЛo^(rtt԰ahz\\\qF=s=zXxht*ԩScn-ƗBɓs)::Zu;Vgx_VZ?W한l׵}vY[[W^<̘1Cyyy6oެ[nWʕ+z%)77Wqqq:|-xj]VQQQ%]|Y˗//7Ν;UPP OOOe:|vڥcV1,ooomڴI_~YZ*IӶm_k޽Zzub I>|>S}ڹs$e˖K|qǏ+00{Õ#G@#vZEGG(U*''G:t|Ci,nڴI'OTϞ=ZIIIի>[J*9ޑ#G̯+}QZ<👑x}(88XW$͜9SnnnT/P}f ̈́P˚A7o^fu(g+++5=긳ࣴ>/VҩSԡC=3ҥzq5|S[Y{h{&otqQ{JEX;t蠳gѣ4gddXuqqQVVm&*Fڵӏ?Ǐ_~Ǐ]$Irvv$={ּ"Ijݺrss֭[Xg@cR!\|Y7nH*瞓$ѣ***w}^{͢!C$I͛7uE[rwwWPPiFjev///IAzz+VH Tu!*33Saaa˗/K*vUe=S3\޽{5k, tN:'x8h\"GGGcX``٣ӧOk#FX<@?e߿_ ,^s5vvv֥K4fh۶mUZ'O޽{SXֱcG;vhҥZtLyzzy] eddͭzRh hrGsg}ftᩧR-t!ۻw:tFG1;;;_^rvv P\\\dcc#'''yyyiÆ %f1X`ڷo/Vy.jJ1117nڴi#iF'NԆ TGR?O>|dgg=zhŊ"DIe_#FE:pv8 GGG 6ΏdU<%Xdki˖-t=^Ν;uq :T<򈢢&֭[ӧ\\\cy?@}Xneo^#͘1CӦM38qJ?~"4͌ƍ7n1,rwwW``v%#͛&lÆ Ƞɓ}vj…n(00t>k񊍍Uqq14?GGG+55UFA)K.MЕ+W3f'0:`888hٲeںuΝ;si֭Zl퍎@c ԙ5k諯2:Ԫ$#E{ի5g=3|Xvرckh5k8[s7#5I-ZPϞ=u! .PN8}*%%E3:N3#1@1(4B\A$-ZHFN83f~~rrrԡC/N8KZl*}t9rĢSNZl~aEEE)::ZShhh,ZGUtt씗mذ̂AIRSS%)Mm\jU@@⌎r*SNҘ1c4tP?HMҀtAc?~ߨo߾FG@D]y ۏ9/R:u>3o$IW\1ݿ$)$$D=z$iŚ={vVoM,\P;vtah]|RNt}W7n|}jٲ$IOtOi;w.dkkCi~_֌3OG1:R{Oׯ_qHl߾]wVJJ 4h.\ܹsu)e'IғO>YO޽-֫J;5EEtbIt֭Jk*0 Tbbbbb驃͛߿5K$IZ؞'???cJڲeIWVjj&LNB0` uQyzz@QQ,XcjFǩ7ϟ_W>|X7nܐ^~ecUӧյkW+{NIIIJKKthlܸqP(@+E ZjN::gQ.]ԣG/LwaH2#ToMښҺo<;v┑H dF1U5y抏6oެ'IyGԶm[}W\V]VFGWaaa:z  LSuWJJJOfcǎ)22R*..^zhL#~DGGYtY"5kL:tٳg-F5ȰfU6$&MG}D\m@m6]*==]br)͇5%VI36 ÜRirȤLEg]oWAW.qݮ^p]~_Xm۶pssC\\JKKU4.HRRR.GFFFׇ֮]3fvGxx8F c iSO҂ `kk  xʘ#7h 2N> SSS 8&""zݼyzacc… (++Cee%rrrj*g|GqF`ԩ8tnݺjȑ#2e ?ǠAA m qH^UUUy&~ 6 4iܕ6 c>qD &&JVTT 66Uk'"""""҂h2ݻiӦaΝy&jjjPXXXL>]PWXXJKKu2`֭HHH~Çؿ?֯_/ꫯpB޽{b qqq UvVUUa̙ؾ};nܸj 22sEmm-`ѢEºuPXX(,,Dhh(xb}:teeepwwswwGYY>!""""""CW)cffyA&&&Xh-Z$.o0*e QDQ鞞Tڷo;J噘χ- ??JBDDL:/_ƛo~-[ԩ,Y#Fw8y$lق>@C?[q o{Eݥ[j`兓'O" 7oP===XYY᭷[o bݺuǥK```~盶mbРA8poooe{ܽ{CE۶mbDDDDDDDGJJC;v˗akkUVsҥK(̚5K;"22RYYYعs'ڷo;v`˖- #{m۷oGxx8N:%۹s' ---dff_pNQ l8;;cŰG^^BBBpY۷#FVXYfaٲeزe"Ǻu`nn03g:w,ӿ$̙35jfp g@YY7x8<'OF۶m#Z5D^^f̘;;;>>>Ζ[^KK둯RRR0f?>h"O>?#u]iɓakk }}}bʔ)믿n;w,,,关gʭ_a̙pppZl WWWXwޕ[GؔQ]t 6m:$3آ>WWW߿zzzزe .^(x7$_~KEq=s֮] c ~>}uՅ%'NclL0VVVׇ Ƭ|cz kdśG/)sRO4 K/?\i[Րc#1!//011a7ytq@PPv ===tM\رc2u|}}e[LK'WŋѾ}{:zN¹sХKXG:::ر#˾kFjj*MǏ믿uuA =#"5~suu_&LjjjMII<<<7n7n<<<)FK<u٬yʿN2/CCCa2u䕭222*%-۽{w޽{b3fK6h[+**ӧO R?`dd$Oȑ# +99Y044/RuΞ=+):t [}?X ̝;AW_ ,XAq;nUsSY\Oi~k֭aرJ())\\\nX?>,)|ޘˆ5󶢢B˗/˴)p%AKKKhժPYYsR^nڵkQ59ߏ7N ~'"""R8GaQ3אWիW/UJ\]]^zԯ E^ IqmWnuɋ>Ee*O|ee0n8U3fmGr=WWWgϞJg'5O\`eexxx>²5k֯_cpqqywѣQZZy᯿Byy90}tTUURAy[n_rxfΜ+W N 110tmx Y 1~xcBee%0|pܿcǎEaa6o#11lj'`oo*^ZyPZZ{PVVǏK.z*VXj;z(`ȑ ڿǏ ?޽ ooo΅ PYYTܾw!sު[? 22Rn{&LZIyn߾-sƍCNN*++*l[ոul8_Dqq16lADDDD ӦM/t(DDjS[[0OÿVhºu]v`@@=+iHV4e+QFvP294D5$y)͗HJJtuuG}$(wnAs $LLLBqq>Yx@ׯ̌l<'wg9sLǎ-[J666j-Z"us@077d\O"nUb4ϙGV6ڷo/j_% E4f[N~jgϞrj uު,q IDAT&yyO / _MM`kk+Ν;'zIyVC )[]]-Kn[q_-Ӧ~'"""z2.]* t钦CP u='oUQF BrrT* #GTZ_{\]];wi.]UWW+m!}9RpuunܸDXX*L8Qpuu6l~* L{*; ꟞=HDDDDDӧO>|XaŘ0ajjj0h ]V*_~̚5KA+WĴr ["ȑ#@ʴpB֟={L믿())Jo׮`Ȑ!-999A-s$?$߿R=yYUOQ!RiWB( ŋ јV?U=_GΝqu:tH*СCχ3GrLdtuuOq=qx7qơL4kIIIؼyàgW^yqqq۷/ $$AFFxMwO-$TUU!''K,%$C\vM BNN4@mmT!$vvv:u*ك*VWcG_xTO]qU4UI2HHHHҥK kkk  ߘxիoƜJɓRϒ?ٳ#PG\{$ʈALL n޼9sh:f-55AAA1=ЦMɚ>fffWuIVTh%7FFZ-733xɊ 1eٳGjQQQ5jt˗/-s +!)/q4&nU9* ,k.^^^Xz59۷ogcx)ҲeKM;9oUS&ۉ'BGGϫ۷o#!!*sRK֭[+θ8c Ν;5Nbq4"ΝCtt4>h:& ۶mرcaeeXYYa„ RyU裏 ### k׮Ō3<,X[[[-ӧajj6n'Fj:jbcc0)311AII ޽AQEѥK}޽{ wHIICУGG?kaذaݻwQ\\VZԹ{:xwq5=zHLLğK.aܹطock8p Ν;ݻw5D||<]n ҒJP[܀jYUOQʼn'(=_"66>>>_~cƌA`iiΝ;m1CRݻrtWʳoy4q`矱c̟?;v@uu5mۊeyNcffbۯhjʿDDDDc͘0ai^y"11Q\>Awww=Z4)))r[h@6㦛!$$DnYɠ 􄧧gbNe֬Y5kȤ:CU |q|ߟ$=c89s`Ĉ4_o7^EEƏ2\^^^ #==YYY2ʌ?~)+̛7O{EIIqY }:֭[[b̙pvvʿ>wOOO|ԩ7(ڨEYYė.]R[u5d?JṢ>ZZZ2.X9r$,Y~"""d򲲲:i:B7eee ۾~:֯_mmm,X@L4h`ݺu2MbzKi ѡChii… 2yVPgl9~/",XJ 2D䌌 ܽ{7ofϞ~0`#UpY###x!=/{_ׅ-ZzK߄rرcŒ3}}}AWWWHKKk׮½{˟)?X(,,߿/=zTprr˗/sR ¦MK. BYY)[NhӦ@XlT[033Ç.\ TVV .\.WJիRE Ν; ݻ'TWW  A˜1cHl9~ 555»+???ȑ#?#TWW Œ3~W-,,[fHbvppN>- ¼yCCCŭ~A}P]]-TVV*ܟOQ^]]-ܸqCطo)'O>  BMM%L8QX=2쏒V 5J .`bbpw^]mc~y[@"jx!U߿`ddpӗ_~)UUO rze^z%}A/a޽2urqqйsg1cFsI W[܍}Ux^ʋi3u255ۯKߧݻw7(Du_VWM߿|֕$׹sdʨ$lRn;v[q);6O8~'"""桨HۧP*((tjǿ爚6O$"""""jADDDD 2Cv-Z`8|0}.]R???z聟~ n~޶m ^P/9.,--`6{۷oǫ c駟rJ,]e˖טtL4Iݻwcccc= |T{V۞={_عɔQ9(sΈĉil\ʎMS """"jZjj:jڶmAt<bbb~&"z6&z^{R<[8~ágХKGGG\xQ=9B[Q9']M@)/^DN:u ?PRR333+9r[2kkJJcNHNNpױcj8""""jnڷo͛7k: jŒQ^^?/L֭[3QwM 4[lAϞ=55\si8yJ,[ GJq):u Ċ+־4lڴ v 7nꫯj:4""""z'Nq~zr n݊3fh8R""""""嬬`cc & -- -[tHD "66Va5[pAϥ'OM_f = SSSL>G6mP\\dlٲGV\r,]G5`ȑXd ;i8B""""z^lذo[okii!44}}@KK QQQ֭k.MDDϸ9s`ĈYtDnnnpsstHOOǁ`nn(:::hժ (j @FFC~bmۆ[nabڄ p-l۶M;w.:w ###^믿b…Abt8DFVVjjj45C\ႚ7nDbb"aooI&aW(++CDD9۷oo6O}}}!y0i$tAn,Z/6n܈{k׮R9s8ro`Μ9TwDZcPTTKKK3f̀L;qqq CFF 0`̝;W\8|0 {{{ >\jR^޶m[!..'NFDDDD6/>SMADDDDD … 1oABB@zz:ann|cwM˗/iٳg ccc:(..Q[[ Mc|uu5233p!]&.www={ƨQ=DDDDDDDDDDDV\'N`ܸq8w8ynCoooh: "+w'"""""CDM@LL _DFF")) R+/HDGG#;;Έox8{,@z۷JcznݒKLLƍHƍVw};v˗akk+nwDDlll(:۷Ǟ={p?.ٳ_ )) N¢Ev˝9sйsg>$i2DDDDDDDDDDD:]]]Ƣ+t(.]¦M-[j:""""""""j8:777tɀ tzzzpqq%Kd=r $$Aǎ 8pҸ<ɡdOyˀ.ZC׮]%|hyݭ[7qecǎ  Y3JJJ|Ɋ111ǿѣG#%%E/^pG}:t*CDDDDDDDDDDDӡCCӡ===鉞={ĉqy|嗈ٳ1j(bk_tDDDoooM@DDDD6GYY75o1dMCMqIN(//1w\lڴ Zה4lڴ v 7n gpAMZvp%?^beZ[[#// VQFضmz 2'v1bL~FFL'iii_|QXlllpUGbzzz:4j+_xyy 8z(oߎ0qE֭QXXbnZ~qqX̙#D"""jڔHDDDDٳ'>}h:z DMBMɓ'֖dІ i&۷|MpQ^^Kb}#Gbɒ%`dd4K==!]YYYAff&֮]+S_~ (**777̜9S,+YڵkbZn0tPa鈍͛7QSSBDGGCyy9,w65kֈq!$$0h }׷o_@HH222PSS q{Wݻw /H!YV7//O I,KDDDDDDDDDDDN:t 5 =%θ~:5 =GЪU+̙3p G۶mí[0~x1m„ umۦȈpAM~g\zSLQZvʔ)8q222+ghhy扟-,,p9HHHpFee%~!,,L~aҥrchժL]tqw]'OƱcp5Iɤ5ɓPJ幸=<>>Xh233O?fӣ QQQI>Oׯi999r毪̙3- 22YYYشi8@Q[[FRq0W_}2CII V\p}/6n>|T޽{0m4^$X={066V}C~~Xղ=;t.Ӿ;Ξ=ÇcԨQJ Qsj ˖-J+((XZZJ# J􄧧>}(XH-gܷA'-Z@`` ht///xyy)mވ@~~>lmmHOO̅@"""""""""""R///lذ~#w!&&ׯ_ V^Ν;#33K,[FGG#;;Xx1푗={È#ohӦ """Ǐ.fǎ)NpsN 6 ZZZ̄?N> }+[4R+fHxyyaƌRi;v˗akkUVsҥK(̚5K}Gvzj8::"33S~deΝ;˴/I;s \sM D֧Oa())Amm-\+Vwɓ'm۶Ryswwʕ++]%i:& tzzzpqq%Kd9rGGGcǎ8p@N`` ``` XRRXmԩS8wt邃?'| 4Errr)!ovM\Aرcܾ'N/^ '''}jٞ]x2uA +\P6d޽ ʳ5'ۇ7Pѳ֭[2dZl_~ׯ_Lj#`eeͫŋԩS;>>={bرO34""""""… q1?077tHD􌐷dV^^I\\\d\v Õ͕IK~jkkMC͛?C r}U2߿~ 6lŋQRRѣGݺu/7nܐi]~еkWm<Ν;3334I""""""\P&r ЦM ӧOCl\]]1k,_0{l[899I}vvvXLMqIVﴴ4lڴ v 7nꫯ>8Goѭ[7̚5 њHRSSaggKKKM,2[MJ3jj n:h׮|MɩA4LLLп888`ȑ\(RwI}OcXuueP'mmm4yǒyԤikkޚE溤iS4Byw&wyy9.]ѣG0rH,Y}fDDDDDDDϭm"** Cŀ0eMD;v,틭[j:&O}vҥK8<^u12e:RGUy###aaa|_SS#wp055i666z*ѣG1===]Qڵk˗/#55bz]؞֭[hݺT^qqXy&;Mcpss_;v qqq/By۶mí[0~x1m„ umۦȈ?o6,X]ӡi_|7n`ٲe7p@ڵkdffbڵ2e BNN|8F!V)))p,XزeT?j]ZZ8k˴mV03qDv BCC9ԞEAxV۷oc՘?>`gg鐞i>>>qG3e8q344ļyT_meɁ;,,,p9HHHht&ìYϓ'OƱcp5IIGŋ1c 1}РA2"Ա?=<eee2mٳ@qq1{6m֭[q5TWW Xz5bbbXXJKK>s9tʤpwwGYY>R'''']Vk. `kk TUU]]]?A7W_̰m6;VVVс&L(?}}}}cѰ>'? ccc>}Z&055WF!""""""z^q zbccQ]]0w}9ٯ~~Ҷoߎ]tիaiiO?{Edd$ رc._ [[[Z ;wFvv6.]\DEEIR<D6m ""8~xkϞ=/nnnƁ]vGj5 yO:vHnE}9sйsgv%igΜQTipBAGGGlmmHOO?MDDDDDDqJzbz1ch: ""3f ӈT$`$󓖘gvvv066FPPRRRw^AAAڵ+Э[7,^Έ;;;PRR"Kn@ >>/F۷AImڴ\tEa9\zѣPsssxyy 8z(oߎ OKK 055ʔkvӺukX恍b i=z !!oir0:{,Ο?GGGòe0k,t 999'|+V !!AqA)))իWa^Zn6l@JJ z-['/ 22RfU٘:uꄨ( Xf ֬Y[nH?3뇪*|5k C[[t( """""".3f ƌ0[uu5\ ++ ,ၸ8_!!!hٲ%6n܈xk{QQQ UХKdggcڵ޽{ÑEaȐ!x饗]C\v vvvJ۴;w?`ԨQ(((@hhh[^ߝ:uBaa!dVeH^~eHOO xxx`Ŋ(,,D۶m5͛7k׮sbٲe(//_-^{裏b qՇK <%Ğ={ܹ/"K.eA46_ॗ^̛7k֬;wGSSS#,, .\#WZHڏ.BDDDD0bԩhݺ5222;7o{bɓ'CϞ=7n~~~*=yd@hh(^z!((a9Æ Sf߾}}zcǢe˖ny}{xxU$1PH mmmL:Ujz믚EݻNNN{===>ػA@3R(󂔊-ŲqH fF=Jȟy ԯɬ,E 3EA 9J)QyE.;e xǃY{{43ؿ/l`.v]c93W 6lŋ=sLrr2ƍ'::  \Mi߾}۴iҩS'CDDWenkd운j*"""|ISDDJXOV ~888ٳׯ_g4n{{{7nYx1nnnU;$$)Sp=舣# >iӦY?///),,p̱cҿ4h#L<]}Ņ͛7w͸ҧO*_y 6$!!$~m[ǹ1a<==mLeW:uX=6&TtN:U93gPf "778tB^^QQQ~,\Rc\Nw]ƍGJJ VL2[_lڴM6ѧOMfoM}ٱc ,`ʕL&HVh׮ "))w}gM6%::4h@dd$+ڃ pRw$,oggg&L .ۿ2]h4Knn.^^^撙ɨQpqqp\vvʔ)S䡇Zf7sL[GjnJϞ=-7moǴhт}qA7o~U]˹yyپ};WfDDD0z:bٲe: """"""WVNJJJ:ׯՕ1cưf~>}:M6eݺuW}Ysgdd\WϟgOOO6mJHH&M'"""WٰahҤ <==2d HYܹ3ٳ#s=?@QQ7o slBoX7|S昷z+ǏLJ͛sA"##=z4>޽{쥗^⥗^u ZM+\uŋ,\:wLnxK&((Ν;RXXhSK_|O=UEq 6>+5NAAӦMk׮Ջ)S\v?9s7x{N:y敺3_pv?LLLjgΜaŊ<4nޤIYbgΜ)HѡCÙ;w.s^ֱDDDDDDDM6eÆ ~!_|c=^^^+|,Alٲ1cмysԩCÆ f۶mo߾Ug;v0gΜr|뭷hٲ%uԡQFNNN899Ѻuk&LG}Tcs= `0hӦ:DDDDDDv r][`qQQwfݜ;w0 =zRG%..,,X]E;w[nڵ+gǎ͞=kORR,]77Jٳgyg,mǎcٲe1FԩSW^ŋ*[(+ ty'+}>"""J/шhu dqu=<>>}ӧ: +44P[.P""""""OJ+9$$$j*/OFFk֬n:iժlْSTaBԩ|73apppM6b 6T8fIQQQiڶmĉKk IDATIfͨ[xӖ.p!7#G0g^}U4ib8"""""""""e r]3f ӦMc۶ml۶{#F`4qrr;tAAAe믿V8Oƍ9z(GYf͵/SNV۵kÇ+9ڶmk޾}{қ%y{{[~vssŋ^'NP~Rs}DDDDDDDDDDDDwݛ[G ""Qڷo>>>>[.͛7',,{_UVm6g YLreddX=6QU 00N:qF vɻҥKyx'W(ٳo߾=Ge<[~I%W0ر rJL&UVHͩo\Ennn̰a8}4ͳ`ڵddd+\p_j?31ڵ;;+y4mLvcVUeN*uGDDcǎ:TAhh(;vu  ĠAmfHKKu )ёTh(RKX%?{NNN_~,Y橬3yd'M6%$$I&qkGDDDDDD r]{'e„ ׏ロ?={dDEEwɓ'Yt)K,ߟ Vh0L:tf͚жm[{1+Fs=?}|ϟG) :3f{aDGGзo_K.G,^hf̘Kvv6111%L&N8o}gٳ<3d-[Fzz:qqqӇgpqq 99'8rtڕ$,  ==d| CDDDDDDD*Or "((܈ ""~[nVA_e4hЀH"##+b+sիh$66\%33QFY1 %441DDD>s[Gk`0xbڴió>'|bH\.]زec\BBiӦ̜9___vͤI8~UߥKM֭8q"Mzz:k֬!88͛3uTn6bcccÆ ٲeK,7[|9&L`0{nF͛K\٢V+fgooϳ>koŌ3%;;ɓ'믿xbùٽ{7p{HKK#??'''xqqq!-- __Rymiii*AߞADn:Æ I&Vw*OHHӓ!C0TGFXt)9 .uk. rWYlذ(ڴi~~~L4TuMVe˖L:RDFFҬY3֭kY]W4!C,6mb{|׼[̞=DE3Yi߾=Nbq۶m-|,!?O' ??TKEϞ=طop-ZX.DĊ3SN_fСYdt"""ׇ}SUVm6:uĀe42ՋӧS~}[G悃޽՗СC<#R땵K999oj_c:@PPP믥ڼ-?p+\D`0vXSd*s+>}}2unn.m۶j7_#Gлwo|Mԭ[pK;zMVVvvvt 'Nrs \H):t <;ؿ?;wܹT_OOOrrrXv+UcW!o.\NQs= :ŋM,y4mڔIǎ-홙 fdffGq9v @׮]IOOٳVE;vSNaԩS>"""""""Rs􎖈\ue.^sq di>ކDDDDDDDD.88X_pƍ'''Ǝ[kb=zĔ)S2eJ{% wwwN8AHH]ٙ^{QFȓO>ɝw a9t#F:YfVm͛ssaU1tBJJ YYYⲲT$""""""Rô…JΝcȑ$%%qiػwآBFG}đ#G(**ѣ1f.^X\~-yyy@^^5vn"""""""""׻iӦ/[.̢E [nN:jՊӧXn<J\\FOOOqssG,^Z(Ę 8;;}GLL =+W`xyyaooOaaa 7ްׯ_x @ƍq <ŋf5N`` PH¼څyU}͛Keڼy3LDDDDDDDfh  u +h"RE >|M2sL|}}ٽ{7&MV}.]Jvv6[fĉx{{Ctt4Y`222V0KKK׷Ts[ZZO>:] +]G}D:ux>}:'/k׮ё ~mbΪU[.=s̱xYΞ=̙3Yjxzzɓqrr*93׮]`˖-8880x`ΝKz,}J^Ӌ/2uTV\qttu<39ϘfӧOޞ([Gb6lXjeGШQ#v777"""p^JǬ_>e3]Bs1Cu(++RADFFy9BBB )>~xƏ_^zFbcc \2335j...WDDDDDDD*OrU1`[k\p}`u%6l@TTmڴ.ulҤIKV}׭[@tt4M6e˖L:`*,"ݷopiZhaGDDDDDDD_|EYϘ1-[}vRQ_xҥKIMMݽ9ٳobgg}usVg={Z/\j&LXm6mӧ+f[;rN<̙3K_l[n1aquu%''ٳgо}{'6l_} <==2dӉ>v"R= L&mڴiU8rrr{!l"_¹N8\ZI6sٹs'ϟgcoo޽{^`ڵꫯ)(( ---ZpAxr|7Ƞcǎر"~'vw}G\\\\>>>YV\z5{5c|7p}]~r"));'O:M!>>g}1~0k,zŃ>Hhh([!/gggNʚ5k8z(Ge͚5L:jE#*a]j*Y,e0.ۧgV00q׮]ؿ/lٲwﮱՙu֖NM)͛Ǹqgܹ1d|8-Z`׮] 2;ҷo_,Ycǎuww $$.]UjlsC=T("""""""֭[oڴ __riѢ, .X[n 4<ӤΫ_EDDĕ5ѵkWmV_DDDDDDDDDj/\UAFF5ٙE-B:uhժӧOJ\\FOOOqssG,^ju兽=6o\*͛quuO>WEDDDDDDjy(**b͖\1?0\pcǎ+`0իWɹ,Y?nY`0{qڶmK۶mZg;w&//;w:\ȍaÆL2Ūѣ4jȪ͍ލ100@za4%77///rssdԨQ\鈈vmtɪߟ_|c&LΖ-[С>xWs5i҄7|e˖qq|||h޼9$22ѣGNxxqݻws|}}iذ!T߁Oy饗pppuJbb"!"\z=H uF^^&L 00WWWrrr={6۷ W_}EBB$$$ɐ!Cjt. Frr27h42yd=Alٲӧgݺuc5j[ošC(((`ԨQ888; ]w?^};`00`֭k(ʫݻymSTTĀlCDDDDDDD2L&Cȍ!,, THP`%ddd0k,>2xbJ57/.V̟???GDDJ""""`@/55nݺ_ү_?[ǩo"7e˖#DDDDDDnpZBDDDDjH5k_́(,,nsΌ9ƍ:t <:z\5ZBDDDDHbb"!"""Hhhc }̝;1cУGufHbcƍu ۷j_~U2ҷ"Vb۶mtԉ\x"""""""7+\)**5""""""""7^xdɥ IDAT;hذ#]D֭KPPH 7n)))W\pڱc ,`ʕL&HVh׮pTp!""""Ֆ@BBc\5aaa,[1DDDl*!!hr0 Ӯ];Fg}`uj[f Up!R \% 5jjՉkL< @HH&M"11ggg'BDDDDm:TQ׮]y饗l"SiiUK)ÃKpBy[G.]0aomGDFsq di>pBDDDD~ 11P[GJJLL1n({GDDDݻ;н{w[G";wԩSdeeѶm[[&ˍtΟ?7O='NWp#66uӨQ#}QFy+V0o_S\^^111Dnxp>s +VqƖ&Mϊ+:t(ׯֹ܌Tp!""""Wh4"""70[GZ`ԨQp~4h@ZZ .p9FÇ-m{[WXXѣζ=z8X`vvvVnj5SNիx"QQQs޼y9sR<{kرcXӧO3}rϿ:_NUDEEyfRIHHsPjINN'y̪nM,,, M6mڴmٲe'W䚰SNlݺQ{ǎc̘1>}Q $$$pa6mJ\\[neѢEV+!-]lZnͲeXjڵ#==5k֔:y|駤1b6lpEclْ4K0aiiilٲRP| 9Sܾ}xغu+qqqxyy˒%Kʝ*-5GDDDDDDD*G+\TVZk rMo׽I&n:bbblE!**6mǤIx饗[h6m \*~:u*$%%luLdd$͚5.YTg!Chyi&L&{믿_~a={S"""""""R9*ƍGJJJ;v`\iժڵARKNHHH|9\J;v,;vd"5d!`lZ,9sسgwqݻwۛR7S<%9}sT%y|;;Rme=7"""""""R>\HtlRfիׯ˗/)o\/".X/Z;y$۷og̞=_|ٳgSn]{ɓdff;|!ClM*aذaDFF˂ .?66r\mr#Dڵkyꩧ -7 pmEjHXX| d>|87nd׮]rrrbرU&ѣIIIL2)Sڿw^pwwĉڵk9U6ٽ[VUݥKRRRϪoVV=PODDDDDDD…$,X~ȡC(**"//ݻw3sLܯѣGGq8z(qqq3ԗJo˳, < RDDD_:w_MӦM;w.?yyyw^f̘AIJJ"(( .: GycooO?ͷ~)**?dݺu/T[ۗA& d歰|w˖-N:5^Ps_'… qqqaذaz Nbbbh֬H qvvfѢEq-PNZj,7puu%..ш'ѣG/^\UjbW^y@qtt#&&RrJƏ^sl'ҷo_iذ!dѢEeW%w߾}qqqaͥټy3NDDDDDDDr…>S~m)**"))YfrJ*oҥdggӺuk&N7999DGGΚ5k&##jiiijnKKK'JWDDDDnO?4ݻw?[näI桇"%% /(%227Ҽys>3ڷooaÆݛ޽{/DJJ ;6J}spppq<<ü̙3QFnM&M۷/III|r^'OcN" 777VXC=Ĝ9sxWmI)$$*hذa= @F܈ ""1y+~宺R|u@=M)~믿^*^zFbcc \2335j...!"""""""ִ…8rׂCVZ_E`͚5Un:iժlْSTa}мyRZhaGDDDn999RŵnݚYfڿw^ xyy1|p~ ` ggg "==~F]wEݺu[СӦMɓeSl~,X3~mb:tW_} .,^yweW׹e^ZTVLL ~~~';Y~~>o&ݺuÃ:uШQ#{16nX{iܸ1vr3W1 jժ`0p뭷ZW|x^[8p YYYYU0yM>w~?Sxzzw[oUXUUמ9Gu^g999tЁzWjT̓>̙3}/rMpٿi0l04ibbsBB5"M$""""RIFd4}l֡CJmWS9[S@@K.X筎l}zYndرCR L:t0uԩ&.{.TzmڴfJmNNN1e-9;;[_x޾̾۷7={3ɓ'W\M7o.ɗ_~irvv.sz֭[Wym۶T8GGGӖ-[IOO7կ_kѢE ӱcj,[IU}&4f̘J]_QF+sW:WYQk;SV܇~hL pӧO=w`ZvmTz$''y`0-Y}~wy 0egg7{l` +s9syNu-Tw5??n2 ~7 SÆ M5ܕW_|ĔyLUsUw%^zY~8p`},RY/^4NS^^ Ws111徟ٻwoÇFl S.]LG19rԥKӿo[Ǫf+XDDDDDDnLZBDDDDj\FFvk!00)Sжm[ywׯWr?T|%0]Τvv$7]kEDD9q̙3;_~ϳuVFIaa!FGZg2Jmі~0j(oF́(,,dӦMu]رٳg[cU֭K׮]qtt;vAqyx ((( ++'xs1`;V#FG%55sαqF),,d̙V}ǎ˙3gxg_(,,$// 6prA˝wk"[qy֯_@HHH٠At\Mu6N=-ϵ]?Vo֬Yw}G~~>۶msΘL&^JYqIF嘟~~Gz?_P/J3ׯ_28q":ub۶mO?DAAC jݺu4h&23a2]aߌ3F~~u%l,gfXΝYQQ¾"ֹsgDž9}Ju:u`5kTHV5xR$իWOoQ^|:/lllʍ2ֶˋfʋYXXYr[nC],rD.]2777pq5+?{1###Y:]\\f/yL-uG^t`W \vƘ~ϝŋ3G)oaa!swwWYR CTXXȬ}bH!pA!B!'ZB!| Jo>d24m͚5ks/_ڵk!J1~x>/R͛ݻ+!BHwQɓU=z4ĉj!e˖)?'NT*+JÝ;w\Gɓ΄[ze.###|wǏ,?i$/k x;~xx8[l%rlllʭ$.NNVT%nmY[Uyh _fw1rO>|wJeD"fϞQۚhӦ 6mK.ٳg|#GP\\ WWWԮ][eٹs*X_# 899!##QQQ C@*S;iӦ)D*>رm!Dpuu  !B!B!B!0bѡC#$$z4_PP5j :? 333L:kkk G>}$X !RRRRb@isvvܺuKmcǎݻw_BPa۷[(&l=^VR%X!{<&&CEÆ ѰaC9GAA^c+I d*aaaU9}ŭm?k*mq\$Çcܹ޽;b11Qy]}?WY]54h =QGC\ܩ|ZEh kni=w\~ HTwss+}U7pA!##СB!B!RЀ B!Rbcck1oi:|۶mCdd$qA~fI܊ X=^r5jomm @j ܊ >x;v@~вeK-t9*hpY+BgmU5-n{{rٳM4A&M%KɓxVmR70f͚ZPoE^^BY.ԩ2gG6 B8|0D"__N|r4u;1cCR-ZӧOkz!B!B!; B!2 __rjӦMôi׽{wt]! Ç>|x7!B!x5233>7@ _~A˖-ն7ohF(͛ѧO/>,ԪUKLff&>}_!::Ѹy&0e:tHrp۷:u###ڵS1@Y[U}h̙3ԯ !C-ZШQ#ԩSNNN`M\LkJyZj''';v )))xd2b1ڴi{wL%TY^=xyy?]b׮](,,D^`ggSYYYjϧ:y׹C(߿é2nn:p@DD B!Byoр B!B dĈ8z(1c @xx8b,Bq5\p={Ը\^^ ɰhѢ2}6iHJJGuĦM0uT3s8ׯ_+<ߤI\z/_F=\tϧO 6ȑ#1rH#GЧOy}Ǧ=z4VXm۶apqqQ؟6mڠ{yHJJ֭[Voddbd2wI u͔[lӧ̼GH IDAT=`7n¾3ȨEuDGGիJՃ+jРAX`.]~z4WK.J/^nݚO?;wķ~۷%ܩҲeKŋ*WvrѵkW4lС(B֭A >}:7oѣG:_~ B!ByiB!BD*V077ǂ p!<~?ơC`:/c}'F~~>|||NHH@ff&6lgggL4 ={D~~>u:(䷵\|Y0ŭm?/ϪT59s 99ݻwyo߾ 6lҾ5k?ۮ.ѷo_իS(;V\ *zj"tGrPfM$&&"<<ɨU 5};uqQTT_ݹ5.u>#DSXr%dhxè2NfBCC!B!BH!BP`` TZ[RwMxx86m6m0t8Bs}iedd5j0k׮ҥK,77:u;0H2dا~޼ySn,7od 5k{ asvvfܹsթS`| [~=KKKcL&Db 3l޼y KNNf~~~ `wU(գ3gd;q{ +,,dۛ` t91&Y߾}fllFN<^x ٓ'Oرc60[[[>bvttdΝclԩLoqkό1 Y~~kB#v!ֽ{w={:6a&YRR6l¹w^_f ׯKIIa,99ۗYZZ_*ZD"UfY~~>X=Mnn._FXIƍc{ڤIܩJbb`,>>ׯZjK׸Խ*}V2_xxׄCBB377WQrCPer9kݺ5ݻC!RIKhq^B!By7ovB!Dc&!ϵM=z}bƍ %Vj0Xhh(*󹻻+ 3332...HLLĖ-[УGb ͚5øq lO>v X HXÇ#.._~ǡ bbb0k,lDpttķ~8888TZlڞ?P(q,Y۷Gڵ! aff Vajje˖ST011+91c-n]yѣ,--!P~2D"ԩSڵ pm3f v܉> Anp,Zsl޼Ytc|ggg۷ {C3)7pHRD"4nӧOGbb"Zj_ -Z&Jܩ1cs䄈 6Le]*WgTѷo_ 2Ϟ=3t8O?k֬A  !B!B!Ֆ1*Rq%}C!JаaC: 2d <<\kB!Tvݻw+V@JJ N>mp;(-- h֬nܸzSSS@T4kLe>@H5&@ ѧLiNNN8z(!FREDD`Ȑ!gү !B!D ::"B!S`` B!Blذajy&6m۶mDv;/ }Y&~Wt۶m+sU'BHv >}Brr2޼y-ZK.󃵵mr+^ƢGx9;;;|߇?ѣ<|~~~裏pqS?O[x"q\B!B!WO!TO40TDDD: B!hf&gΜAj*wm۰rJرcޫWuΝz !DSnnn8r<==  !DG~-Ξ=4@&a̙pBzBBySNe˖￑4"::`bb?^a$''T qqqX~= f͚> !B!\B!_/aB!DK 64tBXz5v트8tUi@ `"ԪU900mڴKݻ:BH={VezHH.\ub„ @5S߿vw}m۶UVٙpѥK}܀!C`툎Vp,?-77sE!3g ss*B!By}q%}WK!-4lB!B!Zj۶-zjDEEݻ(,,<==7Mo5h/yfK!;w2t(q9ԪU ;v@ݺu}ɓaaa7bƍشiSJp'82 qqqȑ#g\|011p.ؾ};={>m_}vL8рB!B!Ɛ!C]-!BpCA>?""" !BD !z_>~*iZgUR$RDFFbڵx葡C!D^x~ E&M0|p̞=2 8y$?:ugϞ=z4?XA*cccqaa[4h 0ТE llٲN˗/QNtcǎʺׯ_WH|2 ԩSEvHMMUp^| 6ٳE.]~+dX|9Μ9333&M)˖-[p <~hҤ Vݻ+R)vލaÆZeB!B!Dszp?B!AIU6 !w }^$B!|9s&ѸqcCSa2 >>>ѦMCC $''GFFF4h 0~x#?~0$%%a022RVbb"%u,--W_)y_}'O ""/_FXX,,,QC[B>D sNnݺO]p^zH;wӧOXnbbbc̙={(R\r"B!B \B!B!B!B,Z`훙A**<ʕ+1g|G`HH>Sm۶3gRޓ'O.]f͚A(qX`رce% u*NR[h y&={f͚~ڵѢE ͞=vvv  RT)[e޽{6m(o۶R|}}Us2[.222c4nXerrr`eeŧ=|кuk\̏=Rf.S <==quDGGO>ArrByU222~ʸ4\F RL ŋx"6mڄQF!00fff|`mm!B!BH %DGGc̘1prrLMMѠA2US@apuu-D"lmm_ $$zolݺUr@Ko\i .eաX I,!!!? $$>>>U~]\\ Qk׮A UV:Xu}[YBȻoŐ!CT1}tcݺu !R"""MmFmFHuI&aHKK3H HIIyZr ~XT1ת͛2s.\6Orr2:w Y&+ehFFFHMMEqq1Ο?@ rn݂@ (9\H9.MLL߽{w?~C֭7;gFFʏ|pi:!B!gϞ!((ǏWڗ o Dnj3~z/233q\r?&O~wرAkEEED||yΞ=2=77sEAz3g ss B!믿Ɨ_~i0!JjZ .\@@@Ο?_֮];oݻw1L::t@~ "j4hiii_&)Ÿw>d={ıcԪUKaqq16o zPW޽xmʊ5Bzz:㑘(kٲ%jժ5ں4ht\v7@RR杢!)))믿sNY/׮]O++C!B!Wx)qqԫWVBrr2d2󑚚ŋǎ/r~gG駟  1rHDEEٳg(,,˗/qI֮] ooo6p=b;LUmx)Oyyy>|\1蓣#N<#/CaÆA("<<yyyeCDDD"/!"Tr)3iƳgϰ}vFF!B!255ݻq ̚5ۯ]6ϟ Tyw^`͚5T^^^e˖!)) rXlRΝ;BBB"|k׮T*J Ѷm[<AAA8qQXXdL2/^ϗԩ`ҥHHH\.GBBc<Ɩ-[x;Wqq1ڵk @ @vPTT0rуڵkHNNWUhRL&CӦMѬY31y{)qy!B!R1 #GDzz::v5kT߼ys̙3_~%ڷogb͘R)vލaÆں B!~BDD B*UxxxR6mM6aذaҥ zUϟ?Jӧ#44m۶5t(2dܽ{O 9s Jeaԩk[[[X,Ç˗/DŽ ٳg+ѹsg,^] ԩS>FaÆJilGK*yzzȑ#|2_,C_7n(n4A]hbĈXt)/_˗++^ٳgV(op !B!B4S+\ܻwcǎEÆ ajj X!C %%Ee~@PVZll, >&&&hҤ fΜ7o(;w?>WlQ ֭[bĈ [ny\pt氵/NinSSSԬY .Dff2Vm_ZZ֯_sssDEE) (M"ѣ066͛q η&4m.UU׌-[mÇطoڶ9yyyѡCԮ]"uA^p:MIIQn]m۶]/>>>rE\>Ut郒qm߾-[1># 4H(*MkI>羬 U[g\~}^_eX ccc4mk׮-.mš˽޽{H$D>}4 B>,ׯǶmp}B&!11K,Axx8ǏΝ;# Ô)SP\\\f;QQQd sڵkL'N!b8J+IFmFR 2#Fɓi%z-r'ssslٲY&D"5kE? XYY!,,  ANcaooP|Zk.|7pvv,--ѵkWlܸ+WBؾ};uB(nݺ_hh(H$lĈƍL.4W_1D8PqL2I$vUbccD"aSN%BDCE!C}My󆥦: B ~?y۴iJ,##O`RmݺՀ}y~B!BȻVѿdggcԩurssѣGxB9bvKm|7EEE?~<ܹpttD\\~>tt4h)<==fx  ???$%%!??IIICNN'OsԨQٳ'3gΠI&(((%KN:3f nݺd2>}-[ݻwfhl%r/ogF@@ԩSZW3+5`f vZ/_k׮ѐdŋ{ԥ?233ȗINNF~~>].]`„ kjj.]֭[J+ \~ر#,,,*fϞ 777\xyyyHNN/1tP<\TZҵMMMT c ^/U?ˠA|KmU[n!11YYYXzAHeJ [y镁#22^BCN< Xt)5kPƍccǎ*ҾF)!B!B!TQ:@*b߾}x5qomڴ1pD#FŠ:t##B!B3K2,$$De=SN-s?'&&D"M>]aߌ3TcW\a 8 *Ͳ̞=`;wfEEE XΝUoV+y)լYS!իWJeV^=V.F {2 )7ʈ[~./)/Ҹ,,,ʬP9[T֡.][K.Je Flܸ`?B+W2lڵjh0Lx-ZrҴ*.]bXrfoo+W0{}J_x1|||2wwJ9U^ONK*Dy[ebڵ`,77W!_<Ν;+WIL"(cL"0779HB!DyQ;ӧOD"a]ve1&HXϞ=+=w!g.={SS={TaTRV j-[LݺuSX)bcc{{P,R5h B!By?U GL|wJeD"fϞQ>>>#G(sTΝ sss]*6RE/222/** > ?ӽ>/U>6m>Hei;j!^wǏc޼yhݺ5qF~2VL@ r4.!BIII~P򵋋bN[ 2ڵcƺu_B!Rf̘iӦ fff022X,?aooo$ &NUVaժU4iʿeB!B!Dwj(%% w-Ǝw+B۷oZnQL666Dvv6jԨQur)ƥs訔fii (..VH={6Fx;8k׮ӧz V. YYYBڵm и:ĭm?k*mq\$d\|.]F(U.=矫,Qpvvƹs琝 kkkdeehڴʾVE>P=44߯JE/U_Ъ[>轀F) |}}닔_عs'֬Y~x9޽{8|pT]6<,^s ذ~nEMa 3Rּys{bҸ<By?IR~۵k`˖-Jؽ{7`ݺu~zپ};={>mxon!R1lWǎ3t(B!B!Wl7kzff&cj"ׯ_7|@_~-[, M8n߾= **J7oDڵ f/.-33S!۷/^{!,, FLKKÔ)S*%6]Ο`߾}Zcdd$]v*A>//Ooqƙ3gqE;w.BCCqAܼyS6u 4uu 8z¿ hOqǤn*}^^=xyyh׮](,,7:u1︪󽀐zѡC#$$VQFHHHСC ooo033ԩSܠ_٫KҸϝB!ӧ?>u777|.;;WF^޽{c͚5JwrIn߾']vŲeː+..͛wwwt#GPWzK|5t҅Z29numgggcQn]>?`0O!'//AAA>|ǏWz;Z~=bP!B!ByTـ n5 .hU.//dXp!|}}mҤ Zi&pz~Za)^˗/,s%|ҰaC9q> .oDضmsf͚aɸqn֭$XU&)ՕKҤekX Pt ;vPX"88 (((x{{ΝSܹsB!}։888 66;vvЪUL&S9Gv p !BH155Ǐ+ ]x/Fpp06lhp!B!By=zڵkHH 4={T}.88 ǜ9slsΈGhh(?0')) Z޽ ,^^^8y$ }BeXj̧{{{իXbw >tj*@׮]r4jCRR>c}']a6鄄dffbÆ ؼy3ƍC!??ݺuCڰ˗/qetYa_XXֶ@ 1b~V*m̙3pttD޽{maÔ|"77u鏾}"::W (_F"^^^gϞO>055-\E`ҥBZQQ~@~TkGf͚HLLDxx8QV-t˗BPac5.uz/ |rZ__2rlll0m4L6|ݻwG,--P<|zqƩI! 77hʶsNx-[Ē%KPN8p vڅtcprrBJJ Ν۷ocǎ8qBX`>c",, OWۿ?`ݺuJ(,,ıcǰ|rٳC All,'7FXXLLL~trrRK;|M!صk>37kEŕ֎.,X ̘1С@aa ػwC B!R l'F8} LSNYI}˖-S?lذERRV\ T/^`Μ9 3O08}4gΜ&O\>V|0`N<r$%%!00.,Y}pssW_}?/_D;EEEظq#222`kk|_'`رF^^0m4lܸQoqk\xJU^3ex1> ooo,_ UR7;Rpp0>}"$''c |8t1c'Npu"%%CLLV}7ocǎaРAHMMEAAлwoDGGO>QZfff4h`ʔ)޾J?HK &@,ܹsի 55Tq?T{ydee qaza}F;;;ٛ!1tPFF! &p(EGGO !!!Ł|OO?1ZnٳgN:T3аaCbȐ!0474<<xX:tH` m[nU}5RC!??H~%PXVHNN?| 1+ `0!g$B!pVүK:z(377gTn7nT/H-|,77W)Dִi2 l޼y*СCTe9SSSv2b/oVVsrrR={nŦr`qf͚rB=W\afff*oٲEoqϝ:uR{]mVVV*UUw.͝;?۷OuhfiiLXXդ=zp߸w^e*VKHHPKd}^RLLB+W(*=&&լYSev9/P dj_Wqq1jԨ\\\@ `FFFUVllϞ=jCחD"bcc{{`W^5H,BHYv49͍I$_f>www&HX^^Bz^^H$ݝO.((ӊ'**k׎O`Jũ.ttǭ>WWWeD"annneK!,<<\kBYf1 Timmۖ}7V.D"aEEETwKYB!BywT Y1j(4hƨQp L0A!ZZm5 gϞEϞ=QfMEXx1N> 3332...HLLĖ-[УGb ͚5øq lO>v X HXÇ#.._~ǡ bbb0k,lDpttķ~8# 1|ܹsK,AQvmBzªU0|bٲeT011+91c-n]yѣ,--!P~2D"ԩSڵ pm3f v܉> Anp,Zsl޼Ytc|ggg۷_ц]ndҍz\W{׽{mI{{3rHӱ4oޜh >E+>ʊG}@pWo '''4iˆ#O_-CM6Jhh(oNKDDDʐu[n&uzŦM e˖\~ /_h[dgg^U8mܷ\_NJ{^EDD>}:[fݓ5:wlUlٲ-[0w\ʾeDGGey{:s >ǎot:_hԨM4Nnj&7/E^^^DEE^nڵSN̝;7ǶTݻٵkƍtOOO o|IR2tEJ7oġC!)))׸Uһwof̘-[6m믿xgJŅbѣG~ԩ$''su} }5u `9BVVGa֬Ytҥk >shܸ1M4rx9kԨڵkIOOԩSs[iӦq#"""_zHHH'/Ν+5ߡ٩آi׮-D ӿ""""""kK' "RXڵcǎ 0PڵkG _O={6o3}x蜋XINNܹs?gϒٳg9<Ν#99n޼iگk׮yy%.\Ȃ r Gfĉ4l~C4\ 6#G/m9r鵷7۷o'11ÇիW/XAx{{LHHHWWW5jpE9[n^3|:v#ǝڝ:ubΝ=zB IDAT,OgXgg{6wJJMMcƌa̘1NCDDDDDDDLQ8;;SN/_ΪUr3|/^Le̘1ԩS~C~PV-"## g\~FcrUV%22?;vRV-zȑ#/X[[éSxҥ ަ'LFFFs?rW_` 00^xHǝڽ{f޽Cͻ{nT?_!"""""""""""""\Օ̙Ö-[8}48::ҹsgƎK-CE\III!)) .:R$%%Dzzi?kkkԩc*hذ!]tN:ԭ[֭K:ukO<Ν3={6QQQ<#1j(VZbMfff'"""Vll,N㡳qF_Epvv&88qժUcL<9߸|zW^Z_mʕ+ɒ%K8{,uٳ>|QF)"""""""""""""e .D裏2o}P\{ޘ1c3f=[DDDad0ɼyucڴi;!Cn:,X@Ŋ-dffbccc4DDDDDDDDD\?0K^8a|}yp7n0geeEڵM&hР:uHڵK;ĽL޽?Iz^^^DGGuDDDdyzze4DJ6mKhh(oJDDDJJLL ˖-cݺu/_l[VV7oޤB E?55CK/TtٶmקQF7oҡCFȑ# .DDD… f.\ 99T8q{aEffi˛(&5kٸXtl޼icc6EDD ^^^NLS'OOOK!"""@ƍٶm3g$((4AAAhW9u}'N֭[ :D ./0aSLzDFFrtREDDDDDDDDYEll콚ZDDDK~,F]oFJJΝё… dee6B󄣣鵃VVV<ʲ_~ϜvZK """"r_nݚ9s0vXuF׮]ٰaYpqe"##ٷoGܺu ڴimڴ^Yf%ӧX"˖-#22???x7Kl ){Vpѿ{52W^X`q5>ԩST,H֭sV888Pvm }9u7oޤq_%=='|jժ1c x >|8-b޼yo߾kݕxŞ={X`AIO+"""йsgƌSvԩSMR>J:upqqgϞB:u kRhSLݡCgժUdgg3`4iBV,gdffZ: ) 6O<+pqqAlْkZpЪU+SC߾}7/*ʕ+G-Lc#::I&GpsscԩSkHJ"11XWSHbccS}V =u֥N:СCnbYvvrx9r>6mڐŴi,m '''ݙ2e Y8C_ڵkb y׏zY: ?ۛ?J*ۗŋgW0}tBCCͶ>>YYY8+++lmm[nIJJ 4 4+Vi̘1E&'""""ܹsysީO>L6о}\U;v,#FYfm'OQF%?`(;;BBB1c%/G<KK `,h۶`0`0qF}7oތ`?>wq7xwܹ3=z ((?lTV\I۶mqpp0;::b0Xr%< """J?я~'::劔{ pEy:#e˖4hЀ5k;oO>رc4hP"&$$SOeffChh(*Y ϡCxquuёdBBBpppw)ҼׯlܸÇ|rزe iiit1;vlݺ^{(""",=ѿK Rxy>|8ڵ# wyS\߾}Yf ^s/_ptBll,C533'|4cݻ눈H:~8M6-uk@uEDDW2c bbb8{,NNNxyyHŊdŊ| 2Ĵott4^^^׏XӸ^9Ύ~JʕMɼ;[k׮nݺŴiXjO^uFQgo>kLժUyw%((E1uT]o*(={`ڶmˏ?Ȕ)S8w˗/{мyݫ 2_~DDDDаaC,X@@@_~%lbΜ9fwԩCeĉKr5jT'233qqq_$));vЦMb!"""""""""Rf„ ܹ3ϛ -CgժUdgg3`4iBV{""~:ݻw7̙3slBrXp!wg^z$&&Kݺu .wΟ @ZZ-͛,^N:q)>\r%̞=>##8r ~~~E8snm۶xzz믿NBB g)rO?4[|7ǏP~?f1""""""""Rz+WqK/1l0yL¿/:t耣#k֬ɷ $$M4lذ%$$`ccCf8~8-'("""""""""Rx"Ν;Kၓθ3es""03gk׎C?@Ν믉z,[+W0tPn޼7W\aҥԨQla|_5n״iSN8AZZYƴ=44SNѨQ#[nܸΝ;9rHE7oƍpBJL>z-5jDBB 4.|۷7{o,&Mc/^q'1FDDDa_iLL ~~~s)ƍk.f͚ŬYh߾=ǎ{8::ٳٺu+@t8vM4!>>N:b  X`RDFFMc "%%H f&""Y+VUVX[[ӢE .] M=z`ܹΝ;cƌs=WbkѸqc?~<`~ڵkygk׮|G9R s%<<|M_ rf?w/idddgmm֭[f]Nrnj1"""" &6cWI&1qD8|}PDDDʕ+?9s]3f ?8o&5k֤f͚)!!'OҳgO:uĶmۨUV+s.Ο?ԩSyh߾=dƍ9RSS3g/۷_fܹ\z,X8rI|}}ܹ3={d֬YfnݺŢEpwwCtڕaÆn4u缷>x =z`9br˩0ǝک\m`qtt`0rJRSS9"""?РAL?Ƨ%$$SOG- )5\\\LN7>u(=a;7Ǐ.(UcHq ===9xԤIG۷3o<:w޽{ڵ+|n'N(5h Wv"330jԨ 6ʊ>TZlI˖-"b L<gggÇIŊ zܹx"UVͱ8f).֮]˾}hӦٶJ*1g/|||Z*}666,[-[MBBիWvڤдiSׯӧ FaL8/CϚ 0qɌ=___|}}ͶݾoY[1c3gd̙9b^z%^z%{;;;MZj̟??*W'K,ٳԭ[wÇ3j(Sq%EEĚ3h޼9 L2˗s1\\\xwhذ!gΜ!88n:C||!)NUЮڽ:\Rc|x.Åw>8{_Td?|ի6m"((-[ru.\ȋ/_|QzuvvuFFF9nb""RRUƾ}7nښ5kҧOLŏo qM | 4ښ7nj¨P;v7ߤvTP5jK,Օ+RbE\\\gٲeELvLɩH憛ǎc۶m,[siVVVdggs5Tɓ'ssSV-|2j2veSHIQc޼yyDGGc|С :~ 8HkyQYp! .k>|xkKbggǴi;v,C `ݺu,XD`("""RΜ95Glbb"nnnΕwLSWT) [ҠSNy1 ׭[7'9r,9¬YҥK~W1 |礥Ѹqc4ix;?5j`ڵs)BBB|ܹݴiSog3ƈ<ڴi/[oz󢈈MѝEu'ͫիnWWT) TaÆW_q^~em#G4f$&&xtzDjooo Qqz5jŋ[n^3|:v#ǝڝ:ubΝ=z4 GV""""bIEOOFDDDdGgΜaE檮"""""""""""""RX|QZW^TZ7o{Nj/hZ*ʗ/ bҥzmwwwh֬ҰaC|||xwMq'Nnݺ/_|?~<TV [[[:vH```;{MJؽ{wywM*Ux }>DDDDDDDDd5kG%++Su~'n޼ɟN IDAT|``ѦXuELupvv&88qժUcL<9߸Frwss-zE^ 5 ǝڕ+Wӓ%KpY֭ ٳg9|0FRJ+""""""""7oÎ;8r6VbEƏoz"""""""""""""RVYÅ<8qtt$**4S """"""""bvvv,^777W5M4aښbTBDD899Q|y֭K.5N"""""""""""""RV{/p?L6mcǎeȐ![ PbE g'"""K>},Pll,trԬY $yq{{{wNuE\HԦM|}} ୷YHiI-H׵kWW^TR3g{кu]ۛ 6ɓuEK+P'OOOK!"""HTTQQQNCDDDq/|焄bF%î\ȃcٳiH!uܙ1cX: )a'O^zlڴ_ ԩC1b%L""""Rd~-ҩHbccc4ʬ{ݵ\rP"""""""""""""R'QQQNCDDD )ƍ8;;sEj֬ɹsPӃ=+WS]""""""""" Zf /^ŋ]X8=hHxEΝ)iEDDիgDDDDDDDDDD -""ooo-[FDDD.`x¹g.DDDDD,4ml`0[Bׯ/H@Ǜr;.sα|rHNNƆG}g}booo<^!..ӿHAҧOK!"""ILLd۶mԮ]? 6_ocY:|EDDDDDDDDJbϞ=xyy"""RDEEY: 0a;w,p78qSNJ*<8âN8ȑ#vi,##Ǐsq֯_ϒ%KpppwK;tZl @&MhժS1TA=ɭ[s.\IKKɉ>}0sL_>k/_޴։'hڴ) 4_~)RSLaƍ\|f͚1i$ RW2c bbb8{,NNNxyyHŊMqnbڴiZӧOckk :#F(tHYr:\dgg߫EDD$*|Ν;~gŋ?>7n>+yל9svڵcر4hЀ,~G̙O?Dxx8ӧOwܯt wwwLBll,vvv%DEEYDDDfҥ0l0,XҥK 4SϏK.Qn|1cYLbb" ,ҥK|駼̜9Xh[~=J=<ڵ#))4СCyi]~ݻ}os9p[l\r3{lS\FFqqqq '""""""""Rܳ #ܿf͚L87?Z:B;r3gΤzX[[ӺukqwwgϞ=L"##III1aРAXH|}}-,XPN)1cйsgK!e9}4Z駟UVjՊÇ7УGhт{utm|,\ʕ+޽b|Zp/9$ 899fΜi*(hܜ9s]v,ZN8Q믉0uXx17o{dddgKXXq"""""""""eI9K' """"D=Сf֭ SQZZaaaѡC^y.\HFF)}r#/YYY>- ܺuENڵ+Æ cڵfqy_W͚5իG||<۷owңGFZ'OחΝ;ӳgOf͚EzzlSSSYr%m۶4``ʕz^DDDoXK!""rƒh4 -h,Y$&N"TnݺE۶mbҤIԪU7|M6_w^:6 6FƍR /&;;q111XVZammM-L]7/_nR s%<<|M_ '""""""""RE 8~8M6u[LL qqqoߞDDDDJk׮1b~wO?;3#6##ѣGs1XRR=zpʕ+|Mqvv6/^dΜ9|>g("""REEELDDgŹ|r; |ЪU+8u7oa`0жm[z֭[)_<#G,Һb{XXg׮]jժbo߾cooϲe9r$>,o&111f8v~4h޽{>}zԯ_իWw^|{y9nj1"""""""pƤc<|w4jԈ &?c:u0j(vͷ~_~Xqnw!ٳDDDЩS'GeѢE)KTpQL;wu<==@<<C iQQQp%<<<7+̸zڵk?`ѣxzzr…3x`lmm7ydիG LEW\1m/g{q";=f1"""""""p`ӦMdggٴiY\Qlٲ}YgLI&QBؼy3ʕ_,V=G7ς/9}t9deeרQaÆg8?O.]_DDDDDDDDD \y&22h4h)))DFFZ03̙3nl5Glbb"nnnf}ɓ^a4m^x\G-̺ƍB 1o< @DD]zX7o ,`۶m>}ٳghiذ鵽=`t|/^jժ9nj1"""}[~Œ111GLL}JDDDJ#GwѼyszkL޽iڴ)w-Dȋs͛~:4b%kggg^ux":tG)VƂqƑHZZ?qƦ} ׷o_<==9x YYY$''3i$ѣ)aÆXYYGJ˖-iٲ%C7 '""""""""RnbѢEӡCvʰaXvmش4pssC+,\ SLnOkHMMeʕmS#+WzTDDDIJ ƟfO]/NW^-tɬYL]n^شiAAAlْׯpB^|E|wҥ lmm ..@unQA>[Xr98"""RL0:tp&Mĉ 9C)-,Y1c+++ƌū СCM6|4ڴi NNNRR%̙cv,SB<==xg '""""""""Rp>$--f̘ATT).##ѣGl2Ν;Gff&IIIDDD0n8f˖-ѱc:vHZZ[n-y=cfs{sos"ЬY3 Bvv6\rXƒ%KOʕ+̝;c 5Xa:tܮyt:MVp/泭U/_α8fVj);wu<==@<<ۦM+q#"" Odd$))) 846h RRR`f"""b TT)ʕ+s%.\-ٹv%kz\Wη~K:u*lذ,x-iӦ<gʕ\t7nG} WF ͛ӧ?d͚5cժUfFg̘1E>?EQ϶SNܹG'GХKQDDabڭ[Xx1[n%)) 6lȫjVAXd _}.\G^`Ĉ oRSSYr%m۶``ʕ 2Uޛ$"""R\vӧ0qD g$"""""""""T:\7 *Ǽy0`\~,_777 ɓ']ŋ^6cDDDDʂۻΎŋFձI&TBDD899Q|y֭K.50qD֭K(Pߟ7o2gΜ"NPP͚5[[[6l)nxxxPZ5lmmر#w1;v,t֍ڵkS\9lmmiҤ o&}FQOaݻ7*Ub9ٽ{7UT1u O>!11LHHH`ƌDEE:.##ѣGl2Ν;Gff&IIIDDD0n8nݺo>[l!---"ӎ;֭[K=NNNUVw}<[;o{C^h߾=;v/g…,_z^{ 6÷zjۭ(W.g=q#""""PfMƒxG/9{E^rI&1iҤ].uss7y@i߾]kromʕdɒ%={upY>̨QT]JDDDnzj0 dffqFBBBXj^^^[|9ǎŅwy r9p֭O>޽{h޼y\c{?>:KDl67iyt:&p7[ Ocj8cjFgD*ṵgM7"4.ÓN I9iteBd(&?="|Z\}}>ko׊`'?[;VnNv!ĉe]\ɤB޽[&k[pz]܅ 5FJ*88X*,,/,Iz衇 Nj{w}WVU111$*ɤv@s n6ޞqwwץKdZu3F oQݾ}$I$ 0@ 0ac!!N$ׯ޹ש0w#@oЅ?^fYo*++u}iРA$ggg{رc%Iqqq:y{}zd65g{m"%I2l5\G}T?RYYz!???͙3G{vѢEڰaJKKU]]-I Ѻu딓~Nyxxhܸqp,,QZPĉe]H:ɤB޽[&YzR]pA{s… (n.$p|3Zp.\h]ppCE)))*..$Xǎٳnb*..Vllqw}.Irvvnvرcyf)&&Fwj۶mںuf6n(針*jkkUTT}JRk(,,@G`t***J޲Z1*ɤHv`5))IG?8I_f̘+??_ PHHn*WWW-X^۫W/I?8OJF!I*((66jԨֹyhn &ɼ7榄=>}$);;[ׯkf@jE5$,,LNNNԙ3g$I}ѨQMͩPjj?υ IDAT裏>RYYz!???͙3G{vѢEڰaJKKU]]-I Ѻu딓~N֜yxxhܸqmz@sud኎ի%IsέT@ ==]F`X6PGhhBCCozmS<==pB-\Ѻ`ѣ,RRRT\\,___IRqq;ٳgtdX͛ &4S߾}TTT}]YVHVL&"## Nuu 2m2ogyk钤l_^h@_^FdXdZիWKΝ+???S@}4\M:iӦYvhkEШ6k4iR[M nCkOطo_EDD"""`t Nw9rF7e6%Iyyy 78u뮗\IR`` Z"==]ӦMki@3X,YVc^xAoQƵ=dرC>^YYYrss5@7o&L`t T@@ڬ"""صkzfiTVV)SǦN۷+--MS5\)**ĉէOܹٳڹs?PYYY:y._[cƌQtt\FoV6lUUUG}T/ni*++}ow߭{L3gΔredd_^^^qooofeddhٳgS_ZІ֯_tcЦV,10\m(++ӫÇFE7oԱ\IR``&Mdp"Ρo߾2:r竸Xӧ|MԹTxVXѤ53Ϩ>﫢^Y]]9sĉ@rpp$}TPPPytaݻW'Nl=gXdZ@֭0p#裏TQQj;wH=zTzh":vѱ: [[g|Ϟ=pI%I:x?w$)''mݺUӧl٢CiӦM_Z)k^g?޶mN8x@OaÆζ_wAIСCejp/' >\W\QBBQUU%K(<<\&Ixeee1M]wݥ}iѢErvv֕+Wo>yyyiђO>D/{9"ItRs}ǒŋ?$Oש5'IJLL$iJHHЄ gM0At)IR~ӿ:5cXÅv>ZW\uM...햭)TVV)SǦN۷+--M4~x)''G>?… 5k%IΝӂ _ԛ}W|C=TV,**$6xϟ?/Iٳg:ۘN<\IR``&MԞM9!>~l6l6kϞ=u}e6[׸vvwi9r}Q-]TΝsmyy222////f222T^^~@畗W竱zJ_IҞ={`B^y}ӧ"##l2eff6;Q '}ȷ2![n$?l5^дiLW\O+W57[ӶDQQرc%+ɓ'ok&٬9sk,I*,,mV:ULSLM:UeeeJKK30vk?6h)eXgOSL~猍UPP*..NGkN:%Iׯ__77j(}ܘ1c$IK.UPP"##~ɓMZ'22RViif͚@EEEiȐ!jm0=䓒3fWdd[U ,3bI a5jTޮ^7*,,L?F֮]VVV_Whh~a=z7T]]miwxT^^ ٕ[fY*//o;!whs{5`W6LW_Ο?/]6gƻ888h„ ~h\a/*88XnnnrqqOSZJf͒$رI9\\\i&W^rqqѸqM-YsѢEJMMbd<==5fm޼Ύ!!!rwwWNNN 999иqt?***RMM*++uq7jUWWkΜ9ڲeΞ=(55UիW]>Pee Reeͩv'5T[[k޵O껞Sݗfv6vиYfٛ׳gO%&&:lg=z(66V6u`׫… p6bQJJ+I*..ֱc4{l7:$ܹSl6F{QRRvءiӦImۦ'Nŋ5p@*11QVvv&LwAIСCe_gΜQrrrƇ ӧo8_~~~GJX޽%I.\wmVLTT{$]p9ۘ:EC׎\R+WWO')66V7_N7ңGY,Xb;vLgϖ{si*..Vllqw}.Irvv׍;V7oV\\bbbt}mۦ[l6kƍ~ةVEEE۷$i*--UaaaƊB{ tvpEEE[V>fZe2i`2܎$3ѣ+..Ng1c|EFF* @!!!ںu\]]`{m^$Iaaaz'%I#F$`5jT!/.ZM VIIJJJ˻m%,,LK.Ր!C" 8P3fuJMMbd<==5fm޼-U]]-I rrreɑƍ7 mիWKΝ[it4QVV,1FBCCz:OOO-\P .l.88Xuz!ŢWT\\cǎirwwoM@AOX,|HܶhP@@1EEEwߕjULL$jd2)22t:h@͛7O3:@a6dޖ>Lܔ^ӧO$eggkruum,VhlÇWttV^-I;w N 4KzzjjjZIVV,1nE[X,eYEVVV[M c .&""BFiI&0ȼy4o|X555X,ڼy$)//pTnn$)00P&M28.ܖ jӦMrss3:6>~|94ѣJNN֎;T[[ɓ'kРA6l]pd2j*EEEpϗ$>|\cC]JK,QxxL&$),,LʢYm`;S-[h}fYf\bsppK{Ek4iʔ)SLiii&'vtm#&8fٳεfbcc]s׎ێ;-_\#Gԣ>Kܹsu-//WFFelVFFoU ^yJJKK$///-^Eڽ{._/jϞ=zgtE{|Jջ>((Hڻwon :.vWkmz˗BK.իWl2UTT(!!A-ZZ~:TٳڶmCֻ6f@gg64Psōbj?Sg?Yswxs꣏>Rtt$ԩS~ջuj+c ;w^?~\ Я~[/00a$I_}}~ez1[ tepධl2륗^2: ~ V֪[n99uիW%Iz.mkllc@WTTW^yEݻw7: Ͳa>}ZΜ9:mӧOp:G$s=޽{K.\Pzۘ2.tyUttQh#G(==]Æ Sjj}v9r^ӫW/IҮ]TUU3g())s\Rr劎=DIRHHfzl5ЕpK;zVbt\ rww׊+d?^l%Icƌ$[NFҤItwp޻K3fP``}Yɓ5#F$Ի66jԨֺUhХl6+""(H^^Z|}RRkG㣘wX`uwEAAAZd ]vF)'''yyy駟ƍ4%]999ɑƍ{V}O'|nݺ1[rV\Y'O6uT)--d$ܹsZ~8* 8PO?/^,IuvWTJJۧoFw}{1͜9S...T}Svhr$[n5e]Iz6mڤ{D8pƏ &4WcyK_Ν;;Su}3ߍ}i&-ZH ƍe;ڵkݻ?ϟ/777M}o˕!yyyٯlVFFO={{].vTQQ3gꫯ4dٺp$W*..NR>@ w.((H޽{5qfh1ժJ>>>JMMաCiӦ?m68qB<駟*33SÆ Ç-yyy7-﯐ݻWzg[$ܹSСCO+Iڱc-VSO=Dyzzj˖-zg#Sff4$ 0@Ԋ+ӯ_?ܹS3<#I裏]JLLŋoi]OOO*%%EotE]^ck5gk :TlDC m9m޽%I.\w6f` .th_~x -]TF7Nj*ʕ+:~VZUvر8ы/X>ZDsKWsȵlcp2:4&..NӬY@6m}oӌ31c>c+229WWW-X~ܫW/?^aaa2Lڽ{wsiٲe={4qDs=^7**JJJJ@g~̘1ڹs֭[uIx;vO[jǎڱcGyi漷#FUPPPuIҨQZ=#c ֑#GUVyB6]^^)egg0΍ۍ7*%%Ev풯$X&Lٳ5sL"uMVUcn'pú{??4[ѣGl6ŋuU} z!FEEۻNjdRdddfP?~[IIIJJJsW^5kAp޺)!!A?O.In4 Ĩo߾z_Z?k̙2:"Z%իWKΝ+??4\AE(he-}otLFi&9s( ti555zw!͟?_yyyFtp4\0m6c#GW|}}siƍ*--դIM+Vڵk>c;VC }JOOo :xW>Q]ѣuaӄ ZuN:#!phEEEO EDD]ѣG}vرCFt$ѱlphдiӌ ]K/$M8(?ז-[7*44]_~uMڛjb1:Ц@6PVo>۷OWn݌Ξ=۷k˖-:~YfiذaX,Z @[.իz饗__=zq/O<==7|SAAA|h"}Fp """.Z!!!4: Tݵ}v{FGFhhڴiFp jkk.UV2:ׯycthfYqsmSNi;z͕$jҤI<'.lOzz: SՕ)33SO=|}}fx5j\ѣJNN֎;T[[ɓ'kРA6lX+%[Cw}lm۶Mw{VtMM[JK,QxxL&$),,Lʒ-jkku͞=[ޚ:u;믿O'O˺5fEGGݽ5lMtjÆ ڿ裏j ^5m"~Jh߾}otw̙3b\}[fY>}zԗػþ(F9Jnf 㒙i)R ).c9)j.a4f[&$~#e9wp$-""""rW(BDD6Xx1qqq:u*WLF ӾVҒyؾ};'Oh4R|y֭?O߾}-6`̝;wy/{λqŝE|."""־}{<Oi;x gϞQFTV3g2|,_+W0a„"͙Fhh(gϞ5mذk׮Y9F#'))\믿`OyƍIOOjæMx嗋t""""""""""""""w_;w:ЬY3͛Grr2FΜ9ʕ+ر#/W\uÇӰaCfϞ͑#G ''Oxx8?8+WƥKlܩDy233mׯsƍ띜l)`ݺuׯk׮|9xvٳرcG[d gϞZj,^]v1gRRReμ'g$$$.]JRR,[~h~iÚ5kWU 2S[R…H>~74iBll,<>|tHNNfĉ-[өS'mcܹDFF{z*lٲ^z+WУGM]w*77f8"#Go֡ڻw/o&<ñ9???[lI ؼy3ׯ_ ;;͛7Sre7oٻw/'66O>)Sp"ǵm6F4hЀw}ת̹yf"""]6ԬY{_B ? c=f5N5,ڈؒpqZhU(_E}:uK.4k֌Yf1h E`X|9:uX"[uߟٳg3i$VZePEm۶uֱyf 8}4K.eɒ%$''Sn] BݺumΝ;pBvAVعs'/_&,, {{{ ‘#G(NR3gx'-ʟyw2ӧ~7k… -[֪FDDDDDDDDDDDDDĖt…N:EXXիW///zIRRR mn@nݨTNNNԪU#GZuǎRR%bbb->npdzEժUqrrjժݛB n1UVINسgORRR߿?8;;S|y}YƏϥKS S3Ѯ]B5j޺ԩS<쳸/ZUD=\2NNN4hЀk8WIdJs}EJCnn.#Fm۶u8""RL jՊo|~ȑ#5 ///[hs _K77OK.~SNȑ#TV`ƍGttt2%Jܚ0`;v y2lgg?Mʔ)"""""""""""""p!""6c:vȕ+We,[V\I5ŋy71?~)Si&v؁;K.TPs6lhQn:uFFFXx1_}V*p?@˖- 33kײqFmF&MmK֭IKK3FYhwJ*ۭJ~իW,^Ǯ^zޛWhh(0l޼Ν;[<йsg>}UiHiꫯHHH`߾}EDDJ͍+CpttuHGyƍObb"۷oET\f,XOOO0&&MܪZj?~o.OLLj{'szyyq)֮]{+˗XE˗mDDDDDDDDDDDDDDlM'\M]p]Ɛ!CHII!##]vѧOF#AAArss"""3 GNNĉFoߎ7`ʔ)qqq Eggg6m,55ݻAΝILL$++D:w̵kxWHMMwPyv۶mVZF&MdvȐ!ѷo_RRR0uVׯɓ'?~|ŖWI7_~iӆ3gč7 ϴַ^痔¡C|2ӦM@K 2?Çiժ (Ҝ)Zׯ3j(xm@Yb;wVE)yɡwFvo]va4INN&<<\70۷ ""Çy s9MO>}\ѣINN&'''Gmԩ<)V2S[R…ٳ9wF⣏>7nܹs>>+W-[2j(;I+<<___<<ѢZjV'lcOpp0G5'''i`ԩCjj*aaa4nܘ^zQn]EtE`` /"p5jpAiԨڵcɒ%0d8=)f͚DDDDDDDDDDDDDD&%\M[A[ߧO6mT/_GdggӮ];&OlQehϏ\N8a.L2ŸK7ow[;;;F@lllZ6`&jժСC_u>>>rR-``ԩEbѮZjnݚ_|;Tj坻4ҥKٳ={IOOŅ8}BcڵkXoI/\`?TRqn|(ZYDDDo7n`۶m,Y,-& IDAT:t@Ϟ=ԩζԳgO򽖒5kgժUΞ=K.]ׯ9y[DD=@TT[EDDDDDDDDDDJt…ԭݼy󈎎lٲ^:ߍW^~b7EjmqP`FٲeIoAzMLL 40/,Z_~sR-;]ʗ/O۶m '66TCff&cƌ)qrrOo߾|x>{"""b{YYYֻSn{= 8H"##?iqr)BDDl}n`0СCaÆqA /tϟoU`F沆 ҦMRSSyWIOO/p3gÆ 3kSr >7n 22֭[{QԨQÇJ3_޽?~<,tɓ'дiSrSr˭K/ӦM#77ע.77DI^~ E_eADO+77;vЯ_?T޽{mH1m4MF=l%\M 8rOٳglݺ~k@DDϚ5k1cO>$m7&0ggg.\ȨQHOO3faJ03g=2c ?Nvv6$&&AxxӜe˖e֭h$))@mۆ ghڔԭ[76o̵k&11 [I/$$Ο?OÆ y7ʕ+￳~z2e ?b2eCvv6FcqۗUi&uƑ#G~:IIIڵ(ZϞHQtEo ;Ƹqxi޼9vbر"""""""""""""""rg YDD,[={u^ׯk׮ddd;g}ƀ~~~۷1k'4iw}Eybb"8=GJXv-ݺu#++˪ٙ˗ӥKrSHA?2>lJWgs<> VZ;{n޽;{'uhZ={ ***k?@TTE^ :?Jjptt\riӆM6Ym?vX 矧|899Qn]&N֭[-|}}9ts̡}xyy舋 kצ_~8p d _|xyys %]xw_>888ó,-J;'7ndÆ kԩS777QF?GZ%[,\>h\)xyLJ|zQW=Z.\`PDDY&ׯL6M"""""""""""""""wN(%CRִiSz-[رcx{{Svm~g[sG?Ϸ`6 :ŋA0aϟ'k׮ɉN:1}t<<<,3p@qvv^`ԩxyy87իW4iќ={///zɘ1c,4ΒuAΝ;quuƍrJsrssq_~%'O ___x Se+;bٲet͖a5+V """""""""""Xbv?+Vh0D>FFFG7o>MA1gĉY&}{n&U|ٱpB-2[t)qqq߿OO|$ s٩S`Ϟ=lܸ;;˃JgI 1:rH>Chd޽+W0tBY>}(z-mQF\~a5ݺuzCDDDDDDDDDD侠R7 ׿`ԩSWWW`>!>䄿9 &&9/xqpp~2.]Zjqdӧ3sLsrŅ  2eG駟r9 @nn.'N(ȟANNׯ'88~SR%bbb8{-DDDDDDDDDDDDDDD:.yWlSӦMR) p!Mƍ9y$ׯ_iӦ <ƍ:L)e>ѣGIDD""W_}֭[SV-["EШQ#%[_Znݨ^ %\EQQQ: )={: صk۷P^ԨQ'OcJ:WzXvm$$$ʕ+2e CU…<233qqq)\r+WF$w⭷i""""""""""""""Qv@DDDD",,~ׯcsbA= K/&55Çc0hժUw72 =z\VV- 3g$--zz ybȃƍ|PR%m!p!""""rTRƍР9UVsN}Y:777MVjݍ*UĹsS='Owޡ 8ZoѢ݃ȽŋYlOϏɓ'SJ[&"""""""""""""""wH "T~vMVVё3f7;vdĈv?""w͛ywٷoիWgϞԭ[֡H)Q…Xcq)rrr\25"$$^x!R3!!y}vNc>b-nyiս{wwn.44B9;;O0uTZlCR 1;w{&66֪̙39s+WҡC <<>S`^~e6aaaKi'RAAA: RѼys7on0DDDDDDDDDDDDDDD.R…oyG:t(?<߰ĉXS~z:uĖ-[ppG(ΝKdd$1@j֬ .]dƌ|у;wgEJU\\l܁h[ uD6ml]q1-[ƈ#prru8"""""""""""""""b#v@!!!?~-Zpa~mׯ+NNNԩSpvI5k~`|,_qO=+VuЯ_?_ΤIlH;}4+Vu"R+Vϯeff2`V\iPDDJՅ ={6<̚5[%"""""""""""""""6 lԩSlذ~ *ЪU+FM ێkq)Sضm/_Zjt֍pʔ)cncbccT111/_9|}}߿?seРAL<-[SR%ڴiѣy \ˈ#صk...4k֌p6lh/%%iӦe~\]]U:ubCqc+LqϴI]v;j(fϞͶm,Ikzgff2sLk>˗)_<5bl2wMSP}I/dĉ=z*Uжm[F~oɓLVXvm1ݣ73رwwwǜ9s3f &Lfeew^6l|ݺut֍ >Zݻiٲ%NNNl۶&MK֭IKK75j{nTR*#RUǏgلw~ [\hٲ%/5kرcۦ8 %Y83gdV}\]]Yjm۶5~oUV|w,_ƴ8***k)>mgkypYL.^HZ4hP~oEFF2bZh믿/Lٲem'l_ͅ ڵ+iii 2222صk}h4įj/77+""\?o<'N_~пN8hdx{{sLbn /P{pvviӦtޝ :wLbb"YYY$&&ҹsg]+Bjjjcǵkضmjh42i$C !--}h$==[R~}N|8vvvlٲCrhٲ%FD˜N_ypuuٙFpbY]y6nH prr^z\֭[sfϞmn{/TZT]_?sY}5lؐ6m0|pz|yСC:tgHDΜ9ç~ѣu8""E)yUXիߣhDDDDDDDDDDDDDDDA{lݺu 4(>}iӦǸ|2=z ;;v1yd-[0p@~~~r siJ2eq'6o ;#Ύ#FoVe 6ʕ+ժUCDEE/|||ٳ[^%]?ԩS9x Æ իW\rMDDDDDDDDDDDDDDDPJn=͛Gtt4e˖exzzZz*P+LEjmqmJ(h#KٲevZ...EwXl_Xh/2[^w~y/_mNll,ӇLƌSyKjժEZԩ&MbENwM2%TnQ~'V[a`ggGժUͧw}΅ r9wn.ѣΝc…w}~ٱdmͽ'IWu]'|~5kFJJ 񄅅7(3p%Frrr9rc0Xt)/tS4k 7ѣGXņ;S˗s%K/ľ}8u , 44ڵkp1ݕJ~eʔ`0p̙B.[,6e˖ѽ{w?Nݺu3f g=zHc$Mh/ΚUԴ.˗7Í75k4i҄͛ªUm&kM0}~ZjE4c=X7olْƍӱcG"##Ο?τ hݺ5[a˗/;+W6?|;:HDDDё&MGJJ jղuX"""""""""""""""'{tΝ;/33ݻԩSmMK4M3g,fޯ+W`0ܳgO}Lo/M/իW'$$?vZmvWb+^  IDAT=Sv;NNN "y5kGa„ ҩS'NnܸQxng! ǎmI^?Sgk.+O?yqi_Nzz:bҤIDEEi>4œvXԩ3e˖I&̛7Ϣڷoٳy,SJڷo8ߦh :t(6l$00B`Vu jԨa.kذ!mڴ!55W_}5ߍ&gΜ!22;;; f.o׮SN~ "##hݺuE50 >|ت.ʥ[I֯w?:ɓhڴEyKy^룏>2Q<==T,Xo]"##N6?E%_󈉉`ڵ۷3rHK,j֬I||<&L(tl9ĉhҤ/`ȑdzsNfϞ ;,YٳgV/f׮]̙3WUFDDDJߠAOIKKŋL8E_ΥK$m9`Yp!F~#==|) dΜ9MX7nkFRR۷w^ׯOll,| SLn9t˨Qё Z?cYՙLmDDDٳ~ sb'99tƍ`>-uKVVԨQ'O2mڴ6m 4jԈpu>LӦMٲeK %$sթSGn>tr_ޤ\9sذaYYY>}z"s1}tWԩSE+"""""""""""""""R Z^J`0e\~u^ׯk׮>ck???w. ӧp-}...剉u{{{Fm77t֍,:ggg/_N.],M#} r 7ȑ#Z*K3ŋ޽;6mʷϧk׮&̝;|3f ˗/'%%_~5kFff՘s1wkbzK.%88تOJذa 40~o9ٳ'ps#~R|˖-gϞ~I$$$$i&ƏoYvqq!44 {lΝV `ooO xg۷?`Ȑ!~Mc4\N-6nܘ|3Ȯ] {L"wEQEDnh7Ζ?O>$׮]3'/ʕټy3m۶^z$%%;SO=9~8};7-Z0~qd}?<=vvv{?>(gϞm۶k׎.]Pf–,֬YҥKٙ]ӢE c:t?Hhh(ժUёrѦM6mdYرcŞ#44Dݺu8q"[nJСC̙3兣#...Ԯ]~q|-^|EOpp0^^^888믿΁JÃ]vR~}\]]qppۛ~X!4c+xzzqF6lkF:upss5j9zU… i߾=888裏зo_/^O?3oa„ 3Yfi<<>>N:鉓5oo߾&&={$::ȣ>ʀ駟,-~`UXy۶meر4gǎIMMeƍTXbӮ];Xvmb)M:O>aȑ=zjժ:RU 7댌 v)d[{ 9NsŋZ?$"";oFNN5jɓZ})3r.OOOBBBcϞ=1/2tTRE"""""""""""""""rQ…<0z|@iҤ GAvS'yK=-[0vX ѣdSѸqczEݺu|HLL35k֬oEDJdd$YYY9֡|8VZZ|wc.Sk߃jժ``̙\pӧOuV2AVDDDDDDDDDDDDDDDA $$$o]`` cǎnݺ899DZݻ7Ǐ76lUVX1>mꊓ>>>L<0K3g]v'''ڴicNɫ]vc;vPLڴiS""׹s9r$*Tu8"*Uиqch޼9OϏAgȑԭ[;w舗1mڴRnUR%)\4yHŊڵ+{<*"""""""""""""""[ ""R:uSNi۶-m۶(+(vu)[,֙.L9r՛oݝ ϟٳgZ*gϞ_~+N4ieʔ᭷޲u("իWӫW/6mDʕ b̘1ا\rܹ &_sY<<>>fGR(0ɵkԬY3(P@?.^֭[hѢZn2'N\rn˗/׮]$Ij߾}FF<ŋS0~L7;t#GjJ=zP*U̎eQpa#GH*U0]re2e&m&՚}͞=[˖-aСʖ-իgxNԘ4igϮwy(I@@̎幛QXmQm۶Lh9Rm۶|||ԦM1B ~w͞=[Æ S|̎ ۧI&@EX,… %IsΕbҥK%If͒b13&k׮cǎN:ڵk 613ԴiSY,]zթ߅ ;8t,^ztϝ˗kРA4h/_njik̘1*Vov)kɪP,,X7o G#?| W;vԺuEDDhڴij޼|}}բE M>]l:uJ 4h':9sM6S^xSWvX׽~*SJ;mGDDhҥzgUhQ{bŊ f"""8+V$;vi^hh$SsN>GuX8ٳgkȐ!~aEEEiqT .:w0}7rf\DGGkȑj۶6mhĈsܹsرcmׯrέUVʕ+5k|}}͎ȠG$U\tz[`/UXQV+H.\3gΨx RXXSN EVdIZJ;wT^$I[l_j$i֬Y {I-[&I' Pz)ܹScǎMNl۶7WPi6WorZ$6ETT8\rgϞʕ+٣X~f\ڵkرSNv횂M m̙S F˗/kjժ},d2&{ӛC Q%+W. >\VU|󍽟PbZgϮjժiذa͛7;{С*QoOϕ+$)$$D˗/?mjj͚5ߥKT=lvĉ-(WRH{ .bQ=#ŢM69lR>LDDM͛W-Z鰜c_okرjР4b~lS;wvʕ+|}}P䕐Ǐ;'>^$irwwΝ;[Qjժ\ri…:s挊/ )00P>>>:uϟﴽzJ;wرc%I-ҥKOh ܹsuIem;vvos='777 [IYd$Ν;?/$رiP͜9Saaa ._)c 3 C;wT~㏫SN״i7@&GEZ;w$rʲZ5k$FZOzz%INJ$nM{{{jS˖- { S>CJnݲڷ+ $ݼyi@Fw{m\wVxxZj{^z-[HU*{V &IڼyS.]8wmݺU4l0UTIٳgW5;-k+NPovʖ-"EH~Q|y]|YgϞu<۷o޽{UbE_^|&O,ItZޓgϮUGI:q$dɒNF3o<=WXXF .hݺuܹs(`+Wr:#ް>uT]zU1112e,^y{uJ&LC)..Nĉ%I?|ݪU+Y,}׊O?eJr=:ƅ ΂ JV^h9sF&MJ~vr$IϟwZ@hذ7n ٳ}]/Hd IDAT$ҥKjժ9g$]|i[/JVrww [!C?۴mѣGO*_nݺ[n?~-[3gHraz%Iׯ_$͛iy[!66B)djٲw͛7… իC%J8%G5aM4ɩ(F ,ׯM6ڵk]gݺuj*}%I~~~N߮si۶m:rCN05(4m WTVM׵uVծ][ 3;w˕+J*h|Xe˖իʿRp$SUX1BBB.] xt.\X5jPLLʕ+EJJ,?JHHPF޽J(K.W^U^te(QBzvtb/H۷|}}ս{w/_e[ݻ%[⊭`dϞ=ݏdԨQS.]o?~ܡBԣGO>z*V:2֖vf̘w}ס @ܺuK!!!jԨJ()S_?N8AC.2)Œ.Ml_Μ95zh[ڵ$i͚59srar:qTƍeZҥKU^=y*88X_|nݪ[ V ԧO˗ル<==5w\͚5K?nݺ_|QÇ׆ WT\W!C(..N;vP||~iuEgϞܹsl2mN>]|vڥB iӦݻ<==}4i?X;vPncɓG5JV>7nͫ3; PݻV\f͚iٲejѢ̎ favBBBr:(ȼ/^}IggΜQ 4k,8Cٳʛ7{1 1E&EaDB̺w^!!!:tեKH'T^̎doNrĊ'|2 3q7;r̩ѣGk͚5r劮\5khʑ#$Ø1cO?Ãj )o_֭[|JHH0;2!v5kԀ4uTI믿5j @rxf20-\P˗/͛7U~}?^ rw}pD)՚i0Ϝ9s4}t|X˗Wniv4H4dŋkźqׯw}W Ird$wm69rڶm+oooM61b38%@O>DCU͎ٳUB駟~СCu9mڴIݺu &X,X,fHWv:vhoԩ]`d-ӶmoHG 6jձc'0;`K3gThhUtiuMÆ $YV{ߨ(jӦM?c饗^R޽)IE#V"""tR=*ZObdXtRuUy͈jԨav Fiv t-[֭SxxܹǏۋ-k|ܹ+W(((Hoֆ %???y~~~ƍlZh14C#($$D/^s:@aW_رc\/^ݻwk^٣5kHrjڧw)IPӺmm>k׮iƌ^V>E@VAEX,-[HU*{QFwӦM &lٲʖ-z)=Znݺ$u IRɒ%*UʡZb7oŋk̘1Umۦ_~E3 ?^38רQé $I-[tSN%ׯK4f kݺ6mڤ&Mh…jݺriv,@{nߣڵkDf j:LF=#0v>Lrmrkks]+>>^ٲe3;`7qD(̙3xbcLcGO<ӧO_~QZS_ooo?^k׮wUpa]zU7oT…ݼy6oެ~i*TqIR͎x($$F@f<z5i98>|X'Nt[^=Iuq'|"Ţ~ rʕ$?iݶ6[a6lʔ)Cҝaھ}z^x8@Ν;~йsԣG$C[nաCԥKy9r զMy{{kڵzm69rD5jpXȑ#>mv !jϞ=ZfGCZ`-ZsΩf͚ѣN}> ޽^SڵUD cp_\̌r̩sjھ}"##SOK.5j<==}ɣ ͛7O[lѵkה;wnըQCW2e}O?TW^Ull$I&㏵cu!ǎ;'OWBBF6m8iaѢE;wv)ooouY]vU*U̎x͜9S/6; ( B iԨQmW\$=cӠA4hР$ٸqc5nء-w P``.]ŋK.]_~ʕ+׃Ceٲe:z,Ybv iyl|d f Ȃ:t Ţu7ٳgi&Cy1;k׮Yfz5o<?~\ъŋrJhB͛7Wxxq!CVZ/믿*::Z￵sN1BO?V\l߾}u R#qu-t]uٖ{X= i\@Իwo4rH(QH$zϟW͚5;wn%1=&w/+*{*R:t#Gw̿ߵУGIR```io럚s6}${bˑSR YؔiM!!! $XDRD] $)$$HUViѢEڼy{1uQ3f̐;u׽O;vP-4/GZr5kОԃْ3gNEEE٧,XW_}UN}yرCs$Osȑ#5v$#Io޽{UV-yzzۿ{kNNΝ[WVÆ ]׮]Tn]8֭[Fܻw4hJ*]vOl:5t:s挾 enW:a(""Bu]~͚5jѢKҺuԶm[qĉzl4cyfIRtTg{ؖ2eK_ucοߵpmy{{ƍ:}|I~gΜQ2eT`A]rEo~sc`ĮA[w̄'w}O͎gϞV޽;wnZJ/^'|Bնm[EDDh:y򤢣޽{+66Vrra8}&L`?os;vL InvM4IWJ(h׮]S Ї~SrO(::Z:tum8p@5Jt;ɓ:|n޼iӦ=PH1۰a]v)&&FGU˖-umuEg3IԱcG  aԩ<==OF]3;6zpu %Hi>|dO@@;0 @zz+W.㣏>2; LҾ}{f͚ƬY8d{'L`H2r=LrMXXaH2 0oС$CNݻאd*Uޖ;wnCq$aÆzz/6͛7 8ȑÐd?N9rĐdY%$$C 1'O_4}㧟~2\U0%K}9;y!ȕ+WKq7n!h֬2w1ԩ2f/6M=%*WlDEE9̻;vlr$7+w6$8x$c޽a<_Y̽ϽW= @fRQHH˷'}`?P믿nvdZz7TP!i}7x޽{K6nܘ:n޼N:)..NM4ĉ㏒8-kXdΞ=ko$ɓ'{hӦMC:tw}W~z˻RZ$IO<$Yf nWR%K.Yiʔ):tʕ+Mڶm&N \rھ}}s؜;wNaFN[h IDAT|II;}РANxxx؏cZg|R%9RrL6rH̙ӡ˖9=ժUK*Tŋay6lХKTreY,I~nǬk^zpu yx]pAsմiӜC||N:r%'Gرc$oo$#ݸqC{ў={sNm߾]OV&M5k7Μ9GjϞ=ڽ{<(I2 #eRrWIJ4odؤuĤ-}YIS)%w{Oz饗큁܏Y̽ +0>}iȑ#ꫯh"/:LRoONyiʛ7[,XЩOddXQLYV?~\kN2qqqߟh#""$)тyJnݺr~J^УGϟ_Ǐ%Iϟtڸqz4v=w+P7nƍs4Hȑ#nݺdmkٲe6lΜ9wKqGW…]A2ʕ+MOj_,clϗ/}/[׮]5|pYF)?Sk׮tAu$#W YO<,}ĉ[| Ai mL6MӦMSllԩS ֨Q={,T%KW_Վ;( ޔ '>>i_UoW_bŊIn#x? 6$o… ;)@VjTV\)04zh=Sڵ|My{{W*UuV={VcǎUҥ͎CL29EĨcǎҘ1cԲeDȑdcǎ?&|7 6rݻw;K+%JPϞ='Nhڵ[KԜjժIݏ&qqqZ~(I3g~W;VzR˖-F8IHHHv |vrmȘ,i߾}.mmׁ&QQQN˜>}C`IRppCMz_?1@fC#jjCm69rڶm+oooM61b38%@]rEjժO Ҕ)Sav<___}嗺r劂/2iiӦ}C˗/5k>x`:twԫWO4ȑ#rssSRmjRFtUu6/^ԩSۛ4i"I2eC :u$AIfORJMGuԖRsl3FJr'N$;ۊ[)IrBӧNKjJ4i$#؎#cjiӦ9kɒ ,(u@PPPIZ[VT@>|X!!!:z *TOF_3?,,12`]vf Iԩ]f@f3gΨy jU94{l-Y0dm;wVnր?~ܹSM6՞={-[_~ڵ<<<4a2k֬ѧ~Uj…#KkK6lEEEiYsUre}:s#G裏>b_#F8^S޼yeiFǎSll;6mh֭ʕ+x>:u$kN6mҭ[#G( @ #:[j_Ϟ=秿[jқoP+>>^֭[6mhИ1ck}ͪUXI![(>>^GUnfSsk֎;Լys/վ}DG1H֭͒[:㊍աCԢE 'T^ۊjP4h>Dصp9rC~[ҿ*6}d5ر4! It:15k4j֬x?7^yx=z|rgq-c̙/l-Z0>SN9a?1`k?o 0# iRjǏ;7FŊ OOOw1")QQQˍѣGVJ~?9s4$|gk֬h߻?w 4\SO?6ef5~Yr˿Ź~7o4*ThŋΝKl)=aׯ_77n|s/_>cŊN׭[;wn9r|~| 0Œ … ].^S%ڗ/_n,X)KbŌC9-w^#G.}صg޽N}ܸjk&c'[<_={͛ .Ν;Ç5~x_ll ˺s玮\ I*I6lPTTˡ7H'VΜ9UL֭[_~ɓ5m4)RD/_6)0 }'OraaaׯթS'߿ _ftAKOWŊ3gNyxxL2zwt,Y2ݲIRaڵʕ+\r]Sڵ5foj۶jڴr-?$G ,P|aÆ4vX9R4gΜD_~Q>}DZB Zxvrʘ,]vںu,<<Ӊj{ĶYn]EFFj֬YX,s֭[I&Gk֬IQ }g\ ҥK0a<#Fj;vhܹQC}_~z4}=PxtYCNCՏ?ޝ՜iggBb0ֆ,e1Ѡ ɾ `B#;ed-Q4Ȯ"i{n>9|L{˗/ЫW/9tZKlllۛۧYݻlܸ7r- D߾}122ʥB!B/|>/ė)_|ESė'+B!Bmv_M+`h:  իWN6mݻ*09s(_<ժUcٓō7VRJ!Bիԭ[Wxdd$]vÇ\xQ-TdO@@st.FKiܸqn*B!B!B!B!tоcǒ?~Xd }Ņ,ջ{.VVV)_$4y9EU+SSB!ˮ]}HH͚5JEsqqYfTZf͚ſKRRR֮]Yx$[!B!B!B!B!Iu/^Tyw<7XZZrAׯO\\Vk׮ڵ+իWi+Q<uB!򪨨(߿Oڵ|}}iѢ_}TZU~^O<֖ӧOf f}SSSׯώ;h׮].E)D湹?j; ![[[m!B!B!B!y$\|4%yXYYaeenی344d?>zXZZ+\0[*T@DD >B B!6g:wh>~~~4k .peybF~PBsVX!<]!!?CB!B!B!B+&&&lٲEa!B!#KHHݸB!B!y$\&Nȋ/r9b3*O^B!Df,[ӧOk; !?L˖-B!B.IB!j; !(;;;m Ǐcoo߿ٵk]ve֭j!OW\\+μ{N˗?3|Ǝ˜9sϱ cʮ˧@K!sαclllBdǎSa!B!" B!ĉ $#ٽ{Bd;vB!BΝ;̞=C#J,Ivpttvj3Z`.^9qQQQcccԩS)RL2xxx%[|nݺ̛7#F?%\0w\y eʔcǎ8::bbbu%''s&Mٳg)PL:&M eѢEx{{s= ,Hձ_~x --ׯ_g͚5)R///V7niҤ ˖-c̘1TVMi<)$''~z/BCC)^8ڵcڴiԭ[7ݾr"3xm ]vݻWYhoߦJ*vvv$$$0{l֭[ǣG^:'NdРAjĿKPPQQQ/^MoѦMgD!B!B!B!2G.>m 6m05< @a!ȣv>>>|wDGG+EFF憇v+X7nd$%%)3|9 `˖-1%Kۗ=uQKؿ?666yFylܸ;w{n:tΝM6'ݻÇs 5k{ڷoOLLX||wwwm Bŋ7Na!ȣ$"y9{&&&q1j(*VH@@֭[[[_Ν˔)SXvIJJbĈL4 *燃̟?3fpiu떡kȟ?dH˛7oѣgĄP~ 88Jt҅_ r̭[5kW7n111 :'Rre9wG&88?UVHl;q={*ӇիW흭 MXfʔ)tR4h[ٳgvvvRL\%{CCCz**URIQXr%ׯ۷ <}ѯ_?pqqƆ/^0tP>̲eT.͛˗SWQFq8{,gV&\|B!_ɓJZx-GU9 N:ũSر#'Z37b oNrr2}Ԕ h;4!B!B Dakk"WݺuK!!C# yyիy1̚5Kysss-ʒ%KXrJyJ~~~o*˜y-}Iy‚[߲yfeŝ;w믳|]˗/իWmtttStЁǏb ժU+X[n?CvU IDAT{%,X@קM6Sn]<== ٍCYԮ]; ԯ_7of]vԪUcǎ)wL]6r6mZĒc>L@}:u*uP|Ŋ*Ο?}s,Y A(R7jի*POݴi5Roڴ)6mĄt[!BH.8yd1{l=J"E2dڵ\rDEE燳3^^^+Dy-͛7L6޽{+ܭ:u*;vPQ!B!B$#ٳ!D?j;!B!Rةa̘1ˇ ’%K8rHׯtԉs窔{{{0j(fffjyx?Q<8qr&MXbi;%ŤM-|,ӦMS߿?.2+uiBgSSS[Zj}vZ*B!_333 M 8pPJeYɒ%ڵ+ۗлwoի?c<֯_?n5B!B!Cpبb(ȻvޭB!HUpp0r5(vEdذaܾ}5juVtuuU€퐐CCC^|ILLLRƫHHIq\[J5jP;Vpa޽{r|ʔ) 4grY}F޽;}9ۇr *īW2=/_Y%|Z,)gғHIMRT~Gq)}} ;w -B{.z=z<<<066ѣر(]4mڴaԨQ*THc=={ʕ+9y$o޼]vL2EcT_S_[///TdIXl2B3g7o^^^вeK~gJ.R/e'&&5kp1={Fҥi׮Æ Syhm6/^L`` C;V;֬YÑ#Gx!T^=zгgO~mƷ~Kٲeǿ+ضmhѢH!B!B !By eʔvBKU񡔻5dڵkqwwhѢxzzRD :^2>QF\x6m6*+Pk P+VYfqeݻdž ذaիWȑ#j d5erei֬Y`bb6٥pb ųe>6 O!$IOiپ};SL!<<xf/wޝs99u Ν;Szui zt%KvYUeRKS}%%%~: c˖-Ԯ];>2:9x?%#n޼IRSSLfWLII["twLMMucǎ(eu w@5k !...S}3ŋZ,`Vѷo_éUӦMcݺuxzzrM%BW)&߿_ݻ7[n`ɜ9s___V^ Oۼy3qFΞ=˚5k4@>?ŋʟlBpp0u͍sN 8<{Q{ .{+VjeOfٲe={ʗ/σزeKqi&éP...={uQ|yذaZʕ+3gpppPW{9{,Nbde3g_8#B!B!Dj$B_UZLJX~ &|rr9B!gϞ@>}ؾ};n".."##9tC ayz%*>>3fо}{r $%%M`` V}̜9xmi^e}:@݇; jH֔ =yd7o>S.oWԯ_)Sp16'NRJϟ_㇟(vpuuݝ/^лwo.^xX,rj}TREB!B! #N<7o6m{ȈcmmԩSyM.G)SSzɓ')W;&((?~< ĉ 6L*Bxٸq#:::ݛ 6pn޼ɥKشir2 $.Rs֭\V׍78<7o}} &hr;\Cv]]]<==ymu߾}˞={եgϞ90ҹsgDrwwwG׮]UO0@mu֩]v|)'4i҄;I>}4NW> .DGG &(w  M .R߭!3TB| R+k޼ڱ-+F38:wj ϟk׮3rH %JPK%*dҚ̿h"cIIIʉcr#g0߿Zŋs1^B!===zAttr___; 5k۷o'<<МP^= 6T>޽ J3ߍe˖Çi3""BU~nР(E)6&<׎;ǒ%Kӧ...j;=vRSB!B!"5pe)Wܬ_Ǐ+W>ׯ?fZL!ħfĉܻwM*wQ @__jժ1zhv܉!ΝUa2͛ǹsP/‚%KKiѢ ,Ãrq9ӣTR4oޜ5k0l0qtt^ʔ)>|8ͺ"::VZQL\P5jŊ̙3tܙ>|8GOO9s(ٳ+WR^=6mڤ&#G$_)S#bcc9v=J5kPtieԩ*lFIѢE9~8Opp0֜8qB 1f̘la~ˋׯ_ȵkװӱe$:A4h<{D>}ʑ#GE<|6mhLhٲ%Æ q-ƏϪUR]8p>}B||<|w>}U1cɬ|RJGDPP P&>1K!B.^Jͪ` ~:qCiw^BƇ;d(=fE䐔+;eWZ^ҒP~}Xj]ve׮]jm5Ŭ8{e!B!B!GV|޽{ǚ5k8r>D__իӣGcccYn^^^|D OOO (kdVn>Y5qD NNN*eӦMc۶mrer|B!T/_sssΜ9õk8u[Vx˚b6n&R266&<<˗/w5Ȉ;ww^ҌW^8pcaas7oi&;|@ժU;smT (++ ʊ`=ƍYxRJITTJRi#B!B!DZd/Њ+Xv-w%!!X^ʬYTVgĈlܸÇqqqaرi<pabccU>\Vh޼99r$ǯO!D]p]m6>|HBBO}_6*bee֭[ocbb {<}4bK)ݝwѯ_t-j׮ ޽9wV9r W)|5666̞= .Kx%'Nرc;+qiz}x93|p :tXbq=uݻǹs(^8:tkĉ IIIܹs3g쬱Lj+;I ͛7,X0S ڵ+888`ll>Ŋcǎ9r#GO---jׯs.\===*VVƆ'N`ffժU~ի|7KV3UCeƍ4hЀchhHطo3f`ڴij>x !B|*zERRӻwoΞ=K||$&&LO=ž;w 5kΝ;jPSB!B!"5p`={SN)W)ݾ}ޖ-[nݺq9iРϟgϞ=mk23yT!Dx%G888p1ٹs'}!!!ccvnR{M0AY*ё$lmm9y$7n`۶mT\`V^ݢR1=|~gС"$$CѡCbcc駟xsN4֭[εkpssRJ$$$b fۗcǎq pssFܿe˖XlT,͈ݻώĝqV< >g& jZ)Cabb;AAA\~]vѰaCYjUxDGG3vXeÇ޽{i֬rhJ|w$''cuvArr2ݻwG__?GUϟ+[nxyy)e˖\Rcƕ޳}u4řT888`nn}:H7n Bc֭<{QFHʕɟ?? 6dΜ9Ö-[>nݺ1sL*V~-7<O4̪M69NNN NNN͛5oҤ NNN4nܘ ҴiSe˗U*4i+WFOO дiSD{ooCYdbDQ~iiJܙg&R`ѢE4nܘ ```@ XhY۷ 5k5j@__ڵkaÆ4WիvRY-));wkd֭ЦM-[FjՔt\}.nj)E\r!B!"p0MtttY[[+wcP߰`PNΝ˰aEb``5kݻr;j\ }N0 *K||<E[[[А6mhyxb,,,(^8:::(QVZxbT/^L˖-ӣlٲ IDAT 0ggg u4řRѢEY~=?e˖EWWeү_?6l؀aCԪU  ^:*+vԉB v)x!B!Bev";????prr[[[ (  Kϟ?HMIqLQG!DqqJ|||?~:111;$ZjoRN7|@\\8}4ÇGGG5TGGÇlj'4^W^R9ndd۷qpp4iD9ADۇrbccͿRH޼yvd%̎sf3Y/S"[ԩSUX߿de<=j]]]FPRQaaaкuke=Tj~N^>je1Çt\}.S)B!B|Ά gEeΜ9SHԡ)ɣpL͛7lӨQ4f$\+5jxF֭A#'sHJB!y !DnkѢ&MvBdٿ?ʄWWW4.$B!B!DJp244TѣGٸq#/V&\qݛYJ"22(J*R#"o۾};p¬YbŊQ쨐*WիWuV&5$%%$z(RKHoŎѫW/-ʊ+ Çڵ]vQR%6mڄqܿUȍ7hڴiܸq@yّ3;ΙLfݻwrʥ[w_6YPܯC gϞ,Zooo?Nɒ%y9GEWW={ϩkDq X^DTd\}. ,B!D8<{k׮E9p@"/)X ӧO_~QHg-[# !B!Bϟ$\|zADD'Ok׮('}z۶mٰaL8^|ɖ-[ؼy3fff8;;wHNNݻTT 5kɝ;w++֬Y37.Y!D&,XW^$˜9s&cԨQ#>^~Mllloz*>>>Jٳ'۷gIѩ-'XZZbiiɃŋ\xw2sL֬Yelْ@<R۷os,n8gVn?3q9fϞ=7իӥK*VH%Q۷pYĤgrhѢNÃ!CAbb"m۶L2Z5)\p;(Rs)dg !ceeŒ%K '_Kƍ5j .`*B!B!ơ7VZѬY3 TR@hڴ):ub(P@9q 5ݻwo7 p5,,,> !Ȏʕ+pL{- o޼aرt!>n޼swȑ#zJe"!000Pcz9|ݛy?G-+~@WW۷k'oߞӧw۶mPWy'޽cq(#Yzfғ֭[ҝrJf͚ő#G7n666tAewޥoVWjlڹ>Իwo<<<عs'rW6VM dLIJJ9W^}.B!ByP,h򹱵eѢE,Z~i;!B!B %jLXZ[[rҤ1d "Eڵk9~8?p4jԈ#FZ>aV\Idd$tԉKÀTbH"t1X!Dfnݚ V\I˖-U)߿??3[Ey|ܹЩS'FfNƍUn޼I.]PNޯ߲eKN>O?ʕ+S]=22 <ުU+]իiٲ2)OtVLW$ fGVСCiZ9-'c366fС8;;իS͍7f͸ѯ_?E4iDCCC^|I`` *e;vȱ3;]޽{2Κ3/&44ʕ+Ӯ]4*vٳZه~T&k񰴴ŋ[-[$A%''v4СܸqOOOBCC)^ZRWN^&;vggg,,,ԞQոR{Vs)B!>7~`ywDB!B!B!ޓ.PVVVlٲ___|}}پ};cƌhѢ* ?~<{ܹs;v $[t;wÇPpalmm  ""BY7""4M!eggGѢEt\ro燣#+L0Aۛ͛7SV-.\2Zv… y)o޼ٳπgϦD3ӧOKRR7oTպu[V㱴ÇX[[3ydΜ9˗/Wo߾$%%e"##)V ,P )SpE޾}ݻw={6[lɱ3;΀oÇDBBBcLZx1Gggg7oڤʗ/Oz)III2a/_GVƣo߾+WƌCXX1j(7t 3gセGԮlٲ\p!Cpuu?S;_d5Ԟռ\ !B3tT !B!B!ėNvٿ?L8WWWrtB!4)WK.ebmmVgƌԮ][ oIܷnJ*̘1'''T5lؐ#FX"nnn9۷o3}t}O?1vX_}K,a̘1x{{Rn``%KPBgȑ#&,,Lʀʕc%?x?n+V`ʕ899cǎTwPb˖-7Ne1cΝ;Gٳqtt̑3;uܹs3FyL\̇WfyBXx" 6 GGG\]]quuU)3f *R(\0˗/ޞCq!6gҤI&Ջ[ Z5)RVSN)wQXpZ"SvJYs)B!+++,Y0==P!B!B!R#QsZno9_`AO/\ewϞ=,[ j,B!2M6۷իWsiCe˖*޽>lllR NNN*UD=:t(jmLMM9x >|?.˗ܜSfM}oߞ{䄯/Ϟ=TRhт#FUEaΝ^///߿OBB+Vcǎ >%K~2{tuu۷/;vLJPbbbӣtҘbnnׯqvv ???vܩ<7|Î;Xl.\ 66:u0fڶm1"+qge,XiӔ;o)S&ͱ̭g&-RjU,,,tj۷o_Ϗ aaaP~} D۶mR &L͍Ν;{Gƍٷo˗/̙3<{jժ1vXڴ;Kܚ3QrEY3ב 82s+sfZD,A$G{V܈{Td("?[|<|<ι뾮}s]ϟsajpppܹs8::MJkM,3w\mݻw)S llEJJ"|.%}=o(W>>>Ybccc3;WA,YzU. |||?gֹsLC$1nnnƕyyyy'W_v-C IteK\v OOOΜ9?K\|SL;5H^ホ^|drT"oSvm>KDVvxqG!Ch Is2dٲecժU8p E EQyYhTf%FWWWrDDDSD C^`DEEuVJ.ʕ+TRG&""""""yJFDDDDDDDDDš IUT 0#GRJgΕ+WXr% .g"oƕ]ED2V?AAA\v *DժUi߾=3@8me+V0uT>l,kڴ)gΜaݺu899='NЪU+ߓCb0%6-{o3k,*"/񨈈,p!"""""bԨQsIϒ% Çvڙȋ+666C,Ydv"{.};wLp͛lذ 6P^={ɓ QJf5jTv1e|}}7nsm۶i^2wo\]]0DD$h<*""""""/@DDDDD^M|ǔ+W9r5kV+F-wޙ;wЮ];v믿_|ƍ9ql޼C;wnvA^%iӆYf=zdGvZfJ6m4sν;HkkCD,G2; WNb=ztf!"""""l\rڵk?/_>e˖4jԈ;rڵk&E,H"ԭ[;vqFZjh 6ׯO"E20JQE:Zz5W0DDDDDDp-5kkƖ-[z*mڴhѢdvx/ӧOSBo___@:u裏224vcΝܹs^{~S\fU;Ƃ ؿ?aaaҬY3<<<ȕ+ޡCعs' d޼y -rttd=+W&H8wg޽ܽ{B ;пJ.u;wG2uT>L٩Y&J* λx"-bϞ=ܸq9r`ooOÆ ޽kHnlIIKLJ?y .… ˗<<w19sZܧ<~ׯ?s̡riڇd5EDDDDDDD2.҉Vy 801+ ;wp}GFF2fڷo-m۶ei{ѿѣ+V'O營fӦM-Zx ϟ믍W\aԨQJ޽)V?ɓ,X!C[ٻ~]Mo߾aÆ 6ҥKsEOΖ-[0`7nH" yٳ'NNN=z#Fpe̙ŋu'NHxx8:uW^(Q'OpƎٳg5kǏOJ{\\| ժUc899qelСCٶm 8tshccC-ϏC&hϏXZl5fĉ/_I&쌕'Odĉ>|y8"44ESZje<Ǐi޼9&L0׬Y6mڰzjc(W\맟~""":u0|(_<ϧK.߿uժU$ڵk_ƟiRא矓/_>eFڵ3gM6e˖-ƄWZ=\\,[̸IrLHvͪUΟ?owM|||8x ^^^ &2ݛ&ZO2j(̙O?dͱc8v%OϘ10(iylܸ\\\sqqlڴɸ2HJ={:u$Yŋ5jW^TR|wd͚Kx7,)O<}jRޯ_?Ç;B LvMmlq3'9Wڵ͖5~Izi۶-ӦM$xܜ+W‘#G8r'O 666űQJZsHR3$JQѣ&ѣ\vڵkcggYx7odŊ-];wĉ)\03g_8䧟~(Q &opIƌٳgׯIۥJbܸq,^///onbXvԨQh2e +Wd7V-[//dku'ַa%psS e{$Iv+ʕ+Y~=sӓ'XcER8vΝh2:@LLIamb "##Ϟ=Ek׎y2gN8<j*VZ=?vvvi[\}~IU@k5|[6moٲe ,XPnJ֬YMV{X~=| W\IX ;wf'v:~*i׮b& o˗0bZlI,Y8v{f׮]?s58q";vc&kI'-[ɓ'T#GK.1yd<ڵk|$`ܻw/U}޽YfQfMN:ѣ~:˖-3Rƅɹѿcb4 /}"/5jlGҺ :CW׍t1!{n>3ɕ+F"((_XoU+W5UTaȑl۶-AÇޞٳ'7o ɓqtt$k֬-[q${@l[/%}1\1!0Li&羧G)&'KǾkd|H,Ye?~G'L_륥ŋӾ}{۶mO?e[J_z9~8ovÇ WTӧDFF&˩}OϞ=_>w\&NHΝMݺuӧXY%rqa/իaW:xQ[0,((lٲѺuk,Y®]ػw/ߧW^ƝsܹÐ!C8uTv% %ի&i}… xwfw^i[J_zYhQ,X@ӦMM&&=z4y~~~c9(6lH|8}4k̙֬3k .]@6me|h_IiԨ?gdx4MF~Ml`eeo<5O6SNagg;_~evt7!'L9"-|^BFrv?XbbqOJ}޸09==O-9X:XSDDDDDDD$)"ըQ$u`ҤI(P;w?sbbb"$$ Һuko{sfۗgٳg۷/ gΜt%e˖xxx{n"""!$$ĸ\'2 cu֙Z/@tt4>>>&Uoʔ).$羧G)&7Kƾkd<%\nJ>}WuԡEL>zwe4hFNr놅b j֬iKbŊQF VXAXXX^pe} >4 2w]nˋAFn>|8~~~fW\KKbHO6l`ڴiL6 6dX"":J*} N>7oŴiӨQ w&OѣGy G믿nݺuԨQ_~ʗ/#`~˗/? zj"##9|Hiݺ5~)666 qttߟ7Lhh(Yf5HߥKD'6hЀu1|ݻw)T}\rɾs/‚ ؼy3W^%::%KҨQ#zmGl}~Yf-[#FpI/NӦMݻ1i57|???f͚šCׯϨQ3m4ƌcH"fUV Ν;#of::u"{xyyqYlllR 1קt 6 Vׯgܹl۶wRL<<mLg '[ڧDٱcG9rw߉/ߍ˗SLOI {&eNNNt1U>Or{zo0bWcM1b-[$K,;v޽{k.ck׮aggĉqttرcfy{0Pg%\H JxD?ڵk_؄Į$22ʕ+O<\p<<]4iw}Ǯ]ڵIv"O<4j(CDD$1eʔ1c9NQ5k֤f͚:ƆN:ѩSY\9[;w.E˰aNψؒj+WŊYzű8;;`dWdI,YbQ6mzn?2رŋ'Ab$ݛxUXYYѦM<==i۶q>'Ok.bbb(_<\pOOOV\iQ… ̞=[ϨQظqc47ȓ'^^^,Z۷s-rM-N֖~.]믛OI3f/d,XMҳgO=5==tl_rbt쫱HSEKlh ԩS9sCCc;v0rHg+| 4Ȥ=}4JJakCy5}G@MOӽ{wz0h @֬Yy7RJ_&~,]݉gN@@*U` .3lْܹs'/"""nݺ~z (щHcM eV<6mNΎM&[/&ad˖&aҪUc2s[ED!22c.\`vh+Ν;g,}69sQF~<ܿڵk @ٲecH9|.DD_뭷ޢ_~L>SzLJDDDD$\p/_Ή'hܸq&G%rXSDDDDDDD$(%o>6l?~,XM2o<&O\2OfҤI JN *pM.] ҥK:""H,!~/W^8::D>}lmmnܹs߿5kְtRca,Y%22}09;tUlYN<ɦMԩS㆝&%3<^{;wkfr,,,XGDDDDDDDD^|̚5X6}tzI312 IRnX~= >ooolmmqwwDD$3rJ.\Ȁ([,Νc… ֪UիW'PT)[nQFܹsE=7NsլY3N<ɯJDD 6֖hN<ɏ?hIkyKΝ;\~=Ab!atȫ꣏>DDDvZscٳg[nAQHΝd9r_~|WlܸFQddۦM<==YhQ '''5ke~g~gVd]WZhժk׮eÆ lذ!yŋ7IrLI<իٳgMٳgx뭷IƘuoi&Ν;ǽ{Ț5+%JN:4k$1%'ly~'+!ʕ tSDUfv"""֭""/yҥKt۷cjՊ СC:wLݺu8p`D-"""""""""|Ja &פ(PJѣڵk׮MBR ۷`PJ:ubɒ%t'']DDDDDDDqܹ!fhk֬DDDDDDDDDաt憛[f!"ruuD^*VVV4oޜ͛gv(Rly8}4*T0{חPN%""1|_5>9&ŋ)]tϋ/((m۶q>|HܹqttaÆT^=Ǐ35ל6lѣG\2M6D2W5gG{s#q% }eccC…Sݻwx)nE4y9("h4糷DDDDDUsNc>̜9sXr%tGGGV ȋ`ڴi?fΜ9 < (( \\\߿?֙gF8u>>>|2l0J.MŊ3;4v0?}4&MbժUd˖.]0dݻرcٶm4hЀqƑ'OO8رc ƆyZSÇ8q"\v [[[3f 9r0˒% mС,]lٲ{.gݺuP@ O}ʸqXr%/^ƆX .zIR\~6l9s\r!)1C """"""")vi<221cо}{lmmh۶-GϏ9sfd"""bH.HȞ߿\rѮ];j׮M… ȑ#w^EKb4nܘ"EаaCf͚Ō3L&ˋ/dŊsޞe˖w,_ʊiӦ?n8VZew}BCC>7gTT7|_tɓ'sA6n܈9xzzO0e2o<:@DD3Ia˖-ZW{~1b|Ǐgƌ :4CvMHl\q}.\0&}k<ИWDDDDDDD墄t-_E^>x{{gv"""""I22˒%Ku:u2uܙ˗d뗉щ ~& $O}LTTo'NЦM)B"Es weܹܹH>([gpԫW~+WDE`ٸtޝ#Gh}b۳gSLa2p@ .lgr]b3fѣdϞ 2x`sӣyg>|Hҥڵ+͚5#,,-ZP@Mv`|2m۶DYFc^.DDDjԨٳ3; yIӳgO^j, 6;Ӈ'OnܸǏgΜ9&O۸q#$8ٴiڵKU{ 1ٵ!$$[nQre+Ɗ+L&'óp<<<,3<<ѣGs-c!q3W_}Źseoߟ3g0j(OL?ͩ^:˖-ԩS -^;v# fʔ)ɓ'v㊈`̘1&?_ݹss1&N eܸq<|͛5&vZc'OBHHhx6a:**U&jժ;v{ҨQ#G2uC`_ݺuMo 9s߱cUV:qgggks=aaaeooo,szbccUvvvcq'lmmt[ne֭3 L7[=Lvذa Ο?ŋݼy+VƏh?Wgz7<ǔ1uT֭[eԨQ@{zJnݸsg2vXbbbhٲ%;vˋ-[иqcc@cƼ""""""""/%\ /^ŋgv"""ի/^'opر(٪'ORJ9.]ɓ9x k׮M6]-vϞ= 0ٳGODDDQF?~;w$\&&гgOիG,Y8s ƍ?ck$C4$pichCъ+f%ƪhK-mVQ%BjQHL!RRC544"w7'$ #欽^}N{uϚ5kpeʔwߥ|=z3fX͘UXf 'N^୷ˋsٲeQ/NY.]6{2zhWNbb"ӧO… ]]fgVWٳRBN8_~ə3gXr%]v5;Ãʊ+Xbv2.~'#4mƜ9s}۷O Xvfsu~vr:?===kg:@n܎aj׮ @N:5jmڴ@|LnFMjՌ|`w۶mٳbLVWeum^5j~~~888PF #!4gEB޽;W^5yo߾#G兓cƌ!..bŊѩS'=Jll,p2ǁxg4yS'[n5)i¨Q:M㉏'<<`6mjڷo3f`ҥdddm IN_df#9s:~xcv.Z1SݦEDD$g4oޜ_~zo>_NΝ?_NJbb5|f;Y5 yy boWWW.^ŋqww ^3Yʕ+cYJ*U<==ߟy@^5k,]Ӻuk *d3U0]#3S =z4T^}qڴi9۷'$$@KjԨKOOh֬7o~ =s:tlڵkShQ;;z*4o; S5 A.]䤄/v5k4r8::ZٳԨQì=\ ҥK 6Ç[{ΫPD~fMI{nϭ]\\<csYуK2o<4hHvќWDDDDDDD񣄋֭[s< 1[Rǘ1c͍~ RX1~wVX x3gmnՍ77n:u2СcǎeٲeٖWӦMol܃*Ӷoe]T@n;iZڸ"""OoMU.U}Yj[n^zDGGcgg/l '112ePN<==y=;U0-~~Ƽ+dTR/sNڷo9;w4g5~ӂ\k܋ |ʼ3Q{ao,Ykҭ[7Zhavzz*U;/^^ze{ΨQXr%Ԯ]옓~Zj={X*6YٱvZ7onA"EHII_D̟?xƎ˙3gE&/ز{oV9gڴi>|OOO^z%*VHj̪e~UYݻ${#}Z{:8840{bɒ%ر#-"!!Ըqck=XDDDDDDD BۉdɒDDDf`Ȑ!8991k,f͚W_}ehs6o<.\@׮]nݺxb͛ǠAlG*TB CDDDS8qPn]ݴnf>}5kstv\]]INNʕ+3]DDDr͍5jw^;F\\fL㏍șw.}դʔ)ٳg9|YUcǎY1}YΝ;̙3ygsEl۶ڵkeԩS^,ѣTVx|ʖ-Yđ#Gvl7]nggg5kFf8q;wdժU̟?H(^8.]ڵk/^k׮}ƈ#ըJVŊ#66'wߑ M4aĉt+yr=V!!!m۶Yɓܾ}B ѦMUƿo.^h$(PbŊ1|yzz޽{3,Í+YMWev--Z`V^ƈ7ۄ;=M?K.?NժUs۳gO/_ҥKΎ 5y<-䡹t4oޜ УG6l؀pg/4h@6m3z IDAT5kFXF^lڴҴiSׯ?>6Fvdzݻ͛3p<75k;tfN_ߦGf׮]O?uƽZ삓9~8 QFL27n}5,YB:uL2dK18oʔ)$$$2eEf͚w* 9r۷ose |}}s];Ϝ9cUT ӧO[\f#"""yOzz:cƌ֭[[~nݺɓ'>}ў]5jY}!n߾ i1S2_|ɓ'IOO .K.L0[R%4i͛7 ܾ}K.f>Cn޼IFv79vod^Lk-άԩcb['Nĉ>ŋ3g~7bccZ:XT (Q}N֭[\|""##j 4ksttX;vӇTvi6ֳ>KYjOȑ#;RJQJqUVlٲ&L<{ƯʤIرcƘ&W^ϋ2_EBBǎlٲlƘ4i1'ܷo'OM^1=O>!997o2m4|}}-*&=쳴mۖW'yEDDDDDDD?pl'#G0zh 8Cmϟ'<<f̘J|W̝;׬-99%KpU&N,44k׮y_|e3o]~7|lסd-Zݻ gn57oo5III1Ϗݻwar"""r'5..ITED{㏜:u>}طO>[$.\aÆK(Apwwg͚54lؐ[K7n`nLDD)Cɒ%?(Sum6f̘3,?yYŊiӆ;wr)Əo7lbntqqʕ+ :g}3gҮ];ѣGy+T{6k0`nbǎ̟?.uvAnb,>X"ZYmۖ]vqypgw xs]v1g#q$>>>Yݩ%|Rƍqss… xzzU;֭[Gpp09r.YуM6oѿe˖ s;yQ^Ue SNh1J,i1'Z*}]n?x 6nH||6ng֭ǎc̙ԫW8˻kW{YڵkQC:w-k >ѣG9v{!11 gcqX[hFܷDGGSH5Ν;sIf͚e#Ν;2d˗gt? .4>r /2vvv޽;jՊ .~z\]]ƹ|2-[t|Gc/ItXDIqF PCz_NѢE;|_b]tt4Æ \rV;ҜWDQyu=S _|Ѭ=kyY3g`Z2๑K/]İa8|ű8(ndyo777Ξ=]Ti{XRR5k4kz]Ν;) wL?0ffj3ٳ >e˖Ѷm[6l@rl#1w\+WPX1F`ٱe5k/7nd̙ѿt钧S4iBJJ FgggN>ԩSyݻ7=w[ӣG:Өm۶l۶k՗׮]˳>?G'KD yRRRqٳ~󊈈<^pݭ5YA'ׯ6\6mӓ^z+RZ5c0T.ٚer5jٳfp믿oPZ5ΝkmMNe歽֘Y3Z""u9'NtҬ]֭[:G֭[ҵkW.]JLL ZuXTӦMi߾= DGGF6l={dTZ֡CۊyGVX|9!!!/Qc)R3tPcի>}: ~c< .2e mڴ`˖-|*Tщ<4ibmf9E ''Nԭ[h?pE_wwwN>͚5kpwwܹpJ(@bbq<--W,JG^^cݺuDFFҪU+J,iv<==ٳgA֭d N:WF ~rՕd\ٱ+W}DDDL~gɓ' ,^s1uT8@ttpwbUFXXy\p˜>}:5btI_H?ɓ'IMMt4hЀ~Ǭ]6 O>`V+>ȽZ*]ve޼ytMI""͍+W˘1crMs^LJ.-Zp LG}Dʕ9|0SL۬Y3"""3f AAA c…|72{lΜ9}Ÿc^y8q~UkJ(ʕ+ر#ϟ-5'y ޽{ӧC A.\G_sN6lHN16mJDD'O棏>jժ:tx7n'+kUJHNNO6?#Gh"^{5VZ?o MF׮]qlݺa=?}矉Gf .̰aÌǦ:Κ5k[ӦMYn[?r~~~Ί+ruI^ $$~'N0zh5k֌> m{f͜9s}2kkհaCnJBBN7 y<}Ҙ9s&~!ŊcŊkaڵk9t/I&DDD{ƍǂ 裏O ТE ZhArr2۷g֬Yxzz2j(F,"""""""""""""""""?:]\\\)R0(^8 ۨ$huvv&<<@ݱŨΐ#([,S#Gߟ"EHj՘2e `ҥΰaԩŊ???ƍ8r%Kd :jժ3|xߢ=/個-ɓ3%]XfEaԨQ v^foB ѳgOz왫Ŋ#((dmZ=32w\([,III߿n:UnݺujaYlS_UDDDDDDDDD%\cZb億bvDf$RHƏСCJWf.\щȣ{n D||<8;;:|_eڵ|w7nСCu6{hٲ%Ç'..7oҦMN|@hh.D.]:ɧxwlCw-͍DDDDDDDDD$_PE>?'O$55ҥKӠA뇛C]6 O>`8*y._ѣ3gM4aTZa;ӦMJ*X3UA6OUYDbccٻw/oGaɒ%(Q֡H``|>>u""]dd$CDDDDDDDDDPEfgg7#!"tIOO'<<>,X@``  uhΙ3gXx1aaaVoooJ.Ͷm۞脋jժ[o[o?omۖzj*UdhEdL>aSwߥQFCDDD0}ton0DD!|TDDDDDDJy ۷A0aŊuXVhh(nb…lݺeRL֯_h}[PM0 ggڷoOYd -[a"r-[FΝm<%-[Fvl`ݺuhaSfݺuV+>*vHD Ν;Grr2 \xѢozz:vvv6xg9z(/ű2eʰeO֭׿ŰaldeD)Ji"_ZZyu""h>*""""""%\C,X 2223g{֗oXmOMM%99$׮]{⫅XK0)\0 ,z9_Yf#[[ """""""""""SCԽ{wV\i0D$-[F`` >>ˀ>B +{hN)""""""""9Q…#r1 ƍٳ'ӦMtҶw ymcYfڵ֭ˊ+TE)7c ,X`f̘ҥK_ۛZj:4y̬^CreBBBxw(XP=JGlٲ;I޹j*FM^_}:۷oƍTX^z1zh|Νƍx"J^_~8::;~cժU(Uɒ%ѣӧO3v1]'&&6n܈#5wߥTR9wk׮͛|2Jyggg,YP)T Q"==06lqppbŊmk׮dԩ^L|}}Yd ={""b?Krr2Ǐ3,ꊫx"5hЀ={жm[իDzeh֬GŅ8t6mbұc8^ti}r@dddeW#<<<8u^zF4N.?~n:^ʭ[8r䈑lYjj*d;w[nqyyr4i$~5`߾}ǦNʚ5ky&W^eݺuۗW;,^4Yh#%%{nn޼ɕ+Wo 5Ϙ19spnݺEJJ ?&22~zRRR>$7#%% 6~DDw:vHVU"((HTx爎_e˖̞=!#жm[|}}Y|9))) x{{;涟)Yk̘19r۷ose |}}8p״3gJ*piXMm>"""""ر#oߦO>ҩS'vAjj*GaرF{nzWy&ӦMחg{mSrʕ+qX|1Mw^x҈gʔ)4n8oOSHΔpEFFrY<<<gǎcpB:DYhv"**Zj{nV^ g;vΝc…9Ղ HLLlٲ}ϝ;?NDD9ʕcŊзo_lb_b_~%;v`۶m5 KbbbR6STBBBZ*d,[ OOO[&H999dƍǠA~x8q" 4\v 7xWWW?AF୷92Nƍҥ ŋ󼼼HJJo߾ԯ_}r9 BsJɉ.1klfnJ3f 5joL6n{{{*TXn]qܵ\rFF?35j~~~888PF C̉ak֬iTؼy9AAAxyyQP!wFIb/:u"..HF߀; Y/_ެ<6mD͚58q"F"!![%b3 `ܸq,_ӲeK[%D)QСT\GGGX"}a„ yLxx8coo M6%""l'#FPlY퍹l˖-qrr"::"hiѢC|FDDDDDĖh׮pgba2rH)RTV)Sп|s8::FN(QhN^ƴ6)BBB pQՕyOѢEqppJ*L:VZe{aÆѩS'+#~~~7΢_nY-ZyѥK͍ܰnݺK)EDDDDDDD$'2<+PZ}l9"'qqqJll,Ʊ7oҨQ#y寿z...F) tڴiYb^^^^'11.]PlYVZevm۶  6;vd;v6}PP!9::kv;ԩS6l`„ sTpaK`` 6ƨ_>iii9IJ1%GDHEDLΝ;Yt)|FRܱ~ڶmWjժI$_Zhݻw7ڳ>={6seʕ-[$ڵkǀׯ#ryä%?МR|TDDDDDD'pv"ͺ#iv`YM">4nܸݟ,ڶm/˗/'%%^xooo:FJ8}5Lm>"";<={YfxzzrA&LdHʕm0Z bܹ_bԨQݛav 4O>O>cDDDDDD19X X9u}ɱo>}矉(k[pa f<.Q:tݝ5kw5/~'BCC Yf7j %Kjժw;޽{yfΜ9C߾}͎yyyYF޽}0a_˖-qrr"::8;;GDDK:u9r$СCJxL?~t^x["Ν;tua޽IDDDDDDDDDDDDDDDDD$Gpϕ,Y`PT)vs?oҤ M4sŊ?N+FPPAAA9^/dkxgy@ΝKRRe˖ ))3`r<.]DPP4oޜPre[%ĉTXƑIʕٵk:7&""Ν;:,T"kҤ ,_Wɓ' /#|2ݛ2eiEFFN=l< ̞=ooo֯_ŋ駟l8v{?~H,mLe9BroqJTÜfu` %ƈ*ffϐK yE\z=_y߻Ԟoikk+kkkʕƍ5p@SӦMSffѱ V(:t蠵kW+WN6(ٳdɒ6mFw}W/BVVVx yyyiܹ$ooo5jT… 4iK9;;k߾}[ѱ𘥤AF֭~z 0Œiڴ>|tbt @c> xZPpQCFG#Off5a+VLݻ7OFjժ1...WΝոqc}7j֬ѱ P4۷Oڳg 3flٲFB:xӍ@6m{ァ9s襗^2:J+VPݺu5b%%%Oŋ7:G}\ۯ^)SM666$WWW}GZfJ,$c(žDĽFY,(lĜd͚5Zf1њ5kgt p5M>]N:۷+88b ͛:{1iĉ WhhڴiXa`tsΩW^6www;wNAAA&uYV(@!!!0:<4:|ؼyuYM>]FRbo nKIIQ͚5o>5h8x:w]vsjҤ"##Un]cE­[tRm޼YgΜQUZ5uY]t7--Mҟ_|Qo(KKKIV0sBB._UVqƪPOŊUVwUҥU(Nk׮_T˖-RJ:Ɲ,ϟ׿/m߾]W^U֭5iҤ\ИIy[=ɓ'kӦM1c:t`jGM6$?bbb*Uvr{rk<3]|YK.֭[uyjݺ,kkǮZJWbbJ(6mhȑ(9+@ĝqi5Jk֬nݪʕ+ ̱c$IUV58 BznݺYfZb:udt,˗oܸ$%%%ʕ+t :T4=s,???{M6)--M͚5˱Yf͛խ[xuFvvvrppО={_ݴ/11QOVӦMUre-ZHَ?{VZK.iƌy߿N>mjtʕ}eG[τ o>}jԨ*VgW*T0\pA}ɶhJJ|||tMuϒyRSS5`?~vY*>>^9 h /Jrut-M<9_YMM>L5kԿo}Zn/+L2FGAy?]]v233<ӲpB޽[њ0a$iզ~+VUn]*..NaaajР))IL111ZjȐՖnlﲵoܸQ&IZr111ڵk,Y"I|jժ={E<>#GX-ZHGB'OJ:uyRRR;΅ $)"> TX1uYAAAڱcZn]vŋ}Z";e}YtY.w֭|ga P4Osm7o\M*44TڹsKլYSgΜN[L>>_]&uA֭3{MCz$<YmY}@v*sss}7< ~:ʕ+wޚ:u=V֜Ob9q(c>qxԹםאc^yug݊/n9kEspp|X={4:"7nɓ')(zE+W4:)S:u꤀-_\}ѥK4|SI҆ r$$$(>>c /ؗՖ@ё"dEGGEVl$jȑرcgdd)Gʕ%I{֞s׿ծ][Ǐе_~Y҃W*[V+WLm:G^wZtڳ޻KE_%nZNNNݻ6oޜkFZZ.\N:I;vy(_i̻)!!A[nkSM6rttT^q_^U4ŋUNNNrqqQ~P6l Izw}Q={jذaݻw˗/k޼yzw?~}NII[oi֬Y*y_|YVRƍ]GŊUV˹^K.iȑjܸ$iϞ=M˻yZjRD=o5l0yzzj}!ܹvZ'jJ>7oZ`4tPS߬pNյkW9;;nݺR3/.\>}d+HIIn޼izO^Z|rS7n())IIIIr<==/))Ids=dkKMMՀtqSٳgxTRyy;s2d9׮]Ӻut-M}h̙qLFL?W۶mSbbb"t+++5ʴ]\9]pAц Լysm߾]+s gۛo *ܹs\4im˖-qF'LֻwomٲEGM۷q~^mn՝r{םteM6MJҌ3TX1M6M:uV^ҥK_~Rbbd;ϠA9F˖-?\$uq[nɓ'տlrE^0g( ѩSdkk@޽[K.ue+V[BCC05h@񊌌lK,߽r׮]5sL)SF˖-ӠAԢE 6Laaa9Vȫe˖鯿Rڵhӓo/*Iᒤ j݊ք $ݾ7Ο?/ITRރ˗T RRRW_UxxbbbL_"OyHjժ|YmY}=zTm۶~m>|X cѿmٲEwVft #s'U>>>Y,--eiijժo߾>}!YXXL2jٲ=s̘1T,,,L۫TRڱcG ;v쐵ڶm[ bnn.]H=Z5"رcծ];,YRSf͚e*߂RK.ʕ+'KKKm6ׇ`uF[嗯hܸqt!&ƍӹsL/Ԯ];.]ZŋWZ4{lu5jR͚5Ӕ)Sr <&Yǃ(i# 6l=etO<)IԩLkZjo߾/e }bŊn zm`2@Qǜ)ftA޽ rn}vw|M]zU7n4dT>}tR:vV77y헟km׮m6_^?b y{{[nԩSڵkVP~TNYW5KM?67YsՖs@^5j֭[ݻ>u%!(=֬YSjȐ!JNNּyT!<[b~oZJ,iӦiĈzw%I/deeDp'E+\b+W$ޖ$I҆ ߱jժ%IZn]V۸\bjm%_~_~L2ԩ|rG.]ߖtI5q--^XzwLg럵uMRG /H.^c_V[Vx3gj׮Y6mRXX8333͘1CVW_}:ѱo!///͝;WsΕw=1g(Z((ڶm+I5k$͚5+GVZI&OÇ͛:,X  :7'O%I3gRRRTEGGkرƑrI"""tU?~\95o\4w\={V׮]ӧ~*u5s;w֮]4۫z꒲ ~NNNjԨOW7o˗u 8p@#GTll7o.777q-[$͜9SPbb|7Unw5$NYmY}aرC 6ԩS5f%%%]vFPC;vСC#G xlr+H/xxxh޼y7oi @a(ftܛ~8qB}o߾}j۶mJLLT޽ҨQLʕӅ *mذAZһᆱZWիsꫯj-[*<<\>sIRfrׯ_?EEE)11Q?4hPZ飙3g7GOk?Iհa/hҤI9UVMYߺuN&M\FgQVR퍎a %KҥKթS'-[VŊS5c I!YXXL2jٲV0fUTIJOO71B~~~jٲ^z%RիWװa_V_QFM?,--լY3M2%u RvTti/^\jٳաC|ϵG5k֔,--UZ5WӧOw?I*_/_#FN:*U{9[ל9sdeeҥK+((H=zP daa *]*SL׼n߾J*;vcY[[VXu떖,Y5jh˖- OETXQ?:vwyG}ё2fFx)$$Dn?NgΜQǎekk~~ /V@@"""TR%I ޥK 2D48)I uݻWÆ ޽{5bM6MFBh޽1: 2~&M>}_%J0:Pyzz*kZ~6'}<=GObF(--M&LPvdmm~Mgϖ$5lxG}BBB4n8IF{68-I{Uz"V17nԩ#=zT֭S "GFGCƍF֡CIZn&M{JHHPr4x`iVdIM6M:sΜ9HM6MVVVF QڵrJ}W:z퍎;Cݻw̙3jҤ~g#Sݍ޽쌎MӦM3(i ظqdgg^/I䩻xdo񆼼4w\I5jdp*Çm۶iU华".##C^{5)Vvmǫ{rvvֲejt,!rvv6:j>|1@<<|1 W\ OOOyzz@yxx(~'y{{ĉ8qƏ/KKKcaU]vCZҥK @ࢀ@>L-gjر QߪjժFBL2Z~&M{Oɚ9s,,,Pp@w-kʔ)*S֭[]  ͞=[uuAtFGP(( =z0:|PHH1'*!!AÆ ?QFiʔ)6:j*'''_^ժU3:ϲeff)xyxx+xoy{{iӦ*UۧٳgSlyx(QBM6O?dt$!UfM]VAAAڶmԩct4x+ڱcz-o^-2:Lj UV۷v#GޓрG-[ETRj*M2ERFFѱ<\9r?TXXLo>C7333ʕ+0a6lTjѢE*[?\AAAF@fff)Shڵվ}{]pXȷѣG3}퓟Ǝ1ch…ڿN9uE52:~zծ][K,Ѽyƍ x~U^\]]sNI&:xё< .o۷oϵի2edcc#[[[꣏>իWpJnFGx~WuQ]v:_dz%##CǏWjՌHׯ={bŊrrrw}gt$. c<AAA:wzejsww׹sd`2(:'N:_e}תXрƍ7: `RBmٲEnnnܹ̙ct$B,c޽jݺjڗ!*a IDAT SNrrrRǎlu/^,WWW999ESDDDr;C,|VZƍB >+VVZ˗/?@ѐ &jժ*QTɓ'ڵk>233_PG2333ewmӋ/aÆʕ+={V׋/%KS9֭[Q5TD .]ZNNNꫯڲe^u͜9S>>>ڿZjPG$k'+Q4gM8Q}׍ 6|]|TȐC>gΜQ``'s۵4~~~Z|ߍ7$]rE>gn6mڤ45k,Ǿf͚)>>^7oVnPd\vMZRBB~̙3M6\ڱc>hBvvv:y򤼼TR%-YDk֬y1ԪU+?^Bŋ͛Zt$Vuq1tR'L銍Ull.]?0Oՙ3g4zh\R:uҦMꫯXiwq/_^˗7: QFvի;pVpZbbb4c IҊ+tAխ[WSXX4hxEFF $-\PwVtt&L IZz_^yM 혘IRZrjy1o<%$$iӦڷonܸY?%Ie˖ղet%{yK.)88XʕSff鼙q5jѣJKKɓ%I|iܹsuqk׵}v%&&8WV?ׯtddd/PZk.EFFj[H9zWnt ڷoݻw믿Rƍw^# .0lKR޽eiiiڎ$͜9SիWViӦI6nh[T)IRHHWnnnJHHVsȑ#MUT",,LrJ5h@ŊSڵ,vX֭[kԨQھ}m6 >\mڴylcdYpUdI5JtIҒ%KԤIYZZE-q.kkkIW2ӹs4l0eff_o85iDcǎհatAu" 4լYSqqqU|M W1 jsիN>@5o\iii'NPfffWFFF&MRRR7nhĉ}$EGGgk͵rԯ_?ܹS?~?4IJJ ^zСCݻ7l4h~Gm߾]Φ\7oZ`4tPSΝ;Ak׮UZZUzuIٟsf{Ma5jԐ$o9feڵ$C{UFFΞ=cL[6ݺu>39;;+&&F...Z`njѣ5F^K hݸqC2dHժU-Z˗/~_+ij̘1jԨ_x-\Pe˖w.@o*>>^7oTƍct$w04:ijL!!!u^$I yޗ}ĉ9R@@!<<\3gul*9gvtIWذaiÇv_hʔ)ܹ P\]xQ:|p}JΝ;հaCzuEϪRN8L2JJJRٲe/ܹsW_}U'N 6yw}e+WfdɒlmwrppٳgYfi27NEݻ~-ZH3:…r-kkkC666P2eԲeKg[IU>>>Y,--eiijժo߾>}Cs̘1T,,,.Ij߾J*;vȻcY[[m۶}{a?vڥ#GW_UbT|yuEB///ZpT"IR.\SNK`UZUŊ5F~(QB۶mӰaK/Dѣ,Y!CFJVVV^Vjݺ9CRl0kkkk0`ƌ7o (X1y.%/V@@"""TR%IӧեK 2D48!pop]~]gϖV* \R P-j*=FG,ǦO>XbCBBdcc޽{ (իWOsѴiӴo>-|o͝;W27gA)q? (/%K^z5j +++ . HXXOɓ'5bEDDW^?lllֱ W^Ք)S&U}^jt<Oط~:uhѢE;wM+0ӧծ];?~(@ggg;wEjӦK#O . `ͻƍULw޲ʗ/:(88X˗ƍhhނsΩW^6www;wNAAA&$ڵ:v(GGG:tH| ȑ#Rҥ<{9YF'NԐ!C4w5]#s ZJ̊c*PԬTMM Z*iQJP55d2 5U[J 8Ny\gz˩>{ۊ3;#ؚ).\;v˲S2eԶm[k.QHhΝr .W_}U$%ZÇkӦM^zTRf)Tz衹sSժU>}v){{{yzzj*\p}?xn… {n]zU V&M4`˗/y͞=['O^~e1BNNN[noQZTHEٓ<\,..N}L"777رC͚53;>}Z...z͎E'OVJԧOi͚5*Xl_|˗'|{;w{X 4H u/_ŋԩS/R}+'$I/Ry<==5w\;v,I͛7KZr\\\|ͷo֛o'իŋ9Qƍ }_^%}o߮Hկ_?I+((H;vP|=r??? Bv)I:uʕ+'.]Z'O$}f$ڦaAު_TjՄ%\ǏUNժUӸq$IwNfرzg[͛7:?p͝?c*Z٣6mڨUVO͎dK,F!O?U.]xbEGG'oIڴihFv$IgϞM"EH._jK.%u&^zuIŋS=gJ}TV-^xA7I2e$Etcik׮Iϟcul!!!jԨ]*44Tݺu3;GΞ=( l2M:Ucƌћoc .Ç}R;+h۶mjժ)::ZS˖-~8۷oZL^|y|=;F|XAAAѡCIҒ%KR Z|$%'O&~1Is=+Gb$IǏOt<{WZ񩧞$ݸq#Icu<[lQʕW_i̙ ٱÿ/FfGrVZ_UN8av$ [`E6ֶm[yxxoUddʖ-rIJCƍ%IǏWxxݻWjΜ9РAo%VZjHOW8EDDhʕ߿ԢE U^=I֏>HNR\\;SJ7ojkԨ$iԩ:ytIM6MԠAK8/_^믿&9G:r]۷W֭UNiذa1;tWڵdv שT.OOOmذHl:uOӧ'*{ν{޽{uI#Q=GGG; ,k׮}rss͛%X#&&Fvٳqƚ8qbY *޽{':VR%u}?|ͻwo}&*{gK/~INJSNI؂戋Ӝ9s4yd-ZT;vPf̎@UP!m߾]ÇWǎ5eM0!a4a >|XN} *^*Sz)S$˗//^,///F...jԨ.]hWѣGxⲱQlllq{{{M>]gV P׮]iv,0 CEVWs+IJqHN3|hƍ*^$ҥKj׮~{UV%9õkEiӦ/U\9c#ٳG:uRɒ%i&(QH@b o-!UVM=z01e˖B ڲeV\;wиqc*&&FkV@@ّ,ł NNN}Ze˖5;ISPPTvm߿H@` [S͚55n85J'OTf̎ ;wNfy߿_ 6/E :[f֭1uԩS'c׮]|||ԤI[Nʕ3;X,IaV?a:{l;\dff9v^xc 1{N$,o޼Zn&MԩS5klll̊ X .2ƍqFc@b/_1cF+VٱҥK|bvh׮6mڔd9aXrӧõf(PhccE&ɎC@vAC @d}Ν;'IÔM6LN]tQ2eԮ];խ[W)Jy@TT{=U^]wQ@@ [$={V哛QCAAAʟ?֭]v x,paE֭1XuԩS'c<l٢Çڵk1c*cH'";]ȑ#l2ꭷ￯WjСڼyզM}rqqI>22Rн{TP!jJ|#_ܾ}[~֮]K.Mݻwĉ$wFsf'Ojȑ󓓓:uꤙ3g*o޼ ukZf.\ {{{UREo뗁;̖y奯Z˗/WϞ=ڮ^ZݻwWNnݺ=܋qWwQ`$חڜܷoW_}Usѐ!C8@ֱO9XJ .  &d͛7OJtwZdI}ŋ+U= &wtt4hÇ'/kʓ'UrfzJW^MTZpa4 CcǎՌ3IҬY4rd`΋ׯ׭[tI=TjU˗O*TPsa'Iׯ_W͚5uDu^{5mٲ%oIN'jРA3g1;@na>|rه#..NgVJtIm߾]k֬aKĉ/I2dlllHM4Iy$nݪm۶)&&FTRt͚5+>g͚ÇN::v޽yzzj׮]Ip}Z?~$モ=~A111u͛'IS #U˖-͛7իW/ݻwOon޼K`) k=I9sΟ?/www*&&F?N<\EǏb hB׮]Y.YOC Qxx}]y{{X .} һᆱ[#GZ΋q)88XjRHH{=e˖g9ࠥKjڴi;vt .VqƩz}_hr~) @w5h IRnRlKtQ)""BcƌbQ&M/3y ʔ)#ŢJnRjTZ5Iw-@y{n}K/iΜ9ڽ{wBDf̽WԾ}t]iI>Μ3f6mڤkתiӦrJYbav@uV 6LW^|CX@|{Jվp믿l7nnݺ OY /`׿/矒%K… Z`AbiF6mJ H뼸~V7nĉ*U.\jժEruuMvNd܋QztرDu릯:Q]kɐiFahӦMzJpxl/^TkVZ Yl+VLK/1ch -S@iĈ*YlmmUP!kN [Cf5g.]Zώ>>>Q*U[˖-::/ ]J*%I*U>s]xQC Ȍ࠽{jzΝ;kIZcNV\YzgU~};3aqqq;w&ME/+bv,@ (ӧ&}9ݻw[oiѢE裏mv$@dkv@!C(,,Lٱ27nܐ1d";;;-X@+Wȑ#?dd}SN cLe&MҥKx”/_^X4hoHxB(7NիW׭[/RfG?ov &(X{G;w֔)SjVغu W>А!Cdkkkv,Y` _]K.ّ` @"/^TǎkVZ YlL1p@m߾]?4h/ O\$IqqqOUbE8qB?֬YbŊ <7n@EEEN: 2;0 C+,,Lٱqㆼ{nHě;w8`v SÇ7;dpO[ .`M2 [*P|}}5tPCǏ͎O@[Xպuhv @6`kv9VXѣG+OX!gϞ1p%Jо}ԴiS+Zpّ9ԿUXQrpp3<;j֭f2E*rssS˖-5~x8q"պ'NղeKY?vlmmU`A =z~GZYdȈ/]v*Plmm#GXH?QŊR,;s=zTE?UedXs%76EDDKUP۲1;dؙ3gXp*7h4h8c?S-[T h"+**Jx֯_^{MZ͛7͎DDDh۶m:uLjI&iԩڶm[{{tu?~\fRJrJc&ǣGڴin޼{)""Bŋ׀tDx IO_/]n`&\@t}͟?_+V|}}~z(Qhʕ+u@.aX4i$YF/V˖- WmۦbŊi̙ Qddbbb>@6mڰ/ݵsN&[]vdɒY,s?CvR֭^z%sJ|q##$I6mݻwEZܙgϞѪUjh^ZѣUs`0'O ~)$$D[6;X… ջwoce:u}),,Luӧ͎&ϫaÆ ѨQTR%999^˗ׄ 'WWWO?ٱs-[ڷo_{՝;wԲe,N5TH5mT;v cv,q]IR֭ekk+''>gf+Z7oׯkÆ ]~_͛g$t,Ν;;vj֬)0ta͘1Cy5;@PF PB[vav$x"0`}Y988MݻwWhhh-#?;|:uꤧ~Z*SuD߯m۶駟ֆ b*Uh钤?IoxⲷWջwo9s&뒤CI&rrrRզM%̙34h WWWլYSSLדmlI" ?jEF珔qNinQM5jҥKoyh}z饗SOV VVwt9nݺH"W5y3Gj!?#O-[&{]^zɞڹlI vW@6sխ[WcƌѰa͛ Wj۶tխ[W!!!fG\k֭z+~Ivؑ9nܸnݺ)..N͛7״iڵK4dȐ$m=<n8G"Muzdoool+Y*W֭[ʟ?nܸlٲɎO8g;wH IDATg $0>#sԩSZj%ۦ^zi ɍ5]Jw,3o!oooW_M8P̸0IR͚5-[#a\{` bd6loH-X@}b1;dX]V-ZP…͎ SH}ZO=TqFm_(zuZxrIΝ;#FdJǹ_XuD?{ttUνw^I)?իյkW?^*TĉM63#s"M|R:Wz%7־;9TX15kLw%I˗/ݻwռys-Z45Gr5gRZ`\Y[ @<\ 4sLU\YO֮]l2=fGӜ={V f9r6oެ7iӦ?͎$/]յkWEFFjʔ)jӦMu˔)#I:uTݵkWIW_}|wyf%lDgU>}㣟Y7o֭-arqqѶmdo߮yaÆYZuܹs}{i…֭[Z>$͟?_aaazշo_i&n.dUT$9r$6~dxXgt,3{>$wޒe˖I,Yx "wwwk֍_޳g$egNsTT#Ȝx%IfJÃa mGJaѱ|_bmUZjBBBTP$ά9?R!IӧOOv'Fs46Y[ XpY2d^|E.\X'OԤI@<)Ξ=R*V )SFڸqّ G2d (E Rtt٣gϞԩS/TժU|D;K$grppВ%K4n8ݻvx .T…m6URE_~Ο?8EEEԩS1c<<<_i„ VZ>ϯ={} UllBCCվ}{ݻWz뭷{ u&Iԩvܩ;w(..NN=nl)8wYZxzzJ (::ZΝȑ#5o޼t/..N/_͛ռysM>]vvv񑭭mm}YI,>?t=W^vz#sddN_ŋ׎;ԩS'ݻ Uiaѱ|aÆ Slll:ҥ$iĈ 5UV:qbccΝ;EFs46Y[ @" }׆O˗/7߿ov$vZhaDll1h b}xyy^^^)~֭[ '''CRy%_f>yaXW^=#***I`lٲacccN|}} d988}]6eT7+xƅ 2-[z_JYZ:d8::&… Sl*ȗ/_c\{3qĄߦ22'8`͛76/N;aѱ|F%9Or9tծ)= WWdX|ym2+ɌxΝ;-ZKZRxxz7rٳ*[1 ;;;}W/4i$u]fe˖:~gyFvvv*P5k;vh;w.}W?^}U^*T|={1I*U(88X .T-&;;;9::\r8p;)S$g֭uQCnnnzcǎ]v龎丸_*U$''']FұcTdL˖777 ʕ+' ?O _~Y}QNb '>3-X@ӧOWNtcXU5#FbŊrrrJ(]O12;\@hڴi>}*T ???թSX0AU|yuA 4J(av,)Q>Scd9vtUjU͚5K}>b 'K/@ݽ{WjՒّXpitK͚5SQF֖͂ .]Z~~~P&MrJ#10 -ZH*TО={~zg5;kƍ6lzq0 c x-;"$$D R@@?P3;*!!!ͮAr}'T pXBy5;dիWݻf ֭['///c!vdDEEiܸqQ> ߯3f@ӻwoڵK.^hv$tuQN̎@tIu1; 6x?C꯿Ҍ3[o)O֧@f9͎SjӦjժ7 \m>|1*XpzwfuQsQb̎ޙ3gTlYc@ynݺQFZxwaQUnf Zf⾛[*K,KsOL5]1HM0\,wADp~|yy{;,CݭKD$Gl"""CPPcH. "Rݽ{9s@ɒ%Y~=;vv,#66N:Y;H*Vk׮e̘1d;ݰ*""y#H. "R׏_~#F.\ڱDD ɓ'…vvvL:g}âE(Rd+oooCDD$֬Yc""""""""""KZ;5ܼy#G 'Od G?$!!WWWkGyd~mmݻi޼9Νv$@.DY~=5kd|7۷ڱDD X\\\DDj֬aaa$&&ҠA~gkGy$.^;mڴܹsӡC+'=?+ aĈ1GJDDDDDDDDDDDDz4BD s內'M4!&&~ako""Rre ʗ/o("" v4oޜe˖Y;Hf͚f۵jղZw7}aFȑ#1cGy EDDDDDDDDDDDD=e,"^rr2_5>,ǎc֭QlYkG)*UĈ#CDjJ(ׯݻw?`0X;HIk…q۳gO֭[?]R\9ʗ/ƍ֭[8ȣ "EDDѣ6lGm۶֎%""""bbggǴiӘ;w.'N[nUDwww`޼y?0c ݭSҰpB.^HnLeݻwŋ,\ЊDDDDDDDDDDDDDr&\Htuy4h@"E8r&LDDDDD,ӧ[la4k֌?ڑDDM6xxxЭ[76nܘݍ7/xWcǎ|ܼyӬq"Ill,I&nݚI&M{.sˋ ҬY3zŚ5k̎uqChժOŘ;oܸ?@zx'Lm|Iӄ7nsEDDDDDDDDDDDD6{kn+Vw|acccX"""""ԲeKԩgڵԭ[ڱDDJDD;>>>TT+Wnnnx˗/[obccHIISNܼy~'O]p`lwZ}߿g}6qe6"""""""""""""&\Hw5~i7oNrrrdLB͚5eΝ,Z iEDDDD^ɒ%ٰaL0`X""8f͚sZhh(FbŊ.\"""XzqD@@?<Ԯ];w:ѣX"NNN*_n7DHHW\k׮DDDnݺ ѣ96nK?7~+W6k#""""""""""""[;Hz2mҷo_O?Āy;vln>m1c5kdȐ!DGGpB *dh""n=eLbڞ0a&LHCv?VZΟ?@ڵԩcv{]xq޽k*6l}aaa1{lu-|2ŊKUg,3Kppcd%"""&\He0_~ѣ,X>ݻرc?>ZbŊTZڑED$.\ȩS裏ED$W߿?UVۛ-Zf|Ikslllj{'P!~ڵkwfڵ̚5%K0h tz`0am6BƲ=""""""bAAA֎!"@Y1DDDDr&\H|r6ms=Yx1}eܽ{ŋӣGkG,ضm֎!"'nݚp:vHzX~=/cdHDDo߾ԪUEq ‹/ȼyIerYbccQFʗ/ϩS8r 409rreŋ鉧'رŋ_fhlll0 ShQbccS-)]4.\ڵk.]ڬڵk6""""""v s&\Hd"")S}ڽ[TXTXL[ogѬY36lH@@////:u1C+6m믿Nɒ%֮]˱cLjѣf͚֎/""YpI*VyիW',, ooo4i’%KxWKD$Ks9r܂ٙ?wy={n:ONBNDDDDDDD… <֎W IDAT,|""""6MJJJdɒFaoo =>>>ԪUZjꊽm>>>4k1DD{͛73d8q"cƌv,'֭:u* C0DDDDDD$BCCYx1>}x 4h@^xW񑰱`0dq7,X]%>>bŊF۶mݻ7+W>ϟѣrJ;sS >sYD`0Ӽys{1tbZDD$U\9G>)3g5j`ĈDGG3oM߾}X"NNN+W___-y~x{{SLqqqaرܼyӬݾ}شieʔaժU,Y2ܵj>`cbbx뭷PTP???N8~gZj3JӓZĉWWW(Y$u壏>իldơ7Em6ԩ֭ˆ ppp`V}ZiYp!5j2eo6KN+^/"""RɚdK,vL\2M4v n߾Mꫯ @PPi{mooog~X۷o;v *ʕ+СYyz78;;`^x1o6)))֩S}QHǼy?~<qaԯ_GGGS ֭[)Rk֬M6F-HLL4wttd4lT?Ӻuknܸa1_ʕ lٲْ[2{Fȑ#-f̝;O?ҪOs)S0zT휜Xb;vL͒S*̹w̹)""""!K/:EDDD8q0p@Ý;wGD ٶ^z饗^YymGҥK'x`ccc>|ĉ[n8`ݻPD ß~'Nh(((T~I0 {5MkԨa aaaY>hѢꫯ"## o6DFF^}U`(U᯿2ϘF^{j7޽b :t0ۧqЧOÉ' IIIî]Lc0`@eWV_z !444StΝP~H}z 0Cbb!**i %J0\x1GԹq_FAAAfo 666L6 OOOkGyÇcooʕ+EDDDD իWӳgO7nLHH%Jv$pɏMDDD-3+\L4>T#F`ڴiiѴiS5jSL1Ս3)So?Az\2E%>>k׮QxL?L8-[}vlmmMuwޥM6ڵ+ոO߿?g6;]hժ%Kʕ+rgggr %K4'**ZjQ|yΟ?-U++ׯTR\z˗/ST Q|2KN5̮*uj8;;=G1Ǐϱ,9us\VDDDD`yVevED$gkٳOOO7nڵkqqqv,GONhhcdZ&M:tcdچ >>Y;HZ;H̶o Xb]RJjsM 7껺ALL 4>6&i$_X1-*T(CQD >:ٳgYh-Ņ[ơCaÆѣTZ5<bq {+ԹqHAo'\L6 OOOka֎ "+9sdOVGH"X|M~7>SlllMDDDDDDDDD2H"\~Wfz5~wy,YB5ƍܼy3C}4mڔlْ ;գSN,YWr5{TW 0>akk9s;vJhh(;qqq 6ue{\mr!BBB25`nb`HpbbboIZ9*YdfɩsqeDn~T """"q \+'[[[&M… /x35駟2_bb"ݺu#!!>(cw ٳg֟իWsu}fKŊի ,_ݻwH\޽{cggǜ9s2|M9B`` wXBBB2˒_~byXXk,}2;}J.DDDD9y$J4???mݻi޼9#)ǏO.$$#F0bBBBa*)ڷo~JrrrlllСYȑ#9z(^^^7.>Zl  REFFbccCʕMeקm۶\p7xFΝcԩ2rHSK/)S{>weԩ@+dFʕ!***U]FReg\?WWWLbb"۷'""">*T`TT)Ge%%%1ff̘AJJ}s֭[yr< d߹2r͛uH~.rK.oeˈ#11;wp6oL޽yy )))\~h[^z%֬YcX9ƸdaHHHyyyX&k֎!"R -Z(ݧ*U 6гgOvnH"&*W .ŋ'}O x" .b2o:t#G駟%Jжm[nݚf<ߟ={/SdI^:&L`׮]&[ԪUcǎ1o<ڷoOrpppPBѯ_?>lq@N8t=z\rS\9|M>*^8ޣF8;;coo+.Nuyvf3rttdڴi0vX)^8vvv,Y 0n8N8W_}eq9TR8::ҠA~Gf Ҿ}{)=O=T6޽wwwR Fرc&%d:WYWFսr{_DDD ĿK׮]9{,e˖ߟ-ZSOaggٳgٴis%>> cggg9&'VX\vǏh"v؁ ϱD?Cƍ)Raaaxxx)SL{(p!""""y_ͻKϞ=;w.֎$"LV֪9e鄆r-\\\x7ySIHH`l۶_~޽{Z47xWx9sYdÆ +V,G+"".DDD$'=h*+…4Z"=z4gϞA,\]])TTRAb /Nxx# )]452-=h0 ))]2ehڴ)ׯ_g˖-ݼy3ׯ_YfYl!"""""y;Yr%ڵ֎$"eݛ7ruܹCLLiŽ߿?/?Ν;_2l0޽n_[l!!!FkԨ lݺ5&"""""""""""""9N8<4i҄իÉ偯;vNjhѢSL!!!?̞={xǘ5kŋO3G`ٲe9r$5Zj4jԈQFqԩtpQ|}}Quԡo߾;uƍe˖T^^xOOOO-l˨QFQfMo6mdVg:߾}@uFݺuqssnݺۄgXyիGjԩ;vH3s.] I7>;ǚ׌qѪU+-Z2~VZ.e)""""߿ӧOS~}bbbID$K8w˗'000o} &+'r={u̘1,SDDDD${s4jԈ˗Ӻukk<=CN`nv _|q1tP۶m`ĉ/_*Uҹsg6nHΝTT)U]ʕڈHUVz* ">>vItt4+V7Ν; 6/5rHSIL>{,Þ={8~8?*U"::sܲe wwwLeC%116mڰyfbbbؼy3mڴ!!!!C?X<1ch޼9!!!DFFLŊs|YO>xuΝ;9~8QQQʹs>}zeWV_fn9sEժU !**~+WRN fPY9Gׯ_gذa}lBLL ׯaÆ?b_t-Y|9N:c˦+l۶4&M0sLe6kmcþWO:ŦM_ ɍx vIi߾=s̱v$L9}4كEI;s ^IZe+V,UFDDDDDDDDDDDDDr7bҥ\t@JprrN:L8???nܸ%K=Ç6m}TLRR &L੧ޞz_[?5HHHÃٳgSjUZ*gÃk׮[ܿ~̞=uL LH:d8a̘1TT {{{ *D L3oߞm]/=ʕxऍk_Pn] *#/_|1113+hٲe\r 2{l\]]qppF,Zjժ_.]Xr%w5KIIaŊfs,]7nТE ON*ULc Ls,ٝa͍߫ERlLܯPB0p@FaHZ"""^*IlmwʫikWc~EDDDDDDDW:.I_pk.zi7`߾}iƍ 65kƨQ@=RsǞ={Le.\8#1 @~R!֖~{n[:?< ]TWjU駟-۽=IIIۻw/qqqԬY3USO=>HVю;Ύ_ڵquu… վ}qsswoΎ[/s={~KD M666?`fϞ'7n IDATv,z_߆}~TB"""8x`}.]k׮3ۈHeoZll,;uTu;wJ*W_agggVi} e*Z(ׯ_'>>bŊeh'IܯvfWRTe 9p@FÇ9|05jD֭iժٖ^q֭[%Ξ=ίʯJtt4!e/ۧSL!$$͛CBBLjbsV'ܡM̶[l6lH"̛7%Jjd|ŊJ*q12tc9@JJDx4'l''ϸCFt҅bŊ7_ʕ+Yr%+V3=5aa_F={e> MdUVΑqiM )^x}vܙ/۷se{1._̎;sfk_HJJsUgg "_]r/f竈'<ׯ_7ڵkǺuطo'Oۛgy3g0a„0/Áfu1tPΞ= >cܹر#S}f=hʍʖ-KƍINNfժUZd5kF2eLms|8mڴIh~w֭cwؑ@O)F[nؘ͛*VHdd$GYf9r䈩]v*_<]vk׮ܹ>}#ٲz2*%%KкutΜ9O>ݻ]xwbkܦ#777"""8v'"=z4>v޽{Yj{fŊ+;j+ȑ#h"Uq%ew.k}{H>UhQV^ͨQy׳c_ @ΝSwbbsԮ];"""X`M41c0oM6/^ǏvZN8Aɒ%SM(αZҶm[>̜9shڴijj"ƣ:)hNɓSN[oa=z4AAA+W=zdk_"""""" :EDDDDD$;z/#Gz>|׳rJ9ri۷SzuNjvc%,Y+VPL(RGᣏ>R 駟ҹsg/oM-(_/^LXX `ԨQTTӧO3={|sةS'̙?~>-[Ю];޽#:)hN8jONNN֎ "y{7"":b >3>3RJѷolٙ?wyYºu>}: ־DDDDDDDDD`8s ֎!""y#InEٲeꫯ4h?^^^|ԨQô=c bbbx}pttL6mbժUlٲ._˗Ã={RZ5}nݚ3{l~'.]Dҥiܸ15㰤hѢXsm6Ν;ǝ;wxꩧh۶-˱l~鱳x<34m ۭ[7 $66GGGj׮M^hٲ%+WfȑӾ}/+nݺ̘1s%T°ahѢcƌyԩ qqqY6ǚV 60sLvɥKxg>>D("b ? ""pl ' ӦMo%{E 3gвeKyT+5ȣ7|pMfڶgʕ֌%"H LDDDr~""MmoKϏS Wj֬Ibb";vrʩ-[@Zq24B$Z~=:trdƍ֎ """"""""""9̙3[;R֎/h…HUvm2d>kɉgϲl2ϟ@ݭTDDDD 0("{mִ򢈈HAtqU !,, ^GMDPJH"""ӊC.D򨀀zAtt4=zHUoccѣiР҉HALppcd#HywٳgÇ7߰l2 onnn <}VDD yH.D5ki&[ǹsseʔ???ԩc""""R 2DD1c#sСt+""*Vh""""CٓuǏk׮+W///ƍqvv~1EDDDD$p!=䓌71DDDDDlܸ:X9Hd>l """""""b=VYA2g…\xnݺʺwҥKYp!b:&\H6m֎!"R mۖÇ[ӧlEDDAAA֎!"""'ޝpGd+%Pѯ-S ըPTjM-6UZZԾ - Kb%$ b,,7 >#̙ϙd|aѢE>|gϞaiig}1(O\\˖-c߾};W-`=zi&@}F'Oj\QN>O?vgÇjlW)S!޽{899Ѷm[VXŋILL$99[ne>tӧO k#990`...xaV;}t~lӧO'00B0Ǐ uIII5F1gN:ӧOIKK?~iӦQ^=RRRCY:^.(^n1]B "##2p$B!q}*Ud0B!BUy$} of͚xzzfP(q|xxxo>F΄ T߿?VRx[dI={888ЫW/z }t2$3efBn޽KVZj|W|Ԯ]ccc^/f" gggŸJll,[netRFa_ou%((dg<`jժ 0kCRR;w&$$ +͚5㭷ӧ:u ///֭[ٳĤ+ HkPPPAAAC!M (_CB\9y$~~~0tBIiذ!666899iMq8<{-$CcccJ*E5hժ wv=<ܹ3W\aǎ4l0ϟkkku_Vm1q۸q#3gΔپIAv2ťK_e>>>{={.ЄB!B\WqmeEFM6UNF-[@m$c?FXX/WWWsࠫܶ[PLeJRG!^7&::۳uVgҤItޝm’%K0PįŋSjU9fٲepQ?>Qc>c7n!!!XYYQQBqttggg8q"s5PM&\3B!PIz B|7h,a׮]ڵ ~wJ.m(_M'$$"##}ho\4>}JDD[ӧӽ{wCV zɌ3~ȱ=z( WnF4o,\M6N>}I&T!B!DQJC 6`dd3&Pdqbmԩ8pm۶?h"֯_ϨQٳgjvt>5ʺŊX !L6]vq]*T@:`Rn?Gz?y$3gϼ/_k…^vN :ϸ^{@Q^cv>/\e(]4AAAԮ];cмysy?>ԩSGk{V^ͯʕ+W(_<:t`4jHkjsViQ zm.KC jlmm4hBBGBEՋ7oRJqppFsMYt)`С[cccCJUh599#GPzuhwA.]Ě5kػw/Ǐ\r3Htޝ_m۶waffeϟ}v:K?Eef @k@bb"'OW^XXX/&M/%J(0B!BUR7omjժq5N>uUlYqvv&""{vZΝ̌HOO'>>^I822R^nۭMŊɓ'TXQmٓ'OTu":'|ӧOUe111x{{ǖ-[prriQ]?4UYtt43gdϞ=:tRJ~zN rܗ666qqq!11QUvZ6o֭[vr8v$%%Ď;ؽ{7e˖'N?$..NU̩S8uk֬!,,*U% )RRRݝSN}AAAtMmpuƟcYŢ|+(Y$̛7Oc?t!vuM\z5/^`9&[(4i;K.eʕL6Mίʄ Tccca۶ml޼O>$m֦(ߋiJ&0tB')M6ݳBE&L͛ٱk. Bݺu177Ą:u0j(6oLٲe9v^^^@BBǏ׺<,, 7BRxq*VHVXlC%==OOO#*UD۶my)wζ]x)ڵRJ04[[[ը?W޽{WU֯_?ݻի B!B]֭={6111$%%1k,lmmOU~ӧO̙3r~ڶmu놭-7o&!!zamm hƍ9n`֭$&&͌3nm_>rT̔2BÇիqqq7+WѣG2dɸr5OZb W^eذa1|p^Jrr2nݺ3sLUPt钫6ѦMوbbb۷/t֍ssΝ;Gn݈whݦ;1sHNNV;n8/r $$$~6lȵk[Fy=9+W8{,Ou:tʕ+\rEmم },YRygg76m:֧O.ﱷ',,$Ο?3ϟ?gܿ?Wm֦(ߋDxmg7oΆC!(^ !VDEEQn]C"(bn߾͢E !66ӲeKFị̆؟={KF\\899ĉPB-ZDٲe܇5&L`ҤIlڴ>L#ŋs㣪fuCjԨg}[%3ƒ1bѴlْ˗ɔGL/^`ٲeٳ;w`bbݺuS{z \ ߿o̐!CT/3S\\7nET\YUjժڲqFH2e !B!y0x`8s(_|Ao>nܸZ5kjƠA>}:3fHh֬zңG,,,رcGtppϏ~~ VZimuքp98Ν;-E!2Zt)S󮽽=)Syd;,,)S/m-YϟӧO/^*o۶-6lE[~ /ws,XgXc燣#g…Zծ];X۷oСGQ0k,ʗ/LsppLJFm6-Z2(11(|||To;VkI&ѨQ#ջǼoҡCu6mʮ]h۶-aaaƭ-]ϧ3srrbΝguƦ|*I)| 4`߾}y6l_qɒ%L$$$nݺWWWÉٓM6S߿ggg/޽Kjj*wϏ]r,yiKXXϟ?ӧݻ>}V̙38;;anܸAJJ qqq?]2DĊߏYSgPX1 ޽{ ӦMĉ<~4?~́߿?rMҭ[7vÇIMM%""aÆi<()WaaaܼySk7or1ʗ/۪́T>iii\~SdD\ٜ8q"ϟ'11Qcv{ .dŊiBBgϞVKmdڵkIIIΝ;Zcŋlٽ{7 Z;qjՊ٣ B!sI@bŊ^N:QLLLLxw9sZG2eʰzjzMʕ166r׏5kd;NVz)ShРbee(Ǐz8qիʕԔVZi툗vkG}Dɒ%9tv:DҥرC!2R:u{xxh]>dl9>y~G}H*?rHummmIOOիDJ.CK/gW:8++ĉ ԺQ4}>}V;/;{yy백!==۷o-{4J,{ԩSIII믿k׮Zo߾FY^ڧ$9N8QcŋkNz>uΝ;ʕ%\uƦ|*1+WNX.TK.ҦMrY)k 3Mѣ>>4i҄Ǐ}v/;(I6FwStIB!B! Kj՘>}:ѣ[?P^r0a;vkdG;;;~z9‘#Gشij3Dvԉm۶q1vޝ>J(~޽{9rϧRJZ]T)\]]9}Z۷osi 6SBEDDZ;,СCvueÆ -:69u %^crfJ[ffK/UƠ9J2ѣG0`5k֤f͚ <???$Ɩ>_fԭ[WWW={vu};-Zh]'ز%/Gkjժ R]O<ԫWO뵨(\WMT~c $.mxEQQ! 9x!gfРAooozM޽ ]v1k,f͚Ů] B!Bhذa<`ȑxzzRV-hڴ)ӧO͍8֯_vÙ7orjvggg2oooҥ SNF/^-Zh֟IBB,^zabbBzXx1bH@c 峲 q.,Y&(m9sh޼9昚ҤI̙`^M6#Zlŋ[.&&&4lؐ5kP~,׳gOl٢p0--͛7g[ٰaqqq8880|ԩj˪UlϦ֔.]*Ux V+ <LJGѫW/N}j*sz7n^1{@Σ=|@mNRB!B!ty}}+Q?۷oΝ;ܹs۷?h'I!ěC)Z;+_iii^p1c`ddiذa{mf˗X{?Y'OxĖ_~)7ׯ_gժU:GEE1v-?篠}:ʲ̲VNz|t9yXoN } bر#>>>: uf5ޤĘ{(peԸ)SqF?%)) ЩS'*UDʕqttd B!t4J룏>ڵkYnӓ[nQV-~7_ロwr3LVx)(+em$s%$#G^W_ѦMڴiÄ ؽ{7)))z-#}իS^=N8:qqqkBRf8PWn$%%ѷo_f oŋF_ӧO՞*<~u;VO_j֬Yr%.]bǎI- }[:y}/㓛6mPlYIOOgݔ*Ug(؆ 1K,ӬZbŊNV]XX("Q0޽{ӻw,+n666+V  -WnÇ2ޜx![n5`dB!B.dUoӦMST)-[uz΄ 3V(𣢢rU EI6"9י^\2Anٓŋlȑ#ԩ7o[l)HIIQAҲB8\UR%Ǻ888СC? y\9M 4ЊݻcllLpp*އw^U+Vmg5) "l(QB} ʖ-3+W?dРA<}s\OIٱcF"ɓ'|讨X"}4$L#B!BBߩʜ9s3g3t8BHΝ6m}||022i9s=z0iҤlrJeΝKKKUOǎO>zܺuٳgSX1Ə*W5kƀZ/^`@####Ο?UVe- }~)s(==]r|t=צxtؑ;wͽ{СC- :ϊy[ݺu ))Ν;{qrr"99#FfzlΜ9eiii̜9x=ڬMQ'\d'c"F>}T3&iݛJ޽7o:\̢E8p ,\GO@@5B ~5JB!BADEEeuu###:u*FFF̝;W5jIVmF-ZСCU5kW_}*S:ng5ӧOb˯N:}v:̙3qqqvܸqSHl9)߯oN ڿXsl[$Soѣy&VVVxxx0c .]޽{ug^i*UкukRSSϏTڵkGJTuVmrjKV}U ]nݰe$$$P^=C䶞rŋ~wlmm>|ƍg6Qʔ:B!B!B#GR\9>LΝ9~8III߿aÆ1p@/Ul߾?9θ;bXz5=w%!!}fpssS[gٲeҨQ#IMM%11s믿bkkKll,&MR{2bʔ)ѣ$''A=8p%K#PIsqq!((xRSS9w[^_AK WΞ={pqq… AϞ=9zhb|Z?+Jǔ)S>g0() 4Yf۷iժ&88Jll,{͍֭[s&U(ӧ/^$993g'Jڵ5fȪ{(pOC B ZXbccYb*T/vW\Ɂx9Ϟ=L}ZTV^z1c Y|9-/3[[[J.MHH26@yƆ G6?ٳgƍGGG\r3J^ cٳgն2ի*b̀1l6J̴ Sq! 43fЮ];Zl'͚5ӹ9s`ggG}ĺu077gܸql*=zk׮n@tJY۶mx!B!B!kzx{{SD ݋%JC,[dϟ~^>.]4FFFZcѢE/PjUJ*Ň~iٲ%~Z\߿zqU<<<Ą%K{1abcc2e ?5j 333mۆ fffذm6RWʏw} .ЩS'J. wz[^_AKʔ)æM(U[laÆbcc_ł 066)]ϧcddDtt4¼γҼyse'լ);/^f:vo *U⣏>bڵ3fvڕl!>>>bffFƍٵkUVe۶m{(p 3~V*U Yp!/^`…$&&2j(UƓN:7?3+W޽{ܹSU'<<:uhoeeVG!0ݻw i߾=㲶?VVV#I/\x>QFe{{{]|+++ڵk*kܸ1mڴ|Z;+bbbX|9ŊcȐ!re{K.:]t͏vaeeu~ "̌iӦ c)))ԩrpm=X":::RlY.]Ķm۸r ˗Hg[ر#K,z),qe5pa7'O8%tAѣSLAbjjnnnj/r[tҬZ WWW,,,066lٲ888f)ƏO166VGQdI.:tҥKa!B!B!ȉOݝwyʕ+Gǎٳg#FP> ?|򘚚ҠAN5:44jԈgϲl2:w&&&cmmͰaHPtڕSN1`,,,(^8|gk}e˖ѣ|w4lؐ%JPxq֭_MxxFgj}Ʀ+ yi_֭9}4}j6oެ %V|kcaaAӦM`[ugetܙRJQxqjԨQౙ2o<.^ȷ~-e˖ؘcggǤIr [ 2qRxqԩ7|ٳgytj6E^$(l{U9YiԨ]taΝL2˗/2 ʮfС?~\իWTc IDATf)uB! Spp0nnn$$$:!D2`֭[ǏAclق1ǏW̺uhРgq~z6oLJpssTR>}ZP6ӦM{9TVnܸAHH+VѣG|嗼j\v-aaa1oZjqu~W;F%8p`a׮]Yd Lӧ$6]_N^@vZr%"Oz|t=*[usm喖Zlխ[_~E;?qĉ\ͮY_EB޸ү_?Μ9˗Q7nAUO<^L)S!Bh,--)^\~BJ*o5#GУG:? 6T}VxbI8KKK~';/^ŋ5mڔÇըQoooFkؘ/cǪWZyApp0j˕81bdРA˫T65>cJ122͛@.СC\~>}-6mٮ<%K2w\c:t(xyyi${xxxsN]ƙ3gʐQ^RJ`صkvR[g̙L81đ={a On6KfѢEsA<|ZvWF8vBoWˠAˋ &充 0ptB!B! N-ECB"J,Ibb"/_^z˕Yԛ7o^ء !N޸pgPfeFHOOWȚÙ;)xbŊʔd,S(e9*BQ\cGS!ě;wtRBCC>%Jq|iF7tއ ,^pY&ݺu/Tckkkc\xbllLjհgԯ__>?Cvŋ9r}={6vvvqUVX J!7.ᢠlذ7n:x{{6jddDzz:,YȾ˗Q}x"Ȇ˗'668ʗ/~\\B!Da֘K!kfƌ}hт-Z贎)}o߾ygݺu3gN+r躼L2?^kˆMݶonf K.iڶ駟駟jղbUg(WoT\9mٳ':lkVժUcڴi:jԨիoC9rmԨQ4kQ !B!0m0BMzzCBqs?$<<?Pc3fBH…;w4h1uTh޼95lٲs.\Ȋ+3f }Ŋȑ#<õnwĉ,\rѦMzꅉN֭?qvvV[dɒj*_B!UTTu1p$B!OOO @DD XnddĄ 3@tB! BQx{{ӿC!B!BhKX6fƌQ]vkNܜ!C0dȐPtilc+Q]tϏ{>ݻŋݻ7nC!Bߊ+Fnݰ2t(B!Yb֭[PR%lmmqssiӦS!B!BF.]D.!,, {{{z] !B!0p֭dΝsN*U'|bB&jԨL!+BfVʤI xEx{{b0B\aY'44a!%xS|ׄpIe,\M6N>}I&T!B&W9F_~k׮߿333G'B!B!$vvvl!₝(;/...E!^{A"!$$Dkybb"'OW^XXXУG&M/%J(0H#Bd$/$\6lH߾}Yz5aÆJ!B!BiFѣ B!///C!=oooo0+@իWs=*ׯ6l`Ռ9Ҁ !a!!-I(b:5h.]ҥB!B!"{III̟?ѣGӿ B3I(B!ț/^l2Ý;w011ʊnݺѽ{w \ ߿o̐!C055Kɓ'cƍhтʕ+TZ[[[6n)SL!Z!WWW\]] BZ !J2Bkva7nAAAC!H'OǾ}O5tXBJąB!n…矪)))={g]+99Ç{VZŹsXp!Ŋr?w&!!VZi,kժǏgϞ=SB/44: !EԫпU B! /...D!x(uNNNA!huNLLdΝlذAQreyn޼" !xlݺ!!ȇVj0xc`lmmIII! 3fi&U뉈QF|XYYquOپ};ݻwɓj3[(> ᆱRvaIBqnܸ<BU_򪐄 !K3B!yuA!̆ غu+|,^=z0rH]p!BQvZBCC~:iiiT\;;;L.] b022 ==]oԔ *дiSO~\NR.\ʕ+ٿ?SLر#C R]|9&LѣGˊBĄ3&.[ɒ%y^^^DGG@^իZ=eFӧSZ5ԩ?@ {YҥKԪUKcrQ!ěHF0BѫҿUZ'\7q: !!!B +++C z9r 6cԩ[FҥKԯ__2wޅBFwnnnj,unb˖-899aʖ-k(_?H`` ~~~Jk,))%K e??~3g2vXO?tPmK7cǎ$,,0/^;ݸqydddy!eʔX)uB!B^ۄ QUQ(tuD!٫8"Mǎ%T! dQ#uq6l3aѸRvm}Z :Rhxx8 .dӦMӧOiҤ"B!,wޥUVDGGSZ5+>cj׮1W^חYf3/ھ:-f HMM%66[2~xXt)#F0@%%%ѹsgBBB011aҬY3z->}ʩSbݺu̞=&]dEfo*3[u {{{8mXhׯgԨQgٳg.Wfіħe7 B!B<5BaP8!Q|999d0⍔H'h-OLLd zIDB}fddOxx8TVO>aÆajj 4=66Ǐm6ZlIe5jm4h*Uzg-'**O?Gew%88Pvܩs٠6mė_~I^^\v.\ÇB lٲQFQjb:t(M6U3޷onnndffeofӦM޽.]h<ɓ'ر# (0t߻w/"226mȲOs<~X.&..86nHLL oVV1~999kE\\<~ӻwo:gϞw6]t]SXzJ搛7o֭[ٽ{7ݺu=~;(ρسg~igÆ <{QFl!ѬY3Xf |j2/f !,,Y%eʐ!C?>쳷:HΝ;_|"gnnNJ*<|WWWj֬޽{i׮; *Dž۷o_֧'<.W uX ay+ @ bѢE*/E\p`<==:t(\x4兑=z`ӦMܽ{۷cee7oQQQfXbׯ&'' Ο?ϼy 岳5j6mp7nϞ=+CA۶mmۖ >\'AyC>s?~INN&33h Fvv6ܹsG^~~g߯^ȑ#cԨQ\zl=J 8{, .;@^Jtfff|GS%ԻI޽IHH ++zӧOׯwxL///>;ӧO֖l͛";~x?~INN&;; """hҤ ׮]cΜ9e2_IUINN󤧧tR/-- Nbb"YYYѩS'mhEuFhh(P"1::G2uTo.mٲ$ɓЬY3N:Ş={NeǏ{ I2@ YM?@ 077u֬[cǒ_lja֬YL4 yիʢZ LLLh߾=[n`Ͳ%euq}:uDhh(M4Ԕ͛sA[.㩫2͛7СCcjj{Ν;ܹ3>d͚5Hv̌VZxRʒOrr2M4)t7]K IDAT~UVѤIvڅ^Zy@–-[8q'N`3F-&L`޽|8QN>sW0 000(^|iӦѪU+T1UTёӧsʕ2oEn:/|W7oĉzj(+]m'-Z`֬Y;;; Jl^i{}(ͳb<|={e={Ço'NNNO?)QMK{{R,]?NllDyw122~̞=Ο @zب@#3FaÆ)==KY`~) ѣ:88V D~`N544dʔ)8p@c}2GGG=zR^N*((7n6mJ~~QiiuSiҒs璓7|Z>w^LVؘiӦil8]]SWyeOJ&MR k~w&4t-Zi @̙3P)SҼy@ (C F**Y&_|E9j&/R``2667ミH"@ ^,ZRGap,]|&N 7.#M"%%Cj\py&7odΝٓ[/%#++ɓ'b 洴4N>ӧYp!cƌa…1bĈVAgHKK#>>xXnzZꓸ8رc111:`|2d'O߿Dz} "..BA:uݻ7P(عs'<|*Uо}{틉 |c֭[ٴiӽ{wϓ'OX~=gΜؘ-Z_֒%Kشi.]Ą6m0h ͵˳gرc'N 55ccc֭;w<}cggGժUjժѴiSߏ3*T(^._\*0ꫯ*q3g111İj*\￁蜚믿lÇjQ<$@ ^uYfrR$|M1k׮ѠAn݊~W_VVVci$}%CH GgkӦMӓhCΝ;̧~iLY_aͩ]6xzzҥKAt9ZlN6m[.㩫2~pW\!11SNqIzҒ'O<NQ;xb*<獶 y‚ٳg3vX ={駟T@Pt,e}+Q:@NNח۷3p@@5iӰ̟?_:ܧObcc4f۷s=_@  DHHHh,l ˗/[nX[[SzutO?B(-޽{iӆod ++/2w\*Uqqq!77~eʢGOɡCHII!''СC޽;YYYx_䋭޽{9rggg Me9p瓛˭[Z# Ȉb Cxm ɬY8z(O}ѣGٰaCښ={6ϟ'++'ON```Ν;s( .]Ě5k_dǏP(h֬15kBĉt@ x yЭ[78YQ(\={sNY'O_ʮU8brYygr(]WBJ J*j2oI3VHѺe^Õ"k3"(>}q.C%44T%7ظq#}I&*~K2?Mkf$''TL}OO[ʕ+6]]SWyeTR}vlmmŅyNjjj稩}]_ǔr96lqj4KUxQs[ -Z0zh,Y’%K)̘@:"9X4mTFd_~*<޽ҳgOgϞ<|ݻwf@P>xzzr>cohҤ ҨQ#f̘'\2;W.o_&OLdd$ɓNTZ.]aN{{{-[Dy믱yL8QŐHP(3gpu/_̸q㞋n>'ՑF۱Ce<6'~Pv4 ݝ+WиqcfΜ?aaa\tIށ]ر@%{2s[ xhz-OyҥKYt) (7=e٩aѢE888wΝ+}"@ ʟÅ&ܹC;vcƌܽ{̙СC0`GfÆ EFdƪUbEf(McnKPĘ1cLJm۶)NŨZj4mڔ(:@ ׯ3b֭5kdZ#&I8E} ֘bkkԩS8pքogg/֭SE BZ055VZ :TkjveO>MNJ*h5INNfԨQ4h333*WL-3g֗OV˗Yb:t͛y-Zo>LLLXzZ4m]^w%mj.`u?ֶ% ˖-CSZ5zEdds&%%1`W)ݻWκкuk0^Sѷm|||4g֭ШQ#2222E_/˱/j~ <5kbbbBÆ <.zdJz3O_N-P%Wm ʥߩ#FbllL&M5jq;v,666RvmzާÆ ^zЫW/>|8o65|_O[_~%5kԔO?(>کq߾}ӧOŋ~GT @FHe@ :R6 ]) `Μ9hXHUhEk.=z/m Mr`Wv- ֭'ZZEY=O9?;;;Re5.md}ʌ3ɓ'p1bi3''9sFJJ "Q(4kL8͚5CPT #**>uq {.hѢؔP޴i[p.\HT lQ4F.СC*ޞ@n߾MNNofӦM4o\&'OҡC"""P(w^ڷo/_J>}-Zf._Lvv61{l7oν{L:~<{#GYfxyy3wRo}YW^5 =@%է&?~Lv0aQQQ<|P6Zۿ?:u_~)qGxx8l۶Trrr8{,{viZjL_}uikʕT^UVػu>>>e,--qqqJ*DDDh5r TZ2{M߿{{{6oݻw寿bܸq[a^^^^őQf^n߾ {ァR^x 8Xq㫯T`CS 0ԩ4m)SΊ3 KjutEu}J~FO>رc<}Hlmmf޼y*Ǐ >d ""&Mp5̙Sf)Id%_ )boS[~V6S.*ZËft壏> ..H9___hڴ)ǎ###BALL mڴ!??_VGZZrDSNx{{uYYY$''xbxo*2\Sk[ժUcժU%;?Ì3hٲ%PN~~FCI0`e:HMM\x,Ξ=K׮][Wɜ?t/_'90P7RSe\SV裃=2-ccc{I#mۖիWMFb۶mx{{v<5H (s̡qƘ Dx7oܜÇhJwѡCLLL:x UfA7n|9ƍ ֬YCF`ҤI*XZVqm)[|9 6Bvf(.~`ŊM~~VPWWWf͚Eƍ1553:T٨bŊA͚5122ʊ;qF'RV- ,--5fbŊڣ@ :G7уSNP(`ȑ 4ccc5={>/x{{cffƆ 6m###~M^2mJ]jժqʕ+撙IBB/3c TT\]]IJJ";;$\]]Ғ1cƔ <}\5/k>7|pjժÇqss… 䐔D߾}Zh]t֭[mOOO9ƒ>|CҮ];ܹCǎ\ۿ֗͹sO9vZf 44\\/@ (k/R/uX  ŋ^ׯD[n7 ::OOOĉTZʕ+DEEquD sĈrz&M0|p9 DiڔǎK]6>>>|WDEE;oq2m/YOb޺ukZnMJXl~~~E0k,&M$/bCA쬬,ϪU۳uVZl͛hC%eהӖ+3yd#<<GGG9СCYj7ndΜ9*yyy!dPc5k֐NϞ=ٶm\ެY3O4P/kJ;Og̘!/lZYYם5jp O}\Pښ۷o燵T\txmUX'''|2111i&XrܿǏ?eAM4+giذRk™5*M/$RSSA5Ο?Vּys{J2H^_INd8|0f̙L>q...*~aeeń 0aBrݺuHTPu떜֭[3r"uUVZ믿ҪU+5+WdS[ϝ;'JkBr6oذ!+Wdذa,X@Y6m:uJlPx6 IDATYf8_B  #,,LeAAAԫWO%aaa\pA xE7}yUT۷ӽ{wvΝ;U兑N?,_/[[[[k.ɓ'3bVZ^ 0sLmFrr2O3J)cʔ),_7k122bر,\333 aȑjA9jԨAXXZ6-Z\-X<cSj;v(o%ep2d___}GFFYєuÇRfMKvIHHP9.@ (s%ȈN:k.Μ9CV8{,O@wccI^_[~֕ybK9&]u;w^LVؘiӦN8880h AW˗Uhܸ1SNҒ͛7#.\СC|'Cq-dϲ{MHؘ)Sh|Tzv~%nD۶mپ};֭㫯~\|u֩:::{n~GKիǣG_سgM6o s玜,E-M2fRRR6l:t^zr߿۷+$<R@zQ8H_$DŽwOi}¢DE[Jݝݻ{n9~8ӧOgɒ%̟?_%Yy0dGPP'O >k֬P W={… ݻXZZȤI2;]|Y6hذ! , :: ׯ4iFm;;;Ο?O`` ܿ###֭>>>*N8;;ǂ _IMMښ]2uRQʊh.\HXXW^%''z͔)SԜR7]Ek׎xΝKxx84jԈ9sгgOrzյtO}_b2{ly뭷pvvf̙jkÇ̌e˖qpttdܸqՋ 2x`V^M߾}u#SSS-[9rK.S*UDFڵ+^^^[QѨQ#K[.}eTVMM~Æ x{{EVV5j(/#''GkQ@  S"11QeEꊱ1!!!c:uh߾=C 夬ׯ'""*T=FXCA6???޽ub*:@ ( s#aH:wLXX;Z"** CCC9DDr 5jԠe˖ԩS 0/5.MŽVΐ!.l4\Vҗ@+IIIB&''k7b]F غuoA9U|QXYYǏy7JTG{arm"%$'`M'r:uйsgOU J2_ŊIOO'==7|6$e!Vug]y׌HN.8\rDN:ɓ'JOH I-[XM6Ŷ|v}ٹs'#88XZ\})}wjժYkVX,1dNÅ_{M\p(b֭[{ЫTrҫW/;ƭ[ԲO>>}K.1e}fff*ץ;kkkT{aQWJhKSӇkײ~z֯_"ޞX/r6O={V?jSjURRRvZDj-+#ے7 ״LƍIKKݻnKi`ٌ;Ag~'N7@ ʼ@q?zѾ}{#1|pWM4a%/n=A7x3rM+XeU_󃂵M6KN>Jx*Jf@~)8q6_-h#((H,AIؿʶE# u@ݒ^ Szu>HNN&66V*̛7AѱcGc啨-)҆d4&ɐ4mJQ2 Ql۶M"JHe AYQ֯_OHH*U",,*UHJB2\xbrssUOmRomt1:t(*oܸƍ۷/M4QɖTZݔg$ϗ$_XSR9]YW^5+W^l۱͛'G}C/m!`mmM@@.\Օ\S[Mggg:u+jʌ"1h سg<~ݻccce5i SVYUy_^ܓC4annٳqrrRJacc#gq111e---;w.zCCC*VH˖-U+xzzRzu ]}E-MҥKyw011Ą:uЧO߉vannΙ3gԎ{,--i۶+T6mrif̘kCA\\ܽ{I&a`` k~nm) {BBgΜ!55<,--/K-Z0zh,Y’%KQKg/@ (=h $9`@ ː!CQ:,?BWuF||QwD||wܑ#8::{n~GKիǣG_سgM6o ܿ۷oݾ}[A xiii:gpcǎ-[EZVn%n߾=:tVZ+%Zl3[l nHOOWqHKKu+ >3>3o~W;ƱcǸt/_fܸqٳugvӧ՜ B2fșfplUZA~֕}Bdd$=Dpp0 ܰZj{Z3)hBꤥi4OOO/qVVVl޼:p)fΜ>הw=z(p*ۿ?={(oӵkWS(w}WdZB[[[IHH]vݝe˖j*Ə5Į]x葊-gΜԩSCɓ'enݺxzz /l0_ֺ3~Æ cѢE_QFaggӧ4oޜnݺW_ѨQ#Xn P744ٳgddd9K)BoeJϺR^LqɎEESXz5#GTwg04,:>aggDZc8sFY}zڵk˗/gŸ9sM髯off& "77#FvZNBB@Plڴo 6ʔkI&DGGA$..Nce:FP0l0ڶm%o(p<ݛG/Z[[駟vڵk8q"QQQ書W_aff2iܸqڵ[naeeEֻJ ݺuve֏?`ȑGRRPp?駟y @ ^o.]JΝ9{,;wVo``N~e ''~@ 2(gDa@ [5fP^ҥZlOOOڶm9&&&4hЀqJ s̡[nXYYabbB۶m tiӓիchhHNNPIpܹ kkk X"-[WXѮ];9s挚gΜRk4q@ (-Onn l'NȹspuueƌE!Ek 7IHH@wё]r]OFFc߼y%K`hhĉݻh"={RٳgCBbccj4~n;ĉʢgϞjΝ#-- ???6m| YYYt҅:KNRk? ֵ~p?kE^30c e5(bէ?>3k~~J|>̛75k3Ǝv|})}wsҤI矸f۷믵w޽\2ϟ'((DVVcM___k+}6w_y#_///ݙ0aXYY/Ajj*DDD0z"י˗/8ַrʬ_?'N0uT5e˖iiٲe\v@5'x{{cffƆ 6m###~ www@=ZڵkV???\Bnn.$$$xb>3f?TiRJDDDJRR$%%Jdd$3}(=8ӧO%!!A6R^3~P`gq Zn͗_~ɑ#Gx-[1(H1 /_f„ \ֵ 44\勼f"77;ww^w/&&&cl\t4cĉܻw<|8jøqrrrHJJo߾DGG+`eeŋ!88Xe>הÇYr%o9sۻw/nnndee333c۶mG\riGhݺ5.\XVZ?~z=t?<͛ǂ 4ꡉ̝;###,66ۣP(׮]ˈ#Do}ɉH9IMX"7oVkWӱ׭['wafΜɶmHNNo߾O?~ݻS:xyyadd~СQQQԮ]?KKKy>sA_}ui!--M@VG_c3p@Y˂x班-ƬٳgǏe1p@ 򦴽cy[ Wg4+o  @ (?@ J([G,cnn , g @ٳ',\p޽%L4]ȗ0^^^4lؐ MFFgL4Ioϟ'00P߿u }m:;;ǂ _IMMښ]2uT{=CVVVDGGpB¸z*999лwoLsM022oeĈp!HKKĄz ;;;x1,X?~9sӧOi޼93gΤW^Zu[~ްaDEEE5u1+Wwߥ[n5zDu˖-… ȸqwaU_ 8vǓۜ)MP$sDֺuըQ#ըQCΝS:u[HgQF:qf͚/RU)SRpO+յkWc Ȓ-[̙3D@ $+\Ysٳڵkq]xQ/uy}ZE[o)074:)L0Aǎܹs"]rE*W&NT~Gڼy$Ν;ǵvZ*UJm6%$$I&oҤ9۷sOq=rٲeZle_h߰@ PڵԿ<3gMںu+BF<۬xŋ/^y,y̘ o,YO۷okԩ>ݾ}[ӦMG<}i:xV\)'''OZv%I5kLw|j[j߿KS7믿}jӦM&$$_jܸ:v@%%%Y>^+WӧB2N+\ѣG>СCetx&O>rwwך5kdkkkt$s(K^^^F INNG2d>SNJ*6lQFi_}UIҏ?hiv횤VxXj[j ӧOKԩvN۸q$_&IɊ֭[g)XvΞ=:uhĉZbcc5{l9rDPLL BЬpEcmmK_WDD@kȑ{YFȘRRRdee%'\gH.$#S8)-]jEڵ3iŊӭ[K.Eҥt钦ߎ;$Igϖ$J*6m<<<%La+ӬY3WFRvTT)#@s=9RZ`Fat$(GiW^dR6m$TQ$WWWF!Qsk=zs1gŒ%KtժUK.]R@@@o߶]p!Neʔ$mڴIt|}}3?ӧu];vLgϖ$kҧz꒤tǧ9m۶ںuNuΝ; 6l`闒qnݺp5w\-YDgt(0~lR{Ν;չsg#@@ O3zInϞ=ynDM2E]tɓ'+111S(n޼iӦXb1c)btMIR-$I .TյkW=s[lYG5һᆱ+WVZ֭OӦM%Rۚ7o] @e˖I8111$(&&iJVX5k֨w?4|KGGGI͛dK}9rs@ӧ6m޽{F|… jҤ~8pnQps\}͚5e˖d2),,LZJW^U-m޺zVZe`2y߽W?Ə/'''IƏWZV5jtҥKFM4є)S2wj֬)rʩW^Ztlll,}ڵkbŊ):::*Q|ͧ>7W#6buN:d2iJHHPj,Ikٲ$iҤI:wݻ~M-dҠA,}SW|r>>}_%rJf9::p*UZhիWyرcU|y.\XIIIX H'OFmtwչsgC_|(YF?!-((Hjժ7j޽z%I+W[f.]kʕ:xVX!''']pR(+jƍڿ'Iڵkeƍ%I:xky"u$}"kF(UT5cƌl?޿$f͚MmKMH+>>^6mlmm@RLL^z%IΝ;ݵvZ8p@кu4tt*UJG͛ua}7/_۶m_ڶmpuqYpգGV!Ŋ֭[;v򅔔:tO*\ѱ ߢgXԮ];휶o>IҸqTB+VL&MRLL>sKBI&W^֭'Jtc?^*TPѢE#I?,S8pҥbbb=zMwFΟ?/鯂UT)MׯO~~~2d\\\r+\Mo?82Zp4i$#@W#O4[nzAUV|]T)I-m#Gu!:tH|'ٜ姥8}ZTN sCӦM%I~~~rܹsd2߶kѢ$i:y޽'OjΜ9͛?ܝ:ud땐jժYRƫc\|c)SFi&%&&ҥK}hիKbccӍږV``l٢/8'l۶M͛7W5MVIyo߾ڱcN<:Zݻ]|YKӯB ڲwޚ={|}}E}O'j̙2:X\򤨨4;w4$fϞ~K5~Gr9^۶mնm,agg &h„ ퟕhŋl6kŊS%Iqqq:~F|&""JFG|A3gԘ1cԻwoըQHk޽*((HK.Հ [[[lQpp%88Xѣŋ+$$<1٬`cYڵ1{OV7rŭ[h}rss3:<(k&)Gl>>ڲe #,Y?ZdQ"##ժU+L&ڵb ȣ(.88r ˍ<+bcc%IK⒮˗%Iu…,U,i2<OZk;;l1K*%I~ǧ9rOCСCOԯ_?fZ]vMTdtcCɒ%իW/K;lٲ򒷷5kBx$<5vXM:U^^^rrr2:Ç_~ dE vIJIIImeen܇<֭[#u}-[Fq_@C/^ԉ'kYO8bccyf9::fLC2\JuY} չsgI\7n>7nܰrZŊ5aM0AgΜQhhBBB秚5k{VjՌ %ŊӢEe˖FG%%%o߾Z~V^^z pΟ?p=ZGVxxx.曒9sӺ{N:9sI&ܹsw~7-ZH&I M]iٚI2Ź2.:ud땐jժYR3W.IM7nj[j Ԯ][fŋuAiFrvvVÆ pBOF䂎;MÆ Srrq<_zK_~lB#p@.3f٣t;[N)))֭ꫯr+ӧ#Gwɓ'գG4lmm5j(v2et5yzzQ7oNd2=r>=i+'[gϖ|}}wqq|ݴiSٳGON.IO$5o3J5RF`} մi4fhBfY*Sq9_jŋ5fxF]|YnnnW^yH' ={d؞)SK.rtt<==5yd%&&rJ91110iٲerwws="EY3f̐$X(QB+Wl .RJEZzuƎ˫pJJJʶsy yqN5jF666Zӧ[m׮+tFGGDK#.\Xm۶ժUtEDDL2:tokݺu= ʕ+״igtϠ'NqƒRlUJJJ!+++l6g'fvCN~ٹj/U\9Iҕ+W>}h`(cGvvWǎlOgҥZb6mڤKᡁ'͟gƍڴiBCCsNߖڴi#kkk#;wTV-5jH!!!F ٱc:w hƍ*]ёO.x_USNUVԸqcC۷odNJHHոqcuQi1qMAb IrppdRXXn޼g {e2~z{ 38!Իwo988)988Xѣ+]zJqqq={.^(777999iȐ!ڷo@|V/Vhhvetψ SNںu+Qp@&n߾+**J񇒓u9M81]ߤ$ 4HAAA駟x\R#G9׶m۔&MפI%$$hvnWJ|}}ժU+kRLLʔ)Ӵix+22RӦM,{5l0߿_/^ԨQw^5o\*U￯'N:t:hСJNN6:n̙۷Ǝ5kH 2QNNNZr}5{lYYY 71:1LYj!.%:i$+$M}ylu-yyy)::Z:vht$@6LJի=t^|YX.\x\׮]$,Y2ݾԶ>VB5lJM6UӦMh"رC:uƌ-[l6SK6:. 4vX@q)..NvR F\WH]"'WLJJJ팖{nݺc*T(ݾ6$/VHH1PfYFP [ozKڲeBBB{ޓfdgggt\lmm:hjٲёs*8p@UT1: Qp@&ŋ:q^{5K'uttTll6o,GG'^W\э7doofߍ7,}(H!@N1:bgg.]K.q6nܨu]ŋopFHrssSǎ5d8qBFGOEGGC5jPdd$@Ex7uE͙3G3gT5GsI׷e˖Zz&MǫZj~֮]>L&IK.J)))|*T I^\tbcc-} Qrr1Ȳfc ҥKo߾۷\p}*W&M9lѢEU.\q@>^zUk׮ee3(( >>>ꫯ?O>ۧO޽['OT=쳵ըQ,eʔѵk)GGGm޼YM6՞={ti9Ӓ͛gω>|X/_6:|B jذ1 aÆ[///-v>|K.)44T!!!Zd*U$ooou]QTre_Ҍ3d6U|y#G͛qiذa?>+@G _9l2h޽u떪T=zhԩ-QV\˗k׮]z/. 4H/رcd]rEIIIvi…V^䈎V%oΉ`ŋ+$$)٬`c@L*UhҤI4iN8kΜ9Sʕ+)ǏWPPƌ0ݻѣG+ @~~~=zё lٲ:ujxI?TR=zc?LmVm۶MVxqfXBqqqg8p+wO<< #>>>%>rKݺuUn]j Ղ 4yd5jHڵ^|E@gkkŋC8pZlit$yXbbz表(H\Bxו &m۶*QbccGIի[[lQppƏ/I z葭s@NU@B'VVVj֬5k jΝ ĉ5j(iFPҥ 5x`;;;uM]]v۷޽{FGrʚ8qfΜ8C9ƍD:x b @cc*THfYf9Ȉso>i߾}ս{T\95lP}s$)%%%zX…UdIUTI[֐!CTr͓ԩ3gѣWc=zTW:ut)Iϫzi2[9hѢX|||S>y8󒤟~Ik׮աCtY[[륗^oݻTRig6NV2p:tHԨQ#u5WVL;zwO?)<<\j׮^|EuUfY 6)7n4zh[8͛7[o֭[%J `V)\zUj޼/_s)11QIIIauAnnn?[ ܻwOׯ_5o<ժUKk׮5:Vݻ$iŊY/8i3F>>>Y|={`'p]|YIII}Ο?e˖GW^}8F;v4n8;V:~ѱ\䤑#GkΝjܸVI&̙3F|V-Rxx0ҥKo[_|'?qںu3g(!!AΝ;3gdɒ޽kt|'%%%+))I?vܩ;Ν;իlْYϞ=UpaΝ;{H"ѣ \ SըQC x8IF9-11QSLQ.]('''yzzjJLL_ԩSuY=zT;wg}:unݺUll1 qssSN4d%''RRR4qD S)RXQp۷.]7xCgΜј1cTV-FիWɓu=sڳg.]jt|ZʕS֭+%%Eԟitlvڸq#nذAׯ_WvK g2d2He˖رc%I NN<)I"EVٳ%I32cZJW^U-m޺zVZe`2 W>cڳg4i"???U\Y͚5Ӓ%K/ (66V7: \^zOVҔ)S#(GVVVxŋ^>>>F3bcc5`UPAE|||t g>,&&F^^^zdccUj„ uV~ںu^xmܸQ=\ԩ#___Iҧ~nsԻwo/_^666*_߹sG ,믿.{{{)RD?ܴ{'iٳgrF...ڼys#IZb#O*޳_^VVVj۶ms~w*T wQVVViޛ^UUxquïSUVjܸz۷gX qرd1OR쑺:QFGYW߿KS7믿}jӦMieQyu^e˖׵|X o~}QjJ p .hj֬Zn9s["͛7 \rvL&͛^YTP!O͛7bŊ0aԾ}{YGcT\Y׿4k,@.~z-}ڲezmt$@ZGCqСKە+W7jÆ ruu}1lwѽ{,m.]G}۷+::Zŋ$]V4h ͬҧOծ][Z-[+͍?~zmڴImڴpÇEs玤 6oެm۶ijܸ~֭[czRR=Gj:t^|lxR*THV"7oE:zh~MQQQںu"##աC,4hǎԩSc;N:i͚52eh׮]Urt}.]ݻwlٲrwwl'nnn*Y٣7odɒiYhRRRd^:;۷okΝ*Qܞhތޥ~/wq5_Jvױ-A$)2d63vcF FB|%0 *%3S:~>ky}s=iΞ=򦤤0x`A;7o$((SNpBLM>Rw2k,Wv.\<55bbbxQ ߿?SNetڕ&MPF ,,,\ٳIHHAq}ߟM6lӧL0ڵݱcsuuѣܹnݺe|B!,,,ر#;v$11-[€ʗ/OJJ SL;b0`.\ %%DKj?s,geeE&MRw2<~X;k!Cm oooR'((>>>:YzrMqww'%%;vs=V\ uf߹s'ɸcmm… EL\\qa.]k֬ԨQ9]6Ge˖-iDGGkhVXpqq^zsN0`@ظq# ,8p@?/EյkWMFYr% y 2đY+WC_02eʰqF:D߾}ػwxVCZ1M&B!"c666x{{en޼dɒ׏_Ug"!x˗sݻ"fn_f9}Z|裏T&M֭u Ѥ;wΠΜ9MwrvvVӦejzsm:tBCB!Fqqqj֬YYN 6Lu!xyxx*Uc"vR T-[L{4!BCVBaM@T IDATtB-l&lolFuV>tw6ܿ`ׯtС\vM{z(~z~ɗ/?~a?u;VlYkQxx8|^sssƏa{קjժ4c_N5pqq4^777)¶m۴3]pB;w.&&&,^Oj*T77l͛gzn"r uIOիWpwwY/ܮfe={Pre,,,h߾}ñ"**9sгgOHNN68UjU?>wf|7wrr2(_.X Yw@z4i}a !Q͞=WʪBAVcǎtԉ_~… ;$!1p!B!ⵥRz\p!:4/VPPtk^5t` Y> MAӤgp  h_?|0~~~.]ҥKӧO6nHJJJ~yu1ĥKgҤIm;;;RN:u z[F\uFXlNf_s<3Y&xzzr> z*ڵ\r8;;s~g:ĝ;w*[>O3pH44[fD>|0˱,XI&ٻwK۶m[oɓU,Z:aÆ3PM6Ņ[n>3 Ҡ|w4 =6B!T~)Ν#::/_NթS|vBMʖ-K`` SN%..!rȔ)S`ĈY?BdB!B5d5?)P7oH"zy4/bfٳg }`B _3sf04:" 7~5VXAnݨV.]ʱ؞G2ͻn:ʗ/Oqwwgʔ)ڵ;Kmf4fNݻ7ffflٲEMxx8{v7[l`ܹt ݻpB|={|vecccPy7hNvTxxh=TB޽QJ1m4{3,Xwww-[ƪU̞=[G3xgGVVxVժU4`ܔk[X1ߕIB!BgggfΜիWٻw/gƌ899ѬY3/^۷B2cƌΎ#G;!Kz  >oeƌ2BȀ !"...; sexl9#G~WB46ܻwT[ZZ^3g0l0LLLXf ժU{a΂޴iSvaPSX15/){voƕ+W o߾TT ?ÇJl/s o> &4BBBҥKTRI&l26ofvHSFsyեaooO6mHMMeժU]Fɒ% =;פe˖#<<Ǐsa,--ܹ3=z_?`˖--Z֭[TզMOΩSx 111L>]/o˖-0agϞ%--;w0o<\\\Bwɀ !"*߿?$&MvvvĉIJJzQ !9]v/?yD111C:Gɓڟ/{ٲezN: NNNڴӦMٳ'̙3155et777k>}̙3x^!011!66V^ZNƖg'K ԩ ^x޽{={߆>ڵ+fB)SF)-"]tpLll,E}ဢehmݺ///={ЮvEYt).\sss*U_|-AAAbgg EXBgѣG_׭[=zƬYծ''OJ*XZZbiiI ?1b^^^*TKKK\]]4iR1ft^Æ c…hтwySSS,--TC aAퟬʵussƆz"""ծ!B!xulmm%<}ZXյkW?LRJ 4H>xa5yrttTfffBݽ{WOLLLJ(}:%K${ҨQ#urrrb޽TX˗/R|y,,,weرܾ}ɓ'`PT)bT^+++W͛"882eʼt7Urڶm-ر\-;Y_3 qwwgΝڲ~z5ki,cǎ`Ŕ,YsssjԨի4i+Vرc֕>*P֭#lذjժaiiI駟X`fff/l; ۷o*D;˖-ufIƍ֭y .͚5ŅS._}֩Sdɒkӂ.B!x1GGGF9s g֭ԯ_J*駟r9c)/eر1j(>|H`` ʕ '''&L@rr/&&&^Z~gwlڴiC)^8C ѣG:y۷/ŋښ^zC})'OrXYYQ@5j?NBE}aaamۖ͛g/nXg !1!oޠ.os޼yڴ5kd9ǏU޽7ddzRJթzj~!psΩ}*GGGeaa *ڴivܩp:+d=}pRURE}*999øҥKUv픝PS*UR R'O|a?*???egg͕zӧ͟Qw7nVVB jԨQ֭[[V߳u=ŋ+WWWg,ʕ+Uڵ*Xjݺ矕RJZJuWVH).\}mիQ%&&*@(P òUTQQFy3?D);tt/X@j߾}֑{EdFjʍ>}zSnZgfεV7V7nP7nP7VBeB{=ԩu5c&ٲm6pg٭[~?RJB iWXr*TrppPw;$PR+w|*W^N:};f̘ ?5k֫naC^={255UފB!Dv7uB1͛7W*22RGi=t9-[:wz?T~駟2E)}$::Z9;;#Fd!xdo/*@UTءqyb\iii*88XƍzN:SeCFkFFBBB^aB>!B侴4gկ_?UHejj7o/^ܹc"K<<<;CՠAu bccU&M{mݻw+ռysբE ebbvڥ͓3SL1 MyWWWuy&LUxqm>MZ ԑ#GǏUҥb(T/?~ԢErkE6d>bZZ6l211Q3g~Bv3QJ)BWĄ`|}}pqq14mtЁ[nѰaC5jD-ppp+gh>.\-[צAݺuYti<Ύ;(VNw͍lݺ%{B!ЫW/4=&ի ؐXq1c ||| 1Bo.yB@~ !Ǐٱc!!!lٲ'O憏;D!x+WP\9>}ʥK([A h޼9Ӧ5ٳgӰaC6ls711VZ᫯` S!B!"YYYڵkuAAA<}J,/ᤤ;T!HW2e033\rh *SfڴiDEEQZ5f̘i;.\RKEӧ4{5)׬Y3fΜ5;wdԨQL6LcNVx/޹s֭[gv)-B8p!e*mۖ۷3ydjժErr2-Clذ!2Ç/<Tǹ&MG!B׬Y(\0'N *U_ 3hѢqB!B!xlmmcܸ֭qok׮ѥK4hyAS!^}Ogx3{׆ Ѽ zy~:AAA4nܘD&L@RXdA r_vp/N2WWW8x`6B%.B,(X ,[UVσ={v7$::G0bŊIB!Un]bbb>|8UVsssJ*7|'S!B!h/ΐ!C?$00#GвeKJ.ѣߌB;PJlO#Gfm;z{qjWB!rB!]tҡC*Vȵkkٲ%+V`„ ;+r=֬Yիqqq abbRWRti*WL||ɫbeB\gjBCDGGm<==4fHB!D4i҄F( IDAT?'B7ǏٶmϤ憯/;D!Dc}]j֬ɏ?hpȓRRRׯ֭ᆪO>I![!"ٺu+;`;;;B5aaaxxx; !&,,ݻ; 9rDB7NXXC!deeE׮]ڵ+ Oһwoˇ;mV~ !r ,]vܹm;$!ɱcغu+mڴ1vHB!22B!%WꍎΕzs5}Æ wlٲ/_>#G'BdMjj*=z0vB!^.⍢YB!o s- s-ZݻC&M0555vB<͍]GqIyB\\:tΝ;DDDPV-c$-$.B73Ce̙|ԭ[Q !Y,/ !B!B!rL%r !!!]%KHϞ=իk6vBc4o___<==eVm!?>۷gΝm! F:u*&MbرL>c$B`S)dM6ٲtB!B!x_z Dfu$%%1i$OOO&NHRRRD)B!Yfffmۖ˗)R~!vvvtڕudBk FJJ⍐ƠAOYp!3f̐B!^/…BzŦMBڑBU...>M|rnݺ6LJP/_СCB!BmOOO߿ϦM W^X[[ӵkW|||hݺ5W;w.ժUc;!^k=gϞݻ 6ХKc$BW^ȑ#9]"޽CBɜEnCS,--)^8 6$ {{/F_(6lH=^YBz*ݺuё7ҥ 7n`ƍ8::{n8{,/^-Z0tPlllm#ٝ;woٿ?IIIjՊǧ[>6}6?Vbb"˖-c׮]/^ӿ,--Xv-գD%Kڵkݻ7 0kB!BdSBߟJǎ)V=zLJƍ,Beʔ!00SGR[nѹsg.]Ğ={hРCB!ҫWV(x_!!B)))ڗ.\H͚5V8q n:RٓJ*Qvmc&EKŅcǎqIɓ'~: 4ёŋl2]_fBB}ڴ_~G}6SRRM5?~<˗ʕ+L6Ge<<<8tUVՋAv!p!B!FTlYƏ9y$k׮%44jժ닏ʕ3vB#bΜ9tԉݻw{;$!^GsΔ-[p~BM B! ၯB!^;!!!lڴaV{Uʊ*U0g9<ءlܺu ooom,_C1:!DviߙGEEQhQvѣɓ'ڵ%JЬY38R3gΰ}v.\cxq۷Szu֭˸q6lNޗis׮]L6 {{{ʕ+g}۶m8weʔѫI'B!BY&5kdԩDFF8q" 4ח=zPdIc*0;ҥK>CN}ҥKٹs'7o‚ӥK ϖ;t3f`׮]XZZҤI>c/vMXXgϞ%99ŋӢE JZZ:uH"lܸSSSmW鉃7oδ,,,`8p@;"+/&6Xt){Ν;/^VZ1p@lmmu޾}sA(_4is&Md쐄Bk;x  jժ`ee#^^^lݺ2&&&96+++С<}4Gk)9Ν9r$#Gd0*!ͷzj_#+W,]46n 8|0 00u?x aooύ7XfMmȡC ""^zaccÊ+tj\4m4s(Z({ҳj*.]AAA>|e˖aooŋu&..{{{mޥK`q!VwL#Ȼiذ!ԩS8p͛<7 btY'OԖ#ǏI?u^ޗipGj+V գIB!Bˋ7_h"dɒcҌ"3%J0zhc"+?3gd2B!G\nݢC4mڔ~gϒDJJ qqqlذN:ѱcGQ^9!ěLMM1cжm[gxիWg 8u%K.ˋ"E`iiI6m+eѣG)))/vvvQ`AZh+tVpssFVDDiƠB!Bf(W'N$66=zL͚5yw6m/_6vB`.]*66WWWRSS9|A !W>ʕ+ 8ҥKceez711t{^tt4ݻwwҒÇuEDD}vy6nH…3F̘1^ٳgKKK… /%JҒu %뙝믱n:jԨ%/>JNNfΜ94k֌bŊannNر#K!#ěӧ,YOOO5jDfӧ6m˛Ȃ pwwQFtܙEi_t<;$!!kR^= 6...]\\gWSݻ7[HLMM3"55_6gki:y(V;IB}$::޽{+PӦM#""HV\I6me͛HoG d׮]DFF2}tlllf۶mټy3Gaǎ dȑs̙3P^<~wyB!B:U_}'4k֌9sP|y7n̂ 믿"ʖ-رcu>"/ٷoM6L2Ǐ>N:zTLlˍ맡Y&/_|۷/Ǐ'11ڵKMjj*'NK.{E2%뙝믱d%558U;wػ㯤Re# ,e7LXul!|g 1a-2ӐbdFY3i0wΧS*t,q?}}]WZZZbرDEEqm=zĭ[رc;v.uxbVZ˗y!$$$0m45bݺu7nh\ogݻwSmNNNz !".]0c ĉL>~өS666?}tرc̘1x2*ĐӧפjX"={d׮]ҠA| P$11oooV )'u'3fpq9~83ggP>sL1KHHI=KrmS^!T J*Z=C !B!(.nݚ%KpuoNڵZjt҅uDjyw?~C K.tԉ={L!UWl.n߾+iii3$222aСdeeT*q~**ע~`ժU/\y^^^\p,ߏ5ǎc֬Y|'j [X;ٓD.={׏dezzzٷok&++iӦi3f iii|g$%%Ezz:;\x)Sr*+(㜣甔DBBweΜ9Enߝ;wP*}N8Aff&tؑ#F<3V]|6Ncƌcǎ=zLN񺊈LqFN<=!!!:tp>>Ldd$@8pA#ByxxPn]6l-[dРAԫW4x}m۶8::@&MrPe˖|g$''ckk[u;)L4 '''<<<8{fӧ8Jhw`xz,Zj9t̚5KgƤ6h vlOOO_f͚\rEs̆ •+WrC׬$B)LMM  227np "## s!B!o.###>c֯_OJJ *UÇSJ\]]UQJbo>}# 3g",,Le !xc[+V/sښRJѲeKV IDAT\ѣ{.K,ɷX&MqP*m˗/'33777-[F͚5122M6aM~蘺p-Eq=:t@DDvvvcggGDD:tc:o۶-j 333ڵkʕ+8xVޣG0{l122Ԕ֭[_Xl9SFFL4c3?XXXPZ"oʕܼy;-4nܘ]vaoo̸uRSY95nܘݻwӤI_>?#~!ofŊ/ׯUVbbbB-X~=Ǐ/(r>83V^/u+qqqNdx2³ ԪUgtS(֬YS+Bii|R|yܹD~\\\4icccj׮uvl;w.[dɒTT|rO7n}.3gdذavN@kƸm> cPF }fgƤfnnΚ5kׯ*UАJ*P(Xv-|уrQdIlll:u&f5ggg̈UgTTeʔ̘!oM2rH dԨQ:; !B!xƖ-[q/o߾TROOOãG"=zk׮|dgg;!Ǐf̙3SD=*Bt%۷::ygϞ\3;ݽ{BAvv6̜9Sk/ȑ#sT-##2e19?~|/ %J`„ ܹSgF+yjW^$vʨQh۶-իW.W7[>_~Iunk׮]o۶mL0!>%Kח=zXr| {> ?'???J~0n8~Woߎ?/^̳kG]Gו7SL!66X-['JR˗|8w\ܾ}xiS>S_Nxx88;;SreP(hѢ@m!iР . V+xxx?J~B[7“'O`iiA<6l/^ښP hmԨQbRVUwx:=msG1}V/111xxx`eeC !""[N/=TRX[[T*ٻw/yUw,ȩ(KLLYf:qtt|fܺb)),ltéStn?<۶mcĉ|GXZZ۹C(ԣW?=u^/G}Ν;4i5,]]?jw^7uWP!푞έ[40@=m?@jj*?… C7nРATRE3}@\S;k-[Vg~׹=2x`"""hҤ&ʕ+]>}`kk_Xl9=ST SNkӢOʕ+oyRSY9^uzzzVM]6kצGL6{>2ڬxXXXУGV^4h̝;WGi۶m:q|xw'39=M#B7_۶mqvvɓ9k׮|tؑ͛ӷo_(_|=LMM  227np "## (oh!B!B!VuaҤI9;W'Ndlݺgٳf4tԩyiu???N>ͣGu ,///M^L/_֤խ[@EMu:B!|*UĄVZ1\;nƏرc_>JDXZZBpp0ժU˵OӦM9r$2j(B!B!Biܸ1}/^?ɉ@}Zn͒%KHIIwB̘7oDEE;! $>>GGGyN!MQl.ԳI{{{=s"ǧ y_: X|9NbԩxzzңGc?~\6 :4hd4m舟f͚?~Zh36lTR3FW=CfVZ?iNB!/ V/ӎ;8p ,RJ/PD J%6l ::Çm6|}}mRdΜ9̙3BQ !WHH",,!!!B!xJ(A۶mYlfV5jCժUҥ ֭+@Bի]taȑdgg;!{nڷo=QQQTZU! !/]⪨K.3}t:wLɒU̎;4_}Ǐ|С'W|JHHP9;;U߾}_JlE9iQڗV PGuIUVVĉ޽{J.gRSY9c._JPN>Tǫ>CRjV#FU٪DՀ4K.BUpppoe˖TW^դ]zUZr#BOo'RR*y !DA~B&7!Bn߾Zjcǎ*CCCj;w>|x,,,T7nw(B2uTOc}#B+Jz!!!u1Oc\]]YҥK1bfG>3u1tP;::oQT)D\\\HJJʳCCC2eJm۶mo߾dfffbbBXXX3 uumOMMe˖:uJ>ժUԨQVWv>˳/J83ϵOPP暢Y|c޸q#X"vI&+W2l0uL80ӧO;ׅyo.Q*:V׏6m0~xfϞMtt4>BO 88XBo!o"|B!7nNhh(bŊBAV4!^tׯOYnlF5kXx1^^^I!(v%]2k,Krr2fff4oޜqѹsgwN:̜9өUgܸqޞ֯_ODD7o+++:tQhР:wN||<3g_bŊtׯ_vbaaALL fb֭\pRfMzɄ XK8}Z?oa޽ԭ[)SеkW<==133+t,=>=E9jؘ\2ݻwgĉXZZj011a޼y:u 7o7| ua,_\ÅRʍ{)ԔF̀d…B![#$$}!x M޿BB!v=ѣGsyBCC eҥXYYR>wB1̘7o :6m;$>nnn۷~ݻ;$!B/u !^u7p}Ƒ /~7ÅZHHfv' ^Bjx?==bC|>CBƬhѢ #R7yBB!B #44/R~}Q(ԩSG Fpvv&%%#GPd,?Cݹx"۶mB!jLUٳ:Z MwhB"WLjETyB!BF-FB!Biذ! 6dҥK̃{.?#sl/LwMzz:NNNqrr"==={v!B!^,}_EY CGs!..-Zp1>|ȉ'hݺ5 AAA+Wu֑y "55kR|yT{W֭ٳgIOO\駟49<:tL?,u']vIZZK.`ѢE>fFFF|'lذ133cĈT\6oLFFFud43! #,,.]йsg#-BBx3\DGGp] B!VZifuظq#'O___j׮5[dd$z 44x2 [100 !!ÇcÆ \vի3m4lllHHH`ҤI/M5j ʕ+zj57? P~\8@>}^J[B!B!x[`kkڵkfƍ :;2fΝK֭etաh"ԩ1c>}:ol߲e +Vymۖe˖'hUL޽ܹs9qzbĈ1)Ɲ;w 44BzBPЩS'>!^5cJŊxM|wL0ooog- IDATst$BO˗/9myfy/MJJ ƍ]v899xbpppwhZ;v,cǎGB!D?ϟ\+C`޽̘1 UرCw9r[[[vɂ 5k۷oaddD&M_hƏ&&&"̙3NOYV!B!B!ċ<4@X[[ƌ4hЀXlmmf}QukP֬ΝQkm*+00SSS×_~I 1cό0ʕ+'{իL6$>Vȑ#joɓ'cjjCG1zh|||;w.sΕB!D.!R!BBB4 Yyرc,^M6RpssƆ>@ߡ !ou˗/УG7 w1cpԩ\T*WаaC<7.RRvm ´Q=2y|괜 !B!RBݻwf``9zFs^#t"3[la8p???1c^^^jGaTR// .Jhh(˖-z긹T*_[!S2eO?e˖I222`ǎѷo_}$BB7Xlח8L8WWW,--Z*...BWA 3W̞=SNQzu<<<sEtm:w̾}سgtB!tBZppp! (Q"׃fRRRpwwפ) RRRXf#B!|l۶-WG8>ɫA7ݻw*KzZ3l$&&v0m|w#٩yB!EJIIk׮iӆUVqi222իt֍O>T} !++ ,BCCcذaܹsGa!^a{@TOvv6Ɍ7:vo1o!]}̙"ѣYt)Νәܹs,]ѣG\&;cVܬY3zg???رc־v\<]Gtzff&SLutؑI&qM} YfTTI^J #--9B!ҡCӧO#nݺł ppp9}LL YYY>}M.]0c M'N0}bhQnicݺutRri7|9;vGE[ڵk8pֺB^z u%99aÆѲeK DzEi8تU+@l4H!B 2Ӯ];N8_~-Sn]9x ʕ?`ѣGywYt)*T ..'N;4!@ٲe9x ԨQ%KRBzEll,7tVr -tY&-ի9 PV-J,Ifff( Lj#X"&&&OÇg4i҄RJQT)aݺuE}AQZ5V&)))v9r;bjjJѣֹ_RR^^^X[[cbbBrhڴ)SLь*姰OM BtҸk>F.]iӦ.]ݻk9y$ J*allL&MضmyzK_|9uȈ:uh?|W1g͚5yUB3o<.^Çu? 4 ARif+R8p *y!7n(T* J+F],]}ؾ};I!x,Jtk-ZĢE -[ABB5Ҥ?~4:t@dd#|=Yͅgxr1:445khFBFz~:0͚5CŢ~JBB ͛9N 6ϏQFk7Μ9@5rFG!E Ǝرc-ܜ3fܦtVti|||yftӕ^6.]RիvժUڵk >33+B!x5EEEѭ[7x !""]LSSSu駟#M5k{!**ҥKhB Ϭkv}v5PYn?[lSN:3"==[[[.^Ȕ)S^Xl9ڵdׯ֢E lllqwη${.sΝ;(JMN8Aff݈#٦Zd k֬Ν;?t JB`׮]˗qvv`…Ze<<={בB;#ҥK_ѹsg{=FMllϋW/毿X:t(| ˗/oB!KR,.∋LiXF Xv-666<נAؾ};w!;;s1i$Դ˖-c„ q=INN&,,L3հ.-<ˋuquʹAAAx{{\4k֌%Jh:XEGGc``Ea)h{/^̪U|2>$==MOa͝;4MG^ИvMzzfHOOgϞ=Enԟ 9?Kr^˫@ɒړE߃JGm45uB!Dq255% Hnܸ7$ RJ;}:C L2T^ U #{_Ǚ3gb8::RvmHLLw-gkk7~~~GӫW/زeKYڅBb  oO[7obkkKDDwi/p<Ȋ+'S楠UA0DFF‚zqnݺ͛7IJJZ̅Y=mEaiӦJjժŁ:ujc/hLAt]W==dΝ;-ϟuKsYǵ֏;￯I{w{niEEצMu߮Zjժk}=F!ěƆɓ'siӧ6lA4hЀ3fh}8M4 333wOر#_[nI!xÅu5ƍ 333㧟~ۿ?G֖;w`&3_TE wAvƌ`hhHZ`ǎ:kѢ*J3QTh)h{&<<WWWtv)() {Ac:s dլYS+uBBB I&rMe2228|M>D9v3fL_Pn]NSB!(NJ9s0g B!B'O\\RRRe 6/bmmMhh(ZՃ4jԨ@1YXX/ ufvϙ:ֹJ. kyu'<<<ʊ!CkV-P233i߾=VVVZjԨAv$,,,ϺMrRm֬}٦zz3N[ZZjm322Y #Ҹqc;.^iӦ ͣv8::pBx)SyvZbbbxIoy&@!BX%988hϞ=ٳgkֿlׯ_͛73f NʵMR_A/pezs{^b7oΚ5k8x ݻwtna)h{2e Ʋl2<==Q**UJg=P ۷077U:MGzJKK# 333NJɒ% @P0yd6mڄ9۷'""3|,B n{ySre~>#]$B7 4Å ̙3t+Wۛ &o+TqŚ+c_d!^zs1RRR8~8mm۶ڵS^=Xx1NNNlڴ);[6vmcR>'2BN_"EGGg̘G1b+VbŊ1XUCJɒ%122ޞqe9shڴ)E|ٓKw9::bjjJddd###)Vmڴ !B!B!r8 E?iiitFOOkbeem9evWR.8g_ze*SNZx}b{]]vɓܾ} z%jU!Cr.^9;'NиZVǦ<:4}u u^B!DnҾ}{V^ͣG xQBvILLu`.]ŋuGvUVԯ_d !Ȅh[.,\kkk Z@Z;v BNԶjOӯ6M߼ݾ}yQ8qB~FFFX[[Oxx8|gY~rs<%Jٙ˗zj|||xsQy9&&eJbM7e ! M2җM:h:tVCDGG3uTLLL9r$ѣ,Xre9dɒ̛7cǎsN i>///Μ9U̙3x{{k\9L!B!B!rzlJJJÃ&Meq 9enY IDAT`ɒ%lټy3Ϟ=S[ KgVߕ?~\^~R zb\r۷p7[^ߪU/TupI۳[(IYBBBm1Bebb#Gɉ5jp]@=ĮmL5kÇܾ};Ċ۷o!D^c1b&BBBB%!Dmذ///]!BQhk׎SN1uTڴiC"_Nٹs|={Ǝm-[̙3,_&Mm;<~)UV֭[ڴiCDDlܸ1EhݻٳgrGGGN<̙3i۶Z/_2{lZnIʁ9oԩSGm}[n_ZZk׮믿ζm???iSN xvÇ M6j` 4)]47'Ne˖jۂr;?W_|<B~+Y$zW^/qqqŋ$''sE\\\8p9N:І'fDDϟ?'55ϫ&kĖw^o#Gp [=J-Z*Ç2255e޼y]H]# --~1yd/^/-BY .=NlٲXEERRիWWmRSS$--5j͛7 dWѶCODD2n8ڷojyf[b bٲe߿X>0`*&5jԠL2|) 6?"SK&...82Ӊ"!!jժѣG166Ƌ/Xz5<~TB˖-8p ~i1\xӧo>/ʕ+G6m9rȔfuS~n͛7IIIܜΝ;wQ\76/..333>ݻU6億*UDRR111*U*spu{"""믿Y&&M SSS/γg2w)&MDdd$ϟ?~7:dovu[n^9[nW_ɋ/PwU.B??Nhh(aaaP~}pwwrʺOE]Ƨ~:tZx1;v/4jH! !p!DaÎ;fĈfffx{{8:!B!=!!!: !;fÆ 2[!dZԇC9166o߾7O}ZYYf4=%KdڴiL6M'isJ*Ebbf ^:VT`ffq?kkL?r7x-7n9vҺ!B;;;0m4;4i'nnn|ᇺUr5j`ĈL8www*VD6nܸAIIIѣXZZ:$!B?}] Daabbĉٶm111İm6&NՊ@B!B0 777tB!SSSv˖-Ʀ B! jՊe˖͛TÇbŊ899fu(FEٲeu("'OI&+VL&[!d"={6ZQ !B4h uB!B!Ȇݝٳgcgg17odٲe̚5 ~8R!fll3l۶uѧO^^^899ɢB ٙ>}вeK]$2سg۳qF/됄BL"///t=zУG]!B!B!Bthݺ5Ou֙1c ZhQ !bŊƶ-ZE,Z={~zFŐ!Chݺ5PTOYͣN:?^N>*T`:$!BRO8|pμB} CBkW\f͚jeSjUzA "<(㍎Vi:.vZ;Ç144?yxxxPD YM oRXXǎQFt޽@B!B! }/!B ر#;v$11۷n:}쌩J*7 &УG,,,t;+""nݺaggGxx8ŋuHB!ȃ7BT !2 YrA' xW2a+Fpyq]z}sUYrr2W\ʕ+l߾˗S|lѵӧOh"֯_BKKK>s]&B!B!DKa!;COOO!!3^^^:LLLL޽;ݻwӧl޼u퍉 xzzҶm[tx Ce͚5|7ܹSἓ֬YC>}޽;˗/׌B{c.Bݞq'O7o;wd͚5vEVϱcTVT.]D@@/_fѢEL<9v4)I7WWWUNƎˆ 011)8B!B!x>̂ t5:A.]d2@- U,Y___|}}eÆ [gggJ. ^^^4k ]+rАŋӼys6mDnt;eƌ=f̘!;BLBV n~^)SÇsN.]prٳL:RJPHׯϴipqqú 1G+V 66U'X???F'B!B!Ds6lMס!riÆ AdMWb˖-!ʗ/8p wal2޽;:T 0d)VCz륥1d,YotB!AOɉRJ믿r=tBdW\f͚ŋٓrʱcK:wLLL X[[~aƱchԨݻwqDB,XÇ={dрYBB˗/'""?ӧOU G`ߵyOLMM4֦_x޽{ :wL.]r+x;2e#?~pTJjG{`` ÇҒKfKxݺu̙3gbll_|!C2Qh{mYn 4|+T-֭/x΋B!B!o#Y!_OHH[BI*Uߟ+Wʺu?>| xzzRn]]*0sLjժŤI5ky%%%ѣGv%kBzryԩ}醚k毿qǏCjմlQX>}EYp!gΜuXBBӇ;w3RRR|j@~z 0UVRRR!((!C<ŠP(￙={6߹h"-[Ɲ;wHII!!!s1e6@~Xp!O&%%%Om͙3xߟ'NӧOٴisQm͵ݳg gfooOBB{!B!B!B!tÇAhPfM&N˗9uݺuc͚5|ԭ[Sr ])Q\9MƼy8wyk=y6mڰ~+-BwLpq`yW,T7o%}Zbb"ƍ333*V cǎ%11Q !t,88{QbE"00P`krE֭KHHǏ',,?'Nm6@=;Dttt"? 4ё{b``@߾}/@xx8 .$**C1rH֯_Z*ڵ+ӦMDZ}Ҽys+HNN֪jժq&Om|87o|qK.1|plll(Y1vXnݺF5~ׯϬY}64oޜcaaShзo_lllCP:۷qppΝ;>|]$B|V .H]z5ڲn:ՠR[[ۂ|#Gx:O<СC-Z:pgŊ*$66+V02!ěoGʕnjg}!֌;6SL6 KKK V'N`Νy?f~MMMW puu%::Zmbƛжm[lš5k믱̜9////(z#FJ*2>={L=7ʕ+IB!B!]-_|'''GVx^av}1l0 FXXXF%x䄃˖-$&&̽{شi;vCj߽KKK#..3gk׮uX"))Rn]8uϞ=S'N0uTjԨ?)))~6śGӦMaԮ]'RreZjE`` OS$$$w׎]Q(.]9}PS؜nFN%7n)))L>]!mۖ]v1~xիGRR/ɉM6evmrpp֖LیرcZMv CCC٥*3QI:a!B!B>j…O  IDATDƍ+fffTXƎi8!ի7nܠy\po+++LLL022f͚;GRT)<ҥKu[АӺukmƈ#P(ߟ/^:7fС033`&oDGGsĉC:tr^ŋ|amm۳ҥKRX1"""2eƆ;v`hhȂ q}X+++ )WqDuOA>/^ooo~bbb7oGѻwoCZZC}(Q-[FTT)f͚ŗ_~ɠAzAJ!Bt2"tƌg}!֌;6SL6 KKK V'N`Ν1biecҦڇCceeŮ]?>?_BBi-^7.m&vSSS0\]]VqD!Omڴ^<<;wӧg۲eKߘ˗/󱵵ejw*TT<۹sglmmٸq# ԨQKKK@=#DҥWܸqClE f͚INNСCG^O^֬YorHz2e!B!B!ě#&L_|AFZ||<tЁFѱcG̙;+DׯGӦMiݺ5ӧOWK.] 7YfK;NԩSjJu6}M1渳;>>uѠA*T0BI|gܽ{d>|HHH666rbbbxժU4jԈ7cRRRq?͚5S[|kڵ 02eؗ/j;vښիWRRRxV~Yyq5kIJJ"..۷i ?'<}SN1qDׯϣG-S@ӤI Fdd$O}Ν;WX/_2`>bݻ7iii,_\cYfѻwo.]Djj*?&,, [[\Ȭlٲ׏s&L h׮+V믿( ]^up /_2x`Fܹs5k _B!xȄ C?3g֖ݻw߫TT83:SAj+tмҷ%J>NʁJ?gϞٓ)S~zm_|%K~SMyXb8::K\MC ؘcǎ1w\ "))I'Ofg,SBz聹9wחFѫW/޽/={ooopttd͚5-ZC*'4ЩS011a„ an޼~}||1c͚5qƌ3P[آE ͛ݻwv쎫e˖ ׯ{{{Zhaø>UVeРAy>?ykۤIL+ߤ/sppx#q !B!Bkl!!!Yr%jߔ'OÎ;#55ׯ3~x j!#RSSU`CBBBω'HJJӧlڴI-+EXlw!%%Ν;ǔ)S*9s6!?[={}m$$$w\#O<ՕxʵkHLL$**>}111j)L?ӦMSm_l7oҿ0`7o$99CQzuN>ZDtAc066iӦj H>|ܹ3ϟŋ?Ν;swÇ5ٻwoڷoÇy9‚dLVwСӷo_]Frr2 ߿+++nݺŤI-zriӦ:u*z3fԩSԩSÇ@RRǎq( NUy9Gqqqxyyp/^PM4ꫯ4̼-www,'6=Fq1pμxooo/גRT~[RJ :Ǐs5 āpppܜ#Fp]t-u(FRRO[:$!Bp[A4#4I6_<̘l̙\tʕ+̈́  ˶ݼoddDNHNNf׮]ڵd:t@ѢE%%''Vm۶e׮]?zꑔŋqrrbӦMzk,B"Ą@)UEҒɓ'Ŋ#((///000Dhт+We@>|8*U@{&tޝ4ԯ ǏVZFݐ:t(,Y###7n\1fu\fѢEhтrʡ|WYF5"'rsm155%222S;+VL1C!B!Bwruj|ZǏceeExx8k׮ JWƍTT X|9+V몉"UZp9B޽ؿj{xx8 .$**C1rH֯_vY}jժq=<>rkԮLYGQ~'bcc=z4s̡z-ZF?3x`>}ʏ?m;ǎcڶtR^x;K,CCC `͚5,5ghk…￴lْpԩu!<<-[?d9жYfӤILMMi޼9?3GU{IXիchh -ZPUغukŖ^~]T\d[O9o4ic={V>r~g?~LV ###ׯݻp5M^z\zUZjoagg1VVVl޼-[S.]+o;իWg̘1??ooo6nHU&M9&^%L0mKLLTM~_?8::o>كCB!DAS`Ef2>V:yFP(G*lll}T{ ʏ?Qب\\\666k}*Ϗ6666'OOU,MJoV*<== B驰QF*pk.\X`Faoo*СFL<~XaccرcO nY>OP뫕רQC(7nXvΝ;o4z44000s @ivrbϞ=ٶmƾ|KII(?d4ɸ0?^^^Y>Y{"**J1h Pԯ__1k,ϿNbbZj wwwBnʕ*l;;w(ԩ\!B ,EnVQ>=}tΟ?Ojj*Νcl1cpe￙?> 0 ױgQQQ$''seƎ*_f;wVUTA\z{rUVZH-[HLLƍ̘1#S޹sglmmٸq# ԨQKKK@= rwJ)ү /x4kL~3^|͛7U ׯE^PB*Aj 333 4v!B!B! -l۶ xҲ-wWy+|ݍr\ J{~V P^D ^|*2d;vsNPPIIIZonnu=nMߗF M*UR z"<<>}:UVŋ_:Է^ѢEYp!ׯgҧO>3@8quu%---ӶsѸqc8zhe B!DS('\sss޽/5W^ܽ{7S]___9{,Ț5k(Z(Cuf-?~]50t >J*a``9[hAٲeL2ly+CJɒ%122ޞqƽֹsqqaԪU ###Wr9#DFFf/22bŊ!O#F`ذaԮ]E...kuSNy6661{lfϞnr !B!B.&00x[tt4 .^-ty># +V3gʕ}V%pvvf^={Ɯ9sԞrCAM֤lٲ*˔uK}\\ "Mb_tڵkʶm+#ܳgV^Jٲe2+g5Y@ڵ+'Oѻwo@?!C^i@BBBƍԪUqƱ|rnݪH6r(eU[ʱaaaqÆ nZo:u"$$X֬Y1B au[ 8zadd޽{ٵkVVV/^sss m~=?̘1x5~}mۖݻw{B! E ;w=__LƏVd^D ưaòm3Ț_ŋ3m4үݶm[ڶm300񦊶qe<.Fȑ#_8;;m>////_Uk߿ϙ3g߿*^^^E䳼^[y>!B!BQn2ο)M4aݺu̞=iӦQT),X@XX+WfźM/^d@޲wܙ3rHQw2gP(ܹs*Udfҥy [l[nĨb5]fM>|۷3M}U^SNqQڷo~IIIxxxɓN‚3gpy4ic̝;%K0tPl޼gϞeʱɓ8qvezJ*Ջ^zvI5i!cVZZjcN;uT.]Jն)LO2sTn]>ɓ'5QjK>}={6K.V)Μ9CPP[c'OҪULǎ^z9<<<#<>>TRӻwo5jD޽yUTrfv|||WĚ5kFƍ3f ZҥK4@E̛7wq[m[S֚V Ve)kO:LI|={Ǝm-[`噶?===Ue 6M6<|wwwl޽{̞=}}}*wtt`̙|Rm/_2{l annƁ3^?m; .Pzu:vm]e/2ӶYY}?/k׮P(Q(}2^:_5IIIk.LY'Nɉd+U2?Э[7mʁWTRݛ߿ԩSq:ǔp[J)))hт˗/uGnݺkp駟rܹ-_-Y[nwk ?ҥK;wLޝ՘%Jhe3cVHS$#mo܊onbflCT YZ ْHeHKFwU)9w9Hxx>>:ty !*%]өS'Zl qqqUb###||| %99dBCC|O!B!B!B^NPN+΄*UHn05s! IDAT5\r4lؐ Mh555%00~aaa> 8kbffV豝1c 4pwwW-/&BרQ}}}= ۷/+V;;;O׭mݻcllLTTy011k׮B77zh*VHtt491cǎ}{8p@\\\dggV AQ:_~INN&,,ݻ3|ʕ+?e˖XeUɓ's-rrr8<_}Zý{^ܣaÆQF ۇ .\ٳg$$$o…t҅$:t(޽{dggs]ۇ;$''ӡCIJߟ/JX#.^54x=ƍ?T/].]JB!@񆂂OQ)-Z( Ŝ9snzӐE)8qbĉ7:QHoB>"(((m!BB!BP߇_~Eakky͛ [[[իu(jd(UwV)?+VP߼y<__6mq;wNamm3fhP ;vz{j۟hذa1֨QCq[azՏXyOz,nZz{tQE zhS|΍7Nɓ|Kpp\ի+Ξ=q\?BP*\]]3f֫WO奈_AS*ʔ)ׯw%Eݺu֊+W;}P?^Gѽ+{=EjjƾǏ+ZjW:N!%Q):RL\]]UB(BAsN]!B8!!!A!B!`Ȑ!޽ <== 777G'ĻgϞ9s AJJ ƴlْ)ShTrJښyqq222[. bʔ)jӤIΝ;ǯ?{.ԪU;2f>#cݛSN1o<8;wV]veԩ4lذסǏgڵk׮3ԩC>}V[_~ʖ-KJ[n9{@6 CCC~G.\!-[d kkk+V\+:ޞ3g0k,"""sg̙g``?Ș1cg\|ǏcjjJڵ+jŅ_sjժ3TZU`` F"**ORz"?uߢiԨ3gd̙űyf֭[ǜ9s0` P=wލ ͣK. }vOxnݺE`` k֬ʕ+ԩS[ҼysE+BDVBPN B!B!B!e͛7g0fIBQ$X[[k_f L*+S ۷}߿͛7w^,,,hѢoj eɒ%|w߿ 6PF ^A111!,,aÆCq:B9pDDD- dժUܹSSS̈#B!J?IBSULBw}/!B!EK*Q\¾B"תU+>LUVr5֬Y?u%Orѣ=z]vу2eʨcܸqoߞ'O>}tu*WԬY7oG~z]V`999L8޽{ӥKn߾ڵkYz5YtB!Jpѯ_uj!D),- $!B7sN]!B!B![h;wtYcϧC9~8&LȳOӦMcܸq|嗪e˗/H===f͚E5;v,+WΝ;dff@5j `ΝY4nX! !+ZjRԧBkȋB!B!B!B!5|:APt|!ĺux)=z 33Iff&>X;;;ׯ_1EvӇGҶm[.\P.ϟ㈄BQyƍ4hPQV"8ۅ90.]D }˂ulB!B!tB!+++,--VFFFTT cccX"*T333LLL022SSSʖ-)z:gooϥK8pCWVVM4ѣGTPA!zk悃֩ƍٹsę4iӧYl[lAPпlllhڴiE*B!B!( ڶm+ !BQV^JuF puuuB!(Z…:z$\RM "22ϑ۷/899MHHFFFo<B!B!B!B!TB!ĻWL!?-P< Q`` ofi&=zB!B!BG2h ]!x B!!B!B(۷oӳgO*Uy&XXXI.]~$$$W_QZ5vM2e<Ӈdh֬+)#88ZnM~t]s Y&۷oߧO}vj֬Ɂ ŋͲeزe cccCӦMuRV-lmm9{,jٳgIJJUVԬY_~SRRؼy3iii|3==Tm?&cfee1rHTmϲeT ~{%##;;;˾}pvv.5 !B!%L@-œBMAUCB!BPIPnCɫMddڶ3gfΝ&\ر''۔۷/&$$###G(x8;;￳{n eդ}i&NJ޽ܹs1~zY&gƆs1c 3..Nk 6@&M6mVVV$&&2w\bcc h6l-::Z.B!B*...: !B!B!B+ DSm/]Kd mwΏ?Htt4wޥjժ}߿ϑ#G(_uGGGU .]vSZ!B!B!(.]D &&&֭[K5!Dk0B!P. 啾ۛ7ofŜ={CCCtU?#99raeeE>}TR222'"";wPjUz7|F,~~~L<ܱՋ`:tu?!;;={bjj  ŋ(v!(HRҗ_~ɺuCNL2j c .… ԬYceeEƍ b2Q儉e5ɘJ]!C]dbB!BQ& dnO=33ӧӷo_,--prrۛmB!B!B:E||<M4Ѻ*kLJ{8t*b,][[[={Fxx8g˖- 6@&M6mVVV$&&2w\bcc ըQn]000:ʊO>?'O:u7nаaC5jM:u*{FOOs1b qg+uEGGаaCmђp!(V>[&::x9BՒ䔥077իZ&^VfM^ʩSԒϔr{1---ILL$,,L%a^TBJJ TREm2Qv!B!qqqEa!DB6ܾ}ȦM d:N!B!BQi.)'6nXxzzRV- U iiiR&9ټy3-ZP[zڲyf !o֖.]pMlmmٳ#{}}ĉ8q"B!BQK?8]p! .TmϚ5Yfceeϟ?W?3gCLL R|yU?V_mdWҥ -affFZZĄݻ޽{ &p(\gA0558MG!SvԬY-[С̘13fhEyqss\tÇڻwﮑP1͹>NNNXZZ;ٳW|y&Lڶ'22x5kWخ]W^B!B!(W0?o͛/2m4YYY9U[rr2dzl2ʔ{{];;;bccٷoTfBlҤbz&M"22RӧOl2lقBдiSD*xَ;‚U~,,,VjJ*6]]رZjѼys]"B!JbI(*ʕS[xnݺuu>|]vb 6l1cT*A[uTPݻ76l`Ϟ=ߟ={ŗ_~pB.\@͚5i߾=VVV4nܘ~h,BWɽ??N9m!xS*y_LIhʔ)dggENNָq5زeK. cҥ8pǏӾ}{ػwk9yd/_NJJĄ֬YáC}6*TYf9z޽;?QQQ|Wj1DEEabbB׮]_ymB!Did=0BCV-9=ʺu8z(`aaAV:t(zuBYMQ,6ۅ СC_<~SSSlllڵ+|MT*իWɃܥ9!E57o3{l6lȹsj}7l@BBM4aڴiXYYܹs%44GGGT 8:: jġl !+B]DFFjmdKKK&$$## SEf͘?>wݻܽ{$N:~1˗W%b{jIͩT*UҺ?ժUػw/g 8]%B!JbIԩS >&MvZ?η~Kf+ppp8uXxTKKK S}HP b׮]ߟ]vh|@@@\zU?;;e5"=== ?VekQ,ȽR )))RJSSSU}BVu"7SSSΝqJ/'vhKPSNeԩ-ݺu[n}TSB\]]'))5ję3g1bC!(N8AHH...E!Щ] ۷oΞ={4ݼy7om6zɦMTUE$66X,X;wڢNo*Ϡt$"tyj7q!㏁׿7""sPn]|||ptt$<<GG<ǺtkاLRB6aҥ,]@n߾̀TmdӦM2zhF'{FoǏs]nݺJ¸{.wܻwׯ߿qeRR%$ mN%U*UW9V[[[HU߿ !BwW}(٧O:u*={ښPѱcG֮]X[ IDAT[C6l뱵eʕLzqjRWV-Zh*S|e5kFݺut҅W߫Ҩ\Fsss߿Ν;qvv&99k+uկ_5+U}B!C{n^$giiB!+AAAC!Щ72h ]λuvvv\z'ңG>Cv!!!,\pؿKO<|P߹ۮ\jSkdhbbJ011QmMMMT&&&TXQOqhٲ%?-"22 f͚Ŕ)SpuuY>e˖i}Tڻw/Z٩tvv.«Be˖zT^W&c䕤#IMM͛SL!;;(rrr͍k׮ǖ-[~1aʔ)CDD2}t\gA]駟⫯R/** v'5oޜѣG 1c'B ,YѣGuBQluN%&&2g~7nݺEʕԩ^^^4jHA&߾{\\ ,äRfM\\\D/**={PZ5oߞ&M0|Fի5..^ȼyؿ?wܡZjt///.Bw})_<ڵۛ-[jh"VVV8880n8PS… abbBDD~an޼9we˖,YcǪU~ /{> @~O*UDN>}FF,BB͚5r kҒD°,XUT!%%T쩩>B&cql߾Kbkk˳gglٲEpahҤ ӦMʊDΝKll,8::5!/:: jĠl !J*(!?O>ѣGFzz*1jIiiir]_<&333q ʤJ*q%ڶmGGGIOOgΝlڴ WWWZnݻw/'* ܹÿo9sfJ>|8[nbŊL>ggg>ݻGDD3f 88CCCصkF-B[Exx*;y!ϲù1qD&No֭ݺu8}}}ݛMMM;w}Ç3###NԩS_kA v*T+$%%QF 8s #F(BQڹ>B!e'N $$]"BU!!!A碢/HKKSqFoζmٳgiddn:krrrTmW^e۷(*T0rH*WʱiܸF"ݻqqqQ(uֱuVvI.]ĉtЁ'Oػw/M6;;w&==]ՖũS8uk׮%&&{Hb{Ya@?ȑ#_lԴiS<<B& 7ֺ#z*:to߾W_DDsnݺHxx8ys%j׮N:j}bhhX$ɲ999܉j ek׮[FOO ,X@@@Iѣlذsss;F T{=֭1ׯgȑZ3B!(jŖp!9 ݻ R}Y%nnn:N!B!^puu%((Ha!oƍU+ھ߿O߾}IOOg„ =>3gO@@\pAmtmΛ7iӦfUk1b99995jOf|*[z*5j€̤O>̙3kkkOصk#!!իkÃ=z0i$>S~wk\ٳٽ{ HOOgذaxzzRvm9qcƌ!!!3gbŊ"-y> dAmϪUؿ%\hbiӦѺuk~'6mʕ+WMhh(nnnTVXb8 4~ׯo_www>ٳg5c*_<&LPms}$,, {{{"##רݮ]0!;GYBi…,\P=k,f͚佐cQ?~<3g$&&~<<zٳgLRR 4ӧ*ooooIMMAL2(eIŊ5mݺ+Vp)222ё9s横|>l100I&||7uxzz%[faaIdժ }`Ѫ*zb…rOkÇ}vRRRٙSocϞ=ĉ9vFFFZ0L!%˻+>>>Lrr2 B!B!BiժUܾ}iӦxbիGiݺ5Wfܸq||Ì32eZȕ+WS/B:u(WڵcӦM_^_zÆ _.]ʣGر#۷oqиqcoNǎy˖-zg}۱ؘ۳zj;ɓ գ\rѡCصkWŖ<~'5*O>˗/7ѠA^;1,66SfM:wٳg>}:7nСC 6ʕ+vl-"..VZqi={i۶-' @WP>cP.pB˪ʕ@UGOO ֮]СCQO?b 222x ^QRx)ߗv{:u{?yƾݻwg>}Jtt4u,ZHuX @ݺu9vO>ѣԩSs1|cׯ˗ ;v !)DꪶқBʕ+0B'$$D!!JW^-ĻHO򢬊ù~:cӦM믿UHx333>|Hzzz^W$2e2|Y"Lao^k{-xb"Dq`ԩt Y`* 2ݻw'AAAXZZVc != mšO>$%%1uTz쉵*I6k;vdڵxyy鉵5>dÆ _[[[U-=== 7nܠVZI)))$&&j$V(<$9::k׮WV)ݻ_oƈ#8p 666E:M׮]Kzذajс-Z'ϟ?GJKbmm ̯_POfǎ_ՖBɓqY<'噘ŋ9<5QF?}Gmh{X?;;;֭۷og7DUVѦMYjݻwg- &0g߿_{&BG.BΝ;ٹsB!(=ʺu8z(`aaAV:tT?r%(ϥ W3ߒqqqY#GpuT 4G 6 :wIPüb)L}E֭[ǡC?IKK:uжm[ ][S$/Wk(l5k)v\ϣGOԯWqqq\xVZlʖ* y%c˗/_qݩX"gԩS߬]kbeež}[nĖ<~666:uՄ8{,jCqxy%e sK]}+獋gϞlݺkjnnËtL###|||7n 44%KP!) C aܹZ_W5k;ٳ g˗g„ msss߿aooOdd$j]wvvumĈ̙3͛1 (~ٹsԶ={ƨQ`ĉJJIfaZZL0p}դdzɓ'=/۷}1}t?~Z\{5HLL$111߿߯^ |[njm۶ʕ+yO=WkW.]T)eE _ !).B!r9L۷oӳgOڵkǚ5kx"deeqMm_|A^ <9Q3 >\*6SLe˖Z .INN#::oooٶm[-M?ÃF1|N8&##ť@)6<|0S999^pqơdž hԨQctr{˗Rڤ8eB#sS>ϔ/'OH@@<\Jlu ׹sg~IxY^=TR"Dqdĉ4lؐSL,--qrr"((5j͛7g˘1c4& !x9jɉ3fРA 000 wwwfΜgbbB@@XZZ:t`ڵj)&OL5'++ ݻcllLTTF QQQދ !?ɗ_~V-@r}}v튿?h"Uoeff3PrIիǤI Tm$%%=xyy**A>`֭[["`-rrEW'wPmQAB!JIB!B!t֭[iӆ={ӧ\xYfajjJxx8dgg:lQ^___ʗ/gϞѣGdggs]ϗ_~IZZ$..N!.##N:!#Gd߾}ܺu,8::Ү];"##Yr%cǎQĢؼyd*Uйsg:wȑ#YjgfΝU&M"66:uEdJh׮ڵÃm޽{޽?SN1gvapp0G'Oٳgqrr;1:vș3g^m_||<}klْ]4 IDATAٺukn޼/eʔaɪݻsI.\HnV|9@ N:$&&Oƍi/^Wcǎ?gΝ9Fll,dee1fU%sssݻGll,;vTyP(<\h":u֖ pvv.XB! bȐ!޽ <== R"{ ;vT[%11s޽{)S +V **oSV-nܸѣQV󻋂[ǎw"}ʕhooիWUlܸQkUS?!&&bcc" b%TH%/XmlV, ڒ>JyPb& jo)!PIjO-!,~3OLb&5/{{f{9ݺ1k,Xx1u!>>y1w\9x M6ÇPJuЁ#Ga,--7nK.ΎK.eϳgϸ|2| Z+ϟ/_[[[\/}nݺ3=[w͛ӿ֬YC-K=PnbL6DprrҪСCYn 4 ,,ÇhtVպNҵkWf͚Yn:uJg}1Ec&BHɡ+Q-K^Wf>?Ļ!۟%/yK^oKhsssS2]~իW!C(+WV̔ *(nnnJtt9/NRzXZZ*JժU+?HwPʕ+￯@Sֶ .(W*V*+VT<<<,(rIY)RRT)SNʉ't 6LU Aʔ)S'',/qA111Q,--={*Iv}ڛ(O>4_EQk׮)baaw-Z(eʔQe*:tP::rLEׯRBDS.\IW^U4h+}Yc13uo}i\\RP!4v *2|\m(ee i_~?d07_>eGP?VN8$''+T)&&&ʙ3gرC]ɓW.\XoV}8p@Y(5믿KKKP>eɒ%˗4%))IT̙{ LDSSSex%--Mww^C]ٺukߗ씐%99YSF)R$c:7oVҔJϞ= .()))ʟkN.<U||:+UךnݺTPAkj̔u}f~Ϟ=^WΝ ӧOWW,c֭͛7J|mUT_Uܿ_엽^c&B';\!C!BCnP9rD)Y EQ~7}^uChѢWZL[~};ʤIӧO~WhѢ:,Vͯ_-ǎɓtlll۷oZl/ˍgoΜ9:(\k.l{VmNjժ X"|*+ d(:zLL̙3uئM߽zQ,5,/ڷ!SeСzCQ^gܖچrR`hګe___ 6z_+FFF:}GZ+DFF*ժU˲ ccc*;wTw޶m׵ѣGC1VTIDnfSIIIQF2#Fd9ԩS:?o/Ӹ[niQ-)KJWBܹs%U<~ .sߏoS Ey.G=Z ̷8x[uQʕ+@iժѣG+ҴiSPF]oCPퟱW||( RS |p<7*U2o<˯>0yȑ#*U(&&&J2e]j>4z_K)Ubff4lPټyVP +aaauΝ;>LTr):uRvء3nJǎSSSRJرc6lPV(*T?x?RR%Dy#Fh ̮1s̄BQ)ѣ9R ??B!.www֯_sY888p=F>gϞߟJ( ʲ̙3g2qDu9nnn_888?~<*U",,AǤI6m5k󄅅ѤIlTV'OХKf̘AjոtرҥKsy*TO55x5^:| ԩS|\|:oqrr"44!C0n8TBzz:'N/xzz+e+?~&&&8::pBի˗oٹs'\trʽ2}Ե… 5j| ݻwUV|*THg9퍏5kdŊ4hЀB qYFiڴ)Ǐי!޽{TVGѫW/N|7nǏɓ'Zq4ʕ+{ny1*Uv,:Oj߆ӏ>08@6m^Y>-}|>rY+F-[4__^~Yll,gfܾ}sss7nرcO5Җ.]2aHH3g$%%QjU;v, ֙GJJ k֬a֭cll5|Ԯ];Ο?̙39pݣ\r|L0ygfǎ_accC.]?~Y^f{Y\\ƒH%^:~) >2NJHHԯ_I&ѱcLz*B ~V]ϝ;_|ٳg?gܸqXZZXT~SfP7oxG!D~zv^277'999eʔU/ШQ#"##QOH"~Rjyq-R)))$%%QhQu^OI&ܒN˖-g31XCjln,5h߆SC/eʔ1>>-}e։)bTB<!y?d4!>2@YG!D~*.T2cllLzzz9c5k… JbbFu<x۷oߟP50ilS~ !-)2dS!B!B}`o޼(nҙOtt(5ʴ*666 mVIOOޠAP>W RٳgzץQF ٳG] hɓ'Zӵ+TVM>HYnile+zCqM6eY&Mqf%**J3fRV-Hkx[[[mR_QrL6m۷>1^xQk[Nby(ڷ!X>gnǐ6ӲtӾ^¬b|[3] k^m|BhwG!D~zv^^(W^+ѣWeȑu2 }֬YS5W;y2~xP-ʘěB!C !B!o`ee֫f͚\t)<իWcÆ ZPn]bRjc룢q:֫b{ֺbŊh̚0qD?N߾}ښuVRSSs5rbH3jժ5ŋő5k~ 22w^{ڵk9/_m۶>}༯\®]4i...XYYYf1p 6ԙWӦM$ʕ+kˍXEyKj߆S9zAe҆rZQvrYB{u~K^zs^B!D~֭nnnDDD۷;v,FFFiF,X'''BCCiٲ%-4l>}0l09BZZ'OdذaZimmm122bٲe<~u몯ۛ\B!xwwB!B!뒐t?3AAA(Q;vPti4/WYvvvsE4i>阘'%J 11QSʀ`DDDpuVZŪUe߾}TZ5Wb(/3?#KKKUhr(U.../ѣ矙4iw+M61qD\bp SUQ-[6}syƒSyվ ivvvDDDpy>#daǐ6ӲtYzYN? 3Q!  d]΍ؼy3nnnÄ ؾ};ǎ|ܜyC @%Xv-^uAdd$J\rܽ{իSJ^w3f [l̙3Ӈƍcxyy奱-AJěːQB! ;\ܽ{:PT)vJQLL իWe:GGG .#7odݺuqmLMMyiժ{V߬y+((0={爄B!x3+V>|Cp#FȈuQFLx1O<ѫ-Z޽{pKFԩ֭^wr((bcc2dî]|̙3,YM6( zޞzwhB!Bxۏ;Fӧݛ$MFΝ3Mkkkٳgy̻w,Xe˖1jԨLGWٶm riN|X1COfټyHLLI&ѣG駟uK,0jL4=z`eeEŊ޽;}B!!3f|<((###njùsΊ3Zۢ022Rиqc>Sn߾M^HJJ4sRP!ƌ^߶m[̙5y9s?2v}`ddDttֶf͚iز{)={ٳ5.]'Oji95/0uTΝ;e3gIׯV^WEtYxvUyY^ĘXrC^oC~СCy m۶Ut-Zs|EYm_^B9ut[PPGfB!B!B2Å~~~/^ŋN o23f̠TRP~}|||޽;Gz+WݻӇ 6rJ1:!B! >///.]Jhh(ڵLJ:upq6nȪU011GΝ;Yt)ua͚53K鉯/+WB 1%J_ Ay???5jĞ={U| ۷ښ4._̞={7oL>>ĉ ܜ?9>}a֬Yh"5kF…xHs3윿{nzԩSZ*/^d=z>@k4'''vСCYr%ܸqKlٲL)^8?f֭tڕϟcffYjǎq 2^zQN+9u?3۶mĄSꕷ5qqq3XZZrEfϞڵkZuӓEBǎ={6\rɓ'gbxY^ĘXrC^oC… !88zѷo_\]]iذ!e˖%99/?s5^5/n=:?B?| yQfB}C!ؼy3nnnB!"FJ ]=-ˠEfy9~~~۷[najj-]tk׮^ǘ1cg Pf͚133ɉKKK_Uʝ;w%44'O`ccCF;p7oŋ<}KKKZn٪WRR߿{aiiI/B!www֯_s9ݻwӣGLGSӧ_C0x`裏8x EXEp5s. IDATtRe<]puu%%%Ek[…ٸqQUOk{BBM6… :TTR%Ob3eWvq}PPÆ +T}]pZhӧOcС:svv&88Xc*̓ݻ7Y%KO=~RI&qF.]/1CBviXX۷ÇZYkW1f'}'m^oC)@jj*'NdѢE:gȨJ*|( 7]VvWV׼zׯWmkSJNNu e/$DnsгgA!4B!B}ݻ9{,֭dɒ٩Au>ǫ1yd={FNXleܾ}7i Wjj*ÇnݺE@@QQQ,YB <3f0tPu놓jT10$2p@ܹNuW,Z?aÆ#q۲e ϟ?|Rme޽$%%;dԬY3N<ɾ}4n !B!uЁg2{l۷177qƌ;O?T#˗ .cРATV3grqZ*;… kSV-"##Yf [n?$>>cccqvv/p4@N`̙8p{Q\9>S&LХdɒ?~ٳgc/ҰK.?rYlJ/8{,|7NkxWhh(SN%$$DׯϤIرcw\OOOBBBHIIB mKf޽ݻsI_ӧO)^8tЁaÆ{!C(\0 ,… .\ƍ3rH:vHj߿?˗/ϕߡM6?dܻwjժ1i$Q^ŘXrK^oC)seȑ^?huXz5ԨQӧciiɂ ضm7l ԩFFFDFF2l0BBBUuqyjժĉڵkpIvܩ1^n(V^իWcffFݺuqvvk׮ې׬YÝ;w\2ӧOޞӧO3eʔ,_V qʔ){C.=_o[ y].44T:\!B{{{NyyTx}hт-ZO…2dC V5j`ڵzE̶[XXハOf*?:up)ciР;v0<ٓem۶m۶zǡOϴsA~ׯSkkk //bn,Ty;#C۩ᅬHvv}^Nz5?5z #"|Nߙ =^Y3Ǐٸq#5B 8::qFWgB!BwY׮]ٱc\?BK5k\V177ɓ'_+WкukzA=.o߾l/:0f S|:t(G[G0vXt>rpåK7ʟTTiB!B!B! }g7kͶ2B;vΈ#;|̭[0aB~"B!" u }дiSٱc'[/R n`byTg5>^͙3 .PreZj-5k֤gϞ:SWMq-Zݻ5W???²1Z\EQT-_Ts2lCۊZo|B!B!BI2*qss0k hwܠL ɌBzİm6nʩS3[*WX(BѣG$''ÇINN&99~!III$''sRRRyӧč7ݝI&%vsscÆ Y~ WWW6oެ^zVN>edܹs=cǎQhQ\]];w.ŊS}6'NdΝ$&&ҽ{wVXUϟ3e6mիW133VZ| <8BZ:\СCUV|W4h???}J,IΝܹ3ϟ^2ΝӸ|>O{=_N\\\Qudt\rE===]s>ڵkڵ ++,@DD[lSkkoccCLL S8GFFj522BQ)^8{ Cחвi+e˖Yƙ KB%$$VZamm*UbŊ.SFF$%%|r={~Ç4o\9@ʟ0a?z955U6!!ѣGg !((r6U区t那# IIITV {{{@  1c HOO̙3жml סy̝;۷oS̙#ݺu㤦rE;3\xgϞh">|:m>}>~HMMɓ'9rcjihOӧIOO'**ӧkU۷̕+W5kV:Cחːm+իW׹%#:U!B!yGQWl(D~v*B5^Z:g&OLݺuy)tЁ-[.;3g$3 !D{1Yn...s%֭ p ڴiCuH)Bݻw;|UZ5>~N:=z˗/sM>˗/s9N8A׮]ԩE}qϛ7p4i™3gHKK#::'''(UW&!!3<<w\\'N %%Çs9T4~wRRRx1,^8BZf:\xxxìYoРҥKs}wv282e0`u5jԠW^:g6"u8p ܹs|g u޽ɓ'3ydr/^13>0`;w}j-RFR/;;;ӯ_?֮]˦MشiV UT믿V{V6lz}ݺu~ƾ[f֭,\ h=;KeH͛sa4O-Z0NB!B!B!yIߙIeFq!O>el߾;wO5ׯݺuaÆÇ,[,#.xXd tЁǏsdBQpyxx0gj׮ߡbŊɦM>|8lܸUfOrr2W?ka>ųVΎu1x`EGQF1| cĈ|'VŋVFbƌ3n߾+VиqcZlɲeرF^ŋѣG̟?hv튧'0!NpQݙΝ;͘1c!::ӧktؿ?~~~,Y{/.xT.ټy3Es$%%sdBQp?ԩSCw(W^9sŋӨQ#VXiڃqutUVHКLJڵkF51΍2@2es8>#Zlܹs)Z(ovB%^ wX?L&+...hl[XXs3;+S+e%JdF"#}UdI%}4mڔM)W_}W_}eE2a&L^9ҷ|Cڍ>ːARX1ƍTT 7npY  #B!B!ĻD5O͚55u S2dRSS!&&]vO17י3gXd 6mBQzꅽ=Єx;ӷ etܿݻceeŮ]dFq!Ŋ㧟~SNxzz3ǏG(O=}^~ȑ#L2///O?1h2o-ڵUV899ѢE *VZ؉Al:EU(d@w޴mۖ۷Ohh(̝;By^[ !Dyxxo~zƍ뱲Һ B!Ļ.00C!S7o :\JvʼyHLLI&1U΅ 7o/^dɒ%L6-W}$''3i$z聕b͛7Sh|P۟Sѽ{wLLL ʕ+T\-Zh3Ǝ5FZiFӧOYti>DXYXXGc׮]iӆ __ O! зo_͛75:]LLL>}:1^z_'''Eg_Ν;cffѣGY|9D˖-iѢժU˓mllիTR'NHdd$5ԩS|,X WGjՈȑ#kN>,,LgҥK3p@ȩSزe gfB!p;!-ʔ)Sعs'n֭[ܹ)SPHO!BI&wB!Dsuu}gկ5k燣#7n`8::g9w3f)Bճ=z4?C|c\wһwo>}p]V\ ѹsg֭[DZc8v6m?%JV:,vĉ !ڵk_0w\F ԫWgggNʳg8s ׯ_gРA̟?'Oۇ;W^?XYYѳgO/^ٳgyY֭[7܈ ==۷o3vXhӦ:Y`NNNҲeK-ZiTQf }aÆq8y$Æ Jkkk˖-ԭ[u3i!x3 Ba6ls/ԚZ!Bw__a!JJJb̙>|"EвeK<==)[: >t,]ÇL6m8qδeʔΝ;ST)m:IJJߟs=,--i߾=ֺ{]~GBCCIOO}3f͚U/]-_ƍ?>Νp|'9Rc;wKhh(O<ƆӡCllܸFid(Qkbjjի[.DFFRT)ʕ+ݻw^:UTիza1cưeΜ9CVCLLFq1|pؖq_!owEAB9/zSnnnwB!BXwB!k(J~کF*Uزe QQQ 0{{{&$$x9uׯxǏ4h;:<3f0tPu놓jFvjj*Çun" (,YBB/&~!Ν;[nQ )_eذaqqqL>!$y5ϛrOG5#ׯ;wŅBO.]gϞg̘354,YaxgIll, *[r !Ȉ5j@޽y޽;ڵc۶mZXk/iѢ}ȑ# 0@=+.fff4k֌f͚1~x?Ndd$Gѣ|+V͛ӲeKZnw ;ƴiضm7nܠdɒlْiӦg.^E'ŋၗ,ZooooRRR * &88 &/@.]Xb6lH;l0LMMYtz}Ǐ7l!;B!B!ԔwB!D dFR`Uİl2իDž 4i7n`ڵxzzjlk׮ƍT\ӧcooOdd$'O֙[n+V ___V^ի133nݺ8;;ӵkW֭[U'N֖k׮ɓ'ٹs']v`͚5ܹsG#ӧO3eʔlϐUT”)Sx' C;\^xjԨӱdl۶oD IDATu C AuBw(.ٷe =|E||<+Wd֭XZZw *saɒ%|\t ;;BLkV_pvvȑ#oߞ-Zg|`SNbȑtŠ} *Dݺu[._}bГ`>/}A0J.͂ X`A@_ܻwoz2 kt/Y$2A4hPe !x3I !B!o%WWW\]]; !"OI^fM/QFxyyqС\p ĉ4hЀo#F.\'̙3:u -[Frؿ?>>>TXU2evݻ՝tҴiSƍǸqU?CW7nYHHHPo?z(cǎUVwN111/SJ#ĻM"ɌBa4Ə… 2d?# `ƌ0f֭[>Gf077pqMIOOښk׮I !5j~XWvm?Ni֬wt0w9~~~= :_#Ghth֬Z2h !B!B!B!8saΜ9|֭ ?1Sr_0`Z ???~u=o:w387oKӦM6CWU]dI?gsPD tu4B!B7nУGXv-MMMٴiڵcG믿RlY<<<2dժU0@]6o޽{A)*WLHH]ve˖l۶VZco7C;`8;;ӸqcLLU!o<222ʫB!Bbbb^`>RSSi׮ ,Y33\1W=hɋ}3 ",, xnϞ=sBn/_Vcccӧ\*oտ*n,hтdvM5ၟ3XW/{occc%cYߐU2j> )[gBҩ= !B۷}RlY2MښӧOSh+--Yfqvvfĉ|駴h"BI5sEtt4[Vtivڅ[fΝt)|qa>QD ZjL6m]\BFNNNvB!xC͞=C!y#GM6(>IHH !!`\\\r&7t,Y¦MP^zaooOz;4!;(<<JZXjǏ端A/::ZcӧO/FAT122BQ)^8{W\2W\!""f͚GEEiupp ""-[驵ڵkf+++]Ʈ]2bbbbJo )__ׯ_'..5jdΐ˖-۷ye˖#u!BL6>}|r3#- W^,:vȉ'ػwo>G'eʔ!**JÅ(lܸocjǏ?h04aS# ۬ F*V1mFR!L 4LD.&\f 0U;qN騜yޯ|ާy]PR%ƌCntkN1/.BKll,~~~L0ڵkӭ[7wNUvFB!JٟI!%СCDFFҧO]";v`gg0D)WlemݺO>_m۶Ʉ _3uT[뇯/2B }3f̠iӦ0k,zSF n޼ɖ-[߿?W^eΜ9Z׫W/gƌnݚ3g(kȐ!=zP޽N x!G~P(Э[7V\4i҄0V^9AAArfΜmڴ̜9S-¶_ sά[ϛo… ٰau7mڔ,222&V(&N_BBDDCBhInEYquC!-ZOJiّ.O"ZRYD"11I&q!>}B6mJӦMqss#''dbccٽ{7&L ;; *'_X[[Sn]]-B%0b߾}8::wBWHnnCBd}姟~uBڱcC(.UVVFL2}q!/~m]'hŊ\v+ӆ ڵkYbnnn:Nz >*iM6Umee͛Y` ,P̙35JnkkЭ[7իY~=ׯW+aÆ7Nٙ{Jʕ+3a+=ZަM.]rnaۯM5bIIIO>Q9XQۺ;wL\\Uf>Cc48pCB :p @__})w=>};ܹsuB~-Z %%?}] ux===ڷoOÇ$%%{nbccYz5=E }իWuB!^Szbrss!yC^Ro9B!B7n0m4ɉ(~hfѢEKKK>SyJ>Źϟ͍.]н{wfϞTѣGUy,66WWWر#| ';;[yh[¶mɡwЫW/rrrضmZނb.lk?~̼yڵ+Uoݺ7]t[n|ܻwHע[6hCl<ᆪK.X[[3m4nܸΝ;[ ԩL[.[;wB"`qIx{{ckk>5kdРA(;a^:tԉSj>!!!SF GckFOO}}}LMM3f WF˗ZjXYYrJ] dԩS+ҵkW~G8 ~m/Zjb zIժUX"͛7gܹ*gjS-o j%$$`hhֱ K:/yȣh!J\~'>#ڶmÇe/_BCCyBRe˖۷-Zpvɓ W/e>]ve$$$pMvA^?VZtbbb~SB!JRp!BQUV*B >\~ -{˗iO[-Çquu%--MvUBCCIMM% ==5Fͭ[شi999/R?ȝ;w,YSVV̘֭1#k[nn.+~)tu ʕS٘wm͛7͛7+/[zlo}_"=kܹDFF*cݱcǎ#,,jժk.5nީS':DTT/ !=WLLLy~5kV兗We9@*U UBǎرcUZ5&Nĉrʌ;cצګ)Ӧ*U˹r ʕ+;vѣGo<>!J}pB]!( 6:!Tܾ}#FuVf͚{9pqqaƌlܸQe7>!Oj ~QFQBrrr eر޽[+ ݻ7{.Եgbccߟʕ+ciiܜ d8BQb;\!Bhr11B!׎;?uF˗166&44BXXiiilْ5kpA6l@۶m9t6l͛ILLdȑٳHe6nܘDDkEbb"'88@sAGQ>׶ÇbjjJ&M055Ԕ?3AƬMk+55kײ~s̡|lڴDF@||⾾b MgHlR ;p̓@W)!é[.Ȅx1DDD: ! _Q;v sssOtt4SLA:fddg}ܡU!*sssܹr/&>>^x5[ 0 Ξ=KFFԫWŋciiIZ۷/?3Bb%Sə3g}Æ $%%OW'8p M!(uO?0%߮Ϧ9rD98LJ֭[`ff/ƍS ?ӉӧOΎ;v`ggr' 4ёPn߾]2W>'77SNsNΝ;Ç{n}m->3{n݊Z=ƬMkK9 }&&&hѢP;/jSoÇ ~7 95Q޼QR%zzz)g-./۳L_mWlBUgWC!BΝ;=.]"22?X! ʕ+ѣcΜ9j !ЬVZ̞=777FIVtxʗ/9L2pPrss133Ɔ=zйs|CB!@. 3[b׮]cʴ!CvZ嶜B!l~:kuHU~}9~8|2jy 22R9ᾨ̤$BCCQ.\Pq+jSmXp!:uR;~ƍǶm&\ݺuKG!Br]ڰaOǎ 5\!^W`jj_>Çחup/XlɂAJ*aee~~~ܺuݻwMDDg7ޠk׮ٓ=z$!j ^t M5899՘Wvv6-o߾XZZ駟Zfsq֭[uQ[.[;wpkBQ97={E4k֌Ν;Ξ={tKcbbI+K֭[GϞ=5ӦmeO߿?۷Ԕ-[bkkG-z˲^#n=Ǐ9qgVۭ[7|||8}4O<WWW/28Ç9}4۷o3Aff;wSNbii~KKK6lHZZΝ+0Vm]1d˖-ܿ .0gΜB6Jjs]6k,e_'''2b`[FF !BQT_5%''ɓ4i-رc/9B!(=zĄ 8p NNN۷O&[o:!(SXx1:QT^?@Ν; Z*3gΤu1l0V^MVVCBQ l ]w...\|Yvi>|WWWҔiW^%44Tʮ]ָgN8tQQQ߿B!DI￙>>cӦM>ϟ[޽{3om}„ 177gԩݻ\8%q}5boIJJf͚ e$$$0l0044TN"%ё-[: !(S4*Yb׮]cʴ!CvZVXB!** GGGj׮Çi֬CZܹ3Z"((H&\!fΜƍou(oooݻG\\111DGGO?OΝGo߾B^ڄ 祗 ={OWmݺ5fff ccc7nӱcǎ[י3ghذڱFB!DɥKСAAATVMxƍqwwƆAqA" QVsqy/_6pZjʛN `O׮]uŧf͚j;C\zzK%ZjL8'Xf~{5̪UبQٳ'={Ժ+[`l  wRly~}}5yaDlիWW*U˹r ʕ+;vѣGˊNB5`] D5`4h0k$''z*+VĄ>Ll/_Ntt4ׯ_筷ޢw*wɝ;wXnԩSGnݺn:JժU_By }fb0j IDAT!e+'O~څB 5kdٌ=#Fжm[]$ʐ*UЧOL\\5k$00PmE^xzz&\dMZܹ3p+ڕNJJ s%99J*aaa;mڴQ;ŋ,[D^JʕiР=zYc ^hqF.]AjԩxJO 7[ *tפIƏ'\߸Ϙ1cp,]NTTΝΝ;TZm2j(:tVy_#/ސ_xuڕlٳ'ddd0w\@(پ};xzzOw522I !^u6luB! ) _~EѣG8q'Np=x!)^zPRSS (p]vMNԎuԉC% !^Kׯ_ёx/^CEĔ)S_ =V!#Gl2<<P?~\-DFFbddu]j"++[nQV-cnRB!S/ܻw#GDݺuIKK#""+SDIn۷MY]ΡBQd/`AD }6$D{7{.\p+++W ?4nܘӧcggǎ;˷3gаaCc]#yu˂ 2e ^PIcфqi!k׮xzzbgg'GbWR%ߟ7nKLL VbƌTZnݺ)'`4mTa !(j… ̞=???5kƩSTb*t֍+Wョ'M4%,,իWcnnNPPtbnn.4hMEFFĊ e!Bcٱe儋?{/MǎYdr&MdJRRWخ>@%:0{l9zJTjժPB:t@@@z"&&F9ᢨU\ׯ(Ą0jJ֬YG( ŀ{mTj7I&PhZ(j]= غu+?-ZPm۶-?֜>}QԿ?M1⧧ |ɤ_d'G+ `C!s|W|w$%%Ē%K9r$*;effܿsMVvL##F믿2sL<==eW|AAA2B!^̙3ٰa>>>,^XW[oŠA4hgϞ%::h|}};v,5Gbmm]E#B,=]29::ҨQ#.]3;vdĈ\tI-35"%%''':t\rʁ5j_~|ty)>boBQVٳCj<ow᫯ɓ'tڕɓ'OLLIVZN\\2<]uH1ZAOOѣGw^k֭[p]tŮ\#Gd֭\zUyI&+w,(*막6C|Pm"ҬTQ유iIl6֕w7"ȏڟ6l )) x}bEMUj۷/}%--XVZŏ?Hm322|﹵j"++[n6-e!x-]qaiiɚ5k[C%lL8PLp6lK.͍$E*TK.t҅3f?{nXz5~~~TZkkklllU*ل ]Y&ӦMSIS[oWV'2qٳ'={TIR ,_+WP^=\±c=ztVB!^5[y֯_۩R !!!T^]-Ovv6P+6lȉ'HOOm۶:ɓ'*=C!xRJTZN< }ФIw鼋t֍+Wョ'M4%,,իWcnnNPPt\233iРM6%++  &e]vv6Z ///&NHH'OָӓB+W,,,X|9...IjԨA ;w]v7|5_!Dx&\tUOϞ=144$##s;E >۷'Tu !eb%cǎi\r700޽{^‚'NPvvvtޝx: ܹs7|S۷o+c+'ȑ#9r?L )؊rJB~XѦbU[`!Tj7:uɓڵȟ_k$ڶm&LN(ݻ75jޣ{Z^W: !DEDD:R! %)..DScƌsT^͛7/0e-[FV^r>SN^~~%""B> ÇϜ9s3g1333忝ٻw/)))jU\Y=>y&ȈH:wL\\*?wBΜ9=W^%22?X!l,\(zpi۶-nnnx{{xiҤ M4ÃǏ~bbbصk˖->GҡC*Tx !KWe 8r}aƍo֨QQFkL>3tP@ RrbK!(+=z>=xs}&L@= #--gҾ}'Jxx8#GJ*揊ݻ*4h@jj*)))tUcǎ)'ccc`|$%%Hl/zJJjj*j4o\%]OO߿JfffZSmf,[p:}k̜9!Cv999ZQLW G1p@]!B^rHHr9EXh+7顴ٷo ԬY+WRN1ccc<<\АP-[ƞ={vUT WWWEU&MŋÇڲ`6lJ bccZ,/ODD...ӰaC]$tytڕ`p!/hƌlذSpW ڵ+]veƌܼyX_zt [[[z"B!^k''NyT\===ׯԫWl߾=nnn̟?ʎB!P^x1O4;w?ӱcG>~G޽OQѣGU%̛7]bmmMPPnۛ.]Э[7[ݻRvll,XYY)c?>722CLkРA3Fm¶fƌtޝN:뫌Y~׭[Juܜuqu!׷o_ؿ?gxxxDYZ5&NHdd$d̟?_mpHϞ=ٺu+d׮]#8vW\Qr ǎIma !( PonnNLL ̛7VZ_zj7޽{ڵ={CŊ %էԩSp?Ύ>}вeK|M$))]vMHHzzzXXX`kkKϞ=BR7lX!J=yB!Do`ٿ?S3c }EOȴj*߲hԨ3foaɒ%,YD%_v+*;Y1cp|oZ/_cW_׭[~ bbbQ9O?T,;m3Ο?ՎxyyHl/rJҢEe*k&88J*{xx@FF R96k,|||4ӲeK<2Mz+SmRJZb 6nƍ-^zL4}hRu5 &xxx믿rERRR066V52^W$""B~B+hGEjj* \|cccfΜI9q\vM%oXXiiiloooLLLߟCm68rro׋.\@zy椥1uTΟ?ʕ+qssS9qƄk׮aÆ/1gLMMٴiueժU#GdٲeI!xʕcŘl2F됄(}}}vJ׮]5k˗3}tWNݱgȐ!Y! %BRʊ_`100M6|tE%ffu 0Fd> 4>/T`jjΝ;ټy3vܼycllLǎ:t(Mj IDAT6Xg݉dɒ%߿Zjѹsg\]]yn&lܸ`|2=wƆѣGSfMWCƍ"-- ccczѣQZVZ… 9|0ٴhuy1uT9ƒ]v$T۾X"| #F`ӦM$&&r9nݺE122m۶ңGʗ/ړkTTPΟ?>mڴaĈt֍F1i$֬YC^yY 3wB!^k֬QabE-4>Wسg>>>n333|}}7nJhj7nӱcǎASlmڴvޭ6IwX///@<x4lC­[Ǔ˩Sعs'Νӝ( R|yZhQ{[߿? 'OdĈhт˗3hn<{m*TPC맸G5"BQprrVZ}W!!!̝;W!D5d.];III.!BOOҥK B!B!_WA?f֬YDFF$33[2{l>â[=xiӦ?O||<666|w^>>l޼z"/f͚Ell,`mmoͭ[HJJ"((h*V2UL3uT+___"""000qBmi3ё~/\`ݻTU\ &(רQ7oү_?4N>|Ç{n2339rʱ +++viӘ6mӧOөS|;gƌCzz:jw ???ʕ+LӦNNNrAʉ \Ν;Gjj*fff*y}(M !({كUVx!...qFtBY-Z`ܸqbooOڵurttd͚5C!J"W*  6l(eԚ5kزeB KOOu2Ξ=˦M'88XmcjLǏhLCeg3C"lI!0)XGL҆J2gD}1GRD?|t:T$q\u_4gefӦMcl޼cj)Z:s Gڵ*UD>}hӦ C !<<ҴiS\ ,aÆ =ŋ*ϳ*S xzzr>} vvv̚5Ke&X|J;Gݻiдo^~B˗/qwwgΜ9ۗwOO5jԠ_~xyyI…Bٳg? vBQd 4Pyk oi!{p!B!+>dDFF3LMM>|r欉o>oTB޽qppPH aҥ;wRJ_wߩ̰62e i&HKKJ*tgggʖ-7k;~7o&33\ƎKRhذabONNۛ#TB׮]qtt Ǹs*W>3g0vXʖ-cll0BG|wbxcNNNtޝ/Ҹqcm#-/^-iF! +kkk+[KB!B!g)))888p=eY\\A899q%eYBB~~~\pOOOtuuU;v,IIIyf^|[\t)+*u ɓ'̝;7A={̱==O2zhn޼{pp0111x… ٱc܇sIᅮvgбc\cl߾=˗/?/ r_wDArNCjj*j[XX޽{0`@"(:vHjj*ӧOGp.\@͵Ж#Fk.AAAaggBQ?~p) Mnݨ[.^^^XB!{mȐ!YqK%B!,_sssYʕ+9n Uξ%KB !B!ĻĽ{Q~~~DGG23B`` .]I&s BCCi֬111l߾]mO>0oԦ QQQʤ 60}t8vWѣб9bfVlȋ챯[7oRfMF\~+22˗5j*ׯ'>>ZjvZr5c N4ݷ `4=+ȽsVTVXQP)!>}`vJV&66+ >,eʔal߾ؾ};gϦtO:::|ȤI|Z]MU?111ɵݜd=>>xzܿ@fTLpp=eY~O=֬U9[%(9~}w0ٓp rgs?P|ye:BIWW[[[lmm(EqBM 4t8@(ƪT !(3f ((SѪBKX[[k; !(vpq(%A>>|>XmmΝ;ͣQF\tIy;t蠬[bEnʀHHH`9ϟ={ՋUVܹsiڴ)W\]؟9_~%vGGGuFʕy!YgϞѫW/5kV5]79oSay9''11;w%VܹsGYG!B!( .0`{nzɉSd*Tp⽷|r>sVZń Vdd$k׮%22;w UF֭5j_~C|'g"׉LJ#GpmөP 4wތ3Fex5kB+q~ ˗\~ʗ/Oz޽;Ԯ]Џ5)J[>脋0VX9ϟ?'<< qFe"E^r%4i+ܹsbbbؾ};*K7*VaÆj*ʢ$B!{O>Ga!D% cСܾ}#GZwȑ:tsaggtL4)/6;wLxx8fb֬YjⰰP&,XYYaddĎ;}SRdI6nȺuT&.ȪVZL>1p]Uuܙ0~~(TTI6jԈ+vvv߿+W,ٳr VnnnDDDtR.]VK.̜9kMq圴k׎ÇsT*V#yWI&BٴizzzC!B?~<-ZԬYS!ӦMcݺu20X! A4ifbРA2 9ݻwmwcӇ 6`hh(_D=zDTTQQQ,Z???Y, ^q/_Tcbbba…|wxxx$rM%\( ^W5m+[,O>%((7oҹsg To߾}xxxPF LLL={6ciicQۦLRB!Br ZLȑ#<}5kʺyʕ '''ԩ ͩSѣGyuΎ[nƍ`ʔ)\D t%J0e˖-[<*UШQ#zAn(Qkc/_<^C#*WLn3fʗ&MBWW}3͙9s&{ҥK9~8*UW^888͊+ؿ?)))t 777٣v|}}},X#Gزe ϟɓ'|G|gXZZұcM^tMMqٓ_~G2|p=ݻw/ ! ֭[ٺuB!BEjj*ǏgڵO?Q=2CCClmmYz$\!D!9s&8"/,,,y&5j`ݛO?%Jp-6mĢEo߾DDD,%"]>ӇݻwөS'nJ 4ֻp:tǬXoG3ؽQF\|m۶)hիׯʤGh}AaܸqxyyajjʦMh޼yu4iK.-(,ٿ.YW =zЦM:Ķm8{,V"00+kpO>uUۦ(SB!ćiѢEZ}eN2ڵkӠAwB;ѣܹs h1bv"((FFFi9:!Dn xM0k; !X ɉ&Mp)Jfffj ///IBBbeeEϞ=qvv2þx/ݹswww~w/*UD׮]qssQFj2^5X.\ȡCHJJVZX[[3c =ݻZ*aaa9&[4i҄ Ě5k.?>TZݻFݺusWff&'OdڴiDGGSti:t3hժ~׮]cɒ%DDDRLLMM۷/'N؇Ɩ^k׮Vύ+WСC*G!sNKK_e˖-\x$*T@֭:u*;wָNnN rM6nȼyz*ѣӧOx]1߾}+++ڵ+;vx{{c``}OsEڵVZ|rLLL4~g]F ڵ+3gΤI&j5=5)ʯI}dА}˺u1bOLLViiiX=zPjUU_|IKK{Q !Dӧ ,k׮j kkkbccX"ZP_eʔal߾ؾ};gVYTQlڴM6i; !K6mݻC!(6;v,vvv=#GH(ؼy3CBbc\vUVi;!ѣ4mڔ5kNbb"hт|YLk׮M6o<|ϟsM.\HǎIIIQ ^gTk5rH=ɓ'Uwڅ֭<vZ7oNDDDm8q;rAx1;vCDGG=y$-Z`ܸqt8ugϦy_[v~)k׮͵mccc233yqbINN]vL>}Pn]O]K.憋 u~z^edffr]듘ȝ;w+ܹ#B|jc%?[nQLWٺu+C btBQp...{nnݺEzz:h۶-TVM! ! E8;;xbƏBEa,,ćHVB! ױ͛bmm퐄ѐ!C} 2w\"##/ԇRJȐ!Cxݝur5ضm ҥKT^]M{{{zO9y$GƍOڵKYwҤI$''3f\\\Oĉ?K.1geB֛ƖUA߷~ˤI;v,6mʊN:ѠAtusu+,XSNѸqcV^9sI&;_}U+^vڕ&Mp زe 666)緿]vcllLrr2r5KK|y^նҦM~5kƍ7ؾ};vvv\vUۻAp1bՋcǎm777ZoȑԮ]saggG֭ٳ'ׯtL4IYbŊƾkڵk bUuСp:/B=z'GƆ)Spz)))0n8lllpvvfڵ4h ݻ̛7aÆaooϚ5kTVx%7ndĉ2|pf̘Un_t {{{̙VGSLwNNII!<<&M8PJ7nLxx B>֖ILL ;vU-S(W{oCAω-K,aɒ%ؼȄB!B7[ne˖ϣl!2e0byBb͍rI2x^ҥKSKM6Y'ʕ+sm̚5 SLſ_]6zzztЁ 6~ze}$ 6,pVXӧOҥ aaa4n}}}7nLXX]t/ر#aaak׎eҩS'֬YcT,Z:uꠧG2eܹr2m۶ZlYM8SKDD4nܘ>Ν;ʁxEO:&GXnڵL2*U֭[n:Ν;6 "$͛gקaÆl޼nݺ?zje73hҤ ԬYxШQ|?ի7hЀкukJ*EFزe ]t!))Ih@Aۻ0HʊYfѠAԔ#G**槞2SȈ%J`hhHΝ PYbʔ)ԬY%J@Ϟ=)[,GUѣн{xFB[RR9rd^xݻwTf2sLy/^ÇڵYf$R(̞=Sۧ| ͛IHH ##4^իڵkIIIQ[)ITTiii4kLm[fHKKS{S,B!B!B/?ɓbРADGGSn]m%D;[nw^m"ņK,! Ǐk;!D1s7|q@!##={2|8;;knnNff&nR={ x*}⢶b21j?~ZYVxJyZӧAAAm7&33B-^?-ZĹs2e M4AGGOraϟOnݨ_hsrm2335 駟oS~IVnnn,YRLGGSԩZ裏rOCCCJ͜92eʨe߲+](*Ň}ҷozL<ɓ'ZGC\rK||2)>>3g0vXʖ-BQ0۶m/L0+n:""" sl߾{QZ5&L 7n`Ŋܽ{[2dkԨ\2aaaq }tuuI&dddp|||ꫯ U,ͪVZOzs:ӧ011QkTYGFB!"\2OV۴iqC!Bf޽pׯgСI|iذ!;vdK!D1x`V^ͷ~ˉ' Q\t ##\)fё۷oSN6l@%T_~ chhǏINN*mg(WĖ]:uʕ+B+F"::h8nݺ_W__heׯq<~bbbȑ#ܸq={I-^OV7oŋp Μ9@fff)^,,,4+V5|"y e|?rNTҔW\\\]Q~ T`Ĉڵ \\\WaggB'!5%SN0j(GGGeRBLL jVzP~}ƌ;'NPK=zͯ0RRRK.Mjj*v޽{jJcfn|'[@b5jmSe@!B!D|>|XDBOӓ7WB!Dڵ#F`ddɓ'iРC@6l?v8BQl,_͛秜]^*Chh(˗g۶mTXQӧOXQNbccuy'##CeU,9 X/_~I9?$ LMMٻwr7-7~YUPAeUVqYΞ=ƍ߿?_~%JSձ+$)) _R)!ĻLppB!(Çk,3gdʤy+++f̘MԖ B!3Xh#F`ʕ񾰲bĉ0{lm#F&Mpvv~T\Y! r?~$._ĉ!00Fxd>}ctЁXٓWҲeKkW?~LRR*URG1-ѿݻwٿ?DFFrUnܸw} =\?RRR?sM-_<5hkkkj׮M*UhذrڂDGGG,---&Yt*K eoݻwԩS+bӦMtM+](r Zh3/`񘙙i9*!ʾrbeEv߰WͲʚa84mڔ'Or\BHH;wƆݻ9nնIjZ"UQU! b„ XZZj; !Bc }ޗ x ߟhccÆ Y !B㱱ɓYѣGk;$!ޘ>0c ߬By̙3Yj"GuԩS;v޽{y4 Bjj*sΥo߾9555̙3\pvڽ!Cl2~W&M?'[lɓ'*cPLMM?W^j8qBY03j(FΝ;9t[ ?رclٲo6׺pwwˋcǪlKHHP˗i˗/IMMUƍkٳgرZcǀWIu o,^///Fr9s???tuuX?k׮jǏ^U_oBޮ;V[[[,Y’%Kv8B!A1ݻwsWZ5TϫVZХK͛ׯO>eڵjO!ٳg2M}k5Qd>+JQ&B!B>x!f͢k׮m;;;݋ڪΩX}Ҷm[kVZEzzN}LHH-[T~6^:愄h|&B!^4oޜD%B+$$$cm"Ŋ! ,ۛ3gh;!rqP}hh(:::G|ʔ);wNnntڶ .CڵeZ{$&&2x`RSSsl޽{,^]]]L,ٳ'-R$˗IsZ ?j׮/^TfaaVV99spܹ\۟?>۷W)W;6lZ[K.U;xX"111j4ƝkŋT)PEonԩ7|CZZzz8Czz:ƍqU%Kx 0`m]]u!BӼysvލ?}˗'((ի|rZlI||D@}uL022ʵMCCCؿ?ݻwÇ oMǮ]6>jWBwmk; !ÀxwRRRppp޽{ʲ8\]]ꦧĥKe q<==skϞ=jA‚ݫB!˗/qwwgΜ9XYYメP}///pX>|8^^^L0Ç̾/DQʕ+W^xxxдiS ! %Kg\MnݺƍcժUSzu&NH9~8&LM˖-ٽ{7M4￧wsnܸݻYdrқ37+VpAN:\~WWW:Dٲeoذ`aaaARS&d0c+5j;vVZ1fLӦM)W'OLJ-[PdI̙r\ Ғ/_1ׯ_gʔ)TR8.\?zHeڃW۶m͉gʕ믅rMdС|\xSrqU Yh/^$"" СCi޼9}?ԩSDFF;w֘T3g&&&1m4"##OVdW_o$\!BիWqvvV6p@lj'HHHP722*Ֆx{{㣖ѨQ#I'Njժ\26[lIDDׯWo֬Z[ӱ̈*q2 "֖ m!BU :Ta|Ђw5jয়~aÆ?3f\t&Mꊩ)wÃoߎ%U-l@Æ PEEEI…B!Dqa~B"DQDqG! <==iݺ5֭cĈI55k$88~ZnVgժU*cJΝ s000ȱmd@ueժU8880|J m۶e*ekV޾vZK(Y>cf۶ml۶Me{R O>1ضm/_Gjk֬?Vb++Y$;wdȐ!ݻOOO<==5ohh/m۶U)oѢZY j3g$$$k׮qI_3سgׯ_C*mz{{w~IV+VΎ 6WZ-[P|yeYA:ڵiӦb XDL8 RT eرW^m۶QtiܮIvE.}Y&E!-Zy䉶B>}pUzzz|Gtޝ{2n87n19|0{B ӠA͛{4i҄M^022BOOҥKS^=ƎӧՒ-kN:FFF,Y###ӧw?4144$::~FQLJ,I:u9}[~@Ŋٳg;Æ ~-[]]] iݺ5sի**ӫW/X?1cưvZ5kFR044/`Ν̝;3g啧wQQQۗ+O֭ٹs'cƌ)k0tPBCCiԨzzz|nj7gbffR }}}-[F\\ӧOCCCJ(A hݺ53fڵk/&[X[[s!͕㿦NvM4)ʯM' ךW̠hF]B}lݺUBq ##e˖0i$s۸q#aaaXjժ[ $3 ,[}*-Y(fVhBQ\}AAAj|dD6 9vRiiio^ڵͱ-CCC8q6mڐv,t,,,#::p:'BEff&/Օ={H ܹsYbj)BGQ~}FŋB )>$o& z[M !B"_~9r;w*sܹUW_i9:!yuׯFmܿ@?Nbbr6N:1d )ڢEӀ BM7#:=}46uuVi:B!xnj5;wO?"yoIBʕ+3o<&N=5vHB!($pakk+ʄBּ:W.]3|k<?ڥB =~W^e̘1(ӹr W\aǎ*WCsi<==ٸq# ̅ 033S… 2SB!DO<͛73k,fΜn:}4͛7/NGGL /:uŊ+B;mڴaL2/ej;$!BBOPB삃:tB!">|ˉٳg2|p\]]DT|}}ٷo7UTw888H aҥ;wRJ_wߩh62e SΎ~6mD\\iiiTRΝ;LٲefmGѯRJ_<|Pp`lll399+2ݻXYYQfMmۖs7ѣGTR]舁ZX`C__3aTKٻw/ ajjJ~udBBBhٲ%ժUSW^sssBBB6l˗G!Dh#L2x{{ɑ#Gx)&&&1k,g燏+W333S)SXr%гgO~=U8z(tt\!p}o-B!B!x{eqqqdqrrҥKʲpj';$ؼy3/_ͭm.]d____:Νc{|qttoߞ&Mn| aaaDEEaooߨM6l`DEEq1V^ TgU>]1cЩS'ƍGhhrfnCRlYTP$\t!_jݺuܼy5k*/5jjdDGGG5>:aaaXh9ظqZ/** (SBQtusss~7dYb...888;ݺu ƍ8LQG!KO?qE _9郇KE!uԩSڵ+(+deeKJJ ;w^z̙32d۷';;ڶm˪UT.Ҳ6͛8V\ɓ'O  0L1*O(xyy7( "޽g5zRN +WdG!$KKKƍǬY_*e!(IxN(,^;;; eѢElڴ mmB $00Pa!xMOWVZBŌ)$444jEWXt) ڵcȐ!ѣGJX ăHHH(1TSSggg”+@4k֌>h222HLLT,E2+ԡ[t gl۶'OJdd$3f࣏>*ܕ=Nq-_- !([y?zCQu)By!'$$?6lȒ%KHMM_~\Ο??3ḺҴiS""">|8NNNٳggg޽͛ק˖-TEu҅uod,Y?L'33N:E޽INNVY}CAq̎; 6App$\JqwwO>ߟM;!ڵ+| /Vw8&::Za!D jy]ׯ3ae=111]5F'BODDD_!^&β sj׮'OwU|ooo FXX,J!jIÆ o5jvʪVIKKwީsWˈ#((hu!jCZb˖-e:9P ə3g011!::GG޽III!>>T1ÇЭ[1(uB!BOrikk5M6A/uuu ׯCeݺuZ&+++ԤG|WL6 wӶm[ׯ\ٱϞ=J˖-W3}t6l؀~5j+qƬ]qѪU+ׯOVgݺu8& ҠAZj+WT|tMMM455122b|geSF%Αr!ϒ!,ȧr!aذaXp֮][j!.]*.\Hzz:}0Q;w*ɥgʔ):t>O<==ܶx}*BQF gѣG5~~r'R6|#S[^ fff*/kKM!77(233:t(vvv٩۽{7l6mϖƆllllܹs;Sn8ƍW1Sc.]ҥKٱcsO133cܽ{OrE \.͛`ҤIjH=iݺ5QQQʲ( pttTcdB!B!=yO?+++;Va]v%))>}l2n߾ɓiܸ16l@CC7n3oe˖tE9beۨ;͐!CԤ_~Vt===6lC r6atttWw(BQ[?ʕ+G!V(>ۣbe\Ѣ8+++ٶm'O$44Hf̘G}P"W,_à IDAT]^|E,-BXt)52cǔr1,,,uMM/Ͳe(,,dҵkWu&+kȑl޼???T뫬!nʟ=zQmmm|||={2$>> Bd8}$/2!rÇD@@ ,X@駟x"/WWWZj_iZΝ;M1cF3W !N Q=2BWQbb"hjjr!儎UO`` e։&::DNNN &0a„jeOXZVXr b݌1B!DC@@?~g*eeeKJJ ;w^z̙32d۷';;ڶm˪UT.Rximeii͛7g\'O<[!ldff*ݻ%oQnLrr2wӳ=(+##=zlWfѼy8p@c< !66BƏ1{VCBJI3f fffl޼<:w1zx{{sY_hu,[e˖aoopB!B(,,믿fذaۗǏW+BQuݺuc\Rݡ!DgccgϞw%--Gqi?Lxx8M6%""wē'Opvvݻ[}}}BeHMM_~QT.]8:uĹI;vÇܻwOT\C)* ?xŋcggmڴ֖ExVpvv???T9r߿SNROKKs*u}v (1#A !?(?N~~>ڵc̘1|9rnB__AG$]*|>}---ϊl ӧ 4---O?ľ}S[^̕u혘"""ؿ? 4`Ĉ?\V^_4h@>}:u*ڵr}*vdd$Wȑ#hhh`jjĉWֽ> ЬY3ey-ѣ =ZeW!B!B!xܼygggvҥK3g$ ΤI|2oB:Mȑ#wޝuѩS'"##quu`ذa̝;Hrr2gf嶡x[oUn tsdnݺܯoժU <+V0j(sr8}4666L>ӧWDLg<88:֮]UV'&&k*p%mmmOڵ+hjjbddɓϔtuu ׯCeݺu*S̟?mR~} 1b:::$&&!11]]]{ڿ`!z~)$77ǏsE=zg}ƶm۸~:??`˖-Çeݬ_i޼97nT>Tɓ'ܸq~իW{UmP?tP+z߿̥̋\~5kְcg,Y$>|9x k׮v_@T'֬Y7^էxNxyС=L<ccck=8q"seݫWNFF!!!ԫW<;w$// ,,,HIIa׮]|G5xuBׁ|3%?!** jN!x5xy\\)))L6 cccٲ?rgVf̘13gXbԩS100>`˖-ܿ<`X~=dffHVVPou aÆ޽{KM(sU\]] F"66ӦMFͦMTVw[S[qOL6/eŋTLQGMtt4=RwB!DڴiCx蕜ˣXݰxb߇lmmYh6mB[[E)Bݻwquue˖-_ۻSBcڴi,]۷;! 9w˗/gܹ=zUT.\Hzz:}رc$00Rm\tI>yuܙӧOsA)˓Kϔ)S2e ǎ믿S.^ xؐ۵m˖-cffƣGHHHϏXeEdd$gΜĄ bddDVV ^>=|0ݺu+Òp!.ᢶ^/aL4 xz!u͕+W_JtU>RϥXv)nԨ:CuΩXJ?믿&33D3AW߿ѣGXn֭+Q?%%+p*^UʟT^7TmBV\^Tv kהeYGRO'B!^ cǎUw/^ Xv-ׯ_W&nڵkPctB!x8qqq=vލCBxw־bBz-Fʕ+%B!jч~lޫW/Oζm KKK ޽{ dݻÇ|rFͰaÀg_^XX(*ppp 88~7nlٲmT=-͍ 6`nnNZZnnn%Ihh(Ջ .+iڧHѣG۵MGG\dСaggRo*'ر#>>>ؐM;w#ŸE!..ӧ0c LMMBr*>]1x[β,&Qty:g3̤uۗvѩS'<===wU?tP 8tVVV\V-WZXX_^e=Lh6ڸ5:W~}mEbH~Q\Ci}(e5k,f͚0B(SصkW^ECC###ƌ25kְ{nZhᅬTɌt=6nH߾}n3336nȤIhܸqtB!D1aaa̞=sssiݺCBlllضm[^$www>C~7BI^^^lݺ$ebRD-[۷*m*ϟOZZC QۗȾ`(1GcE)>ҥKYtr//jw9sgLrr2+V7WZ[[zENYnݺPNEBTKpQfsppAa!uJ֭9w={T޲eK\w}G˖-k8ɓ'/O<)1ؾ:۷xh޽K?q۷DEqUws~~w 9r$_}򝼇; Y|9dggRAOO矫 ~ؼy3we̘1Znnnhhhw)muԉ>O>9zOj߿?g۶m>>XZZҸqcׯ!1eLGG/QFѲeKի.}eɒ%՚&9e,,,BCCN:1g~IYUVԫWGUǏ..7!CШQ#yqNNNXYY{ݽ~ڸbO055~4k kkkoEC!BQ5s̡aÆ$'' '??ZLQ$Y(r-7n\bLQG!&=zٳg3~x&O%B XZZ_sE Ѝ=Oʛo̙3gggA۶mKMtjEYZZ?͛7Yr%sU}6 `ڵܼy|/q.///[ y1$''B!e2e }e֬Ye8!DU  )@OOO!W\BB?8A+g VVVXYY5j֬YCNNm۶ '''N憎N/B*9B!Kn^&L'OFOOOf%//---f̘}??طo4lP:ɓ'ܹgggtttعsCATӒ%Kسg̙3x=ʮ]iӦ w/v~ <`a``@6meѢE}׮]#FߒJ{Z!KMM壏>O!DE 9w.]C_p!ۗcǎm2:wӧ9x ߔɥgʔ)L21cp<==%B!^iӦٳey!O>xxx3JLF#UQk B!B!^]$ӧOӡCmfȿ>\|YYvRΙ3geW^%<< BBBW1nnnʙy)>g@@S_bk֬Qs56nݻw]:WGEPPrss:ur0+LˋÇĪUg3ZTvuگ*~X~=mVy5kЦM.\uC ȑ#ӦM\BddNUrÆ Ю];"""믿h?|M_^(:}\ѽW033+S\MV>|nݺ8^Q#/gggZnMTT,** B!^U8::2sL>~'I ///vJRR}ACCaٲeܾ}ɓ'Ӹqc6l؀4ngggn߾ @˖-ҥrʶQw!;;!CI~Jyxxx2Đ!CܶB4h&Mӓ((qƕ:tZU*kvi劁޼hhh`jjʢEJwbllLر#>>>$$$8foߞ 2qD޽\tttTa;vݻO?|rkTꨨrCiիrXbv? ~m Eҗ`…Cy?K]PP@/`ZXXU2ꨉɹsgI#)F(!^%o=U\zWZZZO!gbnnΎ;HHH>U0xU4i҄$̙ChР͚5ƆdyYNppy!\|/_NǎiР>RUѰaCiٲ% 6dܸq Zrssc͚5m۶~JBQ}_5oOݡ!ȋVZZ!!!RXX166wM!P|||͊-ft֍bccٸq##FqaooO~<>**ZKFEE̴2(+qX[[z .(322RӧO뜊 7n`ܹ/%6_~}ع:W>u7.qLQG!^}f̘QB!ٴi...уǏ}TL__@ˬMtttr'''&L`„ j~WZVXE*)h۶-7o˫ܘBԜ{?(!쓙43Of1Q990d|0̊DD-9D9YdDޟTyvu߯z_׻z̙֭31c#FwuHB!D# %ӧOSSSό3 H !9svv{C!J&cJ%+Wi&6mIJe077gРA 4KKBȾp[X;بǫUȚPX}fxb.^;vܜw~뭷xIIImܹUS<>9Ѷ?x1T$^]Bg֝=39UVŢe˖ܹs}1bĈ߷oҾ 8}~&̉*^m:VX$([_899(IV!"==iӦĉYd *TuXB7ȈÇzjܤBA&MbڵL:-[:Qmܸt]!.EhHRR bӦM*e'B!uXXX0k,f͚oFpp0֭c޼y|899iy0339s>H9~dz}v%1uF111PzuZw "##>|ШQ|_C~އԫW7oriJ-OP>===233y @UΞ=Ve~Pa*?siffF\\NZ9~yܹ@:tu~\?]ϋqQ*̉ $''cbbdB!B 888pW9B...,]]vѻwo]#e˖-GDDD`U۶m%BQ9::I5b[b߾}q%ҨY&:ubTTIiw}VXy)]toQߺu {{{_~矄cffqUt ӓgRBuƔ)S*L_\#GB 6lzR#55"##{.5kO?eԨQj;s>~ڴiCڵuʊJ*U^B!ٶmBR [[|N#{][lI˖-Yx1фhѢQ:~Ӻtޝׯw1w\{=.^w}Ѷsά[wwwhܸ1>$(( 6`eeŪU5~ay1uF\\~rѣGԨQCI2uC~޽;^rѳgOjԨٷok׮gϞUy}rҩS'֭[ǂ ;w.\pACJիn݊=wa…9=|%sα`z衴\ٓ+W`[7o˗?~!{&""QF1fv튉 c޽YOҳgOou(M^I&$&&XB!B.22cbbKlS!Dᰰk׮b_!xlllpttՕnݺI1aҤIL4Ia!DT,.|}}W;HHH=R<~#G_y~XYYqIΞ=K͕sgϞ%!!mbffqUƎZ?̋/pww8;;s=5׮]c̙<}3\\\pΝ;py|||Rw&55UmKkkkN8={4 !:ckkBbׯ닂>;vcǎx{{{n6mDʕlagg/@_͛Z6d5|p8{,C Q;WbE\]]=~a٩S'v̙39sK.amm$SSSoߞ8p111,[e˖iէOgggϭ[9rڹԩ,]Kh\FqYZZg)3C a߾}\|1c({,ݝ{鉧FΝ;QgRa|eNڷo9}tJ~\x???|||8t)))4lؐ!C0sLjvZ8@RR+WUVШQ|^}~Wdddiܸ1C ƍyf6m+V 11gϞ{rʱl2_~:ӬY3O=!'UT!00իW111k׮=U*m]]]'22Obee~־===5k111ԨQ={jT\ٷoO!ʺuV]!BQݿaÆҥK8qCB#z|UBׯә?>CuHB6nHzzBRO/ |fqFUS-vŋ\rWrIɓ 08|}}iӦǑ#G}][lje\z*WݺuUV=v4X K^x8 ~WΞ= 9gϞ_I]CUB̟?3tP\]]y!3gd/?l?gРA?P*T@޽Yx1Ɠ¼y %!!SSS+VTک5={ԩSY~=˗gĉ|ܿ &}v ej;wg2uT(WUVeɒ%-ŋ̞=͛7sM i֬O>TO dzh"@wOQ4}ŕ3L255eȐ!:Nҧ(VB!/Jǎ VZIQL=yO?I"Ba+VӓBtБI&1i$]!eKȾ;`n.^/bffFǎ177L=|yٱc]taΝcggqUT wvLW6ѧF;ձ+Boƾϟzj4ݹs;wpLB֭_#ڒٳgvѣG5&LPY0? =-f{ IDAT.^ƍdڴi4h@*'`֬Y(}||_>AAAJӧOزe2'NdݺuÇ9uիW:fZZ;wV->> p vޭĉ*}sΥaÆ\Rʏ?>sܿ VZsӧ+ϟ={FLL 111@!D|ʕ+ʁBQĊe…ʱc֭qqq|GQF zʕ+Y`~-͛7̟?_k=zÇPq}d,X@j&44333lܑuݺuFƍy!AAAlذ+++VZ\LH||FbE||F!(Td!y&0k,7nvKKK<==!22.ĸtؘso+z->>CMơCB.[nK9֫W/v֭[8p+>̙T1b^^^1o<6l,͓'O4^rJaccCxxx Û6mw^~Xn5"((H# bŊ4o)S0sL>}իW+̙T(X˗/qƔ+W{:$''ƍcܸqjqrr:V\߇HԥQ(SGGG]!BQjӴiSN:Euҥ M4ח+W:!(s7n+fbРAʦvB!(|2SNܹ3g2sL.]ښ!Co>._̘1c=zPСk&)) 333>W#F 22gҧOsGV>(Ξ=ː!CUXWWWy9x ϟ1QU٣CyQ!(o9uiiiѯ_?.] 'j?s1ӧ1ch8?Է˱ϬV,7+W ݗ8}4cǎYBz;v௿vL4 ryZ۷su7nѣ_>'~~~;wеkWԫW &`bbBxx8?~\y }1o<"Ν;5j:uBOOW2{l9W>wȱbC^d}۶mܾ}[m_˹u[neԩS|74k֌8IJJbǎJ۷Dݺu4i 4ʕ+h/*N:Z^=ͮ sV%kW)Ƚ9U ͕6X;FΝiӦ9A\|7o;i|orի3bFɓ'YhSNťHB!x/j~LJ͛7g}f!B݋&&&?~\BDj4h7N!D4h VZ_|ѣG56B!+ "wDDD2dG'BLN ĉ˄H ,--qqqHt===233y)*Urp}>V׭[۷osEZhzFݻs!lB֭_F7om6vZ"?s\ ^˜TV{c?Vڔ%ׯ_xyyi311aǎA^57^&*fdM.377\y~uƌB!Dq[(Z>>>tΝ;ǹsx ٳg( \@@ϟ'dݻw9kkkN8={/īB!DI닫+;v$((H@ !/gG!ʤjժ`ƍѣi֬CB!JjW! R-.Yf W^\r5kh裏Xl7nŋ<|  9s=~ayiӹqvd?0k,y&餧smvޭ|*mڴϏ+W(vZeQ3$۷4n߾f{zEh߾}_UϏ .s]U&MOHKKc̙DDDp}?ν{ؾ};f"--?{@k{O_gRay j^uLF:~8aaaC!(raaao|r;ơC߱6oެ … 4k֌7rqBCCiѢ'NPccc*Ϗ9h:j#B+33C2qDصk$[!ÇgչVBQFI-4iCB!Jp!Bw>|smkggɓ'r _ڹ * Ϗ>Cハ7nТE VJrr2'OVZX"9r믿m6eOvueԨQ_~?~;w0c s?Qiӆ{a6lVi"zK=577O?UKLL 7odk]?vX9vׯgm>#\\\ 4qQ*{=/sҪU+bccvjm]$Q8990B"qFBYdeeY [JHII!888:uꄃj"##X`aÆ̞=;;;v܉]㨪:;T *? !lcǎj !DQsqqaҥڵ޽{:!(Y|9ք됄BRA*\!X %44T빊+2{l:wL*U(W 4`ĉ(m+Uܹsݻ7jB__cccڴi k~a9bX"4jԈ)S(xڵKiWvmIOO/1EѣGahh>5jԠM6L2KҼyW^reϟOϞ=QO^?>JaÆacc1h"dVZQ\9jԨ-f*{j``9sjժ`mmرco``+nnnnݚ*UOժU͍iӦahhX3E0IX"5^J*)mB!(nLB ˋ>ݺu [[[TId-韷9QU(ʊ}te˗ءL:SJRBbjժϏ?3=Sicjj ۉOl5Ω!B!.bjjիuBijbΜ9xyyqU]#Bx_$>c>V!B'g֮]ڵkUZUY_QrTX &wѷo_8QBG'D_r7adffgaaaA-xB!DnGBBӧOW^4nܘ?]ΝYnѸqc>|HPP6lʊUV/+dffr-ׯ@&MHLL$>>^#">>^i#B!R|yFʕ+3gI!ʬdzf\]]6B!Dz…dB$33S!!J#GbjjJtt4 cbb‡~5juBd0h ,--uO>e73c 022za !rvvf,\ kժxDEEqY ֮bŊ*ϫW΃߿?l߾sAΟ?/СCa_ !ȍU'GfO899:!(ʗ/7]t!""޽{:$!* ТZQBmܸ[: !D)O޽RX/ Bc bӦM2~xF'8EŦS|yBCČ:쬴366& kr\2ZŅF)mMƊ+HLLٳgуKͰabؘݻ+B|!"+(~mlmm !бΝ;舫+ݺuB I!(,ѱBPB!(s/V\ɑ#GHIIA 6^z{1~~~߿SfMt˜1c066VYYY'gϞB t֍)S(^x{Ν;`nnN~S+X屟ӦM‚UVJW]wNc?~͵ IDATڴiCڵ6uʊJ*UF!E[[WZ*SNeԩFXʕqrrߟ~m8}4cǎRJ!D BUWƍ{;w>@!Dd,--Yx1G!(uB!BQZ=xggg"""x!\v3g}v]JJ 96m⯿"##D6nȨQHMM{ر8q4TvZnݺEzz:;wy===yZCa^6w&55kkks֤gϞ|#Bԭ[W`LMM2d#B!Bڵ+:!(ׯό3Xp!nu8B!DTd.^WRR='N =='''֭[,|N;pBCC]v 0 _c !B!(=֯_Ͻ{d޼yԬY///lB@@}$..~sҴiS.\׮]cݺu?^wyٳgSN ˱"==;wpB6oժYhݷaÆ`hhXםGiӦ9r{{|$lZY03eddٳ+W2i$]#B2M1뮣mڴ^&fdOP= ӓgRBuƔ)S_ سgwsss뇝F<,\(*VHϞ=0a*TDŽЦMj׮nݺXYYСC)B5l۶Ma!D六(Vtu:u?v9W7oӴmV9~ib~UZ[[[lmmpcxzz)";===233y \vM]^[INND\rrF!B!DٔHݺuu(!~Bڴip!@ƍquuÃIB!D˄;v"--/^?<==sq9G//6nHFFnnn޽T5Ʋĉٳ@YBҨ|xyy: !( ] ’%KX`ժUۛPزe :ubݺu,XsbiiɅ СCׯ L>^zѸqc@:Fff&nݢ~Yzu|say9kצm۶1޽{:7BU/33P~:۷+WcTBƍ޽;9 6,1ߔ5kq3rX\9TB ڵ+&Lw͵׽]Ev/^ߟp5}:֭u8B!DP,.U;ٳSp.X|9VVVsN.\͛5.oBCC155eŊp%ȑ#4mTc,ձ#GH…BՋ^z: !($1b={>}=zٙs-F֮~ٙ pBVZ)UIԔ۷gNgҥ,]@ynmcoߞry8Ο?,E!D4(IJJbڵK۷}6?3zbӦMTZUQ\nnn s>ɓ~WΞ= @ٳg&(;իǂ ^M6*v[[\&Oc1}t贵ukr899OBBo6 >}cRR\BQȂ8!(FA\\;vd֭TVM|&M1cvvvtЁj*&NK777xwزe -[T;_F uFnݘ8q"ٵkj"<<\#"f͚pB\\\XfFťKػw/wޥVZtwww7nueffrIk;FŊС3f࣏>xիWػw/FFFckkɓ^C~cM~޿ׯパwI&ݺuk"""裏Xj&MR{M9&:ϬUqכgJ˩S駟}xr,117?L^էsX\\-bϞ=DGGSrepqqӦÇX"'ׯ租~wq5_e2Q~ &#Y&cMenXom$fHP%F1ƾDHha-1~sw:t'|TSNDEEuV\]]B>#<<0xHҫW/7nűzjpssŋXYY)e+7oSN`ժUJ71b/^`ȑL<*Upq ™3g?>gȑ#tܹ@PD ,SuܹsUW^ӓÅ \FC cǎ?ƍsIʵko_ƍ#99aÆ1i$WNFF'N`\pYf) ^5 ݻ=zh~U\]]Yr%ө]Qŭ<,+6o9+eKYr%M4А8ƍGtt4s-FǣGpssSx{{ckkoĉ5jֱ8󆿾}rJ~W.N}5ڵk?!22pU*VX/ҥ >{~B!חC2|p5jBbbx{{ハڵ,hѢ$>>^}||<Z*|B!Bll,iiiTZnݺw5ؼy3<|eҪU+z쩶Rc…]+W`bbB8pډں9sL.\Hՙ1cǏg׮]ܸqgϞQlY6mJ~(Y6g?*eʔ᯿V6\XYY)}ၥ%=J{1vX*UNsʦM8q=lٲ4k֌޽{cnnqׯgժUDGGcbbB&M߿Z L6mıc?166ZjiӆO?4y+hThРک*T~DEEѵkWF!M2Q_nnnV!B\ɷ~;88K,ajs;~8^^^L8Qw={F߾}YbRުU+6l@ӦM ֭[Zl)))iӆ-[(]կ_-[Ю];ߏjݺZ| ?m۶رcjuO> /}h4hЀe1ƖSa˗/+? !!AvE7UժU `ݺujC7k֌uQV-Ν;W1 3?|XÇ)]4۷/ЅB<}///:DJJ ܸqClϙ5kܿ OlقmfΜy)))ٳG-5za\v-J60/^oƓ'Ox<`ǎjj={T+$$/oRر#Ƈdu'O0}t믿_Rҫzj8y!ONJJR'44͛7s=222HKKʕ+\۷9wmwQҴѨQ#^CU!B!BAuW_};wγǏӯ_?222Ϙ7o_deeq ӧ.]Z;Qg&MvP!'O`ǎZۏ=Z? ))I\SNWV~}sNŖSa?f/?'UTiSug]献T<{,z;YYYZ 2m۶0yd6JTSLŦzN&''k>}t9c#5Fw;lذAߡ! XlGg!"6ÅڰQz...RJիsUTΝ;1bӛBjoAJ3f 5kʕ+,]ݶm׮]VZ 6jժq]9i"##}cu5-[ƭ[غu+j}2uT4hYt)gJ]Շz:tUVsNtSvgΜf͚}(udSB!o`bbbx9nnny. -._Lڵso8)w,9+Բ8 !^ .ٙM:^Çckkˆ 022Rʈ:e,--y:/jsn5j>dԩ|DGG d駟ҵkWt邩iŖSaҥKc?~REE9fauu&3Rmre߈ĉUx6mM͵=ޜ'h-Wwҥ[q~]RbE2dB3d&M+mB!Ezp}Ծ+?ؘz1rH~UV;5j`hh￯6-CСCTY٥KeSd߸q#666>|Qlɓ|0;::l2|||pss~$$$ĤI*Kٙ].55K.affeszFTe9OiB!BMIMM%==;$?; XΜ9'Nd„ ,[LSZp,,,lٲuT GYй36x;[}/زeZVY={R^=_^dT*S«(LܺγsFWUG> ...|ٳ?S1 3+!rsRΝ;@Z^PrU|9$8=z4օB藷7̝;Wߡ!Np133c̙;':/]'Bݽ{u몕޽{@ީoݺQJ O*L?8￙?M^v"YaWY&5k֤{<[i&?~<]veΝ4jԈ8233iԨi/?@Scu}sXNAٳg9{,7n?sΔ(Q"/hǏSN2U!DJhhB!D1Zķb >#ż5rgPex-^ ӧO>}:zRN9ѣӦMcӦMָ]$%%#I\xcb``59Frr2)))UV:u]vѬYֿr M6k׮_^#?~Lr4ڨN~Na||ܺu{r9•+Wv_5E[asI~' |93攕ZYZZZ ͳsFΦlpS{FTPu* 0j#Sz}g m6mAZ%Uym)#ĻƍBUXٳg3~x|N/BpQ>#<</?3IIIjpibbbСFU&Uƣjժ__}vv,/ ˪U9r$ 4PJƍqvv7k&>>~~АL&?Ӆ1b5<2s*|4hЀ#Gpi5;; .$ Cj<'#((CCC ӧi۶F܇8.૯byfByxxرcٵkB!u:ssscѢE,ZHI!Bʕ+pe?C) ˗/'<<\+,,LOoj<ŋ"f͚޽[k_l!?ڵ+&&&ܹ8 iܸK+J*p%rϪ{ʕ+ZRtiڴiÜ9s7oݺu#%%kSAکNBSIU* !B! ___<233:_5j~M㚶lE[a> &3:uDllZs#/_N=z4;vٳgk׎֭[/[,111Yܺ3tQy]L6~ [[[to݄qmO>}鸅?Ei֖4:t[111tԉtFgEixгgOkRcffƪUBXt){a֭G!(6$ÅB!:lܸ~ԬYk׮)'uV{JIJJbDFFR~}f̘Eg\\͛7۬XB)WF700 ++{aee:u… >??? 2e gΜח&MPreRJL:_Uvɓ'Z :::ݻ5C !˗/ѣtooo6lHtt4aaaYccc6,_ nݺf5jSreƎǏg̘1|jmiڴ);vA?;RZ5?εkرc-xyyV?j(-[ѣڒԩS9p|W<LJ޽{H%t钲 $ E[a?>8880p@Gƍiڴ)ϟˋ@1lْNpp0ܹs˗q:ϐ}Jrr2[l{dff晱M>g򓑑ɩScݘz|˄ L03fPB.]zF6 3Æ c޽޽{3glmmz*ӦM#:::|}}_qttߟƍSL=zDll,M*QQQۗYfQfM.]ɓ9r|Ff|)s_wC aŊL4YzB9Z_~|7tЁ%K;$!BdÅB!:;wȑ#ܹsOO|vޝ'Or&OvD %J1bj+W&""Bc1`q}/ĻhԨQ,Y۷pBK:uX`ӧOw8B!q!BK,Y3gҦM,,,022Fʇ&&&J]sss̙CΝX".]M2wBe)(>K)Y$&&&_+رCWR% yy0`4mڔrahh 5j,--5b433SW-UR;w.:tP.W:ubܹZ?LLL011jժtޝѣGOA۵hт%Kri>N>vB!WzY6ӓ bbb‡~ԩSطoFh=yʔ)ԪU SSSxSNz(QcݡC8y$cǎ|̟?Q7vvvQfMfΜ dҴiS܈eС>}WWW숹]|@BDߪ:B׫SN1dV eʔ}޽QFտvc 2ұcG{=LMMSsaZOAmРϟ'00:`ee %KΎ#Fp*]v%66`ee1VVV 43gн{wCKKKCz033[[[Əϙ3g4^26]?###f̘7oiժ˗Ȉ%KRzu:w… 1c%J`޼ylR{{{= e˖Ԕf͚}v VdqfСJؘ?߹|SϙSB9s& wذa]FQD ,--i׮۷ogⷀWhѢqqq 4HiS~}~'\]]4d.]Ĕ)S###{=5kƴiӸz*}]-źؘ5k2qDΟ?i/ϗU-r,BzmeBU 9\A[VGGG9z"gϞѢE LMM9vZcǎmPCUF*0n8.^sUE<{,vjK4h ԬYk8881?111!:::8D+Ox{W_~ݼy___.\l@B׮];;׺R5D^Qeڻr G!DϞ=aÆԫWY!ze:V-B!(j "-- www177ݻ^:u9·[ZZiiiO@^DݺuСCl߾]Y}v*VH.]Ԯ]IOOC$%%aiiΝ;-^}޽9~8'5Ի _&<<Ǐ v%!DA~)#QyhРA5jԠM6zFJ,ѣ7od?yij{!( ǏE`$%%āq-^uί\°aHMMUӹ|2/_f۶m^Zɜ$̙3qF۷/vvv4jHߡ !߉YfJy\\VVV=Ն ʖ- וVVVܼym۶螖/_NBB… 7ۦ|$&&cʗ/vJ!B5kƁ۷/ .Yf(Q7nj*,Xmehhȑ#?>sL! !ٙݻ3vXΝ;CB!7\9rKuBwHxxCB Ν;<ҫW/ʕ+jʕ#%%3bĈ.WЯ_?ի稄,"""oNddlU|ѢEҬY3ƎK͚5ŋ,ZK.ٳ(U6=}ӧӫW/ep=6m6mڅk֬ۛ9s( ͛@VX,Ѵk׎ׯ{Dr000 ++[nQZ5nӦ k֬ӓI&QV-=z' 'OJFà 6ЪU+6m 5ڵk͛756VܼyS#BâEO9s ~u|||prrz !̜9B\/^LzXt)Ǐw8B!^[ni&z]] !r6mwBw!;ws坤Z` y\B9y$e˖e9r;wʹs;w.4noooz#GbquuUdž C ! ̾}uC QVZ5ɉ(Ҹ~%)[,>GXYYm۶_pΝ;ǀԮ,Yq̙3177g3sLnj3ظq#ZciѢ$>>&M ,B!x5M4,Z]vs*WL˖-;v,SP}_6\!D10qDfϞM\CB!޸"pR\ !'44; !B!?ѣPF  DN:2a씍jO}0rH?~9t&&&nݚI&QT)ς΅j0/^̹s(Qڵ믿,9$00ݻws=LLL[nt]˕+ *ժUS=99.]PlYl٢M֭[у*UQU d߾}_TPm2|pJ.qGLJ={`jjJ˖-3f *TPs?mLXXM6RJJyʕ',,baaBDa2XXXʕ+9p˗O?eذaXZZHM8 >̋/U ƍqF0a˗/'11t(]4AAAZs}J*E&M9r$0k,fҤI̘1Ν5>Ç3h >Lҥi߾}̘B!ޔ%K5,/xFE͉yG!D.SLaڵL7oLff&yǺu딟?9-,,۷/AAA8;;+:@֭u=%%CruMbb"ZWNFOKK#**8֯_,. 3ovɓ'8::jHLL wgϞZB]!L2L4I&[XXÕeLKKK<̝;sj-RJիsUTΝ;1bB!&M/.277gwww`*UB!Bwڵkyc˖-:t? 5kѣs4h@hh('N <J:uJYqN<ݻwVZaggݻw\BBB}6M``ZFŠgÆ ;v#G'kyf=,4UmF(\T^-[pQ \dٲeDGGs!LƍҒk2l0>FExxIܜ5k֨V;u~:UTQիWcmmMBB8GaҥDGG5weJ]?;z(uCU#0x`*WLHHR cdB!Blф;!Zٓ3f^xpB7Ԯ][CuVIJJ‚GlٲǶ u @)}sDB!5QQQo^a!#G0qDUg ={޴0sLwNTTݻwŋرWrI ;KA~tP6ѭ[7,X@DDM6}{zzҰaC4i´i3fL1̔)S nnn3NJ8p JIǷo|椤qrrW^Kk}i/^ĉrN>}P|y}$B Z>w\Kҥqwwm۶_?~ك g.拧O2}tzꅕ=z`ڴilڴI!BWK,aɒ%C!Pc``Sܛ_Q"g ___.^HժUO~.8;w$===Ϟ=cΝY:l [VVr=8J(06bM[>888p"""8{,_ѣGӳgOZjӧORJj}2x`ʕgϞÇ"vCIM9羠[A۩E*O!ŃnnnCw$Bwȑ#Yd ۷o[nG!^^^0}tBFmÅdQ}o:#** KKKN,W:uWWWի 6_Qpp0U)ׯ6l 88=F']vZ/֚,իsVVVܼym۶)ZpDٲe~r=##Cc!|aƉ`ҥ8::j\?vcƌ!22RcEnUVڵk={?X)?{F]HMMU2gh6tWeii ...\p{vZ/^l[.l޼YkmU O?ƍ9vhB߉YfJy\\9:wę3gtm Ү|$&&c?~B!ZlIxxB!(R8;;/.LJC2l0B!Ļ("xyyѶm[7o΀ؽ{7}$ =zмysZn͗_~֭[5 iӦj'qV\{{{HNN:?B!.TB>QQQܽ{WaUT .\Hbb"iiiboomڴӓK. /{9rFhӹtӦMSʓT{-ǹz*/^>yZcn޼9իW… \z5k߾=#>> Ο?ϼy46lݺOru|||0 3/mλu놽=?OB# ŻSNT^+VBQL|rYnwHB!kU,3\pm "::@ *ׯ… 4hЀPN8Axx85"&&HN:9u U1ܿ_ڑ#GXt)ammݻwY~}cn:_N*U^z5$$$f6իWg˖-=zTY<~-[Xl:t)S-8z(uCU#B!3Pn]ϟON^ھt憕FFFXZZĚ5kN8q"ΘajjJ7oÇڄ R FFFJǂsv؁%;w7.]`aa;xy Ņ{ccc={6JqѫW/ʔ))L>s+]漠y=N:bjj _|fRk?vXprrbŊbjjFT2TT) ӧ*UȈJ*ѯ_?֬Y@ŋӲeKT " @s*h> sss>Ç)]aE!|ɗ|%mYYY%_%_ ?=Bv55k֐pBQF >)S(ۅBwpaoo_SN)<==iذ!}i4NܳgX[[PfMfΜI݉{yƥZ@alTdee7)S(u6lOOOFȷߜ~ԩSꫯطoF&MZj@AAAjBHHׯ_ɉ^zѫW/~._ doȭFjuB!]dmmwu@`ii7|7|oyt쌳㘘w|cP133S۴+WN##ǽ{PZSLQ6w^cR^9/hy͹ ...CꪨoV^5kc~eʔaҤIL4@)SFBܿx ҮTRzjܹC*Usqqq1B#ۧ)<<\!Vk֬CB! ̙3 -Pb!1gÙ={6 .w8B!kS,3\ܼyƍ7iD[/&|ReP-˝;w{!EF}v}5Ƈ~VwjQWV}ה(QǏdKPPiiij<|^LUG!o^}O>\G/9TP޽{PB|̙3Kr%}#B6o,EU-;=3w6 me)%%%7޽{ݻ/2zA-"ɝCаh@qvvٳgg=={LR !o/N\Bqq$N:ũSpttdjByx",Z,&L@5SCԩS'~'|||QVlYZn|oggG׮]1sLƎl:dҥ,YR ! $.ī MaQ\|ڵkÕ@!X888p1B< >@ƌݻBZ Z*׮]ٳ|Jٳg5ZYYqMmۆcٓ(iժu\ºu9;wN@p>b{\$T9̡LK5r!Zhc5_9J6kv Fq!ILäHJu} ^z_﫫z=_/K.\@bbމ>x󅓓NNN$''k.VZE@@*ܜt077W;?++KUG!Vqɩr &..CCCH.][.=zH/UĉՇLJ$_@^^}ԫWw}@dM&Mؾ};ϟ4hЀ~wwwAկ_,jժIgTm9uS!M& Q>>Sݫފ;!! ֮]B`СjՊ:<8B]ҥ |p!XժU ޞu1x`]$BTق  pqƍ,Ykkk<<}dӦM:L痞...۷xnʌ3$ DEE~,YLQRe7|7|uB!xݻ}]f͚ŠAgggfΜݻwqB!DzCBQ]2zhMFnnB!*\bĈ\p1c[w̘1ٳcǎ1rHcL2E)8;;caa֭[cΝOݙ5k4l۶-C-\]]ٽ{7.]MX&M4J???W;VpȮ]w^?ǁ%|!O͛7 ȑ#ѸqcŋU_9pboo -bժU>}}}}~mF*~Yۜ;w.-iӦ̙38Ο?Ͻ{055s >*mQq(}(nrrrXn֭[ҥKacPT0/_΁קSN1SSS2n_~СCܻw.]0~x1ܽ{7NNN4jH8שS~Ν;UILJq*ޗGye999DEEѮ];Tu7 **~QV'!B!yܡ2& uddd0l0U_ S !1tPMu8B!O֭/u8B!DŭXfMqrrĄjժѪU+/ի TZcccuʕ+ve6m5jժܿ_U^zu 055kjԨ5ހVgOjqwAk&44!CP~}VJ>|8+Wظ9;;3{l^uWNi޼9cƌa޼yz{АX6bcc122R<"Bݻw={6111ܹspy$7o7o&##p56l؀?=8gܹ$%%q=ܹÎ;Xzj*rrr077`͚5?Ç~:۷og^y/ơ,qe֬YDEEq 8l۶ٳgWWX={T0k,ܹSa̙DGGsٷoK,ԩS&5Ezĉr_}yT4c~LסC믿ZB!(L@N#666ՋSo߾ҷuEt!22S2uTDz!ċի̙3w} FTTFl틍 |(Ξ='vvvٓ #~'yqpp`رj;^|,ȑ#:b*uwvv6k֬sj5lkkk֬YCvvv1#.Bj֬رc G!D16lٳ9B!*T1{l4>)#Ewpp̱֩S؉E-N:x{{]l{E%h+wrrɩjժ +V 55Usjj*L0Amc!B~7^J4iO&00L[nܹsl IDATْqѤI\Bpp0IIIDGGӳgOs,--ܜ 6a<ɠ +t Qxܖ&$$ki߼ysUI&B!O?e޽޻wٳgk.7oCLL zb޼yjTDߕMBBAAA]BСCiժDi!/33WWW_*;{,gÇ;wGNDD񄄄h|65a#ՊAAA $%%DNN#F(1*?V㘭- 8L1 !/0`BQI&|rNƍuBQa*e…L>GGGx" .cǎ:ʶmW%|caaȑ#uB]Q GFFiժm۶???O>Q}H+_bcc5&yGXXXarrr>@dzj )))rE?<ޑ8>^fYƲhBuƍcj}+w4V? e43%miDZ2YQA~~B!u:޽{k.pwwG4hЀ,駟رcݝ+ʖ|q]f͚ŠAT39s&֭f͚:PQVZi۶-_~%uoeƍV^MJJ 5biӆdf͚ٳgYr%jm7mڔsҠAVXAHHѪ 6wammM~~>QQQvZFÇU;Kh{| )s2\i@6m4U߿_.B7oN޽%B!*9}}},YB޽ytBQ!*eE>}X~=355XYWT5k2w\>F<^900G'Bϕ+W } !kĉZۺtFYƍU_תU G=Qݣn޼… VS6ǣGxS+q(}P*<W^'hk###ȶJҾ}{_uJJeKeʤ±dnnεk׸vjB6333+WQ1.+FdV1Qr exuE-B*&>KDEEallLHH͚5S333O>0l04ho~BCCPK>|8 OFBQ8::̤IHJJFI!xb2Bf9<ߧA۸y _QzVVVxzzh"N:8*!/]81J*%)Ln*͂:BÆ ܹ37EL:ضڵ"33SP׮]S+q(*h_?eMZ6 &e,ڍp?8ڵk~\\~yōqi}Y禰Ҍ2^m,kۤI4iB!D%suٷowޥy=3fsssYb;vڵkԭ[wwwD܂ &{l޼ѣG%[dffȑ# dƍvߏ?;vz1i$֭[lڒN fܸquңGƏF;k֬! cǎQF }]&OڍѣG>͛7j+fggf:waÆX[[fF5\ɐ ʝԼysƀ{'Of޼yǏ?...^\풔G,SB!^F>*?K,u8B!JҦMpB'V).pqqEסK׫=- !x5lؐSNGUmzq{իW!WDG/T}8|ej__y믿nZu,rR~}RSS9yj'OP*UP({.@">}7xC͂le,6l˗9q:tP9sFn^aƍXYYi .ezYK,c4UMiĄׯ٪:7b"""tB̔* ''www^'OT%[t}<<Hmt"""'$$DKi„ _yj V^ORRIII0brssՈ֖xOXBgWI:(nyh͛9z(?aaaxyy- .r}OrݲBQ<===NŋuBRhҤ ӧOחQF3n! B!űeڵ,[k;we˖i}뭷شiK,ᣏ>iӦܾ}~-[o0gΜ2_m&&&ose~GU;wS* -- 2okk?Cdd$zzzabb­[_O)܇tܙT4i͛7ܹs,_x1YYYڵ^zquU=m.]еkWUk֬!88'ҺukΟ?j֭[@LL gf`bb͛79pׯ'//;;;^rů$c4UMiƤYf\~+Wh$V(W,JOxxB!6mڤ0 \|KKKKڴiCRR3g$##CnXXɴk׎3fмys.^lٲr7NWzW4طotܙ'N0sL\BXXE]իIIIQF̟?6mڐ̬Y8{,+WS휦M2w\4h+ !::Zpa;'** ֮]Jؿ?}W?e%BL 9{,m۶-%.\ 11.]CbllNNN$''k.VZE@@@ov:{F^6椧1e\r!eBg}Fhh(yB$\!ӷo_GjjjGQ C8}4ڱ5jZ+ͷz 8~y:tJ2OW}ٳ'=z04zw֭[)rҿ>}вeK_@sw BKJԔL6mIKK߿׭֭[ŋ5++ynݺ!B!b``@@@xxx5BQYB!EFFsΥ{Ԯ]UҬY3&Nxjhh۷/COO###:woV6ǎ-ӢE &O}vU룧G~~~裏hݺ5:t///TRq(}(JZ ===ӧUF#FFFӡC">s:uDժU133ɉ9s񡯯ϼyptt}}}lmm0a2e XYYQvm066oooMFǓT?7]b``qjҚB!x('vQSNu/]֪$ m+T~}ҊV  /_.͢h߾Zr%7o\1=RM<5jǷ~СC !//OLj׮чLYG;v,;v>;;;|ƍSsuuI&憍 nnn\r&MV澕 :oZ󽩩)ׯ6 ,^{{{ fY[[;?ѮL&' !B!7 W^L4:!ܞ噴'BQZu?V+v-puu-q Æ SM}TGFF<;dȐ M!σy~,8QН;w=ޱcGصkcǎ-ޮ]T +;2AObQ*@QXU sttƆ={yf=?@XX^^^ 8P\m1+!g7ya愆āˣE3={ծ]P.]ʞ={qٓqƕoygggUFdd$)))4n{{{#MOzzjWL2===vݻwf֬Yj;n庵ݻwo/^Lll,GVk766###zUB!B] } !ϋ O(ZB!0zhpwwCCC\Š+xuAOLL *~^z|:NOٻwMwgVMTy&111ЫW/͛W;":}4ƍ#''GUv}N:ũSغu++Vкj.!! ֮]B`СjJzB7n̹s8z(oѣu-,,x"[n¢} 8(BCCEuN>իT;gt1턄^}2biiɅ HLLK.Dr]< '''ٵkV" @pannNzz:YYY#xXZZWb:u퍷wz\TGGGKG͚5>}"溵]V-\\\Xb4jxKQbb"&LаvBd!dΞZn͔)S3gÇ^zI!(Y K!rpp`帹1l0N?}^^^DGGs5]Ftt4ԨQC Qj{}6|}}ٵkFFFL<-[pAO ,--ٱc_~eyg7ߐC.] ..}l2^u zq“ݻw5k KKK9s&wޭHP `?΃HJJbuw'OÇܸq%K`mmrK.ڷoO߾}ݝ^ʃHOO',,qq]{= o8Tx ^ºuǎ;vLu%^!ښדK˖-iժ;r/j,ݼEJÆ Wcaaȑ#uBlݺu[Na!KKEeCZ1cCB!ʥwطo#Ff/B9777,,,%55|i߾= L!>ʬm۶ 6PN۶muVbb"QQQBfTӧ666 6( ěoرc &&&TV;燳3eRhh( 6LU6|p~BCCatB1 .0f̘b3={p1IL2E)8;;caa֭[$߻w;w@@@F?ݻwg֬YZc033ӈm۶ :ľ ruue\tIR&M4J???W;֩S']ve޽?~\@>O:I;߽(jܹ֬sO5j[l!00G'% Ea!K)""BJȈQF1a„T!xZ*ߏ?;vz1i$֭Vpc&88ݻws ֭K=?~RMT^sDD񄄄`hhv΄ R믿#|||Tue|Ѯ];ڪ]6C%$$;w:hSIJ3AAA^ZuN~~>III$%%Sd{i?V [[[?8p~ygffٳ:u*SN-MGGG-988X:ux2-N:x{{]l{E%h+wrrɩjժ +V 55FJbb"&L})x6d'EVB<  I*U ښ+W2vX]$B^UB!B۪U~:m۶eÆ Q^c}( IDAT䈰0i׮9p!!!XZZrŠիWBF XKKKΞ=ʕ+5iڴ)6l`V?cccVZŸqxw㏉T[{ĈjL/S幦`Æ |w8pOڵkoYۿ?mڴhCY#/Y~=oѣG?yбcGGbruuaÆñ`ȑ:L!B<-֭cݺuC!^X<+W:tÃ?[n:!^.N:E֭uOdd$qqqB!BQ ۷>&M㣶BA#Gzw㤌s2`0`xBĉl߾3gp! )K?djՊP(/h骝|M|||"::OOb-HÛo @1c'Ndy{{ň# m+W>qȑ#$$$p!"##WuaРA^ [[[9z(jբSNeF-[ @ !B%<<\vB$""ݐK"##3gK,u8B!D4 ~){}[$OBBAAA]BСCiժ:tx1 !͖-[VB!kkk2k+W:I_91]ҥK899iYׯ_gʔ)8qBS~}HKKS%h_ׯ/_.6΢h߾Zr%qԼysڴiC6m3f gʕ_W_e֮]Khh(_<|~[#1sMɓ'3o<∋ b'Lj׮цLYG!^4d۷sy߿O xqwwPT +++<==Yh^^^ɎB!B!gbb1ƍ]vI!(Kpw^s]f͚ŠAٙ3gn:j֬LB!tՕ^z: !xIbwTRL n%'Jܹ⫯ĉ4nܘwy͛ojIJӱcGصkcǎ-]vV8 ApWbQ\kmޞw1Az긺ěljUUsMOGGGlllسg7oѣ]ע*  ===\\\**O{ ]y^./u:!B'ҥK4iwu8B!Dtp\YEP2226ll/BgC2 X!NAᅵ={mۖm .^֭[UIEQ&`jj @JJ4&旧Ehh(hBӧYz5 8~1AxW0KKK.\@bb"]tQ'&&ڴiÑ#G_5_xL,5jׯgڵ_ѵk2_k*x䄓ڵUVPdEi377'==,RB![&Mm۶%99 w(9r!!!ܹs?&Mp}97|իGY~= cbbRsMӧ-[w(nݚt.^XLRiݺuC!B<[vvv: !ⅳo>VZž}x">~t҅cҷo_]L(w@-iҰcǎtؑ!Cо}"=zHHHH --֊=jժԮ]f͚ѳgO\ئƿ"cE8q+V ::gϒCڵiժzݝf͚Ux˖-ۛ7ojlc$ƆѣG3m4}9B!DeS).ܹG}gzz:apBn @^^QQQ$&&1[[[?]R!xmٲ-[: !Hcǎeǎ;v>@ظqJ<̘1ٳcǎ1rHcL2E}n݈b̞=['Obkk)8;;caa֭[cΝ_ݙ5k233c̘1jem۶eСY+wҥKkҤFYitޝQF?vZ֮]QiӦL4I|Ѭ[(_J3ZN:Oiڵ+{?~(!Bg'""#F: !:"+^FFcƌa._˗_ӧK%yY}voΉ'ذaCu̙͛atÇu$&&߳l2y_Dyyy|O> 2yd]|Ə_am !*… yU-h%BTF2bդШQ#ϟO6mHNNf֬Y={+WY >Qx xBA`` ;wĉ̜9+WV!߿6mh,ۿ$\!x!M2?Pa!KO[sssBCC ѢE ƌCϞ=K<Ȉ/_Ntt4ԪUN:A-Tu?3e˖9ڵkeڴi|s2Pzuaƍ$%%qmԩ C9š{wwwW-j׮Mhh(K.eϞ=ܸqssszɸq'|B.]X~=7nܠZjUuZj.Sk*x:;;SZ5"##U Q4n{{{\]]ݛŋѣڈȈ^zkLi1b6muBQDFF:!PDDM\z[[[RRRdԩTZϳn:+prrbΝTV)TZ-Z`ǎܿ_0%1M6U<+͛7IJJbɒ%lݺѣGcjjsʋT{޽{gȑЩS'LMM}6G!<<EqQmVIEyZQ 7o޸ѲeK]$Bh^)J*?|08|Mڷoό38q"w.S"DIO|oプϩS+k OYG!xagg0BYZZWlmIJL:SFڵJ[8::ʕXPN/^\lmqj:u퍷w5E`ccSl=zx:^+wKO'''-ҜWV-\\\Xb4jT0aB**eAiҤOקgϞٓ? &p9jԨ)Sw^7oκuرq333}]}]&N;v?׺cɲe˘2e B!$t_rB+<1Cm!+Bff&xRMa2e!B!B<ܽ{e˖0j(Gl۶pUHxx89R !vB!//իW133Gжm[UT)«>| ghܸ1f̙Ʋ}vիdž 4- j׮xxxl2'O`vɵkרWzGR(:t?```=3g䭷8̙3|7ܹ5kҼysO^CYc+NY2b۶mZ.mۦW\Ey?eiS(Ǒ#GX~=#F(<~G6n?CVV&&&t҅>nݺ<&?>v֭[k׎yѯ_?18q`رcj1YYYm6z-8qڂ9 믿̙3УGf͚Ev4k^gQ2< Vуm۶i#BTzϪÇ+\Gy/SlyT9S:vȡC裏8w_~Z”)Sfܸqx{{ӴiS9Rl=9oҥKԩzzz$&&2e8/|A}1q-\\\TѢE >3>c}ٳxz,ҥKٹs'g̘ /C;wc˖-93gP^w)i< [hmڴaƍ 6L!O(<<\QJaeew}R899)=W=zTѯ_?oUիJ?+rssΝS5J}kkkŋ1 0@W9rDѷo_bԩSVVV[ZoO?-q̄xޕB!B(\\\^!xQ"B<^*s\E߾}K,Q(}! !3QY ???Δ)S=tEj>S;C8СC @ѬY3UYZ"++>3c ޽Çj>|޽Cݻw+ZPܼySǏ+eVPy_~6GP(k4/8Cit^A999 @ahhXlM6UZ9sFkERW_}=z8'??_acc/,a$ݸqC}QѮ]; _8E?UBqD?l#++ÇcjLYFKelDɾ%ISHe~-R|-eK"H0C:Ϸ9i!u]:s?ysJ:dһwo.\v899ikiiIvv6W\Q=za!D]hh(Δ) L2̜9}i=ҤImm۶ 55UƆ/XӦM&%%b˩$^?~Wvs1~aePO<ɷߟIvv |rAسg3g8\rJTZjUbSR iiiZϞ=+{qB ׯ_!!ZZELLֲFFF_PV-ʖ-KZ/U~ DժUקcǎ̞=[3fԔe˒vlٲetܙrQV-'%2aDDF mB!B!BZa'$$`iiI߾}ʷoVVҒ"SUx]?>cfڴiX[[ӱcGF sJBIg`` ӧOg@dBΎ:еkWFݻ5rJlmmСg͚5j2--[ҦMjժ]6lݺ,BQx hڴ)/^ƍ?ܜ-[PlY.]?)vBjQunvUlkU\@"ǏgСaffƨQعszƖSI~u֥iӦDDD(s~};ֹ( 3/ÇA$))={0{l111 ;;[Pm&ۦMtAk{Jݻw;O>ڮܹs/WY!Br@^V3X"...N氶:ϱ~6NʕqttˋLMMHII!..+B!B!BQ4iBƍILL$22]ĉܸqkqT7|Ñ#G4 Z3g8s ̙3G^9uVb۶mdgg@Æ iѢEi&DZ ???ӧO9{,gϞÇ 2 &L,qdzj*]sڿ?tQXǎ 8N!DqZE ~6l 00###VFW077'&&sѮ];̤\-Q-&k###sSU9ȑ#Z*?_닯/ 4ō-~*666Obgg_233nQf_U:l۶ WWW5fQ9+1wްaCbccIHH3)C3g`aax5S(WY!ga IDATBW6M3bK@@D C-B!ͳ}v Pa!/K;F^3p@~GvޝoŮ]{*9͍~Zj1qD:uDժUٹs'~~~̜9 6G#fϞ͠Ah5k۷obŊųsNV\%O>%$$mۦ$\@fpuuA$''Ntt4 0EΟqǎq1ڎ;& B \2ܻw/yILLdʔ)O&M#--4F.]a:%\\p6mп ݻ1668G[jϹz*aaaDFFɅ |2SN%88c+뗓*b޽ٱw^e_X驵=~D]MAeP~!ԫW5jиqc6lEyOιwիW8ZDz"66B%\ѳgOVŞW.^gQ4'Nի-Ю];J; ! " /IŊ;w.SLaذabŊW2^!B!^wO>/(0Bi[[{f;v۷okEݻ=z *Я_W/22VZʱ:u0yd*UĚ5kXf k׮-h5p-}lٲJ1:S,E&gUT@RRݺucРA 4H_hh(ԩS3w\ @HHHIϟnݺիG!īܜX~7y?f?`kkg G||<:u*ڃf]iӦ)e׮]-oР'O$::>}hs _I233cԨQ5 _+K:~uܙ*Uo>ٿ?+WO>y)L2deežgX~=Ϸ djnܸ|o0({YfDFFrI5w˱cDzd<==3f ͚5768)S GɓC=** ?q*?Yb7o.0oK; ! o٢Dn''',Y’%K4iB!B lyC<ޚ(ڂ㬬,<==CtڕQF{nOŊׯϞ=cϞ=Z믿8+,, &Э[7ڷoϧ~ʒ%KHOO9>;w?гgO:vȬYFatRĸl2>===%1W͛888kXd eʔaƌJ{޽Xx1YYYjdeed ^zhرF[IV/raeeō7ؼy3nݢGuUZ55y{{f?ܜO?4߾ߋTl2G8nQ9K.DvvrNnL<ǏӧO~!##'YcҥmϞ=cѢET RWWYcNǛB QZQ؄B![bBvUV<)gϞٳ<|!Cjȑ#v k׮XuMnJjj*?N񥥥1zhRRRI EƌCRRZ7o&::ooo*UvβeHKKHpXx1;wToذSSSoNBB|G{RL{xtY|w,\2cƌ)}f3220ar|YoooYjIOO׺xcǎDGGsBB*g_%]Gִoߞp8}4k֬ߟI&)$hKIX.Ϊ?B.'''V^ͱcӧ4oޜǏuV|}})W9^͛W'f|||]6SLȈ(kFviӦ Yf|7333>}˗ٷoK.̙3Gm'rJ>s%\]] RJL}'OU]ի4nܘ&Me\\\߿?zzz={s|6m"%% rYeAR^rWPɹϏ$LMM?>7&!!ٳgs%|}}qrrR;~x{{k,Jg˖-ԭ[???<==aÆرڵkqF֯_ѣGtܹis[a0OBB͚5Օ ;+;;v ƍk\Gv1I*U`kk- qF-[MLLHNNfϞ=zիsM߿OՎݿ_#ajj͛4haaakNϚ5khѢ\{ *‚5k0vX.\… uz)/^Be2g͛{=AAA700 u;HLLZ㸩)? (_^틞 KEIYf~.]D.]Ԏ_q{~AAlڴ]3ƍcڵgf֭\x33|U۶mwر;vѣ)[xݻ3grJ|}}[ٲe2e -ʷI`` Ǐ|vQB֭[yA^ɿ('NP !Dqk׮woIB!BFrtt$ B!^͛7+o rkٽRJݻծk.s=Jvv6۷OY֞Sxx84mVZw1eÇpssy|Ǹ2yd:p1tP;`aa<ӓ'O,@6lׯW@Clٲ<{v߅PݩS\\\‚ +w/nnn8;;caa{gӦMXZZ <_իW 5͛$''k$V$''+}BZlllcѢErM*UD۶moRB1zh,,,Xp!Ǐ'==3d[ 5kٳgcΝ>}۷oSlY޽;&M⣏>:fe…?PfMpqqњp[UT,Z \ӧOW}3gΤf͚/,¾~y111e˖ҴiS+رc̛7>|H˖-={6+0"r;аaC0aN~W|r100m۶L:~aaa)y(N: QF̛7FQ)QE__˗3i$8x .\ÇѨQ#=z4|AӨQ#ƌC\\fff 8gggjԨLJ''O]vOQYߊ+ؼysi!xXa!^IB!B!B֙:u*#**(֮]ѣqtt W^,]CJ*UHMM%,, CCCz}6ӦM#11Qc̼vڵkJbJ˖-=O[rIn)))dm׾~9dr.fιA+V88TV-]ƍ7_><|Pmwa_3X.]|}]T}x]1www<<%I%ΎrHRR>]taĈJ?CCCٰa֭[T\VZ1a͕3f`ܼy z?LDDÈ Ktk!BUJx.\P*aZnCB!(Of̰/ !A!BΟ?sNGeǓ}vvvtܹ."ԢeQ{PueȐ!ׯH. DEEо}{B!^*U`kk- qF-[pi~TV @Yp SORRtQiW^u?$..v)qqq@S߾} ! ՎgeeIvv6S- s߅ٳgOsWzun޼^ڱ+}xݩ~J*L>ӧkkkʕ+舗)))ϫ1~x;B!hڵkGxx8,Yva``+Wذa?ƍ+HB!x1J}Jڵܹ3SL}oH6nHdd$<{ZjѮ];FUջ_&z,ߋ c5֒Gm\tbddDÆ bرԫWD_pvv8U!JZ'\K !^S7ofݥB!*..T.} < DK/හ13f $$ė>nbJۗ_~ɖ-[$,\rO.]1bsuFչst]Ϸ~Kff&<{ ʕ+WX~=۶m)B__׳rJx!| nnn߿_֭[Gxx8wܡzٓ*Uuf̘իy&r zzzoߞҶmbwaooo6lÇu+WUVL0ssso޽矉`j׉++f! [ɉ%K0iҤ<B!DѼ{,_TcŸmu-Fɾ}4]vk׮clllزeKx<~oOOOԎݻwhYhSN]kʹB^X…5SIB!۷ob "##y 4`ʎ9pEhh(5jԠo߾;}}}@}X1110|}ztttˋLMMHII!..SR%GzӪ9::Xa!B!Dر#IIIԩSӧӷo_>ʖ-˕+Wؾ};/&$$[[[
IDATX!B!KkרS?~׫UP'!!f͚yfN8A`` -Z ::`@}ؘ?I1{RѹEFFb ?7u;vn~~~$%%ajjܷuҥKjT֭Ν;9vGTM9OAs_|mڴw8peW_zLLL裏xqqqL2;vǏ@۶mTǎqqT}BX"s%887np ;w.*T(B!BVrr2ƍ LLL2d Z-&&{{{j֬> 4Ņ`߾}ԬY;w;wf_~8~9F)2rH.^}у+RZ5lmmzŋ0a;кuk͛ǽ{SSׯ0?~ڵ+իW\rԨQ~^۶mYf3f̘~_CCCBCCiٲenݺRbŊ$%%I&/_5k|r{߳B[S;oȑ#L@1ZhѣYn^^^,X@O?̪UW׮]bO_ѣZߓ'OxbygJݺu#00f͚,^/nl9뗗6kk׮~~~XXXp̙jܸ1;vʊ0֭[ǬYJ/^@&M u .\~ȡCM4i®]ӓٳgjLW=+xJ'vvvtЁ]2j(&Yr%tЁf222>9wT0|pd:t(vҸΓ'O7o;wG̙3۷o8vίUXt)}|,[LcaK.DΝٳ' .T+C Fvv6jpdmmMVV7nÇnR;wǬ[NCJFl6U!B!ylyC[xC<^Cծ'Oz|رy>_~%ݛ ?x ֍---ʕ+Jja!D]hh(>)S3go>O4Im۶>k! K9ִiS%[N%?$;;[-BE9TuilǷ~ Vu!/EGkTj}^kFgϞ$[|tY!ۭ*\gժUOrYΞ=Ç2dL07&>>UV廓jL׮]sάXBYӢEسg?&$$8xtƌCRRvM6oLtt4TTI+ /?~̎; }Ozz:;vԈcǎDGGseQB!Bi|2 .d|$&&j1{憳3ܻw6mڄ%?fggsÙ׏{2vXƍGϞ=^:o/}ТE ,XyYݻGعu ___ݙ?>M4!!!A.]obuT9͋.s1cJJJ ׯgƌʱSϞ=Yd ;vP.:uIJeزerMFqM5+T;X5jHB!B!x 0@mWo!%gZ7.EZXFTڌ7?ssslBٲeՎ6RU(H*Uwiii^0;^ՂTymfnnVre@ +F?~xgϞߟO?}}-xtAtt4'NP6/)VۺL6mXEJ*Bݻ'hmWϹst+W=+x ;wӧm۔Dh֬4hЀd݉&88Tȹ?{[4EFFb ڴiCbb"fع)ϧq$$$0{l.]Fvkݺu;w..^^^x{{sa%By>xy/B*۾};˗/0Tm߾CB y]޾B7ӧO%ᢄ6l@`` FFFQZ5><tXannNLL Ν]v:VIAU FFF<|P *4.|Xk>|xylVWWW&O̡C4R:duϟ?<_[z!B!ěbŊ_UVqQ[qٲe|DEEallL>};vZy>>>[pܹCٳ'_}U*7Ga4/IAZj_|mXt)V ?Oh$Itܙ[ҽ{w޽{?ՎEDD`hh!oݻwb![/(B!SreRSSw^I$&&2eI&yƃtK.İ~..\@6m߿?7ݻ1668GU@U>s>s^JXXDFFr._ԩS .؊b~!ԫW5jиqc6ly{|w (heeEll,JP%S񒸟Y!핬p1uT͛GTTQQQ]ѣG訖vUlmm^rRjƍܸqCI\&%%E[՞hk׮;v^c.ֲeK_qN U;r=u޽ //'UB!B3gZۍ7͝ZTә>}z״:]v7"/UV.*/VZggg^^UsW1>i^eNtooz}] ;;;3f0c ʕ+舗)))VTR !ěLf8B6qttѱB!Kry5jʍHTT|$ !oѷo_{1&==~!u|_\\tԩk<˗vZMum_Nv"55===1O}eXYYi }Ϙ13g`ggǬY{契pG}Dݺu?h۶-VVV<7gvK,L2j?ݛ'Oxbfeed JQ^=iӦj:vѿ$c++Æ 8l2Gidt颶333 yo8SQܜɓ'Ӈݻw+vfddd0iҤ<+w,]T#ٳg窪u*zzzdgg癐ӫBJ&+R xyyLj#HMMU={񈎎w vWNy`N{-,]zܿ_|UB!BlllGm{{{bbbVƍ+śbŊ̝;`gpp0sUR)o۷+}vbB!x9rѣG̞=AabbB:uŏ=zQ !Dsrrjժ;v>}Ǐ9|0Ǐgذa+Wwww`V^M+pC'b``ߤs! ȑ#Y~=5j`߾}4k֌իWDff&=">>~ KKKn߾ͬYԪ L8###> dddTTɓ'{K ÇdffTlY$c+WfffgϞ0|p%Ν;ZϏdȐ!? N:E>}̌1cƼ{\x1z"%%;2j(<ȝ;w8p#GҩS'nܸAnXtis̙3|DFFhT044`Νdff_*\g}FJJ ...`aa_Wu޽;쌅ߟM6aii',W*~׏{2vXƍGϞ=^:o/}h_`?ٳ?X{Vh;nݺ닻;ϧI&$$$(Y]tyaبQ#n޼IrrFbErrG!B!TΘo>\BFF.:t`رԪUCo֭[q~ҤIjժBWG@@ABwRZ!*˥QAnRE[l''RN!Ԕ͛73h h׮F5k֨6k k֬aر,\PYҡC\\\ի,ٻOO(a&x=ml9yԔ%jene&Xfzg[)!["v-ܔPt ϑ|>Ŭ>k̠2K-!"""""rhڴ)F/Kkl>㏼$''SPP@׮]>}e\|l¡Ct۷fV k͉#] Zlɣ>ʂ pttƍlٲrZhAn?~<~~~V}sZZ-[xbz͛LZU^Ѽ;??xluc;b0gڴiZ,*"Ґ;t^}Uɉx%K0zhW1ѣWr}Ȓ%Kl.r۷/'Od޽f͚C=h IDAThsqW_zj>3~'nFMhh({&&"))_;C~ϊȝn -y$$$ @Ν1bAAAvDGG;pa.^H֭bܹtvlڴ\-??ɓ\r6m????FYfk׮_$%%{3gP7sqq!&&z#Gp%xG5k?|njúuHJJbV}$%%\ {|2AAAϖ,VX7n<3őJtt4NNNV}ϙ3<qaaalܸ۷[_v'OrI^J```]*[yr .UMjj*TDvӳgO*?O1bDo~ܲeKf͚ŬY5f>}xw+ݾ*oӦ DDD%~U{VM6iӦĉvxn5cmR/Tۮ]'ج+k =+"w/suueѢE,Zv>>>619rdeiӦ ֭ضNڴiCHH!!!WV<[h4ENN:u ''t̙SӧOӫW/SloUv%!!ʤIe\l۶>}/Ӿ}{^u>C-۷o';;N:j*zͩSX|9YYYlݺyYݥKù{"::Ç[.v 0 \vΝ; }GttM@kke `nd%\HHDǎԩSH /T.8ĉlܸ%Kxb6l@zz`0Xׅcǎd<==qrr",,4>CKÇF~hѢgҥ:tT!!!xzzҲeK+W,]ƒHKKc޽ԩUNʼm9}4{BɭvjFDDDDD1j;\Hrtt$<<޲޽{Y~=Zst""""""UG\\Fѣ8EQQ˗/' wwwYlvѱ^)*ܥ.''[8Ъu򳫫+7nܰ-X+WBJJ o&J0'8TUem˗pqq)Ug.3ip! b޼yYeDDDDDDaH=3  ZLL /^䩧M2{͛gDDDDnN{&Mjt jѢE0tP9G}_o;?>&Lpv0L1KJJJds6mZ\VUDDDDD!SE55?FF!C0d{!""" L~~>[lСC\t3{l-Zusʓ$11s=Gkec۶m]R jҤ &WZ>deejWyFnn.yyyYYڈHf2ݔN?id xgx%..3gRXXX۷b\ ʕ+:NM̙3T>`ڵΝ˶m8<׮]… DGG`8pBKMaa!yeذaY\y0 <䓖vF "" ~7222Xz5#FǏ`0SXXH=ٳ'`{wsUgvسgEEEdggYyW^={T2sH """"""(ѤI:tС>_r}vԩ?~(<<}X|9ϲeصk^h4b4؉dw"""RV….ktl` >|ŋ4.nܸ-[8x .\Et֍X_ܚgk.[i߾=Fb޼y899Ye/^LϞ=.n3??xL,m:v` >>iӦRϊHök.&NhHDD'㏼$''SPP@׮]>}:cǎjϖ-[8t.]}<̞=gggK;x֮]KFF-[Gej^:͛7yCn[ͻSDDKLظq#۷o>+WK/Yխ]|pou .UMjj*d„ Hhw""R\\\j a4ҥ |̘1={Wq\| ~gKYVV+V7y-rss#55hM̙C^^|ܸq0f5*&E:ED4w޽}+Ǐ Ν; Ǵ4{P[o@RRR>y饗399޽{:\fn#""""""""""/00&MСT,33}|\׶m?L>}ؽ{79O>$іv۷o';;N:ljÃ,nZ.]{n Ö4yfm[:EDmu*<-- ''' %;;QF@@@@|L&>Μ9×_~ ySPnO~U׮]ڈHJHHw"!C;͜`q|\׎;%K ,,̲ 9Q",,~п.]ʳ>ˡC7o9!!!>ʕ+4:L[*;o[SDDK%\Tł Xr%)))ohUV?pBRu&T?\|Ru2ss>}^z٬KHH %%C2iҤ MDD*p _{5^{5UVj*R:ԦYNN{hͺuf7nXj^Ӭ20mmѺN/pqņBECȑ#|G|׼ر3a„2yoܹ3ӟ֭X+UiriӦeږ[DDDDDDDDDnhAHb4H /pQ_N8ƍٹs'&ɓ'ӳgO `HED!Û(nբErǩzMaL&˘%%%k2oR___ؾ};AAA\rkז{,XqYoU Ru2s}L&:tTuQEEE,_ߟe˖QTTTQHYزe }%-- 6EZZKsYYY ==ݪݽZWwfỶW^ٚ[emuH}i Ǐ`0SXXH=ٳ'`;ܹs8~8%%%|,[R~ʕrǶէygϖjo.ΖV""""""""""""""""w"`wu&&&/SOYʦLŋcd""rL [ðaXf ka0x'-F@DDodddzjFQkcڵk={(**";;j[:EDĞdEPP9|0Q3,+VۛSrη~[ض4n:*""""""""""""""""R?nܸ͛dȑ<ٳTB6l؀/> ƍ7ޠ愑H󉏏gtҦcǎ ϯÙHU4~777222IHH`֬YvAAAxzzCpp0C%88IpppǮzͲq[#F0i$ڶm[yk]ؓ.fߟ+V?֭3f`ʕv/SN4kvɒ%舃?Wfܹܸl9fHJJ*>)) gggF]ADDDDDDDDDDn_O8\Xh-q\DDDDظq#ΝڵkrI^~ebcc-JJJ;w.۶m\v .͂ qF8pBKy{{SXXk}~""R=&Xz\܈ZhA޽yW;v 111L4:ЬY3:t)Sغu+U&5˲pBhӦ x{{|j[:EDĞ;[n|||\\\ޜta֭[c4"''N:Czz:sɩ9H /p2oƩi,'N`ƍܹɓٳ' C"""""޽ 6`0v'22;w;8u}eҥt֍gAjj*{Ϗ4KݻT d&LPٿO?.qxxxfmڴ!$$rە],k GGGBCC }eu""bO 6ᢡ ?&66r;SNst""""""""""Rߎ=jqn㴭E^ @QQ˗/' www#.[]vXqHWl5ƒͨQ ]bb"xxxp}ϯq̻uҥT]׮]ڈHi]%\T#&Ld2OAAAM4iӦe6"""R3Z)""uM Ud41CDDDDDDDDDDgylKYnn.qqqSꫯo>ٿ?رWWZ"%%%̝;SNY.\@tt4lܸMʉ'xcǎIXtU8@aa!ޥ꼽IMMk"""""ꊯ/:u>m۶vZ5;gϞe߾}Wy 777rssͪ.//FDDn/ډҺNKSEDDDDDDDDDD۷MNDEEAVV[nR7=--܏;9~8xxxpyvQTdǎ:u}_|ABB 55{ʕ+z*+Vƍ\zp\]]ˌ%99޽{\fn#""""bOǏ`0SXXH=ٳ'-Z{衇wo~:.]+sZښw8wW^={T 2siؔp!""""""""""%`uW~aSEߟKpСZ-44oooZhA~ $&&AϞ=i֬w߿vF+ySO;ӧҥK]Z "##9r$>Znƌtڕ Nʐ!C3f .Zb…ڵߟq0l0233K`.1bDPDDDDDDj[s{ """"""""""Rrrr߿U8|7tP ~q*bˮ,/ɓw}wc\|}[mDDDDD̪{[my$$$ @Ν1b%ٙhy>ŋiݺ5^^^̝;ݻ[.^M6KII cƌaݺu$%%1}tpvvf0c:K0o(""""""""""Rn]e͢* nܸQfd|m^8UY͛[niOdLr j<9v[s3o""""P|3WWW-ZĢEmハUY֭1DEECNә3gNNN՟T[\\qqqCDDDn#p1|pj[j'==!CXpww5iիWqvvJQ K'{kusYg5Dzlڴ,éSظqc %//777۵k˗ݝ}Y.f̘aվO>L899K/ѼysÙ2e /";wf,Æ ѣdffe5Fff&`"""""r4hc͚5̟?5ԟg0Dh4; 'pa"r8%dHIKK+Ņz-9¥KpssGa֬YZ.\MHQQ˗[xb6mDnn.%%%Vuk׮_$%%{3gPTٙhy>ŋiݺ5^^^̝;ݻɏ?ʕ+Ã^|E"##yWl2f֭[GRRӧO?)) gggF]EDDDUuh4j1Hb4w"r3,"w:KiHڴiCHH!!!stt$44P[~SX]+rι+-bѢEeyWxWJ?<ҺukF#QQQЩS'rrrHOOgΜ9899HC w_|Νw"@yzz2d{!""ULll%%66wwwNjv"7]ߋL vvizNHH %%C2iҤ MDDDDDg0DҖ""GGGy6m{ejNDno9%\ /ѣGc8q7sNL&'OgϞ 0K .DĖ@{ ""4h ͛ǚ5k?>^^^vJ }~=^DDDLkEDDj.ѣ n좢"/_N@@l2vڅc})"""""""""r[ vшhw""""bG ADDDAڢ ŋyꩧ,eSL#&&y1:i Ν;g0DN<==2dۄ>?4l';1 @㽱TMNy7HNN]2}tƎk.??-[p!.]Dyᇙ={6Ζv x֮]KFF-[Ge7ne<ȅ hѢݺucYuiiilŋٳ'7o."VyE.k|˴oߞ_?hKΦSNZ޽{s)/_NVV[n-EV.]{!**h>lIؽ{76l`0p5Odd$;w$00j7 [[w}DGG[2Nkse @޽Kk.KNNŔԻ@c0DDDDD ADDW5;vԩSۗKҭ[7Ξ=KDDݻ???E6رc,YOOO,IftR}Y:T*"$$g`` \rRDAAdgg3j(tSNrT~޶>}=V]vj#"""""""""R_&NhDn['N@DDD.z]DDnwĄmXTvabb"xxx9<<???ߏ_hHK… 8<z*]NN{hͺuf7nX,Xʕ+III!%%7|`F#ZT拗m|2...e6"""""""w\:vh0DDxc4f]sx9|}}mU8Z#(""RuM@]iҤIο9V-Z(w>VXA)..7`ر|-L&璒R5ܦMK-e5}^EDDDDDcǎ1k,z-[s;zӤI:7߰xb D6mh޼9ڵcȐ!,[xmn u72o0?? bŊ""tQg_cwfmQգb9RPWs4P57zT^pQs=&++>}Ãt b)OOOݽZ㻺닯/N>c۶m] &T&M`2z*΀l777rssͪμ8r;ŋ1c|I~~>c{YvI)..^`ͥn/Jjj** , ""& 55{Z>]~_~]vB6mHa4mgҤIAg9DDDDDʬ9twwٳ۷ZkFPDD% F||S7okUqq1=GEL:шڵʕ+|Wfk>ZM(KEw/~:?# oeժUYԞ'2qD{!"ReP7ʺ&7߉\DDDDDʮ9|衇غu+aaaУG~vヒ``̀ԖB5O?4nnnddd?ÇY,킂$''`Jpp0ϟӓ*@dd$#G$,, ///KvϸqsԨQ[#F0i$ڶm[y{ذadff\V駟&;;?O^O>8::@^Xli۶-G|-[p!G[n|l۶1cpwӼys.}Qbbb/ 11/5kܹ݀?}v{HDDDD3fеkW222:u*C a̘1jՊ ZjHh nnnニ -Zw޼꫌;Ņ&MDh֬:t`ʔ)lݺZb ?ݺucƌ\ntԉf͚QRRRn .$ 6m7˗/m=fHJJ*oRRΌ=χHm8{,gӓ-[N`` NپI&JKKcĉ}ݖrXKJJO>f6k١.UDNpppSN̘13gΔ;//~GGGڵk/6;s sΥ{lْm2h V\/bV~| [lٙDXn߃ l~zo~bbbӧ-Zfɥp{P}5tPrss*""ӧ0zh,YBVVVƓEXhN鳃~vb^uF͛7}<9rwI߾}qpps<3u>|z]DDDDrHKK1+ٙhF#4k WWWF֭[vAZbXXn/o`0~K?`2 ~ێIc/DDDDh4Fco矛\]]M@UV?9|8::ZߺuYf68TPP`i;{l`Z|y[\\lJJJ2Vkrtt9f֭Me+%%ԪUR988[jrqq)ڵ)77bUU_%Kŋ+͙3.]j3^{f -[4۷T{[Gys׳my-qU(^g{ "wѢEA; ӠA=Fi:{lW_Fa:)''4|pӉ'e;d2UzAJϫ1v\b*snM4\pkofk=TߍʖLEקiH4DjR=AAAtؑXKYll,L:Վȝ… 9s EEE?~3gRRRh… VLRGDDwޱw1g_ܹs())?{8qW_}رc<C˖->|8\z)?~|VwGil7g__ɓ'駟ڬ_t)C%%%b˯ԩS駟cv{,zV_̙3e *QU=i=jʘFjj*}իVDu˗;l2||sÝ١*"##ꫯ9vƒ>dW^) _SNORTTĔ)S,'j{LkEDD5c}Ewת!5f6lϛ f?aﰤ""""bV; EDDSXX [ovqSMiɒ%Vu!!!&4yR}嗥vhݺ 0;fy.]jL=Vuׯ_7=C6ܹsKy!`j۶UnJiLͪm._l\tqTXXX|^z SV]}7WcԨQ Pzt1j!|G|;qӠAL>>>uǦML6㏖ .lڴiSSCR}v>;Rul.]LͿy9s4]vͪƍGyVZU'sPu۪|&04$}}ژ;jH5DjÅ2h ͛ǚ5kXf a?gY?sLϟ?T<+W;w رcd2Skݬ:96mT\]]ϷY|rn9׳29r$o6jժ}TEm5`૯fܹB6{tTO@$S؀A-喱-ڂH5&`"Ap!"-T1 "D.-r  x K 1L$_kegLfw,]KO=/_"cܺuK+VP\\zGyD=6lN6\~[կԳgO=Zx^ZVM6nI%;~5kVhhu2LZfM}7)w'Ofs>I;3gΔS~HrociF銈p$&>PW/^+W8&iHb IDAT„ 2I:sRSSe˖9&/[LVrԻq>Ç@{U3Fyyyg*==]JMMUPPPZ'OJZlYݽ~ ջw21[ںu V@E;yc?eggk:xkW\}I?'=ZiU9ǚ"_jFCA.^ݻW>PFFqFhѢLݽc}’'􋋋^\ބ`IRAA< ))Iׯw3iʕ2dz!ՍQQQ4999VZ,?=Q+>>>{OGU\\nܸQ㺫SKڵӞ={4|IիuuIڿ222ԵkWeggkӦM}ׯ_/IZtݫ]vW_$]VxZ׫VR^^"""{*%%E:qV\YXGk&Iիc'1s-$iϞ=|L,2{;ycO]V۷Www}WqCy充*XC@ձw^-V͛7{QKիCU؆'_e˖JHHp']t>5c_/t)jю _}LR+U0`$)##ãs̔$p~>͛7,OHH>#*;;[gϮtWw~GVs a2~*+geeI,X(]v;w$i˖-;X,eddСCeZ+]}vI̙3չsgK.1c$i۶meN]={jԨQ:rBBB4f̘*8~$M6ej۶S;ycOgQ^^x͞=[)))ڸqJDUα&cͣ_gyF7obbbʭ۾}{IRnn[~g$Iwt'|˗/ǧL.ٿS{N))):~6o,IڱcGVoرӊ+~O}4i$I[oUnLY՝x+ڬ`owiIRLL„XI҉'uLFi߾}zw4bP-??_R[noFc- 4Hiii R^/JaRvI2{;ycO뒤+Vѣ?F'ܺurYnSNPs!ukÇCw<1h 믿y(#F'piӔ8͚56}Q}̙3߿~rcٲeFcǎH999z'{nw}eaU\\r];BBB[oI2u+Iz{n]~]_}N˗{^Ug'ib1s-Zl)ItRe:@u1v3t{ͷ~7o}YIpwޭx?~\EEE:p })22Rcƌs:p[=چ ww[5Y,[ ;lr_?֤I$?˗/w]nݒ?%|||\իڵke:|ﯰ ???ۜ9s\צMl5r_Fl|I}\^K.|rc8XÕݻW?=CjҤաC+:pڴiSkywѱcꫯd2)$$D~~~j޼zYf}]5jԨ8 ;vd2_ڵo~>|X?OOKKӠAt]w_{oǯ_k…NL&٣hBѣ?jܸqUm*''G ѣq}Gjܸ^~eGDI… #W^9s${z-Z$驧r|=Z={ѣ7(22̓kUxעO>2W;TO};cܸqյkW5jH!!!/??fϞ-IZb㕑zH{ /СCN{u"_f٪st-̔$UkP||$b| $I=\blv*L&$jve}ھ}Ν;Kݻwׄ ԡC6mRFF$I?կ_?%&&*88XuV:{7oO?Tt%vء .e˖/~q)$$c8q7FwEAAx uQqS[lQPP13yk @$>>^mP233ݿuIBJ@]hAHHNSVzTXg8p`f͚i>}zB OcܻwufRRRIR~~<dzԊ=zƍF6l"##@-}o߾5 h`?Iűb(,,L Gɓ'kF9_ W&M4w\mڴIgΜљ3gi&͝;W76:<rU ĉh"IҤIԽ{w .@fٌH22F6_6,(XP2335l0Pdff* 0x w"@C WqㆆntKmذA6l0: ^.`8"btKl6CE? .[dvmt ҷo_M<0x1bTɓշo_è1F~ؿ233233~233*ӧF1~=p fY0ԱxCPOX,fCD~'\‚ Rʜ;wNV׿U_bcc-[W8~:vumgddh߾}={ju~p׮]ڰarssue?Էood2IVk]P?T+IO~SNM^yܹӐɕ}-[Lk׮fӈ#]yԆ?3g>3^vҮ]4`͛7O5ڶ!?TLyt;w]ٳgkС Sxx4k,]vvԴiSM2E6muV͟?_~mjz C?XpJ&j*IRrrL&֬Y#IZtL&aiii:wyGȑ#u9!F:xl٢\R n cݺuK3gΔ$-[qw^Iq>Ç@ƿxb]riRM+~ ջw2zlmݺUC (&~H&LБ#GuϜ9Tjٲe-ч$=#ӷo_-YD(6o,veԆ^ 77WԩS'kۇ~롇k.׿$:ZJyyyPjjݫĉZreciFׯמ={4zhIׯ_/IZtݫ]vW_$]VeVk;϶kN{kk{Ϟ=|qe:wUIZz9N:)==]WFFvlmڴIRw}'I 0{Wtܹ2vޭ%Kh޽JMMUxx^¶K3*?`&~򓟸|]v-Io~Hi̙ZOfΜΝ;+ @]tь3$I۶m+sӧ+22R5rmˎ;Z,eddСCeZ=+Z;oW?.ڶmT0LN?ۯfeeI,X(]v;w$i˖-TTT$I6%ݻԹsgKNv $\}}bЛo)ɤ/^{7H:vXa|IR.]ʻutڷo=$$Dt-Gٔ)SԨQ#۷OFT]~}$I-ٳguu2L׿I҂ b7ސ$㶟~iL&[N%mO>]1[h!Iڰa]<-\;JN:U2{ꊻ꣏>*I9s;7o… zd24aG]W`.]_J;vߪXgϞի5n8]vM R׮]+77W:p,X Iz+l4#iW0aSVVrrrO:m7nDm۶MOѣEFF)sGbb,X Խ{w-Zŋ0m޼c_ׯ׻ᆱw}WԻw2=oWmG;wTnnSaU&PIIIڱcrrrTqzgΜ?_ŋ>ٳgVRRSC=#FTvs6*?!?0~.^NB˖-*88Xz^v VZZP)44T#Gʕ+qqqq3gx*00P۷WRR͛7m4EDDOEEE_СCլY3w.'{{ޮ~?q?s5mT zP*rjӦM*٬0)$$Dʕ+^^ jׯ7o.___hB</^zK5rŋշo_+44T>VXJ.|F`jf/IX,._[bRRRaEDDHkرGoW|||dXd6]nL&$h! D}py@C.@KLLT֭&X,)!!@]!./x+wi FhҤΝ^zIF$mڴIK,Qƍ x+އ ފVDGGkĉZh$iҤI޽QD>]|_F,s IDAT{I{ff^h9 MC5|_6FmXpP .J7:$)==]Ff񊏏7: ^А`ɓ'+660$22x C=zBbx7{4$FmxpK,Qzza0lb1: ^lFkEf0j !a+0!3zMꊏ! w"@CktކwǏcǎ.eddh߾}={juwb2ʔYfڵƏ:Y<&?@cxWsNY28e˖iڵl1bԵkW"RQm[nە>H. `<` _NsN׮]ٳ5tP)<<\qqq5k]VQp)6judggkƍ֭ z&w``0L2LFQt9=3#GܹsJKK302_C|}}z&wgjΟ?%Khݺvڷog}V3f̐tvJIIQVV;jJO<Ǝ@Irejʕ+Zf~a:nZ&Ik֬ѨQ\ @r-%''k֭:sԾ}{=ӊT~-IW\Qrrmۦ .UVzϫiӦeKNNִi+VHr/OpG6m$I.]r*w7Fwx&?@ *PPPc믿v;v1Y"M0AGq9sFղe[&?Swe[ںu Rͳγl2Zƍ:|>ǗիW5f9Ξ=tegg+55UAAAN,^XW\qLnPɓ'%I-[R^ rsaqpX,TݻWNw[z9N:)==]WFFvlmڴImV={$I>`cug֯_/IZtݫ]vW_$]VR}UG>p8qB+W,^vg͟?_yBEuQk^z9y;B"74,<L&[%' մ۷KfΜΝ;KwYfiNu$I ,Pxxۓ-ΝXmٲEuqIR6mlk۶SYWb(//OСC5tJqtE3fЋ/m۶iĉN$$$(00yBy1cT)Fw ?3 5TԩSnݺ9w޽LӧOKbbb\ĉuEIRpppm2{)Sh޼yڷoۧ?=zf7n\n/`(ɞ|7eOvn I~~~q),,J1{-M1~Uγ;icٜ^TZWV~L__2eNI0p@S;vƍu!-_\W֤I4dۿuVJ>BzPݼU^ r7~gj .c}W:t~9:TnXXN:͛7;q]-[ٳgu%liۥKu@Մ(&&F111:r>3}Zxq .uIs5mq\PVEB\\̙x@ T핔y9ꣃÇ+44T~~~ ȑ#rJT'yBUxׂ>P]<J}ݚ3gSٙ3g$IZr* ԩS5u 9p@ 8Щ쮻lVJJ!I5~xUtc(&&:hIj֬OӧWE*;Ny܍QrZUp@yL&[N/_֭[qnݺh{jݺ,b(,,L 5@eM0~'\=T+ǵZH5چ+*fVkNsN׮]ٳ5tP)<<\qqq5k]VQGžXVeggkƍ֭ X;hXXp7L&L&ax4;wNX&V{wUV)//OJMM޽{p8qB+W:z^{5IR^<9}?P0~'\drdWb(//OСC5t*ʒ$-X@ᒤviܹՖ-[<Ǐ$iӦ̶m:n}vI̙3չsgIR.]4c ڶm&Nv!!!3fLn@i<L2E5Ҿ};hĈJMM׫TӒL&Ǐ}ԉ'*ŋ2e:Y~~ۋ J֭$o~~~{4h ),,Jw7wP *}Yi򎴥 8P={Ԏ;qF:tH˗/ի5i$ 2ģz6^ZvIo{*uhhj+WuG1~`5'\ࡐ(%%EVRbb._ŋ{\~͛7jή0-[J.]Tf^8 $2~jڴ PWQQ VZZP)44T#Gʕ+Rx<9}?>xp5A+&&F111nM:USN5p@KfY)))WDD$)??_Ti 4tQIj֬OӧWzLwc OKLLT֭eXeEaaaJHH002PT!>pL&S*w6B&M4w\K5j$iӦMZd7nlptp .h5qD-ZH4i$u@mP|{Xp˝dkll6: PGap!P9_6,(XP2335l0Pdff* 0x w"@C WqㆆntKmذA6l0: ^.`8"btKl6CE? .[dvmt ҷo_M<0x1bTɓշo_è1F~ؿ233233~233*ӧF1~=p fY0ԱxCPOX,fCD~'\‚ R;ձcG222o>IRϞ=5|o^C,8\j: ڄ_+baeLYHVT/@H9t$J*dK@ NiVB߶>W\{~l=y.ٟ=\guF1Ɓ( u]YlY3{,Z(MMMK3jԨp Ei:3ym5>@-v_lٲvǷmۖ?&MJYYY3a„w}ٶm~:3ym5@hǨLeeeg͛~)]vYa/O?y13ݧơXS;vؑ9sw?gȑ 3~[nܹsdɒ9CrkMIII!7o… s)dᅘ;,Ypa 2d?ȏ?g}6˗/ϖ-[rG+y"n͙3gN.]_5rH<\,/rN8ᄬX"ofOnhh(|_|y裏nCXs P/B~s1Yxq>\tEIB܋/kfĈ'|s禼;_df֎81@q|I{'I3fBѬQbƌ9$|r-Ytin?3mڴ9kkkSWW~p5Ig&O]u5N-GtoC=O?4~i{L:55550`@!nݺuIvϳf͚Nq$ɐ!CkkX/7Q'$=ztqׯON<#G>&IvQjMҙMػnEVM+f7n\N=|y7_gK/o9'NL455uz-[tzO>I}9<Ǟ-gEk:]I:- ܾ}{{2o5CZ NuuuV^{//Bf͚U0UVVo6oVvÆ ˆ iӦ 6űM6bfzhY&sLqorTUUW\$U+$]IvE>}Ԕ=NS:q/~=>( SYYW_}5[n5*I'QqI3f䫯_5O=T*++s7b4nݺѣ$~mǚc8Ӓ$On[7\@'L3gGmN*|ꪫ1'On7`q|p6nܘ &,oVN;,[,Vjq$YjUۜ =W_}u,YƜ-]wuSLҥKnݺL:E\EEEjM^ёcfy'O&Iƌ&V@o  ihhدל0aBxuQ)))IIIIF*=P!nKMMMү_fر?~}1bD۷'I9 4(}Q> <8g}0СaÆe޼y7n\ 裏c=;7dȐ̛7/\rI~e3ZWgt;ȤI2tДd̘1w{j թ׸y睹;;7n\ƍb젃JMMMΝgĈIgʕ2hРݟWg̙7tL6-ӦM4w&i3}ʼ8@ ML2%vX,XP[`A2y"f8o=oǫ'inW\$y7Og5zK]Лqnz O>97tSx$7ߜN:Y5-}K=^o{tMMMjjjH.M8t{ `[ hhb'IR__bAMMMSz; ~K}@o[3~bIEEES_~)@VUUU*&.(^ {.bt#/}@w E}}}닝 ;Mmmm d}-}Y֭[W4n"UUUN(W^y)@VUUbeг4\ҷ t7.ZpЊ V4\ hhE@+$It'ݶ&IENDB`PK!>data/Archive/design/design.txtnu[eZ publish Enterprise Component: Archive, Design ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Introduction ============ Purpose of the Archive package ------------------------------ The archive package takes care of the different archive and compression formats and handles them universally. Archive provides the basic implementation to extract and create the whole or a part of the archive. Some research will be done during the design phase whether the PHP stream wrapper classes can be used to provide a common interface. Current implementation ---------------------- The current implementation implements only the Tar archive. The implemented algorithm doesn't support many (or if possible all) Tar archive-types. Furthermore, a clean up of the design and code will be done to provide a better interface. Requirements ============ Design goals ------------ The Archive package should (at least) provide a low-level interface where simply (a part of) the files can be extracted to a specific location or an archive can be extended with new files. On top of this interface a part of a virtual file system can be build. In another package? Design ====== Introduction ------------ In the design we make a distinction between archivers and compression libraries. If a format supports both, it is categorized as an archiver. The compression libraries, if not available in PHP, will be implemented as a stream. The stream functions from PHP have a different resource handler for files and directories. Therefore they are hard to combine and makes it impractical to use them in an archive (which is streamed). Supported file formats ---------------------- Archivers: Tar, is a pure archive format. Zip, is an archive plus compression algorithm. Compressions: gzip, implemented as stream in PHP (zlib). bzip2, implemented as stream in PHP (bzip2). Since the most common compression formats are already available in PHP, we can simple use the stream functions to access them. (And use them directly in the archiver). PK!g3{ { %data/Archive/design/class_diagram.pngnu[PNG  IHDR X)bKGD IDATx{TUW  hN^3i㤩y=h:xi*Wۘ}Cr/%RPXi%/&Lx1R$D:g8@c-֜?|>dz] T= p8ՆTSPm(N@8ՆTSPm(N@8܋ۧ˗@  /`t j-vN?^IIIFP͒t!cPs (11QDD9ՆSˍ ^0:u;PΟ?$c$:t)@ JLL4:J0:u;PjCq *ʕ+FG)VP  (##FwqqK}2lk*| P%$$(77W>D(*22R׮]3:(NZ\\$gqhv*((0tT7S@eZ߯_͛7b7|ct4)@ΝSddՠA)""BǏ/v]X,5jxyzz]vzWusYF4n85nXcǎu/-۹s裏q2dHHΝ;գGyzzGO=9RjSNE-[T^^^cԲeKx*K 0@^^^СCunW}|rqqQPPPYN<)=ϯ5깽{SN[r裏jˡfC6mիWum>}Zo飬,9ܹK>]~ܹSjɓ'ȑ#Vƍ+E6nܨ'xB۷u5%''W^/K}bl߾]}k/֨RVR>}{nڵkڶmzTh΢sԷ~4o$iРAruOV2~걌 9RzSnҁ4el6+((p_Ϝ9iӦΝ;>}Μ9\ٳG==7|)'|+W(88X&IԽ{wOKuu;"ISN?g*77WC=OY"##%IW.zll$iʔ)*^ɓ_ZSVV>skNj{Eۅl{cƌB’%I{5Uzz̙e˖顇RÆ գG}5k_{y< H^yfUVԘ1cEmڴz>Hn:9$I&Lp践mK2o<["I&MҟgnZիVZ%駝FJOyuk.9RRKY]*%>}h˖-ի5j}>$}kI{GB?:p\]]5hР jSl<^cǎ~ƍ< 4H/vgIfΜ]ɤ9sơ~жm⢈k&L?o߾N}b3c ={J^ZbIjРyi͚5֯_۷okjذy/s9uMtƍ Yڵ~a:tHS~~w-ZTh=P{P@=vqI_;ktQOG$22RgϞC=>Hnnn$I;w.s>H?@k[V߾}?jÆ %ѪU+di׮S_F$IwܹN*Iq/zTRܱK䡇rkܸ$)??Zއ>ڶmvGpo8z`4?Tbb6moqsMIR&Mʜvdݻ-V8R,6Na:tP^t)ݻWdXdZխ[7u>沈l;Tއߣ}l)999ڹs$SWP@=f ڵkQ ~f͚%_^:t(u [a?~\_~e>|X~mV$KU+{JqH{/u#<`m߾]ǏWJJ秮]TSlǷ|^NNƎlk:thcmX2ͽfI҄ J-?~(o6zh5kL[nUNNդI7a\EK]5fݹsGQQQΖ$=rqq18 P=7xCyyyNt/T1B+uKV^tjEmڴ$ݹsGׯ$=;sLIҺuʼHyT///EDDڵkZt^c:3Tb[I~~~o;g֭z뭷$qSfΜOO<Ç+''Gwִi4a+**d{ԩ֮]{-f̘ (66Vsw}lڵKcǎ$M4Ic]tI&Iݺu+uޞ={k׮tvY-O)IZt$#}#يkl٢VUԱcGvHHaj^zI)))X,jGjʕڸq 4fK.5bjSl.%%֭}-͟?_#G5b͛7Onݪ)d2֮]+Id҆ $I+Vd22&Jt;7n8+66d }wz~ݼySmڴ3<;Tttvڥ^ H5i>VPa-[LjР~_$I֎;teyxx]vzꩧ4l0 X,zUV9)wIkgffjÆ zkӲeK{qф Դi{)V$q)fnZ7ojդIjϑ'ի4-X@wѐ!C$I7oԳ>ӧO]rE :|bbbԨQ#MׯKrrryfkܹ+Ww۷o믿_,EDD5e˔P$R]O?T sÇkǎz˕ ^ı>jJBBBmW5kիСl٢={hᒤk PLL8իW_iiisuڲe߯ɓ'KvmeI?_tٳG$iƍw:X,N;mVעEKZ{`ym}1)Vұcbm߾}W^yEjԨΝ+ŢqsSNPΝ5gIҮ]={ՠA.(7nܰ_D9r,˔.ɓ'%T|ST6mw`$d/XtL&>I믿nS.]$Ij߾}.^(IܹC׮])]vޒ|{{5h@ԟ'3F111)s~[1Hy!Ijڴ5[m @}Gq K_ؤ(R8p>c-X@;wVNN} W{)b(::Z"Ţ+VHBCCeX?$:_W_9~~~Z[CիvZM8Q7nвe*4($++WܽӢE Iםlc;S0jSqJqЫW/Io+W(''~'IRjj򔚚ŋKz]z)L&mڴIz$]WΟ?9}||$I[nխ[ti-Y]ڶΝ;4"܋܍@}VS~jΝJMMՓO>pmԩ'NԮ]tyML.\аa۷W'OTL&]gXƖԮK.i:x\"g?S߾}5vXy{{jkK{Wѿ_Ol}?n|bbbdZrJ\jyL2Eo"##5|p+$$D^{ٲet(D( M8ѡ@&--M ,Н;w4dȐrg)kƚxE׼y}Y>}>ʕ+JHHÇF9̱tRmٲ${?V*sI>Segg+,,i0>|X;vO?]-Y9YVIRHHHmx]pAс]luq(!!ARbbtÇ+99Y dl m ?T<ʚfኊ֬YSo߾1cvø=mVעEʕy͚5z:t-[hϞ=>|$)&&LkUь}^6yWE\vN>իﯴ49aZG/diڿ"##%I{t撔y߿_46T S0cǎŶmv-I;w:u$j޼yNsܹS m۶Zp$9MS*gںu֭[^&IVUK.l2=~xyzz;}$IըQ#͝;WE_=_y2+fq_;wc;FW_}U?<==e6%I?̙֭[A0a.y^'O$ni6m8Uc}0H!.]Kۯ^uI?q9IR׮]4%IC-v2n U'88X4irssh[ϫ$t$}~yXUwUt͋/J:wo}= ?Gk˫5!Ijڴ8[m @SPPvqq똢n޼Y+--M:t5JbٳgW_{ʞ*jѢ\ׯElG)jJBBBmK/^,ժ<}ZxKΝ'NΝ;?Y&IӧOa;:'ϸq$I111z뭷\ݼyS{+0gyGuVݺuKO֒%KKoʕ+ҥKe24|R.%)*$EEE)55UyyyJMM~ݻ׬*y^lENj('vN@)N'|gjҤI;i$}JMM5lP/㣌 1B~~~ڶm[eny &hݺuڸq6n4_֭ /T-[wջ+I sV;wTjj|IkSN-uQ<2qDڵKϟɓ:&y^zRJJVBCCͅ8E|7¼CYfrwwWPP-Z$ImҤbbbd6'777y{{_~s_V@@ܔ[-Y<4k,\R< WWWyzz*((H3fкu컓^|E9Rw<==;kѢbcc5p@5mT ֛ovYרU6mX=Zrssƍ8y{{WU6p@zzf͚>Ӆ 4l0jվɓ'վ}{>$IX,~*=ۘ))11Q$CG68(NZ;:CBB}^zI))):zV\7@cƌQPPtbt4P@-PRq]RRR*,j):wEwi n5rHIFy)))I^^^'0L&gڵhL&mذAbŊ2mc*==]cǎ7N銍50(Nz,XgϞ?~va/r),;;[+VСCճgO 2Drssc 9ʢl4͜9S/ŋ֭[jzw˼~ffaÆ)??e2SO9dk)<<\ Ђ tU m6lؠ{L-[ڋ233|OS0bbQBB$uֲX,$HRVVL۷ƍ}N89s8͝ӧk͚5tn߾˗/+&&F8ôitaڼy-[V?OZ~Zj2ӴiS3F.\g}pmϞ=>}8ڶmrrrt m߾]'O֍7c ?Segg+,,)_XXcǎ2 fZ%I!!!Ŷmu+&&FPttN6ׯ:tHҥ>dI>nWV֭e߿_'O$޽ر˖-S||ڶm+VQFZ+""B5؊Szпo>-_\PLLu%_>P/I vf볍o(N`b;۶v̝;W:uBCC5o<9w)IRPPԶm[-\P}jfϞ@5h@3Ͳe˔ ooo{.ZwFSN/Q;ǎSƍ0W_UXX<<<ԩS'͝;WcLyɓ'%TST6m7F2LKjҥ믿_]O;wNԵkW-KZiii^FڵwXLz*qF*,,L_|ܹ={O=z8t"IpႽ<0##COG e볍o9:r1EݼyJ36fY 6TAAVZU7o~ZGj޽{%9#ɩXV4? mW6ҞS0bё#G~PEGG;oժرc֭رcNsܹsڶm^*~-_\{աC 5amڴI7n_|!WWWi\jj5G$?hBW\բE kׯ_9YVIRHHHqIŋeZZ/vۿIܹsu ݹsG?d2i=l!""B=$/KySOO>э7#YfNx 3={V&M*uI&?WjjƏpaÆzmeddhĈӶma0R͕̙g}VбcԹs 3())IRGH?TvAcƌ {꥔YV:Ӓ9-Foڅyyy)::ZCUf -ZHiۤIl6OnnnV~簋/)77n:uÇK)7ӧOc-[pW2Lڴinܸ|9sF$k׮'4Vvv{} &'NT˖-t,@}ntP6֦Md-Yᚏ"## JV;>'((HC pB͚5^˗aÆ568:b 3g(77W>z)S舆e24w\xG}T3go-IzZ9jS#\]]e6e6R+m߾c,K8r5:]PjntѣG@%$%%l6:S5j1TҨQԽ{wcPs 5 <<\Fj)ԀEDD@0͊7:u)ԠD#(?SAF2:Jغus\{;@/te\BkZ,)buϟ#GO1b͛[nU*SEL&$55Uo(((Hjذv(IҾ}xWJOOرc}ƍSzzbcc LPQ@=VhaLffy7Q=Ojٲey<͛7$]zZ``,vUꚶGр4}bsiii9s_R/vիZ` ={jڱcGa=c$e˖2Lڰa233DP)͛7꣏>w}<]rE 2eO2E+Vѣ}v^l233D3m4>|X999~6oެe˖ٯgeeiʔ)ھ}nܸ۷oĉ3g\~t-,,LڱcG8zb8|׮]ӧO+ @111:pV^-)..aÇ+**JZfN}jƌJLLTnn]״i۶߯Euڲe߯ɓ'Kvm .~߿_tg8َ)蚢5V1w\uIܹ}= 8P[nպud2jjҥ2SǏ/OOϻ={ՠAEDDHnܸQ=j޼yNsϊic%hmQæw޺u떶otd&NhWW][_ikdK+~[,Iڼyssv0):jJt1mIjѢ$Nl}1(Sl;?ׯ_?IRTTRSST-^XO،7NzKiii͛7g+fU{%I/jU^^k=־}{I-)gX9eddhĈӶm4qDڵKϟɓ:_&LкuqFmܸi֭[^(uͪO>DgϞդIJ۫W/j*44jXcj"Rk rss%IM6UllF-___WƍS\\5kV\~<==3fhݺu)uͪh :T͚5h"I}AԨQ#ݻi{I&XP>@=7p@ 8Щٳ5{2ӣGѣkTS$yZ`C˗%Iq2Zz.^IŋW_iڴijԨ] apOӧL&6mڤ7n(??_gΜk&Iڵ'e˖OǏvN0L2oM!TM6iɒ%Zd5EFF:yyyi…5k&L IJNNհa >G T=0b7TFXCkLlDzFjzLnMELd4˭`PR5W#JTQ0DG~Ay}fa{}&37k9<ϟPmݺUS$<3h ͞=[˗/$늈hSp'mCEY3;Es )h3^FQkt-xcVhN%$$hW4,,1vGs `Zr1Ç70:n< *++kt -)#hjt;М6ñ>@۷o / жm ۗlnRfsltO999ڷo$iСJHH04)<Ν»6WܹS/_$]|Y;w?ߞqTjj֯_zM8Qaaa 7:)< K^z%}'{SlilwwLբE'$I… +___Cxln2ܹs_@P.]TRRFGkҤIɓ'0097r\RwVmmW^yE ,伋GMMV^}W֭^|E%%%Ga$//Onҋ/(___ V^^^{5|?XW^?W^yEcƌAnݺ4m߾]UUUV>}4n8?uqw_۷O+V'|"///%$$h֬Y{ァ]v[#F|r劲5x`9{!٬lM:U6@s nڵkJJJӧcǎs4ܮNfѣGcUUUJOOWYYRSSjO$Icǎ$(;;[JJJR.]Ҵit[o͛w49kHMMڵku|9#GڵkZͪk 6m~:tuO~fO?UMM\揊RIIo߮ &ںc}p:}{*--i uѣz駕+''G*))Q^^$]Rl6_W={Vaaaz'$Iaaa ٳgj%飏>҅ SOiӦMڵk^~eIRzzz뚺I&7ڻwvڥ7|S~f׵2О={4k,IҲe驍7X3f̐$ڵ]\\,Iׯ1{ QhN@fOc}$)99Y"""pBH,Y0yzzwJII$mٲMLƍ'I㏝w-IPuYɲl次sΒm*..N6ͩu7O}}}]kκ/]$Iwk)~ΝGm\띮;t;ktFo۶Muuu|ڶm[9Ժ֭[[oi~>C3F7nlv]kرc9ˆikh+ٳ >|XC q>|إd2ԩSϗdj\#nV\({osIҰa$I˗/׹stu2z69k7nf6lؠ= $y{{7HY O$) ժm۶ɓJLLl611Q;wTiiLtSN3g:00P.]RllL&~J&Mt#a:tI&S^^Ν*((Pii^z%^{sS뚳iӦiɒ%Zl-[T:#5gÆ Saa\򗕕I}ٶ vNbd뫴4ĨK.RXX/^,Iq)==]E&I ȑ#f4͛yzzڵkںuѬ/uV}7ڵ222_ׯ{=3\S뚳X[z'#Gzw]g{ܹ\STT$???ǎ;FP___ot6YYYZ5{ukرcV?lVիyfHΜ9k̙JJJ28jJ233.l1bf6lؠ˗/֭[p1p@ӦMS=#233e2\0) 7˖-Stt xl6jƌ'|}}@۷ӘlvQn4tP%&&*88Ms3l6.''G$ :T 2/ÌqsUaaa@tYmڴI۶mSjj)׫^'NTXXÍhNWXXۛVkUTT(55U/~ mڴImvLբE'$I… fxxln8EǎO??JFj ?^&MrMf*٬*--U:s挞yeK.iڴipcz뭷tM;OUSS(TRR۷k„ iӧtݻWiiiN}ح[NGO?,߿_999 WII$I6fs{L͞?P>҅ SOiӦMڵk^~eIRzzzsHRqq$_~.5h>S0ؚ;ih>$%''VDD.\ނIҒ%K&OOO[)))18uMI?7bk#Gc=}77n@AAA1bDs޽[\ܹe?_^^.Iի|?S c}pN$ 8i<""¥R໎?y_裏'(::Z[lƏZkCN cMhNMS_|>!C8>Rk2t)d2zoFYYY=~ СCU\\2ڵK?tgw/RǏSO=u׺ڵΝ;ju^uuQFI.]2ݸqCGҥK]j{9IRrr;7oŋd65k,G}WQ8UVVgѣG׼4aݼySS\\\6L|r;wNׯ_/٬_~r؏t;ؽݱs njj۶m:yMLLΝ;UZZ)S8ԩ̙ ԥK+ɤ|zQCw {'ooW}Yٳӎ0 O꥗^rkWaÆPeeep-++sa 6M6{JKKSLLt"///iŒ$GeXd2驀9Rk֬q d޼y ^ziҤI'|~s$?^nv ={OcƌGVΝUTT2_QQ:MVVVyݚ4vX+//(XjV^͛7+$$Dt?^3gTRR Z ;&F!٬ 6˺u***;HhpB5m4é 33S&X 4) 5˖-Stt xl6jƌ't_JIIQ^^TUU|1vGs ++KVZbQff1p4Ўrrrh2hN@ l޼)@۷Әlnҳ6Ukdm9w_999ڷo$iСJHHhBs s窰ݚ7{>4JMMU__'*,,LFGSx6zH5_KcKS2jkkh"d2IbccpB׷U62M>N_:&MpeZPǏ׭[橬lָqZ>׬Y\_WO~C꥗^Ҋ+tq 1bj*IRuu,XÇok׮WkLS~5fggk rCfYٺr}g&]$>}1v1-XNfѣGcUUUJOOWYYRSS6=3gTuu$ڸqnݺ{>b ]rEÇװaÔ?z5v$1E9s4^W_}U'NpԜ;wNYYY*))Qzz:w_6mr\wSHHrssӟ$-|7}駪QTT{TRR۷k„ m]g5i޽{X/jUΝf{sʳ> }.IZvN8]zuqTVV?ڳgce˖S7nTqqf̘ᔻ%囹oI*..$=1{ @k9ݭ!q{Grr/oooEDDh….-(($-YDaaaT޽"IڲeKi UǎeZ%I/_nҳSL$]{4wEDD(sI 8vٱc;|M=b$}Z`zꥎ;jԩM-4]^^.&;=N5c}pN$ 8i&JIRLLL:~xmh7s@@$֭[Mza7e_^Ҟ={tMEFF1z\gΜ$ 0iϞ=}:~ȟۿo9}ҜK$I.u1{ @k9٘`%z:ܳNW^mjfvPܾ$=c0aTVV"I \wu75tرqݜ9o嵐Cs ngϞ/ta 21~aZɤSN)??_&=cSjÆ Z~# 6 ɓ'u!=3CIڵΝ;ju;Z}^pF%IZtt 9rDK.u}$I:vn޼/>l֬Y]2Gô//7nmۦ˗/?tF)IZdJKKu :okVEd?&vۏ+h)vNMXVm۶M'OTbbbڹsJKK5e{:uҜ9sׁtbcce2To?jn;!!rss%]ȴiӴcUVVjNBCC]$}6L*++SDDSmYYvNb뫴4ĨK.RXX/^,Iq)==]E&I ȑ#f1͛yzzmx};q\o1pFQPYY\ch\߿vN@ XV#v9m*//W߾}w}:t萾+d2)22RVUfIfkq}NN'I:tZ)%ÅqsUaaKƍ7*??JUVV?ҥK϶W׫^'NTXXÍXq /_\ر^}UeggXEEEJKKӈ#tu%''… 8Zhd2X-\PFxМl6;1wmܸQ>>>/ۿ_U;v"""b G?RMM6nhtvkҤIɓ'00c}p#.\ʕ+{n֪O>zW`Ir:FWVAA+uM/#IN0m66nܨzML>}ZJOO޽{洃ݺutQ=p(//O$6q]UU%Iz;o޽U\\h^YvN8GիW+88XǏך5k{ݻwkʕڻwgjݺu|Μ9={꣏>r|?ܥXvk-S0lvg}&IJNNV-\%K(,,LݻRRR$I[li4׭[$I:tg;M2q|0ˎ;Ԙ7|SQQQV4gcv)IZ`;/KrIR^\y5&N:%I8pxDDKmee$)&&w?~ѹtY}ݻuu~l΀9{}#Ieꓮ IDATCu$#^ӿsҥK${1{ Es XIH]}}uCYsW6zРA:{?kƌM|wMi};WWWw://qMov;~kk(XDϞ=%IvZL&$)??_6OIIIsJ֮]owW킃%Ir_3Klvc^JKK<(Iw\z2ڮ]J]5)QFI.]2ݸqCGҥK]j{9IRrr;7oŋd65k,G~$?P\\_^{M+WTyyTWW jԩNhȑ#%IK,QiinܸRGg}Q(Iڼyjkku -[~wZd$i /8r8p@7n7.}#ng[ZڶmN|}}h34М6et%:t0:X,FGМ@;>|rrr±>h3@;ؽ{V1ŢLc6hN@ d@q )h3T^^}:fIf3"RfѾ}$ICUBBBihN7w\ڄҖ}+ht4OMMV^}W֭^|E%%%Ga?7v&;;[+VPii:v~&___G+W;vŋ֭5c 9ŋoB*::ڱ;5e]5x`9{!٬lM:Ut)k׮)))IOv;v&:͚5KGuUUU)==]eeeJMMo6sLUWWK_7֭[JNN$]zUN8xܹsRIIչsgI6L>]gΜqn۶M׮]kѺ>S(**=QQQ*))5a„7Mdff Vzzݫ4]A֭[G駟VVV߯DyyywIlr^ziӦM*..%I}ڵku 8^Z:~֬Y3gΨgϞ裏{]T\\,Iׯ{cS0lvظ#99Y"""pBH,Y0yzzwJII$mٲEϟPuQVUte0ˎ;;w$-X@/٢uKN?S &N:%I8pxDDKmee$)&&w?~EY9 @t-ǘ8=g~Yǘ7X{ҥK$:m t1:]R;^CիWAލ77ٳޙ)Y=Fqd97ѳgO}:| ?|KdҩS/Ԟ1%I:y:gy1~!G>={ĉ:peee.mκvsΩZ]vuW]]@r_iԨQKL7nБ#GtR{Ncǎ͛x>f͚5Qk=~dNk9r$iɒ%*--Ս7TZZ:j_xGt oӻۢuW?C}^) ժm۶ɓJLLl611Q;wTiiLtSN3g:00P.]RllL&[uڴiڱc*++5}t{NcSL_kƌѣG44g]Æ SaaTkߕ& vNbd뫴4ĨK.RXX/^,Iq)==]E&I ȑ#fC͛yzzU﯌ %$$(((H ɓf8j}||8GFRrr{ѣGs***ryOQQt7:,YV5UUUiر V^^^ߝZJW͛"I:sƏ3g*))p7VU5pacĈ#d6a]|YnREEyI N6mz8)r,)1cH-[h 2Dl Ԍ3 NUJJTUU*)%%E:u2:#iϟPmݺUS$4h ͞=[˗/$늈08܄,,Q 86Cs )h3^FQ`t-+bt ;BCCot -gyvN >\Ç7:hNdeej@+X,4:nQNNMf4)x#h͛7at<9\}u3͒$Mks999ڷo$iСJHHh|0)<Νf7*55UׯW}}&N0 >< [fkƖZ-ZHqqq2L Vll.\6 fq kҤIɓ'00;?w; 5-Ҩ%:ztȻǟc6u-Z bb"B's!2o7@Qspr$<{}u]cs>_@.^ӧ;w&((I-,X:w̴wLqcr39r`uO<ٳ tGѧO>#Yv-;vA~ 6`0vZӋJ@DDD 7SNYRRR:uML&L@rrٳ… qv._|Tn޼ɗ_~Ivv6o~!aaanݚe222ҥM.]HLL S<<<,> MtɭYfV}DDDDDDDDDDDDm}DDD*'Nо}{v___'O \G)l5o9$;;ۦ_xx8\r[]|5j،3I)"""{sɱ:vrr*On׮]+lVreb43lذ7oh"ϟo3ٶ؛-EDDDDDDDDDDD"""RA4i҄_gi߿M_OOON8ƍ,0^^z|'رd}Q֭˹sHMMnݺVRSS-}DDDDDDDDDDDDe1d/ٳgDVVd6}{ [oEJJ wҥK| &L`kMƍ8}4_ݽPqcrHѣG ׯ'--l;;@a=z4 6$,,͖E""""""""""""rQrH1`̙C>}cذaL&j׮a٨Z*3f **grY1cUTqtx""""""""""""Rm#""RAL<///6o̱c䡇sΌ7 8:2ӡC;w./2JDDDDDDDDDDDD C)"""3FPAvLHQr%HDDD$ADJ 22aÆ9:  E)"""hADDDDDDDDDDDD\)9EDDFF)wJN);wO>qt"R u+0DDDDDDDDDDD* gG "" 8y$CDJ(22G!""""""""""RrH9pt"RADDDDDDDDDDQ)3JN2m}DDDÇӢE qiٲ%-Z_~x{{ی9r111>|lR5 &d!""={d]ddC\ԩ)7JNyZ%\txߘ={͸Kߖg?pB֭[GNN#FLJv9:4rMh$,,a%?իĺxbx |||Xh];ҠAK b0Xv->,5j(}#tt"//2[DDDDDD(9EDD~:ƍԩSKbʽ2330aɖgBRR .ڦ'/;vٙ]vli߹s'NNNٌYlU۹sXv-iii̜9Z׮]ѣVILL$$$Ēb6|-([l!##.]ߥKg)EDDD8F0G!""""""0GDD ԩS4jԈvŋ*^dڴiCxx8 DDDЮ];-NZb2<<p:J^]_۶m-a;1AAA-> @ӦMm6k̪m#""RA8q[=y$v:rH#44]v1p@K-}neI&q!s999ysiڶmkn3g،1']|5j5HPrF\%%wr'x899'*ֶm[سgo&!!RŞ>CѤIzIiݺ5Ç/ܽUS{l[f~HQrHѤI~WoUd6}===9q7nӳD뺺ݻٰatЁ*UgBBB]6GʢR%A5jٷoՖA\SA֭˹sHMMnݺVRSS-}DDDb|2dffٳgSNoNr-(ƕD^ xxxТE ĉ\爘vQZv?*ۏ}o߾̞=$8x g϶ۻwoz-RRRs.]?`00aK_/[cN Jݻ$%%iӦYիfdeequ޽5[hҽm>"""R񄇇 @ff&k֬qpDOvv6W^%!!7|={DDDDDDDN)"""D`` ͚5~c̘1~ͦ1ch֬o} IDAT ((N:ѿVZE*U4iɐ!C8pݵ(/^:ǜd2}ttBPP?|JJqGˋӧO3vX;v,gΜˋcswڵ+III6mIrx笎w999a^ܹs_?O$&&2k,Vr_k^/{cDDDDDDDl)9EDD>b20LvUZŋ@ZT>>>̜9Y h4鉋 Ջ˗[Uy7hܸ1...O"#XJרQVZy o&jժҺukfϞXnq5j 44ÇӠA\\\hРFbxxxs߿?ٜz 4"""R$%%?P^=>3ԩd⧟~rthJʕy衇xgXj+WtpT"""""""G N:L>o={NWU_^{56nHBB}s۪_~IHH`˖-m111L&mۆ?B[F f͚E\\vbŊۗc2㏹se{լYɓ'MBBѼ6)y%TV Ⱦ}8}۷ """'N0~xpssӓ@wrr*dbذaԯ_WWW7oΔ)SvZqXQFQZ5Fi՞_l'NCTVͦR\qbغu+Rvm ޽{ɉ eoVV 67+s) s5gi\JJ GqƸҸqcƌ/{%%%ѴiS:t)=x"""""""%T=z`0~zرc;$]ff&(DѣGӰaC,maaaxzzT뉈㏳d~70tЁ"YjU+Vx"oѣуׯqV^ W^mI|رcٻw/TVDJpO>$ ܾ}WE׮]LJ={ry6mdOtt4ϟgϞe\~GZlY16mח+Wrn߾͙3gXb۷oS|={r%>ׯ_ -%eDDDDDDDJN  9sӧ~~~ 6 Dڵ-͛gcR~WժU1cQQQ={gŌ3RJ'""GqeJzz:&M_~ƍ޽qƑhc5kҥK-_;v_|;w0a;Fff&;vۛ&osѪU+ pꇏgϞT/IMMe޼y%^`ĉ?~Lv܉77o_Wf[l󡡡7(sKvv6/^d3Jƞ;w#Gr  DRRn"))Aquιs,cJrvO<ڵk-MDDDDDDD4JN &OkFVR xzz2dhܸC, .PR%ZhoQ&ktЁ`Νܹsy-DDD( .\ԩS?>TR,Y«Jjj*~iٳӧob4--Zĭ[1b9͚5rtޝ5kj*9/_>kn>6˴ihӦ  1ciڴ)+Wk׮,Z|cygS7oJ※?'mڴڵk3tP%K...ԯ_aÆqiL /of ,ڵkݛ 6кuk\]]iݺ56lw\r ZƔ>l޼'|7nO_s-VZ gY( """""" Pr ݊[nsqYf ...V9@۶m ך5kuz\ӦMٳ'nbڵyѤIbּys6wwwܹSxs[@ɟK-ܹÕ+WgԨQlݺ.]R`57_>9Lrrr>m1U\y)9EDDDDDDDHKK+QKA5믩]Mk׮PzBe޲g۶mvonsHIc1suu-{=tڕ8L&III[LZҥ aaaHKKcʔ)MOOf͚vרQׯ[Jrk֬999?"QZJ9^zUWxx)3ڵHn޼ȑ#w! Ͼp 5+xgM _E >ZjW_qM"""^:FWRTn*%&&=`ޯs[nc=YT9QUrt"""nݺ0Dxyy9:2Ow^{=KJֿ2`Ĉ/!::op ´i]w۷e˖ѵkWsIIIIbb"7od۶ml=deeqQ{=&O M)K/D5ضmC !99L2d۷o*4˗/~ܹ/ZZ9h4`y_EDGNNNa4+::Cr s}gKc?P` !$$qa;wᆪJ*1BCC $tR^xFڵk,2y꣰4_^שS'y8py\]0ƍǒ%K ƍ6lmXv-j/i&~ij֬Irr25ʷa|y`~~ISDDDQNN^zU_+"G2`رciҤ +Wf͚ۗ?E^cرZjJ˖-ywٶmUTիDEEQn]KuFjժ_իWK-fbjYQKAh֬#Gd6)8p {%((OOO*U'=?Mb }~ꩧ8q"nTJ9>>,[P}\R5wN<_VLJJ [l`0`2'|CyP)9EDDkLr%㉏~c6.]ʷ~[ڏ?… Yn9991ڵkDDDDDDDDDDDD8GDDF@vvU{vv6 }ܹ3AAAMj`йsgg}FffϽcaN>jߵk~~~61||֭O<g϶dμyxꩧ駟f\v{O>L02~ڵtؑ X7lڵkIOOHYPrHquƍGtt4iiiܾ}Nj733 &b Μ9۷9{,!!!٦'/;vْbsN&_$117oʗ_~-]?Ϛ5k8 MHzϜ9c39ԨQæGDDAW_W_9: y@(9EDDāroc^999VNNNڵk mƞ={}6 T\nRL~troKnVMw^gg۝ mEY[DD䏨DDDDDDDDDJSDDD*&M믿~%ɉ'ظq#%Z___v͆ HOOCTRD֨Q#?ξ} ڷo@nݺ;wT֭ku.55GDDA6|pG ֭V"""""""%H:y$ CD˯ٳywiٲ%b6}{y뭷^|E[DDDDDDDDDDDDJSL>>}0ae>sr̽I2ddd`ܹ3>#33б;;5HHOOgϞ [q)ݻw/6liر)Sn:Kxf#"""""""RQTrt"pKL֬Y/_.\`̘1l޼ܩS8u_~% `͚5xxx8 ǽ @dd$FasBI֭ۗb2ҥ ׿ܹ?ϖ{Z#((WW"e.h֬Y4j2c Ltt4.\)))l۶~PfMʕ+ٵk]t!==SZ5|}}K%.www]FXXGW^ :CZyanܚ5kfGDDDDDDDP1(woѣٓZjYoѢӦMctޝX-ZĉH֭ݺust""""%֠Aڶmˁ|2۷oSNԮ]۳sN222HNN]vԮ]j|Q&K_v9UF>}fȐ!,[RN:<3D\\pwKҊ_~}vkg}իyyg,g:;~ܦ-6EDDDDDDQq'N0~xpssӓ@wrr*dbذaԯ_WWW7oΔ)S+5jժUcȑVv :t@j8p`cquuv 4{? 6̳JIVV 67+scԯ_ 6$ܫM6̙3%K޼y?=zPn]*UDzxꩧؾ}1= {O-{#뽕/Կaz t?)""d2xb& kU&Zdggb _nI֭7o/ڵk6['7nJLL,\իW --ͪgՕuֱk.ڵkA@@˖-cʕ=4ϟoSn]RSSm3T"O?m sΆ /0`@Z+xs玥ѣGjլܹsիWosY>6{l\\\aرD{.N,֭h4 իW"&&;vбcGqгgObccٴi ٳ'>>>@џ^M0:uy_ƌC֭{(כN^lW.]Dtt47o&**~ZUq,$KYh"""SD,)) b^O<s/$tڕfzU8ɓxyyлwo/_[oɓyGz*WfժU -Zٜ:u?*f4hׯ'''mZ%ߗ4AqiL€xG\e-Zp9N8ar KD)/_fС3i$ӟľ}Xl!!!F:d$/<{lN ҥK-ǎ_Ν;L04nܘ={0vX~G}fΜi57|ùshժN:?̖-[/"==D L8^{FȘ1c8r׿eƲl2)Ǎܹz*8&E9sw^Zn_|/۷I&{n{%k̚59sX*JZڵ+$%%YϤDDDDDDDD7G/… L:M*Ugɒ%ꫤ駟;Ϟ={>}:o&FrnѢEܺu#FӬY3*WL-[j͜˗/t|>/ӦMM6xxxиqw+|4mڔʕ+ӵkW'gN:l޼sYp6mvږ}֋\̟kժUVQ7,, +WҵkWV:ubʕ8p ϵ=Y[I^ٮJ}-"""";姟~:έ_~m9[4n233[񘓝===qqqÃ^z|BUTקO>,Yv`=J5!C0}tZle+1c;Xwwwl⋋z۷8+E!RLZA>6֭={ ̓L֭رc{Ү];?Nٴiv;:t`޽R1/W\ӓL?n) w0 WWWΞ=Kڵƚbb/99&###jժBVVq{>i$>#̙?K|'@񞋋 ܹsgzr*Uek{Vř$Ϸ]SQNrd/V{m%y_0'> V;e˖hт~m3ȑ#paRRRزeKdd{ wDn߾h$ۯ_b+my};7T.FDD{ߟÇ;4GJD $>1i$6mjٲ-ZIJeꫯ,IOf⋖R1LG"99ϿKƏf͚5V)pm۶-t\k֭֬[*1ٳ'۷ogڵKvhҤM[qb1k޼M;p7Y /}!!!V)=^Jzz:5k,0z=O?Dbb" ۷gU9K|s+{k*Ĉx_cZ%2\txߘ={͸Kߖg6M޽{-/^,5/?pB֭[GNN#FEDD-##7ndfy=z46m",,ɓ'w<==m"V~K.%""5j_T1vpra?mm۶|+M,_<s"EIc1suu-{=tڕx޽;&$x-}\1LЩSBʢR%z׭[ԩS9zhƁgU9K|s+{#k*%]'666s5"!!lH$$$Cqn2y?:Ō34{<Ur_uG'ܸq~CZֆ ´iӈjժODD${+ 0p@FUVeƌ꫖D(>TDDDDDDDD{pyW^CꫯիyG]Ü8PdBMLLСC[XJ /@HH`j ﹘/v?3u-O3rH=J˖-yYl_5?sYϷ$ GȱO Co)qA^褴b`0\>)\p#GZFŅ , 4h777vG}dS:t@pp0seܹ::,bQr87v*Ҹ7o2rH222xwȳy{Bͽb nnN0/RچNZꫯy&T^QFY+s1?'==IKK˷2Ma{:̙3;v,VULt|}o*rŋ>}:}sc7%## @Ν8p }>79$>>ުƙμyxꩧ駟fv.]̙3y'ҥ ӦM###æ_cǎc{qy?FItt0az=w\K$p7{EDDĀx 8` ?{`ٲe6璒prrYf{E&0_1)ԸB3]۷IMMe޼yڵ>7$99\S111k'͛7~:۶m3{ݩ K,!66<裏صk_͛gtR~}/b~___򈏏M)b!!!ԭ[D^|E͸}1qDFI5 3sN}ڷoXy뿨Y&QQQ̞=˗/޽{M>F @||</^ǧ*FݺuSN\x={xˣ2aލI\*v]"""hذ!w]vqmIIIW^eΜ9tᡏteܹw}ǨQn/t̊\_cb۹}@EAu8… ɑ#G(۽7nӴk׎M6q1bccر#IIIܹd>f\\\x9wի|~s_4<<C,7ni*r]5kƾ}hٲ%?#*-Z'''?0sLr$ ,c9s&pAƍQڵcÆ ̝;-[_?1+r};w f͚@ůAu8nMVJ[h1Q!44coowsaaaxyyaggG͙?>@KڔK.>|_GJC /{5ݿ?gϦm۶c_ZСC̘1OOO %99O>|״iӆݻwwy>2?{1cƐ'իO?4-b߾}ԪUk׮sN4h`r z駟rڵJQ3~)F.FڵԩSDDD/憽=jˋ'rJKL?~<֭cǎԬY?.\ܹsXz#7**_|ڵkSF ~ߙUTs쏃ЩS'vooo% 4Vea(U49h{qq_xv^]I}+qVZݷիW5jF⭷b˖-PXXX9sZhazX.''vttدOuޝ.]JXXcҤI>Go߾pBS{vv6/*9xUVdffry$TZbIDDʬ &"ec0v"""""""VDPP9?GoѣG~N<Ɉ#̶ժUSE@@nnnڵbHSIKKÃEѺukN>ܹsIMMeڵK4mڔSOf"##ٷo)9eXnݺE\\lٲ *)%-wԼys"##qpp.mDZnm1-11Q)"""""""bUJNG*==[2x`k""֭[vUb֭AD]#"eE_{IIСC̘1OOOBCCM $F3mk߾=:t`ټݻ"9e̙1$;;۴ɉ\IKKwXGQ(qܹs5kfGDDDDDDDZ"U"66!H5VC v""""ŋhժ}eddRԩ8EhwڦL‚ 8z(G>`̘1 jժU U.IVVیm>""""""""֢*`00 CDDDT+oG/lR\J}%G׮]ٿ?~)~-VbƍL>>c^îmOϞ=;v,U&xll,ӦMcڴiZIHOOg֭CD֭[9v옵޽;K.%337od|||l׻wo8y$oɓ,^={{L^^-[ (Jzztuu`ǎ瓖FxxxK?b\c[E L"V@۶m͞k׮J7HHH2|L2+WVJsqV\ɖ-[(,,dСxyyѱc*_I/[PPCM{Wسg'O䥗^26~x`Kzz:cƌ1iVn@mzJVVk׮Rݻ7۷oע_YwNBB)))fq¿cW$YGDDDDDDD2rXUi)-99,#!!믉ߟwcUf\ܹs www3gUT/?U Ӻuky DEE1d5j5b]ryxqpp-Z0zh,X`7}t<<͛7EHH';aaaWn]fΜ̙3ۯ%+̚5Yf=Yk׮``͚5ddd@FF'N`ĉ899w\GMSZafmIIIgv|||äILc&mcŊӭ[7 UlmyթS{9 ݻwcZa{.W& nݺѫW/^yva/''y5jdjoܸ1>>>ĐSc׹s,ڌAE}Ynj3HMMޕEll,ӦMcڴiZ.IDDDh4nܘhS[tt4nnn1Šܣ)R?`iӦl۶F6mҥK 03gΐgW||<_~4qVV/^=zZl999fRPPI8}ҥKDFFʕ+M'_Y|9:t(|fv;pzbʕ+Y~߭[8uNƍ_W羾$%%/|oABBBUݽ{_}Ć |d\-[PXXСCcǎSDDDʦ e8Vά.?>:#G`Ν,_ZjY9:UN+JII]v%>wsswĉܾ}{bkkKbb"7o4g5+WܼysYpE?,ƍ9}4ڵcӦM;vX:vHRR;w,xVׯvߟ &ڵk5&ٳRھ};poy#GpS-[%&&кuk1oWBB}_IJJO?SNܸq>{|ΝK`` nnn9sEDDDW;w&$$KtR&OT9EȘPҶm׏SN/ǎ#;;?|':t}}1b˸\PXX$3h 4hP:{,3UI[._ÇKNN~-k׾ɉ\IKKwh6qYMZ׬Y3>"R5DÃ7|aÆqر*!**+W0l0Sټy3QQQTyL"""O`v"""""""""Ux %KdEh"xwM~SfMBBB?_~iJNW^fc,#==^7np1ٳgmJ 1b[l!** ___>̝;w֭5j'YL‚ 8z(G>`̘1 YYY%3HpU/_ΡCϧE5ٳgEyyyY={ ?qƙ&'1Ƙvu[rYn޼IÆ ݻ7!!!899=p<ٿ?j_dԬYbbbxg̖lkܸ1>>>0r_DDDDDDDDDDDD:Tk5C={,O.]puuSN:tMǎquu5ۿUS =77cԮ]>}fӶ/sqRRR8x poIʊϏݻw3o<:t͛7Yjg۶m~666Jی}Dnܸq㈋#;;[nqYSbJQL4uqEnݺťKdʔ)ܽ{b駟hР>7$99\n߾Mff&111iYfG^^YYYlڴo_|yyyZK^^ul""""""""""""R"U.99ڵkGrr2+VۛdK{.֭ƍ=zpM>Crss-(777ve'))cթSl#G-[8|0t޽Rrqqߟ5kְ~zfٲe>ƛ+m+zYD+:: .Ndd$G!""¬ƍ9}4ڵcӦM;vX:vHRR;w̫}-۷9s挩UnL6o K0ILL|D믿M۷ϴ=11֭[[fl3AUSJz^G.]jaLN޽;˖-3 ݻw㰱t<==xYv-̜9-[r56nȆ aݻ\pw}mۚmLaa!:t^z`֬Yߟ-[?`oooUVdffry$ϛȣS|ړMIo7g^{5{ ,, www7o4hqqq 4btqqaر3gΰ{n{klU׿ҼysƏOLL is/+Tq)7c)]PP;vv"O[b0U)9E<) 40UTiժB@ӦM~Dž xMEՕ,pssc׮]=sIFaֿVZL:ıJykooOHHEQغu+`LXXKix{{wޝRRRA H1&uɬ/@zz:%Z_>;wffW^eԩ9sb-MfnݺfKeeelGDDDJ6x`k D}qj׮7&M2qZ5jFUqծ]W^W@@5j 6644iBϞ= 6{x8x F2ԩS~=xE/kcLt:=lllاV2yP,E-Y3gФI{9ZhA۶m2dHrppvZLhl+|ȿZ;y(9E".._~yXO>ӧ[v#x~~~\\\6mӦMo\A[^j׮``͚5ddd@FF'N`ĉ899DkҤ ?~->zRϟg׮],UG 22WWWS۷QѠA233~rdׯ_7)S (9E呟wFixψf̙DGGf|XW~Xx1-駟̙3,^آ?ڵk e̙lْk׮qF6l؀Wݠ*,,$==OOχȑ#ۗ4.\hjΦ~5_VI(eZj ""[7h y"Y;SrH+ b4yM2;wdԪU˪ >s~'F}߾Gf|ݻw'!!Ͷ+X|"RB z<ׯoQҥK4lЬŅiӦ1mڴ營E{iI2qvv&,,m+mk`0f222 ##'N0qD<|||Ν;ge7wll,Gk׮ 2*Cy("""ի>>>|dggs]~G,X@NaqDGGڢqssXHDDD}2x`quu5N[ٹs'.]ҥKܹSV-k'"""j7w~~>s%00777 `Μ9Wq""""""""̙36m[VZF@@Ѧ%n;w&$$KtR&OM1-#ŕ+W6lm\r(+F&"""""""Rv5<lllTs!T{ ΅o/OBBӇٳg7//5kְgѰaC?1n8L޽KDD\t {{{Zh4hY"qrrqDDӧOˋիW)˗/j*ͥYf5TsrrgQF>7LJFsyNHSr}v1{lZh #));wl߾+Ví[#<<-[dV%x5͛iV,֭[իWiӦ o 6wO>!22:wbb"[ؖv9v옵yhta&(9ECh""hk!"""*KJܨ,`ٴmooo׿믛ݳgaaaHϟϠA3%899Ktt4iiiݛ@ۈ#ʝ̘1T-044{96mjYff}D}$"JDDD(9EDaaCjI!C2 AD7… oެSN}/qT)S`=ѣG3f Zj)6c2Hy]xVZ{߬,-ی}D#}$"'**УGbccTED~kWD7Fv5jX~|޹~~~tڕ駟߲j*6nɓ˴,NiUS M &9ٸ6cEDDDDDDq4iBZZ| nnn?]v]\\ߟӧOW_n:-[Vlll(,,ƍԩS0bSO?J6m5G 4hlM}Dt;f0DDӓ.]X; $%TsΝPG=wll,Gk׮ 2*Cyhu9."⋬Z0.\H9woEk̙3iٲ%׮]cƍlذV^ `֬Yߟ-[?`oooӘpJYdeec^~e.]DxxEݻҥK ^z,_X4i'|RܭZ"33[$?G!y\ȣj7 !!JheǏrJlBaa!Cˋ;Vy".xMGkĈ|W;w &_xS2ѣٿ?'OdĈfjժԩSMσ #<<"ؘpv*5޽{}v{={=j/F {ɓKfƏ߹wNBB)))fq¿ٳELDDDD-EEHHHvs3w\qssݝ̙C~~~G)"""""Jrrr';88A`` 888Я_?BCC-֩SH nnnB޽YvYE͛O?hтѣG`SӧၝuԩRn]eܹ4h@TT~~~8;;cooO֭yw߿}~prr*lJz|/|ΝK`` nnn9sϷvx"""RI:wLHHK.eҥL<oook%شiyf+G$"""""QҾiWQ}4iY۷Yd zO>^4ٳѣ?<͍7J=wzj֭zW^aǎf_I(''??ڵ+/˖-#77}SSS GdfUNKNN111<3fK5nbbb)~DDDDDRRRѰaCVZEINNᄈvh""""""%U]"%dbل[\d;wf޼ytЁ7oj*϶m4iUS~)+㾶/ƶ="R7n0n8֭[={ٳg[-((`ҤI[/r-.]Ddd$SLkXYO4h\l999fK,!66<裏صk_͛gtR\r%}ܺu'N$))7orumƲe_|A^^sG|||T'ϟg„ xzzRfM %yOq <-Z0k,֭[ܫPXvmSBcb;<;wv 0cسg]vWWW7|s8bccCƍ}v}o߾MƍM{]*ٳ၃=}so޼ɻK^hР5jԠaÆ'c~7KSUa={,F {{{ZlJ,"""")9EXO='ڍ*4 YLvv 0-ZAc+qxxmEoTH劎… ɑ#GHظq#O]vlڴcǎKǎIJJbΝ%&۷9s -[n垳͛… SRRؼy36UU Ύm۶Ȅ 8p@n߾+Vp8YزeK~z0]5kNjjwQM6e$&&2fKȕ'DZnm1GDDDD:;x ۷;?3Ν;W1͞[]sUnݺEZZz2<Ν;lܸOnܸ;w71c7ߐGڵ*~_رcܺuk׮sNw_]j^^^>qqq\|{///\|gx{{~z.^Ⱥuԩ_~>9999tޝiӦqAs qqqӇr,[76l 33۷oʔ)S*oRDDDDF k b-ݻw'&&KFzX|94i҄O>޽{vZXhmڴ,^={{Y߿?-[,}tuu%++;v/sҥȕKUVdffry$ϛHٕNdSChh(۷ۛ9sk߳gaaa$͛3| D\\ z]\\;vC9bĈ+A͚5-[`0Xz5ٳMK 9挜%::4zM`` W\IפC̞=W_}{b̙3MAAADFF]XΝ;{KuV"lݺ[;j+++@rrr:u*!!!wĉYH gΜ1PʱF/6U裏L?#'NΝ;L47|=ʘ1c8~8ENff&[6/ҥ ^^^/ϩS4-YXƏϫʴipww'))ѣG[oŧ~Zj,&L !!5k0p@QQQ7u)L F~~>ߦe˖|駟2dN>Mƍ+toh۶-~!r Nʑ#Gxy饗*|e[ @~~>Ce8}43g~$祤I:JN'+ž={8yśǛw^Mp7h+`H 6=6&Ʈ]Jwl߾{{ĥz%ݽ{wHII1U9%H:ud^ ==ǪH$;;;ׯOΝ?~ه=ӘDQ\D7'''-Z&dIL‚ 8z(G>`̘1 jժU~eddR2^/ZS\\\KVVsی}DDD۱c;vv""|\rPz-S{׮]ڵ+μfۋ;z(`ƌ 6cСCL={d<3lذ"!X qȑf#Gdܹ])s̡]v_XFmIYz5}رc/ݻwiJr }ʺ.b rssyپ}im۲}v˾}XriCׯ7{ܥK֯_O˖-9ydc/<%%QÞ.]y+r~?C_N1wؑ8ző#G*7)""""UGHP$*[ gggiݺ5 DEE1d5j5b]Bod7oO?4uqG͂ LOvvvw̩SHݺuqppחsVK^ɉZ{AԩC~}>Dd׿⯃[%}yi1;vݻw[oYTȜ%UMYf*Ϗݻ??.:KTEmޢGMq,n&š½3XWCZȺU4oN(B-ܔM$cS?Pޢdj)D2̀f[`` ͚5#%%~Ҹ^xboصYZvZqf̘Aii)}Ͷ۷s] uq]R344o~_?^sxyf; :P.̳h"}Zhau_y~'EDDDr4iDFF>c=Fhh(U,Q_,|}}nnn,Y%K<um۶d2K^^ݺuW8~8sεp "u{|8q{~  .gϞ:-[gY\ >#֮]˫Z~yzzry??om?~8@Cubԩܼyn5RGEDDLD#F-)UmΜ9?'x;wҼys*+VeΝ7G[jG P7ץ:,}{qu?`47o)˲} V0nF@dd$ٔm&YꬺX>,TH"""$'';; cK4enz~~!IIIk׎?Ot{,铖Ff爣xjEe'駟foV"''{[>uaX,-,,ڵ޽{ӻwoxHMM￯m][koxDDDDKSQ32nC/!(qss#"" X\NIIaү"R?O opp0$;;.qu,\Cܸq {U|5ITTQQQ6ʗn?G8p/2sLm^^^vmuIOO'''.Ɯv1""4$$$`2HPqIնm[nݺŏ?XiBeN:ł h֬۷o駟tn߾]9rssjŐɩS۷o46{l222cȑXuv?rM:vhS>;vXz)&OLϞ=ܹ3} И4yks~۵k͛7+哑6>i0FKm.]2F;1Gף~%">Ps_M5{hҥf<|pݻwڵ Ǐo>|3`7U… ̀ݶ'Os=f\ZZj4#GT9_W3`4ZہJ&TgWn9w0Ϛ5ˮOm˃blѣGݻg޽{QFŋ5=f\XXh֘o߾]c1>h_Gm qjڜߨ(3`9rń r^HOUN~h?֭[ZMcNPZPP]v%!!ږ`[ZIDD;sLےXh-")){1222/~Aff&w!--sH-ƍ߿?[nYfUoЪU+Yt)}EEE8pSXNݿ?/_h4sU9СC8p /_&55Z[X˜9sXz5`oAvHKKߟ\JJJߟҦM~_Ssܯwq=f̘5k_PRż9oCϜ8qN>͔)S*"""""u1hQGΔx?\jyРA/M i:Ç7_||e_gz߯Dч*-Zd4hmG59|es^^yĈcǎ5p(k~C}ZݠcӦM6 Tibcc͚5soСbl6O2 un̯U{93`_U:nMK9krmRRR̭ZrدUV?vTDze}1?8ڷ6[_۷op[:4k)"""?,Z}Һuk\\\0 @nݜ8A a͚5YDDDt,[I&a0ߟp8Jk„ ?~3gҽ{wZlc=رcٿ?oMos̜9tƏOquu婧bʕѺuk~GRRRԩǃL&ڷoϟ'~:Y8bQR[/G% @-0 ̘1cǎ1qD}jrgϞG}Āhժ+V`ٲel޼N4yk{~ ‰'={ۗ;vXg񉈈HH0eg "Xrr2&a4z...L&+ׅ@VV#?\zKiӦsN qbt"M7?j#G2rJo߾Ɖimڴl6?t,5U?p\Y~m۶h3f0c &C>}>][ 暉HQW^^^L)?FAA <.]XtHbb"|""""""""M*H1b#Fpv""""""PXXȬYt钵,]ԮoIIi IDAT #77v!::ٷoEEE 6n۰adyT"""""""")RvAfC=>}߲DDDDt_cSbү_?v#GHJJbdff.Ke}@߾}ƶYQiIIIAD2eg "!990DDE%s*k/Q Λoi755H<==իL8{2qJ:s =zֳgO>""""""""p" bADO?!;///<&O?0DDY.\`6>>>v}/^ñΞ=[\7n]vv,m>""""""""p"""F#H*VDTLJ)16ϛ5k>ݾ}1]\W<9WDDDDDDDDjN)"4ԇgΜ'9j3wRR`Ȑ!ZDرI-_$(3L$$$8; GRo9q=ĉv} .\`Ϟ= թS'y&:uvMkyxJNq~t܅Xǎ#::]va6yf ȣ())!CPH;v,~-Vbʕ$\p. Ųn&y(9EI,[I&Y<'<GJNFk?sUNjm6m;w$>>'F'""""" Ctt4_~%oߦW^|r\]]}݉?$--WҶm[|||7oO<ŋٸq#0n8֭[ǡC1cMݝc6́4Z6XDDDDDRr4iׯ_gƍS\\̘1cXtþEEEƒOΝ?~]$qAAA\vvY/_ν{x饗*w߾}1l0mÆ #33ꫯ(&i~mӫPVV?@ZZl۶ //RٳmURR™3g8s {!66\t1ٵkf^{ ooo DDg?%K닻;.\෿-HHH 44 RA"R{_}ׯwv""4b|Mg!"""HRr4Y۶m#//ݻ{ɓ'ؾ};׏Kһwo.\@dd$X|'lذݻwٻw/QQQڵӧTIqa^R}׮]駟ޣsۿ㥗^t k7-##C)"*(++ʕ+DDDp1>CVXQ!V[}']4ϳ`zEii)N=O&::ztkc-..fٲeL4 ?$'' qH9V0a1QQQDEElСs̩9܈`iݺu%Ҕ]xd&OPDD*L˖-#K)}Y>;x K.gLJ7,Xojj*xzzH"""8q"{&iӆ۷os5j&MbҤIՎ- Ɖ)pN$wyZ ,,{zagϞ6}D4ecsqq[n׿fԩ9r!5io-Z0p@"##իL:6m4vI|||>3gb2}%._ O>Y}oܸ@vY,}Dy]ꫯ(..w̘1KI-EEEƒOΝ?~m¿͛Gnnʕ+őCtt:<:uz9׮]KAA]ЫW.ҭ[7߹s> _alݺݻsW^aĈׯVe+=(NGQQÆ 6l0233ٿR"?qݻwѣ6999v} {!++i???bccٺu+AAAܺuk*VKRHaa|mbbm忄K$..۷o'77~c9BRR 336)VRN:ʕ+:th,W^dddb v_W͛@TT͛7gddd0gJ$lذ/%Kk׮h֭;wnݺYIll,={-[ӣG>2229s&iiiW^!22>#fϞ /oARRM"ヮueעu@߾}Y,}DDDDuUF#/"pڭhd„ NpRU͝ĢEXhm*)9E_DFFrQJKKox=0N>ͽ{~:0/N^~eF#1EEEooo;- '%ҡC>S9wQQQv5kΝ;^+Rܖ.\`76HՌFͣvK@XXe˖n7njj*p=ۛ͛ӫW/"""ػwob2d믿Ps8d郫tRzAV 'YX$$$?IʲIn]g}Z%vEVUPnݺUX|}}Oٶmկ0zjL&}Wٵi5yZ>,Ue;g~/"""" r3aݺu[/IMM%;;6{*>|8 Phȑ("4p@3???cզ@ر# bRӒPQd}뭷xw9|0>`̙L&Zn]~ڴ[˗) =t,}o߾SRR–-[wW4__7h׮6Kԭӧ;NȒp-Ubyԥ7Yl&M]Oxx8{MDDDDD%He$ꃫ+111lذ/B^xطoM_wwwIKKիm͛OY"GUjȑ#)..f޽vK渺DLL VթR-:9Ѳ " !4:+GZc}a6lύj\zSZۦMΝ;'$$ĉщHciڶm˒%KXdM=<<_,|}}}p:@u$22smDll,yyyt _̝;צz4ݻr {9k' .\={l'gY\ >#֮]ktR~yzzry??omyN,}ѣ޽7xn K&7oޤSN6,5Ulk}6m"##۷oӳgOf̘ lÁ~:;wf̘1̙3wwwk?KMbb"k׮%;;VZ/[oYr -[w޼L8f?geeYax{{yJoxpl3  !!`4c߲j*V\SO=ũSXj]ѣGe O>l߾m۶a4ټy3p2lŋuGgMl(/2yyy,Y &ЧOmhԨQlٲHV\O?Mnnf92m4=J\\oW^ˋ={uk]N|Ip]%O""R7LDDBBhT,I0LуݻwCpp0رqAAA\vvY/_ν{x饗 _uk\|vAff&qqqv7̝;ךt}vMYYaaaDGGuVkwrINsΟ?Oppp}9x ve[f…:tƍc0سgOɜ %((HS~?p/^d̙6ۼ2ѣGȶmصkvGuuRIOO'''<KKHHd29; &: M}s}G\v~{Ν;oo$..ΚuVΝ;GnXr%}%77e˖qYlbM='668Ҭ)| p"ݻwٻw/QQQڵӧTIqyV^259WsҖѰuE4h!!!Y5k0*U_111Ѿ}{Zh7+V0ݝ8L&͛aQŋ֭͛7ֱdΆyꩧpuuՕ޽{̻[~k׎xLB.]h޼9]taڴilٲz`DGG3j(ꊷ7o۶mCuuRqhӦ СC3vzSDDDDK23k>p@qݻgKzYYw>|>3gb2]֒ RS=nGnܸO֯f#"""""b)"""??0|ܺu2[iX>qNڵ+ ֶ P"""b4+]v6))ɚj֬C_>٤-[V9/Y|9>,waӦML0ݻwWkʪfώ&>q[uqhUDDDDD=JN0aQQQ3{ɓ'E3g#͍RRRr W\!%%j-*"",ǎ#::wyŋa?D~_~deea|||KwUgVw`0j~e֭q-֮][,I!6GVvSNܼynGDDDDDB)"""?,Z}Һuk\\\0 `]Eęj:4h!!!Y5k0||||Hl2&M`)..vvx"? 999GXf ܹsիWc4yWF@dd$ٔͪU9rd~嗭Uӧހ+/^|:tO?sUv4e) .؍kirA"""""hkiHNNvv"҈%''3ydg蹸`20LER}-"X?U\zSZۦMΝ;'$$ĉщ44_򗤦Ϳ˿l={砠 8ŋ9sM?/// "22(:tƍc0سgOc5O>uֱn: fׯhÇNNN]R&YGDDDDDmJN1eg """"""u/ 99ӧOs:w̨Q M6?\222"55WWWFoIΝդ/@QQӹsgƏϬYpuu711kגMVxy뭷pss~:7n$==bƌҥK펽DL.]]vh4H`` ڵ{,H7>hkܹOͽ{~:0̛7_H=Jii)| ]'| .mY*Թ~t%g;Ftt4vl6km]C]D}JJi>}CiF޽{Y|9˗/~i#;v$88ئO?kfousA ۺuk.\Xc /̙3̙3>n8$ÇNNN>>>6,VFYDDDDDDDDU"Rl2&M`)..n(EDDDDD0w777\]]ygXj5c׮]6׮]ˈ#hѢ]taƌl޼WWWݝ8L&͛QزeKäIС;0ƍM6:tnۡCpwwgر5AQ׬Y3=CFرc&EDDDi"e=>|sUNjm6m;w$>>'F'"""""R}ڵ.SQ#=֭a]2*騽m۶,Y%KTٷm۶L&bccˣ[nqqΝK6mx "Mň#TERD~#K)Ҥ]vW_Q\\L޽1cK.l?,**"66T{:w5k>KM((( 11ӥKk]b4ILL$00v5a9s,\\\x0`s'X^~;233{.&-[ObLJJ 2)SU"""Dg@hh(  DDDDDDDD:%HUXXȬYt钵ĔJJJ7oֶ+WGNNѸTJ־}(**Ysbذadff~^}Շ<*{IOOVGYY?iiidffm۶:(<}y DBBy$)9E.]'}ɓsU۷o'77~tRzͅ $33&NHVV%222۷] %SWYYYW\!""cǎbŊ:';;>AQZZJDDD*..fٲeL4 ?$''VWaH4h BBBXf Q4^f!TJIt""""K)p^#-- 06}SSS^zĉٻw/'Nt3gУGm={#"MŅnݺ_Srȑ:.5kf]:6z*SNM6;wOHHC+"""ɿid2a2HV:$" .0p@vGw]x???FaIH9{lsݸqvmYTڵk,_1c0tPؿ}"6l؀C套^bӦMX$ݼynG2f͛WX*3x`򱅅a4ٻw;9F%KPPP@bb"K.~]vh4HAAAWDDDDDDDDDDDDjOS)*JK6k}*}v-cY+"R^aa!fҥKֶӧOtR%%%̛7\kە+W#''hIuy:udmڵXB:%Kp1V^]v%??(tb=aÆٍ1l0233ٿTqW2aڷo_.]ĉҥ]Rz}8s O>sPLpg|s^zwdffr]L&կj<Uzݻ$yɾUMJJ 2׹H]Riw'l+>0 ٳ,GfffsY-_a ^t_cSbү_?v#GHJJbdff~HeyOJii)Nbʕ :ԮO^`Ŋ5k׎w}B/_NYYJaa!xxx@߾}ưY3<ׯ_o3}tۢzjPIKK]Vs5ǬKU]رcDGG;xb6lǝ4"MرcoYj+W䩧ԩSZʮѣٲe aaaҧO~Goζm0l޼_l6sEx'… vI( iYYY߿?p)p|MDFF O`ĉݻ׺4Ymc_kյ^b}:~i1LQ,9>WիWf͚z!dgg0h JKKke73\|ZjeQWUe:MU׻.T'VgT(..fٲeL4z3?$''DDDDѧiO opp0$;;m[f…:tƍc0سgÇ'==|||l|2rȺ90ydYh^}ŋ9ٳytؑA1{lYY?;sNdpss#&&hKn߾M^`6LJ~HZZW^m۶0oݾ}!=uKMX΋*6GNDDQDDjڵk_bz͌3Xt)`KQQӹsgƏϬYOqo~N~;yڴiSe|s֭_~e~j*χ|2:wbb"k׮%;;VZ/[oY+a?kAA1118pׯӹsgƌÜ9spww򘣢8s oge<##(RSSquueĈtܹʹƾ}Xb&L焇/alcbbXx1 _|ɜ>};wйsgFEHH_qZ2ׯ_gƍS\\̘1cmڵ+FD!""""R"MZǎY|Mە+W `ѢE,Z1}}}>0h۶-&X֭yyy?~sZi:wη~ˉ'l9q]_ سg& bٸq#gϞ駟&77hN:͛7Ty󦵏HSLgYR7L&=z`7;v/,,d֬Y\tvi_—0o*|}}?~<fܩ_~TABaȸq׿źuXv->,[N/vԨQl߾|||xg_bǎwjՊZΞ=smL.u bbb0`۶mۛX سgO(..+BQHٳgBqwwGј: ! s1u 5e}\VDGGs9yի999P^^E^^}ϏݻS\\LHH$&&3jFC#FΛ7k.&M|ԩS 2;HOOƍmV=/Bnhz' SNDDDjINNVS:/ӧOӥK֮]K^cʕ}vS~zz)VGa 4|8Ņ~m؃#PWx;III ~_9DGGӺuksܸq䐙ɐ!C8~8|W9rcǪaԨQG`Μ9hZ***y߿?~~~|wz#`nn·~hhߟ%Kl8 R믓ٳuFm:֒Ͼ}駟8qвza{=.][XX2׵kW!B!)N,M}8s tԉ^z ///W[fÆ ,YD S!ģ,-- ',,T^Jn 00PC4kkkZ-}ɔcee /駟Vc}]>cʨnc2& … ^ZVZEhh(L0M6ƼytHKKZg>w!B!ĽS׳~zuyڵ]{~X[C={)SwQQQ׏iӦk.vafsرU}7|=u-2?!B< Mќ>75Hss1^{AP(UVMw;^[c>;vH>|_|;;;y9BUUyyy 0;;fצMgCX DDDF1x\#ie_fff_K+ɉ#Fн{w⯵wr*9^γ׎B! !1|peX[[S\\|3Q7|kwppЛbH!AEXX;w3gңGu!w>>>ǏϩSϹvnnn~իW=ϝpttԩSjStㄇ3`)cSSO=u}*>cݻ7yyy5& C?V >}Z]_SScXwr:99qiNYYYjτ XN8ALL  @Bll,'NPcyG;Wa̵SĉJ IDATɓ?mgϞYRڔ!B!9E!x@̾}8s tԉ^z ///:vhKۛ 6us^!Zj"##)//g֬Yjٳ%22ooof'DS2g?gzzzraFLl۶-˖-S|2SN{6ڷ/TUU>۷o S}/O?s϶ب/?>}gϞe:뜝նX~W i {{{w̜9`|SӨeffRYYIPPڵc͚5ٳYj;wƨ{ȑ$%%7.@AAh%˘k>:Daa +&L+B:t()))'V~b$!B!9EZnj/PFQSkFǎiݺ5;vdl߾[[[RSS[l7n sss:vȼyضmshP.\@ݔE>>> |Xcii}aݺujΝ;o;[{‚pO7 &Ю];֥ammP$B!ЪIGLL sAΞ=MAo=gMzXY`0^ !~Z"::Fcp!'apI&_+}L2D8GGG/>ˋ< aff?Ε+Wtb_}U J<<<())щ6lEޭ˜e_6xvEhh(˖-SRDEEi&{=Md^x~JKK>a '|ݻwNS߱c%%%899sQ駟=ʨ(0xի^?J#dḺk.***y&gΜa<&PܹNEtt4zS !BMx9rDN.!0Dȝ(B!&PAELRSS%??}O?q ^ׇ/C _~d6:7t֍ IJJ]_;Z-ÇG>}pqqcҥ;fu6uU'FɤIԑ)ZvvvT+BYZZҥK;w.l޼mۚ8;!BqO4B>i!Zr׽B}x mnRbf?psb-mڴQ6T0Y sIAxhP|eB!0)NB!B!Q;VӧOkjjt:u੧9w^ZprrӜ>^x ޕ(9r䑚HF!::i!}ѣ;ӧOf{{{u988kϒCHH&L9Fb3<ïJTT;vՕm۶u,'Nd֭fGaa!Fs;9={RVVFqq^Jqq#B!Bq?!YYYsNjkk9s&=zP_B<]q"3!3rH $00Po}AA#xzzݛ3gmۜXOOO>Lvv6:m۶eٲeF &LP>cgСN2˰ajB!B!ƒ!ׯ_gʕL>]yԩ3B!B^ ٲe ڵk18`t0x&LMHKKc޼y:amm͸qjB.Vq?KHH@ј: !BBcSYfmg&66HMB!QcccNS߭(q6mԬkkkY|yq 4nee/M~m{k67׽33ۊ5Ts+CiFUVz>]?[7fhBϵk)+((P SnU]]ŋSJKKjfuV^^^pB^}U۷kܝ2&PUUxu!C7|#Ӝ !B)//gҤI<|;wwww:vHRR]aa!={4.55={KEE666KB!^qSDiZ8}F#;;[bVVO=^͉upp{Oɓ:_Ŷoߞ2\Bu]rEB<9wՋ(//׉"//}G)..&$$ qww'33^}Uغu+99ߟQF3I}KMM% *uyЫW/})mR"B!FJ cΝ2sLz衎-B!)Hqx`=zcri֬YWTT`oo.vZ}Yrrr `„ z}6'vԨQl߾|||xg_bǎm6eĉlݺ֬YC~(,,$88X/gϞQ\\WR\\!L yU=33di\\\։?x !!!8::Э[7pww'))I-h?~<?~'Oʼn'O>CDEEyfn޼ɐ!C[c,,,ҫk׮:1B!h\BBB&hXBB3f0uS)%%`{pp0///FMNr ǎc۶mLvv6:m۶eٲeF &LP NC%%%\\\\t) 6ipYLb"ݫW/zꅧ'l߾p>C֯_v555[̙3KS˗ыSڔ!B4nϞ=ٳi!a Wl–-[N")) [[[ZZ u%M43k,>}z)(jժEFufŊTUUi&'22rf͚͞=X"##6avB!Qff aŊ?KKK,,,ӧ֭S:vܩqF077cǎ̛7m۶|3ޜXkkkZ-Zn-#Gd5jL>;;;,,,7nz&L]vKKKښqlVgUVz֏ի6lzAkNfHEEM6l20.!B!"{666:gӦM껹,_˗7Pv+++|}}m4 FCDD%%%tN:ŢEh׮] x999~^xAmb(..f޽0ի'O/+*Qֿ;ޞ?Q۷+WMsv5F!{L7778u?h4<|I=Q]ΝS 뻺ŋj%,,2XÇoؼy3YYY TVV`JJJԶsڵF6dѢE{7n_rM7;ի>}Zm+++#&& Zm-ٳDƏٳ|޽{\8uQQQ6[qqqsΔJǎom7RYYn|'DDDĔGEEEMt'פ1ЁeZ1d222o6mZ B!ƑSx̟?Ν;iTCB2JҺu֭ͥ[;j(β~w.]7\]]uSFQZ-~!EEETWWsURSSYb~7NNN| SSghVB!ģ&!!S!##!!Ǐ:2eq߾} .+9whZ=Jxx(۷/111?~x @FFG_,`pIŎ;())Q)yOmȓO>ݻIOOg$''/8}4]tQ]DD}v+((`mOeL<`LffQy:rssqqqщU>6lXCD!Fј: ! s1u 5o>}\V(E2.../9x !!!8::uE AAA{9)Ӭ7immο>|???\\\xXtiン3Pw]iZ***й߿?~~~|wx{{lSQQ|F뫎ѯ_?Yd z2ƠAh4DGG믓ٳuFmtީ֒Ͼ}駟8qtƸkҘk{^2E#B!Ľ&)B< 76l`ɒ%z_ !| MujᄅիW֭|fmmV>#99rpqqa1EEEݛӧOv};v V;C7-mMM媸kҘk}\rEoҦ!BqIqB4i=^x3f .4qw%AAA$&&l'&&D۶mMB!1aaa: _?;練EXX+Vwe˖-z_Gz߾} .JsݺuRSSCNN֭Ӌ5js%ŋXe eW^ ///bbbp555oי8q:e!'N $$'ORSSÏ?HpppO9rCvv6555dggnذa\px BCCiݺm388X} k'N &&jqqq!66'N1Ӧ=zj P+**(_1d}\C={PҦ!Bqɴ>B!gggǙ3gSNKxyy5:dx{{anqC !BmUUU_^^SF?aaa$&&^x$95\ӧ# L:4q^28eΜ9߿OOFdgg데ضm[-[.qeN{~7[6nƍ3j(V\h.:tB &L`n?>}gϞe:뜝նX~W ij*W{{{w̜9`|S#/effRYYIPPڵc͚5ٳYj;wƦԐ#GD`` 2ܚØk>cCBnndK)FB!^qO|dxShժ$&&?,DFFR^^άYԶٳgKdd$&NkQkPq%ᄅիW֭baaZ[[jHNN+++\\\Xx1O?SVVFuunaaAhh(|WPQQ?s=;Ço-,,g˖-:tk׮1b9p8#ɧ~Çt۷g̘1bܸq#Vرc3qDt'crV^NU舏V"44SCVXAMM iii<3xxxpٹsgsMg54a6mDZZY: B!ٙ3f: !}nƌ⋦NC!BСC$$$PPP7С#Gۛv-pIOO'44baao6:tP3&F-/tЁ_~YO߸86nHvv6=cǎwҥK|ǤpuF_c֬Y|ᇼqPOKlmmdlee%|w\t:0zh.\ غu+\z]2oǏ\?|f( .[YY닯om36vຆ4M6W^W^Q = FrS^wr YYYh.]PRR©SXhQW !Bq7Iqpss3uB!B!Z'|BDDN[YYqqqTTTfu|:7HJJԩSDEEw[]]ŋS+--EՒKXXZXhW\Q/y&@]Ƃ ())Qٿ?׮]k<8;;֭[ kK߻?7oz*:OVʈ!##V~yyeϟŋآ"ߙ}_8p* 2 MfGéחcmmMqq1|?30|kqppЛRH!B{ɬ!n_LL Zƍ޽{2e}>}.]j9z(8::RTT?/һwovMjj**Z`7n$::nݺe%==^zm)1Bԧѣy1c5y 񨰴$((DJKK)--%11 ڶmkB!#LFND||SB”^{)!@BBi!]L/T{ff&֒Ͼ}駟8qP7*G}hߟ%Kѱ $$GGGuFPP$%%ӯ@ߟZ uÇO>{tϛ9DGGӺuﶂD)_~???|M;\9r+V_q7-8@]P}]vՉ>wx߾}9sj:uK/TQB<76l`ɒ%8+!BqO̘1)!c{1u w 1c/Bx"˖-#??_o]mm^u sn+ٳL2`~EEEzmݻwWV &n޼)+Lү_?MƮ]رcMn233՟]裏󣢢ӧN:ʱ?^mS~ٳgrIu˗NiSb F#[_iB!HqBqf4B!T EeC_4_|1bݻwO> gnRbf?psb -mڴQnժz}ϧ!o)))gر ֪nVaeeѣy駙:u* 4bsFݻq۶mcƍz}zޕ6c'B!BB{Y|9˗/)xHЪU+yCQL!r1Z-'OY_SSSO=wsbػw/z 'O6k{+++VXoFHHV.]NY[[LYT2ҩStڕet h~˗/g…k߾=W\NiSbB!BpS0/1++0vImm-3gΤGPB `!uQƎӧYf^QQڵkygQ7&LgsbGLJgy_(v؁+۶m3X&N֭[ a͚5׏Bѣ>|8z|2{aڴijTy&Ν+}i0vȑl߾֮]K޽cݺu 6L:t(qqqlذx 6oL||R" l~:+WdjSN% ,--eB`ƌNAqc0rH $00Po}AAC Qԉݻ73g۶9>|l<<&:Daa:(Kff&UUU:#GdlڴM6蜣ۡLT_6mnpwqY,XY3$;;?O:o[n:G~ :rssqqqFIHH0u BѠF!.q_hl.GIdd$̚5Km={6DFF6B!BޟXyg̙3sN‹7j*;='N kmmV>#99rpqqam۶1a6mDZZӉOKKښq^{)!B!0)N .uVӹz*]ve޼yL4Ii~λK=ضm[UUUDDDpA~:t/G\\7n$;;{c;`iisgۭUVVǠAرӹsg\]]cܹشB]:C7tn}SQa||<ǎ`Bqبw#\-)͍e,_Ѹ^1nee/67̙3F ؿ ? >ߍ???u FCDD%%%tN:ŢEh׮]FAј: !B!&$)weϟŋն"ߙݻIOOWNNNt&Tի^J#-)%%EMy}uvS~:+Wd888ԩS NO!BҒ )--Dh۶wٳgIHH0uBѨ?n4B!Z2r0ߞɑ#G9͝ot08y#PW;III:gZ-SXX׵kW!ë)D"##)//g֬Yjٳ%22ooof'B!8p lذ%KbĽoAs1u B!5)NгgW)hٳL2`|QQ^[՟mmmyf\ٻ/PP1\`*kJXo%%( yKwK2KEtͼ` xET`Ŕm zAB-0K"r E~;'pf@@}?y|gy9̙ynn/KiS!\׮]cڵ9rڷo ,4Z &..WbmmͰaØ2eW:)Ę\^{54iBTTg.]bѴlْZ]wBBann˵X>+1DDDгgOiZh#L8Q{B!>Cn%9{M!B!Bj")FX&&&D}MQQQtUM^RRRn߾fffoJ_*6CBxcʔ)\|Ym;wRZQQ3f --Mm$$$TuQFe`Y|9111˩S S }߾}ӧOCRRg̘1W!B!B!BaB'Wxx8/_֖%KйsgΜ9}HKKޞ о}{'))hFErrr ""M6LN߿F#GvZzٳgʕ+;ܯйsgؔINB!f}̌nݺ뫱o~yڴi2MG!BQ;еkW}.};"qIy7o֭ԩS5B!&R9Ezoqqqki,:uAbլ^@4驱~̙3u6i҄7n0zhlllo߾:tT/s2e+!,JZ=4˾go...:UرPѣG)..wԭF^4w@c"Cbqp6B!!_ Qk:ZtСj{c20}^T}Ƶ&Ǿ>WWW:ѣcΝXXXXlB!zHr*`ԬY3BCC رcҡCy饗~sԔ8 ptt>`ذaҒ6nȁV̘1:y~z(**ٙիWFx,--:thEQrOQRR\TQn߾oԴiSƌömHMM%>>НPW6Y޽{Y͐ؕ}/zҦk|B'YdddM u5Bk* ֭cݺuD2bdgg3~xm„ l߾Pu_!BH߿>̟?kQ.tXYY1w\Ν[a ''' Npp0l N:iРAB>>4lP]8Tt^36 9ںސ_CQPP!CrssgϞ4o\moѢDDD0qDUQB!CSE&MĞ={plllB,gϞeٲeZ}̦MLJ;rMغu+lذ_YK.}GO?ȑ#ٵk%%%*%VXqFZlΝ;}/,,dϞ=o}ACQ,__ll,N",, ++~*󻒛ɓP۾۷|SӇ$Ϙ1c`B!Dmp> !baaE&33LYhׯ5Ãm믿M^x7_z{{Ӷm[RRR_ٙ[R~}̙mҤ p#F:%)}@JSN%++.]fTJueNҔbB!dᔔC򨆇{Mj:+ù|2p140(HKKޞm۶qq"##޽;IIIDGG#d6mEBB'O:*_ٳG=66WWWvڑ&L(I֭رc>|X>cu۷o`$$$pQ u ׇ%55۷sQf̘@@@ua$$$0m4>ΐg;/ cGq֮]˱c ֖+Wsu>*b̹غu+jՊ͛7?V߄:wLiS!BǗ$Q<̜9+WrJf͚CM%&] ((z)֭zt]KKKBBBpwwƆ:u`eeŠAشiF5yѲeKԩCQQѱ.<`}VZE~[.͛7ˋ 63 4y!0>>KKKj> !B!.%k׮:+___u놙i3..SڵcѢE[^zj[n;h 6mJ\\wݻѼyss19Kr&<.S}̌nݺwKv2Fe~W< ڵ;C[emVB!x|ɴ>BBrgBMpBLy;w.sέpNNN899UG;O> ܿԮ];}7nի.}coذ!A˖-ԩSL>JDB!BTVX+/f#ʴ=zxz.]m_pԩCqq1wLkyaaگ۫?+SܻwOv֭ȑ# %>>!CpQrrr6m~cG_1{l>#ILL?gɸkTvsٳZ,))ѹRFҟJ }ACQKy4*͘?]Q(=%hܸqFi-Sڔ>B!%SBGĀpttd׮]ܺu{?G/U|_Η_~ U]&MD-WñӳZcB!ģ###jJQZ$)A@7n @vv JJ'芭_SSS+U2j(1Sj ܿ)a޽,\{B>3ݻ~+Vٳj OOO>j{ϫWvSӊ/a2>.[WR%I2+kˮlؕ6}~_B!ģM*!Çk.X֤IuVz ;;;FQ۷`ѢE;jbLtt4k׮}oB!w}CɓcJJJpssN]adN8iӰgӦM;v888ѿUVO>}^xAmW*8fccCzz:111[vqqqqx{{k-WUС.֖^z@jj*f4o\SQXYY₋ iii|l޼UV1f I&\xQ]ݻwu&$CGqХ&%%Eɓ'xgl9Zjŋ9q}QەJk֬YYYЬY3eʔFeۅB!G*!ΝKΝ_>0zh)m[ͩW}e:K[?l?<3gdʕ\Yf,-BQCl/((>lmm=z4~~~TsB<^/u>/mС,[T޽˙3gXlV˹s(..YGGGf̘U5(ӛ_|֭[z*dgg}v6n+RƌCqq1jgȑj%|:v숝Ω;FQQΝOmuVev0d|]煢fҥ~IpvvmTRN8ݻwYtV_e#ezҔ !BSJs;wtBZlΝ;èLMMqwwݽC>}m86B!ģL[:BCCfjۄ ؾ};̜9fHr| j&y{{sARRR_>sQ7i҄7n0zhlllaԨQ8pD֬YÚ5kkUYӼysiժFeC<&M_g%҉ "66 pB;wNJFm`;΋Mj]tͭʶQsӓokTruvvJB۷/"55UF!BQIrƍB!BT~>n߾M۶mbj\ʶ+σ7ovvvlذv|իX[[3l0Lֶ"""Xj)))ԫW_~ٳgcaa1mBrssgϞSlhGGG"""8q"5S6x^AAAran߾Mvd…qF8@vv6 63fhL3o<֯_OVVEEEԩS5k7|O?D~~>1ie2j(=zZØ)ѣ[.T4ZL4I{q])..cǎxzz?Ď;j]r!8:/{lVZŇ~Hbb"M6W^?*snĺuoco>ά^x4ciiV,B!/B<>mۆrZ !*xeQCJ311!<<\0Vyy*r ݹvֲ?P&`hrʳ>6lqEEEL24 bjjƍ_W#9E̮]`Μ9{",,իW1ch^œCu~dĈ]=6l@pp0_}:-qFFFbL2#|2߯B!QTNՑ#GXvmM!x׏~B!zؼy3׮]K.,Ykkk>SbTڵ#$$Daaaaooς h߾=Dtt4FXG6mXh_&$$Krr/ܹVJ[BB$Q  @~~> KKKY|9=z4i{!<<~҇֔BJBzׯ_M!P"K.sNƎ[ӡ!j;wbffVaT;wtBJk3]Ct'''s[__Jsqqqckk O`YhF"66V+9GÃnݺUa<ϟ'նm[>Bkj5eM4aڴi5B,Zwy'ڵk_~ GQO[!xܹS볲ISDX33E!+WЩS*]K.⢳ ڷolee{*ƍ4jHkҦB<\J޽{)**/ {fʔ)4o޼CB_!ģkΝ?~B׷o_V\IVVXGGG^u_&Mꫯ(((ŋTzחsQ\\Yf ̘1u*P)iӵ+mU=B!Du۹s\BΝ;5> QӤrxb:tHR$%%uVZn] QgHɓ' dǎ憝ݻwxxIr6A!j7x8RRRx4M:UyРADEEzjV^ @>}*}oooWWWllleQPPз/B!}h֬899ѨQ#ܹ3˗/gj9sJƍ177O>|ҒݱN:XYY1h 6mdT5yѲeKԩCQQ4hЀxXZZ2tJO yC򨵏m۶ۤB!cM*ZA*<)-[gOT9P?~6aoNhh(3gάB!5 XXX0|ϟ^_y+heeN=Z}䄓F[Æ qww'88 Zl @FFNb4hР !_~RERHjB!OINk׮vZ9BAA۷ˋ  &..WbmmͰaØ2e 0'1M6h__5C aڴiXZZݻGPP'33333ڷoȑ#5jΘʋUWơ6""UVBzx嗙={6"""ٳ'͛7W_ߢE `ĉ4jc'Ο?qqԖ+WFbb"YYY 8ceeѿ'###ILLW^7Z+BM4={p콍֔BB!BE-j:ǚ:Ir2e /_VΝ;&VTTČ3HKKS233 !55@LM_~Vܾ}7|/mYYYl۶$BBB;ٲeΝ;9s3gΐѱbjMaa!w޽{o>u ߧOؿ?cƌ1:n!D{w9tPI41?ԩSSۊ8<ϟ'&&`5ɮɓ' dǎ憝ݻwЄB'-waĉDGGvZׯ_ h8rHy!Duqww'<<q666annNff&M6훘PRRR-*Ga9rti޼9/"ojUڗ_~{lcUN5jD۶my饗5kBGסCڔ;פO><^|EmFbb"G/g%33@-OugAA|`kkѣ󣠠o_!{9s&+Wdʕ̚5 KGNIItBXXXMe>BǏ$]I[nzΎ:uЮ];-Z@llQ1Ջ'oOW|=ZW\Ndd$;$''32$[^zL<>&LP!BPox^)IQ~wݻ[[[V\O~~>Νc4jԈX\\\{nXMh+**~?#F///SkI')KOOGRt...%F… FPN~i^yBCCQeddsiFʕ+jٳW|駸BaaQqfH۫?[YYp=ƍ4jHJGQ=]… 2d{ӓLjgݺuлwoFg}MLWnn.dԨQpё#Gj?࣏>_~ 2 r5uB)ժk=[&99YM+oO8!C1c1Q_p3gү_?^z%-[UDcKDD={Ԩ ֢E  77W!B!B!xbkkk>36mJrr2}MV+\xҥK,,,077SNqQz):Ć j:Ž͛K/%%%L>?BZISD0fY{P۷ݻ%K"K/jػw/ .瞣>Ç{nc38fffϺSi35~PʛoQQ2e ܺu;wp9BRiEEE̘1͛7sܹCff&!!!̞=}5jN IDAT777._e`˗/'&&BnݺEll,'O֨dhSL\n'OΝ;FӪU9u\iӧO'))Brrrؽ{7VRrG~~>}Z֧OٿQ#B!ģ ;;GGG^~e._#ÇUleU2$T4䵺ꊫO>*CTFFF2w\ΝKddd'$==iӦUmll --Mg>JNNfر<ӘӾ}{ϟ_5͛76lPHW[zz:?< 6dĈWvի4i҄#Grĉ 011EV){.-ZP+ 9.ݻ~(zrޞKƞ}C ‚&MBRRRK?Vq,,,O?e4k֌ubmmͫXldddk׮ I};cs1i$Zl9-[ۛQۧt󘘘OWu Gcϟs免 ffftؑ5kTy|;BV"jVZpiILLVKrr9USNi+KWYJ\\\f˖-L4[ni|YqYfh-Sڔ>B/<<˗/ckkKHHǎ#((Hg"EXXiii۳m6?Ndd$ݻw'))IJLW!<< 6T,;vW^ܹs7oM߾}ʍΎo 66~_z\1cZ"k^ 0PXX͛7;v18ҷo_ΝK||<7nܠׯː!Cm*bjj̙3_`X{gزez+Wؼy3=zкY}ٳ'< ?#gϞ_f0t=bccqpp`֭deeq].\ٳd!j52tP~'-[ŋyg9{,˖-;x`6mڄ/>>>tؑ7o֭[qttTЙPRR¥Khݺ 4M6ŋҥ iiij|9r$̟?ÇӱcG~W@IYjHԩYYYk%(-u !Tޝgeۓ___uܟϏ~[\\jZvXhF"66V27n+[lѣӇ\N>MÆ `?Z![n2k,8~x3&v'''8{,Ǐĉs~'㣾{xxQŐc᧫2W۶m5!UÃ≰sNk:ZrС _mU>Vt ?3$&&Tvl puuUo=z4~~~ܹxxܸqWWWrss3g3g8uٳg5nU|ٲejEٍ7?3ӧO3fӲeKSz*111Ghh(t plsO/l,XUСקW^|嗼;~ ד… x467l9m۶̌}vnݪNĉ5ڕe燽=VVVlٲR&֬YC6m033o߾ꍲǏ01cдiSKVVƲlC&Mpuu;.ʵ*]{UaDEEѷo_4hi=jTLcxx8[lo߾XXXP^=^|Eocu=2!cƺ2oY֭ <(v특9]v%**>7Ю*sU;):gTaƎ1_|ANNÇ'""N:annN݉kq)V  ܾ}v… 5p$$$7r;g̘AԾcdeeiL`F_|~:͚5㥗^bԩꗖp?nݺDFFrE+WWt'VCЗ3W&>>^-ҒC^!ğʾ)^+z_,ɮ(8G!6mʘ1cضm&( 5{)(( 66Vksss&MDPPz>US@Uy~@c*YU !P5B޽{~233133}9Rb~~>qU6lSLQ/o>>c}x5ޗޖsPPN"oeΝ;wB4h3gΤAY~3V~:ׯСC0d*!f>|X <G}077zEjĉuL ē@dM)S駟~,YONN&Lݻ8;;kUDW#9::Nִ^'Nd…DGG→7~5p@6cbQ[Zm{ڵk'yyyzj6o￯. Ν;xzzR~}RPPX=f͚ /hT$6/g?Ccƺ2oYJekk8p{<ֺGtؑǏ{ѻwo e8s(ۙ;wk֭￯yet$GBӦMjEff&VVV̝;W)S@e̅ƍハRa1UWQ>moذ!f^fddp)On!ZjO?ӧnOkccCzz:111:KU'k.vѣG155U/qɓ{Ν9qwy@+*}CUf"''GXNNG!*(DswwW) ~iӦ w&55oooضm?00P[Ν;9s3gΐ~9YTTČ3HKKSfffBjj*U`/]s+{{={^zVt QIr @~~> KKKY|9=eZ&MbϞ=I/Y d:t(?˖-c<쳜={Vi&|}}cǎܼy0n݊zG %%%\tI~iFɮ]())㩧tR53gQѐ'L' ۼnݚ"N8'|SQ N:EzzV\өSB'רQ4ʩ !wt Mʴ:+?scuHKKޞ о}{'))hFQx*RHyMF裏9s& .dÆ |b vV*QJϟ?#F`bb™3g>}ZRX+ K߱e֭dddЪU+,YgΜѺL_M6͛j>P; i.INO,}YoƍDFFҨQ#kUL TP9p@כ6m*79EMĢзoytB߾}IHH >>Ljj*/ݺuSs\:t@rr2Ν{wjTATJLII gϞe޽|w@NZ:x ,P?xw E*PKʌ=,cǎm۶X[[ӹsgڶ<ƌuU5͛ )ɤJ}sƒƯJ~~>666FtcјQF;^%<*SBTq/|||;w.;w~bccѣ 7(Ug̙\+W2k,/PU#99;,,, Ņzubgg#.}1ҒݱN:XYY1h 6mڤQc޼ylْ:uPTTdt? 0@gUVѯ_?֭KbÆ F;ȠAx155;;;z-nݪqgNUoE 9V4h@XZZ2tЇB!5GGGXb|7,^X0{lիGbb"~)nnnPXXK.UV^&YW~^GYf͢C9sv](Ik׮兗K,aǎꝻ啵7*3V/_иp|5nƌqNgM#ēHѣǓG}T4t8Jrl޼?tIII'> 7zB"##d„ 9.ǏO{Tyȿ/nݺQ-] 6pY>c&OFUc*Oqq1AAA1R2fU֕s5͍bW^y(3Ɯ?J]bbu8qQ'SDgjjar 6mU&933kkkv+++Νܹs+\NNNyEMӧO8k׮>7f\+zUܝel@cհaC &##CMԩSL>]J4 !x?^+UtoҧOXUQ<1E_΁)22RܫW/ƍWmsrrW^Vqap*m2! 'N`ҥ :Tw<22777 Fll>oׯ_/t1XM4-Zccc5B8{wRPPӧ={vwWb9PNjʔʕ+8::>pڔ޽{ӣG\Nc L6 dSq ((kkk݋=ׯŋܽ{RSS?#׮]Ϗ{5ݻwܺuk~oFqq1=^^^Iׯ_T|w%33 ̌`5ƌ1oyc[oѨQ#8ѣIKKwqQ_" 7QT`|E1/e-4Jد̌ jTR)^RbYJ(!0ML)bsq:1s>9s8R-9-9^x/ yyyTWWs fΜY*wm$!w myDD'NGۛ\/wF[Ç+76(͋/3fffXYYCŋYrUkR<ޘѡC&-Ԗ0ѣ 2[b 97fff8::޽{!))rђcݒc? FCعs'C <;wҡC4 {n͚5Ky=flmm[ƴ8%%%Ν;gN8p $~O HrBq bҥ 8 LLLpppFӺuF3f k֬i0W<^իWxbFaBZM*5c ڵK.K|FHrIR .kINjǏѣ ߟ>}pq|||xǘjz ̰ŅEqQĔn%bccyꩧԔ?OMZnlٲEI'O?7dŊlڴU񙚚booaaa:uӧjuX7m?3|7)rVk2{O785jyyy,X@9^$>>)!ڂ֍+%DImV!DcT*ChLLLPTmX5e[~vh{_!>/^dڵ65kHMMÃ%Kp j5{3336mZ~ZͲepqqQ~m~jבMdd$~)̜9._;CFFfff? zCn~_x駱#%%Efٳgɉb@S!ǼFInݔ=zJBBs̡cǎMyKD ݜMh2鉩)IIIeƍ$@yG}p֌1]lׯM.p~x ptt$((_~fm^? 33ׯӿ|||8}4jDZo]9V7377GVn:+***Lhh({iqpp`̙3ݻoq0tlɓYf l?33&M#+ĽŅ&Zq5 ֹsflfeeOMMMcirc޼yn9K]:t`,X˶d-=F}?o:}}}Zs1,В )m{ܜc 0h nm7X]~w68ڒ@ڲ3[qN a,"ncǒd0wm-G!BUTT0|Ν;8qBIL bbb((( **J'Y~7֮] ԖhHyy9Snh?xrrr RxԩS\ׯ;{gFaӮQQQ)}]F~~>TTT0{fw])Ow}e>ɉd=z*}&&& d}ر#f"&&/R|FFP[*rٜs|Ϟ=TVVFNN{eƌ hݿ{xxzmmmYt)K.m՜~`)//ip[mcǎwsjoSe +`oKXhq0tl5*hQ.9v-һn !uN>])(?HY!B!B4Fܹs8::ÇQ:#Phm۶B B||LFFr711*r}śo*((`:tv$'_m"IC1̞=+++7n\@Sϡ,?6m!ĽϏ=zh6F>>>FL!o>}u(%r9EVl`BJ!H!BY%@ܞ eС1˗K/OKK <<\)yѷo_˜>}:wnU'N~hwذa/o>P[B;_hh(I||<_[[[eh40a^^^xyyx)iӜ @6m?!!!ZVs&vҩS'СCQVVF^^RF>9zO< c]}#YZZ/ ӟڵk0rtB!ĽK.kJ?lh )⎐gBOIlڵ3vBVRTA!̙3z?&J08{,@8N:Y#G\RoGqq1PQ6YiӾ0`@b~x@dx fƍ̝;JU 放&Qh5g?gkKKhCbb"q!_ѣ15'CM=楥@m鏛i۴}Gy@V^ ŋLB!DٓRMƦM$9E!ƎKRRBڧ^ssRvĔ%n~P"nc+75DL8~ItttG$q^[sU*)))\zM6swwgԨQ8p;wdž ضm/fƌꎚCաC&&-ҥKf̘A||<dff%}Ҝs\>Om$ qQT.BFڤs!e4!B!ճgOtoppp`׮]iU,666\r>R0ǎiNkc޽;].]… ȠPg-DGGW\IbU[}˜9s077'11Cabb˜1c\Wsϡ],UmB!B!D)kz-ۘV8yd6$))lF̙3oUhB[U"!e* Fc0¨&M?Ux뭷xXj^͛7JPPg۶mlݺWWWeHvQSSٳgƍ;w{w„ l޼pz- Daaoݑ;ƌCBBW&<<Ν;vZٳ'׿?{lvͩSظq#֭`ڴiԩS߿??fff _K4g?oޗxiӦSSSðaܹ29Мs|?3g%hVB!B!tIrFꫯĘGEbb"555̚5 ~#BJ I.h$L!j͞=/s?< ^yeΎR<==qpp`׮]:{̌zcc߾}={sիN_W8~8O?N \ a޼y>|< DDD̈#ꍷRs___C@sΡ1cƐNAA{QPP`06!B!B$6VjbQeXb^^^ƞ,_d,--oUB!BTCߣ,--QDEEAyy9}LJ+Wbnn!&&>s1bOl2֯_穮n0>SSSx衇eȐ!ر#|8pK.ѵkWx ,Xҷk׮Çz*ߟ'xm :g}6nȦMԔ$ڒHƍϯkҔZy=~xy΁CM='Of͚5dffCff&666L4D_mYrr2*aٳٱcB!=LSDК=X.\s==l߾B!B[K.\R{{{v[[[.]ҥK\;zhN "(( o6BBB iãm6goiow<zM߾}uw4skkkT*@qq1ǎcѢEXYY5uD#zꅷBy{{c; kBܛ-+ĝ$)ͻ9qƍjKII fff8;;3m4O~KMdd$~)̜9._;CFFfff? /YYYDDD9cǎ套^R~;5vvv`bb?{,899sNHHH`ȑtMףG\]]IHH`Μ9tرUBq9y$ P4hnIIIdgg0j(yS!h㩬$88wwwlll8s ?#mQee%UUU|̙3ǨghdF^ :cǎeرC!D=B!":QQQ)׮]#??|***={vLG899Laa!W^>Ą_]gwyG~Uvͱcضm[(Ϛ5K222ug*++qss[999ݻ3f!'*UG%**Djjj5k... >ء !mԩS㏉ ""Bg .4Rd-[ŅgyƈԖ _VeRSSYv-F^K~BMRh׮];c 6h4u:ѶHrhF֭[+׮]cDDDhǎ#؂oN޽cӦMDDD'|B=زe jZI]#Gw߱|r~gmF`` zO_|6ol09eܸq@,ۮ-++KSMn+V元,_d,--B6ѫW/>sN>Muu5ݻwg̟?_gG!u˗quu%44;$yYz5/fĈF%O !ڲ=nrR!12Bhk$9EE}"7JFCQQ&L //[_pp0j7mBBBݻ7P;Z׎l2tPBCCYx1'006;uꄗqqq:t777ZqɓJuGcR9X.\s==l߾zB!J%70D޽!$m^;v0vF-i!BV":K,7 ;;l6nܹsQTܛ P^[YY) =M?j(imis5]͍CquFiR:v쨷MGqx"k׮TUU쌯/!!!h_gʔ)̟?sss@7)17n@Vw^JJJ033ٙiӦ1}tMnLje˖¦MҥK_t8qr|*++#!!#G<ݣG\]]IHH`Μ9B!B!B!$9E7>sCݝQFqvI^^6l`۶m,^Сv&-M$ѺqFҥ 3f >>2334.mTQQuN8a0񢺺 bbb((( **״"..NvSQQ ے"##)++kD@YYsΥXi/g*++rss#''{J4!B!DB{Fܹs8::ÇQ6mFaa!C !>>#G!55M mU9֭[Ç 88fVW߾}7l0[R\\LϞ=ٲer{YYY 8PoMG!B!W_UovQxXl֭رcw8B!JC|cn[>oB52rL6b:u*租~zy뭷x'<<ɓ'+}ڵkGMM gϞW^J}B!5md WUUb pppӓ˗`i!mS}|cn[>oBE":~~~ADDμ#F\Z).]6h f͚LQZZ'ڵKKrr2[`̘1SPPB h?Nkٳg0SN5su]fիW~ZK,7 ;;l6nܹsQTXXX*6mHc%;Z73R:v7Oۦ#Bkv;BhNUll,.\SڞyoNll,FN!v?\y#-&4YOOOLMMIJJ={2n8nW믿Nvv6]tᩧb:O/[syuV^?^gɓYf ƆI&݆B7_%Fg]vYyyy;uDii).\Io~IIOݝQFqvI^^6l`۶m,^3f8Rw7oTOq31ѯrm3tlB]cBqx"k׮TUU쌯/!!!JIKK_ޞ)SS!HHH`ȑ:Y{聫+ ̙3`B~6l@VV___Nӯ Z;}tL8 bcc^tЁ'|%K(ܸqZ޽{))) gggM[5_ZVl2\\\شiSjolF!FSDgGO7lK7SNYmnp^^^P[jo߾:󬭭QTDGGS\\4... IDATرc,Z++-;ٓ~<}Q]{ͨ3gΰk.e۷/(%nkk\ ꫯزe JrJkckHϞ=)**oMi׎,UW׮]9nܸAhh(QQQ)]F~~>TTT0{F㏌L'IV!y#ے⎫ҥK|̙3`????zFQ4 ܑXwvTUVQPPA~~>Vʉ'~:.]Օvtmغu++ׯ_… l߾>zJYfڴiSYYIqqq) ԜؚKOxx8| ~-o^-TMG!$''+eD_rr2G1vsHLL FVm6 2d9r$NNNLtVV[MG!D-[pE DJJ <((**IGGGȩSؼy޺{MJJ YYY̝;Y)))[ÇApp0@|}śoy[>oBmd!ڐ%|\\\~$,,_~YI`IMMeڵXXXܑXwٳ/ fR?zIk+ʴxzz]>}:';;_oO?uϏp""";bĈ\>>>|W7ٱpB#Gx$,,TJJJ())!550,,,BqyW={P4'*XdI7-** .;6ѣDEEkl2֭[wSK۴0a?~?Ǐ+q5{ӦMSG]{ͯ;v젪""""Zy#n"e}BDPPz?TWWӽ{wF֭C+=#zj/^lB!ntcxCoEjj*~!>E*++ywWUUUX///ijOOO/_Nrr2FP g/߿8pǏ덴haa+LQZZ'ڵ1cƐNAAwe7O^׿4?O?3ok???ٳg;wN^z5DDD%Խg„ f֬Y^|!Hr#fΜimXrr2*ay&&&T*9VW!BĊ6Cԯ]vt҅^zT[cԠ#Gr߯q?… #υ fĈЯ_?eX~=ϟɓ'f233Չ#33e$!hqڵ+DEEqa^J~'PuؑX>8Kڵ+O< ,ֶԔ$rpƍOg_W^yҨՕ+V0eʔ|!HrzꅷBq}U>g͚5%K=r\ oonNgggɧ~)3g$ ˗/;Ǐ'((kkkVVVj*ӱ` tU_cTݸj5˖-ŅM6QVVFBB#GG9sرcXtʕ+uJJJieҥ,]ufmmJ"::b(..رc,ZBqrtt$<<~:u"((7v<<<\k~}۰$88F7eF!DSm5vXƎk0B!BB̟?s)m'NPSꪮ& B R:ZkƍDGG봝?\›o @TTqqqJk׮O~~>̞=Xv-ӦMkoyy9SONN111 RxԩS\ׯ3{gFa,\Pg^^?>6l **8LG899W^>Ą_]gP233;v_hS)({졲0nnnw^f̘q hƏOee%cccÙ3gxwxoh4=F^ !F!D[$)ⶊoяzBJB; !BswH~~>˗/… :}mFaa!C !$$gggΜ9Cxx89992}trss[]Jh3Ю];Yh(֭Օk׮{n"""HLLdM*Zz 7'''z-Haa!+VԩSl޼Y))e.^ȠA=׿1I||<}eݺu/?fԩ 2۷ӻwoشi'УGlقZ&##Co'OqFw}NJ+(..f֭ @ϩKLL2JVVԋAۖ%)mkBnn.SN?&""vvvn.KKKx嗙3g] [-!SnuZ|!h$9EIIIAцOIl3g4vBVHNNFR; !-껩ps{nn.jG:t(#F`K:M c޽[/222?믿jG+ѲFCQQ&L //Vp ߯7z]߰a _d߾}Jrxի\hhukSlmmY~=|r͛w4 ۷oNLM6z 9sP\|YoPF СC %00+)-9|||t} zӧ{=}UyYz5/fĈ|;B!oy#qGx{{;!DccpKBynjBݙ3gr~>{,P;!Neq]xW^yNo^MMzɒ%dggƍ;w.*YO}#G\RoKqq1PRxJS||<eeeo<:t(3f?f֭7i g[ז.s2-!ՒsJpUZZ @ǎj۴}'MLLPTw<BEF8iF!D[")B!0vXƎk0B!uMةЮ]Fܬ&wѳgO?FswwgԨQ8p;wdž ضm/nQ)kkk&NH~$::#ܸqC1mJ"%%Wi&"###==?'|~555J,Сv&D.-9ꎚRw;Ҷ5 !B!~"ڼo$5jBH||}UH{JB; !0={?ǣ>upp̙3ڵ [LL vvv)LMk  ꫯزe -JNѲʕ+qttرc:#r;v @8uޝ~SN1hРFtRYv-65AAAo׮555TTT(v+Gٷ~3"֭8v|2]vՙ-7tsB!B!ZNShѣG"11f͚ Ç7vhBTRRCB$ !DI&?j*z-|A;VZg̈́DٶmՕM6M8{,zjq|'7|Sir ]taڴiԩS߿??fffJs Ν;{;a6oLxx8o P9~ƍS3V^Mxx8;wfڵ$%%ѳgO޽SNqF֭[`'Nddddͳ;v0c JJJhp}[oo2`?o 3KsΩ 0s$m٪RB!B!D$9EzTUUb '<==Y|9 Bx{{;!D+ر!!D0{l ~Gρ8~8>>>:,,,xWim"'ڵKvd͛iGڜ0awfʕ\R߉'pssϏp"""-Fx 48Ϗ}qYΝ3W^:m_IKK<:},X`p۷'$$yqa6lXKeeN HIIa͚5Y77 ;  ڜs>cƌ!==MFrrCBz%''׿$''$ !Bj"c1$66 .s)m?<۷o'66B!n3KKKj5QQQdddP^^N߾}aʕ+}mllᣏ>b\pkkkFA@@S.[sykAff&ׯ_pij5鉩)IIIJٟ={2n8Z)vvv8Kڵ+O< ,V۵kWbcc\z~OKJJ 7nlt$nݺxb贿+FUUX)S4 cccäI CJSzRR5J~LB!ҥ$%%%ڲtR.]:qwwko#;v$<<༅ L{xxq[iN "((ݯBHHH}5kfi$88Wߺ^wZ[ʧ!M=۾5*hqrrcǎh"C4JBR; !1vB!Hr{h4X]]M@@Jbbb((( **;2k,bbb/u~`?~<{졲Pnnnw^f̘q;wU!nj~gRRR/bС W_}tuQHLLYfÍBV?JqwwƆ3g;9B!g}FQ4 zDRSSںVVVl޼Ygm=鬬,MG!V'khבKVV۶mcԨQTVV[JOO7vXb^^^888舧'˗/9FB!jԩDDD0qD}QNo!"KKKHMMRSS SΞ=KrrB%''scarB{Prr2gϞ5vB(daKj{S422xlmmY~N 4Õ}%,,ӧ{nONN"..CFYYyyyJ}j-%лwoG!n;YJC<{]v2@ll,.\SڞyoNll,FN!0 zӧ{=G-{G d,^Xm@zIIIA!5{lc`TFJ !=]vA"o(Y ?uLJDbccqssСC\~ѣGcjZ_W~3mB)7'ܸqZ޽{))) gggMӛ^333 !##CINy{iZͲepqqaӦMTVVMZZ+L2cnn_~ 6Eyy9}Wyn1Vٷo.]ޞ'1E IDATpBllls簳#%%wY<==qrrbΝȑ#unWWW3g!~abbJ B!BqIr0GhH*^ʦMT4ru.]1c 7K-md !-**8eڵk瓟OEEE>|8}}###)++S7 PSRRBLL DEE)RxԩS\ׯ3Իr͛GQQvy!&&F)vscǎe̘1_іv?~<{졲777a޽̘1c%B!B!B!@λmҥK:7Aصkzrrrt5gILLСC0fe~׮]|^6m!0֭[Ç 88݇UUb"Hy~9xƌdEMԌ mE9d\QSD 0e+7SzbRdkA<ɐ:! ׸ـ.kzk>FmG|uww'777| yGزe ӟHOOgȑ:t;v~ǜ;w~۷~~X*ZqM6QTTD~HJJ$&&ҷo_N>ƍu֬Yt&Rb)R`ذa6۳YbDDDDDDjSt鄅DDH}HRq+fblذhgɓ?x{{pBtPmrYbDDvb6IOO>|ت !~cz̞=j={';vݝ(233k1`vJdd$}ݷop1b1JAAz눈ŋs}|IJJʕ+ޖeݻ6Raq j&O ܜoVWRR>jcYm\gϞ}Grr2_~%?O>Qsuf=K%FDD5k:tЏ~ ?[l%/,;;*VXA`` nnnۗ/_NUUU+g)"roS_-""nxH+u 1b?پ};6l >>裏طoeeeS .4F[Z6aV^MNNs̱Z ǏoQتYFIiHѣO?رc_BCC2eJ 6QSЯ..]2^wС95ԍ7\V3=z0elBAA999u%G^K[KHkѰ"oN]h(992f̘a͜9[LHH"""-I)nDD11dCXF]8p V˜1L$&&RRRB~O=z iؓ+SXX޽{㏉mpqʵk׌9}}}ܹ77zcz!qi~Fo߾G'0-ênAAAl۶4KzIii)jr#FDDDDDڿ7nݻ9{,xxx0i$c4HJٳg}zgFa|Zw[2j(zmoooRSS uG{ݹsXf  ̙c#jK)rϩ?y6|gf0͸1{VWD.&Me˖ /0dx_akDŽ 3<ƍ$<>9mZjj*V"::x5k֐N3gOqF?Laa!|A&MĶmۨG0:RmPjڴiNAc20NCjǦM׮]#??|._̬Yz* .Ј={,IIIWve>>>:tݻw7jL{˗?>|vIWA}H[:''N5ɉ(-Zdر5kХKVUD>DGGCLL2//Z׹ɐ[6s璕mt’%K/سgǏg?UK/d޽;.\ 777vIpp0_|gΜa޼yV0>s!##-j3f ؜ǂZiof3&i, 6m߾k͵k$&&4/%%By"""𠸸h:Ď;IPP=Prvqq!))>}QVV3^^^,\={$998<ȕ+W'5V׮]tf"|}} $00*nϞ=DGGӷo_݉bdffLtSN7iРAV1""mE[@dd$#Fn>|r^yX"""mS䞓٨xɤ' EM탾?MZԷ WWW vKttt1~~~ٴӭv{1 V˜1L$&&RRRB~())ѣ,X]ֻ}i/^oA^^yyylذya2F=s @N>]~.\,fLcYjM)"""rϨ?`>3fQc6qssHDD^T0]vZ :uC6yt=z4ӦMSuj^[ϏѣGŧ~ʱcX~=)))S7TWW׻K.ջC888,YbDDڊO[k3Wm*N{ƭSxzz2qZ㜜bѢEFˎ;Xfӓ"""rwyWn #GGZZL>OOOFy3;{kQ\\Ν;qssk>zIii)jYyy#""p1?h{+"""mm]ww}3իWӱc:cqBBBXjV"44!cEDDEnmcM^+V}% ˗SUUu;iҤIx{{m6*++2d8::q< }&55 u֬s!rG1\@@:u"=="ƍ#88؈sqq!))>}QVV3^^^,\K.eݺurU&LիaΜ9V9b "V٣vrr"!!8ϥKpwwg٬\Ν;EDD6H""""""w86mdvsef͚}{l߾xGѯ_?222(,,ʕ+|g888[sN#.33Gk>}:IIIh߿?O=vmp!v͔)SqD8WWW 7Ϫπn&DJJJׯ%%%=z еkצ]G\ҪٳFjK)Ң85k읆'WEDDD]ooo]Fff&111ZrH%5TnAA[nelڴxbbbw}?&!!(Q8q˗/o%%%>l3"Lyy9lܸ˰ 6f\ゃ0̈́`6qss~BDDnzꩧdٲeBqq1.=ݟjiQgΜ!##S;i222pttw"##)H3U,R‘]r%f3EEEH``oٲe 29Jg||BBBjO`` 6m/LJ ;f p)#[ 4*FDbh)bѢEc֬YC.]Z5;%^xm۶CLLݻ/}i9*NVnD üӦMw """"wŋy7#// 60oIN7VpݺuYf{?NHHV 44(t[ 0?/W^塇'dS}HPqH+0LL&{!"""R"5G&++O?cǎ~zRRR #w};884h}K!ō7~=2e [l_StСmY,1"x=IKC۴d?`~S}ȝVp֬Yc4D;v,is\]]ߟBLll)NiǏ[ 9m6/qpp`̘1={RZZJyy9={Z2Pv{I/G7'xzz:aaai"3gΐa4D222ӟd4DDڜI&ͶmۨdȐ!xzzhnz)((9rh&L`XF79sպ> &M?ŋG?0[*..ٯiDDDDDDDD59E*ٵIxHKKӧiY."RofͲw ""mRpp0c˫unŤ6wzx=z0w\~ӧw΅ ͍;w̙c:1cΦx j]GDDDDDDD^:dgg^UUŊ+ /_NFFNNNHhLqH@@:u"=="ϸqn%66_LEE5޽{1}ۛT֭[75vߺݚS0zhM֬퉈J 5.88> Lxx8f777fϞjE*Nvcp~q "##z* .Xٳ$%%QPP@\\,[#G{E>}(--%&&޽{aUr]vQYY2:ݻ2eJ ȑ#őFuu5ӧOӓ#G;5z:''N5ɉ(-Zdر5kХKVU:pvd2a6FD""w/|OO['mS8p QQQ3g??ԩSB d#"wj $992f̘a͜9[LHH]slTdҍT"톇7nmgΜ߿O>m>44?O6 .Э[7e6KȝVpƍ$$${nΞ=#L4(ƻMee%ٳ^z3|:wlUTTʨQݻާOIMM%((~UDDDDDDDDDDDD*Nyó!7B׵ Cua/]Ԙkeٯ2KǦM׮]#??|._b^z RXXh={$ 3]vQYYv|||8twth"""""d5e]#ߪy)joȱB㎷1l/ONRRW\sÇgΜoooRri#… tf;6KS2uT{!rϘ:u*O>h#66SNL6 R^^λqtt䩧"<<gggc{%##'Orzꅯ/!!!t&sSGGiq6F\Ĺ$11={wѫW/yϟOΝNwnwX%&&={йsgƎ+B^}RSS5j{6郷7PH[И~!y]ׯi@\[+aaaչ~~ۦ?)?O~~~Y8;;c2HLL~PRRѣGY`!SD5?ݻ?+Nqss;wC֥gϞR^^n3Zyy#"""G"d2a6FVQQy())1>s._l{%^|ERl¡CHJJ2cӦMFܵk'??˗/3k֬&ۘ,bcc) {}vG}D~Ƞ+Wg믿 HLLVii)\x7|IlWpB#ٳ$%%QPP@\\Es~'{Λz<.;w42339z()))k.*++LJC{AzM6:F >l6l͍ٳg9;L4-[ /!CcgaƍDFFΐ!CIIIax{{СC)--ئ؈5ydL&'4Am޼[o'\&vӦMѯ_?~_3l0 YbOfƍk׮ۛk׮ILL iii5ŭR5& wwwFSIoݺi&㉉ӓwӇ?ouV-[ĉС,X#禎l yGÃb9t;v0F`hD]!NŁXf Fĉ,_o0l0-m.mVC^u]VDDDZSDɉ(-ZDPP;v`͚5tىȽ$88hbbbZb;w.YYY?~ܦ(K.,Yx?f)((ɩqƵX"""RS2uT{!rOOBUWGÇ@DDÇn~կ~ŢE@dd$#FG%""_|ƍ]r%f3EEEH```19X̞=ۦ0n: 29 O||fl6f3-(++wTUUq1/^̡CN9B\\K.eڵ=zi?٪2],9Լ>,ܬ]]]'11M6ŋmr͡%X ْXx1'NZ~f-gCXعs'7w5?nȑ#ۿֳgOZYbDڪ\kҵ"""T""""-ɉ(vٳg9{,;v **C"Hd*++y`Fcbs >Ct;UUUX@۷/,_*{'~͟g__~mX___#\~Ǐ;0n8#vҤIx{{m6*++2d8::69<իW9y$˗/7/^k$˔і>< """qBBBXjxyy9+OK>j(طoq#:t@=xWرc_$''SVVƌ33guV cv"-oݻSN/&L_|3g7oղXMLL 111VҘZ/\+W,?y$>>>tޝ .;wl>q6ܹs6#xv҅%K;Qyk9Szܹs~aOn3f N[Fj+ED"i5٘뼶W׊H)*:tG?ulٲݔ̙3흎4Qp '䩧|IWs7Q]{S88z嶱?eg?#66K._c̘1c<쳬^gjj*FwF\>}&55HUߨL;w&!!@wNΝ?~<6ݺu#99iӦѻwo:vH޽9s&7nՈ `ʕ;;wsxxx0w\x&Kcrh)~~~899ѹsg;ctRGǎzj!\\\HJJd2Fǎquuח7Z߉[Cرcԩ{fΜ9ӹsg#f„ tڕsrrpqqaw4/{5wh5٘뼶W׊H)ҢƎKzzv`NADDDD(..M6]F~~>\|YfY0~zo ?Xf ps\t_|"-[p!ڵ+.\ 88sOfʕL8}|fnܵk>máCؽ{7SLi3,[e˖Yv'<aʔ)={;7o>|xlܸh~_SXX;q1cƐʪU`͚5ӿ~l֬Ydffri6lڵkSR\\lSR\\lĈU*Ni#GGZZL>OOOFiD w " *2]pp0xyy5h˖-TVVZ}vV^իiVjrtt$$$/8s ͳZ6`_ٳǏ*^u;v$""_|r1}QƌCvv66糠.ikT" UUUX@c怀/_NFFNNNvPDDDDDij5.tԉt߿?ƍ#88Aݻ77j_d ٳ*Yb?|:u{G?bΜ9<#uv֍d,Ο?OϞ=K/۳gO\r3w\~׹#F۷a0aW&''9sX2DZF,##d4f֬Y|'NCDDDb*N6)sڲdʘ1c6sLnJrrrO܉W}v߿jL>ݪɉe˖lٲzu C~ }%:: ""xd"11@II Getˀ:uԩSy'읆];M:; Sͳ$$$tR<==Dw}G^x?>;w޽{ɓ\r^zKHH՗xϟgݺudggSUUų>kEEE5޽{}ۛT֭[K5!f`mj[*==<F's._lϮ]us:ݻ2eJ^DDZ͑#G#--jO'#Gwj"""rsrr"**E;Xf ]tsv"۲e fͲw""e20Nu)H 1uҶ8E wwwQRRR(,,G!""СCرɓ'uV-[ĉС,Xc7o[oI~~>+W'77aÆ,8ED6YKhsPUUŊ+ /_NFFNNN-<㄄j*BCCsV" 'E-׋&O""w.mS.,+ܮ֛g϶gϞ=DGGӷo_fKTT'O&33(Nٿ?՜8q?||W\tfVVps~Çů~+-Zd۩S8pq 4*FDZszLYY3f0fΜ֭[INN&$$Ďى|[7:uS'|bjԩEDDE8E Kř3g5sαdN8aW]]mo1bUc=fޅ ֭2K%FDNYr ؽ{7gϞ&Md5޽{ɓ\r^zKHH]v)!!KI||<ϟgݺudggSUUų>KDDDry,SSSw}+WlkDEECHRR8%66-[ڵkQ`rss6l:\E^}U5+/ՃW^ԩS:u;wh5dk8rqqqQ]]dȑ>OH{iy6nHdd$ 26oތ1y(**zŋу'_h|MFSxm?tPJKK)..)B)..6bDDSWH>wڕK.a6)**ח@ĉ믿櫯G={WYYYDDD0|pկ~ŢE_M 0Yfŋm,)[ISN7 ]jL-gi222pttwm` IDAT" Nj4NMy|2O<-ݝׯs }N>>̞={r)c &'cƌ!;;YFZ7n\SD./7 //<6ly0Lt&!CZ;w%Kp ڦUoX|71ª30^[ NnܸaeC?xe.\[n6Y,1"""'|'|b4DD{ Ǐo7~Lj& jNɔ1c m̙lݺdBBBZ5{iS?-""홊SMh...$%%Go>pvvˋ 2x`#^?0dfϞ@ZZ>>>tܙ֮]޽{|2O?4ڵj&L`0ge9990~g!ϏѣGŧ~ʱcX~=)))6k{'Nп~i<<<>|xs:j f!KN-ǭO~wС8۹r ڬ`mΝc͚58p*<<<3gJٳg}zg[ ׆b޽dddpI\B^%$$Ęz[lxgm-ǚҥK4Fѣ9wqb {d-q ͵TFe5EE>}&55Z2֧~ZiSͫMWWW wݺu#::ey\e(b*:._peRp/BPWƅQ&jX#9diYILJTb\PI " d9:~繯xz###֮]ڵkɡspY.]GBSSSlmm%33GoSM6\|Y^RRReI.]|2OFiW,+k???̤o߾G~~rmJ!TQFuFVXXȢEYL],..ՕL-77`222(6j2; ?//pn߾,PPP Q}k@bEؼy3K,aڴi9Rp5i|T!55Z}B I/B!ʫBSlj}999t҅P5_‚$"+iԔP/^̘1cx7rQUnǚ@>}R!tK$O !(OfN bŊ̛7hժB<휝mVVV:رceƍlܸQkŋ+#BɉGr%&MTaZeSZ͚5cݺu,\SNq9 #8qZO=˨Q,!BT*CgCh*|{ZZǎӓ^z xgZ9rxX,ߩS'>///숍ήN_KMƌ .W_?wpǏ`ݺuOyo6+VkvrrZ.!;qD.\@JJ O̙3|wDFFc^xǞ{Gii)666ʬ5ҥKtMݻw#{%OKBQ8EZ|VՅ^ziӦ͎;عs'&Mb۶m$$$0| 3aE,B!ijM]>h r +++ZcVٚyuVZŅ )?P_U+j:aeC>}pqqݻwȇ~Ȗ-[*ݯ VX,QXo޼ <\y7gEzʕ+_h۶-~! Ufff呟ƶ|B$OK<-q* %B 244ˋrss%&&///ZjB9s֬YիٳKQKldddPRRy7OOO.^ȃq1ָ*}ws0xR5SԩSsE֯_߾}ɓ'ӧ)))gu2~ys^ʢ;wϚ5k4*Ņ_~.]ZϚڻwo\nSBiIBQ̜"B֭[XlY# !ݽ{ 60c .N{{{֯_OTT:PQ_qqq Ǐ'==]kVZj*y6my&s'&c;X6nƍuElllprrѣ\tIcyI&i]7n>#"">ݺuc_PP/oQa:bN8AFF2FzkB?Ӓ%O !x)N BXBT%** ]!AޓB!ôiu]/S]Ɯ9sso>BBBpssatBڪ*H@@ܹs ظq#J_cccٵkǎڵkaee+=zP^۷Gqq^1׬YCII |~h2 Q i2sW#GdȑC!B!2Xv-{&--Z) 壏>BRѯ_?eJb\]]TLFF0{lo8q7>>ѣGpaƆT>}z}T!="֮]ĉ166&;;>A8BQ_9t* arBݑ<<-E's"""8y$1BnffF^^i웟B!B!9s"""(++cՋ:4!DuBZ"3!D}9t/F__X&O됪ёXرc7ݻw鉇={7{>ښ;w*y:u*9eee 0^޻wo*BV!B!BGSD]ΘRwaf̘Mhoo뉊аAB43g:!D-|A}6䄟mڴuX5ҬY3֭[… 9uΝcpqqrrاUVZJX'** \`Ĉ8q 4eddTqQB(**&**-Z: !B<Ť8E4 NSµkט3g6w\GHHnnn:N!BQ_[,Xݻwٿ?ICM>KL6hvΝ;166&88]vq1]VVVңG)?=ZcۤIضm ̟?_c[BBL0Rѐd c!h !C!JSD.\ dK 9NvxXhٳ???ݻc￯奭-+ެ[8%==-[2~xV\1ɍ7ؾ};'Nݻ+UPP@xx8C }J{ǎ&<A@@&LϏ .PTT|Q7|ܼy_FYiK.%??{~JKK,XeBc>|"lllؐJ\\ӧOѹB̙3AYYgϦW^ 8Pס !ԩS8;;su٣ͳwyUٙCR@Rann.RF,11???]!5rH/_04$O˗WyS. xwػw/ߟ0RRRd9ygϞo}}}w5ʇZvݺu#::$,Xcǔ}999t҅PN:E`` ?ֱӧ6uBg=ݻwٰa3fܜN:aoo{n+BZqq1=KKKΟ?/=z4&M"33^zoT///bbb%77hժUG-+W0JQQQ: <-O(\0P)B'?< NNN(Ϗ97:uxyyaggGll,vvvL0ϓ )))ܾ}iӦDƏ7=<<ڵ+smeǁSZ+++~mVXqK. ^޽F!ij6K4!!!\v9s(mse߾}Bq9|2۷og:F}cmm'͚5qssc֭,[ ++ UQ A!*tJRlBDc#)Pk+lmm+쟕裏 qqql777K8E__ѣGW򳩩)JիWx饗44hֱn޼ 6uB/\)--%008rssiѢL:;;:C<<<___iٲ%ǏgʕVzm۶-+Wp ,бcG g޼yD!)*))a˖-lڴCrbcckA.!B!B4!R"tՙ)YSʪΝ;; @zz:7o 66m0h )**"33ҦM*ۢE *qysnWRIU2ٳGy~}Ο?),,;~.]J~~>cYa>JE~Xd 666,n!BW.^ Νc͸WwB!B!)NM9}Zz٠GG~~>fff˷ !Ztt4X[[s}bcc!""NSu놗:t ((`;Vaq/aaaXXXO֭HJJO>Zے8E!DVZZ/밄BTҥK[y>i$^|Ezĉѣ>YYYq%.^Ç4f|Ʈk׮qpp`ZZVDxyiiifH>|8fi:V`` WW^ܹk(--%008rssiѢL:;;;%k|\X$ !c:tJ* sss劄QSN%''k2ez/ht%++;v@޽#;;[EY޽<^!_9o>>>M|֬YAg*Ja4i,ZW*m/^WWW233\ 2dwa…\|Yi#,,T,X_Maacc7oו,6nȃx7Ki웗Gxx8o߮Ѳ59jK.U."߻wSZZg_selBtt|׮]tܙ(r=:>PÇ)**Fk|RSS$B7]πMPO2/٣<>ϟ*pV_yC!yB:ahh111撛KLL ^^^jJ !1ggg|||=z4/Aʪ}+|ԥf͚n:8uΝ`Ĉdddhn+BпRRRokR)j*2yC pppJիtԉ`N:E``C{I #%%HHjj2ɣwiݍojjʋ/ȥKq@~GmVk={pe:wDNbJ>tBhh~ǞŮ۷/3m4~`ڵ$%%qI>S5&@[n,5 ,رc=5}8y$͚5c$%%d~HJJO>Z}x"OWRR… x4f6e5 4.pԩS+GDDԸ_yC!!֭[ٺu+˖-²Vjlܸ_| ŅM6sU{饗/n,BTDSB`9t* 8998:!BSaa!k֬aΝ̘1O>v:gޥK*Irr2Çg֬Y ᆵ|cW@ @˖-INN(DE8ۼy}e[Ȗ-[p]ta̘1XZZү_:ͣUhB1T˖-+lׯzr񚼟ԱWtLu[}>!CSս!IƬhx|Rĉ>|8Ǐ;wO>{l2O^~U|\X$ !!Ŋ+McbbN!%&&­[ cΜ9I_9qD!Μ9C@@1{lzuu҅siZr9dggsA柄VVV:uh }=##V1?C/deeѷoJ iӦ /_VTh&)̌<133ئ^ڣ|x6MVV;wtKcV23rff&G%44___{T}"P!DEjV)BQK͍[uV-[VBr=֬YØ1cxȐ”Fĉ߽{ 60c ԩ_w6pB0a}222())Z}Ǎ'/^ܸq?kkk\]]껶=TD}5$$@_ycǎۛtJJJHOOW5jwJӧOSRR͛>50bnJ^^c˖-X[[3m4N/~z@WMASPzf/&R=n%Å 8t۶m㭷bCCCzɓujePN59EEEٓ^z3T_yC!SDuBF,**3g: рpppuB!4z*,\P!Tumo,BBBvF!ܹsٷo!!!0:!D]ptt믿ťʾ...?~tC[jŪUmڴ͛cnn.F~8;;r,Xk׮mNNN=zK.d}ҤI^{9r/^>>hl{4T_Eǯ|\X$ !!| !B!y=z4tMa5j(N˖-?~<+WP[TTDPPG]vk,Zweʔ)ʾ_5ׯg|7Z㧥QPP@xx8C }J;bmmMxx8Ĥ^ω*344$00s899qF%̮]8v׮]+++\]]ѣwl߾<+gϞmۖ7obbbB>}*Ą>S?΍7033W_eŘ*}  ߟGRXXȘ1cX ! SNq=z聋 o͚5ٳ'NNNOMWMASPӤIضm ̟?_8 +K,[Li[p!ǏGXk____:t@Ν2Ziy:j2fCyDFF*Ku҅QF\~G>n,BTDLAGXXJQT*GCɏB<秧!_ ٙL|||x뭷ßzzzT*eֲ+S)m=fڴiEuC>̞="ر#yyy̙3֭[+u4>s|||Xj˶mx>}zW,Аrssy7ԩ111u~|!jjΝ_(E999ٱtR-ZEej_'v??? /ky=߇OBKא^jHSDJLLOa!#G|r]!BgDii)lذpYz밚nݺE "88cǎ)){%33n:,--ۛTbbbĄM6ƍٹs'lٲSSS*,IJJp&u[RRč="֮]ĉ166&;;>h(:tJ\k)h׮~)K.eٲe 2K{Ѷm IKK}DGG3j(^xnII>BQzu9sCB4bQQQhBa4(] FÏ? ;xxxм|}RN8 $&&OPP666L}:йsg#SL ??8bccٺu+tޝɓ'o0vXZn˗V!Ӣ2B&)B!DHLLOa!ȑ#Y|B@hh(+VܜD 됞dggsAdeeѷo_233 ݽ}#??333mJ!B]۷/G%**իWӷo_3iҤ ?s̜93gRZZʿ/:Dll,0n8&Nѣ0`͚5kW%BQsڷ !4X[[WzE"##qww]3B(\BTTBRTT)))CQMSNeRƍ'/^ܸq?kkk\]]}aaa 8`طo}G=z ޽{5MG!BWfΜɅ XlpgȐ!xyyʯʎ;066f >>l޼իW}v(..`ҤIl۶ϟ1~BBL0֯EQ{ُrpphqՆ_~曵>ܐ!Bz%)QP/S_~JHH׮]cΜ9Jܹsٷo!!!0:!B!~_5- 66ɓ'8We*j755U>͛ټyV'?)'Nĉ5@PP999tΞ=ҥKiݺu^~9RfB4 ]vu:!9Z!^hL8E4zGnn.-ZҒSbggѷ 9NvxXhOܷm۶-+Wp B~;vښp͛'wl !j|+{%99}zOB}hnKJlr IDATJ!Df鳿2l0VX%%%\p\x}:oweÆ ̘1sssY~=QQQB!jݻ[???^uС:4x`غu+˖-JQ !$LԦΎ4<'/.\eמF֭s*˗/3vXf̘349rooo:u^^^Ԥ0Ԕ۷k,q%uwG!Rۥ{*͛yh޼9 {{{ț$$$k׮1gmܹ۷tBRRRpqqQf?tvvuHppp*B!hpuB!Foʕlڴdٱc ,Acz+W`kk[qZXXp=[n /(n޼ ~6u!xR WJKK $..\Zh%SN*k۶-ׯ_WSԺv_6mٕ+Ws8p@'99___K7oάYpuu%??>xZhѣȨ֯]<<<___iٲ%ǏgʕUtm6bbbeʕΐ!C45ر#ք3o޼ sBU\\̦Mزe ƍ#...]:,!B!B!c?u/--MQUĉꫯظq# ޽{|'L2+>n;wb޽t҅%KpaoccCQQqqquB;wC?ϏÇKaB}:dggsAͫ<^MӮ];'33}`ffF^^i엟B ?ܿX|||X+yڴi'Jhh( 0qaggppvĉcSFGFF[nٳ;wC^ؿ?;v$44@u[nxyyѡCرcxzzjU/faa?[~ЧO}mIII! wq9!s->" 帓StfqZ4ŚϴЌULсf"9OUa:vuۭۭ^~=r]~JKKYr%~~~ ={sss}%!?0{l Ŝ?ϳ{nBBB*)6o6_uJPPQQQcaaA~uUTTkqƱw^ @ii)>|8;wʕ+xxxЩS'>Sbbbj=˗'%%{jhggǍ7(((`ӦM !Ctm۶i$x{{j*秪N0i(ཐ9T! )0ax{{/ӣG~g4icE=?g֭XYY)Ot[\x7~zzINN/_HB|G!.>7oޜ;wKeʔ)L2E>njØ1cĉ>}TN}:J^}s@ Ub | &&&67X+ڵZ!օ pqq!55+Vh" صkxE5k֐?>ݺuL֬YCVVAAA,_ǪowtRLeoo/1115.*DCfN:ٴi{fĉw [laԨQ̘1B^^;vM6+R*W6?2ҭJϞ=ټy3< +V`Ŋ|Jrիtݻw'""~qqOUٳgvvvuV<<<1_̓UA7$2 !oD@@@Æ c/ҵkWpvvf;[ҬY3.\X5nܘ%KШQ#;ٳg2dPQ=*U[JBq,X@ӦM9~8}:aի[3g~'iiڴ)aaa=zRznk;U5@A2~۶mjn޼ T,iTMG!ăQ^^ׯ?<==%1L:S; !SNepaHKK`ŊXXX`hhHfxȑ#>",,\M988|faZVeCCCZnW1 r!lllHLLd޼y5J1}Y6oެ1ѣwԕP%駼 1l06nܨ-[7[ou%kidB!&SDPSF=DGG+ :toCCC9x t޽N}ӧ&M"667i&ƎڵkIJJbƌjhٲ%GB @v֭[K!. aѢE<3;vLʼO$Rё}H /P믿8wΝ#??'''e۬YXbsaҤIлwZ'?3k,~-++KܔEEEܹ2ƍ Q{LNN)K Շ@n߾\-..ݝ ϵk %== ޽{)((Zc֤o> mUW+iYھzRlڴi;]vBrr2>>>^VJRyZjT3fÀfRχ~ݻ;>>3gT9T!;IN7 &7/2=zԿpppӄr&MDΝ)..ӬY;;;?L0;vP^^N߾}52|899ŋٸq#ׯ*%I(ĝK !׮]c|,Z4kLa=&NP9IBԟXb +++/  **JO4-Zal–-[022o߾1qD UEDD/бcG}zŹs%77Wct邟O=!!!rA%9ex{{3n85jĹspssS*WT%Eݺu#44Tydddлwo,Y9/_ߟ3@MUڒªxtڕO?ѥKZLXyYd ΝcH1U=9|0/^nemڴ77ɓܹ?^bJн΃NNNDFFyf)U+9ru1`233իS sBQ$QOcL>8֭['_ !  ('kiinggٺu+QQQDEEiK.̛7O}ƌڗ//_Vոqc,Y›oɱc8{,}eȐ!:tt.HΝK6m8t6660uTN0x,ڵK!4X}ڮsA͹s\t [[[L”)Ss̘13LN8ӧIMMɓDGGqF|I=x >>>s;w*.l?|0dffrN< ;wՒoeJ:vT$1qD ϟzak׮j}xL4Y~=}L5j8p>8Q7n#F*?`aaQׯ_g͚5^;;;8S֭[瘟 */qu.\Hffc.qT@U\Pڕ/^߼yX*UooovѣG߿ڶ͛+ $ŸҪU+nJ&Mزe }ŅsOOKϞ=ҥ ?SЕ';w$55Ç+I^^^$VO̕Cٙ(°ѣ2x` / 4H~-U$sBQw"D=sttBB[0\ՠA4>dٳg;f Dbb"_}gϞeÆ 3w\eCRXXH||<:tPۇ...W$FeUF5jTmKjrJ233133cᘛs4ϔ+..._%RrjTm5!֭[sQ/_Η_~Ivv6tЁxpI~gl٢$zuڕ₇۶m?LJ+WV; Æ chڴ)x{{c0a~\M4O>!##ݻꫯjTN]̕Cm۶LP+{T7PV)zN!yyy,X0\\\iݺBT_ Z!( ߿-[$ՋӧOsNz-}vP̌ٳ J*.T0i@ PRRqTE|H~~>-[t2`jj˗ٽ{lIuڵkGNNnݢ]vjnݺaԦM>#>#b .@-idȐ!O1cZiӦ1mڴQa6lp׾3gd̙MNх.s.P}>}:;v **Gb``!C4-Y ?:.sBO]B!xl 6cǒƍwH1~~~q5]F\\~~~5BQ{O>W_yfIL:;uTVMNaa!K.eʔ)ұcG/ &`eeŎ;(((GXXXUK$UVqEsfU;|@zz:%%%;w>DZc(..&++ ___=//z2̲k. tNULJ,JKKq1VVV+}{ SMGxee6'd„ ٳ<Oh[b{jj*;N*B)B!СCnݺ>>>4nX!wÃիW0wאBQ;x{{=6m}KXBaFnnl߾0<<<*Q}ӧOg֭DEE.]0o޼jrrrbϞ=OKdzl2-[=++ kkkڴi͛7ԔݻwckkKll,k׮eڵX[[zlWWWIKKӨ٬Y3.\=d:Dzzt@BǏ.s.y.f̘ALL Pնm[؟}Y^:.sBN*QF#?#?l۶MӔ">>d>cueY5k(wX !cǎѯ_?/رc$<"ӌ1Bт֯_Шpr /_ȑ#חvm"##0`~+++"##}vzTGgٲe###quuS;|'###,,,x뭷غuRDccc?~ JGqq1ddd(}]Fhh(1zh֭[Gff&4o}w)_߼yWbddMqq-عs'eee '3g$;;[y̞={޽{)((Zښɓu:VB{b?~|?h  TڶmQڵkj]ުU+eT *cƌa̘1jۍۻ1jJ111aѢE,Z>Pq1ёϳ}u IDAT9s nnn<.+y$6={խ[7}ZnT̡B!DH!B!&55+++6l ĔGXnHNNV '##޽{m6N8Att4#%%8LMM׿Eii)gΜ```@rr2EEE_xҥ $''3sL}_P!oR9EWGIa!j҄Bp)))ߟkkk?ﰄ*/SS{;Sʜcǎ@E'N$>>'2zhΝ;ǩSĉ1i$K9¨Q;;cR*999J^^=11%Ks`ii;uy"ᥪ]B<^~evA@@jڴiVQdllW.űn:5k EC++/caaq2 !@;!D8%5jH!!CŅ+W2o< P@rjٸx"F⣏>R]GӦM믿SS .*hcnnnbb@YY/ЧOi͛@ŒUT}Uܷ~ˏ?Hqq1O=f֬Yfի;w.zJѐ4ԹCܺu +++|||hܸAP!$! CQTw !*.tRӧ?DUWL^Y)pܹT\$۷/iiiܼyDH6mx9rdddЯ_?ڴiS~4i-XW 5Q=^[Mx')1BԤΕwSBIrB!B㏸rq}]^SSS._ݻ1551c8s [l!??"7%%O?;wuI033ҥK>}kkk]lPeڵ#''[nѮ];mnR!B!BړoCSaԋz.?~Ak>ϑ#G勄x9::0Лr>3<==֭)))WaΎ͛7プ=z? <<[beeŦM9r$WfΝJrʐ!C ds\/"6lߟ˗ӧOΟ?ϊ+4ٓ._reB!B!=IN o͡CHiKjj*AAADEEQ^^믿HJ !6I2lf͚EBB,_\cYxsuu%114ն5k֌ *kKKKN:EϞ=С]tg_~]+Ԇ3̙3Gi;vp2d:Dzz:jTVz1 !B!BKaa!K.eʔ)ʗ=!B!DƯ7ۓT߲eKBCC9x hKKK޽Z1cp)d"##eI###Y~='??Ç޽{;kגČ3Զ%%%ѲeKF]/q 񸑪B,&&GGG}7NNNڵKa!&)A&,,\M988}vctB!Q[oŗ_~ɿoh޼zVg7-ZĢE{{{5===šEx{{]c-ZHHHt t5 :wԩSBhԩ 8PaBh:u*;wwB($9E4hʿ:uJ=88OOO,,,شiSI.UUGFFHZZM6eԨQ,X@ȯʆ HNNΝ;tڕ3f/~bbbʢckk͛7BBB۷祗^b֬Yjeo߾Mdd$ PJ^j*RRR믿pttd̀ڞCU -Y~ӳgOt9?~ABԣXz-1bCpqqo!""///"""055XHqw666; !ՈwB!x HrxrmD ]q-عs'eeepM\\\~/l2JKK7n7n$$$Dm999DFF˫www222k׮Jzz:AAAw^ ؏5)))۷ɓ'x!è֭[=חӧO+WqUСCJPPQQQcaaA~O!̛7p|M111wXB<01|O@\\֭YfzN϶mprrwBqWDDD;QFA!}X/['IN Z*).\u֍P"ҥ ~~~>^IN9BG*q%88OOO,,,شioFy饗5kZ"jǏ'00CCC^{5ݹu~!I& 6 ///ZhsnܸA1bs̡e˖\rɓ'cffFll0aW^%6633Z~7=rm} hVa޽,__~Yg|}}5j~.n>Dqؿ?111deeQTTDÃ͛WmIYHfx;w.M6Udd$ P[駟ʊHOL!#Gʭ[/B!B!JS^TPJ],//W,..M4Q~׶fm\r%1|pyjU.n++100jAxrm|qq1ddd(}]Fhh(i+WTKԩ111~o000w*7|K.)a۶mJΝɓѧOoZZ 833:^~ vݗcVoooRSSYr%<@XdIMks7ov7nHHHZ"##˫?=zHTٶm%%%xyyw^ x5)))۷O.Xt)SO;,!9|7%/ {/Uk؃Y]TW>z*?~4i3<Ù6mrsJM~ؕEGGsq $뿡U@!_u!JW*WѕC/44 0n8 155`ݜ:uJ'%%E髺Wm. !-ݺu#99YNFF{f۶m8qhGJJ qqqHOOg=zwwwhܸ1;w$999sK|\tN:ʱc cǎ\x͛7( |ڸL2αWURRBff&˖-w}|4@/RhS5ڞzΫSq߾};P`ѣGOHJJRMRRlK#6UBSNѿ 櫯!~''j'&&*?员"{<888͕+W(..&??JIcWJPP/ӓs}%t}7$2!'SDרQ#˹r ;wo6my&vb\vN( 2HV^?O<֭#::333KǎcԨQ\tI<ڶmٱyf|||GuV%zINN/_HB|G.j{ jw%$$Oǎd???&NH||<'NT۟7=zёM6deӧJQ*ۗ%Kၭ-m۶%!!OOO4iBII tЁaÆ9 oF{}0`DDDor9xtڏ6Uy缲ÇS^^Nff&~-.\ɓzE;t ٳgɍ7ϟ^V2ղ>Bu> 6x%hQ$)bbbdСC5nꫯxW믉c̘1"4dڌUY|֭f Rs9Jaa!K.eʔ)o#{t}7) B IN *SSSv]m_[[[bccYv-k׮Zx HKKW_U6{lqYl˖-OVVZ+f͚pB!Cp!ӱT뛞СC|Յw+W0~xUVyssswm\Dʞy+!&L ,,$FѣGus̡quƍӶm[ٳ1sr Ν;GnSm_]HmCeu=թ_~ -gҽ{w֭[PVVݼyZSMGtf̘ , ڵkvwB!-Ӑɓ'iӦ 9r)))Ri>IKK`Ŋ<@g9r>ClPU*M888}v4nX>ܯyZ^F! IN BMof===Oɡ,\(,,ʊKK/)vFPPǎݻȑ#~/$JKKѣҲeKBCC9x hKKK.΍;kגČ3bMJJe˖=NUU|ȯ.kTѴiS} _I&ekFA||<jI;%H}3}΃J}+WÇܜ{NUӵůj BիWbiiə3gjJSDA!hHf߾}\v&M`nn΄ 4BBB۷祗^b֬YU}^z ccc^|E"##SaッB믿as]veƌϱi֬/"sU˫Ɖeɘ &pUbcc133|~em믿ruJΝƩUw.U[ƾ5{}6 0:(O?4VVVDFF2}tB/U2o6T(n:9Baa!̘1%KU=622@hڴ)Fbj7߿(**}Ae>B!t$)3fF>퍷w{;_cZϜ9sߵ=XaѢE,ZqZh#!!!dggөS'3gv7`jj˗ٽ{֪!cǎO9s*5l+߱cG Drr2>|Ç}P~WvOx">,un ]΃>?~PڴiK%%%vڑí[4S-KT]Յ pqqӼ{xzz*IdA!Da޼y_|_q9Ν;G~~>NNNNFFڵkNPP]7nPQu122ݻw3k,Ёܾ}[sM\\\~ŋ,[Re*=z(m6JJJR׹sg8y$iiiRPQ} ;;bffV/ǣt{֬YX9s0i$lllݻwz.jKsv/ƨڻw/Z+F[[[¾}y$W^B4faaW^nݺ\ܲe ׯ_g%66Ç3i$"h>@UQ]:IĄ-[0{l[oEttZEhڪ9صU5F]Wrr2zدMG} _~cǎr1kLPҥ $''3sL@}ݾ};P8ѣGO* B+"C???ϟӁR֭YfzN$&&֬Y3.\Xocp\|pWܹFСCС /-9۷y,_CCCpppw%**^˧z4[[[Yl˖-؞5mڴ͛cjjݻk=Ɛ!C8tXZZmKOON?op!,Yo:w u%;Tm?u͛7Ν;DDDp%lmm2eF|BBPݱcG⢟'N$>>^c9TVɘ0aV⫯bsvvV[jȑ#@rН;w*UwW;Э[7fϞMdd$7n֖mے'M4:taxU]VUĉ>}TNB ]j;o_TT׷e^^^ɉPfÇS^^NO^ IDATff&~-.\Pn@e>B!BÃիW0w\ sBS]hٲ%|>^A@^ǽeCRXXH||2FFFk5vuDz\9/γ.cT.K~x.B2OWUy>_U_G5*Woʕdffbff177^k@!$!B | JNDD5 񨋉ÃVZqt0\4hN Ǐgddd~lB``rԔ˗/{nLMMuCϺu밶~Q͛G\\\KS{lcWw M6\tI^RRKl2!ݼB!zfllqqq\vk׮T7o믿=gϞ!HMM%((ŋ9s挾Bh„ XYYc ѣvvvEii)7n? wwwNr .\ 33 |ŋ4_MTwEaa!.]" @_mϙk;Fut9^eT+S=ImR-NII Ν>q1Wid>B!t!SB!CxxxzjΝ[B>e˖l2YYYX[[| B@S!%5Qa!R2J^^-"$$ggg֭[ܙ'D}u霆(,,\M988}vctBjo144$::ZYV̌Ckٲ%||i₃`РA2mBEBڵkW^˗/+޽[]roooǏ(ϟ'33 &P^=saΜ9/$''/КBo߾:u߿@fti4u:c899MKKϏ]?`nnˋ,%!cquuʕ+xzzbmmM6mHOOgÆ nݚUVp rssن 111N![XX#??;;;C$B!B!#)ֳdРADEEs>|֛ѢE ex|[RxǏgÆ 5=mpprpРA~MaXeS]v%==$B/%/])̈# <<\!]nn.?^<..8Xv-#FhEe\rooo޽{ٵk/r G쫩>d͚5LDDDвeKvޭ5% (?Z͘1Tit{Zh~Hdd$111/ ~ӷo_<<<'22Ґ!*rB]" .ͤf͚Qz%hGt&Mpuuյ̺M4AVKjj*m۶ 55X-ZwL!* ;;;HLLԩSٳ///%9‚=j7V,۶m#))=z7˗/WNffkJ!<<<_ ⋆K!xnsNNiG`Z)M6"uUΝ;9}4ݣUV5 ҴiSo~L:'''2339w 4`ذaФIذaaaa4l[[[,YBVtڹs'+VK.رǩ"Ǿ=ܮ ˋ85jkҥKг ZM6T*={6SSFhh(DhhKe >>>DEEM3gƍ\6lٳgiܸ1:/QFZ>|I&aeeÇu3~xܹÇ*w\QI&H-[_~ݻJrFv)v.JU_ٓ~RqB')BTǎ#00`֬YN?~<2n8:wO?@ z#GdݸBΝ `߾}T* EEEܾ}YXgӇ;v́:t(k׮k׮ճB:ƍ̞=k׮ɒ%K$Dm5uTC DV 4t4oooݫ|~ǓLUJݴ4HHHۻv||}Chh(KPF-{L۶m… biiIRRwY'!!pyիǡCRF>wlٲ .燥%w! @nǎ?q֫c׾}{>LTTs̙3(w﮳LSGQ=j/.ݹs.]йsgtB.]sN# ݻwѣܹsL8???7Pj)I:8vVw}`e?=Us˫*N !~rU*ׯlܸ7xbBQe}agڵt֍ ҰaC:uꄣ#ׯW5m???j5ԫW333FݻF Ybm۶^zZ_ KEb) 6/₥%xw222ذacǎԔmDDDдiSF]B?FŅ>HBQ1=PW9#00`~7&O̥KA.]W;vCԫWxZnnnݛ +j*N>+;waÆJ_VZEiԨg7=imllhР{V^^t֬YZ T8ؗ^u;ڵkGF;bbbLIj,iĈlْ0=z<6,,֭[3lذj;UnjÑ#Gطo*<==Qj(ʵSCBL#D5P&Faggzfff,_˗Yo̘13FoUe~)~N7|7|SܤIj5*o=ˢEtB}ꫯXb۷ŋa !uҥKY~=DGG}vΝZ~oJJJ*֭[?Fǎ)**"''M*e+Zu57ܹsGg;œ?ԩ򻉉I4Hs>}ujiT8ؗ^I9vŏf EYf:j4uգ鬬,%imӦMlڴIΙ3gA//}y꥗^R~o޼9Pz2c?~jycЪk_\7iӦѥKe$!Dՙ)I&&&r)ك&M‚=Ex78~87-[j-/,,dǎo*o[ZZ?J\-..Nk+W/>q݊+i;sss\kfB~Z3ϖ-[Y~y,YBhh('O.s[/?IIIѣ±<% "**Ν;iݺRǣ**vݹ|2wY?$###RsV6JS%!!OFNB!s_~8;;qF6nŋ6tXBZݻL:Zʹiӈ!7tզ:ÇYɓ'caa%^VCBǣRNnn.;wK.(#G͍7np=RprrRjX 0x`_qttɓdee#]ҥKfȐ!Z=Gqqqg}<~㼺}$$$PPP+W`رO\"ǩǾJzN3݃aiqB&[nqu^|R <ۓȭ[ʌyȐ!lܸtDR1qJ m&M?P)0SQ*3/ ))|9w+W&ΖE9r̆ tkm"KCB"jDHHCBb!!!L2aZFV: !3 44 ҰaCN8ѣ yyi'##ӧ+e3flx>888 t$O@wttٳLٸqc-[|nѢ = xwêUtb9r$|p>}۷o3w\ڵ)-[QGL6V8ؗ^IO 2ptNHHNuYMÇ`Nbdd >(5wy0x뭷-X|;Cuddd`eeŀWxT=rHfϞ;}8x ^Yd>#Fl޼͛7L_m49^rB$9EԈS:!B!z>wo4oa QkBx;wb tŽ;JMr)Yqqq4jԈ^{Kbbb/CTTtЁ9s0n86N:EHH7n //VZ1b155-u_rss%,,_VZo0|糲 ZCiJEPPgϦYf>B5e%S~}INNʊCkڴ)~~~ڵ3gΐA&Mɉ^zIb mFzz:Jy˖-ٻw/~ȈA1i$͚5ߟ/gr=yWY`fffqxyyn:iٲ%NU+icDzyf"""3gֲ6m*BT!霜[x7ˌLJoV+Y$sss… K/ȫZR&ccc&LΝ;InmgڵkܻwӡC^}Uf̘R>˖-ؘ0>|Jb͚5Z{]6xuH!3****2t~fΜBT̙3 4p$W?QCyӧO3w\عs'vvvIjgddD``2XϥyRRIqœSu͛7y7+Ҽysev'Qܽ{W'uo}v|}}۸qb+/̟?D c3%gÆ ,[L.hyf>#&M7?KF*;vˑ#Gh۶-L0E1|G(j_WC!DuHߋZ撌"Hlb0[[2dB!Snn.x{{3qDKZje谄x&OD`cǎ}}ڷo;/q%9eϞ=ܽ{=zVZ׿))Օ~###YheK@@ՋUVѩS'RRR &&P&L@TTݻwMYTT$!D sppرc*z9x EEEL6.]ЧOjT5!m3g4tزe }={_W+!*Eܿ{{{,,,8zhuGÇټy37oƦm;[olZ?~kײvZܸqٳgc֬YZ5nܘe˖) Bxx8 :'$$0tJB!B!@SDR2 %<<|!k֬ap^LLL܆B!(ΝKDDWfժUN!([YI+V`۶m_v-[1aaa<|JŚ5kx7*9x{{sx饗pttW_U\"""?ܹ3f~`Ν])1cgggF'BQw|r?sg萄xn31ch}WWW\]]ˬ_---(3f͚Zg…L,M4AVKjj*m۶ 55X-Ziygkk+H ! ڵ3t!}B<hP:!Jw^T*Z111T*´PTW_JEzzβ۷ok/IMMER)odk2q=M5}^ʒʕ+>|8666x{{W+䦗niii[,\ KS56mbaa3-B!B!D]$#ZklٲׯivI*C#߿;wаaClmmmxyy8$899GBB?:qzK!&&'O2iҤ!x >5RUaa!gΜ!&&}U W\=8wiFkYdd$ 6$??(\vMNuyyիWseݻw+W)**bڴit҅>}T5T!wߥEk-(5www}fϞ @hh([lqNË"ZlZWL:!!xJuvQkYXX/Oll,666pi"//ƍKر#~~~4lPg.];P@@ՋUVѩS'RRR &&P&L@TTݻwپ,**JSFxxxˋΕ+WصkqW={*)FZIN9s&DFF$h 5)%>*RIؾ};wwJmÇYɓ'caa=W&$$ [1gCq\S4I%GӮ]rSSSyLMMљvdr&KAAlll\kiqddd0}tlƌddd_XEt1zEDD}>>>"j56mbӦM̘1!B!B"j] IDAT^{ ###%9ɓ4jggg4h?Oqr1Æ Z_ RoN+QF3ZJRRR4kLg;2M!wvZF5k'OIIΎo㣕/<4 xZNɉ#F0h z-6nHnnneڵ 61c_I%ׯ_Z'&&G1p@LMM4hyyy:#ܸqCk;ۯJ\YYYlڴ7|Sw///v+Oi/_fԨQ899iדZqj~wssCRi%l|wT*\]]DkӦ * ʵB,\~O>+83g: ddd:*r ެ\+VuVbcc RZ?˒%KXr%ܿ|ؼy3Ǐٳ5p-V5Ok!5EFNޫƍ9t2d#F𶍌(**۴k#G{npqqso>T*;vk׮B$CѻwoYz5K,Ѫwww&LǕɞ7̘7oܹsqu[nݺ3Mi>#:v  ޽{ݻsI;v,ȠK.O'v֍ׯ?/>19q;7 V8;;WҔh̚5Kk7ѿj5̛7xf̘:7o7Qq4uŋ8::?s1tHB<7fΜɑ#G uBHHja=\^I&xzzqjvMy!k֬aʋ`^LLL YPZ?iݺ5.C y/>|{k.^~v*XJ-&IrͱҥKtU5}[nNѢE ߿==zGGGΞ=K\\fҪ߸qc-[|2d$$$`mmU7!!CV8.!Dݠ/@scSַo_%۷o`ggJW^=ZlI~X`V?{]-[u{h/fB)Q4I\~H^|E]~E=)TqBJqsuΝJ[^e M7xb.^H||<;v߿@P2M!gxzz2rHN}:_|ԴN:EHH7n //VZ1bu5qFGG7|C:u*NNNdffs94hapqqI&ޏ,߿C6mڠR bz؅Ϯꧏ= ٳN 0m4֭VyVV;wܻwVZ1j(.\HӦMuګlY} QFk,]RB!j$g=:+V`Ŋ:(Y>fƌŠ˗|2jҤ j___RSSi۶-X-ZBVVV?իZӤ\zU)))=zRHUFtt4~~~hdeyAAW SSS:t@rr2cffF^у-[Kll,tj9L(%Ul۶$zAbb"ZNsssԙ.33S#ƍYnիta \/!jf:DQyݻW#㉏'''3g#!!oooOKei׮ooo\\\J*KOO'((k-]vѶm[BBB8vƬ[q rssщƆN<ɤIO>[n\~>Lȑ#ٽ{7nnnйsg~wطo*;vK}6ڵr.\^#99YhٲeѣRXXΗo###lll?=jGhn=`2fIV yaZRKM#)%5 H(-D." IvECgd2Ms<7a;7,͍/ ׿fޛg2,m6Fŋ xÒk=ʦM۷/֭ߟ͛73h @Ϟ=%;;la骞={VAJvY|}}9v˖-c5i$Ryxxm0DCgTso899q&**x7nHVVO?4 .k׮dggDZZxxxYOJZ%)o7 8܈cɒ%,Ylӧqqqt{O=;vȑ#@wŸcҌ+Ke\pɓ'lspp0)sssc֭|G|G%ލRUKi,F#//@ZhOF 䭷bҥDEEѺukHBB8::#33l>_ ! ={^jNjTѣG3zhk!R/l۶!Z (^N-q?7772o>ر#]t!00J R]*OFXx1_Edd$ 64w!8uvٳ=z(y΀wܟgݺu,\Ν; 5ށoq9s=&uDvyaÆܽ{KrA-ZD>}xgXp!ӟ8pʾ"hƏOxx8ׯ_/(_HM*Я_?Yb3f0D %$$Cq t邏K,1Y[UVsA.]D˖-qttϏnݺΛ7O>\ *),,$11wҽ{w||| %** J׻wocv8;;ӨQ# NL\[&""O?x\B۶my:u*ƺsƆ}q-xxW,)`~-[fcǎ,XK|#裏HLLdĉ&HLLUVKUvRL4CpB/^LƍRgfٲeڵk|Ń)6o޼RqUN uDQSy}O\x.]X999)zgSќYW=OwS|-""5MSD*㏛JrEڵkgRnkkܹs;wn>|8Ç7+K֭[TiӦ^imT޻wr֪U+RSSK^|ce` xʊ4e/5R~,kk-[ۛ0rrrSpqOnׯg֬YtԉR[f>(::3cƌxE-wz8;;7|É'Xf 7ndƌ%JfN3 |gfۗ/_ΩSgȐ!tڕ޽{6mZbÖT84hP> e:"R<ݧO~'KoӻwoJyʠ͙}}Eу7{7*_HMZhiժouWHmΝ;4扌l!y/L6;v0sL>C-("#$$(;v,=zo߾MD*wwwb_+W;=fY9ӲeKϟς JA0/<<6mpyB5WG۶mڵkmdaي"h<+Gdd$*?{n:x׌S:v?O?΀?n2ki)"""5W_/2l0{9FMzz:mڴ1D6k޼9rE.^Hll,POsI8_K׀(==RKiܺu{///ر#,^[nUa"RF_}tޝ=zw:Eqi޽˕+WqrrXp7a`I<6l&--:)))pi/^l,~zˎðEvv~ e.u!"?"11''11VZK/U:&y%O?lذh[~4h3F3uDDD駟ϕ+Wh۶-/SNֶ*NQώt.EDipT+WWWADDH^^>cرY6mX;,899qQ222ӧq[FF999 0{{{֮]KXXsssٲe ׯ_/WyyyL<cݻyY={_bG iiiݻQFEqwwlmm;w.s->|Y%3F[k;v,cǎ5)kݺ5AAA%p9mIyye˖x{{FNN:u ''Ǐ3}R(HVSyiӦL0 &;{ `2U6gd->K:""Rl<:xgغu+QQQl޼YSD1;w4) ͛7HJJ"99O?'fy}`ooIII!44gϚMJJW^f e:""R}|}}СƲH̖QSZ>|[; M ,\?_Px k%"0,TqǼyhܸ1۷3x`:DQQNb׮]={Gpƍr… ݻ7/a֬Y&uϜ9@ΝOӼys5kqVXVZEfͬ(_HMEEEADj4AAD*!:Cxxz"iԨ#G$""D Frr2׮]cڴi4l˗/3gN:eKG駟Lxg^zEq2C^ߟ+V0c |-""5ESDDDj+CDC5ܹٵkΏHV|]zÌ)%co~zvaÈc˗s)2d]vwތ3Ƣ Yhi+ @`U e,,"Rs5[DP)"""5A"Hdĉ9s+W?I"Hǎqvv&))L:Đ!Ch߾Njj*i88{{{Ο?ϱcpqq1gffm۶-\vmۚlv횱,[DZ<::s2w\͖ """{|rh֬ǏCFݻ ! IDATL4JBAAOfׯ_~ ;Faa!=|Yݞ={mPf#""""""""5G3TлKBBBS\wEQQcǎG 5VWo&MѣGYlͣaÆKDdРAoߞK.aoos=g͍8,Y’%K^iPJ9s ӦM31lIHH 33GGGmV Tc)"Pb[xOOO/^LLL ͛70EJ\]]5kH=Q***bݺu̟?nݺF>}T?BCC4;| ILLݻt~BCC*&Mիٿ?7odȐ!,Z={1b}L8d[bb"Z⥗^*6fk "RzuAqǏg۶mCDDDa"R"""tƍ3[l޼za-"wy`.]J&MӦM3A[&((SҠ-[@@@@u[l7aaaЩS'rrr8~8ӧOE?0R=ai 0aXrȣi꧐ZES^wݻ/Ҹqcvȑ#0OXX_]v+L2doxN^^[loXC899e&L@֭kEDDD*/3vvv>|~Q+"u/;w$22 >>>VN~ruuaH)4 Nz!$$ 6߹s'OrIn޼(((Ϗ,c݋/Nff&!!!ؔΞ={/qjjػw/F£Z.]#۶mc̙iiB37oN`` fb„ Ʋj*5kfDM6{ͼv5""舌I)R/lݺիWĝ;w#88($7n$++~ ҵkW "--X<<BrEn1_HDOLL GvRkP+No_;vkNϚ4idddcRYf̙3M6\zOOOؾ};$!!Ldff0hР><r9v&Lয়~"44wy!l۶m۶Y; ^A\=J6mra_x'\tqz-6oLDDVN,<-<])OHMv"5ӓ%K?&MФIvʤIXl^V;;;6l-nnn|&̛7N:ѰaC 1b-Z 11,DZjK/T,"""B}С"RG?Hkycݺuxzz3x`~zjyy7XfW+/...,^جرc 6 ?? oYV\ɍ7JGaa!˗/g 68kkXp! :KrMXbccw ͛7_޽{Z/ҥKyqvvfܸqŕx,Y3|pV\n΅ ߿?%gȑ8ó%ב 1;w\]]yu떱N>63d<<>>iiQ@3HC2w\Ν[fÇM;ײeK #''N:Ǚ>}:-ZAX(++ ___{/_άYhР+3fCw\]]9sèBBBذa;w8y$'O͛?2ֽx"dffMޯgIk׮%,,lٲׯ;&OLNNݻK1\m0`kڝ>}:׮]ׯ{hѢp\]]8p |&ߑ:tgqqq1۟ iiiݻQFUĺEDF3T1___:t`rWTdd$vvvfKT{b GÆ 9vg!&&k!RopkQ:V^MJJ " (c7O?ͦM8rۗ4].InD~+o7ow%%%̧~ `2_~INN_BCC9{l7ҥ IIIN{IgÆ ?N:NJJ aaatؑs_#33͛7lC>88 _ĴiӀu=z=zн{wzA=K]zxׯ1t-Zx3<… ӟā7G@@ۛu￳pB:w  5In`,~ȑ#7|CÇ?>c(./tSe\Rb]777qǼyhܸ1۷\kwc?~<\~\}=cxyyaqqq!//'NвeK8s |ГO>iRGjiiPVVoEA~gŊ̘1A/"""R]Ϙ7o]t!--gyaTٳYlvZ&O@.\(uisΕnv*)kI/_fΜ9:uʬ^QQO?`>k$U|?- j6GϞ=\Jk׮͛77{]^^?>>DEE ܽ{88իnl2C۔SEDES֨NDÔ)SwUrHu)i3|78q5kְqFf̘aÒq?5M6i\İTăm~ʴh<< "")"""""uƍ9s&ڵ#11!X͙3gJ2::T:Dvwwwؿ?ׯgʕNO;;;پ};vvv5%mrPxx8mڴ텅4j{{{Ο?ϱcpqq1n̬Tխcǎ 0X~q*ϰTĪULΑArr23g$66֬ӳ'xsSOUY;vٙ$2339tC }:}Ą ꫯ"99h޶m[rssvm۶5yaRw)O+O?HyvPڤa"""""Rk]|///&NǏ}]Ə_ϟϼyXzKxF_}tޝ=zw:Eqi޽˕+WqrrXpaM 8}4/6_~_~ ;Faa!=|A_]܌qgddPXXHFF~!`zve={SNӹsg8{l3tҭX\n߾qrr7߬Gݻw4if}9r$w'ofn0mZCYyMyZyAGyZD2͜"""""R2m45kƷ~˰aì%$$X~-{=w9zzzxbbbbh޼yM)"KPPlstt4>4idddcRYf̙3M6\zOOOؾ}{bM777Xd K,1ӧqqqLJsMf>b#Kگn8p .0ydmfe70nܸRhРƍof߾}ddd믛l:ujD&Nh-11VZK/U>p<]E.kPTTTd ѱi&Ə:|0VrT"R1Li͐DDj};PPP@hh(ID i \ܻwPŋiܸ1]veȑxxx',,}믿Ү];^yLB&MHLOO'//^{O>1Off&;wuwR>SEђȜ9sܹ3_uƶmԩ999xxx0}tLR!>TG%O稜I)R\]]quuv""""uZ~~>gڵxyyfڵkgDD*%$$ 6߹s'OrIn޼i*((Ϗ,c݋/Nff&!!!ؔΞ={l iiiݻQFUщiRGDDDʯ}\v '''-ZDÆ Kۯ_?Yb3fѱBER=aH7zh `0DDcĉdggfNJ <œ:̞=e˖Jjj*k׮ex{{ܝwKϹslիnlPGDDD/..΢޺ID)OHm)R\]]quuv""""uRaa!X;,j1|poĉY72c F@QQQqF llW66iHZL4 /_̙3KH=KJilmmqwwݝ,Yrqpl߾;;;h۶-\vmۚlv횱T}-""""bE㣏>ёwٳ50EDy#Gɉ|wN=hܸСCXhOݻ\r?'''u 3ٳ'f1 uDDDDDDDDzh+xINNf,\F'Lpp6GGGI&OFF>>>&5kƜ9s۴iիWΎ۷3p@4/@ff& X;R0zhka5111&EDDD#իEDDDܹsܹ3GgvH""5ӓFgРA&jՊp>s<ȥKhٲ%ѭ[7cy'KAA#F࣏>"11'ĐHVx饗jEd̘1ADDJm6mf0DDD)"uƍ9sJx"SNe̛7e˖ѴiSk%"b?-seܹe>|8Ç7)kٲ%ބCNL>-ZT D䡼v""R"k """W\!''>}X;-[0c ڴiCBBvH""/;-# IDATw$22 RA"R>̪UC5ȣk̙Z; @SD'N3X9˗/W_}iٲy(''jozzz4͛7'00Yf1abccYj͚5XD .ѣHbbbhܸðiGLLL CHSDꀌ ;;;k""""ڱcSLI&ٳ^z!Kߟ+V0c HmDDJ5~xk`UZMDӠAk bBSD'Nh:̝;0|}}yǬEjzN+: ##777k!"""t&O̭[غu+oC N 5kC' |M֮]K̙3|ĈgϞ >nݺܹsݻ3gpiS1999sK.4ܹ7_|YV|[U305OyDGG 3cƌj<"uYEsAu_|hWߋ()FKuy>+KETn_"6 NN>N>}ȑ#L0˗/a|||w%!!sʕ+$%%ď?ȇ~h?o&C5xb;f|~jo%;BBBcңGkDE"> N222hܸ1{v("""R-[y9x :uvX""e?~<Ǐv"C$$$cǎ9r{accc,wG'_~0K`ڵ׏B5WMto;݁}-{=ӓŋCͭH]SVϬkUC"rǏW^4nڡH1'Nחsαj*hР)SttCwB`i֭[9y$<<##<Jll+,, ФI"K7n쭷bDDDoD*6iy3T~Z """b},_e˖sq vjDDDDY#44{rE7nL׮]9r$&u c߾}믴k׎W^y)Sq:X|`gغu+III&$''sϕ88%//P8+Wh׮Æ cڴijʤ+WOHHH֭[ 6 x|޿㶒_~a͚5$%%q |I&Nȫjܾ}v憿?-Z(|fyρ[laʕdddдiS^|EfϞ];K;W\;vШQ#ƌ׮]oq < вeK>s={˖-ߟ;t耓[la„ n j:O[hPC*~}3TZCDDDg2aN8|ܹsMzƌcDooo"##F† ܹɓ'9y$7o4.UVPPYYYƺ/^$<k׮pmkݻǢE,>,_[tԉrmv܉ K.,C~~>...f޽{5jTHmRyYޜhI1\<(PKX5>*GgHoEj_\͜"""R zjݻw?0o< L:)22"G?5m_GSlդp!2۸q#YYYS-jӒs`йsg,5'O=d$''@pp0 6믿&))iӦp!{=$%%ЫW/ e:"NNNgryr"X-iߠK.$%%8]~*+C-aI\U0To׷>CE}.R?~>}X9-;;_|s2o> һwo7n#_>|@-Xh:ѣGyꩧصk1߀w[’s``hڴqfׯ[~e{4i8`g…tܙM2a,.`t`|I:"uEmeI͉O,R|?͡$.k|UFu_PCb'OC<EDD cܹ?HIIٳgl2RSSIMMeڵL<ooo5kfwKϹss=GDDɼA*%-/>> ?l,駟 u={Y̙3SNm+**MK΁A׮]mmmwE>̃*lyfzz*[6g(3yt.m'vK,oN$W %)PKXWM~YrKS] ?48E;~_~wy]v1w\׿|&""&×/;(*3g< 򈎎&55gggƌS}ʣ%J*>|87p ֬Yƍ1cFdɝ< M6%55;wpÖ(i!6jTu_6hР\/_ΩSgȐ!tڕ޽{WoYM7nl|\ޘ-մiD%ד!i(.=O%m7'Z+rU1k%)+OW4VMoQp}3TZ,##Ç[; z'&&{1puuvH"""w%!!l;BBBcңG[EJ}gkk;dee~֯_ʕ+vvvdgg}v*^&Mptt$%%[G~JܱcGrq 6?=ϟرc333+x ~GΝ;W撔ei{Ќ%.zj۶-\vmۚl3,sQ\QSy,i9ђݻwr 1NNN5LG_>&fŹDFFddd0h cݗ_~XرcXbܾ}˗ěoiV?%%N>ŋׯ_w,9u%דalʪb*Zy<,ia9ђ<^KmӖU՟oխGgHSDj,ܹcT;w2uTlll3#."""K7n쭷bDDDoQKPPl{pI&OFF>>>&5kƜ9s۴iիWΎ۷krex.\ɓM988~Μ9ôiӌ#F(c"~mGFFɶSǒ%KXd~N>KΗ%.z8p dff-dӼ tyXfys%yܒtiKey[WUU~["fN222hڴ)zv("""}:/ܘ1cڵ+ 5kԩS7V\ X_[nTV;wgΝT^.]EJ]yaK֎㶴_8mK\_o<6zhlقhw("""~Mrѣ֭(cgRٖ :Cjgܹ8::Z&7yW_fdd0p@Ξ=kQ^0!Z܍SE7{'9z(}OeL8q"ݻwJINN?SMȑ# (w{=^{"cL}_(!! L_;|-RQİh"֮]Kݺu8{,={$,,C9B4^߇""MCˆ{)g5sH9nܸȑ#ԩO?4JL);v,wfϞ=,X'vٳٻw/ٳԫWKw^.\ﭳF{ns⎭ҥKf͚5رW_}Xs9k> 3w Pm2""Ypp0uԱHfӳR"""+"RN}:׮]+T~رigggyl+l)i&hҤ NNN4jԈI&ͻKZWo۶ qѬY3޳{4p@ Cw2-wV$''ggK=z% Z\]]4i֭?u1i$\\\Hߡ"C{ "]p/cPDDD*[n0m4:vƍW)[dȑ>|Phժkӌ}ʞ9se 8q6///M暷/@@-lV[Ν~v/_ͭP96Sg%""3fogDDD?"R(IOOgРA;vٳgy |>|zѾ}{h֬}-|*_5* OjMٻ%Q5E: ]0*n֔C h4S%a1u^̘1'GJJ O<}i[DAb%(IIIɓ'srr,:RSS-fb1-T5e===9}4ׯӦ*Nz8y$M6RAquW=㋵j׮w}lj'.]~{͚5pW\f͚\b.#"""""""WGZDRRR4k={V0? /ĉCyW ggJ5-iyӧOj۴nKHŦSDʡT^~e{!""n<ϟϘ1chڴ)4oa<:t 0a&L(ȑ#ԨQ2ׯ{)¶mHMMee]\\9r4p@lѣGy7ۻuVdŽСk֬;,VfӦMEa,ڵ OOO֯_oSmۖ۷^(4 /PfN)gn޼ɑ#Gw("""nݺ;0zhۧ{4fv튫+f͚1uTsRʕ+-GGG@*UU "&&PnkV^X www:t%KJ4#``… ]t!22溬1rHz?`M6%f͚,^]憳3O=ӧO祗^2=z4uɉl~֭ժUcΝbݹs'իWK.%>^8$$${ я~)oh4Ƿ~{ǵEDrv_YjgϞӓ }\\\ d,[_ބӧ6hM5={J>}1c= 7n֭Ջ fvnn.&Mbʕ:u @2dC.];#'K.矷""\eâEXv-uٳٓ0W$AAA"2j̙3۷Q]iٲ%PT -[~@} bd-#R)=_">>w}fgeDDDDDDDQrH97U>#iٲ%1114oޜcǎ͛eС<#,]Ν;3h lBpp0W^O?Ã<''γ6mʒ%KxǙ2e SL>3'̘1'OO/III_ұcGO`Μ9wMNYz5ḹuVڷoO}."""%ʤIxw̿׭[ٳ-fbi׮]DDʳ 9S!HL)RH9sA|}}V`ۛ%KOgNԩ#G$::xwܹsO IDATa2g7n ȑ#2e /_6_v- ,0/Ӯ];ϟWΕ+WogϞ >Ç1~~x ƌ3K}>>|iŘ1ch߾=O?4JL?d0l]9wk֬;ڝ1ܹs3f GfΜ9EJΖ1477~!Cp̙2NFcSDѨYSDDlر]={ZV}?3!!!'ҥK!884y~pE6mJ 8umbѬ^H ѣG-ʾADD>}Y{js,""R ֮]k0D*Do텶ËRTQ,'sM1w\̚5kpuu-l"(q>{^z1~x[܋\Ο?ϤI0||ez)oc )fN)GRRRhѢrfϞ=1 PJjԨAϞ=IJJ2ΈcΜ94le9sߛ>f͚EFR 7o޴ [TZm۶1|p~PjU˂ cѢE₋ ͚5m۶ٳ:uꐚRԧOB%rӇ-[;ȃjժ<̜9&M_aU8/ŋ߼m\xŋ12yqёu?}9McE3.]JN ̜93g[&!!B ĠA̯o-mYݝy1o޼ 5':t_Htt4HXjCIg(8uRR|TR}Ε+W>}:;vٙvCdѢElڴG=C`0pB6nqvvˋW^y={1n-[ȑ#GGCDDDPZR9wʹiشi~m}},\[r%}Q:uoAխٙƍǎ;۷mX91y…=&MS*Γα VXs=GZeԩ?+V_H$?[Gk;wҠA\bs*k1X_֖+lVXAtt4TZΝ;3b,'Ƣ1HDDr´֢(77h}ZhAJJ 7wX""""YfLݺuILLСCdee GGG&N@vv62ϟ'66tΝ/Qϝ;e˖ݺu4Ҹ~:AAA7|-Zd… XWZc2}t$YYYlذpwwKoZvC ɓ'$$~bcc50}vq/Cigtt47b䟟I~_}iӦо6mڰ~6nkfeܝף-cmI:u 5kҾ J:Εd 3'deezjrss)A""R%)))ԩSǼHeĉPXv 11@{@)j;IOOg4hЀe˖ôihҤ WN:,] c8t͛7gܸqxyyqiؿ?֭3?n19gu6l`ڴi\b^|9cǎ{888FXX;w,1ٵkgÌ?sg^Z˖-ɓԭ[/>>7[T۷Rg(mi^>;)q8Ml(gyѣG_7ɯaÆeDĖqі֖Zj믿ΡCpwwgȐ!fi_Y_%J2ԯ_UM^js,DD89E0ȃcȐ!|׼L8/}DDޭZ!WM65;^^^zߙ3gѣG8q#F0ydHJJb9r$.///ԎǤUVMG}w(gϞb{-8wMxxx|P4p-I~/_ͭ>6SbhXk '''jԨ>˰a,f(/I}MdmMIƱ`Z-77X4Hq"RdffrQ͜"""B\\oua׮]zrXDDD*$` wRj";:y?[E׮]iժ۶m?̛78|;.UraիGYf۷T$$Fko7/mq|q/CI8K/gyCmʈ܉-㴵ף-c$m5]Uܝ1ggg#EcG)"@ZZoVrTh/^d|g;DEEY4ӧY~qwwGуCe.]Jtto&%%k1ɓ999JEjjrF6cq)RRR,SRR7[n@JFI?;),{9Oj֬Ʌ r 5kִgZfv`hX[Ѧ5J2Ε8fM,DD8/"%O}P}m&) ^5bmt+qX4Hq4sH9`4Tv""RO1dXÃ˗/ӫW/<==Y~}¶mHMMe\\\9rupp0QQQL6iӦYc:t`Æ L0 &ȑ#iӦԎFXl_~6֭[9s ׯ_hI[swwg75miV%=dyR9ֶm[oNzzz~HOOoT^5bmt+qX4Hq4sH9`4iѢ)U_~%O?4[l/?Vb+99"=uDvvv_zubcc '''СK,xʻW^L0'|`ˋ&O|ǸnjC׮]quu`0ЬY3Noʕ+K J*ԪUA`.777/^L߾}UNNNԪUd7 4hЀ|r|a`W֞'EcݺuZjܹP;wztҥ̏A*;^5bmt+qX4HqHevm?=`_~FKDDDD0}XJ,[LL -bڵԭ[gҳgO:t#,/uE@||}Ӈ-[; -"R1Ӈ; 3%ؑhdCDDHK.wӓ]vU/DDDD`0DDVw"""R (9EN~G;ZhaPDDD,|DEEjDDDD@PP@}`DDWe|Qr(9EDDʕD"""pssc֭o!H'E}H֮]kO>EDDL)9EN8/dСlذwvHDDDDDDDDDDD*%IJJ zw""Redd0zhү_?PF {%""""RHNN6o;z(M6:&QQ}SZNYbnժU$%%ЪU+M/R8zSD;vL3l߾ʕ+5uTZӟؾ}{)hdܹ\"v`4 w""R 3h ;ٳ Wr<0tٳ9|0TV 7yft˗9w{h222,nMvv6:tȼƒܹsqt¸r YYY^\"##lqĉL0۷oӽ{w]Ɛ!C8y܅ HHH`ƚ.##PΞ=k._r{[- [b?>-x XbW^>9撜ϽLڴiS6mڰ~6nkfkܹsYl[HKK#--ׯܟ͍~͛ڵyߎ;h׮{O_ 6B\\6Ǯ]DD0͜"r䐖oo4K9"888覦L>\\\0 >\coy&~~~6gϞ%zT.Ǐ^`ĉL<;wҸqc{%""""bdM3nL۷W+Ů]_S:vh1 6fZ.(**&MDF4i@ĻKZyVWm̘1ԯ_jժIrr2})%22gyggg|||7n[n5ݶmƍYf8;;{wO`K%aK,;voۛ̚5ӧX,sTV}aR;z(KRRA 6(#RX;NxVZO?D޽INNHڸ_?L޽9v{~-2HDD*<Νرciڴ)4oaܓΝ;3sLsrƍZ*|l޼Ν;cL7mqzQ'N'6-kv96mzzLXloѢE==Mhh(;v`ܸq?ggg{%""""R d|||HMMl۶-[A-صk:t___<<<,k)`Po܋.˙?tll[- [b9|0գ}xyyѬY3[d&=XxBs6-*-t׮]iժ۶m?̛78|M^{55j^#!!t^׽iw´HvcǎQFTZ p-z888'X7!!k񇪃m4lؐH6/--.]C裏2|p_nQ… 裏JPPPc˄ hڴ)UV͍֭[S.].\`޽L{͑#G?~yիW˴/cZӅm 'W^ߟO?L7nL&MYlmW^y/WO#*7eh4@nJw´H裏HNNe˖SO=7o&66C#tR:w̠Aزe9O?Ã<,F9vaaam״iS,Y?Δ)S2e } .~ɓ<KRRzc4/cǎdgg'9s5jTYuHHDDnnnlݺ;$2SfMHNNiӦԪU  OZb-._L^dm6RSS8pEy|[xQKaٴi fwpp0[n̙3Z_Ŷe=oaޭ[B7Qm[- [bС6l`„ L0P]GM6ei۶-۷o'==???}ZZnDALTTӦMcڴi\KE%1h ⯱5jbۛ~(v]"""i2j*w|}}IKKɉ8:uȑ#پ};l۶~Ν;F*Ufɒ%03g7˗׮]  x1 k׎zDGG3w\.^U$""ֻ|2 _~Ջ*1EDDDD*Ӳڵ+Pfi.3zh֭/w'NNNӡC,YrߞvY&/k׮SO=y饗Xx1}VZ899QV- %Kpww75 ,\޽{`K.DFFjߖ~ޒ%1cеkW\]]1 4k֌SPV\Y}QnݺQZ5vYhΝ;^:]t)i;ӽzb„ <  ^^^0yds9[x衇n׮]e J*ԪUA`(QEDD s?jժqƍbרQK._߼y{4yQ3҆7o4QE...ܼyL\]]u]v 777+V 44CjՈdĈTV#""׿Űaptt?6OA-""""R$$$dk,&&EvZ֭ ٳgٳ'aaaf@'(("_W$XfΝ9 31xeV."V{)5sHͽ+WϔHRm.ӗE4ʿ6I9{,mۖL"##yljDDή^СCyyIKKSb(88:uX$|SDDDDDDDDDDD)"O??%Ǐhdʔ)5 GGHŔhDDH>}$&&l0DDDSr}`4"""/K͝;cH۷Cb]k; "rFj׮c=fPDDN>Mhh(;v`ܸq?^O&HH``b;"rhaѢE5{oDDDDDDDV""oM@@"r_8p={; 3l03j(bDDDDDTbbC)Dc0 x]YWDHLLI)W"R2339z(EDD`Ŋxxx}veH'EDZMDqppw""RRSS}d._LDDV"<׿ŰaèR _}]twH""""""""""""v2f4iѢ^ʨQXhdxxx;,?mGiӦ\o<*oʢ^k)XUZ$Zj EDJSDʘh$ aHۺu+ܸqիWӫW/{$"""""""ӟ}TFsrJׯM4ޡ<Д"RrrrHOOC2رc;w.*ϧVZKDDDDDDDT0 eeVHA7nߧwxzzЫW/ƏObb"vPDhD*o,ZhaPDD ݻ___XlWVbTHV/#Zx1/^m ŋ,^؎<"RRRRpqqޡH)&22^x///8p-[?!!!ߏ?6mޣGٸq9tԉp2 &2LL̙C=hݺ5ݻwg޼ydggq:q/2uTnܸaQ~`ĉtܙVZѿ6lPΌ >#?ЪU+^~evZ.]>_M6?"cl$le˖-ӡCs̘1P`{w_ӵ}T@/1\TR1Vm^-mVҺjk耢 !Tj WB"2Md8GH~4g~qZW\sI{JNN֋/(IqSNEFF*88X{m۷.\`kn:up_g8e̙7o^###l2h„ gv晸~:]O?٣W^q)@:pիI&QF*V8P[˗Wڵ0IeӦM*P~7K"""$I5bHRJo R MŋuժUKڽ{BBBT^=ٳGV:bŞ+o}J~WEʕ+Q{mݺU/$ivt)=Ú?vܩy顇ɓ'pB[ۯZ.\У>EiΝ3gN8.#~^dYt$)((HvءٳgKmۖg~$=ZYGq K1 O<(;tQ>Ї~-[rʮk2*F}udkݻ:(>>^۷o)͛7Osݻݡl&MU`T}I;3z-UPA $ض[mԨQP .1c(44T?e̘1STn]=Zi&[͛7KF5kM;sG~H[j޽Q~'}g%)4Gu-n;&=ci\#@.9}])hۧ5j:=gէ~j+NY~<<<4d^Z7nԳ>(P@M6MCG={VԾ}{Otw:8ү3';wTBB=cȈuz3gΤf]N1r Kꫯ: -[^{Mڼy(\ҥU~}Zj*[$bŊzGtyU^ݩ-_~Y˗׏?޽{k:xwFa/D7eQf 6j׮]m?ի6mڤgϪo߾iUP!ͺݻ_~ѱc4`6mڤ+p:8ү3ҬY3]V{t}=zTO?t]4iD[lQDDׯfuԅD0r uիWQYr:wuE&444֭[KJ,N3rH=*X$IE˫`*^5k ޵-J. u*V??okWX1-X@;wVٲeU`A-[Vݺu… Uxq[[www͙3G;vժU+3& G5J[UfMM׫W/+WNK,[dʗ/n c(NrAxx֭;6mڤ:uhݺuZr.\%J:￯UVŋxVZ_yZ!W򣰰0l1)((H_|:v3fL2ҠA 2DSN$k_S@Gq u曮_;wT^t?aN P@@c@´>@;|T^=WGޭ[gyF+W֡C(L9aP]kPϞ=u͘1C,cw9aU  \!))I&LJ.p 0s 1ѣGիW/:tHSLU T``c| 륗^ru h=zԩ3@6: :`Cq Ξ=(խ[QqiG;vرc5zhVȦN:: dXcΝ#GbŊڽ{x Wm(NrPXXx⮎BR2 IDAT ԿmذA#GXyB``]G(NrPxx8S@.[x2eh۶mjܸ#!!!p___WG} gϞҕ+W4d}:t>#.\ձN::Q䐘:uJsuwVZS7nT-\ T"<<\t5[:tP۶mNa @)@ *V(/lذASBBV\ۻ:)@ cJ2dڴizJa䐰0=3yջwoEGG+88X]vuu$!FNr@RR>u: InRPPUzuEDDPO0r ;x'8p@={ٳg5gՑ9j֬(g$%%i„ UҥNa @>)@W͚5('9rDzÇ5e >\ P3 )5kh֭~m]xx֭T7hԩjР ,_) J,\ݻwWhh+7n:ܳk̘1zw}vU^ձ(NTzu(P@}:v쨨(/P%TF uY?k׮:.1FsQztuٳGGVB.p?cCyխ[7ݶܹsڷoBCCr:q, k]pAƍiܸqiw OURE:uT(}Q=裺v ,oŋk*Snݪƍ:\i}UTI 0@ջpe+ٳwﮰ0 Sc8xzut&LD}.HkƍբE WG1r t)Gt.J=zW^ы/RI8RJyUfM 0E56lؠ~)))IW /H0r *Uĉ˗/׆ _`.LwOll 6mڨI&00r 9sFIIIJHHȑ#ճgO5iؾ}zhk׮{#N\uY}Gz>#W\QF_իWWDD)#N$_^5qD+Wũ wW^:̙~:1Ƹ:.]ZQQQ^<(777WG\'jҤIjڴϟ+:PFN%I(Lo9rD={O>DCbqu,!\ȫ5kʕ+u֮9.%%ESNU 0 68ImڴѦM\r!3Fmۦ*U:(1Ƹ:1 c4k,5J>>>Zh֭XB9p)sΩM6>|^uٳB\kѢEzU|ym߾]|$NjS@:Zdcy˗5h \RÇפIXgrm䔐(H"ڴi] Tt)X<)::ZÇŋկ_?}'*^c ˵poYnﯔ^Z/#>)L Ghɒ%9ׯ_ȑ#5w\uE_~J*X%K( 1܇)!!!wP!>eGׯ_7|ô{ dWΝ]}a;b WGx;V~ڵk9stu,0_#44Tz҅ 4|Ցp8|"11Q'NԤIԴiS]V+Vtu,L %K( 1YTTʗ/ŋ*U];b$c~wzJ^^W-""B={Աc'hСB;wvu8>IRBB.]^{ũHNNԩS5n8կ__aaaRcE:upu… %I={L^gqو#cg+yo'N3h,c4sLիWO o :8-222\v 0@*Tʗ/@9rn{ŒrPuI}Z ںu|||t}鲭[NzհaCIV/N8Cڵk6meW_}UC՟m߾]>>>ĉ32`IҼyn_`$/wý k]tI:tP߾}էO߿_5ru, G,\PZ_\y쬖wܹ:u<==q㆒tmܸQ/bbbԭ[7Z\2{l]|YG'|"yzzꩧܹsڵk/3g׮]z$רmfҭ[ԥK͜9S=3믿NקC=zYo}ՇBcǎUZTxq=wEz>L+V4iYfIvޝiW^yEJO?4._5k[;vtři+UV-:tH6mҧ~n- о}TL͘1CJRhh>hpЧ~*IZlƍڵkH"*XJ.-[e2 8%X:t֑<֯_a׮]Snݔ6mhioܸQ4dȐt6lP>}:h㏲X, LGX,Zj3n3Yn]ƍ%IW\0$yxxgϞJJJҢEl[xս{wyzzJʙ[l(uM]t/p8s  *C˗W``9b3Řԩxr ҍ72e[n*Rvf}fΜ9 H"z8$mذAO=:h8~,ʕ+$mT\9[{+G˝pl'N$i&~G-Iڼy\yV<+dt4Cv}?+ZO?:]OְaTjUyyyD_}?8p)]lL[dIFRKɒ%3sF1QQQ/^H2W^v/H2͛7YfF1cFm̱9߭[2ݞÇIjժiժUH2uޗ8rYˉg&? 0իW˛~O{#ﷶnjwӬY&>Y[啦… M}'̍7#))ɔ+WH2{5k.#ɔ/_$%%=k-Z}ݥKX-[(P5ڳgO91H2+VyʕFϑq6[J$3{lr[no=d=ϊ#͐չ9s/Rdɒ _߯2 07ntu483 TXќ?־CNS<6y{9%QJ!!!*VV\)ootmYhlN믿A_f6O…s$VF 5iDǏ׶m$WjԨԩck{%7111߿ڵk-[СCj۶c!Rǎuu1B'N͛7sN_ ŋgIL4ɶ}}i 8P4hN>mݺU>>>:p>t֭[H=jذ$WUVŋ?gzn'NСCt5M6펲HҫC?TBBo.g9̀$Iͳ}o4glaÆIVZi̙:rRRR2=uuVyV,{w;CX*=LIIѥKԷo_h񮎖ƈ#VZ),,L ֭[U~}9sFAAA+WtYVWy@N0rߜIȑ#pb+WfخXb:Hv#Gߺ>'d_f_pdzm1fȐ!F3gNvޗ:uw9/b*Vhʖ-k;W=.&Md$1cgĈnڹs)TdFf[on{IKcǎF4iR|d:ud7P{#t8߰aqF#<0ƘxST)SP!s4.]d܌y1fl)))fԨQF)Z7_'m{;yVr*CN#nږf͚fĉԩSdt/I2n$?~H2޶uws˝rpc#IڱcCǫk׮վ} V\Y-Z$Iѣݿ.ݻwO>;͒:w%KjŊWHH-nݺi}lrO\\g}V 4СC/:5kHjwu$gǵkԭ[7%%%M6::Z?,lѣ,VZ s[L[׸qcIҕ+W2!IٳҽZxս{wyzzJʙ[fX4e֯l٢ҥKEڤfo}V7c69])=zd4ibmo$sϥYkI_6)))ג}IСC9ȍ1&))m.\H2&444=jߌɳSRwnwz/)JLL4?ٳ)^)Xiݺ?wMӰaCϚ43[1&22Ҕ/_ .ߋ˗/޽{IwImرGvFʰݴiӜ:wc3gdJ*e~mu,_~}_ׯ_X,ӽ{ ٹ_{)N%ϟ7%J0L˖-ݻ͛7ͦM̀)T9pm+WIN:ƍYKHk~SfM#Ɍ7cڵk$Ӱal'$O?eKFGd̶g><dr5j(ݾL|?ҤI#lݺ~ޗ~NĘɱB`gQfsY8%8b^z%a<< ?ǚ1c3_5R u֙[nׯ3f)QΜҥKMʕm9===M-_|a.󳷮{igQ(NMk֬1^^^nРA~ڼybۮqƶ_>Z̈è.]efnQFF]v:z_530l S_߿ԪU+V̞=;Q{~˙!9b .l,Yre+1#dw9rH37,Yv{.\h$޽{c2dd̙nq&0ܹsY|.x*Kvn͛7ϊ3N)]zL:5ÇptթSH2NJɓFԩSmE=TVH2;wؙ}WYlY}RRR޽{ܹsͰal6L֭ʹin1f瞳Wzus…tgYe({{XWXXG}Tnnn*QZjkio߾ڲe{9իW|_UzVZҥKk׮7 @%Kʕ+u˒  I߿m/wӽ IJJ҄ ҥK+<<\ bqu4c>>>;v8_||v8?^۷ϰmʕ%I{ѢE=zҽ{4,9s*YVXxhѢ֭[vޗlu֕$YuwwĜR?ťۖ~Vɐ{9ҥKգG=Z^^^jڴ/^)SpĉJ*b9:t(MD_#GTJJx ^Z%J$>}ZOd\Rv횾[_ڵfΜikʁ IDATwE=z'ꫯ?Çm}XM:U^^^Z~|Mծ][&MJL8z5h@AAAZv\qѣ>|xιZjٻ8q8%UZUٳgWjjժUљ~Hc]n3hڵ֭[kر$,YR7oԕ+W] RpaEGG͛*Y$ex|GUml~/h/ɚ{f֟9ƍ룏>Ҕ)Si&pu,ڶm+IbO~ȑ:x^~e;6c4o\4o޼t"""dXcIxbIСC3wȐ!Zəu&KnR``^)Sʕ+ڵ-np&[޽%IǏ3ɒ$??4뭅z)))g$ٳ'ݶǙg%dʽ$&&j TrԫW/%%%髯ҥKe}kl_GEEUV7o5|M6V$ =/W^yE$iĉmÆ Ӿ}7|S ,ֵkW]pAW&M1cGѬYl9Eb… yzzߖ$:ό~Lsɭ[m9"baZi}%''ՑOdM%$ӲeK{nsMi&3`n *d8`gʕFSqFY?n<<<$;Hk~ƍ3vZ#4l0[OI槟~S&F8%;e=Fmʍ]vk}N:g%&&~H2fСf۶mڵk&))\|٬YƼKF)TٱcGZY|ILL4nywH2>>>f۶m͛ɓfĈ<+et&CVsogINN67o64J2/\|9>:M̟iG#ɔ-[l߾n;k={dy̮ydddl-j$9[? vڳgys7#Ɍ;0#ɔ(Q"蜭S:j޽g({{)N'Pɓϸ?$&&:GoYxyy>4}1cF 4Ȱm%y>}iܸy1ƘΝ;If:ϹsIK.uY},ϙFIv}N83٢L֭|n/n/_nf͚eeu{MSz3gN;d Y3"uߎ FyG$Sn]3es̙LsTPPd~io>h.^hFi$͛c)Y.ɬcΜ9cbcckf75{<));v̴kH2m֢?͛f߾}nݺ~.]d1RJ{cnݺex$n1d,6l9x𠉏7W^5+Ww޶}c2=gcy$3uTs a6l}vcy)+RRŘ3L"ELݺuMXX#!rֱcL߾}ͣ>jL%LVӵ~Hq1lݺ>cLtt4KNFbccMɒ%6d@#,FqW_}e$>,Ӝܗd͌#)dZnѣV)\)P)^5Ǐ7v;}i۶)R)TyGj߾}}۸___z,wY,sn gS:udG8|pm\^jWn{K…/r_͑nmfk߽{L[Gv5kVmڷoo/ne-ZhVZQ]ʖ-kVbt>m۶g;6ZI5tV``m_3%IK,;wNӯzKƍc!X,-YD?+W^gŋ*_|d> &~Ѕ Txq5mT&LPڵk?+..NkVPP:vh7GjnnnzԸqc5JmW^ՠAzj%''N:z7?5kHϟ/RG$]vzUdI[9֯_3gjϞ=tTZ5uQ׿ThQ[e˖i̘1:{ʔ)/V5jBBB͛뫯?}vc+y)-ZHʗ/ ` i)ℬSr;@}!]tI:tP߾}էO߿ SpUV-:tH6mҧ~*///W7nPPP*U$=c3fmm|i $M>=46i^gߣX,:tHZR"ETL "IZtիB FZp$iŶ-ZЈ#ei>|x?W*U#FH{41+VHfϞF]M6̙3UhQI'|/B/_eӧ oi}l;QBWG}jӦM۷rJoՑ؉'$I*UСCi^O4I6lЮ]TF }GrTV-ץJ$֝d ..NÇ׳>F)""@K]aϵk2fXr:ePꩄ$-]ۮ]… ?4ib*GѬYuݻwk宎˗kݮYSo߮> @@@,YOl߾]{VttյkWWG'{1;vL*VeѣGСCz'w^;9~R>[n׮]v{{{O>ӧݫNx 4(G29<ܛ+⮍baaaaqz [߮pרQի+""%,ǎwIv'{J'IxmK/$߯$EFFjԨQX,jѢ߃u&I8pnݪDٳGL׶rʲX,9s_unݺҎ S+BCCիW/?^sQ~\ ???:b… yxxh„ ?X9Rqqq:uxȑ#UpaթSG9r>s Ҋ+c5h 1 .iӦ9{ȑtwVpc[oiРA2d f[}ܛO۷:p]Bq ྗ'jҤIjڴ֮]cSwC TBWڷo &~Ѕ Txq5mT&LPڵ%=_EgϞ}-^ziҤI g}nݺ`u$DڱcGp6oެ }Q4{l-]4MہM_~9"IQvo;{%wթS'WG;˗/c,+00Pno}˗/Wɒ%qF?^?UlY]6'5 6̲MhhhvVHHmnzJ;wWΡl׀"""ԳgO;vL}jWe ngXdJ~ u)5ky]V-e8/B|1ҥVz:35uT7NWXXTXC(y=[b}eg;!v7oԻᆱ;|򒤗_~Ycǎ啣ĉի߯kȑ*Xc秐W:KSM{3g͙3?݂ teuն[nZt,X!C01F_|񅂂TZ52R *B -\ _iӦ^SO=vO>э7Ҵkذ6l[niS-{ʕ+۫qz5c %$$ɓ2dԲeKM}:vvvNKDDDDDCXb3z4t)H:sJjj*۷/_Α#GY&ڵjԨAZZV;v`ڵHjԨɓ'6DGGsA݉eѤIvڬ];w-[ҷo_G֭GG%00􂑋  ys;@޽y'ՕI&qʕ|Zl\rϬ܎=Jf(W=7_ޞʕ+ӵkW~_zdggMMFE/IKKח/^L7(6lO<}58'""""""Ϫ3ܫBJ.glR;;Mx;;;Lhs42ݏED%>>wwwoYhʕvZ"""""r%&&NVVN"66f͚9S8::m/[ ooo>3Ξ=9rgzE7n0-7m\ܸq駟0s7ZW^yݻwsuOiժ?CyѶm[N>_gLBBOm۶w_^J?=z4z{G@@?3ٜ={8ꫯܟܙUS c0X`M6eFݻ׬㶋)))f{oxܺu$99^%ǪUpE~mGŋk׮+߿_~i}vyz˗7nvvbСdeeKzzqPO>~cܸq#Fo۩W{a_SNѠAl-Z͍t?ŋ̛7r6lobǎԫWLys  """QQQ :_TڴiMRR8p/qWH6sqLwwc|M.^G}T`?IIIL:'kڷd/ŋSvvviӆ+V駟ZtR dn6ɓqwwɉ5kS.|Ԯ];;;ZjŒ%Kؽ{wٓ*U7p)}gΜ믿r (2{lV^M͚5Yz EQ~}6oL-(S 6?}\xtDDDDDD<)~~~ԪU'N7>>NKDDDDDȸo~L6lȷ/ҿԩ(M60j(c~3kp֭Ɔ4h666s…|j۶Eb4rH^xg@2e8;;ckk3gҥ899YF֭)]4 <%K`ooo)_<₭-NNNk׎K>%N:QlY-ILL|ZBD ;vӓUVK\\ժUvZ"""""ben.lccciԨpszb lmmYVX_EvUپڵkӶm[/V\oO?EbjVlYnܸq @ddYKߗ~~q >#Zhq W@8t=/""""""J[kmX"AAA+1ɉ3~ C-y[˕+/8q4'ػw/Ç7=dyeff2eܹ31...NKDDDDD.]O>8*T_~Iʕ-b\|Klٲbt \waÆjՊ;wH6m0 aA-4 IDAT9<#F`Ȑ!7 UDDDDDDfNGՉ1Ƚ1 4k֌pꫯT""""""fʕ+Innnfy7!:: 8Fa <?Pd~BM.S5 :}ѪU+ϟ_,ywO*UT,㈈8ȴiӈ'==t6mi_yy^:)))򦜈|ce˖0hР 3/ >}PR% 233|,n˼yXb5j>ήXlOJJn$)SA͚5cԨQ̝;s2zh6mjDD,55-Z0w\شik׶vZ"""""zW9s&ⰱK.f&L %%=z0yh߾=RSSN:ܸqhx5j~i3k.%ё2gΞ=K~,yfz-Yf իW/͛gv fϞ @Ϟ=m,+N1  kaư7yY""3>{EDDDDDFEŊٹs' dffeΠA(]4c裏`w1rHʔ)CTT>} 6oL~`Æ Dyk%"""""5k#}-Zё:NVVϧI&cB山c3ϰh"lllxw^:ʕ_ L4 K0zBo=xܝ%?իWiܸ1-Z)}9{,Çw$..7ҠAʔ)'ׯz|Z[DDDDD8EDD,X&M`୷کCK.ݻ~iX"/26l`ȑfk`۶mtܙJ*aooO1c[l?xVjN|}}T_~%gRҌ5kQQ˺uJ4޽{uV(]4ueĉ߿ƍ""""""N@DDѣ}v̳>[`LI9y$$%%q)xꩧh۶-/3|HJJۛ>}Xn"b}/_f„ |ۗ>*UX;-ШQ#mwwwt'?ٶm})D/°aøz-++Çsa֭[GDD=ٳ j*rss۷/nnn4iکH ضm:/_fժUZMDDDD׭cgZ; "+e+N1n? Y!ʶmSR͛իWiѢ$%%c>cׯOzz: .,< ڵkL2^zB5ѣ'OڵkNODѵk7n:tqƤ0EDDDDԢE }+ݻ7-Zv""""""EfSK*<aر\|+WҼyseW+WdРATP~Eә3g۷gÆ ͛7fɜݻ7{v"/)ܕO(5sv&Me˖a*زe)=$$$88͛7bE111qz` >>έ(yQV-ʔ)c*tE\ǎ/Oy7"559saݸq#akkKݺu6m wkd,Lqrr⣏>2`pafԩc#" /0k,fϞ֭[U"""""""""""""")ƙG̙Ü9sL3f`ƌ$f5iǏN8Ys=ɓ'Mmcǎe$%%ŋ >atxE999ѠA4h?YYY,]p{=>>yf^X#K/_… <}ϟB ی1"`!,,)SO?D<Μ9C.]T6mt gg<_|y>|g};..$s>}DDDDDDfՙStiZcFRw><:v7|ԩS$33EѥK֬YSg(""""""* Á&  ,iӦ V)))f{oF?...fNNNҥK95hР@3G̋A[?wk4~xؾ};4Z*/^8fOnn. ,ÃWLppEȭf۶m׮]cʔ) jԨA=SVZŪU,bj׮͘1cLlݺhq*V3dvž}UVl۶TiwS#"%+""SOk.=<ӧYh;wʕ+ԩSӥK˗/͛9wժUCR|yS7ʕ+ #%%2eK/1vXK9aӱՕ]ҭ[7nn0LÙ0annn,Y,Vyˬ\͛l^hРATPh7BDDDDDD)0KXX[t8;;3x`,Y)B DEEѧOٙtRL=z`ԩԯ_{{{quuߟӧDŽ Y&deeS<7d…k׎'xRJaoo#GO?rʦ/...DvXt%Eݻw7{JN([,񉉉/__~'NꫯH`` ? SDDDDDPK7_1 ,]77 @ZZZq5j`޽fm """X|9~~~\tXrUS[^VKժUx>c1FDDDDDDn=)""ro.]СCyWyٿ?GHjj*p8%UV̝;SNiZb{vJJJ ٤ЦM"ݵkWg {֕cǎݱʕ+_p59¬Y۸ѣG-5rA"""""""*mDDdm޼]ƚ5kѣSGЃP믳qFRRRxW 6Ϗ͛7s1jժeV~~~2k,[7\2ϟGnݺ|l׮k׮>>e˖q=nժ۶m#55bf=b[iGիW=z4/͚5c*Ls{1ʁ̶UEǎPvvv4hЀٳgӥKS\ O>8;;ckk3gҥwi=:u*{{{\]]g馸 &PfMlmm*qѫW/*V=-[dʔ)w}yݩS'ʖ-KbbE/__~CDDDDDDVmիW߯Dzjzm4;vߟ .K~<̶7mdeدȝܷ>}ܯDD[L20:w_5111b\\\8pGA[È< ~~~?~p bDDDDDD,xyyH>"wȴix74h̟?+g'""""""/Nٱc/aD1кukƌc48YYYL>9sЮ];]Hf5js`4mYȣċS;իݻwI%"իWcggg48Ϗ4ϟψ#vZ"""""" '.̀,""""""%ċSP"0`Sxdgg3gO?Ͼ}puuvZ""""""""""""""[q_}1sLƏORHLDNNs5?2a푚9 x0.#)) ooocDa믿Orr2o6AAA.H'\DDDDD"W[nNC䱳zjzm4DDDDDDLټ… Yj7774ibD˒%K8q"#99OOOk%"""""ׯ)4k׮1ezꅋ =z`ɬ^GGG+g("G2l0lBPPo6NKDDDDDs111X; y<0)<"**3gЯ_?S[YbQQQ5ʊىȃ*""SOӼysk$"""""ٱcylnݚ1cX; "y`S,Z;wrԩҥK]|p6o̹sV:t 00˛rrrgÆ cgg+]lN' IDATvXC9##6nAjܹ3C5ˬ\͛lj^:^^^\AQBbJ"KOOgذa|7?3f`DDDDDDLvիݻSy^;;;k!"""""RdEqٳ4Nʍ7x<ʕ+ 2#GN:Ell,DFFRlY.\Mqׯ_g߿W2`1b4ŦIjj* .TR|dddвeKZlIrr26lgϞpuDQrJFMʕٶmJ""""""y>"V`|F)""""")e cٲe={ vZoN˗sj֬Idd$v"""5jҥKMk׮`ڵ۷3i$VZeݻI&$''oݹs' 4fי3gիۗ}0EDDDDDDDDDDDDDV+N2n\xĉԪUe`?w-[vvvxzz ͛MTbbb… `VpqFBCCqss֖u2m4LvթS,FDOk׮q 6mĢE(W)6Ų>'Og-q'NӬ3`رL>$Xx1`;v>>>yf~y*T`gl3ƈ… 3h BXXNNNNKDDDDD䞝9s.]PR%6m֭f/</F }[l!>>pׯOڵkzJÇ< oA17#)) oooc|DDDDDD6V+NeA?4mllu윜;֭[/ٷo-"::ѣGӳgOrss ʕ+y*e9AMD|ׯgСW_)T5jdn"##I&ߛBdd$SN]v%?Omf ={pBVZEnn.}͍&MX;5Ֆ)'|00jԨ޽{ڍ...fNNNҥKbǬ[`INN6VZ/Zfl3ƈȣҥK :.]жm[RSSU""""""S{yٰaw&>>\[oK4m۶hR8׮]cʔ) jԨA=3bbbR)^^^ˋ+W`̹;vH*UXt)UT֖5jo0bnܸEQQQ9s~ϙ3gbf""""""-S:7n$%%W_}l߰a=Ϗ͛7s1ժUˬϏPf͚ŬYb6mj֭[IIIafq7δݪU+mFjjY𿷆n-Gq: ҽ{w/^*cJxx8&L͍%K7GEDDqFUFΝ:t(f|w^CIjh׮FlٲsGm6]Fkݺu 4(n}%77뛵6o㹯\0RRR(S /cǎѬ֥ n(wrrrgÆ cgg+]v[n/_ʕ+i޼?իW7^ 4 *uy=0)[jUXp!v"33zϋ/q*T **lݺsQjU^|E )G.]89O?M6m3ŕ/_H>l™3g(WM6eĈԫW۩S'>|iL֬YCNN!!!mtu+(־Gwso^ .4puz* o%##-[ZѲeKٰa={,y=0)wRF BCC ɫbŊt1|||cǏgƕ+W___"""8q5kĉݻÇ+"b}L20:w̖-[L<ʌ3ź}ui"::Npp0=zP7lb &Mk g$&&O9qO?4nnn߿SZs9"+JFkfڴi鼋QPPjբL2bK.jۯ[aEq=k}2,C\\.\W^ MqnݮN:f1""""""Rf攇#ӦM7dРA3|ׯ;+G3o̙39s昶g̘3@7:v@3ۦ={q?[暾?~{8ggg?Nzz:u3\^J*o#WWWwӅ-Z䧠o־Gwso^cǎe$%%ŋ y灛Kf8>h֬Fbܹ=MZ9+).)))sax7vZ""""""[g;R:Ɯ9syi۶-4jԈ>}}.mXÃǏ[r^u5jDDDE!onn׫cǎx{{uVKǢEfѦezT)ɧm/"""""R8*NO|}}v"R3gӧOg߾}ԫWiw~@Yt)vM6%<>>C1b1v"++C1ydSKxW 姟~";;0sL^x6m?6l\~0vXhժz8#q¸ӵ(־Gqv튗}<33<=zԢc1FDDDDDD SDD ''LFiذ(Ng֭0p@}7δݮ];:u*SNСClْwqaM;ugY9r$+۷oό3̖s)JޅUreΟ?O=pqqaݺuZkߣ~~~2k,f͚e֥[jŶmHMMXw6m8hB_i߾=o&Mb׮]*L^r(_<₭-NNNk׎KR1qD:v숣#4jԈw}Tܰj* W^T\{{{^~eBBB̡J*,_7|FQlYʕ+Nj/ȢExppp k„ ԬY[[[ -(־Gq{ԩS_>ꊿ?ӧO7uԉe˒hGbb"˗_.5yg 0cm{KLL +{qivaZSv,Y'R^=-[=+"""""0Wqy-Y j֬ '֭ÇgС5(""""")C/ӺukJzy ԪUq[&--zlΐ!Cزe AAA{"""""""믿&&& f!ŲB""""""?-#"_k l27nΎ;9s SDDDDDDD#L6xIOO'>>iӦY,$""""""+Svءe}DXܺOq9s&-qƴk׎H:wL`` ̜9GGbWDDDDDDD͚5cԨQ̝;ѣGӴiS+g%"""""p)5<-=={w^ӵqiB i MTLj:[-RT+JVƚM"jPRDoN&dz<^{lIOsμ;| >cǎsN5j //CDDDDD$Ҳ>"IJJG<,\hpqq!88~M)""""""""""""""@)"7n!!!Z ggg ???lB```.F("""""""""""""xhd˗CHHxyydBCCضy2Vb:q+Wy\rP~}v횥DM61e,X@͚5SoԨ~!Æ E_.D)"""""""""""""3)>>>:tؾrJ.F>#vܙDÇ˪U0Lt 774oȋ< Ο?O^޽; HG}ĬYhݺ51Bacd2v"  y"yyyv""""""63)aaa̟?:up]Ə#JBHv͵s,7>>1cйsg\]]ԩ>>>^'',/ܽ{ݻSxq+}7od׮]l۶;vpa_-DDr ?a#>cǎlٲ-s]-h\|ݻm=z`Ŋ,^!Cbt"ߘ1c8tޞm۶m6oNHHIIITV͛C&M(Zhn-".]v"ILLTrdG&9%#uXǢEزe 7%J^YJp=z46mbĉih߸q#>>>L:5Uc…l޼/@ŊСQM>ޚ\ub,YV\I^(RH_$/Yv-SN|sm*UDfh֬ϋmΜ9ZG$yyya$O$dVBB&22hx"~~~DDDK|25ȑ#9|0ӧOvڔ,YhN FJs/˖-3 '<<[n1i&L5'!!!l޼7|3S.={H޺wʕo߾4k֌2ert""# ""b2r;cts\$w}Uy"9*))-_H5j+V$**ɓ'BPPPk$'\V,Ea„ 2cDz`ƍǭ[>}:i_f sÃD֯_ԩSYj鞯5c @ժUSܶw^%aڵ|W4k֌J*v8""9*000C<& @H˵@RےҖ-[}:v[b}]8@xx8*TxC2a f/// (-ccbb]R2d˗/ӦMy~Ν;Gǎqqqa9z'NPre*&RJ"nzqϟrM۶m-ܒQ@_>]v}Hɵ䔔ffٞyк7o̶cYe˖ԯ_;vvZ~7͛yw3\jڱvvv˗/6s@-s};wϖ;wpIƍG…iҤIn#>/Vd2ѭ[7ܨYfn&""""""c]9Օ(֭[k/TVH|}}>|xci߾=۷'22[tRf͚arc/Ntt4ׯ_x_nkbbbpuu%!!GGG.^Hb JήqeϞ=,]={ERR...ԫW}vnǝG96']z)휲s ?*I+)㈉/`|erJ||UXfΜI۶m_>ڵc֬Y6_Ń^֞{ll,+Wnݺ%K4MDDDDDD̲>9QZp7߰}v._LB]6^SNҥKL0RJPT)>SƍԩSSԩO=9s2eиqc#?/$::ڱZ/`ƍݻwSpaZhs 믔(QyO?ѣGs|o߾9s&M?3X\2>>>tؑƍsN,X{wKH^f\ɓxyyQ\9{"""ӧnnn}}} +έ[WJ#+VdȑMnҥ 2›3-**:uPP!LVbزe ёEҡC:a'OΎ%K[ݻ,Yofuٽ{76lge͚5Sswwgԩ|rkk\DDʕN:FS3PN&LkR͓޿O޾`*U*UbǏL28::Rjt45nfٚ5kK߿]v1rHVZe[|9 f͚χ Ji)Wk֬a޽۷[Ο?O2eXt)g…:u*(q֭KVؼy3 0]rjժfvooٲe9sҥKYhJiVP{eĉ6޽{Zj}6sy|M޽)Y$F?3#GݻQ_5 ƓuI,899Yl/]wq9s ӦMW^Iۤ$ƾ2˗/')))ǡCPBY4kݺ5 11k׮DÆ 9x`qѤI.]?fs%4i`u1VXb6p9ݻw盙GkשS_ΡC?~eR`AFMhh(?Ϝ`3zhjԨ/F`۶mbٳ':'N}R*_Ey|)91 ŋ\x ƏOr;<yйsgbcc6lN">>ӿŋL&Sɓ'?A?HHH`׮] >|iӦmƍDGGSjUMzpssŋr)ù~Q6? 0{? /۷2e,Z( 2w]7RVKOiԨM̞ofʵ0۵k͛7֭[]  Fll, ԩS$$$۩V'&L굲֗_~ŋv.]]vL&zƍ#66gҪU+̙c1Gn-"YJ Ēӧƍ4iEC?~Kn={_I6yő;փTbE{gggݻg;w5jXUUql۶ʕ+kf[… 2bK/yI$f{LL E_3s<SC aƌ̘1w}ڵkvX"""ꫯ|2Fb֬Y (P_ru fر'w} ,Ν;t֍S|yhܸ1+VO\^W^'・;Δ.]:KJ#gϦ\r888аaC,X27ߤXblذh}/_hѢtu.ofʵذa[&>>իWӼys+pF /NNN4mڔ@֮]*___O?\N߾})\0eʔaz""K˖-ٰacǎ套^̛76mL&SزZ[z)wvvf̘1$&&2e%R#=?謑<& 9|R inj""""""Srcˋ3g2sLzለ#̼{w~s%͛7;ѣwޥUVL2b/!CRd2X?[;;;Y^#(('ݸ4i-3;4h+WҍW)y뭷{.K.ط|rٳQ.3%>>… gl9ěkwѱcGܹ÷~믿O2ehӦ _ƾիc2ȳKƍ-K4FY ED2+44 Nhh(sviV)qvv},Ze˖ѻwonܸY>[.͊'!!!,-O:tȢݼ5TB^sɗ \MTR9rĢݼm>fFl9ŋ'dn3ǗSDDDDH ;;T_իW/ /b -o,#+Vp6mJٲe-+W&MpV\(Y,y  Ϣ=>b^z eCfr7+ע{$$$`2ҼF`ٓeRlY˚5kHHH&['SKd~rHVNCxxxwGJD5kѣ9~8III\zٳgprZ֭ر0ziѯ@ 6.Z(111t WWW֭[g#WuFϞ=ٺu+'N`F{VLHƍcРA^7|˖-[ ]v}͉p߶mgϞ_~ʖ--ްaCvIDDDFIMSDDDDB p5L&S_iU9v~!vvv,_jժex s2ƒDFFrAp1f&얲zJZUS s|gӦMVrI/Wfd&ެ\]vwߑ?~"##S-%eo믿3:thL&S۷ogfe6nܐ2ѣuԉcRJqttbŊӇ & .^^^boo3M6eɒ%7>cJ.C.… ܹ3Eё-Z0zh]6]v%))3gYx1-[H"888PjUMF6m~EatqqqG,YĨ]ުU+ ,ݻS۽{7 Ed""""""ؙ5 6>5ow%;#"OիW兿?ƶȓ$[Y}[WN:y׬wmիGXX'Nd̘1UGaϞ=F1ӧӫW/-[n^z|rFaJZZnMBBH(_|/'o&&''tϛ7Ϣ:uܢELvvvikР)>>d2L]v5ŋ[_mLݺu3:~fbvg4_6_|1ym.fJ*exmLLf&? 0=ӦϛL&릪UOҥM<HBIpL]k[e&n[)9ED]MÇ7 >Iyk1{e„ ޽[nQV-ƌC۶m8p`VL"""2///r; v&SسA@@)ED2Üb^:嶈ȓDD$XC<:("""""yTh܎@DDDDDDDDDDDDDDDD_mYGՉ'\EDžZMo;hݺ57nٙ7蘥9@_>]vDDDDDDDDDDDDDDD$3䔏>;wf9$'ر7np vA˖-s9j*L&ݺu͍5kvh"""""""es; 'ի0DDDDDDlD'ܹ3$Tbڵkh׮?AAAODrJ||>CDDDDDDDG&9A\œ9sسgTXzQFI-qqq,Z-[SD ^{5#dg&1ƚē\PP^ɉ֭[rJ0`@.]b޼yݻ7oR|yz-ڴi~{=.\͛x"TX:бcGƲrJ֭^dI<<3VJxx8>>>\|٢ˉݝQFQbED~H:-YsAbb"ׯgԩZc~{jժ^Gs޽{"""""""˺tB.]r; 'Ώ?!d+!WF۷o`ԨQj׮Oylɓqssޞ *0~x֯_gxUM1Сk׮h߳g| e˖`=P~oC?tܙPˋ /&&"E:GDDDRKHn|2mڴg_~ܹstyh(ʸ'Nxg ؾ};AAA=z7oRJѡC4?KzҪ"H%_>}TRzLkW8%[?˳f^)=" ~t5K󉈈 #9㯿TV-ݹgLi߾=lݺK2k,#~ŋ'::ׯSxq\~#"""""""S-eΝ;<ѣٷo...;4lؐ~K.f-[ƈ#ox|AQΝ;̈#Xf NNNzLkZcxƌCΝ:uꄏWy-Z3e&MD*U8vSLIշYf,YѣG駟RR%]o`*&gRlxN:űcxiРAs5hЀrɩST 6dʕ̘1ɓ'30g)S ?ly:t9r$mڴRJ_888q[ۯrDGG* żSvyٳooCDUPyGYp! .4Νܹs{a+V%Kb+U d޼y̛7b9/TRݛ'On:-?E/thѣ+V` 2$~y"9ۛ7ҧO Ӈ;vFϞ=-(PaÆE%&&N:ʺu=vkYv-ݻwOw;;;wδi ⣏< IDAT>o߾lٲ0ڵkgݻ7'OfԩL:բoڵmװaCvIDDE;)ƍڈn.&",Yh aȐ!L2-Z۷… LcX`EI2)kűh"lM%x߿?8CzHLI[nL&Tk7ow)m<ʕ+5kaaaϟW_}CkèQصkEr֭[Yz5Ǐ۔(QM2d ,14V,\m۶qUJ(/H…m/bueʕԭ[Xɒ%`ʕՋ"Ed:^GM,444?Xp!۷gᩧ͍'XqWpa{{{iڴ)K,StiIHHȑ&D6l؀3m۶pvQH6l@bb"ŋgŴlْ"E@ժU6mmڴ1YϖׯSN;*U舣#+VO>L0~Z`޽;y޽… [|@%""""""":+WP#͍P#رc7o /bpiԨ>k,bccMIKBBfҥ\pD.^C޽{FpC4)Tov}$HnKf "$$۷osu{f͚Xj֬ S3bBCCy&w%::+WzH)M͛7yYb.]2 沛-iӦMť'qqqτ"OTN(Vcǎhx"%Jhwvvf ><9[lI˖-SR^6eߴ>(nj񜜜ؾ}E[RȣW^y;nܸ{?j%ݛ%Koj!˗W_ܹsxxxXTO{.\~J&Mhܸ1LåK8q"mڴ^zhтQFG7$'NHσr蛑@# 9000󉈈dN(^zۀQ|ܸq:pmc1Yfٳg)ٲe 'O {{{*TX~ ͊$)HnKf~)e˖%m7nrIII\r)_EEҦM;NgѢE8p`.E&ɉҫW/3g DDDn`~bbbxᅪCq!# ŋݛaٳEQR>bΝ6?M(;|0Z Dnpss3󋈈dE$ӧ3}tc{ҤIL4 ͛7?~ O?/«JDDW^|gϞHӧ]\\8w/^B i7Lܺu… Yz瑲ݖ*Vh| dO͕+W%o6lǎKd2=p̎Mx饗,]p!qϖd~[HTm<Dri 6s=G ߿Mk ˣN: 23fRv\JDD$ eѢExzz2fXl~~~̛7"9e)S '&M"""ٳg-q!sl9Ϙ1cܹ3t V^S.G(""O^z%ˆaǎԫWERV-C\\ԬY"j <8!y5jp9ۗnrѣG۷/իWgѢEFHHHHGv[b7spp07ǒ:@*Uӧs1ʔ)C&MX"իWk׮/+cmUpd&.jmn&"""""() //E]oIk pBc{ܹ̝;&WK9g}~??T)Vp)>;rw^xb._Lݍ=zb /^̐!Cr1:yr!;K,aԮ]=@˖-9rK.֭[4jFW_}͛7S-YDEEn:#Q3=ׯߟ6mCݻǂ 0LmHLKUQ%&9{NJLL$ MDgΜ1߽{b26-J?ȑ#ԫWh?r@~\ŋ)^žׯ}DDDDDD'EDDDt%ƍǫJ޽;ׯ၇_i TR߿+Znmw˖-!dg͒xO>͐!ChԨ͛7gʔ)ǧg>v[lݺӴiSׯOv1cqqq1f^yZlg}իWx8ΝKiР:Kvll,+WnݺK,+W$66sI)ҁ-%ؼys`$4l+VI2W0/I.G$%%qUfϞ{ Pvmo͛%11G2tPiذ!;w6ƙ+~G9sL3Öحk;wСC9uKUV߿?nN@k-ɓ'ݻw cʔ)4nئlau\2QQQ1<.Dɓ'\r|DDDЧO܌'_{ʕ+Fӧ;v,IIIϚ5X#ٲe pO>Īs_ݼƠAPo߾Ͻ{=zsXk,ZȢ-::+Wr &Nho޽p?rASJHH`DFFm/^Ϗ|}}6m"..OOTxzz͛y7t"""$/^ڵkJʕʕ8wUTTECNpuueݺuӇ;vFϞ=-(PaÆYM:wyQF:Ff͘4i+M6e͚5||iVn^Kuvvfڴi5mڔ3vXƎjL֎V޽ٶmgϞ_~ʖ--;r6lΝ;H&'iDDDDDDr*<ƬItR\BjXf v7YOB ݻHu}:IIIO||<_| d־ +W5kְw^㦄y/sjG'G޽{ٷoQƜ܉'?>ϏҥKsyt|r"##qww' H͚5 !((w^VjsHV|qQZl o%}>cJ.QQp八+8;;ӴiS,YJEbXl~!իW`*T͛3o<6l0:wO?#3&S琜[#(=+Wݻb TbO>e˖899Hՙ2e^mժUڱ*R/k׮`oo =z`ɒ%8;;4-lNZ`i7ܽ{7 E9Hn3L0 oooӚ0"K.ۀ-"$IVZo&NHPP~)]vLJ72f:t`{7bżm@@nnn6O˭[1b 0AΝ; 6PФI4cKLbn[|q#R!!!iMk2c28v'OԩS]v}Xy,>}tOnlO4I&.\X}-m\B1bok׮M39͛ >0>T)RbE{ݳ9Vk\raÆqرTҺZKD={ۧ111'S2ѻwo~gO &yxr^^^9};;;;::fi|JO}gΜaԨQ\pYfiYAOαc(S M4bŊT^=dX=ƃZܼy3^ܖӯXrrrb| ̙j(A'ٳ9saD ШQ#>CD$O СC 8www,Yy-|1{믿8}4ժUx֎oٲ%111Ye;7ō pqqaҥ<6GѢE 6fw婧6ѣԪU_(SLpuu%**u֥zR*^8\~=ղ>ׯ_7UN Œ3xw]v.G%"""""3R?>Ξ=իs0"[z50DD򔈈NaÆ̘1hn߾7x౬ߴiSKbbbwf^3=z\\\{)J"s2c$$$pq|||7nX4i$&&믿ꫯ;wf=z4Ǐ'))W2{l<<<ر0zi@ 6nذ!޽EY r]r5CLE+t59biIh\23c㠉"j<i3 1SZEe< z\W2klݺ'qM?>hODDDDDDDDDD^7sԎ(x]^ӦM'((ƍӠAڷoϼy߿5U=<""~䄇Æ #&& Vz7770 qww'00N(Ņ۷[}v*-nY֯_og^^^DGGWSUHu,3gμf\zz5c[eV:(( иqJ@|9;Vy+FX //}1~x\\\\CDDDDDDDDDDz)GxǙ> 0Vc:th1$=ٵkݻwDDDD aݺu$&&@bb"j[ HIIa]'%%!Cv""""""vS^ynzz,^@<==k;w^/^ի)++cذaҹsNMDDDLTT'O&88T-ZDFj9;._PDDDDDDD┭[V9_QRTTY` _Vt3gd  Ddd$)))8;;r""""w.]0qDߘ&Mϯ(11NCDDDDDDDۦ8mWs3uڕ-[yfz]H||UVĉk1;hh4v""R-ZNCիW/^zNCDDDDD.@u9sYfѧOzȑ#IKK\bRTT{ǀѣO?4K,S[kTWuN>899oSTTt6nȄ  {gǚ,))aLDDUlqq1&L|a88ܺӢE Ǝ˒%KXx1aaak1v)8[ۓh>"`ĈHԉ)8q///عs'111]9LVXyYr%w&99Ν;Ijj*`}PVVLF*gSGZn'|BNNNZ p222رc~!۷oaժUر &0w\O`ܸql۶Fב@o3ňȝ:TVQq<++͛70c :uVnذhhݺ5QQQ 83pz-Ui>'221coUܶm(++СC||_… VmҥK_e˖ùsjtG0W^V,bDDD:thm "u[Nl듛 ?l1g{q `sGVzԩ>,| 1F9s SLСCVseeeVc},L)#F >>t┃.NҥK̜94h$,""""""7N(N۷/| saٴk׎+ IDATC1g޽{3 m۶eŊ|tRj2?N-nJS>}cm۶JcvO}{<6|pVZE||<'N9MDqʈ#/5jTFb˖-dgg3rHF1e&MPPPA0 ]nO>U '++"@֯_ϬY5kq& s={d֭g>z9!Cv "R\|Y)"Rk6nHJJ Yf2qD\\\*=̙3,Zt.]D6mHDD`Y SXXHLL 6mٳ4k֌>}0n8qBN/K.(1}]>;w.[lQFILLL  {~;ǦqqqF HBBEǎS퍣#7ɧ*L4j|ڴi쌓;vdΜ97իWׯ...l߾j۷F߾}oH^"""""""R|L>,.\@II N"))sVzŋ;v,ׯ\|Ç SʻpcƌaժUs\cZ=pB +-Jxx8ׯV\ɻk7|)**|G]?Ϥ?SXXȺuX`W +cƌ^?L~gΝ;ǧ~… {|LFFEnzw}GQQ^^^s=}/..f„ ,['Ore󉋋__RTTdHKKEDDDDD~us Ug|5kf1Nhh(UDPPո=f+:\Æ cذac7&::f@ub4%//oooطoǏ (N>M{?ɉ'8p _sIyvMii)۷'88fg~?]vqYڵ+Ǐe˖埪-aÆlْ#Fr?}4o`HBBp,8rHڵ ݻ3tЛZjp駟^z߿|$11'NśoIٿ?>}"v;v ooofϞM9x 3gѣ$$$XmҺuk,2)~d >IIIl޼0VZE˖-Y|9K.eܹ駟Ҽys-[FLLgϞ0R]-[}Gll,qqql޼3fбcG8x >>>uqJϞ=WjK+VpA|A"""hӦ DGGIjj*ȯ}V222xg""""""RcM甪ri\O?DZZ|:/^{5nz]GFFyf.^Hqq1gΜW^aĈ6ŋ6mSNc߾}$/-j|۶m_C|̛727o`ƌtԉ Gdddbz!sM6Y3rHꫯҺukӟpڶmFJDD-[aÆp9qA{F-hذϛMb?>}___~_дiSڵkɓ'o-moذh|}}qttuDEEXmyfVZYĈQ':ߟO>sZmҤE=8;;ɓoh"5jTى]*+N1bcc `̙8;;|rXd 7.] LJٳgûŋQI悂y֯_?^tBII ?j^uUVTs%fΜ1 4HRRRpvv鹉ę3g2e +++\A%???ؼ<z!qӱ'O:TP_UHRZβmڴ1mw''N ??֭[̡/f^:LCML[1ի"==￟X_^M0`G.((v 4fNtN #44ӨQ#0 4DۙʭѥK&NȂ X`&MfxN^|9111{WV87 p~_Ƙ1c'rv@TTZё6moW;TSN=JJJOV(>}{<6|pN>M|||-f&""w,?>LJ#Gk\sU,W^n 69Pt:u7-wތ5+W u_۵kԼeZRRR_MzlnS^UXv1]{lgHDDDDDDW':888`4ͭNMDDXd \pVZ?Ѣ%&&SҥK}|ŭ{Ν;Dzex'-L+ևEEEƲa~G5kSO=رc->()_ӵkWKkµ[mL-,,$))] @EH6mv ..&Mp1|II [m7|W_}#'W\ @˖-"!!___  aݺuG2k,֮]k… ),,4E{ʕ+ٽ{7tܙLRSSͱ'Ş5s*;1ST82k,9r$y܈#hժ=F{<|V!!!hтޔoLc5)VSqfcH&L6-ZŒ3>Zwȑ{㣏>Z~^y[fϞU8::[l:(::___iݺ5QQQ6DaϚ5o&GvũUV1"""biӦ3NNNtؑ9s昋OW^m8gggbbb0`{/\0[ƍСCOOONBBv_ԩSёb^,_ɓ'ӱcG\\\puu巿-K,߶*tpp {[մ8}wss#..ш`wwwIHHү_?\\\ؾ}۷oܕGDDDDDDno({?!"RFS3*a̟?_Ϟ=ٳgW?8:y$Pv{/Օӧ??*… [o?^zΟ? /@nn.O==0`͵=jسܷoL1"""ƍms|w4[-̚5b,??f͚Ys=Ve>T "((FV7Z 6$88`]ϽlcǎƗƮ]*Nhh(Uh$66<c߾}?k]\^ҫW/oiD.ТENADeo!qkr|E^^^OVsǎ#""'OpJ̭ݝ3gœ9shҤ {)++r .T j7ӱMc*;c=FQQFnn. vºuHLL4+%&&b09rd-g'"""""rӶ>""""w,bbbxfT}ԬS=o.b7`0,_~aٲe.L1i׮-M[v=1i]z{ӦM8w՜i#""r߿?sΥO><# 2,4ib D>>|gUf}OνK^^ .੧2y"##&..&M>3 6GLL SN5ݛf̘AXXm۶/+V?ߟKu>{֬}Weee?~IԩSZcDDD$aaahт?ob>zرc6֥K&NȂ 4i~~~\HUT&"b?{Sy6l@vv6-?]\=~„ ر7qFΝ;b~׿R{k/Uqvv^c񤤤r0j(lBvvU;F1eʔk_=kV5i҄ ``ڵٓ[c{裏ڝшhTϏHж>""""w(x]^ӦM'((ƍӠAڷoϼyR=<}{<6|pN>M||-EDDDDg4__^鈈XSLE+#ĐF~~> 4M6<36֭k֬!##z}7nnnngϞg֭\t>}qk)_ӵkW\8"bccٰa?#͚5㩧bرV-ͧ$v튧yyDpp07:VDDDDDDD>-Җ>"h4XiإNTxb/_n~}ex"#Fڵ+ر'өW<9.\1c8vyԩS\Lpqqx=ʕ+ٽ{7tܙL/䓑@Lc{ZT5nXŅ .ȱc d "ڶm/ 48>E'Mvv6%%%dgg3g}QsO>iݳg%%%8pzYA޽1cʕ+={w}&LP|xrssLc=?~NCDꠔ4Nb->>ӧOsϙdžӧ])d甐;w.sεjS1ʙ3g,^WvM6qqFm1עE #GqF9¸qYQFb˖-dgg3rHF1eʔӳgOnJNNս3uZ)_#"""/u>{\#Fv"rڸq#)))>|f͚ĉqqq tFFseÆ 899ѫW/^z%5kf^ϞX"bccٰa?#͚5㩧bر899Y… ΦaÆ<NΞ=֭[t}!"" IJJk׮xzzǛ7o?IIIӸq"""""""ۦsJVVYYYՊ4hf͢]v899D6m5jzǵm7nL+mܸ1 :OOOd$$$nurr"&&ӤI۷/3f̨_qqqF HBBEw{ׯ...l߾jnѷov""""""""|ӧO'++ .PRR©SHJJz `޼y]ϳ~zFk[\\̄ Xl'O/LiiպǏ'33s駟pB|aa!G&55sQ\\_|a/"M(**"--SDDDDDDvW':*Z0` zU{[{ #,,9Nxxx:Ou %44h$66<c߾}?ȍj*y駩Wg6IOOgѢEtڕCɓ'Yb'N;vŊk-ՉBBBXnBD B"""":rE6oLjj*… k׎>}3ܔ6'OwaݔҾ}{mnc?k.Ξ=;]vel"*xؓ)5̮]޽;CDDvUxVV۶mC_ .Xn2ҩS'f̘IؼyUqJub7l@tt4^^^nݚ(뭊ShѢ#F ..΢˖-[cǎ_}U&Ol֑#GhժEȝ@)3QQQL<`RSSYh5DDD.{WغuUCQQرb<;;l5k7,ƌÏ?h۳g{7ޠ|BBB(((0ONll,m۶aݍŋYz5eee 6 ___:w\۩-pL¡Cʬƺwnĉ5=~8@]y=j5֦MצocZSN=VkưUk+wH]K.L8 0i$j9+njs|ƌرOOO^xz=?5kX|9ӧO磏>7 %66fΜ3˗/'..%KX,] LJٳgûŋquG|ҥK̜9c04h|C'""FUuښ?>LJ6mбcJhկo(F `ʳսAիg5oZ)Mc!""""""RW8ĚF#FFmrپ};$$$i_Ņ%Kd>r͛7W[W`̘1V-sG(<<}{<6|pVZE|| ""r1mG&M8vyĢ#;;b{ j rssYvPzp1cV ''*iӦ:usѴiSsΙcDDDDDDD֏g]̙3̚5>}УGFIZZmy{= @=xYd ǔ_cڵ[7l0^xFiƞ={ӧ&L0k<tޝ{[~z~OZnذ,sa)(,,/ ޽;Ypۦ5JJJ?>=}aҥkW^ݛ^{/^wUτڵyDaaaseΝsa"## Gz-rrr())a޽DGGЯ_?5ۻwoj7ÇsΞ=˻ヒ2=͞={())[V<Vs1Sȝ@SDDDD/2vXN8a;|0VL0󉋋#''ŋlQo~zYi+cƌ9pB ͅ psѣG5kW\駟ZW_eÆ 1mڴJs)5sqƌcSXr%bYfG}7)))?̺uppp^mg/r233IKKg)!003k,f͚e5a5"C 6Ď5-[mQ WPLb597rƍgׯUJϞ=ٺu+999V*:2y饗x饗x"ӧO>Yf?f/+·~o(ࡇ"""_|M61qD5i۶-FK/A˖-'pܹι2L9r_yZ;WƍTd{wީՍuww'44**+5Jxx8Uƺb4%//\Ǿ}?~U4hт!CӈnȐ!t֭cZ??~\ѣUӓ'NO֭mƔqEܬL &'OήL>?YrBCC歷t>uW R3}OLY^k.V6m_;;;W=9WƞꇒL1"""w֭[Gbb"aaanvj!Ջ^zӈHLS*F(++x]^kTt…*;uĉ'رcG)矧cǎhؾV0u駟;FDD'Od…\׹ʳ -Uuiذq[{=?Mc= bʢEhԨQ-g'""""""rc┕+W2bĈ} Fk; ;| _}CvEϞ=>>|gf}OνK^^ .͘8pHI&}%00={6:t>zs){~&xN:EnnUi{l$""w&{[шh4DDDDDDDn[V2dȐ[u*oDDh#F/cԨQUƎ5-[ȑ#-5jĔ)S̯4iBAA `0vZΝ /7|CDD9zٳ?φ ܟ'&L`ǎlܸ7Zuܙӷo_i&?ѣ-Zha5v;ggϞlݺ'srrۻGDDDDDDDDDDwk7ZUiA3111 0{wo9͍8F#GGG͝?w:u*8::R\\l`L<;₫+oYd o65u5mڔxhܸ1 4}̛7[sٲe<3xxxP~}|||7nK,xq3tP<==qttӓÇ-ϩׯ...l߾j۷ViAMst\XXCkڵ ݻWȭY,h֬Ÿ;VfPPAAA66lHpp0ʯ׼M6e̙׌KOOVN͞{0j=דc3h$66<c߾}?j&"""""""""":Qr/^L`` ޽{Yx1WaÆKΝk;5 =cNPPnnn2o<~ZP$!!![Ds!Nbb"j[ =\˗/v"wFcm!"""""b:OU-諣ϥK9s&`0ŠAҥK܅L̝;>}#0dhҤ ƍ NLTT瓟Ojj*QQQIDDjOn2dHm!rW2dݺu4DDDDDDvtNtڕ-[yfz}׷W||UVĉk1;ѢE >s[ѣcǎ:ɝK.L8 ػ󰪪_AI 49W!RDEKLM4 ALɱ9e(AM! 'D"Ne0s+(("9r8Dpx?ZgǑ3gbccSQ !Yf1k֬C!B!G&92W  >>lh׮ÇgĈᇌ;իWꫯw |IHHի4k֌鉾>[Ν;엚ʌ3XbTڝt>>>ՋHzvy;7~S&BQ-:::JpQB㉈0xj^a!B!D<)|]N8'uǏWߪU+<==Y~=ʺ2m4N:eggDFF 8uqidx~'%9%''K.=qqqcgg13rȚ !B!BHOOOn Q)B!29e|r]e˖-ZH0a?[neȐ!tYaaa:uΝ;`ڵkGff&>>>È#x饗8qǎΎ"݋IIIܾ}222xW022")) :h̭jKJJ!B!B>F1c {~'^u222ѡo߾@2?7[զ#BQ 4B!T#U@Vyյo>bbb8y$7o_d >\gRg /hEJJ ={duB!BJ[rJ?^GGGzٹs'Ǐg1sJy8p| Jy&tڕtrrrؿ?*ffftޝCϩS֭fffnhQɍ%!BT=QQQB!gx{{֞Nzz:AAA,Y Z??޽{ӤI/oNhh(|~-/U8ŋ|̢Eа.B!Bc2|pfȐ!oߞ?==?`Kbbƶ… }%,,M6akkˆ xXf ۶mPSz7oP{^dffj$dff*}B!СC?B>>뫶ƦJcx{{F~~Zĉٿ?鸹m300`ܹM6Ɔ4^x֭[\x_|QK޽9pfddЧO*B!DYrsYQ]&7{!::3gpm5k3f_KRR$$$=f͢Yfx KիWi֬}}}q####==F3gׯ_/0`,X@)//i֬ `ʔ)(bccpwwWKL)k̘1/j~`X[[aÆ ۡvϱO򈌌GjݼyslmmݝƍW !B!x(}Q1,,,9s&WVk711!((o}qaڴiP3~l IDATHZZFB=jK 4>2amĄVB!B!G_}jm/_&22\-[mʕJ۷رcajjZL6SN)eggDFF訍;uTeI۷om6Yp!PD2i$}~nݺUtM&O|:O$8q(}0"L<Sacm~G󱳳fggGjj*..B!ӹDXX$''e}] W֘1c155e޼yr˚5k4S4Q&--iӦϟ?4?quuرcjVdeeq1ܔB!B!DIJJ"99(}xCn:>LPPVVV\t ԩStܙ9BTTݺu#55q[nIJJbҤI۷Oپi&hٲ%7noDgϞj?~_xF}/\VܹsmڵSW-T6D5~.]޽9BUuk׮ZǼtfaaŋΦm۶Z+))֭[8&U9FﵲՔUTmeM'B!~HrJ=y嗙1ck֬`̙sTB!Z.\Hrr2L>޽{ӤI/oNhh(|~-/RիWcJPPׯWKNٰa9991oڵk9s Ji^Km<xb\\\J\hIB!J}aժU>}-[ү_?ڵkGN=zֱ6TKY*}%z} 4,?vxj.]pE+LN9y$o6:u"00Pq¹UM0α6~ڮU[UB!BȲ>ՕkײvZƍW! ,/s!<9!!! 6 ssstuuweڴiܻwڼ<쳘0yd@\ҥKiӦ k׎O?(KOO`X[[ӰaC ޽;>>>@k( ʕ+;Vi7nW\!88#Bq?)))1g Hg*}UIi|VZl Vf++##cXYYp1vϪ_gϞ;81HKKSnܸq7xCoBBiii}+;<֮]СCٳ'o&~~~O(**bժUۗa,X=磏>R(v5[jEZZ{U+?weRQ|9f̘=+V@m^yyyDFFңGyI^^^!r-ZO]|9qQ%rРAcVojngΜ޽{\~?[[[R{LJ_~"N<˫=jC)**"==+VЧOo^իL8x{.'OdΜ9лwo\\\رc?__Ǭ0α*Fd /@ffFUB!B#!Bnݺ'/^TΜ9 42m4N:eggDFFZ˪8q޽{WXjRyyyJBBNNjIΝcɒ%ܻwOIl?y+͛7of׮]G)}===Y|9SL᭷ޞΝ;ӯTdԩ̷of۶mpBz?H~~>vvvHMM%>>#GVxB<|űd,Y̙3j͙8qZ;2f}wĉ߿tdX(MB;wn͍={pYL4HkDUxxxw^.\IԶjJחӧk}߿?|27l߾>> @ku=slffFNNXZZK޽9pKf֔MB!BQ?rB! <</beeEPP& @kAXXNsDDDp֭*puZhQX۶mKRR˖-`ƍ\v;}vy뭷ҥАVZŽ{*> ###Ne{qryZhXYYq9BBB4`$''+O˶mHJJRbMLLTSSS6n;C~>}:QQQjUp*z-+:nݚ۷LS-ջС6UB=CCCCԩ+VP޷l٢{{{6l&L`Æ k]&&&ꊥ%@HHH*m fff3p@% &7nLpp0G]]],,,7n!!!777'44ٳgөS'066^c^ZܹsqqqI&cggŋk8ϧE*V4hFFFnXX[[+#G$33`^z*:>RRRxw:u~waܹzj5=cԨQ?a+J{JJ .mڴa֭jcѥKt}yfڷo&ըӧ9r G6mW_ϪYc)WsXX/"Pkպ •+Wiڴ\~Asϱk.,JUVﯺ{LOmO 6Ȏ;謬,FԩSkO}(B! Ζ=zt]M%B!IUj{jK\p'''c;wҹ,,,x"ٴmVknݺƶ6mڨ|%=}kll|[oΝ;&ܼyy摞5SʪͰǑ@׮]U8*{ei׮}U:t@8q"իYjU"eR=]\\U:J(/Oզ#B'v"<<///4YRcI!!B!'B!O%4h}ʻyfۻtŋINN09ɓtԉ@tuumk:T_omϟg\t ???h-CM5j]G;CAAqqqKA@@)))UǢ|_VPզXUmzm!`hhҥK={6İn:eB!Bԏr!֭[B<핒B!jW˖-9~ڒ2ǏkiiIff&XZZV{Gxx8C \m{qq16lC%hsr9:vXa?GGGrrrؾ};ZRwʊ?‚7WPʊ?cǎ-is1=:/m6O]U~I.:aӦM|27nXƍJ!B<^~ef̘5k9skB!B!C… DGG?iOh9Ra!kX 8q+Vۿ.\ș3gwׯ_?֖iӦ)}U+TK ^ĉ'//wrI̙CJJ {徱5kpen߾ͪU孷R988_Cqq1'~~~@iҌɓ'Yh=ĔNQQkЧOZkܸqzjΝ;Gaa!7o$11k _VP*,U[MzBhIKKy+L]k*B!BhxSTj*!hB<Ə?ĉ+;qDOzz:nnnj ;w򳙙9998;;ciiIll,L> hѿ>*-o@zz:oڶwyG~ڴi$''g٣֯[nxxx(?7J*aھ޽{p&MR֪U+ѿٴi[la˖-}ZnVײ6U:ݻ7 ##C茌 vzB!B!B\B! ɉgy bmmͲeW+bjj!!!j*ϟO-եPi777'44ٳgөS'066^c^*WӦM ёƍGXr%C Qsƍ >sss6lH˖-2e ׯW;xq3zh,,,‚qi7{lqppgEGG}}}>}:6mL_kYs4###<11110H!B!B!Dݪ)B!fnnΒ%Kڲh֬Z)c޼y舣m5ww*WYˆ>>>iӦ,^:T[u6i///j4Fu{IϞ=+KEkYWUCccc\]] $++-Zűcǘ:u*FFF9*!B!B!uHNjj5jD֭?~;w`„ j)ew}չs1ckXqׯ#FXmۅ eJHzjͱ%22< !B!p; !J9rB!Bj{d*T?wĉ8q[n1~J/))!''kЩS'텅L6SN)m?::y=_}j_|Hrss%w4iYYYJ~[niwq[q۳n:=mԩܸq۷om6YpZƍ3f駟pttT%&&?|vvvȑ#+[!B!7WWWYGzp=B!QXTN)o|>|Dزe}TElmmѣ ">>]]]yaaa:uΝ;#G[nݼy3$%%_ ~6m"++-[qF>L@@FW^Ҳ\rEc[֭پ};IIIL4 }ig֮JNӧIIItAc UB!B!B!B!c唲T֞Ȉ7oqpp*ϯK.]:uƜ `ee@۶mYt)#F ..#F %%%>}ݻwo?pMe`R ~!gV_tPÆ<%%%j-ˋVZ'AAAjI&Jrr2vvvqqٳ@iKyT}BQF]!!3,B!B!.<̙3?RRRꫯ4ihG䒛dZd.\ֱΝ;|5Νӧ5Mx"]tQӽ{w,,,&;;[I0FDƶv)ߛP\\\Xnnnlٲ`HNN޽{KIJ*Oզ#BӪU+FUa!CC$:{,/mbjj?F?E /\cTT)))SB!BTY%ù:P;::ҳgOΝ;9~8ׯ',,3g2r 555exxxb ߿ZmH*[eժU>}-[ү_?ڵkGN48ʉ(ݻw';;={oWǞ={)7hР077gȑDDD,IZҧ8::Aڪ2B!j=B!D?Ɂ*|iJe\ߏc]X#;pQٲe %%%3kkkuVoFs; IDAT1 !B!x|hf<&LMMqrr"00P<<<⋸SRRr7ƒ񕚚U=-Ĝ9s6lXEEEl_~Em{FFF|`*-e믄(K =(wwwٲe лwoe{ӦMqƾ6U!Bԝ4h _%_U/!xR8p;w7 &&TϠTw\[AA/KKKpvvfѢEklB!B!>Ç'++ ooo B?!>>,[.]pY/_[׮]:t(vӓ)SkѴiS]O?7|CAAoF=2|pnJII ]vgQ \|L$LB!GTTT} xDDDcǎCqʻ|2?3fff|:tT/{̕+W;v6n86oLpp03f̨B!B<|||WmM044䣏>bԩDGG3rHy&NIOOMm?Ν@\\K,aɒ%9s;;;سggϞeʔ)A)e-\;wO?秵"LYxq&L@tt4@޽9pYU>B!;FwJr\vuq! h׮&L`zRK~~>$$$pU5kD___2LˎCqq1А7xHbbbxwj5޼<ػw/ׯ_Yf 0)S`bb)kkk6lؠ+??___ߏo3gΤQFjOÆ =z4ӦMƍ\D۷/^^^+I=Pm޼9DFFNƍ{B!B<e}ʗ+3K,_D__}}}ڵkĉ㏫< G޽{]Vi711!((WWW,--BBBԪ8::bhh>:ubŊJʖ-[' g,\PklG>}xǧ}իj}m4hFFFs~V"**|rsso#>>۷oǮ]Xfߏ?H~~>vvvcّO|||B!Bty,*hKZqrrR>De̛7yUƍѺl(Mۻ1W#I2U~ǏuִmVm1E-رcL:##**BٳgՒ{>[.P~ fZo<O:ń xgٵk::3|p RUZr*Jub.kFEE@Ϟ==z'p.^~):tĉ,Z+W ԩStܙ Ю];233!55FVeߟK.ammMښ_4zQ+񆆆ryZh'|B8u/ܹsh,Ӷm[*0eUv\7QQQXZZ_ɾ}R뗑͛iݺ5lذ___ٶm͛7gƍ엔@4V%%%1r ϟB!BTN+??ׯ7͛7'<<\i Rc $!B?Ǐ3gRSSMcر#:tի:tҾG!;;mVyK:z(̟?/cǎwXB'իWY~=ϟqmmmվ*k߷oPq.]ƆEiҶm[.] @\\}cW5Eeܹ]vUݻWc777)UҶm[ 剮_ۣۛ+wanݚF)ݸqCٳ@LiFB!BQǢrxVgFАK2{l֭[A*Bǁ4?[&ST1OLL | JzGɧ~ʎ;*w`>(UQk Xx1...XZZEаVB<رc7o&!!}Yu%33ݻkKp@tϝ;W\yyyJBڵkՖvVٷo7ok׮j}/]*ɣ&(7i@RGe|ۮ];{m/999@iTm>B!B!DEr‚Fѻwo>3tuu+/3c ֬YÚ5k9s<+B<?,A3k,N999$&&b``СC4>Qr cǎUƍǕ+WȄ;ww1zh{9<==iذ!_5VKKKS_;&ՠAq)͛n(,,ϝ;w*-mVD[ˆJMTgFiml@1jjyB!Bt)Z ܲ\]]B֭Nc{rr2f"&&ʊ?cǎꫯ*jr iӦ\|7nдiSmʷ !B!I!I&1}t,--;v,=wޭЄq-<==#77wr%1BMƍtw%;; ̙SSqM&O͛믿(**DDDI~~~W|qMeH|}}Ϳ/3f /^䧟~R럘P2<9#GJoi{|ǎM>S4jrMZ(o%66{xn߾M^^vb͚5sEs~G@#??1`O݋#0p@VXAFFEEE8q+Vh߿? .̙3ܻwׯckk˴iӔ ~7N>?O^ҫW/ZnͩS8^|||HOOto>}{~+\uIjiTme B!B!!֖m۶g}ƥKprrE{BԻp.^AAA>| *aaa:uΝ;#G[n*O'k+_?-Z(1beeŹs t͛7MRR|ǏHGEҧO ch׮]v?\ .\Ctر֎2Չ6m۶%))e˖U&`$''+7/}}}e۶m$%%)5{k|%%%СCqTm>Bɓ'+]FWW++:ƏO6m?8q"={?;qDڴiCzz:nnn 4M6a``ܹsfff8;;3l0v رc+\zA2jU'^ZjEVV&MgϞL4K.ѪU+&MTR޽Tm5IB!Bt!Š)S5k?wܩЄ⡨F}O$w===lllXhƸ @Ҷm[.] Thk׮J5{Vbb"?3;vd|\(QSgΜQb ]...$''˲?~ccclll*RU=EU%EP[aMc 777njrMx{{Ӿ}{e)ܹ hݺ55Cuٳghݺ8mڴQ#xdffrJvJΝ/ʒS ɉgy bmm$$obbBPPXZZ)U?>-Z@WW[n{nLMM:th4nܘݻwkYx7nLpp0G]]],,,7n!!!V$j9Aadd5(eB!B4*z:E!JuC6iӆEi*O#UIݻkKPwrr:ֹsj%,v֮ҥK5Νӧ5i[G7nݺő#GXv- , 77WIqssc˖-cggGrr2ݣW^4lX?{._u֮]޽{Ԕ\ك  LMTQ%b({H]vQݪ?T|77S!W^%::177gԨQ+U-G,YD-;;f͚2o<͛W阎8::V;CCCSmo&M˫y+z)߮oUUnll+deeѢE }رcL:U=V!B!'B<ZjUs^z3l0 |~!xo,Tv|҂%6FUWߪU8}4-[_~k׎N:1zkll̀?3Jr9#G$"" gذa{nƌݻ),,䭷R{z/))Q^mOhuP)TvM4jHkNRwm1$_Gdd$0|p>CӫH߾}GGGLLL00[xkv"<<\I 77zN!B!*!СC7\\\pwwO>u~CK!-[sq^y}---$66KKˇǎW_Uڏ;Q033JT\vwwwnʖ-[HNNFGGO\:;;Ν;3f ;wJMAp-XUA렬&SuWӦM|27nܠiӦjTKoB<æMprrzS 2[닯6Ւ-fhhҥK={^LL ֭9B!BTCON9tǏ!o.\ 22M6HV7nnnntܹNBeXO>_|ӧOb '$$ EKXX6m֖ 6KtpB+`988| ;vԩSJLeT6Çy9<˖-Ssss177r<\x_tIm>ٺu+%%%tڕgys.UZjE=HMM%>>_ڶm5999ر#Gq?\ꜯ^x˗/ZrEB[qqq-Z`رuQUV޽?sѫW/<== /23f`͚5̜9SB!B!6uV96ֵB<3JY<##p"""Xr%111 6bB2~x~&NXi߉'~5ʸ0w\gU3V9&˅ 4iڶVZi8,Y’%K4?s vvvƠZ <===f̘>aD m1V\5rHRSSYjw1]?Ibk,!Z$P"bRM-OVORR%-JȊ%*B$XJ*Z "d2Id5 5/3{{gb~9Buضm+Wdʕ+jQs)LuܙÇs/>>(ۉ8BS՜8ql‰'hРz quuUߡHyH!B!(*B! UV,^k׮q!zN:ũSr]fbb?NNNT^ *`mmall533# WWW,--122\"ӧO~^xVJ`` CN:QNF 077Ϸ3f舉 ƴlْŋ+* *PvmzɺuhӦN*U(ϻu릵, ӗ988PfM,,,ѣN)S|He/5.]̣Gt.^ŋٹs'ׯN:@EYaaaj uc05j bʕ4owwwiԨB-}e˖-,Y%Kh-Q2])|߿/,XId;vj**Wշo_0JTpp0CWCB!BB+)%q1>6߿ʕ+dӦMe.9eѢE8p333<==ٳ'uİvZOŊYpaӲeK%9gϞZ4)nnnrQ .ONy>\\_jXGѱcG&MD&M !!+VSI􅾥1w\%...̙3LLLaɪWg?~`V\ܹsڵ+>>>tYa !3gʊ={p5ө[.vvvxzz*ɒ"wu-SѾ}{X|9&L]vzJǏdݬ[CCC}BL8ggg}!+J!!B!DLRL> IDATH^Hui"##177' ƍ+,,,۷/:ubDFF2x`Zn]1iJ4I&*8LMM׿EXX'O$==]k&ؗgϞ%T^ *жm[|||pqqQ^ܹsÇ+e#F $$@]鲳___~'055wXB044U,H} ^R}v>|HݹwkwxB!B!eRINOĕ,ٷoTXM2`Bݹ\*׳~/jժᅬ/ ""D?~LZpppK{9|0iiiٓٳg?j%Sdgaa;V~P*4}/gϞRJՋɓ'L|@5ضm]^IIIP~}6nsI>}J.]055SN/:u {{{JLLߟӧcmmڵkysǧ,&& O޽$hXYYi%jyca vkڊח]vQBʸqxK.%**+ҭ[7fΜI*U CZw߿kUV8,*VHe!B!ʙX6l@xx8';v>cСȐUVɔ>B葫+7owB!BQ(rY???;x)*s苙Z޽{-[ZθquO>%99&OLVVRw͚5NÇdddpmBCCYdR/55ѣGcJhejMLGQTԫWjժiKjjj ()} 1cXz5qqq<} ]#g?9l2QTw߱sNo>?~Ljj*wVc{ER)IKۣRطo_e.!B!~mٲ'pebbb4i+Z<2B!*)۶m`?~(f͚@XXX*:ЧOۇVݠ .\@VĉӦMN<Ɏ;!!!̚5h;Ʒ~ #Gz6m͛4lؐǏ˗ub믿W sβFm6=z4u;nnnarMBE׮]%d'grJΝ100JNoJ&M… ue9ԩSڗsss{>cw '==}Kֈ'$$cǎ1n8,Y[n%::1ch7\٦LSGKﰱwaժUB!Bc?9so;!B!BrEod$LMMy!7oի8880x`\hݺ5cǎisP^= Ldd2}PTTj˗_xC0{l%ɣ]v|L4I}MRB Zov3g x0@JJJ۩Vfƍ;v {{{RSS9s UT]v}qåKsʼ5k֤y$$$p5^|Suyڗ8::'%.._p֬YS9scif7)vZIrNQWyvٳyoc֭[mܜsS/^,].h˖-#!!  s9[&aơY[KŊn‚AG||2Kih7o!dee)S䖜ϒW222|2NR; s|j_v[[\i166fȑCϓK֨TR円h.z777vͭ[psswHB2UC(!^iiilݺAk1vXLMM ?ĔitnݺŶm>|8gϞ-vJbcƌL>իWsbmS!B!ȩ\ϒLprr… 8p___ ͛7à 6C1,--~:;w2miQW^UgddPB6lիW^YAI`` ]vu.K.qFez`˖-q1 ܹԔƍsUN>͹s077UVZiѢ>}ӧONƍF(ڗ666ƲuVƏׁ'|4Y&oԬYSkf"wSrrsqQVZ0X~BLF]ѣ_5...T^]at|dR>yk׮GLL Ƕm =}yҘ;w.VC0g"""d:Y!B!%Fo#ǀe˖-T*|MQ.GQ~}oooo޽{|W2n8?~t3gR{dddpy-Z~~R$88? n߾MPP1iii{iӦ@|R6bܹC`` G!B!˫\2rH|||Xd K,Z֮]mĄ3vX"""4h:FСC={www*W̔)SDFF2o<͛Nbb"s.^Ș1c}b7O<___:=z`ܹ߂OCѢE vʼn'FɮK.ڵ'O*E5>...XZZsB(}٣G<<<شiaaaߨQ#&Nέ/RpquܙÇ>Ռ 9' 7d֭lڴ3a;^双| (r1u޽|Gd,wSQ:޽˪U8z(iii4mڔ?ٳg#T*֯_믿U>Ta4ϋ2 JA-H<QbEFٳbСʲAbb"?VZ888兩iuRSS CZ#tkUV-!B!y)3#:u?0o<7o14mڔQFgv1tP233YbRnffF@@XZZbdd9lذAkt3f舉 ƴlْŋ+ (ccc}:Ȉtpn_N4 ???]6cmmٴi2N^}8O>reǦ޽{H[J*֭[INNfʕܾ}P^=B!%ڵkЪU}Jbb]zz:ƍ֭[<}dٕgI<:u*P}#mVwޝ;wO5j]v-~Dܦdz^2F)i%Oll,͛7Wʖ-[FBB 6{4mڔ-[h4ܾid,!B!%ES!}|; +++ǭ[ eӦM_+++\]]׿BRe``'Ndǎ?ߧOK{.jҩs}\2{Ξ= E^:lzmニ Ggȝ;w>|R6bBBB K ?Zͱc ȈJ!222Y`UV_ 6~̙3ZIgΜѩkiiٹs|O%ӧO A)LrUeyFFFSYtݚ5krm|}}>ί0n8/_J*t,;̔w3YYYZueX411_~dffs\c۵k8::*e:VE=BVll,={dܸqʲٷe֭={dڵ lgϦK.уkM`aaoj쬬8u^ζۗy}ҥ ./&--M킾WSSS CC! wf͚믿N.]8t7wX/CѦMfΜ.\O>zw,^x2228w/ۣ֩GILL$33{W_akkC3҇fPxH۷oɓ' 4׬Yn߾Mhh()))T,j* @ժU6l8::*֭!!!n0}9h ٱcFR  Tj/^Lpp0ϟqƸ2|pZn^:III̘1py7nnnO5*ߺFСC={wwwe+Wfʔ)5jp}\\\3ѳ8 Ovy%tR9DFF2o<͛Nbb"oAܹ3&>>^gxI!B!īMFNBQ T\9:dffEyfnܸAzz!=(( .ЪU+9qiӆ'OcN:s)qF^J֯_Ozr 6lȷMBȬYرc|9r@1hFwܹ'''ƌqssTGCҵkcddTj'/4jԈÇB͵Ϙ1GGGLLL066e˖,^X;便]O>#G`ffp#B!B 9E !ʿ\]]Grr2]vN:1wwwڷoﰄ\V.k׎9s0qDLJz./Xggg"##qvv.~mfϞ'|/WGEEVIHH`Ϟ=\|_@g HLL()ժUclܸc`sC IDATǎaooOjj*gΜJ*:wgWؾ4hgΜaZ ?QSJs{Qk],91k,|M\]]Yv-O(S-yW/^gv)R4u( dҵk.L۷O1cF>^4 =UV9SNeԩnSYSagsm݂Sض5VO˲'涿]J*~zn޼Iy&Ofر\'B!BF'XYY1dȐnF2d;vw"\| Xr%͛7777˜mt ͅׯжm[%V$%%k;W\)V7o%d֭[]LBBB2Z]_8z'N`Ŋ̞=%ݝ0رcdffbggG y}٫W/VX/BJJ 椤pӧO~zb\οE9'ߩbZӦM&&&ύFEzz:6lߟ/e˖z_=.sss¼W߿< LSGҔƮ]\2w8+W0qDYtWt JŬYptťׯtR@O#G{n6o̙3g#wYZZLY$B!BG't҅.]v3B!ʀM2|ϟ fʕ̝;y`}(&g҂sTr',[6lHiڴ)-[,}UTgϞ~z%9‚AL||2~׮]faؘĞ={6l{!==jMVWm qΉJ*Znhl]v%--H)s9r$(ƂKŊ繽4 ^Ք嶯8222ؿ?!!!l߾J'|")/ÇaŊX[[sAV˖-[Xd K,ZVF >D111aL4 vU;B!BQ[i7#xyf}! ;;;|}}ٻw/uwHBRaÆo9swyG)?sN]KKK_Ν;,XիӧF:}G~4IԨQW*322$/fffZSalBXXǎАΝ;续 7odذa4 ҪW700@V#e_sE( bccٺu+ǏYyI.%0՚5krm|_|WhõkHOOnݺ驓,(JObL0!ߩ B!BxaV/!Ir+*V|0ݛ~ŋ͛ŋuу 6̙3y7 bӦMڲvZIIIB 6Zh J_;ǏW^\z *)))XXX8,nܸ_~ @˖-׮]ej5o6իW7:tɓ۷K.Ѯ];4ik܅5jp}oΠAHNNֹ{WaΉ1bCƲb Y?h|/¼W5k۷~N&&GBד'OׯVVVL<#F;Wٳg4iQQQ5KRV-}U`PȱB!BQ^Xrʐ!C^TSB(Etڕ^zJ/5777~'~wFoQFq!Ξ=ֲʕ+3e&KKKvYF/BRRGZfeeU[;DFF2o<͛D6+S&Jca2AqI-[L/]Qm۶rJV\ k^9'Gxxxi& өӨQ#&N.^PyvܙÇs{||

|dzzj}%si&L +m}LCޏB!Br G/..???P 6 kk\BzW^Y~͛7+)BnݺR5kqu.] @۶ma٦RHKKcݺuxxx9"*{uȑ޽͛73sLم*KKK阄HKKcǎg ۷/Wn߾7tޝӧOӲeK}|R6bBBB K !DANhذC\9s&VVVٳk׮Nݺuӓ:u;2N:~ӧ駟RJ}eĉL8Qa!B!)3)$3}tYv-lX׳~/jժᅬ'lܸUVѪU+6lؠlɓxyyxbz;99q-|||={6MrY*UD^~g%9ܺu ccctgcǎ[n%++ oooYѣyO?ģGtw^T*:9y$cРA+!xUT\$æM?~<&L wwwCŊKm}-w !(I/}W\!$$NCHKKחEQ~}"##ysUXQ. nnnA!B!\%4i҄ … jՊٳgӴiS_'Odǎ8;;[oq9N>=/Ǐ\2;JKn5jĂ [.ׯ' *)6m͛4lؐ?kkkΝ;Ǽyt 2MYtt$!D>*U3DDDC%44T!(w !ɭ['$$'ORn] FǎǏ?ӹ}6seڴioeݐ!C2d╳}v} B!Ebmmm+pwwf`mmM4a\׌ĉ0`?~ѣG=zfJ*)w+(:ٳiٲ%+V]v|:ۺx",%ƍkB|5j`̘1DEEqU̙SjmjI(!eNs!xUiFӧ %޽{ >*UPF F}׿E*UÃCf͚E&MT7ۛǏX8ֹsݻ7UTVZ?^!3{jdee1o<5kFJZ*vvv|w틂t.VVV,X-[w^n޼W_}[oU"툒ue}HHLLO?-7)B!B!UFN$kh$%%k+WЫW/K%9e߾}TT ///v?L^АnݺGӦM5nܸ@֭mPjUe2M!Fn222P\9"O9/. !Dq|'+ФI~WT*7nА@7lؠ ѣRF\|1=zPZcݻCC{,gQѣSvZ233i֬Y|tbbb!%%SnAԩSZjN~TR'JÇ/i޼9 sE5kU*{cAb~vЩS'Z*!B!(}zKkA漃yw?|xcoٳg>cǎԨQmrQT*.\M6yPQbEyn4q/s虽L.4 !DPռ[X[[|I|>k>5ә:u*=*TO>a…ܻw &sNqrrbJf}JTT~l2,--Gs#<<7obiisΥr:q5΢uYNʱc011aȐ!,_*UiӬ,,X@XX;ƴjՊ>OOWA.]wBr* }'O̙3X[[_0o'Uk!"##CqFH]Z5ѣTgff>w}@o1cG``C:FY:7n~mmmmuԽzڟYj֬S?֪V3fu^bEaKB٫|Ϥ(gΜQ>|Cw.}Mmju֭ՀիZ^rE w﮳nQ,J[waVWjGGG+Կ 233QQQk(ݺuS===C*}ݔE*u^j_Rꫯ2___u~*+OQ!B!UwrGx{{Hff&㫯֖q)u}] ٺu+cΝ;P"{KFFϟgѢE:u5^~]g,PB!Jݻ$ϟO\\=z_gٲeEڮ4.\FFF$&&R?>@w?yh7niwSΟ?O.]K*΢լY3.]J~о\V+iRSSoXzu}!dd44-[TWR%^koyse4ix78w\YZj<x111a߾}L6z T*U1c7[nDGG+S f„ tЁtN8uUC{almmr(@ܹÕ#FpiB!B:9eԨQ4nܘgNǎӧ6mrL2E[fMڵkǏi֬uQF4hЀ,7o) ݝf͚qmƌCN9r$͛7שIY)ڵkcBz1ebcc믿uT\ɓ'Ʒ~Kf011aƌ^lox066^Iضm[mjt M6TP-ZaJ,΢zj|MLLLsϏ;w0~xj5׮]wWElùy&tYIlРk׮͛,\ڵkǶm̙3ʍ|kkkmۆ?ǎ$\ܽ{yѳgOpwwg߾}&T*V^vvvߟotNuʊ+ׯ:u>W>:?ӫW/:uÉԩwƍ˗癨Vu=.\Ȼヒ=s39FS,55P:t~kakkKhh(&!Bgz??*E9 3r䐱4cfafi9]FpV2lrs(&9fF,; E|v}ޟz#VlO/rg}Ʒ~ŋ)[,M6eȐ!' <==Γ5k솟 ˗/gڵ?_~???on2ˋ?ӷo_m\ro߾HiР4zҼk `ǎر)Sȑ#뾏;cȃ޽;W:xX~wܧVZsYj֬Y$qywxwX~=sa 2_~O>ݻL˖-j<:taÆ1uT;b?`?8ǤIMOOgȐ!MINNf͚5\vXŰ(Z4T @bbq޶m?h} jLDپ};iii9;QQQرzGDDDDDD̨$W*Tѣ=z=퍷w1c0f̘{{8/[,&L`„ w[lY||| $11jժaO/DD,y=iŗ_~I`` 1o7dLN10a:u‚cǎ1x`Ϙ Sת0q}$&&RzufΜǎcԩAڵ 2 hTrH S<.GժU 5#;OjLZ=/gϞ%'''+33{k4 **sʕ%y=3lZnMBBnnn>&LٙЬY3qpp`޼y1"aOP^=yCB .]^~eVRSJLϟOo g׮]OlbMK:ѨQ#iڴ)'Osܝ;wVVVԮ]ӧF~Ik;5j`gglܸ8o߾}|wuV.\Ȝ9sm s מ={4i 40~&N@$[oaJN)lmm>}:6m"))$6m)S|^믿65kΝc4Ç 9?$''3vX,,,xW;GzƱ:u`aa'|Bjj*XDDxꫯxױZj;ݻwgz0rHj֬IRX"]vСC&-Xk…Ԯ]RJq5zͤInݺ)S2eаaC&L@HHH}yQOsEիG͚59{,ƍcȐ! :X:𤹈<ܿ/J ;^R%͂kooG}G}T} ;^kegg'֭#%%̙om"%_BBFbÆ t҅M6QNsU,N(Hky>Z[]ܹs9uիW_N:4hЀݻuVpݎN<7\WK˼ zEDDDDDPrJ1c,,""%ׅ HNN+ǎ;R >>>L2@OϘ17H hݺ53f矿xZ .ϏO59y$=oǏ/) ˗/Օcҳg|[RHu ͛G@@ٺu+:t0wX%V9z(/qѣy:88p96oތCёgC-111X y~WN>}VN (({{{c*DQkUиWΙ3gpww7n?~'*U"99WRR%mW^5Em}DDDSNNɓT^BÓ?s)i1 O={ ._ƍ$oaNjz={?ARRq||ܸq7np1"""Խ{wN8ALL ǏWbcfƍ4hЀs2}t?ĔԾ}{8~8rk۶-~~~ő˗Yp!nnn6WE C{jӦ ƒIll1^z8UV̛7dn޼ܹsqss3¼IOO'..ɓ'ǯ]v_0תqm=O8Yd mkjW+%)~T9EDD :vիWgggs$"""wߵ5OŊX#HxFٳ';{f۶m={unٳgl+S F2'%%oooؼy|C ݻIHH`&sjԨa2;sNbccy7L{Ə۴iÖ-[:u*SNͳv\\IEQkUи|}}ٵk 4ȸ+OIaֿVZw^?嵡ZIB""""""R2rXooo_I)sNUJжm[Vӧ<"ׯ_gر4jԈ~={ĔB6&}fkkܹ3(UNNN̘1rXYYQBڴiÊ+Lh3jժaeeEzzzc._Gvw{j)ʊvѮ];>6nȕ+Wiٲe3tڵkg}F׮])_CGȑ# >0p@f͚Eʕcu֤1a<==)WΝcΜ94i9׏2n8V򅃃CvA""""""R2<|||2"""%1#WWWo+) reNʲexVb#бcG fϞٳM[ȓ֖ӧ3bMXheʔ1st""""""r?zrJDD-zˈÃÇ; 5kJLJի;Ƌ/ȋ/h0fL2kkk۷/0n8jԨ֭[_HOOg_dTR!5k֌C2o< FӦMܯuxR"[nCXz*L4_~>}SO=eDDDxV^͎;ػw8?;ƈ#2ez,--UmWI_#""""""bP޽H1w\>Cnϰaԩt!Yv-Wёݻ$'XRRǏgժU=zs%"""""""س4w"""RxKk׮_$>c6mC1ӦMj֬ɬYhܸ1v"!!>H)OtϟOzػw/_|;wTb#*aooϠA4h7n0w8"""fuVʆ СK6wHbf;v`ȑ={1c0qDlmmONqss ::8OzX[ҥY&{_/t E)xyyLz˳ӧٱcű} СClْݻ?pl""~rIVJŊQD"""رcΝcԨQlܸ7|<뱱n:vj0D8֭6w""""""'wN~_'?#ӦM\rf#?/_&22H~Wo]9r%KvZrrrѣNNN4nܡcl^S 9|0XZZdz9|0< #7n0eu놃Loƴih׮-[gϞlٲ%xҘ:u*[ӓ |333}z=--ŋӹsg^|E:uҥKIOO3w׮] 26mвeKx ͛GZZ<e*L<9Ϝ۵hH /_jj*_7Ƴ`_gnab*5IMMe͚54oޜ*UǫVk֬!55-"qttd̘1˸q㔘"""Ù7o۷_~s*1EHMMe̘14i҄}j*%l0DDDDDD TN%KrJ ;Ʊc?h߾=-ԩSagg;oh߾=pm΅ ã@매Я_?.]d;}4SN%++N:̟0a1Q#--02337n]!%%РA 2'Oǒ ,YKO>@Yf ׮]cƌy 118o۶mwyXZZrJ#XXX䛜ru}]Μ9cOXXQQQ?o0d8DEEcz;7w""",[ʕ+cmmmPaժU?t># DGG}D̠wADDDDD侔66l`|M{ٿ}̷~*ѼysرcVVV{&sWZɓ'iذ!aaa>|p7nLTTI+իWe"##9p~)7ILLzꄄpA/_O?tTPggg|2.]⧟~瞣bŊyYr%gΜZjqAqttӬXb*51Tz_~rWL>o>PuS䎎9BV߿?]t!..C*1EDDDDDDD3۝ۓ2ks!$44p\Bn݈6&*J>̵kҥ 7o4B6$m۶;v,5j???ٸqc'NvL IbeeE&Mmr]c{"vL>о}pqqa֭,\9sٳg&MAX[[ӴiS&Nx8[hANNB́1͐GFՕI&{0$>>5k9NZL戈H^5j &&_~g}???N:eDDf޽ 2Uk;$).]ᅬDGG'Pres&""""""""P"+9r$KСC|Gу c5voN>KfСX[[7S,--iݺu׿p+{SO=p' ZvMz^˓@ΝMxv j5dp%K߾}9s&k׮51;<52YI&w=GCۓSnТ'wx:k\ؘ sMRRR(_| sDD$͉'aժULFFCb&&&qQV-ڴi?~<{5whRdeetRꫯXbU+Dpss#999϶[93A.aœ\3zhFMxxODDDDDD(-9Őq{;{zzuVN+7odҥtؑPJ\]]#%%={ТE iҤ qI7n}c(Թj>j3e222ȷ I%"ܹs9uիWחiӦ{Cp.U]ruu5& eddpac/i01>z6s-"$rqq! _~oFjժ{!""O///4i_|A>}8~8GeܸqԨQI A5j'>>>}g' 'O̳PpO&'N09NA}ݻPˑ#GXd cǎe̘1,^[DDDDDDĜJDѹsgYr%ڵk,X8ӓlBBB?Ã7o駟rBxg*3}!'']f͛7I≎&**8СC1rH:udrLW?`Nlllhڴ)lذT5jD2e熈 SaIJzj sDD,--iӦ AAADGGD""bbСDFF?3k,4h`IJJח֭[Oüy)%S ݒS I$3wܱjO7n`ʔ)t fܸqቈD$t777 Ҩ[.NNNX[[XZZSZjիhӦ2b.͛Grr27odܹoYRZ5\Mj#++˗/pB2dH,gϞ=k_2e5j}6mزe SNeԩy։___vE||< 2n7vdK.O~ؽ{7 0d[5L SaIVػw/Ǐ~P$): ,?qۗ=zjHe°!44!cd۶m9Əϸq㰵5wXV JY|9;v )) kkkԩC.]ڵ+WRɩSLEFFѲeKvMtt4ř3f NNN,[$ۓkrǼk.֭[G\\7oޤrʴiӆCbgggcZZݻ2eкuk{VpMKK#00;wSre^{5hV:555kмys0Uƚ5kӧ)w+ԩ!/ IDATSqvvԩC?i2țd`r>cƌZjXYYTxzzR|y_>s̡cǎuwӴiSwNVV7+W |||pppʊ *ЦMVXaRcرxzzbkk 4 vZV{˗ӭ[7}3κuRbEʗ/'ʗ/Opp0ݻwJ*XYYQJzŊ+Pqnab*5Ύ9)W۷yHᅄw^^xf̘A5С\~ቈ]dgg{n}]VJnݸ|g/uypqqԩSL6M)O%Kg@FFiii;v3gz)UFjj*qHʷ{@9{,iii8::SO`RSSM:O>aDGGsu233INNf͚5y[_nJZZ)))| 0 3dBBBp$%%[8gggn߾4c2IKKcǎ>?fS w9-[@KU@bb"]ve 8ʝnJ~/"%ǟ͛Yj[llٲ$&&yTDD+''cDzzj.\@ӦMgϞEč7`޼y<|GJz*ܕFM6\~ŋFFF[la8::i&&MĎ;5k^^^tؑ/uV~i._Lppp0_3}tڵkgL1бcG&OlD;Σu֤1a:uꄅǎc/_od*Uƍs)LBbb".~tR6lȤISΝߟ&Ol*3j(T%Hذa||9rD)777׽og~044p\Bn݈6&ƪ'Oŋ899O*:;;s~>5iSŅ[pB̙o5???7o552V5$gΝ䄕kflٲ87>>:Zj1R@Qe1>}i&-ZD2eȓbŊta;y̜  4J6111ԩSDDDr ogH(K.1j(N:g[~Ճs'帺p;pO>m8%%V97Øa9(9E8͚5cС̛7aÆ)y+""Ӊwt֍rʙ;$ׯ\rի|,\H^|Es%E,wӓ-[g+=ҥKYjÆ 㭷KKK&22?9?Ջ~ cj ܹs9uիW_N:4hЀݻ;!kܫEZ Ƿ[$0;GI)DaHK2d7>>>xyyfq_5aaalݺ yrrr aҤIdddxb /E*T@Νܹ3'Od׮]`crj̙3p1*T@Æ MBŊ!&&tjժUd$:@PP9sƸ=33Rv 4ib|Pz;sؼy=+ UTd^JJL]z8GDDDDDD\t7HDDDW_} 6p>cΝ;oAj=z4׮]3w""Vvv6۷oTZ^zƲeHNNfΜ9Qc? 87|8 W.]pss/ --u\Vl|]YXXNVVAAA&∡ kkk~G:Ĉ#"Uff&K.nݺl޼+Wo>%<.\oooN3666PN?O 40~liiir-[ֹ1cPZ5HOO`رxzzbkk 4 AvZcL4 ///lllX"=z`.]+W |||pppʊ *ЦMVXaR ;;;ߟ8\ro_DDDDDD(<)""!H wߑLydffq#HTcĈ}:TZ!ŋS7oޤ]v|gtڕ˛;4yBm۶Çsy&NȘ1c5wX"4k֌C2o< FӦM#HN1yTKcHIn"R5kFf͘7oRbUTO?]vTR|lڴ ooo)|||1w"""""""&GDDD8VVVjsӕ\+"Lvv](1EƍLҥK1b^^^֝Dxx8GfфAd""8ԩ]t?=,]s&"%ҥKgeKxxx;4'OW^G+:u>RYw`y<)}u/lll3ĉ&)=˗/IPP "22˗/Zӑ#GXd cǎe̘1,^s%""Ő3'!!۷SNƏOժUڵ+QDJgұcGUY&7o&))KҸqcs(?F+W^`Ф B/zį0s/O#O&PkР3>v;CrJ޽ &""ooo9{%|8]v5w"O5j;B+6weKqw)iii9r;;;y숊"==d^AS-[r5;f2Kjj*-Z0K\ŋٳqW^\x`3F&""%Ereƍ.]H RlY֯_O^"Ntt4 6T Xt)\~Zjѷo_:v'޴4fϞ͞={(S :t`ذa.]ژTr)};;;Zlݻ7 !..+93f NNN,[$WZZܹʕ+k1p@c{۵hт 6q lڴ)~,_ݻwse*W+ A(W˗/{r ^y)k]SSSYf ͛7J*Uƚ5kӧ˗w9x zRJGD#GFϞ=i֬)K.1aS))Ej0DDDDDD D<d>3 --cǎ1sLBCC'N"--͸ߎ;oc)))\p<<< ~JJ /L:͛7?alBZZ)))pBz)UFjj*qHZj`nOKKёzd jxq/ 2.\@FFIII1rHӼys,--(XXX /^~L c&T Mz*l۶ ??}nNZZEDDA=z'@׮]/?3gBӦMY~=K@233Yd ue֭Z={(1E LJ|||_DDDDD侔 6xb<Ⱦ}0ak׮,bbb[7vލ%ܼyǏ*|ٙc&b>$$K.† طoo&AAAyr ߿Bo5noР`'wrJV0IN[KڵkɌ3lyZ'OҰaC8|04nܘ|+TPggg|2pi~{+gʕ9sjժ ёӧOTILLzꄄpA/_O?縅p}ׯ815` ͛LDD999QD˗Yh-[cŴk׎?믛;D{ڳg͚5>`ӫW/,,,<̖f۸!$44p\Bn݈6& />̵kҥ 7o4&ySڶm[X ;5j`gglܸ1'RvmlmmyW2!ŋ899OPR%pS|}}ms7;w''']6ӧO`˖-עE rrrS8@NN-Zw!1ϏFammUݻsIhР4mڔ'>PԬY3qjժe2GDD(-[޽{m6aLOȣpdכ7obaaAҥQD"Ş={h޼9*T<[[Gȃٲe #F 11???Fa)6>ݛ}ȑ#,YkגC=prrqE)*TsrJǵkX`q'ل=<<CΜ9cDL6 '''Zh-[4hHqpu&OLÆ 9s w&<<5j;4yBʽsEziի/^4{)֧0뇿?gf&no%SR%6mJtt4գJ*ԬY?gggJۓ7l޼wy;woa2޻srqq믿_ 0yxx_orJ~տCll,&˔)èQx>>̪UꫯLKR$ѣ*T5jdX"m͚55;w0uT>G .Xyxg%K0bj֬ɢER] v뀀fϞͱc(\0[?N6{իWYp!{%***Uлwo:tl۷ę3gL20x`-DGGtRm?C2ex7߿޽K@@52](_0HHH ""+V&>>p|}}IJJ2ݲe )^rvv&::[f+ !;OϞ=1"h".]X"W\s 4[8gϞZDDD 66"EX:H}6>>>|WԫWӤIKǒTVKmƓԶ:tqLdvGGG|||xgYt)*U?̙3???ԩɓ)S saݺu<[-Zѣر#VVV?~AQxqvܙj>___.\K/Ę1cV.]bʔ)=zqѹsgݻYdl+ E l$yB噙SDrZ>}(_|_ppp0[HDDIt ._l("*11-[зo_}YӲ"O$|}}Y&~~~,Z0E''dSlٛ5j*Up¦/ܹcھgFIJ(Z(cǎ%,,Tk.:D:u駟;w.ӧO *** ۶m`ʔ)ԬYkkkV7o6={,`YGUR%Y'|>#z@pp0ݵ""T8s c„ 4k֌>}еkWJ,ih"`0pA ի4nܘI&i+yj2d~W)Ucd;cAFVUVܸi.g puӧͶ7CXSN)n?͛7"?f#""""""Rq+ 6d̜9ooo)sEDDT;Ϭ\ooo>:uD޽iӦ tLǶ~z΅ xGT^Dr?ѣY|9-Z_ұD̤NF6k` TcԖ3fpiy^uUFݺuqwwOwWyŘ@ m,""""""W8E<<<,CDD$G*T;ұcG"## dժUݻ^{E[rxwٳ'׷t… ϰcժUұDr{agg$y$}YOΟ?O:uRw|}})]4.\0mOHH`/988p%6l؀Cy퉈 22{{d"##M}DDDDDDDddSdɒ 0.^yj8;;3sLS_~~9_>}Z)T1b\&-Å 6mZnڴ)3g$""Xf̘YǙ3g7nΝ;K˖-;v,gΜ!117n0w\25./t%m-A$""""""ש8EDDD$\r߿lzyKwWݝ[:E\|ݻӲeK*Uɓ'2eiK.t1;...|4owwwJ*{=9vo6͚5#00;a7m?sLҷo_T±cqƴk׎+WRHj:XĉfYm͛7*N֮]Kr&11ґ$gӦMxzzR|yzMTT׮]t4\_|Aݺu_ٰa6mzꖎ&eaaamĈTXkkk<СCquudɒ㳜ޞe˖Ѷm[/NB]6ӧOC~#Gm۶bccCݺu:u*`͚5xxx5%JŅ˗' ]v-Zݻweݽ{7vvvi&+""""""0npwwϭD)c<|M̙w}Gppp[nGGGKǓÇo ƍ8;;3m4)[䪍72tP"""=z4#Fp–%ڶmK۶mVbkkѣ=ztS? *0eʔ43/^<>H\J(a6lX+V .]ʕ+WX"W\ѣ 4Ey .gNTnnn9= 鉇>l:t7qFlB۶ms1fҥߟgRft߿-[Opp0 oߞwyEBjی?EѰaCGƍ-KDDDDDDDD$Wty\p4hĉX"oĘxbjժE^x@r1> eh?///}]"""3gӣGHҥKQk֬a*L|YٳԪU1prr ,,,r4i{d+++ZhA-7o7ndŊۗeҦMS;wfM\2>/^dҤIXYYYLK.κuزe k׮eر;f&M? IE`Ȑ!9r3qDJ*eX"""O-,baDDD D >L%GaY@nݨY&ճt4lgkknnn\v {{dHJJgϞXYY /ťKoP姟~W^TX0jԨAYhΝlٲi~^F\L+]z1cưl2^u=Jݺu-K$Go"NPP'Z:HEDD$˞┐KGȲƏ+t҅qrʙ-Ynݺ%+zׯ=_|.]:7+IIIL8ɓ'_mZŅŋӪU+믿pb-!! 0qDJ(ի֭cƍ0EBܴDssst|'>>^)"""ey8%+K< -[Ƶk޽G^e˖1x` ]ѣ|fڶm˞={С͛7gӦMT\)n7nÃ.\ȠAm^௿_,cΝ|eĈ=;;;KQC aȐ!!"""""""OK777,C$їĩI"/>>^HXqJjS?Rvؑ={0rH*Ud:~j?SV ƍgϞrfVR%YK/ŋwDFFMll,o֭[ܾ}bcc)]4nbʔ)$&&2uT,}*OsѥKΝ;oFv2}5jD<'ѣ3f瞳t,'F9%5W\<~ߙ>qZje뉗,Y$S͛7w>f#"""k޼9͛7o&)) kklLtQǏ7%&&&Y[n%{m, 2*SLΆâ|VZ$/y1̟?N:kѱcG.\ϙ"}]hԨʕ3/_'''{cĉ믔)S 3ɓ'-MDDDD$┰TA1b+VK{Yl+Wkkkʕ+G=X|9%J0?tP\]])Y$6668;;3~xqYlm۶x*Tڵk3}t:tsj׮EefvލmڴqEDDDDD8pF1x`zř3gׯiN~ O&::ԾuVn޼ ͚53Ϟ=w&+HO\\^^^Xx?&))qO-[޲e 8;;ٙh{%"w%HJ(\0ٓSN*ǣpsslٲPZ5FMTTTVX<Xbiet 6Xb:' mhҤ 666.]wyÇʊ˓b߄ʗ/ooq&':t+++j֬gbeeEٲe9,[:uPP!ʖ-KnRI67GDDD$LqJZڶmˏ?ٲedɒ5͛7sA6oÓ2zhoξ}7oe˖M B L2;w~V\oOj4+V =ʕ+WLW\ѣxzzRhzoDDDD\j9b4yg|y <<{gggJ,oٳSaSD/2=zx;(P{%66߬j'UVe޽L4_y:ͪU8u/"1wёo?8"""aÆl޼9ǴMzŊ4i҄krupӧOEܻwZ ߒ>Z43׏ÇMb+ 5kh߾=$>>۷oLӦM9tP9j֬믿իWٴiS}6oիWyM9d֨Q#^xΝ;ӧͶ_ 0 7$$$puqrrbƍ~>""""D}Yj׮m;qԬYd7iܹs?~Hf͚XY|qqqٳիɓ2p@.]e˖п KnȭlݺuW0cbj3&Mpbcc9y$:uxzz?dSr->>>Nxx8PHK7R藟o+̙3Y:HԺukL)[np fNmB5emH~c\f>Hqq&[zHzABBڵcԩɶ l/&ku6lʊ={&֫W/֭[zڲ_YkSPpazMBB+VHmժUiY3;>[ׯO58x ׮]3oܸ$7n}?g '$;ZDDDf͚ŬYѣ㈈+tQQQ=URpaTرc5;!!!ӪU+ӶkҪU+J* +W棏>2}ٔo?RJ} Fddds111|oOT^Dh۶-IIIX{ѬY35kFll,/&**lIrpp`Æ )΄-dfZjp%ی}D$}wy~~-/^l&'Gvvve\gΝ) /X8Y2+ԩCӦMٽ{7`'NꫯhKNlƥ})l۶ H8L2)(QH>#W^~EDD$Qq<s;f͚EXX7ȑ#sI5kEhZ_~% .$::Xv `.g̘SZ*ٳ*UpqM"?ϟCt '''N>ѣ~4hЀXjժEr3G}VN:iN:šC2744ӧOgoVdGgOIix%f_~ڵkyfN:EHH888P~TK}6JG)""""oήW N:;WZeψ#Lkܽ{$5j#G4Ҕ[n/^ƆMxb~tǎKݺu?ٹs'W瞳t4|͸lMjڶm [gQ>#FbŊX[[>>_ .i/fmժUDO@׮]-v>""""i2d3???Ç5C=x܇dEDDf#… ou C׮] zÇ-[f8yYƏNe Nw|ɓ_~WZ:S߿XΊ6ۆӧڦOnر!&&Ƃ$/Пԯ?䯿2,Yx  111;vh1,Xp>?08::ᅴ~O {on[0|g`ؼy0899e\ׯo ?- 2%#Kk{j0+V8`'+KF%#f5[FK/l_`ACddd ӧO߿o ۷7^x!ٿ{>&"""C9~;9=HURgPr,c˖-i˖- ɓ'M)TP 9s={$Ϟ=|"۷8q" ,W^a߾}4iұDD->>>|G `͛D2bŊiܸY R^=I&p1?fYkԨ… ߿?SNeԩk=|w<|rڷond)꫄/gs-֭[7ӬM6Di dРAejʗ/Ϗ?ߊ^H){a޼y9=͚5cȐ!!""O(+++ ;5kweڴixxx0|~:fb̙lْ;v{\777N:E~LoݺErRsL6 ///VZ ~;' '``3.\O,MD$5lؐ3sL 4p*'S8z(ӧOg۶mDDDPhQ^}UFHoׯ5j`ԩ߿hVJϞ=9r$ cooO3t\Fɏ?۷)UTdi$44'Knl[͍ZjsQ*UD׮]5jeʔ&NjS._LPPnnn9=<łR\DD$#ʖ-˵kרUiѣG~zGÆ /Z(fJVwlÇi߾}'8;;'ۯF;NZ)qa cL<ҥK[:Hl"٧f͚,]4C}oݺ17oNS^T)bbb2u̢E18Y2sԶ￟ؙ\3+uf̱K*ž}aݺu\zӵkW&L/%߻~:ƍoٙPׯoX"""""f5lt̙39sd$ m}Y3|ϟEFIII,ZSpa;<<UVѺuk9B:u,KDRDΝ-C$ 1D$<ܼywyEY:H7)Ç'$$$CIIIܺu;wʕ+TR.{,X ʕtr,X5k0 t֍5kR^=KG7o&MTR].]X:#>>^7}<˗/gz'])N IsE+IIIÑ#Go4iRNGLSFjrbhf̘̙3ع%&&ꊃ]taܸqakkk"""""2d/^dĈ|\ 營cE bŊ|',D`eezdgϞ-"""O<7sΝ;;v,4hЀq1dȐd}m)SPLJΝ;y O9ZG%xt..fg dܸqL<???ڵ ӧ駟8w **ʬѣQ,Z3fӒJzbɒ%ɖVy={MRJ>"""""}:u*3gΤFܹKLf t IESR*1fr%ׯl{ |2:uJqg)5< 6d888d8fNoxё]vZV\I߾}\~CrimVZE5=V鹭c͛7(^Y?cd@Fɝ;w1c,\g>Z`eenG4[Gj2[a0LRTٙ9w?Znm}ƌ>}_jժQnTפ.\p TftLc[JoH:u oooBBBx2e >cSlϞ=ZzD$wM^DDD$#,RV!?_~7^}USofK.aÆǚ$30 ܻw;;; s3X"sv]X1FɨQ2eKҥpi{BBB-󰷷'""Hm3.hd۷4iW^a߾}4iұDDD$ї"__"""mҞڴiԩS9q ?~Smٲ%cǎ̙3$&&r Ν^^^1KdbpM39eحZEgqƍgjs;Afl{xy!8˩]6+W䫯"44T)"""""""""L[֧gϞ7;}_~رcxzz&VHjz]tin޼I.]ppp`Æ Y?_~ɗ_~ sL]c=0yf&L ;sLޫd<6mJHH'NA8q͛?v&x{{s! ɓM""""""""""s3ڲd:uDR(X 5kdҤIؘ닇X[[SD \\\X|y1FAŊ&...+%KgggƏ39eʕ۬}ȑm[[[lll[.SNeY&ϣ]v-Zݻwgٙf]~///5jD9t_} SDDD䄓S?{l68 6aÆ+yDDDDDee8k cǎTP*ĢEXt)ׯbŊ\rΝ;3h oᄒƵMR|-"";wPD\oժUf3/_>YIDD)ľ}xwy饗?sm_j߾}8991tPٳgTaHBBB,:NLL Ǐ*T@.]7n111MDDDD(tiӦѪU+^}U tҦ%bD2 '<<`|||(R㉈HdzuVsѴiS֯_[oEݺus-ĉ9<6Hn w4k {{{9̙3)^d.$Zl׮]{=zp5-[fd""""tG5J*O?qExgy߿?ʕtDy5lؐ3sLiРSHfݻwuֱi&n߾M߿?qttdʔ)'))G7~Wsmlܹs4iJbڵtұDDDDr̍7ꫯ !&&VZ1f̘FGGtRm?C2ex7߿?666 a](#]z w^R {68w% F%^|yW^*:\S ("O%""dq6l`lݺ80a;w^0Xkk\˶{nOuƚ5k5kV/oΐ!Cx"Çg̘1Z:H{.ʕ+{ˋSNĉ,XR<3߼y>}puS3aرclٲhͶ9;;֭[ڵkNynYpϟ믿N">>sk. /Ǚ8q"9/b^zL8\[S^$'\|777ZnM9~8 SDDD䩷rJ\?ϊ+ؿ?K,ܹsf}WZũSx饗R^=BCC 7KuFׯ_N:ڵw}__4ٻw/k6;cHnPq9ofȐ!ڵUVq56mĀMI{GÆ :thf??{-G̏5fRvFʏf}ǘk3>%)LLۘGC#M IDATas82JH?TWr^.˼:^=gF[lݝzN:\DJ۷;w.[&&&iٲDDDD!ǣӧӮ];,--ر#~qT\-Z0k,""" U87M6 ٳ4k,ױ͛#""""Rݶ>"""""mڴaxzzbkkK͚5O\\111eݻ8p saTZL_|ɓIJJbƌL2+++c_~:hr5ϱΝ;W\E9?!!z1r5jԨXv[vPf)e5TPFG24l0[<==9vM6qdܹcoo_qvv6 ooo"""KmWΝcĉDDDƂ hҤѱDDDDJ̽URo0L9Jܷs7ox(?=s+UʽxzvًHY*BCCK{y GIVXAdd$$22KKK-u<==y4iRu,\֨Q#^|EBBBT"͛77o .'d߾}tX""""jҤ ϟرc899cccsŋܹ;;"U?r%Ν;G۶m4OzHJJ"99z8l#""""RVJ8iӦΝ;IHHҥK`ΝO?DLLL,m;v ==7|3Gƍs=o͋/O>>V^k+Wf͚t֍uXdԩ4nܘʕ+^իG`` ={FXZZҦMϟkV>~$SӦMy!""%gϞDGG+bnOMMsѲeKCZɓ'=6mbذa$&&ZYE,L&֯_`ܹ;l%"""R҂ \5kְ}v7n ˗۷/Fw18w~]4mԼHQҰaCsp):dXa … IMM嫯;w$,,1cƔq:y?~///=ʨQ3gu5:`ڵ7 7bggkK!V)"""""_X۶mi۶m)!!s0p8EիWet҅GsKDDDD dmmͬY8q"C`ǎ,]jժNDDDD7*N)FZ888OOO"e)++O?3f`eeh""""Rt ///-ZرcرDDDDq11t!ƍGll,&L;5j0:3CDDDDs """"ׯZQS%&&2|p\\\W111,ZH)"""""""""Rn8EDDDDԩSر#QJ1G}D֭ cϞ=mh""""""""""Rq/ggg7nqJDrr2UhL)]~-< 3f`„ 9sKDDDDDDDDDPt]DDDDĒ%K2e ZUXXXA*xL–-[puu%<>>L:+++cK...CDDDDD@)""""RjUg5:Hv9&MĮ]4h .I&F)ׂH)3LFG @)""""Rj,--ό!Rݺu .\ȓO>ɾ}֭ѱDDDD)FGpپ}1DDDPqABCC&%%3n8Tѯi""""EoAPqJFyѽ{wxW8}4&MRaTH)"""""RF_Μ9sXt):tСC8::KDDD@tttϽ5899i_O?(RfM:w̨Qh֬Y焆#,""""")""""P.\/btrd2~zڶmˆ X|9GUaHƏ?ȤI8rHΝСCٱcW\ݻo޽C?:ԩSYl111e[DDDD*>H8p_(bFǐr8991bx Ξ=ȑ#TI^1=ݻquu%++իWi+Wr5زe ?7o}dɒҘ1c ΎFѯ_?|}}IKK+Vn <FG2D||{دammmt)GO9s&[!C`aaat4CvJj%YYYZݻw%-[O>۷PcfTzϞ=y۠AUfnq!!!t|aÆ888СCQFYDDDD ]-44ۍ!""͛76lit$ݸqMCʉÇ3vXbcc0au3_DDD 3228y$'O֭[oҥKӧO?>;wDDDCPP5k,8;;۾kRSSqrrɉ#G{n_b """"+Ny7Kj()!*N?ra\\\S.deeAʁDMg}F݉m۶Fbضm˖- """7o7oγ8%Q\]]9rdP߿___RSSӟT`tR:wӧ%!! =/--?y<@6mrvAH(׿QʍLjժet 1Hff&K,aΜ9ԪU0ݼ)>Ellly&7nt֍0`"e8s gϞy bҥdee䄟_M6ͼIaر۷/;w0e.\… y'Ξ= @fr׼y}DDDDDV?pYC)]&""R0%[nA 2~x.\_W|||6:b餤(lߟp<<<8q"*U*0c>,Ko޼_WN8ܹsy饗rv@PfeyXrJhhhi -"6>"""4:xNJXX{&<A_>l#))dիXrrHI(x@y$$$fc<2x j׮mt )e_|۷g޼yp)TP}-[ʓO>=PUgΜ9kOOO.]D&MX~} SΝKll,?~???zes)|}}iРk׮ͷ0੧~/_v[vUj+ȣ'&&޽{ckk1:Ν;ǤIصk b4mX""""Rc޼y9u1s]^xyyp .]D޽_жCu3G[۶m4hիҥKѣ9u]t5<"""""ES*k׮QjU,,,Z*׮]+-,,iqm6\\\hݺ5Va#G?("ed2~zڴiÆ ѣ8::MDDDDt ///-ZĢE;v,;v4:T0*N)H:tիt$%%LN(9_GGGlիW̟?_|[nݻO{nFcHMMl޼W_}~ _Ύ;pvvѣ氷祗^_e׮]y_套^(EDD"UZ2:#͛lْ}E8;;3bx Ξ=˨QTI"HMtttG}G}Ku.y}:/UVTV GGGV^ĉINNf̙3|lʕܹsA'мys,--ڵ+6m>5u:thKY&7~,,Yf͚aii3+W~(0K[._~%III9]r]vQN """"RXYYYԨQ$ YYY\6mκu8p=DDDDDDDDDD*<C63ƍxJwwdLff&z?o//\:88`2pB~;wbaaGcC‚;vo륗^V,ƌK.Z-HժU6l_>DZ 2222dժUJ}_Q!ݸq@[s &0|pΜ9cXDDDDDDDDDDJ_<+?ﱑ#GVZi&*Wsxg kӦMܹs_~M8֬Y3^z%;BBB,hҤIdֲe\m666?Ȼڵkyo%󾈈T4?ӧ...ªRE?VGlذݻC۶m%"""" ,,"DDD$.z1y|||7ngΜQaH^@=""""%A+CV8v/Kϻ}6nnn2{l\]]۲eKbbbc_CaÆ| : ֯_ϼy YJ4i۷oO>!44ի3xT$iiixzz石rJFitB^IيgԩѻwoiժѱDDDD8pKCB 5:TZ9^}UΝKfff㡡XXXkh:u*'N_~8/ 5kr‚͛p]7n\zyygzd) xxxpu,XիWqss˵Pq"++W^yoZ)eޞ_4k(;w0w\ڶmٵk;vPac">>0cTHaaaSˋ˗sA^}UС&$$uQJر˗ӡC6l؀Es3+VHÆ 8q"5j ** & ݻIHHqts=ٳg#G|r,XT$*Ub„ tܙ-[PjUZhat֮]4iIIIx{{ceeet,1Vv)yxxxCDDD*R k IDAT7&88kkk /5ݻwgժUtR}Y9gĉT^ <ٞ|IVX4l[[[^yN:E.]6m֭`رʟzJyR,C<ܺu~^x!W/""" S;w::;vԩS0EDDDDDDDDDRqJ1k0b4i%jբG޽1cs1/Ԯ]+++Zn͜9sطoժUرzVqݩ]6\~IJ Z5%[QytKpc4mh""""""""""RmYfMoŚk׮t5k&--Hcc2:KQxAۼ(<˜:u*)))3~xTѯ3"""".ǎ#<<`2K.xxxШQkx#,EDDD\G͛7^1DD\\Ǐg߾} >???쌎%""""@ff&seΝOxx8ߣyfL& ^[HT""""9r# }G$''3{l.]O?͡Cptt4:T@ȢEعs'UVeȐ!у&Mӧ bm6ׯ_P'--3f0`sx~%,, kkSDDDD} """"BnС/qDJdbÆ iӆ 6@tt SDDDD888z駟غu+VVV|駌3VZQjUر#/W^!55[F ʕ+̕+W 40g*N)L&3fݝ1cưsNjժet,6nܨeKqvv歷7̙35Jk WXr%K.⋼[l߾=y[nd21x`ڷoF^M6""""")""""唭--[d˖-h8[n'Odĉ̜95kKDDDD*={{pM6n֭ `9eee`aaQoM6ÃkגU=c28}4_~%?3G͛2+++g/H'ȽT""""RNժU0c{V,11 6н{w~Gڶmkt,I&ETT| #Fݝjժ5hЀ.]Tlb좗pU&Oӧs3L_ڵkԨQ#W>"""""RqH1bmmmtGBff&K.eΜ9ԬY\<))PI^+ܯgϞ8::wΏ?Ȋ+ bرN:7|ȑ# 5,--kl&|<==א pi4iK/D˖-i׮̳*Uov[A!""""R+N""""Reddᑰo>ƍ2e ӧOX"""""Y&޽{Y~=/6׏;wai׮]c"IaYXX`2uիWܹs/** kRNΟ?o>I*٠^z$%%LzrKNN6_ZÊ;& [[[c[x{{믿Nxx8Z2:H˗6mO>$.]rtO3`l»ヒzO/_&::pxS׮]cߟD͛xa?syfϞmnOIInݺSOŋs\xGDDDD~2sa^}URSS"0uTnjtr'==sҶm[;Ʈ]عs SDDDD0|p͛Nj/H.]cǎ9z{{FFF6l'''x7?>gΜI&9Knڵ+vžfΜC ᧟~2?sL;;;Xv[׮]ODDDD*_9xxx"RT }]zݻw#P~}#;vbҤI$&&kz]J*iҤ ]v5d\2SNՕ?hȠ~mۖ={+Pr"$C … Z͛7z?&22aÆ8IѣGHV)q0G@VV퍿nR'Νc| 8 ҴiSc|8 6dƍ涍7bggǐ!C L&""""Y"""""9Jbb"{5-ڲe SL!%%ƏO*CDDDD"f֬YL8Cc.]Jj N'""""U9r ko_~o߾4hЀS$gϞ婧*ڬ_>xzzҨQȕ+WXp!G!##wwwƍPc/:]1צ8כeaJTT 8<""Rr[h޼qD-..dzo> ?vvvF2ҩS'Xhcǎcǎ̋Sbcch׮]۷/(E2e/HOO'!!m۶W_@=/ǎ3?zjI,PQ^ޒTZqQ?~6oތdbРAIDDJ'XYYEX3gK,駟СC8::KDDDDD 1DDDDQnSW}uoÝ;wpDEE{m65'Oԩ% zmrF{\iii̘1?yܯ_?|}} +ׄ/*LGd>cڴidddl2FIJ&""""""""""2`~lذUV@HH˖-sjժnݚ;w{b*UTV[rmʕ+LDDD3h fΜitRuq\\\x뭷۷/gΜa*LB+wW?GGG܈'رctޝѣGl2\]]ҥ {fŊk޽=nݺ믿΢EHMM5sř xzz ;ǽ:w1k{Psԯ{%?멠q}?c~/^͛7sfॗ^o߾dee}1BΝiР_Æ E\7n(k+"""e'!!ׯTsQtt4+V^z'GMl듽UO?;͚5c֭鉽=׮]c\zv9fΜݻwݻw/^̍7OOOgř$&&vZbcc 0O>a͚59KJJ"$$fϞuexgKtҔa~=͛ۜ?ܖDpp0Gaڵggg֮]7|CϞ=} r^|EkRSSqrrʕɉ#G{nJDDu._̠A"e -- [[[c,VZŌ3$00Cbaaat4|ULSо}@m[Wy ݻT5C%1\ciz0qQo>|||С<3L>ojbO:t} [[[:vٳgh֬Y7o?weɼx{{XN*WQ{%&&[oD:uYh SDDDDDDDDDDD)+Rd[` ,0?3gs~_"!!zPg>[||<y?wW^eɜ>}:W?TE0SN0X<{\ԯ{]|gy&Gs=c삲2͛7ݻt\s5jԨk>""R\~777ϦMbc&%%KKKc[ff&˖-cԬYP `t,B;pFЌ;TeOau{WԀtj! ,4i҄^z-[Ү];y2Oa;v ֭[EFd~Js7?~YYY?kݺu߿?ƚRތ*^(M抈??3ܸq*ȕޟ5cܸq_bԩL>B#""""'\KDDDJLDGGs1FIYnftؑUV?K.q9ڶm[x";wήQQQ]ּ333v(}ꫯHII駟v[]x1׹mٖHDDJƍU;t#)tΝKv8v_|;wTa2֧()o{ĉ9ӓ'N0dȐǪUɓϻuFDD3gd̙:s NNNԩSk׮ѯ_?عsgW~K׬YciiYkOa[nl۶??''kS-.z:η~K||<#FqnӦMsdذaZcǎ9eFDDO#Gk.._Lzz:dzyf}pqfԩ,[̼eHY0L 88.22ɓ'ӬY3nݚʕ+Yf ۷oq\|}2j(yΡGHKKcܹ|Ghт"""""vk޼ylٲU2dzA&M~lllضm/liiiٓ &{ueGSy~GZtm#JMM%--իW0t< >]vqFqFrm]$""eoёիEPl”)SHIIaܹL0*Uci~0:H6m /`t C9駟غu+VVV|駹V ر#;vc޽lݺQFȕ+Wpss3 ;~̚5' XvҥKVZd,X `F)P\\&Loeذacgggt xxxCDD@lܸ"+YYYZݻw%-[O>|֭[1L <8볍5UҦM\s':::Wd޼yٳ+++\\\0aBUYnܸAHH;wA @HHCFzDDDDDSDJY HNN*WoN:ŢE;v,;v,""ݹs#GqF.\)RRR={6K,駟tX-k-""啊(E. 6gddpIN<ɭ[WE#z*p-Z0{7|v ۷ && j֬ _Mjj*NNNwrrȑ#޽X.8EEDD;FDD$))~Ǯ]xQ(&>iӦe9r$*U2:#m۶m,[ 222`޼yl޼\@͋< ߿___RSSӟT`ҥtܙӧOKBBAAAz<clmTqǏO>TV(Znmt$){%>%-**bI4"1b4* Qc!Q$Q,HRQ[,"QA!ҕ6aav~s;wݙYs/lmmQ-11| ooo!I{>| .h; ""z͵n}vDZlzN"`llݻ4hƍq+))(]vڅ 66>s!K IDAT66ߨ)w%Kၓ'OJ;ܼyЦMrK:Hi;xlmmammH4nX!+wޕ }"!!zXTgr"":GGGj; ZkܹXb-[`ڴiptt4_ѣGh׮a͚5ؿ?p}ghee%ܳgOǏirK$y4SmP5 Deggk|Xt)gggv!5ND/D2K>|8p)߿W\͛k.xxxHD?qq̜9S%`\t zzz/`ggT޳JFp)ݩEr $DDDDI5kh"R **J!jcƌvTH״8#)) sohn""""UF`gg;;;ĉرcSƎ`Νׯv*rJXXttt-~Hk;cJ9YUNB=_ׯ_gҘ @GGh^jٳ1c:w cccUV7nVիz_YٹR2^z|D ;|6vX,_o6+V[~},Xppp[oԫW͛7ǠA={o߾h޼9}}}i#F111嶏AÆ 1lذjH>rDdddMMD a߾}TRR/~-n޼mj;$U.ÇXp!"##1j(߿:trD CAAwzu.x1~'9wﮱ)1sLխb<{ /_˗i&|tv xzz"99SHk ̄Yfؼy34i\vMۡNwbv>stFFFGNtR;w8}4+KOO͛7ǻヒh,Z /^vxDDDT"::^^^044vxDDDDxtb :b1FPTv*m/!)ŪEFFb?>""*9s ===\xw܁F^z!%%K,C# xfΜ֭[prrBJJ:::~JHH|M}DNN¸v4i4h'ʤWۃ РA=ʱc`ee}}}4ncƌK*֭[с-**4*%&&ƛo{Ta;u____n\xC 7n ;;;+_zY^s|0`6m ]]]4k F©S*֬YKKK#!''G yyy’%KCCCK.‰'UUΜ9#4jHPchh(>^a >.3g˖-[GYϟ?bbb/^ȤW| m/;w\~yyǬ,Ra:::Ʃl}*Sz䑔wxwfBJJJc ԩSo>YYUP޽{yt333b#;;[}JDDDmYYYX`z쉌 b077vh%|'rKF8z22331i$aĈXfǏm+!ݻ'?с̺)S@GG5pri"1{riO*x9J3cuvBaa!&O CCCɽQÆ +"U=<<<ʥ˿?w߿A`iiYn[o56ʥxBmA}]cǎ-ZzdԫW/>|XԫW/t.\@zz4_~AII 틦M*T9$~Օ&s9mcU;/^u$!!p-8::M6駟 WWWXXX ,,L?##...2ܹ˗G)N 5kRRRyRSSdlܸQPh˖-|NKKCxx8]S777dff?~ %%%Xd `ƍعs4aa!rKSŢQe9ryyy) qQ|GI""""vŋQXXMkB$ĕuP}u3gѡC޽חY@=kx֭[ˬkӦ SN!<<\nhժU4ubh߾}4ccc@qqqϘ1}BBBd~.;qiԨ={l#OUχ:KLaWRRVLciwŵk . wꐛ V6r**Wҁ,Iβ &`ժU8p>cNSє>U=^{ׯ_D"eYYYUZ2KwL]6V5ʾDk;:'**J!Qѧnݺ]رc>}.]`޽8s >C@HHHr۵kXi']v!%%ݺuCXX.\H9c8wn oɿ%˪S6m`޽Ŵi'O߻w/ ϟǙ3g 0NeڨJ,UOll,s⑤ID)00Dcƌ1{lvL!ʏf(?H`hܸq<999Tc^^:uJ&<#UEB___mJҥ [n%''O>xwy9.oܸtLEEE S$T'yxyپ}{ovvvXj;c(M22I˖-F^U9˒# ;㔥H~tHyt:T*瞤6UST=mcU(:/^W[ """jS$$Qv*wYٳ J[dt䎲&O,S@-Zq!Μ9Apu>|oŋ@JU̢EmurrBHHCccc 44wŠA0n87ҲUmce({|T?7ocLYm۶CDDE2iJFFddd`ٲe D߾}^zi;IҎ})UV!""wPSCWK-.=$ܹsa``8|0aBBBJVŢQeddd$Mӧ:t(å|iGN:FHHbcc_"mܹs*msL8yyyXb\K^̎;SL  ?'Oɯ UcnǏ)ۇϟ#22 6ĤIds\&NQ*?#++KfuM[z5#E]~ޘ6mdFQw*!EU::_IYr_pA&*&Lb //{ɝF$䮿tRխqW|WoQm&w8~>DDDDA#(KՋ>W֩h!k׮ѪU+ 8۷G׮]Tz*'>VVV8uߏ+W`صk<<:$M_`^cbҥ1x`\|ׯ̺dtmڴQ\\,O>\wwwڵ ?#V^W^Ub FFFprr¦MvZ<}ӧO/7M:ǥO>6l; &`Ϟ= x1P^=,XJVA@IIJSI^(2eJu1b~w]ÇYWRR???ᆱrƏ///۷OJMN飪1cň#퐴&s9m."##QjU*..D"EA8w 3fkoo/D"ڵk-HT.}رH$J㷵D"!M?e*Kz %]&lذADMUҕ=>QF "HxiuO>D"TZN#Qm~D0`k;z ЪU+R!){c7p!??_߄3g (fwrrr*֭[@/4!77W8qеkWW_ bXvK >|X@ᵦ*(S^E_rE 4h@ ŕˣqAwЬY3[o 7nPk ˫^u@ /^(Ufٳ4HHNNL"P^XX(Btt0|p'>}Z2*j:ZW>~tݘ1ck׮ /^]&3F  WMu]WWWW̔OQˆ#˗/ /^_.888M4Q\Qnu:绺meڎϿ47"""F59eǎH$A!((HDoH$L:UHMM󅯿ZD4_. O>;A$ nnnҼ>@4i X,D"CUQBH$DEE BAA믿 "H8p48m({|T?D"ᅲ_ұ?/df2___^zŒ3d~T#҄BoLMM֭[ ٳk;42U<(Yyf"Haҟ҂|Aaa۶mJ&LU#([:?bG t]a$cǎRzG RxT.r IDATTfPP-[&m={CаaCVuoE8::Z٥@n[터j*iGx?`jj*;wV6]]6 vNϿ47"""FϷ$s5wMriSNEӦMqU|߿tX3fTZ+ڶmWb۷/F7o4A˗/ &O[nI߸qиqcرcs^ROU|}}1`X[[cɒ%KKKi>yq*Fe){|T?-IU)N""["((ܔ~D5ԩSѣ/^ NA$ȑ#qeL6 Zx 6 Gٳe*1m4>}>LMM~+Wɓ'ahhgϞ!::M6ĉ*ؿ?={VmԴ3gO0E[nHJJBPP{=COObŊjW۶m{g @WWnƌرcz 4jC/ooo,[ XtuuѬY3 w܁},M}[>=z4.]ɓ'0773JSHXYYʕ+1c;wFXXs]]6joUN,C,Wi4 .NV-S"##1|̟?S)Jt+R=vFvriM6Ŷm۰qF?ϟ?G< 6DHH~ApttDpp0\>h!B""$Zaaahj3SFII RSSDr @:JJu|,[ ƍ9/T.]QQQ022:nش>DqqqBCCi077ɓ.~Wt XxtCy7o333 GHDDrd{! Sb51ō"C˖-xb 4RoMڶme4iӱm6-FFDDDD;+^^^Fjj*RSS ///GODDD{?ᅬݻƍXt)#"WR&MЮ];ܿիC""v\)))A`` Ǝ kkk 0SNž}T*M6L'N`֬Y4hyyy%K@,_X,mNp% 2fdgg#<<{Fͥ lc""""׋Ʀ!RH$;rTDD 9s&fΜj;zMcڵѶm[=zÆ vXDDDjժ2220fj;":gƍعstIIIHJJBnn.*MJӶlق`|iiiGVVD]033CZZ|}}Ѽys|*G:KGvv#ʑ#Gre >>GG}R\DDDDz)qttĺun:L4I|D9{8stJ/**ױrJtݻŹsuV@LL +V@nn./_|Wͅ5jR{v!66Vi%66йsry%is Aqaܾ}/^H $L4 }QhSbח.߼yֶm[T"""`gφ./ꪲ#HF67RJYÇN:ʕ+ؼy3v|G֧ڵkquj DѵkW?^աjGM{.I!""""RƞGEETDwDT[سgv'''mCuXJJ <<L;x?DDDDT{3O<'F;ѣG==j:t(޽ oooizVV4i/",, ={D`` ݱ{nڢw5R":uBZZ}ڟ U:""""z=U{申gbÆ ], 22R!i\bb">a֬YXreoUs~^ǜ9s+%!!Acǎ."##ߴj pqqR .DQQbbbP\\;bɸw⯿Š+ТE @-h"|WիΊ:1}bbb,.&& 6İa!DDDDڨ)>ܶDZ4.##˖-C`` ^zxyyy022zvi[TTTM;Bqvvvjm[]7sLu>5jFr,֩h x Zl x ._ 777+)H0rJԯ__PTRR~K,BBB _XXzvi QMpqqEBCCannɓ'k9:"""" i;"""{\>} ""O)SuLhРF#"""""###xyy!::HMMEtt4`hhSw^@,#** ͚5vHTĶm0p@\r]tJ,4D"""""BO1rHx1Ѽys:ty&:u$&VC'$uPGdd$VVV?~F%"KZ _}fΜuOզ[labbݻwc„ U.711zRk?͛7R^AR9DV}=GGG8::j; """"49%99еkWnݺxݟ9N> OYظq#""" &L SۡQ-Sb޽ظq#ݵ!OƜ9sp ̟?K,AÆ \=߯vǐvU9{ uN,פӧOW;TV_M֭H~~>-[q0vX,]QQQ022HDDT8r pHMMp1{AǎW[YD3E= """""""""zD,K?;wA,#<<:m۶!=='NM4 ضm##"W\ao`aa8ݻ֎)D&?xADDDDDDDDD9EYO>ņ pY}pvvƗ_~ @v<رcѬY3>}:@V"><<z* 0tP̝;FFF ;(( ,ƤLAAA8z(RSSc̘1Fxx8z͛K̤L tttWaPp1|g>/^EɌUV!22O<9l2x9ݻsNL2EmXX(iHQ]zǹs`ddAҼiii/\;[n-xyy!""߇>u놏?ӧO]L9Mgރ45>U~:is[6mয়~Brr2\]]aaa0i\L>?ݸqC̚5 )))ҴT 997nDz53@233ϟ?O?,Ym-4UڵqF4PXX$$%%!77NNN#G //666곱A||<=>H@DDDT >|ya޽ǡCжm[<ϟ?e~<|||#G^zؼy3bbb駟bhݺ5>|wwwl[nUM:JVZ~III8|0~rS`ݺuHHH@߾}B\v 055Ŏ;gggYYYؾ};7n,%x9bdY:Jԩnݺ`˖-5jLY 6Dff&q5c٘={vqӫOQN= Mgރ4ٳذa $DDDDU)e]k׮.\+WazҲ\>ɭΝ;JǩKݨQ#@IIR{4U5w\XB:-[0m48::PO#y%iH!""8v&L+++vN*sΝbĉon߾ $%%,رcC.][muQ(M4 {M(n)kôipQ=z˖-Ò%K0w\W?QE4y{"""Ҕ"** Q4%.:4:rSirrr5[E*z+P]ÇN:ʕ+ؼy3v< /ISDDTmذ9p˃СC߇~pttĥKPTT4,\:::2d4ooGll, ~摜ӷnReM4 3gΠpss+}-[=zG*y2i}T_߇k庺ԩSz*&O,͓.7n;v,qQu꫈*rqq|}}+ӧ\n^y񰵵U:F""푚sΡ{jxyyaÆ ֭bccamm]2===o>;w"Hf1֭[x\]]abbzzzرcz$%%o&ѩS'iWTf駟J'M7o]hf͚wwwˬ+-:4y{"""MԝrQ2͛7CoeϿ%sH騑VVV?~|MDDDDFNvriFFF LMM x{{}kaÆ #Q~}4j e.,X-[~(((VG}kرX|9~mC__۷+VX!7b#&&\}111hذmJ""zmڴ B*m۰~z$$$Tc 8wΝ6m@WWM4=ЫW/;=z4=m۶E@@?~,~zkizC600S0{l000ury KKKݺu'vQGӚj&xADDDT59F$&&bƍXp!,X\|Ya0|p̙3ĉQIUQST1`bٳYYY()){HX%չLDhh( MDDDgϞO>A޽QXXxlݺvLDDDT[AAAA8z(RSSc̘1R]ʔ]llGnܸϟYf4hall,MPP,X gUFxx8z͛K433X,Fxx8Luv!RdEu8|0ݻ?5O.sAKDpwwZ4իڵ+ׯPx">SpwwNJ+`jj4aÆhذ R6xADDDƍsNraa!\tY.{˖-IKKKCxx8-*_U#G //666ʶA||<=>Hv{%;ԫWpttv(u/mΝ9s&֯_777mCӧO_ $$;h;,:CFlM}=ٻw/ b8t|}}Q)ʔPnؽ{7G憘ruk!!!W)ƪ ܹsXvN!"""zͼSf~~~XػO\PP1QM4p$JLMQQrטTBM4J5`⤉ĸGY*`뜟G@9ls]s/s羧0|pK$DVVAAAL:֮]-|DDDDDoJ%55PpuuOO"U|c-mDDDDD7n3f **(-[oիW7֫\2w%33UΝ;zׯ3~xΜ9XNNN2C":͛7UV2Cyt(9EDDpEطoΖIʁD>֮]K=8uZtX""""""u(ym777ٿ?۶mԩS,]k2zhv4k͛$%%ѨQ\$&&w^͛Ǚ3ghܸ1/͛7M6 0 Y581YR\u eZSDDDSb):).\3_C2.++?3gc_aD͇DDĒ,Hggg;>}={j*-ZdL i֬7odx{{c߾}X:)Ϗ?ĉ{#b͇DD,hҤC)Õ+Ww޴hт_~d=z_|AʕyWƍٳ_+fmeeENN?sG/̙3)))PqZlɵk׸tR$K.눈ȣ%z"""RXYY1f% 0^z͛ˬY{?F) ܹsyyg:u*:u2۷/dffӫW/tB޽Yp!o^3oÊ%!C8ٳgu]똡+XEDDD(S:[1CNNCr"## 0g4h_M޽-Vw%,AHYEhh)Sbbb \Ã*UfΦq"""͛7-?}wtЁ3g0uT%ݻY: 2iذa4hdP2d#KQrH9C@@-Z6#@OsE[6mD&M,Z)lll'<IMMUVӇZjK=2^z8;;MÆ û+lA5yY^wFTT 0HHœ;æMXp!׷tHRF}W?7o2k,ƌCժU-VO:ȣgLJ 0zh:udDDDDRJ=9%>>6mژOy$00(>lقMYxV-ɯ1Gzz:ӧOӦMcӦMf"RDEEc=ƱchѢC2&55YfgSOq{9KUadddc?ܫRi d|^ ذaK,),t!"##gʕkSre6l{ǨQ{.K.t%ZjjՊO?GGG~Wonʽ+Ve "))+VX02) KwNǎ9zS$ӲeKXh}SYHH~Ðr0?t>+"""""""""*s899mRw6)wwwɉǏ/2j(c^bpZZK,ݝg}^{Ka2!bСԯ_?o2dȐ|˯arsb7qE|||֭/s!==уTZ+"""""""""+o* [?///6m͛GGG֭[Gbb"gΜ!-- [[["""oѣ7oիX[[ӭ[7X-֭[f}YQ8},11 R?xڵkըQwy%q99dܹ͛fԩEٰw e˖-#88ؤ޵kذa)))̜936/;$$$n: 17s>]vK~\\\&""~H"RuܙΝ;[: )C~7?i\Q2&00и%@ff&qqqqm nq/ϊ%XYYY:yR6>>m~8N< YYYݻJ*qaܹCՍm׿$4k֌scϐ0vZN>M۶mi޼9.]" h۷/7nQF/q94m?LHHcԩGaoo^ʊ8FIddq,H[s^5jĬYhݺ5Of\x+W㓫]~+9>|֭[Pva]rrrXr%?{.˖-~"ڲe Tdǎ̝;7S zygEDD4u֍0K!"""""Q\Jڴis2cHIIO>ܹsC޽C 31A Hʕi֬رXrKb^n0e4iBjՌSRRݻwL8x }O=;w?O>xV:Ei}0uTڵkGժUi߾=~!{5ς2s:wGx :"":~8...1~q2ʰM~zfaCCC nW9ƽt>+"""""""""+S:o<͛g|>k,f͚qO?5&DDDPZ5|||ͷ~/L||<*U7p?3yxsei֬Ysrr}65k4;^nмysvvv@$\~:uꘔ?3g䪟 6/W\}&;vիy3w9ݼyZjg(3ݻƤHׯ3}tc/yq1c 2EՍ 3ǸgEDD4:tx\_nSק}rMO.]S;vСCqi:t`j ͞={Xj-2&uY_[JH||<m۶^z%*U͛)]v`iDA3,U \Nٳg{.7n?ɉQF>tԉ_ooo"""u|7(v튧!bܹ֭s͎~^PyG߉gܸq\pFѳg\=JFFgϞeڴi򔔔e}  66,bcc3g=YÜϩe˖\t)W?2CXN:EΝz*Gw;yt\vz ԩéSX`SBCC-Y郓_~%iiihGGGtuEs]:ܯԶ1'9nݺtԉZlIhڴ)|2Z*]|u͛xxxf2dիWg&esw~?5Fݙ5kRծlٲ>> K27=a '\vuueǎ痫ٳg_?fA԰aػw/?3oɱ&M*+N|N]vөS'Lؼy3Æ +6m司,7nKqieE,mذa0w\wsygEDD1wӧOo_繝Avv6}!11 F qw6!,,̸so."""".ߛ<an3i$5jDʕf͚元+WWWWV\>{{{V^رciӦ ԨQ^zK2|WnfxzzRvmqqqaz 27=ʏ5M6e_VZ={bkkKddd~"##Y&=z(XEtO6lJLy߿;2eFӧRFo)b <<SæM)1++o"""R!Ĕ)"RpÆ A&BCCqppȵoVVVYF) >ZjEtt4۶mcǎJL)ܹcD4ϊHYTmr gϞԨQÇs<ܼyRzu^}|:}4-w&+Vd@3h XbEblllgر :p/^k()vŘ1c_?It7Z9$&*-t>+"""+dggDDDTZ͛ӧO qꫯy뭷r,zMZ;++ UƸq  +={;wP^=\]]u1i$Y|9nbÆ tܙlРNNNlذCDDDDD B)"e3< ,`ڗVDDʾK.1~x+^uvM&M,۷V#)t>+"""U`` W6>$..8n߾m._~7VVV&lݺOO|ڸq# `oo_x-[FppIٵkذa)))̜9آEu1e׮]⒫o_~ODDDD"Ryyye0Di KKגc'NбcGKa1̟?sҤIvڅ3eeeY:J{Y)l%Kprr"33;v0w\6nhLNi޼9۷ԩS?1Yϴnݚz*q d;s____^{5cȑDFF߬Y3BBBn:W]CÇ"""""Ev '|ñ}m۶ lcm۶1agܸq RO?[:  IDATG~%_Wr-+yү_?N:֭[Mꫯm6:tq8x 9999s;wr;RSSs2d|ܹs4m4W'x¤HaUt"""eYNNN)ҥ 'N/ʟm۶Y:x"z_K.;w)S(1iӦEx,"""""e׸qVQQQ|駼pΝ\u_~ej׮޽{III %%={PfMz8ww"{u|M|M>cVAj7oPV\u e:""""" 6$::~!I)JMMeԩiӆ+Ww^֭[GÆ -HcxXعs'~~~oߞ;wtRz͛MZ[[kΝ;عs'T^=1~h֬_Z͛Ǚ3ghܸ1C ᣏ>",,,,aVR_ uDDDDD Ķ0`@Iu-"شiCp _ wgdd0aVZE*Ux9s&7n`lٲLٲe 3iaaaTVW_}yxRSS ʕ+8880x`Onrqn߾kkkYd vvv+66 &plll߿? ,F&}OgƍOX[[Ӷm[y^Ol cɤ0o$We˖\?̞=ٳgW_DNNNUhc7|C`͚5dɒrŒ3Xx1ڵȑ#r?Æ # s2w\c:uʳM~f޼yxzz>p .O9^WWWv؁~~~={|wڕs9NyD֭[zak׎ի3n8Yf .]W^L<Ƚ.]+5...$-[;aӡCTSO=e\eڵ/e˖gaZd -ZƆp|_@͚5Xh$%%Ï?eANNk֬UV^@;%<4C=У,<lEʜA???Zj54oooof̘gWWW֭o=ݻwIIIŲɓqsskkkڴiÜ9s1b7n|`={bkkKdddcԬY=z9Ny)/D[[Z: GBǎ?תUs6m\25jȷs]?Cm wU,p\\Yqgaƺw)bry7X`o6DDD0}tNʸq㰵}`[K;q>GeĈ|ڃ[D4KQbJZqwwݽ}T\]v#G \ Zj1CʃרQ///r 5ʕ+1a„b8dgg8::eq%u ._̼yUC֩SO?~LnܸW_}O?]xJc?Ibb?餧ǜ9sxrY<'Ndȑ={-ɣFAʹ0{lR իWcǎpСbNDDDDDDDDd|8& ?p-6l@ΝMnРNNNlذC"RDDʖWsٳCɓYn={$,, GGGK%ePrr2U>>;+6< bҤI8::|r`:@s8H]U}6ÇƲg/+##QFqicYbb"!!!HJ/|8gfĈt֍mRjeΜ`ȑ$''p6oLvv6SN`ٲev6l %%3g(Xhn2&3NDD|0`Cp6mdDDDyre6lHHHG%((8kriڶm˺u8vaaatЁh;ݯn:W߆2C)fϞMTTS*o;2}t&Lӧ"osIK!-[d=`ƍ&u_ucժU^w%,,eΜɠiӦlٲÇoo>Ç9r_|@*s5k֌Ç^ :DDDʫ&MпK!R!__"""RlJmS! ptԩkN:1m4ƌcRwаaC ۗ;vZB^ΝP{'x¤][999֗?̄ ؼy3}a4kaI9QZ54ib0)|֖TBCCIHHOOO<== 777Μ9ñc8~8'N#,,e˖֜9)S&$$Ù3gعs'.\ 555> kȐ!&[3NDD|֭ݺut"""""Զ>.]cǎ&:uU=Ͼ.^n޼ ~2C); ,`4jԈ;w+X:,7n3f **(-[oիWϷ]֭iݺ5dddrJ?>˳9s&͛ ;;XvuƏϙ3gr-MC9:DDDʧu֙ls("O7[Hq(4!X+)++ֹ3iؿ^_3n8]ә8q""%(!777ٿ?۶mԩS,]k2zhs=Gzz:;vȵ 5Æ #((Y9AժUXo޼y9sƍ /мysڴiÀǽ~DnμNs8-,,!T8֭c֭CDDD*Gjƍ?p)׿O:.]b888=Vݺuvԭ[XrrXݻiذ!mڴt(R.^̀X`7tX""fwwwN>͞={Xj-2&nݚǏyf}\}VE+9SAaBBBS YYYTʊn߾M͚5by/suÉot"NffSDDDUѣs!>>,3gNݻwkٳܽ{7nĨQu whٲ%/Pf#""xbz͚5k,tMO?MBB{eƍJLrO>899_F-pttLW-4hGx"rA&O N^̙3ѣdddpYMf,OIIWYnJzz: ̝;c3NDDDDDDDD>>nedddÊ+={6|Cbyf&L@rr2gf̘1ޕ/"R 6Ν+1޹F:t(k֬aƍlܸ1W_M6e̘1eΜ\]]ٱc~~~:~Y\\\We>3>3\\\ <9:DDD]݂A6m͛4Œ9;;]Xl唘"Ɔ yǨR ̜90ݟf͚元+WWWWV\irܤIhԨ+W6޳gOlmmGdd$5k4ޕ(""+))_|0mۆnm)Μ9Օ3g0a%Hc|???Zj54oooof̘aRwر?NJёw}5kW#ɋ9s}z6g^9WWbĉ2yd&MĒ%K8yd!""""Rojsݭ@zL0a&Lx`nnnըQ///r 5ʕ+$..8n߾mUϽnJxx8nnn 4}'l߾;wcN<ڵks]vK...DGGA~y"""""%uT^^^xyyyĘ"""Mvv6+Wח TڥPʀK Rb,5g*k<ڶl%Kprr"33;v0w\6nܘgrٳg7o_6mY:tŋӹsgΜ9ôiӸz*k׮cu֭[jo(;|SDDDD*s)""""'&&QF1k,{1K%Lj׮m0DDDDD[an%55PpuuOO}:W^Ϙ(bggg:tƲ7oPV\ e:"""""eVN #33cDz|r9⎔,_ӧSZ5֬YàAth"X[[[:yWD1Rmpvvfl۶SNtR֮]ѣM xyy/**UL/ggglck絵Lsf)J,9eӦM%յCw(~:'&&/R)ؑ#Gx3f }5kִtX"F۷o7^,ɏDDR6mD-Hggg;>}={j*-ZdLN9vAAAtЁczXN8_cYݺuvԭ[פ}rrHYUb) (EDDLҷo_rrr8|0ڵtHRf^z%N8SO=eDrѶRR_}ʕ+һwoZh/@ժUԩSyǘ;w.+W.xgf֬YjՊ8ٳN˖-v.]ʕr%cؓS*nEDDuV3<×_~Iz,)++ IDATŋ3sLj׮ͦMLH)O4) F@@seܹ&:uxWöۤ쩧70>ڵ+ >>A||<=bON9t/.nE aaaAT#Xd%)?ѣIHH`ĉL:K%"RhHYЭ[7ƌc0Dʔ%Ã*UFBB7cذa;Fxx8ޤW]b999dK܊+HJJbƲAĊ+,HW_ѵkW7nLtt4۷tH駟&11C)VS,wea>t!"##gʕkSre6l{ǨQ{.K.h"""""""""{&((Z*͛7O>פnZZ޽_zѫWޝEUя~T\r!L50ORJ Q)) BP"&&,"2?0l6,1sqy{9XlEQXX@;::::}􁱱1accõۉ puu۱b 8pM6=:uP_1&jN-lll$.\PCCCBx{{#""?FϞ=1e,_]tj/>>ЩS',XݻeeeL<hG SbPSScHDDԊ;vWDDDԔ:ԝ#OOOߗ!%%)))xGzznnn.RSSY?3abb" Ǽy숈ھe˖8t!-- k֬ATT^z;,f%ZC]]]ΑP{RyhSShhh`ҥeEEEXt)eyyy8y$ ~GكPGB__KJJ?BQQ۶mkG+V@~~!!!sH,X r[GD3<_~QQQptt>}Z\ĉHOOLj#pI ѣgxHbb}ll,`СR1Dusŋ90{)6l؀ѣGJKKu-<~/S|ʂ>~@OO'55NB\\ywww())!$$X|9 **oU֯_?"66K,\|־dHDD$? 񇈈))5^ž" ++ fff?>ϟ/Q… 777 ۷c8wtڕݺu U_ޓwT P8::ҥKk}*dQ}ȒTޢ/_Bs pvvȑ#F֬YZJbGGG 4H^^^xy ų4 # PPPPk0$""8p@akAAAځc#>>ƒ%K`iiΝ;egg,,,=Nfff&99 dgg#88C!jw#-68('sO#22=nܸCĉXzxﺦ+**uT$LT5{1n݊#G`z#QG޽{; jdɇZ*o9r$߿?%%WUUj;VCoH)++_7ocHDD$ف͛7p` Q ie„ 022_;;;eeeHKKSSS̟?_ (//Grr2v4iRtLGHvj[[[یįdX[[Kܹ36l ~'O`ܹEXXLMMqJRSS DD-!88~!ƍ ;Çyf 7naQRy cʕ$9\]]%("""XdD}2y9 Qt֭fLze={iii(**!LYfk׮fU =ږl*6j#jj|8աz ޽{ѹsgv ___,X:::PRR/^ ???hjj6qo5,}T_ڟO?VVVM~b]6mBtt4|IOӧKihh>>>Ɂ> ''IIIXb~DDmDaa!lllpyx{{cٲeڵkq-|prrB.]Qy*lll`ccSu888Z8-o@dHDD\rY쌸8`ʕ055En"44pQkиkLVsS\\={`߾}M~slݺχ.W޷lق`9B""""9ΜڢO>@WWWj:i"(''&&&GDD2<%L}}}͍S9 Qfll\cJLL ???̜9PRR֬Y{{{|jHرc˗/;Çh"qŋC12"""S+Ah%԰}v[Nٳgqiڣ^z۷á_5v |w5k"j3Μ9ZDDDmSѢעkɗ.]Bpp0222PRR={ Vϊ&7n兰0 tttm{… 044(/,,7"""cSL%*$''CUUSN롦d'ڧ>m@EE\(++c5kfϞ])UNqq1|||p_ٳ'y,[ ***R7oތEa޽7n\3o?N:aG~~>vލ((++cpppQXX@;V֧O#00666ڵk=z)믿UV\z5QPQQàJñn:ܻwشiu%Qii)RڏÇG,//(((Ν;%yxxP<8 %%`jjZcXtDYQQ.],vO<+V@~~>!!!s_Uu q2 %%Ϟ=UoR#==]\ @TxzzBQQrBy,[ gKWo{AhhѣG`q%%%m۶|?3abb" ywDDDDͭ NiN%,--u`X~=;̙3ϟGQ .EDbHDDԶ$&&V;ǩS9s&+V ::Z8 @ hcL#++ puuСC["33~~~Xj>ѻwo@ pvvn󫪶6d?Μ93f`Ĉ_~KMMũSЯ_? #77 PgϞIΘ5jD1c|K,e9US̪ v{fff9Ù3gpqIՑ߆ "~]y9Wݒ˲Ǔ'O]v'*!"""'ΜBDD v)1Bʼn'pq˫cL2'OFTTTurC A^^ݻ'5޽{:DDDD;WDDToӧO;-==k׮EDDlmmk.GakׯDze5!---8%&&VVVM}X"A]k5ą pB 8.\C c8p#F@\\ 555; jŘQk`iiyAԪ$&&ָmƍoRMP^^h| 5ܹooo>}AGPP.^;w@AAǏǼyoHӵkWȑ#ǏѣG[裏)7fܹԩ&Mm[.]@ ѣ|2>| u^{(o~kyꫯ>@8ҥ M蘈KAȻ'OfxDrHDPP9Ν;;I(" (--+VXEEEyFDa6A)UuE$ >>>'~,''gƊ+<(߈ %n˻ヒcǎq`\~'O-,,,+Wr` Qgkk>}H D Բ@DDDD;ZDDDӧOf(//իW兞={;4""""""""j԰}v={ٳg}v>hFDDDF'ynݺ!C4<'<(++_|M,ZHjill ORPPǏǂ Z]""[EE|}}%%%x{{ ڨy(ICsbTQQAϞ=1~xAOO㴤9MDDDD믿UVa߾}իWHQC NOqʕF]$GٳgRܺu nBXX|||dm6ׯOP(… 1x`=Zޡux q5Z ;v@a-D;xBC); IDATCO?#GldZjżH%,--Q:+W4dzg0n8[ @yy9n޼###عsmԅϟc֭?>tuusŖ-[ 55Z/_b޽;N#8::'OƵkk;,""jKM1ES\թӋ/pxzz">>}BCCy<P4˪y-5666íIrr2/ѩS'tcƌ &&F!>ĢEe/Ç+ȈH^>}{p7`РA8XXXoooDDDٳ'L˗K.ƟGI-```Pƍ1x`xyyI%z$''CUUSN%{8<| bر⥇O>066F`` lllеkW:ڬ[na֬Y(**BTTƎ+:]iiiX~=n*EEEܹàvGnn.1p@̚5 gϖ[\\ \pzwy˖- sOT[;.]Bpp0222PRR={ V=􊲲2䄨(,XڶkʿȟC!66EEE߿?>̘1oY5V]]]ܿZZZ ?ϗdggcܹߠ>OؼV~gy-QaԤK.EVV,//'ODBBe˖/1gL8#Fm{xxPbZuVX|@II BBBPQQggggϰl2ܿ_OFFFr(..6$$$ <<͓|9</^C"""zzzͅ0m4$''cȐ!H'/OOOߗ!%%)))xGzznnn.RSS)1d͙:|0|||$ 1zh۷[5\]]1tPc֭̄VZ%?ghhhСC8v;5 ={ɯ0`yU۷oG޽@˗//C"%%[lÇ% :tT;X^#݋͛7GCpرZZZ 9sSiiC 44pA Ν;N>-A cĈprrq=!!!gϞٳKRߜvN:ptt̙3Xэ+mmm(KǎãG0l0|ٳ'K|w9sfUcG`` 2i$smɨ>圍ke~Qe'NDPP """":.U-oƸ|2#G5 NNNXf """.N>ӧO͛7믿ڵk~:^ >|zmkk: VVV(((e]VXncUCDWYY~gٳ|0.]kΝ;ظq#6o,D  Y!uuu! YYY0331|.\g?0`oߎٳgܹsR5DCrʢ  qM?oիWU1^| ԩԶj%K6m$͜5HCrݺu87n܀ꌡ.u圵+g^KDD#""""̜֫R.V6fjwС:t(PZZ ???x{{c޽سgOm.eך^-r=EHvmQ_onظq#aaagJm'#??^7cرcÇcɒ%DΝ'33IiL=† pMmBQҪnKcCkHUO/LLL/_b„ Mrԕ3%"""""""j{ZzՋcV%Tw!nҤIx9Ν;' lmmzQYSW7Ej[;ʪ!-*D4Rݻv킮.~G̘1CaQ#'5,1~xDFFǍ7p!8qW/URJR^سgn޼}71|p,X1\v `hhXgݪ,9RmW5Vmmm̛7'ODjjx9iթ+g^KDD5O===ܽ{III7n<)) +.:t(]\RXLZE߾}ƍx77nܐۣG!??=zؖ/CDDsy]ؼy36mTADzV>QSԄ,,,K.رcߠŽ{&45Yr  'YYY 'Oɼ,׻woİadj'bcc3gӈ"LMMeEdϼc8q"ɨC NQPPP(DvvxR333 6lӱk.O-^׮]@ @QQ̙ڵkؿ?ܼ6ڴic׮]puu!n޼)>ʆ <ܻwObhpMC&"Wܹ 6q%}MԎPRRw͚5 999pttČ30h $g077Aӧ8q?cccxyyh\^"KT[; N,ܹS\^PPmmz ܾ}۷~[sd?SSSb߾}pssCqo߾j<Y6z¬YpB5 ݻw1Y}DDl""""6C N“'O0w\",, @vv6,Y"Q@6668~8N>ӧOKѯ_?]6~'ܽ{vvv555ŕ+W ###mnjh"֭Þ={ЧOy={ݻѿ\pSNwXDĺu&.wx;;;DFF"99:w 67&/%g333;w...pqq:~FFLLLjA RUؽ{>C\px$~G׍9 88@y[M%"3%"""""""j{ZvJe X7n>PZZ ڵ+|}}`@II :::Xx1)qufffիcʕ8~xljjjjwN:a+/#oC]]]Fyeҥ M,qQIOOo˗/ѣG1b۷;v@RRQjˇΝ BEE***8p cq.]@ PRRx3G4&/%gM6aPSS ]vaPڨ_~XhN:CCCz___L>]v2ݻwcƌ9gm444į'Oܠn|~d~= BPؘ>>}}}@NNfϞ+V`ٲe aaak[![Xv-~',Z""_Ԓa!!!G P{"""""""9H)t&O ccc9s;wO3F-#qQ" R,Q! k.̞= ,K80c˖->|8DDDɓBDDD͢?Ʒ~ sDǼm$kmj%ZҌ3p̙jO-۷cݺu⋚gϞŁйsNqq1.]3g૯,ڭ|'(((ݻft;%""v>̙3Mmݴv8<ܹR&Leˠ#믿UVa߾}իWȨC'&rUDDDয়~[o%pڥ ]/^ 9S PRRwHZ""""""" Ni34EEEXZZRNo&!Pڝ"ܹ_5h;,"""@Ν;'Z-DDDDDDDDm ")MԩS2d[|嗸z*u`FDDC!""""""""""jS884n߾UVq }N(C!""""""""""jS88'|ѣGqqq8z(z)Ј((((++9""""""""""Ssxuh"AppCftub͚5 8q>3oeˠ1DP( a>DDD KKKyADDDDDD$oQ=k1qD|(//w81i$a90vMΑPk|Ǹq&9eĉ8qbSCكua޽ԩ&P>}-[ȑ#066Fbb"ƌ#ﰈ{왼C6&yIXYY5aH\v}χ.^___;v~~~ϠoooAAAAޡQ"c>DDD%X=~\&DDDADDDDDD5N88ؼy3===y=z[l~ SSS$&&bԨQژ_O}HlܹsG[NNNf͚^z5S~o Ə 4D իW#99֭ömۚo QkߝEǬj\qNkm,""""""""jӃSZO?W\b8::"..N<99pqqY?l0DEE!==]jpJLL @EEiiiȢӧ! pB <Gnqe_ptt/p WYaEDDDDDDDD4J W\S$8;;#..:::Xr%LMMѭ[7 ?>3=zZ?|p)SHl N/bbb{pJsϱuV̟?sb˖-Z U^^///lݺ]tSpByEԦ ru3FaPל9 P]g666tTDGGC[[~~~9s&===Yx%:,1PWWLJ~uuu$$$T^}4___<|--^>oC/߿/0څ;~)VX7or` ٳadd$0c>D,""""""""\t 033{a߾}(..uGSL `mmj/bxwmxxxHhk׮aʔ)(Zb`ɘ>}:<<< }˱gL<SL ??NNN8q"ͱm6<{LXX:::… rJX[[ע233j*L8ovڅϟgP͛7%27?~%j2\K.ŋN L<{Frr2ѥKyF& v5s<} N>UBAA111:-Ӑ~?q1b^!C@UU]vń pzP^{ /_DRRW2#""Xg255oH oΕf̨:uǎãG0l0"**J@ ד%;~8rrrзo_;vL#޾}[*>YA6d9]sH,""""""""t(\zÆ _cP4" 9r$add-[ԫQijDDDHcmm ͛1`ᣏ>π1h  899_~PUU :%%%nzB־vppTUUaee7wDEM~7<|F^=z􀡡!GԶ7͌"8믿fBIIxhpD;ݹ1%Di&@]]HLLw}''K. prr9͛!d9]sH,""""""""U.#lذ7oޔ& k޽{1cHIMei?SNŗ_~)UUUZ ?.^S"557kH>A(:XT&g*,_~%(<<#GL!o#GDΝ~zq 2jjjشig;tBEE&&&A5)>r)=:u°au8qlH[ĠA&1ÇrJBlr~7z "##1n8hiia̘1Aqq11zhhiiIߝ\߹DVN&K?r܆%t"U?{̳Vy4>>uE[˫ַo_qx q7ݻHJJ¸q墵uuudZ;#s! 3f̀ xyyA(w/о:,$%%!%%RK 6 HJJBRRJKKѿbCWWCXXX=z@^^ѣGmP!)ذaBCC1gN OD-S<㙆FO>]h^>ogKIIi8VIIwWܷo,Ypc֭pvv;ӧOGRR;gϞg&N9rEEERK4,ߝS޽ 33>Ed틬,\v &&&rѲH!d9]sEMgQe-6sJC/(--EFFl"..yewڅT#%%v풪kff(//GrrIdWԗh 4a᯿QXX2a)ϟ/}]хdTTTDi9˗ɪ~]wvvFFF^|Ǐ믿1uEӆLTVD4^x/HIIʁ)DrVݒă]RuhGm5CtcY߶^x!.RSSammV~amf8  ;;XxqS#ܹsJ#<:u N'שS'\rׯ_ܗ MiӦ… _E5X5~m۶5ѽ{w:vW_}noQ-޹<*U~6mbcc?Xi݌3?ZnҤI8z(\777r[5Rk:u')Z/ ÇtuuaeeUV)>@۱c QFM6Fn_PõUV ann--- 0661yzz}BQQQ+SSSDDD`!{aƍMmuUߢEJ[lmmmq޲eKB&A*BKK ưGxxz044D\\JqqqhٲbT;Fb9r$˗//`a Q3ϣqqq" ''J wggg Æ X&#ɋwŲ.]@"`ӦMC߾}ѷo_߼PUCê|NSm۶ ѪU+G#jr-`8::㣲[5Rk:u'AKQQQpvv7YYYOЮ];۷O8!$${AoƘ1c0sLL>]=6Gƌ7o"==fffbGj ~G~LD5'/Qڽh{;;;9sF ͅ-222TrׯFrVw_022V ޽ hׯ_͛+eԨQػwuԸQuQS T;E9>;?Ǐ ׮]W_}/0*:u*,,,>T*Uƚ8ؠ,L={gϞXf \x)D޽{1rH}±cTFt+u8{,.\;B[[3f 5244vk׮EΝgϞfΜX[[C__իeQc,""""""""~qcĈu&&&Jjg``+V`ʕ+ݻ:tر:fVҢE d2d2PU"##{n3F8?ŋXz5Ν mfUYDDDDDDDDBDDMYiiix1~x 6 X` S^2,N!"֭[J֓'O~!''gΜAXX,,,ĎFD L v """""""""""o_'""Xx1 c֬YhтuDDDDDDDDDDDDD/z+NٵkW}uMD;Kjj*ϟSNVر4jĈݻ7ĎBMߗXvڅqƉHI?&"wW\^}U4j=W_}ף_~8w(v,"zq}E!"""""""""xqL&L&tDD d?~<Ŏ( x{{6m+%fPzHƋSN>ui[";wIW&OQHRrr2͛x̚5 ~-LLLĎED Ď@12dŎADDDDDD[o޼ՉDk.|d2,[  رGaܹ0`A@bb"6l"ziAWWWzĶk.?^DDDDDDDJ4>rGn jxQQQpvv;FsM37oġC{Q)++CXX~ SND";Q*++;5!"""s""""""j4>r QS;;; !!)\pƬY ɐK[;Q"z"88gϞEΝŎhܿnnn>vZiFhDDyzևnΝb eG(++͛l2a֭prrH)DD_c5+W\AݾyFDDDDDDDDY,NiĒ~zر `„ ֭|MQ39s 55XbZl)v,"FGiŋqIEbaDDDDDDDDDi}Rڵرcl2w .^@Q:yd7Èh)666lHUXX޽'*999ݻ 1Qo)))uн{w=z8z(z)v4""""Q:~4i}=]v!##033=̙CCCP9s. www)I[GHHbccq=ᣏ>ӡott4֬Y… a``hlذ'ODAA K{^^1`+[XXјCff]vv6Pr/Y~="""틋q%\t O> YyyyJE">>ӧtttзo_ǎSE>V"##sN<|HLLT[ΤISq0""""""""(><<=PYYb>}(mnP;| )۵k&NWWW_zzzbG_///ر| ݋]Iucǎ)?UW|#hڝ;wݻw|Ѿ}*-_)E> .W_}xcӦMpuuL&~ˋAjǭÈOTUeW^ttCE.]`eeǫ[[[0h:0Luڪ+)O-:::%zy˗ÇGXXL"va͚5󃅅~W9RXDDMǏChiiZzPؤ] >8q݋~ 7nĶm0w\|/egQQ7ÈO9%>>9MLL%%%JE)))Jw#&''^{5V*ƍT*!CDRRXҶm۶Fnn.ڶm.77WцTn.L9|0_aҥDDTR#PVߣ+௿իWѳgJ۵kׯ_ŋBx"zF¨QGb˖-XfMS*H$O>E˖-ѲǭÈ-aȹsPTT ,[L|T 99+W888Y.gdd<ڵkaccYfX>Cʕ+\|~~~*mCP߸qCe|Ym&͛;v,>CXYY)n0H3JJJo lbհ?OE;{{{ϯSRRRPRRZ oxߣG ~g_GnuE>jU7-ٳ̄[ݾyFDDDDDDDDT)8p/_˗P}...Jmz &l[...8qRRR0i$1M4 Gŕ+WX᧝N} SzP1m4"%%Һ3f(~:u*;7oUʲ:u*V\ 7&&&رc!JSiؽ{7~tM(WVo^FNILLtxk/// >ՅVZ(رcR5k`Ȑ!ֆ9L Wm˖- LT ---ᵺ[NWWptt tuuG ...-[|P DEAAĎ!_{F@@/_K.0{Imaaa>|8Zj1b]V\ IDATZZZ077k5Zرc|rՅ.t|Wvh߾=PTTTepttD֭׷ǭn߼#""""""""?AtgggȻ{}P9kҶ1 BHHكn߾1c`̙>} 1cC믿0fiG;(^ 믘0aꫯY;r#nZ8Ԉ ^&#wN~z^$6i}PGdd$,YRTe!ɓ'w`ժU kcǎw;KXDxFDDtܹSDDEEaϞ=b ""jXH`ŊX`&O طo֭[}}}5 61"""вeK#5?@NN,XNDPZMqBT莚TFlxFDDt7ND8F3gs΅ȩֳg0o|2 }Rر^::::011;5^i^.NMALL&v "Q?DRRكO>DH ɓ'Ú5kУG8qرH5ˀaDDDMGTTŎADM bG ""z)4"jZhٳgwѣqΝ;鉼<bٜ‡ ;w;51QQQƇN"jƏ/vpqq?ŎEDDDDDDD7ND8;ɓ'ěoٳ ea 5 6rD"A}vxzzٳgXv-fΜ-X7HDDz$Ď@DDDDDDD)C DT#wAvĎѠRRR0|>}ӧOĎEDDDu!""j ,--Ŏ@D"ɁT*EQQtuuSSۿP[ٮ6z˗/#)) {a$z¥KjT^xjr y>j#""ƧFN!"h|gؽ{7ĎS=z/7nDqy؈^ 00{ӧŎB%$""""QEEEPTT۷cܹ"j\N%K $$ׯav5all\|DDDD͑ƋSN> gggMwKD5KKKիWcxĎTA-[Raڴi‡x?~,v """"" L2o) ɓ_ 22ׯmaa!I&xq͛7c֬YزeFs5e6rJSrja>L&É'V;d̝; 9s&ЦMcQ  MDDd2`ff7_Ebb"._ +++5ppp{*N/xF  www|g3f&c5iևTZZF+mۆDLL $ |'OD"}Js :TeYm͞=[e[o^UÔ)SPRR-[(۶m1i$2p@nRYø}6z‘ qFlӦMm]8_A`mm^Yh65DSP͜>}qqq055Exx8>BKK ڵüy0k,bƍbը0ܽ{'NT,srrݻw?ƹs`cc|g)|`]DDDDDJKKHR]XYYx>=Ieput۷oW[\۷odzg`ooKKKu;vСC3DGGWGT&\.]Tx>*ɋ̘1Tܩ8PeԩT.__]v!''&L@V^^4ObJ<奧ﯶ[[zɧ5HDDDGѣصk222PXX333cΜ973gŐ!C333E5i <'$$wGaJSƚ5k===Xp! m|SSSԛlx{{#""ѳgOcQ=222;5?S~ ;wDVw^y (}"g?^SjG4W8R,ruڻgϞÙ3g~HMMѧOEۺuNCmsǎXt)233}^^Ty۶m5ONkF96M#11O//طorssQTTCǧɓ'ϰ}vߊӧ#??_V>U]>͋Yyyy*09VU <UI5L_sԕ`ڵѣ?;w"66)DDDDDDDD/ yGB X`$ mVgJ} C^$-- .\VۄŨQ,Vquu{^ڵk>ňDDD2ǏqqiNjsQQQ8q"233o!!!ػw/~w]S#""G9E>d7>H$\t 3gD\\JӧOcݺu0`ӱl2ܹs۶mS :mmۆ4 K.E.]p \ طoƌoǎb + Ahh(?(>ٺu+n߾:oEnp%,_)""h߾=iiiիW8ڷo_UGΝR_qqbbQ^Μ9ѣJV3gO?IxIݸq?qMر-Z4ڷZ;y$ϟ+WK.]DDDDDDDD/]")) gϞG}T 1qD믿ƨQ*mۥK\xպp˖-"/Pgضml٢&PMdѴc…سg6mڄ;we˖prrRjWE–-[xbE =qaoomʥ6 ̙3eee)~.++S|۳gO;w1bJIIIG[O;5www 2DF}{lccjSpڵk@}7 GQrZ\ݺu:w+V8%K`ii ===8;;PĉK :::_|Q<W1Uбcmh&MR;\cqչr -uI ɓ'1`"!!ؑ4&++ xwѾ}{\|~~~,L!"""""""z }_RR~ΝH$*_{zz"%%cǎŲe˪ǻ  QY Dl۶m̛7~72nݺ#W$K}0003=zիW8q4C}^F6mҥK˗ajjZeځj6yUϋ**?2yAAѣGվV5):r]T\^XƔ/h"3aaauz4&EEEb a*eΜ9ذaΜ9?+WD>}p9DGG#<<Xrb}aÆ ӧ""" HٳqF ,@Vwwwȑ#slll^X[o_~HNNFll@SYꋛ6l؀իWPR>&L͛7c…'''7bV ߿mjsz*<==_ ֭[8p лwo6KE...ؼy3߿:~wϋ@[msɒ%pssæMi& .(wG}ÇJEDD`ʔ)GDDD/F9r644&&&LʯJi+Jq @*jСCdff")) V,OMMuڵqE7y/^}8H1J}!(( `ȑD2QMj>α:m۶Evv6rssѶm[u6T;vvv9r$F)vy&<==k.5 111siĈx"lb|?>\]]cժU8wѹsg8;; zzzxۇmbĉW& {ţGЦMdonnnHHHP;j\Mlmmo ##zR*7 9c Gzz:0p@,\#G믿)S ((~b;[[[oo믿޽{x ''')G[O;i; "vfKu8Fܹs(**BFF<?VjT 99Y1$Ji+G(--ŃvZ`֬Y5>yʕ+\|~~~5K^gJJ JJJ^mz-X[[޽{pqq#Gb\| .D||jGwqJ{2y9ggfQRTTUV ؿ?""R? v """""j$u놐ܼyEEEx9B>*zq<|Ϟ=Czz:-[(iӦ p}W+!>|EaJeI^_e> *SEtK.U=<{ Z괭qN2(,,Dnn.bccN< 66Ve;KKKΝ;(..FZZ4&煨1:jM"z:tu||| w{Qr=!LHcQh#$&&"11Q:/// >ՅVZ(رcR5k`Ȑ!ֆb:]]]Ӷe˖ L&T*aooZ`8::SZj0?҂9 IDATccc `eeCCCƍwߩT{xx[. __ZgsCKK EEE"..N}\\Zla_Rׯ_رcGwȀ SRbG """"""""""j)ZRLSQQGZn]a֫-¢ElWYFFFw֭[cɒ%XdI}aɘc5  @FF,Yv/"""uЪU+ciTNN HݿD"D"iBOu===HR1(++kli{>K3gsZXRii),Yggg̞=رjݻ7]Ǐc靈@DDDDDDDDD"oj.7"dgg4iƍ'J Qc-vHLLOOO޽7oٳEHH8q"8p ._&[r888CEzz:-Z""|b """"""""ҘT̰qF"11/_;Z ̚5 ׯqaq R)푘ؓ'O>}ݻ8u""" JŎFDD̀ tttĎADDDDDDDDMЍ7KKKA*iiijK$>*JLLĸqҥ ɓJsmٲ###L8QiyUnܸ|I@ll,lmm =IIIU!H`aamKJJ`aah/W祺@B|xwжm[hkk #Gĉ'ڎ?QloDݻ#??Ny+yq)S@*BGG:֮]|yR(22R(M߉ἬW_}UhӦ? bG""""""""zP_|}T22Ld^ѩSccc?}}}a*ۼuk``><<\R۶_~“'OTQRR"XXX . A* %%%jGa?O0Y뢣-Z=G A:t@سg{C"999XǂuϩD"bbbݻ' D8~RnLLLmmmsS|Uyq߿_000PͪU4V-.22ߩ.<Ǐv;BJKKüyp L6 ?!v,""""""""j C Ν;ŎADDVNN̙3*.^B&!==]i$xATZj.] 駟˯]3gf#>>HNNF@@k:lC1AЭ[78|0FQt,--W,0c ̛7-Bv퐐\z~-[i777>>jfZڞ͛#F ::ݻw.|M8p{XԽfusFx5eee֭[T* AAABiiرpZ>CӏU& ,/_, P=z$tI 888L#Rɓ>AOOOH$7]~]H$NFFʺdӧAKK.\(_W,R-/9())STA* DXn`hh( W\o`]KMV Uݞ={4lv֧^i~Z(8;;k["ApoMo̙31c[y/~E !-- ^85Q:777\~]vۡի}V;3TZױcG :'N@tt4fϞ:,M.],344p3f~@hh(>sSy^*ǫbڴix+m˗/#!!ϟŋ?cjj͛7cԨQpww_{?pEw9̡ 3tq|,f°'CҌmRt !-Iέ9HRݿ?zӝr~\s*z􎟟Eq~]xjJgƧ{V\"| m6cQ]߳*[[ۢZdzg^R7ӧO'++5k0bJ(aЄBǜ}Gp%BCCիWXR*_<$''Sre?.D"B;QQQiӆѣGckkիW9r$!0 ߿o0B!BPֿq H\|Y@&MĤIB̛7>}'666_cR:tF046h *VȶmHKK#00r1x`~=//bѢE^/2|FI>}4*deei`@vNQܯ,q)~NSΞ=Kzz:.]bРAz+㼉%)L.0̩Shٲ%Ǐ/[B!ffffB!P(X~=( 6n+mUXn?  9r${RJ@vugOOOLLL;vFNj*q1t,,, bŊٳMbff57o.Db<%ϋ!'))QFѦMʕ+Gtt4˖-B M!cJ.mHB!,V^Miݺ5| _~ΧSSSYb}uwww4SRRظq#}o;CNIII)=B^zȑ#Q%KB tڕ{_k? ȑ#9r={bŊ*U `:DҥyTREybŊl߾Z,EMU=EWCˋrttGaaaA.]عs'g֬Y^N y&ƍ[ncu҅cruQa1_*Zٳ8::bii)"s ѣGԮ]aÆ=w<<<8x wޥjժtԉѣGk'Fd޽ܾ}%KRn]K~4LMMӓ}RjUzɨQ(Uƶw@ ( `͚5̜9sss|}}Kzz:cǎ… 꾷oˋX(QBs{!556mh-kӦ ݻ !0{m]vkN+}:6lK.={ ;,Q@A]ŋ>3vB!BQ5j}Q+[,=Ϗx:t8pF}LjSsΥ_~jUԪUKkYڵ5!Ba,/-9%|yGFFr1LB͚5prr)m:tHݷI&|̘1 &pAurJQ\E222pssc޼yXXXyfIB133a!B!)=gWWW\]],X $mĉ̛7'OrIVZȑ#t~7}9N\\\۹wΊ6U!B!EDFt-}ֻy&Sf4ƅ 333N9{,2~x 00a:!; lЫW/nJz^re 4vBIbB!Bh$**ѣGӸqc9q| ͛7baaA>}ӧ.\l2=hKKK_Ύ;4xUT!!!dT,99YG!Bczi)xaÆ^Zj\vhZln`_r ^gtԉX>S <==_~[o}vH!m6c B!Nll,7e۷/7odՋ?PdIu;퍓SN~u899мysu#FPvmbbb:t(-[{lذҥK߫VT ӻwoU-q!B!XVN/ٷo111|g7|p<ȑ#5լYSm8;;₋FV_ m۶9rX1@.īKT2rH=Ugٲe888?ӷo_BBBxJHHw) !B!xNF9H||<5jԠ]vrڵk9tӼysƎ1eɓYr% н{w~g´Q\9vX!BwY*UXnnnn8q4իLj#ܹʗ/ϺuXf ݻTRΝ;舅oQ\Ex͘17.kԩLj gϞFTܻwKKK)Uoߦr/m&&&@vX0DFFvZ=ʵkHOObŊ4hЀ={[ooԩS~đx4k֌f͚1h >C={@Μ9Ù3g}vėc?!B!/ x~ġVy,,,4i&Mʳ_n֭F9xzzrMW͛7f̘1-[;!y왱BbXVNVyѕRBNԩS¾0YjK,aݺu?+?k֬ښJ*e((F0~x#GU|M2~I+ݻ+^^^ 0@ѣ 5KHH`׮]ڵ/9sؾ}{&^O'O… Z7B!>|8!!!aiiU\!Djٲ$f͚VlS^Ur ^|78;;kT([, ,`,> IDATX[[)J! aÆ~z_cTXt)eʔaڴiߟ:uPti}j0B!E_^ʔ)ܹsppp믔.]"5~-~Bbxݨ.}6o&88sExe:u3zhOiԨQ QPjUݩ\2˗qF̙|9oz ƌógXp#^z#=sÇy1zzɑWQjj*eʔ1vB!B'ƍҥKYt)ǏyK!^{C D^k7)5Rr^r ^)qqqݛ.]b ꫯo9x :uzQWYhwΝ;T\N:DÆ 9sݡ˼ܸqSS_ܹs˗/cee~^^ @3Xf ֈ5w󘖖ƪUغu+ϟ'99+ҲeKLBto<^z믿B.]b Q[j}t/ft'''ׯwgggGRRkf„ |wzHYV!B!^_/IQa!Nɒ%3vB0h cړ""UҳgOԩC@@oJk׮qybcc9w.\… S~Hr-,,>'((-[\"w+233m,Y{:SuwwחŋoaȑDEEh]X6mڄ=YYY,ctЁeSHHKlmmy䉺֭[￳m6ėPN\\'Nh˭(~^DQ*y& !B!B6[[[lmmBk2d7oN\\;wᆪe˖TP:uлwo֬YÃ޽;k׮%**4(fݻIIIիsŅ(5jıcHMM%--'OҺukJ%-x9ѩS'^rEi߾=e˖{BBvvv}ʙ3gڵƾT"^晴&B!B!BIrtzɍ7xZjO?INN毿"$$h֬fffF^Gk֬!113fl2իGҥiժ}ɬ\2qN<ٳ2eFEիWS VZEڵ)Y$ڵS'LmذAkLooo4UU9s&7‚իP,#F_~VZ,Ym۲zjN:g, rڵK#I 11*U)SPD ϸqhԨ*TC̘1jTUӶm[ʔ)-[d4fNJ#)|TrNϊ+x;v$((FQT)5jDPP;vYf Ջ7ST)6mJhh(|mϋ(Z%Jf!B!BaD 7P(/R˗ ֫Etڕ)SW1~6mӧܺuH_TPg;EK~4i&M"00ȶ#L#ѣ1w\5kƛoi+N &\>j(/_޽{VINNfdddн{w/^|7Nk]Bٱc&&& 2Dcg&88SR%qo^ |Zm[ ))Iz]dذa0m42___={СC)]4Pbbb+Çۛݻwsy=zđ#G8r/nݺxyy'ʵk.{ yTw;wdĉ;wj,e߾}L:U+)DL6Ck.RI&igjjʴiׯֲyEӧ/_a4ǎ_5vB 7gB 4!!^17o6v?"66Fioܸqo~ȑ#DFF>oVVСCDDDaj֬Y1s-ؽ{7nnn4im_gΜ͍M6T*/iӦMS%/u!^uE+Dapy=JNGڵkԫW)5T~a ӧtQCuZh߾=fƍ:FjԨVXT֭զj&?HHN=yiԨ?#?#< ""9z('ݻwرc<79<:uh<{VZ4jԈ0RRR(_<ɄS~}իw]1hѢO\x@ᄋjJg{af2O B_TfM*(C,STґ#G\3i%++۷o3w\Μ9ڵk?~ƗsO>寿͍'O2m4(SL ^ O|B֮]K`` ˗g:K  BݻwP(>}z_dIFѣG o;w0gtBVPeJJ ?~z-[~ݻw?>;wM6̜9S!!<<$n_}EN;v,}6nG}[o;P(ظqQQz^'իW(?NϞ=^ZZvvv2|飷oݺu&66m>wlX~~ニK646h &NȶmXj+Wk+y9~8[noɳ LFFF^hWf̘1n߾:++% Ocaa]P*ٳsssڷozu? ""=zh-W=5sZ r N<3%**J ""(B!g۶mCTP\=jb˖-2bW1FxHҥK̘1CktƎ.zyy[\v Ьj*<==5%$$qF>|>}:gΜՕ͛; o}ѧiӦT{>|8IIIqqq̞=Lz d?pW_iTNHHߟSRR9r$7oTݽ{· Րq Xs ߯˖-#%%EgRSSiӦmڴ!""{2`Cx =9ExdyQ\у(-ZD׮]15u_|AϞ=52'OLLLztؑh<==BbccU׮]#33___&Lƍח 6h"x!2e0dV\+III5Jk#Fpq͛G5 mZMLLP*ZI&qqq@vBPn˖-S %Ԕ]eILLwޘ^?puu[nbҥtY޷o_N8 ݻwQ[A^xYŗ|B!G> ! 3INE.66ƍ|Ǎ7V .ښs1sL5r7ň3[.ׯ_ٙׯj):(##WnZ, ӧӻwoLLL8wcƌ!,, Ȯ,=o<ƍٳYz5sǸbaaVre o~X5)) pBVٺu+^^^OY`\pYfz 6pMjԨ… ܹs̞=[+~Cb5d\V14<*uK@lxx8Z%9U|A~~~ʜ~/xyQ%CnܸPPvYy)'OT=ZYT)̙3uo߮M4Q>z\rEiffLHHP>~XyeFrΜ9JR UJB}m֬PڵK_Cbxy-~Y%477Wʓ'Oj)yy왲M6J@iff0a2,,LP&&&*CBBP*?+͛Ϟ=S>}TT*SʯZP* (_OOO%SPZQoo߾+>}<o߾J@YlYk$''+---{hӧO/^T*+Ws[9/9+PyBW !/B"2~ܼy666M6)JIiccܶmF?;;;}pF͛75?J-:v쨼u:YYY+nݪtuuU*mll/[Licc1bFtR'--MicclӦMJeLLm(J666SNi8qBicc0`M};BȐqwr R\TB˗5SiccLJJR斔QKk⅝.)B!Dg8p-[jqwwWbbb*~T*_>5ŋUZn+q舷)]r3$ҤIZhADD|c^bjjΝ;c޽3 <==52lll8|SlJS2zhVZŪU4֙5k7nի>}5k>w<}z쉉4)wr{w֖۷}vfff_UPP={dϞ=ٳGc3l0m!B!ȟDzEŊٿ?7nܠ_~[W4fm@N< @V4h#B+ ,`@ׯ_Yf5o\k>}ܶbx *W XZZ%%%sErߛ?~gjȸ*y}gH,=Eu,Tj׮޽{@vuTm>x+cB!DzEtt4#GF,Y *еkW_?4x#Gȑ#ٓ+RT)4h 8tKSJ5=+Vde_46zhF/ݻqppߧlٲ(Q Zlɼyr ZݺusssLMMywpttLJMbff]taΝ̟?Yfz|CqF4]һwo:t(biiɰa8sVAȾvYś)뜾H E!B!OhԨ)sܘ2e 'OfŊDGG;,!(r'z)/?!Ct.q!B޽{Zp=011쥗411)S];v GGG)[,fffԨQRҷ96!uP(ԯB`ƍXB(|֭#11QILLdݺuFL!^j]yUڵ+/&66 Ν;5<@ǎprrҥKdffr]~ cǎUU]VyQ'N ==K.1sLuÇ8}44m///7oN@@O~O>%66'rUW!ݶm[.]JBBiiiP(T/ĐALL|GQQQdddpy-Z/jȸaH,*;Eu,QPMyS8A*$G.B![JJΒOzz:0~x#GU|%&&2bիnܸ7زe z" #D)BQ0wݝp=zDڵ6lzꛚ tуcffӓ}RjUzɨQ vN?3Ӈ'{۔,Yuҷo_iUI9nW?y$˖-cΝ2h ƎKrr2K,ѣ,YO>Sbnnd_Kmܸ>zKwyG(@>9B2$9eȐ!޽k׮1bĈ<1b&&&Cj,+]4}JwҒ;vh_:t@hh(gfZ/]|ܹs)[,Ԕs2x`̙æMח(jaa%K(Yd/d߾}giuttT=|p}ؿ!K5;bCuʕ+SV-lBll,#FJ=]dW>|8III궸8fϞMff&{?~NB'##Sىcǎ… un߾ ݶQF? +@Νܹs<~Xoequu%((H~ڵT^͛71--J(9sسgUڴiCDD{eK!(ϟxS2e͍G#ԩСC={Fbcrbڵ:tDi޼9cǎ^z꾓'Ofʕ$$$))SAXXԯ_C_M Ν;̛7jժL:9sg5RJaiiI֭qppXn~WRuƉ'HKK^z1Ν;/_uֱf>ݻwR ;wQRJ+8p?}899gϞjȸaH,9mڴ)cO cذa(W(ފdɓbz!16nȲeˈ̌.]0qDʔ)36B!(OGll,UVݝ;wiԨ+vKi߾=۶mbŊ}fΜI~h׮GaL0H !^7oȑR m}bLJ$6l… Z*˗/g֭xyyi%ܿ@,--Yr%7nСC___.\@ƍ1cu8;;AppXlԩS+VPlYujʢgϞ 6m*prJll,ԪU׳zj\\\b˖-;ѣG녇`mm5-<<\SPϳʕUܾ}Uj[XX0i$&Mݺu[nZ(_<:嬜+O?O?}w!;1F_9UPSܜӧ3}tv]cH7?Eby6$fCoͱӓ7oRzun޼Itt4cƌQ[LN)h,[D]d3d [l!++ '''HB!DScʻ~:-bܹsʕ+өS'hذV\y]9$22%KpaQ̜9rȮZhnnsUl׮]\tN:i-H,c֬YDEEann'|œ9sJ˼ܸqCg }]ܹ˗ ;/aaaڵ7| Ĕ7n cǎ~HNIKKcժUlݺϓLŊiٲ%SLQ\X6mĂ r o6ݺucԯ__oAc+)66O?U{n|m!^I~~~; !^YN:xݩQTǹ߫;v ~Zf͚899齷ԩSȞ`ƍܽ{W|߾}8;;SsΥ_~S ݶ*1‚+Wj<]lY=ztЁ2p< eooիy)3f̠VZ888᡾GٟWuj׮G!>RSS>}:ݺu\r\~%KЬY3#G(q >ԉD~~~XZZjM$ ѣ|xyyx:ulϙϩS iӦjժEPP:hfyEFF7s\!BW2e+),,&Mo?NBBh=AυZ'))gϞϒ%KOxK%333FITTUu  d'QуSN3Cݫѷ|tiڷoݻw_%1E!($ BB`,X@֭[@v5Y~B deeoގBP'ũmtD)))ܿ_cĉ133ɓ,_////uEȂ[Χ֭Z5ӽ{tVW!j:uD-%22J*iU⿦L2̝;`n߾۷ fܹ.]|ziSrNmW{dd5tP)yٮ2uTuC ˋd !Bos>Cݻwϸqxw///x"rWEXx13fW믿3f ;iӦQzuN<ȑ#9s K,JN߽{7 X[[GZlW\aϞ=ӉvUΝ;G͚5IIIyX i &0i$UFDD#F .. }v=#GI߾}[QF;/%x133?hsqq!**Ff7oN%ĉ,Z>,_xN:?ҸqcOغu+ҥKD"[ѣ|gB۶m e߅x 4! 4vTy>ѣoޞ Xz5˖-S/֭Zl߾g/ǏתЭT*OOO׻M333[W?U/+w_Ezz:o6[fԨQZB_dccøqXt)ǏYuX_ŲrJx^!*9Usf"B![չwZ2v(5k֐Ȍ3XlգtҴjՊ~dV\8'OTϷ|ޟs3C~hڴ).]4_׬Y7ocȵkXtQm4+BVV.\JBQ%@B!zj)x嗹tlRo9333E޽{ ȅ ؽ{ޞ,ܹ9q!ijB0=y#*"%Ϟ=wϟI&lݺsss6m k֭C=-J ֭'&&Fg@z&£0X[[PPPP&L`Մj$Jw^}6T^xJr9N...̟?}ӇիWQ4%$$PZ5zrS!BT\29l'mLfT48::{nB<ׯ/7ąBeccݻw}ѣm:uӧcffƖ-[hccCvv6999Ց#G !%%SNѢE Ky0aҵkW4]~S~7ڷoOٲe 9@\\i˰aXjAAA̜9[[b7ܽ{Wcd> `&NQڵk=zDJ 8+o$@VݪU+-[ƌ3 dȐ!'B !*7oH~~>\vZj=Uw&ەӧO}8{,w‚ ҥKFD1Vi5q=z4~-QQQ̝;( Bgك2dBM)(n R\\\˗/]|YqqqQ02,G$O#?S<==M/C<ʫ?۶mSo߾˧Nѣb9s(cƌZw P4h(<|PqrrR_~)vIII 899)>T/W5CWz}UO>QeZeJ{^z-{ҥKRR% sٳg۔ScZ޿σN:)jժ2VѣGoJ.]J|"<(%k׮蓭[_JyoWV999ʘ1c33 xJ7^/zErUիa !ODyzz7!^ HE"BgE.]5uBȔ["2e ׯ'11~@9|0111Srewqvv&22''Ŏ  N:L>[[[SvٳWBoΝy8v{.~z/_hO;/7n}|wnݚ>}R~}snܸA@@mڴQo_~}233={6 ,ӧOl26oެ._accScq!F ?ɓ'3gԯ_qƕ)8fffꫯr!K&MT !L'<<QFIxx8SN5mPPL0Gnn.={$%%KKKM6ԬY{q vApp0_}ܹǪ8z!:SLaŊL:Uk{!xYC: !D9ҥxnIrYYYpBO5k4qtB?חBΞ={6l/^ZjRn]4h?;v*aڶm~h"Ҋ=ު?M6eÆ ?%Kdr;w CCoN2 &nPr1<)tЁ^}UǼ4aÆ۷Ξ=˴it`nnN@@|sCPPAAAϟOLL gϞȑ#Xv-#Gd֭_z%J[y_~0}]|}}qwwɩBPzz:ppp`Æ &55'OGBÆ ךڬFtڕ]2vXt®]ӧB'C!_~۷3x`S"(۷3`S|++2YRf͚̚5K6u8%B!D{>K˻?qeرJz*U(իWWz-eϞ=ZekԨQ@QE2e(s)ry]v:ٳgұcGJ*J5wwwSh;s(/Ωi/1%33STRJĉzOaWVeҤIŶ;%%EѣbiiԨQC߿J9lL++WTvԪUK177W~)+vŽ/^/zG*:L#hG$9E= !E,{c./SGgܽ{W9~uKKK,,,b]~Kݻwv})wֻ?} E/zGҒ!OB!B/jQ!07o2h 9s&gϞ>|Ǔ'׮]NQ@M6ߙ8q"L4|,, ;/?#C-6lmmiӦMeƎK߾}9tc4nܘ$,]GҪU+:Dnn.yyy\ IDAT$''ӹsgE>ӻB!B<*:!B!*Vj0Bޗ_~H4ԩ:u֖UV~b `Μ9xzz3tP˻v֭[i߾=7ofѢE Kc'<<~i޼yn;;2_|~Fpp0z_~ʢN:uׯ_of͚ 4(y9}4m۶-6cǪ[n_gϞ$%%k] 22vکwؑH6mJZZu/Don!Dq^y Wwll,>!CfhBuTe:tݻz?^ܿ_o] Q#8@jjjرc[m۶( CYfd-ċ%%R!BgAAA<*BT8::[ٳzpy4i֭[177X P1mݺ=zP~}u 4[n߿I#ZVXT7n0,v„ ^P䔢S@΋ w%''c5iDk =*zJܹsCxxUHYcQ0zZl$$$еkWRSSIOOC8;;˖4i҄Gѥ(]I%TT$۶mϏsСCYa!arOK<-...&!D',,ׯ3l0ÇuVtp((Y%S B!DE5c LBSqmEkdSN1}tزe -[,UbHI2228rAeSRR8uAeKKy0aQStgϞ=vBW"L^^^Ͱa8w͛7gsN~2_ŋپ}B|>66333맱|٤/N= Z 6-[0mڴb{:Gv)k,O#F,_7n0l0iJs^7o999Ӈbcy!_|E9Jjjuc"33xTʕ+տ~X!EDDp ZlI\\4<;wuÇ ɉLt5hЀ8;v,xKHyk׮PzjΜ9i۶-#Gds}N>ϦMp@#K.ܹpqqʕ+_2~dff2{l,XOfٲel޼Y]E!]Z^4!<:t9sP~}գJqvvM61m4~guҵܹs1bܽ{Wښ8wݻwgРA 4G6ݺ9sx|S*A\UFa3R!BW.\ADEEsrk߼y󰴴$33]beeE&MXjk֬)Ν @PPuԡrʴnݚ͛73|6m #G\(qqqW^\|n\۷3gһwo\]];v,[l!;;[O).̚5YfOBիWxW-wqBJa~ +<=xB3fPjUYjC%44!!!{k1|y|||ʴ &PjUVZũSZ*:t`ƌ;4mڔQF˩UBtZjuOޏ>h= /IIIHKK#44wD{;vuֱm6EaС4kL+aN!d'9RJQ%X&EURzzMNؿ?;w_eÆ lٲS7j(:֗ݪm+UAU αB!袣1bBCQS SӬY3BBB *{֭RѵkWvw}5Q֊ǐݒb1fݸq7n\us^?a뺔ڵ;[+7j(Fs^^^WN_rrIJJvL<777WA\\|lڴW_}<>gРA8::yؾ};VVV&P!_~K.I˖-srr?~\cļǏwwwয়~"""+W*A EQwժU 33Sޞ,ܹƺ;w!B$"`ʺs,B!%2Ott4;v0uB!Dk7qFkײvڧ@CHHHVZSvm:'''M56l`Æ =؞7aaa\~]cÇuVӭ !͍VXA`` 5j`͚5R^=wNxx8,^-[%K N.ʕ+ү_?6mʥKQWEŋԯ_}֬Y7ocȵkXtiۭW^y,.\ru!Lb* !BT|&L ??Sbr6uB"? 6HNN 6dԨQׯzjvڅ;3f0'Pturr2+W7+WfȐ!L4;wl2SgҤIDDDpU|Hff&\j[l^zu|rbccݻlڴݻwgoeŊ~rssuެtuu%77={:.!(Ÿ=O=aaa[[[TB-XlF2-aaa 2ڵkcnnNڵ>|8]4o ,,,hܸ1|'rgϦnݺke̙ 4իcaa+/uuݧOIHHoBBժU㭷2x!*>NtFFzκuT;v˗Ӯ];ԩCVVK.v?[ʕ+V'i͑ELL weѢE:7nPSu ߿:KgϞR͵&B!ʏ$<Μ9SaXu oaa:u'''ۘjɲ<۷]vqIrrrh޼9={+ӫi2XԩC yb !;ͭ[Z%..x<Տ < >>Km6F-[ȠuѸqc.\@`` )))ڵ_PnR֭[뉉a߾}̝;ר"""q-[O?UV7ʕ+QF]kkkٺu+ 4 22`.]Jf믩SlܸKLLEZT-KLLB%^:sU޽{ӻwo갲__n]uIHHW\Qn_rǏ3qDg8rh~bcci۶ >ݻG@@=bܻw bggHWFbFHLLT'lݺxHRR_~%F\{\\ 44T]  !B*((S}Q/'??WǰaHKK+:JIP|̙3n޼I~~>iii^{,رc[9s0{l֮]MBR%jJk (bccu "55U}-`޽ҬY3iԨ .(sssGXhԨVVV) T /w!̙CߟTU)vvv_^ zC|}}iڴ)xzzG Z*^^^ܹsGݙ3g#հaC2B!.GN:#EEEȑ#M϶6r u-OMMD4Tu @||:û}xzzŸq8qÇC5rH6<(:ugrrrrv4C%)c!BgCNN*U|nQF(}NJYn|aeeUi+6?IIIԮ]ɓ'F?#22?M6ꫯ4VS>gРA8::@7o۷oWBQל/_կ/^ŋ3f'Lrr2AAA;OOO,--]x@Uvm._̵khԨ2p=UI&߫Wh&իW UO5ERvv6n⥗^R3plPoܸw]}7o|@LUF!*}Pʔ uVVV,\ӧ!wŚ5k&ċB^i/܉vqqQRvNJ&M8q5>0.U2ʍ75jFO?e۶m;wx@{a9B!xvTR!<T}]ժUi޼9VYf޽aܡCHHHVZӿjժ9NNNL6I&QPP LIqu ^6|p_NXX #B!{# 6mڐdž ׯ_\ú~Qggg9y$=zۛuŘ̊-[*DQ5ztřΪU\^*ZflBx^uLŠ+XbSN]vKgS9hv^qno˗s)իGnhܸ1ZҚ,W !B<߿/sȖ? 6HNN 6dԨQO]Faƍ̞=f͚/|޽{?qppo߾?^OO?}vN>M^^tޝ)S`mmDS{1J*x{{'W^m.l6n?_={Gݢ:::rej֬I\\/Aݺuٹs:Aˋڵk>(GZ4?z`EwQOd(c{嗹tlٲ}Ϛ5 ֬Yΐgff52LI͔=YYYܹsGr!0%TO-'(b c;ׯWw322Xnf*URfM)>rFw αB!ijn޼ѣqzYff&п+W$;;[}>??I&.s5BCCIOOgݺuĈ BBB4ELL weѢEz4CmgϖX,m6øq4deeMJJ Z Xt邛[]8q7770n8ee9shhVFNزe nݚh~bcci۶-)))ڵK֭[%11$KuRB'RSSկ'ao߾]bٲِ㫯͑;wuÇ ɉLËuĈX[[kS%t ux, 3|̙3qaBCC[.W\aFi'DEEѨQ#֮]NILLEZۨl޼KKKfΜ.zC#iuҥ4nܘWG=ܹ3G&))=zlٲRmL|cƌޞ4}]tBll,&Lйsss033FݻGڵ+C FF$ks^j*B! 9r7Ww +܉f…X[[h"*W… >|8 ,`۶mڪ3=<uygggڴiӦMfʔ)zc^: "22$\]]_F}ܜ=zTbL|Opvvߟ)So>&OlT+WׯN̙34h@k jy1*eU4ɓ rƪGW]vU'^TVP6mľ}~3i$4i.;{l֯_OVVƈj"22X~G~wԩCn1ƺu8|0yyy4iooo|Mu8;;GPP3gRR%qqqa۷m֥O>^F.!!jժ[okB!d&KN)n4C;K.?O>Q_urrbܹ,XKg"˜9sx! дiSFƍٶmwu-c!B"z*`耪*Qu/>^?Xlywww}5kV[cªV^^^%Znh|Zz``u秱̐gee/aL{u-ӓ\ʕ+?~'jM])e'B 9r ։ϴ;;׺퐫W1n !Bg]ꦿ~7 %x)<9uգ[n4nܘVZ1dȐ5C=z͛X,m~7rhjbDGGh\|$)'Od̘1jՊt>u)zT\:=őGpp0+WWJ3殺 {"0`C +::;v: !*ѣGܹsQkv!(?ШVWǎMs&|wc)ɃOLu퍉,ɉsq/ǏWa///+mFRR*UMo߾E~U="88EQxw"e9L^8w-R/{.j EQx"/u=Eߜ={ Ξ=Kݺuӧ̘X =ܽ{w dŴlْ ,Yh~R^z{ EQhӦ 5jPܹ3ڵѣx{{3m4:w%_~%ɸ1h t> xb-Z+BZZz$^z]gi#F >>LXv-xj,.\ru!Ba_)Sb NJvLyfGDTTIr IX!Bƌ޽{IKKwX7a„fi2hii̙3կwN||<hӸRfMn޼޽ۨz SMiT˖-J*%(cb1jѣ矹x"cǎض~Zˊ3j(oNjYt)'O/~~~Z{ŋ51|e˖x{{k,{W1bu}mnnƍ믴i7778@zzwtD!!wׯ__~ԨQ˗/3`j׮M||+֙3gJhﳦ(}Xq1̓돍UթSRO%'<==$**a!@T~'O'99Ç7u8B!BJjjޛDѻwolmmR -Z`ٲeׯ}WVP<==qtt;;;o͙3޽{ceeZbɒ%m6fϞMݺu177'??zA 6[Ҽy)k =lkkKXXC vژSvmNxx8vvvlcc7Z_V-"##>}:Z|M6lOkICϧӧԪUCqFVjt}_;;;@>}&!!A|BBժU㭷2BH#NTLǎcݺu̙3ٳgvZTwB!B!FFNB!Bj֬W_}E޽M3ɉbfb֬YVo=޽{F3333uB! 㣏>:GSMm6EaС4k֌mۚ R!DEĮ2IZMBO!Яvܹs1777uHϬ_)Sb NJvLoI IOOۛf͚.MF͍7233 @+nʕdgg4i2׮]#44t֭[GJ# "$$DcYYYp]-Z]c(c)x+;;cru{~}UkghOA.]l!)7mL((N'ԯ_n=!ߦAgB||Cxxzzi0hݺ*ܸq-[駟Uo JNiԨ6lBFF[ϏƍsIIIa׮] 0[K133ĉL8qrMSPS\U"͛r O?Yf8q2կ݉hBke"B2'|*q֭1eF'0rONҥ ]t) !BaB!騒QZjʡC3g9rFr޽{ x̰pB @||:(©S8{,G ''ShKI>ڵ>}z3gРA5lPx:Ĉ#L(C≺qk֬СCܿƍ3j(e .Qߴ2U$垜-_01L !ew]TbHB[QreK9Eۭz٢Z&}B!B<|2NNN|駴hт'N0o<_QM[)S% !JĒSv-"BW_}޽EU{"^F n5RBSL+52/\/)aؠe!!"qd@s 4ESRBhJq 9xfm`~?33wkHӡt KzRdgg㧟~ªU0vXܹs? [[[DFF4h~7FD"JJJHlLX,ƀ*MPwU%5d㧟~{V6Sko QYY eB""""u48T{sU*%%i.eUlmmqF;r}:$J$tXr QwSOi:.C':,)aرJ?78 ((O=BCC!C/lviӦ!&&ň#`gguΝ;3f[nګ`ll ---HR¢㨪xSG^z  ֭[1n8?l9r$QRRRRR"! 5;BRۤIxMBD s#*m봓*Z$t씔$&&… Q0}t̛7ODDDDݟ \\\4=INYlN8\+r|ӧ 777e:::Xn D``¶.]{{{ 0pvvH$BRRZJxSG/777|R-5&LqVoʦ,BT6ea[TDԒ'"9+`gϞkEnn.b1؉Ѷ^X  tDԌxM@'\pAsC&&&FXXΝ;cċ/XطoRRRp-^^^>|ÇGaĈpssÕ+WÇ6l={P^^:Q񴧎8^}Edd$vލ'Oݻx7e֬YصkҰtReiii000̙3u1]n{aӦMX`0]36n܈vfDDڐ!Cpe?>~ym.S%QK䔮xgoпܼyGc߾}?Q/,zR$$$7t(DHBBC 4rf!((>=ddd4 CC&iX NNNbW5W.e}x>n7pqqATT`nn(++CNNV^ ==fM]&V'DGG֭[Xxжd:t`tDD̙3qel߾۶mèQpEl߾]:%*S%QK4$_ #-- ƈ o6pݻWѶ/^XuO@Ua8z($ |}}"Ha "uܼy@MM KbΜ9rSNΝ;8p OUV@';w"77Ì3vZzDFFq+++̛7ϗVHlذֈh򞾲'7̘1&Mŋbij줤$ vC-[o%ǿ6jԾ5Ϫ(**7L_|۷oǽ{oU.,""""""""͛7#117n7͛7CGGGQ7UQQ!$>x!(#X͛7C#66+WT/ WFVV߿J|عs<,, Cii)XbE}ݷU= t /,zg퍐`͚5 Oc}6lllp9s@, 8bC,ܹsCȑ#)))#Gvލs̙34Y _Dlnj쌌 ѣ+k!""#00=233~0p@?ԩS 999믿?JAYYW6UJ$zu䔃cǎEll,~c„ Bbb"nٲwE`` ݻؼy3>>tlj/8{,>Sk ;w@4uи]Ps? ""O?СC5u6/ܫqߦ>VJJ ֭['''c8x`*vV쭡񁏏"""?%Kh:j:&=={haf IDATzzz@vv6Kj@@ƍ>}`×NRض/,,,Я_?a*a?DxX`UMoedʮņ &ׇZ9P__+W`˖- $ |R-5&LЈ quAǏk}a(NCVVV{###߼vZlٲ޽{|rs UuLT. TDy)(--̝;W"k֬?}6֭[/*J`ڵkq,--J{. ޾LS=@?‚:} &Mӧ_f-TT*YWW--[W/ŢﲶW"'acǎʕ+àA0yd\>fépD"tZr: @iX`Gx" ^xVVV3f .\(ׯ-'ƍõkp&S.\e˖a̘1.xt /,;wCV4qI4#&&FF~m!<<ػwՌhܺu /ږ,YC!:: o"4 W^ENN{9=''d[uaܹ;w. pI߿;wT)91---*=ب~+cbbrTVVDnYeeЇ'{)z \\\:l e41&u}]rH$BII T:޳gp[PP0jLX,ƀwm:={6!H0g-GDDR)^~e!1EՓu{[DDDiy&Ñ 6 K.Ŝ9s>Hlذֈx(8q;ٳgcʕ 'ODBB.]cptt76NQguIIIww&pZhR)F%ұQGmm-oߎT[opNꘪ(k.$&&bܹXv-'qqqpwwWZёbH^BBC 988 ..!!! SO=PcȐ!/APPm&޾};`ԩj=o<s#oP|P*Tƽ) @EE+q췲Gr(W})ӦMCLL #F?gNI?"66&L@DDq!L:'N ̹s0c c֭B{UUt=yd⧟~'~mL<:::_駟"33X`0'yU """*++X;n߾-!00=«*Ν 兂ύ7 0޽{%ršJܾ1uioꌝMcŊrmm96 -- D ?#$L7$ ƌ#̓wߡ 푕Ǐia"_}+MADf˖-É'W^yEnٛo)SPZZ˗PhSp {DB"28rvڅ]vs.U[HMME~~ZCDDDD1wVÆ Cnn.sa֬YϠuyfa֭ݻ>@uu5P) =//] p=eP@pp0>Clذ{Ayyy'>|4| vXXΝ;cċ/(lqǕ+WI&_dz>ۺuЫW/8q݃6mڄٳgu[{աlg͚]v!-- K. """jݻ}}}Me5|Ѹ=;;k˪ @6䦱9q ((H8ﷴ͛1|$''c3g@*ŋ8v~WfIqڛ:ckkkѣGWkejƍC@@zK1ٹs'bccadd={}aSXX:tzÆ CD]… 5Q!{P6333دo}ܹ;wnsrrJc~~~-WeDEELH.++CNNV^WKŃ4Qe522|||?Th/ 9644lYV&Z'2;ݛ݆'\Ȩr6/,Q[[0zׯP} GYLii)4ycHxm[/^TP{<ئvnܸKKKR)޽+L(8ik׮=#W?MXVQQ]c6Y"zo#!dNz*=zDH֑H$DpssptDD{9&ou.B=/,V6=8!C,QThX5h9qa>/^Đ!C / cƌQI|uio=n8\v gϞm29… Xlƌ(hkk(*mmmM1qqq#Gp}DDD`Ν Kq[YQH$pqqtD]Vll,\]]5Ft)z]]]l޼`gbb"BCC興;xw4QT """z 4`cc"%%%HJJH$joff&@,cbaÇѻ uio={l$''C"`Μ9066[^__HRBH[2.\O?-|_!C6UTwDhh(Μ9a=&&&rUVV }zg퍐5k`kkᨈsuu*|QƇ%:S‚8 ((O=BCC!C/lviӦ!&&ň#`gguΝ;3f[nګ`ll ---HR :[3N{Qgɓ'?<==oc/O?ppp jبj۶mغu+F\a3f=fk~G\]]"ݻwxjr($}V8\\\u}D"tD.Lcr i/,˖-É'W^yEnٛo8}4rssuώHNNF`` u%c3D";vpp0z-\| ۛ6mm&7}FU666k9r4ٚmmmcŊ8wΟ?WHL:U$"n 5BEI&/(ox MADԥ)NMDDDDD&:511Att4`hh>}`رc̙ Hmmm111r_{prr.1c`Xj 6ڨS{8p}]3zzzNj/p´Uc֬Y۷/h"DFF_~jߑq^ݻ0k,!--MZZ 0sLX~\`WFXX{=lذwFNNN'GHDDDDDD)DDDDDlJ>>>nаqd ''VR-U:c@~wwwzlZgT>mh\}}} ** eee077!''W^uW]n{aӦMX`D"7nDBBtuu;3L""""jGD""""""Q<<}:VZ,&..;wDnn.3f`ڵBUzDFFq+++̛7ϗVHlذֈh2GY{KՈĉajj*c,YDQ7~ܾ}6668rΜ9^{ ~@qq1!q9DEE EEEQСCqddd`a#Gwƹsp> @Kl/=,--[~75vFF` ەVll,/Z"gggL<?<-[Jomm-vލsbxW:OyϪT̫=%+#447KDjtDDD^]]4A&xsjzz:ރ @n"#K* qǏ?~m:uJQ___aŨ顦pttĂ `wssC߾}k[Bo6l\0"RWll/zU+ B7n@,#??aaaիGDhR$$$p>" HHHtDDD=ƽ{4u!ׯ_9~eee'4Om!+++,9k׮Ŗ-[Lݻ˗/ tttT_ .U[ 2YQ[~4LNa>;;;>I&a…u!V+--̝;Wv'6ĊyD &5wo.O2U888 ..!!! SO=PcȐ!/APPm`S=yPVV???̙3#Fo@T*Eii),,,PQQ :nܸVﷲGr($}H=ׯGjj'gÐJXh1a DJDd T'JNMMMY1Tmo./`ddoViSMK12#z;wѣGC,,,ZrIl28qxW䖽{:u X|\? 6Uxxx (( ${Y‰3D"ܦ#9]va׮]{{{~|8 ??@utJݻM6aB&ggglܸ 0PH$BII ZUHk=ӧO PUUӧOwRdm~uYF{g 6`BZ"""H[[[i2i^vvv?4dbbh899}ѣc̙3Gghhh,\ֆ),Y=31j(}<==e߆ `nnmmm5ua߿? {{{lڴlYfAOOiii MKKfΜ j ;;;ၾ*::nŋ%K֭[`dDD)̓>sbĈ _oڴi\t =;w'^^^B_YT@ɪ5ĊyD$DUNi*\믿+o''M-o_DDDD=K)233CPPP___6ۯe]p/1tuu??ׇ PVVsss@YYrrrzj5] Ezz:ݻ+++,]"** 'NbXr80ajaĉ055 <vvv; ;cP'N>\uϬGDMOXyy9~G 0>ӑ7obРAKk*#СC#""""uL2z=zDH֑H$D _|4wʕ+q5ҥKBbJCuuuBAAv b#,, z5]Cmm푕Ǐ 7Qwݻ7Q\\ t IDAT2dN b1ۇܺu .ݰaكryvBZZ.]*+LY2ٳ^z qqqHLL?=⭮Fdd$N:;w`>}:VZ8###aX[[#""B.8}4tttK/a͚5ׯ:عs' .*++c9s}?___ Œ|"""U:jʎpUw͛7w߅;BCC:D"k`ff=z4qFܺuKQPPcVVV())APPn)##0zh8dmLN!"zRfbVө$(ONNFUU#ǣUUUطoǏQ]]G"$$DXZ?~\gxg퍐`͚5 މڛܫqЧObƍ }O8 5aii͛70tPeÆ CDD<<<0x`H$󈨡.Y933amm#Famm_~٘8qb{۶mѣQPPM6111 XZZB, U`jn?@||DDԵGD-)dwfF9#)2|ͮN?^r)uܔ&_,--+LOt~~~~1b+(믿C_~$z'""""""""&;;[R{Gj\[KK>4\^oڔKDDԞX1%+tfFyuu?V蓒9޲2e^~]aYGk >\x߿P:ȑ# |*nj|"""0qDOt8DDDDD 2/_ ϟW+PRR$D"211Ayy9*++abb"Lav""zZ?V#tZdwFF~f_o,u2ѕ%ȴj:OiLODDD=_޽d.7u3gl߾x!}vӦMK#ܹs| %o= Cك >HDDDDٺ(M {{{gϞ;#D,X񚙙իs='ӝ0#z"Y3%""|puutDDmoW^g}===qiMn֭['|0`*** H$888 55 SNm#""""j.2sL\|۷oǶm0j(\xɌ#F>"""<(J(--~W\x1ydL<CEAA~W1M:::"&&AAAضmlllPPP mBL#GDyy9JJJPODDDգGQgtDCib]]]DFF",, gΜAMM ,--@طoRRRp-^^^rӷoذ{AyyP|֬YصkҰtR8``` Tr!""""҄.Y/`M~񠥥ŋcǎHLLN:R,_\nB*ewfQO$kddH;366F``\ۍ7k722|||ݦ₨(PVV^zzzm""jBBBϟ04%4wűc`dd_~X_yرcxw!駟ӸsLLL/7l 2; 3򉈈'wC ""z"-\P!uRT!P yNNN000@II vxu<=zDH`'\]r yEJJYYb:BSJiܮlT]W~M3#z2u>DMAeUavvvl̙39,|XjU͛7w߅; 11iױ?$ $ "zi:ey?GUUqlٲ@gUwyxx`r2#J@>}4 uWѣ^zA$DxЯ==3FHHBBBf؉4KVNn7fQO_]aQknի\\\:&$"z$$$`[)cpaРAu{tDDDԁdSyt_XX#G6ۧ 11.\@MM Fӧc޼y044q_z%ܾ}| ,GbРAr}0o|YYYC߾}~&thܺu /ږ,YC!::ޝӓ(!!A!Q7ÿDDD)DDDDDDDDԣ}:VZ,&226l5"""ldo8Vmm-qiॗ^š5kЯ_?u233sN|7ݻ7.\///TVVbǎ8s $%%SZhR)F;w"77Ì3vZ I%/^~VVqpph2}}}XBMczjTVV q|G@@sss~Ð!CrM2NBzzrU 5ǽ^^^rU\nܸX|WdzwbiYYY8~8^u'Eau ظq#>"""Mk)S >>7KDDDDDDDDԢCxꫯBKK yyyXz5Қ\O"ڵk033ÿo=yyyظq#nݺ%(..9mۆѣG6mBQQbbbrX,!ӰC$aϞ=CJJBrJ~~>:C@pp0_`ؿ?"##qa;w͛; =C͛1h DEEA,#%%1cƠ M&888@KK 77OkQPPcVVV())APP7zh222ҁ0wZS_F~~>V\"rzi:""""ӧOtDDD^͵9s?#lllp1|'رcOqЧObƍ*?~PeԩS 븹)MPſ/XZZBWWo&$4#Fo߾B% :t(www*6Cc *a,Cl/֭[7 Fׯʕ+r%渟8qkkkhkk7o$'' }  "u,jjj0g\t 'O?MDDT'qǓi""ӯ_?M@DDDT7MGŋ2d^xXYYa̘1XpJc5rUimumW'7׮]ٳgLNp-[1c ** j>}QFW^t)s%ӱdR:Nk{K5V퇲c,kSwH՘3g~(M%"*:,9 ""Vb 0P\\,,!zV%6d\|ϟdz>+?^^Dnnwԩj+!R3M<Ǐ< vZdff ,PX_cٗ*QQQBU---ѣGrKq6m .]£Gp|'W6lZdm ['Kaaa0}ta騫jSѯ=biT<GxHu4MP||<|||éJ̞=/_fb uO\B J*e[/<2i$K=%+Q~z6yBBDUUN> '' /7ݻw:III)~Ic7?#,, wq=oʩT7-r܁e!04{ okMmiXr^唜وFaF0D~^^^^~\\|<,?;v,+K$1eС\z#GСCC$\UNsӯz2|V\B!ڲ B!XCw}'''LLL]6;wfɒ%L>pۙ3 4f͚ڲxbj׮577'88www4i1M4aܸq_ ihccJP qFy:w)c^/RkòtYȨ䖞={jLT]̌ <== 5^@2dh;&&333*x=z;w`ĈDEEUzL)KWeųl2ݻG= %>>ǏҡCnܸU%]dȾ߿χ~VVV4oWWW>߿oxDJJ$!:U:oU "eeLLL$!BB9:ש&@ jUq7X^~}|||)6^U5ۖ]IԩÄ 0a\sΥofffT .u-u,,,,S^=<==YnhTN>͌3055-pDJIKKɓXZZ{qq?iڴ{&%%%gѠAj֬I׮]ՕǏ2j%887o,7naaa3k,F'ݻ <7nplmm B`SbKQ ͛02!Bkݬ]a! 988`gg֭[ //?]8BQ]y{{ӬY3BBBe!!!XYYiM $<֮]+zɓ'6;;+WL^9r$W֨xT𾷮QQQ1l0LLL:t(yyy:?u̜9SYG1h z쉇{y,\X|9999Zн{w\]]ugԨQtޝk׮|EiwÆ u:kkk9|ҷ8EŪkyI׬K꣸ߗҞLT*ݻwW9h֬vvvT*233bBTA&)BVr-VXǹ>m۶eĉʜ3ܳYn⯿q 6S*%W  4 oG`` ƍԪUm2j(\\\?T*/_NRRuaРA̙3GҞ "'L^A!yPLB!}Çg֭Rh"yLTT+VК ITOVbƍϹ={gr=e2sL7n ((sαj*4??ݻw0rHQTڵSRF /_NffrΝ;x{{k$[\t cejO#OqIx饗uIIIңGZlY!磬{ԩ|gL>ѣGӧOtBZ(-}YyQuuNfooOBB7ިxŻs毿"::m:$!(UN)ν{:u*{%##\~W% jÆ \~\eP5g*-UVwߑBnn.ٜ={O?TM }̘1FB!B!L.]>K.lܸ}mfdd'6m$$$k.,XɲeXlƍ3t8Ͻt-755{͍D[[[iӦ -(rJ+\%cԨQܹSvǏW?~w}kkkLMM#11;vhmӦMLLL6m䁧.aÆ:tHI6|I&888T(Ddd$6m_vvv;w/OOOR]Z׬< Ǩ:|@Id*ȑ#deeaff\}?Wo߾kN~EVY&F"88#==ӧcll |Tċ;vcǎL4~z//J(-}YyQu͵ک!*_IOO'::!DuR-\z]j,U ࠪ`ƻ:!1gԩC||<_}cǎ%((yqYXX972B!B!DE믿Xf UV|駼8pׯ>}HbPW.\Zr'''… yyWfl۶M6??>]~ctaZ WQF)i=###v ǨRǩt8!D/HFF$!)UV9p6bJqY҅L<;99ѳgOٹs'gΜal޼~[SjR/nWs#H!B!BUzz:;v@R?PNFɎ;2du1tBQa,,,pvvٙd~6l˕VVV\z]vaeew)}VX8fϞMTTTչ6mʵk׸t:u;4oޜ={˹s8vӘ欼/oqqqL4 @+aFQ{ܸq:u =z4<|SN)+ 0@WKKKܹCdd$o7n @]iKGEۓիWybj"!G'M˖- BTjYku,Ys#Ξ=˒%Kڪ~~~<~۷o_cgg̙3*!ꩀkԨQٱuV]"ܨcA2B!(Z *&BQk.<==iڴ)^^^ܿ5k֐Fdd$U2fƌS4% zꅟ9Ihݺ5III?=z0d6mDݺu;wWWWFΝ;(u5We('OQF$%%1bCDDӦM+iҷo_RJ˖-5^GEӧ0a {{{ϼyHMMUV̞=[٦+NC߾}qwwAZJ{t]>*|siGo߾[Q:iii 0\ILB97{ѣ;wN#AB!DqBa(?èT*vAzz:|縹iLP7+5k$""˗/O1$w}Ǒ#Gy&գ[n̜9v)mϟ_Ҹw‚_8GիٷoFDa5"88UVq qqquVO og?jBm%D[v-֭#22RyH 3f`ԩbȿ':~:>|͛8"!4ղr @Æ YpƲ7nиqc̛7yO'''5_R;ggg𾊊AҞzɺuHMMD>}3fHbB!Dj׮mB q)ˆ %%Ν;cbccc𴸸H %22a!aٳ||| JRSSqttȈÇceee萄RU 333^@׮] {nd)B{`bbbHBKNN&<<JŅ x?~[@@@:KKKOn Os#H!BdСddd`aauNhgg~銦e#""gϞWYB!t`W^erS-SdS9B!mBbݾ}m۶R8z(fffpB DZ 37G-2a#:: 222ɩ*C,*OZp;v,+I!]rP~}:?C$UZ&!Ba(瓗gPBEff&sAj֬Ɉ#زe Ç{ѣG]sNFݻ)PJ:v}>CܰՕ>-[`bbbB!*˗qttҒCѸqcC$UNj !BL ߿϶mpssiӦԨQ n޼IDDeb2Luɓ'ޣA$$$:j/887o,7n7o$88؀ !BT~ӨQ#{ILBm۶eĉ,XЬͺu8t7fذaL:ڵkh$¨/(6l&&& :JETTӦMx333 ܾ}ƍ133ӊ300ckkڵk5/鸲  ::u2tP~mԩM||<˗/gԬYwwwfΜIzz:9ǎVZ888CzcQTtޝ&M(6k ;;;T*&Lܼs(D5 B… 8Mr!,-- BL%W֮EزeCB!B<=Jb۶mܹs^z駟Nf S޽{L:?CY믿*=|3g,qAAA;wUVXM-??ݻw0rHQTڵS\xx7|,--P Tc˗QZOUBCCy>>> o߮wѢE l٢g裏8pkmooOBB7;vӧC!ry?ɁhРCBZ֌3w+(1cߟB!B<󉏏gΜ9ё}]~wbcc={$AHH͛7'(('N39c$''ӥKBCCW^!!!(@Hbb'Obcc-\~]myݸq#/_EJuѼys.]뵶iӦ ,^Xk]qALL2Α#Gs9ˆc̙`ll̶mۈe;vL.66;jSLF!Ͼ~ɠרQ*q 0kkk<()BA%TNӧ} !B!B<Μ9JBRqڷoC*8Lq ???^z%u|ٳ5:t7o̬Y4?~2=}ڴiiPTܾ}[ڵkaj &Hzz6nZE9~8^^^C7tpqqaΝHNNёvڱgׯo萄ZP0 = 7!B!xV\pJExx8ɴjՊc2n8^yC̹z*]vXޭ[7)))ixttR}effra-[Ʋe˴9r,ojj*$! ׯ_FQڵSW?Tj׾}{ mVDk;w`nnNLF0!yVsNCP!~ge޽:9B5SJddB!B^JJ q)5kƘ1c ޾ʅ?/ O7Rܔ9T:%=*vyamrrrؿ?nnnŶ+MEѕ0V֪)l[NˍQ\}کߊB!gΜatЁ{,ϫJKN3fLeZQ\INB!i۶mɛB!uVˆҒѣG_п se˖o9s^{MY~VVV\z]vaeew_)}VX8fϞMTTT)ۼys\ӧѣ F''rUe3x`~7,Y'|B_XdV~zƆwyf6mڄk׮<'%%kkk.^/ /@^tҫW/ZjErr2/^Ʀ\ߟ'|BNHNNVWURIKKիZI( N$åT6W8:<|CﯔK{w4׫1(гgO+ 0@ի022bkkkRRR5k-ZoHN)K 0۷oڵky1ܽ{޽{seeP222/T~~!Ǔy8uW^a׮]"E(3?ٕ"T侊S6̛7yPB!ryyyRvU!D +++~m ͛l޼#FHbxyyѺuk]ƤIٳ''OڵkZm'MD֭IJJbу!Ci&ܹ֭s2rHv GSԨQUV7֤2ezɔ)S~:L2E㸪R޽8w:$Qa < ::ڰ=*⧟~bժU̟?+W*UDYlу~\~gOPP 4`Æ ddd0qD?~7_KKKϥs`ǎKreڵkǏ?HNNG%))Ik_ꄖCff&W`ʕ4hvvv"%xSO1 R!).!ВCdd$ƍiӦx{{K`` iiil߾wwwLLL s!11ȷMLL ٙ PfMlmmYx1FҐAAAxzzbee1Jovϟ?-Z`ll̽{طo:bٷoܜ`iҤ 4i҄qƱ~z,,,JuÇ޾< )111Zbbb033cUѣZR뫺R'#1(:ٰT*z%>~!nnnXYYѼys\]]~'GrqXX 5k֤SN_͛7+m;w.GO>DGG3{l Ta}\LLLD;w(###oxר]6YFk_ꗗ/_ΪUy&o$$$0h ^{5"##%1E!J\MkSxe貉4)<A-[B!.ѣGT*vAff&}eٲeѸqcC(аaC.\ƍZBZ'''Ą#G(?Ob-V庎ۖ]Qի'֭#55-Zӧ1c<i+ #--'Obii{IHH?iӦOܼyST0n8f֬YvEڴisٳg5~СCөS'*.](7lxR%WҥKZ2:88hkҥL2rA>C3gIII :{{{oNݺu IDATK<!xrJUMq#E "o޼Ipp#B!޽{+ϱ<;ƬYh޼9C%99>9s$TcٱuV222?k׮PoEYf(BBBbL~fΜIٳ'#F`ҥdggk}6/fhѷ:u GGGfΜY-n?,[_]9˗s=/GGG֮] @zz: ,O> 0>{iE^^Æ ĄCzJqq|G 4={޽{uvv6 .'''/_NNNV?)))tWWW5jݻwWH_.]ĬYӧdɒ%J. 7///뇋FB@JJ vvv5 xR޽;M4Q5k ;;;T*>>[SXzzz늚"(‘~SJVZZm=<Q?[l_4nܘ3k,-?>ʀWu{JIJJN: 49s(F ܸqZjѶm[FKǨO%OӫW&66,Znĉ>|@&LܼK!,=zdB@BB*-[/2g<<<|SSTOÇg֭hkii nO[ĄE;0a+VȃQeVZƍsss9{,gϞ޽{4>d̙$''+moܸAPPΝcժUUf֭[}ZZ* eLLBjjn:3r˗/'33S>oYOVVo&/_8P Ҫ_}v-ZeR{nF 3*]v1uT }uҥK,\Ǐ+V%..xr=44GiU̲Ύ'OK/KJJ"55=zвe*ݝ1c,mF^^~~~%n>o}wkT:v  ;;{{{ۓy7}lB[֭9€' 7۴ilْ 6p 3ڿZ6mUaJsƍ|2-Z (('Nn:7oΥKX~>Ν;GXXqqqJ%ٶmJ:Aɓ\~[[[lll֖ׯk7l[ԩ۷oرc= o"""Q uŞ={4e*@Vؾ};L2E#. 7///LMMX:vzxcOOON:<{zwQJÇW_ѧObccqpp믿Juׅ Gi7x,رc撐3ڶmۖ5jf233d۶mIbBZ&мyse3ѣ>{7h}@*XJ;g+H!BT~!IIIC!D%x"| ;w_f͸ȅ Xx1;w6tdӦM?~vł ex,,[e˖)(ZBDD7nnn$&&j};v'OҩS'_1Mtt4AΝUݺu/WjǏGK/DZx嗕Z >VƆڵk @NN ,UVԩSGTxz/\D=Ν;Kxw???ٱc>mڴĄiӦOaҥ4lؐC <z!4iT]SRq(##TEe^5֭|gh_pPռyseP޽{ioرc/o>.^ɓ'AAAA6SSS 777%"c/)ƒixr R!B!DeIII!""0N:EӦM3f ۗz{!Ϧ9sO||oݺܹs_+tUk~.4Zx?i^~e긯_+m۶WT]ԉs9r,̊[WXӮ];{uUϢ*׬YQFLLL ő166KϫEV?p'..ǏӫW/j|hΝ;kOLFTŋٱcXXXŋy'׮]cÆ unݺ5+WۛYf_)))Շ>ԩCtt4lݺ F7|6c jժE@@/^ؘ:0rH{@!xUYr>^ hue-Vv`V\mTKi\D !B!Hiiilٲpⰴd|_yX#٤k*]ٳ'ܹ3gΰzj6ooL^jA^,/}/_hٲ%m۶twww,oVQ\v?%?ԩSGr#߿&''k@Z8n}`=GfÆ ޽GGG݋KU[V-wÆ y7 ܹsJx>u=$ rYZZW_W_&44P'NdĉTVEZnaaիYzum7oBQUχ DTՠ{5}% J"b/)62B!BQ^waǎ)$s !(8;;? X|rʊWk.$.}Lnii ˗=f͚lْ˗/s)Ν+Wy\rӧOӣGeӧ*4>>+V8Gjqqq̞=7mڔk׮q%:uTa15oޜ={˹s8vӘ:]G}L0[*FFF[YߨQ#HOOQF۪i*\}8pѣGʆ $1E!ʩZVNiٲ%gΜ^S9sFmU J;LTv0ϵAB!BdΝsj֬ɰaPT:Km˖-/!4mٲ!]h7`֯_>>>p]6o̦McڵIIIQF/ }T;q ,^XYAÆ :t(WߟŋK/qy> 鿲ߟ'|BNHNNfɒ%fEx" /z٦W^jՊd.^Mݻ7*KO Xblْ;v;7x8&M0S]?5j[n%??_~ (۷oOZZW^z~_锄(l߾}=www%1E!*@LNC/ @PRqXQv0ϵAB!YO?iMY[(Kl>{ERg=z֭E由IddBDDDi}ґ2B!B<\\\neL8M2vXܹ_MZZwf„ ϗ/R~ $&& Օ ҡCj׮Mڵi۶-&M?Vڙ'VVVcaaT(riѢ<|qヒ&&&Ԯ]Ν;d%%<<x2%}`` nnnXZZRvmo.kܜ`iҤ 4i҄qƱ~z,,,Gnn.‚_ض#Fܜ}[dFԪU;3|r `dd pRMueW򽃃ƺ!C`jjJLLv1111x-;;wՕ &wIbBT$euVZűcʢM6? Rvm┶|w9r7oR^=u̙3i׮%-- p~ՙ?dffdbbbx1666?@z_]EGEELӲeK틷rM17v]˯_ΪU8q<]vL4jl[ks= Fo51m4.^޽{155:*Q!BP:P?ѣ}voqwwݝf͚:DQN5j $$OOOC"Sy#x0w\ZjŶm۴֯]uI-HMMŅ3f0u"-v܉;&MbڵEVOBQ&rZ jq7Xnaay7o^trrɩ6Eeϛs]҇ŕӵ;;;\A17v]˛7o^> *W[TAӧ1c$!J1 qFC"ϥ|g˖-ѵkW|}}qwwUVQT-[hLY,Џz !xdggs}e &l͞={ 08;VSU 333^`EAB!`fff0ŧ~JDDXYYŇ~Hݺu$,,7j$Wi9f%%%1o<011a̘1,]TyZZ , **{7|u|yyy,Zp\Bڵҥ ofoVSNRիtԉz lmm \DFF: !BT#𱵵eȑ:ۙh"yelŊ+4Bgǎxxx0yd֬Y#)BQIerٺu+hԨ!2B!Duc Q=ի022bkkkRRR5k-Zo)-QЀ}6 ҵkc{.{V'2Z_*??|x(eEKNN&<<JŅ xdرU0 )/B]4iBzz:vvvall\dW_}YftR~muVU:1eʔ)^ZSܤ0o<:vHݺu122 WWWBBB)_ij rҥ2B!D˓)B<-[Fbb"=zয়~"77>}@ ذaL8ǏMFFׯR{~~si(}\pl'7PՖ.]˗i׮?#999=z$}ZONN^+WVЙ,?/2;wfݺu >x._B!ϯ{_M&MJlɲeXlƍų`풘"UZVN122OOOC" @B! )337Ϯxԩׯ]vl޼Yёs|rC||< >V\ s>Ν;zt(|  5kx5effFzz:˗/ŅzzKT"""qƌ3;8B}KqI5-w+ܷ׍DR׭UD3-4Ƚ4}E%]S4DM7s|<|ws`9ח_=l1""""""YixzzoV)""! <..ΒFd IDATVu̙(;vd婞֭[dbҥDEEѸqcڵ+=\mEDD2wHV맟~Ã+1EDvsdvM6n"""""~ d >)R;w&,,̒4ş)Wr=ӧOxyy7P|y퉋Kƍ2d=t֍9s$;h ͛G:uȝ;7s_fԨQ,\0Y{i&(Y$ڵȑ#|ǜ;wM6YiӦ-Û{gqyϟիWqwwyxxat"Yd2ѳgO}]MfpDD$TrJJYꩽx"={ё=z<~v2EDDĖbccȗ/#I~L&V"!!m2o<:wLmH?/̂ ,vˋ'ҺukKyǎx"ތ=s2b*Wٳ`}rLtt4~㯿XbG:.X&SriժÇzfΜɶm۸}6ʕw޴oުϨ(Ν~:ŊE 80ׯ߲i&bbbhѢ|/=!=fDzbYn!!!;vX+Ff"OC)RCzf([DDDl)..!ݻw d2|ri֬}Hn___=Jtt% 44kZSnܸŋqppZtԩDEEY%mweصk~~~sE~pႥʝ;w<ߌHO,fb޼yV/_d֭[|g9#Yh6l k.BCCy7{zD-sbʰaꫯl<ģ"׮]chт гgOBCCWU9Q<}t:vH С3g$>>R,HLJǏ3l0jԨaqqq|4nܘ-Z0~xbԩSxyyѸqcZlĉԻwgՕ ФI˲et֭c4k֌)SX?VZQ~}YjUKҔs*"""e}kHDDw6l`РA8;;ӡCN>̈́ 8̙3l۶w}ggg[*""pyfsΝ;u:u"66[KNi޼8={L2<T\9sR|y>#GlٲVK'_m>?e˒'OƌCxx8K.3'35j+W.j֬i_~zKݍ70zh^z%rE:uH!=fDzbټy3wZj^oI&2߽Ǐ$%ݯ\rVuDtݛÇ+1ED -syJ*_|AժU9x cǎիVuf= *pY-ŝ;wZ3;ɓy;vlb޺u++=zcrE-Zh\\\O(QϏ 6XY\d ӧO^zܽ{UVCPP=zH8fsw;;;<ȠAKҬ/bŊ1m4.]eǴ^H{f+W.[ "ϸD`` gΜr 8www^|E['""hժӦMK ///~g֮]KV8t9rI&VǹsرcO:byjSSB ŋR1/KSfMڵk[pyd3&~t=%=\v{G&g31gw߽7n?due:"O2{Ǘ_~ipDD$[rJjS _,N:;CZOQ\T)KFqΝYj%Anݺȑ#/1-FeF3~ 699ŜУG2۷4k֌]ҵkׇyf ѣ^'O{n:;ܟU\/sYz2EDDHf8y$AAAL&>Lٲe޽;EDDD?1A_\Y&ƍlܸ^{… SvmnJtt4GVZ.\تmzgMt6#&%۟RYz4k?ƔfLyHOX&OѣGyiڴ)*Tॗ^[n)=̑#G"h"z-%<)gϞgשS'Y݌f'eƍŋd(۽~Vkժ/;:->|p>S c֬YOOOrӚ͝XҚUn6mEj-˗hѢV"##-uDTĔɓ':ɀ)Y$<g_ŬYhڴ)...|T^5kpf̘AFGDD1iٲ%9rc5'4jߒ͚5Kw/$1cp1~:| c>0ߔ)S|2Ldɒ̙ ЬY3,X-ZӦMO\Z*&M}zgt֍ŋ3gN/ ,, ܹsڵ+ ֭[3f̘d<ߌHO,~!mڴ ^z%&NhI@ smے'Olْlߖ-[ȗ/'ŋw᫯u8""쌇ò|ScN ALL z""""vo歷Jnܹ7o[6mqό-[dѢE=Ƥq͚5RZ5{,e)wj%KX^פINq\dzjժTח 9ׯדgY޼oС۪?/ƍSNdz."""""9޽˚5k0L,_Zh;*T!JHOFY7oδ:u*7ޞŋӻwofϞmruue888@ x뭷O-ROk6wZ5>=G"""""$JLLd 0ggg:vHDD'N… ү_?%Hӧ[)YdD+WN߾}"")q%:t@RXbEFOݏF"""""aܹ@BBBtkÃݻSlY[(""T/6l!!!K:ulYiժUt҅^zw)1EDnoRҤI5jmڴ!_|={I&PvmG(YO>/3rH@"""""}߿Ʉd"""_|An53-ԭ[///Loyb미ңG%aÆѫW/VX/sqt"""a?~֡H6rI ȑ#н{w<<L&&gRjU ;+Wux"""BBBl""""""]r~ Ķm(\0]taʔ)4mڔ9s:Diٲ%Ŋc͚5,X! )9EDDD$ܹs: gCLvM,YBPP֭ɉ;GѦMl#Zyj]t-Z7o^BCC)\C˖) <<6mڔĘ{2c 0 ݻSrejժɑȣa<ѣÐGǚ5k0LX8Zlɜ9sܹ}۷qss.]:C}tܙ˗+1DiӦF2eʯ_NVcƍ(QFHv-S2cV[͌ 6mpۘƍG׮])Y$;}PDDDDDlذ@.]Jdd$5bɸ[u""""Lv={dڵ̙3},_<y+WZT"##i۶-7odWDDfGYY4|^Ã@ϟ ܹs: Ct2 ۷c2 ʕ+ԫW1cн{wݴgy;vØ1clHL6 ;;;ʕ+Gٰa ]v\r 6b0ED$ɖ3ܟr=ΝKhh(.]"W\TPN:ѹsL+,,S?cooOn}9rʕӓݻSfM['""""b34ojV7nо}{Ο?O"E9s&[lwߥiӦ-[sEҥ3gUr8{,ڵ5kX}ay\~hfϞMbb"s͛4jԈӧO[p֭d5/8>>0¸u~zOd#Eٰa 4`Ϟ=^*U:Dɦr<홓FOΎ;ؼy3F (((6KuKɡC d <rŋٶm<֭[eǎQT).^ȢE Gɓ Xe_jժ5눈˗ATPӧӼysmӧVb<+yիükжm[ *… u{&11>}p-,X@…f4 8{ݻ>|ƍvZUJN8AtteyKZO2ӧOSbEvI\\6m2'̙3>'۷eС/Ύ;X"6RDDǖZHZG` k׮bŊLoԨQTT <==cѸh:/222 6$W\ԨQmÆ Y`Avʉ'ؾ};QQQ߿yRN?|ʕ#"""""DFF`ڶmK2e;v,+Wf\x3fаaCT"""""Ϻ`ɛ7/ZjWhѢ6mqlܸCҪU4QV-V勲/&5}t*U]-[9sxWqppI&̚5+Y_`ԩ̘1W2d ̙3i>W̜9xjU^xq6n܈͛7W艘9e8::ƴi,Ʀ<;IJ[JN3fNPg''Tǫ_Zj<pϞ=qttdl߾D4h?._P2%}(""""ώ˗/:yƲd|Msαn:PP![)""""(WnݚceKHH 003g0rHFyW8|05FҾ^*U`Vaaa)/\0}e֭ڵ>?c3yd뇳7&MĀz*s̡TR6XDD'"9SNԫW~h*UDʕrma„ :t݋7m۶1g;wΪs=GN_uիWk^rٳ5%]HDDD$ףݻ|M2GJ73߇'ˑ#G7n*TAY!Cp vuQDDDD$t'W^%w\|?;;;Zh /ٳ>}:ӦMql۶&M7߰~zKN8{!!!!Aؼy3we׮] 4(Y *`ggǬYf͚ԬYE-ˌ9K.P\9f͚|ٳg0a=UlO>x{{l=:uئ^z3%2H"[VeժU{Dž ƍRdIV\i׻woBBB%}5jĦM8tP=tPmDDDDաC)V3g&<<ÇK/:<DΝ#((O2e޽;=zvڶODDDD1j(-[ؿ?_5y᫯uȑD+r… Y&}*T{WRJ\\\nݺV'#=Fŋٻw/M6{xxpq#Gdxyye/i[y2$&&CϞ=wo6~~~.\O?/_>[)""O͜WWWƏϋ/TPzO?4#MSҸqc)^8{fVY#Ft̙2=Y޼y-?7ij_۶mɓ'[lI6-[ȗ/[#ٳ 8eHɒ%ѣGICs=gy-5j(n߾j\ .є7o^ݭٳg[.yC oFqppptԉ={<0'N`ggs'$$loN͛ @-w/MJunNNNV,X`̙3źk6n߾lݻwaaaa`,YHHHHxhs3yd2rȑ9ڵkWqa4me˖ hڴi\H]z]˕+g\|٪}Jaƭ[:uZXreqvzY9^<(cѢEƿ/#W\F>h6l@jՈhfI|||سg/[n%::XhРa0a„TcIk\OOOJ(A߾}~\B`` :t"""""իW/\rL&/BCC:t(˗u[lUVח#Gзo_reDDI-7usu~ 0 #<LJusmC (UTtqq1_+Yw^F ͚5cΝ56o̐!C(Z`ĉ4j聟 RŊu""򔰷uOGjjժtȑ#,YN<꾁AŊ LvCԩSԬY3qG)[>6mƍ1L)&-5 *$+˓'m?`k裏,/s]2bۗ;vcزeK:t -ri>̮]عs'Z~)]ς'OH`` ǎ|OOOUfDDDDDDDDDD""""b+nzz=ϟ˗Spdun߾ @|ׂ ذa`TS̉#YF2V5b۶mlٲ_p:īJ5,u3z]ݻ\966R?z _gO,X Pi^s<((ѣGs4O*^iwE d׮](Qݻ3|ׯoDDDD$:w;wu"sssu""M)9EDDDF˭[y& LWۣG2l0XhQ#͛(n߾19ݻî]8z(UVMSƒ m_Oqs.EҥK\zҥKZҥKҥ ]tܹs[[uVN8YbCc ,/Fr(VUVri>O7odٴiK.|lRSCmݺ5""A3ȳ-yVUX۷]ll,DGG駟ұcT뚗9tP^p!z0T={ZOƒٺuFBXl/_><<_~tj{OBBBҥ μ*T`._iӦSDDDD$]~O6m2MDD,9[nYյ"$$!H:k׎={0aZnK`woU,#F2vѼysǼyhԨվCQzu\\\ 11E;<_///-Zď?Ȅ xzb NNNуoɓ's5l^VZi&&MDvR\ݻL6 6mX+WgϞСCKV6l1a#G坟:u '~SNC޼ySQz']bb",[;wвeKf͚MfyRlY''b#yxyy߲m6ڵk75j`ǎL&,X=ޖ6+VoF=p!C0sLϟ3Æ #1tPz-BCCx"W_}` 4vݻ~v=xKV8p%9/. bԩl۶f͚1n84h@|qaaaL8]vQxqhohذ!;v#F$;#**%Kйsgݻe˖ԩS1?bŊq1&Mď?hi,IO"0رcpU^{5>su놳Cйs,;d>43 ݈Hߧixzz~d)n3gδ_nT&ݒ7oaggb 111aFn ?~3{H,i/jꫯQzTMu1۸qQP^ŋ;wL622ҨZjJ.mDDDXi֬Y~ܹ3n8RJ`Oi>o)I~V'ѣGʕ3ZjnMDDDDB֦Mn=g$iӦ͆<9ڷoϾ}ׯ?s6l@ܹy&+VhѢ_OOO *˹yfŒ34kYzYӦM9vcǎnݺ(P9r/_>֭9|p3(P;vjժ䄽=+V>`޽X?>ڵ#o޼SL … U(PVZ?g1n8fϞs0?;{,'NFT^Eƾ}8|0cǎ|SDDDD!ahӦM[6[?u0 Q:G1?ΔE$XlYG3tѣ EѤ#믿&00;8FL:@9d^ RRKY!sf^Shi,(r@Dkdbh" spy=~bZ߽]SCeĈxzzRR?7 """"bn}?-"w{"""%k[^=k9ڵk|g|glٲ]vQjUC>}EDDDDDDDDDn ='"""""R@nn.W.q'}Ç{֖>sH51EDDDDDRSS+:-sʭpww 66B t҅CVH"""""r9s~qQ{1x"_~{IOO[nXSNLNN666%^ޤ݊YV}̘1/R?UX^DDD)>|իWk1}tVZE|||E%"""""'|C=d%:Ĵihܸ1z"..ٳg̞={8q&T rrra˖-7qD.T' IDAT]Tam)dee1w\3 6d̙3ODDDDDIff&'Nd >Xƌ×_~iĉrөS' ƏϱcLjW_G0zh;`PF ˪){7n >T6bΟ?ƍ+02)/Gcǎ|'l߾kRZ5z)8z(˗/ݝxӯ_??M#!!zfԩCll,GDDDD)+VW^XTɪUk׮|gyT߷o_lmm6lo=~- :uEDDDD*Vrr2'NI&TRgggFIbb6667 eȐ!s=ӢE fΜɕ+W kӦMOLˋ-99777xꩧn9]vѥK]6O?4qqqE?bccC ͵677 'O2ydZlI*UUnnn̟?lڽwޡ{ԭ[[[[իGٳgsBImi=ggghժnw]19w! ƍ3qD:'OfӦMo\vxW~: 6_oƬ}н{wvAff&{xxΝ;LEDDDDv?0` 3gᆪI&fmjԨA=h֬lذ^zQr ZDDDDA_!55 /qժU3ߴi]t?… \vSNdwիW-# ߒ>Wd ƍ#..Ln)[͵k׸txzzrСBpqqG;wbQpΝ;G=pqq̡Cpss租~"''t'Ν+V_xzz2m4"""HKK#//?pz_|QݿPk[s Օ͛7Jnn.III+,^˯> 6燷7ǎt`뭷b֬Y|ᇦI&ɓMF8x ƍ,Y _J֭qwwsθ?cW蹝i5k,ږ\~wbذa̟?Df̘… ,qDDD,nQ``!7܊oo ={4?ެÇ gϞ5+_ nnn &}]!22`0 /_6tн{wõk O .\… 777C~JyDn>H6x{{ڴi+ͨ$w]f={RJAnzLrr0ڵ aEٳO:z(0kfu3f0aÆYw!`h֬E aѢEfo0 2j,ƿ3}b綾^8o1{キ8 !;;PN!%%Ŭݹs vvvڵk CKbmժU ŋ aÆiӦ[ԝdjC*UL38@^^]vF򘴴4-0ۈW`` A6meӧ޽; .ၻ;>(O>$Ceĉ̜9%K駟7qef^|EL;w,tFAnn.}孷2o2eű ~g/ #G45j666Z|א_=,J?oQֵkW.\PhUTai&]UV澔Fƍׯ/mb08{l:}4WWWBvBimi8δi,wŗ_y]7n۲>fƔzfdggn:/_nW\1\N DPP DDD[FZncHq\Wt"9!!!%jkq deeq._LVVW^%99,233tX]DDDDnpӥaNP64f͚ų>KTTQQQ裏SOOboo_~O:ѣG!::xݿ󠃵n\;~tbVu)+mrJiL6zrJGbb"mڴnO699b8j(>cnʁTu뒚Jzz:u5;6==FDDD$ٶmC PDmV:vHǎ8˗/R?ϩ]Eç5j(v\޽M b8rfRF~mڴӓH"""֭$$$ЩS'ڷooj[booONN׮]ή㲳M;v,5k7$.._~iѢ;wyŊo֭̚5SN}~_Y(-ddd3CQdy]7)#G$<<$֮]˪Uٳ'̞=3fЪU+.]D@@7oݝu֙{x1 \|K.Qf{1^~elll0=jm \R19tPbرcnݺXKKY0aѭ[7YSqԭ[Ο?OF mbj_3<3<Ù3goٿ?䧟~W^!44{`Ȑ!4k֌zѺuk\\\}^e4׶4Hzz:ԩSǢիeHE\Sref͚ QQQnm֬GLJΝ;ӷo_6oLժU:uE_G6I˿`ʢ`q1"""""""""""'-[%:.;;Ç*q9k[i&FuPc־8JKY:t(j>#;;jԨ#ڕ'I&::(!&MϲaN8AXX{)V, .`ݺu;v 0n82\~X\ҜqY=**lrJll,j۾}{y֮] H燷7T\'''yArpp0ܽ{w}Rzu""",Fݻ'""""""""""W7|͵ Ɔ~O>#G0p@̙S={`Æ u ЬY3_,)Syfl[XCj9r$.]bҥ\pÇ[,3Tcd]f5k׮;ЧOf͚accѣG-ڟq٥L Z|第,\ҜO? ŋ>-[Vf񉈈T;2s+f"66l'''MFXX|w,[4K c֕MZo7={T~YѺ{"""RΟ?à_ww'NXwwbm8XU㇄0m4MFHHH#"""""SLf͚DFFCvv6wfҤI5 [[[-Zd:&44{G&'矧J*lܸYfq9233>|8p#:Ν;pwwSNE۵kWok׮boIb)/'N`ҥ>P0i$j׮Mdd$<_5F=~X\ ®]z*$$$ oqb%''ynLd:wyyy=zѣGM?Jw!K4׶4LDD/999?~CQ^DDv#'L>LU1cРAMe8;;%cZmۚk׮b*W_}մvܹ>իyט>}:V">>XF Zj|tܙjժѫW/֯_ONN+WCc,X#GQ666V7VZflllx뭷hР<=z]2sLx1{)I,}tԉWҹsg6/s~)j<ԪU [[[ׯQQQԯ_0֭kvZnͱcӧ5jΎ|;vШQ#777Ƅ;;;T34h-ڵc̝;VZpСTk[sqrrbԪU;vСCTB֭ٶm+V(DDD*brJ۷/SOYmWZ5|}} %%%BCCjժ9j;(lrqNw[:ޘ)`Ƽʥ䲲;w.ٙ g"""""ү_?7n7Ύ5kһwov?o~*ƍc޽<޽Ur%BCC[)x{{SV->s.]Tf7ckYSJz_zǙ3gnnn899QR%jԨѣV3899ڴiCjհe˖>|MqFq&L`ӦMINNN`c0 APP#GM;A~HOOݝٳgS~"7Ҭ҉G:c6c&@pS'hϡ+Joy]\55k/0MMMˋcǚH{"""%k[%jmZ QDDDNp9֬YCdd$W\Yf=~'9_ӧbz'33 6k.~wիO<㱷7oe۶m?~lի#<”)S^䚂+J2Nq,{i2?xػw/YYYՋYfwFFtlbv pww'88QFXk$""""""""""R\)""""wDooo6m'|BBBcǎŅ S4ƌÅ LeIII̛7<% /_NFFiRBNN'O&11&%%???Xz5*XqڵlذT|ipkJ2Nq4^q2227ngϞ5믹z-_yرL<<<, &&;w2hР^+ٷ""""Rfh׮}M6qڴiٷo< ~~~6oޜHĈi׮AAADGGB!44t-[9s&8p|X~I)SԹT `͜={ƍi&X~='O ;HZnmXfl#""""""""""R49EDDD'mxhҤ իWg駟Zcˮ]Xh...T\͛ /o>:D6mꫯxwYd W\)|J2Nq4^qYh۶-vvv/O8@ӦM-6k̬Hy+e}mV^]H!{'"rw(cҥ,]Դoo72o8̙3xyyYmd… L:cǎY3 E[q77ꄊS\Oijܸ1N"..Sq)Ҏ_u뒚Jzz:u5KOO7|rYreYw+"%R!M'%k~~l2-ZDZXr%!!!4nܘO?ȱz쉿?gfƌjՊK.͛qwwgݺufDEEcq),X`*|2u3ghҤI)Sz=YE`ڷoω'Xpa_Ojj*PMmDDDDDDDDDDDn2rmƐ!Cʺkm۶Ut""RL%ϲk.9“O>iV7a„5vXÑ#G1Z*SN5?#3o<͛gvڤ1p@ +8UxRy\/[N8ĉM}5M)d޽$$$jVg|u߃>Wҿ""RRe>9HDn FYaH1rQ֭ƍYz5QQQdggӲeKƎˣ>zӱjԨ~!w888ɓiٲkFnn.ѪU+|||Y~=[nÃӧ{JNNN)Sz۳~zVZŷ~իWѣgfǎ0}eŊDDD0zhjԨA޽悉]oС ít`2M}}("R.֭cÆ |g4jg2`&M+8g)/EDDn"2H3f _~%̘11Ib {ڿ?+W0D.DD49'Np[ tEEDDDUZ5|}}y5j\UVpt"""""r'8s ۶mcȐ!emV!]FSyWٻw/uflݺapqqC͹1e-[ /kG%"""""we>2.#""R\޽{gee1w\3dΜ9l۶jժ0EDDDDooCDDDDDDDDDD*UW%qFΟ?Me#Flܸ#ݑSVY|9GJ*|KJ HMMeԯ_YfMNoǎdffaQALL ;wdРApDDDDDDDDDDD*FBBm۶5o׮]ꫯwRO]_ŋٽ{7111l޼&Ms!..δ…[ì^[b06l...tVC9rdE!"`0rw䔦M˽ˆ cݦ)$&&Ү];f͚E-HNNfѢEʀpttdL2yn:^u^ҥKqrr"66HZnm,22RSDDDPAAAUt"""""""%RRp޽{KԾmJ#ׯ_'%%___>̇~Ȃ t#GvZ׷T}eee1w\3dΜ9l۶,=ŗ"rw *imrJa 6c ,#G˗Mv`ѢE4l͛ˀgtoooy1b:u*2'N7&ԬY36""""_2Y,_޴j*VZug.h*UQFf$Fnn.p`oo_6n>|lĈlٲ72eʔ[WDDD)-Z0ܘiltd /?@y饗nCZZu2cׯ~zvIJJ vvvhт~a 㤗H/^̮]_+tYO slff&6l`׮]ԫW'xǗhtׯ_qqqaݺu%7ر|ٳٱc ,_~_5scdddLǎ_] pww'88QFYDD~Μ9S.D1dȐ2MN)8oL?X,uԕ+WJUq+UdQg,ʕ+H9PYaۛM'رcqqq1;w|Gk׮??pU4K,!,, lÉ' ''ɓ'h*KIIϏV^m{kN> @ݺu-/_NFFiBHY 0sL>ҥKquuAxbׯϬYرcxxxXALL ;wdРA[D_f|ȝ<>-;;qð0bcc-IIIiӆSNzꛎa|FJ#ooo 6m` _iڵkguh~طo3g`֭߿+W 6~# Xq]@AV 11vDtt4!!!tЁBCCoGnn.ǎ7k׮m7oNdd$ ,(Ź̟?W2o<_믿իW5Mu}ˌmDD*s"mڴVՓSz ٳ9~8yyy3ydSCDՕ-[p!ScrA?ˌmDDDDDDDDDDD Qڶmkuߨzŋaرٳ#GcVWjUN @FFT^ `kk/#F_g֭8::Rvm8p ΄޽{IHHl nݺݞ)G3,]Kx S&X^yϟ9x k׮eܸqx{{SjUtbߡC~2;kDJQreԩ&L0e8,ǵ^ ::~͛K/է72d,3) ˜RXQ~~~x{{LʕqrrGߔdŜ;w3fаaC6lȌ38</`4jԈʕ+@߾}^:GDDPF z}K!""""';$$iӦ1m4BBBncT""""""w>}W_1o<z!Yf O>hokkTJn0rrwDGGW_oZHeMqo1`,3);2sJaV;99(… YpEy߿iO>ǬlذgҨQ#Ξ=K||<&M2-ꫯw2y,>|0Wf֭  ?Ull,qqqL8vOTT/_'''"11oM6|r dȑ#fY> }W'VB$''f56{GRRmڴ!11իW}Rn]RSSIOOnݺfǦڈpvv&''{{{RRRSm8f긲rq6mݻ9y$/_ޞf͚3f<<<*$6kJr*̝_IYSPcƌAqvvXNHDDDD޽{︱;w.ٙ 2p@̙CVVmRDDDDDo׮~i̤UV`ggg~…$$$ÇYhp#yq1.Sz ٳ9~8yyy3yfCDՕ-[p!Sc&de6""w 999lٲ#]zqѦM/^Ltt4iii撙Ibb"ׯӓ!CpՊY`R ժUחPRRRHII!44___kfźrgڸq#ϟgᦲ#Fpy6nXLN3f /{tڕٳgjѾN:;.]0aRSSiӦ Æ +v|k`pvߟ.]O|rl2e ?0>(oYVׯn:H׮]޽;>,}Y_s\\z2=5Vk7; 88;R~}S Npp=U(G5ơ7x{{{iѢcǎe/_?-gѬ[{{b7}t5jDʕMO5j燷7T\'''y-HYxbΝ;nj3hذ! 6dƌ?ŋ72T^>"""Q{@ |ԫW5kPNbccMs*1114k֌8֮]K޽_>vvvԪUnݺoCZ eǎܡ49yy1bDE#"""rK3f _~%.]"77$͛GXXݕ+Wxزe Ν#77T?~<}O4IOOO>aիWr]Fff&?oREY|9fDٱcVO 33;w(;Mxx8o!66п8p[/hѶf͚Xο/Wn&66BNtt`fc8991m4ˆcٲelt7… fmOll, .ooo9{ٳg>&99'ҤIT3#G$11j{n2dș3gZ^~ey̛7񀙷nݺu 6kҬY3֭`}?5ʬܸo-;t~s̡]v899ѨQ[`ر4m;;;<==Ynp#HQ D:uꫯHMM5;<_~%kf@СCTپ};T^=zp2 Jd3}GxzzRZ5TBΝ裏8r8׏`~СK/ϱcǀˬҥ[vв>""""S,[TYt)<3v<-ȑ#rS ݺu+O?4|dffҪU+\\\YWΜ9s>k׮ g}FVVNbť>okcJNNXVDDDDDDDDDv|QX?Mwia\gV|ٳǬ5Ɖ#QaYM6xzz?R@Nh߾miqq5bc6;]i_[nEh///|MvnxckCBPS߯ED*XqygٵkG'40a1cwqƍg֮I&e1f-Zŋ-&O{Xvm8p ΄#lBBBQ#F0kWsaccúu駟4TtL4l…[cǎ`ƍYv'a}5Fj՘9s&3gμi✷fÆ ={FpY4iRD)~CDD"qXp!{萐 O M6/XdSL! ͛7ٻAC#&r\0gfcrX6Okl9|9g!F- Ӳ! tP.yo^z^׻]z>U>qKKy^:ά_+Wr-&M5Piޗ-[2e+Ohhhl>||ԩ۷gϞ|}}|{BY IDATq"TALjԨKTT˗/Z?wV*V9E!BhXXXhT, RB!B!Bj"22MVVL:cRZ5BCCY~=lݺ=="ӧO???<<KKK=oͯJvv6.\`ȑVT){ZѤrJ Q@9rdG$B}LW'fRCCCYf FFFB!B߱cdj!S˫saÆ1|p֭Ʋ͛79e4ݝ)SqF6nܨwѢEs%~g5Ԕݻw[oo>֭ۧ[7n\<)e̙3[y1w\֮]KLLLE%B!oVbժU̘1;;K!B!J%//O>mၵ5IIIxyyMhh(C qxzz+ワ/jrJdd$Z-22RSBXPP999LYQ( !JO* !ȑ#ݶ333YhÇCpBvܩVB!x֪WUֺܹJG!/>>BT~䂂ԛhB͛lذH߿O&M7n藖͛9toߦ^zՋ)SPfM`7ҧOfϞVë́s wU ԩS͛73w\lllشiFt?i vZZtsss3vX3B!3KN)'ɟRPjRaZms===J[(6] !LPPPE!DB!B۝;w?~755 77Wm={6~)'NĉlܸWWW022*V>SΝ;h-Sڔ>BQFY!!^ U*jçN*4???F9UVܜ1c~Yۛ]RZ57n6mLY&899aiiIժU155U+^166ѣZˎ=J͚5۷oB!(){{Bn#"b`Μ9GGG\]]  --\;`INNZvXsM>׮]ޞz縗VHH~!~!!!!e2IPPdgg} Ō3h۶-WܻwGq]i޼9#''L?e޽[c !ry˃ȑ#~²0̟?Ǐk//G֭[O?5Rl"##:tFsΩDY3gΰn:vA^^FƆv=ոBT&7[ό3*6b( Eb9r}}}\\\prrΎ:up=N>M`` ۶mcժU|KE!BW^?$!!ȿ4hALL :uRcbb,MMM>e6lX#//tj֬ @BBV.fff$''ƲTBpNqI4h+:t!BT.]j*bʕ{ÇƲl2uVm 7o ʕ+W8f:uo$11˗zum[5V BQЕ+WعsgE!(;w,rʋzxzz2k,Ǝ @hh(k֬)B!x)ӲTTرc=zuA̜9ccc6l ظqcǠ$LN̙3c(\GJJ GVƌ$^^III|ܼyuҫW/,X8e V8u+VäҨQ#F… ջZ ڲe wF= 6eV\s%?Crz޽{*h"N>M5޽;| vvvqEZh+իWVMÇ?͛7xzQ$ټy35kd꫅oOǎYf 3gΤiӦZǿ/.]Dڵի-m۶ZuV~߅ Xl௿~ۗ мyBm^^?31QQQѭ[7.\HǎֻtWT^kkk̬Y]vL!}Oll,Ʋɓ'ǏϡCr ڊcxyy|r߯ԩÝ;w:t( ѣw/P;::j+~v.]8rqqqZ%!Dadh!* ʲ&SoVbժU̘1CI@!B8x ӦMG888;j*222\֭[,^^zѹsg\\\^MQzj~muܿ_ӧիӦMhW_FF/{ooocǎHLoԨQL>]]q_BBnnntڕ޽{l2rqGGGCN066,Ĥ\.\1 ֮]ܹ3 bÆ ZsL4 Q֎=-_5'$''oAXXXǬ^-[nݺENNXݻk|(=zD@@xJѣ"cpuudddPF`ǎ 0'Oݻw K.υaccÛo͛7u ͛jbJI???rss6mSڵՕG㣳Ͽ/\]]9<>֭[`oow}WΎ[rurrr~:[l}8puO!O`g ???뇉 jՊ+V0p@ ~~~9sssV9cƌSSo{С,^-[b``L0O?T7w\6lHժU*hΜ9 >Zja``#-*~v166ѣZ=z5kҷo!B'Tė899zjV^͘1c*:!BT7n?ԩSܿLppt&MDXX#'' .L8۷sMuAAAL4Ig7iii&e;w /rJBBB޽{|7ݻ#<<,Yj2URY5j0qD>%=SN%::,RSSٵkԪU Ɵ[׮]ͩ}222hРjfi{vv6ӦMc˖-7nٳU۷ w9::Axxx-DiݹsÇƜ9stDEE1i$qrrƍi=|L:G1m4._Lvv6?͚5̙3XB+dZj&u nܸ}ܷK.qYRSSYzS9s&;vf͚g}Vd,SL(4I&{_> !CQF၃'N ++s1x`={dݴiڴiݻٳ'7֭ӹ~ٽ{7]tؘ7|Ǐk_ ͚5C__իӣGD={J/B!x? ն@,--* !DyIIIޞ>}pU5*@=/tU}Vڞ(/UOPZ!!!||2KLSB!*@aj駟iݺ5?_~z|)wS$,X-ٱpb}*+ZR?O6mJ9ϟO100P/(?x7nz1855U]jժA+++ y8ݻ.W9d~lll_>ds˖-~:/_BniƆUҴiS<==4PHnܸ8M4#DyR9sJ%*2f>|HYlr"ֺ婿{t IDAT5رc#44и|MĢ>}V[ΝӻАqCl٢, \\\022J(+A=rsaS-ZHk*UkZ离;Uh:ɿ~A3fjر#@F8p նڴiC^^ƝB!JWzu<== ƍܸqP<==tBQݸn۶mT>#/3gΰn:ܹ͛sYv-111*:!BQ[n1gΟ?) h߾FV_増rBYZ( ѬY3rRW"I-K[[[ ^077իܸqM!//tj֬XC? VNQ(S(v9v*ΝX?+WR뒐>sFjҦ<)7ESr2e5k5_(۷o+++e77L%#ӧO?քBQՅ-QrNNNSZ !DyUjl޼Y}vZ֮]+DHIIQv3f ۷oOgYQy>VVV1BÈ#O!*'Nٳ4h\O3_h/AZOCy[oU#77M6oVS(.1M4!33Ξ=V ֭[Sn]bbb!;;ƍ뼀]w^N:V$)6I2q] } ryf͚:ʿ&1?ott*L)i,eMb]5JsJ+{ֹcT\]v|06{=~~wfϞ]&B!B2ӧիӦMSeddvZLΝ4h6l ;;[k2m4z聃V"##C۷Yd {ё j) `oo1m6?=9{IUY/!!777vJ޽Ylj?СCܹ3ݻwo9^~iii^~[=Z74Сj:ʼrJ׮]B!O/**>}Ȓ%K{Qn]}gٲe,]-[ry-[շGҥKiݺ5jnݺ8^===rsqi&L̙3ܹ3FFFo|W8q.]0|pKzҺuk!77GGG$zzz8::wߩ ${Ϟ=gӼys޽K@@۶mޞM6RJNN&))I+ E**tKBf͚qi?&GVVG&##%K:<'&&8tılرcٺukƎK@@[laŊ#G2{l[6nHHH5kd̘1JL4UVi&&NX9cbbJ*/ЫW/v%Ѱ4S$)_fZO<+KVVV|w 4ÇvB!)P~7hܸ1v".. &`ccCPPzޤ L6MVƍǺusk7nGcdwz^/-- WWWujsxgΜaʕaaaArr2˗/8sݒbԩYYYڵ\,Xu4YpYΞ=Kzz::c>'N$11QmKNN&((h|}}n{R,###GGG9::Mxx8Æ }pESSӓsUBBBcs%66V(={:hҤ =" 3g9Rv۶m:+!==OOOLMM5V*t_7fDFFl#""wOO?رcGuViذ!DEEC HHHP9.I,约.Wڔ>PS%-+xzAAAZeBP7o<>|ѣGy͛7Ņ˗/yfvءUټy3֭㧟~4m/^???+>۷133wL<SSܹsY~=:KnuuVBBB8p/_FOO Fǎ).J6mUT)t}U^-mr^fM|}}o %%5j`ggǴih֬~/8z(ƍѣԬYSC뉌dxyyakkKTTSZ5uBCCY~=lݺӧOgÆ aaaY011ĉ|.p_Ϗ:wL9s Yyib)/SLa\ОJ$sqqvvٙSV-޽ӧ "00ңG (0Fŧ~JӦMp1ǎW_JY&iii޽!Ca~ӧOgڵDDD0tPh֬ xxxpaTcƌa1/GGG ps(ϐB4FY!!^04B$( .EoNE޴iS<==2daaa 2~<Ο??KxOETP㰳'fz}СNNN2qDΞ=˘1cx$pwwW%;;;˽{ܿ@ѣÇY=:?%d+zxx0sL:ތSX.^]}moo/8oחI&錡s:t###FEHH~~~Joc֮][dEU2sLVXaԩS5[XXk޳gOqcݻ#F :IX޽{888py4lؐHyy(4 q1֬YSQ !^d}r+<ɩSǏHNҥο:t[n1gΜBRnttt$;;H3322޽Fʟegg3n8hڴ)k̒쫲~TT-;t1nxx8~:899iS(Oat?^Xx{/GGG*g7*)B!buޝ ϟO~Y&IIIt۷j|>>8p~tLLLhѢ}ՕW_}1-Z0qDbbbbذaS^=~~~L>G,,,РA>}e˖qA/ׯO߾}?βĥajjJTT+V`Ϟ=\|4i»Ld[B!DA]vUB!*B']_eʕ?FobmmM6m*)cZT^}U( ΊÇg~W6l@@@3fКII(mUTZ=ꭨ\$9%d=͘!!!8qx9&BQ/_5թS)STPdyWzu<==5kcǎOf;,xlll)V߂4[nt֭k.JHa)&O$&Nĉ풼/5k֌e˖lٲRZI4i?sYaǤul۶=U^^^Z! !MV!JK*ũS8}4SLm۶agg͛5%IIIݻKK"*Y}}}SRZ55jDbb"O֘r[r,_ZnM||<֭?,rkI2x`L||<d˖-x{{ҠAbbbԩZRfff$''ƲTxyHrJ9s ֭cǎ1j(lllh׮]E&BJB~dgg+йsg&MyE(connnZ 3f`ggWQ !B!ʃ2-BWPP~mE!3JG۶mu.={ς pwwyܽ{mۆ=6mX'**>}Ȓ%K{Qn]  bɒ%rE>e~gh׮6m͍۷ӭ[7u===r VVV'ywvg4oޜ?ЬtRP=ˋKI6ʍ%Ž&-ZLRRVJRRG<$9%RL-Z,CpBvI՟IB!ܪTNNNxAϏB!/#FTtBLNN$-e2a>LllFFF̙3G}ݣGXx1/… 8::xF5I(3dԩS鉱1K,Zjxzz2f>v؁ uΝ; :KKK[}-女vQ7?Cq\]]5YYYiG.]8rqqqZV~6J"^\<=#OHIIј|̘1W !B!B!B!DLF9wY&899aiiIժU155U+{䯴1o>>߿z[o1i$ غu+k֬Q2SDGGƲe4~_%`А>}0{l 'of9rLzꥎ_ZZtA3vXLLLh !B!B!BqB/p 9r M!^haaa8Phߢf055??,r{&&&xyy\B @5?>b%m?9=ooׯW}-,&]f%VZ^&ԨQ'''|||v 6ڵk0uTܖ\*rJqx{{&qdgg3m4lƍ2{lrssēϓh~޹sׯc``@׮] cԩDGGEjj*v[]+͏?3n߾}ddd訵ё 5V!B!Bh#//B! ꣏>Y3gΰn:ܹ͛sYv-1118B!?~<mXZZjMe$*riӦb``@@@mIJJˋhBCC2dgϞ%&&GGG>|ȡCR deeaddرcYY7ӓW^y|}}POmƵkhԨ}666={VfjJkɰaÞ !⹱sN RaQ)ܹCB!B9=33E1|p,--S#,\;wjTRB͛7u5jԠ}ĪW'fbرf*8:=e'/&߿///uήMɐ!C cȐ!ۗgr)9y$/ǎO>jrJϞ=+++޽{ÇA6m'fŋㄗ4iG!CNNB!BRd)))=Zm3f ۷o77 N! ͛7III᯿⯿R_ߺun޼.Q}ؽ{wF/^onnnZ 3f`ggWQ\WNQ5W\(tÿorxx8wq59J*t޽8禦mW^Vc=]wρVҦB!ċ/00PdB!B!֭[Ycǎ5ƍLLJ_Q^=z-&Mf 7iiiӡC>رcuB<ɄTt(ܹs۷ok{-5֭[ܸq[n1F5xWxWW?~‚zQ~ Sqrrɩ%̨.Nu)甾>r>LNS۷رcdddOvSN+qZ5ë_JeJm!ŤDBA!.%D4gB!*t&M p51%lMF||v |}}cݺu:+GFFZ&<}h̷̙3ZF"**ZZ4oޜ|||o{./>|Xcٸq#̝;Wc[bb"[fܸqB!BAz'""}; ! ԃu©-&bdͼrٸqcm1+Dpxyy3oRxꩧѣGs nܸ4֤I:v쨼t³>KNر#:uK.s4iR#Ѝ5J~BTZR\###-[ƲelllWX+nYq744wwrR $##nݺspvv^B!5.]*`aa!&L 77###:D͵"eY?x\1::$ ]-D}3c } DSTT$)B!ݻ/py^|EeZsMLLHKKUޡCɡCrrr9B{4Mԉ'$ !DU'S:GGG+qss <<vEB!5e;v̄rss%!!KK Jv\ٳsN9s&fff 4Ho1 !+]7( 4hL8QQ=\ll,|ܺum2l0yygϞh>O*JQW7_~O>?~O>Dkرcپ};ѷo_n߾MXXXXX{W\\Lzz:=z_~deen/TփByxXvgӦM^CPn[M6rB'NH^!PFqxzzKff&I˖-B!ǎ+wݻwJ,gϞuҨQ#iM$hT*T*B!D=pM6mĉ'(((w̝;+Wh\$'00xnܸAǎ8q"NNNŻ҉0K#663qD 0aQQQoVkw! #G;+pBZng@@+V v\xyy@˖-0a/EIJJb|4m;;;\\\O?4k֌1c憡r,QQQ 2Ν;+caaATTs̡M6=B0UVQ111fybbbXj 0@!ըFѹsg>SHNNwH'NFv8uO?K.̞=KKK{9BCCqqqaĈzX!jVYfƘ:cǎFFFJXZZj544DRHFFݺu ##sLVp```31c999ٳ_ښK®B"BQݽ{'''he۶m8poq=ܹW_}Ç&ш#'..q kեD٤zTv<3 4?j]'//wwwzE-055C=iѲ^j׮]ёN:Ѽys%a7.,Ohm۵k m۶yٓwy}4;fff333̸|2gΜaȐ!;z*ݺu?zj\quuxO^ (VqDGGcbb͛ѣi̻x"ٓ;vfff޽cccBBBN< @VS>9P'\:t?;wO=## eݻ7}W|矜#55^zq)ON8))))Z7˗{V !TZle˖4nlllWZTꊷ7,^ssj_GQ}*RNRѨQ#*{4j;;2Ut{X59,,X@ǎ100`֬YUԤ\TvUi[PPPQ*Ԯe;!hź.<ʕ+u%!dݺuMҎ=J^^F5ƫkka7kӧOku ]|]FT8(֭[:su[HH7od|Gtؑ 6w^Tٳ't҅@8zr#wϞ=@ɍZ 8x ^^^ܹYf=RTyUZ[G/LOOGۛ5kɓu8q"@I+(uY̙3;wP\\̿/ùptRj֭aX[[h"-ZTc?_]%~~~L0(I Ғ={hU):d֭ >#GuVƏϞ={Jy,]?XOEϙ'7nJR-XSQ5PGbb"x饗ѣ鸺ҭ[7nZT|X5۷o3rH^'""\{~ouKYmz### ֺ!DUXr]MZ!ޫH[=xey'0J;t?9tΫHeѕ0Vժ)yoY7n@}*sx\U񚼸u }]妽@`(@[oq 8nnn>g͚EPPEVZGxx8W^_V*S=n]zTunIضm+V?~d>dN]~g$qJXh,[?\_aSInn.,]{{{nݺ$Hdff2eooo,X@\\qqq^,Yq>*sݺu#--4%C'|RkF_~)sȑ#5G*_o\Ws&BQ+3p@._Rɉmkܹsoqtt$77]vѮ];k6?Uty'ٻwիWӧ 4$Joi+ύ;BBCCquuǧ'苴6n>*J%} !hXw5()9Wrrrk[lڴI7mڤ1Qڵ+ΝW>CSj1!DݦT.UU yvɒ%hт$6l̙3 *]Vq"գҿCRPP@LL 666tlllصk|J*(/4uƍ#00͛ĺu4?5ȈӧhTƿ/ ~ڇ=1rH͓O>22>fvU{v _HiMj>^I&Ae]_h?3!B(]nРA4mTP}WXt)ǎcԨQ$$$okUjjr,]]h߾}@I_|͛3fl٢/u%;;EQ\\3YXH^i+jr 妅B?B4 ƍ_~O>?駟O>њ;vXoߎnnnۗ۷oFhh(ʅFQ\\yꩧ>|8={$55Y_f]?ua<ԯ_?HKKJBQ; _!7U.Uwy7oKе%Æ #!!sy cjSVՔ{PWG9npo!22}q]^}Ulق2LMMt:j.]b\rΝ;gP {.\!C*:A?P> SԩFrJQQsܮ];ϟ9}4wO?eٲeTءbwhh(| 'Og՚sy>3;Ǝ|q@w˭SbccY|#ȑ#GHOOgz5VÞ N#Gرc\xsssm/^p#}]tڵk\r9k׮o;wC*Z+++HMMo%$$Wb:qݻʓw UuСYYYh%I'OILL 7n`С|allH6m^^^T*|||xy&֭ۛcr ۷ӧ|M&MbӦM,YH:v숛7oO>M_/g_|Q٦t!f̘Ajjg?Ν;ӻwo^gW~J_HCgscF?lmm166&33>޽JRZpB077'))IIppp8b._sdmm...aaaӧM.]Ujٸq#̝;Wc[bb"[xXQw9(_۶mٴitޝ{5SjԩdddΤI۷/׮]TR:qo߾}L>LO Vu-գꞳg*-sM∌gFRSO=ҐR. IDAT Ÿo>N:5jՊupm$y'::SNi]@?Qn<j޼F[Sܹs?̈́ pssWWW_ǮSZl˖-ӊaڴil۶Mt҅aÆiYXX[o)wԉlGϞ=ߴ{g._U޻o߾3!DwBQiPrJRRR2dO;6l5*o߾?~ &(III:Kw$زe ,@RѲe /mzECVc)B!oߞ5kheffбcGq##2odfiiec100P,݉5' 77r-+q]UVt^YㆆT*Ƞ[n@/ΝYJ QO̟?x.\U7T P]///U*S)_fϞ=lܸ7%]ֵT[ٿӘcnn`u{'8u|{%#####ƌ|}MypwwW?쳸Wf͚ѩS'λᆱQLJ"K/{9/_Ώ?'>>>L0ggg5k͛IMMO>L<{ޢE 9p$%%о}{ VVVeqtt$..Ν;RXz/?um۶:u OOO166fYv=g5U6ҦWHrB!D7fqwwҒ֭[Ƨ~ P'kS}9::W_$܄cbbjIQ1yKCw}ǽ{ӧW_UD(6mJtt4W^{=GGGe^e*E-]ƍOAA^'Vu-գWxOMk׮6l(Ԋ$Өy'$e,XBIh9M2)STxZ/˝cooƘԡC|||)wec]=gBq 6mڤ0>;)T:߼yhӦ 4k֌yIIIm۶:U ^EXݻwsYqZS\I^i+.INѡY|JaÆI D!BTI&k.Oзk׎ )2[OOOy̙@ll,6mpN!DеkW֮]y] P.d2 pww+r֖ܺQB!DNLL 3fw(Bz&&&F!TB+׮]#$$Dibjj\uWJy k.rss:u*[n%22RcTLƍ#11e^zz:lݺ̧X+Ficǎ/_H9r҂ J.j|_XXHRRIIIlٲ /!B!D'mzM-9s`5($88XB!BIYngΜaС3p@._3| AAA899Ѷm[BBBx믿ptt(y XbJe(_~l߾'|??{*)\z>}ΠAHJJRJSСC;BBCCquuGSQYO !B6[[R'+̤ܿYfݛSbmm17??@q;vdĉ899Ѽy*}ƍʊ%Kp2dFizccc,,,bΜ9iӦNB!BE}~ءQnSO=ؾ};}!,,LIyW8q"dԨQ$%%1a:Tmkзo_䉽?[n)Tly3f [l_W֭aX[[h"EB!DMtӹ-::$ ]m&B荴N&c"RRRHIIݻJB\\\HMMUfffŋUVf6l@xx8< .5bc~BB!BѠK8x III 0{{&Tv *_o(yHʕ+ >\}cƌڗ7 , ..8V^K,BԊ˗s1IgϞח;wR\\̙3133cРAzT!6i[H^Qtgcٞ={s;?*ڹs2/,,THDD= 4dbcc4N^Q.t)s[Fjlҕfun%`Kf͚i͵'## FI~~>MTTTQ}~L0AWDxPv?>޽O?e˖R-1 !~ `W$88WWW=F' OC!6&ɶ>K,'))$l‚ PTeҹuiUΝ;tI٦ܦMJ`B!iС :Ta!Dлs%Əς ѣw8pgy\x%U[_{5>FQ\\˗133`ڴixyyR͛[oooƎˑ#G*VٙPٳgqvv֚ۻwo^gWǔ"B@Iṳ̊YfݛSj=O`` ܸq;2qDcJ?([:Ν;DEE1d:w166‚(̙^B!ZKNy0LkKKK FBBŋ>}:]2AyyyוRسgߟ+ԥl7hY]!B!x;!K.{i:V5kFHH ۷oӶm[:uDvv6gϞoo>N:5ӪU+֭[WxWXݻ9{,/2UQ \]]@/^!ח;v(BJJ wUZ~Bjj2733 .^j&??#Fhm1b)%B!DՔLό"00;vHnnF ̙3Z*U[l .n;tǬSB!%""FK^򪅗T*򒗼֭[,Y={ҴiSڷo5.\P888BqqɃ88::(I_|ziӦ<:uJIII 9nѢ ,ZN:ѢE غu\ggg177e˖lْNHHHBpٳ;?;;wT慅'::ALll,T!*fR!Bm}NJFFL4}r5 cDz}v<<cڴiٳ-[ٸq#̝;Wc~bb"[fܸqU==B!BPW~BT\DD6BQc~RRdiiɰaHHH`????Xx1ӧOʮWFиqcm1!%FŨQS$˹LҌXl˖->`\+W*R $##nݺspvvUVI!BcC!B!022R8p&&&^CdeeC4(sB!ģ)#_}ḹV !B(%%g}Va:{ХK}#B!xLM: ݙ4i}ڵk4kL7vXoߎnnnۗ۷oFhh(%PIOOG׏,ҴPҔ9B!N!!jYu֮S'*OOObcc$33X<==5z^ !BEqqq ;QX[[1GҥKenV}J#!B<b̘1 >͕yԔ .0{l e˖,]Tۮ];lll2e #GŋZ1F]G(G=1cB3_*<ꊷ7/`,BQ/8880c ,--C B۶m}6fb׮]I!9vVgϞח;wR\\̙3133cРAzT!B/5ƆMիW޽;GVWZnMPP۶mѣdggchh9...Gb 6oLVV?7ܹs5bHLLu֌7X!QF1j(}!$9T*T*B!|MF= w8iԨg&!!/ 0p@6o,[xDǎ9^PPի(j*bbb0000B! +++:H@WKKK4 QTAnܹs8;;ӪUB!B!cGGGطo\`:M6/ҽ{wRRR;;;x YXX`aa0jLpp0+cdggȄB!cbbٳB!D!SB!#| {%>>={;QG3۳o>}]n݊-NNNőIfݻ7SNZcn~~>s :vĉqrry5Ϝ9Ý;wbȐ!tYcllQQQ̙36mQ !BTNM%v!<==yw3glڴ-[j,B! TNB!xL|׬YoooƎpDִiSػw26n8RRR2e vvv888pM=F)De۶mSTTD~~>)))|GOBHH;EEEdffĒ%K~>||FmĈW'B!4 <WWWfŘ;,!B*4jԨv-B!*ٳgd}#kkklllڵ+P}۶mo2p@l´ioϞ=`aaAQQˋ;w2k,HMMe\޽{ڵkINN&66kkkΜ9Q1Eɓ_+ɓ'>}zB!DUvRPTC!AQF]ݻB!U5}e˖-GjՊh"m&Lŋ[`ooOPPzV44ep&ojՊ<ùz*/2Z-XvիW/<==ZmJtVksB!B!B!DV\\̼yq{Qa?^Oi999\r-,Y-ZĆ 9s&AAAܻwOc^zz:VVVXXX(/uB,nM6Zc9B!B!BW^9ĉJyc!~;!u|W_}7|ÓO>pD=cmm͂ }6m۶Uƿ+166&%%1J=XEW;fiiɰaHHH`????Xxfaݮn۸#1i+B!B!jONQBԾIBLJѣG;QM20gXj9666رVZ9J!jVVVXYYʷ~KHHׯWSLLLHKKTz:ENN:tؖB!I +B!jZ%!B駟;w.gGSO< 㥗^b̙\pݻse}'D:u*3i$˵kh֬2oرl߾۷/o&,,P,,,JnN=ׯYYYi%)sB!j¨QwB!1]7X!Bk999L:e}#iӦgO^^=dee1w\(,GGG3f Çssse޼y055… ̞=C2~xBCCiٲ%K.Uk2ȑ#xV 1~%B!B!:[9ҥK :h6lvvvO!B4,g֬Yܹs#Gмys}$9+++\\\$<<\i%~!k֬s;sLiccCӦMիtޝѣG++[&((m۶qQ144]b7o&++BƏƍILLdܹ1$&&ҺukƍW G,Bщ'MC+B!*N&,_cǎduc9{,ܹbfΜ HBxzzѣG֭ | K/ƍYx1?ǎwզ:իWckk ]vƆUVQPPP Q !!ؽ{7}7ofĈGOW IDAT4 &-Z'''Ν%b166&<<\ Ąٳg12!B!B!*XXX)\2@dd$1:!B/^d޼y,\'''}##L6dڵkcD{euS waΜ9Ʋi&ZlY!B!BQ\[K'`Ŋ_f˃X~=.\Ek,Yׯ_Ϗ'O)seҤIk|O?q=:v/+Z*X $>>7nбcG&N͛7Ww2d;wVƍ **9sЦMJk!B4 ofڴi$/i/ϯsҢIJJ`ذa9"!B\rì_;wh$jT3999ܻwݻws}<<<uܼySyϕ+WXf SL`˖-j;++(rssʌRSSLx"4n\q,?bcU:B!/55q1Nԩc̘1_^!DCĩRPTC!B/_αc@nn.$$$`iiY!>V._̛oݻwB.]ĥK8p}$}]ٳgeΝ3sL4h^B!xP gΜѫW/NMvxh۶-\~]ߡ5X.\?̌MҲeK^x֮] ߽dggcoo988Mpp#B!޵Q'dTU޽=߿Gxw1 66ѭE5Nq *rD4ZwPRӆji栕H HiF갵nKTэ"?fd2&xo7z^=a̼u ǏfJJJnǏ0`29rܹs899 1""">|8>|1={6S;ڵk,]-[pIhڴ)Ejj*+<ӟ9r7*)))\v?O888/@JJ x/]'g}/ŋIOO… <+ 3g۷ovڼ⋌;ZjL`` nnn$''ˉ'HNNͭBQe[YTѱ~a~Μ9C=drd_yע\j5طfWAA o޸@Æ $!!aÆTEE5j:,!Fee޼yTO#"""rZh֞W\a߿/W0/**b8p{IeѢEe~~6l@7&$$~zFY{ PPP`,8w9ss"""(..6m0e222E \zɓ'Ĺݻɡuc999ѱcGܪd>*ұGɇ~믿?]v駟6J_ݎ9Z2__5xyyEVV[l!00Ws+VF JJJx"uLWc=O?đ#GhٲeqDGGS~}=j<~Uj,{z]]]9vׯ坤 4ԩSӠAcy03d^ʕ++AȝV^=֭[GN=z4NI]d4DDDD6VOʕ+lܸ9s搘h,NY|9駟fԩ4mڔcǎ1k,HII+]޽'NAfÃ_dggӾ}{x ˖-̙3lْ>Gy>5kmVo+HHHo1+N d|W&)7n ((Ȣ(,ұS/fٲe,[ {{{ڴiCϞ=3ͮ_5U:GK+==-ZkhKOOWq>>pA;޽{ٽ{7III,YBSe5sd> @&M}MbDDD4ղ8Pp+ׯ/7ۛd>c>c2KÇJNN39v~lܸ"""9t^^^eKXX۷o'''ծ]ҥ ;v 77vڙЭ[J;/_G}ė_~i@:z饗_oO?M^TzL233Yd #F 88ڵk?\߆,Zm۶0|ϟo7p*'N'4>W׮]+3f͚CZZz"##|^ulmmbp;עEhт0eҥe޼y(K(%u9 mٰ͝}5qD7n-EEE7gQ^=bΫAビvvvhтsҷo_cܤI{{{ZjٳyHLL,\֭Ktt4bkk3ƚӧ嚖FݺuݻwWDDD {aԨQ?ެU:2e AAA&`ʃF?S [&T?/LJM6A6m|2/o߾^ܒy…߼y-/ټyY{:jԨq~n[Ɔ 6׷1YvvX2vnfqY˛s*:[z*3A-/C66_ڪ\DDDErp7*)S0eʔƗ5jĬYnS1(\yyo:N:u&**<7n @^^cԨQ8::޴_Wk#b5jM׮]c׮]ԩSitڕ$k!""""Uٙ0`8֭[Yl , 00WWW;quux Ö> .,s |MRRR̶*㧟~ȑ#l\nQFtԉtrssٹs'=zsq;,EٳիWo?vPv1FEԨQ.^h\񦬕[nUtX2_ 4ԩSӠAcQ,NS|W1ydpuu՝"""+W0p@j֬Ɋ+KYv-+ZJw=ݍËח>:Ν;vZ""""""""""RE8 ))Nu-"刏gڵNCDD,opA233WzꑒBǎ=z4NIDDDD1h k "+WZ;ܱ━ީEW\Qq=o111]zX]͉giӆqY;%>J""b;V"""""KKKfƌ 0T}>`„ <NEnF*zcver({QUSN 4V)xzz{nrrrhݺXNNyyyt777,YBTTO:EBBϟ1<<<ؿ?fh옡-==])"""bTXX 6$665jX;%{… 9pdffҠAk$"""""wȎ;Bt/[~aRRRZr7簪Ǻ.]b @@@ӦMcʕ888T""ಹ[yzz)ۛ~T\իWIMMŅݻsNvM˖-ٴi| s… kL:VZaggGvʼ4i?n#"""ꫯrq֬YS"rk^S\\lDDDDD?SN{nׯ;C=DVVS_LL Ofƶ!Cpibbb܏ZqJEլY___Ο?o\%##|̙3++|$&&rQJJJ*k{9̎ 1""""gʕ$$$дiSk#r{GYnL8鈈p5>3ܹ3ݻwg],O?йsgŋ)**2ƔusȘ[nex{{өS'Gdd$&qgϞe̙3:u*]vgϞ{\x,]Ɵ'xv)))/{ /ЩS'l\mB"""޽;>>>,XlǏӾ}{2 IDATחO?R9˜1cڵ+?6СCѣ~~~\vdǏ鉯/p@qqq15lOOO(((1k^gY˚l26l@^ظq#666c͛qssG4mڔVZ1h 2.hY|j ؘڴTlٲwysһwok#rxg"886mfDDDDDh-/0|x"CѣGscɓ'&77Ed%KeSN9s&p #Fgۼys9 PPP`R,Pp&_ǓEttي#99?7nʕ+te+lllx%%%lذ0`X~=#G,y;wPΜ9c9r62e x^ɓMdC^^;vvGE~~>p}^W^͵ks ֵkWtBtt4?MPڹs'qB"++-[x&""pFѩS'eΝXff&Ѽ[fo@^ZسgI{nnYa_{Û 1"""͐!C8p &Lv:";0zh;k#""""@3/|ڵ;w2eq˗/޽'NAfÃ'NyrYy/[3gвeKٹs'JHJJ"--͸U7|SXʤݰ*KPPPV4iBrr21$[^8oCQnHOOEf 1"""UZ7ńQTTd|Pڮ](**СCL6~ /0k,իWb7oc̎ 1"""`*,,ߟ&Mq%"U>'00E}}^Va8 ";;KTgO0c risNvM˖-ٴi| s0fL:VZaggGvxwok|oKc(ruѦMN m2e ͚5ޞ`~wNJ&MUÆ o5\7Yn]o4i8::Nvv6k֬1{O<p}x{{ʕ+W7>b\anv'O;j28TnzĿ/*2|ԩSvpazQLi?IHUkX[npiСqooo6nHDDf?tPK֭[9|O>fE(]taǎ60b8OII :uݻw-+"U֖x:vH`` ;wpEDDDD2o>dffdFApp0k6?~KY9R[q0[’1Ϝ99xY\II? ` \߂ʜ(,7;[c(oӦI!'Nq͸7~ѴiSc]ϟb.\@ݺuo!O׫Wk׮[fM|}}!--^zA~~>:@_\/0Wgg^Zy !11ȠΝ;Sϝ;Y6CHU)e-;v#0{pҤI=Zb {{{.]JPPޞ޽{_>}ptt4Y --uһw +"""ٳgf˼DDVzXn7ްv:""""" ?/LJM6A6m|2/o߾^ 40ya"""j+ܫBCCiذ!qqqƶ8\]] bf"""b-?#C !$$qY;K/Č30a;vv:"""""___<==Yj4k t%Í:tbΞ='|'G6Vk0lRYik.8tӦM3?_|Yfg^?~X%)Ƽsrrz*999̞=0]Qv|8Я_?cZܭ[7\\\8}4nnntxeM-k+ʕ+.]crssM~W+UUђhJy3f DFF2vXEDDWRRBXX+k֬)>>888`ooOV={%11{{{.]JPPޞ޽{~[iNNN0h \\\Ņ!Cmq6mڄ3/Mc뇓6mʕ+5hЀ|||prrΎ-Z0w\{9\=..ױ2u1>޽ɱ>}HZZҨ[.{EDDnPv:gС)=}fΜɇ~HjjE:ӱcG|||v:"""""Պ>?y1~x4iի͎gDEEvZ7n @^^~~~5#G۷> ekJذa3f 22R)"HӦMYbIII̟?鈈u={ 6̸P6lH\\-..WWW-DDDnWMk' """r9|0!!!?H){f޼yL)?///k#"UQFZ=z0c X;%oYp{vRRq>|͛WSNZQDD(?aaa9^{HԩK,aȑiӆ k$""""bǏgʕ 8ک=fʕNADD1*N &c{eѢE$&&RRR/m۶ym3ϰh"k#"wȈ#ػw/4oޜgy)XV>K3tPk!""k' ۱cGҥKL> \]]iԨL6K.,EDDb ¥KXjNIDӾ}{9{o8ELpill2dO&&&ƊylݺUVjtDgʕ1d}_~aŤsq^ykWPPҥKٶmgϞGW^ԭ[ @BB , ''Zj /[okXt)[lɓѴiS|}}3K.eĉxxxgܨ[wyc@qqq14lOOO6lNNN]{U={6ԩGeڵt֍ɓ'3|k$""""*ÇӼyVJ^ݔAU[qT.uOJJ"33N:1hР;2ȃ-N9w9sv"""(..\pW_}GN:E||}ۆ ӧbf"""Rbxz;ĉ܋2//6mژ?&ܨiӦ\v[oQV-233裏x嗉P bwYΝ;1C!FDD~0uToիyǬX- Ԯ] H_IXXI{VV0OOOlb`Ϟ=ՋѣGE07~P{B>S @Ν߿?/9˜1cڵ+?"##sQkڷo1aÆxzz@AANSjԨq[Ͽؤ4;;CNؾ};֭g,_cx˻s8fYon ϵ1Y2TIII%**:X;&~aܹ3o6-vJ"""""R޽Yp!и-[?I޽7=8q{{{vjcJQQGƶ'OMnn.-*3nK5|._իvs ̙39r߿?.\W_ѣƸSNOVVƹ+((`Ĉƛj6oŋok,2,eɒ%DEE<ԩS$$$pyfΜiqΕyM~}eֿYYYlٲBH)ؿp#GnרQ#gnյR;;;3`/ ,XRBn|UֹUҠA 1"""Ç[;fy-[ŋ>4\]]yg(..6~~Umۆ sssС' ==XpG{˗s~iHJJm۶deeRfe~ޛ4iBrr21ox|ٲe9s-[Ν; ::_pQ7nLtt4v"**Fqbcc_~%yyyl2vҥKd,2eI.+V`ʔ)@ZZ үtZhakh3ĈHܕkҥ :u˗/3o<<==o5k999\zfϞ @n,OOOVZEaa!͚5({ՕǏ߲vZ.]ѣG3gNϻ [;v̬_C[e NΞ=?DFFZ; g̘1ڵ鈈U#n7b(8<\|o_qJϞ=M )w 5kO0c 2թɓ'NZ:t(ϟ77ۤIpwwёpYf1PN֭M6L:m۶co\߆UVѮ];}ۚK Krٹs'we˖lڴO>slst kqv[ÇJNN39km6?n~6pww7kPf͚Ŝ9s Hڵkg|\~}Ν;G@@_>INN??(sywYcw҅;vk'?).2dEEEZDo>ʢqNIDDDDZy裏)[lVZ3 6^x\lll޽ _[p<^ު▮޴iScggg]fl;qp: ҴiƤg5ueȒy_WS,̙3?ŕT*ʼ&JΝc{ IDAT;Y#"""s߮ҠAbbb ;;;Zhܹs۷1ɉ  0dbcco:-@DDO=ӴiSxq'NqRTTt>ǏOPP///O^.k>}htAZZu5V‹܋y[֬Yã>jtDa899t""""" 6:7nSV mڴСC;w۷ӱcGׯϳ>˷~Kaa!m۶ *sȍ eqQ*7*7έ9֬i~%`IaI.{GRRR}V\~f۽"""vF1k֬[իWɓ'3yƕW)\Vʭ5ǧBc8880eLrwYcשS`3Ǿ}5j~"""ϟOlllIV^=֭[Gǎy7vJ"""""Պcٲe\x]еkWϹpٖ>ʱcX~=Uge:vhl߷o9qQcraeY2[䒙 @ttXѣW^f͚wl.ӠAN:E~~> 409oʻoWN aÆpuu%$$ĊT޾}xW7nNGD1͛7'..X>Sk#""""R<ذzjcqJ.]Xbp}zKV0l\9tŜ={O>OOOF]s"##9u/_f޼yxzzo3Yի0{luf}{ի|f[2[&vC1m4c\ǰ=ӱc̎nܜUWNSw-[w3f`ܸq 6 .\Hڵ~WСNGDQ/>'Nu)T 4]vdggӼys\\\hҤ yꩧ*E9w~zؾ};999f7T֮]Ǘ׭{ÇJNN39km6?Έ#LMBBBغu+_7Ǭh’yʰ$ooo6nHDDf}:t//;6ҥ ;v 77vڙ3rc!XN+{1cIdd$cǎ5{3&""r/(..fȐ!\v*KYDLߟܹ)""""rξia _VQ>'NqRTT@ݺu&88WWWlmmqvvۛػE '''hѢsΥo߾8'''bbb4h...!CkooҥK ~ӻwoƷd,2,eҤI=Zb;:ӧKKKnݺݻS$"""@ >>Cb"rQDoNZZ -EJ\xΝ;cggGZZNIDDDDH>3Xv-7 //???Fȑ#aODDBZ9EDDDK˗/磏>?WaT:uf,-""""""P6lH\\-..WWWDDDr*NΞ={5jǏׇ"R6mJBB̟?鈈Hppp`ƌpIN<ޝU]⎢VX 6iO( uƁ2L[J0+E4WPEG%E*u)JP#@`D0.s\cf?֭ԩSl:*t@y:{ս{w{sTS}ѻᆱ &Cz衇L'nݺ)<<\3gΔ$=s @9RQ(Q~~UV-jNP3F{QHHv)I?(44T3v}8_+V(\׸q㔜m۶t࣏>R=Էo_m߾]3N-aѢE={,XΝ;PCh͚5:}*n: *r?9e֭4hPy_@"jiر8p5̟'ZJ}ћoW_}tT*>Rn88gϞU``;PCSzԥK=RX,PUp @ES~xYVIjQF)55UO?Ԯ];I׊+Lg`8TYƍSJJvء&MEGG;waÆkrww ƇS|||$I)))}wl٢5kh:ׯ:o߾z*ڊ+$ISpp"n… 5g-[L;v4$GGG^Z4h֭[ZjcjņArss5emذΝӖ-[eGӦMc]٤jΜ9Z|v  ///ute0?AKέުիWk7xtPb1pʍt\͛7҆ T^=1BzR͕$͛7O_~j׮_ZJڻ ozWկ_?r-}W^ʕ+UNÅΏ? =>}(5buYAAAkŊ3PNH|>35h@111jݺukz私>S~m.\3ghυ(>>^ .Txx:J'//OeZM'5 >\{СCۛN@ .wwwG>>>gdd(<<\ݻ~mo%Kڵk%I.2r%WWW=Ӓbմi^ziʔ)駟VӕI҅ \~~~z'/\3|͛}{ٳ 5kwٲeUf oѢ|||l2]pdoF늌T.]L9`k9r,^Ze޽{%I={ub;??^}ϗŋzgQ:}4begg{>9sh:~.]l7ҥK }ֽ[l{W/p-X@Sll,2rJ($$D6ttv8UVJHHжm4|pIҿצygJnݫe˖3g{m֭c[o%KW[x=nM111ڱc,X[oU-g IҎ;eM4I|u۶m$q(x` QRR5yd2i޼V^ߚ2e*pʄ .''' 4H|ZI^^$w"{I&{UڵձcGM,?.W+Q*~AӃ>Srw+::ZoVZe:n2Sm۶ 4$]|L6kLR:u+yܹsgIɓ'RGN<ߥKI_= F-'''%%%i֬Y0`bbbS:$~(x` I^^'jN6l0=s:tLMSiON]v- ]`cÆ WԕZ}=iʔ)ԩrrr4w\=cZzu\܍~TQFiZf6lh:uU}Uff)npJJJJ7CPP$i…(qMzz/^,I (}%KgoGy=Wz뭷~+55UӧO$=ÿ?KO})??_o-IѣG槞zJ>>>Zj)///IEO]$_k}y@PlS~ԠA-YpaÆiԨQ6lL@ȷ6KӠA CU$)%%pI7o,X5knLȑ#5bÅ(#)SKL71BVRRRڵkWiP)O>ƍNRmNN2dZhK>tRr-z ъŋLPc8::jժUQHHl6$(w uԩSn:n:M:UΦƺx&M6mI[ɓS&44TE|Ib(88o,KǥO>[6m0E֞>}ZÇWӦMUN 4H/^,]|YSLT~}u]/n֭=z^{5=e  sssSBB6oެW^yt;ns >{nICBB ?\jRff:t .h߾}rwwձcGիWOiiiruu-v ^=ޒI&矋}gGI233խ[7=zȚ'xB~iޒ4a{%~3fN<)u] Ek&õ|rtns-)))n0EwGDD(""0,""B))){K.W_}IRFh"?^fӐ!CtyƪqEv{q%ooo+;;['O$%&&>sL=zTڹsrssyf۷ص Z֯_\]pAsΕ$EEE)77WAAAruuUll,)jC49PnN+VHչsg988;Tll$iɒ%k{_|Q7o6mڤ^>`Q **JS^|EI/R5k$I~n9::gϞ.vzI"##5g9sFaaaÇk͚5jذai>6fΜ)ܹss\0!G$iF$ӧCJJJҝwީ3fԾ}Ÿ.˅eddHw^}={,v3gN:/4vXuAӧOWvvh"-]T^^^Z&]VZ\fN? r$YYY|=w[]y+!?zԩS}Wx-Zh̘1:uR}-PS)11Q[l/l:0ppppE]5\t2hݺ>cǎUV]/+--Mڵk^z%͚5\( OOO8p@[l#bW^k7nܨYf_۶mSϞ=5{lmܸpM)'7GiHF-[ҥKJNNȑ#m۶,uyzzju6lXabL2ӠA<~}[VVtСbh֭ҥ233ձcGeeei޽jݺ;N:AJKKSFԼys9sFԪU+;v{HnW?ݻ+55ȺYo[_O>kזҥKӧN3fhܸqsIIIQϞ=5j(s,Rp֭[W b j s=z衇 o(EiذaZlM@ik_ս{w988h֭rqq1Uѣkǎر( S@Ű߿l٢N*/??_>N8d5it\OJ-@en:7|S֭ӊ+Lrࠕ+WҥK f3p p ~>sP%}z?ϦsZqssSbbnݪI&>5ԯ__/^TNNL@q!)((H ,0ŋ5tPksZp=f2UFVVz)kNѦsZ\{5)@ ._uO~:tHv,l6|I}7JNN柛pO>:~դIIp5NNJrI(::Znnn0a$^{5}WZz5)p888hŊWHHl6$(~$}T||kUPy\RӧOܹsg:j777%&&j۶m8q(GQ ԼysO>zNT(AZZ{N<vhEDDhsS|jӦM>@ܹs V@O?) @>>>055zh >\{5NJ!OOz5e={`T6MԥKj*9::No̙{~tHb8(QFFڶm[ɓ'nݺz U@2~xرCk֬$ժ˗f)$$RNJpQyxxy^zzwCeP9,^Xf]\)u IDAT\Mھ}&Nh:dv@enӦMtynץK}vY,C`ή]t+<<\3g4%KPspr poVG,>%%%)66&ygΜQ߾}գG;s駟֋/gyF|5'WUxx~WY,?^ڽ{wÇj꧟~RFL'M޽{ڹs\]]M'fO>k.5mt'tP~7=ڽ{9˗/iӦnݺ[n Qy}7ھ};)PEXV-_\ eZMgaNrqIRfff JxxyM8p룏>ҪUԡC92pssSbb5aEDDNPp[*YYYjذazo]7Tl۶Mzĉ믛ܠK駟V\\BBBL9pS$K4Pfl:*ƍ5n8zL*@.]+22RqqqsTsQ4p@W/@ ݻ;P.]L',vn: }Q5o\SBdgg{n׎;b: Pl6~aeddh׮]rss3I>@)yxxpr jnkذa:u֬Y` VUX, f3b8(%OOO 1c ^Z˖-n:p)11Q;vMNJCgϞUff(W׿ꫯj̙ݻ;w5k,-Ytj$ST+GQHH~i=t3F#GTjjՈnMGUA~~\\\pB 4taYYY޽ի͛7N:l6=#:rv%777INNJAmڴQFFv_~E $IVUU  f: @5p P:r æNkժUjٲ@%ҴiS%$$hΝ7n)@mۖU^BBx EEEtܹ,X_K,1c8(///~ :T>׿Tbرc5rHٳt*b#/C=3gtɹstwyڸqM'*9ͦG}TVJJ  Fpr P^^^)ͦ*''GWf0P*VUqqqZ f3 b8(?OrvvѣGM@L4I_Լys9*iӦJLLTrrƍg:@p PjՒ>l:J->>^3gTtt|}}MN:)&&FgŋMbLUM6ma:J%55U#Fѣ5d9*lڵkt]w[nTn7T%&LЗ_~T)Ξ=+yzz?j5l6}Q>|X)))rss3K>@yxxpr J///OjU||<)rQo: @p PF޺xN:e:iܸqڵk֬YwU&Md7t*<<<$IG5\%ќ9s;TC;vTLL>-ZtJn6խ[WS$iҤI߿@56`;Vڽ{) h۶9b:|Po@ 0c +00PgϞ5b8^^^RSPP֭8YVIj*>>^kVu%I*!S)*0wa:PuQ .|EU~ڵk|0OOOɓSp7oرc5uT/15~x)%%BZvm^@9(3gΨyڰaze:@ uqGZjgcڽ{*dLq24UD '7YfjРM-ZhѢE *ժx9::tRk/^ԤIԦM999u֚)rݸ8Y,=by\=|_ZZ飺uiӦ ӯZdӧ5|p5mTuѠAtb_˗5ey{{IW50jS_S@Z~a:"#FhQ=Jσ>?\jRff:t .h߾}rwwձcGիWOiiiruu-v ^=zҤIE>裏$I֭=ZdO.WVzz5ydIRbbb3gѣGᡝ;w*77W7o־}]`eՅ 4w\IRTTT9}@) z״b |p nkȐ!fP4nXZ$ 6Lv؏"y嗕&___8p@/uiݺ$رcڣ4<==%I[l)|RRR7naÆi֭JNNĉu93{ ) ruu222Lx }Zr?(IZpM|>}ZǏbQ^ nܸQf͒mۦ={jڸqcᚂSN $jϞ=GiHF-[ҥKJNNȑ#m۶,uuI:uT&@%.]ۿ?w]ݺuSTTۺu>@F2 ʒ:T5mݺU]tQff:v쨬,ݻW[ֱcԩS'5h@iiijԨ7o3gHZjcǎz>~>77WݻwWjjju!!!+*Xo[_O>kזNNA]ΐ$yxxo5:xÇ36l۷^P:u$I5R@@ Fu EEEަu֊ɓ'.I={ڴi#cjժZlprrҦM&777999)88X~a#GԂ ԵkW9;;Y۷פIhѢjSP\M4曊Ց#G&MhPm;wNw}nV}Tm۶ձct%)ͦeggkZiܸ{n7t/^ԤIԦM999u֚)޸8Y,X"+f+ߗ>}nݺjڴ믿Y{i >\M6U:u4h ]xuOOO+##CSLT~}u]/@+hÆ ZjnV9:(66Vs… M`.''G=zPJJJ|A}U233աC]pA퓻?;^zJKKkkR!>HnݺѣE<O% 6T߾}P1c\cIҲe hذasP/f͚ZsT n냊s=JMMեKt뫯RLL$QFZhΟ?fiȐ!:bccոqc]9Ke v+y{{+==]ٚ$_^pΝ+I*O@ug=3zLoxWgΜ1pr *\No>=zT~{~<<kזP3;vLw}z쩕+W6fTwU-a/SP6l۷kjժꪀ%%%ĉ*MO֭'O*<<\4{liF-eM6),,LnnnrrrRpp>"\\\ԲeKO]vվ}{M4I-(;;[O=Zhŋ35jD}7"&89(},X`:@%g͛7kΝM'P)^Z5|p9n'K6 x7vZ-_~GPP^~eiΝs [3Trk׮kH=sM޽{_~MA KgϞ/b:@%~ >^ׯL' [/ TtUJÆ fݻWG60www9;;ȑ#ST26M PNNh: *箻… 5o<-Xt2b8(VU:t̸q}v%&&Yfs4yd+99t2`8('^^^Xc:*oԩݻ?PJ ۛSڹsF+44tՂjU\\տNP K||t(++KjӦϟ/b: SNZ`}-]t8///8qBrqq1v m:@9裏4o<-^X:t0JvZrrss*f: Nʙ$ȑ#KZꫯ*((t(777%$$^}U9@p PZlzæS'N(((H=Nj:___EGGkve IDATZzq0T7EJOO7_hB/b1nаaÔC]v뮻L'5']vTqv]C Dկ_tf͚Ν;+00PYYYsxyy1Tq֭[e˖m۶s@9pttʕ+A˦xyyѣ7$$$hڴi5kze:-Zhʕ/5m49@p PڵkK.3ۧ޽\ s0x 8s>}rJl(3[f&(S*$C3c޿?z/E{ݻ䀦Mj޼y8q{&j5:\|Y%Jڵkծ];H?S7VժUqF (""B{QZWVNr<<q@.SOiڴi;v6nht ϣ8A5kd[ 7|S}5:ņ6:l Eiذa|L&qVݺun:999 r jѢn޼ݻwH@^da լYSW^at@v횺t"777\.nnnٳgկ_?@P5jH?np` ґ#GvZ(Q8 RVXUViƌF$ST|y,YRG5: P`M:U+Vʕ+itjJSNm޼8@Cq <==)N n:5JSNU6m7|S]v~Wyʦ@ݻ.^u(P>,uY!!!F@BB|||CiΝrss3:XX9ajO?dt @ձcGծ][|q@>Ho 2:gP5jԩSJJJ2: P $''k׮JLLTTT\\\UjŊ ӬY 9VZJNNǍÆ ݻ_FP֭5i$ >\۶m3:QիcǎZFGEiܹ VF#GWݺunt W3Y9 رc}Y1Bq@?[oTH#@w)fh2LFGĉ'd6չsgȍ(Nm jڴVvڥŋ 06lP5sLFrCF' V^z%={VQQQC zw4|pر8@)۹sfϞmt q͛7א!Cukڸq~l #Vk.Y,UTH@n)F;u"""9*""B}]裏gϞTV҄ GQ g2ҥKOIIIFGr VN1XhhkH/_kM&$iʔ)9rL&~O>?~fȊGI&ӢEȽbbb$I;vرcվ}{;vL:tP&M4k,TfM} '|bt W(dtsN͞=e͛7א!C4իUBEFFj޽޽5j%Jhʕrqqɦ٧}7n zHX9%9u"""Y.DEECz衇Yf: Zڴi]ٳF )Txx S=֭[Y +rիWdɒjٲevɤ?ھ}֭[e~0&$@J(իW+66VC5:`SRTTڵk'ggT~w_]5k|ҥN: '|ŋ0)\ڵk:wŋSNiݚ={\]] H >=z{x(Nŋ*\L& ./>L&Lv]fxyyd2~L&իWOw_!::Z V6mmO / i60%@?^ZR.]gt8ȢP%%%Ib >}t/cng.3 իպuk-ZTdխ[W?vءiӦH"H?'''U~~~C)@-YDK/8VVW޽˗+111; UBԫW/Izς $IK.MXڲe:w3gΨ]v߿~A>>>FGȔ%K*22R׈#<0Y^e˖UtiY,:thJզM]tIi]j.]6mڨ|2dN:eWdhÆ JNN֥K#Gh۶m9s&<^z ќ9sLa;U Oʕ+pP@@>찿dnE]v?,UVMo^z\:z쩢EG)oQF*Zڷo,yfy{{EJRǎ4s;vL&I˗͛7yʗ/ooҷo_Iv?-7nK/$wwwM:Ӓ3gʔ)B lٲzm6פ]">cݼySÆ S^-Z tU#Fq&+{Y*44T-E>ckN/_NuUVR۶mS;*>S"E`?^tT}x رCEMўJ*ܹsڷof;y{{CRg3h˖-ݻ+,,,SYlㅅ_nJq5naժ-[j튊RǎS7::Z;vSO=e/{~<<Hmƍ:wj׮-,IjҤ<==uY}i>?*>>^~aHҀk_URRvܩի+11Q^Y${UI/,)spѣV'88XVU={oaŋ5i$U\YJ}gʔ)ڿ֭;w*!!Aڳg6m*ժI&zGW_iz*) _srrRhh *nݺ9,N S}'ӨQ4c U^]iС׼ygϞ=7n$iĈ[`_ݻ?֣>*ggghB+V$}駩ƴ߻w?fyyy]+VR68}T"ggg5kL ,$}wifҥJ. 6ܹs)iݺu*U$eضYdI^s-}fΜx[rvvoVXl5k"EpjҤ-[&I%2穧ҼyRT)SFڻwFat P\mݺu^{yJ6mٳn޼6mh)Wl6j_~Ikڵ2LJlzmg.GBd&͠AR5mTt…{njK/͛Ztis}nܸ^zٷ[{y'UvmV/uiyyyWk׮i*Vf_eZհaTl]v׳G)V hѢE9s}@*S>|X!ɔSn]IU 믪^VX!''O8!N+Vjٲ*W\*USO ͌/_֭[UdIѣN|bbb1cƤy~ZxTbcce2裏JgI^{4R˝\]]ս{wIo!Iٳ\\\Ferʒn5?^:t^z%M>ﯿʶ{ҧO 2Dӏ?ht (NAVbEH"դI)RD<.\$͞=[? &HbbbTX1L&5jh2LGS&MR{… )رcWPF)IU|y*TH^^^O5vXըQCo߾l'iӦl6sᅪd )ڶm*00P<򈜝UD =sڴi ?{jzTdIVZ8qn*WWW]tI*S}Wɒ%f]t)۲4)VM{jժ%IlNWK] ] KW…g}V_|&LcJ,Xm?\ׯ_ r#j U@@lcȋ$I˗/wx ٷoZhzK&M2:VN jܸϟɓ'kժUF2W~TV-խ[H@r ̙3U~}uYF2r9}JHHP@@Vёt8<|򊈈͛5~xFq yDӦM5w\M8Qk֬1:. 0@W>}tEq y̼yTvmuYFTp[nFGL1-}2ׯVZ%dt,!VNe*W]k׮jҤ1+*""B֭ĉ+2͛7W͍7o3fhȐ!2j۶ёT(NeBCC`t 2-_ޫ^ڷojԨat$ Srp#@Qd`͟?_ܹ٣bŊ 8%ڵ ӢP*22R 6T~.dt,@@UTIҔ)SQl6g$2j۶rG{7ԛoɶMrSO=ӧkر/Hb[<'66VTn^^^eMz-m߾]%W;wV\)ժݻS? :t{SSjՌS{؎ ۷{_vMcǎ<<^zIm۶Mʕ+Zpl٢Ke˖3< +VVP3f(&&F ֳ>7xCE$ݺuK .ԦMtY9;;Zjر:ub;X,.\ÇS ,HN+Wƍ\r>˗[ŋ؋RBCCϫqz뭷>>h޽ڴit钡L>N#GAzgm}XI㜶tR]pAuQdduYll2P5[[Vңjժ Պ+4k,8%X,Zp$KEs̑$5lPI׿$I'NH_ $ILn;աC-^X˖-S>}te͘1#SيB{gKs;RLIR|||s6[imڴѤI4bm۶8( (N#bcc%.Nqt 4kL4}t;wN-:wlײeKI￯ݼyS111\N>@y{{+00PgΜQʕ{G4eVӦM5zhIW}ii+5kZhnݺdɒ~nGםlm)2LZdWFG@>GqJqw1ʡCR?eʔQHHZnŋYk|m/^\!!!֭ʕ+''''+WN={Ԓ%K{jܸqU\\\jժo߾zw+IIIIi9l0DrqqƎvt6mM;vH5;TX1=sȊEj:~ dts&j5:DA^,Xŋ+**J+V$>}Z:u/~˗;<@~zuAfkftOVNrX>}T|_|<<<ԫW/(ڶmwyGoP^f9GƵX,92nAPH?^CU޽%Iњ={\]] N3f8]bRJFG@>Cq 4jH%I6lhp*L&,Y"ooouU۷oѱPϰI/c@*Zz4ikѢEFG@>j֬e˖)88X .4:S$C7n^u}F@>Aq {wԺukuUgϞ5:BFcFGLP׮]L0LOk׮ڲe\\\<\[nFGP%JիմiS :TёQN: 7n@# 8%ٹsfϞmt Ȳ͛kȐ!F@jԨQ4hO yCF@JNRDD1 K"""wwUVԥKy+RFGL 0:BCCոqc髯ѱr HSɒ%kĈF@Cq z)$$DsҥK_+""BGQbbʖ--[jrssU%vڥ)ShrqqQ5d-[>^FJAYx6oެ?Se˖ /_~Y... ӌ3… gobeKu5=35jTYz3w~39spB >\Z`|ttnݺ^xAE?0EGGk)?=dݤו+WpBmٲEʖ-gyFAAA*Vڵk%I{Vrս{wYVժUuwgZ9;,j3ە+Wƍx zŋo4h@-f\ 0@u?nt$Bl듇J۬XBok׮]o'Hvؑjܝ;wjڽ{UB9sF}Y~g:|Nzǵw^EGGJ*Ԯ](Iںu~ӧOGҥK{n-\PǏ|ݹݟe$sz7#33gUVծ]R۷OgΜjԨ!IΜ9sIrb{ϲetIUXQڽ{/^ *ĉZd_%IXbާ{b؏w%I]vlm>(ئM&ooo… F@.DqJb+F[coFS:ua}G$^1no|||WS8!#}7o,Iz)'''UZUǏ$_>ո#GTʕUpaH._l?m6IҨQTn]9;;aÆ֔[F2w~393s֫WT[ ltQfo%3ss?ѣG~rvvV mٲIt֭<}9zsˑGJ]rG}4ElNNN Srrlt$2lܽԩS5uTĉ5qDIW>pႆ ~)XV5Uwc2G:uJd9qDjժٿmtg1m맸'pxI\%DJ=ɜH̙@ʕ+?P~aknݪWXb)sbAzefnǶ=Q R۞̙3r?ٳgUjUYV?5#~jω/G.^(I*^xs6[իբE MoVSS꧟~#<^zwQxx=*FKJ푞 `hggg&)yۘw}wHoF2gf^ecƍJJJJsׯkƍڍdfn2Q ouO?}+;~='~s[[z@аaC͟?_ӧOOߠ(xX9%X,ڿ%KhzհaC-\0E={HUT)Iɓ'o޼ &&&J"$=c~7]V~;=#:y/{mkHoF2gǜٶ={v|2d痡szӒO*TЯI&i /hZ|ڶmҥK֭[Z`V^|E6@&)Պ*Yn91)SFΝS||ʔ)\||p>}hׯj׮z +"///ǎ޽[III:rƌco|r~&MRlln޼ߗ$i&՘OKF#G(99Y>#f+~^ky:I&ex,G2~YǏ맟~c=M:ӴiSURE1+󟖜~jٲ7o*&&F'O$h޷iӦjذOW6mҕ+Wt :tHo٣f͚(.EEEڵk:yLiˉb2Hj֬)IRw>}f|}}+)Niٲ֯_qiܸq9r$KV߾}SSw۷mۦ+E_WWW 6,'uW^uQ۴iߌdꜭYFԣG{nb2ԣG}[owOKN|?G[lѩS\ʕSM2E ?QF駟ĉS}˖-Yfi֬YpEʉ(U.^(___yxxhڵj֬o߮X5l0E,lF__|}ALG]rСw1bZn"EEuɓE+WLƌj޼ *r饗^҂ j-V/999]-[Ԓ%K2ڂ.\(???*UJ...z4z HF2w~39+sv mذAz|vکxڰanܸOKN|?/^\!!!֭ʕ+''''+WN={Ԓ%Kҥl2 :Tu֕-VZi6m\]]S\3l0DrqqƎrf>+IIIIniǎرCŊs=@T\9EFFj֭zwVYhhd{ w$,IX,@`-^XQQQX$ԩ_~H/_Cpp^~eEDDK.F1,pO>*_|˗#ՖB#zWԯ_?>|80))+::ZgϞٳgǧYf~ԩ㍎PFi>}OW_}U 64:EDD(!!mc ܥ`Œ#}/7:0EDDe˖zw5~x#b6m9sh„ ZfqQ _}ѣG̛7OkVNot<L& K\EjܸUVo`|\y 7:dYʕ\RJPV{iرFG@b[5o\~Ə9Sr;w* eZ|1kڿeXTzu# PKYV#@Qd?~GuI{QbŌlƶ>0Zzԯ_?X 8RJPTT> Om۪dɒꫯSN*W֯_ot=_ ^_w}W͛73>>4hЀ 6DDD/^6RSSYv-׮]c&fϞͦM &&CzjVjuLƏϑ#Gם;wPYp1Q`ܸq\z }6AAAΞ=kf˖-ܸq#ysqqa,Z [o[^r 1/y8uꔱ,55 bŊ\|#G$>P֭KJJ W.RիWs݉`DFFҪU+6kADEEg\9v< IDATVٳԯ_+Vϲe8qDsӨQ#>s|UroԳgO6mD~ Yr%N^zOHHuɓ,_XwŊ\x͛ݻy ܹs QF,X"*>>ݻw3yd֭[g>..f͚m(3)7xooo|||_lSJCrcݻws7o͛?>g-ɓ-ZW+ɝbMm۶0sL\]]QFL6 3o...+WθBǵk׌;qss֭[o4e-[)Sÿo ;vf8D-pppe˖cc={0qD\\\X"AAA$&&_=w\"""Z*|8$p"##r $&&$?~PWÆ MꈈWhh(xyyuV?i[R888`31cpg /2a=jVNNYYM[j3gTxNlذOK2k)HF ""y:SJD-[;,X֭[h۷믿N߾}M29NJJ29nKa:;;i& +FG8xIakT'N?d̙f 7n0YZ᥸*W nYWݺu8tI0߀cw:rUү_?BBBXr%#Gڵk̝;XVZ\zլ}CHIݻ7>'Nd׮]GDDDDDDDDRnؒx2339vSL1MxINN&++~ѻwo6 S[nq1tÃ[=z 3grA8|0~޽;]tSF 6n͛79u|qۜ>}ڸ[uv kRRYYY$%%1k,:wl۱cG̙Cjj*s=g}___}QJ.Ã?t lcB_5kPVmDDDDDD[o1` ofpDDDDDDDD '؜5)]v%&&S2uTǎx\fML4oޜ!C][~~~|w$%%1|p˗g„ ԲÇrqp')RD~&OLbb"&]v%**y=GEa|9r$;vsqq1)5j۶m#))g}֤1c,oooO`` //-[dȑ̜9>,1u;vd׮]$''.s'Ј;;;С^^^R|y[%""""""""wSJ(69mĉՋ *舛f2&u[Τܹsԩe˖ɉ%KhvaV\P|||pvvޞUҵkW/_^U5YlԨQGGGzIPPU899K/O0oooU#;VǙe#н{w>SZjo*Uqrr''' ˩ZnZ W^TR5kٳӧO}h¸a///NJӦMqttёƍ{gwTXXvccc\2={zDDDDDD r|8q_|ለH!:YDDnC{ɰGbbb֕ߒ%K aƍԫWg2`ƍѣmؚ/EDDDD+&&~1o<^~e[#""""""""K)"b#GRNDpͶrûo={l@)"b *0m49wΝ#::iӦiwL2gyoooΜ9cpDDDDDDDD$emNO<̙3^z֭[8*yF4hvaHJNy%&&ޓaCZj|k׎>3[$""""""""yh[)՚4iʕ+ eٲeGDDDDDDDDPrzcԩ+:E)"""""""@xwٳ'ޜ;wለWeu""E~z|||l AlH 4v: yUV/$^{5[#""""""""hNNԩ)7oM6:$S3: b!<a׮]ܼyݻXwZZk׮M6899שSǘ5bTR9ԪU(:vĉ;wCy)90$rOРA6l@rr2~~~aeFŋe'Odԩdggӷo_ΝKZZ1)!33scsJrr2 .L;,^RSSYv-׮]c˚~ x(|ٳgl7~oHOOӬ}OOOغu+vzDDDDDD;Z>LJ6m0l0[$"""""""@Ӷ>Hrr2 VXŋi޼9QQQ޽{Pv5jD\\11b9rwww"""ؿ?jՊ׮Yɓ'޽{Yt)k SXJ)'/UVqYׯϊ+gٲe8qX785kfVPf#""""" 6l&L`:tለ<ДRQ,ٳ'BŊ "11/¬Çlm6fΜ+4jԈiӦc{n8@ټy3g\~XOaYOޱŽ@pppuּ?q?~ mذIڵk.]u8"""""""",mS ]#88`31cpge4iR O_~?x2339vSL1_v -hOa-t/멧`̙_"e_5;g(+6Q""""""ȑ#yWu8""""""""RJX2j(mFRR>ɹ1cܵ/???;>|ɹ3aq׮]aԩL:լcǎI5|2^^^8;;i&)S| >oǏ3vX޽{%lr[Z W^TR5kٳӧ]\2쌽=UVk׮,_d'ҫW/*T#nnn̚5˘Pn:|Mի=VSX$݋rttdٲex{{SF ٳ'AAA??{bŊƚrٳS$"""""R*8::~z2226lٶIDDDDDDD`c fb yE*K,!$$7R^=Ξ=ˀ7nGqRnXDDDD~@.]x뭷>})rwWSI@xx8f<ڶmKXXO?Cy (9EDPӦM#::sq96m˗ux""""""aÆѡC[!"""""""@(kDO9sx饗hݺL)"b[!""""""""""""""m#""""""""""""""""VN/CT """"""rSrwu":BQr}jAD֯_ϠAlb S< rқ/""""""""""""""" Pr}GKDD/#)urٳg)N:ꫯ: y@888n0DlJ+튈HiӧY~Rm888: y 4H""""""""SSAD|}}m':yp)9EDDDDDDD|2ʕΎrq忴;;;ЧOrpvvO>s">"""""""_֧p}zl߾3g0`ux&<<<HLL4;sN9|0ׯ_iӦtޝSJ:uq4ibRfXAff&O=׮]jժlٲGG易+ ۷3x{ާyf6oLTTׯLw%""""""R INNf1Y#==W_}'˗$))yѿ;[YdoD}w\v k׮c~ 2qD|M,XCl2˗/79䐓cӾsnݺŹsXx1*U"**K,ss"""""""R'.(({Ļ֭[ٿ?qu&Mď?hPd׮]OLLs/xge8|ݼywyooo[.^^^L27oӾEDDDDOڵYh5k$11Ç:RlٲԩSdzpB-[fDDDDDDDR xxx?+WڵkX`A={K͚5Y|9}f͚Sn]^~eƏOvv6-urjԨI^: ?֡Saaa\pCˆ ƅ  ad"""""bɯرcqqq\r8;;ˑ#G,ַ'D #<#7f\~=߸VXyTP^Pl+O<*Uo߾Ŏ`۶moGGGjԨA9x`qOQN,ʢN:ޗ0k'##>.]PV-ʖ-KڵygV|x]ahɓЩS'2k,Jb)MKK?g1ޓsih#++`tBYd W^%00N:ѭ[7}]nܸaKtt4o駟B }6meӦM~7ciii]6mژ֩SǘfOҢE >S~7233IMM%""'x"gTPxŊoߞ?/r-N:ٳҥlV^ wK^cSRbn:z)ϭ[?cǎ8p 8\]]y'9<_:111?'|WWW[nP|ycYZZ;v_ql.]DLL ݻw端2_hNNN,^,YٳK-[իWSbE6"""""""SJ6&4hЀD>ծ:;w.iii`dX~ܾ͡}xŋ4i\~,RSSYv-|^ZZDGGsU233ٲe AAAf0lӱc|ZR%^xMq|7222z*6l`ܹE՚q\~^x5kpy=`$==k׮gi&^ynJFFiii|̙3ڜe7I4oq_|#G_ɓ':u1a)ɓ'Czz:/_&""sqq1&$%%KJJٳmۖ[u4ӓtnjq"""""׺|2ޤ1aN8͛7gdffùsL1̜9x>3~Q IDAT7nٌ?Lvͣ>?ٳb۲e 4kBvpuuܹs|7ĉ\z?X3_~_~Lã>JFF eرXkcҽ)픜R$''n8FӁ;of9rwww"""ؿ?jՊ0֬YIc޽,]U8{,gŊdzl2N8aϥKW^n;rkàADEE?;w0I,[4f+WԩSԫWP nݺٰaqqqwmrHIIՕD(WWWRRR,R+Vŋ4oޜ(vs=@hhW\!22X׆9kfo3,lͽYff uDDDDDĶ.]ʅ  dܹ<裔/_駟kqU>ٷoSN`ĉ-Y?!Cxb6l;w6>;ZʬM3ڈ#L ǖr2e TZ]X?> 4;Wܿ 85kyfRSSM]p5jJvM:u*׿x׍ ++WcǎTPrѮ];y_lLJz O>m۶Ѷm[/FQbҽ)픜RQ,5|p۶m`̙booOF6mɒw4oޜ͛73|W1,}nݚ~,{{{+ίܚ0x뭷{epڵ{0 x AAAhZlI`` ;v0kcI`` 4\rF^jr!a#/,T{BŊ "11/~FQBƌ7)]RfMmf\9++m۶D.]ǁ;Hy5lФؖ!Q_xްGA^zaÆE޽5k۷`v999&W\aӦM F\r%߸|Ib/u/@rxbŊ&V^ͭ[>|q;;;OŊyǘ1cn70y^_ɡuf0n˛ۂ pvvf,XI&QbEVZEٲe 5K^DDDDDD+SLppxƌ̘10]O5K^'O4~x"&LѣfrorZhaR7ɉ3gp95jd1nܸAʕ-/ίܚ0hܸ{ժUm[mĒ={-[:%%Ŭ&M#;8wk2$|޹s'ׯ_7Wy6ĕ;<ժUeҿˆ{ݻW2vXcB5TRŬPGDDDDDlȑ#8;;Xcǎ_~Ge͚5BgY?nݺbrA<|w]b@ʊA@sbvv]3f #44I&n%s_*_?,_믿ξ}رIƒ!9fƍܼySNz%9wcx#ΰLIڵ+pg"))ɸzΝK'NpQϫC4hЀ#Gu;0gRSS 88{ydggGffYŒ5ڰЯj֏[Ƚet޽V]СCIOOw Pv8^°dŊ1|?Ç7_RLٸq#DFFRre fR8 C,YG2}tׯJ3yWy&#F ++cwp\""""""" SrJ)Q)~~~4lؐ$Nvݻ7V|L0Xא1uT<==>|8?c>|8M4!55cҾ}{FIӦM-иqcRRR [ntЁ#Gw^uٳM=62o<:wl12$xyyѷobǘȑ#qqqٳӾ}{III/`С.?mggСCQFQV-xgԩJBΝ+ԯ_mۚ^i,k(+D ) >YYYf###3[7$)) ///1,1$KNNΎ իx l7 UV]`ݢr/TP___x"C5f8 +1ܹso޼irnĉ?~CtRƌCJJ _ȃL)DdÇFʕ gggZ*]ve&AL8^zQBqssc֬YƷ֭[ٳzٲex{{SF ٳ'AAAcY&+W^͍+RR%h"P|yk&L7ժUOOOyB$棰|Mի=Ŏ1*Uqrr''' ˩Zju7ojժ<3}gR 7o֭[֫UaaaՋ*U@f͘={vYL I ʛTcͽݻ7+V$66֬X*WLϞ=K$n)UF\\O= dddsNƍLj#([,3g4^'|B-XreI/"ʕ#,,@Ο?Ozz:;v0&uVRRR0KϫC<㤤m۶BךX>PR\...ϓÇy3gޥK߷nʢE[.-?ŅիWqƿ,]NNNx!6܆"[d !!!lܸzpY q,* [<)5=wP,Z_|xr?2zh:t`ǎ/_!CIXXXD>3ƌÐ!CXv-b]ܭt]vHHH#))bޗZO?Ԙ8;ڵk9q9ʕ+>>T^/?b %[{_k̘1XVZQ\9VJ=ꫯ>}q%KwVw9{,&)=z`?޸ҽEDDDDDDaSlL+ܟ{^{5֯_Aiݺ#+r{R2"""""""TbY[G "r?z'0K/)1EDDDDDDDDDDDDD""}&"""""""""""""RLel<"""""""""""""""""SDDDDDDDDDDDDDDDD)k2;;;[ "R,>>>ADDDDDDDDDDDDDJNtԉH[!"Rl...ADDDDDDDDDDDDDGDDDDDDDDDDDDDDDDrٳgCD|||u"""""""""""""bcJNO:"S"""lSDDDDDDDꫯ2`[!r_h׮CZ[ """""""""""""""".R\p>}PzuoΙ3g0`NNNĔx$&&ˎ?N&MΝ;\~Mҽ{wO*Uݾ-Y#\Hڵi߾=~~~ԭ[D, KqYo5]QDFFo>ڷo՞-}Dp|||lUR$''frok׮b% 3ydkRDRRL:]3Z۰f233III!**-[pBZhqO|X,\u֑Ð!CpuuUVMDDDDDLJp[!bSvvvADDDDDDHR䗜b8.iyvU6ػw/NNNtؑjժqyXr%&M>+vQ9?Yp!cҤIDEEQB@ɭZ_Ec7o;퍳3^^^L2[=""""""""""""""RtelܝrJ-[k׮`ޞŖCll,5kdۗ5kbooOݺuy?~<,ZsʕiӦ|G￳i&[Uꅅqj,6l.\ ,,̆<|rwww/_n,KHH YfѳgOcy~HIIa̙w^|M\]]Yd*_򮮑NHH۶mv<ӌ=GGGuċ#Fdq C !''M_~Ƒܚ m]s璔Drѣ:*T(p ޽}_cǎAڵڵ+TX>vXl;vҥKԮ]ݻ3vX*Wlu{mIaSZZk׮M6&cu1&t1*U9^\p>}PzuoΙ3g0`NNN:?~&M¾R* VҫpZ^ɾ}h߾sܝSJ+?>>>4hЀ 6DDDp9ѣGIOO7&lݺ۷S._LJJ tܹsIKK7qĒLƏϑ#GeΝ#44d.\H2wرcUT^x[8[qz*lذ۷oT[j'e/&$$Ĥ^jj*k׮ڵkL>=s%ׯ_^ԩS&EDD@hhh^ Ú7ߐY;$$$uVxOb^~[ົ,x7صk:p~.\ȺuaȐ!EDDDDDDO)ǵgdR\k!'((-Z@˖-[Bر6 ˚tqNQ^ 64#"""""W+Wwr5l `Er … :X6l0.\@XX #)]O)`3f`ƌ裏)[n\rW_}vzArr2eʔK.&mO_~ϟ?~]v՚~}YHLL4Xrrr9k lF/ѣѶxbўФאߓ'OܹsX;wGDDDDDZ˶{wՋ?tЁo|fnݺa6֮]ˁݻ7gϦ{=z K( IDATzz:O>$fbС899o>&MDff&p^fŔS_khI7z}]ԩ d߾}̛7ٳl%C^6Gyggg6l`$CIe8af0\(**ʕ+9se˖a25>O?1n8nJII /_fL:ψ#,~!eee9r_SCb/{kT?2uTk8pMݻwS^^NQQs1ϟ?9un}Y^,X@AApB| =u]=zfK,AAAv[dee/ӹsg<<<#//>f1cX%gl۶ zO ݺucmv-v_|A^Yl-W謮!WCycfϞMPP+\]CҥM_˶>"""""""R7UNE4$9LJ`뮻r]tѣG*]k׎g6mbܸqرƌcտM6L6ͪ->>|7v~y7^ cƍ曼v6TCc{kT]moy{{h"mزe ͳ&XQQ!!!v9vǏ:ֹsg!Aaa!V}-4e"5/^ŋoop2??Yݒ|`ay`ذavWyiMm]k҆S_ [TRSGSǁ[Ww=؜טuygϞ˦GDDDDDDD)(^Sxx8`[4vK3f xzzb6 c6ڷoϚ5kx Ãm#rJ׿ҦMsMƈ#pss#$$s6khaojF.]xyѣ_~pqss#(( 2qD֭[W=HJJ"22___\\\eѬ^oo = 8333kXEDDDDyD}Ԭr>/^ԩcƌW_%--^6djh<[5f,cޖYǚmqv}|fikߕ/*"j:GDDa>c f̘a^O5Íė꼽>}:ӧO3.֭[3vXƎ[̚5Yf_}~kTW bvYLj6$n3g2s̺¾8kڶmKTT@qq1L4 z&"""""S^^_~%'Nwެ^ݻw?`q|>|^z5x>???=ʦMY4''llS{xEE݄S_Oc5zuԉ#G_ZUkɓ'9w>>>VΝ;gkSiqbbbر#F[rr2~~~6ȭ![%KpI.]ŋ1L˶m(((:_sqƱc l۴iôiӌaaalٲy1o< ]v={شiS橯s#5z3>CYU8pMɍXAaa!V,k5ST9EDZ{wɓ'd,Y”)Sl&ȭf2WCRRxyyJϞ=YhC \foooXzU_~pqss#((  ֭n ύFBB#F]vcw]fxxxis,33OOO{./SUUU%KII!::˯w[Qtt4R"""""uѿ'Xj|P\\̓O>ɤI0aMɉd~iT9EDDDDDDDDĎ:vhvA"""""""R;%IOOĉ8qtϟO6m-i^&O̒%K2e JDDDDDD֢f*22!4繈QQQ֧ܹ3#Gtt""eȑCDDDDDDDDDDDDDUNifBCC ut""""""""""""""""7Su"99a)9JKKst""$;RRR|FPrJ35rHG "h~CWbWua4SDDDDDDDY{x4S0L5<⮻j93wZZ999׏țHMJJirt""""""" eKddd4yLC޻w/+V`ݺuTUU1j(۷MSDDDDDruu%99a8^[S䖑.++cܹ1???"""3gׯf)"""""b9#G:: igG c2tq8uO?6zhN:ERR#iT9E̙3 ##2 ٳ---%11m۶O?ѡC̄ pss3UVV֭[9qtޝ'x'|*9//3 dժUV}?rJp]vgaȐ!u]RRBjj*wF;b2HMMeرxyy5dEDDDDDDnCq]w5_~ڶFDDDDDDRr[II ǏhOxMrbcc9pv f3Xg竅{VX5k~/_f߾}۷/}ؖ.]JIIUH}={N>m>|yqZ빟~) !77[2|$""""""r#Kdddؼˊ+XnUUU5@{m}}]ԩw&!!ڦڵk9p{&%%={F߾}%==qF{nvɬYXn`]$//Vn_o5;>}^zqFvSO=lslzi3GDDDDDDQ222eee̝;#F燿?̙345%"L&ϵڛŽ;={6AAA+bw۶m,X@\\\֭`˖-F_IKKfĈY%e̘1V[WVV/2;wÃ8<СCtX׮]Hӻrc$%%q)~imќ:u$F&"""""""MAH?~>}Xs=6};auaԩSy!''zE6m%~F}YlY,}DDDDDDYr%\p]30d~%%%$$$}vΜ9C0`'NgIIMMeҥкuk}QN;$$$uVN8+ݻw''缼ȑ#F'OBnn.f٨,j1i$Ν;Kذab ֬Yc|2c߾}\xkƿtRJJJDnu駟RZZJHHͱrssٺukȭAHu /ҪЦ6m"//'77ת7Æ #115kYtib$\xh^;ص YH;pizƍٹs'O=ff9B@@fݻw?f6cw҅7ύ7n;wfΝ̚5 u/Xɫ֭ټ7k;;;={ڌkiA)Ro `|TTT~}+Wp-[d"66O`2x)--;$00WWW%IJeP]ڵk~HYYG!>>ަ_Xd 'OҥK,^dHdd$~Mg} x %-- ι--*X|:[?\bn{jwn|h:u*[&''o5 ̥K%{={///c6KirW#h׮nnn]ﺊHȭm۶̚5>oooOӯ9a6lX} ߟ 4xmEbb"W߆gҤIFei{>L^jw}G~~>ў_68g};ҥK>|xsrr/ Çmɓ;wcΝ3Hˡ)"!&&;l%''ǘ1c -_,Yɓ't/d2SO,.X***(((`…@㶅}'0Lrwدrرki?#G7ѣGmƵ5f iT91LM2BVy;v,,_6m88:ij>,۶m?o|a;v[ܹM[}İ`mHڵٳDDDǦMj3,,7oobӯmoAaaU@uDDDDDDDRt2yd,Y’%K2e5izyyy7  WWWzɢE2dˋ$"##___Fիn̛7=z憛ݻwgܸqkF3f u9m4Fm݆!!!̝;moAff͸xzzc5x=DDDDDDDrrtd)))DGGc5."r+0]DDDD.d˷j* '|I&1aG<999LTT"""""""T*MCǎc̘1LDDDDDDDB+G """""""ҔL&S{jIݙ?>/"cǎ ==˗ӦMG'"""""""7SDDDDDDDD䦻{7i{eŊ[*FE`` }qEDDDDD9999:FQq< Fqqqڵ ___^}Unʞ={HOOgܸq\p?O۷I 6,)V߫w䔦X2Νˈ#ߟ̙CYYu/"""""""""""""".%ܢ%OKEff&۷g :₿?ʕ+\Ib$LN)--e޽xxxAnn.Vꛜ8uO?6zhN:ERRMGDDDDDDDDDDDDDDmB}g_".]D cxxxzӧY|9YYYѽ{wyfϞ `UqoΙ3gС `ĉxzz,I4 ̘1@VZeY%To(--%>>;vЦM Ĕ)Shݺ9999,]͛7ӪU+"##ܹs,Z;wC=̙3i۶-6m`ر]QFQUUE=֖RSSYt)nݚG}Sn$#yWz_k m۶瞳jkZO4sqlذJN:m[hh(۷o'++HN(--ߟnjƬ{yy9VU\N8l+V|ҧ~JiiKu!!!uV^EDDDDD䪗^z %˔Zݓ[KZ IDATPPPlf޼y5zbΝ8p&9Ų孛dgg[%߿!nԺݻ+Vn:5jh[&tdggk.~m233k=/99Ǐlf$$$MjXf G! 蛘?f6t֍l15Sz{k׮ݛCZZ}%77tzi3GDDDDDDV8##Á@\\vחW_}[g7n.\OǍf>r_mn^VVܹs1b~~~9s(++EDDDDDDn%JNEL&w_|A^Yl-V<%I"..>}Jpp0s̩W߻ۨ}vsƌcLC+t wwwy %͚5;777ٳҥ [fرF8 е9s&;wuó-g9uWLJ=z?Z1m6,X@`` ...t֍eC75uժHSy,'++Lڷoի:t(۷?˕+WXre`ϭRZZ޽{gÃ\˭79)$%%q)%ѣGs)nz<"""""""m}ZӧO3m4}˗EYYݻwg1^Ш^qoΙ3gС `ĉV$f̘A`` V2l^N9Wii)ر6m0h LB֭aҥl޼VZIll,ΝcѢEܹWWWz!fΜI۶mشicǎuQFQUUE=֖RSSYt)nݚG}Sn$Լ˄A~ؾ};yyyƶMNu/--%11m۶O?ѡC̄ ^ )))!55j:vd"55cڽir͍R/tԉtޝ "##5Wͤ ''zYWVMiȹp59;]$O>?~]v՚~}YHLLťkj|=zٙ"*++p%/YYY='''[4fJb0밷Ɩ 4zD'On pE&LǍ"#1 .sq9RRRl6$,]Z?2k,v\MHII3gZ[x17n4$ /G\t>ggg^}Uc6mۖ{Ϊk=i$Kذaqm@qq1=:ul edee)}/X4fˉr f3X¸O)--5b.$$\n=ȭL@999fNСCWTT=端j|vw??FD8 99nJVZEUUmֵk׮Ͼ}wVzE'??rtR~ amڴwOnn&f#"""""(p5#;;]voYy?~f3w&!!nRÚ5k8rFD9|0W9[ndggMB~4233c,VWXX{Ǯ] >>6l@vv6'Nn_kaN7 kݥK6nHvv6ǏUF69899HOc}ڵ8p޽{ž={HKKo߾撞nH,m>"""""""JNivMyy9EEE̙3h?= . … m` 68^Ku ˖27<@pp0?ƍc֭peԩSɡ1u],$$$Ħ*!!!\rlu^C[~8r gΜaٲeL&a&w+%˶PYڪo$"""""rL&w_|A^Yl-CdIO>luWW߻ۨ}vsƌJ ݺuݝoBIuf;͍(0{ltB֭;v,`Ōе9s&;wuDGGӖdKɿoN:E`` կ/Eу~o֪ƬmۀBqqq[n̟?-[}:\Mɲ/iزe c޼y6Nj얕O>cܸqu9vVEΝm]v={ox~7-oXmQصK^ؼy3{j/͛*&MNƍcǎ0fmڴaڴiAaa!V} %+HOfڴi}zqmۖ()..6"/..&??I&Y'"""""'Lv8rqN:7W_??FW_}eߟ|~=????s17ٲe 2[dժUTUUk]vʑ#Gg߾}x{{ӻwo~z}瓟Oyy9]va~~~=zM6]wɓ'9w>>>V,['liT9E =&SYYɷ~kؖ0cǎ$''ml $"""""Hw寮"̙c?nK%ȅ RXXHEEc…6}X`TTTPPP`m̖-enx`~'ƍ֭[)))߿SC1b ]X&&&RYYIHHMU'''BBBr f꼆?0qqqqΜ9òe0L}-G-BUgi^TDDDDDDS1 2x㭎kΪHu̟?_|Ѩ:mBq0l¼yl*V5::O>q9GLL ۷oرc?XΝm]v={شiSǸoa6~ax -juի7ofϞ=nP6oLnnq^c[qƱc l^hӦ ӦM3ߟ [XX4.YIDDDDDDV)b9s&ӧOgϞiggg 99خEĞ{wɓ'd,Y”)Sl4Z8} 777Xp"ƺuNBBÆ oUVf"))H|}}qqqחѣGzj|M3f |j߾=k֬_$((ڶm#<ʕ+_jRBc׺.AAAgggZ[gePcS쭻'f(pqqۛ0V^mU exxxi3vff&FU_*GKBtt4_C""hcEDDDDr+{ĉ :4CV"11?x᧸'|I&1a„Drr2QQQv4Sy""""""""Rz穬o^{qp\бcGdli锜""""""""R!CπFI^^ڵ3ݝ瓞Ή'8q̟?f+$յ2͜9Ν;R^^w< utҌ{L<%K0eͧf!\y.""""-3QQQ4~DDDDDDD섆0DD[Ν4Ύ@DDDDDDDDDDDDDDDDZ.UNifvt""-**dG!"""""""""""""f!4DDDDFKII!%%aH#(9EDDDDDDD^x'|a4 Ci0gG """"""""""""""""-*-d2gs,--GddMMDDDDDD˵/99(G!"""""" JNk޽XuQUUŨQ o߾MDDDDDD(**dG!PNNNADDDDDDQHeee̝;#F燿?̙32G'""""""""""""""[d2[III:u~h=z4N"))Ɂh[>cq%:t@XX'OHn&>>m۶Fhh(/:t0kH_Rٶm?:t`L0777qSSSYt)nݚG}Sn=s ?Ƞ0{lk/))!55___cǎL&RSS;v,^^^׻""""""":tr O>/5i7rDiiiЯ_?"##o"""""""r(9z뭷HLLj;y$?_آEشi.]b˖-vZܷX8`w f3Xgg=&MܹsƸ6l8j)..6Ox駔bs,$$\nXEk{饗Ȩ5acǎ?ϳcofrˊ+XnUUU5@반DDDDDDDqO {0k,ٵko66X|9wl6?ڵkwڵ8p޽{ž={HKKo߾撞n3n.]ظq#ٌ??8R\\LNxwؽ{7 |6ceggгgOc6K둑Q_<v}˗EYYݻwgaVCJKKILLd۶mOtЁ3al^9Fzz: <www Djj*<74ޒؾ};gΜC 0'igBB3f 00UVY*--%>>;vЦM Ĕ)Shݺ9999,]͛7ӪU+"##ܹs,Z;wC=̙3i۶q-w}vDjj*cǎ{/"""""""͓Sn5xpbn ~Z{?=_18_ڿ֭[g9cÆ :z~aԠAlIֿ0b쫯ٳgx@ ={/ɓ &%%_%%%JMMwӒ%Kl֚z.I?LZݱw4pQQ>c۷Oqqqe˖Y~4c I׎(6˓$fOs̜S:NZp%^UUeoH:|%IcǎVrG)IWqq\r\RFRSOIu!oom۷o_IҩSl1s2V'5`(88e;wJ3hPPջwo%$$Hnz ,a瞓$}gM^ߜz82ee׮]6DGG['j7|S{xrL&$Ԃ ԳgOuESNd &Ǐ$f^zYc}:0mݺU/ŋm֋Fw}y衇4i$ko%766V{Qaar4wf?Stt ?~[UҵM(ÇWNNlf2bĈfh?;<*FI:}kSRR佪- !{=ݻwFT4p@ڳg\cnh_]v^_ X>}X>\WQQb IDAT!IY39}`rJ;eoo1c]߿.]jiظqU+Ν;OovZAu+JNNd`M-quuպu!jъ;v<<V\jo>͙3Gيhuu 2?ry___;wNZ386&CQݕf`054.]"oҥKmrG)IWqq\r\RFQqqq\Q@'Nбc_BÆ [˰aԳgO=zT'NhuaaaD^ܖm~N扫>֒q] z5uTI~smժUrssspu[TTo߮^MjϞ=*,,777͝;G0a qIɓoxLN4yd;k֪zcbbk.>}ZӦMZ ݊ϵe˖fRÇWNNlVTT$e 7qGѬY|r-_\g϶G-@QPPpcݵn:{UΝ%KH\]]-JNNd`T쬋/j۶mֳ>dƍmۦ~Uzyy)%%E󓳳4e_窫k1vXyxx(77f-77W2}`r]F`ܶd2d29 @p}iV2IRnݬzWꫯ61c4f̘fݻw[9vUӼy~o\z(~=d2)))I $ȑ#9s<<<&&h'|*]zU}z-I\Vݻ+--KKK`9j }LN3D˖-Ӳeˬ|||4c Uf_{vswwWBB^~eM:UUV9txS``mۦNuuu5l0M>]~~~.J{NxG4k,-_\4{l;*4Q.Z,++K&eNNN2Lz @M8e@L8QC qt&1 ut)mLzz]dRZZ`4Q.Z&;n駟]Z6jĉ.Zl͎.Ȑ!ChLtߋ]Fs h̙9s8 )hF$͘kַ~=5j{9yyyh϶۷ݵL8p@4tPEFF)S[T[[k߾}VB*99Y/VXXc l^{M999vv>իWkƍjhhФIA9Rwt hNAӸd׾}>|v~A6m?A_UrK.iѢE`$M0A .TVV2 Bc p &N@GMќNݮ ܚ{*77WwRSSgY׿Ck֬њ5k:+%%Eϟɓ-)S?VJJf͚tDsќ9s]nS:/BYYY*..˗խ[7i֬Y .yyyZlv)WWWjΜ9֭eJ׎IJJΝ;CݺuO?ӧfߌ XBҥ|I+VS9ѥK4j(-XU喙Z֭Ӯ]T^^nݺiԨQ1c<==-y[l$M:ժ1z&MRCC|A4u_WPP֮]{øt{߱9qmУ>jݻwhTFFN*//[{)Ї~$عs甑*-Yjwޱ4_\|Y[nՑ#Gay{{7;Nqqq:z庲2%''HWվ3gTeeeO?TW^U||kM$ӦMSii۷ŋ-~O555z饗tI|%''[yIo=ܣ^zHҊ+T]]m8~'ޱ=jkkb|رC/bб9<,I?o>O$ݻWV,={V6lhQ tQ=JOOA)??_6S6mR^^M&Iڽ{e/JKKգG}Gڿ֭['N=_^'OT@@~%%%_%%%JMM䖗KZ|[ѻwo45w|d}ZnX>},]bV <=nٳΜ92~ x<==[\f;$yyy٬c9I))رcѣqGWddݽ;wk`nXprs+`gozsNl{6޻q=̙3ڷo S[Ud"]\uuu7)wcγwսw'S:H#I:yeުꨠÇK~_}+ANҖ-[d0n#G:y:K{ב#G4dKȑ#dUO?[*--M<>^kתA>1SN6UM5i;չsTYY)___JK7b;UWWb-\{UTTz>|Xcy+#G$ǫXW\QyyV\)Ѩf?SO=%IJLLԡCT__oVov2 YXXzjҥ#FXr `PllvءjOo+>|""",י6oެK.ɓZlYk6<|d$Wt)|s̜=LN´uV-^X/Y/..>r})66*硇ҤIlXٳGussܹsL/tq͘1;vƉ[]vӚ6mZ``MlٲeZ`~#GԿۿYsM6/IVᆬ;QEE&L -[hQQQSko1&S*((oh̘1rwwﯥKZ:6nhb so~]V6{Je2d0,ooo)55E6\]]n:EDDG=z㛽RRR)???9;;OSLQjj>_^//s=z'fܬ;w"""ԵkW*$$D-jqfw $]kPnnM~nn<==5zV?"f銊?Cwh64ڵk͛7+ @TZZ^3g\!ڢ(IRZZLNФuݪ --MH!9@ݕlLJHH9:;m#}ZYYY.Z%++Ktt&Q.Z,**%h#;1s3Wb+33S$ :T)hs>իWkƍjhhФIA94L6ҥKZh"""d0 &h…t钣DsJ;e4-t$))):&OlM2EϟWJJ+->?5k(//O555ի~gij[NvRyyuQFiƌ]zU֭ӎ;TVV&G=y=kkk;wu릧~ZӧOս322裏޽F2224uTyyyݦ4S: … XII/^+WhvK/'OZbΝSzz󕜜,Iի~zKO?oF|.^(IR]]tQKnYYUTTիW?\ -$$Dڱc^|VsX裏>҅ CiӦM/ /HoxuI(99YWRRURRTKM$I|߯/Rϗ$mܸђa=zT?uAeffjРAWvv%7//Oԯ_?1shhNi'F՟{$ UPP=v-I׀⢁j]vYrTҔ󟊈PAAUΝ;%I zI֭[-Ǐ$Ӧ^zYc}:gJ۬JKK%ICM6M&InnnӧOK޳򹢢Begs@@sJ;QPP`<%q\:ut[}Uؘ1c4tPٳG}kYF6lٳ/JܻƦn''ہ>~6pgqOtKJr+%IG Õ+&&FUUUZb%|͖-[TPP`'??ߒ+I3hᒤ˗ܹs|}]F 7.,,LB׫PK.$1’sh4O>QmmxI\\\,y#G$ǫXW\QyyV\)Ѩ8KSNf5"XΝ;UXXqYwu111ڵkN>iӦYZbbbe˖iٲeVϱڳg m榹sZ>\999***C$Y7)X{|}}1cK...ׯy=37K))))S(55Uޖ &hz*WWWGz뭷,yJNNd`TI(cǎrssmj͕Fݒ)̱ҵkW͛7Oͻ=~Pxx k͚5\=uU=rwwSO=W[]]{O>qiŊ3_{!5Jqqq6jkkxb=c3fVXzz4j(]VTYY (44T#GG]xY222裏޽F222T]]}K wEM>]gΜĊ`ܺ:ѣXYYUTTիWɩ$?^ mٲEӧOWNnK555z饗tIKܹsJOOW~~au͊+T]]mqϟ}I֨z͛7*wզM,?+ @YYYw{e?Q矫V!!!6 Q~~vء_|ٵ09JKKә3gd߿_֭ۜa=zT?uAeffjРAϷL>)((\SPP`ٳgx@ ={*_^'OT@@%7))I*))Qjj5{V^^,YbsI?Oeff*77rݻm)**}Y&,[LO3fHKuyyy~ishhNi'4>z^<EZp;;w$%&&*((Hݻ$I[nim{Ng5y}s굗;p@˔]v\-WWכ>=oz-wwww$͘IDAT?_<\]]e2$I?,X={K.:ukG?~\ԳgO={e@{ı>ЩS$I>}Zҵcx)))i^Ֆ{OMݻUSS#OOV[ZZ*I8pU|ٳgm17y/K]J^j׷o_ӧ峻u$///5s̜@{DsJ;󔔦ihhީS4VSSUWWdΏ?۷+""ɼ[F5tjJsҥݸSÉh/k{9ѣ믿֯kK믿5 :uꔶl"{YjBBBlۧ9s(;;)ͩ_9!CXGiӦYnEڲeKhÇ+''GEEE Z+**Բ &S*((u)<<\{:w -YDjTrrL& 0ZMx ggg]xQ۶m}&k7nm6OK))))S(55U޷%IJKK])c=&ѨO>DUUUz;[;Bk-&&Fݻw?d0lZp=3Ol2-[jG3fpPezo7www%$$_ԩS%IZj\CsJ4o<j۶mTWW_Æ zGyDf%IgVpphN逜d2d2]-io)@Gqќ;1]싌tt bYYY2L.@6&00P'Ntt*'NԐ!C]6)mLhhBCC]mAsJ(Gf228)mTffK)mĉ]͛]6brJuqeY233uIСC=@hN^{5䨠ѥzÇkڸq4i$iРAR`t@999.ᶹr%-ZH2 ׄ pB]t6T nvh4h4:v!%%Eϟɓ-)SJIIq`et|4t07\b|!5Jqqq69WIIf͚P=Zt~AOjС$>Pxx k͚5Guu222裏޽F222T]]} Z kŊjh3gRte}駺z%Iх ,הhźrƏ/Ids甑*-Y5)..NGʔ"^ZNN>s*$$fkǎz[>@ӘX}$[yyyM64gϞڴi4m4Iݻ-}.\zH6mҗ_~^xAl%IW^^ۧ?O&eÆ :z~aԠAluyyy~<9fS {G؋7nFi,::Z-c޼y $EEE)99YUUU{Jx K^||eٗ_~;vL۶mӉ'W_IjjjaΝDKt^[n?/I:~kM5*~4e -էOgoooIիW-gJ>.\ܹsu1&=}$)<߿"##oz͚Wb+sVkGs]SNjhhŋ)zHs_衇aށ$I$Sp0L2L. 9w )c:;ؗŲ4qDG 9tt FsJc2d2]mAsJw^Ze@jΜ9.99X;}]JVV<2LNi233]XTTKF09w )c8M2K۷oZ,33S$ :ThNAkɹ#ta^Z7nTCC&M 4ѥ!М&5nBɹc{.]E)""BA4a-\PYYYrwwwh}tN.-c4oxؗkɖؔ)Sty82:S:h4*66*/Ѩ;wZe4cKˡC4j(InqsLmm>kذa?~֬YV?^%%%5kBCCOhҥtUnyy,Y'xB!!!ZpjkkmVFF}QYݻwhTFF[];w;S:ѣGK;fՐcI7KBgϞBCC-+Vڪaf>HgϞO?2%''W^իW[h3g*??_/_Vee>SX²^]]iӦ);;[oZج@ќҁ Wҕ+WtIR}}v%'''˒"IүkyxxXݻd >oذAG?t},%Ƞ3gH `um$yyy٬cr49S5x 8PО={4dhڻwjkkuQ 4H>>>V6wj$5444^SS=qqq|ԩ h\Oζ;924)И1ct}GxBCC%Iן'RANҖ-[d0n˞-ѣGz:w*++kVYYic;6O|$?$5{o4Q>,M.*..֕+WT^^+Wh4*..O=$)11QR}}[6}$:uf3crJ`o߾$S/3glєUTTh„ 2 ڲebccg*::*MsεhwdQS_1c%>vX&Ç+''GEEE Z3OZ1bDl19*((hyc̘1l,STZz믿9;;NdL& 9;;[aaaJMM&jݺu\]]5zh;V͵Y͕Fs km0 ^@\Al$HHЄ B! 6"EF g?O6+9O1f-꺎_3\.qcXDDf>v]Bu30hmxz|>y"0Z,]Eux83uͯ y_mHr'Iz^lQ ޙ;dczL]2 u'qDQc=&l?,{~K]*;N:lҭ}KhPQ̰ cj=_=!vUn߫Šc;D2Ќ[섈<a[~eԢ0 2 F6@lN 6'A$۲ֵm2xJ{+1@!ʋJ$7n]F:](`j^s͹ ˄슢p6b}1Q0촟F3#"Ks;X#[Jj)314lėo1۱P] Z~ 6' DKETǩМƏs>M4I7Z ǭ;5V{HH-nh<0wG&8bp>ްF|<#2@lN 6' k=Iy_>_lWpu*iϫjdV׫;VzlU^Z3nX,ԏЄ42\XrMbƖ2-hƴ 5H$ xuF{ͳ.^ȧǺT.U)7L{/sdWL8]i)NI(qGuկ+ r*q.G]i=pkT/[A؏89quHZp\]fzbp8hTLWG/j jDqH1U#}W C_^GKbOGȗ"3ue7"8;Ĉ,㐵 2؜obDKڇBCbH~#rTNFd+60@lN 6' bp8@lN 6' bp8@lN 6'i}<XjWD:H'fY` ~?]bp8@lN b-8e6v+珿P{bK4b]?5q m*m"#1ЎAOo 4!-"O۾V"j`dp8@lN 6'x9C_y[! ʣAl9ƜC.OkFt"aCj* D}i^ZP]o[GDrIhb뛴Q%6U0I͓z<e.x?/|?_]xR bp8@lN 6'j_j2!@&{\k@lN 6' bp81^lW|HZ5m$PJ}8"'V>~-3*b1qpƏl*"ޕSwh a=~vSRh5n( { :-{ EVA kRlv'oRs?L44HuN"̼!1ȝD+Q3bK8UӑE楊Db +"GuS-VDEJJlLj@Tl އ7F81^leFdRJ` UeMg3ѯ? bS#~3}Qd}ǘ1úLj&g2ff1#1LzFd 03"c Exr{V5>J~O0"84`Q 2,DF2/*7"pBau˰Ѿ(l}ff9=\eH2e&}*lD7Z>0 ;=6ľ ʈܯb_"2"251 1F 1,x#s-ڧ`‰5[1D+"7ba2I'/2&c+"%:Έ-)2&cȚO#jvwVFLDd Ky P`DX%+0%Ü,Zǔ s2ވ;nu7:#ddySRI}qbJLdD.#bJጟFVR<~JŌ7"ۡl r"e# Y| LЏw4"`Ji|i{V5>J+4`ZMTZ?\'Re*WvXK&-xƏl"FzmAVN@=׭dbz]рF&ЕFqX\(<@Iһ|tI'mNQN% ;wy*|<25Qt:ڦc6=M#U+x'ZRB~(<О͈<qz*7#44zk`O +"H'Ӊb 0'S8HRn#]p`dV~ gS/зxz$g!0F{vr bDFdwolɉY1 PPpc oDN].^YR`Dn bF;| L#@lN,&6@L,>YҮ 3#4=#hmhM }b69eƌzE菩ĚXG4w}ibvǏok΅{~[خFb-Lʚ f"89zXȭp,d6! d93fS^D3ZMh6Y5"ےFߚ `DnPd1#20p82m[[Ȇѩ)޲k2M8*S vCE?| s13g;=Q-0+"o{#KdOU׮|;lNVωwoDw&ʎ|9N2v5':bhN/ ׎9$ʈlWF䧣7z,D ꭒ~Y5qZs#OtTn.:lʅ~6"oSdhGV"~%⫀8TW[ޘVcڪFjwuioznӈluvU_VZJZ'쯴z0"X|w` VF,bpb;`0Vf)roɉ>1GdYӧ/0ވ܄{ޜw8oëu3#3m݂1u6(A˴gڨz1okn"zԺ>?9i,<=)I41+y+ ѓSgmwGT& 3a9M6*֦Nu*eB-q]FhQlfg"#r7W/HgN ODIe{3D[.v2ŭK7a"#rK9U14*ښ_zClWY\Âؒ9G*z"ˈE#DCF?U+mF*R|qω\D~ vKM4)ܤb Cy-oЈ#5n RV-W FdscDX%+@lN޳=?}n 뗯-3L#@lNTLVkbp8@lN 6' bp8@lN 6'| J?t IENDB`PK!XV00data/File/design/md5.pngnu[PNG  IHDRچ IDATx=䶡.`֗(`hԁ:CB./NOp @ &A[4?H!|g9M$?h?Lifo> [y1oĝ[ c`}%}}{)*R6^¯Gw~{1>줺_* ~{|[Ȼ;.~`o"!"!"!"!"!"!"!qSqm _jy[W9_$| ! `Wg锸}fp hV~k.' Ϭ?S֎!U3 ip6ԅ^IЎ]I`?h7Nrw<\?<}?k{@C?4D@C?4D@Cv 7ۣ}{*po,smwT爮-;o[:>'eJMv\r~6oojR`zDC6Umf y)8S^4fU{d- @=P|sk@E~ᇳ___/gW~~s@]~__o{쾟3s[pKf]`zO[؇m2u,``1+٘b ef&0iPb?huy=/9nYSqeC!:)f?ds*]Fn_뺯3ʏA9mu'[]Ԏj{~`U:_rT}Rk'>{fʹ}v/ٲL>>`` eae ~SB }2'H}ho&?TdM  Jn[]P`"x&}&.p /҂)w'-Em8.Y5w˯_=.gK 6wnx|f31ߨS~"/p@6 ̏:ܸC:oR3n_6XX%(ϛYHg|E|xfAS䅒Yt~d%ee:طA~8.$LV~ض\Ս{O>~X_?P2_)l + |!^~h+3e[f`vf~֗ 8z췘L=+ Y`"=/<ѧ6%GwnS%}q:;cY.Effeߦ^gt/1,NMdN4'۹W*Jp>,MpҰ([\'?x*y] ˙uZ|B\tYe Ft"=ExYVק,fSN7+zGژڌx }7])![p,K35&^ڒvԍM9bmMJXP2_A ݷ]XF*fZ |?˩U,[W4a[KW?AkbokÝ"!"!bT?q?q8W    T}7w`%,g W3͞3cĕ٩|<5LU#Xw}Ku_~˯_6zV8C` _=J/k~ӮBS㓦cYݾVc9)<|XmqS>n&ƯKN>>՚KSmd"~{L̛PV2!)?mqQɣ_z80=ScU K"K&za\I>o9~)x塧 lWc% 7~ȿ^WԷ.f3[.exP/2J ٓϿ`MpmItd&՘{q/ 9ޱ.gYY. O׬m _a|_@S+7K]l\nSE%wQ|,PL:|_;w`zG)i/\AMNYV.݉f)mٗՇ8OnХiSW. 빉֒Oc`qs#:>f<0bSoe2fS}7z ڬ ϻfKEw-IW? I6pkp-~h~v{J>k:)o KxL!CӺ8 TiƷ-+˷ ,Խ+Fk?U;%,Sa/u4yFrz_|-LsPTqrd?V_ƋX/YK/m 6 P:t7p<Tj"=xINg:\HɌOsYf[~*x.کȂ=UZA3?c SL˶?7ׄ`N2䨷 ,X cuw+y`x5ly hٲ:$ǿ|rtʷT`ഀB,ғa%;t˅*J XBrD?j`+-~h~jkֶb-n%mOm=F?U; ~ mYf 7KSS(_'^\gJrlBS5$MӍV:F^Vɚ=SKTj"=58&VV~nm3tmٓ@X5~~5DZ`<`WsiS#%L{,$VO,Pdjq"=%_ȧ5{XgZpo遃Ok|ԇ yn[ؖ?4D@C?pyυ|vZg(6.?s|eW^%0e0k$oy1e~xcLIp?U/ʿ,eLd#~d 8j789aчwJFs+StklJ96:$K\Cw&Sv~j!0lTj%s655nˋr^Gcme֤c15~x @2+JZTmn&]%OZPx1*U9O-$>|J>~q%tCu?],]}c%3ilKW?dr㩂>4iZ= C._?WasiԿWasZH4G-E4D~ZU8Q@?mz5}h9CwQ ~ ~#+~< pg|Ԡ{NSOCR~}I}"iV@'i?N)N`{.-Q-O8ԧf)Q3 ܟ@l8Be "30484.D@C?KAE ~ٌ ?7)Ʈ>&/&!E?kƎp c'R;/H}Dsd%?7!J~4F%w%<26'1ܘڴf\Et"4CfDC?04ؐ%!!DX@2F6 ~Eƈ,h,& 56᷈f ~hb4@+N0:?bRk~y` !kb؄n˸ ~ $O4X@ܐԇ)ilKS5-܄ PBwTJ `}($n[~j$v"2%~h.IsOq[plHS;= zogW~<~9x;ğ*36ώ(ztm}opP){@>Ds2wߑ$a'3iLs&p0Tĥ؛j@s ;R!*H}8vg@E1'sM#DCi1ϡ4%A~P4:~hz~`/v@?kԇ: ~v䣿e~P' H6ؒQP9lƨg} p ؆ԇKlOZI}j ~`99r?k:pE-iTN i ~6~H} ~`8?P64.A F) ~hgW!7f?0 *7&? {Å[rZ#o&0nnOF-I}hg6pW~ ̦]p]ogW8قk7y6;д#6aUt3v vI}ք⧔! ~JI}5qz )p4ohv>-e $c4c2ꇛD/ۻÿnt.?)_<3u̾/k2U=Ԭ?2IN.4>cW-˸ ?BnCmC?r3Si{%7of*% |AmA3zA S{ /^ ="s ~`cɴսk wQ 2䁗W3ŎYNeK~s ×ݷ f~|~̾s  9\ԧ6иWw?بsw7{}4u,#>>? /-mdw'&_BO"fri('gdݷ)'3EI}`u'&;I}`.ą&&+*F=?@.؎r>n?7N;u’Z\].6΀X6Zʹ&SRsr6TR=i1B.ߤq(pB?pGe>w?__w?օ";!QrUԐ+uiBR{L:63܌&D[>7HN2~r,dr*“#EJ*p[Z ; ooICQ,cS\~,zǺ->nƍBڼ?VqGfwkXvz/8.W͔9.yrM7%'/ 6H3~ Ŧ>2g2 ,y`Gp=pKu ~"=HnaH,}A܃Ci Ϯ ~ؗa@ULC>~*HGfZum8V3bqbXO? \plWΫ؏~hJkv)}2eA^jےX@w,?ɷe}Mؐ/<;ZCƇKog˩B2z#pLzO Q[y<.3%y3_mIDATAAfP۩!0uN42rJJ;ZoWdGς;(_l|>:uAZZo w>hʬHH˂._JΝ(e}6}iDf݊Sx; ]Ɇm}rq;f{'5T65:`*1dk~+ses`,떀 J|.g_Q]:f;Α,Gr93?}Ꮒ}X`49w*K}} ,~,ϲ<(7#n,߷ 3ٟf͊;[HO7hEɿwsGax@SϔYv]>oٽ:/Zp3`[a u_&0Y2 [kaSؠaW]g`?떮)2ݖ7L >G8̂Kfɋb/_όקȌM\F 2ݙw3ֻ,mz/+p[MoC?+@)V{O@oO6=j%mꥸLۏ֛yveg=˹&#v}opЊK}ؕ&CkrA7",p]u&VjpQK$ !A'%Ex>O8{++{g̩G^ f V[[8E{WZp34Uh=740Oח=ZZ_])'^J+h[h5{eZ^W͝ϤvZP Y\~}ߟ]hNԘb?Bɭt3uhLwY8k4V,84Fs"ȃA%[N}O>@Z5taݩlVBOP+k>iC,Zԇ [N}j˒g 囚xт\Ez*>8Ezjd#k$I0-?CjjO@C.{㗺9.{@s"nπ v1(!g,S޾O{30z/X'^mھ/3>DO8Pj~3r36qf_ l<@!]l\ؙP>?3UM}OLhE@C?4Dõ"0g0ܻ0 \E@C?\ b%?7k~!~F1-Ҙ>`jg?\As؄$@~Rϝ 2 %xx<7UslKss`Ls[5w/pEs[_׼{~lÃjOt"! }`sogWvwȏ[ -N? DP>`W<3VEӜ SIC8}\̆]ao[%@Ls=_*\ۻgW~h?O>|pnMzh@C?4D@C?4D@C?u~(e ?3o?%_5lP 1N<|L7M(oπO>EgFÿ u?߼k\x=[x^"!"!vvd;wo_<훚 ?|Y;s%'- f?2{6r7~Wr=a} }U0>8Z|@C?4D@C?s)! ?wp@5|8Q9<-܀ڶZgLmH[.ϵm85 P?~;uX*,i?EzH"=[-!Hu !"!"!"!"!"!bͺK ~.x<|ܚ\~hǣ!"!"!"!"!"!"!"%*SHìTIENDB`PK! [oodata/File/design/file.xmlnu[ Enterprise Architect 2.5 Package PK!\"data/File/design/class_diagram.pngnu[PNG  IHDR @ PLTE\}tRNS@fIDATXMn0 GqE|xѮkCBI% bXD}9>7f'FnG=]A͸o  g|jbVM'[Ć~u ]2ƕ1xf9 QhB$c+gʀc-=U2=X8iL2hqsCr*#af _bWea " -Og8iZSڐjGL*yg_k cäLdJSğ}dD}F"lAH܋09DްAö`$o ۛpFơZv(=r2|P|̗+O_q3ނ`[4x%RIENDB`PK!oi.channels/components.ez.no.regnu[a:7:{s:7:"attribs";a:4:{s:7:"version";s:3:"1.0";s:5:"xmlns";s:31:"http://pear.php.net/channel-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:75:"http://pear.php.net/dtd/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd";}s:4:"name";s:16:"components.ez.no";s:7:"summary";s:24:"eZ Enterprise components";s:14:"suggestedalias";s:3:"ezc";s:15:"validatepackage";a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:19:"PEAR_Validator_PECL";}s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:24:"http://components.ez.no/";}}}}s:13:"_lastmodified";i:1709505579;}PK!2".channels/pear.symfony.com.regnu[a:6:{s:7:"attribs";a:4:{s:7:"version";s:3:"1.0";s:5:"xmlns";s:31:"http://pear.php.net/channel-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:71:"http://pear.php.net/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd";}s:4:"name";s:16:"pear.symfony.com";s:7:"summary";s:21:"Symfony2 PEAR channel";s:14:"suggestedalias";s:8:"symfony2";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:4:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:29:"http://pear.symfony.com/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:29:"http://pear.symfony.com/rest/";}i:2;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.2";}s:8:"_content";s:29:"http://pear.symfony.com/rest/";}i:3;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.3";}s:8:"_content";s:29:"http://pear.symfony.com/rest/";}}}}}s:13:"_lastmodified";i:1709505579;}PK! ~%.channels/pear.phpunit.de.regnu[a:6:{s:7:"attribs";a:4:{s:7:"version";s:3:"1.0";s:5:"xmlns";s:31:"http://pear.php.net/channel-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:71:"http://pear.php.net/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd";}s:4:"name";s:15:"pear.phpunit.de";s:7:"summary";s:20:"PHPUnit PEAR Channel";s:14:"suggestedalias";s:7:"phpunit";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:4:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:28:"http://pear.phpunit.de/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:28:"http://pear.phpunit.de/rest/";}i:2;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.2";}s:8:"_content";s:28:"http://pear.phpunit.de/rest/";}i:3;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.3";}s:8:"_content";s:28:"http://pear.phpunit.de/rest/";}}}}}s:13:"_lastmodified";i:1709505579;}PK!t.channels/.alias/ezc.txtnu[components.ez.noPK!\.channels/.alias/symfony2.txtnu[pear.symfony.comPK!TY.channels/.alias/phpunit.txtnu[pear.phpunit.dePK!܄#.pkgxml/Symfony2_Security-2.4.3.xmlnu[ Security pear.symfony.com

Symfony2 Security Component Symfony2 Security Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 HttpKernel pear.symfony.com HttpFoundation pear.symfony.com EventDispatcher pear.symfony.com Routing pear.symfony.com Finder pear.symfony.com ClassLoader pear.symfony.com Form pear.symfony.com PK!'Jz++.pkgxml/symfony2.xmlnu[ pear.symfony.com Symfony2 PEAR channel symfony2 http://pear.symfony.com/rest/ http://pear.symfony.com/rest/ http://pear.symfony.com/rest/ http://pear.symfony.com/rest/ PK!^\F[[%.pkgxml/Symfony2_Serializer-2.4.3.xmlnu[ Serializer pear.symfony.com Symfony2 Serializer Component Symfony2 Serializer Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!$n77&.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu[ ClassLoader pear.symfony.com Symfony2 ClassLoader Component Symfony2 ClassLoader Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!n++.pkgxml/Symfony2_Yaml-2.4.3.xmlnu[ Yaml pear.symfony.com Symfony2 Yaml Component Symfony2 Yaml Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!}3YN.pkgxml/eZc_Archive-1.4.1.xmlnu[ Archive components.ez.no The component allows you to create, modify, and extract archive files of The component allows you to create, modify, and extract archive files of various formats. The currently supported archives formats are Tar (with the flavours: ustar, v7, pax, and gnu) and Zip. eZ systems ezc ezc@ez.no yes 2010-03-22 1.4.1 1.4.1 stable stable New BSD - Fixed #16030: Archive calls posix_* functions even it is only an optional depedency. 5.2.1 1.4.2 Base components.ez.no 1.8 1.4.1 1.4.1 stable stable 2010-03-22 New BSD - Fixed #16030: Archive calls posix_* functions even it is only an optional depedency. PK!b88!.pkgxml/Symfony2_Config-2.4.3.xmlnu[ Config pear.symfony.com Symfony2 Config Component Symfony2 Config Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!$v *.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu[ OptionsResolver pear.symfony.com Symfony2 OptionsResolver Component Symfony2 OptionsResolver Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!tWYnn%.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu[ HttpKernel pear.symfony.com Symfony2 HttpKernel Component Symfony2 HttpKernel Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 HttpFoundation pear.symfony.com EventDispatcher pear.symfony.com Config pear.symfony.com DependencyInjection pear.symfony.com ClassLoader pear.symfony.com BrowserKit pear.symfony.com Console pear.symfony.com Finder pear.symfony.com PK!1ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu[ DependencyInjection pear.symfony.com Symfony2 DependencyInjection Component Symfony2 DependencyInjection Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 Config pear.symfony.com Yaml pear.symfony.com PK!=4 (.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu[ MonologBridge pear.symfony.com Symfony2 Monolog Bridge Symfony2 Monolog Bridge Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 HttpKernel pear.symfony.com PK!-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu[ Routing pear.symfony.com Symfony2 Routing Component Symfony2 Routing Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 Config pear.symfony.com Yaml pear.symfony.com PK!|g$.pkgxml/Symfony2_Validator-2.4.3.xmlnu[ Validator pear.symfony.com Symfony2 Validator Component Symfony2 Validator Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 Yaml pear.symfony.com HttpFoundation pear.symfony.com PK!d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu[ Locale pear.symfony.com Symfony2 Locale Component Symfony2 Locale Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!*OO.pkgxml/ezc.xmlnu[ components.ez.no eZ Enterprise components ezc PEAR_Validator_PECL http://components.ez.no/ PK!a.pkgxml/Symfony2_Form-2.4.3.xmlnu[ Form pear.symfony.com Symfony2 Form Component Symfony2 Form Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 EventDispatcher pear.symfony.com Validator pear.symfony.com Locale pear.symfony.com HttpFoundation pear.symfony.com PK!F%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu[ DomCrawler pear.symfony.com Symfony2 DomCrawler Component Symfony2 DomCrawler Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 CssSelector pear.symfony.com PK!?4 %.pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu[ BrowserKit pear.symfony.com Symfony2 BrowserKit Component Symfony2 BrowserKit Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 DomCrawler pear.symfony.com Process pear.symfony.com PK!t8 %.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu[ Filesystem pear.symfony.com Symfony2 Filesystem Component Symfony2 Filesystem Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!>tBB&.pkgxml/Symfony2_Translation-2.4.3.xmlnu[ Translation pear.symfony.com Symfony2 Translation Component Symfony2 Translation Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 Config pear.symfony.com PK!oA A .pkgxml/eZc_Base-1.8.xmlnu[ Base components.ez.no The Base package provides the basic infrastructure that all packages rely on. The Base package provides the basic infrastructure that all packages rely on. Therefore every component relies on this package. eZ systems ezc ezc@ez.no yes 2009-12-21 1.8 1.8 stable stable New BSD - Fixed issue #15896: Autoload not working for all lowercase class names. 5.2.1 1.4.2 1.8 1.8 stable stable 2009-12-21 New BSD - Fixed issue #15896: Autoload not working for all lowercase class names. PK!3'CC).pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu[ HttpFoundation pear.symfony.com Symfony2 HttpFoundation Component Symfony2 HttpFoundation Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!.pkgxml/Symfony2.listnu[pear.symfony.com/BrowserKit pear.symfony.com/ClassLoader pear.symfony.com/Config pear.symfony.com/Console pear.symfony.com/CssSelector pear.symfony.com/DependencyInjection pear.symfony.com/DoctrineBridge pear.symfony.com/DomCrawler pear.symfony.com/EventDispatcher pear.symfony.com/Filesystem pear.symfony.com/Finder pear.symfony.com/Form pear.symfony.com/HttpFoundation pear.symfony.com/HttpKernel pear.symfony.com/Locale pear.symfony.com/MonologBridge pear.symfony.com/OptionsResolver pear.symfony.com/Process pear.symfony.com/Routing pear.symfony.com/Security pear.symfony.com/Serializer pear.symfony.com/Templating pear.symfony.com/Translation pear.symfony.com/TwigBridge pear.symfony.com/Validator pear.symfony.com/Yaml PK!8.pkgxml/phpunit.xmlnu[ pear.phpunit.de PHPUnit PEAR Channel phpunit http://pear.phpunit.de/rest/ http://pear.phpunit.de/rest/ http://pear.phpunit.de/rest/ http://pear.phpunit.de/rest/ PK!u&6%%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu[ TwigBridge pear.symfony.com Symfony2 Twig Bridge Symfony2 Twig Bridge Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 Form pear.symfony.com Routing pear.symfony.com Translation pear.symfony.com Yaml pear.symfony.com PK!UU__".pkgxml/Symfony2_Console-2.4.3.xmlnu[ Console pear.symfony.com Symfony2 Console Component Symfony2 Console Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!kb*.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu[ EventDispatcher pear.symfony.com Symfony2 EventDispatcher Component Symfony2 EventDispatcher Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!sYY".pkgxml/Symfony2_Process-2.4.3.xmlnu[ Process pear.symfony.com Symfony2 Process Component Symfony2 Process Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!nJ/J/).pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu[ DoctrineBridge pear.symfony.com Symfony2 Doctrine Bridge Symfony2 Doctrine Bridge Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 Validator pear.symfony.com Form pear.symfony.com PK!A~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu[ CssSelector pear.symfony.com Symfony2 CssSelector Component Symfony2 CssSelector Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK! v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu[ Finder pear.symfony.com Symfony2 Finder Component Symfony2 Finder Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!܋Fcc.pkgxml/eZc.listnu[components.ez.no/Archive components.ez.no/Base components.ez.no/ConsoleTools components.ez.no/File PK!\ \ .pkgxml/eZc_File-1.2.xmlnu[ File components.ez.no Provides support for file operations which are not covered by PHP or are just Provides support for file operations which are not covered by PHP or are just missing. eZ systems ezc ezc@ez.no yes 2007-12-17 1.2 1.2 stable stable New BSD - No changes. 5.1.1 1.4.2 Base components.ez.no 1.4 1.2 1.2 stable stable 2007-12-17 New BSD - No changes. PK!IZ%.pkgxml/Symfony2_Templating-2.4.3.xmlnu[ Templating pear.symfony.com Symfony2 Templating Component Symfony2 Templating Component Fabien Potencier fabpot fabien@symfony.com yes 2014-04-05 2.4.3 2.4.3 stable stable MIT - 5.3.2 1.4.0 PK!n#)v>>".pkgxml/eZc_ConsoleTools-1.6.1.xmlnu[ ConsoleTools components.ez.no A set of classes to do different actions with the console (also called shell). A set of classes to do different actions with the console (also called shell). It can render a progress bar, tables and a status bar and contains a class for parsing command line options. eZ systems ezc ezc@ez.no yes 2010-03-22 1.6.1 1.6.1 stable stable New BSD - Fixed issue #16055: Corrected regression in error message for option dependencies. 5.2.1 1.4.2 Base components.ez.no 1.8 1.6.1 1.6.1 stable stable 2010-03-22 New BSD - Fixed issue #16055: Corrected regression in error message for option dependencies. PK!pxNJNJ/.registry/.channel.pear.symfony.com/process.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:7:"Process";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:26:"Symfony2 Process Component";s:11:"description";s:26:"Symfony2 Process Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:48";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:32:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d39ea12d1764b05af5e85dae2c48c793";s:4:"name";s:40:"Symfony/Component/Process/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1c079058bd8ecb9a361d7d315fb5e5ae";s:4:"name";s:38:"Symfony/Component/Process/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bf954605bb40623c26cfca6fdc344c5e";s:4:"name";s:39:"Symfony/Component/Process/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"723a4615b94a21c979c9cfe85d81e50a";s:4:"name";s:58:"Symfony/Component/Process/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b3c8598f88e6ac643dda6cb6f29fb3ba";s:4:"name";s:64:"Symfony/Component/Process/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"72ef3efed027815b107a71f4e987754d";s:4:"name";s:54:"Symfony/Component/Process/Exception/LogicException.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7726c705c207d8bd0455597b19f5e035";s:4:"name";s:62:"Symfony/Component/Process/Exception/ProcessFailedException.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"da8b86018e9365453290e986630fdac9";s:4:"name";s:64:"Symfony/Component/Process/Exception/ProcessTimedOutException.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5173fb5053527af7b83077085b192d67";s:4:"name";s:56:"Symfony/Component/Process/Exception/RuntimeException.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ec007221c50ca2fa099de00cc14d95f8";s:4:"name";s:46:"Symfony/Component/Process/ExecutableFinder.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:33:"Symfony/Component/Process/LICENSE";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fba1a6b8ff2371258f20c316c3aee410";s:4:"name";s:49:"Symfony/Component/Process/PhpExecutableFinder.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2218c2a825f09243ab31c4194dc71ac8";s:4:"name";s:40:"Symfony/Component/Process/PhpProcess.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"38416969b8bd90a8627afbdea4d56fbb";s:4:"name";s:42:"Symfony/Component/Process/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d6a4515f04d6a7095c32c8becf869ea2";s:4:"name";s:37:"Symfony/Component/Process/Process.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"22a24c881ccc2a334cb39f3406386ab4";s:4:"name";s:44:"Symfony/Component/Process/ProcessBuilder.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9170706e98976ed4b63ec5496e553454";s:4:"name";s:42:"Symfony/Component/Process/ProcessPipes.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e656122ad88214d14d5fb0da26038958";s:4:"name";s:42:"Symfony/Component/Process/ProcessUtils.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2d4849606123482d1ee255038021f68";s:4:"name";s:35:"Symfony/Component/Process/README.md";s:4:"role";s:3:"doc";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8c50bc22c7ee63d0b781721e49cd29f3";s:4:"name";s:55:"Symfony/Component/Process/Tests/AbstractProcessTest.php";s:4:"role";s:4:"test";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"536f711e6e2aa61bf065b29e8631825f";s:4:"name";s:54:"Symfony/Component/Process/Tests/NonStopableProcess.php";s:4:"role";s:4:"test";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7f5014eeb10fe782977f36a0a363b339";s:4:"name";s:59:"Symfony/Component/Process/Tests/PhpExecutableFinderTest.php";s:4:"role";s:4:"test";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5636117b645854523f4e49119e05286a";s:4:"name";s:50:"Symfony/Component/Process/Tests/PhpProcessTest.php";s:4:"role";s:4:"test";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4bb65137b612922b87bae61f12ddaa93";s:4:"name";s:71:"Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php";s:4:"role";s:4:"test";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"841d9ebee0e41be0280387ae00485d31";s:4:"name";s:54:"Symfony/Component/Process/Tests/ProcessBuilderTest.php";s:4:"role";s:4:"test";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"548e570239c6a450fba22a768ada8542";s:4:"name";s:62:"Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php";s:4:"role";s:4:"test";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fadee2df6610863207b16c6077b5c282";s:4:"name";s:64:"Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.php";s:4:"role";s:4:"test";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2afe80bbab70e5a8badccebb32021372";s:4:"name";s:52:"Symfony/Component/Process/Tests/ProcessUtilsTest.php";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"00f0e0d73858eae9e670635a5c0d66f6";s:4:"name";s:63:"Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php";s:4:"role";s:4:"test";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c3d833e3cc8e7545bfaefff2d369b07b";s:4:"name";s:62:"Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php";s:4:"role";s:4:"test";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b75bfa6a7dfd6efbc39a5f7f870fa64c";s:4:"name";s:50:"Symfony/Component/Process/Tests/SignalListener.php";s:4:"role";s:4:"test";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d952eb9a5f29bc454a9263a38453feb";s:4:"name";s:53:"Symfony/Component/Process/Tests/SimpleProcessTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:32:{s:40:"Symfony/Component/Process/autoloader.php";a:4:{s:6:"md5sum";s:32:"d39ea12d1764b05af5e85dae2c48c793";s:4:"name";s:40:"Symfony/Component/Process/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/autoloader.php";}s:38:"Symfony/Component/Process/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"1c079058bd8ecb9a361d7d315fb5e5ae";s:4:"name";s:38:"Symfony/Component/Process/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/doc/pear/Process/Symfony/Component/Process/CHANGELOG.md";}s:39:"Symfony/Component/Process/composer.json";a:4:{s:6:"md5sum";s:32:"bf954605bb40623c26cfca6fdc344c5e";s:4:"name";s:39:"Symfony/Component/Process/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/Process/Symfony/Component/Process/composer.json";}s:58:"Symfony/Component/Process/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"723a4615b94a21c979c9cfe85d81e50a";s:4:"name";s:58:"Symfony/Component/Process/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/Exception/ExceptionInterface.php";}s:64:"Symfony/Component/Process/Exception/InvalidArgumentException.php";a:4:{s:6:"md5sum";s:32:"b3c8598f88e6ac643dda6cb6f29fb3ba";s:4:"name";s:64:"Symfony/Component/Process/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/Exception/InvalidArgumentException.php";}s:54:"Symfony/Component/Process/Exception/LogicException.php";a:4:{s:6:"md5sum";s:32:"72ef3efed027815b107a71f4e987754d";s:4:"name";s:54:"Symfony/Component/Process/Exception/LogicException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/Exception/LogicException.php";}s:62:"Symfony/Component/Process/Exception/ProcessFailedException.php";a:4:{s:6:"md5sum";s:32:"7726c705c207d8bd0455597b19f5e035";s:4:"name";s:62:"Symfony/Component/Process/Exception/ProcessFailedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/Exception/ProcessFailedException.php";}s:64:"Symfony/Component/Process/Exception/ProcessTimedOutException.php";a:4:{s:6:"md5sum";s:32:"da8b86018e9365453290e986630fdac9";s:4:"name";s:64:"Symfony/Component/Process/Exception/ProcessTimedOutException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/Exception/ProcessTimedOutException.php";}s:56:"Symfony/Component/Process/Exception/RuntimeException.php";a:4:{s:6:"md5sum";s:32:"5173fb5053527af7b83077085b192d67";s:4:"name";s:56:"Symfony/Component/Process/Exception/RuntimeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/Exception/RuntimeException.php";}s:46:"Symfony/Component/Process/ExecutableFinder.php";a:4:{s:6:"md5sum";s:32:"ec007221c50ca2fa099de00cc14d95f8";s:4:"name";s:46:"Symfony/Component/Process/ExecutableFinder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/ExecutableFinder.php";}s:33:"Symfony/Component/Process/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:33:"Symfony/Component/Process/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/Process/Symfony/Component/Process/LICENSE";}s:49:"Symfony/Component/Process/PhpExecutableFinder.php";a:4:{s:6:"md5sum";s:32:"fba1a6b8ff2371258f20c316c3aee410";s:4:"name";s:49:"Symfony/Component/Process/PhpExecutableFinder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/PhpExecutableFinder.php";}s:40:"Symfony/Component/Process/PhpProcess.php";a:4:{s:6:"md5sum";s:32:"2218c2a825f09243ab31c4194dc71ac8";s:4:"name";s:40:"Symfony/Component/Process/PhpProcess.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/PhpProcess.php";}s:42:"Symfony/Component/Process/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"38416969b8bd90a8627afbdea4d56fbb";s:4:"name";s:42:"Symfony/Component/Process/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/phpunit.xml.dist";}s:37:"Symfony/Component/Process/Process.php";a:4:{s:6:"md5sum";s:32:"d6a4515f04d6a7095c32c8becf869ea2";s:4:"name";s:37:"Symfony/Component/Process/Process.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/Process.php";}s:44:"Symfony/Component/Process/ProcessBuilder.php";a:4:{s:6:"md5sum";s:32:"22a24c881ccc2a334cb39f3406386ab4";s:4:"name";s:44:"Symfony/Component/Process/ProcessBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/ProcessBuilder.php";}s:42:"Symfony/Component/Process/ProcessPipes.php";a:4:{s:6:"md5sum";s:32:"9170706e98976ed4b63ec5496e553454";s:4:"name";s:42:"Symfony/Component/Process/ProcessPipes.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/ProcessPipes.php";}s:42:"Symfony/Component/Process/ProcessUtils.php";a:4:{s:6:"md5sum";s:32:"e656122ad88214d14d5fb0da26038958";s:4:"name";s:42:"Symfony/Component/Process/ProcessUtils.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/ProcessUtils.php";}s:35:"Symfony/Component/Process/README.md";a:4:{s:6:"md5sum";s:32:"f2d4849606123482d1ee255038021f68";s:4:"name";s:35:"Symfony/Component/Process/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/doc/pear/Process/Symfony/Component/Process/README.md";}s:55:"Symfony/Component/Process/Tests/AbstractProcessTest.php";a:4:{s:6:"md5sum";s:32:"8c50bc22c7ee63d0b781721e49cd29f3";s:4:"name";s:55:"Symfony/Component/Process/Tests/AbstractProcessTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/AbstractProcessTest.php";}s:54:"Symfony/Component/Process/Tests/NonStopableProcess.php";a:4:{s:6:"md5sum";s:32:"536f711e6e2aa61bf065b29e8631825f";s:4:"name";s:54:"Symfony/Component/Process/Tests/NonStopableProcess.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/NonStopableProcess.php";}s:59:"Symfony/Component/Process/Tests/PhpExecutableFinderTest.php";a:4:{s:6:"md5sum";s:32:"7f5014eeb10fe782977f36a0a363b339";s:4:"name";s:59:"Symfony/Component/Process/Tests/PhpExecutableFinderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php";}s:50:"Symfony/Component/Process/Tests/PhpProcessTest.php";a:4:{s:6:"md5sum";s:32:"5636117b645854523f4e49119e05286a";s:4:"name";s:50:"Symfony/Component/Process/Tests/PhpProcessTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/PhpProcessTest.php";}s:71:"Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php";a:4:{s:6:"md5sum";s:32:"4bb65137b612922b87bae61f12ddaa93";s:4:"name";s:71:"Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php";}s:54:"Symfony/Component/Process/Tests/ProcessBuilderTest.php";a:4:{s:6:"md5sum";s:32:"841d9ebee0e41be0280387ae00485d31";s:4:"name";s:54:"Symfony/Component/Process/Tests/ProcessBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/ProcessBuilderTest.php";}s:62:"Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php";a:4:{s:6:"md5sum";s:32:"548e570239c6a450fba22a768ada8542";s:4:"name";s:62:"Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php";}s:64:"Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.php";a:4:{s:6:"md5sum";s:32:"fadee2df6610863207b16c6077b5c282";s:4:"name";s:64:"Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.php";}s:52:"Symfony/Component/Process/Tests/ProcessUtilsTest.php";a:4:{s:6:"md5sum";s:32:"2afe80bbab70e5a8badccebb32021372";s:4:"name";s:52:"Symfony/Component/Process/Tests/ProcessUtilsTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/ProcessUtilsTest.php";}s:63:"Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php";a:4:{s:6:"md5sum";s:32:"00f0e0d73858eae9e670635a5c0d66f6";s:4:"name";s:63:"Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php";}s:62:"Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php";a:4:{s:6:"md5sum";s:32:"c3d833e3cc8e7545bfaefff2d369b07b";s:4:"name";s:62:"Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php";}s:50:"Symfony/Component/Process/Tests/SignalListener.php";a:4:{s:6:"md5sum";s:32:"b75bfa6a7dfd6efbc39a5f7f870fa64c";s:4:"name";s:50:"Symfony/Component/Process/Tests/SignalListener.php";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/SignalListener.php";}s:53:"Symfony/Component/Process/Tests/SimpleProcessTest.php";a:4:{s:6:"md5sum";s:32:"8d952eb9a5f29bc454a9263a38453feb";s:4:"name";s:53:"Symfony/Component/Process/Tests/SimpleProcessTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests/SimpleProcessTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:13:{s:55:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:67:"/opt/alt/php54/usr/share/doc/pear/Process/Symfony/Component/Process";b:1;s:59:"/opt/alt/php54/usr/share/doc/pear/Process/Symfony/Component";b:1;s:49:"/opt/alt/php54/usr/share/doc/pear/Process/Symfony";b:1;s:41:"/opt/alt/php54/usr/share/doc/pear/Process";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Process/Exception";b:1;s:68:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process";b:1;s:60:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component";b:1;s:50:"/opt/alt/php54/usr/share/pear/test/Process/Symfony";b:1;s:42:"/opt/alt/php54/usr/share/pear/test/Process";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/Process/Symfony/Component/Process/Tests";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!/.registry/.channel.pear.symfony.com/console.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:7:"Console";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:26:"Symfony2 Console Component";s:11:"description";s:26:"Symfony2 Console Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:42";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:178:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d7fa5d3e678f32b207a275d566bd226b";s:4:"name";s:41:"Symfony/Component/Console/Application.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a67fcf08fe6f3092f954fdd247d138d8";s:4:"name";s:40:"Symfony/Component/Console/autoloader.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2b61d6b18ded64f0686599db5c7fb5b";s:4:"name";s:38:"Symfony/Component/Console/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80d4d8e858f5a83230701aed15e6f9ff";s:4:"name";s:45:"Symfony/Component/Console/Command/Command.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d10467979ea85e92951425fd351347ac";s:4:"name";s:49:"Symfony/Component/Console/Command/HelpCommand.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7f0bd50020e8b9c39d79692f3e32db8f";s:4:"name";s:49:"Symfony/Component/Console/Command/ListCommand.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9e146f5ae7085917809444efe2d868c6";s:4:"name";s:39:"Symfony/Component/Console/composer.json";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"10001de60b8e31092612e73dc02300d7";s:4:"name";s:43:"Symfony/Component/Console/ConsoleEvents.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e5ffa840297bdf9232762c38218846dc";s:4:"name";s:63:"Symfony/Component/Console/Descriptor/ApplicationDescription.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e08a534aa99b2e90d1538a0c166973e5";s:4:"name";s:51:"Symfony/Component/Console/Descriptor/Descriptor.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5b9abe215ed28ac8ca7fe9d72fc9ddd";s:4:"name";s:60:"Symfony/Component/Console/Descriptor/DescriptorInterface.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a997223049fcf34294263e3a6c37e230";s:4:"name";s:55:"Symfony/Component/Console/Descriptor/JsonDescriptor.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bec9d13cc9cb6e778c4f4083199137b6";s:4:"name";s:59:"Symfony/Component/Console/Descriptor/MarkdownDescriptor.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"97b571928164645af31610ea97bc43fb";s:4:"name";s:55:"Symfony/Component/Console/Descriptor/TextDescriptor.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a9214dd6cf39faa121dc4de62996071a";s:4:"name";s:54:"Symfony/Component/Console/Descriptor/XmlDescriptor.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2832db2aee4207de5d53d012b314436d";s:4:"name";s:55:"Symfony/Component/Console/Event/ConsoleCommandEvent.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aaaa8c390cd99e01d7bb2649a735e469";s:4:"name";s:48:"Symfony/Component/Console/Event/ConsoleEvent.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"22e5c027468f33b0bd20540b41af7a74";s:4:"name";s:57:"Symfony/Component/Console/Event/ConsoleExceptionEvent.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"82fbfa586f39a859d66a45221cb773c1";s:4:"name";s:57:"Symfony/Component/Console/Event/ConsoleTerminateEvent.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"304b90bba47ad3ed5534a37ec1647980";s:4:"name";s:55:"Symfony/Component/Console/Formatter/OutputFormatter.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"75e7364468e427f080f86354f9bab9b9";s:4:"name";s:64:"Symfony/Component/Console/Formatter/OutputFormatterInterface.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4d0b8e5a84926a6013be77aa123e61eb";s:4:"name";s:60:"Symfony/Component/Console/Formatter/OutputFormatterStyle.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"091bf3ec019e14a48b1f61ef7cb6871a";s:4:"name";s:69:"Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"27952fd939968e3615ce7ada4c761e0e";s:4:"name";s:65:"Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5bb73eb73014de416365c07cd81cac5";s:4:"name";s:53:"Symfony/Component/Console/Helper/DescriptorHelper.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae0bb3641414453024a3d71275abd1c1";s:4:"name";s:49:"Symfony/Component/Console/Helper/DialogHelper.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86ebeb32b3353bc7ba4363bf7a05fa2f";s:4:"name";s:52:"Symfony/Component/Console/Helper/FormatterHelper.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"426298ce1ccd85ab527a5cef78f9a33b";s:4:"name";s:43:"Symfony/Component/Console/Helper/Helper.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e9012e6f3559129d513da4ba75ebf4e9";s:4:"name";s:52:"Symfony/Component/Console/Helper/HelperInterface.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9c0badab04f9b052cec6a06c3f11fb07";s:4:"name";s:46:"Symfony/Component/Console/Helper/HelperSet.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c75592e1f3b10c1f35961c50d55ae58d";s:4:"name";s:53:"Symfony/Component/Console/Helper/InputAwareHelper.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c6c85dbb2f08fa52bc6739ba6896bdc9";s:4:"name";s:51:"Symfony/Component/Console/Helper/ProgressHelper.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1671e0f028279a642e6c0f7dcaa474c4";s:4:"name";s:48:"Symfony/Component/Console/Helper/TableHelper.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e95b97c2b870d6223e84a995c93f16ce";s:4:"name";s:45:"Symfony/Component/Console/Input/ArgvInput.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1e51135fb1c605381452c4d0cae3f1c4";s:4:"name";s:46:"Symfony/Component/Console/Input/ArrayInput.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87ba519b169574bdcaabaef68740989a";s:4:"name";s:41:"Symfony/Component/Console/Input/Input.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2f88afd2a0f1601dcfd3cce07092197";s:4:"name";s:49:"Symfony/Component/Console/Input/InputArgument.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a67cb5e626983b20e2c03b618d7ab012";s:4:"name";s:55:"Symfony/Component/Console/Input/InputAwareInterface.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"74e92dce0c01082eb3d96959f3268509";s:4:"name";s:51:"Symfony/Component/Console/Input/InputDefinition.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9a40ecfaca79fa6bed0e459c035fdb5c";s:4:"name";s:50:"Symfony/Component/Console/Input/InputInterface.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2712657bb89ede768dfb9d0eb1f1d256";s:4:"name";s:47:"Symfony/Component/Console/Input/InputOption.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eaf496e1188492448d9cfe8dfbcede6a";s:4:"name";s:47:"Symfony/Component/Console/Input/StringInput.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:33:"Symfony/Component/Console/LICENSE";s:4:"role";s:3:"doc";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"07bca2bc77753b0b0cc4502f109c4a8e";s:4:"name";s:51:"Symfony/Component/Console/Output/BufferedOutput.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"64e00ce49a3a47e8ea7b8885f10c1ee6";s:4:"name";s:50:"Symfony/Component/Console/Output/ConsoleOutput.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9cf400160437ff90febb665841a968fe";s:4:"name";s:59:"Symfony/Component/Console/Output/ConsoleOutputInterface.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"561f460b93be0c27aa9be546af49e9ec";s:4:"name";s:47:"Symfony/Component/Console/Output/NullOutput.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"15c209a7581a632e6979d5441a02f241";s:4:"name";s:43:"Symfony/Component/Console/Output/Output.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ac6d776cf82c8b887395c54482f17bd7";s:4:"name";s:52:"Symfony/Component/Console/Output/OutputInterface.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dc57630f625779ad86f6f3d8240ad0c3";s:4:"name";s:49:"Symfony/Component/Console/Output/StreamOutput.php";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c94fc23909e8f1d27908cd0486653611";s:4:"name";s:42:"Symfony/Component/Console/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"70a92aecafcdc1f689a2a798acccefe4";s:4:"name";s:35:"Symfony/Component/Console/README.md";s:4:"role";s:3:"doc";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3613d8d83b78ce3561680a447eb6a24a";s:4:"name";s:55:"Symfony/Component/Console/Resources/bin/hiddeninput.exe";s:4:"role";s:3:"php";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fedc847f6c992a242e45a167b0cf1866";s:4:"name";s:35:"Symfony/Component/Console/Shell.php";s:4:"role";s:3:"php";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2c7b88716f13cb54825a933832a74a8";s:4:"name";s:54:"Symfony/Component/Console/Tester/ApplicationTester.php";s:4:"role";s:3:"php";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b7bf197b61b1b3c23772c57a2ec3ee5";s:4:"name";s:50:"Symfony/Component/Console/Tester/CommandTester.php";s:4:"role";s:3:"php";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4113e99075832dfdf616eb1d40466b5f";s:4:"name";s:51:"Symfony/Component/Console/Tests/ApplicationTest.php";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"95ad26aa722775521f90d097b79d23b7";s:4:"name";s:55:"Symfony/Component/Console/Tests/Command/CommandTest.php";s:4:"role";s:4:"test";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e8f9a01b23091cef3ed6346feaf38b9c";s:4:"name";s:59:"Symfony/Component/Console/Tests/Command/HelpCommandTest.php";s:4:"role";s:4:"test";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e7562df5cc8110fb5a6e44cbc39a7c03";s:4:"name";s:59:"Symfony/Component/Console/Tests/Command/ListCommandTest.php";s:4:"role";s:4:"test";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"531b8d11ed5d639162a8cbc8c1b7fe53";s:4:"name";s:69:"Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.php";s:4:"role";s:4:"test";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8b6ccffc99cb2ffea82e6e65171dc329";s:4:"name";s:65:"Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0738e024a2a5fd48f033acec21ebe484";s:4:"name";s:69:"Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.php";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e364df76cc57c1a8221422eac8425501";s:4:"name";s:62:"Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a5a110579ab493bc21572ec836e8b94e";s:4:"name";s:65:"Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.php";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa6b0e47cc2693587024ee3d9b2efc6c";s:4:"name";s:64:"Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.php";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea331a512e8c0d80230ff1f7b1254316";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/application_1.json";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2e34db40b7841a8df627415fd72762df";s:4:"name";s:57:"Symfony/Component/Console/Tests/Fixtures/application_1.md";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3d936937d3bcf607fc54faad2558a453";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/application_1.txt";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d819500ef4e850b75c623682dc38c900";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/application_1.xml";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c461b890d0d7849cfb5eb5bbbc113e66";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/application_2.json";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fd2188a4c78bd7bc1a3778a0af6311c5";s:4:"name";s:57:"Symfony/Component/Console/Tests/Fixtures/application_2.md";s:4:"role";s:4:"test";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d66df90611c1e4fc0161d4307d18ece1";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/application_2.txt";s:4:"role";s:4:"test";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d9d7ea7073a523ad2a07ae345b22316f";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/application_2.xml";s:4:"role";s:4:"test";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b40b7c5e2ce450d92801ad9f5420ea77";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/application_astext1.txt";s:4:"role";s:4:"test";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"345da50027f0969cf6b362f3f9088186";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/application_astext2.txt";s:4:"role";s:4:"test";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"507250131eb057d025531c669a4aab19";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt";s:4:"role";s:4:"test";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fd7e97279731abc448a7577095054ca8";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/application_asxml2.txt";s:4:"role";s:4:"test";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa0a9b41081ebab06350041597bd4542";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/application_gethelp.txt";s:4:"role";s:4:"test";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"977a66011fcade49927bb6ac41477792";s:4:"name";s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt";s:4:"role";s:4:"test";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"38d86d41d4fb194a695eaddfe2a8d2df";s:4:"name";s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt";s:4:"role";s:4:"test";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"711b8a7b6ec59bb13332c79763666e14";s:4:"name";s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt";s:4:"role";s:4:"test";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"037657ca60cd7c8ff945ce145684aec6";s:4:"name";s:82:"Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt";s:4:"role";s:4:"test";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0b5b31d2023ae8ec6e2eef0e08e0400c";s:4:"name";s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt";s:4:"role";s:4:"test";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47745f267210a2e2fb9860082194efd2";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/application_run1.txt";s:4:"role";s:4:"test";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff916ea07ab6a3777814eafa148c9c34";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/application_run2.txt";s:4:"role";s:4:"test";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e1651d791eebaeed9a568412fe433ce2";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/application_run3.txt";s:4:"role";s:4:"test";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c7759de3fcd0263d72d1fad2390dc914";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/application_run4.txt";s:4:"role";s:4:"test";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5bb7afd8d7266c4b53acdd0ba4bc87ce";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/BarBucCommand.php";s:4:"role";s:4:"test";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8464fa011bb28109fd087727f1216458";s:4:"name";s:55:"Symfony/Component/Console/Tests/Fixtures/command_1.json";s:4:"role";s:4:"test";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"44b8f270513ba511d0d971b52b2396d6";s:4:"name";s:53:"Symfony/Component/Console/Tests/Fixtures/command_1.md";s:4:"role";s:4:"test";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"40f52be95eb599167faf4fb1382e93e7";s:4:"name";s:54:"Symfony/Component/Console/Tests/Fixtures/command_1.txt";s:4:"role";s:4:"test";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d4a21bb6906c17693a2cf2d990f17441";s:4:"name";s:54:"Symfony/Component/Console/Tests/Fixtures/command_1.xml";s:4:"role";s:4:"test";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8ff624584c774ae83144627314d66587";s:4:"name";s:55:"Symfony/Component/Console/Tests/Fixtures/command_2.json";s:4:"role";s:4:"test";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"65763c3a87b5e2a625fdd143edaf03fe";s:4:"name";s:53:"Symfony/Component/Console/Tests/Fixtures/command_2.md";s:4:"role";s:4:"test";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5680ffddd8fc44a29d0ea39f9ab09906";s:4:"name";s:54:"Symfony/Component/Console/Tests/Fixtures/command_2.txt";s:4:"role";s:4:"test";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8cac2b7fac663f8d0fd15c22f1160981";s:4:"name";s:54:"Symfony/Component/Console/Tests/Fixtures/command_2.xml";s:4:"role";s:4:"test";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ac50a755a5dcf9dbbf7d03564c134b5c";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/command_astext.txt";s:4:"role";s:4:"test";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d94936284533d2495f2eb207fa02e232";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/command_asxml.txt";s:4:"role";s:4:"test";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6a54005ec1a08c1a7f9d7b098dec09f3";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/definition_astext.txt";s:4:"role";s:4:"test";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"205994db49721172eac27b69ff37ec4f";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/definition_asxml.txt";s:4:"role";s:4:"test";}}i:101;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cb827ac9aecc15b6592f8c153317b31d";s:4:"name";s:67:"Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php";s:4:"role";s:4:"test";}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d929bab60eb3fd020e15b45a3c54d168";s:4:"name";s:67:"Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php";s:4:"role";s:4:"test";}}i:103;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"50c23e03725ffd75f65d76b07e71887a";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php";s:4:"role";s:4:"test";}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8cc36b0c8be8ac7db7897d5ac4eee699";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php";s:4:"role";s:4:"test";}}i:105;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df52584a64822a983eb5d927acedb8c1";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo1Command.php";s:4:"role";s:4:"test";}}i:106;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cf36c22795c10c04984b683ff3f1fe79";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo2Command.php";s:4:"role";s:4:"test";}}i:107;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"14ec4962d6e9d9be56dbb5a90f1c01bc";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo3Command.php";s:4:"role";s:4:"test";}}i:108;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a747ae989c89cbff1df48d301d69ff9a";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo4Command.php";s:4:"role";s:4:"test";}}i:109;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ab33a181019dd14b892e920906a83e41";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo5Command.php";s:4:"role";s:4:"test";}}i:110;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c409f073d1a760445d7c692bf6668848";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/FoobarCommand.php";s:4:"role";s:4:"test";}}i:111;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"45276372456804d1c3cc11c30e1e26e4";s:4:"name";s:55:"Symfony/Component/Console/Tests/Fixtures/FooCommand.php";s:4:"role";s:4:"test";}}i:112;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87e6eeef0f89e57d691ca8a35bb91e12";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.json";s:4:"role";s:4:"test";}}i:113;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f51385902d2eb98e5c7236b26f720741";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.md";s:4:"role";s:4:"test";}}i:114;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"49ec5d491a17d9f6c93e3b6194757de0";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.txt";s:4:"role";s:4:"test";}}i:115;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0c308f004edf7c0b6aaec03f028e8747";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.xml";s:4:"role";s:4:"test";}}i:116;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b189366871c1bb8b146087dcc1b20cf";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.json";s:4:"role";s:4:"test";}}i:117;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3f2fd328c9393a8ede70602631d68c9f";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.md";s:4:"role";s:4:"test";}}i:118;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c4567546600e6c71ee236a870b9a5d16";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.txt";s:4:"role";s:4:"test";}}i:119;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"57a965ef131103e13d8befdb1a0e8465";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.xml";s:4:"role";s:4:"test";}}i:120;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eacb43809707dd26dcb8a0c34f1cd337";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.json";s:4:"role";s:4:"test";}}i:121;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"92b02b5435642c4f31ccc943b751c30e";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.md";s:4:"role";s:4:"test";}}i:122;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e512053db481dbd2ac228f790e4a5c31";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.txt";s:4:"role";s:4:"test";}}i:123;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4b5eacb65951dd1047832992de231669";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.xml";s:4:"role";s:4:"test";}}i:124;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6b6cd5a30b7f04a27b3615fcb66fbb60";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.json";s:4:"role";s:4:"test";}}i:125;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.md";s:4:"role";s:4:"test";}}i:126;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.txt";s:4:"role";s:4:"test";}}i:127;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d1ccbc21759a3a9fbf5c8540d9083f47";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.xml";s:4:"role";s:4:"test";}}i:128;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"96c29539ac20c5289ce924a2b53e0a74";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.json";s:4:"role";s:4:"test";}}i:129;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"65e283e532971f65a0531cef86ec1ff7";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.md";s:4:"role";s:4:"test";}}i:130;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63bc1a5ff3064f65a2acd1f3fe791164";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.txt";s:4:"role";s:4:"test";}}i:131;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a856c4c0e7a21895a75fccd1f7ad9652";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.xml";s:4:"role";s:4:"test";}}i:132;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e3e2853d5735de1d839b7378cea925f6";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.json";s:4:"role";s:4:"test";}}i:133;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cf4db1e7e783877fedcc11f228f057f7";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.md";s:4:"role";s:4:"test";}}i:134;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6517879eab6c613d4ccc9e8f11dc00cc";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.txt";s:4:"role";s:4:"test";}}i:135;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cf9890033c9b3296c3f0a84ad7a40f26";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.xml";s:4:"role";s:4:"test";}}i:136;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a0d3b5beb936e28bcfa0b2a09038e477";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.json";s:4:"role";s:4:"test";}}i:137;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"55bdf86d23a2c802d4c7d36922a16cc8";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.md";s:4:"role";s:4:"test";}}i:138;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6a351cab07e83967475ce418f11389c9";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.txt";s:4:"role";s:4:"test";}}i:139;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"732625b8bef91e2b6e5e42b135714673";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.xml";s:4:"role";s:4:"test";}}i:140;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"275c5ca8fae2603962435abee86abc22";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_1.json";s:4:"role";s:4:"test";}}i:141;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2f3b3fce4e6cc97d37c2cdf2a8545a17";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_1.md";s:4:"role";s:4:"test";}}i:142;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7c446b0b7764679b0675e2bf7c15d5ef";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_1.txt";s:4:"role";s:4:"test";}}i:143;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2441944e792817317e54ca3e6bf3478a";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_1.xml";s:4:"role";s:4:"test";}}i:144;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8ad4b5bb7f68b81ac5baf6f86c54f216";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_2.json";s:4:"role";s:4:"test";}}i:145;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"febad80dc8502990d7631dfa7e710725";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_2.md";s:4:"role";s:4:"test";}}i:146;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4cebdddb6ee8776268fe824f5ebc8b14";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_2.txt";s:4:"role";s:4:"test";}}i:147;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ad9f550cbdd67e7bda7bfb78ebbc4d57";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_2.xml";s:4:"role";s:4:"test";}}i:148;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2eb676e70f06dff589fc461b96da5c61";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_3.json";s:4:"role";s:4:"test";}}i:149;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"03a09ae47b81986ec50edd6608fa2426";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_3.md";s:4:"role";s:4:"test";}}i:150;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7eada46556b0ce341069f353b063e45e";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_3.txt";s:4:"role";s:4:"test";}}i:151;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8c91b697596ccf87b48c58ecbae02aa6";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_3.xml";s:4:"role";s:4:"test";}}i:152;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"20c72909569d5ec92465f7c7dc002381";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_4.json";s:4:"role";s:4:"test";}}i:153;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4b02ffc507306a9d887e73d2fca429ba";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_4.md";s:4:"role";s:4:"test";}}i:154;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d49ce52263e22bbdd37e687455478ea";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_4.txt";s:4:"role";s:4:"test";}}i:155;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"960e79c93c46361c3bd250b5fe73d25b";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_4.xml";s:4:"role";s:4:"test";}}i:156;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cdfd10039b833b3d0cd4bc946d6d0e52";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/TestCommand.php";s:4:"role";s:4:"test";}}i:157;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d65f80f685c098367d357b79b1085660";s:4:"name";s:75:"Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleStackTest.php";s:4:"role";s:4:"test";}}i:158;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"772ad7157614e0a3336b0e79bfd8c018";s:4:"name";s:70:"Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleTest.php";s:4:"role";s:4:"test";}}i:159;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1932fadfa3ba33810457dc7c7caf4200";s:4:"name";s:65:"Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php";s:4:"role";s:4:"test";}}i:160;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c080187a3a540acbd38ea4e72e197073";s:4:"name";s:59:"Symfony/Component/Console/Tests/Helper/DialogHelperTest.php";s:4:"role";s:4:"test";}}i:161;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"caffe5a35cfde20acff28a1b2ede9523";s:4:"name";s:62:"Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php";s:4:"role";s:4:"test";}}i:162;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0c4b855c7ad31b88262a32f083903d5b";s:4:"name";s:56:"Symfony/Component/Console/Tests/Helper/HelperSetTest.php";s:4:"role";s:4:"test";}}i:163;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d460c56a019e5bfd59f1d2d91970812";s:4:"name";s:61:"Symfony/Component/Console/Tests/Helper/ProgressHelperTest.php";s:4:"role";s:4:"test";}}i:164;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7c598e6ffdbd3c17865a4c54cbe34c78";s:4:"name";s:58:"Symfony/Component/Console/Tests/Helper/TableHelperTest.php";s:4:"role";s:4:"test";}}i:165;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2d5b2e942330756fcbc30062e9007f1e";s:4:"name";s:55:"Symfony/Component/Console/Tests/Input/ArgvInputTest.php";s:4:"role";s:4:"test";}}i:166;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a90b8bafe8ede004c6ed61ecc8224a3f";s:4:"name";s:56:"Symfony/Component/Console/Tests/Input/ArrayInputTest.php";s:4:"role";s:4:"test";}}i:167;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7fe249cea32fc176d04f2520a018bdd8";s:4:"name";s:59:"Symfony/Component/Console/Tests/Input/InputArgumentTest.php";s:4:"role";s:4:"test";}}i:168;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"debb5202554762ad79bbd9353fcd04b7";s:4:"name";s:61:"Symfony/Component/Console/Tests/Input/InputDefinitionTest.php";s:4:"role";s:4:"test";}}i:169;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b6f2af5b4b79ed25113742022e86c77a";s:4:"name";s:57:"Symfony/Component/Console/Tests/Input/InputOptionTest.php";s:4:"role";s:4:"test";}}i:170;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f9129bb377ebb93a88cfcc97795055ff";s:4:"name";s:51:"Symfony/Component/Console/Tests/Input/InputTest.php";s:4:"role";s:4:"test";}}i:171;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6d3e24ab1bdf3f1048c89aded3fdfc42";s:4:"name";s:57:"Symfony/Component/Console/Tests/Input/StringInputTest.php";s:4:"role";s:4:"test";}}i:172;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5f42c7a490159ffee9e4d44297f6cbb0";s:4:"name";s:60:"Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php";s:4:"role";s:4:"test";}}i:173;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b663167dfed0b653e8bc70890b8d417";s:4:"name";s:57:"Symfony/Component/Console/Tests/Output/NullOutputTest.php";s:4:"role";s:4:"test";}}i:174;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eb5d8d732894bc94242983e61d9ea828";s:4:"name";s:53:"Symfony/Component/Console/Tests/Output/OutputTest.php";s:4:"role";s:4:"test";}}i:175;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d9e51b68858e010abf7c9856411f9f3e";s:4:"name";s:59:"Symfony/Component/Console/Tests/Output/StreamOutputTest.php";s:4:"role";s:4:"test";}}i:176;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ed2c4ba2123801176abd8f7b15cfce2e";s:4:"name";s:64:"Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.php";s:4:"role";s:4:"test";}}i:177;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dc805845c9fb25bf57604fda8b19c86d";s:4:"name";s:60:"Symfony/Component/Console/Tests/Tester/CommandTesterTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:178:{s:41:"Symfony/Component/Console/Application.php";a:4:{s:6:"md5sum";s:32:"d7fa5d3e678f32b207a275d566bd226b";s:4:"name";s:41:"Symfony/Component/Console/Application.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Application.php";}s:40:"Symfony/Component/Console/autoloader.php";a:4:{s:6:"md5sum";s:32:"a67fcf08fe6f3092f954fdd247d138d8";s:4:"name";s:40:"Symfony/Component/Console/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/autoloader.php";}s:38:"Symfony/Component/Console/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"e2b61d6b18ded64f0686599db5c7fb5b";s:4:"name";s:38:"Symfony/Component/Console/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/doc/pear/Console/Symfony/Component/Console/CHANGELOG.md";}s:45:"Symfony/Component/Console/Command/Command.php";a:4:{s:6:"md5sum";s:32:"80d4d8e858f5a83230701aed15e6f9ff";s:4:"name";s:45:"Symfony/Component/Console/Command/Command.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Command/Command.php";}s:49:"Symfony/Component/Console/Command/HelpCommand.php";a:4:{s:6:"md5sum";s:32:"d10467979ea85e92951425fd351347ac";s:4:"name";s:49:"Symfony/Component/Console/Command/HelpCommand.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Command/HelpCommand.php";}s:49:"Symfony/Component/Console/Command/ListCommand.php";a:4:{s:6:"md5sum";s:32:"7f0bd50020e8b9c39d79692f3e32db8f";s:4:"name";s:49:"Symfony/Component/Console/Command/ListCommand.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Command/ListCommand.php";}s:39:"Symfony/Component/Console/composer.json";a:4:{s:6:"md5sum";s:32:"9e146f5ae7085917809444efe2d868c6";s:4:"name";s:39:"Symfony/Component/Console/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/Console/Symfony/Component/Console/composer.json";}s:43:"Symfony/Component/Console/ConsoleEvents.php";a:4:{s:6:"md5sum";s:32:"10001de60b8e31092612e73dc02300d7";s:4:"name";s:43:"Symfony/Component/Console/ConsoleEvents.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/ConsoleEvents.php";}s:63:"Symfony/Component/Console/Descriptor/ApplicationDescription.php";a:4:{s:6:"md5sum";s:32:"e5ffa840297bdf9232762c38218846dc";s:4:"name";s:63:"Symfony/Component/Console/Descriptor/ApplicationDescription.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Descriptor/ApplicationDescription.php";}s:51:"Symfony/Component/Console/Descriptor/Descriptor.php";a:4:{s:6:"md5sum";s:32:"e08a534aa99b2e90d1538a0c166973e5";s:4:"name";s:51:"Symfony/Component/Console/Descriptor/Descriptor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Descriptor/Descriptor.php";}s:60:"Symfony/Component/Console/Descriptor/DescriptorInterface.php";a:4:{s:6:"md5sum";s:32:"d5b9abe215ed28ac8ca7fe9d72fc9ddd";s:4:"name";s:60:"Symfony/Component/Console/Descriptor/DescriptorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Descriptor/DescriptorInterface.php";}s:55:"Symfony/Component/Console/Descriptor/JsonDescriptor.php";a:4:{s:6:"md5sum";s:32:"a997223049fcf34294263e3a6c37e230";s:4:"name";s:55:"Symfony/Component/Console/Descriptor/JsonDescriptor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Descriptor/JsonDescriptor.php";}s:59:"Symfony/Component/Console/Descriptor/MarkdownDescriptor.php";a:4:{s:6:"md5sum";s:32:"bec9d13cc9cb6e778c4f4083199137b6";s:4:"name";s:59:"Symfony/Component/Console/Descriptor/MarkdownDescriptor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php";}s:55:"Symfony/Component/Console/Descriptor/TextDescriptor.php";a:4:{s:6:"md5sum";s:32:"97b571928164645af31610ea97bc43fb";s:4:"name";s:55:"Symfony/Component/Console/Descriptor/TextDescriptor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Descriptor/TextDescriptor.php";}s:54:"Symfony/Component/Console/Descriptor/XmlDescriptor.php";a:4:{s:6:"md5sum";s:32:"a9214dd6cf39faa121dc4de62996071a";s:4:"name";s:54:"Symfony/Component/Console/Descriptor/XmlDescriptor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Descriptor/XmlDescriptor.php";}s:55:"Symfony/Component/Console/Event/ConsoleCommandEvent.php";a:4:{s:6:"md5sum";s:32:"2832db2aee4207de5d53d012b314436d";s:4:"name";s:55:"Symfony/Component/Console/Event/ConsoleCommandEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Event/ConsoleCommandEvent.php";}s:48:"Symfony/Component/Console/Event/ConsoleEvent.php";a:4:{s:6:"md5sum";s:32:"aaaa8c390cd99e01d7bb2649a735e469";s:4:"name";s:48:"Symfony/Component/Console/Event/ConsoleEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Event/ConsoleEvent.php";}s:57:"Symfony/Component/Console/Event/ConsoleExceptionEvent.php";a:4:{s:6:"md5sum";s:32:"22e5c027468f33b0bd20540b41af7a74";s:4:"name";s:57:"Symfony/Component/Console/Event/ConsoleExceptionEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Event/ConsoleExceptionEvent.php";}s:57:"Symfony/Component/Console/Event/ConsoleTerminateEvent.php";a:4:{s:6:"md5sum";s:32:"82fbfa586f39a859d66a45221cb773c1";s:4:"name";s:57:"Symfony/Component/Console/Event/ConsoleTerminateEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Event/ConsoleTerminateEvent.php";}s:55:"Symfony/Component/Console/Formatter/OutputFormatter.php";a:4:{s:6:"md5sum";s:32:"304b90bba47ad3ed5534a37ec1647980";s:4:"name";s:55:"Symfony/Component/Console/Formatter/OutputFormatter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Formatter/OutputFormatter.php";}s:64:"Symfony/Component/Console/Formatter/OutputFormatterInterface.php";a:4:{s:6:"md5sum";s:32:"75e7364468e427f080f86354f9bab9b9";s:4:"name";s:64:"Symfony/Component/Console/Formatter/OutputFormatterInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Formatter/OutputFormatterInterface.php";}s:60:"Symfony/Component/Console/Formatter/OutputFormatterStyle.php";a:4:{s:6:"md5sum";s:32:"4d0b8e5a84926a6013be77aa123e61eb";s:4:"name";s:60:"Symfony/Component/Console/Formatter/OutputFormatterStyle.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Formatter/OutputFormatterStyle.php";}s:69:"Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php";a:4:{s:6:"md5sum";s:32:"091bf3ec019e14a48b1f61ef7cb6871a";s:4:"name";s:69:"Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php";}s:65:"Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php";a:4:{s:6:"md5sum";s:32:"27952fd939968e3615ce7ada4c761e0e";s:4:"name";s:65:"Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php";}s:53:"Symfony/Component/Console/Helper/DescriptorHelper.php";a:4:{s:6:"md5sum";s:32:"d5bb73eb73014de416365c07cd81cac5";s:4:"name";s:53:"Symfony/Component/Console/Helper/DescriptorHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper/DescriptorHelper.php";}s:49:"Symfony/Component/Console/Helper/DialogHelper.php";a:4:{s:6:"md5sum";s:32:"ae0bb3641414453024a3d71275abd1c1";s:4:"name";s:49:"Symfony/Component/Console/Helper/DialogHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper/DialogHelper.php";}s:52:"Symfony/Component/Console/Helper/FormatterHelper.php";a:4:{s:6:"md5sum";s:32:"86ebeb32b3353bc7ba4363bf7a05fa2f";s:4:"name";s:52:"Symfony/Component/Console/Helper/FormatterHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper/FormatterHelper.php";}s:43:"Symfony/Component/Console/Helper/Helper.php";a:4:{s:6:"md5sum";s:32:"426298ce1ccd85ab527a5cef78f9a33b";s:4:"name";s:43:"Symfony/Component/Console/Helper/Helper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper/Helper.php";}s:52:"Symfony/Component/Console/Helper/HelperInterface.php";a:4:{s:6:"md5sum";s:32:"e9012e6f3559129d513da4ba75ebf4e9";s:4:"name";s:52:"Symfony/Component/Console/Helper/HelperInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper/HelperInterface.php";}s:46:"Symfony/Component/Console/Helper/HelperSet.php";a:4:{s:6:"md5sum";s:32:"9c0badab04f9b052cec6a06c3f11fb07";s:4:"name";s:46:"Symfony/Component/Console/Helper/HelperSet.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper/HelperSet.php";}s:53:"Symfony/Component/Console/Helper/InputAwareHelper.php";a:4:{s:6:"md5sum";s:32:"c75592e1f3b10c1f35961c50d55ae58d";s:4:"name";s:53:"Symfony/Component/Console/Helper/InputAwareHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper/InputAwareHelper.php";}s:51:"Symfony/Component/Console/Helper/ProgressHelper.php";a:4:{s:6:"md5sum";s:32:"c6c85dbb2f08fa52bc6739ba6896bdc9";s:4:"name";s:51:"Symfony/Component/Console/Helper/ProgressHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper/ProgressHelper.php";}s:48:"Symfony/Component/Console/Helper/TableHelper.php";a:4:{s:6:"md5sum";s:32:"1671e0f028279a642e6c0f7dcaa474c4";s:4:"name";s:48:"Symfony/Component/Console/Helper/TableHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper/TableHelper.php";}s:45:"Symfony/Component/Console/Input/ArgvInput.php";a:4:{s:6:"md5sum";s:32:"e95b97c2b870d6223e84a995c93f16ce";s:4:"name";s:45:"Symfony/Component/Console/Input/ArgvInput.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input/ArgvInput.php";}s:46:"Symfony/Component/Console/Input/ArrayInput.php";a:4:{s:6:"md5sum";s:32:"1e51135fb1c605381452c4d0cae3f1c4";s:4:"name";s:46:"Symfony/Component/Console/Input/ArrayInput.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input/ArrayInput.php";}s:41:"Symfony/Component/Console/Input/Input.php";a:4:{s:6:"md5sum";s:32:"87ba519b169574bdcaabaef68740989a";s:4:"name";s:41:"Symfony/Component/Console/Input/Input.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input/Input.php";}s:49:"Symfony/Component/Console/Input/InputArgument.php";a:4:{s:6:"md5sum";s:32:"c2f88afd2a0f1601dcfd3cce07092197";s:4:"name";s:49:"Symfony/Component/Console/Input/InputArgument.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input/InputArgument.php";}s:55:"Symfony/Component/Console/Input/InputAwareInterface.php";a:4:{s:6:"md5sum";s:32:"a67cb5e626983b20e2c03b618d7ab012";s:4:"name";s:55:"Symfony/Component/Console/Input/InputAwareInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input/InputAwareInterface.php";}s:51:"Symfony/Component/Console/Input/InputDefinition.php";a:4:{s:6:"md5sum";s:32:"74e92dce0c01082eb3d96959f3268509";s:4:"name";s:51:"Symfony/Component/Console/Input/InputDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input/InputDefinition.php";}s:50:"Symfony/Component/Console/Input/InputInterface.php";a:4:{s:6:"md5sum";s:32:"9a40ecfaca79fa6bed0e459c035fdb5c";s:4:"name";s:50:"Symfony/Component/Console/Input/InputInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input/InputInterface.php";}s:47:"Symfony/Component/Console/Input/InputOption.php";a:4:{s:6:"md5sum";s:32:"2712657bb89ede768dfb9d0eb1f1d256";s:4:"name";s:47:"Symfony/Component/Console/Input/InputOption.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input/InputOption.php";}s:47:"Symfony/Component/Console/Input/StringInput.php";a:4:{s:6:"md5sum";s:32:"eaf496e1188492448d9cfe8dfbcede6a";s:4:"name";s:47:"Symfony/Component/Console/Input/StringInput.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input/StringInput.php";}s:33:"Symfony/Component/Console/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:33:"Symfony/Component/Console/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/Console/Symfony/Component/Console/LICENSE";}s:51:"Symfony/Component/Console/Output/BufferedOutput.php";a:4:{s:6:"md5sum";s:32:"07bca2bc77753b0b0cc4502f109c4a8e";s:4:"name";s:51:"Symfony/Component/Console/Output/BufferedOutput.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Output/BufferedOutput.php";}s:50:"Symfony/Component/Console/Output/ConsoleOutput.php";a:4:{s:6:"md5sum";s:32:"64e00ce49a3a47e8ea7b8885f10c1ee6";s:4:"name";s:50:"Symfony/Component/Console/Output/ConsoleOutput.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Output/ConsoleOutput.php";}s:59:"Symfony/Component/Console/Output/ConsoleOutputInterface.php";a:4:{s:6:"md5sum";s:32:"9cf400160437ff90febb665841a968fe";s:4:"name";s:59:"Symfony/Component/Console/Output/ConsoleOutputInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Output/ConsoleOutputInterface.php";}s:47:"Symfony/Component/Console/Output/NullOutput.php";a:4:{s:6:"md5sum";s:32:"561f460b93be0c27aa9be546af49e9ec";s:4:"name";s:47:"Symfony/Component/Console/Output/NullOutput.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Output/NullOutput.php";}s:43:"Symfony/Component/Console/Output/Output.php";a:4:{s:6:"md5sum";s:32:"15c209a7581a632e6979d5441a02f241";s:4:"name";s:43:"Symfony/Component/Console/Output/Output.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Output/Output.php";}s:52:"Symfony/Component/Console/Output/OutputInterface.php";a:4:{s:6:"md5sum";s:32:"ac6d776cf82c8b887395c54482f17bd7";s:4:"name";s:52:"Symfony/Component/Console/Output/OutputInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Output/OutputInterface.php";}s:49:"Symfony/Component/Console/Output/StreamOutput.php";a:4:{s:6:"md5sum";s:32:"dc57630f625779ad86f6f3d8240ad0c3";s:4:"name";s:49:"Symfony/Component/Console/Output/StreamOutput.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Output/StreamOutput.php";}s:42:"Symfony/Component/Console/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"c94fc23909e8f1d27908cd0486653611";s:4:"name";s:42:"Symfony/Component/Console/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/phpunit.xml.dist";}s:35:"Symfony/Component/Console/README.md";a:4:{s:6:"md5sum";s:32:"70a92aecafcdc1f689a2a798acccefe4";s:4:"name";s:35:"Symfony/Component/Console/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/doc/pear/Console/Symfony/Component/Console/README.md";}s:55:"Symfony/Component/Console/Resources/bin/hiddeninput.exe";a:4:{s:6:"md5sum";s:32:"3613d8d83b78ce3561680a447eb6a24a";s:4:"name";s:55:"Symfony/Component/Console/Resources/bin/hiddeninput.exe";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Resources/bin/hiddeninput.exe";}s:35:"Symfony/Component/Console/Shell.php";a:4:{s:6:"md5sum";s:32:"fedc847f6c992a242e45a167b0cf1866";s:4:"name";s:35:"Symfony/Component/Console/Shell.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Shell.php";}s:54:"Symfony/Component/Console/Tester/ApplicationTester.php";a:4:{s:6:"md5sum";s:32:"f2c7b88716f13cb54825a933832a74a8";s:4:"name";s:54:"Symfony/Component/Console/Tester/ApplicationTester.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Tester/ApplicationTester.php";}s:50:"Symfony/Component/Console/Tester/CommandTester.php";a:4:{s:6:"md5sum";s:32:"9b7bf197b61b1b3c23772c57a2ec3ee5";s:4:"name";s:50:"Symfony/Component/Console/Tester/CommandTester.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Tester/CommandTester.php";}s:51:"Symfony/Component/Console/Tests/ApplicationTest.php";a:4:{s:6:"md5sum";s:32:"4113e99075832dfdf616eb1d40466b5f";s:4:"name";s:51:"Symfony/Component/Console/Tests/ApplicationTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/ApplicationTest.php";}s:55:"Symfony/Component/Console/Tests/Command/CommandTest.php";a:4:{s:6:"md5sum";s:32:"95ad26aa722775521f90d097b79d23b7";s:4:"name";s:55:"Symfony/Component/Console/Tests/Command/CommandTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Command/CommandTest.php";}s:59:"Symfony/Component/Console/Tests/Command/HelpCommandTest.php";a:4:{s:6:"md5sum";s:32:"e8f9a01b23091cef3ed6346feaf38b9c";s:4:"name";s:59:"Symfony/Component/Console/Tests/Command/HelpCommandTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Command/HelpCommandTest.php";}s:59:"Symfony/Component/Console/Tests/Command/ListCommandTest.php";a:4:{s:6:"md5sum";s:32:"e7562df5cc8110fb5a6e44cbc39a7c03";s:4:"name";s:59:"Symfony/Component/Console/Tests/Command/ListCommandTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Command/ListCommandTest.php";}s:69:"Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.php";a:4:{s:6:"md5sum";s:32:"531b8d11ed5d639162a8cbc8c1b7fe53";s:4:"name";s:69:"Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.php";}s:65:"Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php";a:4:{s:6:"md5sum";s:32:"8b6ccffc99cb2ffea82e6e65171dc329";s:4:"name";s:65:"Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php";}s:69:"Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.php";a:4:{s:6:"md5sum";s:32:"0738e024a2a5fd48f033acec21ebe484";s:4:"name";s:69:"Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.php";}s:62:"Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php";a:4:{s:6:"md5sum";s:32:"e364df76cc57c1a8221422eac8425501";s:4:"name";s:62:"Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php";}s:65:"Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.php";a:4:{s:6:"md5sum";s:32:"a5a110579ab493bc21572ec836e8b94e";s:4:"name";s:65:"Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.php";}s:64:"Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.php";a:4:{s:6:"md5sum";s:32:"aa6b0e47cc2693587024ee3d9b2efc6c";s:4:"name";s:64:"Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.php";}s:59:"Symfony/Component/Console/Tests/Fixtures/application_1.json";a:4:{s:6:"md5sum";s:32:"ea331a512e8c0d80230ff1f7b1254316";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/application_1.json";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.json";}s:57:"Symfony/Component/Console/Tests/Fixtures/application_1.md";a:4:{s:6:"md5sum";s:32:"2e34db40b7841a8df627415fd72762df";s:4:"name";s:57:"Symfony/Component/Console/Tests/Fixtures/application_1.md";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.md";}s:58:"Symfony/Component/Console/Tests/Fixtures/application_1.txt";a:4:{s:6:"md5sum";s:32:"3d936937d3bcf607fc54faad2558a453";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/application_1.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.txt";}s:58:"Symfony/Component/Console/Tests/Fixtures/application_1.xml";a:4:{s:6:"md5sum";s:32:"d819500ef4e850b75c623682dc38c900";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/application_1.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.xml";}s:59:"Symfony/Component/Console/Tests/Fixtures/application_2.json";a:4:{s:6:"md5sum";s:32:"c461b890d0d7849cfb5eb5bbbc113e66";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/application_2.json";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.json";}s:57:"Symfony/Component/Console/Tests/Fixtures/application_2.md";a:4:{s:6:"md5sum";s:32:"fd2188a4c78bd7bc1a3778a0af6311c5";s:4:"name";s:57:"Symfony/Component/Console/Tests/Fixtures/application_2.md";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.md";}s:58:"Symfony/Component/Console/Tests/Fixtures/application_2.txt";a:4:{s:6:"md5sum";s:32:"d66df90611c1e4fc0161d4307d18ece1";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/application_2.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.txt";}s:58:"Symfony/Component/Console/Tests/Fixtures/application_2.xml";a:4:{s:6:"md5sum";s:32:"d9d7ea7073a523ad2a07ae345b22316f";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/application_2.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.xml";}s:64:"Symfony/Component/Console/Tests/Fixtures/application_astext1.txt";a:4:{s:6:"md5sum";s:32:"b40b7c5e2ce450d92801ad9f5420ea77";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/application_astext1.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_astext1.txt";}s:64:"Symfony/Component/Console/Tests/Fixtures/application_astext2.txt";a:4:{s:6:"md5sum";s:32:"345da50027f0969cf6b362f3f9088186";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/application_astext2.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_astext2.txt";}s:63:"Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt";a:4:{s:6:"md5sum";s:32:"507250131eb057d025531c669a4aab19";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt";}s:63:"Symfony/Component/Console/Tests/Fixtures/application_asxml2.txt";a:4:{s:6:"md5sum";s:32:"fd7e97279731abc448a7577095054ca8";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/application_asxml2.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txt";}s:64:"Symfony/Component/Console/Tests/Fixtures/application_gethelp.txt";a:4:{s:6:"md5sum";s:32:"aa0a9b41081ebab06350041597bd4542";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/application_gethelp.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_gethelp.txt";}s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt";a:4:{s:6:"md5sum";s:32:"977a66011fcade49927bb6ac41477792";s:4:"name";s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt";}s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt";a:4:{s:6:"md5sum";s:32:"38d86d41d4fb194a695eaddfe2a8d2df";s:4:"name";s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt";}s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt";a:4:{s:6:"md5sum";s:32:"711b8a7b6ec59bb13332c79763666e14";s:4:"name";s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt";}s:82:"Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt";a:4:{s:6:"md5sum";s:32:"037657ca60cd7c8ff945ce145684aec6";s:4:"name";s:82:"Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt";}s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt";a:4:{s:6:"md5sum";s:32:"0b5b31d2023ae8ec6e2eef0e08e0400c";s:4:"name";s:73:"Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt";}s:61:"Symfony/Component/Console/Tests/Fixtures/application_run1.txt";a:4:{s:6:"md5sum";s:32:"47745f267210a2e2fb9860082194efd2";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/application_run1.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_run1.txt";}s:61:"Symfony/Component/Console/Tests/Fixtures/application_run2.txt";a:4:{s:6:"md5sum";s:32:"ff916ea07ab6a3777814eafa148c9c34";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/application_run2.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_run2.txt";}s:61:"Symfony/Component/Console/Tests/Fixtures/application_run3.txt";a:4:{s:6:"md5sum";s:32:"e1651d791eebaeed9a568412fe433ce2";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/application_run3.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_run3.txt";}s:61:"Symfony/Component/Console/Tests/Fixtures/application_run4.txt";a:4:{s:6:"md5sum";s:32:"c7759de3fcd0263d72d1fad2390dc914";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/application_run4.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/application_run4.txt";}s:58:"Symfony/Component/Console/Tests/Fixtures/BarBucCommand.php";a:4:{s:6:"md5sum";s:32:"5bb7afd8d7266c4b53acdd0ba4bc87ce";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/BarBucCommand.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/BarBucCommand.php";}s:55:"Symfony/Component/Console/Tests/Fixtures/command_1.json";a:4:{s:6:"md5sum";s:32:"8464fa011bb28109fd087727f1216458";s:4:"name";s:55:"Symfony/Component/Console/Tests/Fixtures/command_1.json";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.json";}s:53:"Symfony/Component/Console/Tests/Fixtures/command_1.md";a:4:{s:6:"md5sum";s:32:"44b8f270513ba511d0d971b52b2396d6";s:4:"name";s:53:"Symfony/Component/Console/Tests/Fixtures/command_1.md";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.md";}s:54:"Symfony/Component/Console/Tests/Fixtures/command_1.txt";a:4:{s:6:"md5sum";s:32:"40f52be95eb599167faf4fb1382e93e7";s:4:"name";s:54:"Symfony/Component/Console/Tests/Fixtures/command_1.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.txt";}s:54:"Symfony/Component/Console/Tests/Fixtures/command_1.xml";a:4:{s:6:"md5sum";s:32:"d4a21bb6906c17693a2cf2d990f17441";s:4:"name";s:54:"Symfony/Component/Console/Tests/Fixtures/command_1.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.xml";}s:55:"Symfony/Component/Console/Tests/Fixtures/command_2.json";a:4:{s:6:"md5sum";s:32:"8ff624584c774ae83144627314d66587";s:4:"name";s:55:"Symfony/Component/Console/Tests/Fixtures/command_2.json";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.json";}s:53:"Symfony/Component/Console/Tests/Fixtures/command_2.md";a:4:{s:6:"md5sum";s:32:"65763c3a87b5e2a625fdd143edaf03fe";s:4:"name";s:53:"Symfony/Component/Console/Tests/Fixtures/command_2.md";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.md";}s:54:"Symfony/Component/Console/Tests/Fixtures/command_2.txt";a:4:{s:6:"md5sum";s:32:"5680ffddd8fc44a29d0ea39f9ab09906";s:4:"name";s:54:"Symfony/Component/Console/Tests/Fixtures/command_2.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.txt";}s:54:"Symfony/Component/Console/Tests/Fixtures/command_2.xml";a:4:{s:6:"md5sum";s:32:"8cac2b7fac663f8d0fd15c22f1160981";s:4:"name";s:54:"Symfony/Component/Console/Tests/Fixtures/command_2.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.xml";}s:59:"Symfony/Component/Console/Tests/Fixtures/command_astext.txt";a:4:{s:6:"md5sum";s:32:"ac50a755a5dcf9dbbf7d03564c134b5c";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/command_astext.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_astext.txt";}s:58:"Symfony/Component/Console/Tests/Fixtures/command_asxml.txt";a:4:{s:6:"md5sum";s:32:"d94936284533d2495f2eb207fa02e232";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/command_asxml.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/command_asxml.txt";}s:62:"Symfony/Component/Console/Tests/Fixtures/definition_astext.txt";a:4:{s:6:"md5sum";s:32:"6a54005ec1a08c1a7f9d7b098dec09f3";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/definition_astext.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/definition_astext.txt";}s:61:"Symfony/Component/Console/Tests/Fixtures/definition_asxml.txt";a:4:{s:6:"md5sum";s:32:"205994db49721172eac27b69ff37ec4f";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/definition_asxml.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/definition_asxml.txt";}s:67:"Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php";a:4:{s:6:"md5sum";s:32:"cb827ac9aecc15b6592f8c153317b31d";s:4:"name";s:67:"Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php";}s:67:"Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php";a:4:{s:6:"md5sum";s:32:"d929bab60eb3fd020e15b45a3c54d168";s:4:"name";s:67:"Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php";}s:63:"Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php";a:4:{s:6:"md5sum";s:32:"50c23e03725ffd75f65d76b07e71887a";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php";}s:63:"Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php";a:4:{s:6:"md5sum";s:32:"8cc36b0c8be8ac7db7897d5ac4eee699";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php";}s:56:"Symfony/Component/Console/Tests/Fixtures/Foo1Command.php";a:4:{s:6:"md5sum";s:32:"df52584a64822a983eb5d927acedb8c1";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo1Command.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/Foo1Command.php";}s:56:"Symfony/Component/Console/Tests/Fixtures/Foo2Command.php";a:4:{s:6:"md5sum";s:32:"cf36c22795c10c04984b683ff3f1fe79";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo2Command.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/Foo2Command.php";}s:56:"Symfony/Component/Console/Tests/Fixtures/Foo3Command.php";a:4:{s:6:"md5sum";s:32:"14ec4962d6e9d9be56dbb5a90f1c01bc";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo3Command.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/Foo3Command.php";}s:56:"Symfony/Component/Console/Tests/Fixtures/Foo4Command.php";a:4:{s:6:"md5sum";s:32:"a747ae989c89cbff1df48d301d69ff9a";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo4Command.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/Foo4Command.php";}s:56:"Symfony/Component/Console/Tests/Fixtures/Foo5Command.php";a:4:{s:6:"md5sum";s:32:"ab33a181019dd14b892e920906a83e41";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/Foo5Command.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/Foo5Command.php";}s:58:"Symfony/Component/Console/Tests/Fixtures/FoobarCommand.php";a:4:{s:6:"md5sum";s:32:"c409f073d1a760445d7c692bf6668848";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/FoobarCommand.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/FoobarCommand.php";}s:55:"Symfony/Component/Console/Tests/Fixtures/FooCommand.php";a:4:{s:6:"md5sum";s:32:"45276372456804d1c3cc11c30e1e26e4";s:4:"name";s:55:"Symfony/Component/Console/Tests/Fixtures/FooCommand.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/FooCommand.php";}s:62:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.json";a:4:{s:6:"md5sum";s:32:"87e6eeef0f89e57d691ca8a35bb91e12";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.json";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.json";}s:60:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.md";a:4:{s:6:"md5sum";s:32:"f51385902d2eb98e5c7236b26f720741";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.md";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.md";}s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.txt";a:4:{s:6:"md5sum";s:32:"49ec5d491a17d9f6c93e3b6194757de0";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.txt";}s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.xml";a:4:{s:6:"md5sum";s:32:"0c308f004edf7c0b6aaec03f028e8747";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_1.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.xml";}s:62:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.json";a:4:{s:6:"md5sum";s:32:"7b189366871c1bb8b146087dcc1b20cf";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.json";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.json";}s:60:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.md";a:4:{s:6:"md5sum";s:32:"3f2fd328c9393a8ede70602631d68c9f";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.md";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.md";}s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.txt";a:4:{s:6:"md5sum";s:32:"c4567546600e6c71ee236a870b9a5d16";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.txt";}s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.xml";a:4:{s:6:"md5sum";s:32:"57a965ef131103e13d8befdb1a0e8465";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_2.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.xml";}s:62:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.json";a:4:{s:6:"md5sum";s:32:"eacb43809707dd26dcb8a0c34f1cd337";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.json";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.json";}s:60:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.md";a:4:{s:6:"md5sum";s:32:"92b02b5435642c4f31ccc943b751c30e";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.md";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.md";}s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.txt";a:4:{s:6:"md5sum";s:32:"e512053db481dbd2ac228f790e4a5c31";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.txt";}s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.xml";a:4:{s:6:"md5sum";s:32:"4b5eacb65951dd1047832992de231669";s:4:"name";s:61:"Symfony/Component/Console/Tests/Fixtures/input_argument_3.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.xml";}s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.json";a:4:{s:6:"md5sum";s:32:"6b6cd5a30b7f04a27b3615fcb66fbb60";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.json";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.json";}s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.md";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.md";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.md";}s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.txt";}s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.xml";a:4:{s:6:"md5sum";s:32:"d1ccbc21759a3a9fbf5c8540d9083f47";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_1.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.xml";}s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.json";a:4:{s:6:"md5sum";s:32:"96c29539ac20c5289ce924a2b53e0a74";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.json";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.json";}s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.md";a:4:{s:6:"md5sum";s:32:"65e283e532971f65a0531cef86ec1ff7";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.md";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.md";}s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.txt";a:4:{s:6:"md5sum";s:32:"63bc1a5ff3064f65a2acd1f3fe791164";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.txt";}s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.xml";a:4:{s:6:"md5sum";s:32:"a856c4c0e7a21895a75fccd1f7ad9652";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_2.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.xml";}s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.json";a:4:{s:6:"md5sum";s:32:"e3e2853d5735de1d839b7378cea925f6";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.json";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.json";}s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.md";a:4:{s:6:"md5sum";s:32:"cf4db1e7e783877fedcc11f228f057f7";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.md";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.md";}s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.txt";a:4:{s:6:"md5sum";s:32:"6517879eab6c613d4ccc9e8f11dc00cc";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.txt";}s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.xml";a:4:{s:6:"md5sum";s:32:"cf9890033c9b3296c3f0a84ad7a40f26";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_3.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.xml";}s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.json";a:4:{s:6:"md5sum";s:32:"a0d3b5beb936e28bcfa0b2a09038e477";s:4:"name";s:64:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.json";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.json";}s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.md";a:4:{s:6:"md5sum";s:32:"55bdf86d23a2c802d4c7d36922a16cc8";s:4:"name";s:62:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.md";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.md";}s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.txt";a:4:{s:6:"md5sum";s:32:"6a351cab07e83967475ce418f11389c9";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.txt";}s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.xml";a:4:{s:6:"md5sum";s:32:"732625b8bef91e2b6e5e42b135714673";s:4:"name";s:63:"Symfony/Component/Console/Tests/Fixtures/input_definition_4.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.xml";}s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_1.json";a:4:{s:6:"md5sum";s:32:"275c5ca8fae2603962435abee86abc22";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_1.json";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.json";}s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_1.md";a:4:{s:6:"md5sum";s:32:"2f3b3fce4e6cc97d37c2cdf2a8545a17";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_1.md";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.md";}s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_1.txt";a:4:{s:6:"md5sum";s:32:"7c446b0b7764679b0675e2bf7c15d5ef";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_1.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.txt";}s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_1.xml";a:4:{s:6:"md5sum";s:32:"2441944e792817317e54ca3e6bf3478a";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_1.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.xml";}s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_2.json";a:4:{s:6:"md5sum";s:32:"8ad4b5bb7f68b81ac5baf6f86c54f216";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_2.json";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.json";}s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_2.md";a:4:{s:6:"md5sum";s:32:"febad80dc8502990d7631dfa7e710725";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_2.md";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.md";}s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_2.txt";a:4:{s:6:"md5sum";s:32:"4cebdddb6ee8776268fe824f5ebc8b14";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_2.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.txt";}s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_2.xml";a:4:{s:6:"md5sum";s:32:"ad9f550cbdd67e7bda7bfb78ebbc4d57";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_2.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.xml";}s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_3.json";a:4:{s:6:"md5sum";s:32:"2eb676e70f06dff589fc461b96da5c61";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_3.json";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.json";}s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_3.md";a:4:{s:6:"md5sum";s:32:"03a09ae47b81986ec50edd6608fa2426";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_3.md";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.md";}s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_3.txt";a:4:{s:6:"md5sum";s:32:"7eada46556b0ce341069f353b063e45e";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_3.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.txt";}s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_3.xml";a:4:{s:6:"md5sum";s:32:"8c91b697596ccf87b48c58ecbae02aa6";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_3.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.xml";}s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_4.json";a:4:{s:6:"md5sum";s:32:"20c72909569d5ec92465f7c7dc002381";s:4:"name";s:60:"Symfony/Component/Console/Tests/Fixtures/input_option_4.json";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.json";}s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_4.md";a:4:{s:6:"md5sum";s:32:"4b02ffc507306a9d887e73d2fca429ba";s:4:"name";s:58:"Symfony/Component/Console/Tests/Fixtures/input_option_4.md";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.md";}s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_4.txt";a:4:{s:6:"md5sum";s:32:"7d49ce52263e22bbdd37e687455478ea";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_4.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.txt";}s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_4.xml";a:4:{s:6:"md5sum";s:32:"960e79c93c46361c3bd250b5fe73d25b";s:4:"name";s:59:"Symfony/Component/Console/Tests/Fixtures/input_option_4.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.xml";}s:56:"Symfony/Component/Console/Tests/Fixtures/TestCommand.php";a:4:{s:6:"md5sum";s:32:"cdfd10039b833b3d0cd4bc946d6d0e52";s:4:"name";s:56:"Symfony/Component/Console/Tests/Fixtures/TestCommand.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures/TestCommand.php";}s:75:"Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleStackTest.php";a:4:{s:6:"md5sum";s:32:"d65f80f685c098367d357b79b1085660";s:4:"name";s:75:"Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleStackTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleStackTest.php";}s:70:"Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleTest.php";a:4:{s:6:"md5sum";s:32:"772ad7157614e0a3336b0e79bfd8c018";s:4:"name";s:70:"Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleTest.php";}s:65:"Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php";a:4:{s:6:"md5sum";s:32:"1932fadfa3ba33810457dc7c7caf4200";s:4:"name";s:65:"Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php";}s:59:"Symfony/Component/Console/Tests/Helper/DialogHelperTest.php";a:4:{s:6:"md5sum";s:32:"c080187a3a540acbd38ea4e72e197073";s:4:"name";s:59:"Symfony/Component/Console/Tests/Helper/DialogHelperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php";}s:62:"Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php";a:4:{s:6:"md5sum";s:32:"caffe5a35cfde20acff28a1b2ede9523";s:4:"name";s:62:"Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php";}s:56:"Symfony/Component/Console/Tests/Helper/HelperSetTest.php";a:4:{s:6:"md5sum";s:32:"0c4b855c7ad31b88262a32f083903d5b";s:4:"name";s:56:"Symfony/Component/Console/Tests/Helper/HelperSetTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Helper/HelperSetTest.php";}s:61:"Symfony/Component/Console/Tests/Helper/ProgressHelperTest.php";a:4:{s:6:"md5sum";s:32:"8d460c56a019e5bfd59f1d2d91970812";s:4:"name";s:61:"Symfony/Component/Console/Tests/Helper/ProgressHelperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.php";}s:58:"Symfony/Component/Console/Tests/Helper/TableHelperTest.php";a:4:{s:6:"md5sum";s:32:"7c598e6ffdbd3c17865a4c54cbe34c78";s:4:"name";s:58:"Symfony/Component/Console/Tests/Helper/TableHelperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Helper/TableHelperTest.php";}s:55:"Symfony/Component/Console/Tests/Input/ArgvInputTest.php";a:4:{s:6:"md5sum";s:32:"2d5b2e942330756fcbc30062e9007f1e";s:4:"name";s:55:"Symfony/Component/Console/Tests/Input/ArgvInputTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Input/ArgvInputTest.php";}s:56:"Symfony/Component/Console/Tests/Input/ArrayInputTest.php";a:4:{s:6:"md5sum";s:32:"a90b8bafe8ede004c6ed61ecc8224a3f";s:4:"name";s:56:"Symfony/Component/Console/Tests/Input/ArrayInputTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Input/ArrayInputTest.php";}s:59:"Symfony/Component/Console/Tests/Input/InputArgumentTest.php";a:4:{s:6:"md5sum";s:32:"7fe249cea32fc176d04f2520a018bdd8";s:4:"name";s:59:"Symfony/Component/Console/Tests/Input/InputArgumentTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Input/InputArgumentTest.php";}s:61:"Symfony/Component/Console/Tests/Input/InputDefinitionTest.php";a:4:{s:6:"md5sum";s:32:"debb5202554762ad79bbd9353fcd04b7";s:4:"name";s:61:"Symfony/Component/Console/Tests/Input/InputDefinitionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Input/InputDefinitionTest.php";}s:57:"Symfony/Component/Console/Tests/Input/InputOptionTest.php";a:4:{s:6:"md5sum";s:32:"b6f2af5b4b79ed25113742022e86c77a";s:4:"name";s:57:"Symfony/Component/Console/Tests/Input/InputOptionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Input/InputOptionTest.php";}s:51:"Symfony/Component/Console/Tests/Input/InputTest.php";a:4:{s:6:"md5sum";s:32:"f9129bb377ebb93a88cfcc97795055ff";s:4:"name";s:51:"Symfony/Component/Console/Tests/Input/InputTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Input/InputTest.php";}s:57:"Symfony/Component/Console/Tests/Input/StringInputTest.php";a:4:{s:6:"md5sum";s:32:"6d3e24ab1bdf3f1048c89aded3fdfc42";s:4:"name";s:57:"Symfony/Component/Console/Tests/Input/StringInputTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Input/StringInputTest.php";}s:60:"Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php";a:4:{s:6:"md5sum";s:32:"5f42c7a490159ffee9e4d44297f6cbb0";s:4:"name";s:60:"Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php";}s:57:"Symfony/Component/Console/Tests/Output/NullOutputTest.php";a:4:{s:6:"md5sum";s:32:"3b663167dfed0b653e8bc70890b8d417";s:4:"name";s:57:"Symfony/Component/Console/Tests/Output/NullOutputTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Output/NullOutputTest.php";}s:53:"Symfony/Component/Console/Tests/Output/OutputTest.php";a:4:{s:6:"md5sum";s:32:"eb5d8d732894bc94242983e61d9ea828";s:4:"name";s:53:"Symfony/Component/Console/Tests/Output/OutputTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Output/OutputTest.php";}s:59:"Symfony/Component/Console/Tests/Output/StreamOutputTest.php";a:4:{s:6:"md5sum";s:32:"d9e51b68858e010abf7c9856411f9f3e";s:4:"name";s:59:"Symfony/Component/Console/Tests/Output/StreamOutputTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Output/StreamOutputTest.php";}s:64:"Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.php";a:4:{s:6:"md5sum";s:32:"ed2c4ba2123801176abd8f7b15cfce2e";s:4:"name";s:64:"Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.php";}s:60:"Symfony/Component/Console/Tests/Tester/CommandTesterTest.php";a:4:{s:6:"md5sum";s:32:"dc805845c9fb25bf57604fda8b19c86d";s:4:"name";s:60:"Symfony/Component/Console/Tests/Tester/CommandTesterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Tester/CommandTesterTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:30:{s:55:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:67:"/opt/alt/php54/usr/share/doc/pear/Console/Symfony/Component/Console";b:1;s:59:"/opt/alt/php54/usr/share/doc/pear/Console/Symfony/Component";b:1;s:49:"/opt/alt/php54/usr/share/doc/pear/Console/Symfony";b:1;s:41:"/opt/alt/php54/usr/share/doc/pear/Console";b:1;s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Command";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Descriptor";b:1;s:61:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Event";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Formatter";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Helper";b:1;s:61:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Input";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Output";b:1;s:68:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console";b:1;s:60:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component";b:1;s:50:"/opt/alt/php54/usr/share/pear/test/Console/Symfony";b:1;s:42:"/opt/alt/php54/usr/share/pear/test/Console";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Resources/bin";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Resources";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Console/Tester";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests";b:1;s:82:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Command";b:1;s:85:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Descriptor";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Fixtures";b:1;s:84:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Formatter";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Helper";b:1;s:80:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Input";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Output";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Console/Symfony/Component/Console/Tests/Tester";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506492;}PK!!6d d 3.registry/.channel.pear.symfony.com/translation.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:11:"Translation";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:30:"Symfony2 Translation Component";s:11:"description";s:30:"Symfony2 Translation Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:50";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:119:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a23a3ebc32ad216eceb315d156d172df";s:4:"name";s:44:"Symfony/Component/Translation/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1b1901736a193dd839f00675dbe001e1";s:4:"name";s:61:"Symfony/Component/Translation/Catalogue/AbstractOperation.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1facd3924e3312ac6a9f6b9f586d84ae";s:4:"name";s:57:"Symfony/Component/Translation/Catalogue/DiffOperation.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c697c25f56c1bc59faffd23ae1bf5910";s:4:"name";s:58:"Symfony/Component/Translation/Catalogue/MergeOperation.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6b00bea9c66c6934740b6f5735573ed1";s:4:"name";s:62:"Symfony/Component/Translation/Catalogue/OperationInterface.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"33507730a223e93eab19a4481c82d258";s:4:"name";s:42:"Symfony/Component/Translation/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"08bb0002b0d0c9ef06a74417374b0db0";s:4:"name";s:43:"Symfony/Component/Translation/composer.json";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"af3a8b385fed749c0606e72124fc01c8";s:4:"name";s:54:"Symfony/Component/Translation/Dumper/CsvFileDumper.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"97df468b756ed060c2d9002ffb331f4c";s:4:"name";s:56:"Symfony/Component/Translation/Dumper/DumperInterface.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dd3b41f5ce0c7514217ae51ee01fd9b3";s:4:"name";s:51:"Symfony/Component/Translation/Dumper/FileDumper.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a2a5ea6e4a593fdb3ac4eb52b08c8fca";s:4:"name";s:57:"Symfony/Component/Translation/Dumper/IcuResFileDumper.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa41a897df4b252a6763a7206a64740e";s:4:"name";s:54:"Symfony/Component/Translation/Dumper/IniFileDumper.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"590cefb5e2fdc8d5163101d1dea6c00c";s:4:"name";s:55:"Symfony/Component/Translation/Dumper/JsonFileDumper.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b221f1f93992940b41df842c71612a08";s:4:"name";s:53:"Symfony/Component/Translation/Dumper/MoFileDumper.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a4faacf4648772530eddd7b531a914e";s:4:"name";s:54:"Symfony/Component/Translation/Dumper/PhpFileDumper.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"151ba9edbfad4aad3a01404ed2d08aed";s:4:"name";s:53:"Symfony/Component/Translation/Dumper/PoFileDumper.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"97630cc685afa03a45769ce3c0c2d7b6";s:4:"name";s:53:"Symfony/Component/Translation/Dumper/QtFileDumper.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c50058cbe84ee0d6bc0c4291ac3c89e4";s:4:"name";s:56:"Symfony/Component/Translation/Dumper/XliffFileDumper.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6cb4733897f48f15596acd385bf27e6b";s:4:"name";s:55:"Symfony/Component/Translation/Dumper/YamlFileDumper.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3f815f25d3ba7fb52caf40896c1a3bfe";s:4:"name";s:62:"Symfony/Component/Translation/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2107111761ca276662adca40be545bbe";s:4:"name";s:68:"Symfony/Component/Translation/Exception/InvalidResourceException.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7022eff2bccadddbd74f490fb372cf54";s:4:"name";s:69:"Symfony/Component/Translation/Exception/NotFoundResourceException.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4594ea6e9bb83b2e11669b85cc5124fa";s:4:"name";s:58:"Symfony/Component/Translation/Extractor/ChainExtractor.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63c8d0cc53c869dc53eddb8bf644694a";s:4:"name";s:62:"Symfony/Component/Translation/Extractor/ExtractorInterface.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"be99041f6caf9560d052545df078a511";s:4:"name";s:52:"Symfony/Component/Translation/IdentityTranslator.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"84efe2082056a419a58c16cb7735ca56";s:4:"name";s:42:"Symfony/Component/Translation/Interval.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:37:"Symfony/Component/Translation/LICENSE";s:4:"role";s:3:"doc";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d6585b0daa5d9b9dbd3aec8f1333b890";s:4:"name";s:52:"Symfony/Component/Translation/Loader/ArrayLoader.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6ceb1af587dc0cc6c6545852f2b9f89b";s:4:"name";s:54:"Symfony/Component/Translation/Loader/CsvFileLoader.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ecc212d52f34f5ad922845af7d071fe7";s:4:"name";s:57:"Symfony/Component/Translation/Loader/IcuDatFileLoader.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"66f2c067c6e251949024920f3bb13578";s:4:"name";s:57:"Symfony/Component/Translation/Loader/IcuResFileLoader.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d9f98317740467a87c342bd7e44a2faa";s:4:"name";s:54:"Symfony/Component/Translation/Loader/IniFileLoader.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b744ab916a07e52c924b2d9712172e9";s:4:"name";s:55:"Symfony/Component/Translation/Loader/JsonFileLoader.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d375de50d632c97a369003780044ef6";s:4:"name";s:56:"Symfony/Component/Translation/Loader/LoaderInterface.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"00cd7c30a5185244b22912679da90d12";s:4:"name";s:53:"Symfony/Component/Translation/Loader/MoFileLoader.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bb211aa1fd5d3d46d8f9fc2e0b630bbb";s:4:"name";s:54:"Symfony/Component/Translation/Loader/PhpFileLoader.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7c81a6760f547728df4c0e7137c92cf7";s:4:"name";s:53:"Symfony/Component/Translation/Loader/PoFileLoader.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"50a221b191e5f83a44b03dfa6195ef3c";s:4:"name";s:53:"Symfony/Component/Translation/Loader/QtFileLoader.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fd528a896f7c6792b370930f64e58a2a";s:4:"name";s:84:"Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8b0466500a88d4e511342b555534b991";s:4:"name";s:66:"Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsd";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6f15280899bde6a3c9edb8d87ea9b092";s:4:"name";s:56:"Symfony/Component/Translation/Loader/XliffFileLoader.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d468c9ed70a982ce1a2efc681d674673";s:4:"name";s:55:"Symfony/Component/Translation/Loader/YamlFileLoader.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d151ded1a0038bed7f8c790384cb7eed";s:4:"name";s:50:"Symfony/Component/Translation/MessageCatalogue.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2204344dcccad5c042762fc39952f2a";s:4:"name";s:59:"Symfony/Component/Translation/MessageCatalogueInterface.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"52bef5f54fe4cf887d90872acba99605";s:4:"name";s:49:"Symfony/Component/Translation/MessageSelector.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"307866c58d58dd1e9370ad0d2c9b172a";s:4:"name";s:56:"Symfony/Component/Translation/MetadataAwareInterface.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"10d8a0a424c95688c056eaf8607eb645";s:4:"name";s:46:"Symfony/Component/Translation/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"72406471bc239d6b3346ca064f67b7aa";s:4:"name";s:52:"Symfony/Component/Translation/PluralizationRules.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cbcc27d78c155093251fccc294affb72";s:4:"name";s:39:"Symfony/Component/Translation/README.md";s:4:"role";s:3:"doc";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ef82bc07c69b7711d658500ab7dd1726";s:4:"name";s:71:"Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.php";s:4:"role";s:4:"test";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba72862554b59d792638dd7bbab730f9";s:4:"name";s:67:"Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.php";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47b9f33d19218deaf1497d67c08212c4";s:4:"name";s:68:"Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.php";s:4:"role";s:4:"test";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"44032d28b28576fee4042715bbacf582";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.php";s:4:"role";s:4:"test";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c9821802aa5b2075947b3154d4d111a9";s:4:"name";s:67:"Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.php";s:4:"role";s:4:"test";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b655aaa49e41936ffe308420769beead";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.php";s:4:"role";s:4:"test";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7777f4777f747b0d66a09b38aba33417";s:4:"name";s:65:"Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.php";s:4:"role";s:4:"test";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3691ee670197459ebef5ec634245d931";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.php";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f5359d8c55084adf386b7a09f084a314";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.php";s:4:"role";s:4:"test";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f61a83220a0aa1785ea3f8b718cbaed0";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php";s:4:"role";s:4:"test";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4f15fb0434c84bfda4ce4c7d838f134b";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.php";s:4:"role";s:4:"test";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fa10f05c9186753ac947af63fafc4f04";s:4:"name";s:66:"Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php";s:4:"role";s:4:"test";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"06948c7abe303c1e5b7b65b3cd2c6d25";s:4:"name";s:65:"Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.php";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b1a95afebdd5bf7aea9b2e18853e026d";s:4:"name";s:65:"Symfony/Component/Translation/Tests/fixtures/empty-translation.po";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/empty.csv";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/empty.ini";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:55:"Symfony/Component/Translation/Tests/fixtures/empty.json";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:53:"Symfony/Component/Translation/Tests/fixtures/empty.mo";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:53:"Symfony/Component/Translation/Tests/fixtures/empty.po";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/empty.xlf";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/empty.yml";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"41f6a7717a25819ac739a14696c0d862";s:4:"name";s:57:"Symfony/Component/Translation/Tests/fixtures/encoding.xlf";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9bbb4b898a5bf5df996cd16e81cf28b8";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/invalid-xml-resources.xlf";s:4:"role";s:4:"test";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4b5652237273550cf07bb6553590ed96";s:4:"name";s:59:"Symfony/Component/Translation/Tests/fixtures/malformed.json";s:4:"role";s:4:"test";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"35641dad0a0e32afc365268d7cb35f5c";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/non-valid.xlf";s:4:"role";s:4:"test";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d3b07384d113edec49eaa6238ad5ff00";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/non-valid.yml";s:4:"role";s:4:"test";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"edbf7f268cd369b124286c4eaccc5da6";s:4:"name";s:55:"Symfony/Component/Translation/Tests/fixtures/plurals.mo";s:4:"role";s:4:"test";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cc4d3e4012a94aa6d416ffba63cec96a";s:4:"name";s:55:"Symfony/Component/Translation/Tests/fixtures/plurals.po";s:4:"role";s:4:"test";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cadcf346671c0adabf12cc639338617c";s:4:"name";s:56:"Symfony/Component/Translation/Tests/fixtures/resname.xlf";s:4:"role";s:4:"test";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc9189406be84ec297464a514221406d";s:4:"name";s:83:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted/resources.dat";s:4:"role";s:4:"test";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d3d7cb5315b72e8a10083800232f975c";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.res";s:4:"role";s:4:"test";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"59bc61ceb778cfdad1353e72a91da038";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.txt";s:4:"role";s:4:"test";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bd4fd753b32b205184d61fe901f3cc99";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.res";s:4:"role";s:4:"test";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63b6f57aed45358ce8ee735e7d358369";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.txt";s:4:"role";s:4:"test";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a784644791b85cf23524cb50532459a9";s:4:"name";s:79:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/packagelist.txt";s:4:"role";s:4:"test";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5db6756e72842744a2f79e7976a27b27";s:4:"name";s:77:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/resources.dat";s:4:"role";s:4:"test";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"936c6496f075090509a4124930e62c25";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/res/en.res";s:4:"role";s:4:"test";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ca509ddac95802697c6409b6bdc24d6c";s:4:"name";s:64:"Symfony/Component/Translation/Tests/fixtures/resources-clean.xlf";s:4:"role";s:4:"test";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"349115d44a4b2b57ec0e12d5de001c1f";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.csv";s:4:"role";s:4:"test";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a1c5d4a3d4363448836f7df17bd3dac9";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.ini";s:4:"role";s:4:"test";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c4739e97d2e782ab9142b7cad4e36383";s:4:"name";s:59:"Symfony/Component/Translation/Tests/fixtures/resources.json";s:4:"role";s:4:"test";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"338bee6e134993372c561235d85caf5b";s:4:"name";s:57:"Symfony/Component/Translation/Tests/fixtures/resources.mo";s:4:"role";s:4:"test";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e5269ae0ff8b573e8e88b98a013a97de";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.php";s:4:"role";s:4:"test";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ebffc260ffc01b8dd02a6a548b13f7a4";s:4:"name";s:57:"Symfony/Component/Translation/Tests/fixtures/resources.po";s:4:"role";s:4:"test";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"01ebead5e039c0d1301339fef7b7fd18";s:4:"name";s:57:"Symfony/Component/Translation/Tests/fixtures/resources.ts";s:4:"role";s:4:"test";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3046798068871c144081a6dad3f88e3d";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.xlf";s:4:"role";s:4:"test";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"721aad13918f292d25bc9dc7d61b0e9c";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.yml";s:4:"role";s:4:"test";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f22180b9a31a19606112508410f0806f";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/valid.csv";s:4:"role";s:4:"test";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a566717bf4a4cdca4fa6d9f26b9887d";s:4:"name";s:60:"Symfony/Component/Translation/Tests/fixtures/withdoctype.xlf";s:4:"role";s:4:"test";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b92bc0ed64d6ace1904940ebacb42a9d";s:4:"name";s:62:"Symfony/Component/Translation/Tests/IdentityTranslatorTest.php";s:4:"role";s:4:"test";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4c7466038f4c30f7e11bdf01f9de3917";s:4:"name";s:52:"Symfony/Component/Translation/Tests/IntervalTest.php";s:4:"role";s:4:"test";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c56f359209f462724e5c38d54d04aef7";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.php";s:4:"role";s:4:"test";}}i:101;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"148fb17fa10a63d083608ee34425f515";s:4:"name";s:67:"Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.php";s:4:"role";s:4:"test";}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8db7645334a7fce25b180ee1e8727e12";s:4:"name";s:67:"Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.php";s:4:"role";s:4:"test";}}i:103;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eeb81233e12eacec0fd177f1945d73e3";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.php";s:4:"role";s:4:"test";}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e717797c994506a18cc642bba845e0bc";s:4:"name";s:65:"Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.php";s:4:"role";s:4:"test";}}i:105;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d906668f133a0c8ad7c7fcb5770d134";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.php";s:4:"role";s:4:"test";}}i:106;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e918b2beafc848955034c08ea5cd56a5";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.php";s:4:"role";s:4:"test";}}i:107;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8a494f3c229871a27bb9fab851bb385b";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.php";s:4:"role";s:4:"test";}}i:108;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"12960276054dc25012433c4e567d57b4";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php";s:4:"role";s:4:"test";}}i:109;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2722873e9cf782a84462ce616be95f22";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.php";s:4:"role";s:4:"test";}}i:110;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae55951ec7a0b72a091921a92ff76992";s:4:"name";s:66:"Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php";s:4:"role";s:4:"test";}}i:111;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b14fcada262a8c6207dd0cc66ec1242b";s:4:"name";s:65:"Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.php";s:4:"role";s:4:"test";}}i:112;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"872c308ce18aec6300ccf4528c935a19";s:4:"name";s:60:"Symfony/Component/Translation/Tests/MessageCatalogueTest.php";s:4:"role";s:4:"test";}}i:113;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c958676ddc85bc7f30a74a48cd800ece";s:4:"name";s:59:"Symfony/Component/Translation/Tests/MessageSelectorTest.php";s:4:"role";s:4:"test";}}i:114;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a8205b61d5bb55f454536626190c7644";s:4:"name";s:62:"Symfony/Component/Translation/Tests/PluralizationRulesTest.php";s:4:"role";s:4:"test";}}i:115;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c186f9c867c206f22c1d85c81a6079d0";s:4:"name";s:54:"Symfony/Component/Translation/Tests/TranslatorTest.php";s:4:"role";s:4:"test";}}i:116;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d001250c9d39b0e193dc7952d7a81380";s:4:"name";s:44:"Symfony/Component/Translation/Translator.php";s:4:"role";s:3:"php";}}i:117;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5ce4343a5bf5d91357af795a7e800158";s:4:"name";s:53:"Symfony/Component/Translation/TranslatorInterface.php";s:4:"role";s:3:"php";}}i:118;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"292d9794772f9374b181254742a2428b";s:4:"name";s:58:"Symfony/Component/Translation/Writer/TranslationWriter.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}s:8:"optional";a:1:{s:7:"package";a:2:{s:4:"name";s:6:"Config";s:7:"channel";s:16:"pear.symfony.com";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:119:{s:44:"Symfony/Component/Translation/autoloader.php";a:4:{s:6:"md5sum";s:32:"a23a3ebc32ad216eceb315d156d172df";s:4:"name";s:44:"Symfony/Component/Translation/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/autoloader.php";}s:61:"Symfony/Component/Translation/Catalogue/AbstractOperation.php";a:4:{s:6:"md5sum";s:32:"1b1901736a193dd839f00675dbe001e1";s:4:"name";s:61:"Symfony/Component/Translation/Catalogue/AbstractOperation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Catalogue/AbstractOperation.php";}s:57:"Symfony/Component/Translation/Catalogue/DiffOperation.php";a:4:{s:6:"md5sum";s:32:"1facd3924e3312ac6a9f6b9f586d84ae";s:4:"name";s:57:"Symfony/Component/Translation/Catalogue/DiffOperation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Catalogue/DiffOperation.php";}s:58:"Symfony/Component/Translation/Catalogue/MergeOperation.php";a:4:{s:6:"md5sum";s:32:"c697c25f56c1bc59faffd23ae1bf5910";s:4:"name";s:58:"Symfony/Component/Translation/Catalogue/MergeOperation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Catalogue/MergeOperation.php";}s:62:"Symfony/Component/Translation/Catalogue/OperationInterface.php";a:4:{s:6:"md5sum";s:32:"6b00bea9c66c6934740b6f5735573ed1";s:4:"name";s:62:"Symfony/Component/Translation/Catalogue/OperationInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Catalogue/OperationInterface.php";}s:42:"Symfony/Component/Translation/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"33507730a223e93eab19a4481c82d258";s:4:"name";s:42:"Symfony/Component/Translation/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/doc/pear/Translation/Symfony/Component/Translation/CHANGELOG.md";}s:43:"Symfony/Component/Translation/composer.json";a:4:{s:6:"md5sum";s:32:"08bb0002b0d0c9ef06a74417374b0db0";s:4:"name";s:43:"Symfony/Component/Translation/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/doc/pear/Translation/Symfony/Component/Translation/composer.json";}s:54:"Symfony/Component/Translation/Dumper/CsvFileDumper.php";a:4:{s:6:"md5sum";s:32:"af3a8b385fed749c0606e72124fc01c8";s:4:"name";s:54:"Symfony/Component/Translation/Dumper/CsvFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/CsvFileDumper.php";}s:56:"Symfony/Component/Translation/Dumper/DumperInterface.php";a:4:{s:6:"md5sum";s:32:"97df468b756ed060c2d9002ffb331f4c";s:4:"name";s:56:"Symfony/Component/Translation/Dumper/DumperInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/DumperInterface.php";}s:51:"Symfony/Component/Translation/Dumper/FileDumper.php";a:4:{s:6:"md5sum";s:32:"dd3b41f5ce0c7514217ae51ee01fd9b3";s:4:"name";s:51:"Symfony/Component/Translation/Dumper/FileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/FileDumper.php";}s:57:"Symfony/Component/Translation/Dumper/IcuResFileDumper.php";a:4:{s:6:"md5sum";s:32:"a2a5ea6e4a593fdb3ac4eb52b08c8fca";s:4:"name";s:57:"Symfony/Component/Translation/Dumper/IcuResFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/IcuResFileDumper.php";}s:54:"Symfony/Component/Translation/Dumper/IniFileDumper.php";a:4:{s:6:"md5sum";s:32:"aa41a897df4b252a6763a7206a64740e";s:4:"name";s:54:"Symfony/Component/Translation/Dumper/IniFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/IniFileDumper.php";}s:55:"Symfony/Component/Translation/Dumper/JsonFileDumper.php";a:4:{s:6:"md5sum";s:32:"590cefb5e2fdc8d5163101d1dea6c00c";s:4:"name";s:55:"Symfony/Component/Translation/Dumper/JsonFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/JsonFileDumper.php";}s:53:"Symfony/Component/Translation/Dumper/MoFileDumper.php";a:4:{s:6:"md5sum";s:32:"b221f1f93992940b41df842c71612a08";s:4:"name";s:53:"Symfony/Component/Translation/Dumper/MoFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/MoFileDumper.php";}s:54:"Symfony/Component/Translation/Dumper/PhpFileDumper.php";a:4:{s:6:"md5sum";s:32:"3a4faacf4648772530eddd7b531a914e";s:4:"name";s:54:"Symfony/Component/Translation/Dumper/PhpFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/PhpFileDumper.php";}s:53:"Symfony/Component/Translation/Dumper/PoFileDumper.php";a:4:{s:6:"md5sum";s:32:"151ba9edbfad4aad3a01404ed2d08aed";s:4:"name";s:53:"Symfony/Component/Translation/Dumper/PoFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/PoFileDumper.php";}s:53:"Symfony/Component/Translation/Dumper/QtFileDumper.php";a:4:{s:6:"md5sum";s:32:"97630cc685afa03a45769ce3c0c2d7b6";s:4:"name";s:53:"Symfony/Component/Translation/Dumper/QtFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/QtFileDumper.php";}s:56:"Symfony/Component/Translation/Dumper/XliffFileDumper.php";a:4:{s:6:"md5sum";s:32:"c50058cbe84ee0d6bc0c4291ac3c89e4";s:4:"name";s:56:"Symfony/Component/Translation/Dumper/XliffFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/XliffFileDumper.php";}s:55:"Symfony/Component/Translation/Dumper/YamlFileDumper.php";a:4:{s:6:"md5sum";s:32:"6cb4733897f48f15596acd385bf27e6b";s:4:"name";s:55:"Symfony/Component/Translation/Dumper/YamlFileDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper/YamlFileDumper.php";}s:62:"Symfony/Component/Translation/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"3f815f25d3ba7fb52caf40896c1a3bfe";s:4:"name";s:62:"Symfony/Component/Translation/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Exception/ExceptionInterface.php";}s:68:"Symfony/Component/Translation/Exception/InvalidResourceException.php";a:4:{s:6:"md5sum";s:32:"2107111761ca276662adca40be545bbe";s:4:"name";s:68:"Symfony/Component/Translation/Exception/InvalidResourceException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Exception/InvalidResourceException.php";}s:69:"Symfony/Component/Translation/Exception/NotFoundResourceException.php";a:4:{s:6:"md5sum";s:32:"7022eff2bccadddbd74f490fb372cf54";s:4:"name";s:69:"Symfony/Component/Translation/Exception/NotFoundResourceException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Exception/NotFoundResourceException.php";}s:58:"Symfony/Component/Translation/Extractor/ChainExtractor.php";a:4:{s:6:"md5sum";s:32:"4594ea6e9bb83b2e11669b85cc5124fa";s:4:"name";s:58:"Symfony/Component/Translation/Extractor/ChainExtractor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Extractor/ChainExtractor.php";}s:62:"Symfony/Component/Translation/Extractor/ExtractorInterface.php";a:4:{s:6:"md5sum";s:32:"63c8d0cc53c869dc53eddb8bf644694a";s:4:"name";s:62:"Symfony/Component/Translation/Extractor/ExtractorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Extractor/ExtractorInterface.php";}s:52:"Symfony/Component/Translation/IdentityTranslator.php";a:4:{s:6:"md5sum";s:32:"be99041f6caf9560d052545df078a511";s:4:"name";s:52:"Symfony/Component/Translation/IdentityTranslator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/IdentityTranslator.php";}s:42:"Symfony/Component/Translation/Interval.php";a:4:{s:6:"md5sum";s:32:"84efe2082056a419a58c16cb7735ca56";s:4:"name";s:42:"Symfony/Component/Translation/Interval.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Interval.php";}s:37:"Symfony/Component/Translation/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:37:"Symfony/Component/Translation/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/Translation/Symfony/Component/Translation/LICENSE";}s:52:"Symfony/Component/Translation/Loader/ArrayLoader.php";a:4:{s:6:"md5sum";s:32:"d6585b0daa5d9b9dbd3aec8f1333b890";s:4:"name";s:52:"Symfony/Component/Translation/Loader/ArrayLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/ArrayLoader.php";}s:54:"Symfony/Component/Translation/Loader/CsvFileLoader.php";a:4:{s:6:"md5sum";s:32:"6ceb1af587dc0cc6c6545852f2b9f89b";s:4:"name";s:54:"Symfony/Component/Translation/Loader/CsvFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/CsvFileLoader.php";}s:57:"Symfony/Component/Translation/Loader/IcuDatFileLoader.php";a:4:{s:6:"md5sum";s:32:"ecc212d52f34f5ad922845af7d071fe7";s:4:"name";s:57:"Symfony/Component/Translation/Loader/IcuDatFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/IcuDatFileLoader.php";}s:57:"Symfony/Component/Translation/Loader/IcuResFileLoader.php";a:4:{s:6:"md5sum";s:32:"66f2c067c6e251949024920f3bb13578";s:4:"name";s:57:"Symfony/Component/Translation/Loader/IcuResFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/IcuResFileLoader.php";}s:54:"Symfony/Component/Translation/Loader/IniFileLoader.php";a:4:{s:6:"md5sum";s:32:"d9f98317740467a87c342bd7e44a2faa";s:4:"name";s:54:"Symfony/Component/Translation/Loader/IniFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/IniFileLoader.php";}s:55:"Symfony/Component/Translation/Loader/JsonFileLoader.php";a:4:{s:6:"md5sum";s:32:"5b744ab916a07e52c924b2d9712172e9";s:4:"name";s:55:"Symfony/Component/Translation/Loader/JsonFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/JsonFileLoader.php";}s:56:"Symfony/Component/Translation/Loader/LoaderInterface.php";a:4:{s:6:"md5sum";s:32:"8d375de50d632c97a369003780044ef6";s:4:"name";s:56:"Symfony/Component/Translation/Loader/LoaderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/LoaderInterface.php";}s:53:"Symfony/Component/Translation/Loader/MoFileLoader.php";a:4:{s:6:"md5sum";s:32:"00cd7c30a5185244b22912679da90d12";s:4:"name";s:53:"Symfony/Component/Translation/Loader/MoFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/MoFileLoader.php";}s:54:"Symfony/Component/Translation/Loader/PhpFileLoader.php";a:4:{s:6:"md5sum";s:32:"bb211aa1fd5d3d46d8f9fc2e0b630bbb";s:4:"name";s:54:"Symfony/Component/Translation/Loader/PhpFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/PhpFileLoader.php";}s:53:"Symfony/Component/Translation/Loader/PoFileLoader.php";a:4:{s:6:"md5sum";s:32:"7c81a6760f547728df4c0e7137c92cf7";s:4:"name";s:53:"Symfony/Component/Translation/Loader/PoFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/PoFileLoader.php";}s:53:"Symfony/Component/Translation/Loader/QtFileLoader.php";a:4:{s:6:"md5sum";s:32:"50a221b191e5f83a44b03dfa6195ef3c";s:4:"name";s:53:"Symfony/Component/Translation/Loader/QtFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/QtFileLoader.php";}s:84:"Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd";a:4:{s:6:"md5sum";s:32:"fd528a896f7c6792b370930f64e58a2a";s:4:"name";s:84:"Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd";s:4:"role";s:3:"php";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd";}s:66:"Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsd";a:4:{s:6:"md5sum";s:32:"8b0466500a88d4e511342b555534b991";s:4:"name";s:66:"Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsd";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsd";}s:56:"Symfony/Component/Translation/Loader/XliffFileLoader.php";a:4:{s:6:"md5sum";s:32:"6f15280899bde6a3c9edb8d87ea9b092";s:4:"name";s:56:"Symfony/Component/Translation/Loader/XliffFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/XliffFileLoader.php";}s:55:"Symfony/Component/Translation/Loader/YamlFileLoader.php";a:4:{s:6:"md5sum";s:32:"d468c9ed70a982ce1a2efc681d674673";s:4:"name";s:55:"Symfony/Component/Translation/Loader/YamlFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/YamlFileLoader.php";}s:50:"Symfony/Component/Translation/MessageCatalogue.php";a:4:{s:6:"md5sum";s:32:"d151ded1a0038bed7f8c790384cb7eed";s:4:"name";s:50:"Symfony/Component/Translation/MessageCatalogue.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/MessageCatalogue.php";}s:59:"Symfony/Component/Translation/MessageCatalogueInterface.php";a:4:{s:6:"md5sum";s:32:"f2204344dcccad5c042762fc39952f2a";s:4:"name";s:59:"Symfony/Component/Translation/MessageCatalogueInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/MessageCatalogueInterface.php";}s:49:"Symfony/Component/Translation/MessageSelector.php";a:4:{s:6:"md5sum";s:32:"52bef5f54fe4cf887d90872acba99605";s:4:"name";s:49:"Symfony/Component/Translation/MessageSelector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/MessageSelector.php";}s:56:"Symfony/Component/Translation/MetadataAwareInterface.php";a:4:{s:6:"md5sum";s:32:"307866c58d58dd1e9370ad0d2c9b172a";s:4:"name";s:56:"Symfony/Component/Translation/MetadataAwareInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/MetadataAwareInterface.php";}s:46:"Symfony/Component/Translation/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"10d8a0a424c95688c056eaf8607eb645";s:4:"name";s:46:"Symfony/Component/Translation/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/phpunit.xml.dist";}s:52:"Symfony/Component/Translation/PluralizationRules.php";a:4:{s:6:"md5sum";s:32:"72406471bc239d6b3346ca064f67b7aa";s:4:"name";s:52:"Symfony/Component/Translation/PluralizationRules.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/PluralizationRules.php";}s:39:"Symfony/Component/Translation/README.md";a:4:{s:6:"md5sum";s:32:"cbcc27d78c155093251fccc294affb72";s:4:"name";s:39:"Symfony/Component/Translation/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/doc/pear/Translation/Symfony/Component/Translation/README.md";}s:71:"Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.php";a:4:{s:6:"md5sum";s:32:"ef82bc07c69b7711d658500ab7dd1726";s:4:"name";s:71:"Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.php";}s:67:"Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.php";a:4:{s:6:"md5sum";s:32:"ba72862554b59d792638dd7bbab730f9";s:4:"name";s:67:"Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.php";}s:68:"Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.php";a:4:{s:6:"md5sum";s:32:"47b9f33d19218deaf1497d67c08212c4";s:4:"name";s:68:"Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.php";}s:64:"Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"44032d28b28576fee4042715bbacf582";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.php";}s:67:"Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"c9821802aa5b2075947b3154d4d111a9";s:4:"name";s:67:"Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.php";}s:64:"Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"b655aaa49e41936ffe308420769beead";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.php";}s:65:"Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"7777f4777f747b0d66a09b38aba33417";s:4:"name";s:65:"Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.php";}s:63:"Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"3691ee670197459ebef5ec634245d931";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.php";}s:64:"Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"f5359d8c55084adf386b7a09f084a314";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.php";}s:63:"Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"f61a83220a0aa1785ea3f8b718cbaed0";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php";}s:63:"Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"4f15fb0434c84bfda4ce4c7d838f134b";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.php";}s:66:"Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"fa10f05c9186753ac947af63fafc4f04";s:4:"name";s:66:"Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php";}s:65:"Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.php";a:4:{s:6:"md5sum";s:32:"06948c7abe303c1e5b7b65b3cd2c6d25";s:4:"name";s:65:"Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.php";}s:65:"Symfony/Component/Translation/Tests/fixtures/empty-translation.po";a:4:{s:6:"md5sum";s:32:"b1a95afebdd5bf7aea9b2e18853e026d";s:4:"name";s:65:"Symfony/Component/Translation/Tests/fixtures/empty-translation.po";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/empty-translation.po";}s:54:"Symfony/Component/Translation/Tests/fixtures/empty.csv";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/empty.csv";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.csv";}s:54:"Symfony/Component/Translation/Tests/fixtures/empty.ini";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/empty.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ini";}s:55:"Symfony/Component/Translation/Tests/fixtures/empty.json";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:55:"Symfony/Component/Translation/Tests/fixtures/empty.json";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.json";}s:53:"Symfony/Component/Translation/Tests/fixtures/empty.mo";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:53:"Symfony/Component/Translation/Tests/fixtures/empty.mo";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.mo";}s:53:"Symfony/Component/Translation/Tests/fixtures/empty.po";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:53:"Symfony/Component/Translation/Tests/fixtures/empty.po";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.po";}s:54:"Symfony/Component/Translation/Tests/fixtures/empty.xlf";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/empty.xlf";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.xlf";}s:54:"Symfony/Component/Translation/Tests/fixtures/empty.yml";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/empty.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.yml";}s:57:"Symfony/Component/Translation/Tests/fixtures/encoding.xlf";a:4:{s:6:"md5sum";s:32:"41f6a7717a25819ac739a14696c0d862";s:4:"name";s:57:"Symfony/Component/Translation/Tests/fixtures/encoding.xlf";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/encoding.xlf";}s:70:"Symfony/Component/Translation/Tests/fixtures/invalid-xml-resources.xlf";a:4:{s:6:"md5sum";s:32:"9bbb4b898a5bf5df996cd16e81cf28b8";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/invalid-xml-resources.xlf";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/invalid-xml-resources.xlf";}s:59:"Symfony/Component/Translation/Tests/fixtures/malformed.json";a:4:{s:6:"md5sum";s:32:"4b5652237273550cf07bb6553590ed96";s:4:"name";s:59:"Symfony/Component/Translation/Tests/fixtures/malformed.json";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/malformed.json";}s:58:"Symfony/Component/Translation/Tests/fixtures/non-valid.xlf";a:4:{s:6:"md5sum";s:32:"35641dad0a0e32afc365268d7cb35f5c";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/non-valid.xlf";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.xlf";}s:58:"Symfony/Component/Translation/Tests/fixtures/non-valid.yml";a:4:{s:6:"md5sum";s:32:"d3b07384d113edec49eaa6238ad5ff00";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/non-valid.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.yml";}s:55:"Symfony/Component/Translation/Tests/fixtures/plurals.mo";a:4:{s:6:"md5sum";s:32:"edbf7f268cd369b124286c4eaccc5da6";s:4:"name";s:55:"Symfony/Component/Translation/Tests/fixtures/plurals.mo";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.mo";}s:55:"Symfony/Component/Translation/Tests/fixtures/plurals.po";a:4:{s:6:"md5sum";s:32:"cc4d3e4012a94aa6d416ffba63cec96a";s:4:"name";s:55:"Symfony/Component/Translation/Tests/fixtures/plurals.po";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.po";}s:56:"Symfony/Component/Translation/Tests/fixtures/resname.xlf";a:4:{s:6:"md5sum";s:32:"cadcf346671c0adabf12cc639338617c";s:4:"name";s:56:"Symfony/Component/Translation/Tests/fixtures/resname.xlf";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resname.xlf";}s:83:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted/resources.dat";a:4:{s:6:"md5sum";s:32:"bc9189406be84ec297464a514221406d";s:4:"name";s:83:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted/resources.dat";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted/resources.dat";}s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.res";a:4:{s:6:"md5sum";s:32:"d3d7cb5315b72e8a10083800232f975c";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.res";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.res";}s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.txt";a:4:{s:6:"md5sum";s:32:"59bc61ceb778cfdad1353e72a91da038";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.txt";}s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.res";a:4:{s:6:"md5sum";s:32:"bd4fd753b32b205184d61fe901f3cc99";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.res";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.res";}s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.txt";a:4:{s:6:"md5sum";s:32:"63b6f57aed45358ce8ee735e7d358369";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.txt";}s:79:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/packagelist.txt";a:4:{s:6:"md5sum";s:32:"a784644791b85cf23524cb50532459a9";s:4:"name";s:79:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/packagelist.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/packagelist.txt";}s:77:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/resources.dat";a:4:{s:6:"md5sum";s:32:"5db6756e72842744a2f79e7976a27b27";s:4:"name";s:77:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/resources.dat";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/resources.dat";}s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/res/en.res";a:4:{s:6:"md5sum";s:32:"936c6496f075090509a4124930e62c25";s:4:"name";s:70:"Symfony/Component/Translation/Tests/fixtures/resourcebundle/res/en.res";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/res/en.res";}s:64:"Symfony/Component/Translation/Tests/fixtures/resources-clean.xlf";a:4:{s:6:"md5sum";s:32:"ca509ddac95802697c6409b6bdc24d6c";s:4:"name";s:64:"Symfony/Component/Translation/Tests/fixtures/resources-clean.xlf";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlf";}s:58:"Symfony/Component/Translation/Tests/fixtures/resources.csv";a:4:{s:6:"md5sum";s:32:"349115d44a4b2b57ec0e12d5de001c1f";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.csv";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.csv";}s:58:"Symfony/Component/Translation/Tests/fixtures/resources.ini";a:4:{s:6:"md5sum";s:32:"a1c5d4a3d4363448836f7df17bd3dac9";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ini";}s:59:"Symfony/Component/Translation/Tests/fixtures/resources.json";a:4:{s:6:"md5sum";s:32:"c4739e97d2e782ab9142b7cad4e36383";s:4:"name";s:59:"Symfony/Component/Translation/Tests/fixtures/resources.json";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.json";}s:57:"Symfony/Component/Translation/Tests/fixtures/resources.mo";a:4:{s:6:"md5sum";s:32:"338bee6e134993372c561235d85caf5b";s:4:"name";s:57:"Symfony/Component/Translation/Tests/fixtures/resources.mo";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.mo";}s:58:"Symfony/Component/Translation/Tests/fixtures/resources.php";a:4:{s:6:"md5sum";s:32:"e5269ae0ff8b573e8e88b98a013a97de";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.php";}s:57:"Symfony/Component/Translation/Tests/fixtures/resources.po";a:4:{s:6:"md5sum";s:32:"ebffc260ffc01b8dd02a6a548b13f7a4";s:4:"name";s:57:"Symfony/Component/Translation/Tests/fixtures/resources.po";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.po";}s:57:"Symfony/Component/Translation/Tests/fixtures/resources.ts";a:4:{s:6:"md5sum";s:32:"01ebead5e039c0d1301339fef7b7fd18";s:4:"name";s:57:"Symfony/Component/Translation/Tests/fixtures/resources.ts";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ts";}s:58:"Symfony/Component/Translation/Tests/fixtures/resources.xlf";a:4:{s:6:"md5sum";s:32:"3046798068871c144081a6dad3f88e3d";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.xlf";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.xlf";}s:58:"Symfony/Component/Translation/Tests/fixtures/resources.yml";a:4:{s:6:"md5sum";s:32:"721aad13918f292d25bc9dc7d61b0e9c";s:4:"name";s:58:"Symfony/Component/Translation/Tests/fixtures/resources.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.yml";}s:54:"Symfony/Component/Translation/Tests/fixtures/valid.csv";a:4:{s:6:"md5sum";s:32:"f22180b9a31a19606112508410f0806f";s:4:"name";s:54:"Symfony/Component/Translation/Tests/fixtures/valid.csv";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/valid.csv";}s:60:"Symfony/Component/Translation/Tests/fixtures/withdoctype.xlf";a:4:{s:6:"md5sum";s:32:"3a566717bf4a4cdca4fa6d9f26b9887d";s:4:"name";s:60:"Symfony/Component/Translation/Tests/fixtures/withdoctype.xlf";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/withdoctype.xlf";}s:62:"Symfony/Component/Translation/Tests/IdentityTranslatorTest.php";a:4:{s:6:"md5sum";s:32:"b92bc0ed64d6ace1904940ebacb42a9d";s:4:"name";s:62:"Symfony/Component/Translation/Tests/IdentityTranslatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/IdentityTranslatorTest.php";}s:52:"Symfony/Component/Translation/Tests/IntervalTest.php";a:4:{s:6:"md5sum";s:32:"4c7466038f4c30f7e11bdf01f9de3917";s:4:"name";s:52:"Symfony/Component/Translation/Tests/IntervalTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/IntervalTest.php";}s:64:"Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"c56f359209f462724e5c38d54d04aef7";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.php";}s:67:"Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"148fb17fa10a63d083608ee34425f515";s:4:"name";s:67:"Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.php";}s:67:"Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"8db7645334a7fce25b180ee1e8727e12";s:4:"name";s:67:"Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.php";}s:64:"Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"eeb81233e12eacec0fd177f1945d73e3";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.php";}s:65:"Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"e717797c994506a18cc642bba845e0bc";s:4:"name";s:65:"Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.php";}s:64:"Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.php";a:4:{s:6:"md5sum";s:32:"7d906668f133a0c8ad7c7fcb5770d134";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.php";}s:63:"Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"e918b2beafc848955034c08ea5cd56a5";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.php";}s:64:"Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"8a494f3c229871a27bb9fab851bb385b";s:4:"name";s:64:"Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.php";}s:63:"Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"12960276054dc25012433c4e567d57b4";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php";}s:63:"Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"2722873e9cf782a84462ce616be95f22";s:4:"name";s:63:"Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.php";}s:66:"Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"ae55951ec7a0b72a091921a92ff76992";s:4:"name";s:66:"Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php";}s:65:"Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"b14fcada262a8c6207dd0cc66ec1242b";s:4:"name";s:65:"Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.php";}s:60:"Symfony/Component/Translation/Tests/MessageCatalogueTest.php";a:4:{s:6:"md5sum";s:32:"872c308ce18aec6300ccf4528c935a19";s:4:"name";s:60:"Symfony/Component/Translation/Tests/MessageCatalogueTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/MessageCatalogueTest.php";}s:59:"Symfony/Component/Translation/Tests/MessageSelectorTest.php";a:4:{s:6:"md5sum";s:32:"c958676ddc85bc7f30a74a48cd800ece";s:4:"name";s:59:"Symfony/Component/Translation/Tests/MessageSelectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/MessageSelectorTest.php";}s:62:"Symfony/Component/Translation/Tests/PluralizationRulesTest.php";a:4:{s:6:"md5sum";s:32:"a8205b61d5bb55f454536626190c7644";s:4:"name";s:62:"Symfony/Component/Translation/Tests/PluralizationRulesTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/PluralizationRulesTest.php";}s:54:"Symfony/Component/Translation/Tests/TranslatorTest.php";a:4:{s:6:"md5sum";s:32:"c186f9c867c206f22c1d85c81a6079d0";s:4:"name";s:54:"Symfony/Component/Translation/Tests/TranslatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/TranslatorTest.php";}s:44:"Symfony/Component/Translation/Translator.php";a:4:{s:6:"md5sum";s:32:"d001250c9d39b0e193dc7952d7a81380";s:4:"name";s:44:"Symfony/Component/Translation/Translator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Translator.php";}s:53:"Symfony/Component/Translation/TranslatorInterface.php";a:4:{s:6:"md5sum";s:32:"5ce4343a5bf5d91357af795a7e800158";s:4:"name";s:53:"Symfony/Component/Translation/TranslatorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/TranslatorInterface.php";}s:58:"Symfony/Component/Translation/Writer/TranslationWriter.php";a:4:{s:6:"md5sum";s:32:"292d9794772f9374b181254742a2428b";s:4:"name";s:58:"Symfony/Component/Translation/Writer/TranslationWriter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Writer/TranslationWriter.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:29:{s:59:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Catalogue";b:1;s:75:"/opt/alt/php54/usr/share/doc/pear/Translation/Symfony/Component/Translation";b:1;s:63:"/opt/alt/php54/usr/share/doc/pear/Translation/Symfony/Component";b:1;s:53:"/opt/alt/php54/usr/share/doc/pear/Translation/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/doc/pear/Translation";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Dumper";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Exception";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Extractor";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader";b:1;s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/schema/dic/xliff-core";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/schema/dic";b:1;s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Loader/schema";b:1;s:76:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation";b:1;s:64:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component";b:1;s:54:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony";b:1;s:46:"/opt/alt/php54/usr/share/pear/test/Translation";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Catalogue";b:1;s:82:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Dumper";b:1;s:91:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures";b:1;s:116:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted";b:1;s:106:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle";b:1;s:110:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat";b:1;s:110:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/res";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/Translation/Symfony/Component/Translation/Tests/Loader";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Translation/Writer";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:6:"Config";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506494;}PK!DzX&&2.registry/.channel.pear.symfony.com/filesystem.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:10:"Filesystem";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:29:"Symfony2 Filesystem Component";s:11:"description";s:29:"Symfony2 Filesystem Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:44";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:14:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eeadcdf200225ed18f3d9bd70b310375";s:4:"name";s:43:"Symfony/Component/Filesystem/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1537577578897cb0d5702f346fae3c82";s:4:"name";s:41:"Symfony/Component/Filesystem/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0719190f9b9a19976e07424c786da406";s:4:"name";s:42:"Symfony/Component/Filesystem/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"11a7d451ae71b6aeba9e1236a53865f0";s:4:"name";s:61:"Symfony/Component/Filesystem/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8a8b119b88f20a5a3078e051a308f741";s:4:"name";s:64:"Symfony/Component/Filesystem/Exception/FileNotFoundException.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"79569770a034723c06472d45b57d74da";s:4:"name";s:54:"Symfony/Component/Filesystem/Exception/IOException.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9ce81ced7d137497a4aa3639b2c445fe";s:4:"name";s:63:"Symfony/Component/Filesystem/Exception/IOExceptionInterface.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"356b2ce6a1d41b8cae77ef6fd9258b06";s:4:"name";s:43:"Symfony/Component/Filesystem/Filesystem.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/Filesystem/LICENSE";s:4:"role";s:3:"doc";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1579e7260973d3c54b34f0a2b0342f8f";s:4:"name";s:45:"Symfony/Component/Filesystem/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a954a92f9fc04cd3aabdff075b04252f";s:4:"name";s:38:"Symfony/Component/Filesystem/README.md";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4108eeb04e7693cca06fb785b91553ab";s:4:"name";s:52:"Symfony/Component/Filesystem/Tests/ExceptionTest.php";s:4:"role";s:4:"test";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e7e4c5588c1846edc92e286385fcfb42";s:4:"name";s:53:"Symfony/Component/Filesystem/Tests/FilesystemTest.php";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0e10c90ef941c3e68756586a5f197b8e";s:4:"name";s:57:"Symfony/Component/Filesystem/Tests/FilesystemTestCase.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:14:{s:43:"Symfony/Component/Filesystem/autoloader.php";a:4:{s:6:"md5sum";s:32:"eeadcdf200225ed18f3d9bd70b310375";s:4:"name";s:43:"Symfony/Component/Filesystem/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Filesystem/autoloader.php";}s:41:"Symfony/Component/Filesystem/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"1537577578897cb0d5702f346fae3c82";s:4:"name";s:41:"Symfony/Component/Filesystem/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/doc/pear/Filesystem/Symfony/Component/Filesystem/CHANGELOG.md";}s:42:"Symfony/Component/Filesystem/composer.json";a:4:{s:6:"md5sum";s:32:"0719190f9b9a19976e07424c786da406";s:4:"name";s:42:"Symfony/Component/Filesystem/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/Filesystem/Symfony/Component/Filesystem/composer.json";}s:61:"Symfony/Component/Filesystem/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"11a7d451ae71b6aeba9e1236a53865f0";s:4:"name";s:61:"Symfony/Component/Filesystem/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Filesystem/Exception/ExceptionInterface.php";}s:64:"Symfony/Component/Filesystem/Exception/FileNotFoundException.php";a:4:{s:6:"md5sum";s:32:"8a8b119b88f20a5a3078e051a308f741";s:4:"name";s:64:"Symfony/Component/Filesystem/Exception/FileNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Filesystem/Exception/FileNotFoundException.php";}s:54:"Symfony/Component/Filesystem/Exception/IOException.php";a:4:{s:6:"md5sum";s:32:"79569770a034723c06472d45b57d74da";s:4:"name";s:54:"Symfony/Component/Filesystem/Exception/IOException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Filesystem/Exception/IOException.php";}s:63:"Symfony/Component/Filesystem/Exception/IOExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"9ce81ced7d137497a4aa3639b2c445fe";s:4:"name";s:63:"Symfony/Component/Filesystem/Exception/IOExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php";}s:43:"Symfony/Component/Filesystem/Filesystem.php";a:4:{s:6:"md5sum";s:32:"356b2ce6a1d41b8cae77ef6fd9258b06";s:4:"name";s:43:"Symfony/Component/Filesystem/Filesystem.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Filesystem/Filesystem.php";}s:36:"Symfony/Component/Filesystem/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/Filesystem/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/Filesystem/Symfony/Component/Filesystem/LICENSE";}s:45:"Symfony/Component/Filesystem/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"1579e7260973d3c54b34f0a2b0342f8f";s:4:"name";s:45:"Symfony/Component/Filesystem/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Filesystem/Symfony/Component/Filesystem/phpunit.xml.dist";}s:38:"Symfony/Component/Filesystem/README.md";a:4:{s:6:"md5sum";s:32:"a954a92f9fc04cd3aabdff075b04252f";s:4:"name";s:38:"Symfony/Component/Filesystem/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/Filesystem/Symfony/Component/Filesystem/README.md";}s:52:"Symfony/Component/Filesystem/Tests/ExceptionTest.php";a:4:{s:6:"md5sum";s:32:"4108eeb04e7693cca06fb785b91553ab";s:4:"name";s:52:"Symfony/Component/Filesystem/Tests/ExceptionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Filesystem/Symfony/Component/Filesystem/Tests/ExceptionTest.php";}s:53:"Symfony/Component/Filesystem/Tests/FilesystemTest.php";a:4:{s:6:"md5sum";s:32:"e7e4c5588c1846edc92e286385fcfb42";s:4:"name";s:53:"Symfony/Component/Filesystem/Tests/FilesystemTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.php";}s:57:"Symfony/Component/Filesystem/Tests/FilesystemTestCase.php";a:4:{s:6:"md5sum";s:32:"0e10c90ef941c3e68756586a5f197b8e";s:4:"name";s:57:"Symfony/Component/Filesystem/Tests/FilesystemTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:13:{s:58:"/opt/alt/php54/usr/share/pear/Symfony/Component/Filesystem";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:73:"/opt/alt/php54/usr/share/doc/pear/Filesystem/Symfony/Component/Filesystem";b:1;s:62:"/opt/alt/php54/usr/share/doc/pear/Filesystem/Symfony/Component";b:1;s:52:"/opt/alt/php54/usr/share/doc/pear/Filesystem/Symfony";b:1;s:44:"/opt/alt/php54/usr/share/doc/pear/Filesystem";b:1;s:68:"/opt/alt/php54/usr/share/pear/Symfony/Component/Filesystem/Exception";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/Filesystem/Symfony/Component/Filesystem";b:1;s:63:"/opt/alt/php54/usr/share/pear/test/Filesystem/Symfony/Component";b:1;s:53:"/opt/alt/php54/usr/share/pear/test/Filesystem/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/pear/test/Filesystem";b:1;s:80:"/opt/alt/php54/usr/share/pear/test/Filesystem/Symfony/Component/Filesystem/Tests";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!>ff0.registry/.channel.pear.symfony.com/security.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:8:"Security";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:27:"Symfony2 Security Component";s:11:"description";s:27:"Symfony2 Security Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:49";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:372:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5365c3fd47df815d4353473ac6373ad7";s:4:"name";s:44:"Symfony/Component/Security/Acl/composer.json";s:4:"role";s:3:"doc";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0ecf07a353f03ea4c6976d0cf98d5b51";s:4:"name";s:51:"Symfony/Component/Security/Acl/Dbal/AclProvider.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"333ff4aca2f234109cd7ebe9a03c7f25";s:4:"name";s:58:"Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a38fab3cddce11ba90e1569be5f0d806";s:4:"name";s:46:"Symfony/Component/Security/Acl/Dbal/Schema.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e8f587fcaf0a3057321516e59fc0ce87";s:4:"name";s:45:"Symfony/Component/Security/Acl/Domain/Acl.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cccc32d88c312fb7dac66b08d9e67e45";s:4:"name";s:60:"Symfony/Component/Security/Acl/Domain/AclCollectionCache.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4fee19b12185f0ee45a2e97f5fcb8a4";s:4:"name";s:53:"Symfony/Component/Security/Acl/Domain/AuditLogger.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2f552f22f35c47d5d523c187d25039eb";s:4:"name";s:58:"Symfony/Component/Security/Acl/Domain/DoctrineAclCache.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d02a171381bed25a818a33a2a714803";s:4:"name";s:47:"Symfony/Component/Security/Acl/Domain/Entry.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f0b1b92b49934c59ecc126fbb41b72c2";s:4:"name";s:52:"Symfony/Component/Security/Acl/Domain/FieldEntry.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3eadb08eafffe705a6dd8de5f96e1ca1";s:4:"name";s:56:"Symfony/Component/Security/Acl/Domain/ObjectIdentity.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1baa7e094b60dbd7a2eaf4d38b5125cc";s:4:"name";s:73:"Symfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea6329b78543f0536dc1b2019c291eb2";s:4:"name";s:68:"Symfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d082f117ebbe68492e03855adbaa7704";s:4:"name";s:62:"Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2a34925fb304b1a8d724ca4cf2aafb5f";s:4:"name";s:75:"Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e48d7c38d196eea74cf250fcddd8d189";s:4:"name";s:62:"Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"82a5465e98dd2475f706a9cacc65db37";s:4:"name";s:70:"Symfony/Component/Security/Acl/Exception/AclAlreadyExistsException.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8b3ec9dfe9d9f345a3ddce26bd4fab8b";s:4:"name";s:65:"Symfony/Component/Security/Acl/Exception/AclNotFoundException.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7e3eb281d553454f0f59d5f282948216";s:4:"name";s:76:"Symfony/Component/Security/Acl/Exception/ConcurrentModificationException.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e3b6ea7de5ec436c7503f1d7312249bc";s:4:"name";s:54:"Symfony/Component/Security/Acl/Exception/Exception.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4be9ba33e0d97e970d6f541480901eb0";s:4:"name";s:73:"Symfony/Component/Security/Acl/Exception/InvalidDomainObjectException.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aca5379067c0fd0c2240eb986eac8268";s:4:"name";s:64:"Symfony/Component/Security/Acl/Exception/NoAceFoundException.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7a0ca03655455c96a2fe053bc72b4de3";s:4:"name";s:69:"Symfony/Component/Security/Acl/Exception/NotAllAclsFoundException.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2415593ec8d8a343e6f4328ddb0c2a1d";s:4:"name";s:66:"Symfony/Component/Security/Acl/Exception/SidNotLoadedException.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:38:"Symfony/Component/Security/Acl/LICENSE";s:4:"role";s:3:"doc";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ab5d60682e988c0e7eb0dd1512dabade";s:4:"name";s:58:"Symfony/Component/Security/Acl/Model/AclCacheInterface.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"870a09318c3c65e3523e19130607f1ab";s:4:"name";s:53:"Symfony/Component/Security/Acl/Model/AclInterface.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7ea089827ee0d4ed26b0d57b8f20dc28";s:4:"name";s:61:"Symfony/Component/Security/Acl/Model/AclProviderInterface.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63c76e68e9ccf7ec307696ac8ca44e8f";s:4:"name";s:62:"Symfony/Component/Security/Acl/Model/AuditableAclInterface.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f989613d6c0286594696efc106774415";s:4:"name";s:64:"Symfony/Component/Security/Acl/Model/AuditableEntryInterface.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c5d9ae1862d7c0a6d442f053d5acac39";s:4:"name";s:61:"Symfony/Component/Security/Acl/Model/AuditLoggerInterface.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4d278f8d01215e4be53a264dad150173";s:4:"name";s:62:"Symfony/Component/Security/Acl/Model/DomainObjectInterface.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"72e6a4f7f0ffe6d84e6e6462827ee54a";s:4:"name";s:55:"Symfony/Component/Security/Acl/Model/EntryInterface.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2968e44f1b60586feb144fe02c5e15c3";s:4:"name";s:60:"Symfony/Component/Security/Acl/Model/FieldEntryInterface.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e1c009bf3a30308c68b2fc8b959fc1d4";s:4:"name";s:60:"Symfony/Component/Security/Acl/Model/MutableAclInterface.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fb020f4efc07611baef0206e0783b87e";s:4:"name";s:68:"Symfony/Component/Security/Acl/Model/MutableAclProviderInterface.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"29d14ee35eebd9faf6d38b97b02ea8cb";s:4:"name";s:64:"Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4c49500b0054ee78894935bebed56210";s:4:"name";s:81:"Symfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"713c07bfa636d7d6ad4d85d91b5f4ac4";s:4:"name";s:76:"Symfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"212111e56b11d7fba72dc585289786cb";s:4:"name";s:66:"Symfony/Component/Security/Acl/Model/SecurityIdentityInterface.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0896de7498e35f5f02a9755832172a96";s:4:"name";s:83:"Symfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"83e5de08b981e358d3daea8b304988ca";s:4:"name";s:64:"Symfony/Component/Security/Acl/Permission/BasicPermissionMap.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7918106bfa1e9cc64ca25efa8f2428f9";s:4:"name";s:57:"Symfony/Component/Security/Acl/Permission/MaskBuilder.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"024f4e1c3b24a5a42fe258e9ed3d83bb";s:4:"name";s:68:"Symfony/Component/Security/Acl/Permission/PermissionMapInterface.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"74a4ed032849f83ee138f3ea572c315f";s:4:"name";s:47:"Symfony/Component/Security/Acl/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5213a3c25b290a621867f47359a85972";s:4:"name";s:40:"Symfony/Component/Security/Acl/README.md";s:4:"role";s:3:"doc";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"29202e9e8819885a0237ad1f5c4f1a3a";s:4:"name";s:60:"Symfony/Component/Security/Acl/Resources/bin/generateSql.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"128855e565e079eb859f350be880f395";s:4:"name";s:55:"Symfony/Component/Security/Acl/Resources/schema/db2.sql";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"61db757bf91fc032fee7a78fe3ca8888";s:4:"name";s:59:"Symfony/Component/Security/Acl/Resources/schema/drizzle.sql";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"be1bec1133a89cf3e7298b380d5dd9a9";s:4:"name";s:57:"Symfony/Component/Security/Acl/Resources/schema/mssql.sql";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"626ac34142835a1c4936290b79a05f66";s:4:"name";s:57:"Symfony/Component/Security/Acl/Resources/schema/mysql.sql";s:4:"role";s:3:"php";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6173f90ea584ec65392676ba164d9464";s:4:"name";s:58:"Symfony/Component/Security/Acl/Resources/schema/oracle.sql";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"50585e970a570428d65f9e9507da8aa8";s:4:"name";s:62:"Symfony/Component/Security/Acl/Resources/schema/postgresql.sql";s:4:"role";s:3:"php";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b93a223813116f02a5cba763bd07069a";s:4:"name";s:58:"Symfony/Component/Security/Acl/Resources/schema/sqlite.sql";s:4:"role";s:3:"php";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"357d0712d7b5b92a0d8315364e0518ea";s:4:"name";s:70:"Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.php";s:4:"role";s:4:"test";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d332e19775917958bec95d017be52be5";s:4:"name";s:61:"Symfony/Component/Security/Acl/Tests/Dbal/AclProviderTest.php";s:4:"role";s:4:"test";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1a46fcac5ad21b5b28b9590b1b4863fc";s:4:"name";s:68:"Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"70968eae1eaa4395492e7dbd5797be65";s:4:"name";s:55:"Symfony/Component/Security/Acl/Tests/Domain/AclTest.php";s:4:"role";s:4:"test";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86049b2dce3364e94f6683df05125acf";s:4:"name";s:63:"Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.php";s:4:"role";s:4:"test";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"099e0b3bcfdb454e46b46687a38d8a3b";s:4:"name";s:68:"Symfony/Component/Security/Acl/Tests/Domain/DoctrineAclCacheTest.php";s:4:"role";s:4:"test";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4022249f6c81298b7f58ea4653ece650";s:4:"name";s:57:"Symfony/Component/Security/Acl/Tests/Domain/EntryTest.php";s:4:"role";s:4:"test";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f3699fe6be1b8b45c015629251cc6f64";s:4:"name";s:62:"Symfony/Component/Security/Acl/Tests/Domain/FieldEntryTest.php";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d56675ee8ce9da6ee089ab1486db1035";s:4:"name";s:83:"Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityRetrievalStrategyTest.php";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"af2604cee5638a6e0642f3c1478826c1";s:4:"name";s:66:"Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityTest.php";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"75605e8ea69d528cea564242326e8b8d";s:4:"name";s:78:"Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.php";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4555d0ee6f2d61a752b0416ee9b79e8";s:4:"name";s:72:"Symfony/Component/Security/Acl/Tests/Domain/RoleSecurityIdentityTest.php";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"78c619c9cec05fdf11f5de9d48b56454";s:4:"name";s:85:"Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.php";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"74e0d9ba1641b5cf21905336aca0d348";s:4:"name";s:72:"Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.php";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a353f4f911920e43f2e09ae3ac32d349";s:4:"name";s:74:"Symfony/Component/Security/Acl/Tests/Permission/BasicPermissionMapTest.php";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3546d4afbaf25b0a4d40c216549ee272";s:4:"name";s:67:"Symfony/Component/Security/Acl/Tests/Permission/MaskBuilderTest.php";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3c9129e03017adb641e9268149b935bc";s:4:"name";s:59:"Symfony/Component/Security/Acl/Tests/Voter/AclVoterTest.php";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8cafc8e1f14343b87cb0f58a25f463a0";s:4:"name";s:49:"Symfony/Component/Security/Acl/Voter/AclVoter.php";s:4:"role";s:3:"php";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"180a2b1ab4b985facb353d6edeeb78ce";s:4:"name";s:50:"Symfony/Component/Security/Acl/Voter/FieldVote.php";s:4:"role";s:3:"php";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0fb7efcc9c1574920f39f115e9863b68";s:4:"name";s:41:"Symfony/Component/Security/autoloader.php";s:4:"role";s:3:"php";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2def4fa9f9525638a5a9c6f556ba1386";s:4:"name";s:39:"Symfony/Component/Security/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f0488bd3f14f86892ce93d89dad55776";s:4:"name";s:40:"Symfony/Component/Security/composer.json";s:4:"role";s:3:"doc";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c78d485138ebdc2fa2be48a396cb9ad2";s:4:"name";s:81:"Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.php";s:4:"role";s:3:"php";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"61167585d6d54cf1861b70f2344632c1";s:4:"name";s:80:"Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php";s:4:"role";s:3:"php";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4a5356ef0cf45593536da075d0d367a1";s:4:"name";s:78:"Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php";s:4:"role";s:3:"php";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dda5e9627c9c68a695cdd5071de86834";s:4:"name";s:87:"Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.php";s:4:"role";s:3:"php";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"00cb0dfecd7dc6fedc2426932405dbec";s:4:"name";s:91:"Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.php";s:4:"role";s:3:"php";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"07f5b8692dd849851a84662b9f60b759";s:4:"name";s:91:"Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.php";s:4:"role";s:3:"php";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ccc63dc0c7c865036a3e64fb6819073e";s:4:"name";s:85:"Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php";s:4:"role";s:3:"php";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df05c4c0bdbdb5f00d68909724d552af";s:4:"name";s:98:"Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php";s:4:"role";s:3:"php";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bdcb91d96aacde5a99192f145495e66e";s:4:"name";s:92:"Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php";s:4:"role";s:3:"php";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"62c25b49d796de82786905533be97a8b";s:4:"name";s:88:"Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php";s:4:"role";s:3:"php";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4f720340d1992a6261fc7cf795ca0b4d";s:4:"name";s:86:"Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php";s:4:"role";s:3:"php";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"563ca47a94d2f91eb98c8091590f6ab2";s:4:"name";s:83:"Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.php";s:4:"role";s:3:"php";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4888d2851eff9cf472a9acf0e93e33a4";s:4:"name";s:77:"Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php";s:4:"role";s:3:"php";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2945e844ab362b935608de1ccf071018";s:4:"name";s:86:"Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.php";s:4:"role";s:3:"php";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5ba08141bb0ac7eb83d877a87e9689ed";s:4:"name";s:84:"Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.php";s:4:"role";s:3:"php";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cfc5b482e19a6559b87fa3cc80665720";s:4:"name";s:79:"Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.php";s:4:"role";s:3:"php";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3dd46ffbfb5919606d71d89c5bf82f97";s:4:"name";s:83:"Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.php";s:4:"role";s:3:"php";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"417cad7687deea94ba31fe8d86fcbdf1";s:4:"name";s:82:"Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.php";s:4:"role";s:3:"php";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"50a0fa6d56839562be5866c8a3915497";s:4:"name";s:70:"Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php";s:4:"role";s:3:"php";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4185126f45762b4301b9b6cb2d159bb9";s:4:"name";s:71:"Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php";s:4:"role";s:3:"php";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e5015c2bc9254901b0255ced46129f93";s:4:"name";s:78:"Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php";s:4:"role";s:3:"php";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"822307b7ea3a72ec932599c9bece3a97";s:4:"name";s:72:"Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php";s:4:"role";s:3:"php";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4143633b44f1659cf8409a64ca407b51";s:4:"name";s:71:"Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php";s:4:"role";s:3:"php";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4bd196890e484daf675d82322028be1c";s:4:"name";s:78:"Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php";s:4:"role";s:3:"php";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cdc9190c3179e73eaecdbbbca659b22e";s:4:"name";s:56:"Symfony/Component/Security/Core/AuthenticationEvents.php";s:4:"role";s:3:"php";}}i:101;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4a6916eb9cf4fc40f478dbb623ffdce9";s:4:"name";s:71:"Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php";s:4:"role";s:3:"php";}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2865601c03c45ce3621d9013c5347d9f";s:4:"name";s:80:"Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.php";s:4:"role";s:3:"php";}}i:103;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b7fae5344cfe097002ea98131ce6956";s:4:"name";s:68:"Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php";s:4:"role";s:3:"php";}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2f64cf4065691e1e0b9c4c0f1425f80";s:4:"name";s:74:"Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php";s:4:"role";s:3:"php";}}i:105;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2ea414aff917d1469902138f7e0d5cd0";s:4:"name";s:71:"Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php";s:4:"role";s:3:"php";}}i:106;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"089ca490f923e6a32cf080b0e2a27e2f";s:4:"name";s:74:"Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.php";s:4:"role";s:3:"php";}}i:107;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff0a673dff9312faaebb78b23a04535f";s:4:"name";s:65:"Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php";s:4:"role";s:3:"php";}}i:108;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"003e7949d849e45e4fdffa9a835a2599";s:4:"name";s:70:"Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php";s:4:"role";s:3:"php";}}i:109;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"15e1e6270e2d6d3318237d3363338f50";s:4:"name";s:45:"Symfony/Component/Security/Core/composer.json";s:4:"role";s:3:"doc";}}i:110;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a7a02c1c8ee5f97fdc8c267b48ae13ed";s:4:"name";s:63:"Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.php";s:4:"role";s:3:"php";}}i:111;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0f16a3510e7372c61dd03b2b3bb7564f";s:4:"name";s:65:"Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php";s:4:"role";s:3:"php";}}i:112;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6c687634e27d9118951ce27c88dfe481";s:4:"name";s:58:"Symfony/Component/Security/Core/Encoder/EncoderFactory.php";s:4:"role";s:3:"php";}}i:113;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1330018384392f42e4b5caa6cb012f95";s:4:"name";s:67:"Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.php";s:4:"role";s:3:"php";}}i:114;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7cd742b70754d9c9d8f0ca029ef4b64f";s:4:"name";s:72:"Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php";s:4:"role";s:3:"php";}}i:115;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0dde4a14a6d89ad005406ffbf9422d1f";s:4:"name";s:68:"Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.php";s:4:"role";s:3:"php";}}i:116;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a97a3832eee0a328215a49fb252282fb";s:4:"name";s:65:"Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.php";s:4:"role";s:3:"php";}}i:117;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e07d25f0fa35b7bfc88b3d19478da95e";s:4:"name";s:68:"Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.php";s:4:"role";s:3:"php";}}i:118;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e976a22829d8fd7b3a67528c5f68610f";s:4:"name";s:61:"Symfony/Component/Security/Core/Event/AuthenticationEvent.php";s:4:"role";s:3:"php";}}i:119;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c303cb0e16eab8cbaa2d24d416dc89b1";s:4:"name";s:68:"Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.php";s:4:"role";s:3:"php";}}i:120;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"92c25b19f903e89aa16d8cd887600d9b";s:4:"name";s:67:"Symfony/Component/Security/Core/Exception/AccessDeniedException.php";s:4:"role";s:3:"php";}}i:121;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cbaf077cb23fd56e405fe305089be4f1";s:4:"name";s:69:"Symfony/Component/Security/Core/Exception/AccountExpiredException.php";s:4:"role";s:3:"php";}}i:122;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"897def6142e95038f5b7e1be80789952";s:4:"name";s:68:"Symfony/Component/Security/Core/Exception/AccountStatusException.php";s:4:"role";s:3:"php";}}i:123;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f216cb63ef5a186ee50eba5144ceddc7";s:4:"name";s:88:"Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.php";s:4:"role";s:3:"php";}}i:124;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"29cc9dc1a7659e59a786dd9788937455";s:4:"name";s:69:"Symfony/Component/Security/Core/Exception/AuthenticationException.php";s:4:"role";s:3:"php";}}i:125;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9208968ac310a1959595d8bfc270c270";s:4:"name";s:76:"Symfony/Component/Security/Core/Exception/AuthenticationServiceException.php";s:4:"role";s:3:"php";}}i:126;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8dcc2180afe1ca2a5ba64b3b7b9374b7";s:4:"name";s:69:"Symfony/Component/Security/Core/Exception/BadCredentialsException.php";s:4:"role";s:3:"php";}}i:127;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1501fc38bd5c20b9c3bc3fde481d096d";s:4:"name";s:66:"Symfony/Component/Security/Core/Exception/CookieTheftException.php";s:4:"role";s:3:"php";}}i:128;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7f862b829f86bf262fef80f92fa1efd9";s:4:"name";s:73:"Symfony/Component/Security/Core/Exception/CredentialsExpiredException.php";s:4:"role";s:3:"php";}}i:129;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"964e01e15a4fc37e74bf8b832495e786";s:4:"name";s:63:"Symfony/Component/Security/Core/Exception/DisabledException.php";s:4:"role";s:3:"php";}}i:130;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"13fca1be9c3957516e99beb9811cbea5";s:4:"name";s:64:"Symfony/Component/Security/Core/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:131;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"437a16a50032457b90bec37786b55947";s:4:"name";s:81:"Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.php";s:4:"role";s:3:"php";}}i:132;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5851c6d868699f1dc1e6eccb96793449";s:4:"name";s:70:"Symfony/Component/Security/Core/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";}}i:133;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0822aa405f9ea4d78d55f91c8b74eeb7";s:4:"name";s:71:"Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.php";s:4:"role";s:3:"php";}}i:134;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5d23c71dcff00d3f9a716115caa7164d";s:4:"name";s:61:"Symfony/Component/Security/Core/Exception/LockedException.php";s:4:"role";s:3:"php";}}i:135;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7e9bb714f4fdc03bf4158d3ebafd9181";s:4:"name";s:61:"Symfony/Component/Security/Core/Exception/LogoutException.php";s:4:"role";s:3:"php";}}i:136;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba9525c7d4bc829f3569f785b9399c18";s:4:"name";s:67:"Symfony/Component/Security/Core/Exception/NonceExpiredException.php";s:4:"role";s:3:"php";}}i:137;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc44ab7bd2bf3f5118c22c174d164773";s:4:"name";s:71:"Symfony/Component/Security/Core/Exception/ProviderNotFoundException.php";s:4:"role";s:3:"php";}}i:138;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eedf3a5276fc76bb3c7854d3ae9410ea";s:4:"name";s:62:"Symfony/Component/Security/Core/Exception/RuntimeException.php";s:4:"role";s:3:"php";}}i:139;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"67db74104de766f8625e248576f999da";s:4:"name";s:73:"Symfony/Component/Security/Core/Exception/SessionUnavailableException.php";s:4:"role";s:3:"php";}}i:140;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d9b2b76d30d8faa7835d19faa92e7746";s:4:"name";s:68:"Symfony/Component/Security/Core/Exception/TokenNotFoundException.php";s:4:"role";s:3:"php";}}i:141;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6a7031722e579b577881dd26548a2582";s:4:"name";s:70:"Symfony/Component/Security/Core/Exception/UnsupportedUserException.php";s:4:"role";s:3:"php";}}i:142;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1bbd1cdc4a27e69cb001f60f6f17b953";s:4:"name";s:71:"Symfony/Component/Security/Core/Exception/UsernameNotFoundException.php";s:4:"role";s:3:"php";}}i:143;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:39:"Symfony/Component/Security/Core/LICENSE";s:4:"role";s:3:"doc";}}i:144;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b24852b42833e802e562d16e16c4e819";s:4:"name";s:48:"Symfony/Component/Security/Core/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:145;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f20b648364f60e5c4c4093a968fc5331";s:4:"name";s:41:"Symfony/Component/Security/Core/README.md";s:4:"role";s:3:"doc";}}i:146;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1e750b4762305800f3dd181eab53e2ba";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ar.xlf";s:4:"role";s:3:"php";}}i:147;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"31cbf1bd957d4f4c3401c20d9a1b10bc";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ca.xlf";s:4:"role";s:3:"php";}}i:148;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0cf2e748f73950fb74f6a5978ab773f4";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.cs.xlf";s:4:"role";s:3:"php";}}i:149;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fcd7c0a40a3a5b074abce43148053890";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.da.xlf";s:4:"role";s:3:"php";}}i:150;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a01afc0ce8bdc7598652c6560fae8512";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.de.xlf";s:4:"role";s:3:"php";}}i:151;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2883d0b5e1e7eeed7ec66ea9853f5cc";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.el.xlf";s:4:"role";s:3:"php";}}i:152;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0c6a0114323a39fad8cb33246be7b7d9";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.en.xlf";s:4:"role";s:3:"php";}}i:153;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7ae3e719888ac0c94aeda98734b5e9f5";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.es.xlf";s:4:"role";s:3:"php";}}i:154;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eef6f0230157636659e13c466e498cd9";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.fa.xlf";s:4:"role";s:3:"php";}}i:155;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d726781df922dfb126eb85c6c1cf7f5";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.fr.xlf";s:4:"role";s:3:"php";}}i:156;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d24525aa71ea6294f1b0dad40d7a5b70";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.gl.xlf";s:4:"role";s:3:"php";}}i:157;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8704be78d7be163b715e166f07257e3";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.hu.xlf";s:4:"role";s:3:"php";}}i:158;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47a2f3df6c37532fe6a486073aebd0a1";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.it.xlf";s:4:"role";s:3:"php";}}i:159;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"defce0bf7d3e026fbdaebb0cfe7abbd6";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.lb.xlf";s:4:"role";s:3:"php";}}i:160;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"79d67b79332d77ce5d39a8531f219538";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.nl.xlf";s:4:"role";s:3:"php";}}i:161;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ca24d84b0c49e93e8425dbc96b5d479";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.no.xlf";s:4:"role";s:3:"php";}}i:162;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f6e927ae45bf961507418d03db1c676d";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.pl.xlf";s:4:"role";s:3:"php";}}i:163;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff2d10ee020b23d10e8a49c3f72b77af";s:4:"name";s:73:"Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlf";s:4:"role";s:3:"php";}}i:164;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2855177bf25fd860bca194067f350e0a";s:4:"name";s:73:"Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf";s:4:"role";s:3:"php";}}i:165;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f07b53a0e13bb3f1267b212e07b49a14";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ro.xlf";s:4:"role";s:3:"php";}}i:166;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f943d4b750be69bd91e03eca27df52f5";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ru.xlf";s:4:"role";s:3:"php";}}i:167;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a570f49a5deb0bba84a8f5ce71018b32";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.sk.xlf";s:4:"role";s:3:"php";}}i:168;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0a5e641bcbd17d9502a2f2f3e1d51999";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.sl.xlf";s:4:"role";s:3:"php";}}i:169;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"823f2ed1191ec9723d46f2516d700973";s:4:"name";s:75:"Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf";s:4:"role";s:3:"php";}}i:170;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a95969c966594fa2afcf4c0f58dcf034";s:4:"name";s:75:"Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf";s:4:"role";s:3:"php";}}i:171;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ef66c814ecc8a2fc5fbbe30dd23f3a82";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.sv.xlf";s:4:"role";s:3:"php";}}i:172;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0d789d9cb295319cb483f864ca99b2bf";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.tr.xlf";s:4:"role";s:3:"php";}}i:173;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c7e13f578ddab881e5bb035d0e905048";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ua.xlf";s:4:"role";s:3:"php";}}i:174;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3050382d1549c2b01456b9361e8facd3";s:4:"name";s:45:"Symfony/Component/Security/Core/Role/Role.php";s:4:"role";s:3:"php";}}i:175;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bca85cac483875c294bb4577942b5e13";s:4:"name";s:54:"Symfony/Component/Security/Core/Role/RoleHierarchy.php";s:4:"role";s:3:"php";}}i:176;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"675f61146da7cd1caec751a2d261b0e6";s:4:"name";s:63:"Symfony/Component/Security/Core/Role/RoleHierarchyInterface.php";s:4:"role";s:3:"php";}}i:177;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b03592fb0521d323c36939ab08985fce";s:4:"name";s:54:"Symfony/Component/Security/Core/Role/RoleInterface.php";s:4:"role";s:3:"php";}}i:178;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8826f3ebe695c64183b161bc895da3d9";s:4:"name";s:55:"Symfony/Component/Security/Core/Role/SwitchUserRole.php";s:4:"role";s:3:"php";}}i:179;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"10ecd1343fe383863fcf07aea6e1484e";s:4:"name";s:51:"Symfony/Component/Security/Core/SecurityContext.php";s:4:"role";s:3:"php";}}i:180;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"55a5781675e114c92bad8bad5aa2830d";s:4:"name";s:60:"Symfony/Component/Security/Core/SecurityContextInterface.php";s:4:"role";s:3:"php";}}i:181;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b63b6b59d9a86eb0d75e0b96f791cebe";s:4:"name";s:90:"Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php";s:4:"role";s:4:"test";}}i:182;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"678c0f4dcee8c6b4c914596f68e8066c";s:4:"name";s:88:"Symfony/Component/Security/Core/Tests/Authentication/AuthenticationTrustResolverTest.php";s:4:"role";s:4:"test";}}i:183;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b7f1e61792f26921f8ac8005047ec5a";s:4:"name";s:101:"Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php";s:4:"role";s:4:"test";}}i:184;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9e46dd36c66d8390ff4ef27308eaf788";s:4:"name";s:95:"Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php";s:4:"role";s:4:"test";}}i:185;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"56a160fc914fa20188f3fb4428231071";s:4:"name";s:108:"Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php";s:4:"role";s:4:"test";}}i:186;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d87ce759a8a0bc6a43e083bcbf65a7e";s:4:"name";s:102:"Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php";s:4:"role";s:4:"test";}}i:187;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"878a24250d15912e8875b761f1b18cd6";s:4:"name";s:96:"Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php";s:4:"role";s:4:"test";}}i:188;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dd3f29d0edf632c2e0668095d433e2b8";s:4:"name";s:93:"Symfony/Component/Security/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php";s:4:"role";s:4:"test";}}i:189;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"333af5f2e4fca41f0ad52c067fc6f6fa";s:4:"name";s:87:"Symfony/Component/Security/Core/Tests/Authentication/RememberMe/PersistentTokenTest.php";s:4:"role";s:4:"test";}}i:190;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63d1895301e8c4db998257793246ddd4";s:4:"name";s:80:"Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php";s:4:"role";s:4:"test";}}i:191;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"165abe0414d3fd9f6b87b77a974dbf87";s:4:"name";s:81:"Symfony/Component/Security/Core/Tests/Authentication/Token/AnonymousTokenTest.php";s:4:"role";s:4:"test";}}i:192;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea0e9ad02afbff6e37eb9dcceb635102";s:4:"name";s:88:"Symfony/Component/Security/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.php";s:4:"role";s:4:"test";}}i:193;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"881577a37dc13881037471af86e54c26";s:4:"name";s:88:"Symfony/Component/Security/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.php";s:4:"role";s:4:"test";}}i:194;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"01615835979113e72ba01df5db514cfe";s:4:"name";s:81:"Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php";s:4:"role";s:4:"test";}}i:195;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"53e2015913c42918f488b6b5768dcfd6";s:4:"name";s:78:"Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.php";s:4:"role";s:4:"test";}}i:196;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09a4601d7459111b412a28d8b3ba77e6";s:4:"name";s:84:"Symfony/Component/Security/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.php";s:4:"role";s:4:"test";}}i:197;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f7de9f0134587eca878b84fa96cd4e11";s:4:"name";s:81:"Symfony/Component/Security/Core/Tests/Authorization/Voter/ExpressionVoterTest.php";s:4:"role";s:4:"test";}}i:198;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1515e17b427defd7ede0b26cd62d6f7c";s:4:"name";s:84:"Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.php";s:4:"role";s:4:"test";}}i:199;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6eafbf6e21bcb931d7deeb6c7a03d09d";s:4:"name";s:75:"Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleVoterTest.php";s:4:"role";s:4:"test";}}i:200;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"262dd768f1ab73f96eee0a29a7665d3f";s:4:"name";s:73:"Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.php";s:4:"role";s:4:"test";}}i:201;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a052af732959cb4100386622650cde49";s:4:"name";s:75:"Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php";s:4:"role";s:4:"test";}}i:202;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c4466a3921e1ef6bc3ffa19e825cc264";s:4:"name";s:68:"Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.php";s:4:"role";s:4:"test";}}i:203;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1a2e9523c0f574255c5e8cc12563036d";s:4:"name";s:82:"Symfony/Component/Security/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.php";s:4:"role";s:4:"test";}}i:204;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47d32cbddb94e8c940a067da8bd652c8";s:4:"name";s:75:"Symfony/Component/Security/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.php";s:4:"role";s:4:"test";}}i:205;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9a3e27e7243e0aef39d89ce5048f0156";s:4:"name";s:78:"Symfony/Component/Security/Core/Tests/Encoder/PlaintextPasswordEncoderTest.php";s:4:"role";s:4:"test";}}i:206;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e84df0653432699a74f9892f39cd801d";s:4:"name";s:64:"Symfony/Component/Security/Core/Tests/Role/RoleHierarchyTest.php";s:4:"role";s:4:"test";}}i:207;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6faeaa1b59d680fc64f68f187d3b8ad4";s:4:"name";s:55:"Symfony/Component/Security/Core/Tests/Role/RoleTest.php";s:4:"role";s:4:"test";}}i:208;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63e6fa508f87e6843cdc7d4dbb310ed4";s:4:"name";s:65:"Symfony/Component/Security/Core/Tests/Role/SwitchUserRoleTest.php";s:4:"role";s:4:"test";}}i:209;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c6a315c41a473173516a7b97d7bd135f";s:4:"name";s:61:"Symfony/Component/Security/Core/Tests/SecurityContextTest.php";s:4:"role";s:4:"test";}}i:210;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"39059760376a28b3a1289ebeeefbf9ef";s:4:"name";s:68:"Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php";s:4:"role";s:4:"test";}}i:211;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"92589d6ad763ccd817043e6b5fb5865d";s:4:"name";s:55:"Symfony/Component/Security/Core/Tests/User/UserTest.php";s:4:"role";s:4:"test";}}i:212;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"51ae9e53749a60e2d99ca0fa4893a68a";s:4:"name";s:61:"Symfony/Component/Security/Core/Tests/Util/ClassUtilsTest.php";s:4:"role";s:4:"test";}}i:213;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"172dc84386daa4193854aad1078407fb";s:4:"name";s:63:"Symfony/Component/Security/Core/Tests/Util/SecureRandomTest.php";s:4:"role";s:4:"test";}}i:214;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a80a7c57b6922fd9a9925a82a7741a01";s:4:"name";s:62:"Symfony/Component/Security/Core/Tests/Util/StringUtilsTest.php";s:4:"role";s:4:"test";}}i:215;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2ecdc8fea6ea459acf382fbd0de514c";s:4:"name";s:89:"Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php";s:4:"role";s:4:"test";}}i:216;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dac22529730e8721ae339aacb05b561c";s:4:"name";s:62:"Symfony/Component/Security/Core/User/AdvancedUserInterface.php";s:4:"role";s:3:"php";}}i:217;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"16ad9f1561e239188cb64ff12a4cd713";s:4:"name";s:58:"Symfony/Component/Security/Core/User/ChainUserProvider.php";s:4:"role";s:3:"php";}}i:218;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"053bfd3d7feb51135f125c471e0919f2";s:4:"name";s:59:"Symfony/Component/Security/Core/User/EquatableInterface.php";s:4:"role";s:3:"php";}}i:219;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c62ec26256558502bdff94ccdff8f4c3";s:4:"name";s:61:"Symfony/Component/Security/Core/User/InMemoryUserProvider.php";s:4:"role";s:3:"php";}}i:220;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a36d5dcfd2e90b7079473de27ece3f0c";s:4:"name";s:45:"Symfony/Component/Security/Core/User/User.php";s:4:"role";s:3:"php";}}i:221;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"915fa1f4c48a7ce2f501c26b7a784f28";s:4:"name";s:52:"Symfony/Component/Security/Core/User/UserChecker.php";s:4:"role";s:3:"php";}}i:222;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"388e848eda1ffa8b46dd0ae9bf227b90";s:4:"name";s:61:"Symfony/Component/Security/Core/User/UserCheckerInterface.php";s:4:"role";s:3:"php";}}i:223;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47ee6a0d6557868aaf10450f4137462b";s:4:"name";s:54:"Symfony/Component/Security/Core/User/UserInterface.php";s:4:"role";s:3:"php";}}i:224;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"482f41d8bda5807c72c319d1d2a11c09";s:4:"name";s:62:"Symfony/Component/Security/Core/User/UserProviderInterface.php";s:4:"role";s:3:"php";}}i:225;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dd14c33e711d9ac06c1507157e32f166";s:4:"name";s:51:"Symfony/Component/Security/Core/Util/ClassUtils.php";s:4:"role";s:3:"php";}}i:226;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b650297a6cfe3a6947488561371c574";s:4:"name";s:53:"Symfony/Component/Security/Core/Util/SecureRandom.php";s:4:"role";s:3:"php";}}i:227;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9ac637cacec94e99f0a7af4154ea16ef";s:4:"name";s:62:"Symfony/Component/Security/Core/Util/SecureRandomInterface.php";s:4:"role";s:3:"php";}}i:228;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e9ba381671f8b8f44a880028850a3dc6";s:4:"name";s:52:"Symfony/Component/Security/Core/Util/StringUtils.php";s:4:"role";s:3:"php";}}i:229;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"681b19bd49acd0a67bf514c0a420e164";s:4:"name";s:70:"Symfony/Component/Security/Core/Validator/Constraints/UserPassword.php";s:4:"role";s:3:"php";}}i:230;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"73b05740588c9089f62ddccb23b85de2";s:4:"name";s:79:"Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php";s:4:"role";s:3:"php";}}i:231;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8bf68c5cb8ecade41dedb7a808186bfc";s:4:"name";s:45:"Symfony/Component/Security/Csrf/composer.json";s:4:"role";s:3:"doc";}}i:232;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8dd9faf3aa313127ffcf0106abafdb34";s:4:"name";s:45:"Symfony/Component/Security/Csrf/CsrfToken.php";s:4:"role";s:3:"php";}}i:233;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4584d3d466fbd310bd1c3730a53aba62";s:4:"name";s:52:"Symfony/Component/Security/Csrf/CsrfTokenManager.php";s:4:"role";s:3:"php";}}i:234;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4f9257a2c8b6285605af062e31e92c51";s:4:"name";s:61:"Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.php";s:4:"role";s:3:"php";}}i:235;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"283b3574fff8ff0c093c8c2c74024fb0";s:4:"name";s:68:"Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.php";s:4:"role";s:3:"php";}}i:236;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:39:"Symfony/Component/Security/Csrf/LICENSE";s:4:"role";s:3:"doc";}}i:237;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4a5e98782fbba28092cafe77c3168c51";s:4:"name";s:48:"Symfony/Component/Security/Csrf/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:238;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f7759c45cd4a446a228ed648286acf8f";s:4:"name";s:41:"Symfony/Component/Security/Csrf/README.md";s:4:"role";s:3:"doc";}}i:239;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3de809f4f691151c195fba128ff1e32d";s:4:"name";s:62:"Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.php";s:4:"role";s:4:"test";}}i:240;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc23118b2998753a1a5d8d744edb93e9";s:4:"name";s:82:"Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.php";s:4:"role";s:4:"test";}}i:241;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"362691003c5cc955877ecd235ef329d5";s:4:"name";s:84:"Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php";s:4:"role";s:4:"test";}}i:242;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6a12af8493e94dd61cffa21f05b8dac8";s:4:"name";s:78:"Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php";s:4:"role";s:4:"test";}}i:243;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dab50ef252b23f81bc0a28dd6ed3c2f0";s:4:"name";s:74:"Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.php";s:4:"role";s:3:"php";}}i:244;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2cac1d204af23007d684c61435e0275a";s:4:"name";s:72:"Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.php";s:4:"role";s:3:"php";}}i:245;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c6aa4826742510546c711553b19d87a4";s:4:"name";s:74:"Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php";s:4:"role";s:3:"php";}}i:246;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3525f5f7040f8b2e3fb7f2df67c3e52b";s:4:"name";s:68:"Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.php";s:4:"role";s:3:"php";}}i:247;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"602d9216e9b1d1f0d22b31c902e5b4bb";s:4:"name";s:70:"Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.php";s:4:"role";s:3:"php";}}i:248;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9df423675054d980e7bae7cc92020c03";s:4:"name";s:45:"Symfony/Component/Security/Http/AccessMap.php";s:4:"role";s:3:"php";}}i:249;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"43086a06e68384eaccab38dfb698786d";s:4:"name";s:54:"Symfony/Component/Security/Http/AccessMapInterface.php";s:4:"role";s:3:"php";}}i:250;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1a26ecccd324ea272277edffc5c84886";s:4:"name";s:88:"Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.php";s:4:"role";s:3:"php";}}i:251;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1249ffb01efe413cfd97a5337cb00137";s:4:"name";s:88:"Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.php";s:4:"role";s:3:"php";}}i:252;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4b78405b37b8d39c63538f637fd497dc";s:4:"name";s:86:"Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.php";s:4:"role";s:3:"php";}}i:253;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d1a101bba266130a6fdbfc92126cef07";s:4:"name";s:86:"Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php";s:4:"role";s:3:"php";}}i:254;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ed65679f667d9ef57a6791a64a8bd6c2";s:4:"name";s:78:"Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.php";s:4:"role";s:3:"php";}}i:255;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"afbc8d72124b7a6aee7879fa64325a9f";s:4:"name";s:78:"Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.php";s:4:"role";s:3:"php";}}i:256;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b7cd3c1e3d2a0a5cacc080b87c9e590";s:4:"name";s:45:"Symfony/Component/Security/Http/composer.json";s:4:"role";s:3:"doc";}}i:257;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6d3ec77aadf630304cff4ed3c026b086";s:4:"name";s:80:"Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php";s:4:"role";s:3:"php";}}i:258;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0cacf36e7c79e4ca8e7fad2ad771335d";s:4:"name";s:76:"Symfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.php";s:4:"role";s:3:"php";}}i:259;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0916b4aabd44274d2a1d24d7eccd3370";s:4:"name";s:77:"Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php";s:4:"role";s:3:"php";}}i:260;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"957245bb0cc25e4ddfa36ff11b60cf31";s:4:"name";s:75:"Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php";s:4:"role";s:3:"php";}}i:261;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e3cec247e8df4a6e97c579e4ea923bc4";s:4:"name";s:76:"Symfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.php";s:4:"role";s:3:"php";}}i:262;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"99b4defc6b93df2b7f1c0b4dedef3ff9";s:4:"name";s:63:"Symfony/Component/Security/Http/Event/InteractiveLoginEvent.php";s:4:"role";s:3:"php";}}i:263;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7ce04d8a18a0487f987e31fc88bd68c5";s:4:"name";s:57:"Symfony/Component/Security/Http/Event/SwitchUserEvent.php";s:4:"role";s:3:"php";}}i:264;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c38b7e9b63bb0cc12e471d58062964b7";s:4:"name";s:75:"Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php";s:4:"role";s:3:"php";}}i:265;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0a1aebef9c2f8f6a328e6227052df7ab";s:4:"name";s:77:"Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php";s:4:"role";s:3:"php";}}i:266;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5aa38481213505e4d4b3308202f16ae2";s:4:"name";s:59:"Symfony/Component/Security/Http/Firewall/AccessListener.php";s:4:"role";s:3:"php";}}i:267;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fffa376fb78716df7994bd30c2c3d8e2";s:4:"name";s:76:"Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php";s:4:"role";s:3:"php";}}i:268;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b35cfc2ded8a8aa315ba7ee88ae788b5";s:4:"name";s:72:"Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php";s:4:"role";s:3:"php";}}i:269;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"850ac32b9360422daedb18164af00887";s:4:"name";s:60:"Symfony/Component/Security/Http/Firewall/ChannelListener.php";s:4:"role";s:3:"php";}}i:270;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"096bd4d9e3b975fcac84503f61384b7e";s:4:"name";s:60:"Symfony/Component/Security/Http/Firewall/ContextListener.php";s:4:"role";s:3:"php";}}i:271;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c9c8fa0fd59936274a596a360568a575";s:4:"name";s:73:"Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php";s:4:"role";s:3:"php";}}i:272;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0b7d00f42228ca3d4827012968c69a8c";s:4:"name";s:62:"Symfony/Component/Security/Http/Firewall/ExceptionListener.php";s:4:"role";s:3:"php";}}i:273;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6f43f337a4368b4d7b1cce0e76b51b10";s:4:"name";s:62:"Symfony/Component/Security/Http/Firewall/ListenerInterface.php";s:4:"role";s:3:"php";}}i:274;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"42ad987ff1e6284b2fd2f11d5cf09725";s:4:"name";s:59:"Symfony/Component/Security/Http/Firewall/LogoutListener.php";s:4:"role";s:3:"php";}}i:275;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"becb8470e4e05de6ad82ff6bf7e646fc";s:4:"name";s:63:"Symfony/Component/Security/Http/Firewall/RememberMeListener.php";s:4:"role";s:3:"php";}}i:276;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3c80c1a805d89cfd4f475aa5d8517267";s:4:"name";s:77:"Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php";s:4:"role";s:3:"php";}}i:277;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e06e2b324e79ee890f1feebba9bc8ac3";s:4:"name";s:76:"Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php";s:4:"role";s:3:"php";}}i:278;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"62963e5323a197109f7f7f3e860154ca";s:4:"name";s:63:"Symfony/Component/Security/Http/Firewall/SwitchUserListener.php";s:4:"role";s:3:"php";}}i:279;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4f883d92d37fd6eb289b50abd37ae680";s:4:"name";s:87:"Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php";s:4:"role";s:3:"php";}}i:280;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"08351ed63f27f17c1b35b08600cc8864";s:4:"name";s:71:"Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.php";s:4:"role";s:3:"php";}}i:281;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ee01a78804fc30696b6ec0eeef5c59a6";s:4:"name";s:44:"Symfony/Component/Security/Http/Firewall.php";s:4:"role";s:3:"php";}}i:282;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2a749495dc3be6af3a2fd28e729c80a6";s:4:"name";s:47:"Symfony/Component/Security/Http/FirewallMap.php";s:4:"role";s:3:"php";}}i:283;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87ce09ab99f6ec6b472a725abff910c5";s:4:"name";s:56:"Symfony/Component/Security/Http/FirewallMapInterface.php";s:4:"role";s:3:"php";}}i:284;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a2bb9c5c5076b9a7978f301b64c00b9e";s:4:"name";s:45:"Symfony/Component/Security/Http/HttpUtils.php";s:4:"role";s:3:"php";}}i:285;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:39:"Symfony/Component/Security/Http/LICENSE";s:4:"role";s:3:"doc";}}i:286;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e5ddc1de0d071bdeacbcd2325ed2d4ae";s:4:"name";s:70:"Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php";s:4:"role";s:3:"php";}}i:287;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"45d84fb75d34ea9135c5b72108e1dbf7";s:4:"name";s:70:"Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.php";s:4:"role";s:3:"php";}}i:288;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eefeebbc791fa1bccf5a3952be87ba78";s:4:"name";s:65:"Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.php";s:4:"role";s:3:"php";}}i:289;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cc172ba7205b41a32dd97a56eadf4cc8";s:4:"name";s:72:"Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.php";s:4:"role";s:3:"php";}}i:290;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aecd2ef66d8aade29cc47157048e4a21";s:4:"name";s:63:"Symfony/Component/Security/Http/Logout/SessionLogoutHandler.php";s:4:"role";s:3:"php";}}i:291;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2f041adb26153b8fb15facf2c6af231d";s:4:"name";s:48:"Symfony/Component/Security/Http/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:292;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a345783d58ade730c9a01639748b41c6";s:4:"name";s:41:"Symfony/Component/Security/Http/README.md";s:4:"role";s:3:"doc";}}i:293;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b72e5cba34abbeea45218aced16a6359";s:4:"name";s:73:"Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php";s:4:"role";s:3:"php";}}i:294;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"435ea3e4c99dd22c771c99f16392c656";s:4:"name";s:85:"Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php";s:4:"role";s:3:"php";}}i:295;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d0150afc723a4bb2f322842c1e0a8ce6";s:4:"name";s:74:"Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php";s:4:"role";s:3:"php";}}i:296;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1d39556b7575907aa6f092bb4c07f387";s:4:"name";s:63:"Symfony/Component/Security/Http/RememberMe/ResponseListener.php";s:4:"role";s:3:"php";}}i:297;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2e0288eec870215f3f4b8e360afbcf21";s:4:"name";s:75:"Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php";s:4:"role";s:3:"php";}}i:298;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80cf473a2f0baee880e458d5946fde6b";s:4:"name";s:50:"Symfony/Component/Security/Http/SecurityEvents.php";s:4:"role";s:3:"php";}}i:299;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f4eee94c1c2e104f0ce7b8d5bd349fa0";s:4:"name";s:73:"Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php";s:4:"role";s:3:"php";}}i:300;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a8df527492a3c775c0c2d3affaec1268";s:4:"name";s:82:"Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.php";s:4:"role";s:3:"php";}}i:301;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1e501db8e61f7fbbe1ce2046846d0d16";s:4:"name";s:55:"Symfony/Component/Security/Http/Tests/AccessMapTest.php";s:4:"role";s:4:"test";}}i:302;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d3e7326491ec2358ba350f4a937d9778";s:4:"name";s:96:"Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php";s:4:"role";s:4:"test";}}i:303;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f238eea0886f4d046befadaa74b02fbe";s:4:"name";s:96:"Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php";s:4:"role";s:4:"test";}}i:304;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5cef550f4e58533d96feab10cdf02d7";s:4:"name";s:88:"Symfony/Component/Security/Http/Tests/Authentication/SimpleAuthenticationHandlerTest.php";s:4:"role";s:4:"test";}}i:305;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"44e155837ffd4ba5e88a3fe86fa0371a";s:4:"name";s:86:"Symfony/Component/Security/Http/Tests/EntryPoint/BasicAuthenticationEntryPointTest.php";s:4:"role";s:4:"test";}}i:306;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cf8ce9dfa9ef2b8cf64c2bca4eeaa2ee";s:4:"name";s:87:"Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php";s:4:"role";s:4:"test";}}i:307;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6f33e2bc5d33de50781109deaa92375b";s:4:"name";s:85:"Symfony/Component/Security/Http/Tests/EntryPoint/FormAuthenticationEntryPointTest.php";s:4:"role";s:4:"test";}}i:308;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9e4221ac3557ad490f50b572a1cb6da0";s:4:"name";s:86:"Symfony/Component/Security/Http/Tests/EntryPoint/RetryAuthenticationEntryPointTest.php";s:4:"role";s:4:"test";}}i:309;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7616457ff22f218eb84d0582b3a32d99";s:4:"name";s:87:"Symfony/Component/Security/Http/Tests/Firewall/AbstractPreAuthenticatedListenerTest.php";s:4:"role";s:4:"test";}}i:310;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"50390ecbf94ded92656d9de6570d63c1";s:4:"name";s:69:"Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php";s:4:"role";s:4:"test";}}i:311;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d3745efe02656a6a40d2421791a65ab2";s:4:"name";s:86:"Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php";s:4:"role";s:4:"test";}}i:312;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f9b4fe52898a270086a0323bc9e744d2";s:4:"name";s:82:"Symfony/Component/Security/Http/Tests/Firewall/BasicAuthenticationListenerTest.php";s:4:"role";s:4:"test";}}i:313;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"39f3a9fbfd8fb369e3518c1f737c69d1";s:4:"name";s:70:"Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.php";s:4:"role";s:4:"test";}}i:314;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fefeae0b89d7bce7c98fd5f79e64fb80";s:4:"name";s:70:"Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php";s:4:"role";s:4:"test";}}i:315;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0cd7a88d1e73a7c2397a05ee835b416e";s:4:"name";s:65:"Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php";s:4:"role";s:4:"test";}}i:316;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bdc936486eb622f5ebc89def545d34cc";s:4:"name";s:69:"Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php";s:4:"role";s:4:"test";}}i:317;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5aa221a87c438540d59e8d06cbc51e43";s:4:"name";s:73:"Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php";s:4:"role";s:4:"test";}}i:318;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4e401aaf8580c5f225065eb296d09ffd";s:4:"name";s:73:"Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php";s:4:"role";s:4:"test";}}i:319;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"62ada44f4eeb63bc411ebff114f5f340";s:4:"name";s:81:"Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.php";s:4:"role";s:4:"test";}}i:320;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"90e0766898394d8523cb8d3093b8ad0f";s:4:"name";s:57:"Symfony/Component/Security/Http/Tests/FirewallMapTest.php";s:4:"role";s:4:"test";}}i:321;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"58a4fef6ae246369bdff44ea9566e2e7";s:4:"name";s:54:"Symfony/Component/Security/Http/Tests/FirewallTest.php";s:4:"role";s:4:"test";}}i:322;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a65c06a07157d8b2f79f1718fe9acc3a";s:4:"name";s:55:"Symfony/Component/Security/Http/Tests/HttpUtilsTest.php";s:4:"role";s:4:"test";}}i:323;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d82d3ab3c92583cd9aa15b9ed8ae9db2";s:4:"name";s:80:"Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.php";s:4:"role";s:4:"test";}}i:324;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b35e129cc7f5bc083d3b855f286a2228";s:4:"name";s:80:"Symfony/Component/Security/Http/Tests/Logout/DefaultLogoutSuccessHandlerTest.php";s:4:"role";s:4:"test";}}i:325;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"31043c56e00a9f85591f7aeb1a0d7abe";s:4:"name";s:73:"Symfony/Component/Security/Http/Tests/Logout/SessionLogoutHandlerTest.php";s:4:"role";s:4:"test";}}i:326;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a4f462fe63db2978e9eb7b9088a332a1";s:4:"name";s:83:"Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php";s:4:"role";s:4:"test";}}i:327;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1dcfd5f481984cbcbe252c35abb90560";s:4:"name";s:95:"Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php";s:4:"role";s:4:"test";}}i:328;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d8f1bc020d5b21d2de0433c2839b08f9";s:4:"name";s:73:"Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.php";s:4:"role";s:4:"test";}}i:329;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e4109def8460d75d5f052f67ec6ba970";s:4:"name";s:85:"Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php";s:4:"role";s:4:"test";}}i:330;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7787c557da28fb7dd4cc86318f909bb3";s:4:"name";s:83:"Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php";s:4:"role";s:4:"test";}}i:331;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:34:"Symfony/Component/Security/LICENSE";s:4:"role";s:3:"doc";}}i:332;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b48391335127152904b86aef4327b6ba";s:4:"name";s:43:"Symfony/Component/Security/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:333;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4dec033fca5592436030a98806bbf6d7";s:4:"name";s:36:"Symfony/Component/Security/README.md";s:4:"role";s:3:"doc";}}i:334;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1e750b4762305800f3dd181eab53e2ba";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ar.xlf";s:4:"role";s:3:"php";}}i:335;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"60f216b50da4b49da27b177ba8ca3b46";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.bg.xlf";s:4:"role";s:3:"php";}}i:336;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"31cbf1bd957d4f4c3401c20d9a1b10bc";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ca.xlf";s:4:"role";s:3:"php";}}i:337;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0cf2e748f73950fb74f6a5978ab773f4";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.cs.xlf";s:4:"role";s:3:"php";}}i:338;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6d1c01434b6521da496cf9c91c144ea1";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.da.xlf";s:4:"role";s:3:"php";}}i:339;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a01afc0ce8bdc7598652c6560fae8512";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.de.xlf";s:4:"role";s:3:"php";}}i:340;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2883d0b5e1e7eeed7ec66ea9853f5cc";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.el.xlf";s:4:"role";s:3:"php";}}i:341;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0c6a0114323a39fad8cb33246be7b7d9";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.en.xlf";s:4:"role";s:3:"php";}}i:342;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7ae3e719888ac0c94aeda98734b5e9f5";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.es.xlf";s:4:"role";s:3:"php";}}i:343;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eef6f0230157636659e13c466e498cd9";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.fa.xlf";s:4:"role";s:3:"php";}}i:344;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d726781df922dfb126eb85c6c1cf7f5";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.fr.xlf";s:4:"role";s:3:"php";}}i:345;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d24525aa71ea6294f1b0dad40d7a5b70";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.gl.xlf";s:4:"role";s:3:"php";}}i:346;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b03fcbcf3c6586ee539377f3f5a3bdc";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.hr.xlf";s:4:"role";s:3:"php";}}i:347;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8704be78d7be163b715e166f07257e3";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.hu.xlf";s:4:"role";s:3:"php";}}i:348;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"40ec159baa27f18ea7ab7924e652ec97";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.id.xlf";s:4:"role";s:3:"php";}}i:349;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47a2f3df6c37532fe6a486073aebd0a1";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.it.xlf";s:4:"role";s:3:"php";}}i:350;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"acf99e98e5ffff85489c97c78a83b317";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ja.xlf";s:4:"role";s:3:"php";}}i:351;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"defce0bf7d3e026fbdaebb0cfe7abbd6";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.lb.xlf";s:4:"role";s:3:"php";}}i:352;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"79d67b79332d77ce5d39a8531f219538";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.nl.xlf";s:4:"role";s:3:"php";}}i:353;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"03051a200f3f0f13a30ed957026a1784";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.no.xlf";s:4:"role";s:3:"php";}}i:354;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f6e927ae45bf961507418d03db1c676d";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.pl.xlf";s:4:"role";s:3:"php";}}i:355;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5140f0e3d9b00962b72eb4f3cce9b2a4";s:4:"name";s:68:"Symfony/Component/Security/Resources/translations/security.pt_BR.xlf";s:4:"role";s:3:"php";}}i:356;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2855177bf25fd860bca194067f350e0a";s:4:"name";s:68:"Symfony/Component/Security/Resources/translations/security.pt_PT.xlf";s:4:"role";s:3:"php";}}i:357;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f07b53a0e13bb3f1267b212e07b49a14";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ro.xlf";s:4:"role";s:3:"php";}}i:358;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f943d4b750be69bd91e03eca27df52f5";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ru.xlf";s:4:"role";s:3:"php";}}i:359;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a570f49a5deb0bba84a8f5ce71018b32";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.sk.xlf";s:4:"role";s:3:"php";}}i:360;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0a5e641bcbd17d9502a2f2f3e1d51999";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.sl.xlf";s:4:"role";s:3:"php";}}i:361;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"823f2ed1191ec9723d46f2516d700973";s:4:"name";s:70:"Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlf";s:4:"role";s:3:"php";}}i:362;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a95969c966594fa2afcf4c0f58dcf034";s:4:"name";s:70:"Symfony/Component/Security/Resources/translations/security.sr_Latn.xlf";s:4:"role";s:3:"php";}}i:363;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ef66c814ecc8a2fc5fbbe30dd23f3a82";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.sv.xlf";s:4:"role";s:3:"php";}}i:364;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0d789d9cb295319cb483f864ca99b2bf";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.tr.xlf";s:4:"role";s:3:"php";}}i:365;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c7e13f578ddab881e5bb035d0e905048";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ua.xlf";s:4:"role";s:3:"php";}}i:366;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b549799b91bf73427ed2c0de26e8d27e";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.vi.xlf";s:4:"role";s:3:"php";}}i:367;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c1985d9108a24d1e66b1832cf6c0fae7";s:4:"name";s:68:"Symfony/Component/Security/Resources/translations/security.zh_CN.xlf";s:4:"role";s:3:"php";}}i:368;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"82c8dfa2a45c9aca1e839e448574b12b";s:4:"name";s:82:"Symfony/Component/Security/Tests/Core/Authentication/Token/RememberMeTokenTest.php";s:4:"role";s:4:"test";}}i:369;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"77f76d7ae94a351ec03076059c96f80d";s:4:"name";s:71:"Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.php";s:4:"role";s:4:"test";}}i:370;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b095a4893cc953a6aa42a368c70c8a5";s:4:"name";s:62:"Symfony/Component/Security/Tests/Core/User/UserCheckerTest.php";s:4:"role";s:4:"test";}}i:371;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"693af9a30d85b3907c6147d9ddb56df8";s:4:"name";s:72:"Symfony/Component/Security/Tests/Http/Firewall/ExceptionListenerTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}s:7:"package";a:3:{i:0;a:2:{s:4:"name";s:10:"HttpKernel";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:14:"HttpFoundation";s:7:"channel";s:16:"pear.symfony.com";}i:2;a:2:{s:4:"name";s:15:"EventDispatcher";s:7:"channel";s:16:"pear.symfony.com";}}}s:8:"optional";a:1:{s:7:"package";a:4:{i:0;a:2:{s:4:"name";s:7:"Routing";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:6:"Finder";s:7:"channel";s:16:"pear.symfony.com";}i:2;a:2:{s:4:"name";s:11:"ClassLoader";s:7:"channel";s:16:"pear.symfony.com";}i:3;a:2:{s:4:"name";s:4:"Form";s:7:"channel";s:16:"pear.symfony.com";}}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:372:{s:44:"Symfony/Component/Security/Acl/composer.json";a:4:{s:6:"md5sum";s:32:"5365c3fd47df815d4353473ac6373ad7";s:4:"name";s:44:"Symfony/Component/Security/Acl/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Acl/composer.json";}s:51:"Symfony/Component/Security/Acl/Dbal/AclProvider.php";a:4:{s:6:"md5sum";s:32:"0ecf07a353f03ea4c6976d0cf98d5b51";s:4:"name";s:51:"Symfony/Component/Security/Acl/Dbal/AclProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Dbal/AclProvider.php";}s:58:"Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php";a:4:{s:6:"md5sum";s:32:"333ff4aca2f234109cd7ebe9a03c7f25";s:4:"name";s:58:"Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php";}s:46:"Symfony/Component/Security/Acl/Dbal/Schema.php";a:4:{s:6:"md5sum";s:32:"a38fab3cddce11ba90e1569be5f0d806";s:4:"name";s:46:"Symfony/Component/Security/Acl/Dbal/Schema.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Dbal/Schema.php";}s:45:"Symfony/Component/Security/Acl/Domain/Acl.php";a:4:{s:6:"md5sum";s:32:"e8f587fcaf0a3057321516e59fc0ce87";s:4:"name";s:45:"Symfony/Component/Security/Acl/Domain/Acl.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/Acl.php";}s:60:"Symfony/Component/Security/Acl/Domain/AclCollectionCache.php";a:4:{s:6:"md5sum";s:32:"cccc32d88c312fb7dac66b08d9e67e45";s:4:"name";s:60:"Symfony/Component/Security/Acl/Domain/AclCollectionCache.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/AclCollectionCache.php";}s:53:"Symfony/Component/Security/Acl/Domain/AuditLogger.php";a:4:{s:6:"md5sum";s:32:"b4fee19b12185f0ee45a2e97f5fcb8a4";s:4:"name";s:53:"Symfony/Component/Security/Acl/Domain/AuditLogger.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/AuditLogger.php";}s:58:"Symfony/Component/Security/Acl/Domain/DoctrineAclCache.php";a:4:{s:6:"md5sum";s:32:"2f552f22f35c47d5d523c187d25039eb";s:4:"name";s:58:"Symfony/Component/Security/Acl/Domain/DoctrineAclCache.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/DoctrineAclCache.php";}s:47:"Symfony/Component/Security/Acl/Domain/Entry.php";a:4:{s:6:"md5sum";s:32:"7d02a171381bed25a818a33a2a714803";s:4:"name";s:47:"Symfony/Component/Security/Acl/Domain/Entry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/Entry.php";}s:52:"Symfony/Component/Security/Acl/Domain/FieldEntry.php";a:4:{s:6:"md5sum";s:32:"f0b1b92b49934c59ecc126fbb41b72c2";s:4:"name";s:52:"Symfony/Component/Security/Acl/Domain/FieldEntry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/FieldEntry.php";}s:56:"Symfony/Component/Security/Acl/Domain/ObjectIdentity.php";a:4:{s:6:"md5sum";s:32:"3eadb08eafffe705a6dd8de5f96e1ca1";s:4:"name";s:56:"Symfony/Component/Security/Acl/Domain/ObjectIdentity.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/ObjectIdentity.php";}s:73:"Symfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.php";a:4:{s:6:"md5sum";s:32:"1baa7e094b60dbd7a2eaf4d38b5125cc";s:4:"name";s:73:"Symfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.php";}s:68:"Symfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.php";a:4:{s:6:"md5sum";s:32:"ea6329b78543f0536dc1b2019c291eb2";s:4:"name";s:68:"Symfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.php";}s:62:"Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.php";a:4:{s:6:"md5sum";s:32:"d082f117ebbe68492e03855adbaa7704";s:4:"name";s:62:"Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.php";}s:75:"Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.php";a:4:{s:6:"md5sum";s:32:"2a34925fb304b1a8d724ca4cf2aafb5f";s:4:"name";s:75:"Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.php";}s:62:"Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php";a:4:{s:6:"md5sum";s:32:"e48d7c38d196eea74cf250fcddd8d189";s:4:"name";s:62:"Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php";}s:70:"Symfony/Component/Security/Acl/Exception/AclAlreadyExistsException.php";a:4:{s:6:"md5sum";s:32:"82a5465e98dd2475f706a9cacc65db37";s:4:"name";s:70:"Symfony/Component/Security/Acl/Exception/AclAlreadyExistsException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Exception/AclAlreadyExistsException.php";}s:65:"Symfony/Component/Security/Acl/Exception/AclNotFoundException.php";a:4:{s:6:"md5sum";s:32:"8b3ec9dfe9d9f345a3ddce26bd4fab8b";s:4:"name";s:65:"Symfony/Component/Security/Acl/Exception/AclNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Exception/AclNotFoundException.php";}s:76:"Symfony/Component/Security/Acl/Exception/ConcurrentModificationException.php";a:4:{s:6:"md5sum";s:32:"7e3eb281d553454f0f59d5f282948216";s:4:"name";s:76:"Symfony/Component/Security/Acl/Exception/ConcurrentModificationException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Exception/ConcurrentModificationException.php";}s:54:"Symfony/Component/Security/Acl/Exception/Exception.php";a:4:{s:6:"md5sum";s:32:"e3b6ea7de5ec436c7503f1d7312249bc";s:4:"name";s:54:"Symfony/Component/Security/Acl/Exception/Exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Exception/Exception.php";}s:73:"Symfony/Component/Security/Acl/Exception/InvalidDomainObjectException.php";a:4:{s:6:"md5sum";s:32:"4be9ba33e0d97e970d6f541480901eb0";s:4:"name";s:73:"Symfony/Component/Security/Acl/Exception/InvalidDomainObjectException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Exception/InvalidDomainObjectException.php";}s:64:"Symfony/Component/Security/Acl/Exception/NoAceFoundException.php";a:4:{s:6:"md5sum";s:32:"aca5379067c0fd0c2240eb986eac8268";s:4:"name";s:64:"Symfony/Component/Security/Acl/Exception/NoAceFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Exception/NoAceFoundException.php";}s:69:"Symfony/Component/Security/Acl/Exception/NotAllAclsFoundException.php";a:4:{s:6:"md5sum";s:32:"7a0ca03655455c96a2fe053bc72b4de3";s:4:"name";s:69:"Symfony/Component/Security/Acl/Exception/NotAllAclsFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Exception/NotAllAclsFoundException.php";}s:66:"Symfony/Component/Security/Acl/Exception/SidNotLoadedException.php";a:4:{s:6:"md5sum";s:32:"2415593ec8d8a343e6f4328ddb0c2a1d";s:4:"name";s:66:"Symfony/Component/Security/Acl/Exception/SidNotLoadedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Exception/SidNotLoadedException.php";}s:38:"Symfony/Component/Security/Acl/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:38:"Symfony/Component/Security/Acl/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Acl/LICENSE";}s:58:"Symfony/Component/Security/Acl/Model/AclCacheInterface.php";a:4:{s:6:"md5sum";s:32:"ab5d60682e988c0e7eb0dd1512dabade";s:4:"name";s:58:"Symfony/Component/Security/Acl/Model/AclCacheInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/AclCacheInterface.php";}s:53:"Symfony/Component/Security/Acl/Model/AclInterface.php";a:4:{s:6:"md5sum";s:32:"870a09318c3c65e3523e19130607f1ab";s:4:"name";s:53:"Symfony/Component/Security/Acl/Model/AclInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/AclInterface.php";}s:61:"Symfony/Component/Security/Acl/Model/AclProviderInterface.php";a:4:{s:6:"md5sum";s:32:"7ea089827ee0d4ed26b0d57b8f20dc28";s:4:"name";s:61:"Symfony/Component/Security/Acl/Model/AclProviderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/AclProviderInterface.php";}s:62:"Symfony/Component/Security/Acl/Model/AuditableAclInterface.php";a:4:{s:6:"md5sum";s:32:"63c76e68e9ccf7ec307696ac8ca44e8f";s:4:"name";s:62:"Symfony/Component/Security/Acl/Model/AuditableAclInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/AuditableAclInterface.php";}s:64:"Symfony/Component/Security/Acl/Model/AuditableEntryInterface.php";a:4:{s:6:"md5sum";s:32:"f989613d6c0286594696efc106774415";s:4:"name";s:64:"Symfony/Component/Security/Acl/Model/AuditableEntryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/AuditableEntryInterface.php";}s:61:"Symfony/Component/Security/Acl/Model/AuditLoggerInterface.php";a:4:{s:6:"md5sum";s:32:"c5d9ae1862d7c0a6d442f053d5acac39";s:4:"name";s:61:"Symfony/Component/Security/Acl/Model/AuditLoggerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/AuditLoggerInterface.php";}s:62:"Symfony/Component/Security/Acl/Model/DomainObjectInterface.php";a:4:{s:6:"md5sum";s:32:"4d278f8d01215e4be53a264dad150173";s:4:"name";s:62:"Symfony/Component/Security/Acl/Model/DomainObjectInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/DomainObjectInterface.php";}s:55:"Symfony/Component/Security/Acl/Model/EntryInterface.php";a:4:{s:6:"md5sum";s:32:"72e6a4f7f0ffe6d84e6e6462827ee54a";s:4:"name";s:55:"Symfony/Component/Security/Acl/Model/EntryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/EntryInterface.php";}s:60:"Symfony/Component/Security/Acl/Model/FieldEntryInterface.php";a:4:{s:6:"md5sum";s:32:"2968e44f1b60586feb144fe02c5e15c3";s:4:"name";s:60:"Symfony/Component/Security/Acl/Model/FieldEntryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/FieldEntryInterface.php";}s:60:"Symfony/Component/Security/Acl/Model/MutableAclInterface.php";a:4:{s:6:"md5sum";s:32:"e1c009bf3a30308c68b2fc8b959fc1d4";s:4:"name";s:60:"Symfony/Component/Security/Acl/Model/MutableAclInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/MutableAclInterface.php";}s:68:"Symfony/Component/Security/Acl/Model/MutableAclProviderInterface.php";a:4:{s:6:"md5sum";s:32:"fb020f4efc07611baef0206e0783b87e";s:4:"name";s:68:"Symfony/Component/Security/Acl/Model/MutableAclProviderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/MutableAclProviderInterface.php";}s:64:"Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.php";a:4:{s:6:"md5sum";s:32:"29d14ee35eebd9faf6d38b97b02ea8cb";s:4:"name";s:64:"Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/ObjectIdentityInterface.php";}s:81:"Symfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.php";a:4:{s:6:"md5sum";s:32:"4c49500b0054ee78894935bebed56210";s:4:"name";s:81:"Symfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/ObjectIdentityRetrievalStrategyInterface.php";}s:76:"Symfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.php";a:4:{s:6:"md5sum";s:32:"713c07bfa636d7d6ad4d85d91b5f4ac4";s:4:"name";s:76:"Symfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.php";}s:66:"Symfony/Component/Security/Acl/Model/SecurityIdentityInterface.php";a:4:{s:6:"md5sum";s:32:"212111e56b11d7fba72dc585289786cb";s:4:"name";s:66:"Symfony/Component/Security/Acl/Model/SecurityIdentityInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/SecurityIdentityInterface.php";}s:83:"Symfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php";a:4:{s:6:"md5sum";s:32:"0896de7498e35f5f02a9755832172a96";s:4:"name";s:83:"Symfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model/SecurityIdentityRetrievalStrategyInterface.php";}s:64:"Symfony/Component/Security/Acl/Permission/BasicPermissionMap.php";a:4:{s:6:"md5sum";s:32:"83e5de08b981e358d3daea8b304988ca";s:4:"name";s:64:"Symfony/Component/Security/Acl/Permission/BasicPermissionMap.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Permission/BasicPermissionMap.php";}s:57:"Symfony/Component/Security/Acl/Permission/MaskBuilder.php";a:4:{s:6:"md5sum";s:32:"7918106bfa1e9cc64ca25efa8f2428f9";s:4:"name";s:57:"Symfony/Component/Security/Acl/Permission/MaskBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Permission/MaskBuilder.php";}s:68:"Symfony/Component/Security/Acl/Permission/PermissionMapInterface.php";a:4:{s:6:"md5sum";s:32:"024f4e1c3b24a5a42fe258e9ed3d83bb";s:4:"name";s:68:"Symfony/Component/Security/Acl/Permission/PermissionMapInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Permission/PermissionMapInterface.php";}s:47:"Symfony/Component/Security/Acl/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"74a4ed032849f83ee138f3ea572c315f";s:4:"name";s:47:"Symfony/Component/Security/Acl/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/phpunit.xml.dist";}s:40:"Symfony/Component/Security/Acl/README.md";a:4:{s:6:"md5sum";s:32:"5213a3c25b290a621867f47359a85972";s:4:"name";s:40:"Symfony/Component/Security/Acl/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Acl/README.md";}s:60:"Symfony/Component/Security/Acl/Resources/bin/generateSql.php";a:4:{s:6:"md5sum";s:32:"29202e9e8819885a0237ad1f5c4f1a3a";s:4:"name";s:60:"Symfony/Component/Security/Acl/Resources/bin/generateSql.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/bin/generateSql.php";}s:55:"Symfony/Component/Security/Acl/Resources/schema/db2.sql";a:4:{s:6:"md5sum";s:32:"128855e565e079eb859f350be880f395";s:4:"name";s:55:"Symfony/Component/Security/Acl/Resources/schema/db2.sql";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/schema/db2.sql";}s:59:"Symfony/Component/Security/Acl/Resources/schema/drizzle.sql";a:4:{s:6:"md5sum";s:32:"61db757bf91fc032fee7a78fe3ca8888";s:4:"name";s:59:"Symfony/Component/Security/Acl/Resources/schema/drizzle.sql";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/schema/drizzle.sql";}s:57:"Symfony/Component/Security/Acl/Resources/schema/mssql.sql";a:4:{s:6:"md5sum";s:32:"be1bec1133a89cf3e7298b380d5dd9a9";s:4:"name";s:57:"Symfony/Component/Security/Acl/Resources/schema/mssql.sql";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/schema/mssql.sql";}s:57:"Symfony/Component/Security/Acl/Resources/schema/mysql.sql";a:4:{s:6:"md5sum";s:32:"626ac34142835a1c4936290b79a05f66";s:4:"name";s:57:"Symfony/Component/Security/Acl/Resources/schema/mysql.sql";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/schema/mysql.sql";}s:58:"Symfony/Component/Security/Acl/Resources/schema/oracle.sql";a:4:{s:6:"md5sum";s:32:"6173f90ea584ec65392676ba164d9464";s:4:"name";s:58:"Symfony/Component/Security/Acl/Resources/schema/oracle.sql";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/schema/oracle.sql";}s:62:"Symfony/Component/Security/Acl/Resources/schema/postgresql.sql";a:4:{s:6:"md5sum";s:32:"50585e970a570428d65f9e9507da8aa8";s:4:"name";s:62:"Symfony/Component/Security/Acl/Resources/schema/postgresql.sql";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/schema/postgresql.sql";}s:58:"Symfony/Component/Security/Acl/Resources/schema/sqlite.sql";a:4:{s:6:"md5sum";s:32:"b93a223813116f02a5cba763bd07069a";s:4:"name";s:58:"Symfony/Component/Security/Acl/Resources/schema/sqlite.sql";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/schema/sqlite.sql";}s:70:"Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.php";a:4:{s:6:"md5sum";s:32:"357d0712d7b5b92a0d8315364e0518ea";s:4:"name";s:70:"Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.php";}s:61:"Symfony/Component/Security/Acl/Tests/Dbal/AclProviderTest.php";a:4:{s:6:"md5sum";s:32:"d332e19775917958bec95d017be52be5";s:4:"name";s:61:"Symfony/Component/Security/Acl/Tests/Dbal/AclProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderTest.php";}s:68:"Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php";a:4:{s:6:"md5sum";s:32:"1a46fcac5ad21b5b28b9590b1b4863fc";s:4:"name";s:68:"Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php";}s:55:"Symfony/Component/Security/Acl/Tests/Domain/AclTest.php";a:4:{s:6:"md5sum";s:32:"70968eae1eaa4395492e7dbd5797be65";s:4:"name";s:55:"Symfony/Component/Security/Acl/Tests/Domain/AclTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/AclTest.php";}s:63:"Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.php";a:4:{s:6:"md5sum";s:32:"86049b2dce3364e94f6683df05125acf";s:4:"name";s:63:"Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.php";}s:68:"Symfony/Component/Security/Acl/Tests/Domain/DoctrineAclCacheTest.php";a:4:{s:6:"md5sum";s:32:"099e0b3bcfdb454e46b46687a38d8a3b";s:4:"name";s:68:"Symfony/Component/Security/Acl/Tests/Domain/DoctrineAclCacheTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/DoctrineAclCacheTest.php";}s:57:"Symfony/Component/Security/Acl/Tests/Domain/EntryTest.php";a:4:{s:6:"md5sum";s:32:"4022249f6c81298b7f58ea4653ece650";s:4:"name";s:57:"Symfony/Component/Security/Acl/Tests/Domain/EntryTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/EntryTest.php";}s:62:"Symfony/Component/Security/Acl/Tests/Domain/FieldEntryTest.php";a:4:{s:6:"md5sum";s:32:"f3699fe6be1b8b45c015629251cc6f64";s:4:"name";s:62:"Symfony/Component/Security/Acl/Tests/Domain/FieldEntryTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/FieldEntryTest.php";}s:83:"Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityRetrievalStrategyTest.php";a:4:{s:6:"md5sum";s:32:"d56675ee8ce9da6ee089ab1486db1035";s:4:"name";s:83:"Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityRetrievalStrategyTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityRetrievalStrategyTest.php";}s:66:"Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityTest.php";a:4:{s:6:"md5sum";s:32:"af2604cee5638a6e0642f3c1478826c1";s:4:"name";s:66:"Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityTest.php";}s:78:"Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.php";a:4:{s:6:"md5sum";s:32:"75605e8ea69d528cea564242326e8b8d";s:4:"name";s:78:"Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.php";}s:72:"Symfony/Component/Security/Acl/Tests/Domain/RoleSecurityIdentityTest.php";a:4:{s:6:"md5sum";s:32:"b4555d0ee6f2d61a752b0416ee9b79e8";s:4:"name";s:72:"Symfony/Component/Security/Acl/Tests/Domain/RoleSecurityIdentityTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/RoleSecurityIdentityTest.php";}s:85:"Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.php";a:4:{s:6:"md5sum";s:32:"78c619c9cec05fdf11f5de9d48b56454";s:4:"name";s:85:"Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:129:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.php";}s:72:"Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.php";a:4:{s:6:"md5sum";s:32:"74e0d9ba1641b5cf21905336aca0d348";s:4:"name";s:72:"Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.php";}s:74:"Symfony/Component/Security/Acl/Tests/Permission/BasicPermissionMapTest.php";a:4:{s:6:"md5sum";s:32:"a353f4f911920e43f2e09ae3ac32d349";s:4:"name";s:74:"Symfony/Component/Security/Acl/Tests/Permission/BasicPermissionMapTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Permission/BasicPermissionMapTest.php";}s:67:"Symfony/Component/Security/Acl/Tests/Permission/MaskBuilderTest.php";a:4:{s:6:"md5sum";s:32:"3546d4afbaf25b0a4d40c216549ee272";s:4:"name";s:67:"Symfony/Component/Security/Acl/Tests/Permission/MaskBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Permission/MaskBuilderTest.php";}s:59:"Symfony/Component/Security/Acl/Tests/Voter/AclVoterTest.php";a:4:{s:6:"md5sum";s:32:"3c9129e03017adb641e9268149b935bc";s:4:"name";s:59:"Symfony/Component/Security/Acl/Tests/Voter/AclVoterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Voter/AclVoterTest.php";}s:49:"Symfony/Component/Security/Acl/Voter/AclVoter.php";a:4:{s:6:"md5sum";s:32:"8cafc8e1f14343b87cb0f58a25f463a0";s:4:"name";s:49:"Symfony/Component/Security/Acl/Voter/AclVoter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Voter/AclVoter.php";}s:50:"Symfony/Component/Security/Acl/Voter/FieldVote.php";a:4:{s:6:"md5sum";s:32:"180a2b1ab4b985facb353d6edeeb78ce";s:4:"name";s:50:"Symfony/Component/Security/Acl/Voter/FieldVote.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Voter/FieldVote.php";}s:41:"Symfony/Component/Security/autoloader.php";a:4:{s:6:"md5sum";s:32:"0fb7efcc9c1574920f39f115e9863b68";s:4:"name";s:41:"Symfony/Component/Security/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/autoloader.php";}s:39:"Symfony/Component/Security/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"2def4fa9f9525638a5a9c6f556ba1386";s:4:"name";s:39:"Symfony/Component/Security/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/CHANGELOG.md";}s:40:"Symfony/Component/Security/composer.json";a:4:{s:6:"md5sum";s:32:"f0488bd3f14f86892ce93d89dad55776";s:4:"name";s:40:"Symfony/Component/Security/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/composer.json";}s:81:"Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.php";a:4:{s:6:"md5sum";s:32:"c78d485138ebdc2fa2be48a396cb9ad2";s:4:"name";s:81:"Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.php";}s:80:"Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php";a:4:{s:6:"md5sum";s:32:"61167585d6d54cf1861b70f2344632c1";s:4:"name";s:80:"Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php";s:4:"role";s:3:"php";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php";}s:78:"Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php";a:4:{s:6:"md5sum";s:32:"4a5356ef0cf45593536da075d0d367a1";s:4:"name";s:78:"Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php";}s:87:"Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.php";a:4:{s:6:"md5sum";s:32:"dda5e9627c9c68a695cdd5071de86834";s:4:"name";s:87:"Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.php";}s:91:"Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.php";a:4:{s:6:"md5sum";s:32:"00cb0dfecd7dc6fedc2426932405dbec";s:4:"name";s:91:"Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.php";}s:91:"Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.php";a:4:{s:6:"md5sum";s:32:"07f5b8692dd849851a84662b9f60b759";s:4:"name";s:91:"Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.php";}s:85:"Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php";a:4:{s:6:"md5sum";s:32:"ccc63dc0c7c865036a3e64fb6819073e";s:4:"name";s:85:"Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php";}s:98:"Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php";a:4:{s:6:"md5sum";s:32:"df05c4c0bdbdb5f00d68909724d552af";s:4:"name";s:98:"Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php";}s:92:"Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php";a:4:{s:6:"md5sum";s:32:"bdcb91d96aacde5a99192f145495e66e";s:4:"name";s:92:"Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php";}s:88:"Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php";a:4:{s:6:"md5sum";s:32:"62c25b49d796de82786905533be97a8b";s:4:"name";s:88:"Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php";}s:86:"Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php";a:4:{s:6:"md5sum";s:32:"4f720340d1992a6261fc7cf795ca0b4d";s:4:"name";s:86:"Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php";}s:83:"Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.php";a:4:{s:6:"md5sum";s:32:"563ca47a94d2f91eb98c8091590f6ab2";s:4:"name";s:83:"Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.php";}s:77:"Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php";a:4:{s:6:"md5sum";s:32:"4888d2851eff9cf472a9acf0e93e33a4";s:4:"name";s:77:"Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php";}s:86:"Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.php";a:4:{s:6:"md5sum";s:32:"2945e844ab362b935608de1ccf071018";s:4:"name";s:86:"Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.php";}s:84:"Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.php";a:4:{s:6:"md5sum";s:32:"5ba08141bb0ac7eb83d877a87e9689ed";s:4:"name";s:84:"Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.php";}s:79:"Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.php";a:4:{s:6:"md5sum";s:32:"cfc5b482e19a6559b87fa3cc80665720";s:4:"name";s:79:"Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.php";}s:83:"Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.php";a:4:{s:6:"md5sum";s:32:"3dd46ffbfb5919606d71d89c5bf82f97";s:4:"name";s:83:"Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.php";}s:82:"Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.php";a:4:{s:6:"md5sum";s:32:"417cad7687deea94ba31fe8d86fcbdf1";s:4:"name";s:82:"Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.php";}s:70:"Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php";a:4:{s:6:"md5sum";s:32:"50a0fa6d56839562be5866c8a3915497";s:4:"name";s:70:"Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php";}s:71:"Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php";a:4:{s:6:"md5sum";s:32:"4185126f45762b4301b9b6cb2d159bb9";s:4:"name";s:71:"Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php";}s:78:"Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php";a:4:{s:6:"md5sum";s:32:"e5015c2bc9254901b0255ced46129f93";s:4:"name";s:78:"Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php";}s:72:"Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php";a:4:{s:6:"md5sum";s:32:"822307b7ea3a72ec932599c9bece3a97";s:4:"name";s:72:"Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php";}s:71:"Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php";a:4:{s:6:"md5sum";s:32:"4143633b44f1659cf8409a64ca407b51";s:4:"name";s:71:"Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php";}s:78:"Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php";a:4:{s:6:"md5sum";s:32:"4bd196890e484daf675d82322028be1c";s:4:"name";s:78:"Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php";}s:56:"Symfony/Component/Security/Core/AuthenticationEvents.php";a:4:{s:6:"md5sum";s:32:"cdc9190c3179e73eaecdbbbca659b22e";s:4:"name";s:56:"Symfony/Component/Security/Core/AuthenticationEvents.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/AuthenticationEvents.php";}s:71:"Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php";a:4:{s:6:"md5sum";s:32:"4a6916eb9cf4fc40f478dbb623ffdce9";s:4:"name";s:71:"Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php";}s:80:"Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.php";a:4:{s:6:"md5sum";s:32:"2865601c03c45ce3621d9013c5347d9f";s:4:"name";s:80:"Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.php";}s:68:"Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php";a:4:{s:6:"md5sum";s:32:"3b7fae5344cfe097002ea98131ce6956";s:4:"name";s:68:"Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php";}s:74:"Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php";a:4:{s:6:"md5sum";s:32:"f2f64cf4065691e1e0b9c4c0f1425f80";s:4:"name";s:74:"Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php";}s:71:"Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php";a:4:{s:6:"md5sum";s:32:"2ea414aff917d1469902138f7e0d5cd0";s:4:"name";s:71:"Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php";}s:74:"Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.php";a:4:{s:6:"md5sum";s:32:"089ca490f923e6a32cf080b0e2a27e2f";s:4:"name";s:74:"Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.php";}s:65:"Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php";a:4:{s:6:"md5sum";s:32:"ff0a673dff9312faaebb78b23a04535f";s:4:"name";s:65:"Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php";}s:70:"Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php";a:4:{s:6:"md5sum";s:32:"003e7949d849e45e4fdffa9a835a2599";s:4:"name";s:70:"Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php";}s:45:"Symfony/Component/Security/Core/composer.json";a:4:{s:6:"md5sum";s:32:"15e1e6270e2d6d3318237d3363338f50";s:4:"name";s:45:"Symfony/Component/Security/Core/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Core/composer.json";}s:63:"Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.php";a:4:{s:6:"md5sum";s:32:"a7a02c1c8ee5f97fdc8c267b48ae13ed";s:4:"name";s:63:"Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.php";}s:65:"Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php";a:4:{s:6:"md5sum";s:32:"0f16a3510e7372c61dd03b2b3bb7564f";s:4:"name";s:65:"Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php";}s:58:"Symfony/Component/Security/Core/Encoder/EncoderFactory.php";a:4:{s:6:"md5sum";s:32:"6c687634e27d9118951ce27c88dfe481";s:4:"name";s:58:"Symfony/Component/Security/Core/Encoder/EncoderFactory.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Encoder/EncoderFactory.php";}s:67:"Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.php";a:4:{s:6:"md5sum";s:32:"1330018384392f42e4b5caa6cb012f95";s:4:"name";s:67:"Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.php";}s:72:"Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php";a:4:{s:6:"md5sum";s:32:"7cd742b70754d9c9d8f0ca029ef4b64f";s:4:"name";s:72:"Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php";}s:68:"Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.php";a:4:{s:6:"md5sum";s:32:"0dde4a14a6d89ad005406ffbf9422d1f";s:4:"name";s:68:"Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.php";}s:65:"Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.php";a:4:{s:6:"md5sum";s:32:"a97a3832eee0a328215a49fb252282fb";s:4:"name";s:65:"Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.php";}s:68:"Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.php";a:4:{s:6:"md5sum";s:32:"e07d25f0fa35b7bfc88b3d19478da95e";s:4:"name";s:68:"Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.php";}s:61:"Symfony/Component/Security/Core/Event/AuthenticationEvent.php";a:4:{s:6:"md5sum";s:32:"e976a22829d8fd7b3a67528c5f68610f";s:4:"name";s:61:"Symfony/Component/Security/Core/Event/AuthenticationEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Event/AuthenticationEvent.php";}s:68:"Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.php";a:4:{s:6:"md5sum";s:32:"c303cb0e16eab8cbaa2d24d416dc89b1";s:4:"name";s:68:"Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.php";}s:67:"Symfony/Component/Security/Core/Exception/AccessDeniedException.php";a:4:{s:6:"md5sum";s:32:"92c25b19f903e89aa16d8cd887600d9b";s:4:"name";s:67:"Symfony/Component/Security/Core/Exception/AccessDeniedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/AccessDeniedException.php";}s:69:"Symfony/Component/Security/Core/Exception/AccountExpiredException.php";a:4:{s:6:"md5sum";s:32:"cbaf077cb23fd56e405fe305089be4f1";s:4:"name";s:69:"Symfony/Component/Security/Core/Exception/AccountExpiredException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/AccountExpiredException.php";}s:68:"Symfony/Component/Security/Core/Exception/AccountStatusException.php";a:4:{s:6:"md5sum";s:32:"897def6142e95038f5b7e1be80789952";s:4:"name";s:68:"Symfony/Component/Security/Core/Exception/AccountStatusException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/AccountStatusException.php";}s:88:"Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.php";a:4:{s:6:"md5sum";s:32:"f216cb63ef5a186ee50eba5144ceddc7";s:4:"name";s:88:"Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.php";}s:69:"Symfony/Component/Security/Core/Exception/AuthenticationException.php";a:4:{s:6:"md5sum";s:32:"29cc9dc1a7659e59a786dd9788937455";s:4:"name";s:69:"Symfony/Component/Security/Core/Exception/AuthenticationException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/AuthenticationException.php";}s:76:"Symfony/Component/Security/Core/Exception/AuthenticationServiceException.php";a:4:{s:6:"md5sum";s:32:"9208968ac310a1959595d8bfc270c270";s:4:"name";s:76:"Symfony/Component/Security/Core/Exception/AuthenticationServiceException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/AuthenticationServiceException.php";}s:69:"Symfony/Component/Security/Core/Exception/BadCredentialsException.php";a:4:{s:6:"md5sum";s:32:"8dcc2180afe1ca2a5ba64b3b7b9374b7";s:4:"name";s:69:"Symfony/Component/Security/Core/Exception/BadCredentialsException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/BadCredentialsException.php";}s:66:"Symfony/Component/Security/Core/Exception/CookieTheftException.php";a:4:{s:6:"md5sum";s:32:"1501fc38bd5c20b9c3bc3fde481d096d";s:4:"name";s:66:"Symfony/Component/Security/Core/Exception/CookieTheftException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/CookieTheftException.php";}s:73:"Symfony/Component/Security/Core/Exception/CredentialsExpiredException.php";a:4:{s:6:"md5sum";s:32:"7f862b829f86bf262fef80f92fa1efd9";s:4:"name";s:73:"Symfony/Component/Security/Core/Exception/CredentialsExpiredException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/CredentialsExpiredException.php";}s:63:"Symfony/Component/Security/Core/Exception/DisabledException.php";a:4:{s:6:"md5sum";s:32:"964e01e15a4fc37e74bf8b832495e786";s:4:"name";s:63:"Symfony/Component/Security/Core/Exception/DisabledException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/DisabledException.php";}s:64:"Symfony/Component/Security/Core/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"13fca1be9c3957516e99beb9811cbea5";s:4:"name";s:64:"Symfony/Component/Security/Core/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/ExceptionInterface.php";}s:81:"Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.php";a:4:{s:6:"md5sum";s:32:"437a16a50032457b90bec37786b55947";s:4:"name";s:81:"Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.php";}s:70:"Symfony/Component/Security/Core/Exception/InvalidArgumentException.php";a:4:{s:6:"md5sum";s:32:"5851c6d868699f1dc1e6eccb96793449";s:4:"name";s:70:"Symfony/Component/Security/Core/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/InvalidArgumentException.php";}s:71:"Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.php";a:4:{s:6:"md5sum";s:32:"0822aa405f9ea4d78d55f91c8b74eeb7";s:4:"name";s:71:"Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.php";}s:61:"Symfony/Component/Security/Core/Exception/LockedException.php";a:4:{s:6:"md5sum";s:32:"5d23c71dcff00d3f9a716115caa7164d";s:4:"name";s:61:"Symfony/Component/Security/Core/Exception/LockedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/LockedException.php";}s:61:"Symfony/Component/Security/Core/Exception/LogoutException.php";a:4:{s:6:"md5sum";s:32:"7e9bb714f4fdc03bf4158d3ebafd9181";s:4:"name";s:61:"Symfony/Component/Security/Core/Exception/LogoutException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/LogoutException.php";}s:67:"Symfony/Component/Security/Core/Exception/NonceExpiredException.php";a:4:{s:6:"md5sum";s:32:"ba9525c7d4bc829f3569f785b9399c18";s:4:"name";s:67:"Symfony/Component/Security/Core/Exception/NonceExpiredException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/NonceExpiredException.php";}s:71:"Symfony/Component/Security/Core/Exception/ProviderNotFoundException.php";a:4:{s:6:"md5sum";s:32:"bc44ab7bd2bf3f5118c22c174d164773";s:4:"name";s:71:"Symfony/Component/Security/Core/Exception/ProviderNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/ProviderNotFoundException.php";}s:62:"Symfony/Component/Security/Core/Exception/RuntimeException.php";a:4:{s:6:"md5sum";s:32:"eedf3a5276fc76bb3c7854d3ae9410ea";s:4:"name";s:62:"Symfony/Component/Security/Core/Exception/RuntimeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/RuntimeException.php";}s:73:"Symfony/Component/Security/Core/Exception/SessionUnavailableException.php";a:4:{s:6:"md5sum";s:32:"67db74104de766f8625e248576f999da";s:4:"name";s:73:"Symfony/Component/Security/Core/Exception/SessionUnavailableException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/SessionUnavailableException.php";}s:68:"Symfony/Component/Security/Core/Exception/TokenNotFoundException.php";a:4:{s:6:"md5sum";s:32:"d9b2b76d30d8faa7835d19faa92e7746";s:4:"name";s:68:"Symfony/Component/Security/Core/Exception/TokenNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/TokenNotFoundException.php";}s:70:"Symfony/Component/Security/Core/Exception/UnsupportedUserException.php";a:4:{s:6:"md5sum";s:32:"6a7031722e579b577881dd26548a2582";s:4:"name";s:70:"Symfony/Component/Security/Core/Exception/UnsupportedUserException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/UnsupportedUserException.php";}s:71:"Symfony/Component/Security/Core/Exception/UsernameNotFoundException.php";a:4:{s:6:"md5sum";s:32:"1bbd1cdc4a27e69cb001f60f6f17b953";s:4:"name";s:71:"Symfony/Component/Security/Core/Exception/UsernameNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception/UsernameNotFoundException.php";}s:39:"Symfony/Component/Security/Core/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:39:"Symfony/Component/Security/Core/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Core/LICENSE";}s:48:"Symfony/Component/Security/Core/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"b24852b42833e802e562d16e16c4e819";s:4:"name";s:48:"Symfony/Component/Security/Core/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/phpunit.xml.dist";}s:41:"Symfony/Component/Security/Core/README.md";a:4:{s:6:"md5sum";s:32:"f20b648364f60e5c4c4093a968fc5331";s:4:"name";s:41:"Symfony/Component/Security/Core/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Core/README.md";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.ar.xlf";a:4:{s:6:"md5sum";s:32:"1e750b4762305800f3dd181eab53e2ba";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ar.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.ar.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.ca.xlf";a:4:{s:6:"md5sum";s:32:"31cbf1bd957d4f4c3401c20d9a1b10bc";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ca.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.cs.xlf";a:4:{s:6:"md5sum";s:32:"0cf2e748f73950fb74f6a5978ab773f4";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.cs.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.cs.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.da.xlf";a:4:{s:6:"md5sum";s:32:"fcd7c0a40a3a5b074abce43148053890";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.da.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.da.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.de.xlf";a:4:{s:6:"md5sum";s:32:"a01afc0ce8bdc7598652c6560fae8512";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.de.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.de.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.el.xlf";a:4:{s:6:"md5sum";s:32:"c2883d0b5e1e7eeed7ec66ea9853f5cc";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.el.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.el.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.en.xlf";a:4:{s:6:"md5sum";s:32:"0c6a0114323a39fad8cb33246be7b7d9";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.en.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.en.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.es.xlf";a:4:{s:6:"md5sum";s:32:"7ae3e719888ac0c94aeda98734b5e9f5";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.es.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.es.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.fa.xlf";a:4:{s:6:"md5sum";s:32:"eef6f0230157636659e13c466e498cd9";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.fa.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.fa.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.fr.xlf";a:4:{s:6:"md5sum";s:32:"8d726781df922dfb126eb85c6c1cf7f5";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.fr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.fr.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.gl.xlf";a:4:{s:6:"md5sum";s:32:"d24525aa71ea6294f1b0dad40d7a5b70";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.gl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.gl.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.hu.xlf";a:4:{s:6:"md5sum";s:32:"b8704be78d7be163b715e166f07257e3";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.hu.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.hu.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.it.xlf";a:4:{s:6:"md5sum";s:32:"47a2f3df6c37532fe6a486073aebd0a1";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.it.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.it.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.lb.xlf";a:4:{s:6:"md5sum";s:32:"defce0bf7d3e026fbdaebb0cfe7abbd6";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.lb.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.lb.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.nl.xlf";a:4:{s:6:"md5sum";s:32:"79d67b79332d77ce5d39a8531f219538";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.nl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.nl.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.no.xlf";a:4:{s:6:"md5sum";s:32:"3ca24d84b0c49e93e8425dbc96b5d479";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.no.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.no.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.pl.xlf";a:4:{s:6:"md5sum";s:32:"f6e927ae45bf961507418d03db1c676d";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.pl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.pl.xlf";}s:73:"Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlf";a:4:{s:6:"md5sum";s:32:"ff2d10ee020b23d10e8a49c3f72b77af";s:4:"name";s:73:"Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlf";}s:73:"Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf";a:4:{s:6:"md5sum";s:32:"2855177bf25fd860bca194067f350e0a";s:4:"name";s:73:"Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.ro.xlf";a:4:{s:6:"md5sum";s:32:"f07b53a0e13bb3f1267b212e07b49a14";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ro.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.ro.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.ru.xlf";a:4:{s:6:"md5sum";s:32:"f943d4b750be69bd91e03eca27df52f5";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ru.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.ru.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.sk.xlf";a:4:{s:6:"md5sum";s:32:"a570f49a5deb0bba84a8f5ce71018b32";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.sk.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.sl.xlf";a:4:{s:6:"md5sum";s:32:"0a5e641bcbd17d9502a2f2f3e1d51999";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.sl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.sl.xlf";}s:75:"Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf";a:4:{s:6:"md5sum";s:32:"823f2ed1191ec9723d46f2516d700973";s:4:"name";s:75:"Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf";}s:75:"Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf";a:4:{s:6:"md5sum";s:32:"a95969c966594fa2afcf4c0f58dcf034";s:4:"name";s:75:"Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.sv.xlf";a:4:{s:6:"md5sum";s:32:"ef66c814ecc8a2fc5fbbe30dd23f3a82";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.sv.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.sv.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.tr.xlf";a:4:{s:6:"md5sum";s:32:"0d789d9cb295319cb483f864ca99b2bf";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.tr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.tr.xlf";}s:70:"Symfony/Component/Security/Core/Resources/translations/security.ua.xlf";a:4:{s:6:"md5sum";s:32:"c7e13f578ddab881e5bb035d0e905048";s:4:"name";s:70:"Symfony/Component/Security/Core/Resources/translations/security.ua.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations/security.ua.xlf";}s:45:"Symfony/Component/Security/Core/Role/Role.php";a:4:{s:6:"md5sum";s:32:"3050382d1549c2b01456b9361e8facd3";s:4:"name";s:45:"Symfony/Component/Security/Core/Role/Role.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Role/Role.php";}s:54:"Symfony/Component/Security/Core/Role/RoleHierarchy.php";a:4:{s:6:"md5sum";s:32:"bca85cac483875c294bb4577942b5e13";s:4:"name";s:54:"Symfony/Component/Security/Core/Role/RoleHierarchy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Role/RoleHierarchy.php";}s:63:"Symfony/Component/Security/Core/Role/RoleHierarchyInterface.php";a:4:{s:6:"md5sum";s:32:"675f61146da7cd1caec751a2d261b0e6";s:4:"name";s:63:"Symfony/Component/Security/Core/Role/RoleHierarchyInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Role/RoleHierarchyInterface.php";}s:54:"Symfony/Component/Security/Core/Role/RoleInterface.php";a:4:{s:6:"md5sum";s:32:"b03592fb0521d323c36939ab08985fce";s:4:"name";s:54:"Symfony/Component/Security/Core/Role/RoleInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Role/RoleInterface.php";}s:55:"Symfony/Component/Security/Core/Role/SwitchUserRole.php";a:4:{s:6:"md5sum";s:32:"8826f3ebe695c64183b161bc895da3d9";s:4:"name";s:55:"Symfony/Component/Security/Core/Role/SwitchUserRole.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Role/SwitchUserRole.php";}s:51:"Symfony/Component/Security/Core/SecurityContext.php";a:4:{s:6:"md5sum";s:32:"10ecd1343fe383863fcf07aea6e1484e";s:4:"name";s:51:"Symfony/Component/Security/Core/SecurityContext.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/SecurityContext.php";}s:60:"Symfony/Component/Security/Core/SecurityContextInterface.php";a:4:{s:6:"md5sum";s:32:"55a5781675e114c92bad8bad5aa2830d";s:4:"name";s:60:"Symfony/Component/Security/Core/SecurityContextInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/SecurityContextInterface.php";}s:90:"Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php";a:4:{s:6:"md5sum";s:32:"b63b6b59d9a86eb0d75e0b96f791cebe";s:4:"name";s:90:"Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php";}s:88:"Symfony/Component/Security/Core/Tests/Authentication/AuthenticationTrustResolverTest.php";a:4:{s:6:"md5sum";s:32:"678c0f4dcee8c6b4c914596f68e8066c";s:4:"name";s:88:"Symfony/Component/Security/Core/Tests/Authentication/AuthenticationTrustResolverTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:132:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationTrustResolverTest.php";}s:101:"Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php";a:4:{s:6:"md5sum";s:32:"9b7f1e61792f26921f8ac8005047ec5a";s:4:"name";s:101:"Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:145:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php";}s:95:"Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php";a:4:{s:6:"md5sum";s:32:"9e46dd36c66d8390ff4ef27308eaf788";s:4:"name";s:95:"Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:139:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php";}s:108:"Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php";a:4:{s:6:"md5sum";s:32:"56a160fc914fa20188f3fb4428231071";s:4:"name";s:108:"Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:152:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php";}s:102:"Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php";a:4:{s:6:"md5sum";s:32:"7d87ce759a8a0bc6a43e083bcbf65a7e";s:4:"name";s:102:"Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:146:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php";}s:96:"Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php";a:4:{s:6:"md5sum";s:32:"878a24250d15912e8875b761f1b18cd6";s:4:"name";s:96:"Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:140:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php";}s:93:"Symfony/Component/Security/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php";a:4:{s:6:"md5sum";s:32:"dd3f29d0edf632c2e0668095d433e2b8";s:4:"name";s:93:"Symfony/Component/Security/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php";}s:87:"Symfony/Component/Security/Core/Tests/Authentication/RememberMe/PersistentTokenTest.php";a:4:{s:6:"md5sum";s:32:"333af5f2e4fca41f0ad52c067fc6f6fa";s:4:"name";s:87:"Symfony/Component/Security/Core/Tests/Authentication/RememberMe/PersistentTokenTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/PersistentTokenTest.php";}s:80:"Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php";a:4:{s:6:"md5sum";s:32:"63d1895301e8c4db998257793246ddd4";s:4:"name";s:80:"Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php";}s:81:"Symfony/Component/Security/Core/Tests/Authentication/Token/AnonymousTokenTest.php";a:4:{s:6:"md5sum";s:32:"165abe0414d3fd9f6b87b77a974dbf87";s:4:"name";s:81:"Symfony/Component/Security/Core/Tests/Authentication/Token/AnonymousTokenTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AnonymousTokenTest.php";}s:88:"Symfony/Component/Security/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.php";a:4:{s:6:"md5sum";s:32:"ea0e9ad02afbff6e37eb9dcceb635102";s:4:"name";s:88:"Symfony/Component/Security/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:132:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.php";}s:88:"Symfony/Component/Security/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.php";a:4:{s:6:"md5sum";s:32:"881577a37dc13881037471af86e54c26";s:4:"name";s:88:"Symfony/Component/Security/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:132:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.php";}s:81:"Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php";a:4:{s:6:"md5sum";s:32:"01615835979113e72ba01df5db514cfe";s:4:"name";s:81:"Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php";}s:78:"Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.php";a:4:{s:6:"md5sum";s:32:"53e2015913c42918f488b6b5768dcfd6";s:4:"name";s:78:"Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.php";}s:84:"Symfony/Component/Security/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.php";a:4:{s:6:"md5sum";s:32:"09a4601d7459111b412a28d8b3ba77e6";s:4:"name";s:84:"Symfony/Component/Security/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.php";}s:81:"Symfony/Component/Security/Core/Tests/Authorization/Voter/ExpressionVoterTest.php";a:4:{s:6:"md5sum";s:32:"f7de9f0134587eca878b84fa96cd4e11";s:4:"name";s:81:"Symfony/Component/Security/Core/Tests/Authorization/Voter/ExpressionVoterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/ExpressionVoterTest.php";}s:84:"Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.php";a:4:{s:6:"md5sum";s:32:"1515e17b427defd7ede0b26cd62d6f7c";s:4:"name";s:84:"Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.php";}s:75:"Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleVoterTest.php";a:4:{s:6:"md5sum";s:32:"6eafbf6e21bcb931d7deeb6c7a03d09d";s:4:"name";s:75:"Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleVoterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleVoterTest.php";}s:73:"Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.php";a:4:{s:6:"md5sum";s:32:"262dd768f1ab73f96eee0a29a7665d3f";s:4:"name";s:73:"Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.php";}s:75:"Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php";a:4:{s:6:"md5sum";s:32:"a052af732959cb4100386622650cde49";s:4:"name";s:75:"Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php";}s:68:"Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.php";a:4:{s:6:"md5sum";s:32:"c4466a3921e1ef6bc3ffa19e825cc264";s:4:"name";s:68:"Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.php";}s:82:"Symfony/Component/Security/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.php";a:4:{s:6:"md5sum";s:32:"1a2e9523c0f574255c5e8cc12563036d";s:4:"name";s:82:"Symfony/Component/Security/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.php";}s:75:"Symfony/Component/Security/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.php";a:4:{s:6:"md5sum";s:32:"47d32cbddb94e8c940a067da8bd652c8";s:4:"name";s:75:"Symfony/Component/Security/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.php";}s:78:"Symfony/Component/Security/Core/Tests/Encoder/PlaintextPasswordEncoderTest.php";a:4:{s:6:"md5sum";s:32:"9a3e27e7243e0aef39d89ce5048f0156";s:4:"name";s:78:"Symfony/Component/Security/Core/Tests/Encoder/PlaintextPasswordEncoderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Encoder/PlaintextPasswordEncoderTest.php";}s:64:"Symfony/Component/Security/Core/Tests/Role/RoleHierarchyTest.php";a:4:{s:6:"md5sum";s:32:"e84df0653432699a74f9892f39cd801d";s:4:"name";s:64:"Symfony/Component/Security/Core/Tests/Role/RoleHierarchyTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Role/RoleHierarchyTest.php";}s:55:"Symfony/Component/Security/Core/Tests/Role/RoleTest.php";a:4:{s:6:"md5sum";s:32:"6faeaa1b59d680fc64f68f187d3b8ad4";s:4:"name";s:55:"Symfony/Component/Security/Core/Tests/Role/RoleTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Role/RoleTest.php";}s:65:"Symfony/Component/Security/Core/Tests/Role/SwitchUserRoleTest.php";a:4:{s:6:"md5sum";s:32:"63e6fa508f87e6843cdc7d4dbb310ed4";s:4:"name";s:65:"Symfony/Component/Security/Core/Tests/Role/SwitchUserRoleTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Role/SwitchUserRoleTest.php";}s:61:"Symfony/Component/Security/Core/Tests/SecurityContextTest.php";a:4:{s:6:"md5sum";s:32:"c6a315c41a473173516a7b97d7bd135f";s:4:"name";s:61:"Symfony/Component/Security/Core/Tests/SecurityContextTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/SecurityContextTest.php";}s:68:"Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php";a:4:{s:6:"md5sum";s:32:"39059760376a28b3a1289ebeeefbf9ef";s:4:"name";s:68:"Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php";}s:55:"Symfony/Component/Security/Core/Tests/User/UserTest.php";a:4:{s:6:"md5sum";s:32:"92589d6ad763ccd817043e6b5fb5865d";s:4:"name";s:55:"Symfony/Component/Security/Core/Tests/User/UserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/User/UserTest.php";}s:61:"Symfony/Component/Security/Core/Tests/Util/ClassUtilsTest.php";a:4:{s:6:"md5sum";s:32:"51ae9e53749a60e2d99ca0fa4893a68a";s:4:"name";s:61:"Symfony/Component/Security/Core/Tests/Util/ClassUtilsTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Util/ClassUtilsTest.php";}s:63:"Symfony/Component/Security/Core/Tests/Util/SecureRandomTest.php";a:4:{s:6:"md5sum";s:32:"172dc84386daa4193854aad1078407fb";s:4:"name";s:63:"Symfony/Component/Security/Core/Tests/Util/SecureRandomTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Util/SecureRandomTest.php";}s:62:"Symfony/Component/Security/Core/Tests/Util/StringUtilsTest.php";a:4:{s:6:"md5sum";s:32:"a80a7c57b6922fd9a9925a82a7741a01";s:4:"name";s:62:"Symfony/Component/Security/Core/Tests/Util/StringUtilsTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Util/StringUtilsTest.php";}s:89:"Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php";a:4:{s:6:"md5sum";s:32:"c2ecdc8fea6ea459acf382fbd0de514c";s:4:"name";s:89:"Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:133:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php";}s:62:"Symfony/Component/Security/Core/User/AdvancedUserInterface.php";a:4:{s:6:"md5sum";s:32:"dac22529730e8721ae339aacb05b561c";s:4:"name";s:62:"Symfony/Component/Security/Core/User/AdvancedUserInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User/AdvancedUserInterface.php";}s:58:"Symfony/Component/Security/Core/User/ChainUserProvider.php";a:4:{s:6:"md5sum";s:32:"16ad9f1561e239188cb64ff12a4cd713";s:4:"name";s:58:"Symfony/Component/Security/Core/User/ChainUserProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User/ChainUserProvider.php";}s:59:"Symfony/Component/Security/Core/User/EquatableInterface.php";a:4:{s:6:"md5sum";s:32:"053bfd3d7feb51135f125c471e0919f2";s:4:"name";s:59:"Symfony/Component/Security/Core/User/EquatableInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User/EquatableInterface.php";}s:61:"Symfony/Component/Security/Core/User/InMemoryUserProvider.php";a:4:{s:6:"md5sum";s:32:"c62ec26256558502bdff94ccdff8f4c3";s:4:"name";s:61:"Symfony/Component/Security/Core/User/InMemoryUserProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User/InMemoryUserProvider.php";}s:45:"Symfony/Component/Security/Core/User/User.php";a:4:{s:6:"md5sum";s:32:"a36d5dcfd2e90b7079473de27ece3f0c";s:4:"name";s:45:"Symfony/Component/Security/Core/User/User.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User/User.php";}s:52:"Symfony/Component/Security/Core/User/UserChecker.php";a:4:{s:6:"md5sum";s:32:"915fa1f4c48a7ce2f501c26b7a784f28";s:4:"name";s:52:"Symfony/Component/Security/Core/User/UserChecker.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User/UserChecker.php";}s:61:"Symfony/Component/Security/Core/User/UserCheckerInterface.php";a:4:{s:6:"md5sum";s:32:"388e848eda1ffa8b46dd0ae9bf227b90";s:4:"name";s:61:"Symfony/Component/Security/Core/User/UserCheckerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User/UserCheckerInterface.php";}s:54:"Symfony/Component/Security/Core/User/UserInterface.php";a:4:{s:6:"md5sum";s:32:"47ee6a0d6557868aaf10450f4137462b";s:4:"name";s:54:"Symfony/Component/Security/Core/User/UserInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User/UserInterface.php";}s:62:"Symfony/Component/Security/Core/User/UserProviderInterface.php";a:4:{s:6:"md5sum";s:32:"482f41d8bda5807c72c319d1d2a11c09";s:4:"name";s:62:"Symfony/Component/Security/Core/User/UserProviderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User/UserProviderInterface.php";}s:51:"Symfony/Component/Security/Core/Util/ClassUtils.php";a:4:{s:6:"md5sum";s:32:"dd14c33e711d9ac06c1507157e32f166";s:4:"name";s:51:"Symfony/Component/Security/Core/Util/ClassUtils.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Util/ClassUtils.php";}s:53:"Symfony/Component/Security/Core/Util/SecureRandom.php";a:4:{s:6:"md5sum";s:32:"9b650297a6cfe3a6947488561371c574";s:4:"name";s:53:"Symfony/Component/Security/Core/Util/SecureRandom.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Util/SecureRandom.php";}s:62:"Symfony/Component/Security/Core/Util/SecureRandomInterface.php";a:4:{s:6:"md5sum";s:32:"9ac637cacec94e99f0a7af4154ea16ef";s:4:"name";s:62:"Symfony/Component/Security/Core/Util/SecureRandomInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Util/SecureRandomInterface.php";}s:52:"Symfony/Component/Security/Core/Util/StringUtils.php";a:4:{s:6:"md5sum";s:32:"e9ba381671f8b8f44a880028850a3dc6";s:4:"name";s:52:"Symfony/Component/Security/Core/Util/StringUtils.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Util/StringUtils.php";}s:70:"Symfony/Component/Security/Core/Validator/Constraints/UserPassword.php";a:4:{s:6:"md5sum";s:32:"681b19bd49acd0a67bf514c0a420e164";s:4:"name";s:70:"Symfony/Component/Security/Core/Validator/Constraints/UserPassword.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Validator/Constraints/UserPassword.php";}s:79:"Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php";a:4:{s:6:"md5sum";s:32:"73b05740588c9089f62ddccb23b85de2";s:4:"name";s:79:"Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php";}s:45:"Symfony/Component/Security/Csrf/composer.json";a:4:{s:6:"md5sum";s:32:"8bf68c5cb8ecade41dedb7a808186bfc";s:4:"name";s:45:"Symfony/Component/Security/Csrf/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Csrf/composer.json";}s:45:"Symfony/Component/Security/Csrf/CsrfToken.php";a:4:{s:6:"md5sum";s:32:"8dd9faf3aa313127ffcf0106abafdb34";s:4:"name";s:45:"Symfony/Component/Security/Csrf/CsrfToken.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/CsrfToken.php";}s:52:"Symfony/Component/Security/Csrf/CsrfTokenManager.php";a:4:{s:6:"md5sum";s:32:"4584d3d466fbd310bd1c3730a53aba62";s:4:"name";s:52:"Symfony/Component/Security/Csrf/CsrfTokenManager.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/CsrfTokenManager.php";}s:61:"Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.php";a:4:{s:6:"md5sum";s:32:"4f9257a2c8b6285605af062e31e92c51";s:4:"name";s:61:"Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.php";}s:68:"Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.php";a:4:{s:6:"md5sum";s:32:"283b3574fff8ff0c093c8c2c74024fb0";s:4:"name";s:68:"Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.php";}s:39:"Symfony/Component/Security/Csrf/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:39:"Symfony/Component/Security/Csrf/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Csrf/LICENSE";}s:48:"Symfony/Component/Security/Csrf/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"4a5e98782fbba28092cafe77c3168c51";s:4:"name";s:48:"Symfony/Component/Security/Csrf/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Csrf/phpunit.xml.dist";}s:41:"Symfony/Component/Security/Csrf/README.md";a:4:{s:6:"md5sum";s:32:"f7759c45cd4a446a228ed648286acf8f";s:4:"name";s:41:"Symfony/Component/Security/Csrf/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Csrf/README.md";}s:62:"Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.php";a:4:{s:6:"md5sum";s:32:"3de809f4f691151c195fba128ff1e32d";s:4:"name";s:62:"Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.php";}s:82:"Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.php";a:4:{s:6:"md5sum";s:32:"bc23118b2998753a1a5d8d744edb93e9";s:4:"name";s:82:"Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.php";}s:84:"Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php";a:4:{s:6:"md5sum";s:32:"362691003c5cc955877ecd235ef329d5";s:4:"name";s:84:"Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php";}s:78:"Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php";a:4:{s:6:"md5sum";s:32:"6a12af8493e94dd61cffa21f05b8dac8";s:4:"name";s:78:"Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php";}s:74:"Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.php";a:4:{s:6:"md5sum";s:32:"dab50ef252b23f81bc0a28dd6ed3c2f0";s:4:"name";s:74:"Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.php";}s:72:"Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.php";a:4:{s:6:"md5sum";s:32:"2cac1d204af23007d684c61435e0275a";s:4:"name";s:72:"Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.php";}s:74:"Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php";a:4:{s:6:"md5sum";s:32:"c6aa4826742510546c711553b19d87a4";s:4:"name";s:74:"Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php";}s:68:"Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.php";a:4:{s:6:"md5sum";s:32:"3525f5f7040f8b2e3fb7f2df67c3e52b";s:4:"name";s:68:"Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.php";}s:70:"Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.php";a:4:{s:6:"md5sum";s:32:"602d9216e9b1d1f0d22b31c902e5b4bb";s:4:"name";s:70:"Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.php";}s:45:"Symfony/Component/Security/Http/AccessMap.php";a:4:{s:6:"md5sum";s:32:"9df423675054d980e7bae7cc92020c03";s:4:"name";s:45:"Symfony/Component/Security/Http/AccessMap.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/AccessMap.php";}s:54:"Symfony/Component/Security/Http/AccessMapInterface.php";a:4:{s:6:"md5sum";s:32:"43086a06e68384eaccab38dfb698786d";s:4:"name";s:54:"Symfony/Component/Security/Http/AccessMapInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/AccessMapInterface.php";}s:88:"Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.php";a:4:{s:6:"md5sum";s:32:"1a26ecccd324ea272277edffc5c84886";s:4:"name";s:88:"Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.php";}s:88:"Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.php";a:4:{s:6:"md5sum";s:32:"1249ffb01efe413cfd97a5337cb00137";s:4:"name";s:88:"Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.php";}s:86:"Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.php";a:4:{s:6:"md5sum";s:32:"4b78405b37b8d39c63538f637fd497dc";s:4:"name";s:86:"Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.php";}s:86:"Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php";a:4:{s:6:"md5sum";s:32:"d1a101bba266130a6fdbfc92126cef07";s:4:"name";s:86:"Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php";}s:78:"Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.php";a:4:{s:6:"md5sum";s:32:"ed65679f667d9ef57a6791a64a8bd6c2";s:4:"name";s:78:"Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.php";}s:78:"Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.php";a:4:{s:6:"md5sum";s:32:"afbc8d72124b7a6aee7879fa64325a9f";s:4:"name";s:78:"Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.php";}s:45:"Symfony/Component/Security/Http/composer.json";a:4:{s:6:"md5sum";s:32:"5b7cd3c1e3d2a0a5cacc080b87c9e590";s:4:"name";s:45:"Symfony/Component/Security/Http/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Http/composer.json";}s:80:"Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php";a:4:{s:6:"md5sum";s:32:"6d3ec77aadf630304cff4ed3c026b086";s:4:"name";s:80:"Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php";}s:76:"Symfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.php";a:4:{s:6:"md5sum";s:32:"0cacf36e7c79e4ca8e7fad2ad771335d";s:4:"name";s:76:"Symfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/EntryPoint/BasicAuthenticationEntryPoint.php";}s:77:"Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php";a:4:{s:6:"md5sum";s:32:"0916b4aabd44274d2a1d24d7eccd3370";s:4:"name";s:77:"Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php";}s:75:"Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php";a:4:{s:6:"md5sum";s:32:"957245bb0cc25e4ddfa36ff11b60cf31";s:4:"name";s:75:"Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php";}s:76:"Symfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.php";a:4:{s:6:"md5sum";s:32:"e3cec247e8df4a6e97c579e4ea923bc4";s:4:"name";s:76:"Symfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/EntryPoint/RetryAuthenticationEntryPoint.php";}s:63:"Symfony/Component/Security/Http/Event/InteractiveLoginEvent.php";a:4:{s:6:"md5sum";s:32:"99b4defc6b93df2b7f1c0b4dedef3ff9";s:4:"name";s:63:"Symfony/Component/Security/Http/Event/InteractiveLoginEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Event/InteractiveLoginEvent.php";}s:57:"Symfony/Component/Security/Http/Event/SwitchUserEvent.php";a:4:{s:6:"md5sum";s:32:"7ce04d8a18a0487f987e31fc88bd68c5";s:4:"name";s:57:"Symfony/Component/Security/Http/Event/SwitchUserEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Event/SwitchUserEvent.php";}s:75:"Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php";a:4:{s:6:"md5sum";s:32:"c38b7e9b63bb0cc12e471d58062964b7";s:4:"name";s:75:"Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php";}s:77:"Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php";a:4:{s:6:"md5sum";s:32:"0a1aebef9c2f8f6a328e6227052df7ab";s:4:"name";s:77:"Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php";}s:59:"Symfony/Component/Security/Http/Firewall/AccessListener.php";a:4:{s:6:"md5sum";s:32:"5aa38481213505e4d4b3308202f16ae2";s:4:"name";s:59:"Symfony/Component/Security/Http/Firewall/AccessListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/AccessListener.php";}s:76:"Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php";a:4:{s:6:"md5sum";s:32:"fffa376fb78716df7994bd30c2c3d8e2";s:4:"name";s:76:"Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php";}s:72:"Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php";a:4:{s:6:"md5sum";s:32:"b35cfc2ded8a8aa315ba7ee88ae788b5";s:4:"name";s:72:"Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php";}s:60:"Symfony/Component/Security/Http/Firewall/ChannelListener.php";a:4:{s:6:"md5sum";s:32:"850ac32b9360422daedb18164af00887";s:4:"name";s:60:"Symfony/Component/Security/Http/Firewall/ChannelListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/ChannelListener.php";}s:60:"Symfony/Component/Security/Http/Firewall/ContextListener.php";a:4:{s:6:"md5sum";s:32:"096bd4d9e3b975fcac84503f61384b7e";s:4:"name";s:60:"Symfony/Component/Security/Http/Firewall/ContextListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/ContextListener.php";}s:73:"Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php";a:4:{s:6:"md5sum";s:32:"c9c8fa0fd59936274a596a360568a575";s:4:"name";s:73:"Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php";}s:62:"Symfony/Component/Security/Http/Firewall/ExceptionListener.php";a:4:{s:6:"md5sum";s:32:"0b7d00f42228ca3d4827012968c69a8c";s:4:"name";s:62:"Symfony/Component/Security/Http/Firewall/ExceptionListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/ExceptionListener.php";}s:62:"Symfony/Component/Security/Http/Firewall/ListenerInterface.php";a:4:{s:6:"md5sum";s:32:"6f43f337a4368b4d7b1cce0e76b51b10";s:4:"name";s:62:"Symfony/Component/Security/Http/Firewall/ListenerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/ListenerInterface.php";}s:59:"Symfony/Component/Security/Http/Firewall/LogoutListener.php";a:4:{s:6:"md5sum";s:32:"42ad987ff1e6284b2fd2f11d5cf09725";s:4:"name";s:59:"Symfony/Component/Security/Http/Firewall/LogoutListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/LogoutListener.php";}s:63:"Symfony/Component/Security/Http/Firewall/RememberMeListener.php";a:4:{s:6:"md5sum";s:32:"becb8470e4e05de6ad82ff6bf7e646fc";s:4:"name";s:63:"Symfony/Component/Security/Http/Firewall/RememberMeListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/RememberMeListener.php";}s:77:"Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php";a:4:{s:6:"md5sum";s:32:"3c80c1a805d89cfd4f475aa5d8517267";s:4:"name";s:77:"Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php";}s:76:"Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php";a:4:{s:6:"md5sum";s:32:"e06e2b324e79ee890f1feebba9bc8ac3";s:4:"name";s:76:"Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php";}s:63:"Symfony/Component/Security/Http/Firewall/SwitchUserListener.php";a:4:{s:6:"md5sum";s:32:"62963e5323a197109f7f7f3e860154ca";s:4:"name";s:63:"Symfony/Component/Security/Http/Firewall/SwitchUserListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php";}s:87:"Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php";a:4:{s:6:"md5sum";s:32:"4f883d92d37fd6eb289b50abd37ae680";s:4:"name";s:87:"Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php";}s:71:"Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.php";a:4:{s:6:"md5sum";s:32:"08351ed63f27f17c1b35b08600cc8864";s:4:"name";s:71:"Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall/X509AuthenticationListener.php";}s:44:"Symfony/Component/Security/Http/Firewall.php";a:4:{s:6:"md5sum";s:32:"ee01a78804fc30696b6ec0eeef5c59a6";s:4:"name";s:44:"Symfony/Component/Security/Http/Firewall.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall.php";}s:47:"Symfony/Component/Security/Http/FirewallMap.php";a:4:{s:6:"md5sum";s:32:"2a749495dc3be6af3a2fd28e729c80a6";s:4:"name";s:47:"Symfony/Component/Security/Http/FirewallMap.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/FirewallMap.php";}s:56:"Symfony/Component/Security/Http/FirewallMapInterface.php";a:4:{s:6:"md5sum";s:32:"87ce09ab99f6ec6b472a725abff910c5";s:4:"name";s:56:"Symfony/Component/Security/Http/FirewallMapInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/FirewallMapInterface.php";}s:45:"Symfony/Component/Security/Http/HttpUtils.php";a:4:{s:6:"md5sum";s:32:"a2bb9c5c5076b9a7978f301b64c00b9e";s:4:"name";s:45:"Symfony/Component/Security/Http/HttpUtils.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/HttpUtils.php";}s:39:"Symfony/Component/Security/Http/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:39:"Symfony/Component/Security/Http/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Http/LICENSE";}s:70:"Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php";a:4:{s:6:"md5sum";s:32:"e5ddc1de0d071bdeacbcd2325ed2d4ae";s:4:"name";s:70:"Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php";}s:70:"Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.php";a:4:{s:6:"md5sum";s:32:"45d84fb75d34ea9135c5b72108e1dbf7";s:4:"name";s:70:"Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.php";}s:65:"Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.php";a:4:{s:6:"md5sum";s:32:"eefeebbc791fa1bccf5a3952be87ba78";s:4:"name";s:65:"Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.php";}s:72:"Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.php";a:4:{s:6:"md5sum";s:32:"cc172ba7205b41a32dd97a56eadf4cc8";s:4:"name";s:72:"Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.php";}s:63:"Symfony/Component/Security/Http/Logout/SessionLogoutHandler.php";a:4:{s:6:"md5sum";s:32:"aecd2ef66d8aade29cc47157048e4a21";s:4:"name";s:63:"Symfony/Component/Security/Http/Logout/SessionLogoutHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Logout/SessionLogoutHandler.php";}s:48:"Symfony/Component/Security/Http/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"2f041adb26153b8fb15facf2c6af231d";s:4:"name";s:48:"Symfony/Component/Security/Http/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/phpunit.xml.dist";}s:41:"Symfony/Component/Security/Http/README.md";a:4:{s:6:"md5sum";s:32:"a345783d58ade730c9a01639748b41c6";s:4:"name";s:41:"Symfony/Component/Security/Http/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Http/README.md";}s:73:"Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php";a:4:{s:6:"md5sum";s:32:"b72e5cba34abbeea45218aced16a6359";s:4:"name";s:73:"Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php";}s:85:"Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php";a:4:{s:6:"md5sum";s:32:"435ea3e4c99dd22c771c99f16392c656";s:4:"name";s:85:"Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php";s:4:"role";s:3:"php";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php";}s:74:"Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php";a:4:{s:6:"md5sum";s:32:"d0150afc723a4bb2f322842c1e0a8ce6";s:4:"name";s:74:"Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php";}s:63:"Symfony/Component/Security/Http/RememberMe/ResponseListener.php";a:4:{s:6:"md5sum";s:32:"1d39556b7575907aa6f092bb4c07f387";s:4:"name";s:63:"Symfony/Component/Security/Http/RememberMe/ResponseListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/RememberMe/ResponseListener.php";}s:75:"Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php";a:4:{s:6:"md5sum";s:32:"2e0288eec870215f3f4b8e360afbcf21";s:4:"name";s:75:"Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php";}s:50:"Symfony/Component/Security/Http/SecurityEvents.php";a:4:{s:6:"md5sum";s:32:"80cf473a2f0baee880e458d5946fde6b";s:4:"name";s:50:"Symfony/Component/Security/Http/SecurityEvents.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/SecurityEvents.php";}s:73:"Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php";a:4:{s:6:"md5sum";s:32:"f4eee94c1c2e104f0ce7b8d5bd349fa0";s:4:"name";s:73:"Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php";}s:82:"Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.php";a:4:{s:6:"md5sum";s:32:"a8df527492a3c775c0c2d3affaec1268";s:4:"name";s:82:"Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.php";}s:55:"Symfony/Component/Security/Http/Tests/AccessMapTest.php";a:4:{s:6:"md5sum";s:32:"1e501db8e61f7fbbe1ce2046846d0d16";s:4:"name";s:55:"Symfony/Component/Security/Http/Tests/AccessMapTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/AccessMapTest.php";}s:96:"Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php";a:4:{s:6:"md5sum";s:32:"d3e7326491ec2358ba350f4a937d9778";s:4:"name";s:96:"Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:140:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.php";}s:96:"Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php";a:4:{s:6:"md5sum";s:32:"f238eea0886f4d046befadaa74b02fbe";s:4:"name";s:96:"Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:140:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php";}s:88:"Symfony/Component/Security/Http/Tests/Authentication/SimpleAuthenticationHandlerTest.php";a:4:{s:6:"md5sum";s:32:"d5cef550f4e58533d96feab10cdf02d7";s:4:"name";s:88:"Symfony/Component/Security/Http/Tests/Authentication/SimpleAuthenticationHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:132:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Authentication/SimpleAuthenticationHandlerTest.php";}s:86:"Symfony/Component/Security/Http/Tests/EntryPoint/BasicAuthenticationEntryPointTest.php";a:4:{s:6:"md5sum";s:32:"44e155837ffd4ba5e88a3fe86fa0371a";s:4:"name";s:86:"Symfony/Component/Security/Http/Tests/EntryPoint/BasicAuthenticationEntryPointTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/BasicAuthenticationEntryPointTest.php";}s:87:"Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php";a:4:{s:6:"md5sum";s:32:"cf8ce9dfa9ef2b8cf64c2bca4eeaa2ee";s:4:"name";s:87:"Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php";}s:85:"Symfony/Component/Security/Http/Tests/EntryPoint/FormAuthenticationEntryPointTest.php";a:4:{s:6:"md5sum";s:32:"6f33e2bc5d33de50781109deaa92375b";s:4:"name";s:85:"Symfony/Component/Security/Http/Tests/EntryPoint/FormAuthenticationEntryPointTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:129:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/FormAuthenticationEntryPointTest.php";}s:86:"Symfony/Component/Security/Http/Tests/EntryPoint/RetryAuthenticationEntryPointTest.php";a:4:{s:6:"md5sum";s:32:"9e4221ac3557ad490f50b572a1cb6da0";s:4:"name";s:86:"Symfony/Component/Security/Http/Tests/EntryPoint/RetryAuthenticationEntryPointTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/RetryAuthenticationEntryPointTest.php";}s:87:"Symfony/Component/Security/Http/Tests/Firewall/AbstractPreAuthenticatedListenerTest.php";a:4:{s:6:"md5sum";s:32:"7616457ff22f218eb84d0582b3a32d99";s:4:"name";s:87:"Symfony/Component/Security/Http/Tests/Firewall/AbstractPreAuthenticatedListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/AbstractPreAuthenticatedListenerTest.php";}s:69:"Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php";a:4:{s:6:"md5sum";s:32:"50390ecbf94ded92656d9de6570d63c1";s:4:"name";s:69:"Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php";}s:86:"Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php";a:4:{s:6:"md5sum";s:32:"d3745efe02656a6a40d2421791a65ab2";s:4:"name";s:86:"Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php";}s:82:"Symfony/Component/Security/Http/Tests/Firewall/BasicAuthenticationListenerTest.php";a:4:{s:6:"md5sum";s:32:"f9b4fe52898a270086a0323bc9e744d2";s:4:"name";s:82:"Symfony/Component/Security/Http/Tests/Firewall/BasicAuthenticationListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/BasicAuthenticationListenerTest.php";}s:70:"Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.php";a:4:{s:6:"md5sum";s:32:"39f3a9fbfd8fb369e3518c1f737c69d1";s:4:"name";s:70:"Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.php";}s:70:"Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php";a:4:{s:6:"md5sum";s:32:"fefeae0b89d7bce7c98fd5f79e64fb80";s:4:"name";s:70:"Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php";}s:65:"Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php";a:4:{s:6:"md5sum";s:32:"0cd7a88d1e73a7c2397a05ee835b416e";s:4:"name";s:65:"Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php";}s:69:"Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php";a:4:{s:6:"md5sum";s:32:"bdc936486eb622f5ebc89def545d34cc";s:4:"name";s:69:"Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php";}s:73:"Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php";a:4:{s:6:"md5sum";s:32:"5aa221a87c438540d59e8d06cbc51e43";s:4:"name";s:73:"Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php";}s:73:"Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php";a:4:{s:6:"md5sum";s:32:"4e401aaf8580c5f225065eb296d09ffd";s:4:"name";s:73:"Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php";}s:81:"Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.php";a:4:{s:6:"md5sum";s:32:"62ada44f4eeb63bc411ebff114f5f340";s:4:"name";s:81:"Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.php";}s:57:"Symfony/Component/Security/Http/Tests/FirewallMapTest.php";a:4:{s:6:"md5sum";s:32:"90e0766898394d8523cb8d3093b8ad0f";s:4:"name";s:57:"Symfony/Component/Security/Http/Tests/FirewallMapTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/FirewallMapTest.php";}s:54:"Symfony/Component/Security/Http/Tests/FirewallTest.php";a:4:{s:6:"md5sum";s:32:"58a4fef6ae246369bdff44ea9566e2e7";s:4:"name";s:54:"Symfony/Component/Security/Http/Tests/FirewallTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/FirewallTest.php";}s:55:"Symfony/Component/Security/Http/Tests/HttpUtilsTest.php";a:4:{s:6:"md5sum";s:32:"a65c06a07157d8b2f79f1718fe9acc3a";s:4:"name";s:55:"Symfony/Component/Security/Http/Tests/HttpUtilsTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php";}s:80:"Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.php";a:4:{s:6:"md5sum";s:32:"d82d3ab3c92583cd9aa15b9ed8ae9db2";s:4:"name";s:80:"Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.php";}s:80:"Symfony/Component/Security/Http/Tests/Logout/DefaultLogoutSuccessHandlerTest.php";a:4:{s:6:"md5sum";s:32:"b35e129cc7f5bc083d3b855f286a2228";s:4:"name";s:80:"Symfony/Component/Security/Http/Tests/Logout/DefaultLogoutSuccessHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Logout/DefaultLogoutSuccessHandlerTest.php";}s:73:"Symfony/Component/Security/Http/Tests/Logout/SessionLogoutHandlerTest.php";a:4:{s:6:"md5sum";s:32:"31043c56e00a9f85591f7aeb1a0d7abe";s:4:"name";s:73:"Symfony/Component/Security/Http/Tests/Logout/SessionLogoutHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Logout/SessionLogoutHandlerTest.php";}s:83:"Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php";a:4:{s:6:"md5sum";s:32:"a4f462fe63db2978e9eb7b9088a332a1";s:4:"name";s:83:"Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php";}s:95:"Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php";a:4:{s:6:"md5sum";s:32:"1dcfd5f481984cbcbe252c35abb90560";s:4:"name";s:95:"Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:139:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php";}s:73:"Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.php";a:4:{s:6:"md5sum";s:32:"d8f1bc020d5b21d2de0433c2839b08f9";s:4:"name";s:73:"Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.php";}s:85:"Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php";a:4:{s:6:"md5sum";s:32:"e4109def8460d75d5f052f67ec6ba970";s:4:"name";s:85:"Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:129:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php";}s:83:"Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php";a:4:{s:6:"md5sum";s:32:"7787c557da28fb7dd4cc86318f909bb3";s:4:"name";s:83:"Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php";}s:34:"Symfony/Component/Security/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:34:"Symfony/Component/Security/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/LICENSE";}s:43:"Symfony/Component/Security/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"b48391335127152904b86aef4327b6ba";s:4:"name";s:43:"Symfony/Component/Security/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/phpunit.xml.dist";}s:36:"Symfony/Component/Security/README.md";a:4:{s:6:"md5sum";s:32:"4dec033fca5592436030a98806bbf6d7";s:4:"name";s:36:"Symfony/Component/Security/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/README.md";}s:65:"Symfony/Component/Security/Resources/translations/security.ar.xlf";a:4:{s:6:"md5sum";s:32:"1e750b4762305800f3dd181eab53e2ba";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ar.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.ar.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.bg.xlf";a:4:{s:6:"md5sum";s:32:"60f216b50da4b49da27b177ba8ca3b46";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.bg.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.bg.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.ca.xlf";a:4:{s:6:"md5sum";s:32:"31cbf1bd957d4f4c3401c20d9a1b10bc";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ca.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.ca.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.cs.xlf";a:4:{s:6:"md5sum";s:32:"0cf2e748f73950fb74f6a5978ab773f4";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.cs.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.cs.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.da.xlf";a:4:{s:6:"md5sum";s:32:"6d1c01434b6521da496cf9c91c144ea1";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.da.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.da.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.de.xlf";a:4:{s:6:"md5sum";s:32:"a01afc0ce8bdc7598652c6560fae8512";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.de.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.de.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.el.xlf";a:4:{s:6:"md5sum";s:32:"c2883d0b5e1e7eeed7ec66ea9853f5cc";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.el.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.el.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.en.xlf";a:4:{s:6:"md5sum";s:32:"0c6a0114323a39fad8cb33246be7b7d9";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.en.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.en.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.es.xlf";a:4:{s:6:"md5sum";s:32:"7ae3e719888ac0c94aeda98734b5e9f5";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.es.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.es.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.fa.xlf";a:4:{s:6:"md5sum";s:32:"eef6f0230157636659e13c466e498cd9";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.fa.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.fa.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.fr.xlf";a:4:{s:6:"md5sum";s:32:"8d726781df922dfb126eb85c6c1cf7f5";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.fr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.fr.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.gl.xlf";a:4:{s:6:"md5sum";s:32:"d24525aa71ea6294f1b0dad40d7a5b70";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.gl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.gl.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.hr.xlf";a:4:{s:6:"md5sum";s:32:"7b03fcbcf3c6586ee539377f3f5a3bdc";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.hr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.hr.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.hu.xlf";a:4:{s:6:"md5sum";s:32:"b8704be78d7be163b715e166f07257e3";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.hu.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.hu.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.id.xlf";a:4:{s:6:"md5sum";s:32:"40ec159baa27f18ea7ab7924e652ec97";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.id.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.id.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.it.xlf";a:4:{s:6:"md5sum";s:32:"47a2f3df6c37532fe6a486073aebd0a1";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.it.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.it.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.ja.xlf";a:4:{s:6:"md5sum";s:32:"acf99e98e5ffff85489c97c78a83b317";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ja.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.ja.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.lb.xlf";a:4:{s:6:"md5sum";s:32:"defce0bf7d3e026fbdaebb0cfe7abbd6";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.lb.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.lb.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.nl.xlf";a:4:{s:6:"md5sum";s:32:"79d67b79332d77ce5d39a8531f219538";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.nl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.nl.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.no.xlf";a:4:{s:6:"md5sum";s:32:"03051a200f3f0f13a30ed957026a1784";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.no.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.no.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.pl.xlf";a:4:{s:6:"md5sum";s:32:"f6e927ae45bf961507418d03db1c676d";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.pl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.pl.xlf";}s:68:"Symfony/Component/Security/Resources/translations/security.pt_BR.xlf";a:4:{s:6:"md5sum";s:32:"5140f0e3d9b00962b72eb4f3cce9b2a4";s:4:"name";s:68:"Symfony/Component/Security/Resources/translations/security.pt_BR.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.pt_BR.xlf";}s:68:"Symfony/Component/Security/Resources/translations/security.pt_PT.xlf";a:4:{s:6:"md5sum";s:32:"2855177bf25fd860bca194067f350e0a";s:4:"name";s:68:"Symfony/Component/Security/Resources/translations/security.pt_PT.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.pt_PT.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.ro.xlf";a:4:{s:6:"md5sum";s:32:"f07b53a0e13bb3f1267b212e07b49a14";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ro.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.ro.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.ru.xlf";a:4:{s:6:"md5sum";s:32:"f943d4b750be69bd91e03eca27df52f5";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ru.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.ru.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.sk.xlf";a:4:{s:6:"md5sum";s:32:"a570f49a5deb0bba84a8f5ce71018b32";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.sk.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.sk.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.sl.xlf";a:4:{s:6:"md5sum";s:32:"0a5e641bcbd17d9502a2f2f3e1d51999";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.sl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.sl.xlf";}s:70:"Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlf";a:4:{s:6:"md5sum";s:32:"823f2ed1191ec9723d46f2516d700973";s:4:"name";s:70:"Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlf";}s:70:"Symfony/Component/Security/Resources/translations/security.sr_Latn.xlf";a:4:{s:6:"md5sum";s:32:"a95969c966594fa2afcf4c0f58dcf034";s:4:"name";s:70:"Symfony/Component/Security/Resources/translations/security.sr_Latn.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.sr_Latn.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.sv.xlf";a:4:{s:6:"md5sum";s:32:"ef66c814ecc8a2fc5fbbe30dd23f3a82";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.sv.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.sv.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.tr.xlf";a:4:{s:6:"md5sum";s:32:"0d789d9cb295319cb483f864ca99b2bf";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.tr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.tr.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.ua.xlf";a:4:{s:6:"md5sum";s:32:"c7e13f578ddab881e5bb035d0e905048";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.ua.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.ua.xlf";}s:65:"Symfony/Component/Security/Resources/translations/security.vi.xlf";a:4:{s:6:"md5sum";s:32:"b549799b91bf73427ed2c0de26e8d27e";s:4:"name";s:65:"Symfony/Component/Security/Resources/translations/security.vi.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.vi.xlf";}s:68:"Symfony/Component/Security/Resources/translations/security.zh_CN.xlf";a:4:{s:6:"md5sum";s:32:"c1985d9108a24d1e66b1832cf6c0fae7";s:4:"name";s:68:"Symfony/Component/Security/Resources/translations/security.zh_CN.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations/security.zh_CN.xlf";}s:82:"Symfony/Component/Security/Tests/Core/Authentication/Token/RememberMeTokenTest.php";a:4:{s:6:"md5sum";s:32:"82c8dfa2a45c9aca1e839e448574b12b";s:4:"name";s:82:"Symfony/Component/Security/Tests/Core/Authentication/Token/RememberMeTokenTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Core/Authentication/Token/RememberMeTokenTest.php";}s:71:"Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.php";a:4:{s:6:"md5sum";s:32:"77f76d7ae94a351ec03076059c96f80d";s:4:"name";s:71:"Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.php";}s:62:"Symfony/Component/Security/Tests/Core/User/UserCheckerTest.php";a:4:{s:6:"md5sum";s:32:"3b095a4893cc953a6aa42a368c70c8a5";s:4:"name";s:62:"Symfony/Component/Security/Tests/Core/User/UserCheckerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Core/User/UserCheckerTest.php";}s:72:"Symfony/Component/Security/Tests/Http/Firewall/ExceptionListenerTest.php";a:4:{s:6:"md5sum";s:32:"693af9a30d85b3907c6147d9ddb56df8";s:4:"name";s:72:"Symfony/Component/Security/Tests/Http/Firewall/ExceptionListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Http/Firewall/ExceptionListenerTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:96:{s:73:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Acl";b:1;s:69:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security";b:1;s:60:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component";b:1;s:50:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony";b:1;s:42:"/opt/alt/php54/usr/share/doc/pear/Security";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Dbal";b:1;s:60:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl";b:1;s:56:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Domain";b:1;s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Exception";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Model";b:1;s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Permission";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl";b:1;s:70:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security";b:1;s:61:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component";b:1;s:51:"/opt/alt/php54/usr/share/pear/test/Security/Symfony";b:1;s:43:"/opt/alt/php54/usr/share/pear/test/Security";b:1;s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/bin";b:1;s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Resources/schema";b:1;s:85:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Dbal";b:1;s:80:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Domain";b:1;s:91:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Permission";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Acl/Tests/Voter";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Acl/Voter";b:1;s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication";b:1;s:61:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core";b:1;s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Provider";b:1;s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/RememberMe";b:1;s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authentication/Token";b:1;s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization";b:1;s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Authorization/Voter";b:1;s:74:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Core";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Encoder";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Event";b:1;s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Exception";b:1;s:75:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core";b:1;s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources/translations";b:1;s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Resources";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Role";b:1;s:96:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests";b:1;s:105:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider";b:1;s:107:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe";b:1;s:102:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token";b:1;s:95:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authorization";b:1;s:101:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Encoder";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Role";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/User";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Util";b:1;s:103:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Validator/Constraints";b:1;s:91:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Core/Tests/Validator";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/User";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Util";b:1;s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Validator/Constraints";b:1;s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Core/Validator";b:1;s:74:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Csrf";b:1;s:61:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf";b:1;s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/Exception";b:1;s:75:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Csrf";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Csrf/Tests";b:1;s:96:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Csrf/Tests/TokenGenerator";b:1;s:94:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage";b:1;s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/TokenGenerator";b:1;s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Csrf/TokenStorage";b:1;s:61:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http";b:1;s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Authentication";b:1;s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Authorization";b:1;s:74:"/opt/alt/php54/usr/share/doc/pear/Security/Symfony/Component/Security/Http";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/EntryPoint";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Event";b:1;s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Firewall";b:1;s:68:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Logout";b:1;s:75:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/RememberMe";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Http/Session";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests";b:1;s:96:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Authentication";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/EntryPoint";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Firewall";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Logout";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/RememberMe";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Http/Tests/Session";b:1;s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources/translations";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Security/Resources";b:1;s:102:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Core/Authentication/Token";b:1;s:96:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Core/Authentication";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Core";b:1;s:76:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Core/User";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Http/Firewall";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Security/Symfony/Component/Security/Tests/Http";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:9:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:10:"HttpKernel";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:14:"HttpFoundation";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:4;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:15:"EventDispatcher";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:5;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:7:"Routing";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:6;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:6:"Finder";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:7;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:11:"ClassLoader";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:8;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:4:"Form";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506496;}PK! Gw̟̟1.registry/.channel.pear.symfony.com/validator.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:9:"Validator";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:28:"Symfony2 Validator Component";s:11:"description";s:28:"Symfony2 Validator Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:51";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:307:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"70881b5188a71a54eaaa5174d35b8a7d";s:4:"name";s:42:"Symfony/Component/Validator/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"460bbf634d57fb9eb81d53f051e8ab23";s:4:"name";s:40:"Symfony/Component/Validator/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b310a8a94f594586e92f197f9c2b271";s:4:"name";s:51:"Symfony/Component/Validator/ClassBasedInterface.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3af3b2a12af30fa1161d400c5fa160db";s:4:"name";s:41:"Symfony/Component/Validator/composer.json";s:4:"role";s:3:"doc";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4673b9af925a35c9c4bed05edab5facb";s:4:"name";s:42:"Symfony/Component/Validator/Constraint.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8aa49d6a48f577e0f496ed051e1e3e35";s:4:"name";s:62:"Symfony/Component/Validator/Constraints/AbstractComparison.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cd63ee91f580c33ed3e5027672c447cf";s:4:"name";s:71:"Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"81fa182a1f3260d61a45e0c9a886300a";s:4:"name";s:47:"Symfony/Component/Validator/Constraints/All.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"76ee8f2dd2d0a1ff7329ddd7f4e812a8";s:4:"name";s:56:"Symfony/Component/Validator/Constraints/AllValidator.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"77b52c16bd1289663a73f66f39190eed";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Blank.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6bf52b86aeb6e4b7e762994e61b30656";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/BlankValidator.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"16cf9f642a14848b9bc3ef3b883f19d1";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Callback.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ad21e0f04423e82992c83f14e893779e";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/CallbackValidator.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"056ebff8baa348be8202ca6b297c4d01";s:4:"name";s:54:"Symfony/Component/Validator/Constraints/CardScheme.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"284da971d7406e599a1233b2d2206376";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/CardSchemeValidator.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"49d0c082a54602ac483ce2afffb57431";s:4:"name";s:50:"Symfony/Component/Validator/Constraints/Choice.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c6988852a1c710e4832e4a0cf5f465ed";s:4:"name";s:59:"Symfony/Component/Validator/Constraints/ChoiceValidator.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09520f3d5eacb03f804fadf2d0afd2d2";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/Collection/Optional.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a084bfe09407f23250f410ed4c00c05f";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/Collection/Required.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5ca5192af79d7355af8a4017b671a8fb";s:4:"name";s:54:"Symfony/Component/Validator/Constraints/Collection.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2a15094f63da567965053d81cec8b6bc";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/CollectionValidator.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d60afc2a00394329890f41050239d6be";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Count.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8912e6648f1801a81237b64ad79beea8";s:4:"name";s:51:"Symfony/Component/Validator/Constraints/Country.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5a7bd5263e9707dd6acab56907453cb4";s:4:"name";s:60:"Symfony/Component/Validator/Constraints/CountryValidator.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b63f576f4acf1cf05dd4a10b8dcdf613";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/CountValidator.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dd7316794387746194d2d2fb42b7eb7f";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Currency.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9dfda60fe4dedc960dec518bcdf21a7f";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/CurrencyValidator.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5e1a2350fefabcba23f44ced82b9e830";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Date.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7146e3c517edfd501fdec3734e5a6f55";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/DateTime.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"113eb18edd006507eb982c46d58fa85f";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/DateTimeValidator.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b2d3caa73ec728ede046f0358cf001a0";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/DateValidator.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3aa9b1e92fed777c1439d01d7eb6af23";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Email.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"01b056747cb908f564510334d5cf80fb";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/EmailValidator.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1203a215e52460149441441579253d47";s:4:"name";s:51:"Symfony/Component/Validator/Constraints/EqualTo.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"85299aea76d2e9973c0a2a1f39796640";s:4:"name";s:60:"Symfony/Component/Validator/Constraints/EqualToValidator.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5bf3ff6df741685faf77a3568bb8b633";s:4:"name";s:53:"Symfony/Component/Validator/Constraints/Existence.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"900f7ff58ceb2ae76007bb5a6394d921";s:4:"name";s:54:"Symfony/Component/Validator/Constraints/Expression.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ede516fce7c1f487d08359ba11ae2ff";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/ExpressionValidator.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09d73194877b4dda8d4300f24e195013";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/False.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"79467bb4ee325740c202f9c8b97010a9";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/FalseValidator.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6e8e581ad9077fb13150682285df29b1";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/File.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d08c81702c68afd2c2757543f7d5193b";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/FileValidator.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"79767d486e626e5c77b78bd7afe4aee9";s:4:"name";s:55:"Symfony/Component/Validator/Constraints/GreaterThan.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ebb17f4ce792e12fecff1e9bb4b41e21";s:4:"name";s:62:"Symfony/Component/Validator/Constraints/GreaterThanOrEqual.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e4430a7d1c6f9f03c7a770ddda909d5f";s:4:"name";s:71:"Symfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2ff68d36a30ee563937565accdaf91e3";s:4:"name";s:64:"Symfony/Component/Validator/Constraints/GreaterThanValidator.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"15201fe63d343b6b1e1a739fcaad8662";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/GroupSequence.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"38089465890121217bdedbd833ee95e4";s:4:"name";s:65:"Symfony/Component/Validator/Constraints/GroupSequenceProvider.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b6c69a9eb08622192d6af7a1f90bde3";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Iban.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"767699246ea9dae9c99b112253ef0af0";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/IbanValidator.php";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c170ea25fe3922db43490b571011a438";s:4:"name";s:55:"Symfony/Component/Validator/Constraints/IdenticalTo.php";s:4:"role";s:3:"php";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"56257e543ffc3632a272b284cd7ceeda";s:4:"name";s:64:"Symfony/Component/Validator/Constraints/IdenticalToValidator.php";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"92f832be76aed1cfcd18d276ff45bce9";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Image.php";s:4:"role";s:3:"php";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a95e09bb82ad891054f0680144487871";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/ImageValidator.php";s:4:"role";s:3:"php";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1ff307af5e1d02b5da016f7fd3c64816";s:4:"name";s:46:"Symfony/Component/Validator/Constraints/Ip.php";s:4:"role";s:3:"php";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"66c5af8b916684cf0c166c280cb00aa5";s:4:"name";s:55:"Symfony/Component/Validator/Constraints/IpValidator.php";s:4:"role";s:3:"php";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0eb759966852ddb84bd6b24c967040b7";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Isbn.php";s:4:"role";s:3:"php";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff5b531b2a454c10fce5ae7c0894a22a";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/IsbnValidator.php";s:4:"role";s:3:"php";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ee14ff1ba2ba521a7eb166ef651a1c75";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Issn.php";s:4:"role";s:3:"php";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"93a39aba6f6a4f5a23ea91108425fa07";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/IssnValidator.php";s:4:"role";s:3:"php";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5ba57bdea0848798ae8da31a78f1c072";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Language.php";s:4:"role";s:3:"php";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"27e3692dbfe009a21c71f826e9ab7fe1";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/LanguageValidator.php";s:4:"role";s:3:"php";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1f0169f057954dec8280c2c4931b0a13";s:4:"name";s:50:"Symfony/Component/Validator/Constraints/Length.php";s:4:"role";s:3:"php";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"93de9c9c5ab7e3b8c19c671004a50ad4";s:4:"name";s:59:"Symfony/Component/Validator/Constraints/LengthValidator.php";s:4:"role";s:3:"php";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eb6377f01e9cc6440dfa4e183ef8c4ab";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/LessThan.php";s:4:"role";s:3:"php";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09d85d86e5798681d39dfe598df6c562";s:4:"name";s:59:"Symfony/Component/Validator/Constraints/LessThanOrEqual.php";s:4:"role";s:3:"php";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"564b53c3325126cc54ee9c14102b170a";s:4:"name";s:68:"Symfony/Component/Validator/Constraints/LessThanOrEqualValidator.php";s:4:"role";s:3:"php";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa4623bfdf3d9d518660aeb634367252";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/LessThanValidator.php";s:4:"role";s:3:"php";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"de036e7a36b266c549985ededcb96344";s:4:"name";s:50:"Symfony/Component/Validator/Constraints/Locale.php";s:4:"role";s:3:"php";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4b3b59f35f25cb78b8b25a266d405986";s:4:"name";s:59:"Symfony/Component/Validator/Constraints/LocaleValidator.php";s:4:"role";s:3:"php";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"25dc43335a20b9a6e3b31b43a762e762";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Luhn.php";s:4:"role";s:3:"php";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f7360bdeef47916280c4e15ce1be91b1";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/LuhnValidator.php";s:4:"role";s:3:"php";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"868b62aca0723c3b457144aaf6c93a62";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/NotBlank.php";s:4:"role";s:3:"php";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d095cf646d98ffc63c8404b87dc64c3a";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/NotBlankValidator.php";s:4:"role";s:3:"php";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"54a792ce51e206d9f1f342acf8de0ca6";s:4:"name";s:54:"Symfony/Component/Validator/Constraints/NotEqualTo.php";s:4:"role";s:3:"php";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba17b4508a92681c1ecb989e31150989";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/NotEqualToValidator.php";s:4:"role";s:3:"php";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b0cf3bbae80822776f2ebe3853331da2";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/NotIdenticalTo.php";s:4:"role";s:3:"php";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3fb62be8d95c084095e2bb8354fa6cb2";s:4:"name";s:67:"Symfony/Component/Validator/Constraints/NotIdenticalToValidator.php";s:4:"role";s:3:"php";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1797b9ea7b21a35e5d2d1d68ca7fe157";s:4:"name";s:51:"Symfony/Component/Validator/Constraints/NotNull.php";s:4:"role";s:3:"php";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d7a3af7c2064d4ff44733151eef7630d";s:4:"name";s:60:"Symfony/Component/Validator/Constraints/NotNullValidator.php";s:4:"role";s:3:"php";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1c8478dc05ca6a3af5499c59220d99b0";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Null.php";s:4:"role";s:3:"php";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"412fc8b35206517d8c2844aec558d6f5";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/NullValidator.php";s:4:"role";s:3:"php";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"82b49cbb8deeed5086002af1d2e3d06f";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Optional.php";s:4:"role";s:3:"php";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1875728a92acf358891dc559c15127fa";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Range.php";s:4:"role";s:3:"php";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5756018ef45c81919b3214d78b0e6eb4";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/RangeValidator.php";s:4:"role";s:3:"php";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f7a9e04cd4262d3f80fcbe70b9c4e806";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Regex.php";s:4:"role";s:3:"php";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea6c897666cc7a6af2ff4d913f82a392";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/RegexValidator.php";s:4:"role";s:3:"php";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"acbae820b5540dde9ec681dd85429861";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Required.php";s:4:"role";s:3:"php";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"67b70d9e097e05da71488e09b6e90b95";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Time.php";s:4:"role";s:3:"php";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"334dffc652e93fa5bd706116c9b44257";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/TimeValidator.php";s:4:"role";s:3:"php";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a78e9cd61bb76287a0522b1e5b7b392b";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/True.php";s:4:"role";s:3:"php";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"637d4488ec6112faf64aae361929d040";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/TrueValidator.php";s:4:"role";s:3:"php";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d965c82e65e8289f8ecb88d83fc83de7";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Type.php";s:4:"role";s:3:"php";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9f24a3872c47a60f1a990c9f199e14c2";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/TypeValidator.php";s:4:"role";s:3:"php";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ee711e399a3f093e7b3545692ebf7f62";s:4:"name";s:47:"Symfony/Component/Validator/Constraints/Url.php";s:4:"role";s:3:"php";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"38d0b621d809fc73a63e73c9b2eec6f0";s:4:"name";s:56:"Symfony/Component/Validator/Constraints/UrlValidator.php";s:4:"role";s:3:"php";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1bb212699fe8609180681b51be678cd4";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Valid.php";s:4:"role";s:3:"php";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d599a1ef98a59cddd0952a2217e6a61a";s:4:"name";s:51:"Symfony/Component/Validator/ConstraintValidator.php";s:4:"role";s:3:"php";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1dc05c3449f8ee63549a2672f762c635";s:4:"name";s:58:"Symfony/Component/Validator/ConstraintValidatorFactory.php";s:4:"role";s:3:"php";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f322ea75c86e7e0fe44bf0e55b45522e";s:4:"name";s:67:"Symfony/Component/Validator/ConstraintValidatorFactoryInterface.php";s:4:"role";s:3:"php";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"62e34e25daf9b43c27cd8111b2c10ede";s:4:"name";s:60:"Symfony/Component/Validator/ConstraintValidatorInterface.php";s:4:"role";s:3:"php";}}i:101;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"687daad19e5f43350617c063490aa100";s:4:"name";s:51:"Symfony/Component/Validator/ConstraintViolation.php";s:4:"role";s:3:"php";}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ef89d7f0cbae45ed31aa8a72fc13487d";s:4:"name";s:60:"Symfony/Component/Validator/ConstraintViolationInterface.php";s:4:"role";s:3:"php";}}i:103;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2c8b4b7b53a10d1f269c2ce53c7e901";s:4:"name";s:55:"Symfony/Component/Validator/ConstraintViolationList.php";s:4:"role";s:3:"php";}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"36c862c3c9a1e8e797fe4b6ef4c91546";s:4:"name";s:64:"Symfony/Component/Validator/ConstraintViolationListInterface.php";s:4:"role";s:3:"php";}}i:105;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4be17f7858f92496b9d0527bcd7cd720";s:4:"name";s:49:"Symfony/Component/Validator/DefaultTranslator.php";s:4:"role";s:3:"php";}}i:106;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e1602d2dcf95a9052da9a432db6c1875";s:4:"name";s:64:"Symfony/Component/Validator/Exception/BadMethodCallException.php";s:4:"role";s:3:"php";}}i:107;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5fcc0f865c77f52e9847378da9f0489c";s:4:"name";s:71:"Symfony/Component/Validator/Exception/ConstraintDefinitionException.php";s:4:"role";s:3:"php";}}i:108;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0b0c94ce85588dd563f8767426eafdcc";s:4:"name";s:60:"Symfony/Component/Validator/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:109;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ed9aa39f207cff711cb5c8fc86114395";s:4:"name";s:66:"Symfony/Component/Validator/Exception/GroupDefinitionException.php";s:4:"role";s:3:"php";}}i:110;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bd79de35ad0e084b8400e08793205a69";s:4:"name";s:66:"Symfony/Component/Validator/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";}}i:111;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7dcead75d21f8d0a56980c4a07d7aca4";s:4:"name";s:65:"Symfony/Component/Validator/Exception/InvalidOptionsException.php";s:4:"role";s:3:"php";}}i:112;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9f68ce5c519e7ae740485b54d04e1d51";s:4:"name";s:58:"Symfony/Component/Validator/Exception/MappingException.php";s:4:"role";s:3:"php";}}i:113;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b53533773e89efd08b4e8fee6b186579";s:4:"name";s:65:"Symfony/Component/Validator/Exception/MissingOptionsException.php";s:4:"role";s:3:"php";}}i:114;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e9bea930f7bceee8d7dde50dd85e9ba7";s:4:"name";s:65:"Symfony/Component/Validator/Exception/NoSuchMetadataException.php";s:4:"role";s:3:"php";}}i:115;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"99d749d07f412b89d5af760e96666226";s:4:"name";s:58:"Symfony/Component/Validator/Exception/RuntimeException.php";s:4:"role";s:3:"php";}}i:116;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"49ee74315300fe571873b44bdd13e171";s:4:"name";s:65:"Symfony/Component/Validator/Exception/UnexpectedTypeException.php";s:4:"role";s:3:"php";}}i:117;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a0a8b64183db5f06140fbe08503efdaf";s:4:"name";s:60:"Symfony/Component/Validator/Exception/ValidatorException.php";s:4:"role";s:3:"php";}}i:118;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"915a47ef778253a6c7a1e2a2528aa996";s:4:"name";s:48:"Symfony/Component/Validator/ExecutionContext.php";s:4:"role";s:3:"php";}}i:119;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"676e8179bba9e6d350680ef1ea759b9e";s:4:"name";s:57:"Symfony/Component/Validator/ExecutionContextInterface.php";s:4:"role";s:3:"php";}}i:120;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ca92e46f393618f0efc6954ca2466939";s:4:"name";s:63:"Symfony/Component/Validator/GlobalExecutionContextInterface.php";s:4:"role";s:3:"php";}}i:121;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"381af269f7e5fb28e87a5c81a3707621";s:4:"name";s:62:"Symfony/Component/Validator/GroupSequenceProviderInterface.php";s:4:"role";s:3:"php";}}i:122;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:35:"Symfony/Component/Validator/LICENSE";s:4:"role";s:3:"doc";}}i:123;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4ff2d258e293c0d3347a56678051e8d3";s:4:"name";s:64:"Symfony/Component/Validator/Mapping/BlackholeMetadataFactory.php";s:4:"role";s:3:"php";}}i:124;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"462497cd0cf5d29d523b5a0d75b81ca0";s:4:"name";s:54:"Symfony/Component/Validator/Mapping/Cache/ApcCache.php";s:4:"role";s:3:"php";}}i:125;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8a7b01dab83206f30d02ceb5ccc8c171";s:4:"name";s:60:"Symfony/Component/Validator/Mapping/Cache/CacheInterface.php";s:4:"role";s:3:"php";}}i:126;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b7ce80520c8d175471f396247948cdc3";s:4:"name";s:53:"Symfony/Component/Validator/Mapping/ClassMetadata.php";s:4:"role";s:3:"php";}}i:127;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b708c68549204312c540ee7dacb9ad87";s:4:"name";s:60:"Symfony/Component/Validator/Mapping/ClassMetadataFactory.php";s:4:"role";s:3:"php";}}i:128;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6d8a4315440eca7b33bee8a2c2df3cf0";s:4:"name";s:55:"Symfony/Component/Validator/Mapping/ElementMetadata.php";s:4:"role";s:3:"php";}}i:129;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"66734470bd1916de0ca3f01784364005";s:4:"name";s:54:"Symfony/Component/Validator/Mapping/GetterMetadata.php";s:4:"role";s:3:"php";}}i:130;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4aafbfbbc0d5d5430ee20aff7da60f5c";s:4:"name";s:61:"Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php";s:4:"role";s:3:"php";}}i:131;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8ad79406bc548394a200e712dee0c30f";s:4:"name";s:63:"Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php";s:4:"role";s:3:"php";}}i:132;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b4a61c8b30fae02788429854ba81036";s:4:"name";s:57:"Symfony/Component/Validator/Mapping/Loader/FileLoader.php";s:4:"role";s:3:"php";}}i:133;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4af7f07bfcfa849e66999ab1ee24f876";s:4:"name";s:58:"Symfony/Component/Validator/Mapping/Loader/FilesLoader.php";s:4:"role";s:3:"php";}}i:134;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8b284df5873ac5725b5c4705b69d530b";s:4:"name";s:58:"Symfony/Component/Validator/Mapping/Loader/LoaderChain.php";s:4:"role";s:3:"php";}}i:135;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d202e225a6b817c2829e10f98d04abdd";s:4:"name";s:62:"Symfony/Component/Validator/Mapping/Loader/LoaderInterface.php";s:4:"role";s:3:"php";}}i:136;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2f1f4e105fe3d987790a62d0a36ace39";s:4:"name";s:99:"Symfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd";s:4:"role";s:3:"php";}}i:137;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1005146f217d0bcdaabe67f3c3e9c225";s:4:"name";s:65:"Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php";s:4:"role";s:3:"php";}}i:138;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c8d1f2225f940f29028386fe2fbbfe7a";s:4:"name";s:60:"Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php";s:4:"role";s:3:"php";}}i:139;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"31fdec6936f6c041c6c9d4a3d3cec86e";s:4:"name";s:61:"Symfony/Component/Validator/Mapping/Loader/XmlFilesLoader.php";s:4:"role";s:3:"php";}}i:140;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a712b89ff6fe80354296a3b399c6139f";s:4:"name";s:61:"Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php";s:4:"role";s:3:"php";}}i:141;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8db3ad3b587098ac95ad6d25317c2e9c";s:4:"name";s:62:"Symfony/Component/Validator/Mapping/Loader/YamlFilesLoader.php";s:4:"role";s:3:"php";}}i:142;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8c45e691d8e03b05b3a893e3acdb5a0f";s:4:"name";s:54:"Symfony/Component/Validator/Mapping/MemberMetadata.php";s:4:"role";s:3:"php";}}i:143;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f44bb51a8950d588ae2dd0ab7bf17a1f";s:4:"name";s:56:"Symfony/Component/Validator/Mapping/PropertyMetadata.php";s:4:"role";s:3:"php";}}i:144;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4db44d9e04ab20b9b5757aaac84e4aa7";s:4:"name";s:56:"Symfony/Component/Validator/MetadataFactoryInterface.php";s:4:"role";s:3:"php";}}i:145;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ee339e11db2658139a134c3824c8afd7";s:4:"name";s:49:"Symfony/Component/Validator/MetadataInterface.php";s:4:"role";s:3:"php";}}i:146;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"00b9e5fab71633739ff82314900aa9c9";s:4:"name";s:58:"Symfony/Component/Validator/ObjectInitializerInterface.php";s:4:"role";s:3:"php";}}i:147;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"78843eae0d52d5f5909f1087a44295b7";s:4:"name";s:44:"Symfony/Component/Validator/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:148;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6e7e28f7b1ff78536561fcda9521b4dc";s:4:"name";s:66:"Symfony/Component/Validator/PropertyMetadataContainerInterface.php";s:4:"role";s:3:"php";}}i:149;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f6c682d20098aac0b0502374eaa79df1";s:4:"name";s:57:"Symfony/Component/Validator/PropertyMetadataInterface.php";s:4:"role";s:3:"php";}}i:150;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"909b0bb88dcdb6cdee5dce42ec11e0d8";s:4:"name";s:37:"Symfony/Component/Validator/README.md";s:4:"role";s:3:"doc";}}i:151;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c23dd67e56958cc57e1147fce770d730";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.af.xlf";s:4:"role";s:3:"php";}}i:152;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2a03a4464216db4d71c91a1fd5f0c696";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ar.xlf";s:4:"role";s:3:"php";}}i:153;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d4011977e7d9fed5e3c57c9b5e09077e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.bg.xlf";s:4:"role";s:3:"php";}}i:154;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a17496bce86c96c7d447a148b2d29e8a";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ca.xlf";s:4:"role";s:3:"php";}}i:155;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bbda69a9cc105df6d0e915e93ea4de6d";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.cs.xlf";s:4:"role";s:3:"php";}}i:156;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"117e80d2ecc0ed11fe07dcef7d023d3f";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.cy.xlf";s:4:"role";s:3:"php";}}i:157;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"793dcd9686793b163ac089ce11e98f35";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.da.xlf";s:4:"role";s:3:"php";}}i:158;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7645ad8b8789c647baf9d713603dcc4e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.de.xlf";s:4:"role";s:3:"php";}}i:159;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"84e8b57b7cd181c41a9f2c609d9d2fcf";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.el.xlf";s:4:"role";s:3:"php";}}i:160;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f6b79a83f78a4d434657c2246bfa3299";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.en.xlf";s:4:"role";s:3:"php";}}i:161;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6d37d37db86c98e7c2c0058e8ca627d5";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.es.xlf";s:4:"role";s:3:"php";}}i:162;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"51f14210b3a9c9a53edaee7055d04e0e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.et.xlf";s:4:"role";s:3:"php";}}i:163;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2af5064bdebe03bb807ff16385d5d06e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.eu.xlf";s:4:"role";s:3:"php";}}i:164;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1e07a45e3288a48103d69c34ab9e61e6";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.fa.xlf";s:4:"role";s:3:"php";}}i:165;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"46b3152b9dd89f59e42e0e72844a12ec";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.fi.xlf";s:4:"role";s:3:"php";}}i:166;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47603272bbc1c04e050be6413d350d02";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.fr.xlf";s:4:"role";s:3:"php";}}i:167;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f86071db1ba3ea2ff60161e5cc8b5e71";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.gl.xlf";s:4:"role";s:3:"php";}}i:168;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"88b6ab9440768505c046b7ef1309dd2e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.he.xlf";s:4:"role";s:3:"php";}}i:169;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a37851b29fd856938b8029924661c408";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.hr.xlf";s:4:"role";s:3:"php";}}i:170;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0b4a4f159d4577d218cf405a8b69f48e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.hu.xlf";s:4:"role";s:3:"php";}}i:171;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"822214a574b126ce160d5caed2a08175";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.hy.xlf";s:4:"role";s:3:"php";}}i:172;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"72642d91259f21b72dd1bf1005ebac4e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.id.xlf";s:4:"role";s:3:"php";}}i:173;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"96673a4cfc1e20bf2417dff5f41093c3";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.it.xlf";s:4:"role";s:3:"php";}}i:174;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"26ce7bce56a82a9ae623a109bcb3c47d";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ja.xlf";s:4:"role";s:3:"php";}}i:175;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9c0e28952956db6812685e121ea2c010";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.lb.xlf";s:4:"role";s:3:"php";}}i:176;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8633947d9242120d0b273bedd0044c6b";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.lt.xlf";s:4:"role";s:3:"php";}}i:177;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5d6b61cab4e816991ff98ff64821dbc9";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.mn.xlf";s:4:"role";s:3:"php";}}i:178;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fc5bde0bb7a5dfafb1a061dd38dd335a";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.nb.xlf";s:4:"role";s:3:"php";}}i:179;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8620371a13ed6d660f8daafbefdf55a4";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.nl.xlf";s:4:"role";s:3:"php";}}i:180;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4a7aefa9d1b652a741d38936701a7bea";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.no.xlf";s:4:"role";s:3:"php";}}i:181;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"43cadc96e23d6bb270ccde1e20cd3940";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.pl.xlf";s:4:"role";s:3:"php";}}i:182;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"807707efabc65ad9992ff9b79531b1ec";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.pt.xlf";s:4:"role";s:3:"php";}}i:183;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86ef4e2fd4d0ca78e4aff92a496d6750";s:4:"name";s:71:"Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf";s:4:"role";s:3:"php";}}i:184;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"710b8a67f921af1756390e5c16732043";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ro.xlf";s:4:"role";s:3:"php";}}i:185;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"60f16b6952726dfd1f92d3764bad85a5";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ru.xlf";s:4:"role";s:3:"php";}}i:186;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fb5f5e62d477c3790fdba5fbc97fc238";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.sk.xlf";s:4:"role";s:3:"php";}}i:187;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e6a4af47341fa4c1b79e73b869df66b9";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.sl.xlf";s:4:"role";s:3:"php";}}i:188;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1f2fb26d0dd0131a51f36f7107c8bac2";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.sq.xlf";s:4:"role";s:3:"php";}}i:189;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8bc6bb4b4b0ff9d03446c0c0ffd49983";s:4:"name";s:73:"Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf";s:4:"role";s:3:"php";}}i:190;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"243a40ad3d4d74eed428066e6d6e7ef0";s:4:"name";s:73:"Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf";s:4:"role";s:3:"php";}}i:191;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ad1dd35b2ceccaa8a744ff08ebb1c759";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.sv.xlf";s:4:"role";s:3:"php";}}i:192;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a51133637a933c33aa1c7be7bc2c8f90";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.tr.xlf";s:4:"role";s:3:"php";}}i:193;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a4ec8b32ecc077c50c875fc46eec46b";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.uk.xlf";s:4:"role";s:3:"php";}}i:194;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"65930b6493ef965d3721753893c549b8";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.vi.xlf";s:4:"role";s:3:"php";}}i:195;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8ea9d18b4b8b0e0973d4461e4a4b31cf";s:4:"name";s:71:"Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf";s:4:"role";s:3:"php";}}i:196;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"336e3f4fcb54962d47342a9c58e80367";s:4:"name";s:71:"Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf";s:4:"role";s:3:"php";}}i:197;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df674acd306f8fa14a401b024b9bdc7f";s:4:"name";s:85:"Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php";s:4:"role";s:4:"test";}}i:198;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1179a8a955d42d44c8ed974c1819fb2e";s:4:"name";s:57:"Symfony/Component/Validator/Tests/Constraints/AllTest.php";s:4:"role";s:4:"test";}}i:199;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"96d4e47954bfb402594f16426d7d00ec";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.php";s:4:"role";s:4:"test";}}i:200;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b269201734d4f62ecf56991d0ca84714";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.php";s:4:"role";s:4:"test";}}i:201;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5b9313f897e13ecc42be33565e6a835";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php";s:4:"role";s:4:"test";}}i:202;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"43d071b4c94aa19cfd7c010958397284";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php";s:4:"role";s:4:"test";}}i:203;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e16564bb61b350db55712205e43c2ee7";s:4:"name";s:69:"Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php";s:4:"role";s:4:"test";}}i:204;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"71210b53ae36ca85b8cab158c1cdc5f3";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Constraints/CollectionTest.php";s:4:"role";s:4:"test";}}i:205;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0b20dac6c8b275500c652f1e9726f68e";s:4:"name";s:84:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php";s:4:"role";s:4:"test";}}i:206;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f860057334309da67249317f86faf070";s:4:"name";s:78:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.php";s:4:"role";s:4:"test";}}i:207;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"83079c79103474984cdabd95062b7d03";s:4:"name";s:90:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php";s:4:"role";s:4:"test";}}i:208;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"abb52acdf76b84de090fd27d778abc25";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php";s:4:"role";s:4:"test";}}i:209;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"088335785b72fe09bb08a78cb174a9b8";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php";s:4:"role";s:4:"test";}}i:210;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"81cfd6f9c23a49e571849bbf93242d45";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.php";s:4:"role";s:4:"test";}}i:211;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"31cd334579c8f399f099aaae60e0daf8";s:4:"name";s:77:"Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.php";s:4:"role";s:4:"test";}}i:212;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2baf2ba710f51a96efb9dfdf4e8e1b90";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php";s:4:"role";s:4:"test";}}i:213;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6f443701a1d6c8b3e6e56fb330da132e";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.php";s:4:"role";s:4:"test";}}i:214;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff807a49e3f2b98577ba78573388e54d";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php";s:4:"role";s:4:"test";}}i:215;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86f3b37b7d92d05b0f6e20b355d2612c";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php";s:4:"role";s:4:"test";}}i:216;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7a87cf58056325eae85ff00bf9a938ed";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php";s:4:"role";s:4:"test";}}i:217;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7893495310cce59b359b7b0b283dfc5c";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php";s:4:"role";s:4:"test";}}i:218;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8df8fad7f1e3f234cd3f70cfab62dd7c";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php";s:4:"role";s:4:"test";}}i:219;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"24905eea4858997f8247238e243632a8";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.php";s:4:"role";s:4:"test";}}i:220;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"89a984927585c53fe1032b9f636133ff";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.php";s:4:"role";s:4:"test";}}i:221;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8a4da84c8f7e8ef54b806bd808bcc0c5";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.php";s:4:"role";s:4:"test";}}i:222;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63c0fea7da6af037f5c07e530c4daba6";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php";s:4:"role";s:4:"test";}}i:223;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"583932c265a6b3fc7b64e3ce5781d982";s:4:"name";s:63:"Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gif";s:4:"role";s:4:"test";}}i:224;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fdcf796bda19a6af822251135ba90fc1";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gif";s:4:"role";s:4:"test";}}i:225;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0aeea019389321d9f37b03634b480bc3";s:4:"name";s:72:"Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gif";s:4:"role";s:4:"test";}}i:226;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7c9ea0cc06b77db6e3ad76e02dfb250f";s:4:"name";s:81:"Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php";s:4:"role";s:4:"test";}}i:227;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3c4700309337c186d07c5db8620a7f16";s:4:"name";s:74:"Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php";s:4:"role";s:4:"test";}}i:228;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"24a0a471799799b4dabe807fcb55eef4";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php";s:4:"role";s:4:"test";}}i:229;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"158ec986b80be1639be50889f6d1a755";s:4:"name";s:74:"Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php";s:4:"role";s:4:"test";}}i:230;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"78dec98020821252b9a0e1cdd237c9b8";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php";s:4:"role";s:4:"test";}}i:231;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b2b8bde3a236afaa56a0efc95040457b";s:4:"name";s:65:"Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php";s:4:"role";s:4:"test";}}i:232;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2e478a4e70021c8be50511adb544e17";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php";s:4:"role";s:4:"test";}}i:233;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e442a58274f84d70010c01704f2be5eb";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php";s:4:"role";s:4:"test";}}i:234;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c000845e88198140e3a2e265ae4b5682";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php";s:4:"role";s:4:"test";}}i:235;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cd2e05c3024174f384f7034838eaa1f5";s:4:"name";s:69:"Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php";s:4:"role";s:4:"test";}}i:236;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2f4d2435eefd4ba92994fbc4c725a203";s:4:"name";s:78:"Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php";s:4:"role";s:4:"test";}}i:237;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d82f8a856a9d95cd7a6d8fd6a0734981";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php";s:4:"role";s:4:"test";}}i:238;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3debe15a84780f2383a690dfbb867a1d";s:4:"name";s:69:"Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php";s:4:"role";s:4:"test";}}i:239;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8fff3ed85f1a0ea2f1414606d66031aa";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.php";s:4:"role";s:4:"test";}}i:240;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d26340b6b9e5ddf8d71968b27c288db2";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.php";s:4:"role";s:4:"test";}}i:241;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"002a50c1e4557d0b89860f47c279fc74";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php";s:4:"role";s:4:"test";}}i:242;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4ea56306c1dbab2f83e077512a59a769";s:4:"name";s:77:"Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php";s:4:"role";s:4:"test";}}i:243;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b3e3c45f358f75c450c27bcf9a046576";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php";s:4:"role";s:4:"test";}}i:244;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e8e343b9fb22cecd94a9a08b993d0c3a";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.php";s:4:"role";s:4:"test";}}i:245;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f02807065a8b9e4e578ec2e806cb9b81";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php";s:4:"role";s:4:"test";}}i:246;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"457e33f80230fd2eebaa65404aa0f085";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.php";s:4:"role";s:4:"test";}}i:247;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9943acc92b78efc760c440e0f8d94998";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php";s:4:"role";s:4:"test";}}i:248;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fe42e8bb7b68a0bb8aae4325746f2bf9";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.php";s:4:"role";s:4:"test";}}i:249;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"61b6a4967362f4ac3dcbecbdcbf11156";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.php";s:4:"role";s:4:"test";}}i:250;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c61759a19cd93a2d382d40ac2e689acd";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php";s:4:"role";s:4:"test";}}i:251;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2d93246dad9e589df5a83163e06fb877";s:4:"name";s:59:"Symfony/Component/Validator/Tests/Constraints/ValidTest.php";s:4:"role";s:4:"test";}}i:252;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"142a99b58afedf51b2c454fff02a65f3";s:4:"name";s:52:"Symfony/Component/Validator/Tests/ConstraintTest.php";s:4:"role";s:4:"test";}}i:253;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0584669a9a12dcadae796248aa9b42ff";s:4:"name";s:65:"Symfony/Component/Validator/Tests/ConstraintViolationListTest.php";s:4:"role";s:4:"test";}}i:254;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1319acdb0db4325c870ae4972e13efae";s:4:"name";s:61:"Symfony/Component/Validator/Tests/ConstraintViolationTest.php";s:4:"role";s:4:"test";}}i:255;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5aaa025907f20560822461a587c25457";s:4:"name";s:58:"Symfony/Component/Validator/Tests/ExecutionContextTest.php";s:4:"role";s:4:"test";}}i:256;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9454ace17fc81c19efac384cf4c50713";s:4:"name";s:60:"Symfony/Component/Validator/Tests/Fixtures/CallbackClass.php";s:4:"role";s:4:"test";}}i:257;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2ce3e43d62dc225654afccb6614717be";s:4:"name";s:62:"Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.php";s:4:"role";s:4:"test";}}i:258;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d4169102f57729661cb27febaab2d23f";s:4:"name";s:58:"Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php";s:4:"role";s:4:"test";}}i:259;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2c1daf935b4f95134c33129662adf08";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.php";s:4:"role";s:4:"test";}}i:260;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0157e96965ab4870f6965fbfa96a1612";s:4:"name";s:58:"Symfony/Component/Validator/Tests/Fixtures/ConstraintB.php";s:4:"role";s:4:"test";}}i:261;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8cd11e6488e0bce8f9c4de961754b500";s:4:"name";s:58:"Symfony/Component/Validator/Tests/Fixtures/ConstraintC.php";s:4:"role";s:4:"test";}}i:262;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2576db20cea1031e94f9b93ef5f9303a";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.php";s:4:"role";s:4:"test";}}i:263;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7763c0812a069714f24f431567726500";s:4:"name";s:75:"Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.php";s:4:"role";s:4:"test";}}i:264;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6b6e6d9a60b2254024c55566fe79b08f";s:4:"name";s:53:"Symfony/Component/Validator/Tests/Fixtures/Entity.php";s:4:"role";s:4:"test";}}i:265;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea31fab8aec5a8884f460f66daf7c993";s:4:"name";s:62:"Symfony/Component/Validator/Tests/Fixtures/EntityInterface.php";s:4:"role";s:4:"test";}}i:266;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a66c0953945928c193165c50757bcf04";s:4:"name";s:59:"Symfony/Component/Validator/Tests/Fixtures/EntityParent.php";s:4:"role";s:4:"test";}}i:267;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"72db5eaa66dc69f67e2d4ad5eb82b0e8";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.php";s:4:"role";s:4:"test";}}i:268;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c97e5a72d1d2befa96bea40821ec2c3a";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.php";s:4:"role";s:4:"test";}}i:269;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"edcb2a57ff4308821104e31a3ffd5167";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.php";s:4:"role";s:4:"test";}}i:270;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"068493fec3128c8cb2d29f6c5b0eaad0";s:4:"name";s:58:"Symfony/Component/Validator/Tests/Fixtures/FilesLoader.php";s:4:"role";s:4:"test";}}i:271;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ad8147295941a1cc399da4034cd61c49";s:4:"name";s:74:"Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.php";s:4:"role";s:4:"test";}}i:272;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ddb0895d24c9c089229b3b932538aabd";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.php";s:4:"role";s:4:"test";}}i:273;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5681169dbdca0c79b579401520a7173d";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.php";s:4:"role";s:4:"test";}}i:274;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fbc643d2960104a96a86a281f0d099bb";s:4:"name";s:65:"Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.php";s:4:"role";s:4:"test";}}i:275;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9d6e84977cc653a0673858a764ec39d6";s:4:"name";s:56:"Symfony/Component/Validator/Tests/Fixtures/Reference.php";s:4:"role";s:4:"test";}}i:276;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7353a9cae56c607794bee8094e41ffd4";s:4:"name";s:74:"Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.php";s:4:"role";s:4:"test";}}i:277;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d720776b21d7ce674a7365e5d2e38d2";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.php";s:4:"role";s:4:"test";}}i:278;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9fe738a4b6ba7f5105f2190fd449268e";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.php";s:4:"role";s:4:"test";}}i:279;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a4495fa7cfe81f702f45d66a7fca8617";s:4:"name";s:63:"Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php";s:4:"role";s:4:"test";}}i:280;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4384111241f1abc0445a06c539451f2a";s:4:"name";s:65:"Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.php";s:4:"role";s:4:"test";}}i:281;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d7f74984a4455152140bed27936361c0";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php";s:4:"role";s:4:"test";}}i:282;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0175b97f1eb69fcce94b306e900db362";s:4:"name";s:79:"Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.php";s:4:"role";s:4:"test";}}i:283;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"05410e4aaaf0a9a25ddc5c4134924390";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php";s:4:"role";s:4:"test";}}i:284;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c75233f90b5cfa4a398e1f9e543bf5bc";s:4:"name";s:83:"Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml";s:4:"role";s:4:"test";}}i:285;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"16ec478e3cf1b1bc1cab57aed6dadc6a";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml";s:4:"role";s:4:"test";}}i:286;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7643e62f12cd427f2b5fd1fa9a5f6133";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml";s:4:"role";s:4:"test";}}i:287;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.yml";s:4:"role";s:4:"test";}}i:288;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3bcfc4369f23356627bddd2555552d7f";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php";s:4:"role";s:4:"test";}}i:289;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e28f9bc1f67084ac7661410da1fceaed";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php";s:4:"role";s:4:"test";}}i:290;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d3b07384d113edec49eaa6238ad5ff00";s:4:"name";s:69:"Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.yml";s:4:"role";s:4:"test";}}i:291;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"561fb1c6e9ee5b4de0ab14129619af6f";s:4:"name";s:75:"Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php";s:4:"role";s:4:"test";}}i:292;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bf3a0038b2c219b56536ee96a18b5f7d";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xml";s:4:"role";s:4:"test";}}i:293;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fee7255c9f688a416d2fe1d34a1e3389";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php";s:4:"role";s:4:"test";}}i:294;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"adc321984d79e773e10da8b4a1d2cbd4";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php";s:4:"role";s:4:"test";}}i:295;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b60229644c0267c6db54c14164b8d4c6";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php";s:4:"role";s:4:"test";}}i:296;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"58769dbf877b4372cf5f4b418bee5d1a";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php";s:4:"role";s:4:"test";}}i:297;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4380de8196121010c2219a131015c0bd";s:4:"name";s:59:"Symfony/Component/Validator/Tests/ValidationVisitorTest.php";s:4:"role";s:4:"test";}}i:298;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b599d3d7e28f3c31dd64a8e4a461798";s:4:"name";s:58:"Symfony/Component/Validator/Tests/ValidatorBuilderTest.php";s:4:"role";s:4:"test";}}i:299;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c0d58093c8f48e173cf012832b5eff3d";s:4:"name";s:51:"Symfony/Component/Validator/Tests/ValidatorTest.php";s:4:"role";s:4:"test";}}i:300;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cb4be714363c679edca5adea512653db";s:4:"name";s:42:"Symfony/Component/Validator/Validation.php";s:4:"role";s:3:"php";}}i:301;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7c3d1976b86cb3bee62b80d06037a82c";s:4:"name";s:49:"Symfony/Component/Validator/ValidationVisitor.php";s:4:"role";s:3:"php";}}i:302;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d9246ccdbae1aac172f0b344b77a0a6c";s:4:"name";s:58:"Symfony/Component/Validator/ValidationVisitorInterface.php";s:4:"role";s:3:"php";}}i:303;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dab18aca325ae61509511a918442e133";s:4:"name";s:41:"Symfony/Component/Validator/Validator.php";s:4:"role";s:3:"php";}}i:304;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f3e3ae245a988856adea2ef86b30d27f";s:4:"name";s:48:"Symfony/Component/Validator/ValidatorBuilder.php";s:4:"role";s:3:"php";}}i:305;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f3528198e3b2790e1a7ffee686196923";s:4:"name";s:57:"Symfony/Component/Validator/ValidatorBuilderInterface.php";s:4:"role";s:3:"php";}}i:306;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7e994e15443d4bf79a747b6454bb5e76";s:4:"name";s:50:"Symfony/Component/Validator/ValidatorInterface.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}s:8:"optional";a:1:{s:7:"package";a:2:{i:0;a:2:{s:4:"name";s:4:"Yaml";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:14:"HttpFoundation";s:7:"channel";s:16:"pear.symfony.com";}}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:307:{s:42:"Symfony/Component/Validator/autoloader.php";a:4:{s:6:"md5sum";s:32:"70881b5188a71a54eaaa5174d35b8a7d";s:4:"name";s:42:"Symfony/Component/Validator/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/autoloader.php";}s:40:"Symfony/Component/Validator/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"460bbf634d57fb9eb81d53f051e8ab23";s:4:"name";s:40:"Symfony/Component/Validator/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/doc/pear/Validator/Symfony/Component/Validator/CHANGELOG.md";}s:51:"Symfony/Component/Validator/ClassBasedInterface.php";a:4:{s:6:"md5sum";s:32:"9b310a8a94f594586e92f197f9c2b271";s:4:"name";s:51:"Symfony/Component/Validator/ClassBasedInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ClassBasedInterface.php";}s:41:"Symfony/Component/Validator/composer.json";a:4:{s:6:"md5sum";s:32:"3af3b2a12af30fa1161d400c5fa160db";s:4:"name";s:41:"Symfony/Component/Validator/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/doc/pear/Validator/Symfony/Component/Validator/composer.json";}s:42:"Symfony/Component/Validator/Constraint.php";a:4:{s:6:"md5sum";s:32:"4673b9af925a35c9c4bed05edab5facb";s:4:"name";s:42:"Symfony/Component/Validator/Constraint.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraint.php";}s:62:"Symfony/Component/Validator/Constraints/AbstractComparison.php";a:4:{s:6:"md5sum";s:32:"8aa49d6a48f577e0f496ed051e1e3e35";s:4:"name";s:62:"Symfony/Component/Validator/Constraints/AbstractComparison.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/AbstractComparison.php";}s:71:"Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php";a:4:{s:6:"md5sum";s:32:"cd63ee91f580c33ed3e5027672c447cf";s:4:"name";s:71:"Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php";}s:47:"Symfony/Component/Validator/Constraints/All.php";a:4:{s:6:"md5sum";s:32:"81fa182a1f3260d61a45e0c9a886300a";s:4:"name";s:47:"Symfony/Component/Validator/Constraints/All.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/All.php";}s:56:"Symfony/Component/Validator/Constraints/AllValidator.php";a:4:{s:6:"md5sum";s:32:"76ee8f2dd2d0a1ff7329ddd7f4e812a8";s:4:"name";s:56:"Symfony/Component/Validator/Constraints/AllValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/AllValidator.php";}s:49:"Symfony/Component/Validator/Constraints/Blank.php";a:4:{s:6:"md5sum";s:32:"77b52c16bd1289663a73f66f39190eed";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Blank.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Blank.php";}s:58:"Symfony/Component/Validator/Constraints/BlankValidator.php";a:4:{s:6:"md5sum";s:32:"6bf52b86aeb6e4b7e762994e61b30656";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/BlankValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/BlankValidator.php";}s:52:"Symfony/Component/Validator/Constraints/Callback.php";a:4:{s:6:"md5sum";s:32:"16cf9f642a14848b9bc3ef3b883f19d1";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Callback.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Callback.php";}s:61:"Symfony/Component/Validator/Constraints/CallbackValidator.php";a:4:{s:6:"md5sum";s:32:"ad21e0f04423e82992c83f14e893779e";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/CallbackValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/CallbackValidator.php";}s:54:"Symfony/Component/Validator/Constraints/CardScheme.php";a:4:{s:6:"md5sum";s:32:"056ebff8baa348be8202ca6b297c4d01";s:4:"name";s:54:"Symfony/Component/Validator/Constraints/CardScheme.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/CardScheme.php";}s:63:"Symfony/Component/Validator/Constraints/CardSchemeValidator.php";a:4:{s:6:"md5sum";s:32:"284da971d7406e599a1233b2d2206376";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/CardSchemeValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/CardSchemeValidator.php";}s:50:"Symfony/Component/Validator/Constraints/Choice.php";a:4:{s:6:"md5sum";s:32:"49d0c082a54602ac483ce2afffb57431";s:4:"name";s:50:"Symfony/Component/Validator/Constraints/Choice.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Choice.php";}s:59:"Symfony/Component/Validator/Constraints/ChoiceValidator.php";a:4:{s:6:"md5sum";s:32:"c6988852a1c710e4832e4a0cf5f465ed";s:4:"name";s:59:"Symfony/Component/Validator/Constraints/ChoiceValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/ChoiceValidator.php";}s:63:"Symfony/Component/Validator/Constraints/Collection/Optional.php";a:4:{s:6:"md5sum";s:32:"09520f3d5eacb03f804fadf2d0afd2d2";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/Collection/Optional.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Collection/Optional.php";}s:63:"Symfony/Component/Validator/Constraints/Collection/Required.php";a:4:{s:6:"md5sum";s:32:"a084bfe09407f23250f410ed4c00c05f";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/Collection/Required.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Collection/Required.php";}s:54:"Symfony/Component/Validator/Constraints/Collection.php";a:4:{s:6:"md5sum";s:32:"5ca5192af79d7355af8a4017b671a8fb";s:4:"name";s:54:"Symfony/Component/Validator/Constraints/Collection.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Collection.php";}s:63:"Symfony/Component/Validator/Constraints/CollectionValidator.php";a:4:{s:6:"md5sum";s:32:"2a15094f63da567965053d81cec8b6bc";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/CollectionValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/CollectionValidator.php";}s:49:"Symfony/Component/Validator/Constraints/Count.php";a:4:{s:6:"md5sum";s:32:"d60afc2a00394329890f41050239d6be";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Count.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Count.php";}s:51:"Symfony/Component/Validator/Constraints/Country.php";a:4:{s:6:"md5sum";s:32:"8912e6648f1801a81237b64ad79beea8";s:4:"name";s:51:"Symfony/Component/Validator/Constraints/Country.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Country.php";}s:60:"Symfony/Component/Validator/Constraints/CountryValidator.php";a:4:{s:6:"md5sum";s:32:"5a7bd5263e9707dd6acab56907453cb4";s:4:"name";s:60:"Symfony/Component/Validator/Constraints/CountryValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/CountryValidator.php";}s:58:"Symfony/Component/Validator/Constraints/CountValidator.php";a:4:{s:6:"md5sum";s:32:"b63f576f4acf1cf05dd4a10b8dcdf613";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/CountValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/CountValidator.php";}s:52:"Symfony/Component/Validator/Constraints/Currency.php";a:4:{s:6:"md5sum";s:32:"dd7316794387746194d2d2fb42b7eb7f";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Currency.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Currency.php";}s:61:"Symfony/Component/Validator/Constraints/CurrencyValidator.php";a:4:{s:6:"md5sum";s:32:"9dfda60fe4dedc960dec518bcdf21a7f";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/CurrencyValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/CurrencyValidator.php";}s:48:"Symfony/Component/Validator/Constraints/Date.php";a:4:{s:6:"md5sum";s:32:"5e1a2350fefabcba23f44ced82b9e830";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Date.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Date.php";}s:52:"Symfony/Component/Validator/Constraints/DateTime.php";a:4:{s:6:"md5sum";s:32:"7146e3c517edfd501fdec3734e5a6f55";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/DateTime.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/DateTime.php";}s:61:"Symfony/Component/Validator/Constraints/DateTimeValidator.php";a:4:{s:6:"md5sum";s:32:"113eb18edd006507eb982c46d58fa85f";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/DateTimeValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/DateTimeValidator.php";}s:57:"Symfony/Component/Validator/Constraints/DateValidator.php";a:4:{s:6:"md5sum";s:32:"b2d3caa73ec728ede046f0358cf001a0";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/DateValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/DateValidator.php";}s:49:"Symfony/Component/Validator/Constraints/Email.php";a:4:{s:6:"md5sum";s:32:"3aa9b1e92fed777c1439d01d7eb6af23";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Email.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Email.php";}s:58:"Symfony/Component/Validator/Constraints/EmailValidator.php";a:4:{s:6:"md5sum";s:32:"01b056747cb908f564510334d5cf80fb";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/EmailValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/EmailValidator.php";}s:51:"Symfony/Component/Validator/Constraints/EqualTo.php";a:4:{s:6:"md5sum";s:32:"1203a215e52460149441441579253d47";s:4:"name";s:51:"Symfony/Component/Validator/Constraints/EqualTo.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/EqualTo.php";}s:60:"Symfony/Component/Validator/Constraints/EqualToValidator.php";a:4:{s:6:"md5sum";s:32:"85299aea76d2e9973c0a2a1f39796640";s:4:"name";s:60:"Symfony/Component/Validator/Constraints/EqualToValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/EqualToValidator.php";}s:53:"Symfony/Component/Validator/Constraints/Existence.php";a:4:{s:6:"md5sum";s:32:"5bf3ff6df741685faf77a3568bb8b633";s:4:"name";s:53:"Symfony/Component/Validator/Constraints/Existence.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Existence.php";}s:54:"Symfony/Component/Validator/Constraints/Expression.php";a:4:{s:6:"md5sum";s:32:"900f7ff58ceb2ae76007bb5a6394d921";s:4:"name";s:54:"Symfony/Component/Validator/Constraints/Expression.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Expression.php";}s:63:"Symfony/Component/Validator/Constraints/ExpressionValidator.php";a:4:{s:6:"md5sum";s:32:"3ede516fce7c1f487d08359ba11ae2ff";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/ExpressionValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/ExpressionValidator.php";}s:49:"Symfony/Component/Validator/Constraints/False.php";a:4:{s:6:"md5sum";s:32:"09d73194877b4dda8d4300f24e195013";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/False.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/False.php";}s:58:"Symfony/Component/Validator/Constraints/FalseValidator.php";a:4:{s:6:"md5sum";s:32:"79467bb4ee325740c202f9c8b97010a9";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/FalseValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/FalseValidator.php";}s:48:"Symfony/Component/Validator/Constraints/File.php";a:4:{s:6:"md5sum";s:32:"6e8e581ad9077fb13150682285df29b1";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/File.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/File.php";}s:57:"Symfony/Component/Validator/Constraints/FileValidator.php";a:4:{s:6:"md5sum";s:32:"d08c81702c68afd2c2757543f7d5193b";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/FileValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/FileValidator.php";}s:55:"Symfony/Component/Validator/Constraints/GreaterThan.php";a:4:{s:6:"md5sum";s:32:"79767d486e626e5c77b78bd7afe4aee9";s:4:"name";s:55:"Symfony/Component/Validator/Constraints/GreaterThan.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/GreaterThan.php";}s:62:"Symfony/Component/Validator/Constraints/GreaterThanOrEqual.php";a:4:{s:6:"md5sum";s:32:"ebb17f4ce792e12fecff1e9bb4b41e21";s:4:"name";s:62:"Symfony/Component/Validator/Constraints/GreaterThanOrEqual.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/GreaterThanOrEqual.php";}s:71:"Symfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.php";a:4:{s:6:"md5sum";s:32:"e4430a7d1c6f9f03c7a770ddda909d5f";s:4:"name";s:71:"Symfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.php";}s:64:"Symfony/Component/Validator/Constraints/GreaterThanValidator.php";a:4:{s:6:"md5sum";s:32:"2ff68d36a30ee563937565accdaf91e3";s:4:"name";s:64:"Symfony/Component/Validator/Constraints/GreaterThanValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/GreaterThanValidator.php";}s:57:"Symfony/Component/Validator/Constraints/GroupSequence.php";a:4:{s:6:"md5sum";s:32:"15201fe63d343b6b1e1a739fcaad8662";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/GroupSequence.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/GroupSequence.php";}s:65:"Symfony/Component/Validator/Constraints/GroupSequenceProvider.php";a:4:{s:6:"md5sum";s:32:"38089465890121217bdedbd833ee95e4";s:4:"name";s:65:"Symfony/Component/Validator/Constraints/GroupSequenceProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/GroupSequenceProvider.php";}s:48:"Symfony/Component/Validator/Constraints/Iban.php";a:4:{s:6:"md5sum";s:32:"3b6c69a9eb08622192d6af7a1f90bde3";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Iban.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Iban.php";}s:57:"Symfony/Component/Validator/Constraints/IbanValidator.php";a:4:{s:6:"md5sum";s:32:"767699246ea9dae9c99b112253ef0af0";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/IbanValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/IbanValidator.php";}s:55:"Symfony/Component/Validator/Constraints/IdenticalTo.php";a:4:{s:6:"md5sum";s:32:"c170ea25fe3922db43490b571011a438";s:4:"name";s:55:"Symfony/Component/Validator/Constraints/IdenticalTo.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/IdenticalTo.php";}s:64:"Symfony/Component/Validator/Constraints/IdenticalToValidator.php";a:4:{s:6:"md5sum";s:32:"56257e543ffc3632a272b284cd7ceeda";s:4:"name";s:64:"Symfony/Component/Validator/Constraints/IdenticalToValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/IdenticalToValidator.php";}s:49:"Symfony/Component/Validator/Constraints/Image.php";a:4:{s:6:"md5sum";s:32:"92f832be76aed1cfcd18d276ff45bce9";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Image.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Image.php";}s:58:"Symfony/Component/Validator/Constraints/ImageValidator.php";a:4:{s:6:"md5sum";s:32:"a95e09bb82ad891054f0680144487871";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/ImageValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/ImageValidator.php";}s:46:"Symfony/Component/Validator/Constraints/Ip.php";a:4:{s:6:"md5sum";s:32:"1ff307af5e1d02b5da016f7fd3c64816";s:4:"name";s:46:"Symfony/Component/Validator/Constraints/Ip.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Ip.php";}s:55:"Symfony/Component/Validator/Constraints/IpValidator.php";a:4:{s:6:"md5sum";s:32:"66c5af8b916684cf0c166c280cb00aa5";s:4:"name";s:55:"Symfony/Component/Validator/Constraints/IpValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/IpValidator.php";}s:48:"Symfony/Component/Validator/Constraints/Isbn.php";a:4:{s:6:"md5sum";s:32:"0eb759966852ddb84bd6b24c967040b7";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Isbn.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Isbn.php";}s:57:"Symfony/Component/Validator/Constraints/IsbnValidator.php";a:4:{s:6:"md5sum";s:32:"ff5b531b2a454c10fce5ae7c0894a22a";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/IsbnValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/IsbnValidator.php";}s:48:"Symfony/Component/Validator/Constraints/Issn.php";a:4:{s:6:"md5sum";s:32:"ee14ff1ba2ba521a7eb166ef651a1c75";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Issn.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Issn.php";}s:57:"Symfony/Component/Validator/Constraints/IssnValidator.php";a:4:{s:6:"md5sum";s:32:"93a39aba6f6a4f5a23ea91108425fa07";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/IssnValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/IssnValidator.php";}s:52:"Symfony/Component/Validator/Constraints/Language.php";a:4:{s:6:"md5sum";s:32:"5ba57bdea0848798ae8da31a78f1c072";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Language.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Language.php";}s:61:"Symfony/Component/Validator/Constraints/LanguageValidator.php";a:4:{s:6:"md5sum";s:32:"27e3692dbfe009a21c71f826e9ab7fe1";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/LanguageValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/LanguageValidator.php";}s:50:"Symfony/Component/Validator/Constraints/Length.php";a:4:{s:6:"md5sum";s:32:"1f0169f057954dec8280c2c4931b0a13";s:4:"name";s:50:"Symfony/Component/Validator/Constraints/Length.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Length.php";}s:59:"Symfony/Component/Validator/Constraints/LengthValidator.php";a:4:{s:6:"md5sum";s:32:"93de9c9c5ab7e3b8c19c671004a50ad4";s:4:"name";s:59:"Symfony/Component/Validator/Constraints/LengthValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/LengthValidator.php";}s:52:"Symfony/Component/Validator/Constraints/LessThan.php";a:4:{s:6:"md5sum";s:32:"eb6377f01e9cc6440dfa4e183ef8c4ab";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/LessThan.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/LessThan.php";}s:59:"Symfony/Component/Validator/Constraints/LessThanOrEqual.php";a:4:{s:6:"md5sum";s:32:"09d85d86e5798681d39dfe598df6c562";s:4:"name";s:59:"Symfony/Component/Validator/Constraints/LessThanOrEqual.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/LessThanOrEqual.php";}s:68:"Symfony/Component/Validator/Constraints/LessThanOrEqualValidator.php";a:4:{s:6:"md5sum";s:32:"564b53c3325126cc54ee9c14102b170a";s:4:"name";s:68:"Symfony/Component/Validator/Constraints/LessThanOrEqualValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/LessThanOrEqualValidator.php";}s:61:"Symfony/Component/Validator/Constraints/LessThanValidator.php";a:4:{s:6:"md5sum";s:32:"aa4623bfdf3d9d518660aeb634367252";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/LessThanValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/LessThanValidator.php";}s:50:"Symfony/Component/Validator/Constraints/Locale.php";a:4:{s:6:"md5sum";s:32:"de036e7a36b266c549985ededcb96344";s:4:"name";s:50:"Symfony/Component/Validator/Constraints/Locale.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Locale.php";}s:59:"Symfony/Component/Validator/Constraints/LocaleValidator.php";a:4:{s:6:"md5sum";s:32:"4b3b59f35f25cb78b8b25a266d405986";s:4:"name";s:59:"Symfony/Component/Validator/Constraints/LocaleValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/LocaleValidator.php";}s:48:"Symfony/Component/Validator/Constraints/Luhn.php";a:4:{s:6:"md5sum";s:32:"25dc43335a20b9a6e3b31b43a762e762";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Luhn.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Luhn.php";}s:57:"Symfony/Component/Validator/Constraints/LuhnValidator.php";a:4:{s:6:"md5sum";s:32:"f7360bdeef47916280c4e15ce1be91b1";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/LuhnValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/LuhnValidator.php";}s:52:"Symfony/Component/Validator/Constraints/NotBlank.php";a:4:{s:6:"md5sum";s:32:"868b62aca0723c3b457144aaf6c93a62";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/NotBlank.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/NotBlank.php";}s:61:"Symfony/Component/Validator/Constraints/NotBlankValidator.php";a:4:{s:6:"md5sum";s:32:"d095cf646d98ffc63c8404b87dc64c3a";s:4:"name";s:61:"Symfony/Component/Validator/Constraints/NotBlankValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/NotBlankValidator.php";}s:54:"Symfony/Component/Validator/Constraints/NotEqualTo.php";a:4:{s:6:"md5sum";s:32:"54a792ce51e206d9f1f342acf8de0ca6";s:4:"name";s:54:"Symfony/Component/Validator/Constraints/NotEqualTo.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/NotEqualTo.php";}s:63:"Symfony/Component/Validator/Constraints/NotEqualToValidator.php";a:4:{s:6:"md5sum";s:32:"ba17b4508a92681c1ecb989e31150989";s:4:"name";s:63:"Symfony/Component/Validator/Constraints/NotEqualToValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/NotEqualToValidator.php";}s:58:"Symfony/Component/Validator/Constraints/NotIdenticalTo.php";a:4:{s:6:"md5sum";s:32:"b0cf3bbae80822776f2ebe3853331da2";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/NotIdenticalTo.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/NotIdenticalTo.php";}s:67:"Symfony/Component/Validator/Constraints/NotIdenticalToValidator.php";a:4:{s:6:"md5sum";s:32:"3fb62be8d95c084095e2bb8354fa6cb2";s:4:"name";s:67:"Symfony/Component/Validator/Constraints/NotIdenticalToValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/NotIdenticalToValidator.php";}s:51:"Symfony/Component/Validator/Constraints/NotNull.php";a:4:{s:6:"md5sum";s:32:"1797b9ea7b21a35e5d2d1d68ca7fe157";s:4:"name";s:51:"Symfony/Component/Validator/Constraints/NotNull.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/NotNull.php";}s:60:"Symfony/Component/Validator/Constraints/NotNullValidator.php";a:4:{s:6:"md5sum";s:32:"d7a3af7c2064d4ff44733151eef7630d";s:4:"name";s:60:"Symfony/Component/Validator/Constraints/NotNullValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/NotNullValidator.php";}s:48:"Symfony/Component/Validator/Constraints/Null.php";a:4:{s:6:"md5sum";s:32:"1c8478dc05ca6a3af5499c59220d99b0";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Null.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Null.php";}s:57:"Symfony/Component/Validator/Constraints/NullValidator.php";a:4:{s:6:"md5sum";s:32:"412fc8b35206517d8c2844aec558d6f5";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/NullValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/NullValidator.php";}s:52:"Symfony/Component/Validator/Constraints/Optional.php";a:4:{s:6:"md5sum";s:32:"82b49cbb8deeed5086002af1d2e3d06f";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Optional.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Optional.php";}s:49:"Symfony/Component/Validator/Constraints/Range.php";a:4:{s:6:"md5sum";s:32:"1875728a92acf358891dc559c15127fa";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Range.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Range.php";}s:58:"Symfony/Component/Validator/Constraints/RangeValidator.php";a:4:{s:6:"md5sum";s:32:"5756018ef45c81919b3214d78b0e6eb4";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/RangeValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/RangeValidator.php";}s:49:"Symfony/Component/Validator/Constraints/Regex.php";a:4:{s:6:"md5sum";s:32:"f7a9e04cd4262d3f80fcbe70b9c4e806";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Regex.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Regex.php";}s:58:"Symfony/Component/Validator/Constraints/RegexValidator.php";a:4:{s:6:"md5sum";s:32:"ea6c897666cc7a6af2ff4d913f82a392";s:4:"name";s:58:"Symfony/Component/Validator/Constraints/RegexValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/RegexValidator.php";}s:52:"Symfony/Component/Validator/Constraints/Required.php";a:4:{s:6:"md5sum";s:32:"acbae820b5540dde9ec681dd85429861";s:4:"name";s:52:"Symfony/Component/Validator/Constraints/Required.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Required.php";}s:48:"Symfony/Component/Validator/Constraints/Time.php";a:4:{s:6:"md5sum";s:32:"67b70d9e097e05da71488e09b6e90b95";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Time.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Time.php";}s:57:"Symfony/Component/Validator/Constraints/TimeValidator.php";a:4:{s:6:"md5sum";s:32:"334dffc652e93fa5bd706116c9b44257";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/TimeValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/TimeValidator.php";}s:48:"Symfony/Component/Validator/Constraints/True.php";a:4:{s:6:"md5sum";s:32:"a78e9cd61bb76287a0522b1e5b7b392b";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/True.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/True.php";}s:57:"Symfony/Component/Validator/Constraints/TrueValidator.php";a:4:{s:6:"md5sum";s:32:"637d4488ec6112faf64aae361929d040";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/TrueValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/TrueValidator.php";}s:48:"Symfony/Component/Validator/Constraints/Type.php";a:4:{s:6:"md5sum";s:32:"d965c82e65e8289f8ecb88d83fc83de7";s:4:"name";s:48:"Symfony/Component/Validator/Constraints/Type.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Type.php";}s:57:"Symfony/Component/Validator/Constraints/TypeValidator.php";a:4:{s:6:"md5sum";s:32:"9f24a3872c47a60f1a990c9f199e14c2";s:4:"name";s:57:"Symfony/Component/Validator/Constraints/TypeValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/TypeValidator.php";}s:47:"Symfony/Component/Validator/Constraints/Url.php";a:4:{s:6:"md5sum";s:32:"ee711e399a3f093e7b3545692ebf7f62";s:4:"name";s:47:"Symfony/Component/Validator/Constraints/Url.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Url.php";}s:56:"Symfony/Component/Validator/Constraints/UrlValidator.php";a:4:{s:6:"md5sum";s:32:"38d0b621d809fc73a63e73c9b2eec6f0";s:4:"name";s:56:"Symfony/Component/Validator/Constraints/UrlValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/UrlValidator.php";}s:49:"Symfony/Component/Validator/Constraints/Valid.php";a:4:{s:6:"md5sum";s:32:"1bb212699fe8609180681b51be678cd4";s:4:"name";s:49:"Symfony/Component/Validator/Constraints/Valid.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Valid.php";}s:51:"Symfony/Component/Validator/ConstraintValidator.php";a:4:{s:6:"md5sum";s:32:"d599a1ef98a59cddd0952a2217e6a61a";s:4:"name";s:51:"Symfony/Component/Validator/ConstraintValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ConstraintValidator.php";}s:58:"Symfony/Component/Validator/ConstraintValidatorFactory.php";a:4:{s:6:"md5sum";s:32:"1dc05c3449f8ee63549a2672f762c635";s:4:"name";s:58:"Symfony/Component/Validator/ConstraintValidatorFactory.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ConstraintValidatorFactory.php";}s:67:"Symfony/Component/Validator/ConstraintValidatorFactoryInterface.php";a:4:{s:6:"md5sum";s:32:"f322ea75c86e7e0fe44bf0e55b45522e";s:4:"name";s:67:"Symfony/Component/Validator/ConstraintValidatorFactoryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ConstraintValidatorFactoryInterface.php";}s:60:"Symfony/Component/Validator/ConstraintValidatorInterface.php";a:4:{s:6:"md5sum";s:32:"62e34e25daf9b43c27cd8111b2c10ede";s:4:"name";s:60:"Symfony/Component/Validator/ConstraintValidatorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ConstraintValidatorInterface.php";}s:51:"Symfony/Component/Validator/ConstraintViolation.php";a:4:{s:6:"md5sum";s:32:"687daad19e5f43350617c063490aa100";s:4:"name";s:51:"Symfony/Component/Validator/ConstraintViolation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ConstraintViolation.php";}s:60:"Symfony/Component/Validator/ConstraintViolationInterface.php";a:4:{s:6:"md5sum";s:32:"ef89d7f0cbae45ed31aa8a72fc13487d";s:4:"name";s:60:"Symfony/Component/Validator/ConstraintViolationInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ConstraintViolationInterface.php";}s:55:"Symfony/Component/Validator/ConstraintViolationList.php";a:4:{s:6:"md5sum";s:32:"c2c8b4b7b53a10d1f269c2ce53c7e901";s:4:"name";s:55:"Symfony/Component/Validator/ConstraintViolationList.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ConstraintViolationList.php";}s:64:"Symfony/Component/Validator/ConstraintViolationListInterface.php";a:4:{s:6:"md5sum";s:32:"36c862c3c9a1e8e797fe4b6ef4c91546";s:4:"name";s:64:"Symfony/Component/Validator/ConstraintViolationListInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ConstraintViolationListInterface.php";}s:49:"Symfony/Component/Validator/DefaultTranslator.php";a:4:{s:6:"md5sum";s:32:"4be17f7858f92496b9d0527bcd7cd720";s:4:"name";s:49:"Symfony/Component/Validator/DefaultTranslator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/DefaultTranslator.php";}s:64:"Symfony/Component/Validator/Exception/BadMethodCallException.php";a:4:{s:6:"md5sum";s:32:"e1602d2dcf95a9052da9a432db6c1875";s:4:"name";s:64:"Symfony/Component/Validator/Exception/BadMethodCallException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/BadMethodCallException.php";}s:71:"Symfony/Component/Validator/Exception/ConstraintDefinitionException.php";a:4:{s:6:"md5sum";s:32:"5fcc0f865c77f52e9847378da9f0489c";s:4:"name";s:71:"Symfony/Component/Validator/Exception/ConstraintDefinitionException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/ConstraintDefinitionException.php";}s:60:"Symfony/Component/Validator/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"0b0c94ce85588dd563f8767426eafdcc";s:4:"name";s:60:"Symfony/Component/Validator/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/ExceptionInterface.php";}s:66:"Symfony/Component/Validator/Exception/GroupDefinitionException.php";a:4:{s:6:"md5sum";s:32:"ed9aa39f207cff711cb5c8fc86114395";s:4:"name";s:66:"Symfony/Component/Validator/Exception/GroupDefinitionException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/GroupDefinitionException.php";}s:66:"Symfony/Component/Validator/Exception/InvalidArgumentException.php";a:4:{s:6:"md5sum";s:32:"bd79de35ad0e084b8400e08793205a69";s:4:"name";s:66:"Symfony/Component/Validator/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/InvalidArgumentException.php";}s:65:"Symfony/Component/Validator/Exception/InvalidOptionsException.php";a:4:{s:6:"md5sum";s:32:"7dcead75d21f8d0a56980c4a07d7aca4";s:4:"name";s:65:"Symfony/Component/Validator/Exception/InvalidOptionsException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/InvalidOptionsException.php";}s:58:"Symfony/Component/Validator/Exception/MappingException.php";a:4:{s:6:"md5sum";s:32:"9f68ce5c519e7ae740485b54d04e1d51";s:4:"name";s:58:"Symfony/Component/Validator/Exception/MappingException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/MappingException.php";}s:65:"Symfony/Component/Validator/Exception/MissingOptionsException.php";a:4:{s:6:"md5sum";s:32:"b53533773e89efd08b4e8fee6b186579";s:4:"name";s:65:"Symfony/Component/Validator/Exception/MissingOptionsException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/MissingOptionsException.php";}s:65:"Symfony/Component/Validator/Exception/NoSuchMetadataException.php";a:4:{s:6:"md5sum";s:32:"e9bea930f7bceee8d7dde50dd85e9ba7";s:4:"name";s:65:"Symfony/Component/Validator/Exception/NoSuchMetadataException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/NoSuchMetadataException.php";}s:58:"Symfony/Component/Validator/Exception/RuntimeException.php";a:4:{s:6:"md5sum";s:32:"99d749d07f412b89d5af760e96666226";s:4:"name";s:58:"Symfony/Component/Validator/Exception/RuntimeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/RuntimeException.php";}s:65:"Symfony/Component/Validator/Exception/UnexpectedTypeException.php";a:4:{s:6:"md5sum";s:32:"49ee74315300fe571873b44bdd13e171";s:4:"name";s:65:"Symfony/Component/Validator/Exception/UnexpectedTypeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/UnexpectedTypeException.php";}s:60:"Symfony/Component/Validator/Exception/ValidatorException.php";a:4:{s:6:"md5sum";s:32:"a0a8b64183db5f06140fbe08503efdaf";s:4:"name";s:60:"Symfony/Component/Validator/Exception/ValidatorException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception/ValidatorException.php";}s:48:"Symfony/Component/Validator/ExecutionContext.php";a:4:{s:6:"md5sum";s:32:"915a47ef778253a6c7a1e2a2528aa996";s:4:"name";s:48:"Symfony/Component/Validator/ExecutionContext.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ExecutionContext.php";}s:57:"Symfony/Component/Validator/ExecutionContextInterface.php";a:4:{s:6:"md5sum";s:32:"676e8179bba9e6d350680ef1ea759b9e";s:4:"name";s:57:"Symfony/Component/Validator/ExecutionContextInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ExecutionContextInterface.php";}s:63:"Symfony/Component/Validator/GlobalExecutionContextInterface.php";a:4:{s:6:"md5sum";s:32:"ca92e46f393618f0efc6954ca2466939";s:4:"name";s:63:"Symfony/Component/Validator/GlobalExecutionContextInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/GlobalExecutionContextInterface.php";}s:62:"Symfony/Component/Validator/GroupSequenceProviderInterface.php";a:4:{s:6:"md5sum";s:32:"381af269f7e5fb28e87a5c81a3707621";s:4:"name";s:62:"Symfony/Component/Validator/GroupSequenceProviderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/GroupSequenceProviderInterface.php";}s:35:"Symfony/Component/Validator/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:35:"Symfony/Component/Validator/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/doc/pear/Validator/Symfony/Component/Validator/LICENSE";}s:64:"Symfony/Component/Validator/Mapping/BlackholeMetadataFactory.php";a:4:{s:6:"md5sum";s:32:"4ff2d258e293c0d3347a56678051e8d3";s:4:"name";s:64:"Symfony/Component/Validator/Mapping/BlackholeMetadataFactory.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/BlackholeMetadataFactory.php";}s:54:"Symfony/Component/Validator/Mapping/Cache/ApcCache.php";a:4:{s:6:"md5sum";s:32:"462497cd0cf5d29d523b5a0d75b81ca0";s:4:"name";s:54:"Symfony/Component/Validator/Mapping/Cache/ApcCache.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Cache/ApcCache.php";}s:60:"Symfony/Component/Validator/Mapping/Cache/CacheInterface.php";a:4:{s:6:"md5sum";s:32:"8a7b01dab83206f30d02ceb5ccc8c171";s:4:"name";s:60:"Symfony/Component/Validator/Mapping/Cache/CacheInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Cache/CacheInterface.php";}s:53:"Symfony/Component/Validator/Mapping/ClassMetadata.php";a:4:{s:6:"md5sum";s:32:"b7ce80520c8d175471f396247948cdc3";s:4:"name";s:53:"Symfony/Component/Validator/Mapping/ClassMetadata.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/ClassMetadata.php";}s:60:"Symfony/Component/Validator/Mapping/ClassMetadataFactory.php";a:4:{s:6:"md5sum";s:32:"b708c68549204312c540ee7dacb9ad87";s:4:"name";s:60:"Symfony/Component/Validator/Mapping/ClassMetadataFactory.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/ClassMetadataFactory.php";}s:55:"Symfony/Component/Validator/Mapping/ElementMetadata.php";a:4:{s:6:"md5sum";s:32:"6d8a4315440eca7b33bee8a2c2df3cf0";s:4:"name";s:55:"Symfony/Component/Validator/Mapping/ElementMetadata.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/ElementMetadata.php";}s:54:"Symfony/Component/Validator/Mapping/GetterMetadata.php";a:4:{s:6:"md5sum";s:32:"66734470bd1916de0ca3f01784364005";s:4:"name";s:54:"Symfony/Component/Validator/Mapping/GetterMetadata.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/GetterMetadata.php";}s:61:"Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php";a:4:{s:6:"md5sum";s:32:"4aafbfbbc0d5d5430ee20aff7da60f5c";s:4:"name";s:61:"Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php";}s:63:"Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php";a:4:{s:6:"md5sum";s:32:"8ad79406bc548394a200e712dee0c30f";s:4:"name";s:63:"Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php";}s:57:"Symfony/Component/Validator/Mapping/Loader/FileLoader.php";a:4:{s:6:"md5sum";s:32:"9b4a61c8b30fae02788429854ba81036";s:4:"name";s:57:"Symfony/Component/Validator/Mapping/Loader/FileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/FileLoader.php";}s:58:"Symfony/Component/Validator/Mapping/Loader/FilesLoader.php";a:4:{s:6:"md5sum";s:32:"4af7f07bfcfa849e66999ab1ee24f876";s:4:"name";s:58:"Symfony/Component/Validator/Mapping/Loader/FilesLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/FilesLoader.php";}s:58:"Symfony/Component/Validator/Mapping/Loader/LoaderChain.php";a:4:{s:6:"md5sum";s:32:"8b284df5873ac5725b5c4705b69d530b";s:4:"name";s:58:"Symfony/Component/Validator/Mapping/Loader/LoaderChain.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/LoaderChain.php";}s:62:"Symfony/Component/Validator/Mapping/Loader/LoaderInterface.php";a:4:{s:6:"md5sum";s:32:"d202e225a6b817c2829e10f98d04abdd";s:4:"name";s:62:"Symfony/Component/Validator/Mapping/Loader/LoaderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/LoaderInterface.php";}s:99:"Symfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd";a:4:{s:6:"md5sum";s:32:"2f1f4e105fe3d987790a62d0a36ace39";s:4:"name";s:99:"Symfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd";s:4:"role";s:3:"php";s:12:"installed_as";s:129:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd";}s:65:"Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php";a:4:{s:6:"md5sum";s:32:"1005146f217d0bcdaabe67f3c3e9c225";s:4:"name";s:65:"Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php";}s:60:"Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php";a:4:{s:6:"md5sum";s:32:"c8d1f2225f940f29028386fe2fbbfe7a";s:4:"name";s:60:"Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php";}s:61:"Symfony/Component/Validator/Mapping/Loader/XmlFilesLoader.php";a:4:{s:6:"md5sum";s:32:"31fdec6936f6c041c6c9d4a3d3cec86e";s:4:"name";s:61:"Symfony/Component/Validator/Mapping/Loader/XmlFilesLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/XmlFilesLoader.php";}s:61:"Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php";a:4:{s:6:"md5sum";s:32:"a712b89ff6fe80354296a3b399c6139f";s:4:"name";s:61:"Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php";}s:62:"Symfony/Component/Validator/Mapping/Loader/YamlFilesLoader.php";a:4:{s:6:"md5sum";s:32:"8db3ad3b587098ac95ad6d25317c2e9c";s:4:"name";s:62:"Symfony/Component/Validator/Mapping/Loader/YamlFilesLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/YamlFilesLoader.php";}s:54:"Symfony/Component/Validator/Mapping/MemberMetadata.php";a:4:{s:6:"md5sum";s:32:"8c45e691d8e03b05b3a893e3acdb5a0f";s:4:"name";s:54:"Symfony/Component/Validator/Mapping/MemberMetadata.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/MemberMetadata.php";}s:56:"Symfony/Component/Validator/Mapping/PropertyMetadata.php";a:4:{s:6:"md5sum";s:32:"f44bb51a8950d588ae2dd0ab7bf17a1f";s:4:"name";s:56:"Symfony/Component/Validator/Mapping/PropertyMetadata.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/PropertyMetadata.php";}s:56:"Symfony/Component/Validator/MetadataFactoryInterface.php";a:4:{s:6:"md5sum";s:32:"4db44d9e04ab20b9b5757aaac84e4aa7";s:4:"name";s:56:"Symfony/Component/Validator/MetadataFactoryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/MetadataFactoryInterface.php";}s:49:"Symfony/Component/Validator/MetadataInterface.php";a:4:{s:6:"md5sum";s:32:"ee339e11db2658139a134c3824c8afd7";s:4:"name";s:49:"Symfony/Component/Validator/MetadataInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/MetadataInterface.php";}s:58:"Symfony/Component/Validator/ObjectInitializerInterface.php";a:4:{s:6:"md5sum";s:32:"00b9e5fab71633739ff82314900aa9c9";s:4:"name";s:58:"Symfony/Component/Validator/ObjectInitializerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ObjectInitializerInterface.php";}s:44:"Symfony/Component/Validator/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"78843eae0d52d5f5909f1087a44295b7";s:4:"name";s:44:"Symfony/Component/Validator/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/phpunit.xml.dist";}s:66:"Symfony/Component/Validator/PropertyMetadataContainerInterface.php";a:4:{s:6:"md5sum";s:32:"6e7e28f7b1ff78536561fcda9521b4dc";s:4:"name";s:66:"Symfony/Component/Validator/PropertyMetadataContainerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/PropertyMetadataContainerInterface.php";}s:57:"Symfony/Component/Validator/PropertyMetadataInterface.php";a:4:{s:6:"md5sum";s:32:"f6c682d20098aac0b0502374eaa79df1";s:4:"name";s:57:"Symfony/Component/Validator/PropertyMetadataInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/PropertyMetadataInterface.php";}s:37:"Symfony/Component/Validator/README.md";a:4:{s:6:"md5sum";s:32:"909b0bb88dcdb6cdee5dce42ec11e0d8";s:4:"name";s:37:"Symfony/Component/Validator/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/Validator/Symfony/Component/Validator/README.md";}s:68:"Symfony/Component/Validator/Resources/translations/validators.af.xlf";a:4:{s:6:"md5sum";s:32:"c23dd67e56958cc57e1147fce770d730";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.af.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.af.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.ar.xlf";a:4:{s:6:"md5sum";s:32:"2a03a4464216db4d71c91a1fd5f0c696";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ar.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.ar.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.bg.xlf";a:4:{s:6:"md5sum";s:32:"d4011977e7d9fed5e3c57c9b5e09077e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.bg.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.bg.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.ca.xlf";a:4:{s:6:"md5sum";s:32:"a17496bce86c96c7d447a148b2d29e8a";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ca.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.ca.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.cs.xlf";a:4:{s:6:"md5sum";s:32:"bbda69a9cc105df6d0e915e93ea4de6d";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.cs.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.cs.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.cy.xlf";a:4:{s:6:"md5sum";s:32:"117e80d2ecc0ed11fe07dcef7d023d3f";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.cy.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.cy.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.da.xlf";a:4:{s:6:"md5sum";s:32:"793dcd9686793b163ac089ce11e98f35";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.da.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.da.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.de.xlf";a:4:{s:6:"md5sum";s:32:"7645ad8b8789c647baf9d713603dcc4e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.de.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.de.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.el.xlf";a:4:{s:6:"md5sum";s:32:"84e8b57b7cd181c41a9f2c609d9d2fcf";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.el.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.el.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.en.xlf";a:4:{s:6:"md5sum";s:32:"f6b79a83f78a4d434657c2246bfa3299";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.en.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.en.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.es.xlf";a:4:{s:6:"md5sum";s:32:"6d37d37db86c98e7c2c0058e8ca627d5";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.es.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.es.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.et.xlf";a:4:{s:6:"md5sum";s:32:"51f14210b3a9c9a53edaee7055d04e0e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.et.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.et.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.eu.xlf";a:4:{s:6:"md5sum";s:32:"2af5064bdebe03bb807ff16385d5d06e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.eu.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.eu.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.fa.xlf";a:4:{s:6:"md5sum";s:32:"1e07a45e3288a48103d69c34ab9e61e6";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.fa.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.fa.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.fi.xlf";a:4:{s:6:"md5sum";s:32:"46b3152b9dd89f59e42e0e72844a12ec";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.fi.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.fi.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.fr.xlf";a:4:{s:6:"md5sum";s:32:"47603272bbc1c04e050be6413d350d02";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.fr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.fr.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.gl.xlf";a:4:{s:6:"md5sum";s:32:"f86071db1ba3ea2ff60161e5cc8b5e71";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.gl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.gl.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.he.xlf";a:4:{s:6:"md5sum";s:32:"88b6ab9440768505c046b7ef1309dd2e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.he.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.he.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.hr.xlf";a:4:{s:6:"md5sum";s:32:"a37851b29fd856938b8029924661c408";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.hr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.hr.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.hu.xlf";a:4:{s:6:"md5sum";s:32:"0b4a4f159d4577d218cf405a8b69f48e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.hu.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.hu.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.hy.xlf";a:4:{s:6:"md5sum";s:32:"822214a574b126ce160d5caed2a08175";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.hy.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.hy.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.id.xlf";a:4:{s:6:"md5sum";s:32:"72642d91259f21b72dd1bf1005ebac4e";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.id.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.id.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.it.xlf";a:4:{s:6:"md5sum";s:32:"96673a4cfc1e20bf2417dff5f41093c3";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.it.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.it.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.ja.xlf";a:4:{s:6:"md5sum";s:32:"26ce7bce56a82a9ae623a109bcb3c47d";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ja.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.ja.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.lb.xlf";a:4:{s:6:"md5sum";s:32:"9c0e28952956db6812685e121ea2c010";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.lb.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.lb.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.lt.xlf";a:4:{s:6:"md5sum";s:32:"8633947d9242120d0b273bedd0044c6b";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.lt.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.lt.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.mn.xlf";a:4:{s:6:"md5sum";s:32:"5d6b61cab4e816991ff98ff64821dbc9";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.mn.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.mn.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.nb.xlf";a:4:{s:6:"md5sum";s:32:"fc5bde0bb7a5dfafb1a061dd38dd335a";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.nb.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.nb.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.nl.xlf";a:4:{s:6:"md5sum";s:32:"8620371a13ed6d660f8daafbefdf55a4";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.nl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.nl.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.no.xlf";a:4:{s:6:"md5sum";s:32:"4a7aefa9d1b652a741d38936701a7bea";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.no.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.no.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.pl.xlf";a:4:{s:6:"md5sum";s:32:"43cadc96e23d6bb270ccde1e20cd3940";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.pl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.pl.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.pt.xlf";a:4:{s:6:"md5sum";s:32:"807707efabc65ad9992ff9b79531b1ec";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.pt.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.pt.xlf";}s:71:"Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf";a:4:{s:6:"md5sum";s:32:"86ef4e2fd4d0ca78e4aff92a496d6750";s:4:"name";s:71:"Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.ro.xlf";a:4:{s:6:"md5sum";s:32:"710b8a67f921af1756390e5c16732043";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ro.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.ro.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.ru.xlf";a:4:{s:6:"md5sum";s:32:"60f16b6952726dfd1f92d3764bad85a5";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.ru.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.ru.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.sk.xlf";a:4:{s:6:"md5sum";s:32:"fb5f5e62d477c3790fdba5fbc97fc238";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.sk.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.sk.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.sl.xlf";a:4:{s:6:"md5sum";s:32:"e6a4af47341fa4c1b79e73b869df66b9";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.sl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.sl.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.sq.xlf";a:4:{s:6:"md5sum";s:32:"1f2fb26d0dd0131a51f36f7107c8bac2";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.sq.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.sq.xlf";}s:73:"Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf";a:4:{s:6:"md5sum";s:32:"8bc6bb4b4b0ff9d03446c0c0ffd49983";s:4:"name";s:73:"Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf";}s:73:"Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf";a:4:{s:6:"md5sum";s:32:"243a40ad3d4d74eed428066e6d6e7ef0";s:4:"name";s:73:"Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.sv.xlf";a:4:{s:6:"md5sum";s:32:"ad1dd35b2ceccaa8a744ff08ebb1c759";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.sv.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.sv.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.tr.xlf";a:4:{s:6:"md5sum";s:32:"a51133637a933c33aa1c7be7bc2c8f90";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.tr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.tr.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.uk.xlf";a:4:{s:6:"md5sum";s:32:"3a4ec8b32ecc077c50c875fc46eec46b";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.uk.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.uk.xlf";}s:68:"Symfony/Component/Validator/Resources/translations/validators.vi.xlf";a:4:{s:6:"md5sum";s:32:"65930b6493ef965d3721753893c549b8";s:4:"name";s:68:"Symfony/Component/Validator/Resources/translations/validators.vi.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.vi.xlf";}s:71:"Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf";a:4:{s:6:"md5sum";s:32:"8ea9d18b4b8b0e0973d4461e4a4b31cf";s:4:"name";s:71:"Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf";}s:71:"Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf";a:4:{s:6:"md5sum";s:32:"336e3f4fcb54962d47342a9c58e80367";s:4:"name";s:71:"Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf";}s:85:"Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php";a:4:{s:6:"md5sum";s:32:"df674acd306f8fa14a401b024b9bdc7f";s:4:"name";s:85:"Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php";}s:57:"Symfony/Component/Validator/Tests/Constraints/AllTest.php";a:4:{s:6:"md5sum";s:32:"1179a8a955d42d44c8ed974c1819fb2e";s:4:"name";s:57:"Symfony/Component/Validator/Tests/Constraints/AllTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/AllTest.php";}s:66:"Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.php";a:4:{s:6:"md5sum";s:32:"96d4e47954bfb402594f16426d7d00ec";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.php";}s:68:"Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.php";a:4:{s:6:"md5sum";s:32:"b269201734d4f62ecf56991d0ca84714";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.php";}s:71:"Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php";a:4:{s:6:"md5sum";s:32:"d5b9313f897e13ecc42be33565e6a835";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php";}s:73:"Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php";a:4:{s:6:"md5sum";s:32:"43d071b4c94aa19cfd7c010958397284";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php";}s:69:"Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php";a:4:{s:6:"md5sum";s:32:"e16564bb61b350db55712205e43c2ee7";s:4:"name";s:69:"Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php";}s:64:"Symfony/Component/Validator/Tests/Constraints/CollectionTest.php";a:4:{s:6:"md5sum";s:32:"71210b53ae36ca85b8cab158c1cdc5f3";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Constraints/CollectionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php";}s:84:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php";a:4:{s:6:"md5sum";s:32:"0b20dac6c8b275500c652f1e9726f68e";s:4:"name";s:84:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:129:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php";}s:78:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.php";a:4:{s:6:"md5sum";s:32:"f860057334309da67249317f86faf070";s:4:"name";s:78:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.php";}s:90:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php";a:4:{s:6:"md5sum";s:32:"83079c79103474984cdabd95062b7d03";s:4:"name";s:90:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php";}s:73:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php";a:4:{s:6:"md5sum";s:32:"abb52acdf76b84de090fd27d778abc25";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php";}s:70:"Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php";a:4:{s:6:"md5sum";s:32:"088335785b72fe09bb08a78cb174a9b8";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php";}s:73:"Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.php";a:4:{s:6:"md5sum";s:32:"81cfd6f9c23a49e571849bbf93242d45";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.php";}s:77:"Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.php";a:4:{s:6:"md5sum";s:32:"31cd334579c8f399f099aaae60e0daf8";s:4:"name";s:77:"Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.php";}s:68:"Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php";a:4:{s:6:"md5sum";s:32:"2baf2ba710f51a96efb9dfdf4e8e1b90";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php";}s:71:"Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.php";a:4:{s:6:"md5sum";s:32:"6f443701a1d6c8b3e6e56fb330da132e";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.php";}s:71:"Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php";a:4:{s:6:"md5sum";s:32:"ff807a49e3f2b98577ba78573388e54d";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php";a:4:{s:6:"md5sum";s:32:"86f3b37b7d92d05b0f6e20b355d2612c";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php";}s:68:"Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php";a:4:{s:6:"md5sum";s:32:"7a87cf58056325eae85ff00bf9a938ed";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php";}s:70:"Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php";a:4:{s:6:"md5sum";s:32:"7893495310cce59b359b7b0b283dfc5c";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php";}s:73:"Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php";a:4:{s:6:"md5sum";s:32:"8df8fad7f1e3f234cd3f70cfab62dd7c";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php";}s:68:"Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.php";a:4:{s:6:"md5sum";s:32:"24905eea4858997f8247238e243632a8";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.php";}s:73:"Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.php";a:4:{s:6:"md5sum";s:32:"89a984927585c53fe1032b9f636133ff";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.php";}s:71:"Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.php";a:4:{s:6:"md5sum";s:32:"8a4da84c8f7e8ef54b806bd808bcc0c5";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php";a:4:{s:6:"md5sum";s:32:"63c0fea7da6af037f5c07e530c4daba6";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php";}s:63:"Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gif";a:4:{s:6:"md5sum";s:32:"583932c265a6b3fc7b64e3ce5781d982";s:4:"name";s:63:"Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gif";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gif";}s:73:"Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gif";a:4:{s:6:"md5sum";s:32:"fdcf796bda19a6af822251135ba90fc1";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gif";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gif";}s:72:"Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gif";a:4:{s:6:"md5sum";s:32:"0aeea019389321d9f37b03634b480bc3";s:4:"name";s:72:"Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gif";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gif";}s:81:"Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php";a:4:{s:6:"md5sum";s:32:"7c9ea0cc06b77db6e3ad76e02dfb250f";s:4:"name";s:81:"Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php";}s:74:"Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php";a:4:{s:6:"md5sum";s:32:"3c4700309337c186d07c5db8620a7f16";s:4:"name";s:74:"Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php";a:4:{s:6:"md5sum";s:32:"24a0a471799799b4dabe807fcb55eef4";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php";}s:74:"Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php";a:4:{s:6:"md5sum";s:32:"158ec986b80be1639be50889f6d1a755";s:4:"name";s:74:"Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php";}s:68:"Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php";a:4:{s:6:"md5sum";s:32:"78dec98020821252b9a0e1cdd237c9b8";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php";}s:65:"Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php";a:4:{s:6:"md5sum";s:32:"b2b8bde3a236afaa56a0efc95040457b";s:4:"name";s:65:"Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php";a:4:{s:6:"md5sum";s:32:"e2e478a4e70021c8be50511adb544e17";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php";a:4:{s:6:"md5sum";s:32:"e442a58274f84d70010c01704f2be5eb";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php";}s:71:"Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php";a:4:{s:6:"md5sum";s:32:"c000845e88198140e3a2e265ae4b5682";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php";}s:69:"Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php";a:4:{s:6:"md5sum";s:32:"cd2e05c3024174f384f7034838eaa1f5";s:4:"name";s:69:"Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php";}s:78:"Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php";a:4:{s:6:"md5sum";s:32:"2f4d2435eefd4ba92994fbc4c725a203";s:4:"name";s:78:"Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php";}s:71:"Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php";a:4:{s:6:"md5sum";s:32:"d82f8a856a9d95cd7a6d8fd6a0734981";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php";}s:69:"Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php";a:4:{s:6:"md5sum";s:32:"3debe15a84780f2383a690dfbb867a1d";s:4:"name";s:69:"Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.php";a:4:{s:6:"md5sum";s:32:"8fff3ed85f1a0ea2f1414606d66031aa";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.php";}s:71:"Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.php";a:4:{s:6:"md5sum";s:32:"d26340b6b9e5ddf8d71968b27c288db2";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.php";}s:73:"Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php";a:4:{s:6:"md5sum";s:32:"002a50c1e4557d0b89860f47c279fc74";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php";}s:77:"Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php";a:4:{s:6:"md5sum";s:32:"4ea56306c1dbab2f83e077512a59a769";s:4:"name";s:77:"Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php";}s:70:"Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php";a:4:{s:6:"md5sum";s:32:"b3e3c45f358f75c450c27bcf9a046576";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.php";a:4:{s:6:"md5sum";s:32:"e8e343b9fb22cecd94a9a08b993d0c3a";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.php";}s:68:"Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php";a:4:{s:6:"md5sum";s:32:"f02807065a8b9e4e578ec2e806cb9b81";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php";}s:68:"Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.php";a:4:{s:6:"md5sum";s:32:"457e33f80230fd2eebaa65404aa0f085";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php";a:4:{s:6:"md5sum";s:32:"9943acc92b78efc760c440e0f8d94998";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.php";a:4:{s:6:"md5sum";s:32:"fe42e8bb7b68a0bb8aae4325746f2bf9";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.php";}s:67:"Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.php";a:4:{s:6:"md5sum";s:32:"61b6a4967362f4ac3dcbecbdcbf11156";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.php";}s:66:"Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php";a:4:{s:6:"md5sum";s:32:"c61759a19cd93a2d382d40ac2e689acd";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php";}s:59:"Symfony/Component/Validator/Tests/Constraints/ValidTest.php";a:4:{s:6:"md5sum";s:32:"2d93246dad9e589df5a83163e06fb877";s:4:"name";s:59:"Symfony/Component/Validator/Tests/Constraints/ValidTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/ValidTest.php";}s:52:"Symfony/Component/Validator/Tests/ConstraintTest.php";a:4:{s:6:"md5sum";s:32:"142a99b58afedf51b2c454fff02a65f3";s:4:"name";s:52:"Symfony/Component/Validator/Tests/ConstraintTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/ConstraintTest.php";}s:65:"Symfony/Component/Validator/Tests/ConstraintViolationListTest.php";a:4:{s:6:"md5sum";s:32:"0584669a9a12dcadae796248aa9b42ff";s:4:"name";s:65:"Symfony/Component/Validator/Tests/ConstraintViolationListTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/ConstraintViolationListTest.php";}s:61:"Symfony/Component/Validator/Tests/ConstraintViolationTest.php";a:4:{s:6:"md5sum";s:32:"1319acdb0db4325c870ae4972e13efae";s:4:"name";s:61:"Symfony/Component/Validator/Tests/ConstraintViolationTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/ConstraintViolationTest.php";}s:58:"Symfony/Component/Validator/Tests/ExecutionContextTest.php";a:4:{s:6:"md5sum";s:32:"5aaa025907f20560822461a587c25457";s:4:"name";s:58:"Symfony/Component/Validator/Tests/ExecutionContextTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/ExecutionContextTest.php";}s:60:"Symfony/Component/Validator/Tests/Fixtures/CallbackClass.php";a:4:{s:6:"md5sum";s:32:"9454ace17fc81c19efac384cf4c50713";s:4:"name";s:60:"Symfony/Component/Validator/Tests/Fixtures/CallbackClass.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/CallbackClass.php";}s:62:"Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.php";a:4:{s:6:"md5sum";s:32:"2ce3e43d62dc225654afccb6614717be";s:4:"name";s:62:"Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.php";}s:58:"Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php";a:4:{s:6:"md5sum";s:32:"d4169102f57729661cb27febaab2d23f";s:4:"name";s:58:"Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php";}s:67:"Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.php";a:4:{s:6:"md5sum";s:32:"e2c1daf935b4f95134c33129662adf08";s:4:"name";s:67:"Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.php";}s:58:"Symfony/Component/Validator/Tests/Fixtures/ConstraintB.php";a:4:{s:6:"md5sum";s:32:"0157e96965ab4870f6965fbfa96a1612";s:4:"name";s:58:"Symfony/Component/Validator/Tests/Fixtures/ConstraintB.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintB.php";}s:58:"Symfony/Component/Validator/Tests/Fixtures/ConstraintC.php";a:4:{s:6:"md5sum";s:32:"8cd11e6488e0bce8f9c4de961754b500";s:4:"name";s:58:"Symfony/Component/Validator/Tests/Fixtures/ConstraintC.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintC.php";}s:66:"Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.php";a:4:{s:6:"md5sum";s:32:"2576db20cea1031e94f9b93ef5f9303a";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.php";}s:75:"Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.php";a:4:{s:6:"md5sum";s:32:"7763c0812a069714f24f431567726500";s:4:"name";s:75:"Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.php";}s:53:"Symfony/Component/Validator/Tests/Fixtures/Entity.php";a:4:{s:6:"md5sum";s:32:"6b6e6d9a60b2254024c55566fe79b08f";s:4:"name";s:53:"Symfony/Component/Validator/Tests/Fixtures/Entity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/Entity.php";}s:62:"Symfony/Component/Validator/Tests/Fixtures/EntityInterface.php";a:4:{s:6:"md5sum";s:32:"ea31fab8aec5a8884f460f66daf7c993";s:4:"name";s:62:"Symfony/Component/Validator/Tests/Fixtures/EntityInterface.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.php";}s:59:"Symfony/Component/Validator/Tests/Fixtures/EntityParent.php";a:4:{s:6:"md5sum";s:32:"a66c0953945928c193165c50757bcf04";s:4:"name";s:59:"Symfony/Component/Validator/Tests/Fixtures/EntityParent.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php";}s:64:"Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.php";a:4:{s:6:"md5sum";s:32:"72db5eaa66dc69f67e2d4ad5eb82b0e8";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.php";}s:73:"Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.php";a:4:{s:6:"md5sum";s:32:"c97e5a72d1d2befa96bea40821ec2c3a";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.php";}s:66:"Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.php";a:4:{s:6:"md5sum";s:32:"edcb2a57ff4308821104e31a3ffd5167";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.php";}s:58:"Symfony/Component/Validator/Tests/Fixtures/FilesLoader.php";a:4:{s:6:"md5sum";s:32:"068493fec3128c8cb2d29f6c5b0eaad0";s:4:"name";s:58:"Symfony/Component/Validator/Tests/Fixtures/FilesLoader.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/FilesLoader.php";}s:74:"Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.php";a:4:{s:6:"md5sum";s:32:"ad8147295941a1cc399da4034cd61c49";s:4:"name";s:74:"Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.php";}s:64:"Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.php";a:4:{s:6:"md5sum";s:32:"ddb0895d24c9c089229b3b932538aabd";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.php";}s:73:"Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.php";a:4:{s:6:"md5sum";s:32:"5681169dbdca0c79b579401520a7173d";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.php";}s:65:"Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.php";a:4:{s:6:"md5sum";s:32:"fbc643d2960104a96a86a281f0d099bb";s:4:"name";s:65:"Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.php";}s:56:"Symfony/Component/Validator/Tests/Fixtures/Reference.php";a:4:{s:6:"md5sum";s:32:"9d6e84977cc653a0673858a764ec39d6";s:4:"name";s:56:"Symfony/Component/Validator/Tests/Fixtures/Reference.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures/Reference.php";}s:74:"Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.php";a:4:{s:6:"md5sum";s:32:"7353a9cae56c607794bee8094e41ffd4";s:4:"name";s:74:"Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.php";}s:64:"Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.php";a:4:{s:6:"md5sum";s:32:"8d720776b21d7ce674a7365e5d2e38d2";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.php";}s:70:"Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.php";a:4:{s:6:"md5sum";s:32:"9fe738a4b6ba7f5105f2190fd449268e";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.php";}s:63:"Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php";a:4:{s:6:"md5sum";s:32:"a4495fa7cfe81f702f45d66a7fca8617";s:4:"name";s:63:"Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php";}s:65:"Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.php";a:4:{s:6:"md5sum";s:32:"4384111241f1abc0445a06c539451f2a";s:4:"name";s:65:"Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.php";}s:64:"Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php";a:4:{s:6:"md5sum";s:32:"d7f74984a4455152140bed27936361c0";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php";}s:79:"Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.php";a:4:{s:6:"md5sum";s:32:"0175b97f1eb69fcce94b306e900db362";s:4:"name";s:79:"Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.php";}s:73:"Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php";a:4:{s:6:"md5sum";s:32:"05410e4aaaf0a9a25ddc5c4134924390";s:4:"name";s:73:"Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php";}s:83:"Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml";a:4:{s:6:"md5sum";s:32:"c75233f90b5cfa4a398e1f9e543bf5bc";s:4:"name";s:83:"Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml";}s:71:"Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml";a:4:{s:6:"md5sum";s:32:"16ec478e3cf1b1bc1cab57aed6dadc6a";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml";}s:71:"Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml";a:4:{s:6:"md5sum";s:32:"7643e62f12cd427f2b5fd1fa9a5f6133";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml";}s:66:"Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.yml";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.yml";}s:68:"Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php";a:4:{s:6:"md5sum";s:32:"3bcfc4369f23356627bddd2555552d7f";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php";}s:68:"Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php";a:4:{s:6:"md5sum";s:32:"e28f9bc1f67084ac7661410da1fceaed";s:4:"name";s:68:"Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php";}s:69:"Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.yml";a:4:{s:6:"md5sum";s:32:"d3b07384d113edec49eaa6238ad5ff00";s:4:"name";s:69:"Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.yml";}s:75:"Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php";a:4:{s:6:"md5sum";s:32:"561fb1c6e9ee5b4de0ab14129619af6f";s:4:"name";s:75:"Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php";}s:64:"Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xml";a:4:{s:6:"md5sum";s:32:"bf3a0038b2c219b56536ee96a18b5f7d";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xml";}s:70:"Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"fee7255c9f688a416d2fe1d34a1e3389";s:4:"name";s:70:"Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php";}s:71:"Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"adc321984d79e773e10da8b4a1d2cbd4";s:4:"name";s:71:"Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php";}s:64:"Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php";a:4:{s:6:"md5sum";s:32:"b60229644c0267c6db54c14164b8d4c6";s:4:"name";s:64:"Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php";}s:66:"Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php";a:4:{s:6:"md5sum";s:32:"58769dbf877b4372cf5f4b418bee5d1a";s:4:"name";s:66:"Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php";}s:59:"Symfony/Component/Validator/Tests/ValidationVisitorTest.php";a:4:{s:6:"md5sum";s:32:"4380de8196121010c2219a131015c0bd";s:4:"name";s:59:"Symfony/Component/Validator/Tests/ValidationVisitorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/ValidationVisitorTest.php";}s:58:"Symfony/Component/Validator/Tests/ValidatorBuilderTest.php";a:4:{s:6:"md5sum";s:32:"5b599d3d7e28f3c31dd64a8e4a461798";s:4:"name";s:58:"Symfony/Component/Validator/Tests/ValidatorBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/ValidatorBuilderTest.php";}s:51:"Symfony/Component/Validator/Tests/ValidatorTest.php";a:4:{s:6:"md5sum";s:32:"c0d58093c8f48e173cf012832b5eff3d";s:4:"name";s:51:"Symfony/Component/Validator/Tests/ValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/ValidatorTest.php";}s:42:"Symfony/Component/Validator/Validation.php";a:4:{s:6:"md5sum";s:32:"cb4be714363c679edca5adea512653db";s:4:"name";s:42:"Symfony/Component/Validator/Validation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Validation.php";}s:49:"Symfony/Component/Validator/ValidationVisitor.php";a:4:{s:6:"md5sum";s:32:"7c3d1976b86cb3bee62b80d06037a82c";s:4:"name";s:49:"Symfony/Component/Validator/ValidationVisitor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ValidationVisitor.php";}s:58:"Symfony/Component/Validator/ValidationVisitorInterface.php";a:4:{s:6:"md5sum";s:32:"d9246ccdbae1aac172f0b344b77a0a6c";s:4:"name";s:58:"Symfony/Component/Validator/ValidationVisitorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ValidationVisitorInterface.php";}s:41:"Symfony/Component/Validator/Validator.php";a:4:{s:6:"md5sum";s:32:"dab18aca325ae61509511a918442e133";s:4:"name";s:41:"Symfony/Component/Validator/Validator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Validator.php";}s:48:"Symfony/Component/Validator/ValidatorBuilder.php";a:4:{s:6:"md5sum";s:32:"f3e3ae245a988856adea2ef86b30d27f";s:4:"name";s:48:"Symfony/Component/Validator/ValidatorBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ValidatorBuilder.php";}s:57:"Symfony/Component/Validator/ValidatorBuilderInterface.php";a:4:{s:6:"md5sum";s:32:"f3528198e3b2790e1a7ffee686196923";s:4:"name";s:57:"Symfony/Component/Validator/ValidatorBuilderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ValidatorBuilderInterface.php";}s:50:"Symfony/Component/Validator/ValidatorInterface.php";a:4:{s:6:"md5sum";s:32:"7e994e15443d4bf79a747b6454bb5e76";s:4:"name";s:50:"Symfony/Component/Validator/ValidatorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/ValidatorInterface.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:29:{s:57:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:71:"/opt/alt/php54/usr/share/doc/pear/Validator/Symfony/Component/Validator";b:1;s:61:"/opt/alt/php54/usr/share/doc/pear/Validator/Symfony/Component";b:1;s:51:"/opt/alt/php54/usr/share/doc/pear/Validator/Symfony";b:1;s:43:"/opt/alt/php54/usr/share/doc/pear/Validator";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints";b:1;s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Constraints/Collection";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Exception";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping";b:1;s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Cache";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader";b:1;s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping";b:1;s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/schema/dic";b:1;s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Mapping/Loader/schema";b:1;s:72:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator";b:1;s:62:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component";b:1;s:52:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony";b:1;s:44:"/opt/alt/php54/usr/share/pear/test/Validator";b:1;s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources/translations";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Validator/Resources";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints";b:1;s:78:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests";b:1;s:99:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Fixtures";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Cache";b:1;s:93:"/opt/alt/php54/usr/share/pear/test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:4:"Yaml";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:14:"HttpFoundation";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506495;}PK!^..registry/.channel.pear.symfony.com/config.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:6:"Config";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:25:"Symfony2 Config Component";s:11:"description";s:25:"Symfony2 Config Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:41";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:100:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d05aef71cd966ce2c36098180be89f86";s:4:"name";s:39:"Symfony/Component/Config/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2e855ecea3b2fd176fcde9dcbee078b4";s:4:"name";s:37:"Symfony/Component/Config/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"01e6d3e3f3a09e1d220b680f222152b3";s:4:"name";s:38:"Symfony/Component/Config/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"237f4a7e38967f0ce1f4088a999e0bfa";s:4:"name";s:40:"Symfony/Component/Config/ConfigCache.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f43a790400b259a8a307fd4da828692d";s:4:"name";s:49:"Symfony/Component/Config/Definition/ArrayNode.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a93e8f4c6f94c2d8bf86546930191d59";s:4:"name";s:48:"Symfony/Component/Config/Definition/BaseNode.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea6292c05f9aa76ec66dded2fe411d44";s:4:"name";s:51:"Symfony/Component/Config/Definition/BooleanNode.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a6478a434beef0f4d0146d4ce64b9450";s:4:"name";s:67:"Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"79419f2566cf399be4660640a0405fa5";s:4:"name";s:69:"Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2935ae381b785ced6f6ec1eded9a9ce0";s:4:"name";s:66:"Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4612723b84cd2729dd94020f1412539a";s:4:"name";s:59:"Symfony/Component/Config/Definition/Builder/ExprBuilder.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea6a82bed9a7bfe2f7c7e4bded4ba25e";s:4:"name";s:67:"Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0de24b6c3b0846189e0e7140340e4c20";s:4:"name";s:69:"Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9a07191e37bffb3d56fd105365371a73";s:4:"name";s:60:"Symfony/Component/Config/Definition/Builder/MergeBuilder.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2c90e62ffffbcb9ee0f5b91d4b466f4a";s:4:"name";s:59:"Symfony/Component/Config/Definition/Builder/NodeBuilder.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"632c164c115dfa3969cc278fabb707ac";s:4:"name";s:62:"Symfony/Component/Config/Definition/Builder/NodeDefinition.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"511a0150b959a7eab00cbf0fed174c0a";s:4:"name";s:67:"Symfony/Component/Config/Definition/Builder/NodeParentInterface.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f03726ad2acc69648e3f4c92c3436b63";s:4:"name";s:68:"Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"23b4be07040f89b6bbc54fff80c97835";s:4:"name";s:69:"Symfony/Component/Config/Definition/Builder/NumericNodeDefinition.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ac0a6d2f8ae048f365844d761db049db";s:4:"name";s:77:"Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d9fa4186f4448c3cad8152bb9b08a10d";s:4:"name";s:68:"Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"48f136a2fe26ef3b84f2f4e785dafdca";s:4:"name";s:59:"Symfony/Component/Config/Definition/Builder/TreeBuilder.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8c0ab61f8ce4e8a0b95fae338d07289d";s:4:"name";s:65:"Symfony/Component/Config/Definition/Builder/ValidationBuilder.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0563011a6e9c41ea7b14fccd4c384d91";s:4:"name";s:70:"Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3c993b6405debf926234927327e1540e";s:4:"name";s:62:"Symfony/Component/Config/Definition/ConfigurationInterface.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"180a524d66b02398fec5f36baf16db87";s:4:"name";s:65:"Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"88061b0ef652b050eacda9f9d086777f";s:4:"name";s:66:"Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4718c796e11ef0403e41dce26b7224ea";s:4:"name";s:48:"Symfony/Component/Config/Definition/EnumNode.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ede2ab4177afff995069bc54c4517f9e";s:4:"name";s:71:"Symfony/Component/Config/Definition/Exception/DuplicateKeyException.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a7eb222da39a7eefc7b0c04a1583cc44";s:4:"name";s:59:"Symfony/Component/Config/Definition/Exception/Exception.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2a12d6760feb9f7c96d61e502f68b2c";s:4:"name";s:77:"Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df898eea27890a50cb912e1dbb88f1b2";s:4:"name";s:79:"Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aeb2ca3c7e035486a4ccebeac363125c";s:4:"name";s:76:"Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4dc25832f90b656b88da8ac50789784a";s:4:"name";s:70:"Symfony/Component/Config/Definition/Exception/InvalidTypeException.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"55c97aa4e81643f04c3abd943cc29a24";s:4:"name";s:67:"Symfony/Component/Config/Definition/Exception/UnsetKeyException.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3e06f85a85b21a16869037e026ec5189";s:4:"name";s:49:"Symfony/Component/Config/Definition/FloatNode.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c06b0c32a7f8c540545b7a78662eba48";s:4:"name";s:51:"Symfony/Component/Config/Definition/IntegerNode.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c735fbb1542c2dbe1d8037b27b0beb7d";s:4:"name";s:53:"Symfony/Component/Config/Definition/NodeInterface.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"864cb20b0ce39fa3d8d30f96ee41674e";s:4:"name";s:51:"Symfony/Component/Config/Definition/NumericNode.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4d853174c3a8b201b3684fd8cdc5b768";s:4:"name";s:49:"Symfony/Component/Config/Definition/Processor.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dea67be834c0088d2b11880b694a38f9";s:4:"name";s:59:"Symfony/Component/Config/Definition/PrototypedArrayNode.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ef44def01e8a4abfa4eaabdab44a3e1e";s:4:"name";s:62:"Symfony/Component/Config/Definition/PrototypeNodeInterface.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"52e870bf26dfc67c5cc508f35728877d";s:4:"name";s:55:"Symfony/Component/Config/Definition/ReferenceDumper.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b0e2b4e13486b70af9a70a2d8b9f403";s:4:"name";s:50:"Symfony/Component/Config/Definition/ScalarNode.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c83791bd28ed5e4abf7e79c3b906252f";s:4:"name";s:52:"Symfony/Component/Config/Definition/VariableNode.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b00d7fdeddee90ff6e91ffa0c0475e91";s:4:"name";s:81:"Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e31db44ccc39c72d40a6a9edc2fa66c5";s:4:"name";s:62:"Symfony/Component/Config/Exception/FileLoaderLoadException.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8145d1e145a232182b2a7780b5fd2ac9";s:4:"name";s:40:"Symfony/Component/Config/FileLocator.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c7ad8a99c8bc28c7e0e151c4fc5acff7";s:4:"name";s:49:"Symfony/Component/Config/FileLocatorInterface.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:32:"Symfony/Component/Config/LICENSE";s:4:"role";s:3:"doc";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eeb0111110364ce7bb3bfcc9d771c21b";s:4:"name";s:52:"Symfony/Component/Config/Loader/DelegatingLoader.php";s:4:"role";s:3:"php";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"db1f00201bb87f7e952648484aedbeb2";s:4:"name";s:46:"Symfony/Component/Config/Loader/FileLoader.php";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"284f38e73bfa8153ed95e7aa99e91b3e";s:4:"name";s:42:"Symfony/Component/Config/Loader/Loader.php";s:4:"role";s:3:"php";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df23b397d09d2260b2fa666de641cef2";s:4:"name";s:51:"Symfony/Component/Config/Loader/LoaderInterface.php";s:4:"role";s:3:"php";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df8900364600fbe7fcb4b32dcd948715";s:4:"name";s:50:"Symfony/Component/Config/Loader/LoaderResolver.php";s:4:"role";s:3:"php";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff8788c585296546155b51834d0c3919";s:4:"name";s:59:"Symfony/Component/Config/Loader/LoaderResolverInterface.php";s:4:"role";s:3:"php";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba93c00cbc0805b83cc9986edb1c47a0";s:4:"name";s:41:"Symfony/Component/Config/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80fb119edb21de39ff671d640fc7f381";s:4:"name";s:34:"Symfony/Component/Config/README.md";s:4:"role";s:3:"doc";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"282da7b67d1a869a71f1810bdc3d8973";s:4:"name";s:55:"Symfony/Component/Config/Resource/DirectoryResource.php";s:4:"role";s:3:"php";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4f6a17cb16d8b483fd9b563fa6d2639f";s:4:"name";s:50:"Symfony/Component/Config/Resource/FileResource.php";s:4:"role";s:3:"php";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a822b81682a486b7817170ad83002141";s:4:"name";s:55:"Symfony/Component/Config/Resource/ResourceInterface.php";s:4:"role";s:3:"php";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b9a1f02f3774a704eab93339d9a34800";s:4:"name";s:50:"Symfony/Component/Config/Tests/ConfigCacheTest.php";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d6c9405065e761fd9bae37c68b9226cb";s:4:"name";s:59:"Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a78dc9a09b81abd4216dc1aa743b212c";s:4:"name";s:61:"Symfony/Component/Config/Tests/Definition/BooleanNodeTest.php";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"000369ac6ed9312c820a1a511480fcdd";s:4:"name";s:77:"Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a6338f1a07bbe404e4caa1b1fdb179fd";s:4:"name";s:76:"Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d03be2c954f36df3c615e6a89eba304b";s:4:"name";s:69:"Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5deab29f7b387cd324ad3a2e3086d80d";s:4:"name";s:69:"Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.php";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"720159fadc5f8388c5c7cc16cfd9559e";s:4:"name";s:79:"Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.php";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"24a37c336daa3cd1a1d80d670505b32d";s:4:"name";s:69:"Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"565ad8f4a0db6f7e6c4173b711bc3976";s:4:"name";s:75:"Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ebf1ffd5db00b1c0e9b914fe83fb3169";s:4:"name";s:76:"Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php";s:4:"role";s:4:"test";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"92624818027c535fe005d85d365bdaaa";s:4:"name";s:58:"Symfony/Component/Config/Tests/Definition/EnumNodeTest.php";s:4:"role";s:4:"test";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2f083bc35c2a3769c24a185d4bffd428";s:4:"name";s:62:"Symfony/Component/Config/Tests/Definition/FinalizationTest.php";s:4:"role";s:4:"test";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"78e5e5856b6071f3c7f9f8da4881a06d";s:4:"name";s:59:"Symfony/Component/Config/Tests/Definition/FloatNodeTest.php";s:4:"role";s:4:"test";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a5a4ed81aef01e766cb948154ae92643";s:4:"name";s:61:"Symfony/Component/Config/Tests/Definition/IntegerNodeTest.php";s:4:"role";s:4:"test";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a81e2313992cb216f88f46113da997ce";s:4:"name";s:55:"Symfony/Component/Config/Tests/Definition/MergeTest.php";s:4:"role";s:4:"test";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8ac64aa50fcdabc32efa4d76fa08737";s:4:"name";s:63:"Symfony/Component/Config/Tests/Definition/NormalizationTest.php";s:4:"role";s:4:"test";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dc6f3545eb30eb7efd1f84278c1b08dd";s:4:"name";s:69:"Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.php";s:4:"role";s:4:"test";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cab8145a6c30d31be3d4897cc68208f6";s:4:"name";s:60:"Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php";s:4:"role";s:4:"test";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8157a7f666d2269ba36f5d12b71b392c";s:4:"name";s:50:"Symfony/Component/Config/Tests/FileLocatorTest.php";s:4:"role";s:4:"test";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:53:"Symfony/Component/Config/Tests/Fixtures/Again/foo.xml";s:4:"role";s:4:"test";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"61483df06205d8340ff30281494ddf4d";s:4:"name";s:69:"Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php";s:4:"role";s:4:"test";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bb1913bbf75e3a341384f2dd58267465";s:4:"name";s:63:"Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.php";s:4:"role";s:4:"test";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c5057b3b1c5b4790985800ea90cd4d7a";s:4:"name";s:74:"Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php";s:4:"role";s:4:"test";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ca56644f6fcffdd18a57f5e29db5faf";s:4:"name";s:78:"Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php";s:4:"role";s:4:"test";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:47:"Symfony/Component/Config/Tests/Fixtures/foo.xml";s:4:"role";s:4:"test";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0b3c991715906416d884a53869b71210";s:4:"name";s:62:"Symfony/Component/Config/Tests/Fixtures/Util/document_type.xml";s:4:"role";s:4:"test";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9faea03761cbb774e569e0ddc15118a2";s:4:"name";s:56:"Symfony/Component/Config/Tests/Fixtures/Util/invalid.xml";s:4:"role";s:4:"test";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5527ef0a29820ff2870e0749cd38c297";s:4:"name";s:63:"Symfony/Component/Config/Tests/Fixtures/Util/invalid_schema.xml";s:4:"role";s:4:"test";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1ffa211272544831555c45f701a9e523";s:4:"name";s:55:"Symfony/Component/Config/Tests/Fixtures/Util/schema.xsd";s:4:"role";s:4:"test";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"57e37ff0b94a2574fe00e18efbc92a4c";s:4:"name";s:54:"Symfony/Component/Config/Tests/Fixtures/Util/valid.xml";s:4:"role";s:4:"test";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7cb65249e81babb2867f7a2afecc2201";s:4:"name";s:62:"Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.php";s:4:"role";s:4:"test";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7ea599ca7987b26ebbc49c7a204ed566";s:4:"name";s:56:"Symfony/Component/Config/Tests/Loader/FileLoaderTest.php";s:4:"role";s:4:"test";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4b52c0a493e0abe0c016757c3b81871f";s:4:"name";s:60:"Symfony/Component/Config/Tests/Loader/LoaderResolverTest.php";s:4:"role";s:4:"test";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"948c42a53d8bad4d6ba2a54c4ec000fd";s:4:"name";s:52:"Symfony/Component/Config/Tests/Loader/LoaderTest.php";s:4:"role";s:4:"test";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c4027624b5fb8e923b71f4eab6a996d0";s:4:"name";s:65:"Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php";s:4:"role";s:4:"test";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e37cf4fd016b4652013a54aed653a90c";s:4:"name";s:60:"Symfony/Component/Config/Tests/Resource/FileResourceTest.php";s:4:"role";s:4:"test";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa364fa2a9af8fb8fb396ba173c2b3b3";s:4:"name";s:52:"Symfony/Component/Config/Tests/Util/XmlUtilsTest.php";s:4:"role";s:4:"test";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b90ce309828aad9fe732e136489b77f6";s:4:"name";s:42:"Symfony/Component/Config/Util/XmlUtils.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:100:{s:39:"Symfony/Component/Config/autoloader.php";a:4:{s:6:"md5sum";s:32:"d05aef71cd966ce2c36098180be89f86";s:4:"name";s:39:"Symfony/Component/Config/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/autoloader.php";}s:37:"Symfony/Component/Config/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"2e855ecea3b2fd176fcde9dcbee078b4";s:4:"name";s:37:"Symfony/Component/Config/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/doc/pear/Config/Symfony/Component/Config/CHANGELOG.md";}s:38:"Symfony/Component/Config/composer.json";a:4:{s:6:"md5sum";s:32:"01e6d3e3f3a09e1d220b680f222152b3";s:4:"name";s:38:"Symfony/Component/Config/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/doc/pear/Config/Symfony/Component/Config/composer.json";}s:40:"Symfony/Component/Config/ConfigCache.php";a:4:{s:6:"md5sum";s:32:"237f4a7e38967f0ce1f4088a999e0bfa";s:4:"name";s:40:"Symfony/Component/Config/ConfigCache.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/ConfigCache.php";}s:49:"Symfony/Component/Config/Definition/ArrayNode.php";a:4:{s:6:"md5sum";s:32:"f43a790400b259a8a307fd4da828692d";s:4:"name";s:49:"Symfony/Component/Config/Definition/ArrayNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/ArrayNode.php";}s:48:"Symfony/Component/Config/Definition/BaseNode.php";a:4:{s:6:"md5sum";s:32:"a93e8f4c6f94c2d8bf86546930191d59";s:4:"name";s:48:"Symfony/Component/Config/Definition/BaseNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/BaseNode.php";}s:51:"Symfony/Component/Config/Definition/BooleanNode.php";a:4:{s:6:"md5sum";s:32:"ea6292c05f9aa76ec66dded2fe411d44";s:4:"name";s:51:"Symfony/Component/Config/Definition/BooleanNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/BooleanNode.php";}s:67:"Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"a6478a434beef0f4d0146d4ce64b9450";s:4:"name";s:67:"Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php";}s:69:"Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"79419f2566cf399be4660640a0405fa5";s:4:"name";s:69:"Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.php";}s:66:"Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"2935ae381b785ced6f6ec1eded9a9ce0";s:4:"name";s:66:"Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php";}s:59:"Symfony/Component/Config/Definition/Builder/ExprBuilder.php";a:4:{s:6:"md5sum";s:32:"4612723b84cd2729dd94020f1412539a";s:4:"name";s:59:"Symfony/Component/Config/Definition/Builder/ExprBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/ExprBuilder.php";}s:67:"Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"ea6a82bed9a7bfe2f7c7e4bded4ba25e";s:4:"name";s:67:"Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.php";}s:69:"Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"0de24b6c3b0846189e0e7140340e4c20";s:4:"name";s:69:"Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.php";}s:60:"Symfony/Component/Config/Definition/Builder/MergeBuilder.php";a:4:{s:6:"md5sum";s:32:"9a07191e37bffb3d56fd105365371a73";s:4:"name";s:60:"Symfony/Component/Config/Definition/Builder/MergeBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/MergeBuilder.php";}s:59:"Symfony/Component/Config/Definition/Builder/NodeBuilder.php";a:4:{s:6:"md5sum";s:32:"2c90e62ffffbcb9ee0f5b91d4b466f4a";s:4:"name";s:59:"Symfony/Component/Config/Definition/Builder/NodeBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/NodeBuilder.php";}s:62:"Symfony/Component/Config/Definition/Builder/NodeDefinition.php";a:4:{s:6:"md5sum";s:32:"632c164c115dfa3969cc278fabb707ac";s:4:"name";s:62:"Symfony/Component/Config/Definition/Builder/NodeDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/NodeDefinition.php";}s:67:"Symfony/Component/Config/Definition/Builder/NodeParentInterface.php";a:4:{s:6:"md5sum";s:32:"511a0150b959a7eab00cbf0fed174c0a";s:4:"name";s:67:"Symfony/Component/Config/Definition/Builder/NodeParentInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/NodeParentInterface.php";}s:68:"Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php";a:4:{s:6:"md5sum";s:32:"f03726ad2acc69648e3f4c92c3436b63";s:4:"name";s:68:"Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php";}s:69:"Symfony/Component/Config/Definition/Builder/NumericNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"23b4be07040f89b6bbc54fff80c97835";s:4:"name";s:69:"Symfony/Component/Config/Definition/Builder/NumericNodeDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/NumericNodeDefinition.php";}s:77:"Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php";a:4:{s:6:"md5sum";s:32:"ac0a6d2f8ae048f365844d761db049db";s:4:"name";s:77:"Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php";}s:68:"Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"d9fa4186f4448c3cad8152bb9b08a10d";s:4:"name";s:68:"Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.php";}s:59:"Symfony/Component/Config/Definition/Builder/TreeBuilder.php";a:4:{s:6:"md5sum";s:32:"48f136a2fe26ef3b84f2f4e785dafdca";s:4:"name";s:59:"Symfony/Component/Config/Definition/Builder/TreeBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/TreeBuilder.php";}s:65:"Symfony/Component/Config/Definition/Builder/ValidationBuilder.php";a:4:{s:6:"md5sum";s:32:"8c0ab61f8ce4e8a0b95fae338d07289d";s:4:"name";s:65:"Symfony/Component/Config/Definition/Builder/ValidationBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/ValidationBuilder.php";}s:70:"Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"0563011a6e9c41ea7b14fccd4c384d91";s:4:"name";s:70:"Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php";}s:62:"Symfony/Component/Config/Definition/ConfigurationInterface.php";a:4:{s:6:"md5sum";s:32:"3c993b6405debf926234927327e1540e";s:4:"name";s:62:"Symfony/Component/Config/Definition/ConfigurationInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/ConfigurationInterface.php";}s:65:"Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php";a:4:{s:6:"md5sum";s:32:"180a524d66b02398fec5f36baf16db87";s:4:"name";s:65:"Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php";}s:66:"Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php";a:4:{s:6:"md5sum";s:32:"88061b0ef652b050eacda9f9d086777f";s:4:"name";s:66:"Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php";}s:48:"Symfony/Component/Config/Definition/EnumNode.php";a:4:{s:6:"md5sum";s:32:"4718c796e11ef0403e41dce26b7224ea";s:4:"name";s:48:"Symfony/Component/Config/Definition/EnumNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/EnumNode.php";}s:71:"Symfony/Component/Config/Definition/Exception/DuplicateKeyException.php";a:4:{s:6:"md5sum";s:32:"ede2ab4177afff995069bc54c4517f9e";s:4:"name";s:71:"Symfony/Component/Config/Definition/Exception/DuplicateKeyException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Exception/DuplicateKeyException.php";}s:59:"Symfony/Component/Config/Definition/Exception/Exception.php";a:4:{s:6:"md5sum";s:32:"a7eb222da39a7eefc7b0c04a1583cc44";s:4:"name";s:59:"Symfony/Component/Config/Definition/Exception/Exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Exception/Exception.php";}s:77:"Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.php";a:4:{s:6:"md5sum";s:32:"e2a12d6760feb9f7c96d61e502f68b2c";s:4:"name";s:77:"Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.php";}s:79:"Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.php";a:4:{s:6:"md5sum";s:32:"df898eea27890a50cb912e1dbb88f1b2";s:4:"name";s:79:"Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.php";}s:76:"Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php";a:4:{s:6:"md5sum";s:32:"aeb2ca3c7e035486a4ccebeac363125c";s:4:"name";s:76:"Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php";}s:70:"Symfony/Component/Config/Definition/Exception/InvalidTypeException.php";a:4:{s:6:"md5sum";s:32:"4dc25832f90b656b88da8ac50789784a";s:4:"name";s:70:"Symfony/Component/Config/Definition/Exception/InvalidTypeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Exception/InvalidTypeException.php";}s:67:"Symfony/Component/Config/Definition/Exception/UnsetKeyException.php";a:4:{s:6:"md5sum";s:32:"55c97aa4e81643f04c3abd943cc29a24";s:4:"name";s:67:"Symfony/Component/Config/Definition/Exception/UnsetKeyException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Exception/UnsetKeyException.php";}s:49:"Symfony/Component/Config/Definition/FloatNode.php";a:4:{s:6:"md5sum";s:32:"3e06f85a85b21a16869037e026ec5189";s:4:"name";s:49:"Symfony/Component/Config/Definition/FloatNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/FloatNode.php";}s:51:"Symfony/Component/Config/Definition/IntegerNode.php";a:4:{s:6:"md5sum";s:32:"c06b0c32a7f8c540545b7a78662eba48";s:4:"name";s:51:"Symfony/Component/Config/Definition/IntegerNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/IntegerNode.php";}s:53:"Symfony/Component/Config/Definition/NodeInterface.php";a:4:{s:6:"md5sum";s:32:"c735fbb1542c2dbe1d8037b27b0beb7d";s:4:"name";s:53:"Symfony/Component/Config/Definition/NodeInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/NodeInterface.php";}s:51:"Symfony/Component/Config/Definition/NumericNode.php";a:4:{s:6:"md5sum";s:32:"864cb20b0ce39fa3d8d30f96ee41674e";s:4:"name";s:51:"Symfony/Component/Config/Definition/NumericNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/NumericNode.php";}s:49:"Symfony/Component/Config/Definition/Processor.php";a:4:{s:6:"md5sum";s:32:"4d853174c3a8b201b3684fd8cdc5b768";s:4:"name";s:49:"Symfony/Component/Config/Definition/Processor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Processor.php";}s:59:"Symfony/Component/Config/Definition/PrototypedArrayNode.php";a:4:{s:6:"md5sum";s:32:"dea67be834c0088d2b11880b694a38f9";s:4:"name";s:59:"Symfony/Component/Config/Definition/PrototypedArrayNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/PrototypedArrayNode.php";}s:62:"Symfony/Component/Config/Definition/PrototypeNodeInterface.php";a:4:{s:6:"md5sum";s:32:"ef44def01e8a4abfa4eaabdab44a3e1e";s:4:"name";s:62:"Symfony/Component/Config/Definition/PrototypeNodeInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/PrototypeNodeInterface.php";}s:55:"Symfony/Component/Config/Definition/ReferenceDumper.php";a:4:{s:6:"md5sum";s:32:"52e870bf26dfc67c5cc508f35728877d";s:4:"name";s:55:"Symfony/Component/Config/Definition/ReferenceDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/ReferenceDumper.php";}s:50:"Symfony/Component/Config/Definition/ScalarNode.php";a:4:{s:6:"md5sum";s:32:"7b0e2b4e13486b70af9a70a2d8b9f403";s:4:"name";s:50:"Symfony/Component/Config/Definition/ScalarNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/ScalarNode.php";}s:52:"Symfony/Component/Config/Definition/VariableNode.php";a:4:{s:6:"md5sum";s:32:"c83791bd28ed5e4abf7e79c3b906252f";s:4:"name";s:52:"Symfony/Component/Config/Definition/VariableNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/VariableNode.php";}s:81:"Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.php";a:4:{s:6:"md5sum";s:32:"b00d7fdeddee90ff6e91ffa0c0475e91";s:4:"name";s:81:"Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.php";}s:62:"Symfony/Component/Config/Exception/FileLoaderLoadException.php";a:4:{s:6:"md5sum";s:32:"e31db44ccc39c72d40a6a9edc2fa66c5";s:4:"name";s:62:"Symfony/Component/Config/Exception/FileLoaderLoadException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Exception/FileLoaderLoadException.php";}s:40:"Symfony/Component/Config/FileLocator.php";a:4:{s:6:"md5sum";s:32:"8145d1e145a232182b2a7780b5fd2ac9";s:4:"name";s:40:"Symfony/Component/Config/FileLocator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/FileLocator.php";}s:49:"Symfony/Component/Config/FileLocatorInterface.php";a:4:{s:6:"md5sum";s:32:"c7ad8a99c8bc28c7e0e151c4fc5acff7";s:4:"name";s:49:"Symfony/Component/Config/FileLocatorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/FileLocatorInterface.php";}s:32:"Symfony/Component/Config/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:32:"Symfony/Component/Config/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/doc/pear/Config/Symfony/Component/Config/LICENSE";}s:52:"Symfony/Component/Config/Loader/DelegatingLoader.php";a:4:{s:6:"md5sum";s:32:"eeb0111110364ce7bb3bfcc9d771c21b";s:4:"name";s:52:"Symfony/Component/Config/Loader/DelegatingLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Loader/DelegatingLoader.php";}s:46:"Symfony/Component/Config/Loader/FileLoader.php";a:4:{s:6:"md5sum";s:32:"db1f00201bb87f7e952648484aedbeb2";s:4:"name";s:46:"Symfony/Component/Config/Loader/FileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Loader/FileLoader.php";}s:42:"Symfony/Component/Config/Loader/Loader.php";a:4:{s:6:"md5sum";s:32:"284f38e73bfa8153ed95e7aa99e91b3e";s:4:"name";s:42:"Symfony/Component/Config/Loader/Loader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Loader/Loader.php";}s:51:"Symfony/Component/Config/Loader/LoaderInterface.php";a:4:{s:6:"md5sum";s:32:"df23b397d09d2260b2fa666de641cef2";s:4:"name";s:51:"Symfony/Component/Config/Loader/LoaderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Loader/LoaderInterface.php";}s:50:"Symfony/Component/Config/Loader/LoaderResolver.php";a:4:{s:6:"md5sum";s:32:"df8900364600fbe7fcb4b32dcd948715";s:4:"name";s:50:"Symfony/Component/Config/Loader/LoaderResolver.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Loader/LoaderResolver.php";}s:59:"Symfony/Component/Config/Loader/LoaderResolverInterface.php";a:4:{s:6:"md5sum";s:32:"ff8788c585296546155b51834d0c3919";s:4:"name";s:59:"Symfony/Component/Config/Loader/LoaderResolverInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Loader/LoaderResolverInterface.php";}s:41:"Symfony/Component/Config/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"ba93c00cbc0805b83cc9986edb1c47a0";s:4:"name";s:41:"Symfony/Component/Config/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/phpunit.xml.dist";}s:34:"Symfony/Component/Config/README.md";a:4:{s:6:"md5sum";s:32:"80fb119edb21de39ff671d640fc7f381";s:4:"name";s:34:"Symfony/Component/Config/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/Config/Symfony/Component/Config/README.md";}s:55:"Symfony/Component/Config/Resource/DirectoryResource.php";a:4:{s:6:"md5sum";s:32:"282da7b67d1a869a71f1810bdc3d8973";s:4:"name";s:55:"Symfony/Component/Config/Resource/DirectoryResource.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Resource/DirectoryResource.php";}s:50:"Symfony/Component/Config/Resource/FileResource.php";a:4:{s:6:"md5sum";s:32:"4f6a17cb16d8b483fd9b563fa6d2639f";s:4:"name";s:50:"Symfony/Component/Config/Resource/FileResource.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Resource/FileResource.php";}s:55:"Symfony/Component/Config/Resource/ResourceInterface.php";a:4:{s:6:"md5sum";s:32:"a822b81682a486b7817170ad83002141";s:4:"name";s:55:"Symfony/Component/Config/Resource/ResourceInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Resource/ResourceInterface.php";}s:50:"Symfony/Component/Config/Tests/ConfigCacheTest.php";a:4:{s:6:"md5sum";s:32:"b9a1f02f3774a704eab93339d9a34800";s:4:"name";s:50:"Symfony/Component/Config/Tests/ConfigCacheTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/ConfigCacheTest.php";}s:59:"Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php";a:4:{s:6:"md5sum";s:32:"d6c9405065e761fd9bae37c68b9226cb";s:4:"name";s:59:"Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php";}s:61:"Symfony/Component/Config/Tests/Definition/BooleanNodeTest.php";a:4:{s:6:"md5sum";s:32:"a78dc9a09b81abd4216dc1aa743b212c";s:4:"name";s:61:"Symfony/Component/Config/Tests/Definition/BooleanNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/BooleanNodeTest.php";}s:77:"Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php";a:4:{s:6:"md5sum";s:32:"000369ac6ed9312c820a1a511480fcdd";s:4:"name";s:77:"Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php";}s:76:"Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php";a:4:{s:6:"md5sum";s:32:"a6338f1a07bbe404e4caa1b1fdb179fd";s:4:"name";s:76:"Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php";}s:69:"Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php";a:4:{s:6:"md5sum";s:32:"d03be2c954f36df3c615e6a89eba304b";s:4:"name";s:69:"Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php";}s:69:"Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.php";a:4:{s:6:"md5sum";s:32:"5deab29f7b387cd324ad3a2e3086d80d";s:4:"name";s:69:"Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.php";}s:79:"Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.php";a:4:{s:6:"md5sum";s:32:"720159fadc5f8388c5c7cc16cfd9559e";s:4:"name";s:79:"Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.php";}s:69:"Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php";a:4:{s:6:"md5sum";s:32:"24a37c336daa3cd1a1d80d670505b32d";s:4:"name";s:69:"Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php";}s:75:"Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php";a:4:{s:6:"md5sum";s:32:"565ad8f4a0db6f7e6c4173b711bc3976";s:4:"name";s:75:"Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php";}s:76:"Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php";a:4:{s:6:"md5sum";s:32:"ebf1ffd5db00b1c0e9b914fe83fb3169";s:4:"name";s:76:"Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php";}s:58:"Symfony/Component/Config/Tests/Definition/EnumNodeTest.php";a:4:{s:6:"md5sum";s:32:"92624818027c535fe005d85d365bdaaa";s:4:"name";s:58:"Symfony/Component/Config/Tests/Definition/EnumNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/EnumNodeTest.php";}s:62:"Symfony/Component/Config/Tests/Definition/FinalizationTest.php";a:4:{s:6:"md5sum";s:32:"2f083bc35c2a3769c24a185d4bffd428";s:4:"name";s:62:"Symfony/Component/Config/Tests/Definition/FinalizationTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/FinalizationTest.php";}s:59:"Symfony/Component/Config/Tests/Definition/FloatNodeTest.php";a:4:{s:6:"md5sum";s:32:"78e5e5856b6071f3c7f9f8da4881a06d";s:4:"name";s:59:"Symfony/Component/Config/Tests/Definition/FloatNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/FloatNodeTest.php";}s:61:"Symfony/Component/Config/Tests/Definition/IntegerNodeTest.php";a:4:{s:6:"md5sum";s:32:"a5a4ed81aef01e766cb948154ae92643";s:4:"name";s:61:"Symfony/Component/Config/Tests/Definition/IntegerNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/IntegerNodeTest.php";}s:55:"Symfony/Component/Config/Tests/Definition/MergeTest.php";a:4:{s:6:"md5sum";s:32:"a81e2313992cb216f88f46113da997ce";s:4:"name";s:55:"Symfony/Component/Config/Tests/Definition/MergeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/MergeTest.php";}s:63:"Symfony/Component/Config/Tests/Definition/NormalizationTest.php";a:4:{s:6:"md5sum";s:32:"b8ac64aa50fcdabc32efa4d76fa08737";s:4:"name";s:63:"Symfony/Component/Config/Tests/Definition/NormalizationTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/NormalizationTest.php";}s:69:"Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.php";a:4:{s:6:"md5sum";s:32:"dc6f3545eb30eb7efd1f84278c1b08dd";s:4:"name";s:69:"Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.php";}s:60:"Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php";a:4:{s:6:"md5sum";s:32:"cab8145a6c30d31be3d4897cc68208f6";s:4:"name";s:60:"Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php";}s:50:"Symfony/Component/Config/Tests/FileLocatorTest.php";a:4:{s:6:"md5sum";s:32:"8157a7f666d2269ba36f5d12b71b392c";s:4:"name";s:50:"Symfony/Component/Config/Tests/FileLocatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/FileLocatorTest.php";}s:53:"Symfony/Component/Config/Tests/Fixtures/Again/foo.xml";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:53:"Symfony/Component/Config/Tests/Fixtures/Again/foo.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Again/foo.xml";}s:69:"Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"61483df06205d8340ff30281494ddf4d";s:4:"name";s:69:"Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php";}s:63:"Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.php";a:4:{s:6:"md5sum";s:32:"bb1913bbf75e3a341384f2dd58267465";s:4:"name";s:63:"Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.php";}s:74:"Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php";a:4:{s:6:"md5sum";s:32:"c5057b3b1c5b4790985800ea90cd4d7a";s:4:"name";s:74:"Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php";}s:78:"Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php";a:4:{s:6:"md5sum";s:32:"3ca56644f6fcffdd18a57f5e29db5faf";s:4:"name";s:78:"Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php";}s:47:"Symfony/Component/Config/Tests/Fixtures/foo.xml";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:47:"Symfony/Component/Config/Tests/Fixtures/foo.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/foo.xml";}s:62:"Symfony/Component/Config/Tests/Fixtures/Util/document_type.xml";a:4:{s:6:"md5sum";s:32:"0b3c991715906416d884a53869b71210";s:4:"name";s:62:"Symfony/Component/Config/Tests/Fixtures/Util/document_type.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Util/document_type.xml";}s:56:"Symfony/Component/Config/Tests/Fixtures/Util/invalid.xml";a:4:{s:6:"md5sum";s:32:"9faea03761cbb774e569e0ddc15118a2";s:4:"name";s:56:"Symfony/Component/Config/Tests/Fixtures/Util/invalid.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid.xml";}s:63:"Symfony/Component/Config/Tests/Fixtures/Util/invalid_schema.xml";a:4:{s:6:"md5sum";s:32:"5527ef0a29820ff2870e0749cd38c297";s:4:"name";s:63:"Symfony/Component/Config/Tests/Fixtures/Util/invalid_schema.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid_schema.xml";}s:55:"Symfony/Component/Config/Tests/Fixtures/Util/schema.xsd";a:4:{s:6:"md5sum";s:32:"1ffa211272544831555c45f701a9e523";s:4:"name";s:55:"Symfony/Component/Config/Tests/Fixtures/Util/schema.xsd";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Util/schema.xsd";}s:54:"Symfony/Component/Config/Tests/Fixtures/Util/valid.xml";a:4:{s:6:"md5sum";s:32:"57e37ff0b94a2574fe00e18efbc92a4c";s:4:"name";s:54:"Symfony/Component/Config/Tests/Fixtures/Util/valid.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Util/valid.xml";}s:62:"Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.php";a:4:{s:6:"md5sum";s:32:"7cb65249e81babb2867f7a2afecc2201";s:4:"name";s:62:"Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.php";}s:56:"Symfony/Component/Config/Tests/Loader/FileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"7ea599ca7987b26ebbc49c7a204ed566";s:4:"name";s:56:"Symfony/Component/Config/Tests/Loader/FileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php";}s:60:"Symfony/Component/Config/Tests/Loader/LoaderResolverTest.php";a:4:{s:6:"md5sum";s:32:"4b52c0a493e0abe0c016757c3b81871f";s:4:"name";s:60:"Symfony/Component/Config/Tests/Loader/LoaderResolverTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Loader/LoaderResolverTest.php";}s:52:"Symfony/Component/Config/Tests/Loader/LoaderTest.php";a:4:{s:6:"md5sum";s:32:"948c42a53d8bad4d6ba2a54c4ec000fd";s:4:"name";s:52:"Symfony/Component/Config/Tests/Loader/LoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Loader/LoaderTest.php";}s:65:"Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php";a:4:{s:6:"md5sum";s:32:"c4027624b5fb8e923b71f4eab6a996d0";s:4:"name";s:65:"Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php";}s:60:"Symfony/Component/Config/Tests/Resource/FileResourceTest.php";a:4:{s:6:"md5sum";s:32:"e37cf4fd016b4652013a54aed653a90c";s:4:"name";s:60:"Symfony/Component/Config/Tests/Resource/FileResourceTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Resource/FileResourceTest.php";}s:52:"Symfony/Component/Config/Tests/Util/XmlUtilsTest.php";a:4:{s:6:"md5sum";s:32:"aa364fa2a9af8fb8fb396ba173c2b3b3";s:4:"name";s:52:"Symfony/Component/Config/Tests/Util/XmlUtilsTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php";}s:42:"Symfony/Component/Config/Util/XmlUtils.php";a:4:{s:6:"md5sum";s:32:"b90ce309828aad9fe732e136489b77f6";s:4:"name";s:42:"Symfony/Component/Config/Util/XmlUtils.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Util/XmlUtils.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:31:{s:54:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:65:"/opt/alt/php54/usr/share/doc/pear/Config/Symfony/Component/Config";b:1;s:58:"/opt/alt/php54/usr/share/doc/pear/Config/Symfony/Component";b:1;s:48:"/opt/alt/php54/usr/share/doc/pear/Config/Symfony";b:1;s:40:"/opt/alt/php54/usr/share/doc/pear/Config";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition";b:1;s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Builder";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Dumper";b:1;s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Definition/Exception";b:1;s:64:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Exception";b:1;s:61:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Loader";b:1;s:66:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config";b:1;s:59:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component";b:1;s:49:"/opt/alt/php54/usr/share/pear/test/Config/Symfony";b:1;s:41:"/opt/alt/php54/usr/share/pear/test/Config";b:1;s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Resource";b:1;s:72:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition";b:1;s:91:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Builder";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Definition/Dumper";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Again";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Builder";b:1;s:95:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Configuration";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Fixtures/Util";b:1;s:79:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Loader";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Resource";b:1;s:77:"/opt/alt/php54/usr/share/pear/test/Config/Symfony/Component/Config/Tests/Util";b:1;s:59:"/opt/alt/php54/usr/share/pear/Symfony/Component/Config/Util";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506492;}PK!K2.registry/.channel.pear.symfony.com/httpkernel.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:10:"HttpKernel";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:29:"Symfony2 HttpKernel Component";s:11:"description";s:29:"Symfony2 HttpKernel Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:47";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:190:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a1af1bc22f997eb0aaeb301a8d715989";s:4:"name";s:43:"Symfony/Component/HttpKernel/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"034988ec8522419fef54715968ff5640";s:4:"name";s:46:"Symfony/Component/HttpKernel/Bundle/Bundle.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eced991d4b8fe038cf5a39d571e03389";s:4:"name";s:55:"Symfony/Component/HttpKernel/Bundle/BundleInterface.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1ab9fcfe250122ae01956d7d1df16c01";s:4:"name";s:67:"Symfony/Component/HttpKernel/CacheClearer/CacheClearerInterface.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"940b15c92fa6ba0a1e508239610228a8";s:4:"name";s:63:"Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7435d5f981a3db589251151722cebbf0";s:4:"name";s:56:"Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"07e93162aecd5b6c4dffea675f2684b1";s:4:"name";s:65:"Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"75d231528a43ed388b3b742e68b6c43a";s:4:"name";s:65:"Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerInterface.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d0ccc4f26ea62bd6a3d1c528664b49b5";s:4:"name";s:62:"Symfony/Component/HttpKernel/CacheWarmer/WarmableInterface.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2d18e70a6cd04cddb49776f32632599a";s:4:"name";s:41:"Symfony/Component/HttpKernel/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d1bc00e92123f8295cb75492e39f9dc5";s:4:"name";s:39:"Symfony/Component/HttpKernel/Client.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"44dd55d48bc718e4380133c689a1cc18";s:4:"name";s:42:"Symfony/Component/HttpKernel/composer.json";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8873220cb27f7c61053fc2feb76d138e";s:4:"name";s:51:"Symfony/Component/HttpKernel/Config/FileLocator.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a649fc31311b4b336290e86a7615eed0";s:4:"name";s:63:"Symfony/Component/HttpKernel/Controller/ControllerReference.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4df25d60d1eefb2844dcbaa250428ca8";s:4:"name";s:62:"Symfony/Component/HttpKernel/Controller/ControllerResolver.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"743a4faee533d426fe09db12e53501ab";s:4:"name";s:71:"Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"25b16c005e61a48d621c219456d553bc";s:4:"name";s:71:"Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e69af41765bee94a115225f3a5d25cf1";s:4:"name";s:66:"Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5dbe243c81e871e949be8298cadf4f4a";s:4:"name";s:60:"Symfony/Component/HttpKernel/DataCollector/DataCollector.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ffd4ec58caeabebaab60382110104899";s:4:"name";s:69:"Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"54add9b16cd4329326a940ce70255f7a";s:4:"name";s:65:"Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"206153be1698da0605d1dff2c04d6f7e";s:4:"name";s:69:"Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3cbcfac5aa0d0d92b5ffe9bfbdb4379d";s:4:"name";s:73:"Symfony/Component/HttpKernel/DataCollector/LateDataCollectorInterface.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7f91f64a97e2780be6d214434d1974aa";s:4:"name";s:66:"Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"39b08f06e47dbe55291666d79dfe77ea";s:4:"name";s:66:"Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6331bb9218f46832e73986ca4ad45a30";s:4:"name";s:67:"Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"27268087d500134868734ba6352b9c74";s:4:"name";s:66:"Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fce90930e38e9cd4641aacf2764ed6f4";s:4:"name";s:64:"Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d66d96e42598dea22dad278b9ac3b2a";s:4:"name";s:65:"Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ab27b3a991a404a9f83ad33c137ddc64";s:4:"name";s:51:"Symfony/Component/HttpKernel/Debug/ErrorHandler.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"abd0e561ece8935db9925995726a9c3a";s:4:"name";s:55:"Symfony/Component/HttpKernel/Debug/ExceptionHandler.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"42886c591f797433ebfa6c4a75e0fb34";s:4:"name";s:63:"Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6def64fd265b897b89f8e82b229ac9f3";s:4:"name";s:74:"Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"177422f6ff3ceb6a638f8a7e5ec4f166";s:4:"name";s:74:"Symfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"12960ef346b18a127742a5cda62960ac";s:4:"name";s:77:"Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"da97a0908acb2f0576a735ee424f424d";s:4:"name";s:62:"Symfony/Component/HttpKernel/DependencyInjection/Extension.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aef8eb59f79f4881d9f63e831c3c8546";s:4:"name";s:84:"Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2c9db8df37168a875bebf70976bc2bda";s:4:"name";s:74:"Symfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"947b8934d83f90492c51cfb3a4e8bf34";s:4:"name";s:60:"Symfony/Component/HttpKernel/Event/FilterControllerEvent.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c9c047b7ab1488a4eb857d71286c42eb";s:4:"name";s:58:"Symfony/Component/HttpKernel/Event/FilterResponseEvent.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aae774c8c1c640f429459d3800a02806";s:4:"name";s:57:"Symfony/Component/HttpKernel/Event/FinishRequestEvent.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63460a57e5067155dccae05cf237d193";s:4:"name";s:55:"Symfony/Component/HttpKernel/Event/GetResponseEvent.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9049ee5a681b82f0471a2a2f3b405a1e";s:4:"name";s:74:"Symfony/Component/HttpKernel/Event/GetResponseForControllerResultEvent.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86e1625ae2dbb2a4d98dff9d02365f00";s:4:"name";s:67:"Symfony/Component/HttpKernel/Event/GetResponseForExceptionEvent.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f7a5741350e52e946bd15455c71bff2a";s:4:"name";s:50:"Symfony/Component/HttpKernel/Event/KernelEvent.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"010c1849bb93d622dcabdcdbfa4f04a3";s:4:"name";s:56:"Symfony/Component/HttpKernel/Event/PostResponseEvent.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"892d5e12db614472e9aaa1f8aec879ab";s:4:"name";s:67:"Symfony/Component/HttpKernel/EventListener/ErrorsLoggerListener.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b9821a05b72584a3a374a93bee0f4314";s:4:"name";s:58:"Symfony/Component/HttpKernel/EventListener/EsiListener.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ec0b722acddc40bc24c04bcb735aefdc";s:4:"name";s:64:"Symfony/Component/HttpKernel/EventListener/ExceptionListener.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0f5e7d02ae8c0deb48e6da848e70c313";s:4:"name";s:63:"Symfony/Component/HttpKernel/EventListener/FragmentListener.php";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b300d4915a4478d77599e2cc5899f553";s:4:"name";s:61:"Symfony/Component/HttpKernel/EventListener/LocaleListener.php";s:4:"role";s:3:"php";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a80ed8fee6a904ffbebca1d9850182b8";s:4:"name";s:63:"Symfony/Component/HttpKernel/EventListener/ProfilerListener.php";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9f012c160c2b78e89e457aed4c054cf0";s:4:"name";s:63:"Symfony/Component/HttpKernel/EventListener/ResponseListener.php";s:4:"role";s:3:"php";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bcfe15dc4f5806b2a8516ef3509c38e3";s:4:"name";s:61:"Symfony/Component/HttpKernel/EventListener/RouterListener.php";s:4:"role";s:3:"php";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"04649898f8756be91b4907fd10654daf";s:4:"name";s:62:"Symfony/Component/HttpKernel/EventListener/SessionListener.php";s:4:"role";s:3:"php";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"57b574b30b287bfbe406beba0769749b";s:4:"name";s:71:"Symfony/Component/HttpKernel/EventListener/StreamedResponseListener.php";s:4:"role";s:3:"php";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c6a6e3f8b65f17d2dc889e4b2c99635b";s:4:"name";s:66:"Symfony/Component/HttpKernel/EventListener/TestSessionListener.php";s:4:"role";s:3:"php";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c73ec96922ce59adb33ca4bfefa8030c";s:4:"name";s:68:"Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php";s:4:"role";s:3:"php";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6cf7e6c73081980c26b6ecad6d0efc1b";s:4:"name";s:66:"Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php";s:4:"role";s:3:"php";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2d4d5a8229cf646d3b4b75d593f14d3b";s:4:"name";s:64:"Symfony/Component/HttpKernel/Exception/ConflictHttpException.php";s:4:"role";s:3:"php";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6b3122c7757ff734e12bec8a74c25a98";s:4:"name";s:62:"Symfony/Component/HttpKernel/Exception/FatalErrorException.php";s:4:"role";s:3:"php";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7a74b213d324d95f414b50650d893331";s:4:"name";s:59:"Symfony/Component/HttpKernel/Exception/FlattenException.php";s:4:"role";s:3:"php";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e8a597fe1f0d5b3525f9649f25ed78b9";s:4:"name";s:60:"Symfony/Component/HttpKernel/Exception/GoneHttpException.php";s:4:"role";s:3:"php";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dff8d6e0c64447e27bc68937a77dddd4";s:4:"name";s:56:"Symfony/Component/HttpKernel/Exception/HttpException.php";s:4:"role";s:3:"php";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5287f16f397ce02139bb29f4f915ba73";s:4:"name";s:65:"Symfony/Component/HttpKernel/Exception/HttpExceptionInterface.php";s:4:"role";s:3:"php";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c03fdcab809f96c2edf326ef5d329840";s:4:"name";s:70:"Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php";s:4:"role";s:3:"php";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"27a47db2975d463cc92750a50af7b692";s:4:"name";s:72:"Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php";s:4:"role";s:3:"php";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ef3c26636669dab061813267c477ea3a";s:4:"name";s:69:"Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php";s:4:"role";s:3:"php";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e082b7408c1b8c6b4e89c909db565d24";s:4:"name";s:64:"Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php";s:4:"role";s:3:"php";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"59bc8fe9c3f62fed6aa80c7004b175b1";s:4:"name";s:74:"Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php";s:4:"role";s:3:"php";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f389be4cfb101bc034f78207e8918de9";s:4:"name";s:76:"Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php";s:4:"role";s:3:"php";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e4519a15bbd32746e2cdb50690432dca";s:4:"name";s:74:"Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php";s:4:"role";s:3:"php";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a11ab40bfda34f0f200196711b7a1a5e";s:4:"name";s:71:"Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php";s:4:"role";s:3:"php";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2bc4556d5f4010d1b0d6eb59a6d99295";s:4:"name";s:68:"Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php";s:4:"role";s:3:"php";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"54ea4537a407708dc6a1fa2b614e6092";s:4:"name";s:76:"Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php";s:4:"role";s:3:"php";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"90c57168f27173fdb9c128cc3dceec6c";s:4:"name";s:61:"Symfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.php";s:4:"role";s:3:"php";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e7b606e96e7696fefaf0290bd134a364";s:4:"name";s:57:"Symfony/Component/HttpKernel/Fragment/FragmentHandler.php";s:4:"role";s:3:"php";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"92c2b17efc0ff03094dbe55603835cd7";s:4:"name";s:67:"Symfony/Component/HttpKernel/Fragment/FragmentRendererInterface.php";s:4:"role";s:3:"php";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eb63af63d6d386b8ce0b6faeda979a5c";s:4:"name";s:66:"Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php";s:4:"role";s:3:"php";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"71d698c9b1e16a25819450db6db7cb57";s:4:"name";s:64:"Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php";s:4:"role";s:3:"php";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fbce96e11756ed0deb106c0192e29a8a";s:4:"name";s:66:"Symfony/Component/HttpKernel/Fragment/RoutableFragmentRenderer.php";s:4:"role";s:3:"php";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fa7788cbb3d094b334c129d4b12df2f1";s:4:"name";s:46:"Symfony/Component/HttpKernel/HttpCache/Esi.php";s:4:"role";s:3:"php";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"45e69313f1a53d5ebab91bf3c18d48ec";s:4:"name";s:67:"Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php";s:4:"role";s:3:"php";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"091ed77cd920fc81d7cc3fa663a20be4";s:4:"name";s:76:"Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.php";s:4:"role";s:3:"php";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c49bf34675051f7bed1f6444d720a412";s:4:"name";s:52:"Symfony/Component/HttpKernel/HttpCache/HttpCache.php";s:4:"role";s:3:"php";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a5f55c6da48996bf5e0cec62eb9dfa9b";s:4:"name";s:48:"Symfony/Component/HttpKernel/HttpCache/Store.php";s:4:"role";s:3:"php";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"23cb34a2a464e310a6cc4ad8053190b4";s:4:"name";s:57:"Symfony/Component/HttpKernel/HttpCache/StoreInterface.php";s:4:"role";s:3:"php";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"90b674ef382b3241a3533e5561c285e3";s:4:"name";s:43:"Symfony/Component/HttpKernel/HttpKernel.php";s:4:"role";s:3:"php";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a26257098916c1d939b7b0a04f44dfb8";s:4:"name";s:52:"Symfony/Component/HttpKernel/HttpKernelInterface.php";s:4:"role";s:3:"php";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba5fe007a2ac71d42ccc2c8d10cf5326";s:4:"name";s:39:"Symfony/Component/HttpKernel/Kernel.php";s:4:"role";s:3:"php";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"84732b3d13c1d962a9ca76189f5f5086";s:4:"name";s:45:"Symfony/Component/HttpKernel/KernelEvents.php";s:4:"role";s:3:"php";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b2547cd0399c7d610c3c31bf8fafc1c1";s:4:"name";s:48:"Symfony/Component/HttpKernel/KernelInterface.php";s:4:"role";s:3:"php";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/HttpKernel/LICENSE";s:4:"role";s:3:"doc";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"729e7e46e4dd1a18559aa41e58548e09";s:4:"name";s:57:"Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php";s:4:"role";s:3:"php";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a63e038a0c6c529619b2197afcf54e57";s:4:"name";s:52:"Symfony/Component/HttpKernel/Log/LoggerInterface.php";s:4:"role";s:3:"php";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fdaed4279e4932db9593cab3d9801f80";s:4:"name";s:47:"Symfony/Component/HttpKernel/Log/NullLogger.php";s:4:"role";s:3:"php";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"480db13c5bc7a6911c241df127572a69";s:4:"name";s:45:"Symfony/Component/HttpKernel/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f42eab7a5e7ec989509aefc70a57e76c";s:4:"name";s:69:"Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php";s:4:"role";s:3:"php";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a0a7571fcf3f33c4958016fef0ac6e1";s:4:"name";s:61:"Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php";s:4:"role";s:3:"php";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c6e448f617b7211c44095e8730c4a2bd";s:4:"name";s:66:"Symfony/Component/HttpKernel/Profiler/MemcachedProfilerStorage.php";s:4:"role";s:3:"php";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"439c84953c390c2310af0b269b63c37b";s:4:"name";s:65:"Symfony/Component/HttpKernel/Profiler/MemcacheProfilerStorage.php";s:4:"role";s:3:"php";}}i:101;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c1743fb29d46daedfa747ed47b9494c1";s:4:"name";s:64:"Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.php";s:4:"role";s:3:"php";}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4d2027032d2e5c190aa65e54394db133";s:4:"name";s:62:"Symfony/Component/HttpKernel/Profiler/MysqlProfilerStorage.php";s:4:"role";s:3:"php";}}i:103;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d24566fd44b8a4b06c64127a5a03c2a";s:4:"name";s:60:"Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php";s:4:"role";s:3:"php";}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"af734240bcbd3fc0ecfc377333f9bcd9";s:4:"name";s:49:"Symfony/Component/HttpKernel/Profiler/Profile.php";s:4:"role";s:3:"php";}}i:105;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3433ee1c2d23c78d68774f83c97eb578";s:4:"name";s:50:"Symfony/Component/HttpKernel/Profiler/Profiler.php";s:4:"role";s:3:"php";}}i:106;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"17d9e40eefdb2fad667dc74ebf858c85";s:4:"name";s:66:"Symfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.php";s:4:"role";s:3:"php";}}i:107;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e10da26d143cc3a6336f7e97c7f4d535";s:4:"name";s:62:"Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php";s:4:"role";s:3:"php";}}i:108;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b69028b6ff27fff88714b26e65d6d6cf";s:4:"name";s:63:"Symfony/Component/HttpKernel/Profiler/SqliteProfilerStorage.php";s:4:"role";s:3:"php";}}i:109;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a88bdc6a3df6948b04db2f5d8c76c865";s:4:"name";s:38:"Symfony/Component/HttpKernel/README.md";s:4:"role";s:3:"doc";}}i:110;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63651d1c2efa91187e171c23fa108bcc";s:4:"name";s:52:"Symfony/Component/HttpKernel/TerminableInterface.php";s:4:"role";s:3:"php";}}i:111;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5db4015a25ec64975433954495425cb9";s:4:"name";s:56:"Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php";s:4:"role";s:4:"test";}}i:112;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"719d0acb32f69e30070481fc995d7c95";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php";s:4:"role";s:4:"test";}}i:113;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a670a188bc612138042a48ce08d0d86c";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php";s:4:"role";s:4:"test";}}i:114;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa85344cf1c9a4ea3472caad8fd270e1";s:4:"name";s:66:"Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.php";s:4:"role";s:4:"test";}}i:115;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d8434d3e6d9ab70624691695c0463227";s:4:"name";s:49:"Symfony/Component/HttpKernel/Tests/ClientTest.php";s:4:"role";s:4:"test";}}i:116;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5e1515ccdd440d46fca79579beb81ea1";s:4:"name";s:61:"Symfony/Component/HttpKernel/Tests/Config/FileLocatorTest.php";s:4:"role";s:4:"test";}}i:117;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"537f569f63ee14058800342fc3e0a242";s:4:"name";s:72:"Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php";s:4:"role";s:4:"test";}}i:118;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"39a22588190c09f58431a38ce9ebd6bc";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.php";s:4:"role";s:4:"test";}}i:119;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0cf6afafd5af55e00d3c5f9ba31d8917";s:4:"name";s:79:"Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php";s:4:"role";s:4:"test";}}i:120;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"db74032e31e4161dc21aaf9443a4910f";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php";s:4:"role";s:4:"test";}}i:121;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dd889c18076eab8becd1544e90472aae";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.php";s:4:"role";s:4:"test";}}i:122;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cdab18131698b1915f326cbe376097c2";s:4:"name";s:77:"Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php";s:4:"role";s:4:"test";}}i:123;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cad604b1dab9e0178b105ccee837ab52";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/DataCollector/TimeDataCollectorTest.php";s:4:"role";s:4:"test";}}i:124;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47bb53262ba95915cc2f7c2c905ccd04";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php";s:4:"role";s:4:"test";}}i:125;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"761aed0102e13403661542c40ff2441a";s:4:"name";s:87:"Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php";s:4:"role";s:4:"test";}}i:126;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"92e4fbfef80def18781bd8a16000b2ec";s:4:"name";s:94:"Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php";s:4:"role";s:4:"test";}}i:127;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8ec326aa5b3ad38b2aceb0f6f9f2b17";s:4:"name";s:84:"Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterListenersPassTest.php";s:4:"role";s:4:"test";}}i:128;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0af1d216963fc1ad9bf090060c450f69";s:4:"name";s:68:"Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.php";s:4:"role";s:4:"test";}}i:129;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3d35f03216a8c24fbec0d4690f6a4e9b";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php";s:4:"role";s:4:"test";}}i:130;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2b58c87811bcb1e4d1e01a66b57d4a28";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/EventListener/FragmentListenerTest.php";s:4:"role";s:4:"test";}}i:131;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4e1ca37427ffb634328d287bf5bb179b";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php";s:4:"role";s:4:"test";}}i:132;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0badf4d0b6a602b51de96b965d34b5a4";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.php";s:4:"role";s:4:"test";}}i:133;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"459a71cfa659bd53df29387cabad577b";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php";s:4:"role";s:4:"test";}}i:134;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"60d79091d972859015aeea894ceb632f";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php";s:4:"role";s:4:"test";}}i:135;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c3c274823c0ae42288813e3881f5b2d9";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php";s:4:"role";s:4:"test";}}i:136;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:72:"Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txt";s:4:"role";s:4:"test";}}i:137;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txt";s:4:"role";s:4:"test";}}i:138;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:65:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txt";s:4:"role";s:4:"test";}}i:139;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:65:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txt";s:4:"role";s:4:"test";}}i:140;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt";s:4:"role";s:4:"test";}}i:141;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:65:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle/foo.txt";s:4:"role";s:4:"test";}}i:142;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9ab5af02cc19f043e6ab4c12f826be86";s:4:"name";s:66:"Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/classes.map";s:4:"role";s:4:"test";}}i:143;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0d04f0c8627b1c410d6d47246199fb55";s:4:"name";s:89:"Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/MockObjectTestProjectContainer.php";s:4:"role";s:4:"test";}}i:144;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txt";s:4:"role";s:4:"test";}}i:145;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txt";s:4:"role";s:4:"test";}}i:146;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"087e3dc7776e8d94ff7ae2852dc912bd";s:4:"name";s:91:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php";s:4:"role";s:4:"test";}}i:147;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"27015c77094432ed5a984416d760fd74";s:4:"name";s:114:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php";s:4:"role";s:4:"test";}}i:148;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a1e589e6fb85f086e2d31f4f37e62fe9";s:4:"name";s:91:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php";s:4:"role";s:4:"test";}}i:149;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6cbbfc883c6a2ff486474f87476f0563";s:4:"name";s:89:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php";s:4:"role";s:4:"test";}}i:150;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"54610c5e45d73507ef3b70c59a6140c2";s:4:"name";s:89:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php";s:4:"role";s:4:"test";}}i:151;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"580c52df0c49dbe51b8953eafa44adff";s:4:"name";s:116:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php";s:4:"role";s:4:"test";}}i:152;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2b6b77bad66ea379f550eeaa0c99476";s:4:"name";s:93:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php";s:4:"role";s:4:"test";}}i:153;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f5505afbf35dae7260891f4a9fd1cfd4";s:4:"name";s:60:"Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.php";s:4:"role";s:4:"test";}}i:154;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"468ec4e8ecf949b24336c3e2557bc7bf";s:4:"name";s:69:"Symfony/Component/HttpKernel/Tests/Fixtures/KernelForOverrideName.php";s:4:"role";s:4:"test";}}i:155;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c9615a710a6e8dfdb0dd2daaa77b8377";s:4:"name";s:61:"Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php";s:4:"role";s:4:"test";}}i:156;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txt";s:4:"role";s:4:"test";}}i:157;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt";s:4:"role";s:4:"test";}}i:158;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txt";s:4:"role";s:4:"test";}}i:159;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txt";s:4:"role";s:4:"test";}}i:160;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"caac83e9f7141808a279c9415b3d631d";s:4:"name";s:58:"Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.php";s:4:"role";s:4:"test";}}i:161;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cf1be212b7c33954b81cbb5f17f90901";s:4:"name";s:67:"Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php";s:4:"role";s:4:"test";}}i:162;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc9d6216414586747e3857fcc1884c33";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.php";s:4:"role";s:4:"test";}}i:163;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fa6ac6afb43b8f9f17bac5f34b8079b1";s:4:"name";s:67:"Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.php";s:4:"role";s:4:"test";}}i:164;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d42e11990c445631c29d351e1050bc12";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.php";s:4:"role";s:4:"test";}}i:165;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0914364078b13a058fc4ad858a9a97a2";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php";s:4:"role";s:4:"test";}}i:166;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"99d3a3885bcaaeaa9d7daa7628d16b6b";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.php";s:4:"role";s:4:"test";}}i:167;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0839be428bd44e163cd68390f4ef49da";s:4:"name";s:56:"Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php";s:4:"role";s:4:"test";}}i:168;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"58d82c49cec84700cfeac27313345271";s:4:"name";s:62:"Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php";s:4:"role";s:4:"test";}}i:169;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b03bb6f91a5309a1e83e6b892a9759cc";s:4:"name";s:66:"Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php";s:4:"role";s:4:"test";}}i:170;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"070e9eeb7eff1f89e79917937aa7b692";s:4:"name";s:58:"Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php";s:4:"role";s:4:"test";}}i:171;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9968d637c2ee0189e7983c285f1cb353";s:4:"name";s:63:"Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php";s:4:"role";s:4:"test";}}i:172;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f8033c30b37e92bfbc3c61885dc4f6d2";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php";s:4:"role";s:4:"test";}}i:173;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cc31bf84e75276fcc9efa9f5f0c45302";s:4:"name";s:53:"Symfony/Component/HttpKernel/Tests/HttpKernelTest.php";s:4:"role";s:4:"test";}}i:174;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"985b62eefe124bbd995e6c9da0b46dbf";s:4:"name";s:49:"Symfony/Component/HttpKernel/Tests/KernelTest.php";s:4:"role";s:4:"test";}}i:175;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f544395e09366b61d2e01f49c15066ff";s:4:"name";s:45:"Symfony/Component/HttpKernel/Tests/Logger.php";s:4:"role";s:4:"test";}}i:176;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3d025b1cac5e80626a19849b06a41e91";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.php";s:4:"role";s:4:"test";}}i:177;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"12f40567e2687864d629e2437915b127";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.php";s:4:"role";s:4:"test";}}i:178;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f88559896ea0d7bea467da273976fcc3";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.php";s:4:"role";s:4:"test";}}i:179;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"285f9b91923d397ff0704c465eb76378";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.php";s:4:"role";s:4:"test";}}i:180;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a9448076fbd5c7d42bb595bf6626226b";s:4:"name";s:66:"Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcachedMock.php";s:4:"role";s:4:"test";}}i:181;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aaee125b4e1132032c58f5ca4c03bb40";s:4:"name";s:65:"Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcacheMock.php";s:4:"role";s:4:"test";}}i:182;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"796c2e18d225e482facc9de766f8bba7";s:4:"name";s:62:"Symfony/Component/HttpKernel/Tests/Profiler/Mock/RedisMock.php";s:4:"role";s:4:"test";}}i:183;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ed9ba23032795739acc33ba5d1970557";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.php";s:4:"role";s:4:"test";}}i:184;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9a65333f51c36b0b6a837f1105c2d022";s:4:"name";s:60:"Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php";s:4:"role";s:4:"test";}}i:185;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e84fca3c3f76faa48cf1b760ab1fc079";s:4:"name";s:72:"Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.php";s:4:"role";s:4:"test";}}i:186;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fad36380de80995905e7a2046f3d01b0";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.php";s:4:"role";s:4:"test";}}i:187;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b8daaba0cf9db86b60c25116c7ab8a4";s:4:"name";s:53:"Symfony/Component/HttpKernel/Tests/TestHttpKernel.php";s:4:"role";s:4:"test";}}i:188;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bf06babf2bdca6d62c7960c8a9e53e68";s:4:"name";s:52:"Symfony/Component/HttpKernel/Tests/UriSignerTest.php";s:4:"role";s:4:"test";}}i:189;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9daa3c983b391a8dae8e4e7b34f26e07";s:4:"name";s:42:"Symfony/Component/HttpKernel/UriSigner.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}s:7:"package";a:2:{i:0;a:2:{s:4:"name";s:14:"HttpFoundation";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:15:"EventDispatcher";s:7:"channel";s:16:"pear.symfony.com";}}}s:8:"optional";a:1:{s:7:"package";a:6:{i:0;a:2:{s:4:"name";s:6:"Config";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:19:"DependencyInjection";s:7:"channel";s:16:"pear.symfony.com";}i:2;a:2:{s:4:"name";s:11:"ClassLoader";s:7:"channel";s:16:"pear.symfony.com";}i:3;a:2:{s:4:"name";s:10:"BrowserKit";s:7:"channel";s:16:"pear.symfony.com";}i:4;a:2:{s:4:"name";s:7:"Console";s:7:"channel";s:16:"pear.symfony.com";}i:5;a:2:{s:4:"name";s:6:"Finder";s:7:"channel";s:16:"pear.symfony.com";}}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:190:{s:43:"Symfony/Component/HttpKernel/autoloader.php";a:4:{s:6:"md5sum";s:32:"a1af1bc22f997eb0aaeb301a8d715989";s:4:"name";s:43:"Symfony/Component/HttpKernel/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/autoloader.php";}s:46:"Symfony/Component/HttpKernel/Bundle/Bundle.php";a:4:{s:6:"md5sum";s:32:"034988ec8522419fef54715968ff5640";s:4:"name";s:46:"Symfony/Component/HttpKernel/Bundle/Bundle.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Bundle/Bundle.php";}s:55:"Symfony/Component/HttpKernel/Bundle/BundleInterface.php";a:4:{s:6:"md5sum";s:32:"eced991d4b8fe038cf5a39d571e03389";s:4:"name";s:55:"Symfony/Component/HttpKernel/Bundle/BundleInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Bundle/BundleInterface.php";}s:67:"Symfony/Component/HttpKernel/CacheClearer/CacheClearerInterface.php";a:4:{s:6:"md5sum";s:32:"1ab9fcfe250122ae01956d7d1df16c01";s:4:"name";s:67:"Symfony/Component/HttpKernel/CacheClearer/CacheClearerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/CacheClearer/CacheClearerInterface.php";}s:63:"Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.php";a:4:{s:6:"md5sum";s:32:"940b15c92fa6ba0a1e508239610228a8";s:4:"name";s:63:"Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.php";}s:56:"Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php";a:4:{s:6:"md5sum";s:32:"7435d5f981a3db589251151722cebbf0";s:4:"name";s:56:"Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php";}s:65:"Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php";a:4:{s:6:"md5sum";s:32:"07e93162aecd5b6c4dffea675f2684b1";s:4:"name";s:65:"Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php";}s:65:"Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerInterface.php";a:4:{s:6:"md5sum";s:32:"75d231528a43ed388b3b742e68b6c43a";s:4:"name";s:65:"Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerInterface.php";}s:62:"Symfony/Component/HttpKernel/CacheWarmer/WarmableInterface.php";a:4:{s:6:"md5sum";s:32:"d0ccc4f26ea62bd6a3d1c528664b49b5";s:4:"name";s:62:"Symfony/Component/HttpKernel/CacheWarmer/WarmableInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/CacheWarmer/WarmableInterface.php";}s:41:"Symfony/Component/HttpKernel/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"2d18e70a6cd04cddb49776f32632599a";s:4:"name";s:41:"Symfony/Component/HttpKernel/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/doc/pear/HttpKernel/Symfony/Component/HttpKernel/CHANGELOG.md";}s:39:"Symfony/Component/HttpKernel/Client.php";a:4:{s:6:"md5sum";s:32:"d1bc00e92123f8295cb75492e39f9dc5";s:4:"name";s:39:"Symfony/Component/HttpKernel/Client.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Client.php";}s:42:"Symfony/Component/HttpKernel/composer.json";a:4:{s:6:"md5sum";s:32:"44dd55d48bc718e4380133c689a1cc18";s:4:"name";s:42:"Symfony/Component/HttpKernel/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/HttpKernel/Symfony/Component/HttpKernel/composer.json";}s:51:"Symfony/Component/HttpKernel/Config/FileLocator.php";a:4:{s:6:"md5sum";s:32:"8873220cb27f7c61053fc2feb76d138e";s:4:"name";s:51:"Symfony/Component/HttpKernel/Config/FileLocator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Config/FileLocator.php";}s:63:"Symfony/Component/HttpKernel/Controller/ControllerReference.php";a:4:{s:6:"md5sum";s:32:"a649fc31311b4b336290e86a7615eed0";s:4:"name";s:63:"Symfony/Component/HttpKernel/Controller/ControllerReference.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Controller/ControllerReference.php";}s:62:"Symfony/Component/HttpKernel/Controller/ControllerResolver.php";a:4:{s:6:"md5sum";s:32:"4df25d60d1eefb2844dcbaa250428ca8";s:4:"name";s:62:"Symfony/Component/HttpKernel/Controller/ControllerResolver.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Controller/ControllerResolver.php";}s:71:"Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php";a:4:{s:6:"md5sum";s:32:"743a4faee533d426fe09db12e53501ab";s:4:"name";s:71:"Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php";}s:71:"Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php";a:4:{s:6:"md5sum";s:32:"25b16c005e61a48d621c219456d553bc";s:4:"name";s:71:"Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php";}s:66:"Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php";a:4:{s:6:"md5sum";s:32:"e69af41765bee94a115225f3a5d25cf1";s:4:"name";s:66:"Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php";}s:60:"Symfony/Component/HttpKernel/DataCollector/DataCollector.php";a:4:{s:6:"md5sum";s:32:"5dbe243c81e871e949be8298cadf4f4a";s:4:"name";s:60:"Symfony/Component/HttpKernel/DataCollector/DataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/DataCollector.php";}s:69:"Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php";a:4:{s:6:"md5sum";s:32:"ffd4ec58caeabebaab60382110104899";s:4:"name";s:69:"Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php";}s:65:"Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php";a:4:{s:6:"md5sum";s:32:"54add9b16cd4329326a940ce70255f7a";s:4:"name";s:65:"Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php";}s:69:"Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php";a:4:{s:6:"md5sum";s:32:"206153be1698da0605d1dff2c04d6f7e";s:4:"name";s:69:"Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php";}s:73:"Symfony/Component/HttpKernel/DataCollector/LateDataCollectorInterface.php";a:4:{s:6:"md5sum";s:32:"3cbcfac5aa0d0d92b5ffe9bfbdb4379d";s:4:"name";s:73:"Symfony/Component/HttpKernel/DataCollector/LateDataCollectorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/LateDataCollectorInterface.php";}s:66:"Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php";a:4:{s:6:"md5sum";s:32:"7f91f64a97e2780be6d214434d1974aa";s:4:"name";s:66:"Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php";}s:66:"Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php";a:4:{s:6:"md5sum";s:32:"39b08f06e47dbe55291666d79dfe77ea";s:4:"name";s:66:"Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php";}s:67:"Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php";a:4:{s:6:"md5sum";s:32:"6331bb9218f46832e73986ca4ad45a30";s:4:"name";s:67:"Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php";}s:66:"Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php";a:4:{s:6:"md5sum";s:32:"27268087d500134868734ba6352b9c74";s:4:"name";s:66:"Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php";}s:64:"Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php";a:4:{s:6:"md5sum";s:32:"fce90930e38e9cd4641aacf2764ed6f4";s:4:"name";s:64:"Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php";}s:65:"Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php";a:4:{s:6:"md5sum";s:32:"7d66d96e42598dea22dad278b9ac3b2a";s:4:"name";s:65:"Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php";}s:51:"Symfony/Component/HttpKernel/Debug/ErrorHandler.php";a:4:{s:6:"md5sum";s:32:"ab27b3a991a404a9f83ad33c137ddc64";s:4:"name";s:51:"Symfony/Component/HttpKernel/Debug/ErrorHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Debug/ErrorHandler.php";}s:55:"Symfony/Component/HttpKernel/Debug/ExceptionHandler.php";a:4:{s:6:"md5sum";s:32:"abd0e561ece8935db9925995726a9c3a";s:4:"name";s:55:"Symfony/Component/HttpKernel/Debug/ExceptionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Debug/ExceptionHandler.php";}s:63:"Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php";a:4:{s:6:"md5sum";s:32:"42886c591f797433ebfa6c4a75e0fb34";s:4:"name";s:63:"Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php";}s:74:"Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php";a:4:{s:6:"md5sum";s:32:"6def64fd265b897b89f8e82b229ac9f3";s:4:"name";s:74:"Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php";}s:74:"Symfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.php";a:4:{s:6:"md5sum";s:32:"177422f6ff3ceb6a638f8a7e5ec4f166";s:4:"name";s:74:"Symfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.php";}s:77:"Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php";a:4:{s:6:"md5sum";s:32:"12960ef346b18a127742a5cda62960ac";s:4:"name";s:77:"Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php";}s:62:"Symfony/Component/HttpKernel/DependencyInjection/Extension.php";a:4:{s:6:"md5sum";s:32:"da97a0908acb2f0576a735ee424f424d";s:4:"name";s:62:"Symfony/Component/HttpKernel/DependencyInjection/Extension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DependencyInjection/Extension.php";}s:84:"Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php";a:4:{s:6:"md5sum";s:32:"aef8eb59f79f4881d9f63e831c3c8546";s:4:"name";s:84:"Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php";}s:74:"Symfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.php";a:4:{s:6:"md5sum";s:32:"2c9db8df37168a875bebf70976bc2bda";s:4:"name";s:74:"Symfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.php";}s:60:"Symfony/Component/HttpKernel/Event/FilterControllerEvent.php";a:4:{s:6:"md5sum";s:32:"947b8934d83f90492c51cfb3a4e8bf34";s:4:"name";s:60:"Symfony/Component/HttpKernel/Event/FilterControllerEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Event/FilterControllerEvent.php";}s:58:"Symfony/Component/HttpKernel/Event/FilterResponseEvent.php";a:4:{s:6:"md5sum";s:32:"c9c047b7ab1488a4eb857d71286c42eb";s:4:"name";s:58:"Symfony/Component/HttpKernel/Event/FilterResponseEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Event/FilterResponseEvent.php";}s:57:"Symfony/Component/HttpKernel/Event/FinishRequestEvent.php";a:4:{s:6:"md5sum";s:32:"aae774c8c1c640f429459d3800a02806";s:4:"name";s:57:"Symfony/Component/HttpKernel/Event/FinishRequestEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Event/FinishRequestEvent.php";}s:55:"Symfony/Component/HttpKernel/Event/GetResponseEvent.php";a:4:{s:6:"md5sum";s:32:"63460a57e5067155dccae05cf237d193";s:4:"name";s:55:"Symfony/Component/HttpKernel/Event/GetResponseEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Event/GetResponseEvent.php";}s:74:"Symfony/Component/HttpKernel/Event/GetResponseForControllerResultEvent.php";a:4:{s:6:"md5sum";s:32:"9049ee5a681b82f0471a2a2f3b405a1e";s:4:"name";s:74:"Symfony/Component/HttpKernel/Event/GetResponseForControllerResultEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Event/GetResponseForControllerResultEvent.php";}s:67:"Symfony/Component/HttpKernel/Event/GetResponseForExceptionEvent.php";a:4:{s:6:"md5sum";s:32:"86e1625ae2dbb2a4d98dff9d02365f00";s:4:"name";s:67:"Symfony/Component/HttpKernel/Event/GetResponseForExceptionEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Event/GetResponseForExceptionEvent.php";}s:50:"Symfony/Component/HttpKernel/Event/KernelEvent.php";a:4:{s:6:"md5sum";s:32:"f7a5741350e52e946bd15455c71bff2a";s:4:"name";s:50:"Symfony/Component/HttpKernel/Event/KernelEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Event/KernelEvent.php";}s:56:"Symfony/Component/HttpKernel/Event/PostResponseEvent.php";a:4:{s:6:"md5sum";s:32:"010c1849bb93d622dcabdcdbfa4f04a3";s:4:"name";s:56:"Symfony/Component/HttpKernel/Event/PostResponseEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Event/PostResponseEvent.php";}s:67:"Symfony/Component/HttpKernel/EventListener/ErrorsLoggerListener.php";a:4:{s:6:"md5sum";s:32:"892d5e12db614472e9aaa1f8aec879ab";s:4:"name";s:67:"Symfony/Component/HttpKernel/EventListener/ErrorsLoggerListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/ErrorsLoggerListener.php";}s:58:"Symfony/Component/HttpKernel/EventListener/EsiListener.php";a:4:{s:6:"md5sum";s:32:"b9821a05b72584a3a374a93bee0f4314";s:4:"name";s:58:"Symfony/Component/HttpKernel/EventListener/EsiListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/EsiListener.php";}s:64:"Symfony/Component/HttpKernel/EventListener/ExceptionListener.php";a:4:{s:6:"md5sum";s:32:"ec0b722acddc40bc24c04bcb735aefdc";s:4:"name";s:64:"Symfony/Component/HttpKernel/EventListener/ExceptionListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php";}s:63:"Symfony/Component/HttpKernel/EventListener/FragmentListener.php";a:4:{s:6:"md5sum";s:32:"0f5e7d02ae8c0deb48e6da848e70c313";s:4:"name";s:63:"Symfony/Component/HttpKernel/EventListener/FragmentListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/FragmentListener.php";}s:61:"Symfony/Component/HttpKernel/EventListener/LocaleListener.php";a:4:{s:6:"md5sum";s:32:"b300d4915a4478d77599e2cc5899f553";s:4:"name";s:61:"Symfony/Component/HttpKernel/EventListener/LocaleListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/LocaleListener.php";}s:63:"Symfony/Component/HttpKernel/EventListener/ProfilerListener.php";a:4:{s:6:"md5sum";s:32:"a80ed8fee6a904ffbebca1d9850182b8";s:4:"name";s:63:"Symfony/Component/HttpKernel/EventListener/ProfilerListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php";}s:63:"Symfony/Component/HttpKernel/EventListener/ResponseListener.php";a:4:{s:6:"md5sum";s:32:"9f012c160c2b78e89e457aed4c054cf0";s:4:"name";s:63:"Symfony/Component/HttpKernel/EventListener/ResponseListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/ResponseListener.php";}s:61:"Symfony/Component/HttpKernel/EventListener/RouterListener.php";a:4:{s:6:"md5sum";s:32:"bcfe15dc4f5806b2a8516ef3509c38e3";s:4:"name";s:61:"Symfony/Component/HttpKernel/EventListener/RouterListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/RouterListener.php";}s:62:"Symfony/Component/HttpKernel/EventListener/SessionListener.php";a:4:{s:6:"md5sum";s:32:"04649898f8756be91b4907fd10654daf";s:4:"name";s:62:"Symfony/Component/HttpKernel/EventListener/SessionListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/SessionListener.php";}s:71:"Symfony/Component/HttpKernel/EventListener/StreamedResponseListener.php";a:4:{s:6:"md5sum";s:32:"57b574b30b287bfbe406beba0769749b";s:4:"name";s:71:"Symfony/Component/HttpKernel/EventListener/StreamedResponseListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/StreamedResponseListener.php";}s:66:"Symfony/Component/HttpKernel/EventListener/TestSessionListener.php";a:4:{s:6:"md5sum";s:32:"c6a6e3f8b65f17d2dc889e4b2c99635b";s:4:"name";s:66:"Symfony/Component/HttpKernel/EventListener/TestSessionListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener/TestSessionListener.php";}s:68:"Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php";a:4:{s:6:"md5sum";s:32:"c73ec96922ce59adb33ca4bfefa8030c";s:4:"name";s:68:"Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php";}s:66:"Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php";a:4:{s:6:"md5sum";s:32:"6cf7e6c73081980c26b6ecad6d0efc1b";s:4:"name";s:66:"Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php";}s:64:"Symfony/Component/HttpKernel/Exception/ConflictHttpException.php";a:4:{s:6:"md5sum";s:32:"2d4d5a8229cf646d3b4b75d593f14d3b";s:4:"name";s:64:"Symfony/Component/HttpKernel/Exception/ConflictHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php";}s:62:"Symfony/Component/HttpKernel/Exception/FatalErrorException.php";a:4:{s:6:"md5sum";s:32:"6b3122c7757ff734e12bec8a74c25a98";s:4:"name";s:62:"Symfony/Component/HttpKernel/Exception/FatalErrorException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/FatalErrorException.php";}s:59:"Symfony/Component/HttpKernel/Exception/FlattenException.php";a:4:{s:6:"md5sum";s:32:"7a74b213d324d95f414b50650d893331";s:4:"name";s:59:"Symfony/Component/HttpKernel/Exception/FlattenException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/FlattenException.php";}s:60:"Symfony/Component/HttpKernel/Exception/GoneHttpException.php";a:4:{s:6:"md5sum";s:32:"e8a597fe1f0d5b3525f9649f25ed78b9";s:4:"name";s:60:"Symfony/Component/HttpKernel/Exception/GoneHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/GoneHttpException.php";}s:56:"Symfony/Component/HttpKernel/Exception/HttpException.php";a:4:{s:6:"md5sum";s:32:"dff8d6e0c64447e27bc68937a77dddd4";s:4:"name";s:56:"Symfony/Component/HttpKernel/Exception/HttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/HttpException.php";}s:65:"Symfony/Component/HttpKernel/Exception/HttpExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"5287f16f397ce02139bb29f4f915ba73";s:4:"name";s:65:"Symfony/Component/HttpKernel/Exception/HttpExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/HttpExceptionInterface.php";}s:70:"Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php";a:4:{s:6:"md5sum";s:32:"c03fdcab809f96c2edf326ef5d329840";s:4:"name";s:70:"Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php";}s:72:"Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php";a:4:{s:6:"md5sum";s:32:"27a47db2975d463cc92750a50af7b692";s:4:"name";s:72:"Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php";}s:69:"Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php";a:4:{s:6:"md5sum";s:32:"ef3c26636669dab061813267c477ea3a";s:4:"name";s:69:"Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php";}s:64:"Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php";a:4:{s:6:"md5sum";s:32:"e082b7408c1b8c6b4e89c909db565d24";s:4:"name";s:64:"Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php";}s:74:"Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php";a:4:{s:6:"md5sum";s:32:"59bc8fe9c3f62fed6aa80c7004b175b1";s:4:"name";s:74:"Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php";}s:76:"Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php";a:4:{s:6:"md5sum";s:32:"f389be4cfb101bc034f78207e8918de9";s:4:"name";s:76:"Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php";}s:74:"Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php";a:4:{s:6:"md5sum";s:32:"e4519a15bbd32746e2cdb50690432dca";s:4:"name";s:74:"Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php";}s:71:"Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php";a:4:{s:6:"md5sum";s:32:"a11ab40bfda34f0f200196711b7a1a5e";s:4:"name";s:71:"Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php";}s:68:"Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php";a:4:{s:6:"md5sum";s:32:"2bc4556d5f4010d1b0d6eb59a6d99295";s:4:"name";s:68:"Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php";}s:76:"Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php";a:4:{s:6:"md5sum";s:32:"54ea4537a407708dc6a1fa2b614e6092";s:4:"name";s:76:"Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php";}s:61:"Symfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.php";a:4:{s:6:"md5sum";s:32:"90c57168f27173fdb9c128cc3dceec6c";s:4:"name";s:61:"Symfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.php";}s:57:"Symfony/Component/HttpKernel/Fragment/FragmentHandler.php";a:4:{s:6:"md5sum";s:32:"e7b606e96e7696fefaf0290bd134a364";s:4:"name";s:57:"Symfony/Component/HttpKernel/Fragment/FragmentHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Fragment/FragmentHandler.php";}s:67:"Symfony/Component/HttpKernel/Fragment/FragmentRendererInterface.php";a:4:{s:6:"md5sum";s:32:"92c2b17efc0ff03094dbe55603835cd7";s:4:"name";s:67:"Symfony/Component/HttpKernel/Fragment/FragmentRendererInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Fragment/FragmentRendererInterface.php";}s:66:"Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php";a:4:{s:6:"md5sum";s:32:"eb63af63d6d386b8ce0b6faeda979a5c";s:4:"name";s:66:"Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php";}s:64:"Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php";a:4:{s:6:"md5sum";s:32:"71d698c9b1e16a25819450db6db7cb57";s:4:"name";s:64:"Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php";}s:66:"Symfony/Component/HttpKernel/Fragment/RoutableFragmentRenderer.php";a:4:{s:6:"md5sum";s:32:"fbce96e11756ed0deb106c0192e29a8a";s:4:"name";s:66:"Symfony/Component/HttpKernel/Fragment/RoutableFragmentRenderer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Fragment/RoutableFragmentRenderer.php";}s:46:"Symfony/Component/HttpKernel/HttpCache/Esi.php";a:4:{s:6:"md5sum";s:32:"fa7788cbb3d094b334c129d4b12df2f1";s:4:"name";s:46:"Symfony/Component/HttpKernel/HttpCache/Esi.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/HttpCache/Esi.php";}s:67:"Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php";a:4:{s:6:"md5sum";s:32:"45e69313f1a53d5ebab91bf3c18d48ec";s:4:"name";s:67:"Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php";}s:76:"Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.php";a:4:{s:6:"md5sum";s:32:"091ed77cd920fc81d7cc3fa663a20be4";s:4:"name";s:76:"Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.php";}s:52:"Symfony/Component/HttpKernel/HttpCache/HttpCache.php";a:4:{s:6:"md5sum";s:32:"c49bf34675051f7bed1f6444d720a412";s:4:"name";s:52:"Symfony/Component/HttpKernel/HttpCache/HttpCache.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/HttpCache/HttpCache.php";}s:48:"Symfony/Component/HttpKernel/HttpCache/Store.php";a:4:{s:6:"md5sum";s:32:"a5f55c6da48996bf5e0cec62eb9dfa9b";s:4:"name";s:48:"Symfony/Component/HttpKernel/HttpCache/Store.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/HttpCache/Store.php";}s:57:"Symfony/Component/HttpKernel/HttpCache/StoreInterface.php";a:4:{s:6:"md5sum";s:32:"23cb34a2a464e310a6cc4ad8053190b4";s:4:"name";s:57:"Symfony/Component/HttpKernel/HttpCache/StoreInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/HttpCache/StoreInterface.php";}s:43:"Symfony/Component/HttpKernel/HttpKernel.php";a:4:{s:6:"md5sum";s:32:"90b674ef382b3241a3533e5561c285e3";s:4:"name";s:43:"Symfony/Component/HttpKernel/HttpKernel.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/HttpKernel.php";}s:52:"Symfony/Component/HttpKernel/HttpKernelInterface.php";a:4:{s:6:"md5sum";s:32:"a26257098916c1d939b7b0a04f44dfb8";s:4:"name";s:52:"Symfony/Component/HttpKernel/HttpKernelInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/HttpKernelInterface.php";}s:39:"Symfony/Component/HttpKernel/Kernel.php";a:4:{s:6:"md5sum";s:32:"ba5fe007a2ac71d42ccc2c8d10cf5326";s:4:"name";s:39:"Symfony/Component/HttpKernel/Kernel.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Kernel.php";}s:45:"Symfony/Component/HttpKernel/KernelEvents.php";a:4:{s:6:"md5sum";s:32:"84732b3d13c1d962a9ca76189f5f5086";s:4:"name";s:45:"Symfony/Component/HttpKernel/KernelEvents.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/KernelEvents.php";}s:48:"Symfony/Component/HttpKernel/KernelInterface.php";a:4:{s:6:"md5sum";s:32:"b2547cd0399c7d610c3c31bf8fafc1c1";s:4:"name";s:48:"Symfony/Component/HttpKernel/KernelInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/KernelInterface.php";}s:36:"Symfony/Component/HttpKernel/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/HttpKernel/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/HttpKernel/Symfony/Component/HttpKernel/LICENSE";}s:57:"Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php";a:4:{s:6:"md5sum";s:32:"729e7e46e4dd1a18559aa41e58548e09";s:4:"name";s:57:"Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php";}s:52:"Symfony/Component/HttpKernel/Log/LoggerInterface.php";a:4:{s:6:"md5sum";s:32:"a63e038a0c6c529619b2197afcf54e57";s:4:"name";s:52:"Symfony/Component/HttpKernel/Log/LoggerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Log/LoggerInterface.php";}s:47:"Symfony/Component/HttpKernel/Log/NullLogger.php";a:4:{s:6:"md5sum";s:32:"fdaed4279e4932db9593cab3d9801f80";s:4:"name";s:47:"Symfony/Component/HttpKernel/Log/NullLogger.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Log/NullLogger.php";}s:45:"Symfony/Component/HttpKernel/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"480db13c5bc7a6911c241df127572a69";s:4:"name";s:45:"Symfony/Component/HttpKernel/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/phpunit.xml.dist";}s:69:"Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php";a:4:{s:6:"md5sum";s:32:"f42eab7a5e7ec989509aefc70a57e76c";s:4:"name";s:69:"Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php";}s:61:"Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php";a:4:{s:6:"md5sum";s:32:"3a0a7571fcf3f33c4958016fef0ac6e1";s:4:"name";s:61:"Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php";}s:66:"Symfony/Component/HttpKernel/Profiler/MemcachedProfilerStorage.php";a:4:{s:6:"md5sum";s:32:"c6e448f617b7211c44095e8730c4a2bd";s:4:"name";s:66:"Symfony/Component/HttpKernel/Profiler/MemcachedProfilerStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/MemcachedProfilerStorage.php";}s:65:"Symfony/Component/HttpKernel/Profiler/MemcacheProfilerStorage.php";a:4:{s:6:"md5sum";s:32:"439c84953c390c2310af0b269b63c37b";s:4:"name";s:65:"Symfony/Component/HttpKernel/Profiler/MemcacheProfilerStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/MemcacheProfilerStorage.php";}s:64:"Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.php";a:4:{s:6:"md5sum";s:32:"c1743fb29d46daedfa747ed47b9494c1";s:4:"name";s:64:"Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.php";}s:62:"Symfony/Component/HttpKernel/Profiler/MysqlProfilerStorage.php";a:4:{s:6:"md5sum";s:32:"4d2027032d2e5c190aa65e54394db133";s:4:"name";s:62:"Symfony/Component/HttpKernel/Profiler/MysqlProfilerStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/MysqlProfilerStorage.php";}s:60:"Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php";a:4:{s:6:"md5sum";s:32:"8d24566fd44b8a4b06c64127a5a03c2a";s:4:"name";s:60:"Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php";}s:49:"Symfony/Component/HttpKernel/Profiler/Profile.php";a:4:{s:6:"md5sum";s:32:"af734240bcbd3fc0ecfc377333f9bcd9";s:4:"name";s:49:"Symfony/Component/HttpKernel/Profiler/Profile.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/Profile.php";}s:50:"Symfony/Component/HttpKernel/Profiler/Profiler.php";a:4:{s:6:"md5sum";s:32:"3433ee1c2d23c78d68774f83c97eb578";s:4:"name";s:50:"Symfony/Component/HttpKernel/Profiler/Profiler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/Profiler.php";}s:66:"Symfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.php";a:4:{s:6:"md5sum";s:32:"17d9e40eefdb2fad667dc74ebf858c85";s:4:"name";s:66:"Symfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.php";}s:62:"Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php";a:4:{s:6:"md5sum";s:32:"e10da26d143cc3a6336f7e97c7f4d535";s:4:"name";s:62:"Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php";}s:63:"Symfony/Component/HttpKernel/Profiler/SqliteProfilerStorage.php";a:4:{s:6:"md5sum";s:32:"b69028b6ff27fff88714b26e65d6d6cf";s:4:"name";s:63:"Symfony/Component/HttpKernel/Profiler/SqliteProfilerStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler/SqliteProfilerStorage.php";}s:38:"Symfony/Component/HttpKernel/README.md";a:4:{s:6:"md5sum";s:32:"a88bdc6a3df6948b04db2f5d8c76c865";s:4:"name";s:38:"Symfony/Component/HttpKernel/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/HttpKernel/Symfony/Component/HttpKernel/README.md";}s:52:"Symfony/Component/HttpKernel/TerminableInterface.php";a:4:{s:6:"md5sum";s:32:"63651d1c2efa91187e171c23fa108bcc";s:4:"name";s:52:"Symfony/Component/HttpKernel/TerminableInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/TerminableInterface.php";}s:56:"Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php";a:4:{s:6:"md5sum";s:32:"5db4015a25ec64975433954495425cb9";s:4:"name";s:56:"Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php";}s:73:"Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php";a:4:{s:6:"md5sum";s:32:"719d0acb32f69e30070481fc995d7c95";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php";}s:75:"Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php";a:4:{s:6:"md5sum";s:32:"a670a188bc612138042a48ce08d0d86c";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php";}s:66:"Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.php";a:4:{s:6:"md5sum";s:32:"aa85344cf1c9a4ea3472caad8fd270e1";s:4:"name";s:66:"Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.php";}s:49:"Symfony/Component/HttpKernel/Tests/ClientTest.php";a:4:{s:6:"md5sum";s:32:"d8434d3e6d9ab70624691695c0463227";s:4:"name";s:49:"Symfony/Component/HttpKernel/Tests/ClientTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/ClientTest.php";}s:61:"Symfony/Component/HttpKernel/Tests/Config/FileLocatorTest.php";a:4:{s:6:"md5sum";s:32:"5e1515ccdd440d46fca79579beb81ea1";s:4:"name";s:61:"Symfony/Component/HttpKernel/Tests/Config/FileLocatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Config/FileLocatorTest.php";}s:72:"Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php";a:4:{s:6:"md5sum";s:32:"537f569f63ee14058800342fc3e0a242";s:4:"name";s:72:"Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php";}s:76:"Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.php";a:4:{s:6:"md5sum";s:32:"39a22588190c09f58431a38ce9ebd6bc";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.php";}s:79:"Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php";a:4:{s:6:"md5sum";s:32:"0cf6afafd5af55e00d3c5f9ba31d8917";s:4:"name";s:79:"Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php";}s:76:"Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php";a:4:{s:6:"md5sum";s:32:"db74032e31e4161dc21aaf9443a4910f";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php";}s:76:"Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.php";a:4:{s:6:"md5sum";s:32:"dd889c18076eab8becd1544e90472aae";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.php";}s:77:"Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php";a:4:{s:6:"md5sum";s:32:"cdab18131698b1915f326cbe376097c2";s:4:"name";s:77:"Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php";}s:74:"Symfony/Component/HttpKernel/Tests/DataCollector/TimeDataCollectorTest.php";a:4:{s:6:"md5sum";s:32:"cad604b1dab9e0178b105ccee837ab52";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/DataCollector/TimeDataCollectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/TimeDataCollectorTest.php";}s:73:"Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php";a:4:{s:6:"md5sum";s:32:"47bb53262ba95915cc2f7c2c905ccd04";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php";}s:87:"Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php";a:4:{s:6:"md5sum";s:32:"761aed0102e13403661542c40ff2441a";s:4:"name";s:87:"Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:133:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php";}s:94:"Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php";a:4:{s:6:"md5sum";s:32:"92e4fbfef80def18781bd8a16000b2ec";s:4:"name";s:94:"Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:140:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php";}s:84:"Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterListenersPassTest.php";a:4:{s:6:"md5sum";s:32:"b8ec326aa5b3ad38b2aceb0f6f9f2b17";s:4:"name";s:84:"Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterListenersPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterListenersPassTest.php";}s:68:"Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.php";a:4:{s:6:"md5sum";s:32:"0af1d216963fc1ad9bf090060c450f69";s:4:"name";s:68:"Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.php";}s:74:"Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php";a:4:{s:6:"md5sum";s:32:"3d35f03216a8c24fbec0d4690f6a4e9b";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php";}s:73:"Symfony/Component/HttpKernel/Tests/EventListener/FragmentListenerTest.php";a:4:{s:6:"md5sum";s:32:"2b58c87811bcb1e4d1e01a66b57d4a28";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/EventListener/FragmentListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/FragmentListenerTest.php";}s:71:"Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php";a:4:{s:6:"md5sum";s:32:"4e1ca37427ffb634328d287bf5bb179b";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php";}s:73:"Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.php";a:4:{s:6:"md5sum";s:32:"0badf4d0b6a602b51de96b965d34b5a4";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.php";}s:73:"Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php";a:4:{s:6:"md5sum";s:32:"459a71cfa659bd53df29387cabad577b";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php";}s:71:"Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php";a:4:{s:6:"md5sum";s:32:"60d79091d972859015aeea894ceb632f";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php";}s:76:"Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php";a:4:{s:6:"md5sum";s:32:"c3c274823c0ae42288813e3881f5b2d9";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php";}s:72:"Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:72:"Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txt";}s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txt";}s:65:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:65:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txt";}s:65:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:65:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txt";}s:75:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt";}s:65:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle/foo.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:65:"Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle/foo.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle/foo.txt";}s:66:"Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/classes.map";a:4:{s:6:"md5sum";s:32:"9ab5af02cc19f043e6ab4c12f826be86";s:4:"name";s:66:"Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/classes.map";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/classes.map";}s:89:"Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/MockObjectTestProjectContainer.php";a:4:{s:6:"md5sum";s:32:"0d04f0c8627b1c410d6d47246199fb55";s:4:"name";s:89:"Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/MockObjectTestProjectContainer.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/MockObjectTestProjectContainer.php";}s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txt";}s:74:"Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txt";}s:91:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php";a:4:{s:6:"md5sum";s:32:"087e3dc7776e8d94ff7ae2852dc912bd";s:4:"name";s:91:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php";}s:114:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php";a:4:{s:6:"md5sum";s:32:"27015c77094432ed5a984416d760fd74";s:4:"name";s:114:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php";s:4:"role";s:4:"test";s:12:"installed_as";s:160:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php";}s:91:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php";a:4:{s:6:"md5sum";s:32:"a1e589e6fb85f086e2d31f4f37e62fe9";s:4:"name";s:91:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php";}s:89:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php";a:4:{s:6:"md5sum";s:32:"6cbbfc883c6a2ff486474f87476f0563";s:4:"name";s:89:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php";}s:89:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php";a:4:{s:6:"md5sum";s:32:"54610c5e45d73507ef3b70c59a6140c2";s:4:"name";s:89:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php";}s:116:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php";a:4:{s:6:"md5sum";s:32:"580c52df0c49dbe51b8953eafa44adff";s:4:"name";s:116:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php";s:4:"role";s:4:"test";s:12:"installed_as";s:162:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php";}s:93:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php";a:4:{s:6:"md5sum";s:32:"e2b6b77bad66ea379f550eeaa0c99476";s:4:"name";s:93:"Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php";s:4:"role";s:4:"test";s:12:"installed_as";s:139:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php";}s:60:"Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.php";a:4:{s:6:"md5sum";s:32:"f5505afbf35dae7260891f4a9fd1cfd4";s:4:"name";s:60:"Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.php";}s:69:"Symfony/Component/HttpKernel/Tests/Fixtures/KernelForOverrideName.php";a:4:{s:6:"md5sum";s:32:"468ec4e8ecf949b24336c3e2557bc7bf";s:4:"name";s:69:"Symfony/Component/HttpKernel/Tests/Fixtures/KernelForOverrideName.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForOverrideName.php";}s:61:"Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php";a:4:{s:6:"md5sum";s:32:"c9615a710a6e8dfdb0dd2daaa77b8377";s:4:"name";s:61:"Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.php";}s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txt";}s:75:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt";}s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txt";}s:71:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txt";}s:58:"Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.php";a:4:{s:6:"md5sum";s:32:"caac83e9f7141808a279c9415b3d631d";s:4:"name";s:58:"Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.php";}s:67:"Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php";a:4:{s:6:"md5sum";s:32:"cf1be212b7c33954b81cbb5f17f90901";s:4:"name";s:67:"Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php";}s:71:"Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.php";a:4:{s:6:"md5sum";s:32:"bc9d6216414586747e3857fcc1884c33";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.php";}s:67:"Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.php";a:4:{s:6:"md5sum";s:32:"fa6ac6afb43b8f9f17bac5f34b8079b1";s:4:"name";s:67:"Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.php";}s:76:"Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.php";a:4:{s:6:"md5sum";s:32:"d42e11990c445631c29d351e1050bc12";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.php";}s:74:"Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php";a:4:{s:6:"md5sum";s:32:"0914364078b13a058fc4ad858a9a97a2";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php";}s:76:"Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.php";a:4:{s:6:"md5sum";s:32:"99d3a3885bcaaeaa9d7daa7628d16b6b";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.php";}s:56:"Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php";a:4:{s:6:"md5sum";s:32:"0839be428bd44e163cd68390f4ef49da";s:4:"name";s:56:"Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php";}s:62:"Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php";a:4:{s:6:"md5sum";s:32:"58d82c49cec84700cfeac27313345271";s:4:"name";s:62:"Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php";}s:66:"Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php";a:4:{s:6:"md5sum";s:32:"b03bb6f91a5309a1e83e6b892a9759cc";s:4:"name";s:66:"Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php";}s:58:"Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php";a:4:{s:6:"md5sum";s:32:"070e9eeb7eff1f89e79917937aa7b692";s:4:"name";s:58:"Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php";}s:63:"Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php";a:4:{s:6:"md5sum";s:32:"9968d637c2ee0189e7983c285f1cb353";s:4:"name";s:63:"Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php";}s:71:"Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php";a:4:{s:6:"md5sum";s:32:"f8033c30b37e92bfbc3c61885dc4f6d2";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php";}s:53:"Symfony/Component/HttpKernel/Tests/HttpKernelTest.php";a:4:{s:6:"md5sum";s:32:"cc31bf84e75276fcc9efa9f5f0c45302";s:4:"name";s:53:"Symfony/Component/HttpKernel/Tests/HttpKernelTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php";}s:49:"Symfony/Component/HttpKernel/Tests/KernelTest.php";a:4:{s:6:"md5sum";s:32:"985b62eefe124bbd995e6c9da0b46dbf";s:4:"name";s:49:"Symfony/Component/HttpKernel/Tests/KernelTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/KernelTest.php";}s:45:"Symfony/Component/HttpKernel/Tests/Logger.php";a:4:{s:6:"md5sum";s:32:"f544395e09366b61d2e01f49c15066ff";s:4:"name";s:45:"Symfony/Component/HttpKernel/Tests/Logger.php";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Logger.php";}s:75:"Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.php";a:4:{s:6:"md5sum";s:32:"3d025b1cac5e80626a19849b06a41e91";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.php";}s:71:"Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.php";a:4:{s:6:"md5sum";s:32:"12f40567e2687864d629e2437915b127";s:4:"name";s:71:"Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.php";}s:76:"Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.php";a:4:{s:6:"md5sum";s:32:"f88559896ea0d7bea467da273976fcc3";s:4:"name";s:76:"Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.php";}s:75:"Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.php";a:4:{s:6:"md5sum";s:32:"285f9b91923d397ff0704c465eb76378";s:4:"name";s:75:"Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.php";}s:66:"Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcachedMock.php";a:4:{s:6:"md5sum";s:32:"a9448076fbd5c7d42bb595bf6626226b";s:4:"name";s:66:"Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcachedMock.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcachedMock.php";}s:65:"Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcacheMock.php";a:4:{s:6:"md5sum";s:32:"aaee125b4e1132032c58f5ca4c03bb40";s:4:"name";s:65:"Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcacheMock.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcacheMock.php";}s:62:"Symfony/Component/HttpKernel/Tests/Profiler/Mock/RedisMock.php";a:4:{s:6:"md5sum";s:32:"796c2e18d225e482facc9de766f8bba7";s:4:"name";s:62:"Symfony/Component/HttpKernel/Tests/Profiler/Mock/RedisMock.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/RedisMock.php";}s:74:"Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.php";a:4:{s:6:"md5sum";s:32:"ed9ba23032795739acc33ba5d1970557";s:4:"name";s:74:"Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.php";}s:60:"Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php";a:4:{s:6:"md5sum";s:32:"9a65333f51c36b0b6a837f1105c2d022";s:4:"name";s:60:"Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php";}s:72:"Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.php";a:4:{s:6:"md5sum";s:32:"e84fca3c3f76faa48cf1b760ab1fc079";s:4:"name";s:72:"Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.php";}s:73:"Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.php";a:4:{s:6:"md5sum";s:32:"fad36380de80995905e7a2046f3d01b0";s:4:"name";s:73:"Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.php";}s:53:"Symfony/Component/HttpKernel/Tests/TestHttpKernel.php";a:4:{s:6:"md5sum";s:32:"5b8daaba0cf9db86b60c25116c7ab8a4";s:4:"name";s:53:"Symfony/Component/HttpKernel/Tests/TestHttpKernel.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/TestHttpKernel.php";}s:52:"Symfony/Component/HttpKernel/Tests/UriSignerTest.php";a:4:{s:6:"md5sum";s:32:"bf06babf2bdca6d62c7960c8a9e53e68";s:4:"name";s:52:"Symfony/Component/HttpKernel/Tests/UriSignerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/UriSignerTest.php";}s:42:"Symfony/Component/HttpKernel/UriSigner.php";a:4:{s:6:"md5sum";s:32:"9daa3c983b391a8dae8e4e7b34f26e07";s:4:"name";s:42:"Symfony/Component/HttpKernel/UriSigner.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/UriSigner.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:62:{s:58:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Bundle";b:1;s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/CacheClearer";b:1;s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/CacheWarmer";b:1;s:73:"/opt/alt/php54/usr/share/doc/pear/HttpKernel/Symfony/Component/HttpKernel";b:1;s:62:"/opt/alt/php54/usr/share/doc/pear/HttpKernel/Symfony/Component";b:1;s:52:"/opt/alt/php54/usr/share/doc/pear/HttpKernel/Symfony";b:1;s:44:"/opt/alt/php54/usr/share/doc/pear/HttpKernel";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Config";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Controller";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DataCollector/Util";b:1;s:64:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Debug";b:1;s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/DependencyInjection";b:1;s:64:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Event";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/EventListener";b:1;s:68:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Exception";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Fragment";b:1;s:68:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/HttpCache";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Log";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel";b:1;s:63:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component";b:1;s:53:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/pear/test/HttpKernel";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpKernel/Profiler";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Bundle";b:1;s:80:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests";b:1;s:93:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheClearer";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Config";b:1;s:91:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Controller";b:1;s:94:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Debug";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection";b:1;s:94:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener";b:1;s:110:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures";b:1;s:103:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle";b:1;s:113:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources";b:1;s:103:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test";b:1;s:95:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache";b:1;s:111:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources";b:1;s:101:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle";b:1;s:111:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle";b:1;s:131:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection";b:1;s:111:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle";b:1;s:120:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command";b:1;s:112:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle";b:1;s:132:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection";b:1;s:110:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle";b:1;s:99:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources";b:1;s:113:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle";b:1;s:111:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle";b:1;s:109:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler";b:1;s:94:"/opt/alt/php54/usr/share/pear/test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:10:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:14:"HttpFoundation";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:15:"EventDispatcher";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:4;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:6:"Config";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:5;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:19:"DependencyInjection";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:6;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:11:"ClassLoader";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:7;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:10:"BrowserKit";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:8;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:7:"Console";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:9;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:6:"Finder";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506495;}PK!ett3.registry/.channel.pear.symfony.com/cssselector.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:11:"CssSelector";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:30:"Symfony2 CssSelector Component";s:11:"description";s:30:"Symfony2 CssSelector Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:42";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:84:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e3e4f08d3d10d65070b694b3f63f7baf";s:4:"name";s:44:"Symfony/Component/CssSelector/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"29b39013d7b608953abbd2ec2a2b108e";s:4:"name";s:42:"Symfony/Component/CssSelector/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"404ca8cc75237ce4158c233f65f6c40a";s:4:"name";s:43:"Symfony/Component/CssSelector/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df4cdb60586ed7c6e160abcecb3946cb";s:4:"name";s:45:"Symfony/Component/CssSelector/CssSelector.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"208a57b71460b044d40b1540a9694a3a";s:4:"name";s:62:"Symfony/Component/CssSelector/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7118a4cf65f680202f0eaf2e908c2c0b";s:4:"name";s:68:"Symfony/Component/CssSelector/Exception/ExpressionErrorException.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa0dca2be11eee1f425fa517042f77dd";s:4:"name";s:66:"Symfony/Component/CssSelector/Exception/InternalErrorException.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"88581acf1955252a238ba1e7a9065c68";s:4:"name";s:58:"Symfony/Component/CssSelector/Exception/ParseException.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9a8cda86fd4170ac7a11c040f4012ba3";s:4:"name";s:64:"Symfony/Component/CssSelector/Exception/SyntaxErrorException.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:37:"Symfony/Component/CssSelector/LICENSE";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"adb8f4d1edc1238e6b87598afc3a14b8";s:4:"name";s:51:"Symfony/Component/CssSelector/Node/AbstractNode.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"824e4ddb5ff40b70d2ad71755ebe8dfd";s:4:"name";s:52:"Symfony/Component/CssSelector/Node/AttributeNode.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c6c998b135e447f8a28e3808f7e617f9";s:4:"name";s:48:"Symfony/Component/CssSelector/Node/ClassNode.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7106faa07e1e5c71d82fe996008c895f";s:4:"name";s:59:"Symfony/Component/CssSelector/Node/CombinedSelectorNode.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f21f0616e8265a5181e5f06a856c933b";s:4:"name";s:50:"Symfony/Component/CssSelector/Node/ElementNode.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e836280bfc66eafa6baf245f0a3c3bb0";s:4:"name";s:51:"Symfony/Component/CssSelector/Node/FunctionNode.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1a328bfb606d0643442c6170a9459759";s:4:"name";s:47:"Symfony/Component/CssSelector/Node/HashNode.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2cbeaac4f48dc4a66db5a248f8fec10";s:4:"name";s:51:"Symfony/Component/CssSelector/Node/NegationNode.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b5a728ee8ad1d423d62efdcf4f657c26";s:4:"name";s:52:"Symfony/Component/CssSelector/Node/NodeInterface.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4e924e9ba036136a008da903df86a360";s:4:"name";s:49:"Symfony/Component/CssSelector/Node/PseudoNode.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b47cf534893303b4e3d0bfdc2c5e2ff";s:4:"name";s:51:"Symfony/Component/CssSelector/Node/SelectorNode.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc8f1629f8cf146261b153e325d8ce1c";s:4:"name";s:50:"Symfony/Component/CssSelector/Node/Specificity.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"728097eaafd9e8018c6c7dcbebccea44";s:4:"name";s:63:"Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9c84b47596c28514679be9c51f81f16e";s:4:"name";s:65:"Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4e97078058108e52db9b12c6da6a9109";s:4:"name";s:60:"Symfony/Component/CssSelector/Parser/Handler/HashHandler.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b7bf58f74e1fc2309e25b7baa9d1d343";s:4:"name";s:66:"Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"83ff03c0d6a16a4fcce0f5de9fa23308";s:4:"name";s:62:"Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"61b35623c7532945151ffa7dd7f5d100";s:4:"name";s:62:"Symfony/Component/CssSelector/Parser/Handler/StringHandler.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8f0d0212ec813837d767b7b26fe53585";s:4:"name";s:66:"Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"809111f9a2ead47facf240b010627cb2";s:4:"name";s:47:"Symfony/Component/CssSelector/Parser/Parser.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dfbca8e2e63ac97e63cebf19545218fe";s:4:"name";s:56:"Symfony/Component/CssSelector/Parser/ParserInterface.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"45ecfcb66b87c2a3784a9632a246060f";s:4:"name";s:47:"Symfony/Component/CssSelector/Parser/Reader.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bbccdac49b44cddfdf5aa335af6cb7bb";s:4:"name";s:61:"Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"804e233a3fea5cef8d63d07ac11d749b";s:4:"name";s:63:"Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc23d8eac5180583a554b3c469f88776";s:4:"name";s:67:"Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"17d6d96570644684f01a2024992ef78c";s:4:"name";s:60:"Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1f69e33454e833ed892e7ba74be9d6a8";s:4:"name";s:46:"Symfony/Component/CssSelector/Parser/Token.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"02f022d181917a067d284db4d05a5fd9";s:4:"name";s:60:"Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a227118fac4ee4eee1a06ae3f58f561b";s:4:"name";s:68:"Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5c6f061f1023771ed9ef034c39987e48";s:4:"name";s:68:"Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a95da42ba62cfcf96ae0721c2aef6271";s:4:"name";s:52:"Symfony/Component/CssSelector/Parser/TokenStream.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6301c7c5ed355dad16bac2f2d7916334";s:4:"name";s:46:"Symfony/Component/CssSelector/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae0bfe1d0ab7683160027e2028a500a9";s:4:"name";s:39:"Symfony/Component/CssSelector/README.md";s:4:"role";s:3:"doc";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"105f97c869d80ceaeab602ace2d02a4c";s:4:"name";s:55:"Symfony/Component/CssSelector/Tests/CssSelectorTest.php";s:4:"role";s:4:"test";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fb966a846c4b2274ede7f234737a3fdf";s:4:"name";s:61:"Symfony/Component/CssSelector/Tests/Node/AbstractNodeTest.php";s:4:"role";s:4:"test";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"092c2094b2f340fe776efd016fce5eb5";s:4:"name";s:62:"Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php";s:4:"role";s:4:"test";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eca9764164e56b19fa1345e505ac00a3";s:4:"name";s:58:"Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php";s:4:"role";s:4:"test";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"214991c4a92512b719f1cc0be325019b";s:4:"name";s:69:"Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php";s:4:"role";s:4:"test";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4cb8f0c44fef00b721da4e933d9f205";s:4:"name";s:60:"Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php";s:4:"role";s:4:"test";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bbed27d30c8c4cc7c9ed8e69088600eb";s:4:"name";s:61:"Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php";s:4:"role";s:4:"test";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"104b5fb3905b0d7557cd64af04afa077";s:4:"name";s:57:"Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d96b688675039a28d44ee2ecd0929df2";s:4:"name";s:61:"Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php";s:4:"role";s:4:"test";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"05dd9359681c2bbafed998ce4e35be76";s:4:"name";s:59:"Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php";s:4:"role";s:4:"test";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4a5b7629d4b212920bd00024a5213657";s:4:"name";s:61:"Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php";s:4:"role";s:4:"test";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b550b9aacb73e080022549bbda34caf6";s:4:"name";s:60:"Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php";s:4:"role";s:4:"test";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"83af69d075f8471eb4bfc9cad8f13ff2";s:4:"name";s:74:"Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTest.php";s:4:"role";s:4:"test";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"196568e95d36d1ca21071e86dbb5eeb8";s:4:"name";s:73:"Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"290658d56ebcffe5ce8f2c2c38e2931b";s:4:"name";s:70:"Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php";s:4:"role";s:4:"test";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2273b97aa4a3c0610549edd8a278f689";s:4:"name";s:76:"Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php";s:4:"role";s:4:"test";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a384123020ded9dca1e5adb522f700df";s:4:"name";s:72:"Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php";s:4:"role";s:4:"test";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5df1ec9081c389b0a8171a15717be896";s:4:"name";s:72:"Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php";s:4:"role";s:4:"test";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6b796bb0920add27d724e9d20f549938";s:4:"name";s:76:"Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1cde27c5bdf7267d0f57d4e1b956a4c1";s:4:"name";s:57:"Symfony/Component/CssSelector/Tests/Parser/ParserTest.php";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b6a8eb9014c35a8bdb4202200bc1c88";s:4:"name";s:57:"Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1b2c8035f78686902f20778b1cb8f797";s:4:"name";s:71:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8ba77c09ff5ffd51dc3ac24c09d0e122";s:4:"name";s:73:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c03a0a760a4fc403aa3924670d8db091";s:4:"name";s:77:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9a34d1dab3847e8a0f506d33a828b316";s:4:"name";s:70:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"abd404d57badfae769653f4db1db5d6d";s:4:"name";s:62:"Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ab650cab7dd7fef95d85b7941012a70a";s:4:"name";s:59:"Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"717695cc05565465bc3acf15d9a427f2";s:4:"name";s:59:"Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"58178acfc40a4729a0c8b11ac242ece5";s:4:"name";s:66:"Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html";s:4:"role";s:4:"test";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"297ff7c35ebed5a7b3e9d1b3a5edfe19";s:4:"name";s:60:"Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php";s:4:"role";s:4:"test";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"36f2db5086cfda27484bc54a7267cddf";s:4:"name";s:67:"Symfony/Component/CssSelector/XPath/Extension/AbstractExtension.php";s:4:"role";s:3:"php";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b146bf7b873f25e0b5a7424b67eff903";s:4:"name";s:76:"Symfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.php";s:4:"role";s:3:"php";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8f84c67fd6012af8de284b01c0754748";s:4:"name";s:70:"Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php";s:4:"role";s:3:"php";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"959c23787abad9e8c4bbba199cf33f3e";s:4:"name";s:68:"Symfony/Component/CssSelector/XPath/Extension/ExtensionInterface.php";s:4:"role";s:3:"php";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5966f7a9794f6ccd306e8dfc127a3668";s:4:"name";s:67:"Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php";s:4:"role";s:3:"php";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ab07740061746645330dd5d41bb211e";s:4:"name";s:63:"Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php";s:4:"role";s:3:"php";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d1f044c7891470c22cdd9ec874cd287d";s:4:"name";s:63:"Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php";s:4:"role";s:3:"php";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d16abca499c10dc7eede468dc8302dc6";s:4:"name";s:70:"Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php";s:4:"role";s:3:"php";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"008dda93517b6aba5b6f149946c576ab";s:4:"name";s:50:"Symfony/Component/CssSelector/XPath/Translator.php";s:4:"role";s:3:"php";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"64ba3e247c7e3d046227828a44179c7e";s:4:"name";s:59:"Symfony/Component/CssSelector/XPath/TranslatorInterface.php";s:4:"role";s:3:"php";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e795b62a50ce86fecf5ef2a576cc42bb";s:4:"name";s:49:"Symfony/Component/CssSelector/XPath/XPathExpr.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:84:{s:44:"Symfony/Component/CssSelector/autoloader.php";a:4:{s:6:"md5sum";s:32:"e3e4f08d3d10d65070b694b3f63f7baf";s:4:"name";s:44:"Symfony/Component/CssSelector/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/autoloader.php";}s:42:"Symfony/Component/CssSelector/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"29b39013d7b608953abbd2ec2a2b108e";s:4:"name";s:42:"Symfony/Component/CssSelector/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/doc/pear/CssSelector/Symfony/Component/CssSelector/CHANGELOG.md";}s:43:"Symfony/Component/CssSelector/composer.json";a:4:{s:6:"md5sum";s:32:"404ca8cc75237ce4158c233f65f6c40a";s:4:"name";s:43:"Symfony/Component/CssSelector/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/doc/pear/CssSelector/Symfony/Component/CssSelector/composer.json";}s:45:"Symfony/Component/CssSelector/CssSelector.php";a:4:{s:6:"md5sum";s:32:"df4cdb60586ed7c6e160abcecb3946cb";s:4:"name";s:45:"Symfony/Component/CssSelector/CssSelector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/CssSelector.php";}s:62:"Symfony/Component/CssSelector/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"208a57b71460b044d40b1540a9694a3a";s:4:"name";s:62:"Symfony/Component/CssSelector/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Exception/ExceptionInterface.php";}s:68:"Symfony/Component/CssSelector/Exception/ExpressionErrorException.php";a:4:{s:6:"md5sum";s:32:"7118a4cf65f680202f0eaf2e908c2c0b";s:4:"name";s:68:"Symfony/Component/CssSelector/Exception/ExpressionErrorException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Exception/ExpressionErrorException.php";}s:66:"Symfony/Component/CssSelector/Exception/InternalErrorException.php";a:4:{s:6:"md5sum";s:32:"aa0dca2be11eee1f425fa517042f77dd";s:4:"name";s:66:"Symfony/Component/CssSelector/Exception/InternalErrorException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Exception/InternalErrorException.php";}s:58:"Symfony/Component/CssSelector/Exception/ParseException.php";a:4:{s:6:"md5sum";s:32:"88581acf1955252a238ba1e7a9065c68";s:4:"name";s:58:"Symfony/Component/CssSelector/Exception/ParseException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Exception/ParseException.php";}s:64:"Symfony/Component/CssSelector/Exception/SyntaxErrorException.php";a:4:{s:6:"md5sum";s:32:"9a8cda86fd4170ac7a11c040f4012ba3";s:4:"name";s:64:"Symfony/Component/CssSelector/Exception/SyntaxErrorException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Exception/SyntaxErrorException.php";}s:37:"Symfony/Component/CssSelector/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:37:"Symfony/Component/CssSelector/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/CssSelector/Symfony/Component/CssSelector/LICENSE";}s:51:"Symfony/Component/CssSelector/Node/AbstractNode.php";a:4:{s:6:"md5sum";s:32:"adb8f4d1edc1238e6b87598afc3a14b8";s:4:"name";s:51:"Symfony/Component/CssSelector/Node/AbstractNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/AbstractNode.php";}s:52:"Symfony/Component/CssSelector/Node/AttributeNode.php";a:4:{s:6:"md5sum";s:32:"824e4ddb5ff40b70d2ad71755ebe8dfd";s:4:"name";s:52:"Symfony/Component/CssSelector/Node/AttributeNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/AttributeNode.php";}s:48:"Symfony/Component/CssSelector/Node/ClassNode.php";a:4:{s:6:"md5sum";s:32:"c6c998b135e447f8a28e3808f7e617f9";s:4:"name";s:48:"Symfony/Component/CssSelector/Node/ClassNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/ClassNode.php";}s:59:"Symfony/Component/CssSelector/Node/CombinedSelectorNode.php";a:4:{s:6:"md5sum";s:32:"7106faa07e1e5c71d82fe996008c895f";s:4:"name";s:59:"Symfony/Component/CssSelector/Node/CombinedSelectorNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/CombinedSelectorNode.php";}s:50:"Symfony/Component/CssSelector/Node/ElementNode.php";a:4:{s:6:"md5sum";s:32:"f21f0616e8265a5181e5f06a856c933b";s:4:"name";s:50:"Symfony/Component/CssSelector/Node/ElementNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/ElementNode.php";}s:51:"Symfony/Component/CssSelector/Node/FunctionNode.php";a:4:{s:6:"md5sum";s:32:"e836280bfc66eafa6baf245f0a3c3bb0";s:4:"name";s:51:"Symfony/Component/CssSelector/Node/FunctionNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/FunctionNode.php";}s:47:"Symfony/Component/CssSelector/Node/HashNode.php";a:4:{s:6:"md5sum";s:32:"1a328bfb606d0643442c6170a9459759";s:4:"name";s:47:"Symfony/Component/CssSelector/Node/HashNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/HashNode.php";}s:51:"Symfony/Component/CssSelector/Node/NegationNode.php";a:4:{s:6:"md5sum";s:32:"c2cbeaac4f48dc4a66db5a248f8fec10";s:4:"name";s:51:"Symfony/Component/CssSelector/Node/NegationNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/NegationNode.php";}s:52:"Symfony/Component/CssSelector/Node/NodeInterface.php";a:4:{s:6:"md5sum";s:32:"b5a728ee8ad1d423d62efdcf4f657c26";s:4:"name";s:52:"Symfony/Component/CssSelector/Node/NodeInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/NodeInterface.php";}s:49:"Symfony/Component/CssSelector/Node/PseudoNode.php";a:4:{s:6:"md5sum";s:32:"4e924e9ba036136a008da903df86a360";s:4:"name";s:49:"Symfony/Component/CssSelector/Node/PseudoNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/PseudoNode.php";}s:51:"Symfony/Component/CssSelector/Node/SelectorNode.php";a:4:{s:6:"md5sum";s:32:"7b47cf534893303b4e3d0bfdc2c5e2ff";s:4:"name";s:51:"Symfony/Component/CssSelector/Node/SelectorNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/SelectorNode.php";}s:50:"Symfony/Component/CssSelector/Node/Specificity.php";a:4:{s:6:"md5sum";s:32:"bc8f1629f8cf146261b153e325d8ce1c";s:4:"name";s:50:"Symfony/Component/CssSelector/Node/Specificity.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node/Specificity.php";}s:63:"Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php";a:4:{s:6:"md5sum";s:32:"728097eaafd9e8018c6c7dcbebccea44";s:4:"name";s:63:"Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php";}s:65:"Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php";a:4:{s:6:"md5sum";s:32:"9c84b47596c28514679be9c51f81f16e";s:4:"name";s:65:"Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php";}s:60:"Symfony/Component/CssSelector/Parser/Handler/HashHandler.php";a:4:{s:6:"md5sum";s:32:"4e97078058108e52db9b12c6da6a9109";s:4:"name";s:60:"Symfony/Component/CssSelector/Parser/Handler/HashHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Handler/HashHandler.php";}s:66:"Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php";a:4:{s:6:"md5sum";s:32:"b7bf58f74e1fc2309e25b7baa9d1d343";s:4:"name";s:66:"Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php";}s:62:"Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php";a:4:{s:6:"md5sum";s:32:"83ff03c0d6a16a4fcce0f5de9fa23308";s:4:"name";s:62:"Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php";}s:62:"Symfony/Component/CssSelector/Parser/Handler/StringHandler.php";a:4:{s:6:"md5sum";s:32:"61b35623c7532945151ffa7dd7f5d100";s:4:"name";s:62:"Symfony/Component/CssSelector/Parser/Handler/StringHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Handler/StringHandler.php";}s:66:"Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php";a:4:{s:6:"md5sum";s:32:"8f0d0212ec813837d767b7b26fe53585";s:4:"name";s:66:"Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php";}s:47:"Symfony/Component/CssSelector/Parser/Parser.php";a:4:{s:6:"md5sum";s:32:"809111f9a2ead47facf240b010627cb2";s:4:"name";s:47:"Symfony/Component/CssSelector/Parser/Parser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Parser.php";}s:56:"Symfony/Component/CssSelector/Parser/ParserInterface.php";a:4:{s:6:"md5sum";s:32:"dfbca8e2e63ac97e63cebf19545218fe";s:4:"name";s:56:"Symfony/Component/CssSelector/Parser/ParserInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/ParserInterface.php";}s:47:"Symfony/Component/CssSelector/Parser/Reader.php";a:4:{s:6:"md5sum";s:32:"45ecfcb66b87c2a3784a9632a246060f";s:4:"name";s:47:"Symfony/Component/CssSelector/Parser/Reader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Reader.php";}s:61:"Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php";a:4:{s:6:"md5sum";s:32:"bbccdac49b44cddfdf5aa335af6cb7bb";s:4:"name";s:61:"Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php";}s:63:"Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php";a:4:{s:6:"md5sum";s:32:"804e233a3fea5cef8d63d07ac11d749b";s:4:"name";s:63:"Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php";}s:67:"Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php";a:4:{s:6:"md5sum";s:32:"bc23d8eac5180583a554b3c469f88776";s:4:"name";s:67:"Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php";}s:60:"Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php";a:4:{s:6:"md5sum";s:32:"17d6d96570644684f01a2024992ef78c";s:4:"name";s:60:"Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php";}s:46:"Symfony/Component/CssSelector/Parser/Token.php";a:4:{s:6:"md5sum";s:32:"1f69e33454e833ed892e7ba74be9d6a8";s:4:"name";s:46:"Symfony/Component/CssSelector/Parser/Token.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Token.php";}s:60:"Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php";a:4:{s:6:"md5sum";s:32:"02f022d181917a067d284db4d05a5fd9";s:4:"name";s:60:"Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php";}s:68:"Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php";a:4:{s:6:"md5sum";s:32:"a227118fac4ee4eee1a06ae3f58f561b";s:4:"name";s:68:"Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php";}s:68:"Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php";a:4:{s:6:"md5sum";s:32:"5c6f061f1023771ed9ef034c39987e48";s:4:"name";s:68:"Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php";}s:52:"Symfony/Component/CssSelector/Parser/TokenStream.php";a:4:{s:6:"md5sum";s:32:"a95da42ba62cfcf96ae0721c2aef6271";s:4:"name";s:52:"Symfony/Component/CssSelector/Parser/TokenStream.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/TokenStream.php";}s:46:"Symfony/Component/CssSelector/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"6301c7c5ed355dad16bac2f2d7916334";s:4:"name";s:46:"Symfony/Component/CssSelector/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/phpunit.xml.dist";}s:39:"Symfony/Component/CssSelector/README.md";a:4:{s:6:"md5sum";s:32:"ae0bfe1d0ab7683160027e2028a500a9";s:4:"name";s:39:"Symfony/Component/CssSelector/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/doc/pear/CssSelector/Symfony/Component/CssSelector/README.md";}s:55:"Symfony/Component/CssSelector/Tests/CssSelectorTest.php";a:4:{s:6:"md5sum";s:32:"105f97c869d80ceaeab602ace2d02a4c";s:4:"name";s:55:"Symfony/Component/CssSelector/Tests/CssSelectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/CssSelectorTest.php";}s:61:"Symfony/Component/CssSelector/Tests/Node/AbstractNodeTest.php";a:4:{s:6:"md5sum";s:32:"fb966a846c4b2274ede7f234737a3fdf";s:4:"name";s:61:"Symfony/Component/CssSelector/Tests/Node/AbstractNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTest.php";}s:62:"Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php";a:4:{s:6:"md5sum";s:32:"092c2094b2f340fe776efd016fce5eb5";s:4:"name";s:62:"Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.php";}s:58:"Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php";a:4:{s:6:"md5sum";s:32:"eca9764164e56b19fa1345e505ac00a3";s:4:"name";s:58:"Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.php";}s:69:"Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php";a:4:{s:6:"md5sum";s:32:"214991c4a92512b719f1cc0be325019b";s:4:"name";s:69:"Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.php";}s:60:"Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php";a:4:{s:6:"md5sum";s:32:"b4cb8f0c44fef00b721da4e933d9f205";s:4:"name";s:60:"Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.php";}s:61:"Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php";a:4:{s:6:"md5sum";s:32:"bbed27d30c8c4cc7c9ed8e69088600eb";s:4:"name";s:61:"Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.php";}s:57:"Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php";a:4:{s:6:"md5sum";s:32:"104b5fb3905b0d7557cd64af04afa077";s:4:"name";s:57:"Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.php";}s:61:"Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php";a:4:{s:6:"md5sum";s:32:"d96b688675039a28d44ee2ecd0929df2";s:4:"name";s:61:"Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.php";}s:59:"Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php";a:4:{s:6:"md5sum";s:32:"05dd9359681c2bbafed998ce4e35be76";s:4:"name";s:59:"Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.php";}s:61:"Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php";a:4:{s:6:"md5sum";s:32:"4a5b7629d4b212920bd00024a5213657";s:4:"name";s:61:"Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.php";}s:60:"Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php";a:4:{s:6:"md5sum";s:32:"b550b9aacb73e080022549bbda34caf6";s:4:"name";s:60:"Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.php";}s:74:"Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTest.php";a:4:{s:6:"md5sum";s:32:"83af69d075f8471eb4bfc9cad8f13ff2";s:4:"name";s:74:"Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTest.php";}s:73:"Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php";a:4:{s:6:"md5sum";s:32:"196568e95d36d1ca21071e86dbb5eeb8";s:4:"name";s:73:"Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.php";}s:70:"Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php";a:4:{s:6:"md5sum";s:32:"290658d56ebcffe5ce8f2c2c38e2931b";s:4:"name";s:70:"Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.php";}s:76:"Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php";a:4:{s:6:"md5sum";s:32:"2273b97aa4a3c0610549edd8a278f689";s:4:"name";s:76:"Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.php";}s:72:"Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php";a:4:{s:6:"md5sum";s:32:"a384123020ded9dca1e5adb522f700df";s:4:"name";s:72:"Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.php";}s:72:"Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php";a:4:{s:6:"md5sum";s:32:"5df1ec9081c389b0a8171a15717be896";s:4:"name";s:72:"Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.php";}s:76:"Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php";a:4:{s:6:"md5sum";s:32:"6b796bb0920add27d724e9d20f549938";s:4:"name";s:76:"Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.php";}s:57:"Symfony/Component/CssSelector/Tests/Parser/ParserTest.php";a:4:{s:6:"md5sum";s:32:"1cde27c5bdf7267d0f57d4e1b956a4c1";s:4:"name";s:57:"Symfony/Component/CssSelector/Tests/Parser/ParserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ParserTest.php";}s:57:"Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php";a:4:{s:6:"md5sum";s:32:"5b6a8eb9014c35a8bdb4202200bc1c88";s:4:"name";s:57:"Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.php";}s:71:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php";a:4:{s:6:"md5sum";s:32:"1b2c8035f78686902f20778b1cb8f797";s:4:"name";s:71:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.php";}s:73:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php";a:4:{s:6:"md5sum";s:32:"8ba77c09ff5ffd51dc3ac24c09d0e122";s:4:"name";s:73:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.php";}s:77:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php";a:4:{s:6:"md5sum";s:32:"c03a0a760a4fc403aa3924670d8db091";s:4:"name";s:77:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.php";}s:70:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php";a:4:{s:6:"md5sum";s:32:"9a34d1dab3847e8a0f506d33a828b316";s:4:"name";s:70:"Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.php";}s:62:"Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php";a:4:{s:6:"md5sum";s:32:"abd404d57badfae769653f4db1db5d6d";s:4:"name";s:62:"Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.php";}s:59:"Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html";a:4:{s:6:"md5sum";s:32:"ab650cab7dd7fef95d85b7941012a70a";s:4:"name";s:59:"Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.html";}s:59:"Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml";a:4:{s:6:"md5sum";s:32:"717695cc05565465bc3acf15d9a427f2";s:4:"name";s:59:"Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xml";}s:66:"Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html";a:4:{s:6:"md5sum";s:32:"58178acfc40a4729a0c8b11ac242ece5";s:4:"name";s:66:"Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.html";}s:60:"Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php";a:4:{s:6:"md5sum";s:32:"297ff7c35ebed5a7b3e9d1b3a5edfe19";s:4:"name";s:60:"Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php";}s:67:"Symfony/Component/CssSelector/XPath/Extension/AbstractExtension.php";a:4:{s:6:"md5sum";s:32:"36f2db5086cfda27484bc54a7267cddf";s:4:"name";s:67:"Symfony/Component/CssSelector/XPath/Extension/AbstractExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Extension/AbstractExtension.php";}s:76:"Symfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.php";a:4:{s:6:"md5sum";s:32:"b146bf7b873f25e0b5a7424b67eff903";s:4:"name";s:76:"Symfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Extension/AttributeMatchingExtension.php";}s:70:"Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php";a:4:{s:6:"md5sum";s:32:"8f84c67fd6012af8de284b01c0754748";s:4:"name";s:70:"Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php";}s:68:"Symfony/Component/CssSelector/XPath/Extension/ExtensionInterface.php";a:4:{s:6:"md5sum";s:32:"959c23787abad9e8c4bbba199cf33f3e";s:4:"name";s:68:"Symfony/Component/CssSelector/XPath/Extension/ExtensionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Extension/ExtensionInterface.php";}s:67:"Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php";a:4:{s:6:"md5sum";s:32:"5966f7a9794f6ccd306e8dfc127a3668";s:4:"name";s:67:"Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Extension/FunctionExtension.php";}s:63:"Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php";a:4:{s:6:"md5sum";s:32:"3ab07740061746645330dd5d41bb211e";s:4:"name";s:63:"Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php";}s:63:"Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php";a:4:{s:6:"md5sum";s:32:"d1f044c7891470c22cdd9ec874cd287d";s:4:"name";s:63:"Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php";}s:70:"Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php";a:4:{s:6:"md5sum";s:32:"d16abca499c10dc7eede468dc8302dc6";s:4:"name";s:70:"Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Extension/PseudoClassExtension.php";}s:50:"Symfony/Component/CssSelector/XPath/Translator.php";a:4:{s:6:"md5sum";s:32:"008dda93517b6aba5b6f149946c576ab";s:4:"name";s:50:"Symfony/Component/CssSelector/XPath/Translator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Translator.php";}s:59:"Symfony/Component/CssSelector/XPath/TranslatorInterface.php";a:4:{s:6:"md5sum";s:32:"64ba3e247c7e3d046227828a44179c7e";s:4:"name";s:59:"Symfony/Component/CssSelector/XPath/TranslatorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/TranslatorInterface.php";}s:49:"Symfony/Component/CssSelector/XPath/XPathExpr.php";a:4:{s:6:"md5sum";s:32:"e795b62a50ce86fecf5ef2a576cc42bb";s:4:"name";s:49:"Symfony/Component/CssSelector/XPath/XPathExpr.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/XPathExpr.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:26:{s:59:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:75:"/opt/alt/php54/usr/share/doc/pear/CssSelector/Symfony/Component/CssSelector";b:1;s:63:"/opt/alt/php54/usr/share/doc/pear/CssSelector/Symfony/Component";b:1;s:53:"/opt/alt/php54/usr/share/doc/pear/CssSelector/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/doc/pear/CssSelector";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Exception";b:1;s:64:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Node";b:1;s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Handler";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser";b:1;s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Shortcut";b:1;s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/Parser/Tokenizer";b:1;s:76:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector";b:1;s:64:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component";b:1;s:54:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony";b:1;s:46:"/opt/alt/php54/usr/share/pear/test/CssSelector";b:1;s:82:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Node";b:1;s:97:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser";b:1;s:98:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut";b:1;s:97:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/CssSelector/Symfony/Component/CssSelector/Tests/XPath";b:1;s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath/Extension";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/CssSelector/XPath";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!W6.registry/.channel.pear.symfony.com/httpfoundation.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:14:"HttpFoundation";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:33:"Symfony2 HttpFoundation Component";s:11:"description";s:33:"Symfony2 HttpFoundation Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:46";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:115:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b884647f8a23d1ceb94626f3dbeb5b9e";s:4:"name";s:49:"Symfony/Component/HttpFoundation/AcceptHeader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2dc45b1974c5106ad115c8853e6ec45d";s:4:"name";s:53:"Symfony/Component/HttpFoundation/AcceptHeaderItem.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"428aaf05f7b32d9b5b0f21b5ff926bf0";s:4:"name";s:50:"Symfony/Component/HttpFoundation/ApacheRequest.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7bfad2b6b760e66d943597d5dd7491a5";s:4:"name";s:47:"Symfony/Component/HttpFoundation/autoloader.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1aa7a69563a388fd41290f35c444aaad";s:4:"name";s:55:"Symfony/Component/HttpFoundation/BinaryFileResponse.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"13f2dd00d17037b16bc5f880141269f1";s:4:"name";s:45:"Symfony/Component/HttpFoundation/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6f84da0f8178f7302a88987dae7cd454";s:4:"name";s:46:"Symfony/Component/HttpFoundation/composer.json";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1d21e30974e0cd17909cbd83570e6046";s:4:"name";s:43:"Symfony/Component/HttpFoundation/Cookie.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bb322f1b660d8526d54738c96bcc9496";s:4:"name";s:61:"Symfony/Component/HttpFoundation/ExpressionRequestMatcher.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f857d7f53c52b92f5b86304b3380b099";s:4:"name";s:73:"Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"82953ad2af851c787ed55bf754510432";s:4:"name";s:65:"Symfony/Component/HttpFoundation/File/Exception/FileException.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"77e5758e36af149ce24c50d5f5c4ac41";s:4:"name";s:73:"Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"098936dfa215052c68b1002c28d276f4";s:4:"name";s:75:"Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ad5b16c066a5f89c35c5117ebc1d53ea";s:4:"name";s:67:"Symfony/Component/HttpFoundation/File/Exception/UploadException.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"94d1593cd9789142752a88ccb73cc430";s:4:"name";s:46:"Symfony/Component/HttpFoundation/File/File.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86252c17f16fc39143aad01fd9240645";s:4:"name";s:67:"Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5fe7bad1c2c974c75aa2c3930334f702";s:4:"name";s:76:"Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"94700d9406139019d43f5f8c76177ef1";s:4:"name";s:76:"Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f0cd17205bf9382d367e9921ceab5d88";s:4:"name";s:74:"Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2f92703a5eb0dc3c2a700de6bc6d6e1";s:4:"name";s:75:"Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f0f9de1376a61059af6fa4e90fbd5a13";s:4:"name";s:66:"Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d0a415ee45ad0bd75cdb2032c2cae123";s:4:"name";s:75:"Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a8f763ea3e59a4ff37cee3af896eb323";s:4:"name";s:54:"Symfony/Component/HttpFoundation/File/UploadedFile.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4ca9658eb9774373d5bf710c2300638";s:4:"name";s:44:"Symfony/Component/HttpFoundation/FileBag.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1f23e1af0de42dd915e7a807fa1527f6";s:4:"name";s:46:"Symfony/Component/HttpFoundation/HeaderBag.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"45993bfa467d14b903e20885e6a2cf89";s:4:"name";s:44:"Symfony/Component/HttpFoundation/IpUtils.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4c78dc282e052cb8859f763aedf2805";s:4:"name";s:49:"Symfony/Component/HttpFoundation/JsonResponse.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:40:"Symfony/Component/HttpFoundation/LICENSE";s:4:"role";s:3:"doc";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e223bb93e05d1476b5f12488151a825c";s:4:"name";s:49:"Symfony/Component/HttpFoundation/ParameterBag.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"169b47a2f05c53335bca6becdd389220";s:4:"name";s:49:"Symfony/Component/HttpFoundation/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7851474c7a43a34dd6639f5a126c8bba";s:4:"name";s:42:"Symfony/Component/HttpFoundation/README.md";s:4:"role";s:3:"doc";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0517940c519e1e6efeb564c84edda69c";s:4:"name";s:53:"Symfony/Component/HttpFoundation/RedirectResponse.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bd5c61af6d0cbe7f7edbba3736b87d3b";s:4:"name";s:44:"Symfony/Component/HttpFoundation/Request.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"970df6f9df3bf9150a685c6c6c3f6aa1";s:4:"name";s:51:"Symfony/Component/HttpFoundation/RequestMatcher.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7ecc8861d7377c89a003417ab5db02bf";s:4:"name";s:60:"Symfony/Component/HttpFoundation/RequestMatcherInterface.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"37fd73c5d42a949fff23de4fa0d15b48";s:4:"name";s:49:"Symfony/Component/HttpFoundation/RequestStack.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"94ad98f4affa4224d887336c1f3ea1dc";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cc8f30d1b460ddd2cc4913bfcd3e78b4";s:4:"name";s:45:"Symfony/Component/HttpFoundation/Response.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"02ccee91a765c8b71e997a5a1885a82d";s:4:"name";s:54:"Symfony/Component/HttpFoundation/ResponseHeaderBag.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f0ac2d2b1071ccec5884200d0ab5e420";s:4:"name";s:46:"Symfony/Component/HttpFoundation/ServerBag.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09a642bc5ffa1e2e7cb7aad84cdbc755";s:4:"name";s:67:"Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47cf442d27aa801d2ee1c43eb1b92ab6";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bb24d40c233c7edbeaed0286f399d22d";s:4:"name";s:77:"Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47e8fa7a8f184ec2bef7e90741a030bb";s:4:"name";s:69:"Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fd24bb3a7c43f869f28c5f27e08bb257";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ecf0692351b914a8822f5138d801682";s:4:"name";s:68:"Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b25cb46112eac2e01f6d48a0c89c4716";s:4:"name";s:52:"Symfony/Component/HttpFoundation/Session/Session.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"baa130a80f887fca702556b7cb7ac61e";s:4:"name";s:64:"Symfony/Component/HttpFoundation/Session/SessionBagInterface.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"33e385a590e619684d37bead5b90a7eb";s:4:"name";s:61:"Symfony/Component/HttpFoundation/Session/SessionInterface.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"93364ba7a594762ef28e712bb9dd7e48";s:4:"name";s:84:"Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6c4948a4a2c2400936ecf7552e67f7d3";s:4:"name";s:83:"Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php";s:4:"role";s:3:"php";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b8368e6dcaa7edfd508726ebf1d0a5a";s:4:"name";s:82:"Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fe93aa5204757c30501b59d3ab98550b";s:4:"name";s:85:"Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php";s:4:"role";s:3:"php";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"36574daf922d67815c3efda0063b7af2";s:4:"name";s:81:"Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php";s:4:"role";s:3:"php";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"26845162d0cd8e65c3524bf2413b6025";s:4:"name";s:79:"Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php";s:4:"role";s:3:"php";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5d66bb0aff4e6e04dea4a71dc6b74f2d";s:4:"name";s:78:"Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php";s:4:"role";s:3:"php";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5cc5b83b3809aa9cbe8023c7cfd3845";s:4:"name";s:85:"Symfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.php";s:4:"role";s:3:"php";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0ba968002df893468d99e77dfde92b95";s:4:"name";s:64:"Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php";s:4:"role";s:3:"php";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8d920694b05fe7820867c8271e5b519";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php";s:4:"role";s:3:"php";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bbe1e2bea9239bfe24e45baadb6a330d";s:4:"name";s:75:"Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php";s:4:"role";s:3:"php";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b886167def5c49469577a533a4c2f6c";s:4:"name";s:73:"Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php";s:4:"role";s:3:"php";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5a28453f64db20f1d07f28af5213cfb";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php";s:4:"role";s:3:"php";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b9152152614a4e0d7886d16e8162926";s:4:"name";s:72:"Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php";s:4:"role";s:3:"php";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4da090373635a3ca9732171dadfd4ed0";s:4:"name";s:70:"Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php";s:4:"role";s:3:"php";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1436f383c0e3500de401861230f5400a";s:4:"name";s:78:"Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php";s:4:"role";s:3:"php";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"af85e7a0bab5c49be82a9244b4cde282";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php";s:4:"role";s:3:"php";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4b1b42d5e606ea929c4406f32826fcca";s:4:"name";s:53:"Symfony/Component/HttpFoundation/StreamedResponse.php";s:4:"role";s:3:"php";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"71279e63c94c58a19de6c9bfe9183847";s:4:"name";s:63:"Symfony/Component/HttpFoundation/Tests/AcceptHeaderItemTest.php";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ca12f957cfb0c92c2f8715b455f29607";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/AcceptHeaderTest.php";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7bc8ed0abe9d2fc50e676222891ede1a";s:4:"name";s:60:"Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.php";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"806f7315eef4b6abdbe35a22c50369c0";s:4:"name";s:65:"Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1c7af317329cb2e4dae2e8582c090aad";s:4:"name";s:53:"Symfony/Component/HttpFoundation/Tests/CookieTest.php";s:4:"role";s:4:"test";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f156d2ad465b76775f67bdbf386083b3";s:4:"name";s:71:"Symfony/Component/HttpFoundation/Tests/ExpressionRequestMatcherTest.php";s:4:"role";s:4:"test";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7a08ef205764facbe5646cd24074c937";s:4:"name";s:56:"Symfony/Component/HttpFoundation/Tests/File/FileTest.php";s:4:"role";s:4:"test";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8fa14cdd754f91cc6554c9e71929cce7";s:4:"name";s:70:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextension";s:4:"role";s:4:"test";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:69:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.empty";s:4:"role";s:4:"test";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87aec5a94c94ec7a5dd1c0839eb0182b";s:4:"name";s:57:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/test";s:4:"role";s:4:"test";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87aec5a94c94ec7a5dd1c0839eb0182b";s:4:"name";s:61:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gif";s:4:"role";s:4:"test";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a167d71d8028a1eda64cc8d899f5f6e3";s:4:"name";s:69:"Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php";s:4:"role";s:4:"test";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b45d61227c547c01973ae0d48082796";s:4:"name";s:64:"Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.php";s:4:"role";s:4:"test";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"17f9729e4532b0faed835935233250d0";s:4:"name";s:54:"Symfony/Component/HttpFoundation/Tests/FileBagTest.php";s:4:"role";s:4:"test";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2ca1229b730159f6f7bf2ecfec49825";s:4:"name";s:56:"Symfony/Component/HttpFoundation/Tests/HeaderBagTest.php";s:4:"role";s:4:"test";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6c47d0ca15feaad0e369dd514101b100";s:4:"name";s:54:"Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php";s:4:"role";s:4:"test";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b443a39c7580eab6e59f53022284ae0";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php";s:4:"role";s:4:"test";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"019b8d85e6f650aed3292af213a0643c";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php";s:4:"role";s:4:"test";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2379f3910f6f55a3c72315a25dfdf388";s:4:"name";s:63:"Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php";s:4:"role";s:4:"test";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"99352f4118b2c568fda24db10858555c";s:4:"name";s:61:"Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php";s:4:"role";s:4:"test";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5ab9a5e9dda53ed1f022634f8136d4fd";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/RequestStackTest.php";s:4:"role";s:4:"test";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6406b7aabef145bb68b018da2b9d7780";s:4:"name";s:54:"Symfony/Component/HttpFoundation/Tests/RequestTest.php";s:4:"role";s:4:"test";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e268328250a58f53892622dff9ed2b37";s:4:"name";s:64:"Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php";s:4:"role";s:4:"test";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a17240ff298468ada33c1f15e3ec5012";s:4:"name";s:55:"Symfony/Component/HttpFoundation/Tests/ResponseTest.php";s:4:"role";s:4:"test";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a86e8988d2cf1a094322bfd0b38c045";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/ResponseTestCase.php";s:4:"role";s:4:"test";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"feb7545b69e0eda1a61be511e9135582";s:4:"name";s:56:"Symfony/Component/HttpFoundation/Tests/ServerBagTest.php";s:4:"role";s:4:"test";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fbcb35c2d86007ac5311394d67081cda";s:4:"name";s:77:"Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.php";s:4:"role";s:4:"test";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c281ff06081b6ae87f4356f37a2814e1";s:4:"name";s:87:"Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php";s:4:"role";s:4:"test";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"763835431c792f3e0b5bbba96794542a";s:4:"name";s:79:"Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php";s:4:"role";s:4:"test";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"18cf905cc6ead1acbf260f484564425f";s:4:"name";s:69:"Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php";s:4:"role";s:4:"test";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6a494d5992105e3ebe9c391b7d6f6a63";s:4:"name";s:62:"Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php";s:4:"role";s:4:"test";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f44ffbb61b65fe70de11d6469e48832a";s:4:"name";s:94:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php";s:4:"role";s:4:"test";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c7f7e944a63d1af11e55e6ec4a9374b2";s:4:"name";s:93:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php";s:4:"role";s:4:"test";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2f1f103720b87b039183451427d74c4";s:4:"name";s:92:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php";s:4:"role";s:4:"test";}}i:101;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8fa508beab426cea19a2cedabd5e9171";s:4:"name";s:95:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php";s:4:"role";s:4:"test";}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"45eae4ba5310a98dc04fcadf82bf720d";s:4:"name";s:91:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php";s:4:"role";s:4:"test";}}i:103;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2c0feb6c09d60d7e5926ea5a8da36080";s:4:"name";s:89:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php";s:4:"role";s:4:"test";}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f36ec391bb99db52a49f7ca30360ea26";s:4:"name";s:88:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php";s:4:"role";s:4:"test";}}i:105;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"11d0598235d0d7f8098bdc2145d9d69b";s:4:"name";s:95:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php";s:4:"role";s:4:"test";}}i:106;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fc2af1f274721774e972a5758278c8f3";s:4:"name";s:74:"Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php";s:4:"role";s:4:"test";}}i:107;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87a2d57546023c4094f6be942a4b13c2";s:4:"name";s:86:"Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php";s:4:"role";s:4:"test";}}i:108;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"592ade20d8c465762c8e5a121d60ac52";s:4:"name";s:85:"Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php";s:4:"role";s:4:"test";}}i:109;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bbc650e69324fd0d48491db754f248e4";s:4:"name";s:83:"Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php";s:4:"role";s:4:"test";}}i:110;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b10ca7f822772f799c1f1e68ad9eaf55";s:4:"name";s:86:"Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php";s:4:"role";s:4:"test";}}i:111;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"da5bd63668cf3a8b28b6190b22b3271a";s:4:"name";s:82:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php";s:4:"role";s:4:"test";}}i:112;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1baf3702ba27dc4cfdfe750f18bd8b39";s:4:"name";s:80:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php";s:4:"role";s:4:"test";}}i:113;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2a32ca244d28b43eb7a15edbb1f65c2";s:4:"name";s:88:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php";s:4:"role";s:4:"test";}}i:114;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"73647306210e7be2a18cf3a523275748";s:4:"name";s:63:"Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:115:{s:49:"Symfony/Component/HttpFoundation/AcceptHeader.php";a:4:{s:6:"md5sum";s:32:"b884647f8a23d1ceb94626f3dbeb5b9e";s:4:"name";s:49:"Symfony/Component/HttpFoundation/AcceptHeader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/AcceptHeader.php";}s:53:"Symfony/Component/HttpFoundation/AcceptHeaderItem.php";a:4:{s:6:"md5sum";s:32:"2dc45b1974c5106ad115c8853e6ec45d";s:4:"name";s:53:"Symfony/Component/HttpFoundation/AcceptHeaderItem.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/AcceptHeaderItem.php";}s:50:"Symfony/Component/HttpFoundation/ApacheRequest.php";a:4:{s:6:"md5sum";s:32:"428aaf05f7b32d9b5b0f21b5ff926bf0";s:4:"name";s:50:"Symfony/Component/HttpFoundation/ApacheRequest.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/ApacheRequest.php";}s:47:"Symfony/Component/HttpFoundation/autoloader.php";a:4:{s:6:"md5sum";s:32:"7bfad2b6b760e66d943597d5dd7491a5";s:4:"name";s:47:"Symfony/Component/HttpFoundation/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/autoloader.php";}s:55:"Symfony/Component/HttpFoundation/BinaryFileResponse.php";a:4:{s:6:"md5sum";s:32:"1aa7a69563a388fd41290f35c444aaad";s:4:"name";s:55:"Symfony/Component/HttpFoundation/BinaryFileResponse.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/BinaryFileResponse.php";}s:45:"Symfony/Component/HttpFoundation/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"13f2dd00d17037b16bc5f880141269f1";s:4:"name";s:45:"Symfony/Component/HttpFoundation/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/doc/pear/HttpFoundation/Symfony/Component/HttpFoundation/CHANGELOG.md";}s:46:"Symfony/Component/HttpFoundation/composer.json";a:4:{s:6:"md5sum";s:32:"6f84da0f8178f7302a88987dae7cd454";s:4:"name";s:46:"Symfony/Component/HttpFoundation/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/doc/pear/HttpFoundation/Symfony/Component/HttpFoundation/composer.json";}s:43:"Symfony/Component/HttpFoundation/Cookie.php";a:4:{s:6:"md5sum";s:32:"1d21e30974e0cd17909cbd83570e6046";s:4:"name";s:43:"Symfony/Component/HttpFoundation/Cookie.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Cookie.php";}s:61:"Symfony/Component/HttpFoundation/ExpressionRequestMatcher.php";a:4:{s:6:"md5sum";s:32:"bb322f1b660d8526d54738c96bcc9496";s:4:"name";s:61:"Symfony/Component/HttpFoundation/ExpressionRequestMatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/ExpressionRequestMatcher.php";}s:73:"Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php";a:4:{s:6:"md5sum";s:32:"f857d7f53c52b92f5b86304b3380b099";s:4:"name";s:73:"Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php";}s:65:"Symfony/Component/HttpFoundation/File/Exception/FileException.php";a:4:{s:6:"md5sum";s:32:"82953ad2af851c787ed55bf754510432";s:4:"name";s:65:"Symfony/Component/HttpFoundation/File/Exception/FileException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/Exception/FileException.php";}s:73:"Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php";a:4:{s:6:"md5sum";s:32:"77e5758e36af149ce24c50d5f5c4ac41";s:4:"name";s:73:"Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php";}s:75:"Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php";a:4:{s:6:"md5sum";s:32:"098936dfa215052c68b1002c28d276f4";s:4:"name";s:75:"Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php";}s:67:"Symfony/Component/HttpFoundation/File/Exception/UploadException.php";a:4:{s:6:"md5sum";s:32:"ad5b16c066a5f89c35c5117ebc1d53ea";s:4:"name";s:67:"Symfony/Component/HttpFoundation/File/Exception/UploadException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/Exception/UploadException.php";}s:46:"Symfony/Component/HttpFoundation/File/File.php";a:4:{s:6:"md5sum";s:32:"94d1593cd9789142752a88ccb73cc430";s:4:"name";s:46:"Symfony/Component/HttpFoundation/File/File.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/File.php";}s:67:"Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php";a:4:{s:6:"md5sum";s:32:"86252c17f16fc39143aad01fd9240645";s:4:"name";s:67:"Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php";}s:76:"Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php";a:4:{s:6:"md5sum";s:32:"5fe7bad1c2c974c75aa2c3930334f702";s:4:"name";s:76:"Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.php";}s:76:"Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php";a:4:{s:6:"md5sum";s:32:"94700d9406139019d43f5f8c76177ef1";s:4:"name";s:76:"Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php";}s:74:"Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php";a:4:{s:6:"md5sum";s:32:"f0cd17205bf9382d367e9921ceab5d88";s:4:"name";s:74:"Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php";}s:75:"Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php";a:4:{s:6:"md5sum";s:32:"f2f92703a5eb0dc3c2a700de6bc6d6e1";s:4:"name";s:75:"Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php";}s:66:"Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php";a:4:{s:6:"md5sum";s:32:"f0f9de1376a61059af6fa4e90fbd5a13";s:4:"name";s:66:"Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php";}s:75:"Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php";a:4:{s:6:"md5sum";s:32:"d0a415ee45ad0bd75cdb2032c2cae123";s:4:"name";s:75:"Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php";}s:54:"Symfony/Component/HttpFoundation/File/UploadedFile.php";a:4:{s:6:"md5sum";s:32:"a8f763ea3e59a4ff37cee3af896eb323";s:4:"name";s:54:"Symfony/Component/HttpFoundation/File/UploadedFile.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/UploadedFile.php";}s:44:"Symfony/Component/HttpFoundation/FileBag.php";a:4:{s:6:"md5sum";s:32:"b4ca9658eb9774373d5bf710c2300638";s:4:"name";s:44:"Symfony/Component/HttpFoundation/FileBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/FileBag.php";}s:46:"Symfony/Component/HttpFoundation/HeaderBag.php";a:4:{s:6:"md5sum";s:32:"1f23e1af0de42dd915e7a807fa1527f6";s:4:"name";s:46:"Symfony/Component/HttpFoundation/HeaderBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/HeaderBag.php";}s:44:"Symfony/Component/HttpFoundation/IpUtils.php";a:4:{s:6:"md5sum";s:32:"45993bfa467d14b903e20885e6a2cf89";s:4:"name";s:44:"Symfony/Component/HttpFoundation/IpUtils.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/IpUtils.php";}s:49:"Symfony/Component/HttpFoundation/JsonResponse.php";a:4:{s:6:"md5sum";s:32:"b4c78dc282e052cb8859f763aedf2805";s:4:"name";s:49:"Symfony/Component/HttpFoundation/JsonResponse.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/JsonResponse.php";}s:40:"Symfony/Component/HttpFoundation/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:40:"Symfony/Component/HttpFoundation/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/doc/pear/HttpFoundation/Symfony/Component/HttpFoundation/LICENSE";}s:49:"Symfony/Component/HttpFoundation/ParameterBag.php";a:4:{s:6:"md5sum";s:32:"e223bb93e05d1476b5f12488151a825c";s:4:"name";s:49:"Symfony/Component/HttpFoundation/ParameterBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/ParameterBag.php";}s:49:"Symfony/Component/HttpFoundation/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"169b47a2f05c53335bca6becdd389220";s:4:"name";s:49:"Symfony/Component/HttpFoundation/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/phpunit.xml.dist";}s:42:"Symfony/Component/HttpFoundation/README.md";a:4:{s:6:"md5sum";s:32:"7851474c7a43a34dd6639f5a126c8bba";s:4:"name";s:42:"Symfony/Component/HttpFoundation/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/doc/pear/HttpFoundation/Symfony/Component/HttpFoundation/README.md";}s:53:"Symfony/Component/HttpFoundation/RedirectResponse.php";a:4:{s:6:"md5sum";s:32:"0517940c519e1e6efeb564c84edda69c";s:4:"name";s:53:"Symfony/Component/HttpFoundation/RedirectResponse.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/RedirectResponse.php";}s:44:"Symfony/Component/HttpFoundation/Request.php";a:4:{s:6:"md5sum";s:32:"bd5c61af6d0cbe7f7edbba3736b87d3b";s:4:"name";s:44:"Symfony/Component/HttpFoundation/Request.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Request.php";}s:51:"Symfony/Component/HttpFoundation/RequestMatcher.php";a:4:{s:6:"md5sum";s:32:"970df6f9df3bf9150a685c6c6c3f6aa1";s:4:"name";s:51:"Symfony/Component/HttpFoundation/RequestMatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/RequestMatcher.php";}s:60:"Symfony/Component/HttpFoundation/RequestMatcherInterface.php";a:4:{s:6:"md5sum";s:32:"7ecc8861d7377c89a003417ab5db02bf";s:4:"name";s:60:"Symfony/Component/HttpFoundation/RequestMatcherInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/RequestMatcherInterface.php";}s:49:"Symfony/Component/HttpFoundation/RequestStack.php";a:4:{s:6:"md5sum";s:32:"37fd73c5d42a949fff23de4fa0d15b48";s:4:"name";s:49:"Symfony/Component/HttpFoundation/RequestStack.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/RequestStack.php";}s:76:"Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php";a:4:{s:6:"md5sum";s:32:"94ad98f4affa4224d887336c1f3ea1dc";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php";}s:45:"Symfony/Component/HttpFoundation/Response.php";a:4:{s:6:"md5sum";s:32:"cc8f30d1b460ddd2cc4913bfcd3e78b4";s:4:"name";s:45:"Symfony/Component/HttpFoundation/Response.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Response.php";}s:54:"Symfony/Component/HttpFoundation/ResponseHeaderBag.php";a:4:{s:6:"md5sum";s:32:"02ccee91a765c8b71e997a5a1885a82d";s:4:"name";s:54:"Symfony/Component/HttpFoundation/ResponseHeaderBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/ResponseHeaderBag.php";}s:46:"Symfony/Component/HttpFoundation/ServerBag.php";a:4:{s:6:"md5sum";s:32:"f0ac2d2b1071ccec5884200d0ab5e420";s:4:"name";s:46:"Symfony/Component/HttpFoundation/ServerBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/ServerBag.php";}s:67:"Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php";a:4:{s:6:"md5sum";s:32:"09a642bc5ffa1e2e7cb7aad84cdbc755";s:4:"name";s:67:"Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php";}s:76:"Symfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.php";a:4:{s:6:"md5sum";s:32:"47cf442d27aa801d2ee1c43eb1b92ab6";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.php";}s:77:"Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php";a:4:{s:6:"md5sum";s:32:"bb24d40c233c7edbeaed0286f399d22d";s:4:"name";s:77:"Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php";}s:69:"Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php";a:4:{s:6:"md5sum";s:32:"47e8fa7a8f184ec2bef7e90741a030bb";s:4:"name";s:69:"Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php";}s:59:"Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php";a:4:{s:6:"md5sum";s:32:"fd24bb3a7c43f869f28c5f27e08bb257";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php";}s:68:"Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php";a:4:{s:6:"md5sum";s:32:"3ecf0692351b914a8822f5138d801682";s:4:"name";s:68:"Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php";}s:52:"Symfony/Component/HttpFoundation/Session/Session.php";a:4:{s:6:"md5sum";s:32:"b25cb46112eac2e01f6d48a0c89c4716";s:4:"name";s:52:"Symfony/Component/HttpFoundation/Session/Session.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Session.php";}s:64:"Symfony/Component/HttpFoundation/Session/SessionBagInterface.php";a:4:{s:6:"md5sum";s:32:"baa130a80f887fca702556b7cb7ac61e";s:4:"name";s:64:"Symfony/Component/HttpFoundation/Session/SessionBagInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/SessionBagInterface.php";}s:61:"Symfony/Component/HttpFoundation/Session/SessionInterface.php";a:4:{s:6:"md5sum";s:32:"33e385a590e619684d37bead5b90a7eb";s:4:"name";s:61:"Symfony/Component/HttpFoundation/Session/SessionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/SessionInterface.php";}s:84:"Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php";a:4:{s:6:"md5sum";s:32:"93364ba7a594762ef28e712bb9dd7e48";s:4:"name";s:84:"Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php";}s:83:"Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php";a:4:{s:6:"md5sum";s:32:"6c4948a4a2c2400936ecf7552e67f7d3";s:4:"name";s:83:"Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php";}s:82:"Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php";a:4:{s:6:"md5sum";s:32:"3b8368e6dcaa7edfd508726ebf1d0a5a";s:4:"name";s:82:"Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php";}s:85:"Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php";a:4:{s:6:"md5sum";s:32:"fe93aa5204757c30501b59d3ab98550b";s:4:"name";s:85:"Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php";}s:81:"Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php";a:4:{s:6:"md5sum";s:32:"36574daf922d67815c3efda0063b7af2";s:4:"name";s:81:"Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php";}s:79:"Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php";a:4:{s:6:"md5sum";s:32:"26845162d0cd8e65c3524bf2413b6025";s:4:"name";s:79:"Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php";}s:78:"Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php";a:4:{s:6:"md5sum";s:32:"5d66bb0aff4e6e04dea4a71dc6b74f2d";s:4:"name";s:78:"Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php";}s:85:"Symfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.php";a:4:{s:6:"md5sum";s:32:"d5cc5b83b3809aa9cbe8023c7cfd3845";s:4:"name";s:85:"Symfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.php";}s:64:"Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php";a:4:{s:6:"md5sum";s:32:"0ba968002df893468d99e77dfde92b95";s:4:"name";s:64:"Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php";}s:76:"Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php";a:4:{s:6:"md5sum";s:32:"b8d920694b05fe7820867c8271e5b519";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php";}s:75:"Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php";a:4:{s:6:"md5sum";s:32:"bbe1e2bea9239bfe24e45baadb6a330d";s:4:"name";s:75:"Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php";}s:73:"Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php";a:4:{s:6:"md5sum";s:32:"7b886167def5c49469577a533a4c2f6c";s:4:"name";s:73:"Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php";}s:76:"Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php";a:4:{s:6:"md5sum";s:32:"d5a28453f64db20f1d07f28af5213cfb";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php";}s:72:"Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php";a:4:{s:6:"md5sum";s:32:"3b9152152614a4e0d7886d16e8162926";s:4:"name";s:72:"Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php";}s:70:"Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php";a:4:{s:6:"md5sum";s:32:"4da090373635a3ca9732171dadfd4ed0";s:4:"name";s:70:"Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php";}s:78:"Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php";a:4:{s:6:"md5sum";s:32:"1436f383c0e3500de401861230f5400a";s:4:"name";s:78:"Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php";}s:76:"Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php";a:4:{s:6:"md5sum";s:32:"af85e7a0bab5c49be82a9244b4cde282";s:4:"name";s:76:"Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php";}s:53:"Symfony/Component/HttpFoundation/StreamedResponse.php";a:4:{s:6:"md5sum";s:32:"4b1b42d5e606ea929c4406f32826fcca";s:4:"name";s:53:"Symfony/Component/HttpFoundation/StreamedResponse.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/StreamedResponse.php";}s:63:"Symfony/Component/HttpFoundation/Tests/AcceptHeaderItemTest.php";a:4:{s:6:"md5sum";s:32:"71279e63c94c58a19de6c9bfe9183847";s:4:"name";s:63:"Symfony/Component/HttpFoundation/Tests/AcceptHeaderItemTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderItemTest.php";}s:59:"Symfony/Component/HttpFoundation/Tests/AcceptHeaderTest.php";a:4:{s:6:"md5sum";s:32:"ca12f957cfb0c92c2f8715b455f29607";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/AcceptHeaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderTest.php";}s:60:"Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.php";a:4:{s:6:"md5sum";s:32:"7bc8ed0abe9d2fc50e676222891ede1a";s:4:"name";s:60:"Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.php";}s:65:"Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php";a:4:{s:6:"md5sum";s:32:"806f7315eef4b6abdbe35a22c50369c0";s:4:"name";s:65:"Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php";}s:53:"Symfony/Component/HttpFoundation/Tests/CookieTest.php";a:4:{s:6:"md5sum";s:32:"1c7af317329cb2e4dae2e8582c090aad";s:4:"name";s:53:"Symfony/Component/HttpFoundation/Tests/CookieTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/CookieTest.php";}s:71:"Symfony/Component/HttpFoundation/Tests/ExpressionRequestMatcherTest.php";a:4:{s:6:"md5sum";s:32:"f156d2ad465b76775f67bdbf386083b3";s:4:"name";s:71:"Symfony/Component/HttpFoundation/Tests/ExpressionRequestMatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ExpressionRequestMatcherTest.php";}s:56:"Symfony/Component/HttpFoundation/Tests/File/FileTest.php";a:4:{s:6:"md5sum";s:32:"7a08ef205764facbe5646cd24074c937";s:4:"name";s:56:"Symfony/Component/HttpFoundation/Tests/File/FileTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/FileTest.php";}s:70:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextension";a:4:{s:6:"md5sum";s:32:"8fa14cdd754f91cc6554c9e71929cce7";s:4:"name";s:70:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextension";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextension";}s:69:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.empty";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:69:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.empty";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.empty";}s:57:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/test";a:4:{s:6:"md5sum";s:32:"87aec5a94c94ec7a5dd1c0839eb0182b";s:4:"name";s:57:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/test";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test";}s:61:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gif";a:4:{s:6:"md5sum";s:32:"87aec5a94c94ec7a5dd1c0839eb0182b";s:4:"name";s:61:"Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gif";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gif";}s:69:"Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php";a:4:{s:6:"md5sum";s:32:"a167d71d8028a1eda64cc8d899f5f6e3";s:4:"name";s:69:"Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php";}s:64:"Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.php";a:4:{s:6:"md5sum";s:32:"7b45d61227c547c01973ae0d48082796";s:4:"name";s:64:"Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.php";}s:54:"Symfony/Component/HttpFoundation/Tests/FileBagTest.php";a:4:{s:6:"md5sum";s:32:"17f9729e4532b0faed835935233250d0";s:4:"name";s:54:"Symfony/Component/HttpFoundation/Tests/FileBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/FileBagTest.php";}s:56:"Symfony/Component/HttpFoundation/Tests/HeaderBagTest.php";a:4:{s:6:"md5sum";s:32:"c2ca1229b730159f6f7bf2ecfec49825";s:4:"name";s:56:"Symfony/Component/HttpFoundation/Tests/HeaderBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/HeaderBagTest.php";}s:54:"Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php";a:4:{s:6:"md5sum";s:32:"6c47d0ca15feaad0e369dd514101b100";s:4:"name";s:54:"Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php";}s:59:"Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php";a:4:{s:6:"md5sum";s:32:"3b443a39c7580eab6e59f53022284ae0";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php";}s:59:"Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php";a:4:{s:6:"md5sum";s:32:"019b8d85e6f650aed3292af213a0643c";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php";}s:63:"Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php";a:4:{s:6:"md5sum";s:32:"2379f3910f6f55a3c72315a25dfdf388";s:4:"name";s:63:"Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php";}s:61:"Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php";a:4:{s:6:"md5sum";s:32:"99352f4118b2c568fda24db10858555c";s:4:"name";s:61:"Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php";}s:59:"Symfony/Component/HttpFoundation/Tests/RequestStackTest.php";a:4:{s:6:"md5sum";s:32:"5ab9a5e9dda53ed1f022634f8136d4fd";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/RequestStackTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestStackTest.php";}s:54:"Symfony/Component/HttpFoundation/Tests/RequestTest.php";a:4:{s:6:"md5sum";s:32:"6406b7aabef145bb68b018da2b9d7780";s:4:"name";s:54:"Symfony/Component/HttpFoundation/Tests/RequestTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestTest.php";}s:64:"Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php";a:4:{s:6:"md5sum";s:32:"e268328250a58f53892622dff9ed2b37";s:4:"name";s:64:"Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php";}s:55:"Symfony/Component/HttpFoundation/Tests/ResponseTest.php";a:4:{s:6:"md5sum";s:32:"a17240ff298468ada33c1f15e3ec5012";s:4:"name";s:55:"Symfony/Component/HttpFoundation/Tests/ResponseTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTest.php";}s:59:"Symfony/Component/HttpFoundation/Tests/ResponseTestCase.php";a:4:{s:6:"md5sum";s:32:"3a86e8988d2cf1a094322bfd0b38c045";s:4:"name";s:59:"Symfony/Component/HttpFoundation/Tests/ResponseTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.php";}s:56:"Symfony/Component/HttpFoundation/Tests/ServerBagTest.php";a:4:{s:6:"md5sum";s:32:"feb7545b69e0eda1a61be511e9135582";s:4:"name";s:56:"Symfony/Component/HttpFoundation/Tests/ServerBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php";}s:77:"Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.php";a:4:{s:6:"md5sum";s:32:"fbcb35c2d86007ac5311394d67081cda";s:4:"name";s:77:"Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.php";}s:87:"Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php";a:4:{s:6:"md5sum";s:32:"c281ff06081b6ae87f4356f37a2814e1";s:4:"name";s:87:"Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php";}s:79:"Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php";a:4:{s:6:"md5sum";s:32:"763835431c792f3e0b5bbba96794542a";s:4:"name";s:79:"Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:129:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php";}s:69:"Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php";a:4:{s:6:"md5sum";s:32:"18cf905cc6ead1acbf260f484564425f";s:4:"name";s:69:"Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php";}s:62:"Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php";a:4:{s:6:"md5sum";s:32:"6a494d5992105e3ebe9c391b7d6f6a63";s:4:"name";s:62:"Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php";}s:94:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php";a:4:{s:6:"md5sum";s:32:"f44ffbb61b65fe70de11d6469e48832a";s:4:"name";s:94:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:144:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php";}s:93:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php";a:4:{s:6:"md5sum";s:32:"c7f7e944a63d1af11e55e6ec4a9374b2";s:4:"name";s:93:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:143:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php";}s:92:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php";a:4:{s:6:"md5sum";s:32:"c2f1f103720b87b039183451427d74c4";s:4:"name";s:92:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:142:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php";}s:95:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php";a:4:{s:6:"md5sum";s:32:"8fa508beab426cea19a2cedabd5e9171";s:4:"name";s:95:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:145:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php";}s:91:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php";a:4:{s:6:"md5sum";s:32:"45eae4ba5310a98dc04fcadf82bf720d";s:4:"name";s:91:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:141:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php";}s:89:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php";a:4:{s:6:"md5sum";s:32:"2c0feb6c09d60d7e5926ea5a8da36080";s:4:"name";s:89:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:139:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php";}s:88:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php";a:4:{s:6:"md5sum";s:32:"f36ec391bb99db52a49f7ca30360ea26";s:4:"name";s:88:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:138:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php";}s:95:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php";a:4:{s:6:"md5sum";s:32:"11d0598235d0d7f8098bdc2145d9d69b";s:4:"name";s:95:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:145:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php";}s:74:"Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php";a:4:{s:6:"md5sum";s:32:"fc2af1f274721774e972a5758278c8f3";s:4:"name";s:74:"Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php";}s:86:"Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php";a:4:{s:6:"md5sum";s:32:"87a2d57546023c4094f6be942a4b13c2";s:4:"name";s:86:"Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php";}s:85:"Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php";a:4:{s:6:"md5sum";s:32:"592ade20d8c465762c8e5a121d60ac52";s:4:"name";s:85:"Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php";}s:83:"Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php";a:4:{s:6:"md5sum";s:32:"bbc650e69324fd0d48491db754f248e4";s:4:"name";s:83:"Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:133:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php";}s:86:"Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php";a:4:{s:6:"md5sum";s:32:"b10ca7f822772f799c1f1e68ad9eaf55";s:4:"name";s:86:"Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php";}s:82:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php";a:4:{s:6:"md5sum";s:32:"da5bd63668cf3a8b28b6190b22b3271a";s:4:"name";s:82:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:132:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php";}s:80:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php";a:4:{s:6:"md5sum";s:32:"1baf3702ba27dc4cfdfe750f18bd8b39";s:4:"name";s:80:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php";}s:88:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php";a:4:{s:6:"md5sum";s:32:"e2a32ca244d28b43eb7a15edbb1f65c2";s:4:"name";s:88:"Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:138:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php";}s:63:"Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php";a:4:{s:6:"md5sum";s:32:"73647306210e7be2a18cf3a523275748";s:4:"name";s:63:"Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:33:{s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:81:"/opt/alt/php54/usr/share/doc/pear/HttpFoundation/Symfony/Component/HttpFoundation";b:1;s:66:"/opt/alt/php54/usr/share/doc/pear/HttpFoundation/Symfony/Component";b:1;s:56:"/opt/alt/php54/usr/share/doc/pear/HttpFoundation/Symfony";b:1;s:48:"/opt/alt/php54/usr/share/doc/pear/HttpFoundation";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/Exception";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File";b:1;s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/File/MimeType";b:1;s:82:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation";b:1;s:67:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component";b:1;s:57:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony";b:1;s:49:"/opt/alt/php54/usr/share/pear/test/HttpFoundation";b:1;s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Resources/stubs";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Resources";b:1;s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Attribute";b:1;s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session";b:1;s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Flash";b:1;s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Handler";b:1;s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage";b:1;s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/HttpFoundation/Session/Storage/Proxy";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests";b:1;s:93:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File";b:1;s:102:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures";b:1;s:112:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory";b:1;s:102:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/MimeType";b:1;s:106:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute";b:1;s:96:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session";b:1;s:102:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash";b:1;s:112:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler";b:1;s:104:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage";b:1;s:110:"/opt/alt/php54/usr/share/pear/test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!4=//2.registry/.channel.pear.symfony.com/twigbridge.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:10:"TwigBridge";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:20:"Symfony2 Twig Bridge";s:11:"description";s:20:"Symfony2 Twig Bridge";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:40";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:64:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e563ac483a8dbba1bc0548a4235a144a";s:4:"name";s:34:"Symfony/Bridge/Twig/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"24b7a25e7391c3ca87f58d8a328a10f9";s:4:"name";s:32:"Symfony/Bridge/Twig/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f95ddec9fc8092fd32900b7bff18b251";s:4:"name";s:33:"Symfony/Bridge/Twig/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ce21bdc85dfe3a9363d954915f655592";s:4:"name";s:47:"Symfony/Bridge/Twig/Extension/CodeExtension.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"65698eda8cff6e905e08122e58687c86";s:4:"name";s:53:"Symfony/Bridge/Twig/Extension/ExpressionExtension.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c3ee7041691d8a13626e3242b50ba9a2";s:4:"name";s:47:"Symfony/Bridge/Twig/Extension/FormExtension.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae8fd7e7957f71843eb72b0dfea84386";s:4:"name";s:53:"Symfony/Bridge/Twig/Extension/HttpKernelExtension.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b1e34bbc300fb73296ed795e3cf200b5";s:4:"name";s:50:"Symfony/Bridge/Twig/Extension/RoutingExtension.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"406e316d507396925ce36c5039bf0c6b";s:4:"name";s:51:"Symfony/Bridge/Twig/Extension/SecurityExtension.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bcbf90a6081eb164ebf8aa26424034cf";s:4:"name";s:52:"Symfony/Bridge/Twig/Extension/StopwatchExtension.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cee4a3d32bbd87757b2c6cd4de05e209";s:4:"name";s:54:"Symfony/Bridge/Twig/Extension/TranslationExtension.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae5855df258047211247fdfb8cb9cb9c";s:4:"name";s:47:"Symfony/Bridge/Twig/Extension/YamlExtension.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"96815060d6bee8fbcfecd4f0ca94cc7c";s:4:"name";s:41:"Symfony/Bridge/Twig/Form/TwigRenderer.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"edf3b98358b100da17afa76a9acacdd5";s:4:"name";s:47:"Symfony/Bridge/Twig/Form/TwigRendererEngine.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"02bc975c2fcb576a69c8e5ffa2e14ce5";s:4:"name";s:56:"Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"96103a4ce079ad131d65578737a381c6";s:4:"name";s:50:"Symfony/Bridge/Twig/Form/TwigRendererInterface.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:27:"Symfony/Bridge/Twig/LICENSE";s:4:"role";s:3:"doc";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eeaac65947d7a23199b9ab2b3421295f";s:4:"name";s:44:"Symfony/Bridge/Twig/Node/FormEnctypeNode.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a7532f88e5dbae6209363fc2d5fdc358";s:4:"name";s:42:"Symfony/Bridge/Twig/Node/FormThemeNode.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9a15391aa07a352fae06f7ed12a9fd60";s:4:"name";s:44:"Symfony/Bridge/Twig/Node/RenderBlockNode.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2e379adad86d64a326c899290ede04ad";s:4:"name";s:53:"Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"23ed426e4e8ecbb7694e7ea41b9b0890";s:4:"name";s:42:"Symfony/Bridge/Twig/Node/StopwatchNode.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0526f6b70eaba23a52160d231433f9a2";s:4:"name";s:51:"Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e1d88cb3d69813c50c1d7f847a3998fb";s:4:"name";s:38:"Symfony/Bridge/Twig/Node/TransNode.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"748686792da8fc6ece450126fadad7c8";s:4:"name";s:41:"Symfony/Bridge/Twig/NodeVisitor/Scope.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"519ceb71a1f48a857850fefc9f899e65";s:4:"name";s:71:"Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"20a1ae206f399b7a45474eed11242532";s:4:"name";s:58:"Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b2790b452896e6c319fef59e08204ca3";s:4:"name";s:36:"Symfony/Bridge/Twig/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09c10943b1bd396bdd40244b6f1670de";s:4:"name";s:29:"Symfony/Bridge/Twig/README.md";s:4:"role";s:3:"doc";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7db396d0e3531236572ab842e1d785f3";s:4:"name";s:66:"Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bf705e344ab695195d83108c5a744291";s:4:"name";s:68:"Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"62b01d26c529435b127df0b68da87a8e";s:4:"name";s:57:"Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig";s:4:"role";s:4:"test";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"de9fa5a69d9ffeaace77f48c8c970a16";s:4:"name";s:57:"Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php";s:4:"role";s:4:"test";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"341920fd913325029b8875d19416f539";s:4:"name";s:60:"Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twig";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"59f22743c289e6a916c20f335245b023";s:4:"name";s:63:"Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php";s:4:"role";s:4:"test";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d721545275f06c65c48b93fff1d63008";s:4:"name";s:69:"Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php";s:4:"role";s:4:"test";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2e4ed81306cf97510d18da3f33289fd7";s:4:"name";s:63:"Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php";s:4:"role";s:4:"test";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"54d08b06b4f1626df69403bfba38218f";s:4:"name";s:66:"Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php";s:4:"role";s:4:"test";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ce9150c7e8fabcbe1539051f087a5c7b";s:4:"name";s:68:"Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b54b450a89e781ad60a2807fb2678eeb";s:4:"name";s:63:"Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php";s:4:"role";s:4:"test";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6753e22fa543cb3368c9e0000e2f270c";s:4:"name";s:66:"Symfony/Bridge/Twig/Tests/Extension/page_dynamic_extends.html.twig";s:4:"role";s:4:"test";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6861f5bb94faf3b42691192cf3017750";s:4:"name";s:58:"Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig";s:4:"role";s:4:"test";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7897b6f0d377c1dcbc7b1a9d34450b40";s:4:"name";s:60:"Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php";s:4:"role";s:4:"test";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"40377cd7f95bb691e04c883df5a09db5";s:4:"name";s:62:"Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php";s:4:"role";s:4:"test";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d43686f93a9702b4cfd91df3053b602b";s:4:"name";s:51:"Symfony/Bridge/Twig/Tests/Extension/theme.html.twig";s:4:"role";s:4:"test";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d172147242bd0b80e328e6e9e88dd5e7";s:4:"name";s:59:"Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig";s:4:"role";s:4:"test";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e4a1661a04d5bafdd840b035f0c9511e";s:4:"name";s:55:"Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig";s:4:"role";s:4:"test";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eb868a90365c1c3b2f7573551a8a45a3";s:4:"name";s:64:"Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php";s:4:"role";s:4:"test";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0af17ef668b1281a4e89bf51028ec695";s:4:"name";s:48:"Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php";s:4:"role";s:4:"test";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b8b963bd2b033ae246edd3ba7d6f97e";s:4:"name";s:63:"Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php";s:4:"role";s:4:"test";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7fd3f6760029514c0a55503418d8b0b4";s:4:"name";s:51:"Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c8f71ffe1e4fcb0bb4a69120feb30bd0";s:4:"name";s:81:"Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php";s:4:"role";s:4:"test";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ec0588a5b4d7dd36d668a39a8849dd72";s:4:"name";s:68:"Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php";s:4:"role";s:4:"test";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d8c329c5c7afb266a65967762f0684f2";s:4:"name";s:58:"Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php";s:4:"role";s:4:"test";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"95b22c803b2c8065500328508c60ed02";s:4:"name";s:66:"Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php";s:4:"role";s:4:"test";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9cd79976725b5279223a0e16a318f292";s:4:"name";s:59:"Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php";s:4:"role";s:4:"test";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f73d33e407b60220f8c6af100a4d0358";s:4:"name";s:44:"Symfony/Bridge/Twig/Tests/TwigEngineTest.php";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4e9ee4d27632d7c1f1de3795480df67";s:4:"name";s:56:"Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php";s:4:"role";s:3:"php";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"748c45d30621f1f2d245102924f7fdff";s:4:"name";s:56:"Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php";s:4:"role";s:3:"php";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0354e3a6d83924f2da374f158de149ba";s:4:"name";s:58:"Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php";s:4:"role";s:3:"php";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"58650d506d0035b1622780ababcfca5a";s:4:"name";s:65:"Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php";s:4:"role";s:3:"php";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"27e4d98f60a06de551c32d2e852c7139";s:4:"name";s:52:"Symfony/Bridge/Twig/TokenParser/TransTokenParser.php";s:4:"role";s:3:"php";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b914862fe8b32c41e260ea530bd430f1";s:4:"name";s:49:"Symfony/Bridge/Twig/Translation/TwigExtractor.php";s:4:"role";s:3:"php";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e11b1b874251de2867b3673a674ff71d";s:4:"name";s:34:"Symfony/Bridge/Twig/TwigEngine.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}s:8:"optional";a:1:{s:7:"package";a:4:{i:0;a:2:{s:4:"name";s:4:"Form";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:7:"Routing";s:7:"channel";s:16:"pear.symfony.com";}i:2;a:2:{s:4:"name";s:11:"Translation";s:7:"channel";s:16:"pear.symfony.com";}i:3;a:2:{s:4:"name";s:4:"Yaml";s:7:"channel";s:16:"pear.symfony.com";}}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:64:{s:34:"Symfony/Bridge/Twig/autoloader.php";a:4:{s:6:"md5sum";s:32:"e563ac483a8dbba1bc0548a4235a144a";s:4:"name";s:34:"Symfony/Bridge/Twig/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:64:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/autoloader.php";}s:32:"Symfony/Bridge/Twig/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"24b7a25e7391c3ca87f58d8a328a10f9";s:4:"name";s:32:"Symfony/Bridge/Twig/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/doc/pear/TwigBridge/Symfony/Bridge/Twig/CHANGELOG.md";}s:33:"Symfony/Bridge/Twig/composer.json";a:4:{s:6:"md5sum";s:32:"f95ddec9fc8092fd32900b7bff18b251";s:4:"name";s:33:"Symfony/Bridge/Twig/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/doc/pear/TwigBridge/Symfony/Bridge/Twig/composer.json";}s:47:"Symfony/Bridge/Twig/Extension/CodeExtension.php";a:4:{s:6:"md5sum";s:32:"ce21bdc85dfe3a9363d954915f655592";s:4:"name";s:47:"Symfony/Bridge/Twig/Extension/CodeExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension/CodeExtension.php";}s:53:"Symfony/Bridge/Twig/Extension/ExpressionExtension.php";a:4:{s:6:"md5sum";s:32:"65698eda8cff6e905e08122e58687c86";s:4:"name";s:53:"Symfony/Bridge/Twig/Extension/ExpressionExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension/ExpressionExtension.php";}s:47:"Symfony/Bridge/Twig/Extension/FormExtension.php";a:4:{s:6:"md5sum";s:32:"c3ee7041691d8a13626e3242b50ba9a2";s:4:"name";s:47:"Symfony/Bridge/Twig/Extension/FormExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension/FormExtension.php";}s:53:"Symfony/Bridge/Twig/Extension/HttpKernelExtension.php";a:4:{s:6:"md5sum";s:32:"ae8fd7e7957f71843eb72b0dfea84386";s:4:"name";s:53:"Symfony/Bridge/Twig/Extension/HttpKernelExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php";}s:50:"Symfony/Bridge/Twig/Extension/RoutingExtension.php";a:4:{s:6:"md5sum";s:32:"b1e34bbc300fb73296ed795e3cf200b5";s:4:"name";s:50:"Symfony/Bridge/Twig/Extension/RoutingExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension/RoutingExtension.php";}s:51:"Symfony/Bridge/Twig/Extension/SecurityExtension.php";a:4:{s:6:"md5sum";s:32:"406e316d507396925ce36c5039bf0c6b";s:4:"name";s:51:"Symfony/Bridge/Twig/Extension/SecurityExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension/SecurityExtension.php";}s:52:"Symfony/Bridge/Twig/Extension/StopwatchExtension.php";a:4:{s:6:"md5sum";s:32:"bcbf90a6081eb164ebf8aa26424034cf";s:4:"name";s:52:"Symfony/Bridge/Twig/Extension/StopwatchExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension/StopwatchExtension.php";}s:54:"Symfony/Bridge/Twig/Extension/TranslationExtension.php";a:4:{s:6:"md5sum";s:32:"cee4a3d32bbd87757b2c6cd4de05e209";s:4:"name";s:54:"Symfony/Bridge/Twig/Extension/TranslationExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension/TranslationExtension.php";}s:47:"Symfony/Bridge/Twig/Extension/YamlExtension.php";a:4:{s:6:"md5sum";s:32:"ae5855df258047211247fdfb8cb9cb9c";s:4:"name";s:47:"Symfony/Bridge/Twig/Extension/YamlExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension/YamlExtension.php";}s:41:"Symfony/Bridge/Twig/Form/TwigRenderer.php";a:4:{s:6:"md5sum";s:32:"96815060d6bee8fbcfecd4f0ca94cc7c";s:4:"name";s:41:"Symfony/Bridge/Twig/Form/TwigRenderer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Form/TwigRenderer.php";}s:47:"Symfony/Bridge/Twig/Form/TwigRendererEngine.php";a:4:{s:6:"md5sum";s:32:"edf3b98358b100da17afa76a9acacdd5";s:4:"name";s:47:"Symfony/Bridge/Twig/Form/TwigRendererEngine.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Form/TwigRendererEngine.php";}s:56:"Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php";a:4:{s:6:"md5sum";s:32:"02bc975c2fcb576a69c8e5ffa2e14ce5";s:4:"name";s:56:"Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php";}s:50:"Symfony/Bridge/Twig/Form/TwigRendererInterface.php";a:4:{s:6:"md5sum";s:32:"96103a4ce079ad131d65578737a381c6";s:4:"name";s:50:"Symfony/Bridge/Twig/Form/TwigRendererInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Form/TwigRendererInterface.php";}s:27:"Symfony/Bridge/Twig/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:27:"Symfony/Bridge/Twig/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/doc/pear/TwigBridge/Symfony/Bridge/Twig/LICENSE";}s:44:"Symfony/Bridge/Twig/Node/FormEnctypeNode.php";a:4:{s:6:"md5sum";s:32:"eeaac65947d7a23199b9ab2b3421295f";s:4:"name";s:44:"Symfony/Bridge/Twig/Node/FormEnctypeNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Node/FormEnctypeNode.php";}s:42:"Symfony/Bridge/Twig/Node/FormThemeNode.php";a:4:{s:6:"md5sum";s:32:"a7532f88e5dbae6209363fc2d5fdc358";s:4:"name";s:42:"Symfony/Bridge/Twig/Node/FormThemeNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Node/FormThemeNode.php";}s:44:"Symfony/Bridge/Twig/Node/RenderBlockNode.php";a:4:{s:6:"md5sum";s:32:"9a15391aa07a352fae06f7ed12a9fd60";s:4:"name";s:44:"Symfony/Bridge/Twig/Node/RenderBlockNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Node/RenderBlockNode.php";}s:53:"Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php";a:4:{s:6:"md5sum";s:32:"2e379adad86d64a326c899290ede04ad";s:4:"name";s:53:"Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php";}s:42:"Symfony/Bridge/Twig/Node/StopwatchNode.php";a:4:{s:6:"md5sum";s:32:"23ed426e4e8ecbb7694e7ea41b9b0890";s:4:"name";s:42:"Symfony/Bridge/Twig/Node/StopwatchNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Node/StopwatchNode.php";}s:51:"Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php";a:4:{s:6:"md5sum";s:32:"0526f6b70eaba23a52160d231433f9a2";s:4:"name";s:51:"Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php";}s:38:"Symfony/Bridge/Twig/Node/TransNode.php";a:4:{s:6:"md5sum";s:32:"e1d88cb3d69813c50c1d7f847a3998fb";s:4:"name";s:38:"Symfony/Bridge/Twig/Node/TransNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Node/TransNode.php";}s:41:"Symfony/Bridge/Twig/NodeVisitor/Scope.php";a:4:{s:6:"md5sum";s:32:"748686792da8fc6ece450126fadad7c8";s:4:"name";s:41:"Symfony/Bridge/Twig/NodeVisitor/Scope.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/NodeVisitor/Scope.php";}s:71:"Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php";a:4:{s:6:"md5sum";s:32:"519ceb71a1f48a857850fefc9f899e65";s:4:"name";s:71:"Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php";}s:58:"Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php";a:4:{s:6:"md5sum";s:32:"20a1ae206f399b7a45474eed11242532";s:4:"name";s:58:"Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php";}s:36:"Symfony/Bridge/Twig/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"b2790b452896e6c319fef59e08204ca3";s:4:"name";s:36:"Symfony/Bridge/Twig/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/phpunit.xml.dist";}s:29:"Symfony/Bridge/Twig/README.md";a:4:{s:6:"md5sum";s:32:"09c10943b1bd396bdd40244b6f1670de";s:4:"name";s:29:"Symfony/Bridge/Twig/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/doc/pear/TwigBridge/Symfony/Bridge/Twig/README.md";}s:66:"Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig";a:4:{s:6:"md5sum";s:32:"7db396d0e3531236572ab842e1d785f3";s:4:"name";s:66:"Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig";}s:68:"Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig";a:4:{s:6:"md5sum";s:32:"bf705e344ab695195d83108c5a744291";s:4:"name";s:68:"Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig";}s:57:"Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig";a:4:{s:6:"md5sum";s:32:"62b01d26c529435b127df0b68da87a8e";s:4:"name";s:57:"Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig";}s:57:"Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php";a:4:{s:6:"md5sum";s:32:"de9fa5a69d9ffeaace77f48c8c970a16";s:4:"name";s:57:"Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php";}s:60:"Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twig";a:4:{s:6:"md5sum";s:32:"341920fd913325029b8875d19416f539";s:4:"name";s:60:"Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twig";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twig";}s:63:"Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php";a:4:{s:6:"md5sum";s:32:"59f22743c289e6a916c20f335245b023";s:4:"name";s:63:"Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php";}s:69:"Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php";a:4:{s:6:"md5sum";s:32:"d721545275f06c65c48b93fff1d63008";s:4:"name";s:69:"Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php";}s:63:"Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php";a:4:{s:6:"md5sum";s:32:"2e4ed81306cf97510d18da3f33289fd7";s:4:"name";s:63:"Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php";}s:66:"Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php";a:4:{s:6:"md5sum";s:32:"54d08b06b4f1626df69403bfba38218f";s:4:"name";s:66:"Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php";}s:68:"Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php";a:4:{s:6:"md5sum";s:32:"ce9150c7e8fabcbe1539051f087a5c7b";s:4:"name";s:68:"Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php";}s:63:"Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php";a:4:{s:6:"md5sum";s:32:"b54b450a89e781ad60a2807fb2678eeb";s:4:"name";s:63:"Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php";}s:66:"Symfony/Bridge/Twig/Tests/Extension/page_dynamic_extends.html.twig";a:4:{s:6:"md5sum";s:32:"6753e22fa543cb3368c9e0000e2f270c";s:4:"name";s:66:"Symfony/Bridge/Twig/Tests/Extension/page_dynamic_extends.html.twig";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/page_dynamic_extends.html.twig";}s:58:"Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig";a:4:{s:6:"md5sum";s:32:"6861f5bb94faf3b42691192cf3017750";s:4:"name";s:58:"Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig";}s:60:"Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php";a:4:{s:6:"md5sum";s:32:"7897b6f0d377c1dcbc7b1a9d34450b40";s:4:"name";s:60:"Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php";}s:62:"Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php";a:4:{s:6:"md5sum";s:32:"40377cd7f95bb691e04c883df5a09db5";s:4:"name";s:62:"Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php";}s:51:"Symfony/Bridge/Twig/Tests/Extension/theme.html.twig";a:4:{s:6:"md5sum";s:32:"d43686f93a9702b4cfd91df3053b602b";s:4:"name";s:51:"Symfony/Bridge/Twig/Tests/Extension/theme.html.twig";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme.html.twig";}s:59:"Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig";a:4:{s:6:"md5sum";s:32:"d172147242bd0b80e328e6e9e88dd5e7";s:4:"name";s:59:"Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig";}s:55:"Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig";a:4:{s:6:"md5sum";s:32:"e4a1661a04d5bafdd840b035f0c9511e";s:4:"name";s:55:"Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig";}s:64:"Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php";a:4:{s:6:"md5sum";s:32:"eb868a90365c1c3b2f7573551a8a45a3";s:4:"name";s:64:"Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php";}s:48:"Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php";a:4:{s:6:"md5sum";s:32:"0af17ef668b1281a4e89bf51028ec695";s:4:"name";s:48:"Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php";}s:63:"Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php";a:4:{s:6:"md5sum";s:32:"7b8b963bd2b033ae246edd3ba7d6f97e";s:4:"name";s:63:"Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php";}s:51:"Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php";a:4:{s:6:"md5sum";s:32:"7fd3f6760029514c0a55503418d8b0b4";s:4:"name";s:51:"Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php";}s:81:"Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php";a:4:{s:6:"md5sum";s:32:"c8f71ffe1e4fcb0bb4a69120feb30bd0";s:4:"name";s:81:"Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php";}s:68:"Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php";a:4:{s:6:"md5sum";s:32:"ec0588a5b4d7dd36d668a39a8849dd72";s:4:"name";s:68:"Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php";}s:58:"Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php";a:4:{s:6:"md5sum";s:32:"d8c329c5c7afb266a65967762f0684f2";s:4:"name";s:58:"Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php";}s:66:"Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php";a:4:{s:6:"md5sum";s:32:"95b22c803b2c8065500328508c60ed02";s:4:"name";s:66:"Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php";}s:59:"Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php";a:4:{s:6:"md5sum";s:32:"9cd79976725b5279223a0e16a318f292";s:4:"name";s:59:"Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php";}s:44:"Symfony/Bridge/Twig/Tests/TwigEngineTest.php";a:4:{s:6:"md5sum";s:32:"f73d33e407b60220f8c6af100a4d0358";s:4:"name";s:44:"Symfony/Bridge/Twig/Tests/TwigEngineTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/TwigEngineTest.php";}s:56:"Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php";a:4:{s:6:"md5sum";s:32:"b4e9ee4d27632d7c1f1de3795480df67";s:4:"name";s:56:"Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php";}s:56:"Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php";a:4:{s:6:"md5sum";s:32:"748c45d30621f1f2d245102924f7fdff";s:4:"name";s:56:"Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php";}s:58:"Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php";a:4:{s:6:"md5sum";s:32:"0354e3a6d83924f2da374f158de149ba";s:4:"name";s:58:"Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php";}s:65:"Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php";a:4:{s:6:"md5sum";s:32:"58650d506d0035b1622780ababcfca5a";s:4:"name";s:65:"Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php";}s:52:"Symfony/Bridge/Twig/TokenParser/TransTokenParser.php";a:4:{s:6:"md5sum";s:32:"27e4d98f60a06de551c32d2e852c7139";s:4:"name";s:52:"Symfony/Bridge/Twig/TokenParser/TransTokenParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php";}s:49:"Symfony/Bridge/Twig/Translation/TwigExtractor.php";a:4:{s:6:"md5sum";s:32:"b914862fe8b32c41e260ea530bd430f1";s:4:"name";s:49:"Symfony/Bridge/Twig/Translation/TwigExtractor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Translation/TwigExtractor.php";}s:34:"Symfony/Bridge/Twig/TwigEngine.php";a:4:{s:6:"md5sum";s:32:"e11b1b874251de2867b3673a674ff71d";s:4:"name";s:34:"Symfony/Bridge/Twig/TwigEngine.php";s:4:"role";s:3:"php";s:12:"installed_as";s:64:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/TwigEngine.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:27:{s:49:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig";b:1;s:44:"/opt/alt/php54/usr/share/pear/Symfony/Bridge";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:64:"/opt/alt/php54/usr/share/doc/pear/TwigBridge/Symfony/Bridge/Twig";b:1;s:59:"/opt/alt/php54/usr/share/doc/pear/TwigBridge/Symfony/Bridge";b:1;s:52:"/opt/alt/php54/usr/share/doc/pear/TwigBridge/Symfony";b:1;s:44:"/opt/alt/php54/usr/share/doc/pear/TwigBridge";b:1;s:59:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Extension";b:1;s:54:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Form";b:1;s:54:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Node";b:1;s:61:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/NodeVisitor";b:1;s:65:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig";b:1;s:60:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge";b:1;s:53:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/pear/test/TwigBridge";b:1;s:70:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Resources/views/Form";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Resources/views";b:1;s:59:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Resources";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension";b:1;s:71:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures";b:1;s:76:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Node";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/TokenParser";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/TwigBridge/Symfony/Bridge/Twig/Tests/Translation";b:1;s:61:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/TokenParser";b:1;s:61:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Twig/Translation";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:6:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:4:"Form";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:7:"Routing";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:4;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:11:"Translation";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:5;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:4:"Yaml";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506495;}PK!KZ((7.registry/.channel.pear.symfony.com/optionsresolver.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:15:"OptionsResolver";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:34:"Symfony2 OptionsResolver Component";s:11:"description";s:34:"Symfony2 OptionsResolver Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:48";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:14:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a351ecd36b8eb4040ec96d7ec31f606e";s:4:"name";s:48:"Symfony/Component/OptionsResolver/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d028132a61a91d82422a3cc88d3ac8cf";s:4:"name";s:47:"Symfony/Component/OptionsResolver/composer.json";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2ca14134f105bf2a71ed27637b98f09e";s:4:"name";s:66:"Symfony/Component/OptionsResolver/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bd08096bf1d71b06a87f0dcd24f80509";s:4:"name";s:71:"Symfony/Component/OptionsResolver/Exception/InvalidOptionsException.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"712f40bc8e04cfe34ae80939e4a2e355";s:4:"name";s:71:"Symfony/Component/OptionsResolver/Exception/MissingOptionsException.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"024bce08820bd8d6cc23550a23bde693";s:4:"name";s:73:"Symfony/Component/OptionsResolver/Exception/OptionDefinitionException.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:41:"Symfony/Component/OptionsResolver/LICENSE";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dccf3a502dc75c9505bd6bdd739bc6ff";s:4:"name";s:45:"Symfony/Component/OptionsResolver/Options.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"70afa5bf5e189ff6d9d635a45a271619";s:4:"name";s:53:"Symfony/Component/OptionsResolver/OptionsResolver.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ef4778c5c504e26462c4c7125f31c85";s:4:"name";s:62:"Symfony/Component/OptionsResolver/OptionsResolverInterface.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b33f90f18f3c99cc4fbd7a7b80135861";s:4:"name";s:50:"Symfony/Component/OptionsResolver/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87e9152d083c05e57a1617141023e4c0";s:4:"name";s:43:"Symfony/Component/OptionsResolver/README.md";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9e6f46d9615ef96878e18e853f1cf600";s:4:"name";s:63:"Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"db23027503faa4cc9b402a87d5108f24";s:4:"name";s:55:"Symfony/Component/OptionsResolver/Tests/OptionsTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:14:{s:48:"Symfony/Component/OptionsResolver/autoloader.php";a:4:{s:6:"md5sum";s:32:"a351ecd36b8eb4040ec96d7ec31f606e";s:4:"name";s:48:"Symfony/Component/OptionsResolver/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver/autoloader.php";}s:47:"Symfony/Component/OptionsResolver/composer.json";a:4:{s:6:"md5sum";s:32:"d028132a61a91d82422a3cc88d3ac8cf";s:4:"name";s:47:"Symfony/Component/OptionsResolver/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/doc/pear/OptionsResolver/Symfony/Component/OptionsResolver/composer.json";}s:66:"Symfony/Component/OptionsResolver/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"2ca14134f105bf2a71ed27637b98f09e";s:4:"name";s:66:"Symfony/Component/OptionsResolver/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver/Exception/ExceptionInterface.php";}s:71:"Symfony/Component/OptionsResolver/Exception/InvalidOptionsException.php";a:4:{s:6:"md5sum";s:32:"bd08096bf1d71b06a87f0dcd24f80509";s:4:"name";s:71:"Symfony/Component/OptionsResolver/Exception/InvalidOptionsException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver/Exception/InvalidOptionsException.php";}s:71:"Symfony/Component/OptionsResolver/Exception/MissingOptionsException.php";a:4:{s:6:"md5sum";s:32:"712f40bc8e04cfe34ae80939e4a2e355";s:4:"name";s:71:"Symfony/Component/OptionsResolver/Exception/MissingOptionsException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver/Exception/MissingOptionsException.php";}s:73:"Symfony/Component/OptionsResolver/Exception/OptionDefinitionException.php";a:4:{s:6:"md5sum";s:32:"024bce08820bd8d6cc23550a23bde693";s:4:"name";s:73:"Symfony/Component/OptionsResolver/Exception/OptionDefinitionException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver/Exception/OptionDefinitionException.php";}s:41:"Symfony/Component/OptionsResolver/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:41:"Symfony/Component/OptionsResolver/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/doc/pear/OptionsResolver/Symfony/Component/OptionsResolver/LICENSE";}s:45:"Symfony/Component/OptionsResolver/Options.php";a:4:{s:6:"md5sum";s:32:"dccf3a502dc75c9505bd6bdd739bc6ff";s:4:"name";s:45:"Symfony/Component/OptionsResolver/Options.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver/Options.php";}s:53:"Symfony/Component/OptionsResolver/OptionsResolver.php";a:4:{s:6:"md5sum";s:32:"70afa5bf5e189ff6d9d635a45a271619";s:4:"name";s:53:"Symfony/Component/OptionsResolver/OptionsResolver.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver/OptionsResolver.php";}s:62:"Symfony/Component/OptionsResolver/OptionsResolverInterface.php";a:4:{s:6:"md5sum";s:32:"3ef4778c5c504e26462c4c7125f31c85";s:4:"name";s:62:"Symfony/Component/OptionsResolver/OptionsResolverInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver/OptionsResolverInterface.php";}s:50:"Symfony/Component/OptionsResolver/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"b33f90f18f3c99cc4fbd7a7b80135861";s:4:"name";s:50:"Symfony/Component/OptionsResolver/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/OptionsResolver/Symfony/Component/OptionsResolver/phpunit.xml.dist";}s:43:"Symfony/Component/OptionsResolver/README.md";a:4:{s:6:"md5sum";s:32:"87e9152d083c05e57a1617141023e4c0";s:4:"name";s:43:"Symfony/Component/OptionsResolver/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/doc/pear/OptionsResolver/Symfony/Component/OptionsResolver/README.md";}s:63:"Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php";a:4:{s:6:"md5sum";s:32:"9e6f46d9615ef96878e18e853f1cf600";s:4:"name";s:63:"Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php";}s:55:"Symfony/Component/OptionsResolver/Tests/OptionsTest.php";a:4:{s:6:"md5sum";s:32:"db23027503faa4cc9b402a87d5108f24";s:4:"name";s:55:"Symfony/Component/OptionsResolver/Tests/OptionsTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:13:{s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:83:"/opt/alt/php54/usr/share/doc/pear/OptionsResolver/Symfony/Component/OptionsResolver";b:1;s:67:"/opt/alt/php54/usr/share/doc/pear/OptionsResolver/Symfony/Component";b:1;s:57:"/opt/alt/php54/usr/share/doc/pear/OptionsResolver/Symfony";b:1;s:49:"/opt/alt/php54/usr/share/doc/pear/OptionsResolver";b:1;s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/OptionsResolver/Exception";b:1;s:84:"/opt/alt/php54/usr/share/pear/test/OptionsResolver/Symfony/Component/OptionsResolver";b:1;s:68:"/opt/alt/php54/usr/share/pear/test/OptionsResolver/Symfony/Component";b:1;s:58:"/opt/alt/php54/usr/share/pear/test/OptionsResolver/Symfony";b:1;s:50:"/opt/alt/php54/usr/share/pear/test/OptionsResolver";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/OptionsResolver/Symfony/Component/OptionsResolver/Tests";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!..registry/.channel.pear.symfony.com/finder.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:6:"Finder";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:25:"Symfony2 Finder Component";s:11:"description";s:25:"Symfony2 Finder Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:44";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:86:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6fffc29b8377e9fb68b5e302b9ff0a97";s:4:"name";s:52:"Symfony/Component/Finder/Adapter/AbstractAdapter.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7dc817125e50b8b230fa1dd7b505a35b";s:4:"name";s:56:"Symfony/Component/Finder/Adapter/AbstractFindAdapter.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a6b49be9beaee46ef1b3ab81b65c3f5a";s:4:"name";s:53:"Symfony/Component/Finder/Adapter/AdapterInterface.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"787a004fec8cb06949f54d45d0a92dfa";s:4:"name";s:51:"Symfony/Component/Finder/Adapter/BsdFindAdapter.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86f218f5471a950cda80784f16635789";s:4:"name";s:51:"Symfony/Component/Finder/Adapter/GnuFindAdapter.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5550d6d59cd92735c58ea80f58766716";s:4:"name";s:47:"Symfony/Component/Finder/Adapter/PhpAdapter.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"70c27b109779dd46d3a9d0ef38565b42";s:4:"name";s:39:"Symfony/Component/Finder/autoloader.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f18e866785861bb62155c98357afe2d6";s:4:"name";s:37:"Symfony/Component/Finder/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff527c6ba5d45d17b691dd2debe2c3d9";s:4:"name";s:50:"Symfony/Component/Finder/Comparator/Comparator.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f50830cff54249c3d2602120bf7adc56";s:4:"name";s:54:"Symfony/Component/Finder/Comparator/DateComparator.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5be54134d90a013d0685a58bdf395e99";s:4:"name";s:56:"Symfony/Component/Finder/Comparator/NumberComparator.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0ade20562cd194d6ef1d87e3811baf4d";s:4:"name";s:38:"Symfony/Component/Finder/composer.json";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6ec2bf13ee80fa36603a8b1cbaeb3057";s:4:"name";s:60:"Symfony/Component/Finder/Exception/AccessDeniedException.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"543b917aa3964799c231b7f5730010b5";s:4:"name";s:62:"Symfony/Component/Finder/Exception/AdapterFailureException.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"509f10771d6f6158695f24d956ccf611";s:4:"name";s:57:"Symfony/Component/Finder/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0026a361b430ca5ce4bc1a8b199f1c82";s:4:"name";s:68:"Symfony/Component/Finder/Exception/OperationNotPermitedException.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9eb6fca673d7b360706d092ebc91519f";s:4:"name";s:67:"Symfony/Component/Finder/Exception/ShellCommandFailureException.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"344148f9472396a75e505102cade415c";s:4:"name";s:50:"Symfony/Component/Finder/Expression/Expression.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a231c7c1fcea375333c3b4a2c14ab532";s:4:"name";s:44:"Symfony/Component/Finder/Expression/Glob.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f6919b0c7a8545c57d85318b544d0f24";s:4:"name";s:45:"Symfony/Component/Finder/Expression/Regex.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"219c3a5985874bf148c4261c21db14bd";s:4:"name";s:54:"Symfony/Component/Finder/Expression/ValueInterface.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a4f805d1284bcd933f1ee022197c9226";s:4:"name";s:35:"Symfony/Component/Finder/Finder.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0b44ed57af5918230d1b82ecee9c3ba3";s:4:"name";s:33:"Symfony/Component/Finder/Glob.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b043b76cf6d7a5356b2515d28c7ff48a";s:4:"name";s:58:"Symfony/Component/Finder/Iterator/CustomFilterIterator.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"62f326275b0ded2de6cd6209ec2536af";s:4:"name";s:61:"Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"91fd43512fed83211c6cce453e6b45be";s:4:"name";s:62:"Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6cf1f8950c36872e6389337ae41c6268";s:4:"name";s:68:"Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"04c5aafbda629dc67e3d1b36ec56f692";s:4:"name";s:63:"Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c414b7cb71b775f369d676c345b3cbed";s:4:"name";s:60:"Symfony/Component/Finder/Iterator/FilenameFilterIterator.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"92a7737c720fb253f300a5e27cf7b0a3";s:4:"name";s:55:"Symfony/Component/Finder/Iterator/FilePathsIterator.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8848c8e1a14338fead3676ff724b0a18";s:4:"name";s:60:"Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"357568ea6a039bfaf363227eb4823b08";s:4:"name";s:52:"Symfony/Component/Finder/Iterator/FilterIterator.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8343ab9d4fcebfa7be797bccd8ef559";s:4:"name";s:64:"Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7bcb38607afc169b07443b4d166cd646";s:4:"name";s:56:"Symfony/Component/Finder/Iterator/PathFilterIterator.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"42d968969a5f86d4131876b013fa8222";s:4:"name";s:64:"Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5e5846ae6b28172c38b8398a9d9dfab7";s:4:"name";s:61:"Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"530f84682e9e9f218d1e349bfd6a62dc";s:4:"name";s:54:"Symfony/Component/Finder/Iterator/SortableIterator.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:32:"Symfony/Component/Finder/LICENSE";s:4:"role";s:3:"doc";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cef311635452da773abddebf14e2f6eb";s:4:"name";s:41:"Symfony/Component/Finder/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2456580383eb35b4f4a2529c6cc1264f";s:4:"name";s:34:"Symfony/Component/Finder/README.md";s:4:"role";s:3:"doc";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d66a35ad507168d1fa3034a61c2a94e8";s:4:"name";s:42:"Symfony/Component/Finder/Shell/Command.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fff1b9b5a47c24fa988f4340a5c52701";s:4:"name";s:40:"Symfony/Component/Finder/Shell/Shell.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c4117456dc277d299cf94ffee5d66410";s:4:"name";s:40:"Symfony/Component/Finder/SplFileInfo.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"feecb2cd50a7a248febac4044933ac3d";s:4:"name";s:60:"Symfony/Component/Finder/Tests/Comparator/ComparatorTest.php";s:4:"role";s:4:"test";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"89ff8698db0e90e9820b4c2d9322ea35";s:4:"name";s:64:"Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.php";s:4:"role";s:4:"test";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"65c58bb38b3d2a7d3c40b1a28869cf9a";s:4:"name";s:66:"Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.php";s:4:"role";s:4:"test";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b079a8f0f48ea5bce7ea931822d23728";s:4:"name";s:60:"Symfony/Component/Finder/Tests/Expression/ExpressionTest.php";s:4:"role";s:4:"test";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8dbffcaf39e52ac3203f592066b7d4ed";s:4:"name";s:54:"Symfony/Component/Finder/Tests/Expression/GlobTest.php";s:4:"role";s:4:"test";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"14318667c0d8f805fe01762c1fc36d70";s:4:"name";s:55:"Symfony/Component/Finder/Tests/Expression/RegexTest.php";s:4:"role";s:4:"test";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c60edd9b00b8f99374c3a826e615e27c";s:4:"name";s:59:"Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php";s:4:"role";s:4:"test";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a73e2d28e02576a7851131285966ebab";s:4:"name";s:61:"Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5509680e7bc94ac0fab1a75680b8cfe7";s:4:"name";s:59:"Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php";s:4:"role";s:4:"test";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5afaefa9e0c692d20ab98d9f573fda4e";s:4:"name";s:65:"Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php";s:4:"role";s:4:"test";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"15e0e93e7d51a82b5b32e3518b7afc99";s:4:"name";s:45:"Symfony/Component/Finder/Tests/FinderTest.php";s:4:"role";s:4:"test";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:47:"Symfony/Component/Finder/Tests/Fixtures/A/a.dat";s:4:"role";s:4:"test";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:50:"Symfony/Component/Finder/Tests/Fixtures/A/B/ab.dat";s:4:"role";s:4:"test";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:53:"Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.dat";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:57:"Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copy";s:4:"role";s:4:"test";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:60:"Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copy";s:4:"role";s:4:"test";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:63:"Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy";s:4:"role";s:4:"test";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6624837e7357e95e2183d9aa82a4a90f";s:4:"name";s:49:"Symfony/Component/Finder/Tests/Fixtures/dolor.txt";s:4:"role";s:4:"test";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"843affd355b258df359cb9b62a64289d";s:4:"name";s:49:"Symfony/Component/Finder/Tests/Fixtures/ipsum.txt";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bd58bbe99a4801c138ec8017d65cc7a4";s:4:"name";s:49:"Symfony/Component/Finder/Tests/Fixtures/lorem.txt";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:45:"Symfony/Component/Finder/Tests/Fixtures/one/a";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:52:"Symfony/Component/Finder/Tests/Fixtures/one/b/c.neon";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:52:"Symfony/Component/Finder/Tests/Fixtures/one/b/d.neon";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:58:"Symfony/Component/Finder/Tests/Fixtures/with space/foo.txt";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"57fa269cea0bbc73e2416764536b6746";s:4:"name";s:68:"Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"173f134f8bccca2c1757a77b2ca77a93";s:4:"name";s:71:"Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b10459df5f2e84c32758ab00b8c2a559";s:4:"name";s:72:"Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fb762b45fa48417171d592421504a258";s:4:"name";s:78:"Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1cf6511c36dee2f1029b6f41ac31ad65";s:4:"name";s:73:"Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"41c49ff40fc3622a48c04df824684944";s:4:"name";s:70:"Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87f862713b1702931fd758cb0f9d70b0";s:4:"name";s:65:"Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.php";s:4:"role";s:4:"test";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0f08a73086ae0c8de3a110563240052a";s:4:"name";s:70:"Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8683e26efd65bf17dc96e21c25b4326c";s:4:"name";s:62:"Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php";s:4:"role";s:4:"test";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3efa2d95b80c889e65bf1c18d898201a";s:4:"name";s:52:"Symfony/Component/Finder/Tests/Iterator/Iterator.php";s:4:"role";s:4:"test";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e14ac4c44a1faa1d22e2188ae20a1e63";s:4:"name";s:60:"Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php";s:4:"role";s:4:"test";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5f9af5d1647b30d511aa017dcf8b3a72";s:4:"name";s:64:"Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.php";s:4:"role";s:4:"test";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b7dae5a3886979bc733067fedf265bea";s:4:"name";s:59:"Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.php";s:4:"role";s:4:"test";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4e8d9d8ecf752a075cc7886c69bf5f93";s:4:"name";s:74:"Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6f6ac3f2c9e2663f778d2ca0e700fc34";s:4:"name";s:66:"Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff1381bf96a6d4b7e99328cd2a2e0a23";s:4:"name";s:64:"Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php";s:4:"role";s:4:"test";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a331462cae2726ae6e1f608f6da87bb";s:4:"name";s:74:"Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php";s:4:"role";s:4:"test";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"398cce21c68fe443d6303260d7c8a5cb";s:4:"name";s:71:"Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php";s:4:"role";s:4:"test";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c08270fdc6490d0f92767a14506df3ad";s:4:"name";s:64:"Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:86:{s:52:"Symfony/Component/Finder/Adapter/AbstractAdapter.php";a:4:{s:6:"md5sum";s:32:"6fffc29b8377e9fb68b5e302b9ff0a97";s:4:"name";s:52:"Symfony/Component/Finder/Adapter/AbstractAdapter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Adapter/AbstractAdapter.php";}s:56:"Symfony/Component/Finder/Adapter/AbstractFindAdapter.php";a:4:{s:6:"md5sum";s:32:"7dc817125e50b8b230fa1dd7b505a35b";s:4:"name";s:56:"Symfony/Component/Finder/Adapter/AbstractFindAdapter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php";}s:53:"Symfony/Component/Finder/Adapter/AdapterInterface.php";a:4:{s:6:"md5sum";s:32:"a6b49be9beaee46ef1b3ab81b65c3f5a";s:4:"name";s:53:"Symfony/Component/Finder/Adapter/AdapterInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Adapter/AdapterInterface.php";}s:51:"Symfony/Component/Finder/Adapter/BsdFindAdapter.php";a:4:{s:6:"md5sum";s:32:"787a004fec8cb06949f54d45d0a92dfa";s:4:"name";s:51:"Symfony/Component/Finder/Adapter/BsdFindAdapter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Adapter/BsdFindAdapter.php";}s:51:"Symfony/Component/Finder/Adapter/GnuFindAdapter.php";a:4:{s:6:"md5sum";s:32:"86f218f5471a950cda80784f16635789";s:4:"name";s:51:"Symfony/Component/Finder/Adapter/GnuFindAdapter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Adapter/GnuFindAdapter.php";}s:47:"Symfony/Component/Finder/Adapter/PhpAdapter.php";a:4:{s:6:"md5sum";s:32:"5550d6d59cd92735c58ea80f58766716";s:4:"name";s:47:"Symfony/Component/Finder/Adapter/PhpAdapter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Adapter/PhpAdapter.php";}s:39:"Symfony/Component/Finder/autoloader.php";a:4:{s:6:"md5sum";s:32:"70c27b109779dd46d3a9d0ef38565b42";s:4:"name";s:39:"Symfony/Component/Finder/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/autoloader.php";}s:37:"Symfony/Component/Finder/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"f18e866785861bb62155c98357afe2d6";s:4:"name";s:37:"Symfony/Component/Finder/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/doc/pear/Finder/Symfony/Component/Finder/CHANGELOG.md";}s:50:"Symfony/Component/Finder/Comparator/Comparator.php";a:4:{s:6:"md5sum";s:32:"ff527c6ba5d45d17b691dd2debe2c3d9";s:4:"name";s:50:"Symfony/Component/Finder/Comparator/Comparator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Comparator/Comparator.php";}s:54:"Symfony/Component/Finder/Comparator/DateComparator.php";a:4:{s:6:"md5sum";s:32:"f50830cff54249c3d2602120bf7adc56";s:4:"name";s:54:"Symfony/Component/Finder/Comparator/DateComparator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Comparator/DateComparator.php";}s:56:"Symfony/Component/Finder/Comparator/NumberComparator.php";a:4:{s:6:"md5sum";s:32:"5be54134d90a013d0685a58bdf395e99";s:4:"name";s:56:"Symfony/Component/Finder/Comparator/NumberComparator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Comparator/NumberComparator.php";}s:38:"Symfony/Component/Finder/composer.json";a:4:{s:6:"md5sum";s:32:"0ade20562cd194d6ef1d87e3811baf4d";s:4:"name";s:38:"Symfony/Component/Finder/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/doc/pear/Finder/Symfony/Component/Finder/composer.json";}s:60:"Symfony/Component/Finder/Exception/AccessDeniedException.php";a:4:{s:6:"md5sum";s:32:"6ec2bf13ee80fa36603a8b1cbaeb3057";s:4:"name";s:60:"Symfony/Component/Finder/Exception/AccessDeniedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Exception/AccessDeniedException.php";}s:62:"Symfony/Component/Finder/Exception/AdapterFailureException.php";a:4:{s:6:"md5sum";s:32:"543b917aa3964799c231b7f5730010b5";s:4:"name";s:62:"Symfony/Component/Finder/Exception/AdapterFailureException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Exception/AdapterFailureException.php";}s:57:"Symfony/Component/Finder/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"509f10771d6f6158695f24d956ccf611";s:4:"name";s:57:"Symfony/Component/Finder/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Exception/ExceptionInterface.php";}s:68:"Symfony/Component/Finder/Exception/OperationNotPermitedException.php";a:4:{s:6:"md5sum";s:32:"0026a361b430ca5ce4bc1a8b199f1c82";s:4:"name";s:68:"Symfony/Component/Finder/Exception/OperationNotPermitedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Exception/OperationNotPermitedException.php";}s:67:"Symfony/Component/Finder/Exception/ShellCommandFailureException.php";a:4:{s:6:"md5sum";s:32:"9eb6fca673d7b360706d092ebc91519f";s:4:"name";s:67:"Symfony/Component/Finder/Exception/ShellCommandFailureException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Exception/ShellCommandFailureException.php";}s:50:"Symfony/Component/Finder/Expression/Expression.php";a:4:{s:6:"md5sum";s:32:"344148f9472396a75e505102cade415c";s:4:"name";s:50:"Symfony/Component/Finder/Expression/Expression.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Expression/Expression.php";}s:44:"Symfony/Component/Finder/Expression/Glob.php";a:4:{s:6:"md5sum";s:32:"a231c7c1fcea375333c3b4a2c14ab532";s:4:"name";s:44:"Symfony/Component/Finder/Expression/Glob.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Expression/Glob.php";}s:45:"Symfony/Component/Finder/Expression/Regex.php";a:4:{s:6:"md5sum";s:32:"f6919b0c7a8545c57d85318b544d0f24";s:4:"name";s:45:"Symfony/Component/Finder/Expression/Regex.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Expression/Regex.php";}s:54:"Symfony/Component/Finder/Expression/ValueInterface.php";a:4:{s:6:"md5sum";s:32:"219c3a5985874bf148c4261c21db14bd";s:4:"name";s:54:"Symfony/Component/Finder/Expression/ValueInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Expression/ValueInterface.php";}s:35:"Symfony/Component/Finder/Finder.php";a:4:{s:6:"md5sum";s:32:"a4f805d1284bcd933f1ee022197c9226";s:4:"name";s:35:"Symfony/Component/Finder/Finder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Finder.php";}s:33:"Symfony/Component/Finder/Glob.php";a:4:{s:6:"md5sum";s:32:"0b44ed57af5918230d1b82ecee9c3ba3";s:4:"name";s:33:"Symfony/Component/Finder/Glob.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Glob.php";}s:58:"Symfony/Component/Finder/Iterator/CustomFilterIterator.php";a:4:{s:6:"md5sum";s:32:"b043b76cf6d7a5356b2515d28c7ff48a";s:4:"name";s:58:"Symfony/Component/Finder/Iterator/CustomFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/CustomFilterIterator.php";}s:61:"Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php";a:4:{s:6:"md5sum";s:32:"62f326275b0ded2de6cd6209ec2536af";s:4:"name";s:61:"Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php";}s:62:"Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php";a:4:{s:6:"md5sum";s:32:"91fd43512fed83211c6cce453e6b45be";s:4:"name";s:62:"Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php";}s:68:"Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php";a:4:{s:6:"md5sum";s:32:"6cf1f8950c36872e6389337ae41c6268";s:4:"name";s:68:"Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php";}s:63:"Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php";a:4:{s:6:"md5sum";s:32:"04c5aafbda629dc67e3d1b36ec56f692";s:4:"name";s:63:"Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php";}s:60:"Symfony/Component/Finder/Iterator/FilenameFilterIterator.php";a:4:{s:6:"md5sum";s:32:"c414b7cb71b775f369d676c345b3cbed";s:4:"name";s:60:"Symfony/Component/Finder/Iterator/FilenameFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php";}s:55:"Symfony/Component/Finder/Iterator/FilePathsIterator.php";a:4:{s:6:"md5sum";s:32:"92a7737c720fb253f300a5e27cf7b0a3";s:4:"name";s:55:"Symfony/Component/Finder/Iterator/FilePathsIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/FilePathsIterator.php";}s:60:"Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php";a:4:{s:6:"md5sum";s:32:"8848c8e1a14338fead3676ff724b0a18";s:4:"name";s:60:"Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php";}s:52:"Symfony/Component/Finder/Iterator/FilterIterator.php";a:4:{s:6:"md5sum";s:32:"357568ea6a039bfaf363227eb4823b08";s:4:"name";s:52:"Symfony/Component/Finder/Iterator/FilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/FilterIterator.php";}s:64:"Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php";a:4:{s:6:"md5sum";s:32:"b8343ab9d4fcebfa7be797bccd8ef559";s:4:"name";s:64:"Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php";}s:56:"Symfony/Component/Finder/Iterator/PathFilterIterator.php";a:4:{s:6:"md5sum";s:32:"7bcb38607afc169b07443b4d166cd646";s:4:"name";s:56:"Symfony/Component/Finder/Iterator/PathFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/PathFilterIterator.php";}s:64:"Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php";a:4:{s:6:"md5sum";s:32:"42d968969a5f86d4131876b013fa8222";s:4:"name";s:64:"Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php";}s:61:"Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php";a:4:{s:6:"md5sum";s:32:"5e5846ae6b28172c38b8398a9d9dfab7";s:4:"name";s:61:"Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php";}s:54:"Symfony/Component/Finder/Iterator/SortableIterator.php";a:4:{s:6:"md5sum";s:32:"530f84682e9e9f218d1e349bfd6a62dc";s:4:"name";s:54:"Symfony/Component/Finder/Iterator/SortableIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator/SortableIterator.php";}s:32:"Symfony/Component/Finder/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:32:"Symfony/Component/Finder/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/doc/pear/Finder/Symfony/Component/Finder/LICENSE";}s:41:"Symfony/Component/Finder/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"cef311635452da773abddebf14e2f6eb";s:4:"name";s:41:"Symfony/Component/Finder/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/phpunit.xml.dist";}s:34:"Symfony/Component/Finder/README.md";a:4:{s:6:"md5sum";s:32:"2456580383eb35b4f4a2529c6cc1264f";s:4:"name";s:34:"Symfony/Component/Finder/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/Finder/Symfony/Component/Finder/README.md";}s:42:"Symfony/Component/Finder/Shell/Command.php";a:4:{s:6:"md5sum";s:32:"d66a35ad507168d1fa3034a61c2a94e8";s:4:"name";s:42:"Symfony/Component/Finder/Shell/Command.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Shell/Command.php";}s:40:"Symfony/Component/Finder/Shell/Shell.php";a:4:{s:6:"md5sum";s:32:"fff1b9b5a47c24fa988f4340a5c52701";s:4:"name";s:40:"Symfony/Component/Finder/Shell/Shell.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Shell/Shell.php";}s:40:"Symfony/Component/Finder/SplFileInfo.php";a:4:{s:6:"md5sum";s:32:"c4117456dc277d299cf94ffee5d66410";s:4:"name";s:40:"Symfony/Component/Finder/SplFileInfo.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/SplFileInfo.php";}s:60:"Symfony/Component/Finder/Tests/Comparator/ComparatorTest.php";a:4:{s:6:"md5sum";s:32:"feecb2cd50a7a248febac4044933ac3d";s:4:"name";s:60:"Symfony/Component/Finder/Tests/Comparator/ComparatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.php";}s:64:"Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.php";a:4:{s:6:"md5sum";s:32:"89ff8698db0e90e9820b4c2d9322ea35";s:4:"name";s:64:"Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.php";}s:66:"Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.php";a:4:{s:6:"md5sum";s:32:"65c58bb38b3d2a7d3c40b1a28869cf9a";s:4:"name";s:66:"Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.php";}s:60:"Symfony/Component/Finder/Tests/Expression/ExpressionTest.php";a:4:{s:6:"md5sum";s:32:"b079a8f0f48ea5bce7ea931822d23728";s:4:"name";s:60:"Symfony/Component/Finder/Tests/Expression/ExpressionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.php";}s:54:"Symfony/Component/Finder/Tests/Expression/GlobTest.php";a:4:{s:6:"md5sum";s:32:"8dbffcaf39e52ac3203f592066b7d4ed";s:4:"name";s:54:"Symfony/Component/Finder/Tests/Expression/GlobTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Expression/GlobTest.php";}s:55:"Symfony/Component/Finder/Tests/Expression/RegexTest.php";a:4:{s:6:"md5sum";s:32:"14318667c0d8f805fe01762c1fc36d70";s:4:"name";s:55:"Symfony/Component/Finder/Tests/Expression/RegexTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Expression/RegexTest.php";}s:59:"Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php";a:4:{s:6:"md5sum";s:32:"c60edd9b00b8f99374c3a826e615e27c";s:4:"name";s:59:"Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php";}s:61:"Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php";a:4:{s:6:"md5sum";s:32:"a73e2d28e02576a7851131285966ebab";s:4:"name";s:61:"Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php";}s:59:"Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php";a:4:{s:6:"md5sum";s:32:"5509680e7bc94ac0fab1a75680b8cfe7";s:4:"name";s:59:"Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php";}s:65:"Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php";a:4:{s:6:"md5sum";s:32:"5afaefa9e0c692d20ab98d9f573fda4e";s:4:"name";s:65:"Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php";}s:45:"Symfony/Component/Finder/Tests/FinderTest.php";a:4:{s:6:"md5sum";s:32:"15e0e93e7d51a82b5b32e3518b7afc99";s:4:"name";s:45:"Symfony/Component/Finder/Tests/FinderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/FinderTest.php";}s:47:"Symfony/Component/Finder/Tests/Fixtures/A/a.dat";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:47:"Symfony/Component/Finder/Tests/Fixtures/A/a.dat";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/a.dat";}s:50:"Symfony/Component/Finder/Tests/Fixtures/A/B/ab.dat";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:50:"Symfony/Component/Finder/Tests/Fixtures/A/B/ab.dat";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/ab.dat";}s:53:"Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.dat";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:53:"Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.dat";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.dat";}s:57:"Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copy";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:57:"Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copy";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copy";}s:60:"Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copy";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:60:"Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copy";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copy";}s:63:"Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:63:"Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy";}s:49:"Symfony/Component/Finder/Tests/Fixtures/dolor.txt";a:4:{s:6:"md5sum";s:32:"6624837e7357e95e2183d9aa82a4a90f";s:4:"name";s:49:"Symfony/Component/Finder/Tests/Fixtures/dolor.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/dolor.txt";}s:49:"Symfony/Component/Finder/Tests/Fixtures/ipsum.txt";a:4:{s:6:"md5sum";s:32:"843affd355b258df359cb9b62a64289d";s:4:"name";s:49:"Symfony/Component/Finder/Tests/Fixtures/ipsum.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/ipsum.txt";}s:49:"Symfony/Component/Finder/Tests/Fixtures/lorem.txt";a:4:{s:6:"md5sum";s:32:"bd58bbe99a4801c138ec8017d65cc7a4";s:4:"name";s:49:"Symfony/Component/Finder/Tests/Fixtures/lorem.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/lorem.txt";}s:45:"Symfony/Component/Finder/Tests/Fixtures/one/a";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:45:"Symfony/Component/Finder/Tests/Fixtures/one/a";s:4:"role";s:4:"test";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/a";}s:52:"Symfony/Component/Finder/Tests/Fixtures/one/b/c.neon";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:52:"Symfony/Component/Finder/Tests/Fixtures/one/b/c.neon";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/c.neon";}s:52:"Symfony/Component/Finder/Tests/Fixtures/one/b/d.neon";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:52:"Symfony/Component/Finder/Tests/Fixtures/one/b/d.neon";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/d.neon";}s:58:"Symfony/Component/Finder/Tests/Fixtures/with space/foo.txt";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:58:"Symfony/Component/Finder/Tests/Fixtures/with space/foo.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/with space/foo.txt";}s:68:"Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"57fa269cea0bbc73e2416764536b6746";s:4:"name";s:68:"Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.php";}s:71:"Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"173f134f8bccca2c1757a77b2ca77a93";s:4:"name";s:71:"Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php";}s:72:"Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"b10459df5f2e84c32758ab00b8c2a559";s:4:"name";s:72:"Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php";}s:78:"Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"fb762b45fa48417171d592421504a258";s:4:"name";s:78:"Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php";}s:73:"Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"1cf6511c36dee2f1029b6f41ac31ad65";s:4:"name";s:73:"Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php";}s:70:"Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"41c49ff40fc3622a48c04df824684944";s:4:"name";s:70:"Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php";}s:65:"Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.php";a:4:{s:6:"md5sum";s:32:"87f862713b1702931fd758cb0f9d70b0";s:4:"name";s:65:"Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.php";}s:70:"Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"0f08a73086ae0c8de3a110563240052a";s:4:"name";s:70:"Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php";}s:62:"Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"8683e26efd65bf17dc96e21c25b4326c";s:4:"name";s:62:"Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php";}s:52:"Symfony/Component/Finder/Tests/Iterator/Iterator.php";a:4:{s:6:"md5sum";s:32:"3efa2d95b80c889e65bf1c18d898201a";s:4:"name";s:52:"Symfony/Component/Finder/Tests/Iterator/Iterator.php";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/Iterator.php";}s:60:"Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php";a:4:{s:6:"md5sum";s:32:"e14ac4c44a1faa1d22e2188ae20a1e63";s:4:"name";s:60:"Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php";}s:64:"Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.php";a:4:{s:6:"md5sum";s:32:"5f9af5d1647b30d511aa017dcf8b3a72";s:4:"name";s:64:"Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.php";}s:59:"Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.php";a:4:{s:6:"md5sum";s:32:"b7dae5a3886979bc733067fedf265bea";s:4:"name";s:59:"Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.php";}s:74:"Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"4e8d9d8ecf752a075cc7886c69bf5f93";s:4:"name";s:74:"Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php";}s:66:"Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"6f6ac3f2c9e2663f778d2ca0e700fc34";s:4:"name";s:66:"Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.php";}s:64:"Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php";a:4:{s:6:"md5sum";s:32:"ff1381bf96a6d4b7e99328cd2a2e0a23";s:4:"name";s:64:"Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php";}s:74:"Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php";a:4:{s:6:"md5sum";s:32:"3a331462cae2726ae6e1f608f6da87bb";s:4:"name";s:74:"Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php";}s:71:"Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php";a:4:{s:6:"md5sum";s:32:"398cce21c68fe443d6303260d7c8a5cb";s:4:"name";s:71:"Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php";}s:64:"Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php";a:4:{s:6:"md5sum";s:32:"c08270fdc6490d0f92767a14506df3ad";s:4:"name";s:64:"Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:33:{s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Adapter";b:1;s:54:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:65:"/opt/alt/php54/usr/share/doc/pear/Finder/Symfony/Component/Finder";b:1;s:58:"/opt/alt/php54/usr/share/doc/pear/Finder/Symfony/Component";b:1;s:48:"/opt/alt/php54/usr/share/doc/pear/Finder/Symfony";b:1;s:40:"/opt/alt/php54/usr/share/doc/pear/Finder";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Comparator";b:1;s:64:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Exception";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Expression";b:1;s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Iterator";b:1;s:66:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder";b:1;s:59:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component";b:1;s:49:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony";b:1;s:41:"/opt/alt/php54/usr/share/pear/test/Finder";b:1;s:60:"/opt/alt/php54/usr/share/pear/Symfony/Component/Finder/Shell";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Comparator";b:1;s:72:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Expression";b:1;s:84:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/FakeAdapter";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/A";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures";b:1;s:85:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/C";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C";b:1;s:85:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/one";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Fixtures/with space";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Finder/Symfony/Component/Finder/Tests/Iterator";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!#,.registry/.channel.pear.symfony.com/form.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:4:"Form";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:23:"Symfony2 Form Component";s:11:"description";s:23:"Symfony2 Form Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:45";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:337:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"501890934b78c1cda42337c3c85761f5";s:4:"name";s:44:"Symfony/Component/Form/AbstractExtension.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c855e95efaafd48a3b35f4e4ed7ef461";s:4:"name";s:49:"Symfony/Component/Form/AbstractRendererEngine.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fda8ea1864e57a50d81607d692e68c73";s:4:"name";s:39:"Symfony/Component/Form/AbstractType.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0cc218c093e9d4631ab2dd2276c567bd";s:4:"name";s:48:"Symfony/Component/Form/AbstractTypeExtension.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ccc700d8c25bc05b9e4a4b327a643f46";s:4:"name";s:37:"Symfony/Component/Form/autoloader.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e4221c7f370be7e1fae189ac0f0245f8";s:4:"name";s:33:"Symfony/Component/Form/Button.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d27ec47e44803a025e38d0067c824cdc";s:4:"name";s:40:"Symfony/Component/Form/ButtonBuilder.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2b9067ff341a18790204ea50c84102bd";s:4:"name";s:46:"Symfony/Component/Form/ButtonTypeInterface.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"902572561ace9999c9f8d8e0f37cd28f";s:4:"name";s:46:"Symfony/Component/Form/CallbackTransformer.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"abf0d085506e63678c96f8f9666c3b1c";s:4:"name";s:35:"Symfony/Component/Form/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0907b59351198bd99ceea685c9f7c7c2";s:4:"name";s:45:"Symfony/Component/Form/ClickableInterface.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5519e4c865c9aab62f36e8ccc2687a0a";s:4:"name";s:36:"Symfony/Component/Form/composer.json";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"db3b117a3b8dd577bbd64a81766ad78d";s:4:"name";s:46:"Symfony/Component/Form/DataMapperInterface.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"555454867c9b8687d4ee00a014b981c1";s:4:"name";s:51:"Symfony/Component/Form/DataTransformerInterface.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc89a72f34e3e1d4a6628d32b1511007";s:4:"name";s:58:"Symfony/Component/Form/Exception/AlreadyBoundException.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"419b77be4914d44fbe8f422c9dce819a";s:4:"name";s:62:"Symfony/Component/Form/Exception/AlreadySubmittedException.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a7e624979068a6ac1975cef01a181a64";s:4:"name";s:59:"Symfony/Component/Form/Exception/BadMethodCallException.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b43e60289f802c13894f4427988c2915";s:4:"name";s:58:"Symfony/Component/Form/Exception/ErrorMappingException.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1f4d4c025c5f49fd0e787f2095dcac58";s:4:"name";s:55:"Symfony/Component/Form/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a93c3e0ef8f9f1833b1ec31f26baaa92";s:4:"name";s:61:"Symfony/Component/Form/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"16b9f308c2cd41c6feea464a4c2a4078";s:4:"name";s:66:"Symfony/Component/Form/Exception/InvalidConfigurationException.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7acb2af6fec7e8015fdf9473ed22e568";s:4:"name";s:51:"Symfony/Component/Form/Exception/LogicException.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6439c29ccaba5ed08f068b56d1cb900a";s:4:"name";s:57:"Symfony/Component/Form/Exception/OutOfBoundsException.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"035137b05f9d396eebf788cd0475bfd2";s:4:"name";s:53:"Symfony/Component/Form/Exception/RuntimeException.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"05fafa90307ac0049080845bfc134e90";s:4:"name";s:56:"Symfony/Component/Form/Exception/StringCastException.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"04e43782ab8e754a86f812f93d3e80f0";s:4:"name";s:66:"Symfony/Component/Form/Exception/TransformationFailedException.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"93ab4195343c65feabe0a9a15e3b4e03";s:4:"name";s:60:"Symfony/Component/Form/Exception/UnexpectedTypeException.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fae7f67d21f3636dcfd9255b18c0f409";s:4:"name";s:63:"Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"75ef902d77e51ff120a5bb80a3ba4b2c";s:4:"name";s:72:"Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6c60da1e88563e1e8ee345e908e99895";s:4:"name";s:67:"Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"93d7bd50a57d6ce541c9e465f1f9c727";s:4:"name";s:69:"Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dd799ebc2f390f6c26a68d9b27163986";s:4:"name";s:69:"Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"249e325333e1e0bbf071c2352f1015ef";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/CoreExtension.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cf380dc09a61dcd25aa19cde02d5a496";s:4:"name";s:71:"Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b1463a8ca32434df6df7fdd15470ffe";s:4:"name";s:81:"Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"95ce9f75d9de781506bd27afae24a435";s:4:"name";s:81:"Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1beb890d4d901ce9a49a02aa567d4d1d";s:4:"name";s:84:"Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bdc67501df308818f4ccb6e87fd4b460";s:4:"name";s:90:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d417455cb1a9c5f1ce2d0ae9b72c262a";s:4:"name";s:84:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4ddb6ca1e45e39c27603e9a61746fe0";s:4:"name";s:89:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c23bb58d706b389464865d3baaa9dc0f";s:4:"name";s:82:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fb47a7c8ec22b84e657ba080eebf9185";s:4:"name";s:78:"Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"987af4de3dad99dbe03d40ad481e59f5";s:4:"name";s:84:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"08fe73eed45b4e64f5a612fe384ee949";s:4:"name";s:94:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"536a31499542c247eeac9f887459ccb6";s:4:"name";s:86:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"84819444537109979c4ded0dcb5449d3";s:4:"name";s:85:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d420953c67b9ce03b78d46777f78934e";s:4:"name";s:88:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87c45ad85d859bc5ac1847dbe26f451f";s:4:"name";s:93:"Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"031be52b519ab452a56e72c0ad919f9d";s:4:"name";s:91:"Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fdab477194f1770c375e73e5571253c9";s:4:"name";s:92:"Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0a1be99705fd6d15d2b67c9d7cc34f0a";s:4:"name";s:93:"Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php";s:4:"role";s:3:"php";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a9acfacc5c1d22709f2d9fb9572e5856";s:4:"name";s:86:"Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4fd81dac92cd7178a4df5463b909a67b";s:4:"name";s:80:"Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php";s:4:"role";s:3:"php";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"def66949bde6d959e70d661d15f1e9e3";s:4:"name";s:77:"Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php";s:4:"role";s:3:"php";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f57106b0d09322f11efddefb368fb952";s:4:"name";s:78:"Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php";s:4:"role";s:3:"php";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1d42403d6e8be3877c66cdf6eeb7f375";s:4:"name";s:79:"Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php";s:4:"role";s:3:"php";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c79a52d764d974eaa9a1d742211220b9";s:4:"name";s:74:"Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php";s:4:"role";s:3:"php";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0bbbf865bc2c1c7b013b19cd49ea66f8";s:4:"name";s:68:"Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php";s:4:"role";s:3:"php";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"058c321dda699e31ae2e164586817072";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/BaseType.php";s:4:"role";s:3:"php";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"601dc1defb9cfe03f57ecb55ec6519ee";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/BirthdayType.php";s:4:"role";s:3:"php";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df30378aa4224d2e19bfb48e3f22be73";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/ButtonType.php";s:4:"role";s:3:"php";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"20d7fadb63815c65c600ff1cab100d69";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/CheckboxType.php";s:4:"role";s:3:"php";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c7bce0021e92409791dc40237e44585e";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/ChoiceType.php";s:4:"role";s:3:"php";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"675668b49022522d4646aa90049c2650";s:4:"name";s:61:"Symfony/Component/Form/Extension/Core/Type/CollectionType.php";s:4:"role";s:3:"php";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"113a7ecb3ad40c9ffb38fd685db1ab3a";s:4:"name";s:58:"Symfony/Component/Form/Extension/Core/Type/CountryType.php";s:4:"role";s:3:"php";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0be9c69f93866ae116791fcfb7a77186";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/CurrencyType.php";s:4:"role";s:3:"php";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5d41f93fff961492d2de8bc4d71e7862";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/DateTimeType.php";s:4:"role";s:3:"php";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"35d0a4afbc155cd3838aebf3a564fb42";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/DateType.php";s:4:"role";s:3:"php";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"146a7c19ddde4cdca72343da4cfe17d5";s:4:"name";s:56:"Symfony/Component/Form/Extension/Core/Type/EmailType.php";s:4:"role";s:3:"php";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"060ed2ce1bef45de0340a9448c5f04f2";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/FileType.php";s:4:"role";s:3:"php";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"50f9fbd36e4a7e4b9136be87bf43cb8a";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/FormType.php";s:4:"role";s:3:"php";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"300baaff3c467b27ddcde08751708dc8";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/HiddenType.php";s:4:"role";s:3:"php";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"39268ae7dc189edbc1f1ac9cf01bdcb6";s:4:"name";s:58:"Symfony/Component/Form/Extension/Core/Type/IntegerType.php";s:4:"role";s:3:"php";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d463acc8367ee0afe8417a0aaba019fe";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/LanguageType.php";s:4:"role";s:3:"php";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a01e0f05fec87b35b3424829d33d1755";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/LocaleType.php";s:4:"role";s:3:"php";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"610e8b6a1425b2eb97a0d7c700edf05c";s:4:"name";s:56:"Symfony/Component/Form/Extension/Core/Type/MoneyType.php";s:4:"role";s:3:"php";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e5cd61198e2bc26e98d427ab26238c29";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/NumberType.php";s:4:"role";s:3:"php";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e404fb615ce73dc63a1849d3debb800a";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/PasswordType.php";s:4:"role";s:3:"php";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1049fece490815d0886c3ddff2bae892";s:4:"name";s:58:"Symfony/Component/Form/Extension/Core/Type/PercentType.php";s:4:"role";s:3:"php";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"90fba868b14c878176ada892065394bf";s:4:"name";s:56:"Symfony/Component/Form/Extension/Core/Type/RadioType.php";s:4:"role";s:3:"php";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f87bd813801d2d880e905cdd0ffa57da";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/RepeatedType.php";s:4:"role";s:3:"php";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c4df569621c1f85389b7c7cbf789bf63";s:4:"name";s:56:"Symfony/Component/Form/Extension/Core/Type/ResetType.php";s:4:"role";s:3:"php";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a6b0608cb9f219f8a8c192f64f141335";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/SearchType.php";s:4:"role";s:3:"php";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d689ab8ea2da255a67b7d2140af1627b";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/SubmitType.php";s:4:"role";s:3:"php";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"02627d9175c745247f7e59cf1c2d4562";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/TextareaType.php";s:4:"role";s:3:"php";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"79f868ef2b8c73154789fcaa591f8467";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/TextType.php";s:4:"role";s:3:"php";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"993e6cee3429a18fabdc70f0a67c7d57";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/TimeType.php";s:4:"role";s:3:"php";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f5607e197c52e096bf060d259aef4079";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/TimezoneType.php";s:4:"role";s:3:"php";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"38ac4b65d20ba774f1421dfd2acd3193";s:4:"name";s:54:"Symfony/Component/Form/Extension/Core/Type/UrlType.php";s:4:"role";s:3:"php";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"faafdc84e0bfdcd503be96fcb730c4c0";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/View/ChoiceView.php";s:4:"role";s:3:"php";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"75199e400bebc4583e278a7b24e96833";s:4:"name";s:55:"Symfony/Component/Form/Extension/Csrf/CsrfExtension.php";s:4:"role";s:3:"php";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a1592bafaa9d2402bb6806fd1ac3e9d";s:4:"name";s:74:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php";s:4:"role";s:3:"php";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e86115910210dec2676aeb707cb5acf0";s:4:"name";s:76:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php";s:4:"role";s:3:"php";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"db64afcb25c6806ce15828e6ac8c790e";s:4:"name";s:78:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.php";s:4:"role";s:3:"php";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a1f980527cf2cec99b44eaa1a09e0d4f";s:4:"name";s:74:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php";s:4:"role";s:3:"php";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c939632d9abebe20853bc59ce816b457";s:4:"name";s:74:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php";s:4:"role";s:3:"php";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c17a0b6ad7348188b47da6647b50cc82";s:4:"name";s:78:"Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php";s:4:"role";s:3:"php";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0de14d86a9825500a9b8a71025542c1b";s:4:"name";s:68:"Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php";s:4:"role";s:3:"php";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5c5494c1d8bb041b3b938f53a48bb1a1";s:4:"name";s:73:"Symfony/Component/Form/Extension/DataCollector/DataCollectorExtension.php";s:4:"role";s:3:"php";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1419e5bb5008ecb2d6d757bd7023fda8";s:4:"name";s:86:"Symfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.php";s:4:"role";s:3:"php";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fdf324521978ceec4f561d76770a08d2";s:4:"name";s:68:"Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php";s:4:"role";s:3:"php";}}i:101;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8e33ae446484b221f1a8f43b96689a9a";s:4:"name";s:77:"Symfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.php";s:4:"role";s:3:"php";}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c6dbee88cf57973284f2deb8b7d62266";s:4:"name";s:68:"Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php";s:4:"role";s:3:"php";}}i:103;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e0250a5d7bb1e0c5022cc5bead2126dc";s:4:"name";s:77:"Symfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.php";s:4:"role";s:3:"php";}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1d3278f320b0fc626c80ff21d4e4d798";s:4:"name";s:87:"Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php";s:4:"role";s:3:"php";}}i:105;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7acc20404d7bc268d80bd71d29b2c0da";s:4:"name";s:94:"Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php";s:4:"role";s:3:"php";}}i:106;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"384aa6433ffc18edb15519d550103ca1";s:4:"name";s:82:"Symfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.php";s:4:"role";s:3:"php";}}i:107;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7284275881ceb92b987717feedba8057";s:4:"name";s:85:"Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.php";s:4:"role";s:3:"php";}}i:108;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6a452e346dc11c0a574bc2fbea9be01c";s:4:"name";s:85:"Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.php";s:4:"role";s:3:"php";}}i:109;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bd10d86a58c151a1d8d2e072dc379389";s:4:"name";s:75:"Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.php";s:4:"role";s:3:"php";}}i:110;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1a1be6feca390ce87d232e08008b4059";s:4:"name";s:80:"Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php";s:4:"role";s:3:"php";}}i:111;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1cbed6494abb39f8a2731ff28bfc3b4f";s:4:"name";s:88:"Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php";s:4:"role";s:3:"php";}}i:112;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2ab352ab8da8a95d82c561e8d014708";s:4:"name";s:67:"Symfony/Component/Form/Extension/Templating/TemplatingExtension.php";s:4:"role";s:3:"php";}}i:113;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b88d4aa06ab3e8e0f4882d2790814fc";s:4:"name";s:72:"Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.php";s:4:"role";s:3:"php";}}i:114;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0024bfd2c88595778a825805a64dad44";s:4:"name";s:63:"Symfony/Component/Form/Extension/Validator/Constraints/Form.php";s:4:"role";s:3:"php";}}i:115;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7c71a0cb31da31a0222bdab4b7b926c7";s:4:"name";s:72:"Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php";s:4:"role";s:3:"php";}}i:116;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"26384c9335607d3a7a760ce64268a5d1";s:4:"name";s:79:"Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php";s:4:"role";s:3:"php";}}i:117;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cbb86a1f46d4153ee8b6dcec13f3e3b3";s:4:"name";s:74:"Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.php";s:4:"role";s:3:"php";}}i:118;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df9d49f2923e93c8a989badebd46d72b";s:4:"name";s:78:"Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php";s:4:"role";s:3:"php";}}i:119;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ee7f3c2ca05510b1e6f5ea736de843d";s:4:"name";s:82:"Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php";s:4:"role";s:3:"php";}}i:120;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ec1709e56bdc7ba193f1d204a1645348";s:4:"name";s:80:"Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.php";s:4:"role";s:3:"php";}}i:121;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6c0183dc4aa13461ba80a4b13bb6af0c";s:4:"name";s:64:"Symfony/Component/Form/Extension/Validator/Util/ServerParams.php";s:4:"role";s:3:"php";}}i:122;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"29479a50cbaa64713f9746a047bffd00";s:4:"name";s:65:"Symfony/Component/Form/Extension/Validator/ValidatorExtension.php";s:4:"role";s:3:"php";}}i:123;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7c15728df791933679ae099b2dc013ce";s:4:"name";s:67:"Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php";s:4:"role";s:3:"php";}}i:124;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"accd5b53d71708b247e3f8c6060b8441";s:4:"name";s:74:"Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php";s:4:"role";s:3:"php";}}i:125;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"da806398ec8fc4c452e1eadda5c74a68";s:4:"name";s:75:"Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.php";s:4:"role";s:3:"php";}}i:126;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"61357f9417507d405f7fb1fb659b31d2";s:4:"name";s:78:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php";s:4:"role";s:3:"php";}}i:127;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"10303cd4370ce781654acabee5f88bab";s:4:"name";s:87:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php";s:4:"role";s:3:"php";}}i:128;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ccc9fe0cfc8d2d1f0daabc141e920038";s:4:"name";s:76:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php";s:4:"role";s:3:"php";}}i:129;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c66988f503a7a69b3332463374596ba3";s:4:"name";s:84:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.php";s:4:"role";s:3:"php";}}i:130;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"563c1163b71c3c482d91bf4877746632";s:4:"name";s:31:"Symfony/Component/Form/Form.php";s:4:"role";s:3:"php";}}i:131;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cca285ed5e381d817d56181ec219df0d";s:4:"name";s:38:"Symfony/Component/Form/FormBuilder.php";s:4:"role";s:3:"php";}}i:132;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b5471bc4369497cf6ffd6e159a023ec";s:4:"name";s:47:"Symfony/Component/Form/FormBuilderInterface.php";s:4:"role";s:3:"php";}}i:133;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f478ae74fe1813693e1ba4e969d62410";s:4:"name";s:44:"Symfony/Component/Form/FormConfigBuilder.php";s:4:"role";s:3:"php";}}i:134;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6a46ac7e9313965ec6b1b95328f346a0";s:4:"name";s:53:"Symfony/Component/Form/FormConfigBuilderInterface.php";s:4:"role";s:3:"php";}}i:135;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0b0436e232cf7100a1ed02dc299cf7a2";s:4:"name";s:46:"Symfony/Component/Form/FormConfigInterface.php";s:4:"role";s:3:"php";}}i:136;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d77ce9907675beaf81a3065d1ecfd69c";s:4:"name";s:36:"Symfony/Component/Form/FormError.php";s:4:"role";s:3:"php";}}i:137;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"99268e4eaad4680f7e037cc00b31b370";s:4:"name";s:36:"Symfony/Component/Form/FormEvent.php";s:4:"role";s:3:"php";}}i:138;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e6d2f1d5c2986877bb25ed96014d3495";s:4:"name";s:37:"Symfony/Component/Form/FormEvents.php";s:4:"role";s:3:"php";}}i:139;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"396ae86cdd76d116832ba1f3b1ac5b73";s:4:"name";s:49:"Symfony/Component/Form/FormExtensionInterface.php";s:4:"role";s:3:"php";}}i:140;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"014013a6a76da3c380b12e79fd5895e5";s:4:"name";s:38:"Symfony/Component/Form/FormFactory.php";s:4:"role";s:3:"php";}}i:141;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b3f8c61b5ff170f0982a10bfa3f449ad";s:4:"name";s:45:"Symfony/Component/Form/FormFactoryBuilder.php";s:4:"role";s:3:"php";}}i:142;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1b58cdcfa7fe5eb921b37c73a4cc8ead";s:4:"name";s:54:"Symfony/Component/Form/FormFactoryBuilderInterface.php";s:4:"role";s:3:"php";}}i:143;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8f8a65e4ffe1ee2ac9165f41ff0defc0";s:4:"name";s:47:"Symfony/Component/Form/FormFactoryInterface.php";s:4:"role";s:3:"php";}}i:144;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bd326b430aabb6ae67bfdd63ac3a0cff";s:4:"name";s:40:"Symfony/Component/Form/FormInterface.php";s:4:"role";s:3:"php";}}i:145;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c017bb0aca3d2dc54133014309b994ca";s:4:"name";s:39:"Symfony/Component/Form/FormRegistry.php";s:4:"role";s:3:"php";}}i:146;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea9fc8c340f5d63126abf4741716bf0a";s:4:"name";s:48:"Symfony/Component/Form/FormRegistryInterface.php";s:4:"role";s:3:"php";}}i:147;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eed8b18f01216d190cf317392856361d";s:4:"name";s:39:"Symfony/Component/Form/FormRenderer.php";s:4:"role";s:3:"php";}}i:148;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4a12fb78c610af0b5f391e272fcb458b";s:4:"name";s:54:"Symfony/Component/Form/FormRendererEngineInterface.php";s:4:"role";s:3:"php";}}i:149;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"514aae640601bd2af792d2f280ad1d19";s:4:"name";s:48:"Symfony/Component/Form/FormRendererInterface.php";s:4:"role";s:3:"php";}}i:150;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9f253cdb5bd655feaa2ba9387c6cf0ad";s:4:"name";s:32:"Symfony/Component/Form/Forms.php";s:4:"role";s:3:"php";}}i:151;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"76847e41a7fc0945726fd7b00ddd9540";s:4:"name";s:53:"Symfony/Component/Form/FormTypeExtensionInterface.php";s:4:"role";s:3:"php";}}i:152;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5097ac9bb6503026cda5c54c7106965";s:4:"name";s:47:"Symfony/Component/Form/FormTypeGuesserChain.php";s:4:"role";s:3:"php";}}i:153;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0fb144de45b5135b11815452309bc75f";s:4:"name";s:51:"Symfony/Component/Form/FormTypeGuesserInterface.php";s:4:"role";s:3:"php";}}i:154;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bbab1badee901017917edff90e58f2c1";s:4:"name";s:44:"Symfony/Component/Form/FormTypeInterface.php";s:4:"role";s:3:"php";}}i:155;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"68bdf09c1c46788c5e90ada37f78d540";s:4:"name";s:35:"Symfony/Component/Form/FormView.php";s:4:"role";s:3:"php";}}i:156;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7003fc846b738bbd923fa5656e22d95b";s:4:"name";s:38:"Symfony/Component/Form/Guess/Guess.php";s:4:"role";s:3:"php";}}i:157;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0fedff65f9ab6dfc490a9b469192b0a6";s:4:"name";s:42:"Symfony/Component/Form/Guess/TypeGuess.php";s:4:"role";s:3:"php";}}i:158;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fc080890a68c7a2e9f145556cfa0b6d3";s:4:"name";s:43:"Symfony/Component/Form/Guess/ValueGuess.php";s:4:"role";s:3:"php";}}i:159;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:30:"Symfony/Component/Form/LICENSE";s:4:"role";s:3:"doc";}}i:160;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"165b5d30323c31b5a70be0d4ed584fde";s:4:"name";s:47:"Symfony/Component/Form/NativeRequestHandler.php";s:4:"role";s:3:"php";}}i:161;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"66ef84fb360f766ab10567f114268e0f";s:4:"name";s:39:"Symfony/Component/Form/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:162;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ab4eca434dd1f8ac7df3666e1ed1b7df";s:4:"name";s:45:"Symfony/Component/Form/PreloadedExtension.php";s:4:"role";s:3:"php";}}i:163;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ebe5a2b970601e8bd9149d2c8dd1d3d1";s:4:"name";s:32:"Symfony/Component/Form/README.md";s:4:"role";s:3:"doc";}}i:164;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e16c038acbd7b2c01bcb48c7f40e728d";s:4:"name";s:50:"Symfony/Component/Form/RequestHandlerInterface.php";s:4:"role";s:3:"php";}}i:165;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0a3c5437610d92506335292ad7b6abf9";s:4:"name";s:43:"Symfony/Component/Form/ResolvedFormType.php";s:4:"role";s:3:"php";}}i:166;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5d25fc04121ed5f6e428165f5936c10f";s:4:"name";s:50:"Symfony/Component/Form/ResolvedFormTypeFactory.php";s:4:"role";s:3:"php";}}i:167;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fa408445a6fab81659c0cefed09bf3df";s:4:"name";s:59:"Symfony/Component/Form/ResolvedFormTypeFactoryInterface.php";s:4:"role";s:3:"php";}}i:168;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8c1edc5a2b254bdde6476893b156950";s:4:"name";s:52:"Symfony/Component/Form/ResolvedFormTypeInterface.php";s:4:"role";s:3:"php";}}i:169;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"256dafb4fae5e462d55a71ab388c0691";s:4:"name";s:54:"Symfony/Component/Form/Resources/config/validation.xml";s:4:"role";s:3:"php";}}i:170;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e0ad0b923b6ac791b49b9a4d33af7a25";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ar.xlf";s:4:"role";s:3:"php";}}i:171;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1d5e19ca06d1aa8293b5887092685e05";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.bg.xlf";s:4:"role";s:3:"php";}}i:172;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c7ad1d90ad05603286ab378d72608d01";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ca.xlf";s:4:"role";s:3:"php";}}i:173;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2b0bed4fc587230bd11e83b7bbe29339";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.cs.xlf";s:4:"role";s:3:"php";}}i:174;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e46f7c3da02bcd4fa8c379469310c217";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.da.xlf";s:4:"role";s:3:"php";}}i:175;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"921a3c43eb6bf008f7d4ae7d2e56233f";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.de.xlf";s:4:"role";s:3:"php";}}i:176;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a7470225a9c04a5c2b5f179d8060c38b";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.el.xlf";s:4:"role";s:3:"php";}}i:177;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8f7759249199e5589331c432c54c9197";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.en.xlf";s:4:"role";s:3:"php";}}i:178;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b086ea186d7babe85d8bfa78957acea4";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.es.xlf";s:4:"role";s:3:"php";}}i:179;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f81867f4f9fd2362db42befa9628c103";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.et.xlf";s:4:"role";s:3:"php";}}i:180;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0ae3f2a05c0e69cc63ef84384913a4fe";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.eu.xlf";s:4:"role";s:3:"php";}}i:181;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"321b2f3f5ac56ff0c81871b44fe369bd";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.fa.xlf";s:4:"role";s:3:"php";}}i:182;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8cbad436ab4b1d574690992f15e37397";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.fi.xlf";s:4:"role";s:3:"php";}}i:183;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8bfa3368c7beefedc897f3098744e5dd";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.fr.xlf";s:4:"role";s:3:"php";}}i:184;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b21174a0425a56615ac95065c4cd4f8f";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.gl.xlf";s:4:"role";s:3:"php";}}i:185;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f03c3342827959500fe8bca223400225";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.he.xlf";s:4:"role";s:3:"php";}}i:186;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b87096c3cc16d9580d15fe9a9ca4d70";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.hr.xlf";s:4:"role";s:3:"php";}}i:187;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c538c1a55b060abb01cc1795a650ff36";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.hu.xlf";s:4:"role";s:3:"php";}}i:188;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d7f271b6e610fa47ae614cd9d92f7c02";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.hy.xlf";s:4:"role";s:3:"php";}}i:189;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"313e2438c2476b78ab637cd9dcd5322d";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.id.xlf";s:4:"role";s:3:"php";}}i:190;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3fa13f3254812a6857a99351cf6003d8";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.it.xlf";s:4:"role";s:3:"php";}}i:191;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3f47d2db87b7262c21c8287472719479";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ja.xlf";s:4:"role";s:3:"php";}}i:192;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f25583830baaccc529f6b4f0a845bd61";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.lb.xlf";s:4:"role";s:3:"php";}}i:193;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4ef7ab23ce55458844742317d905fa59";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.lt.xlf";s:4:"role";s:3:"php";}}i:194;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1cc55c8d2fb6eb1583b2d2cdfd54152e";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.lv.xlf";s:4:"role";s:3:"php";}}i:195;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4429ebdbb00601c0c67f43a06c4e8031";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.mn.xlf";s:4:"role";s:3:"php";}}i:196;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"017afa511ee2a18bddbbac0640cdb685";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.nb.xlf";s:4:"role";s:3:"php";}}i:197;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"94858839db1d8f8324759bf5e87c129d";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.nl.xlf";s:4:"role";s:3:"php";}}i:198;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c72a6e8c5c9dc76b0a9ceb275486acb3";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.pl.xlf";s:4:"role";s:3:"php";}}i:199;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bfda187791c843558b3bcc5327064e43";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.pt.xlf";s:4:"role";s:3:"php";}}i:200;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7cb1b50669945643c707acee4b13cf31";s:4:"name";s:66:"Symfony/Component/Form/Resources/translations/validators.pt_BR.xlf";s:4:"role";s:3:"php";}}i:201;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2eaf2e4ba82e742cb6dff54c69f1271";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ro.xlf";s:4:"role";s:3:"php";}}i:202;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6cbccc04ebb3a58158041e451c3bc536";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ru.xlf";s:4:"role";s:3:"php";}}i:203;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d2e6bd911ddff3c7b526755179cf6ed9";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.sk.xlf";s:4:"role";s:3:"php";}}i:204;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cc42fc67ec1729fe317cd3b1c3b96dd6";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.sl.xlf";s:4:"role";s:3:"php";}}i:205;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"20e303068da12f5f5248ace8162051ad";s:4:"name";s:68:"Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlf";s:4:"role";s:3:"php";}}i:206;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bdf4d302afd0b1b1b406009402b44f7d";s:4:"name";s:68:"Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlf";s:4:"role";s:3:"php";}}i:207;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"642c23a8173bfd547a71b69a694195f0";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.sv.xlf";s:4:"role";s:3:"php";}}i:208;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6c03831d89108e565c8358f46d807e32";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.uk.xlf";s:4:"role";s:3:"php";}}i:209;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"96cbd8686b821bd2cf91839a6c26cc03";s:4:"name";s:66:"Symfony/Component/Form/Resources/translations/validators.zh_CN.xlf";s:4:"role";s:3:"php";}}i:210;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"658dff714ce275350a7f720a86484e55";s:4:"name";s:46:"Symfony/Component/Form/ReversedTransformer.php";s:4:"role";s:3:"php";}}i:211;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3fb340157282afcc9223daeab2aeb49f";s:4:"name";s:39:"Symfony/Component/Form/SubmitButton.php";s:4:"role";s:3:"php";}}i:212;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ee4f0e6ffe3b36ab57c806045f69d3";s:4:"name";s:46:"Symfony/Component/Form/SubmitButtonBuilder.php";s:4:"role";s:3:"php";}}i:213;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"721a1bd36d3a0cd93e5c57956435f861";s:4:"name";s:52:"Symfony/Component/Form/SubmitButtonTypeInterface.php";s:4:"role";s:3:"php";}}i:214;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"70d8401563ddaeefe2982c73218d9a41";s:4:"name";s:55:"Symfony/Component/Form/Test/DeprecationErrorHandler.php";s:4:"role";s:3:"php";}}i:215;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1847328f5ba757c0997121ed38fe9d61";s:4:"name";s:52:"Symfony/Component/Form/Test/FormBuilderInterface.php";s:4:"role";s:3:"php";}}i:216;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8dc56ae07547e6e8a521cb9d68ff7499";s:4:"name";s:55:"Symfony/Component/Form/Test/FormIntegrationTestCase.php";s:4:"role";s:3:"php";}}i:217;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba89cda1179d1dbc7ae395c4f165f458";s:4:"name";s:45:"Symfony/Component/Form/Test/FormInterface.php";s:4:"role";s:3:"php";}}i:218;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f8d472cfeb2fb094a9fed0a0e31e5900";s:4:"name";s:55:"Symfony/Component/Form/Test/FormPerformanceTestCase.php";s:4:"role";s:3:"php";}}i:219;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a14b6e8fcfd683fcf7498f9a02da523d";s:4:"name";s:44:"Symfony/Component/Form/Test/TypeTestCase.php";s:4:"role";s:3:"php";}}i:220;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"01e6c9a75c6347c2c215d6a15b0c79d5";s:4:"name";s:54:"Symfony/Component/Form/Tests/AbstractDivLayoutTest.php";s:4:"role";s:4:"test";}}i:221;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"993f833ed9fb277ec6f3a74a773d92ae";s:4:"name";s:54:"Symfony/Component/Form/Tests/AbstractExtensionTest.php";s:4:"role";s:4:"test";}}i:222;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"25108525cdb98b2c542d79ef69a08970";s:4:"name";s:49:"Symfony/Component/Form/Tests/AbstractFormTest.php";s:4:"role";s:4:"test";}}i:223;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5def14944ef79b573b5bd008ab84ca4b";s:4:"name";s:51:"Symfony/Component/Form/Tests/AbstractLayoutTest.php";s:4:"role";s:4:"test";}}i:224;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1e1eaca7aca8b88c93cd99d5d934dc12";s:4:"name";s:59:"Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php";s:4:"role";s:4:"test";}}i:225;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f18c692af6dbc9682b8fbfae88d5909c";s:4:"name";s:56:"Symfony/Component/Form/Tests/AbstractTableLayoutTest.php";s:4:"role";s:4:"test";}}i:226;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"487f6d057728873fdbda43c763ad9a3c";s:4:"name";s:60:"Symfony/Component/Form/Tests/CompoundFormPerformanceTest.php";s:4:"role";s:4:"test";}}i:227;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3e01bd80c478bfef4e94cce5b05b810f";s:4:"name";s:49:"Symfony/Component/Form/Tests/CompoundFormTest.php";s:4:"role";s:4:"test";}}i:228;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"805f66672b74f69ef369360000ce28d7";s:4:"name";s:81:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php";s:4:"role";s:4:"test";}}i:229;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0eb2d36957cb3f06b8246cf4d62845e6";s:4:"name";s:73:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.php";s:4:"role";s:4:"test";}}i:230;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4fe2229f0a5ccdfed66591f926d1408a";s:4:"name";s:77:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php";s:4:"role";s:4:"test";}}i:231;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9438557f7e55048a10c0da6dc9b5b7d5";s:4:"name";s:79:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php";s:4:"role";s:4:"test";}}i:232;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c887b01a87b147202efc194dd37f5654";s:4:"name";s:79:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php";s:4:"role";s:4:"test";}}i:233;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"de020dd5c1bfe761abc83eb0d407b93b";s:4:"name";s:86:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php";s:4:"role";s:4:"test";}}i:234;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b3671899963fbd7e534be6a316b9f7f";s:4:"name";s:81:"Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php";s:4:"role";s:4:"test";}}i:235;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fe5c56d887d5e3c625a29d58f19f14b2";s:4:"name";s:91:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php";s:4:"role";s:4:"test";}}i:236;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1f0f17c4989a4bf7e663524addd19377";s:4:"name";s:91:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.php";s:4:"role";s:4:"test";}}i:237;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2656ea40e07d5722e5afae535a14c6f2";s:4:"name";s:94:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php";s:4:"role";s:4:"test";}}i:238;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f10f920c63a846fee23f895f6519b30c";s:4:"name";s:94:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php";s:4:"role";s:4:"test";}}i:239;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"81b526febe066ae1212cf792e057a858";s:4:"name";s:92:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php";s:4:"role";s:4:"test";}}i:240;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d391c39a885af56bbe963d2884ce1581";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php";s:4:"role";s:4:"test";}}i:241;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2a0a01ad1cc0ede0f9a9610be868290e";s:4:"name";s:80:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php";s:4:"role";s:4:"test";}}i:242;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c333df3e9adfbd0151953a318603b358";s:4:"name";s:94:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php";s:4:"role";s:4:"test";}}i:243;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cff66917b58654868071c9ee011e36fa";s:4:"name";s:104:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";}}i:244;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ca35365fd4c7e312165063c8754a9545";s:4:"name";s:96:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php";s:4:"role";s:4:"test";}}i:245;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eccc79ef623e695d17510a7c1537a88d";s:4:"name";s:95:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php";s:4:"role";s:4:"test";}}i:246;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e5ee536591d17b7bfe89945a498724ec";s:4:"name";s:98:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php";s:4:"role";s:4:"test";}}i:247;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0eac0ca2189eaf93a9fdaa18c2bfce45";s:4:"name";s:103:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";}}i:248;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"74344e0d818fb775d511fea0ee331e96";s:4:"name";s:101:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";}}i:249;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c7f0520009e30903c4b681d8038d1116";s:4:"name";s:102:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";}}i:250;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3f3ac246acda56e18c45ede2ad738de5";s:4:"name";s:103:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";}}i:251;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"340da808904f9f817f6bb74c6d1d1bae";s:4:"name";s:96:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php";s:4:"role";s:4:"test";}}i:252;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47864719339897429512947960cec29e";s:4:"name";s:87:"Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php";s:4:"role";s:4:"test";}}i:253;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87aec5a94c94ec7a5dd1c0839eb0182b";s:4:"name";s:77:"Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhash";s:4:"role";s:4:"test";}}i:254;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6cb15bfda3938a694ba12e947582ee1c";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php";s:4:"role";s:4:"test";}}i:255;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e0bc897a2bcb5584079604cd7a932c4a";s:4:"name";s:100:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php";s:4:"role";s:4:"test";}}i:256;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"541c2ff8d9b47ce17ab79a9f5c7da315";s:4:"name";s:94:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php";s:4:"role";s:4:"test";}}i:257;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b4d97e836cfe76c4b348b38ef0d3199";s:4:"name";s:106:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php";s:4:"role";s:4:"test";}}i:258;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6cb07a92e893ccd4ddf1f93592d0ea12";s:4:"name";s:89:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php";s:4:"role";s:4:"test";}}i:259;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7726c3ab7d9e202ef7e50c6e18a0dc13";s:4:"name";s:84:"Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php";s:4:"role";s:4:"test";}}i:260;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"200a4cdc92f0b266f8b46b971fc5ec82";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php";s:4:"role";s:4:"test";}}i:261;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d6a45bded973053fe2db03fce86a667f";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php";s:4:"role";s:4:"test";}}i:262;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"040223464ae2179f3aa78e84fd7b8511";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php";s:4:"role";s:4:"test";}}i:263;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"951887c57ca144e04ba2f2001fb12a5b";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php";s:4:"role";s:4:"test";}}i:264;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c435893620ce32c2bee017d4b0cb2157";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php";s:4:"role";s:4:"test";}}i:265;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9e18e82da0bbc8f4370d3f652ed8ad48";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php";s:4:"role";s:4:"test";}}i:266;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"643faa42c8a2cfc19880f78bc9d3bb83";s:4:"name";s:71:"Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php";s:4:"role";s:4:"test";}}i:267;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"196ba14f11fc05ed0a061a909d71b8cd";s:4:"name";s:68:"Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php";s:4:"role";s:4:"test";}}i:268;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2b1c1525d0bf4cf02e807689138ec88";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php";s:4:"role";s:4:"test";}}i:269;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"91b9362007d0d02d7b55852d49a226d2";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php";s:4:"role";s:4:"test";}}i:270;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"42c8e0bc27d5102ce1b9f7d3807c436c";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php";s:4:"role";s:4:"test";}}i:271;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1bad6779778649a56a6df8ba51ac2442";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php";s:4:"role";s:4:"test";}}i:272;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6384962d22490e2965944280e6da8dd3";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php";s:4:"role";s:4:"test";}}i:273;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"145ac554d44d2416c20efbc33490831b";s:4:"name";s:68:"Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php";s:4:"role";s:4:"test";}}i:274;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae9dea4e2cd5149f1469249f0aabe2ac";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php";s:4:"role";s:4:"test";}}i:275;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b7946ff970129706743ad613161fd929";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php";s:4:"role";s:4:"test";}}i:276;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6bfc500ee59b3c0e85c23e2a4007fc52";s:4:"name";s:66:"Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php";s:4:"role";s:4:"test";}}i:277;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e680b158e130d104e812bc59a594fa08";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php";s:4:"role";s:4:"test";}}i:278;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a683610fb85dd825d4141a4b3f528e46";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.php";s:4:"role";s:4:"test";}}i:279;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"369245a8723921b895a4591ba34005eb";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php";s:4:"role";s:4:"test";}}i:280;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fe429eb590a75d6dd3a20bbf08d1e639";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.php";s:4:"role";s:4:"test";}}i:281;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1f837469d11ac48ff637e8fa08da7a44";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php";s:4:"role";s:4:"test";}}i:282;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1082d1f9f4683702300ce6a8be9c835b";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php";s:4:"role";s:4:"test";}}i:283;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e71b97847da4bbd7b694e2a7ea18c7b7";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.php";s:4:"role";s:4:"test";}}i:284;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1f33d8fa306ebdbad2cf4561557655ca";s:4:"name";s:64:"Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php";s:4:"role";s:4:"test";}}i:285;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5607097da4e8ba843c7671fc95bd5ed";s:4:"name";s:84:"Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php";s:4:"role";s:4:"test";}}i:286;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b01b266a7196ae1aaaf9b4d3d8f1f2ed";s:4:"name";s:84:"Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php";s:4:"role";s:4:"test";}}i:287;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"afcd45b858401261360a30c4cb0f9aba";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php";s:4:"role";s:4:"test";}}i:288;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1ee5764d064d208a058c7719817c5935";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php";s:4:"role";s:4:"test";}}i:289;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e69912900a62a5bb4c69d9c37ed2952e";s:4:"name";s:83:"Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.php";s:4:"role";s:4:"test";}}i:290;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"deaf70e32c29e96b0a0f5de433b99dea";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php";s:4:"role";s:4:"test";}}i:291;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d12c0ee191323d8ad5e0926d2484ec59";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.php";s:4:"role";s:4:"test";}}i:292;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d8948496dc0e6214e740ca00ca529e95";s:4:"name";s:92:"Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.php";s:4:"role";s:4:"test";}}i:293;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6e2cdd48baa66831a820c785cf96d440";s:4:"name";s:95:"Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php";s:4:"role";s:4:"test";}}i:294;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b2e0f962d2654c7b7bfabeec6feffe3a";s:4:"name";s:90:"Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php";s:4:"role";s:4:"test";}}i:295;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b843b76574f23418997cf5d299e1795d";s:4:"name";s:93:"Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php";s:4:"role";s:4:"test";}}i:296;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3956a614fe00f61b9df4abd22fb94c77";s:4:"name";s:82:"Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php";s:4:"role";s:4:"test";}}i:297;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"159b78c63cad4f5c62977766f6680a69";s:4:"name";s:89:"Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php";s:4:"role";s:4:"test";}}i:298;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8ca1bca8a4d7d47e6d612d714c3e434d";s:4:"name";s:84:"Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php";s:4:"role";s:4:"test";}}i:299;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"68b380257c232e2600d07153905f0d5f";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php";s:4:"role";s:4:"test";}}i:300;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"831836b41b079545f0670fe13ce7a212";s:4:"name";s:90:"Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php";s:4:"role";s:4:"test";}}i:301;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"49189d46e88a6d3d850c27b162c6e2ce";s:4:"name";s:70:"Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php";s:4:"role";s:4:"test";}}i:302;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5cfc3ee82f42b842bc2d5c384142e5e";s:4:"name";s:74:"Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php";s:4:"role";s:4:"test";}}i:303;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"19620e0f5149427d9bc81ff43f3f6849";s:4:"name";s:77:"Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php";s:4:"role";s:4:"test";}}i:304;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"87696746275168d808097b9ac08eefd1";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php";s:4:"role";s:4:"test";}}i:305;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4be55d217fa73d2f0c14537f75635e84";s:4:"name";s:86:"Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php";s:4:"role";s:4:"test";}}i:306;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aaeeaa8b993916866478b077e0ae5f7b";s:4:"name";s:60:"Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php";s:4:"role";s:4:"test";}}i:307;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5c1563a26ab06e4cc72c80d1b4aa75a4";s:4:"name";s:48:"Symfony/Component/Form/Tests/Fixtures/Author.php";s:4:"role";s:4:"test";}}i:308;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"68c706abf40680b1fad0aa7c383af085";s:4:"name";s:52:"Symfony/Component/Form/Tests/Fixtures/AuthorType.php";s:4:"role";s:4:"test";}}i:309;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80f520948113200553ccb1415f481af3";s:4:"name";s:59:"Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php";s:4:"role";s:4:"test";}}i:310;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"21ddaf5472929f397a80781c71c5904e";s:4:"name";s:62:"Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php";s:4:"role";s:4:"test";}}i:311;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2a8c5376aac3794f6ba81a263e4f2bf";s:4:"name";s:61:"Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.php";s:4:"role";s:4:"test";}}i:312;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:41:"Symfony/Component/Form/Tests/Fixtures/foo";s:4:"role";s:4:"test";}}i:313;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"412bb3f7b15954b7685df57c03cc9216";s:4:"name";s:52:"Symfony/Component/Form/Tests/Fixtures/FooSubType.php";s:4:"role";s:4:"test";}}i:314;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"31c9db4f9cbf24f98688538f63431553";s:4:"name";s:70:"Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.php";s:4:"role";s:4:"test";}}i:315;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"56722f2c6ccf149b5009818e705b661d";s:4:"name";s:49:"Symfony/Component/Form/Tests/Fixtures/FooType.php";s:4:"role";s:4:"test";}}i:316;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"344219ab84242c7d151ff482ebbca70b";s:4:"name";s:61:"Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.php";s:4:"role";s:4:"test";}}i:317;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8178239dc9236054e8df7a4cbf7d7888";s:4:"name";s:61:"Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.php";s:4:"role";s:4:"test";}}i:318;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e23c89ad471d8601a063b068cd6636ee";s:4:"name";s:55:"Symfony/Component/Form/Tests/Fixtures/TestExtension.php";s:4:"role";s:4:"test";}}i:319;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"72d98919f7d17ed12b851b748b795913";s:4:"name";s:48:"Symfony/Component/Form/Tests/FormBuilderTest.php";s:4:"role";s:4:"test";}}i:320;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0a53ef078ccdaf281872d03975b3f9c5";s:4:"name";s:47:"Symfony/Component/Form/Tests/FormConfigTest.php";s:4:"role";s:4:"test";}}i:321;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4808f4d1f807a2bd730db77dc250ea3a";s:4:"name";s:55:"Symfony/Component/Form/Tests/FormFactoryBuilderTest.php";s:4:"role";s:4:"test";}}i:322;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"148b1a32ce39b4536ce2cdabca226c8e";s:4:"name";s:48:"Symfony/Component/Form/Tests/FormFactoryTest.php";s:4:"role";s:4:"test";}}i:323;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cba12233a71fa6ad78db42d0b0358123";s:4:"name";s:56:"Symfony/Component/Form/Tests/FormIntegrationTestCase.php";s:4:"role";s:4:"test";}}i:324;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e899de2472926b4ada8acb636f1b5444";s:4:"name";s:56:"Symfony/Component/Form/Tests/FormPerformanceTestCase.php";s:4:"role";s:4:"test";}}i:325;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eeb0092e76c36e50791699eb2faaaa03";s:4:"name";s:49:"Symfony/Component/Form/Tests/FormRegistryTest.php";s:4:"role";s:4:"test";}}i:326;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1fc848f084ce8f7e10335f8175105886";s:4:"name";s:49:"Symfony/Component/Form/Tests/FormRendererTest.php";s:4:"role";s:4:"test";}}i:327;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fff8d24dbf03762ed0e2b6f15df45d2d";s:4:"name";s:48:"Symfony/Component/Form/Tests/Guess/GuessTest.php";s:4:"role";s:4:"test";}}i:328;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1877e570ea6b354cd5d9d9ba30418edb";s:4:"name";s:57:"Symfony/Component/Form/Tests/NativeRequestHandlerTest.php";s:4:"role";s:4:"test";}}i:329;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5261f73e95c249da67fe334c0927bf1f";s:4:"name";s:53:"Symfony/Component/Form/Tests/ResolvedFormTypeTest.php";s:4:"role";s:4:"test";}}i:330;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cfd0db6db50796656eb604515e87adda";s:4:"name";s:47:"Symfony/Component/Form/Tests/SimpleFormTest.php";s:4:"role";s:4:"test";}}i:331;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a7eeabaf53f6a3b60ec3ac2a78ce5002";s:4:"name";s:56:"Symfony/Component/Form/Tests/Util/OrderedHashMapTest.php";s:4:"role";s:4:"test";}}i:332;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d3566f471dce8351225b74b1c01058b6";s:4:"name";s:40:"Symfony/Component/Form/Util/FormUtil.php";s:4:"role";s:3:"php";}}i:333;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"98034987b9a71a6ec3a3f2fddd95f06a";s:4:"name";s:56:"Symfony/Component/Form/Util/InheritDataAwareIterator.php";s:4:"role";s:3:"php";}}i:334;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fe22cba7385d2b8406b6a7104b9cf58c";s:4:"name";s:46:"Symfony/Component/Form/Util/OrderedHashMap.php";s:4:"role";s:3:"php";}}i:335;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6240f5c5d77934285a2dddab60843429";s:4:"name";s:54:"Symfony/Component/Form/Util/OrderedHashMapIterator.php";s:4:"role";s:3:"php";}}i:336;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"da65af10d658064eddfec592c82eb95b";s:4:"name";s:56:"Symfony/Component/Form/Util/VirtualFormAwareIterator.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}s:7:"package";a:3:{i:0;a:2:{s:4:"name";s:15:"EventDispatcher";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:9:"Validator";s:7:"channel";s:16:"pear.symfony.com";}i:2;a:2:{s:4:"name";s:6:"Locale";s:7:"channel";s:16:"pear.symfony.com";}}}s:8:"optional";a:1:{s:7:"package";a:2:{s:4:"name";s:14:"HttpFoundation";s:7:"channel";s:16:"pear.symfony.com";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:337:{s:44:"Symfony/Component/Form/AbstractExtension.php";a:4:{s:6:"md5sum";s:32:"501890934b78c1cda42337c3c85761f5";s:4:"name";s:44:"Symfony/Component/Form/AbstractExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/AbstractExtension.php";}s:49:"Symfony/Component/Form/AbstractRendererEngine.php";a:4:{s:6:"md5sum";s:32:"c855e95efaafd48a3b35f4e4ed7ef461";s:4:"name";s:49:"Symfony/Component/Form/AbstractRendererEngine.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/AbstractRendererEngine.php";}s:39:"Symfony/Component/Form/AbstractType.php";a:4:{s:6:"md5sum";s:32:"fda8ea1864e57a50d81607d692e68c73";s:4:"name";s:39:"Symfony/Component/Form/AbstractType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/AbstractType.php";}s:48:"Symfony/Component/Form/AbstractTypeExtension.php";a:4:{s:6:"md5sum";s:32:"0cc218c093e9d4631ab2dd2276c567bd";s:4:"name";s:48:"Symfony/Component/Form/AbstractTypeExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/AbstractTypeExtension.php";}s:37:"Symfony/Component/Form/autoloader.php";a:4:{s:6:"md5sum";s:32:"ccc700d8c25bc05b9e4a4b327a643f46";s:4:"name";s:37:"Symfony/Component/Form/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/autoloader.php";}s:33:"Symfony/Component/Form/Button.php";a:4:{s:6:"md5sum";s:32:"e4221c7f370be7e1fae189ac0f0245f8";s:4:"name";s:33:"Symfony/Component/Form/Button.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Button.php";}s:40:"Symfony/Component/Form/ButtonBuilder.php";a:4:{s:6:"md5sum";s:32:"d27ec47e44803a025e38d0067c824cdc";s:4:"name";s:40:"Symfony/Component/Form/ButtonBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/ButtonBuilder.php";}s:46:"Symfony/Component/Form/ButtonTypeInterface.php";a:4:{s:6:"md5sum";s:32:"2b9067ff341a18790204ea50c84102bd";s:4:"name";s:46:"Symfony/Component/Form/ButtonTypeInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/ButtonTypeInterface.php";}s:46:"Symfony/Component/Form/CallbackTransformer.php";a:4:{s:6:"md5sum";s:32:"902572561ace9999c9f8d8e0f37cd28f";s:4:"name";s:46:"Symfony/Component/Form/CallbackTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/CallbackTransformer.php";}s:35:"Symfony/Component/Form/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"abf0d085506e63678c96f8f9666c3b1c";s:4:"name";s:35:"Symfony/Component/Form/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/doc/pear/Form/Symfony/Component/Form/CHANGELOG.md";}s:45:"Symfony/Component/Form/ClickableInterface.php";a:4:{s:6:"md5sum";s:32:"0907b59351198bd99ceea685c9f7c7c2";s:4:"name";s:45:"Symfony/Component/Form/ClickableInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/ClickableInterface.php";}s:36:"Symfony/Component/Form/composer.json";a:4:{s:6:"md5sum";s:32:"5519e4c865c9aab62f36e8ccc2687a0a";s:4:"name";s:36:"Symfony/Component/Form/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/Form/Symfony/Component/Form/composer.json";}s:46:"Symfony/Component/Form/DataMapperInterface.php";a:4:{s:6:"md5sum";s:32:"db3b117a3b8dd577bbd64a81766ad78d";s:4:"name";s:46:"Symfony/Component/Form/DataMapperInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/DataMapperInterface.php";}s:51:"Symfony/Component/Form/DataTransformerInterface.php";a:4:{s:6:"md5sum";s:32:"555454867c9b8687d4ee00a014b981c1";s:4:"name";s:51:"Symfony/Component/Form/DataTransformerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/DataTransformerInterface.php";}s:58:"Symfony/Component/Form/Exception/AlreadyBoundException.php";a:4:{s:6:"md5sum";s:32:"bc89a72f34e3e1d4a6628d32b1511007";s:4:"name";s:58:"Symfony/Component/Form/Exception/AlreadyBoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/AlreadyBoundException.php";}s:62:"Symfony/Component/Form/Exception/AlreadySubmittedException.php";a:4:{s:6:"md5sum";s:32:"419b77be4914d44fbe8f422c9dce819a";s:4:"name";s:62:"Symfony/Component/Form/Exception/AlreadySubmittedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/AlreadySubmittedException.php";}s:59:"Symfony/Component/Form/Exception/BadMethodCallException.php";a:4:{s:6:"md5sum";s:32:"a7e624979068a6ac1975cef01a181a64";s:4:"name";s:59:"Symfony/Component/Form/Exception/BadMethodCallException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/BadMethodCallException.php";}s:58:"Symfony/Component/Form/Exception/ErrorMappingException.php";a:4:{s:6:"md5sum";s:32:"b43e60289f802c13894f4427988c2915";s:4:"name";s:58:"Symfony/Component/Form/Exception/ErrorMappingException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/ErrorMappingException.php";}s:55:"Symfony/Component/Form/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"1f4d4c025c5f49fd0e787f2095dcac58";s:4:"name";s:55:"Symfony/Component/Form/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/ExceptionInterface.php";}s:61:"Symfony/Component/Form/Exception/InvalidArgumentException.php";a:4:{s:6:"md5sum";s:32:"a93c3e0ef8f9f1833b1ec31f26baaa92";s:4:"name";s:61:"Symfony/Component/Form/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/InvalidArgumentException.php";}s:66:"Symfony/Component/Form/Exception/InvalidConfigurationException.php";a:4:{s:6:"md5sum";s:32:"16b9f308c2cd41c6feea464a4c2a4078";s:4:"name";s:66:"Symfony/Component/Form/Exception/InvalidConfigurationException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/InvalidConfigurationException.php";}s:51:"Symfony/Component/Form/Exception/LogicException.php";a:4:{s:6:"md5sum";s:32:"7acb2af6fec7e8015fdf9473ed22e568";s:4:"name";s:51:"Symfony/Component/Form/Exception/LogicException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/LogicException.php";}s:57:"Symfony/Component/Form/Exception/OutOfBoundsException.php";a:4:{s:6:"md5sum";s:32:"6439c29ccaba5ed08f068b56d1cb900a";s:4:"name";s:57:"Symfony/Component/Form/Exception/OutOfBoundsException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/OutOfBoundsException.php";}s:53:"Symfony/Component/Form/Exception/RuntimeException.php";a:4:{s:6:"md5sum";s:32:"035137b05f9d396eebf788cd0475bfd2";s:4:"name";s:53:"Symfony/Component/Form/Exception/RuntimeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/RuntimeException.php";}s:56:"Symfony/Component/Form/Exception/StringCastException.php";a:4:{s:6:"md5sum";s:32:"05fafa90307ac0049080845bfc134e90";s:4:"name";s:56:"Symfony/Component/Form/Exception/StringCastException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/StringCastException.php";}s:66:"Symfony/Component/Form/Exception/TransformationFailedException.php";a:4:{s:6:"md5sum";s:32:"04e43782ab8e754a86f812f93d3e80f0";s:4:"name";s:66:"Symfony/Component/Form/Exception/TransformationFailedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/TransformationFailedException.php";}s:60:"Symfony/Component/Form/Exception/UnexpectedTypeException.php";a:4:{s:6:"md5sum";s:32:"93ab4195343c65feabe0a9a15e3b4e03";s:4:"name";s:60:"Symfony/Component/Form/Exception/UnexpectedTypeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception/UnexpectedTypeException.php";}s:63:"Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php";a:4:{s:6:"md5sum";s:32:"fae7f67d21f3636dcfd9255b18c0f409";s:4:"name";s:63:"Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php";}s:72:"Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php";a:4:{s:6:"md5sum";s:32:"75ef902d77e51ff120a5bb80a3ba4b2c";s:4:"name";s:72:"Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php";}s:67:"Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php";a:4:{s:6:"md5sum";s:32:"6c60da1e88563e1e8ee345e908e99895";s:4:"name";s:67:"Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php";}s:69:"Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php";a:4:{s:6:"md5sum";s:32:"93d7bd50a57d6ce541c9e465f1f9c727";s:4:"name";s:69:"Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php";}s:69:"Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php";a:4:{s:6:"md5sum";s:32:"dd799ebc2f390f6c26a68d9b27163986";s:4:"name";s:69:"Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php";}s:55:"Symfony/Component/Form/Extension/Core/CoreExtension.php";a:4:{s:6:"md5sum";s:32:"249e325333e1e0bbf071c2352f1015ef";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/CoreExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/CoreExtension.php";}s:71:"Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php";a:4:{s:6:"md5sum";s:32:"cf380dc09a61dcd25aa19cde02d5a496";s:4:"name";s:71:"Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php";}s:81:"Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php";a:4:{s:6:"md5sum";s:32:"5b1463a8ca32434df6df7fdd15470ffe";s:4:"name";s:81:"Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php";}s:81:"Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php";a:4:{s:6:"md5sum";s:32:"95ce9f75d9de781506bd27afae24a435";s:4:"name";s:81:"Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php";}s:84:"Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php";a:4:{s:6:"md5sum";s:32:"1beb890d4d901ce9a49a02aa567d4d1d";s:4:"name";s:84:"Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php";}s:90:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php";a:4:{s:6:"md5sum";s:32:"bdc67501df308818f4ccb6e87fd4b460";s:4:"name";s:90:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php";}s:84:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php";a:4:{s:6:"md5sum";s:32:"d417455cb1a9c5f1ce2d0ae9b72c262a";s:4:"name";s:84:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php";}s:89:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php";a:4:{s:6:"md5sum";s:32:"b4ddb6ca1e45e39c27603e9a61746fe0";s:4:"name";s:89:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php";}s:82:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php";a:4:{s:6:"md5sum";s:32:"c23bb58d706b389464865d3baaa9dc0f";s:4:"name";s:82:"Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php";}s:78:"Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.php";a:4:{s:6:"md5sum";s:32:"fb47a7c8ec22b84e657ba080eebf9185";s:4:"name";s:78:"Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.php";}s:84:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php";a:4:{s:6:"md5sum";s:32:"987af4de3dad99dbe03d40ad481e59f5";s:4:"name";s:84:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php";}s:94:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php";a:4:{s:6:"md5sum";s:32:"08fe73eed45b4e64f5a612fe384ee949";s:4:"name";s:94:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php";}s:86:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php";a:4:{s:6:"md5sum";s:32:"536a31499542c247eeac9f887459ccb6";s:4:"name";s:86:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php";}s:85:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php";a:4:{s:6:"md5sum";s:32:"84819444537109979c4ded0dcb5449d3";s:4:"name";s:85:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php";}s:88:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php";a:4:{s:6:"md5sum";s:32:"d420953c67b9ce03b78d46777f78934e";s:4:"name";s:88:"Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php";}s:93:"Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php";a:4:{s:6:"md5sum";s:32:"87c45ad85d859bc5ac1847dbe26f451f";s:4:"name";s:93:"Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php";}s:91:"Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php";a:4:{s:6:"md5sum";s:32:"031be52b519ab452a56e72c0ad919f9d";s:4:"name";s:91:"Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php";}s:92:"Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php";a:4:{s:6:"md5sum";s:32:"fdab477194f1770c375e73e5571253c9";s:4:"name";s:92:"Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php";}s:93:"Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php";a:4:{s:6:"md5sum";s:32:"0a1be99705fd6d15d2b67c9d7cc34f0a";s:4:"name";s:93:"Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php";}s:86:"Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php";a:4:{s:6:"md5sum";s:32:"a9acfacc5c1d22709f2d9fb9572e5856";s:4:"name";s:86:"Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php";}s:80:"Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php";a:4:{s:6:"md5sum";s:32:"4fd81dac92cd7178a4df5463b909a67b";s:4:"name";s:80:"Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php";}s:77:"Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php";a:4:{s:6:"md5sum";s:32:"def66949bde6d959e70d661d15f1e9e3";s:4:"name";s:77:"Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php";}s:78:"Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php";a:4:{s:6:"md5sum";s:32:"f57106b0d09322f11efddefb368fb952";s:4:"name";s:78:"Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php";}s:79:"Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php";a:4:{s:6:"md5sum";s:32:"1d42403d6e8be3877c66cdf6eeb7f375";s:4:"name";s:79:"Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php";}s:74:"Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php";a:4:{s:6:"md5sum";s:32:"c79a52d764d974eaa9a1d742211220b9";s:4:"name";s:74:"Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php";}s:68:"Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php";a:4:{s:6:"md5sum";s:32:"0bbbf865bc2c1c7b013b19cd49ea66f8";s:4:"name";s:68:"Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php";}s:55:"Symfony/Component/Form/Extension/Core/Type/BaseType.php";a:4:{s:6:"md5sum";s:32:"058c321dda699e31ae2e164586817072";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/BaseType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/BaseType.php";}s:59:"Symfony/Component/Form/Extension/Core/Type/BirthdayType.php";a:4:{s:6:"md5sum";s:32:"601dc1defb9cfe03f57ecb55ec6519ee";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/BirthdayType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/BirthdayType.php";}s:57:"Symfony/Component/Form/Extension/Core/Type/ButtonType.php";a:4:{s:6:"md5sum";s:32:"df30378aa4224d2e19bfb48e3f22be73";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/ButtonType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/ButtonType.php";}s:59:"Symfony/Component/Form/Extension/Core/Type/CheckboxType.php";a:4:{s:6:"md5sum";s:32:"20d7fadb63815c65c600ff1cab100d69";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/CheckboxType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/CheckboxType.php";}s:57:"Symfony/Component/Form/Extension/Core/Type/ChoiceType.php";a:4:{s:6:"md5sum";s:32:"c7bce0021e92409791dc40237e44585e";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/ChoiceType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php";}s:61:"Symfony/Component/Form/Extension/Core/Type/CollectionType.php";a:4:{s:6:"md5sum";s:32:"675668b49022522d4646aa90049c2650";s:4:"name";s:61:"Symfony/Component/Form/Extension/Core/Type/CollectionType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/CollectionType.php";}s:58:"Symfony/Component/Form/Extension/Core/Type/CountryType.php";a:4:{s:6:"md5sum";s:32:"113a7ecb3ad40c9ffb38fd685db1ab3a";s:4:"name";s:58:"Symfony/Component/Form/Extension/Core/Type/CountryType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/CountryType.php";}s:59:"Symfony/Component/Form/Extension/Core/Type/CurrencyType.php";a:4:{s:6:"md5sum";s:32:"0be9c69f93866ae116791fcfb7a77186";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/CurrencyType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php";}s:59:"Symfony/Component/Form/Extension/Core/Type/DateTimeType.php";a:4:{s:6:"md5sum";s:32:"5d41f93fff961492d2de8bc4d71e7862";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/DateTimeType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php";}s:55:"Symfony/Component/Form/Extension/Core/Type/DateType.php";a:4:{s:6:"md5sum";s:32:"35d0a4afbc155cd3838aebf3a564fb42";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/DateType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/DateType.php";}s:56:"Symfony/Component/Form/Extension/Core/Type/EmailType.php";a:4:{s:6:"md5sum";s:32:"146a7c19ddde4cdca72343da4cfe17d5";s:4:"name";s:56:"Symfony/Component/Form/Extension/Core/Type/EmailType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/EmailType.php";}s:55:"Symfony/Component/Form/Extension/Core/Type/FileType.php";a:4:{s:6:"md5sum";s:32:"060ed2ce1bef45de0340a9448c5f04f2";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/FileType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/FileType.php";}s:55:"Symfony/Component/Form/Extension/Core/Type/FormType.php";a:4:{s:6:"md5sum";s:32:"50f9fbd36e4a7e4b9136be87bf43cb8a";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/FormType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/FormType.php";}s:57:"Symfony/Component/Form/Extension/Core/Type/HiddenType.php";a:4:{s:6:"md5sum";s:32:"300baaff3c467b27ddcde08751708dc8";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/HiddenType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/HiddenType.php";}s:58:"Symfony/Component/Form/Extension/Core/Type/IntegerType.php";a:4:{s:6:"md5sum";s:32:"39268ae7dc189edbc1f1ac9cf01bdcb6";s:4:"name";s:58:"Symfony/Component/Form/Extension/Core/Type/IntegerType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/IntegerType.php";}s:59:"Symfony/Component/Form/Extension/Core/Type/LanguageType.php";a:4:{s:6:"md5sum";s:32:"d463acc8367ee0afe8417a0aaba019fe";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/LanguageType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/LanguageType.php";}s:57:"Symfony/Component/Form/Extension/Core/Type/LocaleType.php";a:4:{s:6:"md5sum";s:32:"a01e0f05fec87b35b3424829d33d1755";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/LocaleType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/LocaleType.php";}s:56:"Symfony/Component/Form/Extension/Core/Type/MoneyType.php";a:4:{s:6:"md5sum";s:32:"610e8b6a1425b2eb97a0d7c700edf05c";s:4:"name";s:56:"Symfony/Component/Form/Extension/Core/Type/MoneyType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/MoneyType.php";}s:57:"Symfony/Component/Form/Extension/Core/Type/NumberType.php";a:4:{s:6:"md5sum";s:32:"e5cd61198e2bc26e98d427ab26238c29";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/NumberType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/NumberType.php";}s:59:"Symfony/Component/Form/Extension/Core/Type/PasswordType.php";a:4:{s:6:"md5sum";s:32:"e404fb615ce73dc63a1849d3debb800a";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/PasswordType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/PasswordType.php";}s:58:"Symfony/Component/Form/Extension/Core/Type/PercentType.php";a:4:{s:6:"md5sum";s:32:"1049fece490815d0886c3ddff2bae892";s:4:"name";s:58:"Symfony/Component/Form/Extension/Core/Type/PercentType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/PercentType.php";}s:56:"Symfony/Component/Form/Extension/Core/Type/RadioType.php";a:4:{s:6:"md5sum";s:32:"90fba868b14c878176ada892065394bf";s:4:"name";s:56:"Symfony/Component/Form/Extension/Core/Type/RadioType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/RadioType.php";}s:59:"Symfony/Component/Form/Extension/Core/Type/RepeatedType.php";a:4:{s:6:"md5sum";s:32:"f87bd813801d2d880e905cdd0ffa57da";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/RepeatedType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php";}s:56:"Symfony/Component/Form/Extension/Core/Type/ResetType.php";a:4:{s:6:"md5sum";s:32:"c4df569621c1f85389b7c7cbf789bf63";s:4:"name";s:56:"Symfony/Component/Form/Extension/Core/Type/ResetType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/ResetType.php";}s:57:"Symfony/Component/Form/Extension/Core/Type/SearchType.php";a:4:{s:6:"md5sum";s:32:"a6b0608cb9f219f8a8c192f64f141335";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/SearchType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/SearchType.php";}s:57:"Symfony/Component/Form/Extension/Core/Type/SubmitType.php";a:4:{s:6:"md5sum";s:32:"d689ab8ea2da255a67b7d2140af1627b";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/Type/SubmitType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/SubmitType.php";}s:59:"Symfony/Component/Form/Extension/Core/Type/TextareaType.php";a:4:{s:6:"md5sum";s:32:"02627d9175c745247f7e59cf1c2d4562";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/TextareaType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/TextareaType.php";}s:55:"Symfony/Component/Form/Extension/Core/Type/TextType.php";a:4:{s:6:"md5sum";s:32:"79f868ef2b8c73154789fcaa591f8467";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/TextType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/TextType.php";}s:55:"Symfony/Component/Form/Extension/Core/Type/TimeType.php";a:4:{s:6:"md5sum";s:32:"993e6cee3429a18fabdc70f0a67c7d57";s:4:"name";s:55:"Symfony/Component/Form/Extension/Core/Type/TimeType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/TimeType.php";}s:59:"Symfony/Component/Form/Extension/Core/Type/TimezoneType.php";a:4:{s:6:"md5sum";s:32:"f5607e197c52e096bf060d259aef4079";s:4:"name";s:59:"Symfony/Component/Form/Extension/Core/Type/TimezoneType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php";}s:54:"Symfony/Component/Form/Extension/Core/Type/UrlType.php";a:4:{s:6:"md5sum";s:32:"38ac4b65d20ba774f1421dfd2acd3193";s:4:"name";s:54:"Symfony/Component/Form/Extension/Core/Type/UrlType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type/UrlType.php";}s:57:"Symfony/Component/Form/Extension/Core/View/ChoiceView.php";a:4:{s:6:"md5sum";s:32:"faafdc84e0bfdcd503be96fcb730c4c0";s:4:"name";s:57:"Symfony/Component/Form/Extension/Core/View/ChoiceView.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/View/ChoiceView.php";}s:55:"Symfony/Component/Form/Extension/Csrf/CsrfExtension.php";a:4:{s:6:"md5sum";s:32:"75199e400bebc4583e278a7b24e96833";s:4:"name";s:55:"Symfony/Component/Form/Extension/Csrf/CsrfExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php";}s:74:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php";a:4:{s:6:"md5sum";s:32:"3a1592bafaa9d2402bb6806fd1ac3e9d";s:4:"name";s:74:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php";}s:76:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php";a:4:{s:6:"md5sum";s:32:"e86115910210dec2676aeb707cb5acf0";s:4:"name";s:76:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php";}s:78:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.php";a:4:{s:6:"md5sum";s:32:"db64afcb25c6806ce15828e6ac8c790e";s:4:"name";s:78:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.php";}s:74:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php";a:4:{s:6:"md5sum";s:32:"a1f980527cf2cec99b44eaa1a09e0d4f";s:4:"name";s:74:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php";}s:74:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php";a:4:{s:6:"md5sum";s:32:"c939632d9abebe20853bc59ce816b457";s:4:"name";s:74:"Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php";}s:78:"Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php";a:4:{s:6:"md5sum";s:32:"c17a0b6ad7348188b47da6647b50cc82";s:4:"name";s:78:"Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php";}s:68:"Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php";a:4:{s:6:"md5sum";s:32:"0de14d86a9825500a9b8a71025542c1b";s:4:"name";s:68:"Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php";}s:73:"Symfony/Component/Form/Extension/DataCollector/DataCollectorExtension.php";a:4:{s:6:"md5sum";s:32:"5c5494c1d8bb041b3b938f53a48bb1a1";s:4:"name";s:73:"Symfony/Component/Form/Extension/DataCollector/DataCollectorExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/DataCollectorExtension.php";}s:86:"Symfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.php";a:4:{s:6:"md5sum";s:32:"1419e5bb5008ecb2d6d757bd7023fda8";s:4:"name";s:86:"Symfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/EventListener/DataCollectorListener.php";}s:68:"Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php";a:4:{s:6:"md5sum";s:32:"fdf324521978ceec4f561d76770a08d2";s:4:"name";s:68:"Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php";}s:77:"Symfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.php";a:4:{s:6:"md5sum";s:32:"8e33ae446484b221f1a8f43b96689a9a";s:4:"name";s:77:"Symfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/FormDataCollectorInterface.php";}s:68:"Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php";a:4:{s:6:"md5sum";s:32:"c6dbee88cf57973284f2deb8b7d62266";s:4:"name";s:68:"Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php";}s:77:"Symfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.php";a:4:{s:6:"md5sum";s:32:"e0250a5d7bb1e0c5022cc5bead2126dc";s:4:"name";s:77:"Symfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/FormDataExtractorInterface.php";}s:87:"Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php";a:4:{s:6:"md5sum";s:32:"1d3278f320b0fc626c80ff21d4e4d798";s:4:"name";s:87:"Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php";}s:94:"Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php";a:4:{s:6:"md5sum";s:32:"7acc20404d7bc268d80bd71d29b2c0da";s:4:"name";s:94:"Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php";s:4:"role";s:3:"php";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php";}s:82:"Symfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.php";a:4:{s:6:"md5sum";s:32:"384aa6433ffc18edb15519d550103ca1";s:4:"name";s:82:"Symfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/Type/DataCollectorTypeExtension.php";}s:85:"Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.php";a:4:{s:6:"md5sum";s:32:"7284275881ceb92b987717feedba8057";s:4:"name";s:85:"Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.php";}s:85:"Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.php";a:4:{s:6:"md5sum";s:32:"6a452e346dc11c0a574bc2fbea9be01c";s:4:"name";s:85:"Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.php";}s:75:"Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.php";a:4:{s:6:"md5sum";s:32:"bd10d86a58c151a1d8d2e072dc379389";s:4:"name";s:75:"Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.php";}s:80:"Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php";a:4:{s:6:"md5sum";s:32:"1a1be6feca390ce87d232e08008b4059";s:4:"name";s:80:"Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php";}s:88:"Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php";a:4:{s:6:"md5sum";s:32:"1cbed6494abb39f8a2731ff28bfc3b4f";s:4:"name";s:88:"Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php";}s:67:"Symfony/Component/Form/Extension/Templating/TemplatingExtension.php";a:4:{s:6:"md5sum";s:32:"c2ab352ab8da8a95d82c561e8d014708";s:4:"name";s:67:"Symfony/Component/Form/Extension/Templating/TemplatingExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Templating/TemplatingExtension.php";}s:72:"Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.php";a:4:{s:6:"md5sum";s:32:"9b88d4aa06ab3e8e0f4882d2790814fc";s:4:"name";s:72:"Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.php";}s:63:"Symfony/Component/Form/Extension/Validator/Constraints/Form.php";a:4:{s:6:"md5sum";s:32:"0024bfd2c88595778a825805a64dad44";s:4:"name";s:63:"Symfony/Component/Form/Extension/Validator/Constraints/Form.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Constraints/Form.php";}s:72:"Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php";a:4:{s:6:"md5sum";s:32:"7c71a0cb31da31a0222bdab4b7b926c7";s:4:"name";s:72:"Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php";}s:79:"Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php";a:4:{s:6:"md5sum";s:32:"26384c9335607d3a7a760ce64268a5d1";s:4:"name";s:79:"Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php";}s:74:"Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.php";a:4:{s:6:"md5sum";s:32:"cbb86a1f46d4153ee8b6dcec13f3e3b3";s:4:"name";s:74:"Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.php";}s:78:"Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php";a:4:{s:6:"md5sum";s:32:"df9d49f2923e93c8a989badebd46d72b";s:4:"name";s:78:"Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php";}s:82:"Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php";a:4:{s:6:"md5sum";s:32:"3ee7f3c2ca05510b1e6f5ea736de843d";s:4:"name";s:82:"Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php";}s:80:"Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.php";a:4:{s:6:"md5sum";s:32:"ec1709e56bdc7ba193f1d204a1645348";s:4:"name";s:80:"Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.php";}s:64:"Symfony/Component/Form/Extension/Validator/Util/ServerParams.php";a:4:{s:6:"md5sum";s:32:"6c0183dc4aa13461ba80a4b13bb6af0c";s:4:"name";s:64:"Symfony/Component/Form/Extension/Validator/Util/ServerParams.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Util/ServerParams.php";}s:65:"Symfony/Component/Form/Extension/Validator/ValidatorExtension.php";a:4:{s:6:"md5sum";s:32:"29479a50cbaa64713f9746a047bffd00";s:4:"name";s:65:"Symfony/Component/Form/Extension/Validator/ValidatorExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php";}s:67:"Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php";a:4:{s:6:"md5sum";s:32:"7c15728df791933679ae099b2dc013ce";s:4:"name";s:67:"Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php";}s:74:"Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php";a:4:{s:6:"md5sum";s:32:"accd5b53d71708b247e3f8c6060b8441";s:4:"name";s:74:"Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.php";}s:75:"Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.php";a:4:{s:6:"md5sum";s:32:"da806398ec8fc4c452e1eadda5c74a68";s:4:"name";s:75:"Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.php";}s:78:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php";a:4:{s:6:"md5sum";s:32:"61357f9417507d405f7fb1fb659b31d2";s:4:"name";s:78:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php";}s:87:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php";a:4:{s:6:"md5sum";s:32:"10303cd4370ce781654acabee5f88bab";s:4:"name";s:87:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php";}s:76:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php";a:4:{s:6:"md5sum";s:32:"ccc9fe0cfc8d2d1f0daabc141e920038";s:4:"name";s:76:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php";}s:84:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.php";a:4:{s:6:"md5sum";s:32:"c66988f503a7a69b3332463374596ba3";s:4:"name";s:84:"Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.php";}s:31:"Symfony/Component/Form/Form.php";a:4:{s:6:"md5sum";s:32:"563c1163b71c3c482d91bf4877746632";s:4:"name";s:31:"Symfony/Component/Form/Form.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Form.php";}s:38:"Symfony/Component/Form/FormBuilder.php";a:4:{s:6:"md5sum";s:32:"cca285ed5e381d817d56181ec219df0d";s:4:"name";s:38:"Symfony/Component/Form/FormBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormBuilder.php";}s:47:"Symfony/Component/Form/FormBuilderInterface.php";a:4:{s:6:"md5sum";s:32:"9b5471bc4369497cf6ffd6e159a023ec";s:4:"name";s:47:"Symfony/Component/Form/FormBuilderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormBuilderInterface.php";}s:44:"Symfony/Component/Form/FormConfigBuilder.php";a:4:{s:6:"md5sum";s:32:"f478ae74fe1813693e1ba4e969d62410";s:4:"name";s:44:"Symfony/Component/Form/FormConfigBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormConfigBuilder.php";}s:53:"Symfony/Component/Form/FormConfigBuilderInterface.php";a:4:{s:6:"md5sum";s:32:"6a46ac7e9313965ec6b1b95328f346a0";s:4:"name";s:53:"Symfony/Component/Form/FormConfigBuilderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormConfigBuilderInterface.php";}s:46:"Symfony/Component/Form/FormConfigInterface.php";a:4:{s:6:"md5sum";s:32:"0b0436e232cf7100a1ed02dc299cf7a2";s:4:"name";s:46:"Symfony/Component/Form/FormConfigInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormConfigInterface.php";}s:36:"Symfony/Component/Form/FormError.php";a:4:{s:6:"md5sum";s:32:"d77ce9907675beaf81a3065d1ecfd69c";s:4:"name";s:36:"Symfony/Component/Form/FormError.php";s:4:"role";s:3:"php";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormError.php";}s:36:"Symfony/Component/Form/FormEvent.php";a:4:{s:6:"md5sum";s:32:"99268e4eaad4680f7e037cc00b31b370";s:4:"name";s:36:"Symfony/Component/Form/FormEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormEvent.php";}s:37:"Symfony/Component/Form/FormEvents.php";a:4:{s:6:"md5sum";s:32:"e6d2f1d5c2986877bb25ed96014d3495";s:4:"name";s:37:"Symfony/Component/Form/FormEvents.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormEvents.php";}s:49:"Symfony/Component/Form/FormExtensionInterface.php";a:4:{s:6:"md5sum";s:32:"396ae86cdd76d116832ba1f3b1ac5b73";s:4:"name";s:49:"Symfony/Component/Form/FormExtensionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormExtensionInterface.php";}s:38:"Symfony/Component/Form/FormFactory.php";a:4:{s:6:"md5sum";s:32:"014013a6a76da3c380b12e79fd5895e5";s:4:"name";s:38:"Symfony/Component/Form/FormFactory.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormFactory.php";}s:45:"Symfony/Component/Form/FormFactoryBuilder.php";a:4:{s:6:"md5sum";s:32:"b3f8c61b5ff170f0982a10bfa3f449ad";s:4:"name";s:45:"Symfony/Component/Form/FormFactoryBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormFactoryBuilder.php";}s:54:"Symfony/Component/Form/FormFactoryBuilderInterface.php";a:4:{s:6:"md5sum";s:32:"1b58cdcfa7fe5eb921b37c73a4cc8ead";s:4:"name";s:54:"Symfony/Component/Form/FormFactoryBuilderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormFactoryBuilderInterface.php";}s:47:"Symfony/Component/Form/FormFactoryInterface.php";a:4:{s:6:"md5sum";s:32:"8f8a65e4ffe1ee2ac9165f41ff0defc0";s:4:"name";s:47:"Symfony/Component/Form/FormFactoryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormFactoryInterface.php";}s:40:"Symfony/Component/Form/FormInterface.php";a:4:{s:6:"md5sum";s:32:"bd326b430aabb6ae67bfdd63ac3a0cff";s:4:"name";s:40:"Symfony/Component/Form/FormInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormInterface.php";}s:39:"Symfony/Component/Form/FormRegistry.php";a:4:{s:6:"md5sum";s:32:"c017bb0aca3d2dc54133014309b994ca";s:4:"name";s:39:"Symfony/Component/Form/FormRegistry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormRegistry.php";}s:48:"Symfony/Component/Form/FormRegistryInterface.php";a:4:{s:6:"md5sum";s:32:"ea9fc8c340f5d63126abf4741716bf0a";s:4:"name";s:48:"Symfony/Component/Form/FormRegistryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormRegistryInterface.php";}s:39:"Symfony/Component/Form/FormRenderer.php";a:4:{s:6:"md5sum";s:32:"eed8b18f01216d190cf317392856361d";s:4:"name";s:39:"Symfony/Component/Form/FormRenderer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormRenderer.php";}s:54:"Symfony/Component/Form/FormRendererEngineInterface.php";a:4:{s:6:"md5sum";s:32:"4a12fb78c610af0b5f391e272fcb458b";s:4:"name";s:54:"Symfony/Component/Form/FormRendererEngineInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormRendererEngineInterface.php";}s:48:"Symfony/Component/Form/FormRendererInterface.php";a:4:{s:6:"md5sum";s:32:"514aae640601bd2af792d2f280ad1d19";s:4:"name";s:48:"Symfony/Component/Form/FormRendererInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormRendererInterface.php";}s:32:"Symfony/Component/Form/Forms.php";a:4:{s:6:"md5sum";s:32:"9f253cdb5bd655feaa2ba9387c6cf0ad";s:4:"name";s:32:"Symfony/Component/Form/Forms.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Forms.php";}s:53:"Symfony/Component/Form/FormTypeExtensionInterface.php";a:4:{s:6:"md5sum";s:32:"76847e41a7fc0945726fd7b00ddd9540";s:4:"name";s:53:"Symfony/Component/Form/FormTypeExtensionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormTypeExtensionInterface.php";}s:47:"Symfony/Component/Form/FormTypeGuesserChain.php";a:4:{s:6:"md5sum";s:32:"d5097ac9bb6503026cda5c54c7106965";s:4:"name";s:47:"Symfony/Component/Form/FormTypeGuesserChain.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormTypeGuesserChain.php";}s:51:"Symfony/Component/Form/FormTypeGuesserInterface.php";a:4:{s:6:"md5sum";s:32:"0fb144de45b5135b11815452309bc75f";s:4:"name";s:51:"Symfony/Component/Form/FormTypeGuesserInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormTypeGuesserInterface.php";}s:44:"Symfony/Component/Form/FormTypeInterface.php";a:4:{s:6:"md5sum";s:32:"bbab1badee901017917edff90e58f2c1";s:4:"name";s:44:"Symfony/Component/Form/FormTypeInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormTypeInterface.php";}s:35:"Symfony/Component/Form/FormView.php";a:4:{s:6:"md5sum";s:32:"68bdf09c1c46788c5e90ada37f78d540";s:4:"name";s:35:"Symfony/Component/Form/FormView.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/FormView.php";}s:38:"Symfony/Component/Form/Guess/Guess.php";a:4:{s:6:"md5sum";s:32:"7003fc846b738bbd923fa5656e22d95b";s:4:"name";s:38:"Symfony/Component/Form/Guess/Guess.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Guess/Guess.php";}s:42:"Symfony/Component/Form/Guess/TypeGuess.php";a:4:{s:6:"md5sum";s:32:"0fedff65f9ab6dfc490a9b469192b0a6";s:4:"name";s:42:"Symfony/Component/Form/Guess/TypeGuess.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Guess/TypeGuess.php";}s:43:"Symfony/Component/Form/Guess/ValueGuess.php";a:4:{s:6:"md5sum";s:32:"fc080890a68c7a2e9f145556cfa0b6d3";s:4:"name";s:43:"Symfony/Component/Form/Guess/ValueGuess.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Guess/ValueGuess.php";}s:30:"Symfony/Component/Form/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:30:"Symfony/Component/Form/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/doc/pear/Form/Symfony/Component/Form/LICENSE";}s:47:"Symfony/Component/Form/NativeRequestHandler.php";a:4:{s:6:"md5sum";s:32:"165b5d30323c31b5a70be0d4ed584fde";s:4:"name";s:47:"Symfony/Component/Form/NativeRequestHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/NativeRequestHandler.php";}s:39:"Symfony/Component/Form/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"66ef84fb360f766ab10567f114268e0f";s:4:"name";s:39:"Symfony/Component/Form/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/phpunit.xml.dist";}s:45:"Symfony/Component/Form/PreloadedExtension.php";a:4:{s:6:"md5sum";s:32:"ab4eca434dd1f8ac7df3666e1ed1b7df";s:4:"name";s:45:"Symfony/Component/Form/PreloadedExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/PreloadedExtension.php";}s:32:"Symfony/Component/Form/README.md";a:4:{s:6:"md5sum";s:32:"ebe5a2b970601e8bd9149d2c8dd1d3d1";s:4:"name";s:32:"Symfony/Component/Form/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/doc/pear/Form/Symfony/Component/Form/README.md";}s:50:"Symfony/Component/Form/RequestHandlerInterface.php";a:4:{s:6:"md5sum";s:32:"e16c038acbd7b2c01bcb48c7f40e728d";s:4:"name";s:50:"Symfony/Component/Form/RequestHandlerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/RequestHandlerInterface.php";}s:43:"Symfony/Component/Form/ResolvedFormType.php";a:4:{s:6:"md5sum";s:32:"0a3c5437610d92506335292ad7b6abf9";s:4:"name";s:43:"Symfony/Component/Form/ResolvedFormType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/ResolvedFormType.php";}s:50:"Symfony/Component/Form/ResolvedFormTypeFactory.php";a:4:{s:6:"md5sum";s:32:"5d25fc04121ed5f6e428165f5936c10f";s:4:"name";s:50:"Symfony/Component/Form/ResolvedFormTypeFactory.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/ResolvedFormTypeFactory.php";}s:59:"Symfony/Component/Form/ResolvedFormTypeFactoryInterface.php";a:4:{s:6:"md5sum";s:32:"fa408445a6fab81659c0cefed09bf3df";s:4:"name";s:59:"Symfony/Component/Form/ResolvedFormTypeFactoryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/ResolvedFormTypeFactoryInterface.php";}s:52:"Symfony/Component/Form/ResolvedFormTypeInterface.php";a:4:{s:6:"md5sum";s:32:"b8c1edc5a2b254bdde6476893b156950";s:4:"name";s:52:"Symfony/Component/Form/ResolvedFormTypeInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/ResolvedFormTypeInterface.php";}s:54:"Symfony/Component/Form/Resources/config/validation.xml";a:4:{s:6:"md5sum";s:32:"256dafb4fae5e462d55a71ab388c0691";s:4:"name";s:54:"Symfony/Component/Form/Resources/config/validation.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/config/validation.xml";}s:63:"Symfony/Component/Form/Resources/translations/validators.ar.xlf";a:4:{s:6:"md5sum";s:32:"e0ad0b923b6ac791b49b9a4d33af7a25";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ar.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.ar.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.bg.xlf";a:4:{s:6:"md5sum";s:32:"1d5e19ca06d1aa8293b5887092685e05";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.bg.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.bg.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.ca.xlf";a:4:{s:6:"md5sum";s:32:"c7ad1d90ad05603286ab378d72608d01";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ca.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.ca.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.cs.xlf";a:4:{s:6:"md5sum";s:32:"2b0bed4fc587230bd11e83b7bbe29339";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.cs.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.cs.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.da.xlf";a:4:{s:6:"md5sum";s:32:"e46f7c3da02bcd4fa8c379469310c217";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.da.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.da.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.de.xlf";a:4:{s:6:"md5sum";s:32:"921a3c43eb6bf008f7d4ae7d2e56233f";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.de.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.de.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.el.xlf";a:4:{s:6:"md5sum";s:32:"a7470225a9c04a5c2b5f179d8060c38b";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.el.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.el.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.en.xlf";a:4:{s:6:"md5sum";s:32:"8f7759249199e5589331c432c54c9197";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.en.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.en.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.es.xlf";a:4:{s:6:"md5sum";s:32:"b086ea186d7babe85d8bfa78957acea4";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.es.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.es.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.et.xlf";a:4:{s:6:"md5sum";s:32:"f81867f4f9fd2362db42befa9628c103";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.et.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.et.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.eu.xlf";a:4:{s:6:"md5sum";s:32:"0ae3f2a05c0e69cc63ef84384913a4fe";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.eu.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.eu.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.fa.xlf";a:4:{s:6:"md5sum";s:32:"321b2f3f5ac56ff0c81871b44fe369bd";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.fa.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.fa.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.fi.xlf";a:4:{s:6:"md5sum";s:32:"8cbad436ab4b1d574690992f15e37397";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.fi.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.fi.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.fr.xlf";a:4:{s:6:"md5sum";s:32:"8bfa3368c7beefedc897f3098744e5dd";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.fr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.fr.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.gl.xlf";a:4:{s:6:"md5sum";s:32:"b21174a0425a56615ac95065c4cd4f8f";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.gl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.gl.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.he.xlf";a:4:{s:6:"md5sum";s:32:"f03c3342827959500fe8bca223400225";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.he.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.he.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.hr.xlf";a:4:{s:6:"md5sum";s:32:"3b87096c3cc16d9580d15fe9a9ca4d70";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.hr.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.hr.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.hu.xlf";a:4:{s:6:"md5sum";s:32:"c538c1a55b060abb01cc1795a650ff36";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.hu.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.hu.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.hy.xlf";a:4:{s:6:"md5sum";s:32:"d7f271b6e610fa47ae614cd9d92f7c02";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.hy.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.hy.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.id.xlf";a:4:{s:6:"md5sum";s:32:"313e2438c2476b78ab637cd9dcd5322d";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.id.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.id.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.it.xlf";a:4:{s:6:"md5sum";s:32:"3fa13f3254812a6857a99351cf6003d8";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.it.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.it.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.ja.xlf";a:4:{s:6:"md5sum";s:32:"3f47d2db87b7262c21c8287472719479";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ja.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.ja.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.lb.xlf";a:4:{s:6:"md5sum";s:32:"f25583830baaccc529f6b4f0a845bd61";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.lb.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.lb.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.lt.xlf";a:4:{s:6:"md5sum";s:32:"4ef7ab23ce55458844742317d905fa59";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.lt.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.lt.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.lv.xlf";a:4:{s:6:"md5sum";s:32:"1cc55c8d2fb6eb1583b2d2cdfd54152e";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.lv.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.lv.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.mn.xlf";a:4:{s:6:"md5sum";s:32:"4429ebdbb00601c0c67f43a06c4e8031";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.mn.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.mn.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.nb.xlf";a:4:{s:6:"md5sum";s:32:"017afa511ee2a18bddbbac0640cdb685";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.nb.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.nb.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.nl.xlf";a:4:{s:6:"md5sum";s:32:"94858839db1d8f8324759bf5e87c129d";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.nl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.nl.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.pl.xlf";a:4:{s:6:"md5sum";s:32:"c72a6e8c5c9dc76b0a9ceb275486acb3";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.pl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.pl.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.pt.xlf";a:4:{s:6:"md5sum";s:32:"bfda187791c843558b3bcc5327064e43";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.pt.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.pt.xlf";}s:66:"Symfony/Component/Form/Resources/translations/validators.pt_BR.xlf";a:4:{s:6:"md5sum";s:32:"7cb1b50669945643c707acee4b13cf31";s:4:"name";s:66:"Symfony/Component/Form/Resources/translations/validators.pt_BR.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.pt_BR.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.ro.xlf";a:4:{s:6:"md5sum";s:32:"f2eaf2e4ba82e742cb6dff54c69f1271";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ro.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.ro.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.ru.xlf";a:4:{s:6:"md5sum";s:32:"6cbccc04ebb3a58158041e451c3bc536";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.ru.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.ru.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.sk.xlf";a:4:{s:6:"md5sum";s:32:"d2e6bd911ddff3c7b526755179cf6ed9";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.sk.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.sk.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.sl.xlf";a:4:{s:6:"md5sum";s:32:"cc42fc67ec1729fe317cd3b1c3b96dd6";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.sl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.sl.xlf";}s:68:"Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlf";a:4:{s:6:"md5sum";s:32:"20e303068da12f5f5248ace8162051ad";s:4:"name";s:68:"Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlf";}s:68:"Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlf";a:4:{s:6:"md5sum";s:32:"bdf4d302afd0b1b1b406009402b44f7d";s:4:"name";s:68:"Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.sr_Latn.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.sv.xlf";a:4:{s:6:"md5sum";s:32:"642c23a8173bfd547a71b69a694195f0";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.sv.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.sv.xlf";}s:63:"Symfony/Component/Form/Resources/translations/validators.uk.xlf";a:4:{s:6:"md5sum";s:32:"6c03831d89108e565c8358f46d807e32";s:4:"name";s:63:"Symfony/Component/Form/Resources/translations/validators.uk.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.uk.xlf";}s:66:"Symfony/Component/Form/Resources/translations/validators.zh_CN.xlf";a:4:{s:6:"md5sum";s:32:"96cbd8686b821bd2cf91839a6c26cc03";s:4:"name";s:66:"Symfony/Component/Form/Resources/translations/validators.zh_CN.xlf";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations/validators.zh_CN.xlf";}s:46:"Symfony/Component/Form/ReversedTransformer.php";a:4:{s:6:"md5sum";s:32:"658dff714ce275350a7f720a86484e55";s:4:"name";s:46:"Symfony/Component/Form/ReversedTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/ReversedTransformer.php";}s:39:"Symfony/Component/Form/SubmitButton.php";a:4:{s:6:"md5sum";s:32:"3fb340157282afcc9223daeab2aeb49f";s:4:"name";s:39:"Symfony/Component/Form/SubmitButton.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/SubmitButton.php";}s:46:"Symfony/Component/Form/SubmitButtonBuilder.php";a:4:{s:6:"md5sum";s:32:"09ee4f0e6ffe3b36ab57c806045f69d3";s:4:"name";s:46:"Symfony/Component/Form/SubmitButtonBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/SubmitButtonBuilder.php";}s:52:"Symfony/Component/Form/SubmitButtonTypeInterface.php";a:4:{s:6:"md5sum";s:32:"721a1bd36d3a0cd93e5c57956435f861";s:4:"name";s:52:"Symfony/Component/Form/SubmitButtonTypeInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/SubmitButtonTypeInterface.php";}s:55:"Symfony/Component/Form/Test/DeprecationErrorHandler.php";a:4:{s:6:"md5sum";s:32:"70d8401563ddaeefe2982c73218d9a41";s:4:"name";s:55:"Symfony/Component/Form/Test/DeprecationErrorHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Test/DeprecationErrorHandler.php";}s:52:"Symfony/Component/Form/Test/FormBuilderInterface.php";a:4:{s:6:"md5sum";s:32:"1847328f5ba757c0997121ed38fe9d61";s:4:"name";s:52:"Symfony/Component/Form/Test/FormBuilderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Test/FormBuilderInterface.php";}s:55:"Symfony/Component/Form/Test/FormIntegrationTestCase.php";a:4:{s:6:"md5sum";s:32:"8dc56ae07547e6e8a521cb9d68ff7499";s:4:"name";s:55:"Symfony/Component/Form/Test/FormIntegrationTestCase.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Test/FormIntegrationTestCase.php";}s:45:"Symfony/Component/Form/Test/FormInterface.php";a:4:{s:6:"md5sum";s:32:"ba89cda1179d1dbc7ae395c4f165f458";s:4:"name";s:45:"Symfony/Component/Form/Test/FormInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Test/FormInterface.php";}s:55:"Symfony/Component/Form/Test/FormPerformanceTestCase.php";a:4:{s:6:"md5sum";s:32:"f8d472cfeb2fb094a9fed0a0e31e5900";s:4:"name";s:55:"Symfony/Component/Form/Test/FormPerformanceTestCase.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Test/FormPerformanceTestCase.php";}s:44:"Symfony/Component/Form/Test/TypeTestCase.php";a:4:{s:6:"md5sum";s:32:"a14b6e8fcfd683fcf7498f9a02da523d";s:4:"name";s:44:"Symfony/Component/Form/Test/TypeTestCase.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Test/TypeTestCase.php";}s:54:"Symfony/Component/Form/Tests/AbstractDivLayoutTest.php";a:4:{s:6:"md5sum";s:32:"01e6c9a75c6347c2c215d6a15b0c79d5";s:4:"name";s:54:"Symfony/Component/Form/Tests/AbstractDivLayoutTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php";}s:54:"Symfony/Component/Form/Tests/AbstractExtensionTest.php";a:4:{s:6:"md5sum";s:32:"993f833ed9fb277ec6f3a74a773d92ae";s:4:"name";s:54:"Symfony/Component/Form/Tests/AbstractExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/AbstractExtensionTest.php";}s:49:"Symfony/Component/Form/Tests/AbstractFormTest.php";a:4:{s:6:"md5sum";s:32:"25108525cdb98b2c542d79ef69a08970";s:4:"name";s:49:"Symfony/Component/Form/Tests/AbstractFormTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/AbstractFormTest.php";}s:51:"Symfony/Component/Form/Tests/AbstractLayoutTest.php";a:4:{s:6:"md5sum";s:32:"5def14944ef79b573b5bd008ab84ca4b";s:4:"name";s:51:"Symfony/Component/Form/Tests/AbstractLayoutTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/AbstractLayoutTest.php";}s:59:"Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php";a:4:{s:6:"md5sum";s:32:"1e1eaca7aca8b88c93cd99d5d934dc12";s:4:"name";s:59:"Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php";}s:56:"Symfony/Component/Form/Tests/AbstractTableLayoutTest.php";a:4:{s:6:"md5sum";s:32:"f18c692af6dbc9682b8fbfae88d5909c";s:4:"name";s:56:"Symfony/Component/Form/Tests/AbstractTableLayoutTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php";}s:60:"Symfony/Component/Form/Tests/CompoundFormPerformanceTest.php";a:4:{s:6:"md5sum";s:32:"487f6d057728873fdbda43c763ad9a3c";s:4:"name";s:60:"Symfony/Component/Form/Tests/CompoundFormPerformanceTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.php";}s:49:"Symfony/Component/Form/Tests/CompoundFormTest.php";a:4:{s:6:"md5sum";s:32:"3e01bd80c478bfef4e94cce5b05b810f";s:4:"name";s:49:"Symfony/Component/Form/Tests/CompoundFormTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/CompoundFormTest.php";}s:81:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php";a:4:{s:6:"md5sum";s:32:"805f66672b74f69ef369360000ce28d7";s:4:"name";s:81:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php";}s:73:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.php";a:4:{s:6:"md5sum";s:32:"0eb2d36957cb3f06b8246cf4d62845e6";s:4:"name";s:73:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.php";}s:77:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php";a:4:{s:6:"md5sum";s:32:"4fe2229f0a5ccdfed66591f926d1408a";s:4:"name";s:77:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php";}s:79:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php";a:4:{s:6:"md5sum";s:32:"9438557f7e55048a10c0da6dc9b5b7d5";s:4:"name";s:79:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php";}s:79:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php";a:4:{s:6:"md5sum";s:32:"c887b01a87b147202efc194dd37f5654";s:4:"name";s:79:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php";}s:86:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php";a:4:{s:6:"md5sum";s:32:"de020dd5c1bfe761abc83eb0d407b93b";s:4:"name";s:86:"Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php";}s:81:"Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php";a:4:{s:6:"md5sum";s:32:"9b3671899963fbd7e534be6a316b9f7f";s:4:"name";s:81:"Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php";}s:91:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php";a:4:{s:6:"md5sum";s:32:"fe5c56d887d5e3c625a29d58f19f14b2";s:4:"name";s:91:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php";}s:91:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.php";a:4:{s:6:"md5sum";s:32:"1f0f17c4989a4bf7e663524addd19377";s:4:"name";s:91:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.php";}s:94:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php";a:4:{s:6:"md5sum";s:32:"2656ea40e07d5722e5afae535a14c6f2";s:4:"name";s:94:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php";}s:94:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php";a:4:{s:6:"md5sum";s:32:"f10f920c63a846fee23f895f6519b30c";s:4:"name";s:94:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php";}s:92:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php";a:4:{s:6:"md5sum";s:32:"81b526febe066ae1212cf792e057a858";s:4:"name";s:92:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:132:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php";}s:88:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php";a:4:{s:6:"md5sum";s:32:"d391c39a885af56bbe963d2884ce1581";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php";}s:80:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php";a:4:{s:6:"md5sum";s:32:"2a0a01ad1cc0ede0f9a9610be868290e";s:4:"name";s:80:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php";}s:94:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php";a:4:{s:6:"md5sum";s:32:"c333df3e9adfbd0151953a318603b358";s:4:"name";s:94:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php";}s:104:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php";a:4:{s:6:"md5sum";s:32:"cff66917b58654868071c9ee011e36fa";s:4:"name";s:104:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:144:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php";}s:96:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php";a:4:{s:6:"md5sum";s:32:"ca35365fd4c7e312165063c8754a9545";s:4:"name";s:96:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php";}s:95:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php";a:4:{s:6:"md5sum";s:32:"eccc79ef623e695d17510a7c1537a88d";s:4:"name";s:95:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php";}s:98:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php";a:4:{s:6:"md5sum";s:32:"e5ee536591d17b7bfe89945a498724ec";s:4:"name";s:98:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:138:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php";}s:103:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php";a:4:{s:6:"md5sum";s:32:"0eac0ca2189eaf93a9fdaa18c2bfce45";s:4:"name";s:103:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:143:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php";}s:101:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php";a:4:{s:6:"md5sum";s:32:"74344e0d818fb775d511fea0ee331e96";s:4:"name";s:101:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:141:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php";}s:102:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php";a:4:{s:6:"md5sum";s:32:"c7f0520009e30903c4b681d8038d1116";s:4:"name";s:102:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:142:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php";}s:103:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php";a:4:{s:6:"md5sum";s:32:"3f3ac246acda56e18c45ede2ad738de5";s:4:"name";s:103:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:143:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php";}s:96:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php";a:4:{s:6:"md5sum";s:32:"340da808904f9f817f6bb74c6d1d1bae";s:4:"name";s:96:"Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php";}s:87:"Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php";a:4:{s:6:"md5sum";s:32:"47864719339897429512947960cec29e";s:4:"name";s:87:"Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php";}s:77:"Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhash";a:4:{s:6:"md5sum";s:32:"87aec5a94c94ec7a5dd1c0839eb0182b";s:4:"name";s:77:"Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhash";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhash";}s:88:"Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php";a:4:{s:6:"md5sum";s:32:"6cb15bfda3938a694ba12e947582ee1c";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php";}s:100:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php";a:4:{s:6:"md5sum";s:32:"e0bc897a2bcb5584079604cd7a932c4a";s:4:"name";s:100:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:140:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php";}s:94:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php";a:4:{s:6:"md5sum";s:32:"541c2ff8d9b47ce17ab79a9f5c7da315";s:4:"name";s:94:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php";}s:106:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php";a:4:{s:6:"md5sum";s:32:"3b4d97e836cfe76c4b348b38ef0d3199";s:4:"name";s:106:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:146:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php";}s:89:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php";a:4:{s:6:"md5sum";s:32:"6cb07a92e893ccd4ddf1f93592d0ea12";s:4:"name";s:89:"Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:129:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php";}s:84:"Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php";a:4:{s:6:"md5sum";s:32:"7726c3ab7d9e202ef7e50c6e18a0dc13";s:4:"name";s:84:"Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php";}s:78:"Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php";a:4:{s:6:"md5sum";s:32:"200a4cdc92f0b266f8b46b971fc5ec82";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php";}s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php";a:4:{s:6:"md5sum";s:32:"d6a45bded973053fe2db03fce86a667f";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php";}s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php";a:4:{s:6:"md5sum";s:32:"040223464ae2179f3aa78e84fd7b8511";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php";}s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php";a:4:{s:6:"md5sum";s:32:"951887c57ca144e04ba2f2001fb12a5b";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php";}s:78:"Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php";a:4:{s:6:"md5sum";s:32:"c435893620ce32c2bee017d4b0cb2157";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php";}s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php";a:4:{s:6:"md5sum";s:32:"9e18e82da0bbc8f4370d3f652ed8ad48";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php";}s:71:"Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php";a:4:{s:6:"md5sum";s:32:"643faa42c8a2cfc19880f78bc9d3bb83";s:4:"name";s:71:"Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php";}s:68:"Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php";a:4:{s:6:"md5sum";s:32:"196ba14f11fc05ed0a061a909d71b8cd";s:4:"name";s:68:"Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php";}s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php";a:4:{s:6:"md5sum";s:32:"e2b1c1525d0bf4cf02e807689138ec88";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php";}s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php";a:4:{s:6:"md5sum";s:32:"91b9362007d0d02d7b55852d49a226d2";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php";}s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php";a:4:{s:6:"md5sum";s:32:"42c8e0bc27d5102ce1b9f7d3807c436c";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php";}s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php";a:4:{s:6:"md5sum";s:32:"1bad6779778649a56a6df8ba51ac2442";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php";}s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php";a:4:{s:6:"md5sum";s:32:"6384962d22490e2965944280e6da8dd3";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php";}s:68:"Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php";a:4:{s:6:"md5sum";s:32:"145ac554d44d2416c20efbc33490831b";s:4:"name";s:68:"Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php";}s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php";a:4:{s:6:"md5sum";s:32:"ae9dea4e2cd5149f1469249f0aabe2ac";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php";}s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php";a:4:{s:6:"md5sum";s:32:"b7946ff970129706743ad613161fd929";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php";}s:66:"Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php";a:4:{s:6:"md5sum";s:32:"6bfc500ee59b3c0e85c23e2a4007fc52";s:4:"name";s:66:"Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php";}s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php";a:4:{s:6:"md5sum";s:32:"e680b158e130d104e812bc59a594fa08";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php";}s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.php";a:4:{s:6:"md5sum";s:32:"a683610fb85dd825d4141a4b3f528e46";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.php";}s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php";a:4:{s:6:"md5sum";s:32:"369245a8723921b895a4591ba34005eb";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php";}s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.php";a:4:{s:6:"md5sum";s:32:"fe429eb590a75d6dd3a20bbf08d1e639";s:4:"name";s:67:"Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.php";}s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php";a:4:{s:6:"md5sum";s:32:"1f837469d11ac48ff637e8fa08da7a44";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php";}s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php";a:4:{s:6:"md5sum";s:32:"1082d1f9f4683702300ce6a8be9c835b";s:4:"name";s:69:"Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php";}s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.php";a:4:{s:6:"md5sum";s:32:"e71b97847da4bbd7b694e2a7ea18c7b7";s:4:"name";s:65:"Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.php";}s:64:"Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php";a:4:{s:6:"md5sum";s:32:"1f33d8fa306ebdbad2cf4561557655ca";s:4:"name";s:64:"Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php";}s:84:"Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php";a:4:{s:6:"md5sum";s:32:"d5607097da4e8ba843c7671fc95bd5ed";s:4:"name";s:84:"Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php";}s:84:"Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php";a:4:{s:6:"md5sum";s:32:"b01b266a7196ae1aaaf9b4d3d8f1f2ed";s:4:"name";s:84:"Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php";}s:88:"Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php";a:4:{s:6:"md5sum";s:32:"afcd45b858401261360a30c4cb0f9aba";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php";}s:78:"Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php";a:4:{s:6:"md5sum";s:32:"1ee5764d064d208a058c7719817c5935";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php";}s:83:"Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.php";a:4:{s:6:"md5sum";s:32:"e69912900a62a5bb4c69d9c37ed2952e";s:4:"name";s:83:"Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.php";}s:78:"Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php";a:4:{s:6:"md5sum";s:32:"deaf70e32c29e96b0a0f5de433b99dea";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php";}s:78:"Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.php";a:4:{s:6:"md5sum";s:32:"d12c0ee191323d8ad5e0926d2484ec59";s:4:"name";s:78:"Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.php";}s:92:"Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.php";a:4:{s:6:"md5sum";s:32:"d8948496dc0e6214e740ca00ca529e95";s:4:"name";s:92:"Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:132:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.php";}s:95:"Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php";a:4:{s:6:"md5sum";s:32:"6e2cdd48baa66831a820c785cf96d440";s:4:"name";s:95:"Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php";}s:90:"Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php";a:4:{s:6:"md5sum";s:32:"b2e0f962d2654c7b7bfabeec6feffe3a";s:4:"name";s:90:"Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php";}s:93:"Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php";a:4:{s:6:"md5sum";s:32:"b843b76574f23418997cf5d299e1795d";s:4:"name";s:93:"Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:133:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php";}s:82:"Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php";a:4:{s:6:"md5sum";s:32:"3956a614fe00f61b9df4abd22fb94c77";s:4:"name";s:82:"Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php";}s:89:"Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php";a:4:{s:6:"md5sum";s:32:"159b78c63cad4f5c62977766f6680a69";s:4:"name";s:89:"Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:129:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php";}s:84:"Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php";a:4:{s:6:"md5sum";s:32:"8ca1bca8a4d7d47e6d612d714c3e434d";s:4:"name";s:84:"Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php";}s:88:"Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php";a:4:{s:6:"md5sum";s:32:"68b380257c232e2600d07153905f0d5f";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php";}s:90:"Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php";a:4:{s:6:"md5sum";s:32:"831836b41b079545f0670fe13ce7a212";s:4:"name";s:90:"Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php";}s:70:"Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php";a:4:{s:6:"md5sum";s:32:"49189d46e88a6d3d850c27b162c6e2ce";s:4:"name";s:70:"Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php";}s:74:"Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php";a:4:{s:6:"md5sum";s:32:"d5cfc3ee82f42b842bc2d5c384142e5e";s:4:"name";s:74:"Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php";}s:77:"Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php";a:4:{s:6:"md5sum";s:32:"19620e0f5149427d9bc81ff43f3f6849";s:4:"name";s:77:"Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php";}s:88:"Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php";a:4:{s:6:"md5sum";s:32:"87696746275168d808097b9ac08eefd1";s:4:"name";s:88:"Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php";}s:86:"Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php";a:4:{s:6:"md5sum";s:32:"4be55d217fa73d2f0c14537f75635e84";s:4:"name";s:86:"Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php";}s:60:"Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php";a:4:{s:6:"md5sum";s:32:"aaeeaa8b993916866478b077e0ae5f7b";s:4:"name";s:60:"Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php";}s:48:"Symfony/Component/Form/Tests/Fixtures/Author.php";a:4:{s:6:"md5sum";s:32:"5c1563a26ab06e4cc72c80d1b4aa75a4";s:4:"name";s:48:"Symfony/Component/Form/Tests/Fixtures/Author.php";s:4:"role";s:4:"test";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/Author.php";}s:52:"Symfony/Component/Form/Tests/Fixtures/AuthorType.php";a:4:{s:6:"md5sum";s:32:"68c706abf40680b1fad0aa7c383af085";s:4:"name";s:52:"Symfony/Component/Form/Tests/Fixtures/AuthorType.php";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/AuthorType.php";}s:59:"Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php";a:4:{s:6:"md5sum";s:32:"80f520948113200553ccb1415f481af3";s:4:"name";s:59:"Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php";}s:62:"Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php";a:4:{s:6:"md5sum";s:32:"21ddaf5472929f397a80781c71c5904e";s:4:"name";s:62:"Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php";}s:61:"Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.php";a:4:{s:6:"md5sum";s:32:"f2a8c5376aac3794f6ba81a263e4f2bf";s:4:"name";s:61:"Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.php";}s:41:"Symfony/Component/Form/Tests/Fixtures/foo";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:41:"Symfony/Component/Form/Tests/Fixtures/foo";s:4:"role";s:4:"test";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/foo";}s:52:"Symfony/Component/Form/Tests/Fixtures/FooSubType.php";a:4:{s:6:"md5sum";s:32:"412bb3f7b15954b7685df57c03cc9216";s:4:"name";s:52:"Symfony/Component/Form/Tests/Fixtures/FooSubType.php";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/FooSubType.php";}s:70:"Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.php";a:4:{s:6:"md5sum";s:32:"31c9db4f9cbf24f98688538f63431553";s:4:"name";s:70:"Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.php";}s:49:"Symfony/Component/Form/Tests/Fixtures/FooType.php";a:4:{s:6:"md5sum";s:32:"56722f2c6ccf149b5009818e705b661d";s:4:"name";s:49:"Symfony/Component/Form/Tests/Fixtures/FooType.php";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/FooType.php";}s:61:"Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.php";a:4:{s:6:"md5sum";s:32:"344219ab84242c7d151ff482ebbca70b";s:4:"name";s:61:"Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.php";}s:61:"Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.php";a:4:{s:6:"md5sum";s:32:"8178239dc9236054e8df7a4cbf7d7888";s:4:"name";s:61:"Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.php";}s:55:"Symfony/Component/Form/Tests/Fixtures/TestExtension.php";a:4:{s:6:"md5sum";s:32:"e23c89ad471d8601a063b068cd6636ee";s:4:"name";s:55:"Symfony/Component/Form/Tests/Fixtures/TestExtension.php";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures/TestExtension.php";}s:48:"Symfony/Component/Form/Tests/FormBuilderTest.php";a:4:{s:6:"md5sum";s:32:"72d98919f7d17ed12b851b748b795913";s:4:"name";s:48:"Symfony/Component/Form/Tests/FormBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/FormBuilderTest.php";}s:47:"Symfony/Component/Form/Tests/FormConfigTest.php";a:4:{s:6:"md5sum";s:32:"0a53ef078ccdaf281872d03975b3f9c5";s:4:"name";s:47:"Symfony/Component/Form/Tests/FormConfigTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/FormConfigTest.php";}s:55:"Symfony/Component/Form/Tests/FormFactoryBuilderTest.php";a:4:{s:6:"md5sum";s:32:"4808f4d1f807a2bd730db77dc250ea3a";s:4:"name";s:55:"Symfony/Component/Form/Tests/FormFactoryBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.php";}s:48:"Symfony/Component/Form/Tests/FormFactoryTest.php";a:4:{s:6:"md5sum";s:32:"148b1a32ce39b4536ce2cdabca226c8e";s:4:"name";s:48:"Symfony/Component/Form/Tests/FormFactoryTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/FormFactoryTest.php";}s:56:"Symfony/Component/Form/Tests/FormIntegrationTestCase.php";a:4:{s:6:"md5sum";s:32:"cba12233a71fa6ad78db42d0b0358123";s:4:"name";s:56:"Symfony/Component/Form/Tests/FormIntegrationTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/FormIntegrationTestCase.php";}s:56:"Symfony/Component/Form/Tests/FormPerformanceTestCase.php";a:4:{s:6:"md5sum";s:32:"e899de2472926b4ada8acb636f1b5444";s:4:"name";s:56:"Symfony/Component/Form/Tests/FormPerformanceTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/FormPerformanceTestCase.php";}s:49:"Symfony/Component/Form/Tests/FormRegistryTest.php";a:4:{s:6:"md5sum";s:32:"eeb0092e76c36e50791699eb2faaaa03";s:4:"name";s:49:"Symfony/Component/Form/Tests/FormRegistryTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/FormRegistryTest.php";}s:49:"Symfony/Component/Form/Tests/FormRendererTest.php";a:4:{s:6:"md5sum";s:32:"1fc848f084ce8f7e10335f8175105886";s:4:"name";s:49:"Symfony/Component/Form/Tests/FormRendererTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/FormRendererTest.php";}s:48:"Symfony/Component/Form/Tests/Guess/GuessTest.php";a:4:{s:6:"md5sum";s:32:"fff8d24dbf03762ed0e2b6f15df45d2d";s:4:"name";s:48:"Symfony/Component/Form/Tests/Guess/GuessTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Guess/GuessTest.php";}s:57:"Symfony/Component/Form/Tests/NativeRequestHandlerTest.php";a:4:{s:6:"md5sum";s:32:"1877e570ea6b354cd5d9d9ba30418edb";s:4:"name";s:57:"Symfony/Component/Form/Tests/NativeRequestHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.php";}s:53:"Symfony/Component/Form/Tests/ResolvedFormTypeTest.php";a:4:{s:6:"md5sum";s:32:"5261f73e95c249da67fe334c0927bf1f";s:4:"name";s:53:"Symfony/Component/Form/Tests/ResolvedFormTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.php";}s:47:"Symfony/Component/Form/Tests/SimpleFormTest.php";a:4:{s:6:"md5sum";s:32:"cfd0db6db50796656eb604515e87adda";s:4:"name";s:47:"Symfony/Component/Form/Tests/SimpleFormTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/SimpleFormTest.php";}s:56:"Symfony/Component/Form/Tests/Util/OrderedHashMapTest.php";a:4:{s:6:"md5sum";s:32:"a7eeabaf53f6a3b60ec3ac2a78ce5002";s:4:"name";s:56:"Symfony/Component/Form/Tests/Util/OrderedHashMapTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.php";}s:40:"Symfony/Component/Form/Util/FormUtil.php";a:4:{s:6:"md5sum";s:32:"d3566f471dce8351225b74b1c01058b6";s:4:"name";s:40:"Symfony/Component/Form/Util/FormUtil.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Util/FormUtil.php";}s:56:"Symfony/Component/Form/Util/InheritDataAwareIterator.php";a:4:{s:6:"md5sum";s:32:"98034987b9a71a6ec3a3f2fddd95f06a";s:4:"name";s:56:"Symfony/Component/Form/Util/InheritDataAwareIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Util/InheritDataAwareIterator.php";}s:46:"Symfony/Component/Form/Util/OrderedHashMap.php";a:4:{s:6:"md5sum";s:32:"fe22cba7385d2b8406b6a7104b9cf58c";s:4:"name";s:46:"Symfony/Component/Form/Util/OrderedHashMap.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Util/OrderedHashMap.php";}s:54:"Symfony/Component/Form/Util/OrderedHashMapIterator.php";a:4:{s:6:"md5sum";s:32:"6240f5c5d77934285a2dddab60843429";s:4:"name";s:54:"Symfony/Component/Form/Util/OrderedHashMapIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Util/OrderedHashMapIterator.php";}s:56:"Symfony/Component/Form/Util/VirtualFormAwareIterator.php";a:4:{s:6:"md5sum";s:32:"da65af10d658064eddfec592c82eb95b";s:4:"name";s:56:"Symfony/Component/Form/Util/VirtualFormAwareIterator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Util/VirtualFormAwareIterator.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:71:{s:52:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:61:"/opt/alt/php54/usr/share/doc/pear/Form/Symfony/Component/Form";b:1;s:56:"/opt/alt/php54/usr/share/doc/pear/Form/Symfony/Component";b:1;s:46:"/opt/alt/php54/usr/share/doc/pear/Form/Symfony";b:1;s:38:"/opt/alt/php54/usr/share/doc/pear/Form";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Exception";b:1;s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/ChoiceList";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension";b:1;s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataMapper";b:1;s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/DataTransformer";b:1;s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/EventListener";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/Type";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Core/View";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf";b:1;s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/CsrfProvider";b:1;s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/EventListener";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Csrf/Type";b:1;s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector";b:1;s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/EventListener";b:1;s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/Proxy";b:1;s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DataCollector/Type";b:1;s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/DependencyInjection";b:1;s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/HttpFoundation/EventListener";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/HttpFoundation";b:1;s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/HttpFoundation/Type";b:1;s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Templating";b:1;s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Constraints";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator";b:1;s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/EventListener";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Type";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/Util";b:1;s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Extension/Validator/ViolationMapper";b:1;s:58:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Guess";b:1;s:62:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form";b:1;s:57:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component";b:1;s:47:"/opt/alt/php54/usr/share/pear/test/Form/Symfony";b:1;s:39:"/opt/alt/php54/usr/share/pear/test/Form";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/config";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources";b:1;s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Resources/translations";b:1;s:57:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Test";b:1;s:68:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests";b:1;s:94:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core";b:1;s:78:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension";b:1;s:94:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataMapper";b:1;s:99:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer";b:1;s:97:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener";b:1;s:106:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Core/Type";b:1;s:96:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Csrf";b:1;s:97:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Csrf/Type";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/DataCollector";b:1;s:97:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/Type";b:1;s:107:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener";b:1;s:93:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator";b:1;s:102:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/EventListener";b:1;s:93:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type";b:1;s:93:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/Util";b:1;s:104:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper";b:1;s:77:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Fixtures";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Guess";b:1;s:73:"/opt/alt/php54/usr/share/pear/test/Form/Symfony/Component/Form/Tests/Util";b:1;s:57:"/opt/alt/php54/usr/share/pear/Symfony/Component/Form/Util";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:6:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:15:"EventDispatcher";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:9:"Validator";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:4;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:6:"Locale";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:5;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:14:"HttpFoundation";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506495;}PK!Eӭ++5.registry/.channel.pear.symfony.com/monologbridge.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:13:"MonologBridge";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:23:"Symfony2 Monolog Bridge";s:11:"description";s:23:"Symfony2 Monolog Bridge";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:40";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:16:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bdbad7393ee44f10ac322df29bfa77ad";s:4:"name";s:37:"Symfony/Bridge/Monolog/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"094d6ae95193dc93574972855a7d4832";s:4:"name";s:35:"Symfony/Bridge/Monolog/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a8f1a867d0764615189e8bf0b52c96cc";s:4:"name";s:36:"Symfony/Bridge/Monolog/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"501339390d395617968209b4da17d804";s:4:"name";s:53:"Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"21b3ac07925411b737467982255e1eee";s:4:"name";s:51:"Symfony/Bridge/Monolog/Handler/ChromePhpHandler.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1904f40387634917013822e9f3141616";s:4:"name";s:49:"Symfony/Bridge/Monolog/Handler/ConsoleHandler.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ed987f0a4d874ea227a55837e8cdd126";s:4:"name";s:47:"Symfony/Bridge/Monolog/Handler/DebugHandler.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"da8c5260e05c07e61be644d857f3a23d";s:4:"name";s:49:"Symfony/Bridge/Monolog/Handler/FirePHPHandler.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f9fc834e5db8ab23a2894046a5c73f0f";s:4:"name";s:53:"Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:30:"Symfony/Bridge/Monolog/LICENSE";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b938f174102a5986f62e1d936e86ff1";s:4:"name";s:33:"Symfony/Bridge/Monolog/Logger.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"13114b196ecb2d5d366e5d55a86e7eb6";s:4:"name";s:39:"Symfony/Bridge/Monolog/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"befbcf0b3ce8ecfb5781cf0666659938";s:4:"name";s:49:"Symfony/Bridge/Monolog/Processor/WebProcessor.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"854dbd178e5fb104a7456c87fab8c54f";s:4:"name";s:32:"Symfony/Bridge/Monolog/README.md";s:4:"role";s:3:"doc";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a08dee274cc27bc65d50e26ac214d71f";s:4:"name";s:59:"Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"79c355f88c71490f32bc2a5d48aa1ee0";s:4:"name";s:59:"Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}s:7:"package";a:2:{s:4:"name";s:10:"HttpKernel";s:7:"channel";s:16:"pear.symfony.com";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:16:{s:37:"Symfony/Bridge/Monolog/autoloader.php";a:4:{s:6:"md5sum";s:32:"bdbad7393ee44f10ac322df29bfa77ad";s:4:"name";s:37:"Symfony/Bridge/Monolog/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/autoloader.php";}s:35:"Symfony/Bridge/Monolog/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"094d6ae95193dc93574972855a7d4832";s:4:"name";s:35:"Symfony/Bridge/Monolog/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/MonologBridge/Symfony/Bridge/Monolog/CHANGELOG.md";}s:36:"Symfony/Bridge/Monolog/composer.json";a:4:{s:6:"md5sum";s:32:"a8f1a867d0764615189e8bf0b52c96cc";s:4:"name";s:36:"Symfony/Bridge/Monolog/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/doc/pear/MonologBridge/Symfony/Bridge/Monolog/composer.json";}s:53:"Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php";a:4:{s:6:"md5sum";s:32:"501339390d395617968209b4da17d804";s:4:"name";s:53:"Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php";}s:51:"Symfony/Bridge/Monolog/Handler/ChromePhpHandler.php";a:4:{s:6:"md5sum";s:32:"21b3ac07925411b737467982255e1eee";s:4:"name";s:51:"Symfony/Bridge/Monolog/Handler/ChromePhpHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Handler/ChromePhpHandler.php";}s:49:"Symfony/Bridge/Monolog/Handler/ConsoleHandler.php";a:4:{s:6:"md5sum";s:32:"1904f40387634917013822e9f3141616";s:4:"name";s:49:"Symfony/Bridge/Monolog/Handler/ConsoleHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php";}s:47:"Symfony/Bridge/Monolog/Handler/DebugHandler.php";a:4:{s:6:"md5sum";s:32:"ed987f0a4d874ea227a55837e8cdd126";s:4:"name";s:47:"Symfony/Bridge/Monolog/Handler/DebugHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Handler/DebugHandler.php";}s:49:"Symfony/Bridge/Monolog/Handler/FirePHPHandler.php";a:4:{s:6:"md5sum";s:32:"da8c5260e05c07e61be644d857f3a23d";s:4:"name";s:49:"Symfony/Bridge/Monolog/Handler/FirePHPHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Handler/FirePHPHandler.php";}s:53:"Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.php";a:4:{s:6:"md5sum";s:32:"f9fc834e5db8ab23a2894046a5c73f0f";s:4:"name";s:53:"Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.php";}s:30:"Symfony/Bridge/Monolog/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:30:"Symfony/Bridge/Monolog/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/doc/pear/MonologBridge/Symfony/Bridge/Monolog/LICENSE";}s:33:"Symfony/Bridge/Monolog/Logger.php";a:4:{s:6:"md5sum";s:32:"5b938f174102a5986f62e1d936e86ff1";s:4:"name";s:33:"Symfony/Bridge/Monolog/Logger.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Logger.php";}s:39:"Symfony/Bridge/Monolog/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"13114b196ecb2d5d366e5d55a86e7eb6";s:4:"name";s:39:"Symfony/Bridge/Monolog/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/test/MonologBridge/Symfony/Bridge/Monolog/phpunit.xml.dist";}s:49:"Symfony/Bridge/Monolog/Processor/WebProcessor.php";a:4:{s:6:"md5sum";s:32:"befbcf0b3ce8ecfb5781cf0666659938";s:4:"name";s:49:"Symfony/Bridge/Monolog/Processor/WebProcessor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Processor/WebProcessor.php";}s:32:"Symfony/Bridge/Monolog/README.md";a:4:{s:6:"md5sum";s:32:"854dbd178e5fb104a7456c87fab8c54f";s:4:"name";s:32:"Symfony/Bridge/Monolog/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/doc/pear/MonologBridge/Symfony/Bridge/Monolog/README.md";}s:59:"Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php";a:4:{s:6:"md5sum";s:32:"a08dee274cc27bc65d50e26ac214d71f";s:4:"name";s:59:"Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/MonologBridge/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php";}s:59:"Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php";a:4:{s:6:"md5sum";s:32:"79c355f88c71490f32bc2a5d48aa1ee0";s:4:"name";s:59:"Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/MonologBridge/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:17:{s:52:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog";b:1;s:44:"/opt/alt/php54/usr/share/pear/Symfony/Bridge";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:70:"/opt/alt/php54/usr/share/doc/pear/MonologBridge/Symfony/Bridge/Monolog";b:1;s:62:"/opt/alt/php54/usr/share/doc/pear/MonologBridge/Symfony/Bridge";b:1;s:55:"/opt/alt/php54/usr/share/doc/pear/MonologBridge/Symfony";b:1;s:47:"/opt/alt/php54/usr/share/doc/pear/MonologBridge";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Formatter";b:1;s:60:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Handler";b:1;s:71:"/opt/alt/php54/usr/share/pear/test/MonologBridge/Symfony/Bridge/Monolog";b:1;s:63:"/opt/alt/php54/usr/share/pear/test/MonologBridge/Symfony/Bridge";b:1;s:56:"/opt/alt/php54/usr/share/pear/test/MonologBridge/Symfony";b:1;s:48:"/opt/alt/php54/usr/share/pear/test/MonologBridge";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Monolog/Processor";b:1;s:85:"/opt/alt/php54/usr/share/pear/test/MonologBridge/Symfony/Bridge/Monolog/Tests/Handler";b:1;s:77:"/opt/alt/php54/usr/share/pear/test/MonologBridge/Symfony/Bridge/Monolog/Tests";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/MonologBridge/Symfony/Bridge/Monolog/Tests/Processor";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:10:"HttpKernel";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506495;}PK!q=h=h2.registry/.channel.pear.symfony.com/serializer.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:10:"Serializer";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:29:"Symfony2 Serializer Component";s:11:"description";s:29:"Symfony2 Serializer Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:50";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:44:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8924fb8ebee45aa2f1cb733a311084fe";s:4:"name";s:43:"Symfony/Component/Serializer/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"124d3455707cf90eea4b75aad3128b99";s:4:"name";s:41:"Symfony/Component/Serializer/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4650d276ce46d27f209867df3fcf7079";s:4:"name";s:42:"Symfony/Component/Serializer/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df666b9ada7f68fadc2531c41d5fe73e";s:4:"name";s:53:"Symfony/Component/Serializer/Encoder/ChainDecoder.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5369492dbbe7d6ca9e13d39b780e2ba7";s:4:"name";s:53:"Symfony/Component/Serializer/Encoder/ChainEncoder.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d801732fc0ff9fa4f77b475b1949f5d7";s:4:"name";s:57:"Symfony/Component/Serializer/Encoder/DecoderInterface.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"60ab91988770567a746858bf9cebc15d";s:4:"name";s:57:"Symfony/Component/Serializer/Encoder/EncoderInterface.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1faccc4be8d9d1f7ee14019a197b24de";s:4:"name";s:51:"Symfony/Component/Serializer/Encoder/JsonDecode.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fd129010a819c8fbed0f9f8e295c3a6b";s:4:"name";s:51:"Symfony/Component/Serializer/Encoder/JsonEncode.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a0de4192caa291e2d2c478056fd08260";s:4:"name";s:52:"Symfony/Component/Serializer/Encoder/JsonEncoder.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b84dd04f4d9155d8bf22f64ad1ab2a21";s:4:"name";s:68:"Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8a78de10c12341c3cd4f3086b9ae4fb1";s:4:"name";s:63:"Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4b1bb45f51fbc0080c7bd83ec4d014b2";s:4:"name";s:51:"Symfony/Component/Serializer/Encoder/XmlEncoder.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"419f2f11a1889bc399f27e8b8ac383c4";s:4:"name";s:52:"Symfony/Component/Serializer/Exception/Exception.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f5a0271960a36477271010059aef7342";s:4:"name";s:67:"Symfony/Component/Serializer/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4fc4b4a3763cfb4f44c63967e9eb0300";s:4:"name";s:57:"Symfony/Component/Serializer/Exception/LogicException.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"117ae6cc407de0db333905e216f06310";s:4:"name";s:59:"Symfony/Component/Serializer/Exception/RuntimeException.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a874d8aa52e749c940da7945f0b5e86c";s:4:"name";s:67:"Symfony/Component/Serializer/Exception/UnexpectedValueException.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c04f7626016df14e0b48b74a67fbe300";s:4:"name";s:63:"Symfony/Component/Serializer/Exception/UnsupportedException.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/Serializer/LICENSE";s:4:"role";s:3:"doc";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b46b9f066240e486a59059f7c21f3757";s:4:"name";s:60:"Symfony/Component/Serializer/Normalizer/CustomNormalizer.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0c2569d8e753c961b4d79f7986f2bc3c";s:4:"name";s:67:"Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d993fdf8138bdb93b870c77f458c72c6";s:4:"name";s:65:"Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea2945858b665064abdf2c54dd76fb4a";s:4:"name";s:66:"Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"88ca8e957cc8d23917585f78154d3247";s:4:"name";s:65:"Symfony/Component/Serializer/Normalizer/NormalizableInterface.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2727f8dbe1b56a400cc24a1a5fcf9253";s:4:"name";s:63:"Symfony/Component/Serializer/Normalizer/NormalizerInterface.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"59fe1098fedc2bc327d5156c247a956b";s:4:"name";s:69:"Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"03c13b185fe6ec3e58a43bb0f4d2096b";s:4:"name";s:45:"Symfony/Component/Serializer/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6fa24c500365e7fb17861841897a47b1";s:4:"name";s:38:"Symfony/Component/Serializer/README.md";s:4:"role";s:3:"doc";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5f529d8ae97ae12590c6a977dcb219d3";s:4:"name";s:43:"Symfony/Component/Serializer/Serializer.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"334216d0212e8a1a75aa0bdbfffe456a";s:4:"name";s:57:"Symfony/Component/Serializer/SerializerAwareInterface.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d33d507c40129e758c96d23be8431d7f";s:4:"name";s:52:"Symfony/Component/Serializer/SerializerInterface.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0486db74aa7aad1deb7fe72ccbe2d24a";s:4:"name";s:62:"Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php";s:4:"role";s:4:"test";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6f8f697b4c8ea3c42bc80167e05926fd";s:4:"name";s:61:"Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fa38de70b4c6a5793c1db7fcbe72d93e";s:4:"name";s:67:"Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php";s:4:"role";s:4:"test";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"75d3643bd45ff8c2fb0fa4b54be38ac1";s:4:"name";s:53:"Symfony/Component/Serializer/Tests/Fixtures/Dummy.php";s:4:"role";s:4:"test";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"14ce02d7ad086e845aa4179be6688758";s:4:"name";s:76:"Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php";s:4:"role";s:4:"test";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c23b959baa7a357482c451f66411c1a4";s:4:"name";s:59:"Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php";s:4:"role";s:4:"test";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d09fd9c23681cee83015d259becf1adb";s:4:"name";s:64:"Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.php";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7a4eeaec6f791cba2dde2eed9943409e";s:4:"name";s:70:"Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php";s:4:"role";s:4:"test";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7299974c15e42153083a1ed5798bc5e9";s:4:"name";s:76:"Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php";s:4:"role";s:4:"test";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"00773fc534e38166aeb342f31d99b28e";s:4:"name";s:66:"Symfony/Component/Serializer/Tests/Normalizer/TestDenormalizer.php";s:4:"role";s:4:"test";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"878f34a6f5f9dd999c08d24154d605c5";s:4:"name";s:64:"Symfony/Component/Serializer/Tests/Normalizer/TestNormalizer.php";s:4:"role";s:4:"test";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"076b26e14077fa01721e8c8ace4a32cf";s:4:"name";s:53:"Symfony/Component/Serializer/Tests/SerializerTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:44:{s:43:"Symfony/Component/Serializer/autoloader.php";a:4:{s:6:"md5sum";s:32:"8924fb8ebee45aa2f1cb733a311084fe";s:4:"name";s:43:"Symfony/Component/Serializer/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/autoloader.php";}s:41:"Symfony/Component/Serializer/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"124d3455707cf90eea4b75aad3128b99";s:4:"name";s:41:"Symfony/Component/Serializer/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/doc/pear/Serializer/Symfony/Component/Serializer/CHANGELOG.md";}s:42:"Symfony/Component/Serializer/composer.json";a:4:{s:6:"md5sum";s:32:"4650d276ce46d27f209867df3fcf7079";s:4:"name";s:42:"Symfony/Component/Serializer/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/Serializer/Symfony/Component/Serializer/composer.json";}s:53:"Symfony/Component/Serializer/Encoder/ChainDecoder.php";a:4:{s:6:"md5sum";s:32:"df666b9ada7f68fadc2531c41d5fe73e";s:4:"name";s:53:"Symfony/Component/Serializer/Encoder/ChainDecoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/ChainDecoder.php";}s:53:"Symfony/Component/Serializer/Encoder/ChainEncoder.php";a:4:{s:6:"md5sum";s:32:"5369492dbbe7d6ca9e13d39b780e2ba7";s:4:"name";s:53:"Symfony/Component/Serializer/Encoder/ChainEncoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/ChainEncoder.php";}s:57:"Symfony/Component/Serializer/Encoder/DecoderInterface.php";a:4:{s:6:"md5sum";s:32:"d801732fc0ff9fa4f77b475b1949f5d7";s:4:"name";s:57:"Symfony/Component/Serializer/Encoder/DecoderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/DecoderInterface.php";}s:57:"Symfony/Component/Serializer/Encoder/EncoderInterface.php";a:4:{s:6:"md5sum";s:32:"60ab91988770567a746858bf9cebc15d";s:4:"name";s:57:"Symfony/Component/Serializer/Encoder/EncoderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/EncoderInterface.php";}s:51:"Symfony/Component/Serializer/Encoder/JsonDecode.php";a:4:{s:6:"md5sum";s:32:"1faccc4be8d9d1f7ee14019a197b24de";s:4:"name";s:51:"Symfony/Component/Serializer/Encoder/JsonDecode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/JsonDecode.php";}s:51:"Symfony/Component/Serializer/Encoder/JsonEncode.php";a:4:{s:6:"md5sum";s:32:"fd129010a819c8fbed0f9f8e295c3a6b";s:4:"name";s:51:"Symfony/Component/Serializer/Encoder/JsonEncode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/JsonEncode.php";}s:52:"Symfony/Component/Serializer/Encoder/JsonEncoder.php";a:4:{s:6:"md5sum";s:32:"a0de4192caa291e2d2c478056fd08260";s:4:"name";s:52:"Symfony/Component/Serializer/Encoder/JsonEncoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/JsonEncoder.php";}s:68:"Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.php";a:4:{s:6:"md5sum";s:32:"b84dd04f4d9155d8bf22f64ad1ab2a21";s:4:"name";s:68:"Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.php";}s:63:"Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php";a:4:{s:6:"md5sum";s:32:"8a78de10c12341c3cd4f3086b9ae4fb1";s:4:"name";s:63:"Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php";}s:51:"Symfony/Component/Serializer/Encoder/XmlEncoder.php";a:4:{s:6:"md5sum";s:32:"4b1bb45f51fbc0080c7bd83ec4d014b2";s:4:"name";s:51:"Symfony/Component/Serializer/Encoder/XmlEncoder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder/XmlEncoder.php";}s:52:"Symfony/Component/Serializer/Exception/Exception.php";a:4:{s:6:"md5sum";s:32:"419f2f11a1889bc399f27e8b8ac383c4";s:4:"name";s:52:"Symfony/Component/Serializer/Exception/Exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Exception/Exception.php";}s:67:"Symfony/Component/Serializer/Exception/InvalidArgumentException.php";a:4:{s:6:"md5sum";s:32:"f5a0271960a36477271010059aef7342";s:4:"name";s:67:"Symfony/Component/Serializer/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Exception/InvalidArgumentException.php";}s:57:"Symfony/Component/Serializer/Exception/LogicException.php";a:4:{s:6:"md5sum";s:32:"4fc4b4a3763cfb4f44c63967e9eb0300";s:4:"name";s:57:"Symfony/Component/Serializer/Exception/LogicException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Exception/LogicException.php";}s:59:"Symfony/Component/Serializer/Exception/RuntimeException.php";a:4:{s:6:"md5sum";s:32:"117ae6cc407de0db333905e216f06310";s:4:"name";s:59:"Symfony/Component/Serializer/Exception/RuntimeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Exception/RuntimeException.php";}s:67:"Symfony/Component/Serializer/Exception/UnexpectedValueException.php";a:4:{s:6:"md5sum";s:32:"a874d8aa52e749c940da7945f0b5e86c";s:4:"name";s:67:"Symfony/Component/Serializer/Exception/UnexpectedValueException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Exception/UnexpectedValueException.php";}s:63:"Symfony/Component/Serializer/Exception/UnsupportedException.php";a:4:{s:6:"md5sum";s:32:"c04f7626016df14e0b48b74a67fbe300";s:4:"name";s:63:"Symfony/Component/Serializer/Exception/UnsupportedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Exception/UnsupportedException.php";}s:36:"Symfony/Component/Serializer/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/Serializer/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/Serializer/Symfony/Component/Serializer/LICENSE";}s:60:"Symfony/Component/Serializer/Normalizer/CustomNormalizer.php";a:4:{s:6:"md5sum";s:32:"b46b9f066240e486a59059f7c21f3757";s:4:"name";s:60:"Symfony/Component/Serializer/Normalizer/CustomNormalizer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php";}s:67:"Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php";a:4:{s:6:"md5sum";s:32:"0c2569d8e753c961b4d79f7986f2bc3c";s:4:"name";s:67:"Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php";}s:65:"Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php";a:4:{s:6:"md5sum";s:32:"d993fdf8138bdb93b870c77f458c72c6";s:4:"name";s:65:"Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php";}s:66:"Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php";a:4:{s:6:"md5sum";s:32:"ea2945858b665064abdf2c54dd76fb4a";s:4:"name";s:66:"Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php";}s:65:"Symfony/Component/Serializer/Normalizer/NormalizableInterface.php";a:4:{s:6:"md5sum";s:32:"88ca8e957cc8d23917585f78154d3247";s:4:"name";s:65:"Symfony/Component/Serializer/Normalizer/NormalizableInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php";}s:63:"Symfony/Component/Serializer/Normalizer/NormalizerInterface.php";a:4:{s:6:"md5sum";s:32:"2727f8dbe1b56a400cc24a1a5fcf9253";s:4:"name";s:63:"Symfony/Component/Serializer/Normalizer/NormalizerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php";}s:69:"Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php";a:4:{s:6:"md5sum";s:32:"59fe1098fedc2bc327d5156c247a956b";s:4:"name";s:69:"Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php";}s:45:"Symfony/Component/Serializer/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"03c13b185fe6ec3e58a43bb0f4d2096b";s:4:"name";s:45:"Symfony/Component/Serializer/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/phpunit.xml.dist";}s:38:"Symfony/Component/Serializer/README.md";a:4:{s:6:"md5sum";s:32:"6fa24c500365e7fb17861841897a47b1";s:4:"name";s:38:"Symfony/Component/Serializer/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/Serializer/Symfony/Component/Serializer/README.md";}s:43:"Symfony/Component/Serializer/Serializer.php";a:4:{s:6:"md5sum";s:32:"5f529d8ae97ae12590c6a977dcb219d3";s:4:"name";s:43:"Symfony/Component/Serializer/Serializer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Serializer.php";}s:57:"Symfony/Component/Serializer/SerializerAwareInterface.php";a:4:{s:6:"md5sum";s:32:"334216d0212e8a1a75aa0bdbfffe456a";s:4:"name";s:57:"Symfony/Component/Serializer/SerializerAwareInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/SerializerAwareInterface.php";}s:52:"Symfony/Component/Serializer/SerializerInterface.php";a:4:{s:6:"md5sum";s:32:"d33d507c40129e758c96d23be8431d7f";s:4:"name";s:52:"Symfony/Component/Serializer/SerializerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/SerializerInterface.php";}s:62:"Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php";a:4:{s:6:"md5sum";s:32:"0486db74aa7aad1deb7fe72ccbe2d24a";s:4:"name";s:62:"Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php";}s:61:"Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php";a:4:{s:6:"md5sum";s:32:"6f8f697b4c8ea3c42bc80167e05926fd";s:4:"name";s:61:"Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php";}s:67:"Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php";a:4:{s:6:"md5sum";s:32:"fa38de70b4c6a5793c1db7fcbe72d93e";s:4:"name";s:67:"Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php";}s:53:"Symfony/Component/Serializer/Tests/Fixtures/Dummy.php";a:4:{s:6:"md5sum";s:32:"75d3643bd45ff8c2fb0fa4b54be38ac1";s:4:"name";s:53:"Symfony/Component/Serializer/Tests/Fixtures/Dummy.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/Dummy.php";}s:76:"Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php";a:4:{s:6:"md5sum";s:32:"14ce02d7ad086e845aa4179be6688758";s:4:"name";s:76:"Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php";}s:59:"Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php";a:4:{s:6:"md5sum";s:32:"c23b959baa7a357482c451f66411c1a4";s:4:"name";s:59:"Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php";}s:64:"Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.php";a:4:{s:6:"md5sum";s:32:"d09fd9c23681cee83015d259becf1adb";s:4:"name";s:64:"Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.php";}s:70:"Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php";a:4:{s:6:"md5sum";s:32:"7a4eeaec6f791cba2dde2eed9943409e";s:4:"name";s:70:"Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php";}s:76:"Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php";a:4:{s:6:"md5sum";s:32:"7299974c15e42153083a1ed5798bc5e9";s:4:"name";s:76:"Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php";}s:66:"Symfony/Component/Serializer/Tests/Normalizer/TestDenormalizer.php";a:4:{s:6:"md5sum";s:32:"00773fc534e38166aeb342f31d99b28e";s:4:"name";s:66:"Symfony/Component/Serializer/Tests/Normalizer/TestDenormalizer.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestDenormalizer.php";}s:64:"Symfony/Component/Serializer/Tests/Normalizer/TestNormalizer.php";a:4:{s:6:"md5sum";s:32:"878f34a6f5f9dd999c08d24154d605c5";s:4:"name";s:64:"Symfony/Component/Serializer/Tests/Normalizer/TestNormalizer.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestNormalizer.php";}s:53:"Symfony/Component/Serializer/Tests/SerializerTest.php";a:4:{s:6:"md5sum";s:32:"076b26e14077fa01721e8c8ace4a32cf";s:4:"name";s:53:"Symfony/Component/Serializer/Tests/SerializerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/SerializerTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:18:{s:58:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:73:"/opt/alt/php54/usr/share/doc/pear/Serializer/Symfony/Component/Serializer";b:1;s:62:"/opt/alt/php54/usr/share/doc/pear/Serializer/Symfony/Component";b:1;s:52:"/opt/alt/php54/usr/share/doc/pear/Serializer/Symfony";b:1;s:44:"/opt/alt/php54/usr/share/doc/pear/Serializer";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Encoder";b:1;s:68:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Exception";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Serializer/Normalizer";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer";b:1;s:63:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component";b:1;s:53:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/pear/test/Serializer";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Encoder";b:1;s:80:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Fixtures";b:1;s:91:"/opt/alt/php54/usr/share/pear/test/Serializer/Symfony/Component/Serializer/Tests/Normalizer";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!3Ų..2.registry/.channel.pear.symfony.com/browserkit.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:10:"BrowserKit";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:29:"Symfony2 BrowserKit Component";s:11:"description";s:29:"Symfony2 BrowserKit Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:40";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:18:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"73fd6d413cc833c5246ceca2eadb68b9";s:4:"name";s:43:"Symfony/Component/BrowserKit/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6dbcbfc4c59d34785c38be32ace2caba";s:4:"name";s:41:"Symfony/Component/BrowserKit/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5674d7e1c5c7b6fe316522b571465467";s:4:"name";s:39:"Symfony/Component/BrowserKit/Client.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"be724b81eaca8742bce61a417240b6fc";s:4:"name";s:42:"Symfony/Component/BrowserKit/composer.json";s:4:"role";s:3:"doc";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f69714aa6ba33d7e1b0bc3b187304d47";s:4:"name";s:39:"Symfony/Component/BrowserKit/Cookie.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"56cd2a8a6894ee87ad2dc34902176a2b";s:4:"name";s:42:"Symfony/Component/BrowserKit/CookieJar.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"38f98f3e64dae73376a7b422dd2606de";s:4:"name";s:40:"Symfony/Component/BrowserKit/History.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/BrowserKit/LICENSE";s:4:"role";s:3:"doc";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fc3e7c04f789c929b337c69a123cb973";s:4:"name";s:45:"Symfony/Component/BrowserKit/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8735649e3edbb9efbc585ae2bc80c977";s:4:"name";s:38:"Symfony/Component/BrowserKit/README.md";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4861bcb9490eadd0c465c5fedcfc6ba6";s:4:"name";s:40:"Symfony/Component/BrowserKit/Request.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"36277cc2c016b665d292b9ac6e1b3071";s:4:"name";s:41:"Symfony/Component/BrowserKit/Response.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7a01acf3983981e9631779baca742a93";s:4:"name";s:49:"Symfony/Component/BrowserKit/Tests/ClientTest.php";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"95ca664f7f929e6360504b978714aeb9";s:4:"name";s:52:"Symfony/Component/BrowserKit/Tests/CookieJarTest.php";s:4:"role";s:4:"test";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b6ecdb8942a989d1aa67f60c278d2551";s:4:"name";s:49:"Symfony/Component/BrowserKit/Tests/CookieTest.php";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1e71cb797c1fa1e81325c1265a8f4cfd";s:4:"name";s:50:"Symfony/Component/BrowserKit/Tests/HistoryTest.php";s:4:"role";s:4:"test";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"28dcc60e83cc2fba65b3d07eda487fd1";s:4:"name";s:50:"Symfony/Component/BrowserKit/Tests/RequestTest.php";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b193b5af166845cca3e3f7e1aeab1eb";s:4:"name";s:51:"Symfony/Component/BrowserKit/Tests/ResponseTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}s:7:"package";a:2:{s:4:"name";s:10:"DomCrawler";s:7:"channel";s:16:"pear.symfony.com";}}s:8:"optional";a:1:{s:7:"package";a:2:{s:4:"name";s:7:"Process";s:7:"channel";s:16:"pear.symfony.com";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:18:{s:43:"Symfony/Component/BrowserKit/autoloader.php";a:4:{s:6:"md5sum";s:32:"73fd6d413cc833c5246ceca2eadb68b9";s:4:"name";s:43:"Symfony/Component/BrowserKit/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/BrowserKit/autoloader.php";}s:41:"Symfony/Component/BrowserKit/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"6dbcbfc4c59d34785c38be32ace2caba";s:4:"name";s:41:"Symfony/Component/BrowserKit/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/doc/pear/BrowserKit/Symfony/Component/BrowserKit/CHANGELOG.md";}s:39:"Symfony/Component/BrowserKit/Client.php";a:4:{s:6:"md5sum";s:32:"5674d7e1c5c7b6fe316522b571465467";s:4:"name";s:39:"Symfony/Component/BrowserKit/Client.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/BrowserKit/Client.php";}s:42:"Symfony/Component/BrowserKit/composer.json";a:4:{s:6:"md5sum";s:32:"be724b81eaca8742bce61a417240b6fc";s:4:"name";s:42:"Symfony/Component/BrowserKit/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/BrowserKit/Symfony/Component/BrowserKit/composer.json";}s:39:"Symfony/Component/BrowserKit/Cookie.php";a:4:{s:6:"md5sum";s:32:"f69714aa6ba33d7e1b0bc3b187304d47";s:4:"name";s:39:"Symfony/Component/BrowserKit/Cookie.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/BrowserKit/Cookie.php";}s:42:"Symfony/Component/BrowserKit/CookieJar.php";a:4:{s:6:"md5sum";s:32:"56cd2a8a6894ee87ad2dc34902176a2b";s:4:"name";s:42:"Symfony/Component/BrowserKit/CookieJar.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/BrowserKit/CookieJar.php";}s:40:"Symfony/Component/BrowserKit/History.php";a:4:{s:6:"md5sum";s:32:"38f98f3e64dae73376a7b422dd2606de";s:4:"name";s:40:"Symfony/Component/BrowserKit/History.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/BrowserKit/History.php";}s:36:"Symfony/Component/BrowserKit/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/BrowserKit/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/BrowserKit/Symfony/Component/BrowserKit/LICENSE";}s:45:"Symfony/Component/BrowserKit/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"fc3e7c04f789c929b337c69a123cb973";s:4:"name";s:45:"Symfony/Component/BrowserKit/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component/BrowserKit/phpunit.xml.dist";}s:38:"Symfony/Component/BrowserKit/README.md";a:4:{s:6:"md5sum";s:32:"8735649e3edbb9efbc585ae2bc80c977";s:4:"name";s:38:"Symfony/Component/BrowserKit/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/BrowserKit/Symfony/Component/BrowserKit/README.md";}s:40:"Symfony/Component/BrowserKit/Request.php";a:4:{s:6:"md5sum";s:32:"4861bcb9490eadd0c465c5fedcfc6ba6";s:4:"name";s:40:"Symfony/Component/BrowserKit/Request.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/BrowserKit/Request.php";}s:41:"Symfony/Component/BrowserKit/Response.php";a:4:{s:6:"md5sum";s:32:"36277cc2c016b665d292b9ac6e1b3071";s:4:"name";s:41:"Symfony/Component/BrowserKit/Response.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/Symfony/Component/BrowserKit/Response.php";}s:49:"Symfony/Component/BrowserKit/Tests/ClientTest.php";a:4:{s:6:"md5sum";s:32:"7a01acf3983981e9631779baca742a93";s:4:"name";s:49:"Symfony/Component/BrowserKit/Tests/ClientTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component/BrowserKit/Tests/ClientTest.php";}s:52:"Symfony/Component/BrowserKit/Tests/CookieJarTest.php";a:4:{s:6:"md5sum";s:32:"95ca664f7f929e6360504b978714aeb9";s:4:"name";s:52:"Symfony/Component/BrowserKit/Tests/CookieJarTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieJarTest.php";}s:49:"Symfony/Component/BrowserKit/Tests/CookieTest.php";a:4:{s:6:"md5sum";s:32:"b6ecdb8942a989d1aa67f60c278d2551";s:4:"name";s:49:"Symfony/Component/BrowserKit/Tests/CookieTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieTest.php";}s:50:"Symfony/Component/BrowserKit/Tests/HistoryTest.php";a:4:{s:6:"md5sum";s:32:"1e71cb797c1fa1e81325c1265a8f4cfd";s:4:"name";s:50:"Symfony/Component/BrowserKit/Tests/HistoryTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component/BrowserKit/Tests/HistoryTest.php";}s:50:"Symfony/Component/BrowserKit/Tests/RequestTest.php";a:4:{s:6:"md5sum";s:32:"28dcc60e83cc2fba65b3d07eda487fd1";s:4:"name";s:50:"Symfony/Component/BrowserKit/Tests/RequestTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component/BrowserKit/Tests/RequestTest.php";}s:51:"Symfony/Component/BrowserKit/Tests/ResponseTest.php";a:4:{s:6:"md5sum";s:32:"9b193b5af166845cca3e3f7e1aeab1eb";s:4:"name";s:51:"Symfony/Component/BrowserKit/Tests/ResponseTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component/BrowserKit/Tests/ResponseTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:12:{s:58:"/opt/alt/php54/usr/share/pear/Symfony/Component/BrowserKit";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:73:"/opt/alt/php54/usr/share/doc/pear/BrowserKit/Symfony/Component/BrowserKit";b:1;s:62:"/opt/alt/php54/usr/share/doc/pear/BrowserKit/Symfony/Component";b:1;s:52:"/opt/alt/php54/usr/share/doc/pear/BrowserKit/Symfony";b:1;s:44:"/opt/alt/php54/usr/share/doc/pear/BrowserKit";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component/BrowserKit";b:1;s:63:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component";b:1;s:53:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/pear/test/BrowserKit";b:1;s:80:"/opt/alt/php54/usr/share/pear/test/BrowserKit/Symfony/Component/BrowserKit/Tests";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:10:"DomCrawler";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:7:"Process";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506495;}PK!BgG3G37.registry/.channel.pear.symfony.com/eventdispatcher.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:15:"EventDispatcher";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:34:"Symfony2 EventDispatcher Component";s:11:"description";s:34:"Symfony2 EventDispatcher Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:43";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:19:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fee3b581ae2d88dae9a188672e9371fa";s:4:"name";s:48:"Symfony/Component/EventDispatcher/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c627c4133ea8e24eb579e4dafe26a9f1";s:4:"name";s:46:"Symfony/Component/EventDispatcher/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d93bc8dae4fd133748a9bd4ad791032b";s:4:"name";s:47:"Symfony/Component/EventDispatcher/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1f7db4681cb831f0f261094e9dea7df8";s:4:"name";s:67:"Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ec4b2758339bbb8439f50ae9b6134edf";s:4:"name";s:77:"Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d46c34f8bacd815af9a3af406d3b2ce9";s:4:"name";s:43:"Symfony/Component/EventDispatcher/Event.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d4dcc000083c4f160538b434cf9e178";s:4:"name";s:53:"Symfony/Component/EventDispatcher/EventDispatcher.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e248cdbdf829780d183ee5e4aaab2055";s:4:"name";s:62:"Symfony/Component/EventDispatcher/EventDispatcherInterface.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6bc33100c6e66896fb9145e1bd4b8b85";s:4:"name";s:62:"Symfony/Component/EventDispatcher/EventSubscriberInterface.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"db4fa1cfbad8c627e27697d8c7bcb7fd";s:4:"name";s:50:"Symfony/Component/EventDispatcher/GenericEvent.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"94bee16721f3a1a865fc870941ec34f4";s:4:"name";s:62:"Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:41:"Symfony/Component/EventDispatcher/LICENSE";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8131bd69d2ff57e333e8920e29dd03c1";s:4:"name";s:50:"Symfony/Component/EventDispatcher/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1732bff29f8f1972e7ba9430ed2881f0";s:4:"name";s:43:"Symfony/Component/EventDispatcher/README.md";s:4:"role";s:3:"doc";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5c527c6cda062487fd8f233918023177";s:4:"name";s:77:"Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1c72dfdf259e21f9ece7d32f7cb57333";s:4:"name";s:63:"Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php";s:4:"role";s:4:"test";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2d8c1f9d12f69cfd4420faf7874573ab";s:4:"name";s:53:"Symfony/Component/EventDispatcher/Tests/EventTest.php";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8afc099e4ad8943631f79a86c5c17313";s:4:"name";s:60:"Symfony/Component/EventDispatcher/Tests/GenericEventTest.php";s:4:"role";s:4:"test";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"98be8e6e205035fbd3213cd1a5ebd68d";s:4:"name";s:72:"Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:19:{s:48:"Symfony/Component/EventDispatcher/autoloader.php";a:4:{s:6:"md5sum";s:32:"fee3b581ae2d88dae9a188672e9371fa";s:4:"name";s:48:"Symfony/Component/EventDispatcher/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/autoloader.php";}s:46:"Symfony/Component/EventDispatcher/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"c627c4133ea8e24eb579e4dafe26a9f1";s:4:"name";s:46:"Symfony/Component/EventDispatcher/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/doc/pear/EventDispatcher/Symfony/Component/EventDispatcher/CHANGELOG.md";}s:47:"Symfony/Component/EventDispatcher/composer.json";a:4:{s:6:"md5sum";s:32:"d93bc8dae4fd133748a9bd4ad791032b";s:4:"name";s:47:"Symfony/Component/EventDispatcher/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/doc/pear/EventDispatcher/Symfony/Component/EventDispatcher/composer.json";}s:67:"Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php";a:4:{s:6:"md5sum";s:32:"1f7db4681cb831f0f261094e9dea7df8";s:4:"name";s:67:"Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php";}s:77:"Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php";a:4:{s:6:"md5sum";s:32:"ec4b2758339bbb8439f50ae9b6134edf";s:4:"name";s:77:"Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php";}s:43:"Symfony/Component/EventDispatcher/Event.php";a:4:{s:6:"md5sum";s:32:"d46c34f8bacd815af9a3af406d3b2ce9";s:4:"name";s:43:"Symfony/Component/EventDispatcher/Event.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/Event.php";}s:53:"Symfony/Component/EventDispatcher/EventDispatcher.php";a:4:{s:6:"md5sum";s:32:"7d4dcc000083c4f160538b434cf9e178";s:4:"name";s:53:"Symfony/Component/EventDispatcher/EventDispatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/EventDispatcher.php";}s:62:"Symfony/Component/EventDispatcher/EventDispatcherInterface.php";a:4:{s:6:"md5sum";s:32:"e248cdbdf829780d183ee5e4aaab2055";s:4:"name";s:62:"Symfony/Component/EventDispatcher/EventDispatcherInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/EventDispatcherInterface.php";}s:62:"Symfony/Component/EventDispatcher/EventSubscriberInterface.php";a:4:{s:6:"md5sum";s:32:"6bc33100c6e66896fb9145e1bd4b8b85";s:4:"name";s:62:"Symfony/Component/EventDispatcher/EventSubscriberInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/EventSubscriberInterface.php";}s:50:"Symfony/Component/EventDispatcher/GenericEvent.php";a:4:{s:6:"md5sum";s:32:"db4fa1cfbad8c627e27697d8c7bcb7fd";s:4:"name";s:50:"Symfony/Component/EventDispatcher/GenericEvent.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/GenericEvent.php";}s:62:"Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php";a:4:{s:6:"md5sum";s:32:"94bee16721f3a1a865fc870941ec34f4";s:4:"name";s:62:"Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php";}s:41:"Symfony/Component/EventDispatcher/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:41:"Symfony/Component/EventDispatcher/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/doc/pear/EventDispatcher/Symfony/Component/EventDispatcher/LICENSE";}s:50:"Symfony/Component/EventDispatcher/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"8131bd69d2ff57e333e8920e29dd03c1";s:4:"name";s:50:"Symfony/Component/EventDispatcher/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony/Component/EventDispatcher/phpunit.xml.dist";}s:43:"Symfony/Component/EventDispatcher/README.md";a:4:{s:6:"md5sum";s:32:"1732bff29f8f1972e7ba9430ed2881f0";s:4:"name";s:43:"Symfony/Component/EventDispatcher/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/doc/pear/EventDispatcher/Symfony/Component/EventDispatcher/README.md";}s:77:"Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php";a:4:{s:6:"md5sum";s:32:"5c527c6cda062487fd8f233918023177";s:4:"name";s:77:"Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php";}s:63:"Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php";a:4:{s:6:"md5sum";s:32:"1c72dfdf259e21f9ece7d32f7cb57333";s:4:"name";s:63:"Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php";}s:53:"Symfony/Component/EventDispatcher/Tests/EventTest.php";a:4:{s:6:"md5sum";s:32:"2d8c1f9d12f69cfd4420faf7874573ab";s:4:"name";s:53:"Symfony/Component/EventDispatcher/Tests/EventTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventTest.php";}s:60:"Symfony/Component/EventDispatcher/Tests/GenericEventTest.php";a:4:{s:6:"md5sum";s:32:"8afc099e4ad8943631f79a86c5c17313";s:4:"name";s:60:"Symfony/Component/EventDispatcher/Tests/GenericEventTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/GenericEventTest.php";}s:72:"Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.php";a:4:{s:6:"md5sum";s:32:"98be8e6e205035fbd3213cd1a5ebd68d";s:4:"name";s:72:"Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:13:{s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:83:"/opt/alt/php54/usr/share/doc/pear/EventDispatcher/Symfony/Component/EventDispatcher";b:1;s:67:"/opt/alt/php54/usr/share/doc/pear/EventDispatcher/Symfony/Component";b:1;s:57:"/opt/alt/php54/usr/share/doc/pear/EventDispatcher/Symfony";b:1;s:49:"/opt/alt/php54/usr/share/doc/pear/EventDispatcher";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/EventDispatcher/Debug";b:1;s:84:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony/Component/EventDispatcher";b:1;s:68:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony/Component";b:1;s:58:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony";b:1;s:50:"/opt/alt/php54/usr/share/pear/test/EventDispatcher";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/EventDispatcher/Symfony/Component/EventDispatcher/Tests";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!YdYY,.registry/.channel.pear.symfony.com/yaml.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:4:"Yaml";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:23:"Symfony2 Yaml Component";s:11:"description";s:23:"Symfony2 Yaml Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:51";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:41:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"07d78d85581e7b233bc906f888f1f406";s:4:"name";s:37:"Symfony/Component/Yaml/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"00392ab3e6199c8363f9e53646f7da22";s:4:"name";s:35:"Symfony/Component/Yaml/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"97ceba40e4d4b099b853d5390cc862a8";s:4:"name";s:36:"Symfony/Component/Yaml/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"42407158b32c6628e0969cabf060ff6c";s:4:"name";s:33:"Symfony/Component/Yaml/Dumper.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b70928e2c815afc3507267c9b5d69df8";s:4:"name";s:34:"Symfony/Component/Yaml/Escaper.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"40b05314535a494039c342a01e1d10d2";s:4:"name";s:50:"Symfony/Component/Yaml/Exception/DumpException.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a7ee6ec67e04faa2c2c29fef8adfc4fa";s:4:"name";s:55:"Symfony/Component/Yaml/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8c619a51b1b41cf5df563d956acb3a66";s:4:"name";s:51:"Symfony/Component/Yaml/Exception/ParseException.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"39bbaf9ae8b207093e4b8a9c09cdb081";s:4:"name";s:53:"Symfony/Component/Yaml/Exception/RuntimeException.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3613cd189e752204d25f0c5d68a6eadc";s:4:"name";s:33:"Symfony/Component/Yaml/Inline.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:30:"Symfony/Component/Yaml/LICENSE";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"64c3b42307205bf8e361168c7ffbd62b";s:4:"name";s:33:"Symfony/Component/Yaml/Parser.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9e6fe22525058accf018c8080e12e2f1";s:4:"name";s:39:"Symfony/Component/Yaml/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"15ed39836fa36c899e3ec99bdfde8cac";s:4:"name";s:32:"Symfony/Component/Yaml/README.md";s:4:"role";s:3:"doc";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"64109519b10453da72024e12b4c07720";s:4:"name";s:43:"Symfony/Component/Yaml/Tests/DumperTest.php";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"52dbe7660c58107077d0e7069fe43498";s:4:"name";s:52:"Symfony/Component/Yaml/Tests/Fixtures/embededPhp.yml";s:4:"role";s:4:"test";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3fdad64212f2a04d91ccc15f2a5f7200";s:4:"name";s:59:"Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.yml";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"809db138c609075657d8d2e81fabaa5c";s:4:"name";s:47:"Symfony/Component/Yaml/Tests/Fixtures/index.yml";s:4:"role";s:4:"test";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff1d8df08f5dfab1a2f23be6cf19c791";s:4:"name";s:52:"Symfony/Component/Yaml/Tests/Fixtures/sfComments.yml";s:4:"role";s:4:"test";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"835842c734605efa1665b90ccb266b97";s:4:"name";s:51:"Symfony/Component/Yaml/Tests/Fixtures/sfCompact.yml";s:4:"role";s:4:"test";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"809113de6e9d341fce21f0524dbaf43b";s:4:"name";s:52:"Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml";s:4:"role";s:4:"test";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"886595fda5f2aa969a232045dbd4941c";s:4:"name";s:51:"Symfony/Component/Yaml/Tests/Fixtures/sfObjects.yml";s:4:"role";s:4:"test";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7ab74ef2b099c462e66d223acdc12494";s:4:"name";s:50:"Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.yml";s:4:"role";s:4:"test";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2cbc1c292d0a398e7044362758ea2c31";s:4:"name";s:49:"Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml";s:4:"role";s:4:"test";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9bf9b30c034a48fd98f1ed6d4f033bb2";s:4:"name";s:63:"Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.yml";s:4:"role";s:4:"test";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"073781a1d2c37127a4296e9af7616624";s:4:"name";s:56:"Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.yml";s:4:"role";s:4:"test";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0f7fe2f6fe3bd6af0ce48f0fde63410f";s:4:"name";s:55:"Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.yml";s:4:"role";s:4:"test";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4c1744b763fce82db7d4e20c469b20cd";s:4:"name";s:57:"Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.yml";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae486823d3d8c404cabc065416e8b0dc";s:4:"name";s:62:"Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.yml";s:4:"role";s:4:"test";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1a6d2fa2a7f53d4657b35baf4ecf67c6";s:4:"name";s:55:"Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.yml";s:4:"role";s:4:"test";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"326c09dd8c5de226c680154c39206647";s:4:"name";s:60:"Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.yml";s:4:"role";s:4:"test";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bf21b6ca89e2aea63b62f60448b841b4";s:4:"name";s:58:"Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.yml";s:4:"role";s:4:"test";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fda05f67ca13f8d50cb904b191039c04";s:4:"name";s:60:"Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.yml";s:4:"role";s:4:"test";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0ac491faab843691cbf2fa415ef1ec2e";s:4:"name";s:66:"Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"359b6d26b73597096784bc481887d8d7";s:4:"name";s:58:"Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml";s:4:"role";s:4:"test";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8218e514512562e64f82e2c64a433a6a";s:4:"name";s:43:"Symfony/Component/Yaml/Tests/InlineTest.php";s:4:"role";s:4:"test";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9a72d3fa4559d2985c7f4d7fec8fe010";s:4:"name";s:51:"Symfony/Component/Yaml/Tests/ParseExceptionTest.php";s:4:"role";s:4:"test";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a240de639b531334340ecf2dc904d1b";s:4:"name";s:43:"Symfony/Component/Yaml/Tests/ParserTest.php";s:4:"role";s:4:"test";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c118d8ca1bda7adff52cfbe25ce80925";s:4:"name";s:41:"Symfony/Component/Yaml/Tests/YamlTest.php";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa973644950ed041a389710050675f1b";s:4:"name";s:36:"Symfony/Component/Yaml/Unescaper.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b37c543884d443eeb0f3212cd1c5ce8f";s:4:"name";s:31:"Symfony/Component/Yaml/Yaml.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:41:{s:37:"Symfony/Component/Yaml/autoloader.php";a:4:{s:6:"md5sum";s:32:"07d78d85581e7b233bc906f888f1f406";s:4:"name";s:37:"Symfony/Component/Yaml/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/autoloader.php";}s:35:"Symfony/Component/Yaml/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"00392ab3e6199c8363f9e53646f7da22";s:4:"name";s:35:"Symfony/Component/Yaml/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/doc/pear/Yaml/Symfony/Component/Yaml/CHANGELOG.md";}s:36:"Symfony/Component/Yaml/composer.json";a:4:{s:6:"md5sum";s:32:"97ceba40e4d4b099b853d5390cc862a8";s:4:"name";s:36:"Symfony/Component/Yaml/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/Yaml/Symfony/Component/Yaml/composer.json";}s:33:"Symfony/Component/Yaml/Dumper.php";a:4:{s:6:"md5sum";s:32:"42407158b32c6628e0969cabf060ff6c";s:4:"name";s:33:"Symfony/Component/Yaml/Dumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Dumper.php";}s:34:"Symfony/Component/Yaml/Escaper.php";a:4:{s:6:"md5sum";s:32:"b70928e2c815afc3507267c9b5d69df8";s:4:"name";s:34:"Symfony/Component/Yaml/Escaper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:64:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Escaper.php";}s:50:"Symfony/Component/Yaml/Exception/DumpException.php";a:4:{s:6:"md5sum";s:32:"40b05314535a494039c342a01e1d10d2";s:4:"name";s:50:"Symfony/Component/Yaml/Exception/DumpException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Exception/DumpException.php";}s:55:"Symfony/Component/Yaml/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"a7ee6ec67e04faa2c2c29fef8adfc4fa";s:4:"name";s:55:"Symfony/Component/Yaml/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Exception/ExceptionInterface.php";}s:51:"Symfony/Component/Yaml/Exception/ParseException.php";a:4:{s:6:"md5sum";s:32:"8c619a51b1b41cf5df563d956acb3a66";s:4:"name";s:51:"Symfony/Component/Yaml/Exception/ParseException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Exception/ParseException.php";}s:53:"Symfony/Component/Yaml/Exception/RuntimeException.php";a:4:{s:6:"md5sum";s:32:"39bbaf9ae8b207093e4b8a9c09cdb081";s:4:"name";s:53:"Symfony/Component/Yaml/Exception/RuntimeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Exception/RuntimeException.php";}s:33:"Symfony/Component/Yaml/Inline.php";a:4:{s:6:"md5sum";s:32:"3613cd189e752204d25f0c5d68a6eadc";s:4:"name";s:33:"Symfony/Component/Yaml/Inline.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Inline.php";}s:30:"Symfony/Component/Yaml/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:30:"Symfony/Component/Yaml/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/doc/pear/Yaml/Symfony/Component/Yaml/LICENSE";}s:33:"Symfony/Component/Yaml/Parser.php";a:4:{s:6:"md5sum";s:32:"64c3b42307205bf8e361168c7ffbd62b";s:4:"name";s:33:"Symfony/Component/Yaml/Parser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Parser.php";}s:39:"Symfony/Component/Yaml/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"9e6fe22525058accf018c8080e12e2f1";s:4:"name";s:39:"Symfony/Component/Yaml/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/phpunit.xml.dist";}s:32:"Symfony/Component/Yaml/README.md";a:4:{s:6:"md5sum";s:32:"15ed39836fa36c899e3ec99bdfde8cac";s:4:"name";s:32:"Symfony/Component/Yaml/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/doc/pear/Yaml/Symfony/Component/Yaml/README.md";}s:43:"Symfony/Component/Yaml/Tests/DumperTest.php";a:4:{s:6:"md5sum";s:32:"64109519b10453da72024e12b4c07720";s:4:"name";s:43:"Symfony/Component/Yaml/Tests/DumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/DumperTest.php";}s:52:"Symfony/Component/Yaml/Tests/Fixtures/embededPhp.yml";a:4:{s:6:"md5sum";s:32:"52dbe7660c58107077d0e7069fe43498";s:4:"name";s:52:"Symfony/Component/Yaml/Tests/Fixtures/embededPhp.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/embededPhp.yml";}s:59:"Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.yml";a:4:{s:6:"md5sum";s:32:"3fdad64212f2a04d91ccc15f2a5f7200";s:4:"name";s:59:"Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.yml";}s:47:"Symfony/Component/Yaml/Tests/Fixtures/index.yml";a:4:{s:6:"md5sum";s:32:"809db138c609075657d8d2e81fabaa5c";s:4:"name";s:47:"Symfony/Component/Yaml/Tests/Fixtures/index.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/index.yml";}s:52:"Symfony/Component/Yaml/Tests/Fixtures/sfComments.yml";a:4:{s:6:"md5sum";s:32:"ff1d8df08f5dfab1a2f23be6cf19c791";s:4:"name";s:52:"Symfony/Component/Yaml/Tests/Fixtures/sfComments.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfComments.yml";}s:51:"Symfony/Component/Yaml/Tests/Fixtures/sfCompact.yml";a:4:{s:6:"md5sum";s:32:"835842c734605efa1665b90ccb266b97";s:4:"name";s:51:"Symfony/Component/Yaml/Tests/Fixtures/sfCompact.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfCompact.yml";}s:52:"Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml";a:4:{s:6:"md5sum";s:32:"809113de6e9d341fce21f0524dbaf43b";s:4:"name";s:52:"Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml";}s:51:"Symfony/Component/Yaml/Tests/Fixtures/sfObjects.yml";a:4:{s:6:"md5sum";s:32:"886595fda5f2aa969a232045dbd4941c";s:4:"name";s:51:"Symfony/Component/Yaml/Tests/Fixtures/sfObjects.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfObjects.yml";}s:50:"Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.yml";a:4:{s:6:"md5sum";s:32:"7ab74ef2b099c462e66d223acdc12494";s:4:"name";s:50:"Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.yml";}s:49:"Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml";a:4:{s:6:"md5sum";s:32:"2cbc1c292d0a398e7044362758ea2c31";s:4:"name";s:49:"Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml";}s:63:"Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.yml";a:4:{s:6:"md5sum";s:32:"9bf9b30c034a48fd98f1ed6d4f033bb2";s:4:"name";s:63:"Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.yml";}s:56:"Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.yml";a:4:{s:6:"md5sum";s:32:"073781a1d2c37127a4296e9af7616624";s:4:"name";s:56:"Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.yml";}s:55:"Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.yml";a:4:{s:6:"md5sum";s:32:"0f7fe2f6fe3bd6af0ce48f0fde63410f";s:4:"name";s:55:"Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.yml";}s:57:"Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.yml";a:4:{s:6:"md5sum";s:32:"4c1744b763fce82db7d4e20c469b20cd";s:4:"name";s:57:"Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.yml";}s:62:"Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.yml";a:4:{s:6:"md5sum";s:32:"ae486823d3d8c404cabc065416e8b0dc";s:4:"name";s:62:"Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.yml";}s:55:"Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.yml";a:4:{s:6:"md5sum";s:32:"1a6d2fa2a7f53d4657b35baf4ecf67c6";s:4:"name";s:55:"Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.yml";}s:60:"Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.yml";a:4:{s:6:"md5sum";s:32:"326c09dd8c5de226c680154c39206647";s:4:"name";s:60:"Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.yml";}s:58:"Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.yml";a:4:{s:6:"md5sum";s:32:"bf21b6ca89e2aea63b62f60448b841b4";s:4:"name";s:58:"Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.yml";}s:60:"Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.yml";a:4:{s:6:"md5sum";s:32:"fda05f67ca13f8d50cb904b191039c04";s:4:"name";s:60:"Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.yml";}s:66:"Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml";a:4:{s:6:"md5sum";s:32:"0ac491faab843691cbf2fa415ef1ec2e";s:4:"name";s:66:"Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml";}s:58:"Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml";a:4:{s:6:"md5sum";s:32:"359b6d26b73597096784bc481887d8d7";s:4:"name";s:58:"Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml";}s:43:"Symfony/Component/Yaml/Tests/InlineTest.php";a:4:{s:6:"md5sum";s:32:"8218e514512562e64f82e2c64a433a6a";s:4:"name";s:43:"Symfony/Component/Yaml/Tests/InlineTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/InlineTest.php";}s:51:"Symfony/Component/Yaml/Tests/ParseExceptionTest.php";a:4:{s:6:"md5sum";s:32:"9a72d3fa4559d2985c7f4d7fec8fe010";s:4:"name";s:51:"Symfony/Component/Yaml/Tests/ParseExceptionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/ParseExceptionTest.php";}s:43:"Symfony/Component/Yaml/Tests/ParserTest.php";a:4:{s:6:"md5sum";s:32:"3a240de639b531334340ecf2dc904d1b";s:4:"name";s:43:"Symfony/Component/Yaml/Tests/ParserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/ParserTest.php";}s:41:"Symfony/Component/Yaml/Tests/YamlTest.php";a:4:{s:6:"md5sum";s:32:"c118d8ca1bda7adff52cfbe25ce80925";s:4:"name";s:41:"Symfony/Component/Yaml/Tests/YamlTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/YamlTest.php";}s:36:"Symfony/Component/Yaml/Unescaper.php";a:4:{s:6:"md5sum";s:32:"aa973644950ed041a389710050675f1b";s:4:"name";s:36:"Symfony/Component/Yaml/Unescaper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Unescaper.php";}s:31:"Symfony/Component/Yaml/Yaml.php";a:4:{s:6:"md5sum";s:32:"b37c543884d443eeb0f3212cd1c5ce8f";s:4:"name";s:31:"Symfony/Component/Yaml/Yaml.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Yaml.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:14:{s:52:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:61:"/opt/alt/php54/usr/share/doc/pear/Yaml/Symfony/Component/Yaml";b:1;s:56:"/opt/alt/php54/usr/share/doc/pear/Yaml/Symfony/Component";b:1;s:46:"/opt/alt/php54/usr/share/doc/pear/Yaml/Symfony";b:1;s:38:"/opt/alt/php54/usr/share/doc/pear/Yaml";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Yaml/Exception";b:1;s:62:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml";b:1;s:57:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component";b:1;s:47:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony";b:1;s:39:"/opt/alt/php54/usr/share/pear/test/Yaml";b:1;s:68:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests";b:1;s:77:"/opt/alt/php54/usr/share/pear/test/Yaml/Symfony/Component/Yaml/Tests/Fixtures";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506495;}PK!19n9n2.registry/.channel.pear.symfony.com/templating.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:10:"Templating";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:29:"Symfony2 Templating Component";s:11:"description";s:29:"Symfony2 Templating Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:50";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:48:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"06b983618b554cae26b0044aaa5c9d73";s:4:"name";s:46:"Symfony/Component/Templating/Asset/Package.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7e410f0980078e771b887babe9631606";s:4:"name";s:55:"Symfony/Component/Templating/Asset/PackageInterface.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"232397a846ea18664111f3c1d12ff472";s:4:"name";s:50:"Symfony/Component/Templating/Asset/PathPackage.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63a22883dfdbe426044cedb7d53baca1";s:4:"name";s:49:"Symfony/Component/Templating/Asset/UrlPackage.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"23396df31b16af1e830dfe9e78024cf0";s:4:"name";s:43:"Symfony/Component/Templating/autoloader.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"89d1f39500f81f0ace0eed9b8faa5551";s:4:"name";s:41:"Symfony/Component/Templating/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f66f26953286d35a671e8c32cd1681a8";s:4:"name";s:42:"Symfony/Component/Templating/composer.json";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"642fd458181e0187d0feb00b7e0f75e6";s:4:"name";s:50:"Symfony/Component/Templating/DebuggerInterface.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"349f44b99680e0274463b4bc8a40a297";s:4:"name";s:49:"Symfony/Component/Templating/DelegatingEngine.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d4d57b7adde79b59d61784e7101bc2b4";s:4:"name";s:48:"Symfony/Component/Templating/EngineInterface.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"efd612dd3df5651085059babfd618c0c";s:4:"name";s:52:"Symfony/Component/Templating/Helper/AssetsHelper.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"435c9f3811b3c90d60d313b68732d945";s:4:"name";s:56:"Symfony/Component/Templating/Helper/CoreAssetsHelper.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d8603eef845f79857f5b16070419dd26";s:4:"name";s:46:"Symfony/Component/Templating/Helper/Helper.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e8fe75ce7386af338af3950d0034097e";s:4:"name";s:55:"Symfony/Component/Templating/Helper/HelperInterface.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"57b81e8d6ab2d04742b112a8ccb4d872";s:4:"name";s:51:"Symfony/Component/Templating/Helper/SlotsHelper.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/Templating/LICENSE";s:4:"role";s:3:"doc";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"89596c802c4299ca1172753ec423949b";s:4:"name";s:51:"Symfony/Component/Templating/Loader/CacheLoader.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f59523a1dadec70ddced8d1927ffee29";s:4:"name";s:51:"Symfony/Component/Templating/Loader/ChainLoader.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b837a9ec3d5a2db85df099eba2097698";s:4:"name";s:56:"Symfony/Component/Templating/Loader/FilesystemLoader.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"97282ffb972085264fecee72b756b3e6";s:4:"name";s:46:"Symfony/Component/Templating/Loader/Loader.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"109568b82844f26ec90af5c86612c8e9";s:4:"name";s:55:"Symfony/Component/Templating/Loader/LoaderInterface.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ac0b6c8fe96f6a29642e44a8b9d5a0e";s:4:"name";s:42:"Symfony/Component/Templating/PhpEngine.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"66cbf2744288df20f1abc6004d0e56d7";s:4:"name";s:45:"Symfony/Component/Templating/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9800cdf7c1a285748e75873cd5a2937b";s:4:"name";s:38:"Symfony/Component/Templating/README.md";s:4:"role";s:3:"doc";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"548638b42e7d927ed988b8cc3851f88d";s:4:"name";s:52:"Symfony/Component/Templating/Storage/FileStorage.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a6f76f3ee3f61a03fe53ef24e6cb5ae7";s:4:"name";s:48:"Symfony/Component/Templating/Storage/Storage.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"226ffc381aade4bd7bb108d2c64c5c3f";s:4:"name";s:54:"Symfony/Component/Templating/Storage/StringStorage.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"28196c12bf8f3244d8147af0eb7372a6";s:4:"name";s:57:"Symfony/Component/Templating/StreamingEngineInterface.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b776a8c0df58c4fcfaf1e63ff35ffc6";s:4:"name";s:51:"Symfony/Component/Templating/TemplateNameParser.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c2b1e13dc4495ca0f80f699542b170a6";s:4:"name";s:60:"Symfony/Component/Templating/TemplateNameParserInterface.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"306070b0a6238aaac07959f3ea304346";s:4:"name";s:50:"Symfony/Component/Templating/TemplateReference.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2e255a20204431df5138c0365f7527b5";s:4:"name";s:59:"Symfony/Component/Templating/TemplateReferenceInterface.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"59973b4b1ccd3cc2022355241d9c1461";s:4:"name";s:59:"Symfony/Component/Templating/Tests/DelegatingEngineTest.php";s:4:"role";s:4:"test";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a8ac9b5e185e2ecf3418e612a788bd6c";s:4:"name";s:60:"Symfony/Component/Templating/Tests/Fixtures/SimpleHelper.php";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fda093af55ec1dc89ec8745c85eda0d5";s:4:"name";s:61:"Symfony/Component/Templating/Tests/Fixtures/templates/foo.php";s:4:"role";s:4:"test";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b6505a4ee8e1f29f1f200cad2d44f4cc";s:4:"name";s:62:"Symfony/Component/Templating/Tests/Helper/AssetsHelperTest.php";s:4:"role";s:4:"test";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a6cf2f490b1f97c2c077bec828d77cd0";s:4:"name";s:66:"Symfony/Component/Templating/Tests/Helper/CoreAssetsHelperTest.php";s:4:"role";s:4:"test";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7e3bc2e0f3a2d85ba4df24d03a49f72d";s:4:"name";s:56:"Symfony/Component/Templating/Tests/Helper/HelperTest.php";s:4:"role";s:4:"test";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"76d50b1a2294fb8a77d763564d54d396";s:4:"name";s:61:"Symfony/Component/Templating/Tests/Helper/SlotsHelperTest.php";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"71bc444643de4a7fbb625bfe0d8b4504";s:4:"name";s:61:"Symfony/Component/Templating/Tests/Loader/CacheLoaderTest.php";s:4:"role";s:4:"test";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f0ff11bbde7e6014a3de882429ec8dfd";s:4:"name";s:61:"Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.php";s:4:"role";s:4:"test";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc936938ae234301e0730c88b67d4848";s:4:"name";s:66:"Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.php";s:4:"role";s:4:"test";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba61470efa3642af0b71ba3c951d344f";s:4:"name";s:56:"Symfony/Component/Templating/Tests/Loader/LoaderTest.php";s:4:"role";s:4:"test";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f22ccaa9e1bfd0be7d7a4dba394cbd04";s:4:"name";s:52:"Symfony/Component/Templating/Tests/PhpEngineTest.php";s:4:"role";s:4:"test";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80b97e6950ae0e4db418375f6af09909";s:4:"name";s:62:"Symfony/Component/Templating/Tests/Storage/FileStorageTest.php";s:4:"role";s:4:"test";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"32856c6ce86000b67c21b30b4521b939";s:4:"name";s:58:"Symfony/Component/Templating/Tests/Storage/StorageTest.php";s:4:"role";s:4:"test";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fc4254f64c0206186a69673bd355b74b";s:4:"name";s:64:"Symfony/Component/Templating/Tests/Storage/StringStorageTest.php";s:4:"role";s:4:"test";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c9a0c56b51df4382d0628855d9ebf395";s:4:"name";s:61:"Symfony/Component/Templating/Tests/TemplateNameParserTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:48:{s:46:"Symfony/Component/Templating/Asset/Package.php";a:4:{s:6:"md5sum";s:32:"06b983618b554cae26b0044aaa5c9d73";s:4:"name";s:46:"Symfony/Component/Templating/Asset/Package.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Asset/Package.php";}s:55:"Symfony/Component/Templating/Asset/PackageInterface.php";a:4:{s:6:"md5sum";s:32:"7e410f0980078e771b887babe9631606";s:4:"name";s:55:"Symfony/Component/Templating/Asset/PackageInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Asset/PackageInterface.php";}s:50:"Symfony/Component/Templating/Asset/PathPackage.php";a:4:{s:6:"md5sum";s:32:"232397a846ea18664111f3c1d12ff472";s:4:"name";s:50:"Symfony/Component/Templating/Asset/PathPackage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Asset/PathPackage.php";}s:49:"Symfony/Component/Templating/Asset/UrlPackage.php";a:4:{s:6:"md5sum";s:32:"63a22883dfdbe426044cedb7d53baca1";s:4:"name";s:49:"Symfony/Component/Templating/Asset/UrlPackage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Asset/UrlPackage.php";}s:43:"Symfony/Component/Templating/autoloader.php";a:4:{s:6:"md5sum";s:32:"23396df31b16af1e830dfe9e78024cf0";s:4:"name";s:43:"Symfony/Component/Templating/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/autoloader.php";}s:41:"Symfony/Component/Templating/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"89d1f39500f81f0ace0eed9b8faa5551";s:4:"name";s:41:"Symfony/Component/Templating/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/doc/pear/Templating/Symfony/Component/Templating/CHANGELOG.md";}s:42:"Symfony/Component/Templating/composer.json";a:4:{s:6:"md5sum";s:32:"f66f26953286d35a671e8c32cd1681a8";s:4:"name";s:42:"Symfony/Component/Templating/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/Templating/Symfony/Component/Templating/composer.json";}s:50:"Symfony/Component/Templating/DebuggerInterface.php";a:4:{s:6:"md5sum";s:32:"642fd458181e0187d0feb00b7e0f75e6";s:4:"name";s:50:"Symfony/Component/Templating/DebuggerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/DebuggerInterface.php";}s:49:"Symfony/Component/Templating/DelegatingEngine.php";a:4:{s:6:"md5sum";s:32:"349f44b99680e0274463b4bc8a40a297";s:4:"name";s:49:"Symfony/Component/Templating/DelegatingEngine.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/DelegatingEngine.php";}s:48:"Symfony/Component/Templating/EngineInterface.php";a:4:{s:6:"md5sum";s:32:"d4d57b7adde79b59d61784e7101bc2b4";s:4:"name";s:48:"Symfony/Component/Templating/EngineInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/EngineInterface.php";}s:52:"Symfony/Component/Templating/Helper/AssetsHelper.php";a:4:{s:6:"md5sum";s:32:"efd612dd3df5651085059babfd618c0c";s:4:"name";s:52:"Symfony/Component/Templating/Helper/AssetsHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Helper/AssetsHelper.php";}s:56:"Symfony/Component/Templating/Helper/CoreAssetsHelper.php";a:4:{s:6:"md5sum";s:32:"435c9f3811b3c90d60d313b68732d945";s:4:"name";s:56:"Symfony/Component/Templating/Helper/CoreAssetsHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Helper/CoreAssetsHelper.php";}s:46:"Symfony/Component/Templating/Helper/Helper.php";a:4:{s:6:"md5sum";s:32:"d8603eef845f79857f5b16070419dd26";s:4:"name";s:46:"Symfony/Component/Templating/Helper/Helper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Helper/Helper.php";}s:55:"Symfony/Component/Templating/Helper/HelperInterface.php";a:4:{s:6:"md5sum";s:32:"e8fe75ce7386af338af3950d0034097e";s:4:"name";s:55:"Symfony/Component/Templating/Helper/HelperInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Helper/HelperInterface.php";}s:51:"Symfony/Component/Templating/Helper/SlotsHelper.php";a:4:{s:6:"md5sum";s:32:"57b81e8d6ab2d04742b112a8ccb4d872";s:4:"name";s:51:"Symfony/Component/Templating/Helper/SlotsHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Helper/SlotsHelper.php";}s:36:"Symfony/Component/Templating/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/Templating/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/Templating/Symfony/Component/Templating/LICENSE";}s:51:"Symfony/Component/Templating/Loader/CacheLoader.php";a:4:{s:6:"md5sum";s:32:"89596c802c4299ca1172753ec423949b";s:4:"name";s:51:"Symfony/Component/Templating/Loader/CacheLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Loader/CacheLoader.php";}s:51:"Symfony/Component/Templating/Loader/ChainLoader.php";a:4:{s:6:"md5sum";s:32:"f59523a1dadec70ddced8d1927ffee29";s:4:"name";s:51:"Symfony/Component/Templating/Loader/ChainLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Loader/ChainLoader.php";}s:56:"Symfony/Component/Templating/Loader/FilesystemLoader.php";a:4:{s:6:"md5sum";s:32:"b837a9ec3d5a2db85df099eba2097698";s:4:"name";s:56:"Symfony/Component/Templating/Loader/FilesystemLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Loader/FilesystemLoader.php";}s:46:"Symfony/Component/Templating/Loader/Loader.php";a:4:{s:6:"md5sum";s:32:"97282ffb972085264fecee72b756b3e6";s:4:"name";s:46:"Symfony/Component/Templating/Loader/Loader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Loader/Loader.php";}s:55:"Symfony/Component/Templating/Loader/LoaderInterface.php";a:4:{s:6:"md5sum";s:32:"109568b82844f26ec90af5c86612c8e9";s:4:"name";s:55:"Symfony/Component/Templating/Loader/LoaderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Loader/LoaderInterface.php";}s:42:"Symfony/Component/Templating/PhpEngine.php";a:4:{s:6:"md5sum";s:32:"3ac0b6c8fe96f6a29642e44a8b9d5a0e";s:4:"name";s:42:"Symfony/Component/Templating/PhpEngine.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/PhpEngine.php";}s:45:"Symfony/Component/Templating/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"66cbf2744288df20f1abc6004d0e56d7";s:4:"name";s:45:"Symfony/Component/Templating/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/phpunit.xml.dist";}s:38:"Symfony/Component/Templating/README.md";a:4:{s:6:"md5sum";s:32:"9800cdf7c1a285748e75873cd5a2937b";s:4:"name";s:38:"Symfony/Component/Templating/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/Templating/Symfony/Component/Templating/README.md";}s:52:"Symfony/Component/Templating/Storage/FileStorage.php";a:4:{s:6:"md5sum";s:32:"548638b42e7d927ed988b8cc3851f88d";s:4:"name";s:52:"Symfony/Component/Templating/Storage/FileStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Storage/FileStorage.php";}s:48:"Symfony/Component/Templating/Storage/Storage.php";a:4:{s:6:"md5sum";s:32:"a6f76f3ee3f61a03fe53ef24e6cb5ae7";s:4:"name";s:48:"Symfony/Component/Templating/Storage/Storage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Storage/Storage.php";}s:54:"Symfony/Component/Templating/Storage/StringStorage.php";a:4:{s:6:"md5sum";s:32:"226ffc381aade4bd7bb108d2c64c5c3f";s:4:"name";s:54:"Symfony/Component/Templating/Storage/StringStorage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Storage/StringStorage.php";}s:57:"Symfony/Component/Templating/StreamingEngineInterface.php";a:4:{s:6:"md5sum";s:32:"28196c12bf8f3244d8147af0eb7372a6";s:4:"name";s:57:"Symfony/Component/Templating/StreamingEngineInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/StreamingEngineInterface.php";}s:51:"Symfony/Component/Templating/TemplateNameParser.php";a:4:{s:6:"md5sum";s:32:"5b776a8c0df58c4fcfaf1e63ff35ffc6";s:4:"name";s:51:"Symfony/Component/Templating/TemplateNameParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/TemplateNameParser.php";}s:60:"Symfony/Component/Templating/TemplateNameParserInterface.php";a:4:{s:6:"md5sum";s:32:"c2b1e13dc4495ca0f80f699542b170a6";s:4:"name";s:60:"Symfony/Component/Templating/TemplateNameParserInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/TemplateNameParserInterface.php";}s:50:"Symfony/Component/Templating/TemplateReference.php";a:4:{s:6:"md5sum";s:32:"306070b0a6238aaac07959f3ea304346";s:4:"name";s:50:"Symfony/Component/Templating/TemplateReference.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/TemplateReference.php";}s:59:"Symfony/Component/Templating/TemplateReferenceInterface.php";a:4:{s:6:"md5sum";s:32:"2e255a20204431df5138c0365f7527b5";s:4:"name";s:59:"Symfony/Component/Templating/TemplateReferenceInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/TemplateReferenceInterface.php";}s:59:"Symfony/Component/Templating/Tests/DelegatingEngineTest.php";a:4:{s:6:"md5sum";s:32:"59973b4b1ccd3cc2022355241d9c1461";s:4:"name";s:59:"Symfony/Component/Templating/Tests/DelegatingEngineTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/DelegatingEngineTest.php";}s:60:"Symfony/Component/Templating/Tests/Fixtures/SimpleHelper.php";a:4:{s:6:"md5sum";s:32:"a8ac9b5e185e2ecf3418e612a788bd6c";s:4:"name";s:60:"Symfony/Component/Templating/Tests/Fixtures/SimpleHelper.php";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Fixtures/SimpleHelper.php";}s:61:"Symfony/Component/Templating/Tests/Fixtures/templates/foo.php";a:4:{s:6:"md5sum";s:32:"fda093af55ec1dc89ec8745c85eda0d5";s:4:"name";s:61:"Symfony/Component/Templating/Tests/Fixtures/templates/foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Fixtures/templates/foo.php";}s:62:"Symfony/Component/Templating/Tests/Helper/AssetsHelperTest.php";a:4:{s:6:"md5sum";s:32:"b6505a4ee8e1f29f1f200cad2d44f4cc";s:4:"name";s:62:"Symfony/Component/Templating/Tests/Helper/AssetsHelperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Helper/AssetsHelperTest.php";}s:66:"Symfony/Component/Templating/Tests/Helper/CoreAssetsHelperTest.php";a:4:{s:6:"md5sum";s:32:"a6cf2f490b1f97c2c077bec828d77cd0";s:4:"name";s:66:"Symfony/Component/Templating/Tests/Helper/CoreAssetsHelperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Helper/CoreAssetsHelperTest.php";}s:56:"Symfony/Component/Templating/Tests/Helper/HelperTest.php";a:4:{s:6:"md5sum";s:32:"7e3bc2e0f3a2d85ba4df24d03a49f72d";s:4:"name";s:56:"Symfony/Component/Templating/Tests/Helper/HelperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Helper/HelperTest.php";}s:61:"Symfony/Component/Templating/Tests/Helper/SlotsHelperTest.php";a:4:{s:6:"md5sum";s:32:"76d50b1a2294fb8a77d763564d54d396";s:4:"name";s:61:"Symfony/Component/Templating/Tests/Helper/SlotsHelperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Helper/SlotsHelperTest.php";}s:61:"Symfony/Component/Templating/Tests/Loader/CacheLoaderTest.php";a:4:{s:6:"md5sum";s:32:"71bc444643de4a7fbb625bfe0d8b4504";s:4:"name";s:61:"Symfony/Component/Templating/Tests/Loader/CacheLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Loader/CacheLoaderTest.php";}s:61:"Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.php";a:4:{s:6:"md5sum";s:32:"f0ff11bbde7e6014a3de882429ec8dfd";s:4:"name";s:61:"Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.php";}s:66:"Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.php";a:4:{s:6:"md5sum";s:32:"bc936938ae234301e0730c88b67d4848";s:4:"name";s:66:"Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.php";}s:56:"Symfony/Component/Templating/Tests/Loader/LoaderTest.php";a:4:{s:6:"md5sum";s:32:"ba61470efa3642af0b71ba3c951d344f";s:4:"name";s:56:"Symfony/Component/Templating/Tests/Loader/LoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Loader/LoaderTest.php";}s:52:"Symfony/Component/Templating/Tests/PhpEngineTest.php";a:4:{s:6:"md5sum";s:32:"f22ccaa9e1bfd0be7d7a4dba394cbd04";s:4:"name";s:52:"Symfony/Component/Templating/Tests/PhpEngineTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/PhpEngineTest.php";}s:62:"Symfony/Component/Templating/Tests/Storage/FileStorageTest.php";a:4:{s:6:"md5sum";s:32:"80b97e6950ae0e4db418375f6af09909";s:4:"name";s:62:"Symfony/Component/Templating/Tests/Storage/FileStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Storage/FileStorageTest.php";}s:58:"Symfony/Component/Templating/Tests/Storage/StorageTest.php";a:4:{s:6:"md5sum";s:32:"32856c6ce86000b67c21b30b4521b939";s:4:"name";s:58:"Symfony/Component/Templating/Tests/Storage/StorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Storage/StorageTest.php";}s:64:"Symfony/Component/Templating/Tests/Storage/StringStorageTest.php";a:4:{s:6:"md5sum";s:32:"fc4254f64c0206186a69673bd355b74b";s:4:"name";s:64:"Symfony/Component/Templating/Tests/Storage/StringStorageTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Storage/StringStorageTest.php";}s:61:"Symfony/Component/Templating/Tests/TemplateNameParserTest.php";a:4:{s:6:"md5sum";s:32:"c9a0c56b51df4382d0628855d9ebf395";s:4:"name";s:61:"Symfony/Component/Templating/Tests/TemplateNameParserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/TemplateNameParserTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:21:{s:64:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Asset";b:1;s:58:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:73:"/opt/alt/php54/usr/share/doc/pear/Templating/Symfony/Component/Templating";b:1;s:62:"/opt/alt/php54/usr/share/doc/pear/Templating/Symfony/Component";b:1;s:52:"/opt/alt/php54/usr/share/doc/pear/Templating/Symfony";b:1;s:44:"/opt/alt/php54/usr/share/doc/pear/Templating";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Helper";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Loader";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating";b:1;s:63:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component";b:1;s:53:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/pear/test/Templating";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Templating/Storage";b:1;s:80:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Fixtures";b:1;s:99:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Fixtures/templates";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Helper";b:1;s:87:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Loader";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/Templating/Symfony/Component/Templating/Tests/Storage";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506494;}PK!@zx@x@2.registry/.channel.pear.symfony.com/domcrawler.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:10:"DomCrawler";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:29:"Symfony2 DomCrawler Component";s:11:"description";s:29:"Symfony2 DomCrawler Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:43";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:26:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"778e5e4c2ef79bf3eab9659a2efe2bee";s:4:"name";s:43:"Symfony/Component/DomCrawler/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2cafc6f4bf64390dcbd0a455be44b6d8";s:4:"name";s:41:"Symfony/Component/DomCrawler/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d1cc79159630ef76a89b80dc11c51f15";s:4:"name";s:42:"Symfony/Component/DomCrawler/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6509c142e976bd66f4c7ec226d050f71";s:4:"name";s:40:"Symfony/Component/DomCrawler/Crawler.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c551faa84079802e0f9b88648d2743ae";s:4:"name";s:54:"Symfony/Component/DomCrawler/Field/ChoiceFormField.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2cc904288c9ada108fc772afd46eeba1";s:4:"name";s:52:"Symfony/Component/DomCrawler/Field/FileFormField.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d4d90fb70896ed262bd9b01238be9986";s:4:"name";s:48:"Symfony/Component/DomCrawler/Field/FormField.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d945707a2751cc30160d16f1e7868a59";s:4:"name";s:53:"Symfony/Component/DomCrawler/Field/InputFormField.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e58b3d248716078974dd6e62c678c09e";s:4:"name";s:56:"Symfony/Component/DomCrawler/Field/TextareaFormField.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"891f2a57a1951ad1bf4956f5df94b682";s:4:"name";s:37:"Symfony/Component/DomCrawler/Form.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"51dd5f3a8bf36823985d4c1d7618d4b6";s:4:"name";s:50:"Symfony/Component/DomCrawler/FormFieldRegistry.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/DomCrawler/LICENSE";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2ed81516a26ccf90ac75d6404bf9589";s:4:"name";s:37:"Symfony/Component/DomCrawler/Link.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"67ea9aa8b6d108bb9f3268da0569c703";s:4:"name";s:45:"Symfony/Component/DomCrawler/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4dbc593d8cc7445cafc62cd73c13f5de";s:4:"name";s:38:"Symfony/Component/DomCrawler/README.md";s:4:"role";s:3:"doc";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ecd3daf12dad9c75b96803ec9caeaf4";s:4:"name";s:50:"Symfony/Component/DomCrawler/Tests/CrawlerTest.php";s:4:"role";s:4:"test";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ce57f830f14f9225111bba2434fe2927";s:4:"name";s:64:"Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"77e2087cd2c221981f6d465fa3ceeb7b";s:4:"name";s:62:"Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.php";s:4:"role";s:4:"test";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"55c98c4590e2c55a7dd4d1bd6074e319";s:4:"name";s:58:"Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.php";s:4:"role";s:4:"test";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"933f6abce62f92d04cfa09025919076f";s:4:"name";s:62:"Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.php";s:4:"role";s:4:"test";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0fa26bf8503badc839759f9f75d5a099";s:4:"name";s:63:"Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.php";s:4:"role";s:4:"test";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e1d8139694476b22f6cc345f42d0a018";s:4:"name";s:66:"Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.php";s:4:"role";s:4:"test";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2205e48de5f93c784733ffcca841d2b5";s:4:"name";s:56:"Symfony/Component/DomCrawler/Tests/Fixtures/no-extension";s:4:"role";s:4:"test";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"974fdff2161430f0a84d086ed023b85c";s:4:"name";s:61:"Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.html";s:4:"role";s:4:"test";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"00b7ea673d9c353455199b68cdfde0e4";s:4:"name";s:47:"Symfony/Component/DomCrawler/Tests/FormTest.php";s:4:"role";s:4:"test";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a634e1da9e7f548d92635fac8614781a";s:4:"name";s:47:"Symfony/Component/DomCrawler/Tests/LinkTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}s:8:"optional";a:1:{s:7:"package";a:2:{s:4:"name";s:11:"CssSelector";s:7:"channel";s:16:"pear.symfony.com";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:26:{s:43:"Symfony/Component/DomCrawler/autoloader.php";a:4:{s:6:"md5sum";s:32:"778e5e4c2ef79bf3eab9659a2efe2bee";s:4:"name";s:43:"Symfony/Component/DomCrawler/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/autoloader.php";}s:41:"Symfony/Component/DomCrawler/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"2cafc6f4bf64390dcbd0a455be44b6d8";s:4:"name";s:41:"Symfony/Component/DomCrawler/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/doc/pear/DomCrawler/Symfony/Component/DomCrawler/CHANGELOG.md";}s:42:"Symfony/Component/DomCrawler/composer.json";a:4:{s:6:"md5sum";s:32:"d1cc79159630ef76a89b80dc11c51f15";s:4:"name";s:42:"Symfony/Component/DomCrawler/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/DomCrawler/Symfony/Component/DomCrawler/composer.json";}s:40:"Symfony/Component/DomCrawler/Crawler.php";a:4:{s:6:"md5sum";s:32:"6509c142e976bd66f4c7ec226d050f71";s:4:"name";s:40:"Symfony/Component/DomCrawler/Crawler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/Crawler.php";}s:54:"Symfony/Component/DomCrawler/Field/ChoiceFormField.php";a:4:{s:6:"md5sum";s:32:"c551faa84079802e0f9b88648d2743ae";s:4:"name";s:54:"Symfony/Component/DomCrawler/Field/ChoiceFormField.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/Field/ChoiceFormField.php";}s:52:"Symfony/Component/DomCrawler/Field/FileFormField.php";a:4:{s:6:"md5sum";s:32:"2cc904288c9ada108fc772afd46eeba1";s:4:"name";s:52:"Symfony/Component/DomCrawler/Field/FileFormField.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/Field/FileFormField.php";}s:48:"Symfony/Component/DomCrawler/Field/FormField.php";a:4:{s:6:"md5sum";s:32:"d4d90fb70896ed262bd9b01238be9986";s:4:"name";s:48:"Symfony/Component/DomCrawler/Field/FormField.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/Field/FormField.php";}s:53:"Symfony/Component/DomCrawler/Field/InputFormField.php";a:4:{s:6:"md5sum";s:32:"d945707a2751cc30160d16f1e7868a59";s:4:"name";s:53:"Symfony/Component/DomCrawler/Field/InputFormField.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/Field/InputFormField.php";}s:56:"Symfony/Component/DomCrawler/Field/TextareaFormField.php";a:4:{s:6:"md5sum";s:32:"e58b3d248716078974dd6e62c678c09e";s:4:"name";s:56:"Symfony/Component/DomCrawler/Field/TextareaFormField.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/Field/TextareaFormField.php";}s:37:"Symfony/Component/DomCrawler/Form.php";a:4:{s:6:"md5sum";s:32:"891f2a57a1951ad1bf4956f5df94b682";s:4:"name";s:37:"Symfony/Component/DomCrawler/Form.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/Form.php";}s:50:"Symfony/Component/DomCrawler/FormFieldRegistry.php";a:4:{s:6:"md5sum";s:32:"51dd5f3a8bf36823985d4c1d7618d4b6";s:4:"name";s:50:"Symfony/Component/DomCrawler/FormFieldRegistry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/FormFieldRegistry.php";}s:36:"Symfony/Component/DomCrawler/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:36:"Symfony/Component/DomCrawler/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/DomCrawler/Symfony/Component/DomCrawler/LICENSE";}s:37:"Symfony/Component/DomCrawler/Link.php";a:4:{s:6:"md5sum";s:32:"f2ed81516a26ccf90ac75d6404bf9589";s:4:"name";s:37:"Symfony/Component/DomCrawler/Link.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/Link.php";}s:45:"Symfony/Component/DomCrawler/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"67ea9aa8b6d108bb9f3268da0569c703";s:4:"name";s:45:"Symfony/Component/DomCrawler/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/phpunit.xml.dist";}s:38:"Symfony/Component/DomCrawler/README.md";a:4:{s:6:"md5sum";s:32:"4dbc593d8cc7445cafc62cd73c13f5de";s:4:"name";s:38:"Symfony/Component/DomCrawler/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/DomCrawler/Symfony/Component/DomCrawler/README.md";}s:50:"Symfony/Component/DomCrawler/Tests/CrawlerTest.php";a:4:{s:6:"md5sum";s:32:"3ecd3daf12dad9c75b96803ec9caeaf4";s:4:"name";s:50:"Symfony/Component/DomCrawler/Tests/CrawlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/CrawlerTest.php";}s:64:"Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php";a:4:{s:6:"md5sum";s:32:"ce57f830f14f9225111bba2434fe2927";s:4:"name";s:64:"Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php";}s:62:"Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.php";a:4:{s:6:"md5sum";s:32:"77e2087cd2c221981f6d465fa3ceeb7b";s:4:"name";s:62:"Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.php";}s:58:"Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.php";a:4:{s:6:"md5sum";s:32:"55c98c4590e2c55a7dd4d1bd6074e319";s:4:"name";s:58:"Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.php";}s:62:"Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.php";a:4:{s:6:"md5sum";s:32:"933f6abce62f92d04cfa09025919076f";s:4:"name";s:62:"Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.php";}s:63:"Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.php";a:4:{s:6:"md5sum";s:32:"0fa26bf8503badc839759f9f75d5a099";s:4:"name";s:63:"Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.php";}s:66:"Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.php";a:4:{s:6:"md5sum";s:32:"e1d8139694476b22f6cc345f42d0a018";s:4:"name";s:66:"Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.php";}s:56:"Symfony/Component/DomCrawler/Tests/Fixtures/no-extension";a:4:{s:6:"md5sum";s:32:"2205e48de5f93c784733ffcca841d2b5";s:4:"name";s:56:"Symfony/Component/DomCrawler/Tests/Fixtures/no-extension";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/no-extension";}s:61:"Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.html";a:4:{s:6:"md5sum";s:32:"974fdff2161430f0a84d086ed023b85c";s:4:"name";s:61:"Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.html";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.html";}s:47:"Symfony/Component/DomCrawler/Tests/FormTest.php";a:4:{s:6:"md5sum";s:32:"00b7ea673d9c353455199b68cdfde0e4";s:4:"name";s:47:"Symfony/Component/DomCrawler/Tests/FormTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/FormTest.php";}s:47:"Symfony/Component/DomCrawler/Tests/LinkTest.php";a:4:{s:6:"md5sum";s:32:"a634e1da9e7f548d92635fac8614781a";s:4:"name";s:47:"Symfony/Component/DomCrawler/Tests/LinkTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/LinkTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:15:{s:58:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:73:"/opt/alt/php54/usr/share/doc/pear/DomCrawler/Symfony/Component/DomCrawler";b:1;s:62:"/opt/alt/php54/usr/share/doc/pear/DomCrawler/Symfony/Component";b:1;s:52:"/opt/alt/php54/usr/share/doc/pear/DomCrawler/Symfony";b:1;s:44:"/opt/alt/php54/usr/share/doc/pear/DomCrawler";b:1;s:64:"/opt/alt/php54/usr/share/pear/Symfony/Component/DomCrawler/Field";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler";b:1;s:63:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component";b:1;s:53:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/pear/test/DomCrawler";b:1;s:80:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:11:"CssSelector";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK! @O 3.registry/.channel.pear.symfony.com/classloader.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:11:"ClassLoader";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:30:"Symfony2 ClassLoader Component";s:11:"description";s:30:"Symfony2 ClassLoader Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:41";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:92:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86d9a3b8315c0692848769a9c1c3e9c5";s:4:"name";s:48:"Symfony/Component/ClassLoader/ApcClassLoader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"13864652955ff0c5022e5553b509729e";s:4:"name";s:57:"Symfony/Component/ClassLoader/ApcUniversalClassLoader.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa24c1ac162b51d1d2a67f57d35ee63e";s:4:"name";s:44:"Symfony/Component/ClassLoader/autoloader.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d6726c438f9e0dfb95fe8b7bc95e626";s:4:"name";s:42:"Symfony/Component/ClassLoader/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e93bc22ebc1bddbcb25c82b3bdcd9e2f";s:4:"name";s:55:"Symfony/Component/ClassLoader/ClassCollectionLoader.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"524dfe8aff9aefd074d38ecdc888a399";s:4:"name";s:45:"Symfony/Component/ClassLoader/ClassLoader.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3866e36ec0fe67f2469b8ec8aeb5333c";s:4:"name";s:51:"Symfony/Component/ClassLoader/ClassMapGenerator.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86212875c79eac9dde10dbb43b2d24fc";s:4:"name";s:43:"Symfony/Component/ClassLoader/composer.json";s:4:"role";s:3:"doc";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d81299fddda21c2171161445bd865017";s:4:"name";s:50:"Symfony/Component/ClassLoader/DebugClassLoader.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"edc1307f2a08518aefb89f5aab8a477e";s:4:"name";s:59:"Symfony/Component/ClassLoader/DebugUniversalClassLoader.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:37:"Symfony/Component/ClassLoader/LICENSE";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"82e86d3ab5084a7720463b20db3f467b";s:4:"name";s:48:"Symfony/Component/ClassLoader/MapClassLoader.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4e2184459091a9fbfc707851521b361c";s:4:"name";s:46:"Symfony/Component/ClassLoader/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09b871124a6d3cce9dbb4f7727f7f810";s:4:"name";s:39:"Symfony/Component/ClassLoader/README.md";s:4:"role";s:3:"doc";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3fb37ebb53adc1aa6b55c84c49fcf5a8";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.php";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"23912b93dc7de2003f49d7f1e2c25732";s:4:"name";s:65:"Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php";s:4:"role";s:4:"test";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6a58f5ed32089b0458e3ee031f30c804";s:4:"name";s:55:"Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6cd9f7dac5d5f1daa2d40903ae0c4d23";s:4:"name";s:61:"Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php";s:4:"role";s:4:"test";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7839cd8c5550658fbc5dd8f50db33db4";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Bar.php";s:4:"role";s:4:"test";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e85a0c52a4381199ded8fca8e42c1875";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php";s:4:"role";s:4:"test";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80ffae60899e48b99924c3a907d38255";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php";s:4:"role";s:4:"test";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9c0b9aefd4284a57d7f649b8cde024c5";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Foo.php";s:4:"role";s:4:"test";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"44d59b6bdb3555587a3be549beb19451";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Bar.php";s:4:"role";s:4:"test";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"89c3f524e25d5abff91ddae0a9aa39f8";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Foo.php";s:4:"role";s:4:"test";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"59093638625c5324d12879437e82ac23";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Bar.php";s:4:"role";s:4:"test";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3a0c0cab70920049cf7c910659bbdddb";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Foo.php";s:4:"role";s:4:"test";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9affd828e7b937fa5dab9348a1c106c3";s:4:"name";s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Bar.php";s:4:"role";s:4:"test";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"565482b47ad54f50794890243d517198";s:4:"name";s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Foo.php";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3f41e3c6878caa34053b0df735fd06d4";s:4:"name";s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Bar.php";s:4:"role";s:4:"test";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"199f5fc8858ff6ba24e9a1927a436a1f";s:4:"name";s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php";s:4:"role";s:4:"test";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"88f045e809ca7fb0c18dfdbb7bbedbfc";s:4:"name";s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php";s:4:"role";s:4:"test";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0a6020428498f5d43bdd1871bdfe5fff";s:4:"name";s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Foo.php";s:4:"role";s:4:"test";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"133c40a5d435bb2607fcaba19a177e92";s:4:"name";s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Bar.php";s:4:"role";s:4:"test";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4809859bdbb243d35edfa3da736c859";s:4:"name";s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"83f27620b7ba2c11696bdf11716d223d";s:4:"name";s:81:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php";s:4:"role";s:4:"test";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"03276dc89dca3856b642091121781aa7";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced/FooBar.php";s:4:"role";s:4:"test";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"450ce1f75995d3855e2890174cad81c9";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php";s:4:"role";s:4:"test";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"272f5b10737a621697301cef1fd00c34";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php";s:4:"role";s:4:"test";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b52382287fd5a64b85c707f0841c797d";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"03276dc89dca3856b642091121781aa7";s:4:"name";s:70:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php";s:4:"role";s:4:"test";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5d889368e4bd7b30ea2179f77d82816f";s:4:"name";s:65:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php";s:4:"role";s:4:"test";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"03ca66795cd12fdb9d39b41825906973";s:4:"name";s:65:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Baz.php";s:4:"role";s:4:"test";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2002a4177d860d4b3763db043f9776f";s:4:"name";s:65:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Foo.php";s:4:"role";s:4:"test";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1234b8d86aed91dae669333ff5ae887f";s:4:"name";s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Bar.php";s:4:"role";s:4:"test";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c3ff0020d627887437102f59aaa6d5a0";s:4:"name";s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php";s:4:"role";s:4:"test";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"16acd0ac1810324ade58e7f527b11721";s:4:"name";s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php";s:4:"role";s:4:"test";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cbe4fddcef55d82678ce042506df312e";s:4:"name";s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Foo.php";s:4:"role";s:4:"test";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7171280695f683129338bbc9127e8a5b";s:4:"name";s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Bar.php";s:4:"role";s:4:"test";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"64b36c967661286fb774e010be84b5fc";s:4:"name";s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Foo.php";s:4:"role";s:4:"test";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d01e56d7432f31c185ea81acd0c3e43e";s:4:"name";s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Bar.php";s:4:"role";s:4:"test";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8c8934c39f7727374b802bea9c0892eb";s:4:"name";s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Foo.php";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c0ba313164bfc6fc725c67e515af6368";s:4:"name";s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/A.php";s:4:"role";s:4:"test";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c718b10e49ff27e12c0674e674e85a6b";s:4:"name";s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/ATrait.php";s:4:"role";s:4:"test";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0322eeaef5105762706853bd4445f92d";s:4:"name";s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/B.php";s:4:"role";s:4:"test";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f6d6d69da53085f34b2363d23081783f";s:4:"name";s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/BTrait.php";s:4:"role";s:4:"test";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea775929d42f58af393b4f224c59b1c9";s:4:"name";s:78:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CInterface.php";s:4:"role";s:4:"test";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f925be736833be1a46dcb4878537cfe3";s:4:"name";s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CTrait.php";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d1a43cd2eb1d650a46793b4324717801";s:4:"name";s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/D.php";s:4:"role";s:4:"test";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"676dc682573657553221b8997da6fe5f";s:4:"name";s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/E.php";s:4:"role";s:4:"test";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6ea7e288f1a6c11ad35be1011275cf49";s:4:"name";s:78:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/GInterface.php";s:4:"role";s:4:"test";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"087217e8655325395af4f0dec57cde9b";s:4:"name";s:68:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php";s:4:"role";s:4:"test";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"439f18e59d963c281150e47387e575e9";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notAClass.php";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"959a2c47ea204306eccdd8fb6bf09d9c";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notPhpFile.md";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"23a88b412716678374cb83b3bd84f281";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/sameNsMultipleClasses.php";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e4d922295055f51230604c8e3d231eae";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeClass.php";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b183b2f81d0a3580b8494e2a315b5c0f";s:4:"name";s:71:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3925f28e4b3d85670506ec8f20ad5c1a";s:4:"name";s:68:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bbbb1f58e6ce45f7f2fcf18009537d34";s:4:"name";s:60:"Symfony/Component/ClassLoader/Tests/Fixtures/deps/traits.php";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4bc49eb260c97d801f0c924b3cbb9e83";s:4:"name";s:75:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7f38452cd551fb2149367bc6b11329e2";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f8188170d810646eafce22ad6458c37c";s:4:"name";s:73:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike/FooBar.php";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fe464b289785a184fb96897588e17915";s:4:"name";s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2/FooBar.php";s:4:"role";s:4:"test";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"22c1ff3bd402ac54f7663e249ee27265";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/includepath/Foo.php";s:4:"role";s:4:"test";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0bd20d6bd956d80ab403aab7ec1692d3";s:4:"name";s:63:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.php";s:4:"role";s:4:"test";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"669a66483c0b6c6d301928afdc9c4e4f";s:4:"name";s:63:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php";s:4:"role";s:4:"test";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"004debf153631e65aa55a6a595f5e859";s:4:"name";s:63:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php";s:4:"role";s:4:"test";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63773f312e4568035cea34d1e7049f93";s:4:"name";s:72:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.php";s:4:"role";s:4:"test";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0e1341c26bd5098d0666416a99328602";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.php";s:4:"role";s:4:"test";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f7037244d76da1670a0b6ab35980d735";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Baz.php";s:4:"role";s:4:"test";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7017318cc8fb7cb1b43f1f7caf023e5b";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Foo.php";s:4:"role";s:4:"test";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"092caf7c7dda0fd29b6a4eb94e16e8c7";s:4:"name";s:61:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Bar.php";s:4:"role";s:4:"test";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7ec330e5918e68855ea1928650677c2e";s:4:"name";s:61:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Baz.php";s:4:"role";s:4:"test";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2ccc8e12aac56ba8a19cc5749f4ddef6";s:4:"name";s:61:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Foo.php";s:4:"role";s:4:"test";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d6f9450b4d45d80d880d449c0f8ec73";s:4:"name";s:70:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/WithComments.php";s:4:"role";s:4:"test";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"43c84f5dcf75beec1d21efa12d74d135";s:4:"name";s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.php";s:4:"role";s:4:"test";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"14a87e5a8699b57391eff2c94f576c18";s:4:"name";s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Baz.php";s:4:"role";s:4:"test";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ed2a4f5ef1c5a5b94181d4caff23caff";s:4:"name";s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Foo.php";s:4:"role";s:4:"test";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d560ea07154ede9772e22e33f7ef7628";s:4:"name";s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/php5.4/traits.php";s:4:"role";s:4:"test";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"393a45c8a8fc03e36dd139563e531f89";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/UniversalClassLoaderTest.php";s:4:"role";s:4:"test";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aaf07f8f264c4476277d3fc72ce31258";s:4:"name";s:54:"Symfony/Component/ClassLoader/UniversalClassLoader.php";s:4:"role";s:3:"php";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c41f5cdde6c04556fa520cb0eaecb4f1";s:4:"name";s:53:"Symfony/Component/ClassLoader/WinCacheClassLoader.php";s:4:"role";s:3:"php";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"626c7922f978832591daa87ec9388708";s:4:"name";s:51:"Symfony/Component/ClassLoader/XcacheClassLoader.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:92:{s:48:"Symfony/Component/ClassLoader/ApcClassLoader.php";a:4:{s:6:"md5sum";s:32:"86d9a3b8315c0692848769a9c1c3e9c5";s:4:"name";s:48:"Symfony/Component/ClassLoader/ApcClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/ApcClassLoader.php";}s:57:"Symfony/Component/ClassLoader/ApcUniversalClassLoader.php";a:4:{s:6:"md5sum";s:32:"13864652955ff0c5022e5553b509729e";s:4:"name";s:57:"Symfony/Component/ClassLoader/ApcUniversalClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php";}s:44:"Symfony/Component/ClassLoader/autoloader.php";a:4:{s:6:"md5sum";s:32:"aa24c1ac162b51d1d2a67f57d35ee63e";s:4:"name";s:44:"Symfony/Component/ClassLoader/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/autoloader.php";}s:42:"Symfony/Component/ClassLoader/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"8d6726c438f9e0dfb95fe8b7bc95e626";s:4:"name";s:42:"Symfony/Component/ClassLoader/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/doc/pear/ClassLoader/Symfony/Component/ClassLoader/CHANGELOG.md";}s:55:"Symfony/Component/ClassLoader/ClassCollectionLoader.php";a:4:{s:6:"md5sum";s:32:"e93bc22ebc1bddbcb25c82b3bdcd9e2f";s:4:"name";s:55:"Symfony/Component/ClassLoader/ClassCollectionLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/ClassCollectionLoader.php";}s:45:"Symfony/Component/ClassLoader/ClassLoader.php";a:4:{s:6:"md5sum";s:32:"524dfe8aff9aefd074d38ecdc888a399";s:4:"name";s:45:"Symfony/Component/ClassLoader/ClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/ClassLoader.php";}s:51:"Symfony/Component/ClassLoader/ClassMapGenerator.php";a:4:{s:6:"md5sum";s:32:"3866e36ec0fe67f2469b8ec8aeb5333c";s:4:"name";s:51:"Symfony/Component/ClassLoader/ClassMapGenerator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/ClassMapGenerator.php";}s:43:"Symfony/Component/ClassLoader/composer.json";a:4:{s:6:"md5sum";s:32:"86212875c79eac9dde10dbb43b2d24fc";s:4:"name";s:43:"Symfony/Component/ClassLoader/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/doc/pear/ClassLoader/Symfony/Component/ClassLoader/composer.json";}s:50:"Symfony/Component/ClassLoader/DebugClassLoader.php";a:4:{s:6:"md5sum";s:32:"d81299fddda21c2171161445bd865017";s:4:"name";s:50:"Symfony/Component/ClassLoader/DebugClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/DebugClassLoader.php";}s:59:"Symfony/Component/ClassLoader/DebugUniversalClassLoader.php";a:4:{s:6:"md5sum";s:32:"edc1307f2a08518aefb89f5aab8a477e";s:4:"name";s:59:"Symfony/Component/ClassLoader/DebugUniversalClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php";}s:37:"Symfony/Component/ClassLoader/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:37:"Symfony/Component/ClassLoader/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/doc/pear/ClassLoader/Symfony/Component/ClassLoader/LICENSE";}s:48:"Symfony/Component/ClassLoader/MapClassLoader.php";a:4:{s:6:"md5sum";s:32:"82e86d3ab5084a7720463b20db3f467b";s:4:"name";s:48:"Symfony/Component/ClassLoader/MapClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/MapClassLoader.php";}s:46:"Symfony/Component/ClassLoader/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"4e2184459091a9fbfc707851521b361c";s:4:"name";s:46:"Symfony/Component/ClassLoader/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/phpunit.xml.dist";}s:39:"Symfony/Component/ClassLoader/README.md";a:4:{s:6:"md5sum";s:32:"09b871124a6d3cce9dbb4f7727f7f810";s:4:"name";s:39:"Symfony/Component/ClassLoader/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/doc/pear/ClassLoader/Symfony/Component/ClassLoader/README.md";}s:67:"Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.php";a:4:{s:6:"md5sum";s:32:"3fb37ebb53adc1aa6b55c84c49fcf5a8";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.php";}s:65:"Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php";a:4:{s:6:"md5sum";s:32:"23912b93dc7de2003f49d7f1e2c25732";s:4:"name";s:65:"Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php";}s:55:"Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php";a:4:{s:6:"md5sum";s:32:"6a58f5ed32089b0458e3ee031f30c804";s:4:"name";s:55:"Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php";}s:61:"Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php";a:4:{s:6:"md5sum";s:32:"6cd9f7dac5d5f1daa2d40903ae0c4d23";s:4:"name";s:61:"Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php";}s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Bar.php";a:4:{s:6:"md5sum";s:32:"7839cd8c5550658fbc5dd8f50db33db4";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Bar.php";}s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php";a:4:{s:6:"md5sum";s:32:"e85a0c52a4381199ded8fca8e42c1875";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php";}s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php";a:4:{s:6:"md5sum";s:32:"80ffae60899e48b99924c3a907d38255";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php";}s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Foo.php";a:4:{s:6:"md5sum";s:32:"9c0b9aefd4284a57d7f649b8cde024c5";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Foo.php";}s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Bar.php";a:4:{s:6:"md5sum";s:32:"44d59b6bdb3555587a3be549beb19451";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Bar.php";}s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Foo.php";a:4:{s:6:"md5sum";s:32:"89c3f524e25d5abff91ddae0a9aa39f8";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Foo.php";}s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Bar.php";a:4:{s:6:"md5sum";s:32:"59093638625c5324d12879437e82ac23";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Bar.php";}s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Foo.php";a:4:{s:6:"md5sum";s:32:"3a0c0cab70920049cf7c910659bbdddb";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Foo.php";}s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Bar.php";a:4:{s:6:"md5sum";s:32:"9affd828e7b937fa5dab9348a1c106c3";s:4:"name";s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Bar.php";}s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Foo.php";a:4:{s:6:"md5sum";s:32:"565482b47ad54f50794890243d517198";s:4:"name";s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Foo.php";}s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Bar.php";a:4:{s:6:"md5sum";s:32:"3f41e3c6878caa34053b0df735fd06d4";s:4:"name";s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Bar.php";}s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php";a:4:{s:6:"md5sum";s:32:"199f5fc8858ff6ba24e9a1927a436a1f";s:4:"name";s:87:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php";}s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php";a:4:{s:6:"md5sum";s:32:"88f045e809ca7fb0c18dfdbb7bbedbfc";s:4:"name";s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php";}s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Foo.php";a:4:{s:6:"md5sum";s:32:"0a6020428498f5d43bdd1871bdfe5fff";s:4:"name";s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Foo.php";}s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Bar.php";a:4:{s:6:"md5sum";s:32:"133c40a5d435bb2607fcaba19a177e92";s:4:"name";s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Bar.php";}s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php";a:4:{s:6:"md5sum";s:32:"b4809859bdbb243d35edfa3da736c859";s:4:"name";s:88:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php";}s:81:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php";a:4:{s:6:"md5sum";s:32:"83f27620b7ba2c11696bdf11716d223d";s:4:"name";s:81:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php";}s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced/FooBar.php";a:4:{s:6:"md5sum";s:32:"03276dc89dca3856b642091121781aa7";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced/FooBar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced/FooBar.php";}s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php";a:4:{s:6:"md5sum";s:32:"450ce1f75995d3855e2890174cad81c9";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php";}s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php";a:4:{s:6:"md5sum";s:32:"272f5b10737a621697301cef1fd00c34";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php";}s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php";a:4:{s:6:"md5sum";s:32:"b52382287fd5a64b85c707f0841c797d";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php";}s:70:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php";a:4:{s:6:"md5sum";s:32:"03276dc89dca3856b642091121781aa7";s:4:"name";s:70:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php";}s:65:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php";a:4:{s:6:"md5sum";s:32:"5d889368e4bd7b30ea2179f77d82816f";s:4:"name";s:65:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php";}s:65:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Baz.php";a:4:{s:6:"md5sum";s:32:"03ca66795cd12fdb9d39b41825906973";s:4:"name";s:65:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Baz.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Baz.php";}s:65:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Foo.php";a:4:{s:6:"md5sum";s:32:"f2002a4177d860d4b3763db043f9776f";s:4:"name";s:65:"Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Foo.php";}s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Bar.php";a:4:{s:6:"md5sum";s:32:"1234b8d86aed91dae669333ff5ae887f";s:4:"name";s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Bar.php";}s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php";a:4:{s:6:"md5sum";s:32:"c3ff0020d627887437102f59aaa6d5a0";s:4:"name";s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php";}s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php";a:4:{s:6:"md5sum";s:32:"16acd0ac1810324ade58e7f527b11721";s:4:"name";s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php";}s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Foo.php";a:4:{s:6:"md5sum";s:32:"cbe4fddcef55d82678ce042506df312e";s:4:"name";s:80:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Foo.php";}s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Bar.php";a:4:{s:6:"md5sum";s:32:"7171280695f683129338bbc9127e8a5b";s:4:"name";s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Bar.php";}s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Foo.php";a:4:{s:6:"md5sum";s:32:"64b36c967661286fb774e010be84b5fc";s:4:"name";s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Foo.php";}s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Bar.php";a:4:{s:6:"md5sum";s:32:"d01e56d7432f31c185ea81acd0c3e43e";s:4:"name";s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Bar.php";}s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Foo.php";a:4:{s:6:"md5sum";s:32:"8c8934c39f7727374b802bea9c0892eb";s:4:"name";s:77:"Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Foo.php";}s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/A.php";a:4:{s:6:"md5sum";s:32:"c0ba313164bfc6fc725c67e515af6368";s:4:"name";s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/A.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/A.php";}s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/ATrait.php";a:4:{s:6:"md5sum";s:32:"c718b10e49ff27e12c0674e674e85a6b";s:4:"name";s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/ATrait.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/ATrait.php";}s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/B.php";a:4:{s:6:"md5sum";s:32:"0322eeaef5105762706853bd4445f92d";s:4:"name";s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/B.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/B.php";}s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/BTrait.php";a:4:{s:6:"md5sum";s:32:"f6d6d69da53085f34b2363d23081783f";s:4:"name";s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/BTrait.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/BTrait.php";}s:78:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CInterface.php";a:4:{s:6:"md5sum";s:32:"ea775929d42f58af393b4f224c59b1c9";s:4:"name";s:78:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CInterface.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CInterface.php";}s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CTrait.php";a:4:{s:6:"md5sum";s:32:"f925be736833be1a46dcb4878537cfe3";s:4:"name";s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CTrait.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CTrait.php";}s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/D.php";a:4:{s:6:"md5sum";s:32:"d1a43cd2eb1d650a46793b4324717801";s:4:"name";s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/D.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/D.php";}s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/E.php";a:4:{s:6:"md5sum";s:32:"676dc682573657553221b8997da6fe5f";s:4:"name";s:69:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/E.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/E.php";}s:78:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/GInterface.php";a:4:{s:6:"md5sum";s:32:"6ea7e288f1a6c11ad35be1011275cf49";s:4:"name";s:78:"Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/GInterface.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/GInterface.php";}s:68:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php";a:4:{s:6:"md5sum";s:32:"087217e8655325395af4f0dec57cde9b";s:4:"name";s:68:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php";}s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notAClass.php";a:4:{s:6:"md5sum";s:32:"439f18e59d963c281150e47387e575e9";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notAClass.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notAClass.php";}s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notPhpFile.md";a:4:{s:6:"md5sum";s:32:"959a2c47ea204306eccdd8fb6bf09d9c";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notPhpFile.md";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notPhpFile.md";}s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/sameNsMultipleClasses.php";a:4:{s:6:"md5sum";s:32:"23a88b412716678374cb83b3bd84f281";s:4:"name";s:79:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/sameNsMultipleClasses.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/sameNsMultipleClasses.php";}s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeClass.php";a:4:{s:6:"md5sum";s:32:"e4d922295055f51230604c8e3d231eae";s:4:"name";s:67:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeClass.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeClass.php";}s:71:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php";a:4:{s:6:"md5sum";s:32:"b183b2f81d0a3580b8494e2a315b5c0f";s:4:"name";s:71:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php";}s:68:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php";a:4:{s:6:"md5sum";s:32:"3925f28e4b3d85670506ec8f20ad5c1a";s:4:"name";s:68:"Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php";}s:60:"Symfony/Component/ClassLoader/Tests/Fixtures/deps/traits.php";a:4:{s:6:"md5sum";s:32:"bbbb1f58e6ce45f7f2fcf18009537d34";s:4:"name";s:60:"Symfony/Component/ClassLoader/Tests/Fixtures/deps/traits.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/deps/traits.php";}s:75:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php";a:4:{s:6:"md5sum";s:32:"4bc49eb260c97d801f0c924b3cbb9e83";s:4:"name";s:75:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php";}s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php";a:4:{s:6:"md5sum";s:32:"7f38452cd551fb2149367bc6b11329e2";s:4:"name";s:76:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php";}s:73:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike/FooBar.php";a:4:{s:6:"md5sum";s:32:"f8188170d810646eafce22ad6458c37c";s:4:"name";s:73:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike/FooBar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike/FooBar.php";}s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2/FooBar.php";a:4:{s:6:"md5sum";s:32:"fe464b289785a184fb96897588e17915";s:4:"name";s:74:"Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2/FooBar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2/FooBar.php";}s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/includepath/Foo.php";a:4:{s:6:"md5sum";s:32:"22c1ff3bd402ac54f7663e249ee27265";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/includepath/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/includepath/Foo.php";}s:63:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.php";a:4:{s:6:"md5sum";s:32:"0bd20d6bd956d80ab403aab7ec1692d3";s:4:"name";s:63:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.php";}s:63:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php";a:4:{s:6:"md5sum";s:32:"669a66483c0b6c6d301928afdc9c4e4f";s:4:"name";s:63:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php";}s:63:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php";a:4:{s:6:"md5sum";s:32:"004debf153631e65aa55a6a595f5e859";s:4:"name";s:63:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php";}s:72:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.php";a:4:{s:6:"md5sum";s:32:"63773f312e4568035cea34d1e7049f93";s:4:"name";s:72:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.php";}s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.php";a:4:{s:6:"md5sum";s:32:"0e1341c26bd5098d0666416a99328602";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.php";}s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Baz.php";a:4:{s:6:"md5sum";s:32:"f7037244d76da1670a0b6ab35980d735";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Baz.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Baz.php";}s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Foo.php";a:4:{s:6:"md5sum";s:32:"7017318cc8fb7cb1b43f1f7caf023e5b";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Foo.php";}s:61:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Bar.php";a:4:{s:6:"md5sum";s:32:"092caf7c7dda0fd29b6a4eb94e16e8c7";s:4:"name";s:61:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Bar.php";}s:61:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Baz.php";a:4:{s:6:"md5sum";s:32:"7ec330e5918e68855ea1928650677c2e";s:4:"name";s:61:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Baz.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Baz.php";}s:61:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Foo.php";a:4:{s:6:"md5sum";s:32:"2ccc8e12aac56ba8a19cc5749f4ddef6";s:4:"name";s:61:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Foo.php";}s:70:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/WithComments.php";a:4:{s:6:"md5sum";s:32:"8d6f9450b4d45d80d880d449c0f8ec73";s:4:"name";s:70:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/WithComments.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/WithComments.php";}s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.php";a:4:{s:6:"md5sum";s:32:"43c84f5dcf75beec1d21efa12d74d135";s:4:"name";s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.php";}s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Baz.php";a:4:{s:6:"md5sum";s:32:"14a87e5a8699b57391eff2c94f576c18";s:4:"name";s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Baz.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Baz.php";}s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Foo.php";a:4:{s:6:"md5sum";s:32:"ed2a4f5ef1c5a5b94181d4caff23caff";s:4:"name";s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Foo.php";}s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/php5.4/traits.php";a:4:{s:6:"md5sum";s:32:"d560ea07154ede9772e22e33f7ef7628";s:4:"name";s:62:"Symfony/Component/ClassLoader/Tests/Fixtures/php5.4/traits.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/php5.4/traits.php";}s:64:"Symfony/Component/ClassLoader/Tests/UniversalClassLoaderTest.php";a:4:{s:6:"md5sum";s:32:"393a45c8a8fc03e36dd139563e531f89";s:4:"name";s:64:"Symfony/Component/ClassLoader/Tests/UniversalClassLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/UniversalClassLoaderTest.php";}s:54:"Symfony/Component/ClassLoader/UniversalClassLoader.php";a:4:{s:6:"md5sum";s:32:"aaf07f8f264c4476277d3fc72ce31258";s:4:"name";s:54:"Symfony/Component/ClassLoader/UniversalClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/UniversalClassLoader.php";}s:53:"Symfony/Component/ClassLoader/WinCacheClassLoader.php";a:4:{s:6:"md5sum";s:32:"c41f5cdde6c04556fa520cb0eaecb4f1";s:4:"name";s:53:"Symfony/Component/ClassLoader/WinCacheClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/WinCacheClassLoader.php";}s:51:"Symfony/Component/ClassLoader/XcacheClassLoader.php";a:4:{s:6:"md5sum";s:32:"626c7922f978832591daa87ec9388708";s:4:"name";s:51:"Symfony/Component/ClassLoader/XcacheClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader/XcacheClassLoader.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:66:{s:59:"/opt/alt/php54/usr/share/pear/Symfony/Component/ClassLoader";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:75:"/opt/alt/php54/usr/share/doc/pear/ClassLoader/Symfony/Component/ClassLoader";b:1;s:63:"/opt/alt/php54/usr/share/doc/pear/ClassLoader/Symfony/Component";b:1;s:53:"/opt/alt/php54/usr/share/doc/pear/ClassLoader/Symfony";b:1;s:45:"/opt/alt/php54/usr/share/doc/pear/ClassLoader";b:1;s:76:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader";b:1;s:64:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component";b:1;s:54:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony";b:1;s:46:"/opt/alt/php54/usr/share/pear/test/ClassLoader";b:1;s:82:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests";b:1;s:118:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A";b:1;s:116:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision";b:1;s:97:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha";b:1;s:91:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures";b:1;s:118:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C";b:1;s:115:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A";b:1;s:113:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision";b:1;s:115:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C";b:1;s:126:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A";b:1;s:124:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision";b:1;s:105:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc";b:1;s:101:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha";b:1;s:95:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc";b:1;s:126:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A";b:1;s:124:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision";b:1;s:127:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B";b:1;s:125:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A";b:1;s:123:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision";b:1;s:104:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta";b:1;s:127:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B";b:1;s:125:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A";b:1;s:123:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision";b:1;s:117:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike";b:1;s:108:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc";b:1;s:104:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback";b:1;s:115:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced";b:1;s:106:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced";b:1;s:104:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike";b:1;s:119:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B";b:1;s:117:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A";b:1;s:115:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision";b:1;s:96:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta";b:1;s:119:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B";b:1;s:117:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C";b:1;s:116:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B";b:1;s:114:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A";b:1;s:112:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision";b:1;s:116:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B";b:1;s:114:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C";b:1;s:110:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap";b:1;s:96:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/deps";b:1;s:111:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback";b:1;s:112:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2";b:1;s:109:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike";b:1;s:110:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2";b:1;s:103:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/includepath";b:1;s:102:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced";b:1;s:103:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike";b:1;s:101:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2";b:1;s:98:"/opt/alt/php54/usr/share/pear/test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/php5.4";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506492;}PK!ý Edd/.registry/.channel.pear.symfony.com/routing.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:7:"Routing";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:26:"Symfony2 Routing Component";s:11:"description";s:26:"Symfony2 Routing Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:49";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:108:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7adb81f5e4787d2604f54309fff0e3bb";s:4:"name";s:46:"Symfony/Component/Routing/Annotation/Route.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b60bdd621fae7d13b678e3f113935112";s:4:"name";s:40:"Symfony/Component/Routing/autoloader.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cb1e57ece0f6472ce554be747e48c528";s:4:"name";s:38:"Symfony/Component/Routing/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0baf57eaa3bff7b952d404d0dd811ad3";s:4:"name";s:43:"Symfony/Component/Routing/CompiledRoute.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e68bb57f1159982d6ccb4bf32818a790";s:4:"name";s:39:"Symfony/Component/Routing/composer.json";s:4:"role";s:3:"doc";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3d64f0b57c301a19b85b92d88902f492";s:4:"name";s:58:"Symfony/Component/Routing/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6b093524c85d31ed964c1da598962df7";s:4:"name";s:65:"Symfony/Component/Routing/Exception/InvalidParameterException.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2c38201b0c1a4c837e95d468dd663e3b";s:4:"name";s:65:"Symfony/Component/Routing/Exception/MethodNotAllowedException.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d2b4c2e8f43f6fd41e2c37bd6393d2d0";s:4:"name";s:75:"Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a8e5469ab6552d46a8f20e6f7f63f76f";s:4:"name";s:65:"Symfony/Component/Routing/Exception/ResourceNotFoundException.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5bf9cdaf9c5be880c320f3e547b7321c";s:4:"name";s:62:"Symfony/Component/Routing/Exception/RouteNotFoundException.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a387ca727c49a190b907162d5cf0239e";s:4:"name";s:73:"Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"585bce412c6f8b482b00264f04f8904f";s:4:"name";s:62:"Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"93d6bfa4c5d22436fdb2fabb49eb6116";s:4:"name";s:71:"Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0895f6715cb9ad1780264962b2e71b64";s:4:"name";s:65:"Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae2d46c136e52ed92d5b3a0485406adc";s:4:"name";s:52:"Symfony/Component/Routing/Generator/UrlGenerator.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8abf3d984c783ee04d6a04a1ede324bd";s:4:"name";s:61:"Symfony/Component/Routing/Generator/UrlGeneratorInterface.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:33:"Symfony/Component/Routing/LICENSE";s:4:"role";s:3:"doc";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dd2947b7d0e4a3806e8055fb51ba23ff";s:4:"name";s:58:"Symfony/Component/Routing/Loader/AnnotationClassLoader.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7bea5831e2002735dee1875edf8526c6";s:4:"name";s:62:"Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6119f0547ce407854362d4acb8eca23b";s:4:"name";s:57:"Symfony/Component/Routing/Loader/AnnotationFileLoader.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"401fa43c0b8ba75aee4d6ee205f5de8e";s:4:"name";s:50:"Symfony/Component/Routing/Loader/ClosureLoader.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a19db6de99eb2baddcd560a30c232ecd";s:4:"name";s:50:"Symfony/Component/Routing/Loader/PhpFileLoader.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e03178ea7d1f063fd89ee2c8218f5b78";s:4:"name";s:63:"Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7e21f6c0b962f4cbb156dc81e73732a2";s:4:"name";s:50:"Symfony/Component/Routing/Loader/XmlFileLoader.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"459710f5848da9859f1569234a0b578e";s:4:"name";s:51:"Symfony/Component/Routing/Loader/YamlFileLoader.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"507197805b62457c0fe43210c946e931";s:4:"name";s:54:"Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c5f1fa04cbb07a028e79f7c442fc87ca";s:4:"name";s:64:"Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"df4c19109cb173cd91453733a9c97922";s:4:"name";s:61:"Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"45c403eb0f5db93743a04d64c11e4b10";s:4:"name";s:67:"Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"850971f7d3c0b766bb8b63bb7f59cd2e";s:4:"name";s:56:"Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d3d51e47a11338eb959efbc24c56d157";s:4:"name";s:58:"Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"12d3638dbfcc3ecbc7e5e16c46b0a18c";s:4:"name";s:67:"Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9daade9ffbdeff369f03818ef2f73ce2";s:4:"name";s:61:"Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"357c83fcf951bdb206fca135dca5bb07";s:4:"name";s:60:"Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"001a000c9776f18c43a8ee4664b6e163";s:4:"name";s:69:"Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c623f743ec5d8113a010c2305f64b21e";s:4:"name";s:61:"Symfony/Component/Routing/Matcher/RequestMatcherInterface.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6c48a62311dd625f0d624495e1d5d6e3";s:4:"name";s:57:"Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0527f51011e56d17b92c0cd5ae204d54";s:4:"name";s:48:"Symfony/Component/Routing/Matcher/UrlMatcher.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ebcef73fd69167569dbf16207a5cc2b4";s:4:"name";s:57:"Symfony/Component/Routing/Matcher/UrlMatcherInterface.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"306433f88b741f2d72b11ff338743859";s:4:"name";s:42:"Symfony/Component/Routing/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f72998925a6eca826c1fe39175f7b63b";s:4:"name";s:35:"Symfony/Component/Routing/README.md";s:4:"role";s:3:"doc";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"516eaca4237df46d98fa7a57e8937fc2";s:4:"name";s:44:"Symfony/Component/Routing/RequestContext.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2c9cdcdd343d5761f123e325f96027a2";s:4:"name";s:58:"Symfony/Component/Routing/RequestContextAwareInterface.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a0b6b35abcbed3f170a90c9fa56703c1";s:4:"name";s:35:"Symfony/Component/Routing/Route.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d3c52daaaec1113c792edf9236828964";s:4:"name";s:45:"Symfony/Component/Routing/RouteCollection.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0dde56b2dd439922f60b19cc24ce00eb";s:4:"name";s:43:"Symfony/Component/Routing/RouteCompiler.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9bade2ca282845cdce2120a21147f955";s:4:"name";s:52:"Symfony/Component/Routing/RouteCompilerInterface.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cfa1e77acc20b94d2869303a3e343bdd";s:4:"name";s:36:"Symfony/Component/Routing/Router.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"28c2b609f629bb9c437624f5f9897a7f";s:4:"name";s:45:"Symfony/Component/Routing/RouterInterface.php";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"95f849d5323f5a02d2c1b26009cff39a";s:4:"name";s:56:"Symfony/Component/Routing/Tests/Annotation/RouteTest.php";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"329dc6eb58ed2841e9dff812a6f04f93";s:4:"name";s:53:"Symfony/Component/Routing/Tests/CompiledRouteTest.php";s:4:"role";s:4:"test";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Routing/Tests/Fixtures/annotated.php";s:4:"role";s:4:"test";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8faac9caece520eabbf87e072d996583";s:4:"name";s:75:"Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php";s:4:"role";s:4:"test";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"be20633112a29f2ada4e2989a31b7dc9";s:4:"name";s:70:"Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.php";s:4:"role";s:4:"test";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1ec3b14820cead74554134842fa3498b";s:4:"name";s:70:"Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php";s:4:"role";s:4:"test";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3cad48848f57310d3f0136f2cff860f2";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6ee192ca9034e12e89cb048b31f8e208";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache";s:4:"role";s:4:"test";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"371781bd5bc58854e49e0b583470c685";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php";s:4:"role";s:4:"test";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"24139b71d25f2706f9956ce94ec65d99";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache";s:4:"role";s:4:"test";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3cd94c1ff96c25218039f7c6aefb56f2";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php";s:4:"role";s:4:"test";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dd7da1ea21e2d886d079594d07e167dc";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:50:"Symfony/Component/Routing/Tests/Fixtures/empty.yml";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:48:"Symfony/Component/Routing/Tests/Fixtures/foo.xml";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:49:"Symfony/Component/Routing/Tests/Fixtures/foo1.xml";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bf3dd20043754c68c898fdfa423fe222";s:4:"name";s:55:"Symfony/Component/Routing/Tests/Fixtures/incomplete.yml";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d8e1d3483f7f8ccf90232bd90127aa92";s:4:"name";s:55:"Symfony/Component/Routing/Tests/Fixtures/missing_id.xml";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7cfffc2477dfdf9f9ae10de26b0fb51a";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/missing_path.xml";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cf3966d1a8d8470e67a08ae431058d0f";s:4:"name";s:60:"Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xml";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0612cba8c11d5b3cb54e50b2c749c21c";s:4:"name";s:73:"Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.yml";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8018429bdc8e300ac75c368660613c86";s:4:"name";s:76:"Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.yml";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc542914570693788cf3a8d2afbd45c2";s:4:"name";s:53:"Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml";s:4:"role";s:4:"test";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d3b07384d113edec49eaa6238ad5ff00";s:4:"name";s:53:"Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml";s:4:"role";s:4:"test";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"55ada43e144278e471a7ba1cdd7cc295";s:4:"name";s:54:"Symfony/Component/Routing/Tests/Fixtures/nonvalid2.yml";s:4:"role";s:4:"test";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"70579c6820523185fc90f5373c3821fd";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml";s:4:"role";s:4:"test";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c859068a6d836761e048cd0edb727dcb";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml";s:4:"role";s:4:"test";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a4e93f76c7e4364bae051528417adfb2";s:4:"name";s:58:"Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml";s:4:"role";s:4:"test";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"682451e5c01e3d3dd757fc8919d1d43c";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php";s:4:"role";s:4:"test";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7586d7599fd0f4df8c339cb951e96497";s:4:"name";s:63:"Symfony/Component/Routing/Tests/Fixtures/special_route_name.yml";s:4:"role";s:4:"test";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"38aeb5d4ba857600ef5c0215739453c5";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/validpattern.php";s:4:"role";s:4:"test";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"56524e1e940a4197127becdfd7268a10";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/validpattern.xml";s:4:"role";s:4:"test";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"24dd856c57527517f9280aaa43bef110";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/validpattern.yml";s:4:"role";s:4:"test";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"839c3e52a85f8e4d6beee322a3115d93";s:4:"name";s:58:"Symfony/Component/Routing/Tests/Fixtures/validresource.xml";s:4:"role";s:4:"test";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2fd3dead2fc9206e2d3fe8a33bfdedb";s:4:"name";s:58:"Symfony/Component/Routing/Tests/Fixtures/validresource.yml";s:4:"role";s:4:"test";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"561c119c08673fd8436e11424a20d808";s:4:"name";s:56:"Symfony/Component/Routing/Tests/Fixtures/withdoctype.xml";s:4:"role";s:4:"test";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7a9b9b426e9cbbe3c69b31c5a7ad0890";s:4:"name";s:75:"Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php";s:4:"role";s:4:"test";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5d99c062e8a7e57006a53e6579ac95c0";s:4:"name";s:62:"Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php";s:4:"role";s:4:"test";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5639a76d09ef4f3443810984ed8984ef";s:4:"name";s:71:"Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php";s:4:"role";s:4:"test";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2f7f7a0c885391b6b97e8a99883ea05d";s:4:"name";s:68:"Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php";s:4:"role";s:4:"test";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dbfce1fde62363437f0aa8a33613e97c";s:4:"name";s:72:"Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php";s:4:"role";s:4:"test";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4dfd29898087da820c09e85719a5c792";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php";s:4:"role";s:4:"test";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7046a86d62fbf762f17b4776eccb4dc4";s:4:"name";s:60:"Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php";s:4:"role";s:4:"test";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a2ab975045a0d412efbf0d5ac222972c";s:4:"name";s:60:"Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php";s:4:"role";s:4:"test";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d8319c0bc762ca704bb7908703d0c7e";s:4:"name";s:60:"Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php";s:4:"role";s:4:"test";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eebeb2d76e8045aa0098090259de5ee4";s:4:"name";s:61:"Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php";s:4:"role";s:4:"test";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba1d59f0b0d653e1aaf3ee0c6649bff7";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php";s:4:"role";s:4:"test";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0642be5053da073e465f18f1b8fd887d";s:4:"name";s:74:"Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php";s:4:"role";s:4:"test";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b35d71387dc9d1d3240600e639f1bd9c";s:4:"name";s:71:"Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.php";s:4:"role";s:4:"test";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4c13ddc57f8c8669a7d0527d745b8a68";s:4:"name";s:77:"Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.php";s:4:"role";s:4:"test";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"84d694ec0d369ec8cc64177e4a1dc08d";s:4:"name";s:71:"Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php";s:4:"role";s:4:"test";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea86e71e661f737eb99b92f42c9b6eb4";s:4:"name";s:70:"Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php";s:4:"role";s:4:"test";}}i:101;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7ea68114d0c4d2f15535a6f6af9c4f16";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php";s:4:"role";s:4:"test";}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"59b53c89eb44b45ad22a2e44e3cd7eea";s:4:"name";s:58:"Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php";s:4:"role";s:4:"test";}}i:103;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"504c9fa5bc66cfd0cfa38d73fbacfee5";s:4:"name";s:54:"Symfony/Component/Routing/Tests/RequestContextTest.php";s:4:"role";s:4:"test";}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f9071d027efd59e4a55cfbbdd9af4819";s:4:"name";s:55:"Symfony/Component/Routing/Tests/RouteCollectionTest.php";s:4:"role";s:4:"test";}}i:105;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f0ee1d58dd4ec0723688cab9d08adc4e";s:4:"name";s:53:"Symfony/Component/Routing/Tests/RouteCompilerTest.php";s:4:"role";s:4:"test";}}i:106;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5188e029a746903602beab36af4502b7";s:4:"name";s:46:"Symfony/Component/Routing/Tests/RouterTest.php";s:4:"role";s:4:"test";}}i:107;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"88ef12b30bd938f7583c2e9afc89b6f9";s:4:"name";s:45:"Symfony/Component/Routing/Tests/RouteTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}s:8:"optional";a:1:{s:7:"package";a:2:{i:0;a:2:{s:4:"name";s:6:"Config";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:4:"Yaml";s:7:"channel";s:16:"pear.symfony.com";}}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:108:{s:46:"Symfony/Component/Routing/Annotation/Route.php";a:4:{s:6:"md5sum";s:32:"7adb81f5e4787d2604f54309fff0e3bb";s:4:"name";s:46:"Symfony/Component/Routing/Annotation/Route.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Annotation/Route.php";}s:40:"Symfony/Component/Routing/autoloader.php";a:4:{s:6:"md5sum";s:32:"b60bdd621fae7d13b678e3f113935112";s:4:"name";s:40:"Symfony/Component/Routing/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/autoloader.php";}s:38:"Symfony/Component/Routing/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"cb1e57ece0f6472ce554be747e48c528";s:4:"name";s:38:"Symfony/Component/Routing/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/doc/pear/Routing/Symfony/Component/Routing/CHANGELOG.md";}s:43:"Symfony/Component/Routing/CompiledRoute.php";a:4:{s:6:"md5sum";s:32:"0baf57eaa3bff7b952d404d0dd811ad3";s:4:"name";s:43:"Symfony/Component/Routing/CompiledRoute.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/CompiledRoute.php";}s:39:"Symfony/Component/Routing/composer.json";a:4:{s:6:"md5sum";s:32:"e68bb57f1159982d6ccb4bf32818a790";s:4:"name";s:39:"Symfony/Component/Routing/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/doc/pear/Routing/Symfony/Component/Routing/composer.json";}s:58:"Symfony/Component/Routing/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"3d64f0b57c301a19b85b92d88902f492";s:4:"name";s:58:"Symfony/Component/Routing/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Exception/ExceptionInterface.php";}s:65:"Symfony/Component/Routing/Exception/InvalidParameterException.php";a:4:{s:6:"md5sum";s:32:"6b093524c85d31ed964c1da598962df7";s:4:"name";s:65:"Symfony/Component/Routing/Exception/InvalidParameterException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Exception/InvalidParameterException.php";}s:65:"Symfony/Component/Routing/Exception/MethodNotAllowedException.php";a:4:{s:6:"md5sum";s:32:"2c38201b0c1a4c837e95d468dd663e3b";s:4:"name";s:65:"Symfony/Component/Routing/Exception/MethodNotAllowedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Exception/MethodNotAllowedException.php";}s:75:"Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php";a:4:{s:6:"md5sum";s:32:"d2b4c2e8f43f6fd41e2c37bd6393d2d0";s:4:"name";s:75:"Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php";}s:65:"Symfony/Component/Routing/Exception/ResourceNotFoundException.php";a:4:{s:6:"md5sum";s:32:"a8e5469ab6552d46a8f20e6f7f63f76f";s:4:"name";s:65:"Symfony/Component/Routing/Exception/ResourceNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Exception/ResourceNotFoundException.php";}s:62:"Symfony/Component/Routing/Exception/RouteNotFoundException.php";a:4:{s:6:"md5sum";s:32:"5bf9cdaf9c5be880c320f3e547b7321c";s:4:"name";s:62:"Symfony/Component/Routing/Exception/RouteNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Exception/RouteNotFoundException.php";}s:73:"Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.php";a:4:{s:6:"md5sum";s:32:"a387ca727c49a190b907162d5cf0239e";s:4:"name";s:73:"Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.php";}s:62:"Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php";a:4:{s:6:"md5sum";s:32:"585bce412c6f8b482b00264f04f8904f";s:4:"name";s:62:"Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php";}s:71:"Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php";a:4:{s:6:"md5sum";s:32:"93d6bfa4c5d22436fdb2fabb49eb6116";s:4:"name";s:71:"Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php";}s:65:"Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php";a:4:{s:6:"md5sum";s:32:"0895f6715cb9ad1780264962b2e71b64";s:4:"name";s:65:"Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php";}s:52:"Symfony/Component/Routing/Generator/UrlGenerator.php";a:4:{s:6:"md5sum";s:32:"ae2d46c136e52ed92d5b3a0485406adc";s:4:"name";s:52:"Symfony/Component/Routing/Generator/UrlGenerator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Generator/UrlGenerator.php";}s:61:"Symfony/Component/Routing/Generator/UrlGeneratorInterface.php";a:4:{s:6:"md5sum";s:32:"8abf3d984c783ee04d6a04a1ede324bd";s:4:"name";s:61:"Symfony/Component/Routing/Generator/UrlGeneratorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Generator/UrlGeneratorInterface.php";}s:33:"Symfony/Component/Routing/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:33:"Symfony/Component/Routing/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/Routing/Symfony/Component/Routing/LICENSE";}s:58:"Symfony/Component/Routing/Loader/AnnotationClassLoader.php";a:4:{s:6:"md5sum";s:32:"dd2947b7d0e4a3806e8055fb51ba23ff";s:4:"name";s:58:"Symfony/Component/Routing/Loader/AnnotationClassLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/AnnotationClassLoader.php";}s:62:"Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php";a:4:{s:6:"md5sum";s:32:"7bea5831e2002735dee1875edf8526c6";s:4:"name";s:62:"Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php";}s:57:"Symfony/Component/Routing/Loader/AnnotationFileLoader.php";a:4:{s:6:"md5sum";s:32:"6119f0547ce407854362d4acb8eca23b";s:4:"name";s:57:"Symfony/Component/Routing/Loader/AnnotationFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/AnnotationFileLoader.php";}s:50:"Symfony/Component/Routing/Loader/ClosureLoader.php";a:4:{s:6:"md5sum";s:32:"401fa43c0b8ba75aee4d6ee205f5de8e";s:4:"name";s:50:"Symfony/Component/Routing/Loader/ClosureLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/ClosureLoader.php";}s:50:"Symfony/Component/Routing/Loader/PhpFileLoader.php";a:4:{s:6:"md5sum";s:32:"a19db6de99eb2baddcd560a30c232ecd";s:4:"name";s:50:"Symfony/Component/Routing/Loader/PhpFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/PhpFileLoader.php";}s:63:"Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd";a:4:{s:6:"md5sum";s:32:"e03178ea7d1f063fd89ee2c8218f5b78";s:4:"name";s:63:"Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd";}s:50:"Symfony/Component/Routing/Loader/XmlFileLoader.php";a:4:{s:6:"md5sum";s:32:"7e21f6c0b962f4cbb156dc81e73732a2";s:4:"name";s:50:"Symfony/Component/Routing/Loader/XmlFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/XmlFileLoader.php";}s:51:"Symfony/Component/Routing/Loader/YamlFileLoader.php";a:4:{s:6:"md5sum";s:32:"459710f5848da9859f1569234a0b578e";s:4:"name";s:51:"Symfony/Component/Routing/Loader/YamlFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/YamlFileLoader.php";}s:54:"Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php";a:4:{s:6:"md5sum";s:32:"507197805b62457c0fe43210c946e931";s:4:"name";s:54:"Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php";}s:64:"Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php";a:4:{s:6:"md5sum";s:32:"c5f1fa04cbb07a028e79f7c442fc87ca";s:4:"name";s:64:"Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php";}s:61:"Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php";a:4:{s:6:"md5sum";s:32:"df4c19109cb173cd91453733a9c97922";s:4:"name";s:61:"Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php";}s:67:"Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php";a:4:{s:6:"md5sum";s:32:"45c403eb0f5db93743a04d64c11e4b10";s:4:"name";s:67:"Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php";}s:56:"Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php";a:4:{s:6:"md5sum";s:32:"850971f7d3c0b766bb8b63bb7f59cd2e";s:4:"name";s:56:"Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php";}s:58:"Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php";a:4:{s:6:"md5sum";s:32:"d3d51e47a11338eb959efbc24c56d157";s:4:"name";s:58:"Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php";}s:67:"Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php";a:4:{s:6:"md5sum";s:32:"12d3638dbfcc3ecbc7e5e16c46b0a18c";s:4:"name";s:67:"Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php";}s:61:"Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php";a:4:{s:6:"md5sum";s:32:"9daade9ffbdeff369f03818ef2f73ce2";s:4:"name";s:61:"Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php";}s:60:"Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php";a:4:{s:6:"md5sum";s:32:"357c83fcf951bdb206fca135dca5bb07";s:4:"name";s:60:"Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php";}s:69:"Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php";a:4:{s:6:"md5sum";s:32:"001a000c9776f18c43a8ee4664b6e163";s:4:"name";s:69:"Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php";}s:61:"Symfony/Component/Routing/Matcher/RequestMatcherInterface.php";a:4:{s:6:"md5sum";s:32:"c623f743ec5d8113a010c2305f64b21e";s:4:"name";s:61:"Symfony/Component/Routing/Matcher/RequestMatcherInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php";}s:57:"Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php";a:4:{s:6:"md5sum";s:32:"6c48a62311dd625f0d624495e1d5d6e3";s:4:"name";s:57:"Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php";}s:48:"Symfony/Component/Routing/Matcher/UrlMatcher.php";a:4:{s:6:"md5sum";s:32:"0527f51011e56d17b92c0cd5ae204d54";s:4:"name";s:48:"Symfony/Component/Routing/Matcher/UrlMatcher.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/UrlMatcher.php";}s:57:"Symfony/Component/Routing/Matcher/UrlMatcherInterface.php";a:4:{s:6:"md5sum";s:32:"ebcef73fd69167569dbf16207a5cc2b4";s:4:"name";s:57:"Symfony/Component/Routing/Matcher/UrlMatcherInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php";}s:42:"Symfony/Component/Routing/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"306433f88b741f2d72b11ff338743859";s:4:"name";s:42:"Symfony/Component/Routing/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/phpunit.xml.dist";}s:35:"Symfony/Component/Routing/README.md";a:4:{s:6:"md5sum";s:32:"f72998925a6eca826c1fe39175f7b63b";s:4:"name";s:35:"Symfony/Component/Routing/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/doc/pear/Routing/Symfony/Component/Routing/README.md";}s:44:"Symfony/Component/Routing/RequestContext.php";a:4:{s:6:"md5sum";s:32:"516eaca4237df46d98fa7a57e8937fc2";s:4:"name";s:44:"Symfony/Component/Routing/RequestContext.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/RequestContext.php";}s:58:"Symfony/Component/Routing/RequestContextAwareInterface.php";a:4:{s:6:"md5sum";s:32:"2c9cdcdd343d5761f123e325f96027a2";s:4:"name";s:58:"Symfony/Component/Routing/RequestContextAwareInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/RequestContextAwareInterface.php";}s:35:"Symfony/Component/Routing/Route.php";a:4:{s:6:"md5sum";s:32:"a0b6b35abcbed3f170a90c9fa56703c1";s:4:"name";s:35:"Symfony/Component/Routing/Route.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Route.php";}s:45:"Symfony/Component/Routing/RouteCollection.php";a:4:{s:6:"md5sum";s:32:"d3c52daaaec1113c792edf9236828964";s:4:"name";s:45:"Symfony/Component/Routing/RouteCollection.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/RouteCollection.php";}s:43:"Symfony/Component/Routing/RouteCompiler.php";a:4:{s:6:"md5sum";s:32:"0dde56b2dd439922f60b19cc24ce00eb";s:4:"name";s:43:"Symfony/Component/Routing/RouteCompiler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/RouteCompiler.php";}s:52:"Symfony/Component/Routing/RouteCompilerInterface.php";a:4:{s:6:"md5sum";s:32:"9bade2ca282845cdce2120a21147f955";s:4:"name";s:52:"Symfony/Component/Routing/RouteCompilerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/RouteCompilerInterface.php";}s:36:"Symfony/Component/Routing/Router.php";a:4:{s:6:"md5sum";s:32:"cfa1e77acc20b94d2869303a3e343bdd";s:4:"name";s:36:"Symfony/Component/Routing/Router.php";s:4:"role";s:3:"php";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Router.php";}s:45:"Symfony/Component/Routing/RouterInterface.php";a:4:{s:6:"md5sum";s:32:"28c2b609f629bb9c437624f5f9897a7f";s:4:"name";s:45:"Symfony/Component/Routing/RouterInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/RouterInterface.php";}s:56:"Symfony/Component/Routing/Tests/Annotation/RouteTest.php";a:4:{s:6:"md5sum";s:32:"95f849d5323f5a02d2c1b26009cff39a";s:4:"name";s:56:"Symfony/Component/Routing/Tests/Annotation/RouteTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Annotation/RouteTest.php";}s:53:"Symfony/Component/Routing/Tests/CompiledRouteTest.php";a:4:{s:6:"md5sum";s:32:"329dc6eb58ed2841e9dff812a6f04f93";s:4:"name";s:53:"Symfony/Component/Routing/Tests/CompiledRouteTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/CompiledRouteTest.php";}s:54:"Symfony/Component/Routing/Tests/Fixtures/annotated.php";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:54:"Symfony/Component/Routing/Tests/Fixtures/annotated.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/annotated.php";}s:75:"Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php";a:4:{s:6:"md5sum";s:32:"8faac9caece520eabbf87e072d996583";s:4:"name";s:75:"Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php";}s:70:"Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.php";a:4:{s:6:"md5sum";s:32:"be20633112a29f2ada4e2989a31b7dc9";s:4:"name";s:70:"Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.php";}s:70:"Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php";a:4:{s:6:"md5sum";s:32:"1ec3b14820cead74554134842fa3498b";s:4:"name";s:70:"Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php";}s:64:"Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php";a:4:{s:6:"md5sum";s:32:"3cad48848f57310d3f0136f2cff860f2";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php";}s:67:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache";a:4:{s:6:"md5sum";s:32:"6ee192ca9034e12e89cb048b31f8e208";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache";}s:64:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php";a:4:{s:6:"md5sum";s:32:"371781bd5bc58854e49e0b583470c685";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php";}s:67:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache";a:4:{s:6:"md5sum";s:32:"24139b71d25f2706f9956ce94ec65d99";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache";}s:64:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php";a:4:{s:6:"md5sum";s:32:"3cd94c1ff96c25218039f7c6aefb56f2";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php";}s:64:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php";a:4:{s:6:"md5sum";s:32:"dd7da1ea21e2d886d079594d07e167dc";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php";}s:50:"Symfony/Component/Routing/Tests/Fixtures/empty.yml";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:50:"Symfony/Component/Routing/Tests/Fixtures/empty.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/empty.yml";}s:48:"Symfony/Component/Routing/Tests/Fixtures/foo.xml";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:48:"Symfony/Component/Routing/Tests/Fixtures/foo.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo.xml";}s:49:"Symfony/Component/Routing/Tests/Fixtures/foo1.xml";a:4:{s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:49:"Symfony/Component/Routing/Tests/Fixtures/foo1.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo1.xml";}s:55:"Symfony/Component/Routing/Tests/Fixtures/incomplete.yml";a:4:{s:6:"md5sum";s:32:"bf3dd20043754c68c898fdfa423fe222";s:4:"name";s:55:"Symfony/Component/Routing/Tests/Fixtures/incomplete.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/incomplete.yml";}s:55:"Symfony/Component/Routing/Tests/Fixtures/missing_id.xml";a:4:{s:6:"md5sum";s:32:"d8e1d3483f7f8ccf90232bd90127aa92";s:4:"name";s:55:"Symfony/Component/Routing/Tests/Fixtures/missing_id.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_id.xml";}s:57:"Symfony/Component/Routing/Tests/Fixtures/missing_path.xml";a:4:{s:6:"md5sum";s:32:"7cfffc2477dfdf9f9ae10de26b0fb51a";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/missing_path.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_path.xml";}s:60:"Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xml";a:4:{s:6:"md5sum";s:32:"cf3966d1a8d8470e67a08ae431058d0f";s:4:"name";s:60:"Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xml";}s:73:"Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.yml";a:4:{s:6:"md5sum";s:32:"0612cba8c11d5b3cb54e50b2c749c21c";s:4:"name";s:73:"Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.yml";}s:76:"Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.yml";a:4:{s:6:"md5sum";s:32:"8018429bdc8e300ac75c368660613c86";s:4:"name";s:76:"Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.yml";}s:53:"Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml";a:4:{s:6:"md5sum";s:32:"bc542914570693788cf3a8d2afbd45c2";s:4:"name";s:53:"Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml";}s:53:"Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml";a:4:{s:6:"md5sum";s:32:"d3b07384d113edec49eaa6238ad5ff00";s:4:"name";s:53:"Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml";}s:54:"Symfony/Component/Routing/Tests/Fixtures/nonvalid2.yml";a:4:{s:6:"md5sum";s:32:"55ada43e144278e471a7ba1cdd7cc295";s:4:"name";s:54:"Symfony/Component/Routing/Tests/Fixtures/nonvalid2.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid2.yml";}s:57:"Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml";a:4:{s:6:"md5sum";s:32:"70579c6820523185fc90f5373c3821fd";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml";}s:57:"Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml";a:4:{s:6:"md5sum";s:32:"c859068a6d836761e048cd0edb727dcb";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml";}s:58:"Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml";a:4:{s:6:"md5sum";s:32:"a4e93f76c7e4364bae051528417adfb2";s:4:"name";s:58:"Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml";}s:67:"Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php";a:4:{s:6:"md5sum";s:32:"682451e5c01e3d3dd757fc8919d1d43c";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php";}s:63:"Symfony/Component/Routing/Tests/Fixtures/special_route_name.yml";a:4:{s:6:"md5sum";s:32:"7586d7599fd0f4df8c339cb951e96497";s:4:"name";s:63:"Symfony/Component/Routing/Tests/Fixtures/special_route_name.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/special_route_name.yml";}s:57:"Symfony/Component/Routing/Tests/Fixtures/validpattern.php";a:4:{s:6:"md5sum";s:32:"38aeb5d4ba857600ef5c0215739453c5";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/validpattern.php";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.php";}s:57:"Symfony/Component/Routing/Tests/Fixtures/validpattern.xml";a:4:{s:6:"md5sum";s:32:"56524e1e940a4197127becdfd7268a10";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/validpattern.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml";}s:57:"Symfony/Component/Routing/Tests/Fixtures/validpattern.yml";a:4:{s:6:"md5sum";s:32:"24dd856c57527517f9280aaa43bef110";s:4:"name";s:57:"Symfony/Component/Routing/Tests/Fixtures/validpattern.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.yml";}s:58:"Symfony/Component/Routing/Tests/Fixtures/validresource.xml";a:4:{s:6:"md5sum";s:32:"839c3e52a85f8e4d6beee322a3115d93";s:4:"name";s:58:"Symfony/Component/Routing/Tests/Fixtures/validresource.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.xml";}s:58:"Symfony/Component/Routing/Tests/Fixtures/validresource.yml";a:4:{s:6:"md5sum";s:32:"e2fd3dead2fc9206e2d3fe8a33bfdedb";s:4:"name";s:58:"Symfony/Component/Routing/Tests/Fixtures/validresource.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.yml";}s:56:"Symfony/Component/Routing/Tests/Fixtures/withdoctype.xml";a:4:{s:6:"md5sum";s:32:"561c119c08673fd8436e11424a20d808";s:4:"name";s:56:"Symfony/Component/Routing/Tests/Fixtures/withdoctype.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/withdoctype.xml";}s:75:"Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php";a:4:{s:6:"md5sum";s:32:"7a9b9b426e9cbbe3c69b31c5a7ad0890";s:4:"name";s:75:"Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php";}s:62:"Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php";a:4:{s:6:"md5sum";s:32:"5d99c062e8a7e57006a53e6579ac95c0";s:4:"name";s:62:"Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php";}s:71:"Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php";a:4:{s:6:"md5sum";s:32:"5639a76d09ef4f3443810984ed8984ef";s:4:"name";s:71:"Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php";}s:68:"Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php";a:4:{s:6:"md5sum";s:32:"2f7f7a0c885391b6b97e8a99883ea05d";s:4:"name";s:68:"Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php";}s:72:"Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php";a:4:{s:6:"md5sum";s:32:"dbfce1fde62363437f0aa8a33613e97c";s:4:"name";s:72:"Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php";}s:67:"Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"4dfd29898087da820c09e85719a5c792";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php";}s:60:"Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php";a:4:{s:6:"md5sum";s:32:"7046a86d62fbf762f17b4776eccb4dc4";s:4:"name";s:60:"Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php";}s:60:"Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"a2ab975045a0d412efbf0d5ac222972c";s:4:"name";s:60:"Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php";}s:60:"Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"8d8319c0bc762ca704bb7908703d0c7e";s:4:"name";s:60:"Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php";}s:61:"Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"eebeb2d76e8045aa0098090259de5ee4";s:4:"name";s:61:"Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php";}s:64:"Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php";a:4:{s:6:"md5sum";s:32:"ba1d59f0b0d653e1aaf3ee0c6649bff7";s:4:"name";s:64:"Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php";}s:74:"Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php";a:4:{s:6:"md5sum";s:32:"0642be5053da073e465f18f1b8fd887d";s:4:"name";s:74:"Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php";}s:71:"Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.php";a:4:{s:6:"md5sum";s:32:"b35d71387dc9d1d3240600e639f1bd9c";s:4:"name";s:71:"Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.php";}s:77:"Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.php";a:4:{s:6:"md5sum";s:32:"4c13ddc57f8c8669a7d0527d745b8a68";s:4:"name";s:77:"Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.php";}s:71:"Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php";a:4:{s:6:"md5sum";s:32:"84d694ec0d369ec8cc64177e4a1dc08d";s:4:"name";s:71:"Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php";}s:70:"Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php";a:4:{s:6:"md5sum";s:32:"ea86e71e661f737eb99b92f42c9b6eb4";s:4:"name";s:70:"Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php";}s:67:"Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php";a:4:{s:6:"md5sum";s:32:"7ea68114d0c4d2f15535a6f6af9c4f16";s:4:"name";s:67:"Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php";}s:58:"Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php";a:4:{s:6:"md5sum";s:32:"59b53c89eb44b45ad22a2e44e3cd7eea";s:4:"name";s:58:"Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php";}s:54:"Symfony/Component/Routing/Tests/RequestContextTest.php";a:4:{s:6:"md5sum";s:32:"504c9fa5bc66cfd0cfa38d73fbacfee5";s:4:"name";s:54:"Symfony/Component/Routing/Tests/RequestContextTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/RequestContextTest.php";}s:55:"Symfony/Component/Routing/Tests/RouteCollectionTest.php";a:4:{s:6:"md5sum";s:32:"f9071d027efd59e4a55cfbbdd9af4819";s:4:"name";s:55:"Symfony/Component/Routing/Tests/RouteCollectionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/RouteCollectionTest.php";}s:53:"Symfony/Component/Routing/Tests/RouteCompilerTest.php";a:4:{s:6:"md5sum";s:32:"f0ee1d58dd4ec0723688cab9d08adc4e";s:4:"name";s:53:"Symfony/Component/Routing/Tests/RouteCompilerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/RouteCompilerTest.php";}s:46:"Symfony/Component/Routing/Tests/RouterTest.php";a:4:{s:6:"md5sum";s:32:"5188e029a746903602beab36af4502b7";s:4:"name";s:46:"Symfony/Component/Routing/Tests/RouterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/RouterTest.php";}s:45:"Symfony/Component/Routing/Tests/RouteTest.php";a:4:{s:6:"md5sum";s:32:"88ef12b30bd938f7583c2e9afc89b6f9";s:4:"name";s:45:"Symfony/Component/Routing/Tests/RouteTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/RouteTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:30:{s:66:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Annotation";b:1;s:55:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:67:"/opt/alt/php54/usr/share/doc/pear/Routing/Symfony/Component/Routing";b:1;s:59:"/opt/alt/php54/usr/share/doc/pear/Routing/Symfony/Component";b:1;s:49:"/opt/alt/php54/usr/share/doc/pear/Routing/Symfony";b:1;s:41:"/opt/alt/php54/usr/share/doc/pear/Routing";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Exception";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Generator";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Generator/Dumper";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/schema/routing";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Loader/schema";b:1;s:63:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher";b:1;s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Routing/Matcher/Dumper";b:1;s:68:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing";b:1;s:60:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component";b:1;s:50:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony";b:1;s:42:"/opt/alt/php54/usr/share/pear/test/Routing";b:1;s:85:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Annotation";b:1;s:74:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests";b:1;s:83:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses";b:1;s:90:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper";b:1;s:91:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Generator/Dumper";b:1;s:84:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Generator";b:1;s:81:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Loader";b:1;s:82:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:6:"Config";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:4:"Yaml";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!jORR..registry/.channel.pear.symfony.com/locale.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:6:"Locale";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:25:"Symfony2 Locale Component";s:11:"description";s:25:"Symfony2 Locale Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:48";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:35:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"542a733e26cbb9c622157b81f47f1482";s:4:"name";s:39:"Symfony/Component/Locale/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4c0b87688bb528a3a7ea580c26e45a55";s:4:"name";s:37:"Symfony/Component/Locale/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"492a08d5a533b5455b0c0f4a5278730a";s:4:"name";s:38:"Symfony/Component/Locale/composer.json";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c04c627983b2d98473c617463971669a";s:4:"name";s:76:"Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"37f4cb921e4bf39cffab88ca9c073957";s:4:"name";s:81:"Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0acb3d816693f31d77fe86ce33e12267";s:4:"name";s:68:"Symfony/Component/Locale/Exception/MethodNotImplementedException.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d9b3b933f5665a44fc234a81d8716e57";s:4:"name";s:62:"Symfony/Component/Locale/Exception/NotImplementedException.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:32:"Symfony/Component/Locale/LICENSE";s:4:"role";s:3:"doc";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c04b169bfa42cc7c6227cec9664e4778";s:4:"name";s:35:"Symfony/Component/Locale/Locale.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cb19198a8d7b5f9c20b7e5286dfc5399";s:4:"name";s:41:"Symfony/Component/Locale/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"53feb3fe807239186f141bdccd2c8a12";s:4:"name";s:34:"Symfony/Component/Locale/README.md";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"65d4e17de2f07c8974d5a1ba1ea8ecb9";s:4:"name";s:60:"Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0afa98da9f2d567ba83308042be5d57d";s:4:"name";s:65:"Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1556b0af9881cfe4a437c6a6c11877a9";s:4:"name";s:65:"Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"41dd3c3fa8529b6d21084f9cfef7e8f0";s:4:"name";s:59:"Symfony/Component/Locale/Stub/DateFormat/DayTransformer.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5df741e714305d31466a93d4ad487c80";s:4:"name";s:60:"Symfony/Component/Locale/Stub/DateFormat/FullTransformer.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1434500e2980f6118fe9f038fb154011";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8de2a07a2c433f79a3d31fb5c2c7ca77";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f5301ded09e7bb57fed47d3e8655a0f0";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a115ff0afd31e182e27ce4c5cc3d89e7";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1021c5207903eb1d01b40dcb3a502a84";s:4:"name";s:60:"Symfony/Component/Locale/Stub/DateFormat/HourTransformer.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"289e115d57e61733b8dd1b1646d7535d";s:4:"name";s:62:"Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ee9f1d1081ade3a43deba9c85376f120";s:4:"name";s:61:"Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ff38c4bfc0ebc8c6d14e5af40e1eb8ec";s:4:"name";s:63:"Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8ea0c30873f9f25be91854267f35f283";s:4:"name";s:62:"Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"38681181a097a88e205d05a25cb26ad6";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"551a2f8a32c86667a9d9a7e648a1a043";s:4:"name";s:56:"Symfony/Component/Locale/Stub/DateFormat/Transformer.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b9b0b8a353f49639e74f12e1ec85ba69";s:4:"name";s:60:"Symfony/Component/Locale/Stub/DateFormat/YearTransformer.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ecbf7ee2d715f64e448ac48c0ce1986f";s:4:"name";s:46:"Symfony/Component/Locale/Stub/StubCollator.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"33399ff7b83a42d5f3a4e1b0cf0db655";s:4:"name";s:42:"Symfony/Component/Locale/Stub/StubIntl.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80236bbeab6b375a842ab2e8f399eb1e";s:4:"name";s:55:"Symfony/Component/Locale/Stub/StubIntlDateFormatter.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fb93d653fed48a9b3a162af71e9edb2d";s:4:"name";s:44:"Symfony/Component/Locale/Stub/StubLocale.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"241d35bfb8ac82eea2203af325d08756";s:4:"name";s:53:"Symfony/Component/Locale/Stub/StubNumberFormatter.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"138590ade23ab1e386034814c8b118d0";s:4:"name";s:45:"Symfony/Component/Locale/Tests/LocaleTest.php";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"688a2326a62876a742c3aa76779ba504";s:4:"name";s:54:"Symfony/Component/Locale/Tests/Stub/StubLocaleTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:35:{s:39:"Symfony/Component/Locale/autoloader.php";a:4:{s:6:"md5sum";s:32:"542a733e26cbb9c622157b81f47f1482";s:4:"name";s:39:"Symfony/Component/Locale/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/autoloader.php";}s:37:"Symfony/Component/Locale/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"4c0b87688bb528a3a7ea580c26e45a55";s:4:"name";s:37:"Symfony/Component/Locale/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/doc/pear/Locale/Symfony/Component/Locale/CHANGELOG.md";}s:38:"Symfony/Component/Locale/composer.json";a:4:{s:6:"md5sum";s:32:"492a08d5a533b5455b0c0f4a5278730a";s:4:"name";s:38:"Symfony/Component/Locale/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/doc/pear/Locale/Symfony/Component/Locale/composer.json";}s:76:"Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.php";a:4:{s:6:"md5sum";s:32:"c04c627983b2d98473c617463971669a";s:4:"name";s:76:"Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Exception/MethodArgumentNotImplementedException.php";}s:81:"Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.php";a:4:{s:6:"md5sum";s:32:"37f4cb921e4bf39cffab88ca9c073957";s:4:"name";s:81:"Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.php";}s:68:"Symfony/Component/Locale/Exception/MethodNotImplementedException.php";a:4:{s:6:"md5sum";s:32:"0acb3d816693f31d77fe86ce33e12267";s:4:"name";s:68:"Symfony/Component/Locale/Exception/MethodNotImplementedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Exception/MethodNotImplementedException.php";}s:62:"Symfony/Component/Locale/Exception/NotImplementedException.php";a:4:{s:6:"md5sum";s:32:"d9b3b933f5665a44fc234a81d8716e57";s:4:"name";s:62:"Symfony/Component/Locale/Exception/NotImplementedException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Exception/NotImplementedException.php";}s:32:"Symfony/Component/Locale/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:32:"Symfony/Component/Locale/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/doc/pear/Locale/Symfony/Component/Locale/LICENSE";}s:35:"Symfony/Component/Locale/Locale.php";a:4:{s:6:"md5sum";s:32:"c04b169bfa42cc7c6227cec9664e4778";s:4:"name";s:35:"Symfony/Component/Locale/Locale.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Locale.php";}s:41:"Symfony/Component/Locale/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"cb19198a8d7b5f9c20b7e5286dfc5399";s:4:"name";s:41:"Symfony/Component/Locale/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/test/Locale/Symfony/Component/Locale/phpunit.xml.dist";}s:34:"Symfony/Component/Locale/README.md";a:4:{s:6:"md5sum";s:32:"53feb3fe807239186f141bdccd2c8a12";s:4:"name";s:34:"Symfony/Component/Locale/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/Locale/Symfony/Component/Locale/README.md";}s:60:"Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.php";a:4:{s:6:"md5sum";s:32:"65d4e17de2f07c8974d5a1ba1ea8ecb9";s:4:"name";s:60:"Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/AmPmTransformer.php";}s:65:"Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.php";a:4:{s:6:"md5sum";s:32:"0afa98da9f2d567ba83308042be5d57d";s:4:"name";s:65:"Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.php";}s:65:"Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.php";a:4:{s:6:"md5sum";s:32:"1556b0af9881cfe4a437c6a6c11877a9";s:4:"name";s:65:"Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.php";}s:59:"Symfony/Component/Locale/Stub/DateFormat/DayTransformer.php";a:4:{s:6:"md5sum";s:32:"41dd3c3fa8529b6d21084f9cfef7e8f0";s:4:"name";s:59:"Symfony/Component/Locale/Stub/DateFormat/DayTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/DayTransformer.php";}s:60:"Symfony/Component/Locale/Stub/DateFormat/FullTransformer.php";a:4:{s:6:"md5sum";s:32:"5df741e714305d31466a93d4ad487c80";s:4:"name";s:60:"Symfony/Component/Locale/Stub/DateFormat/FullTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/FullTransformer.php";}s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.php";a:4:{s:6:"md5sum";s:32:"1434500e2980f6118fe9f038fb154011";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.php";}s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.php";a:4:{s:6:"md5sum";s:32:"8de2a07a2c433f79a3d31fb5c2c7ca77";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.php";}s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.php";a:4:{s:6:"md5sum";s:32:"f5301ded09e7bb57fed47d3e8655a0f0";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.php";}s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.php";a:4:{s:6:"md5sum";s:32:"a115ff0afd31e182e27ce4c5cc3d89e7";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.php";}s:60:"Symfony/Component/Locale/Stub/DateFormat/HourTransformer.php";a:4:{s:6:"md5sum";s:32:"1021c5207903eb1d01b40dcb3a502a84";s:4:"name";s:60:"Symfony/Component/Locale/Stub/DateFormat/HourTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/HourTransformer.php";}s:62:"Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.php";a:4:{s:6:"md5sum";s:32:"289e115d57e61733b8dd1b1646d7535d";s:4:"name";s:62:"Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/MinuteTransformer.php";}s:61:"Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.php";a:4:{s:6:"md5sum";s:32:"ee9f1d1081ade3a43deba9c85376f120";s:4:"name";s:61:"Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/MonthTransformer.php";}s:63:"Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.php";a:4:{s:6:"md5sum";s:32:"ff38c4bfc0ebc8c6d14e5af40e1eb8ec";s:4:"name";s:63:"Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/QuarterTransformer.php";}s:62:"Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.php";a:4:{s:6:"md5sum";s:32:"8ea0c30873f9f25be91854267f35f283";s:4:"name";s:62:"Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/SecondTransformer.php";}s:64:"Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.php";a:4:{s:6:"md5sum";s:32:"38681181a097a88e205d05a25cb26ad6";s:4:"name";s:64:"Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.php";}s:56:"Symfony/Component/Locale/Stub/DateFormat/Transformer.php";a:4:{s:6:"md5sum";s:32:"551a2f8a32c86667a9d9a7e648a1a043";s:4:"name";s:56:"Symfony/Component/Locale/Stub/DateFormat/Transformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/Transformer.php";}s:60:"Symfony/Component/Locale/Stub/DateFormat/YearTransformer.php";a:4:{s:6:"md5sum";s:32:"b9b0b8a353f49639e74f12e1ec85ba69";s:4:"name";s:60:"Symfony/Component/Locale/Stub/DateFormat/YearTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat/YearTransformer.php";}s:46:"Symfony/Component/Locale/Stub/StubCollator.php";a:4:{s:6:"md5sum";s:32:"ecbf7ee2d715f64e448ac48c0ce1986f";s:4:"name";s:46:"Symfony/Component/Locale/Stub/StubCollator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/StubCollator.php";}s:42:"Symfony/Component/Locale/Stub/StubIntl.php";a:4:{s:6:"md5sum";s:32:"33399ff7b83a42d5f3a4e1b0cf0db655";s:4:"name";s:42:"Symfony/Component/Locale/Stub/StubIntl.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/StubIntl.php";}s:55:"Symfony/Component/Locale/Stub/StubIntlDateFormatter.php";a:4:{s:6:"md5sum";s:32:"80236bbeab6b375a842ab2e8f399eb1e";s:4:"name";s:55:"Symfony/Component/Locale/Stub/StubIntlDateFormatter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/StubIntlDateFormatter.php";}s:44:"Symfony/Component/Locale/Stub/StubLocale.php";a:4:{s:6:"md5sum";s:32:"fb93d653fed48a9b3a162af71e9edb2d";s:4:"name";s:44:"Symfony/Component/Locale/Stub/StubLocale.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/StubLocale.php";}s:53:"Symfony/Component/Locale/Stub/StubNumberFormatter.php";a:4:{s:6:"md5sum";s:32:"241d35bfb8ac82eea2203af325d08756";s:4:"name";s:53:"Symfony/Component/Locale/Stub/StubNumberFormatter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/StubNumberFormatter.php";}s:45:"Symfony/Component/Locale/Tests/LocaleTest.php";a:4:{s:6:"md5sum";s:32:"138590ade23ab1e386034814c8b118d0";s:4:"name";s:45:"Symfony/Component/Locale/Tests/LocaleTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/test/Locale/Symfony/Component/Locale/Tests/LocaleTest.php";}s:54:"Symfony/Component/Locale/Tests/Stub/StubLocaleTest.php";a:4:{s:6:"md5sum";s:32:"688a2326a62876a742c3aa76779ba504";s:4:"name";s:54:"Symfony/Component/Locale/Tests/Stub/StubLocaleTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/test/Locale/Symfony/Component/Locale/Tests/Stub/StubLocaleTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:16:{s:54:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:65:"/opt/alt/php54/usr/share/doc/pear/Locale/Symfony/Component/Locale";b:1;s:58:"/opt/alt/php54/usr/share/doc/pear/Locale/Symfony/Component";b:1;s:48:"/opt/alt/php54/usr/share/doc/pear/Locale/Symfony";b:1;s:40:"/opt/alt/php54/usr/share/doc/pear/Locale";b:1;s:64:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Exception";b:1;s:66:"/opt/alt/php54/usr/share/pear/test/Locale/Symfony/Component/Locale";b:1;s:59:"/opt/alt/php54/usr/share/pear/test/Locale/Symfony/Component";b:1;s:49:"/opt/alt/php54/usr/share/pear/test/Locale/Symfony";b:1;s:41:"/opt/alt/php54/usr/share/pear/test/Locale";b:1;s:70:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub/DateFormat";b:1;s:59:"/opt/alt/php54/usr/share/pear/Symfony/Component/Locale/Stub";b:1;s:72:"/opt/alt/php54/usr/share/pear/test/Locale/Symfony/Component/Locale/Tests";b:1;s:77:"/opt/alt/php54/usr/share/pear/test/Locale/Symfony/Component/Locale/Tests/Stub";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!eBEgg;.registry/.channel.pear.symfony.com/dependencyinjection.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:19:"DependencyInjection";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:38:"Symfony2 DependencyInjection Component";s:11:"description";s:38:"Symfony2 DependencyInjection Component";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:43";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:192:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8083d8117acb0fe0ea5dcd87cf7ffef7";s:4:"name";s:47:"Symfony/Component/DependencyInjection/Alias.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7879012b46b3b27b8d8414b844ca3537";s:4:"name";s:52:"Symfony/Component/DependencyInjection/autoloader.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"514e07efd3462ee25be372a3d60bbd80";s:4:"name";s:50:"Symfony/Component/DependencyInjection/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"675a6bc1d3c3f3b2783f885f0521178b";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6091faa40727a56f10ba2146abf615e1";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2b373903ccf9d566a6927aed6c3c6650";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"69b6713e0ee778e9b2cad497a9082151";s:4:"name";s:95:"Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b1410dc03224741083a4d762836a91b";s:4:"name";s:77:"Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"14bcd46172f5ac3e022e1d8f4fe1b08c";s:4:"name";s:59:"Symfony/Component/DependencyInjection/Compiler/Compiler.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1292a88c9fadf67d117a659fb0bfd499";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Compiler/CompilerPassInterface.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ec4dc3e58fc8046e43c0874a99ea29e6";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d18aa0d044d4725eaacd006c55b8e366";s:4:"name";s:67:"Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5015cca96bf517b4780e5acfbcce2142";s:4:"name";s:82:"Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8517ede71e527623a58dc3bca253c687";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Compiler/PassConfig.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"270937e454d381dae233d817e52069ec";s:4:"name";s:80:"Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"77d93353f41f2505251e003a33993f31";s:4:"name";s:75:"Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"82421fc37d82eeb210772fc9b5cc407d";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bee7b2336c610435c89fdc854101b604";s:4:"name";s:74:"Symfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f9167d35e36bf31d5aac396564f27bbb";s:4:"name";s:63:"Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0ece3d877daaabc8be38509d97752e2c";s:4:"name";s:85:"Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5e11621457d51880c84844518e300306";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"15580e12e088ce2dc2fc89936e27bdc0";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f33dfb27625ccb59d575de3fd0e3862f";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"69e660af3582cdacbfa328e0280a5740";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"965e8e3c37eea82b6eb961df50d9014d";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0e3f4ba1f08962ec73803a78f7a8c3f2";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ce32fc9229295bec473e33ce95cfe4d";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5ed58de81d8eb7d0d3d316ee27368e11";s:4:"name";s:51:"Symfony/Component/DependencyInjection/composer.json";s:4:"role";s:3:"doc";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d87452c514f1fd3daa1d76050329e0cc";s:4:"name";s:51:"Symfony/Component/DependencyInjection/Container.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4318c2ce4d160e6d183edce4928db696";s:4:"name";s:56:"Symfony/Component/DependencyInjection/ContainerAware.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4bbd2a21e9afe2cd25d26c37c54bfa9";s:4:"name";s:65:"Symfony/Component/DependencyInjection/ContainerAwareInterface.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"304f3c4322c235b332992d829d68e50b";s:4:"name";s:61:"Symfony/Component/DependencyInjection/ContainerAwareTrait.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6599366a3251af3d99243b49316fb9fe";s:4:"name";s:58:"Symfony/Component/DependencyInjection/ContainerBuilder.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2531b72281ed8336ff1afbb7ada89bb8";s:4:"name";s:60:"Symfony/Component/DependencyInjection/ContainerInterface.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"047285baeb298041af1ae447da6e55b3";s:4:"name";s:52:"Symfony/Component/DependencyInjection/Definition.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cf838655798392939269b928daeb17f3";s:4:"name";s:61:"Symfony/Component/DependencyInjection/DefinitionDecorator.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3b295c276bb774433a45f1ee0339a299";s:4:"name";s:55:"Symfony/Component/DependencyInjection/Dumper/Dumper.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b9dd1589f9ffac4366fd4148d9e78ade";s:4:"name";s:64:"Symfony/Component/DependencyInjection/Dumper/DumperInterface.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"688f77795fc125e75645706bf19ec8cf";s:4:"name";s:63:"Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bd310f7ab99d2c941dff3b3b402a1fd7";s:4:"name";s:58:"Symfony/Component/DependencyInjection/Dumper/PhpDumper.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"abe8dcd883cb0c698d7e91f2c600f45c";s:4:"name";s:58:"Symfony/Component/DependencyInjection/Dumper/XmlDumper.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"409f8a23d69eaa1272fd7cbb75d23026";s:4:"name";s:59:"Symfony/Component/DependencyInjection/Dumper/YamlDumper.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7881aa76d06f7b9e4bd45dc85ae0d52e";s:4:"name";s:74:"Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d79633abb224cffc0597be170aca74ea";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9022cb0f19ecaf1198318f0c178c5264";s:4:"name";s:74:"Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f1b09121e6850f5271d8bd3a6837efd3";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b78b4f59982df23deaf0242aec3d4a9";s:4:"name";s:66:"Symfony/Component/DependencyInjection/Exception/LogicException.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"792b235a45e9f4c0c7a7280580b1a2a3";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b059f59730003361cceadd8965ad7c5";s:4:"name";s:87:"Symfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6d83c2934f82a5ef7992b7081eaeffd7";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Exception/ParameterNotFoundException.php";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4e4d9c135fec917ae3fa78f25fbd7f85";s:4:"name";s:68:"Symfony/Component/DependencyInjection/Exception/RuntimeException.php";s:4:"role";s:3:"php";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0d73336fcf6534c59887f8b5687d1bd6";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"719ca3a89890fcb941cca1b16a0fafef";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php";s:4:"role";s:3:"php";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8ac40af4863b3c6cd9311cc1a29cf802";s:4:"name";s:85:"Symfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.php";s:4:"role";s:3:"php";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9785d054cb75a079dcecc97fc77a8ebb";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php";s:4:"role";s:3:"php";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3eebc81d79682bdbfe5ce43980d2ab92";s:4:"name";s:60:"Symfony/Component/DependencyInjection/ExpressionLanguage.php";s:4:"role";s:3:"php";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"819fae3f0bfd1d3ba7dd2a4fc29f89e8";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.php";s:4:"role";s:3:"php";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80cf4c6b7246bd342cf87699c23d0114";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Extension/Extension.php";s:4:"role";s:3:"php";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d9f5df364b37addf087305ce17842de9";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php";s:4:"role";s:3:"php";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0eea6361b5960d4ff58646b75864898f";s:4:"name";s:77:"Symfony/Component/DependencyInjection/Extension/PrependExtensionInterface.php";s:4:"role";s:3:"php";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"78118376c3e263f9eb58313ee1bb6f5a";s:4:"name";s:74:"Symfony/Component/DependencyInjection/IntrospectableContainerInterface.php";s:4:"role";s:3:"php";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2195bb770e5851fa1ebd680906ae112b";s:4:"name";s:86:"Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php";s:4:"role";s:3:"php";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bf8b05c0ab1b67dda36944d6a5d0d653";s:4:"name";s:88:"Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php";s:4:"role";s:3:"php";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0ff96280df12f153aee121649615763f";s:4:"name";s:77:"Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php";s:4:"role";s:3:"php";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8857647188554714f60a97a1a5f54fa0";s:4:"name";s:72:"Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php";s:4:"role";s:3:"php";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:45:"Symfony/Component/DependencyInjection/LICENSE";s:4:"role";s:3:"doc";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"262400ebaa94fc67c3cf2c89015cc395";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Loader/ClosureLoader.php";s:4:"role";s:3:"php";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"378be59c411306f23d8adb22fcaedad6";s:4:"name";s:59:"Symfony/Component/DependencyInjection/Loader/FileLoader.php";s:4:"role";s:3:"php";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"682de96cf34a4ac9f93d1e5c9d2cb153";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Loader/IniFileLoader.php";s:4:"role";s:3:"php";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ce3bf3b148cb1be2d7e30a5c589f9af9";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php";s:4:"role";s:3:"php";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"32beacc60968ee62e94f66672e3a7ec2";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd";s:4:"role";s:3:"php";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ed4c6f9c796d3986362a7a67dac9bc47";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php";s:4:"role";s:3:"php";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5df455b7334b17e89c9e094cf5978291";s:4:"name";s:63:"Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php";s:4:"role";s:3:"php";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7b2faf5e73ce778720b67e94cf6d2bba";s:4:"name";s:51:"Symfony/Component/DependencyInjection/Parameter.php";s:4:"role";s:3:"php";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c975b424d378e0060f13f23f218768d5";s:4:"name";s:73:"Symfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.php";s:4:"role";s:3:"php";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ce95aa07d7fe9d8e35dd1cf0af3b508e";s:4:"name";s:67:"Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php";s:4:"role";s:3:"php";}}i:76;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a1d6864e44ce2807160e6ccbd8e2d730";s:4:"name";s:76:"Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php";s:4:"role";s:3:"php";}}i:77;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e9b92b932a912fe805d01f4fa1d196d7";s:4:"name";s:54:"Symfony/Component/DependencyInjection/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:78;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1b27a3a51d5eeea9a6ee9fb5aed79c1f";s:4:"name";s:47:"Symfony/Component/DependencyInjection/README.md";s:4:"role";s:3:"doc";}}i:79;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a472c7a6d20af6710b87a299b9fdb855";s:4:"name";s:51:"Symfony/Component/DependencyInjection/Reference.php";s:4:"role";s:3:"php";}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d464293058a891542cef77f9e14e18b4";s:4:"name";s:47:"Symfony/Component/DependencyInjection/Scope.php";s:4:"role";s:3:"php";}}i:81;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b990c20640f9a64135bcf0369f4e22a6";s:4:"name";s:56:"Symfony/Component/DependencyInjection/ScopeInterface.php";s:4:"role";s:3:"php";}}i:82;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"66c75a60290a0461dc4e28feed7952dc";s:4:"name";s:58:"Symfony/Component/DependencyInjection/SimpleXMLElement.php";s:4:"role";s:3:"php";}}i:83;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3c47bde46b89617dcd69f4ebf5056865";s:4:"name";s:66:"Symfony/Component/DependencyInjection/TaggedContainerInterface.php";s:4:"role";s:3:"php";}}i:84;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d54cef7b3cb33ee1e7042d26c584f7fe";s:4:"name";s:89:"Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.php";s:4:"role";s:4:"test";}}i:85;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1a6f4aa36bb6dca84bcec6c5b3a4aa1f";s:4:"name";s:88:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php";s:4:"role";s:4:"test";}}i:86;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"637d842f3a08a0f1bce0921ba641c049";s:4:"name";s:88:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php";s:4:"role";s:4:"test";}}i:87;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8cecafcb0696950082f24bdc0ed79beb";s:4:"name";s:105:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php";s:4:"role";s:4:"test";}}i:88;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"150d6c72e7fa4958c3750097d6985874";s:4:"name";s:87:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php";s:4:"role";s:4:"test";}}i:89;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d38af5ce9bbb76b8b8e8ff4881347669";s:4:"name";s:89:"Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php";s:4:"role";s:4:"test";}}i:90;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6495d73686ede93887cf537f6e9ec0e9";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php";s:4:"role";s:4:"test";}}i:91;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"69e56c8a628567929f063b36ab9a2e84";s:4:"name";s:88:"Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.php";s:4:"role";s:4:"test";}}i:92;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d8a0328438ce5162a8b8585be178673d";s:4:"name";s:95:"Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php";s:4:"role";s:4:"test";}}i:93;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7547b1b316c37533be6820e12815f3cf";s:4:"name";s:91:"Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php";s:4:"role";s:4:"test";}}i:94;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2c41afba4dc70fc0f903ebe52befd642";s:4:"name";s:89:"Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php";s:4:"role";s:4:"test";}}i:95;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"13b4ec5501d3cba658a6973dcffa9799";s:4:"name";s:91:"Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php";s:4:"role";s:4:"test";}}i:96;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"aa9b5e5dc4e83673b333455f0d863130";s:4:"name";s:68:"Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php";s:4:"role";s:4:"test";}}i:97;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2ff857908d1e4161ea4c3dd8993c9a2";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Tests/ContainerTest.php";s:4:"role";s:4:"test";}}i:98;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ea1ce9dbce7920ea2631ffbfbead7658";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php";s:4:"role";s:4:"test";}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e5b34b5cef82e20befe6943b167b3dce";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php";s:4:"role";s:4:"test";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dbee36c02395ef4885ca72420bf98503";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Tests/DefinitionTest.php";s:4:"role";s:4:"test";}}i:101;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5518fa88c922a8c873133651e233386b";s:4:"name";s:73:"Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.php";s:4:"role";s:4:"test";}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"03e6215b1c0abc0fa0a11642e4786649";s:4:"name";s:68:"Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php";s:4:"role";s:4:"test";}}i:103;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"af6f3ad2f9b929dcbac53b8a48f122f3";s:4:"name";s:68:"Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php";s:4:"role";s:4:"test";}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d6ae9074c31ddfb3794ff731d60b20bb";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php";s:4:"role";s:4:"test";}}i:105;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"939faedda209b4d87552d4fe7cd7ca24";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php";s:4:"role";s:4:"test";}}i:106;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6422feace05a5ed96c42ed848d10006c";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php";s:4:"role";s:4:"test";}}i:107;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1ff966b209cd577bd0d6bb36d7e649e4";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php";s:4:"role";s:4:"test";}}i:108;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1acdceda33fce9015eff3bf7d156135b";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php";s:4:"role";s:4:"test";}}i:109;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"00b3703e57b5c9586ec0e398ea7a20b2";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.php";s:4:"role";s:4:"test";}}i:110;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b21b1c14c129dd16d9414a26aa263c45";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.php";s:4:"role";s:4:"test";}}i:111;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4bf1be8db545cde3ba7d0e6f6297308d";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php";s:4:"role";s:4:"test";}}i:112;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"098b361885203b2d00989fce70938512";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php";s:4:"role";s:4:"test";}}i:113;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f06eb418f0f04a719312f0e4ca232e9d";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.php";s:4:"role";s:4:"test";}}i:114;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a0ccfd20143be600667c0e98fb665071";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.php";s:4:"role";s:4:"test";}}i:115;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"02cffa6095e3a31d691a5bdcdbe7c227";s:4:"name";s:75:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dot";s:4:"role";s:4:"test";}}i:116;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5bf12610e2c2a95c5506a1b92ee929f6";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dot";s:4:"role";s:4:"test";}}i:117;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5eda7f5d745f7686812c80927819c499";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dot";s:4:"role";s:4:"test";}}i:118;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8f1d93f127c665d4f17b81c9cadc1e90";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services13.dot";s:4:"role";s:4:"test";}}i:119;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a7b7d8d68fc8e2f58dfd94d5de28604c";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services14.dot";s:4:"role";s:4:"test";}}i:120;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"17882b73c2f05f5bed8a8761f693ee75";s:4:"name";s:75:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot";s:4:"role";s:4:"test";}}i:121;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6c18955e7fff0a445ccd323169edfa39";s:4:"name";s:73:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php";s:4:"role";s:4:"test";}}i:122;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"658357428dc406d5f951a31a951a468b";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.php";s:4:"role";s:4:"test";}}i:123;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f38316643924184c25c2d323eb2115c8";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.php";s:4:"role";s:4:"test";}}i:124;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d378aa4475659bdd4d5d1d1a7898a5d8";s:4:"name";s:82:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.php";s:4:"role";s:4:"test";}}i:125;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2533e30245d301e424eb76b539244446";s:4:"name";s:89:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.php";s:4:"role";s:4:"test";}}i:126;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b4a17c6724b7c820a73579d094cdd932";s:4:"name";s:96:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtensionInPhar.phar";s:4:"role";s:4:"test";}}i:127;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cd16e7c41fc369846a5eb4a42d1e5b93";s:4:"name";s:84:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsd";s:4:"role";s:4:"test";}}i:128;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"547a11b176c7c7905611acd1582252d6";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ini";s:4:"role";s:4:"test";}}i:129;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4a8f0aad32fe89d804cb85703f0e2965";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ini";s:4:"role";s:4:"test";}}i:130;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cc1e7671d8c8e219998593b0069ac474";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ini";s:4:"role";s:4:"test";}}i:131;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e2432dcd44bad3082cff4aabce9d2f33";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ini";s:4:"role";s:4:"test";}}i:132;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"efe219ab816512283367c226a1656ee4";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php";s:4:"role";s:4:"test";}}i:133;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"99506344d5fcc588c963e91e473a06d1";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php";s:4:"role";s:4:"test";}}i:134;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9b7bf72ef23353c753f51bf557706ef4";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php";s:4:"role";s:4:"test";}}i:135;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"11e72fc308dfdadaedc9544c8756769b";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php";s:4:"role";s:4:"test";}}i:136;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"44b0afab75892ad4556743db23d1e629";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php";s:4:"role";s:4:"test";}}i:137;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80b20e5ead9c8ff04678100303294161";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php";s:4:"role";s:4:"test";}}i:138;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8e9a27269a37e19f37566f39801b484";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php";s:4:"role";s:4:"test";}}i:139;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0a223fc28b123a00eeae0ce7825953eb";s:4:"name";s:67:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.php";s:4:"role";s:4:"test";}}i:140;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d741c7a31311ead4df2057e523afeba3";s:4:"name";s:80:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xml";s:4:"role";s:4:"test";}}i:141;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f932ffc98518b016fc6383139b711c96";s:4:"name";s:80:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xml";s:4:"role";s:4:"test";}}i:142;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d144314f085c31ccb0a41f802f306649";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xml";s:4:"role";s:4:"test";}}i:143;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8a597cf4214e62043465a1d135cbf428";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xml";s:4:"role";s:4:"test";}}i:144;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2a00696fd70991a11a2aa0e1e5d61e75";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xml";s:4:"role";s:4:"test";}}i:145;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"340f21074d0ff685079b5fc0b80dacdf";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xml";s:4:"role";s:4:"test";}}i:146;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7dade70bc8de90a4c116d01df8744179";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xml";s:4:"role";s:4:"test";}}i:147;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"873eec7bf6988585b8be9ed78d32d4f0";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xml";s:4:"role";s:4:"test";}}i:148;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"834d96fb17d411d3c25df34a8e12339c";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xml";s:4:"role";s:4:"test";}}i:149;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e1fb95406c0ff63742800fdc95eb99f6";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xml";s:4:"role";s:4:"test";}}i:150;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d7c935e1400a979267225dfbe9519a9e";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml";s:4:"role";s:4:"test";}}i:151;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"525da15fe7d63e3e0f8ae78a96929107";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services10.xml";s:4:"role";s:4:"test";}}i:152;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0bed9c78fc2a7b638d81d6e948474ed9";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xml";s:4:"role";s:4:"test";}}i:153;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"af73c797e9dabde154c0460a294ab77d";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml";s:4:"role";s:4:"test";}}i:154;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b8fbad821d7f9b92a37c6ec30fbb8a9";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xml";s:4:"role";s:4:"test";}}i:155;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b6edb71e890234adad9ebb17e88fb6f";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xml";s:4:"role";s:4:"test";}}i:156;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"53040074af5e742e3e7bc6a820f0b17d";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xml";s:4:"role";s:4:"test";}}i:157;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6f50270290cb9bafc719886743286773";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml";s:4:"role";s:4:"test";}}i:158;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"15f37e20652d85a361cccc6a6f9322ac";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml";s:4:"role";s:4:"test";}}i:159;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3f0cd2a9228c7f1479f535b48beb3f21";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xml";s:4:"role";s:4:"test";}}i:160;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"71f5c7df64436e6adf6fb4457d7b5075";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml";s:4:"role";s:4:"test";}}i:161;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ca60e6bf5f65fff971f8d13a644a9acb";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml";s:4:"role";s:4:"test";}}i:162;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"561c119c08673fd8436e11424a20d808";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/withdoctype.xml";s:4:"role";s:4:"test";}}i:163;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2b4b910651d1e7de3a74cc6872184be8";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.yml";s:4:"role";s:4:"test";}}i:164;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2651cca5fcafb2d3328d2d18cc825f2f";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.yml";s:4:"role";s:4:"test";}}i:165;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8b67ba68bb2c5551ac4bc3f7a865839d";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.yml";s:4:"role";s:4:"test";}}i:166;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"037bf52fe0bfa7b643b837d08dfdf92d";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.yml";s:4:"role";s:4:"test";}}i:167;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d42f2da1df5ecdf29be4ac27edda0c12";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.yml";s:4:"role";s:4:"test";}}i:168;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"68b329da9893e34099c7d8ad5cb9c940";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml";s:4:"role";s:4:"test";}}i:169;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"98428e36b00061da1b64b1e64781e4d0";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml";s:4:"role";s:4:"test";}}i:170;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8fc6f5242a9a9a0092dcc9387e2f826c";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.yml";s:4:"role";s:4:"test";}}i:171;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9ed1d963ba546e9772a3808f08a91376";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.yml";s:4:"role";s:4:"test";}}i:172;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"be17d9c22568cf11a27193704cc13703";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml";s:4:"role";s:4:"test";}}i:173;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2011daeb4d44240efd2caddf60d84038";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.yml";s:4:"role";s:4:"test";}}i:174;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3e738ce0eb54d9aa53021bb09649e45b";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml";s:4:"role";s:4:"test";}}i:175;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d1b518eb8021cccac6ac53ffc1157781";s:4:"name";s:82:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.yml";s:4:"role";s:4:"test";}}i:176;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6f37efe61e948638cb95cbeebee34a7d";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml";s:4:"role";s:4:"test";}}i:177;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6de30e3ec6f5769fffa3a84921d5ea58";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.yml";s:4:"role";s:4:"test";}}i:178;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2d887f6e7ab72fc1ef7710f090ac6892";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml";s:4:"role";s:4:"test";}}i:179;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0c0c237a0f162b1035bc9a31bfb7e3f3";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml";s:4:"role";s:4:"test";}}i:180;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b26bc2f643dea09195075d0096e874a0";s:4:"name";s:98:"Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php";s:4:"role";s:4:"test";}}i:181;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e0c0229d4f3141bae74c4bbe30a06b21";s:4:"name";s:82:"Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php";s:4:"role";s:4:"test";}}i:182;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"97399006240deb90b22bcdb49ab08f61";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.php";s:4:"role";s:4:"test";}}i:183;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8e3c7ae75fb774783dc26b6c33ca93f5";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php";s:4:"role";s:4:"test";}}i:184;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c26312ff35c5941814fe09fdfecf216e";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php";s:4:"role";s:4:"test";}}i:185;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d702b36279525fb4751489f2e3285414";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php";s:4:"role";s:4:"test";}}i:186;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3ae936ba0577f3144075883fc4a845ce";s:4:"name";s:73:"Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php";s:4:"role";s:4:"test";}}i:187;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f967ec9e8b4a79bf91bd5b4675fbc70c";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.php";s:4:"role";s:4:"test";}}i:188;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6db6b2ca8ed272df55332f0916be0ad9";s:4:"name";s:77:"Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php";s:4:"role";s:4:"test";}}i:189;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"965987dd3ddde1039ebe8c42d83a241b";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Tests/ParameterTest.php";s:4:"role";s:4:"test";}}i:190;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"203939f24651f40960e928d69a8c6a08";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Tests/ReferenceTest.php";s:4:"role";s:4:"test";}}i:191;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ed13f0022bf056748456b80c702dbe21";s:4:"name";s:50:"Symfony/Component/DependencyInjection/Variable.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}s:8:"optional";a:1:{s:7:"package";a:2:{i:0;a:2:{s:4:"name";s:6:"Config";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:4:"Yaml";s:7:"channel";s:16:"pear.symfony.com";}}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:192:{s:47:"Symfony/Component/DependencyInjection/Alias.php";a:4:{s:6:"md5sum";s:32:"8083d8117acb0fe0ea5dcd87cf7ffef7";s:4:"name";s:47:"Symfony/Component/DependencyInjection/Alias.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Alias.php";}s:52:"Symfony/Component/DependencyInjection/autoloader.php";a:4:{s:6:"md5sum";s:32:"7879012b46b3b27b8d8414b844ca3537";s:4:"name";s:52:"Symfony/Component/DependencyInjection/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/autoloader.php";}s:50:"Symfony/Component/DependencyInjection/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"514e07efd3462ee25be372a3d60bbd80";s:4:"name";s:50:"Symfony/Component/DependencyInjection/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/doc/pear/DependencyInjection/Symfony/Component/DependencyInjection/CHANGELOG.md";}s:79:"Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php";a:4:{s:6:"md5sum";s:32:"675a6bc1d3c3f3b2783f885f0521178b";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php";}s:78:"Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php";a:4:{s:6:"md5sum";s:32:"6091faa40727a56f10ba2146abf615e1";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php";}s:78:"Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php";a:4:{s:6:"md5sum";s:32:"2b373903ccf9d566a6927aed6c3c6650";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php";}s:95:"Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php";a:4:{s:6:"md5sum";s:32:"69b6713e0ee778e9b2cad497a9082151";s:4:"name";s:95:"Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php";}s:77:"Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php";a:4:{s:6:"md5sum";s:32:"7b1410dc03224741083a4d762836a91b";s:4:"name";s:77:"Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php";}s:59:"Symfony/Component/DependencyInjection/Compiler/Compiler.php";a:4:{s:6:"md5sum";s:32:"14bcd46172f5ac3e022e1d8f4fe1b08c";s:4:"name";s:59:"Symfony/Component/DependencyInjection/Compiler/Compiler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/Compiler.php";}s:72:"Symfony/Component/DependencyInjection/Compiler/CompilerPassInterface.php";a:4:{s:6:"md5sum";s:32:"1292a88c9fadf67d117a659fb0bfd499";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Compiler/CompilerPassInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/CompilerPassInterface.php";}s:79:"Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php";a:4:{s:6:"md5sum";s:32:"ec4dc3e58fc8046e43c0874a99ea29e6";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php";}s:67:"Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php";a:4:{s:6:"md5sum";s:32:"d18aa0d044d4725eaacd006c55b8e366";s:4:"name";s:67:"Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php";}s:82:"Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php";a:4:{s:6:"md5sum";s:32:"5015cca96bf517b4780e5acfbcce2142";s:4:"name";s:82:"Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:112:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php";}s:61:"Symfony/Component/DependencyInjection/Compiler/PassConfig.php";a:4:{s:6:"md5sum";s:32:"8517ede71e527623a58dc3bca253c687";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Compiler/PassConfig.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/PassConfig.php";}s:80:"Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php";a:4:{s:6:"md5sum";s:32:"270937e454d381dae233d817e52069ec";s:4:"name";s:80:"Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php";}s:75:"Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php";a:4:{s:6:"md5sum";s:32:"77d93353f41f2505251e003a33993f31";s:4:"name";s:75:"Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php";}s:78:"Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php";a:4:{s:6:"md5sum";s:32:"82421fc37d82eeb210772fc9b5cc407d";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php";}s:74:"Symfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.php";a:4:{s:6:"md5sum";s:32:"bee7b2336c610435c89fdc854101b604";s:4:"name";s:74:"Symfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.php";}s:63:"Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php";a:4:{s:6:"md5sum";s:32:"f9167d35e36bf31d5aac396564f27bbb";s:4:"name";s:63:"Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php";}s:85:"Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php";a:4:{s:6:"md5sum";s:32:"0ece3d877daaabc8be38509d97752e2c";s:4:"name";s:85:"Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php";}s:81:"Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php";a:4:{s:6:"md5sum";s:32:"5e11621457d51880c84844518e300306";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php";}s:79:"Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php";a:4:{s:6:"md5sum";s:32:"15580e12e088ce2dc2fc89936e27bdc0";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php";}s:83:"Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php";a:4:{s:6:"md5sum";s:32:"f33dfb27625ccb59d575de3fd0e3862f";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php";}s:81:"Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php";a:4:{s:6:"md5sum";s:32:"69e660af3582cdacbfa328e0280a5740";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php";}s:72:"Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php";a:4:{s:6:"md5sum";s:32:"965e8e3c37eea82b6eb961df50d9014d";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php";}s:76:"Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php";a:4:{s:6:"md5sum";s:32:"0e3f4ba1f08962ec73803a78f7a8c3f2";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php";}s:76:"Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php";a:4:{s:6:"md5sum";s:32:"3ce32fc9229295bec473e33ce95cfe4d";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php";}s:51:"Symfony/Component/DependencyInjection/composer.json";a:4:{s:6:"md5sum";s:32:"5ed58de81d8eb7d0d3d316ee27368e11";s:4:"name";s:51:"Symfony/Component/DependencyInjection/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/doc/pear/DependencyInjection/Symfony/Component/DependencyInjection/composer.json";}s:51:"Symfony/Component/DependencyInjection/Container.php";a:4:{s:6:"md5sum";s:32:"d87452c514f1fd3daa1d76050329e0cc";s:4:"name";s:51:"Symfony/Component/DependencyInjection/Container.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Container.php";}s:56:"Symfony/Component/DependencyInjection/ContainerAware.php";a:4:{s:6:"md5sum";s:32:"4318c2ce4d160e6d183edce4928db696";s:4:"name";s:56:"Symfony/Component/DependencyInjection/ContainerAware.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ContainerAware.php";}s:65:"Symfony/Component/DependencyInjection/ContainerAwareInterface.php";a:4:{s:6:"md5sum";s:32:"b4bbd2a21e9afe2cd25d26c37c54bfa9";s:4:"name";s:65:"Symfony/Component/DependencyInjection/ContainerAwareInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ContainerAwareInterface.php";}s:61:"Symfony/Component/DependencyInjection/ContainerAwareTrait.php";a:4:{s:6:"md5sum";s:32:"304f3c4322c235b332992d829d68e50b";s:4:"name";s:61:"Symfony/Component/DependencyInjection/ContainerAwareTrait.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ContainerAwareTrait.php";}s:58:"Symfony/Component/DependencyInjection/ContainerBuilder.php";a:4:{s:6:"md5sum";s:32:"6599366a3251af3d99243b49316fb9fe";s:4:"name";s:58:"Symfony/Component/DependencyInjection/ContainerBuilder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ContainerBuilder.php";}s:60:"Symfony/Component/DependencyInjection/ContainerInterface.php";a:4:{s:6:"md5sum";s:32:"2531b72281ed8336ff1afbb7ada89bb8";s:4:"name";s:60:"Symfony/Component/DependencyInjection/ContainerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ContainerInterface.php";}s:52:"Symfony/Component/DependencyInjection/Definition.php";a:4:{s:6:"md5sum";s:32:"047285baeb298041af1ae447da6e55b3";s:4:"name";s:52:"Symfony/Component/DependencyInjection/Definition.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Definition.php";}s:61:"Symfony/Component/DependencyInjection/DefinitionDecorator.php";a:4:{s:6:"md5sum";s:32:"cf838655798392939269b928daeb17f3";s:4:"name";s:61:"Symfony/Component/DependencyInjection/DefinitionDecorator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/DefinitionDecorator.php";}s:55:"Symfony/Component/DependencyInjection/Dumper/Dumper.php";a:4:{s:6:"md5sum";s:32:"3b295c276bb774433a45f1ee0339a299";s:4:"name";s:55:"Symfony/Component/DependencyInjection/Dumper/Dumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Dumper/Dumper.php";}s:64:"Symfony/Component/DependencyInjection/Dumper/DumperInterface.php";a:4:{s:6:"md5sum";s:32:"b9dd1589f9ffac4366fd4148d9e78ade";s:4:"name";s:64:"Symfony/Component/DependencyInjection/Dumper/DumperInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Dumper/DumperInterface.php";}s:63:"Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php";a:4:{s:6:"md5sum";s:32:"688f77795fc125e75645706bf19ec8cf";s:4:"name";s:63:"Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php";}s:58:"Symfony/Component/DependencyInjection/Dumper/PhpDumper.php";a:4:{s:6:"md5sum";s:32:"bd310f7ab99d2c941dff3b3b402a1fd7";s:4:"name";s:58:"Symfony/Component/DependencyInjection/Dumper/PhpDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php";}s:58:"Symfony/Component/DependencyInjection/Dumper/XmlDumper.php";a:4:{s:6:"md5sum";s:32:"abe8dcd883cb0c698d7e91f2c600f45c";s:4:"name";s:58:"Symfony/Component/DependencyInjection/Dumper/XmlDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php";}s:59:"Symfony/Component/DependencyInjection/Dumper/YamlDumper.php";a:4:{s:6:"md5sum";s:32:"409f8a23d69eaa1272fd7cbb75d23026";s:4:"name";s:59:"Symfony/Component/DependencyInjection/Dumper/YamlDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php";}s:74:"Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php";a:4:{s:6:"md5sum";s:32:"7881aa76d06f7b9e4bd45dc85ae0d52e";s:4:"name";s:74:"Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php";}s:70:"Symfony/Component/DependencyInjection/Exception/ExceptionInterface.php";a:4:{s:6:"md5sum";s:32:"d79633abb224cffc0597be170aca74ea";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Exception/ExceptionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/ExceptionInterface.php";}s:74:"Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php";a:4:{s:6:"md5sum";s:32:"9022cb0f19ecaf1198318f0c178c5264";s:4:"name";s:74:"Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php";}s:76:"Symfony/Component/DependencyInjection/Exception/InvalidArgumentException.php";a:4:{s:6:"md5sum";s:32:"f1b09121e6850f5271d8bd3a6837efd3";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Exception/InvalidArgumentException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/InvalidArgumentException.php";}s:66:"Symfony/Component/DependencyInjection/Exception/LogicException.php";a:4:{s:6:"md5sum";s:32:"5b78b4f59982df23deaf0242aec3d4a9";s:4:"name";s:66:"Symfony/Component/DependencyInjection/Exception/LogicException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/LogicException.php";}s:72:"Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php";a:4:{s:6:"md5sum";s:32:"792b235a45e9f4c0c7a7280580b1a2a3";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php";}s:87:"Symfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.php";a:4:{s:6:"md5sum";s:32:"7b059f59730003361cceadd8965ad7c5";s:4:"name";s:87:"Symfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.php";}s:78:"Symfony/Component/DependencyInjection/Exception/ParameterNotFoundException.php";a:4:{s:6:"md5sum";s:32:"6d83c2934f82a5ef7992b7081eaeffd7";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Exception/ParameterNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/ParameterNotFoundException.php";}s:68:"Symfony/Component/DependencyInjection/Exception/RuntimeException.php";a:4:{s:6:"md5sum";s:32:"4e4d9c135fec917ae3fa78f25fbd7f85";s:4:"name";s:68:"Symfony/Component/DependencyInjection/Exception/RuntimeException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:98:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/RuntimeException.php";}s:83:"Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php";a:4:{s:6:"md5sum";s:32:"0d73336fcf6534c59887f8b5687d1bd6";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php";}s:83:"Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php";a:4:{s:6:"md5sum";s:32:"719ca3a89890fcb941cca1b16a0fafef";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php";}s:85:"Symfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.php";a:4:{s:6:"md5sum";s:32:"8ac40af4863b3c6cd9311cc1a29cf802";s:4:"name";s:85:"Symfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.php";}s:76:"Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php";a:4:{s:6:"md5sum";s:32:"9785d054cb75a079dcecc97fc77a8ebb";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php";}s:60:"Symfony/Component/DependencyInjection/ExpressionLanguage.php";a:4:{s:6:"md5sum";s:32:"3eebc81d79682bdbfe5ce43980d2ab92";s:4:"name";s:60:"Symfony/Component/DependencyInjection/ExpressionLanguage.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ExpressionLanguage.php";}s:83:"Symfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.php";a:4:{s:6:"md5sum";s:32:"819fae3f0bfd1d3ba7dd2a4fc29f89e8";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.php";}s:61:"Symfony/Component/DependencyInjection/Extension/Extension.php";a:4:{s:6:"md5sum";s:32:"80cf4c6b7246bd342cf87699c23d0114";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Extension/Extension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Extension/Extension.php";}s:70:"Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php";a:4:{s:6:"md5sum";s:32:"d9f5df364b37addf087305ce17842de9";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:100:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php";}s:77:"Symfony/Component/DependencyInjection/Extension/PrependExtensionInterface.php";a:4:{s:6:"md5sum";s:32:"0eea6361b5960d4ff58646b75864898f";s:4:"name";s:77:"Symfony/Component/DependencyInjection/Extension/PrependExtensionInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Extension/PrependExtensionInterface.php";}s:74:"Symfony/Component/DependencyInjection/IntrospectableContainerInterface.php";a:4:{s:6:"md5sum";s:32:"78118376c3e263f9eb58313ee1bb6f5a";s:4:"name";s:74:"Symfony/Component/DependencyInjection/IntrospectableContainerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:104:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/IntrospectableContainerInterface.php";}s:86:"Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php";a:4:{s:6:"md5sum";s:32:"2195bb770e5851fa1ebd680906ae112b";s:4:"name";s:86:"Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php";}s:88:"Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php";a:4:{s:6:"md5sum";s:32:"bf8b05c0ab1b67dda36944d6a5d0d653";s:4:"name";s:88:"Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:118:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php";}s:77:"Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php";a:4:{s:6:"md5sum";s:32:"0ff96280df12f153aee121649615763f";s:4:"name";s:77:"Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php";}s:72:"Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php";a:4:{s:6:"md5sum";s:32:"8857647188554714f60a97a1a5f54fa0";s:4:"name";s:72:"Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:102:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php";}s:45:"Symfony/Component/DependencyInjection/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:45:"Symfony/Component/DependencyInjection/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/doc/pear/DependencyInjection/Symfony/Component/DependencyInjection/LICENSE";}s:62:"Symfony/Component/DependencyInjection/Loader/ClosureLoader.php";a:4:{s:6:"md5sum";s:32:"262400ebaa94fc67c3cf2c89015cc395";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Loader/ClosureLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/ClosureLoader.php";}s:59:"Symfony/Component/DependencyInjection/Loader/FileLoader.php";a:4:{s:6:"md5sum";s:32:"378be59c411306f23d8adb22fcaedad6";s:4:"name";s:59:"Symfony/Component/DependencyInjection/Loader/FileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/FileLoader.php";}s:62:"Symfony/Component/DependencyInjection/Loader/IniFileLoader.php";a:4:{s:6:"md5sum";s:32:"682de96cf34a4ac9f93d1e5c9d2cb153";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Loader/IniFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/IniFileLoader.php";}s:62:"Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php";a:4:{s:6:"md5sum";s:32:"ce3bf3b148cb1be2d7e30a5c589f9af9";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php";}s:81:"Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd";a:4:{s:6:"md5sum";s:32:"32beacc60968ee62e94f66672e3a7ec2";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd";}s:62:"Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php";a:4:{s:6:"md5sum";s:32:"ed4c6f9c796d3986362a7a67dac9bc47";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php";}s:63:"Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php";a:4:{s:6:"md5sum";s:32:"5df455b7334b17e89c9e094cf5978291";s:4:"name";s:63:"Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php";}s:51:"Symfony/Component/DependencyInjection/Parameter.php";a:4:{s:6:"md5sum";s:32:"7b2faf5e73ce778720b67e94cf6d2bba";s:4:"name";s:51:"Symfony/Component/DependencyInjection/Parameter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Parameter.php";}s:73:"Symfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.php";a:4:{s:6:"md5sum";s:32:"c975b424d378e0060f13f23f218768d5";s:4:"name";s:73:"Symfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.php";}s:67:"Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php";a:4:{s:6:"md5sum";s:32:"ce95aa07d7fe9d8e35dd1cf0af3b508e";s:4:"name";s:67:"Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php";}s:76:"Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php";a:4:{s:6:"md5sum";s:32:"a1d6864e44ce2807160e6ccbd8e2d730";s:4:"name";s:76:"Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:106:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php";}s:54:"Symfony/Component/DependencyInjection/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"e9b92b932a912fe805d01f4fa1d196d7";s:4:"name";s:54:"Symfony/Component/DependencyInjection/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/phpunit.xml.dist";}s:47:"Symfony/Component/DependencyInjection/README.md";a:4:{s:6:"md5sum";s:32:"1b27a3a51d5eeea9a6ee9fb5aed79c1f";s:4:"name";s:47:"Symfony/Component/DependencyInjection/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/doc/pear/DependencyInjection/Symfony/Component/DependencyInjection/README.md";}s:51:"Symfony/Component/DependencyInjection/Reference.php";a:4:{s:6:"md5sum";s:32:"a472c7a6d20af6710b87a299b9fdb855";s:4:"name";s:51:"Symfony/Component/DependencyInjection/Reference.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Reference.php";}s:47:"Symfony/Component/DependencyInjection/Scope.php";a:4:{s:6:"md5sum";s:32:"d464293058a891542cef77f9e14e18b4";s:4:"name";s:47:"Symfony/Component/DependencyInjection/Scope.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Scope.php";}s:56:"Symfony/Component/DependencyInjection/ScopeInterface.php";a:4:{s:6:"md5sum";s:32:"b990c20640f9a64135bcf0369f4e22a6";s:4:"name";s:56:"Symfony/Component/DependencyInjection/ScopeInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ScopeInterface.php";}s:58:"Symfony/Component/DependencyInjection/SimpleXMLElement.php";a:4:{s:6:"md5sum";s:32:"66c75a60290a0461dc4e28feed7952dc";s:4:"name";s:58:"Symfony/Component/DependencyInjection/SimpleXMLElement.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/SimpleXMLElement.php";}s:66:"Symfony/Component/DependencyInjection/TaggedContainerInterface.php";a:4:{s:6:"md5sum";s:32:"3c47bde46b89617dcd69f4ebf5056865";s:4:"name";s:66:"Symfony/Component/DependencyInjection/TaggedContainerInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/TaggedContainerInterface.php";}s:89:"Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.php";a:4:{s:6:"md5sum";s:32:"d54cef7b3cb33ee1e7042d26c584f7fe";s:4:"name";s:89:"Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:144:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.php";}s:88:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php";a:4:{s:6:"md5sum";s:32:"1a6f4aa36bb6dca84bcec6c5b3a4aa1f";s:4:"name";s:88:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:143:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php";}s:88:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php";a:4:{s:6:"md5sum";s:32:"637d842f3a08a0f1bce0921ba641c049";s:4:"name";s:88:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:143:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php";}s:105:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php";a:4:{s:6:"md5sum";s:32:"8cecafcb0696950082f24bdc0ed79beb";s:4:"name";s:105:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:160:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php";}s:87:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php";a:4:{s:6:"md5sum";s:32:"150d6c72e7fa4958c3750097d6985874";s:4:"name";s:87:"Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:142:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php";}s:89:"Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php";a:4:{s:6:"md5sum";s:32:"d38af5ce9bbb76b8b8e8ff4881347669";s:4:"name";s:89:"Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:144:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php";}s:72:"Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php";a:4:{s:6:"md5sum";s:32:"6495d73686ede93887cf537f6e9ec0e9";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php";}s:88:"Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.php";a:4:{s:6:"md5sum";s:32:"69e56c8a628567929f063b36ab9a2e84";s:4:"name";s:88:"Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:143:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.php";}s:95:"Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php";a:4:{s:6:"md5sum";s:32:"d8a0328438ce5162a8b8585be178673d";s:4:"name";s:95:"Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:150:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php";}s:91:"Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php";a:4:{s:6:"md5sum";s:32:"7547b1b316c37533be6820e12815f3cf";s:4:"name";s:91:"Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:146:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php";}s:89:"Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php";a:4:{s:6:"md5sum";s:32:"2c41afba4dc70fc0f903ebe52befd642";s:4:"name";s:89:"Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:144:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php";}s:91:"Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php";a:4:{s:6:"md5sum";s:32:"13b4ec5501d3cba658a6973dcffa9799";s:4:"name";s:91:"Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:146:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php";}s:68:"Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php";a:4:{s:6:"md5sum";s:32:"aa9b5e5dc4e83673b333455f0d863130";s:4:"name";s:68:"Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php";}s:61:"Symfony/Component/DependencyInjection/Tests/ContainerTest.php";a:4:{s:6:"md5sum";s:32:"e2ff857908d1e4161ea4c3dd8993c9a2";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Tests/ContainerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerTest.php";}s:62:"Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php";a:4:{s:6:"md5sum";s:32:"ea1ce9dbce7920ea2631ffbfbead7658";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php";}s:71:"Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php";a:4:{s:6:"md5sum";s:32:"e5b34b5cef82e20befe6943b167b3dce";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php";}s:62:"Symfony/Component/DependencyInjection/Tests/DefinitionTest.php";a:4:{s:6:"md5sum";s:32:"dbee36c02395ef4885ca72420bf98503";s:4:"name";s:62:"Symfony/Component/DependencyInjection/Tests/DefinitionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:117:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php";}s:73:"Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.php";a:4:{s:6:"md5sum";s:32:"5518fa88c922a8c873133651e233386b";s:4:"name";s:73:"Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.php";}s:68:"Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php";a:4:{s:6:"md5sum";s:32:"03e6215b1c0abc0fa0a11642e4786649";s:4:"name";s:68:"Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php";}s:68:"Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php";a:4:{s:6:"md5sum";s:32:"af6f3ad2f9b929dcbac53b8a48f122f3";s:4:"name";s:68:"Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php";}s:69:"Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php";a:4:{s:6:"md5sum";s:32:"d6ae9074c31ddfb3794ff731d60b20bb";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php";}s:71:"Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php";a:4:{s:6:"md5sum";s:32:"939faedda209b4d87552d4fe7cd7ca24";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php";}s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php";a:4:{s:6:"md5sum";s:32:"6422feace05a5ed96c42ed848d10006c";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php";}s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php";a:4:{s:6:"md5sum";s:32:"1ff966b209cd577bd0d6bb36d7e649e4";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php";}s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php";a:4:{s:6:"md5sum";s:32:"1acdceda33fce9015eff3bf7d156135b";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php";}s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.php";a:4:{s:6:"md5sum";s:32:"00b3703e57b5c9586ec0e398ea7a20b2";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.php";}s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.php";a:4:{s:6:"md5sum";s:32:"b21b1c14c129dd16d9414a26aa263c45";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.php";}s:78:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php";a:4:{s:6:"md5sum";s:32:"4bf1be8db545cde3ba7d0e6f6297308d";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php";s:4:"role";s:4:"test";s:12:"installed_as";s:133:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php";}s:78:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php";a:4:{s:6:"md5sum";s:32:"098b361885203b2d00989fce70938512";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php";s:4:"role";s:4:"test";s:12:"installed_as";s:133:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php";}s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.php";a:4:{s:6:"md5sum";s:32:"f06eb418f0f04a719312f0e4ca232e9d";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.php";}s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.php";a:4:{s:6:"md5sum";s:32:"a0ccfd20143be600667c0e98fb665071";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.php";}s:75:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dot";a:4:{s:6:"md5sum";s:32:"02cffa6095e3a31d691a5bdcdbe7c227";s:4:"name";s:75:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dot";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dot";}s:78:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dot";a:4:{s:6:"md5sum";s:32:"5bf12610e2c2a95c5506a1b92ee929f6";s:4:"name";s:78:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dot";s:4:"role";s:4:"test";s:12:"installed_as";s:133:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dot";}s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dot";a:4:{s:6:"md5sum";s:32:"5eda7f5d745f7686812c80927819c499";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dot";s:4:"role";s:4:"test";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dot";}s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services13.dot";a:4:{s:6:"md5sum";s:32:"8f1d93f127c665d4f17b81c9cadc1e90";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services13.dot";s:4:"role";s:4:"test";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services13.dot";}s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services14.dot";a:4:{s:6:"md5sum";s:32:"a7b7d8d68fc8e2f58dfd94d5de28604c";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services14.dot";s:4:"role";s:4:"test";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services14.dot";}s:75:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot";a:4:{s:6:"md5sum";s:32:"17882b73c2f05f5bed8a8761f693ee75";s:4:"name";s:75:"Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot";s:4:"role";s:4:"test";s:12:"installed_as";s:130:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot";}s:73:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php";a:4:{s:6:"md5sum";s:32:"6c18955e7fff0a445ccd323169edfa39";s:4:"name";s:73:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php";}s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.php";a:4:{s:6:"md5sum";s:32:"658357428dc406d5f951a31a951a468b";s:4:"name";s:76:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.php";s:4:"role";s:4:"test";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.php";}s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.php";a:4:{s:6:"md5sum";s:32:"f38316643924184c25c2d323eb2115c8";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.php";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.php";}s:82:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.php";a:4:{s:6:"md5sum";s:32:"d378aa4475659bdd4d5d1d1a7898a5d8";s:4:"name";s:82:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.php";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.php";}s:89:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.php";a:4:{s:6:"md5sum";s:32:"2533e30245d301e424eb76b539244446";s:4:"name";s:89:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.php";s:4:"role";s:4:"test";s:12:"installed_as";s:144:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.php";}s:96:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtensionInPhar.phar";a:4:{s:6:"md5sum";s:32:"b4a17c6724b7c820a73579d094cdd932";s:4:"name";s:96:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtensionInPhar.phar";s:4:"role";s:4:"test";s:12:"installed_as";s:151:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtensionInPhar.phar";}s:84:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsd";a:4:{s:6:"md5sum";s:32:"cd16e7c41fc369846a5eb4a42d1e5b93";s:4:"name";s:84:"Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsd";s:4:"role";s:4:"test";s:12:"installed_as";s:139:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsd";}s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ini";a:4:{s:6:"md5sum";s:32:"547a11b176c7c7905611acd1582252d6";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ini";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ini";a:4:{s:6:"md5sum";s:32:"4a8f0aad32fe89d804cb85703f0e2965";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ini";}s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ini";a:4:{s:6:"md5sum";s:32:"cc1e7671d8c8e219998593b0069ac474";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ini";}s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ini";a:4:{s:6:"md5sum";s:32:"e2432dcd44bad3082cff4aabce9d2f33";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ini";}s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php";a:4:{s:6:"md5sum";s:32:"efe219ab816512283367c226a1656ee4";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php";a:4:{s:6:"md5sum";s:32:"99506344d5fcc588c963e91e473a06d1";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php";a:4:{s:6:"md5sum";s:32:"9b7bf72ef23353c753f51bf557706ef4";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php";a:4:{s:6:"md5sum";s:32:"11e72fc308dfdadaedc9544c8756769b";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php";a:4:{s:6:"md5sum";s:32:"44b0afab75892ad4556743db23d1e629";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php";a:4:{s:6:"md5sum";s:32:"80b20e5ead9c8ff04678100303294161";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php";}s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php";a:4:{s:6:"md5sum";s:32:"b8e9a27269a37e19f37566f39801b484";s:4:"name";s:79:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php";s:4:"role";s:4:"test";s:12:"installed_as";s:134:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php";}s:67:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.php";a:4:{s:6:"md5sum";s:32:"0a223fc28b123a00eeae0ce7825953eb";s:4:"name";s:67:"Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.php";s:4:"role";s:4:"test";s:12:"installed_as";s:122:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.php";}s:80:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xml";a:4:{s:6:"md5sum";s:32:"d741c7a31311ead4df2057e523afeba3";s:4:"name";s:80:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xml";}s:80:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xml";a:4:{s:6:"md5sum";s:32:"f932ffc98518b016fc6383139b711c96";s:4:"name";s:80:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:135:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xml";}s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xml";a:4:{s:6:"md5sum";s:32:"d144314f085c31ccb0a41f802f306649";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xml";}s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xml";a:4:{s:6:"md5sum";s:32:"8a597cf4214e62043465a1d135cbf428";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xml";}s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xml";a:4:{s:6:"md5sum";s:32:"2a00696fd70991a11a2aa0e1e5d61e75";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xml";}s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xml";a:4:{s:6:"md5sum";s:32:"340f21074d0ff685079b5fc0b80dacdf";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xml";}s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xml";a:4:{s:6:"md5sum";s:32:"7dade70bc8de90a4c116d01df8744179";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xml";}s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xml";a:4:{s:6:"md5sum";s:32:"873eec7bf6988585b8be9ed78d32d4f0";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xml";}s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xml";a:4:{s:6:"md5sum";s:32:"834d96fb17d411d3c25df34a8e12339c";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xml";}s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xml";a:4:{s:6:"md5sum";s:32:"e1fb95406c0ff63742800fdc95eb99f6";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xml";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml";a:4:{s:6:"md5sum";s:32:"d7c935e1400a979267225dfbe9519a9e";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services10.xml";a:4:{s:6:"md5sum";s:32:"525da15fe7d63e3e0f8ae78a96929107";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services10.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services10.xml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xml";a:4:{s:6:"md5sum";s:32:"0bed9c78fc2a7b638d81d6e948474ed9";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xml";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml";a:4:{s:6:"md5sum";s:32:"af73c797e9dabde154c0460a294ab77d";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xml";a:4:{s:6:"md5sum";s:32:"5b8fbad821d7f9b92a37c6ec30fbb8a9";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xml";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xml";a:4:{s:6:"md5sum";s:32:"5b6edb71e890234adad9ebb17e88fb6f";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xml";}s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xml";a:4:{s:6:"md5sum";s:32:"53040074af5e742e3e7bc6a820f0b17d";s:4:"name";s:81:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:136:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xml";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml";a:4:{s:6:"md5sum";s:32:"6f50270290cb9bafc719886743286773";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml";a:4:{s:6:"md5sum";s:32:"15f37e20652d85a361cccc6a6f9322ac";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xml";a:4:{s:6:"md5sum";s:32:"3f0cd2a9228c7f1479f535b48beb3f21";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xml";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml";a:4:{s:6:"md5sum";s:32:"71f5c7df64436e6adf6fb4457d7b5075";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml";}s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml";a:4:{s:6:"md5sum";s:32:"ca60e6bf5f65fff971f8d13a644a9acb";s:4:"name";s:70:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml";}s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/withdoctype.xml";a:4:{s:6:"md5sum";s:32:"561c119c08673fd8436e11424a20d808";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/xml/withdoctype.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/withdoctype.xml";}s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.yml";a:4:{s:6:"md5sum";s:32:"2b4b910651d1e7de3a74cc6872184be8";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.yml";}s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.yml";a:4:{s:6:"md5sum";s:32:"2651cca5fcafb2d3328d2d18cc825f2f";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.yml";}s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.yml";a:4:{s:6:"md5sum";s:32:"8b67ba68bb2c5551ac4bc3f7a865839d";s:4:"name";s:69:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:124:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.yml";a:4:{s:6:"md5sum";s:32:"037bf52fe0bfa7b643b837d08dfdf92d";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.yml";a:4:{s:6:"md5sum";s:32:"d42f2da1df5ecdf29be4ac27edda0c12";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml";a:4:{s:6:"md5sum";s:32:"68b329da9893e34099c7d8ad5cb9c940";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml";}s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml";a:4:{s:6:"md5sum";s:32:"98428e36b00061da1b64b1e64781e4d0";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml";}s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.yml";a:4:{s:6:"md5sum";s:32:"8fc6f5242a9a9a0092dcc9387e2f826c";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.yml";}s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.yml";a:4:{s:6:"md5sum";s:32:"9ed1d963ba546e9772a3808f08a91376";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml";a:4:{s:6:"md5sum";s:32:"be17d9c22568cf11a27193704cc13703";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.yml";a:4:{s:6:"md5sum";s:32:"2011daeb4d44240efd2caddf60d84038";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml";a:4:{s:6:"md5sum";s:32:"3e738ce0eb54d9aa53021bb09649e45b";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml";}s:82:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.yml";a:4:{s:6:"md5sum";s:32:"d1b518eb8021cccac6ac53ffc1157781";s:4:"name";s:82:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml";a:4:{s:6:"md5sum";s:32:"6f37efe61e948638cb95cbeebee34a7d";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.yml";a:4:{s:6:"md5sum";s:32:"6de30e3ec6f5769fffa3a84921d5ea58";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml";a:4:{s:6:"md5sum";s:32:"2d887f6e7ab72fc1ef7710f090ac6892";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml";}s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml";a:4:{s:6:"md5sum";s:32:"0c0c237a0f162b1035bc9a31bfb7e3f3";s:4:"name";s:71:"Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml";}s:98:"Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php";a:4:{s:6:"md5sum";s:32:"b26bc2f643dea09195075d0096e874a0";s:4:"name";s:98:"Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:153:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php";}s:82:"Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php";a:4:{s:6:"md5sum";s:32:"e0c0229d4f3141bae74c4bbe30a06b21";s:4:"name";s:82:"Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php";}s:72:"Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.php";a:4:{s:6:"md5sum";s:32:"97399006240deb90b22bcdb49ab08f61";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.php";}s:72:"Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"8e3c7ae75fb774783dc26b6c33ca93f5";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php";}s:72:"Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"c26312ff35c5941814fe09fdfecf216e";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php";}s:72:"Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"d702b36279525fb4751489f2e3285414";s:4:"name";s:72:"Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php";}s:73:"Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php";a:4:{s:6:"md5sum";s:32:"3ae936ba0577f3144075883fc4a845ce";s:4:"name";s:73:"Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php";}s:83:"Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.php";a:4:{s:6:"md5sum";s:32:"f967ec9e8b4a79bf91bd5b4675fbc70c";s:4:"name";s:83:"Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:138:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.php";}s:77:"Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php";a:4:{s:6:"md5sum";s:32:"6db6b2ca8ed272df55332f0916be0ad9";s:4:"name";s:77:"Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:132:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php";}s:61:"Symfony/Component/DependencyInjection/Tests/ParameterTest.php";a:4:{s:6:"md5sum";s:32:"965987dd3ddde1039ebe8c42d83a241b";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Tests/ParameterTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterTest.php";}s:61:"Symfony/Component/DependencyInjection/Tests/ReferenceTest.php";a:4:{s:6:"md5sum";s:32:"203939f24651f40960e928d69a8c6a08";s:4:"name";s:61:"Symfony/Component/DependencyInjection/Tests/ReferenceTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ReferenceTest.php";}s:50:"Symfony/Component/DependencyInjection/Variable.php";a:4:{s:6:"md5sum";s:32:"ed13f0022bf056748456b80c702dbe21";s:4:"name";s:50:"Symfony/Component/DependencyInjection/Variable.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Variable.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:44:{s:67:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection";b:1;s:47:"/opt/alt/php54/usr/share/pear/Symfony/Component";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:91:"/opt/alt/php54/usr/share/doc/pear/DependencyInjection/Symfony/Component/DependencyInjection";b:1;s:71:"/opt/alt/php54/usr/share/doc/pear/DependencyInjection/Symfony/Component";b:1;s:61:"/opt/alt/php54/usr/share/doc/pear/DependencyInjection/Symfony";b:1;s:53:"/opt/alt/php54/usr/share/doc/pear/DependencyInjection";b:1;s:76:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Compiler";b:1;s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Dumper";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Exception";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Extension";b:1;s:90:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/LazyProxy/Instantiator";b:1;s:77:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/LazyProxy";b:1;s:87:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper";b:1;s:74:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader";b:1;s:94:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/schema/dic/services";b:1;s:85:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/schema/dic";b:1;s:81:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/Loader/schema";b:1;s:80:"/opt/alt/php54/usr/share/pear/Symfony/Component/DependencyInjection/ParameterBag";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection";b:1;s:72:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component";b:1;s:62:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony";b:1;s:54:"/opt/alt/php54/usr/share/pear/test/DependencyInjection";b:1;s:107:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler";b:1;s:98:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests";b:1;s:105:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper";b:1;s:108:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Extension";b:1;s:118:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers";b:1;s:107:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures";b:1;s:116:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz";b:1;s:116:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes";b:1;s:123:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema";b:1;s:111:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini";b:1;s:111:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php";b:1;s:122:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1";b:1;s:111:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml";b:1;s:122:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2";b:1;s:122:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions";b:1;s:112:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml";b:1;s:121:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator";b:1;s:108:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy";b:1;s:118:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper";b:1;s:105:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader";b:1;s:111:"/opt/alt/php54/usr/share/pear/test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:6:"Config";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:4:"Yaml";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!.P6.registry/.channel.pear.symfony.com/doctrinebridge.regnu[a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:14:"DoctrineBridge";s:7:"channel";s:16:"pear.symfony.com";s:7:"summary";s:24:"Symfony2 Doctrine Bridge";s:11:"description";s:24:"Symfony2 Doctrine Bridge";s:4:"lead";a:4:{s:4:"name";s:16:"Fabien Potencier";s:4:"user";s:6:"fabpot";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2014-04-05";s:4:"time";s:8:"09:33:40";s:7:"version";a:2:{s:7:"release";s:5:"2.4.3";s:3:"api";s:5:"2.4.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:50:"http://www.opensource.org/licenses/mit-license.php";}s:8:"_content";s:3:"MIT";}s:5:"notes";s:1:"-";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:76:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1146b84b00fda99b2d6838fa9a092b09";s:4:"name";s:38:"Symfony/Bridge/Doctrine/autoloader.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a6c5324a02c7431af568fb0ddf4d701f";s:4:"name";s:56:"Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6288b2050507fae3fbcf270b26daecff";s:4:"name";s:36:"Symfony/Bridge/Doctrine/CHANGELOG.md";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7da86c460e3e1814e41daa76393cfb95";s:4:"name";s:37:"Symfony/Bridge/Doctrine/composer.json";s:4:"role";s:3:"doc";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"54fd5d577b9f49258d19b109ad98ea08";s:4:"name";s:54:"Symfony/Bridge/Doctrine/ContainerAwareEventManager.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e725f92a17d0dee93e1522be12eb1367";s:4:"name";s:63:"Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0d5327cdcc6a003bb2dd541c1b4951be";s:4:"name";s:61:"Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d88b54e05093c8cc6fcc688bf43e2495";s:4:"name";s:73:"Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5159d0f708ad9a1b244b725d5c5c252d";s:4:"name";s:83:"Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php";s:4:"role";s:3:"php";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc6c6ff5e47d6bc1ead4eb2454142819";s:4:"name";s:101:"Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php";s:4:"role";s:3:"php";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6407dfb228cb9e74521f045de4567c0b";s:4:"name";s:81:"Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"62012802efbda5aae97d5b17e36c7ac3";s:4:"name";s:83:"Symfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"36edb41f784aa345f1a6b6aee0177512";s:4:"name";s:66:"Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php";s:4:"role";s:3:"php";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8f34ce5da6bd523b2e2c183b9d311454";s:4:"name";s:60:"Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d5f011953d39f7682b2d1bd38bfc103f";s:4:"name";s:65:"Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f458540aedd232db5a808163e8953c3e";s:4:"name";s:65:"Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a6abbc1e07395be54a0cc9bcc7e8a021";s:4:"name";s:77:"Symfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0394473ded0681f92cfd74d66810cf46";s:4:"name";s:53:"Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"70635596be0740792c9b01fc717a07c6";s:4:"name";s:55:"Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"922055b81eb74eab130af3678e23d728";s:4:"name";s:78:"Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"422792a0aec2cfaf54e7aed842e41a1b";s:4:"name";s:50:"Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4027caad2522bb92ecb104212e740bbb";s:4:"name";s:48:"Symfony/Bridge/Doctrine/Form/Type/EntityType.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c3a63e53318e44d71e48d38e72e6368f";s:4:"name";s:61:"Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5c638ddb71981e9ee7de51ad672f04be";s:4:"name";s:67:"Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:31:"Symfony/Bridge/Doctrine/LICENSE";s:4:"role";s:3:"doc";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a264db6fc25f6bbbf6f7f6866ab775b8";s:4:"name";s:45:"Symfony/Bridge/Doctrine/Logger/DbalLogger.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9aba8e500e2eb6c85e0c5142b3ab01dc";s:4:"name";s:43:"Symfony/Bridge/Doctrine/ManagerRegistry.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"028b26c34311c37ce5a78efcb95cd3a1";s:4:"name";s:40:"Symfony/Bridge/Doctrine/phpunit.xml.dist";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0dfbf896145a1d79d4536a6457375891";s:4:"name";s:33:"Symfony/Bridge/Doctrine/README.md";s:4:"role";s:3:"doc";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"97de5e0e6b0a5567a4d05c49145f007b";s:4:"name";s:45:"Symfony/Bridge/Doctrine/RegistryInterface.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"58d4be45f6a67d0120082b9909fb7470";s:4:"name";s:69:"Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cd4fb5647f556391d48bf4417639bebc";s:4:"name";s:60:"Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cd11805976770714b196a683096710fa";s:4:"name";s:51:"Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:2:{s:4:"name";s:43:"Symfony/Bridge/Doctrine/Tests/bootstrap.php";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63a9dd7b5978e2e653914cee374dd6f0";s:4:"name";s:64:"Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php";s:4:"role";s:4:"test";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"22af804224173c290f9ea48275ea6265";s:4:"name";s:73:"Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php";s:4:"role";s:4:"test";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"317c03bfcf9de63ddb87b75b5219b0e1";s:4:"name";s:71:"Symfony/Bridge/Doctrine/Tests/DataFixtures/ContainerAwareLoaderTest.php";s:4:"role";s:4:"test";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"6b953b8a87ad83b1fa9ca6c5b44b28e5";s:4:"name";s:111:"Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php";s:4:"role";s:4:"test";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cbab10b2d43dd63dc2b6c4afd2e3ba50";s:4:"name";s:53:"Symfony/Bridge/Doctrine/Tests/DoctrineOrmTestCase.php";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"91879a9d73006a12ffc8c62d83ac857c";s:4:"name";s:76:"Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php";s:4:"role";s:4:"test";}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"237107a72edb5333186c85275ac35e1c";s:4:"name";s:60:"Symfony/Bridge/Doctrine/Tests/Fixtures/AssociationEntity.php";s:4:"role";s:4:"test";}}i:41;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d4361cc34fb44804debe2ec8e0e832f8";s:4:"name";s:63:"Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeIntIdEntity.php";s:4:"role";s:4:"test";}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"73b3184c3b0a6bfc68db74c507f1ff7c";s:4:"name";s:66:"Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeStringIdEntity.php";s:4:"role";s:4:"test";}}i:43;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8db7e5383a0e848cc8f60964d12d350";s:4:"name";s:64:"Symfony/Bridge/Doctrine/Tests/Fixtures/ContainerAwareFixture.php";s:4:"role";s:4:"test";}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e4cd9ce9c40b8e76edb083fc526bcd44";s:4:"name";s:59:"Symfony/Bridge/Doctrine/Tests/Fixtures/DoubleNameEntity.php";s:4:"role";s:4:"test";}}i:45;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2325d0c65a178f8bfddcf0a76e53cb00";s:4:"name";s:58:"Symfony/Bridge/Doctrine/Tests/Fixtures/GroupableEntity.php";s:4:"role";s:4:"test";}}i:46;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"01edea44eacb41bdeb553b9445bd2b53";s:4:"name";s:60:"Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.php";s:4:"role";s:4:"test";}}i:47;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c13f44c8fccf2a768c1dfe09cdcf644c";s:4:"name";s:70:"Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdNoToStringEntity.php";s:4:"role";s:4:"test";}}i:48;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f3044b3a9be916f4b6433cd993933d4b";s:4:"name";s:63:"Symfony/Bridge/Doctrine/Tests/Fixtures/SingleStringIdEntity.php";s:4:"role";s:4:"test";}}i:49;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"27921595ac59f8d35f99ea9b8a80474c";s:4:"name";s:47:"Symfony/Bridge/Doctrine/Tests/Fixtures/User.php";s:4:"role";s:4:"test";}}i:50;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"62be3ca48dad09bc19de00a6133ae33c";s:4:"name";s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListCompositeIdTest.php";s:4:"role";s:4:"test";}}i:51;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c53d2568937b7272b41253c169f1b990";s:4:"name";s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleIntIdTest.php";s:4:"role";s:4:"test";}}i:52;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"696f31cf938c23921a506d3dc5b1bd3f";s:4:"name";s:92:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleStringIdTest.php";s:4:"role";s:4:"test";}}i:53;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e3002da166df138152291131d2563147";s:4:"name";s:78:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListTest.php";s:4:"role";s:4:"test";}}i:54;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ed38d6eebc677c1e49f92360dc968726";s:4:"name";s:77:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/GenericEntityChoiceListTest.php";s:4:"role";s:4:"test";}}i:55;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"53cb635842c3610fc376aa099a878cbb";s:4:"name";s:87:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListCompositeIdTest.php";s:4:"role";s:4:"test";}}i:56;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2e6faf750e515b875b39ef0f003d8b3d";s:4:"name";s:87:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleIntIdTest.php";s:4:"role";s:4:"test";}}i:57;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c8e9e517d8c3f0df5f28f2fb135164e9";s:4:"name";s:90:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleStringIdTest.php";s:4:"role";s:4:"test";}}i:58;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3f0f7533860351145dbb49b781cd9af9";s:4:"name";s:75:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php";s:4:"role";s:4:"test";}}i:59;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"978f11f0d52668cdf4c0f9777bfb8b72";s:4:"name";s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdTest.php";s:4:"role";s:4:"test";}}i:60;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"300a5b1f88f5435bd0d2fef5d292a66f";s:4:"name";s:105:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest.php";s:4:"role";s:4:"test";}}i:61;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"484e207192fd43eb7badfc0f226df4fb";s:4:"name";s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdTest.php";s:4:"role";s:4:"test";}}i:62;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"657d384a368a05153a8d73dbf60da002";s:4:"name";s:105:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest.php";s:4:"role";s:4:"test";}}i:63;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"315093405e4abafe143eb918ee7789cf";s:4:"name";s:92:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdTest.php";s:4:"role";s:4:"test";}}i:64;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"fbff3030e3294a22d224256064aaec4f";s:4:"name";s:108:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest.php";s:4:"role";s:4:"test";}}i:65;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ba4a60892ec0398da11b48b522615034";s:4:"name";s:87:"Symfony/Bridge/Doctrine/Tests/Form/DataTransformer/CollectionToArrayTransformerTest.php";s:4:"role";s:4:"test";}}i:66;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4748628e6ff78737995c71507068c5f7";s:4:"name";s:65:"Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php";s:4:"role";s:4:"test";}}i:67;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5be318cfed40c93338f512e25f69da67";s:4:"name";s:69:"Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php";s:4:"role";s:4:"test";}}i:68;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b801ad3cbcc65d3883d8258894a5d326";s:4:"name";s:58:"Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php";s:4:"role";s:4:"test";}}i:69;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"98f90ab5043368eb3d7848ef09fccb80";s:4:"name";s:71:"Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php";s:4:"role";s:4:"test";}}i:70;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2feb485f27b025ee74707d55945fed91";s:4:"name";s:55:"Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php";s:4:"role";s:4:"test";}}i:71;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"56abcb81046969cf32a1c8b690790640";s:4:"name";s:70:"Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php";s:4:"role";s:4:"test";}}i:72;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c1fd3987c9391a54ac76430fff7db778";s:4:"name";s:75:"Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.php";s:4:"role";s:4:"test";}}i:73;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4403085a6acb5b72d6876c25374a01ee";s:4:"name";s:62:"Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php";s:4:"role";s:3:"php";}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"28ee255baf4b1e3a6d539f7e598ac2ca";s:4:"name";s:71:"Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php";s:4:"role";s:3:"php";}}i:75;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c432d786fb2e4848b42aad6b61ff9fac";s:4:"name";s:57:"Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}}s:8:"optional";a:1:{s:7:"package";a:2:{i:0;a:2:{s:4:"name";s:9:"Validator";s:7:"channel";s:16:"pear.symfony.com";}i:1;a:2:{s:4:"name";s:4:"Form";s:7:"channel";s:16:"pear.symfony.com";}}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:76:{s:38:"Symfony/Bridge/Doctrine/autoloader.php";a:4:{s:6:"md5sum";s:32:"1146b84b00fda99b2d6838fa9a092b09";s:4:"name";s:38:"Symfony/Bridge/Doctrine/autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/autoloader.php";}s:56:"Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php";a:4:{s:6:"md5sum";s:32:"a6c5324a02c7431af568fb0ddf4d701f";s:4:"name";s:56:"Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php";}s:36:"Symfony/Bridge/Doctrine/CHANGELOG.md";a:4:{s:6:"md5sum";s:32:"6288b2050507fae3fbcf270b26daecff";s:4:"name";s:36:"Symfony/Bridge/Doctrine/CHANGELOG.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/doc/pear/DoctrineBridge/Symfony/Bridge/Doctrine/CHANGELOG.md";}s:37:"Symfony/Bridge/Doctrine/composer.json";a:4:{s:6:"md5sum";s:32:"7da86c460e3e1814e41daa76393cfb95";s:4:"name";s:37:"Symfony/Bridge/Doctrine/composer.json";s:4:"role";s:3:"doc";s:12:"installed_as";s:86:"/opt/alt/php54/usr/share/doc/pear/DoctrineBridge/Symfony/Bridge/Doctrine/composer.json";}s:54:"Symfony/Bridge/Doctrine/ContainerAwareEventManager.php";a:4:{s:6:"md5sum";s:32:"54fd5d577b9f49258d19b109ad98ea08";s:4:"name";s:54:"Symfony/Bridge/Doctrine/ContainerAwareEventManager.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php";}s:63:"Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php";a:4:{s:6:"md5sum";s:32:"e725f92a17d0dee93e1522be12eb1367";s:4:"name";s:63:"Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php";s:4:"role";s:3:"php";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php";}s:61:"Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.php";a:4:{s:6:"md5sum";s:32:"0d5327cdcc6a003bb2dd541c1b4951be";s:4:"name";s:61:"Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.php";}s:73:"Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php";a:4:{s:6:"md5sum";s:32:"d88b54e05093c8cc6fcc688bf43e2495";s:4:"name";s:73:"Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php";}s:83:"Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php";a:4:{s:6:"md5sum";s:32:"5159d0f708ad9a1b244b725d5c5c252d";s:4:"name";s:83:"Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php";}s:101:"Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php";a:4:{s:6:"md5sum";s:32:"bc6c6ff5e47d6bc1ead4eb2454142819";s:4:"name";s:101:"Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:131:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php";}s:81:"Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php";a:4:{s:6:"md5sum";s:32:"6407dfb228cb9e74521f045de4567c0b";s:4:"name";s:81:"Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php";s:4:"role";s:3:"php";s:12:"installed_as";s:111:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php";}s:83:"Symfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.php";a:4:{s:6:"md5sum";s:32:"62012802efbda5aae97d5b17e36c7ac3";s:4:"name";s:83:"Symfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.php";s:4:"role";s:3:"php";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.php";}s:66:"Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php";a:4:{s:6:"md5sum";s:32:"36edb41f784aa345f1a6b6aee0177512";s:4:"name";s:66:"Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php";s:4:"role";s:3:"php";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php";}s:60:"Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php";a:4:{s:6:"md5sum";s:32:"8f34ce5da6bd523b2e2c183b9d311454";s:4:"name";s:60:"Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php";}s:65:"Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.php";a:4:{s:6:"md5sum";s:32:"d5f011953d39f7682b2d1bd38bfc103f";s:4:"name";s:65:"Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.php";}s:65:"Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php";a:4:{s:6:"md5sum";s:32:"f458540aedd232db5a808163e8953c3e";s:4:"name";s:65:"Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php";}s:77:"Symfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.php";a:4:{s:6:"md5sum";s:32:"a6abbc1e07395be54a0cc9bcc7e8a021";s:4:"name";s:77:"Symfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:107:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.php";}s:53:"Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.php";a:4:{s:6:"md5sum";s:32:"0394473ded0681f92cfd74d66810cf46";s:4:"name";s:53:"Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.php";}s:55:"Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php";a:4:{s:6:"md5sum";s:32:"70635596be0740792c9b01fc717a07c6";s:4:"name";s:55:"Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php";}s:78:"Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php";a:4:{s:6:"md5sum";s:32:"922055b81eb74eab130af3678e23d728";s:4:"name";s:78:"Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php";s:4:"role";s:3:"php";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php";}s:50:"Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php";a:4:{s:6:"md5sum";s:32:"422792a0aec2cfaf54e7aed842e41a1b";s:4:"name";s:50:"Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php";}s:48:"Symfony/Bridge/Doctrine/Form/Type/EntityType.php";a:4:{s:6:"md5sum";s:32:"4027caad2522bb92ecb104212e740bbb";s:4:"name";s:48:"Symfony/Bridge/Doctrine/Form/Type/EntityType.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/Type/EntityType.php";}s:61:"Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php";a:4:{s:6:"md5sum";s:32:"c3a63e53318e44d71e48d38e72e6368f";s:4:"name";s:61:"Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php";s:4:"role";s:3:"php";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php";}s:67:"Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php";a:4:{s:6:"md5sum";s:32:"5c638ddb71981e9ee7de51ad672f04be";s:4:"name";s:67:"Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php";s:4:"role";s:3:"php";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php";}s:31:"Symfony/Bridge/Doctrine/LICENSE";a:4:{s:6:"md5sum";s:32:"09ce405e925cdeb923da1789121864c7";s:4:"name";s:31:"Symfony/Bridge/Doctrine/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/doc/pear/DoctrineBridge/Symfony/Bridge/Doctrine/LICENSE";}s:45:"Symfony/Bridge/Doctrine/Logger/DbalLogger.php";a:4:{s:6:"md5sum";s:32:"a264db6fc25f6bbbf6f7f6866ab775b8";s:4:"name";s:45:"Symfony/Bridge/Doctrine/Logger/DbalLogger.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Logger/DbalLogger.php";}s:43:"Symfony/Bridge/Doctrine/ManagerRegistry.php";a:4:{s:6:"md5sum";s:32:"9aba8e500e2eb6c85e0c5142b3ab01dc";s:4:"name";s:43:"Symfony/Bridge/Doctrine/ManagerRegistry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/ManagerRegistry.php";}s:40:"Symfony/Bridge/Doctrine/phpunit.xml.dist";a:4:{s:6:"md5sum";s:32:"028b26c34311c37ce5a78efcb95cd3a1";s:4:"name";s:40:"Symfony/Bridge/Doctrine/phpunit.xml.dist";s:4:"role";s:4:"test";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/phpunit.xml.dist";}s:33:"Symfony/Bridge/Doctrine/README.md";a:4:{s:6:"md5sum";s:32:"0dfbf896145a1d79d4536a6457375891";s:4:"name";s:33:"Symfony/Bridge/Doctrine/README.md";s:4:"role";s:3:"doc";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/doc/pear/DoctrineBridge/Symfony/Bridge/Doctrine/README.md";}s:45:"Symfony/Bridge/Doctrine/RegistryInterface.php";a:4:{s:6:"md5sum";s:32:"97de5e0e6b0a5567a4d05c49145f007b";s:4:"name";s:45:"Symfony/Bridge/Doctrine/RegistryInterface.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/RegistryInterface.php";}s:69:"Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php";a:4:{s:6:"md5sum";s:32:"58d4be45f6a67d0120082b9909fb7470";s:4:"name";s:69:"Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:99:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php";}s:60:"Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php";a:4:{s:6:"md5sum";s:32:"cd4fb5647f556391d48bf4417639bebc";s:4:"name";s:60:"Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php";}s:51:"Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php";a:4:{s:6:"md5sum";s:32:"cd11805976770714b196a683096710fa";s:4:"name";s:51:"Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php";}s:43:"Symfony/Bridge/Doctrine/Tests/bootstrap.php";a:3:{s:4:"name";s:43:"Symfony/Bridge/Doctrine/Tests/bootstrap.php";s:4:"role";s:4:"test";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/bootstrap.php";}s:64:"Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php";a:4:{s:6:"md5sum";s:32:"63a9dd7b5978e2e653914cee374dd6f0";s:4:"name";s:64:"Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php";}s:73:"Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php";a:4:{s:6:"md5sum";s:32:"22af804224173c290f9ea48275ea6265";s:4:"name";s:73:"Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:123:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php";}s:71:"Symfony/Bridge/Doctrine/Tests/DataFixtures/ContainerAwareLoaderTest.php";a:4:{s:6:"md5sum";s:32:"317c03bfcf9de63ddb87b75b5219b0e1";s:4:"name";s:71:"Symfony/Bridge/Doctrine/Tests/DataFixtures/ContainerAwareLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataFixtures/ContainerAwareLoaderTest.php";}s:111:"Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php";a:4:{s:6:"md5sum";s:32:"6b953b8a87ad83b1fa9ca6c5b44b28e5";s:4:"name";s:111:"Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:161:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php";}s:53:"Symfony/Bridge/Doctrine/Tests/DoctrineOrmTestCase.php";a:4:{s:6:"md5sum";s:32:"cbab10b2d43dd63dc2b6c4afd2e3ba50";s:4:"name";s:53:"Symfony/Bridge/Doctrine/Tests/DoctrineOrmTestCase.php";s:4:"role";s:4:"test";s:12:"installed_as";s:103:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DoctrineOrmTestCase.php";}s:76:"Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php";a:4:{s:6:"md5sum";s:32:"91879a9d73006a12ffc8c62d83ac857c";s:4:"name";s:76:"Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:126:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php";}s:60:"Symfony/Bridge/Doctrine/Tests/Fixtures/AssociationEntity.php";a:4:{s:6:"md5sum";s:32:"237107a72edb5333186c85275ac35e1c";s:4:"name";s:60:"Symfony/Bridge/Doctrine/Tests/Fixtures/AssociationEntity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/AssociationEntity.php";}s:63:"Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeIntIdEntity.php";a:4:{s:6:"md5sum";s:32:"d4361cc34fb44804debe2ec8e0e832f8";s:4:"name";s:63:"Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeIntIdEntity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeIntIdEntity.php";}s:66:"Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeStringIdEntity.php";a:4:{s:6:"md5sum";s:32:"73b3184c3b0a6bfc68db74c507f1ff7c";s:4:"name";s:66:"Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeStringIdEntity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:116:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeStringIdEntity.php";}s:64:"Symfony/Bridge/Doctrine/Tests/Fixtures/ContainerAwareFixture.php";a:4:{s:6:"md5sum";s:32:"b8db7e5383a0e848cc8f60964d12d350";s:4:"name";s:64:"Symfony/Bridge/Doctrine/Tests/Fixtures/ContainerAwareFixture.php";s:4:"role";s:4:"test";s:12:"installed_as";s:114:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/ContainerAwareFixture.php";}s:59:"Symfony/Bridge/Doctrine/Tests/Fixtures/DoubleNameEntity.php";a:4:{s:6:"md5sum";s:32:"e4cd9ce9c40b8e76edb083fc526bcd44";s:4:"name";s:59:"Symfony/Bridge/Doctrine/Tests/Fixtures/DoubleNameEntity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:109:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/DoubleNameEntity.php";}s:58:"Symfony/Bridge/Doctrine/Tests/Fixtures/GroupableEntity.php";a:4:{s:6:"md5sum";s:32:"2325d0c65a178f8bfddcf0a76e53cb00";s:4:"name";s:58:"Symfony/Bridge/Doctrine/Tests/Fixtures/GroupableEntity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/GroupableEntity.php";}s:60:"Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.php";a:4:{s:6:"md5sum";s:32:"01edea44eacb41bdeb553b9445bd2b53";s:4:"name";s:60:"Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:110:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.php";}s:70:"Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdNoToStringEntity.php";a:4:{s:6:"md5sum";s:32:"c13f44c8fccf2a768c1dfe09cdcf644c";s:4:"name";s:70:"Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdNoToStringEntity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdNoToStringEntity.php";}s:63:"Symfony/Bridge/Doctrine/Tests/Fixtures/SingleStringIdEntity.php";a:4:{s:6:"md5sum";s:32:"f3044b3a9be916f4b6433cd993933d4b";s:4:"name";s:63:"Symfony/Bridge/Doctrine/Tests/Fixtures/SingleStringIdEntity.php";s:4:"role";s:4:"test";s:12:"installed_as";s:113:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleStringIdEntity.php";}s:47:"Symfony/Bridge/Doctrine/Tests/Fixtures/User.php";a:4:{s:6:"md5sum";s:32:"27921595ac59f8d35f99ea9b8a80474c";s:4:"name";s:47:"Symfony/Bridge/Doctrine/Tests/Fixtures/User.php";s:4:"role";s:4:"test";s:12:"installed_as";s:97:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/User.php";}s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListCompositeIdTest.php";a:4:{s:6:"md5sum";s:32:"62be3ca48dad09bc19de00a6133ae33c";s:4:"name";s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListCompositeIdTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:139:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListCompositeIdTest.php";}s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleIntIdTest.php";a:4:{s:6:"md5sum";s:32:"c53d2568937b7272b41253c169f1b990";s:4:"name";s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleIntIdTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:139:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleIntIdTest.php";}s:92:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleStringIdTest.php";a:4:{s:6:"md5sum";s:32:"696f31cf938c23921a506d3dc5b1bd3f";s:4:"name";s:92:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleStringIdTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:142:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleStringIdTest.php";}s:78:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListTest.php";a:4:{s:6:"md5sum";s:32:"e3002da166df138152291131d2563147";s:4:"name";s:78:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:128:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListTest.php";}s:77:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/GenericEntityChoiceListTest.php";a:4:{s:6:"md5sum";s:32:"ed38d6eebc677c1e49f92360dc968726";s:4:"name";s:77:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/GenericEntityChoiceListTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:127:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/GenericEntityChoiceListTest.php";}s:87:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListCompositeIdTest.php";a:4:{s:6:"md5sum";s:32:"53cb635842c3610fc376aa099a878cbb";s:4:"name";s:87:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListCompositeIdTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListCompositeIdTest.php";}s:87:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleIntIdTest.php";a:4:{s:6:"md5sum";s:32:"2e6faf750e515b875b39ef0f003d8b3d";s:4:"name";s:87:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleIntIdTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleIntIdTest.php";}s:90:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleStringIdTest.php";a:4:{s:6:"md5sum";s:32:"c8e9e517d8c3f0df5f28f2fb135164e9";s:4:"name";s:90:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleStringIdTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:140:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleStringIdTest.php";}s:75:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php";a:4:{s:6:"md5sum";s:32:"3f0f7533860351145dbb49b781cd9af9";s:4:"name";s:75:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php";}s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdTest.php";a:4:{s:6:"md5sum";s:32:"978f11f0d52668cdf4c0f9777bfb8b72";s:4:"name";s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:139:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdTest.php";}s:105:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest.php";a:4:{s:6:"md5sum";s:32:"300a5b1f88f5435bd0d2fef5d292a66f";s:4:"name";s:105:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:155:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest.php";}s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdTest.php";a:4:{s:6:"md5sum";s:32:"484e207192fd43eb7badfc0f226df4fb";s:4:"name";s:89:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:139:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdTest.php";}s:105:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest.php";a:4:{s:6:"md5sum";s:32:"657d384a368a05153a8d73dbf60da002";s:4:"name";s:105:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:155:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest.php";}s:92:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdTest.php";a:4:{s:6:"md5sum";s:32:"315093405e4abafe143eb918ee7789cf";s:4:"name";s:92:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:142:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdTest.php";}s:108:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest.php";a:4:{s:6:"md5sum";s:32:"fbff3030e3294a22d224256064aaec4f";s:4:"name";s:108:"Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:158:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest.php";}s:87:"Symfony/Bridge/Doctrine/Tests/Form/DataTransformer/CollectionToArrayTransformerTest.php";a:4:{s:6:"md5sum";s:32:"ba4a60892ec0398da11b48b522615034";s:4:"name";s:87:"Symfony/Bridge/Doctrine/Tests/Form/DataTransformer/CollectionToArrayTransformerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:137:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DataTransformer/CollectionToArrayTransformerTest.php";}s:65:"Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php";a:4:{s:6:"md5sum";s:32:"4748628e6ff78737995c71507068c5f7";s:4:"name";s:65:"Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:115:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php";}s:69:"Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php";a:4:{s:6:"md5sum";s:32:"5be318cfed40c93338f512e25f69da67";s:4:"name";s:69:"Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:119:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php";}s:58:"Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php";a:4:{s:6:"md5sum";s:32:"b801ad3cbcc65d3883d8258894a5d326";s:4:"name";s:58:"Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:108:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php";}s:71:"Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php";a:4:{s:6:"md5sum";s:32:"98f90ab5043368eb3d7848ef09fccb80";s:4:"name";s:71:"Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:121:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php";}s:55:"Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php";a:4:{s:6:"md5sum";s:32:"2feb485f27b025ee74707d55945fed91";s:4:"name";s:55:"Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:105:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php";}s:70:"Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php";a:4:{s:6:"md5sum";s:32:"56abcb81046969cf32a1c8b690790640";s:4:"name";s:70:"Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:120:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php";}s:75:"Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.php";a:4:{s:6:"md5sum";s:32:"c1fd3987c9391a54ac76430fff7db778";s:4:"name";s:75:"Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:125:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.php";}s:62:"Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php";a:4:{s:6:"md5sum";s:32:"4403085a6acb5b72d6876c25374a01ee";s:4:"name";s:62:"Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php";}s:71:"Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php";a:4:{s:6:"md5sum";s:32:"28ee255baf4b1e3a6d539f7e598ac2ca";s:4:"name";s:71:"Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:101:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php";}s:57:"Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.php";a:4:{s:6:"md5sum";s:32:"c432d786fb2e4848b42aad6b61ff9fac";s:4:"name";s:57:"Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:49:{s:53:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine";b:1;s:44:"/opt/alt/php54/usr/share/pear/Symfony/Bridge";b:1;s:37:"/opt/alt/php54/usr/share/pear/Symfony";b:1;s:65:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/CacheWarmer";b:1;s:72:"/opt/alt/php54/usr/share/doc/pear/DoctrineBridge/Symfony/Bridge/Doctrine";b:1;s:63:"/opt/alt/php54/usr/share/doc/pear/DoctrineBridge/Symfony/Bridge";b:1;s:56:"/opt/alt/php54/usr/share/doc/pear/DoctrineBridge/Symfony";b:1;s:48:"/opt/alt/php54/usr/share/doc/pear/DoctrineBridge";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DataCollector";b:1;s:66:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DataFixtures";b:1;s:73:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DependencyInjection";b:1;s:86:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass";b:1;s:95:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider";b:1;s:82:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/DependencyInjection/Security";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/ExpressionLanguage";b:1;s:69:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/ChoiceList";b:1;s:58:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form";b:1;s:74:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/DataTransformer";b:1;s:72:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/EventListener";b:1;s:63:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Form/Type";b:1;s:68:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/HttpFoundation";b:1;s:60:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Logger";b:1;s:73:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine";b:1;s:64:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge";b:1;s:57:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony";b:1;s:49:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge";b:1;s:73:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Security/RememberMe";b:1;s:62:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Security";b:1;s:67:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Security/User";b:1;s:58:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Test";b:1;s:79:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests";b:1;s:93:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataCollector";b:1;s:92:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataFixtures";b:1;s:112:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass";b:1;s:99:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DependencyInjection";b:1;s:98:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures";b:1;s:95:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList";b:1;s:84:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form";b:1;s:100:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DataTransformer";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type";b:1;s:94:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/HttpFoundation";b:1;s:86:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Logger";b:1;s:93:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Security/User";b:1;s:88:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Security";b:1;s:101:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Validator/Constraints";b:1;s:89:"/opt/alt/php54/usr/share/pear/test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Validator";b:1;s:75:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Validator/Constraints";b:1;s:63:"/opt/alt/php54/usr/share/pear/Symfony/Bridge/Doctrine/Validator";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"2.4.3";s:12:"release_date";s:10:"2014-04-05";s:13:"release_state";s:6:"stable";s:15:"release_license";s:3:"MIT";s:13:"release_notes";s:1:"-";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.3.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:9:"Validator";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"pear.symfony.com";s:4:"name";s:4:"Form";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Fabien Potencier";s:5:"email";s:18:"fabien@symfony.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"fabpot";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506493;}PK!塕"",.registry/.channel.components.ez.no/file.regnu[a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.6.1";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:4:"File";s:7:"channel";s:16:"components.ez.no";s:7:"summary";s:77:"Provides support for file operations which are not covered by PHP or are just";s:11:"description";s:86:"Provides support for file operations which are not covered by PHP or are just missing.";s:4:"lead";a:4:{s:4:"name";s:10:"eZ systems";s:4:"user";s:3:"ezc";s:5:"email";s:9:"ezc@ez.no";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2007-12-17";s:4:"time";s:8:"10:05:20";s:7:"version";a:2:{s:7:"release";s:3:"1.2";s:3:"api";s:3:"1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";s:7:"New BSD";s:5:"notes";s:13:"- No changes.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:13:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1fea496598ff896af1a9e9c8d0ec2121";s:4:"name";s:24:"design/class_diagram.png";s:4:"role";s:4:"data";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4df8185638df9786f8623e98731a5fba";s:4:"name";s:17:"design/design.txt";s:4:"role";s:4:"data";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e66684eedcbb29f0bcec8785edeb2746";s:4:"name";s:15:"design/file.xml";s:4:"role";s:4:"data";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b41ecc87d2a775fbb5eb91df085b4990";s:4:"name";s:26:"design/file_operations.png";s:4:"role";s:4:"data";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f5c40ec66e89cf17fb8dad4c0c8c8f4b";s:4:"name";s:14:"design/md5.png";s:4:"role";s:4:"data";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3a728985b18b3c682c1977f2d6cece89";s:4:"name";s:23:"design/requirements.txt";s:4:"role";s:4:"data";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6a44661d8d0ed5dea17e26938c1c388c";s:4:"name";s:12:"docs/CREDITS";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9b53d942ef8c5a2d0e17e527c8c18792";s:4:"name";s:12:"docs/LICENSE";s:4:"role";s:3:"doc";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e062103b8204517acbbbc57ed1a79bfa";s:4:"name";s:17:"docs/tutorial.txt";s:4:"role";s:3:"doc";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e13077f15f79b21c318dc328bdc789c4";s:4:"name";s:26:"docs/tutorial_autoload.php";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6f5a826d9e4ac53914069ecf9599c90e";s:4:"name";s:30:"ezc/autoload/file_autoload.php";s:4:"role";s:3:"php";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e4017db6ff3d10118bd3b7ed0d50d846";s:4:"name";s:17:"ezc/File/file.php";s:4:"role";s:3:"php";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6f5a826d9e4ac53914069ecf9599c90e";s:4:"name";s:26:"ezc/File/file_autoload.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.1.1";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.2";}s:7:"package";a:3:{s:4:"name";s:4:"Base";s:7:"channel";s:16:"components.ez.no";s:3:"min";s:3:"1.4";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.2";s:3:"api";s:3:"1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-12-17";s:7:"license";s:7:"New BSD";s:5:"notes";s:13:"- No changes.";}}s:8:"filelist";a:13:{s:24:"design/class_diagram.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1fea496598ff896af1a9e9c8d0ec2121";s:4:"name";s:24:"design/class_diagram.png";s:4:"role";s:4:"data";s:12:"installed_as";s:64:"/opt/alt/php54/usr/share/pear/data/File/design/class_diagram.png";}s:17:"design/design.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4df8185638df9786f8623e98731a5fba";s:4:"name";s:17:"design/design.txt";s:4:"role";s:4:"data";s:12:"installed_as";s:57:"/opt/alt/php54/usr/share/pear/data/File/design/design.txt";}s:15:"design/file.xml";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e66684eedcbb29f0bcec8785edeb2746";s:4:"name";s:15:"design/file.xml";s:4:"role";s:4:"data";s:12:"installed_as";s:55:"/opt/alt/php54/usr/share/pear/data/File/design/file.xml";}s:26:"design/file_operations.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b41ecc87d2a775fbb5eb91df085b4990";s:4:"name";s:26:"design/file_operations.png";s:4:"role";s:4:"data";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/data/File/design/file_operations.png";}s:14:"design/md5.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f5c40ec66e89cf17fb8dad4c0c8c8f4b";s:4:"name";s:14:"design/md5.png";s:4:"role";s:4:"data";s:12:"installed_as";s:54:"/opt/alt/php54/usr/share/pear/data/File/design/md5.png";}s:23:"design/requirements.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3a728985b18b3c682c1977f2d6cece89";s:4:"name";s:23:"design/requirements.txt";s:4:"role";s:4:"data";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/data/File/design/requirements.txt";}s:12:"docs/CREDITS";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6a44661d8d0ed5dea17e26938c1c388c";s:4:"name";s:12:"docs/CREDITS";s:4:"role";s:3:"doc";s:12:"installed_as";s:51:"/opt/alt/php54/usr/share/doc/pear/File/docs/CREDITS";}s:12:"docs/LICENSE";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9b53d942ef8c5a2d0e17e527c8c18792";s:4:"name";s:12:"docs/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:51:"/opt/alt/php54/usr/share/doc/pear/File/docs/LICENSE";}s:17:"docs/tutorial.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e062103b8204517acbbbc57ed1a79bfa";s:4:"name";s:17:"docs/tutorial.txt";s:4:"role";s:3:"doc";s:12:"installed_as";s:56:"/opt/alt/php54/usr/share/doc/pear/File/docs/tutorial.txt";}s:26:"docs/tutorial_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e13077f15f79b21c318dc328bdc789c4";s:4:"name";s:26:"docs/tutorial_autoload.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/doc/pear/File/docs/tutorial_autoload.php";}s:30:"ezc/autoload/file_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6f5a826d9e4ac53914069ecf9599c90e";s:4:"name";s:30:"ezc/autoload/file_autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php54/usr/share/pear/ezc/autoload/file_autoload.php";}s:17:"ezc/File/file.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e4017db6ff3d10118bd3b7ed0d50d846";s:4:"name";s:17:"ezc/File/file.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php54/usr/share/pear/ezc/File/file.php";}s:26:"ezc/File/file_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6f5a826d9e4ac53914069ecf9599c90e";s:4:"name";s:26:"ezc/File/file_autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/opt/alt/php54/usr/share/pear/ezc/File/file_autoload.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:7:{s:46:"/opt/alt/php54/usr/share/pear/data/File/design";b:1;s:39:"/opt/alt/php54/usr/share/pear/data/File";b:1;s:43:"/opt/alt/php54/usr/share/doc/pear/File/docs";b:1;s:38:"/opt/alt/php54/usr/share/doc/pear/File";b:1;s:42:"/opt/alt/php54/usr/share/pear/ezc/autoload";b:1;s:33:"/opt/alt/php54/usr/share/pear/ezc";b:1;s:38:"/opt/alt/php54/usr/share/pear/ezc/File";b:1;}s:3:"old";a:7:{s:7:"version";s:3:"1.2";s:12:"release_date";s:10:"2007-12-17";s:13:"release_state";s:6:"stable";s:15:"release_license";s:7:"New BSD";s:13:"release_notes";s:13:"- No changes.";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.1.1";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.2";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"components.ez.no";s:4:"name";s:4:"Base";s:3:"rel";s:2:"ge";s:7:"version";s:3:"1.4";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:10:"eZ systems";s:5:"email";s:9:"ezc@ez.no";s:6:"active";s:3:"yes";s:6:"handle";s:3:"ezc";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506490;}PK!Lee/.registry/.channel.components.ez.no/archive.regnu[a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.0";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:7:"Archive";s:7:"channel";s:16:"components.ez.no";s:7:"summary";s:72:"The component allows you to create, modify, and extract archive files of";s:11:"description";s:195:"The component allows you to create, modify, and extract archive files of various formats. The currently supported archives formats are Tar (with the flavours: ustar, v7, pax, and gnu) and Zip.";s:4:"lead";a:4:{s:4:"name";s:10:"eZ systems";s:4:"user";s:3:"ezc";s:5:"email";s:9:"ezc@ez.no";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2010-03-22";s:4:"time";s:8:"14:22:30";s:7:"version";a:2:{s:7:"release";s:5:"1.4.1";s:3:"api";s:5:"1.4.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";s:7:"New BSD";s:5:"notes";s:88:"- Fixed #16030: Archive calls posix_* functions even it is only an optional depedency.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:47:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"72bf37bbd23ecb988ed26621668b9ea0";s:4:"name";s:24:"design/class_diagram.png";s:4:"role";s:4:"data";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"741c4ea6a06af6567cd1afe5fed41a53";s:4:"name";s:17:"design/design.txt";s:4:"role";s:4:"data";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6a44661d8d0ed5dea17e26938c1c388c";s:4:"name";s:12:"docs/CREDITS";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2a77e280aa2ae4f807969d0ac3c8152d";s:4:"name";s:16:"docs/example.php";s:4:"role";s:3:"doc";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0d01eec9cb573a51f7cb73a1573c5350";s:4:"name";s:12:"docs/LICENSE";s:4:"role";s:3:"doc";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8d06fa57a81f0a0a5896e5e0457ecebe";s:4:"name";s:17:"docs/tutorial.txt";s:4:"role";s:3:"doc";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c62acdb41db6b2f5f90506fda0ffe426";s:4:"name";s:26:"docs/tutorial_autoload.php";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f313af43fda7b4a1d3406d8231af04bf";s:4:"name";s:29:"docs/tutorial_directories.php";s:4:"role";s:3:"doc";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"65dd3a672e2653f9684af63dbe7b8f39";s:4:"name";s:25:"docs/tutorial_extract.php";s:4:"role";s:3:"doc";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b559a62025c86b39e2b8318f3e6ed8ef";s:4:"name";s:26:"docs/tutorial_iterator.php";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"060715d13ae55509316734f4eb855088";s:4:"name";s:27:"docs/tutorial_read_only.php";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"45e5934942ff8129b05a5111bff812b6";s:4:"name";s:27:"docs/tutorial_recursive.php";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a6af136dfae2051d9c681072fc5be848";s:4:"name";s:27:"docs/tutorial_replacing.php";s:4:"role";s:3:"doc";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8bfdfa690b70a22d4561bf29f87e6cee";s:4:"name";s:37:"ezc/Archive/exceptions/block_size.php";s:4:"role";s:3:"php";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"36b0f5f2a917c3ebb575ea2c94ebeb53";s:4:"name";s:35:"ezc/Archive/exceptions/checksum.php";s:4:"role";s:3:"php";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"19eb3fb3e6ca070d4105b047642f473c";s:4:"name";s:32:"ezc/Archive/exceptions/empty.php";s:4:"role";s:3:"php";}}i:16;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9ad968fb58ff679a0179d959b09832e1";s:4:"name";s:39:"ezc/Archive/exceptions/entry_prefix.php";s:4:"role";s:3:"php";}}i:17;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e84a507b5d7b2d207d0a775c26cbe3a7";s:4:"name";s:36:"ezc/Archive/exceptions/exception.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"005847d4bde9c903016e3581509bfaf1";s:4:"name";s:45:"ezc/Archive/exceptions/internal_exception.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"759c2a56665336bf4663c9d19cdd3b2e";s:4:"name";s:29:"ezc/Archive/exceptions/io.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6fd01fdde9913f1321664f289ec64997";s:4:"name";s:39:"ezc/Archive/exceptions/unknown_type.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"ec58eb3f5b58f6abdad6b3b91eb8ee53";s:4:"name";s:32:"ezc/Archive/exceptions/value.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"96b9ad061c90bbeeb5a4daad7d25f586";s:4:"name";s:31:"ezc/Archive/file/block_file.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"35ebb368ad87b6284664436e670957a2";s:4:"name";s:35:"ezc/Archive/file/character_file.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"90067477c3b91fbd36960305b5008dc3";s:4:"name";s:25:"ezc/Archive/file/file.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5b0e79a77cdded79f2f726709557ba0d";s:4:"name";s:35:"ezc/Archive/interfaces/callback.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"43801773c1b08d20220549a839a11b64";s:4:"name";s:31:"ezc/Archive/options/archive.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8aff13d2dce9722eb6c017cb56ba0251";s:4:"name";s:28:"ezc/Archive/structs/file.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"42f4fa41c122b57c7437be5eba2a6681";s:4:"name";s:31:"ezc/Archive/tar/headers/gnu.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2c538adde875f634371fc03fdf96d5eb";s:4:"name";s:31:"ezc/Archive/tar/headers/pax.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f740ab119f65467ebdb063afa8e8a1be";s:4:"name";s:33:"ezc/Archive/tar/headers/ustar.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6411e0637dd4a8f695fee9db1ac4d009";s:4:"name";s:30:"ezc/Archive/tar/headers/v7.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"33fe42a1cae20f63c1d6cf76c56e7a7c";s:4:"name";s:23:"ezc/Archive/tar/gnu.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7859fc155b9533787f030970ecf13946";s:4:"name";s:23:"ezc/Archive/tar/pax.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"87ed07d8eefe3a60197c606b1d2a23a7";s:4:"name";s:25:"ezc/Archive/tar/ustar.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c2ae79e94564bd272cfa2679184473f2";s:4:"name";s:22:"ezc/Archive/tar/v7.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3da3d0671f6672514c83d19c81390132";s:4:"name";s:31:"ezc/Archive/utils/checksums.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"aff89d61a3e1d5098f5ae1c46573b34c";s:4:"name";s:31:"ezc/Archive/utils/file_type.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"376245afd1446211dc5af606e6df0c67";s:4:"name";s:31:"ezc/Archive/utils/stat_mode.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3738ab744b6c5bdd1caddd32ea09a84d";s:4:"name";s:45:"ezc/Archive/zip/headers/central_directory.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f34787c23bf83a287adf52776c9fb463";s:4:"name";s:49:"ezc/Archive/zip/headers/central_directory_end.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"379e451359f472247c253ae9034b146c";s:4:"name";s:38:"ezc/Archive/zip/headers/local_file.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6927126b5039b4c393e270f3d52a20da";s:4:"name";s:23:"ezc/Archive/zip/zip.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1775383dca270e61680af527a93d0f68";s:4:"name";s:23:"ezc/Archive/archive.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f95a0357cca0dee2450504a3c41d4629";s:4:"name";s:32:"ezc/Archive/archive_autoload.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"10cee0df9b58cf85787bf50e11307050";s:4:"name";s:21:"ezc/Archive/entry.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f95a0357cca0dee2450504a3c41d4629";s:4:"name";s:33:"ezc/autoload/archive_autoload.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.2.1";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.2";}s:7:"package";a:3:{s:4:"name";s:4:"Base";s:7:"channel";s:16:"components.ez.no";s:3:"min";s:3:"1.8";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.1";s:3:"api";s:5:"1.4.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-03-22";s:7:"license";s:7:"New BSD";s:5:"notes";s:88:"- Fixed #16030: Archive calls posix_* functions even it is only an optional depedency.";}}s:8:"filelist";a:47:{s:24:"design/class_diagram.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"72bf37bbd23ecb988ed26621668b9ea0";s:4:"name";s:24:"design/class_diagram.png";s:4:"role";s:4:"data";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/data/Archive/design/class_diagram.png";}s:17:"design/design.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"741c4ea6a06af6567cd1afe5fed41a53";s:4:"name";s:17:"design/design.txt";s:4:"role";s:4:"data";s:12:"installed_as";s:60:"/opt/alt/php54/usr/share/pear/data/Archive/design/design.txt";}s:12:"docs/CREDITS";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6a44661d8d0ed5dea17e26938c1c388c";s:4:"name";s:12:"docs/CREDITS";s:4:"role";s:3:"doc";s:12:"installed_as";s:54:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/CREDITS";}s:16:"docs/example.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2a77e280aa2ae4f807969d0ac3c8152d";s:4:"name";s:16:"docs/example.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:58:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/example.php";}s:12:"docs/LICENSE";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0d01eec9cb573a51f7cb73a1573c5350";s:4:"name";s:12:"docs/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:54:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/LICENSE";}s:17:"docs/tutorial.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8d06fa57a81f0a0a5896e5e0457ecebe";s:4:"name";s:17:"docs/tutorial.txt";s:4:"role";s:3:"doc";s:12:"installed_as";s:59:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/tutorial.txt";}s:26:"docs/tutorial_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c62acdb41db6b2f5f90506fda0ffe426";s:4:"name";s:26:"docs/tutorial_autoload.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/tutorial_autoload.php";}s:29:"docs/tutorial_directories.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f313af43fda7b4a1d3406d8231af04bf";s:4:"name";s:29:"docs/tutorial_directories.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/tutorial_directories.php";}s:25:"docs/tutorial_extract.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"65dd3a672e2653f9684af63dbe7b8f39";s:4:"name";s:25:"docs/tutorial_extract.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/tutorial_extract.php";}s:26:"docs/tutorial_iterator.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b559a62025c86b39e2b8318f3e6ed8ef";s:4:"name";s:26:"docs/tutorial_iterator.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/tutorial_iterator.php";}s:27:"docs/tutorial_read_only.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"060715d13ae55509316734f4eb855088";s:4:"name";s:27:"docs/tutorial_read_only.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/tutorial_read_only.php";}s:27:"docs/tutorial_recursive.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"45e5934942ff8129b05a5111bff812b6";s:4:"name";s:27:"docs/tutorial_recursive.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/tutorial_recursive.php";}s:27:"docs/tutorial_replacing.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a6af136dfae2051d9c681072fc5be848";s:4:"name";s:27:"docs/tutorial_replacing.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/doc/pear/Archive/docs/tutorial_replacing.php";}s:37:"ezc/Archive/exceptions/block_size.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8bfdfa690b70a22d4561bf29f87e6cee";s:4:"name";s:37:"ezc/Archive/exceptions/block_size.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions/block_size.php";}s:35:"ezc/Archive/exceptions/checksum.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"36b0f5f2a917c3ebb575ea2c94ebeb53";s:4:"name";s:35:"ezc/Archive/exceptions/checksum.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions/checksum.php";}s:32:"ezc/Archive/exceptions/empty.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"19eb3fb3e6ca070d4105b047642f473c";s:4:"name";s:32:"ezc/Archive/exceptions/empty.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions/empty.php";}s:39:"ezc/Archive/exceptions/entry_prefix.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9ad968fb58ff679a0179d959b09832e1";s:4:"name";s:39:"ezc/Archive/exceptions/entry_prefix.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions/entry_prefix.php";}s:36:"ezc/Archive/exceptions/exception.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e84a507b5d7b2d207d0a775c26cbe3a7";s:4:"name";s:36:"ezc/Archive/exceptions/exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions/exception.php";}s:45:"ezc/Archive/exceptions/internal_exception.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"005847d4bde9c903016e3581509bfaf1";s:4:"name";s:45:"ezc/Archive/exceptions/internal_exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions/internal_exception.php";}s:29:"ezc/Archive/exceptions/io.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"759c2a56665336bf4663c9d19cdd3b2e";s:4:"name";s:29:"ezc/Archive/exceptions/io.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions/io.php";}s:39:"ezc/Archive/exceptions/unknown_type.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6fd01fdde9913f1321664f289ec64997";s:4:"name";s:39:"ezc/Archive/exceptions/unknown_type.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions/unknown_type.php";}s:32:"ezc/Archive/exceptions/value.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"ec58eb3f5b58f6abdad6b3b91eb8ee53";s:4:"name";s:32:"ezc/Archive/exceptions/value.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions/value.php";}s:31:"ezc/Archive/file/block_file.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"96b9ad061c90bbeeb5a4daad7d25f586";s:4:"name";s:31:"ezc/Archive/file/block_file.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/ezc/Archive/file/block_file.php";}s:35:"ezc/Archive/file/character_file.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"35ebb368ad87b6284664436e670957a2";s:4:"name";s:35:"ezc/Archive/file/character_file.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/ezc/Archive/file/character_file.php";}s:25:"ezc/Archive/file/file.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"90067477c3b91fbd36960305b5008dc3";s:4:"name";s:25:"ezc/Archive/file/file.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/opt/alt/php54/usr/share/pear/ezc/Archive/file/file.php";}s:35:"ezc/Archive/interfaces/callback.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5b0e79a77cdded79f2f726709557ba0d";s:4:"name";s:35:"ezc/Archive/interfaces/callback.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/ezc/Archive/interfaces/callback.php";}s:31:"ezc/Archive/options/archive.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"43801773c1b08d20220549a839a11b64";s:4:"name";s:31:"ezc/Archive/options/archive.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/ezc/Archive/options/archive.php";}s:28:"ezc/Archive/structs/file.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8aff13d2dce9722eb6c017cb56ba0251";s:4:"name";s:28:"ezc/Archive/structs/file.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/opt/alt/php54/usr/share/pear/ezc/Archive/structs/file.php";}s:31:"ezc/Archive/tar/headers/gnu.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"42f4fa41c122b57c7437be5eba2a6681";s:4:"name";s:31:"ezc/Archive/tar/headers/gnu.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar/headers/gnu.php";}s:31:"ezc/Archive/tar/headers/pax.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2c538adde875f634371fc03fdf96d5eb";s:4:"name";s:31:"ezc/Archive/tar/headers/pax.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar/headers/pax.php";}s:33:"ezc/Archive/tar/headers/ustar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f740ab119f65467ebdb063afa8e8a1be";s:4:"name";s:33:"ezc/Archive/tar/headers/ustar.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar/headers/ustar.php";}s:30:"ezc/Archive/tar/headers/v7.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6411e0637dd4a8f695fee9db1ac4d009";s:4:"name";s:30:"ezc/Archive/tar/headers/v7.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar/headers/v7.php";}s:23:"ezc/Archive/tar/gnu.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"33fe42a1cae20f63c1d6cf76c56e7a7c";s:4:"name";s:23:"ezc/Archive/tar/gnu.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar/gnu.php";}s:23:"ezc/Archive/tar/pax.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7859fc155b9533787f030970ecf13946";s:4:"name";s:23:"ezc/Archive/tar/pax.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar/pax.php";}s:25:"ezc/Archive/tar/ustar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"87ed07d8eefe3a60197c606b1d2a23a7";s:4:"name";s:25:"ezc/Archive/tar/ustar.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar/ustar.php";}s:22:"ezc/Archive/tar/v7.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c2ae79e94564bd272cfa2679184473f2";s:4:"name";s:22:"ezc/Archive/tar/v7.php";s:4:"role";s:3:"php";s:12:"installed_as";s:52:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar/v7.php";}s:31:"ezc/Archive/utils/checksums.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3da3d0671f6672514c83d19c81390132";s:4:"name";s:31:"ezc/Archive/utils/checksums.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/ezc/Archive/utils/checksums.php";}s:31:"ezc/Archive/utils/file_type.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"aff89d61a3e1d5098f5ae1c46573b34c";s:4:"name";s:31:"ezc/Archive/utils/file_type.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/ezc/Archive/utils/file_type.php";}s:31:"ezc/Archive/utils/stat_mode.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"376245afd1446211dc5af606e6df0c67";s:4:"name";s:31:"ezc/Archive/utils/stat_mode.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/ezc/Archive/utils/stat_mode.php";}s:45:"ezc/Archive/zip/headers/central_directory.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3738ab744b6c5bdd1caddd32ea09a84d";s:4:"name";s:45:"ezc/Archive/zip/headers/central_directory.php";s:4:"role";s:3:"php";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/pear/ezc/Archive/zip/headers/central_directory.php";}s:49:"ezc/Archive/zip/headers/central_directory_end.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f34787c23bf83a287adf52776c9fb463";s:4:"name";s:49:"ezc/Archive/zip/headers/central_directory_end.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/ezc/Archive/zip/headers/central_directory_end.php";}s:38:"ezc/Archive/zip/headers/local_file.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"379e451359f472247c253ae9034b146c";s:4:"name";s:38:"ezc/Archive/zip/headers/local_file.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/ezc/Archive/zip/headers/local_file.php";}s:23:"ezc/Archive/zip/zip.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6927126b5039b4c393e270f3d52a20da";s:4:"name";s:23:"ezc/Archive/zip/zip.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php54/usr/share/pear/ezc/Archive/zip/zip.php";}s:23:"ezc/Archive/archive.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1775383dca270e61680af527a93d0f68";s:4:"name";s:23:"ezc/Archive/archive.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/opt/alt/php54/usr/share/pear/ezc/Archive/archive.php";}s:32:"ezc/Archive/archive_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f95a0357cca0dee2450504a3c41d4629";s:4:"name";s:32:"ezc/Archive/archive_autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php54/usr/share/pear/ezc/Archive/archive_autoload.php";}s:21:"ezc/Archive/entry.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"10cee0df9b58cf85787bf50e11307050";s:4:"name";s:21:"ezc/Archive/entry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php54/usr/share/pear/ezc/Archive/entry.php";}s:33:"ezc/autoload/archive_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f95a0357cca0dee2450504a3c41d4629";s:4:"name";s:33:"ezc/autoload/archive_autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/ezc/autoload/archive_autoload.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:17:{s:49:"/opt/alt/php54/usr/share/pear/data/Archive/design";b:1;s:42:"/opt/alt/php54/usr/share/pear/data/Archive";b:1;s:46:"/opt/alt/php54/usr/share/doc/pear/Archive/docs";b:1;s:41:"/opt/alt/php54/usr/share/doc/pear/Archive";b:1;s:52:"/opt/alt/php54/usr/share/pear/ezc/Archive/exceptions";b:1;s:41:"/opt/alt/php54/usr/share/pear/ezc/Archive";b:1;s:33:"/opt/alt/php54/usr/share/pear/ezc";b:1;s:46:"/opt/alt/php54/usr/share/pear/ezc/Archive/file";b:1;s:52:"/opt/alt/php54/usr/share/pear/ezc/Archive/interfaces";b:1;s:49:"/opt/alt/php54/usr/share/pear/ezc/Archive/options";b:1;s:49:"/opt/alt/php54/usr/share/pear/ezc/Archive/structs";b:1;s:53:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar/headers";b:1;s:45:"/opt/alt/php54/usr/share/pear/ezc/Archive/tar";b:1;s:47:"/opt/alt/php54/usr/share/pear/ezc/Archive/utils";b:1;s:53:"/opt/alt/php54/usr/share/pear/ezc/Archive/zip/headers";b:1;s:45:"/opt/alt/php54/usr/share/pear/ezc/Archive/zip";b:1;s:42:"/opt/alt/php54/usr/share/pear/ezc/autoload";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.4.1";s:12:"release_date";s:10:"2010-03-22";s:13:"release_state";s:6:"stable";s:15:"release_license";s:7:"New BSD";s:13:"release_notes";s:88:"- Fixed #16030: Archive calls posix_* functions even it is only an optional depedency.";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.2.1";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.2";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"components.ez.no";s:4:"name";s:4:"Base";s:3:"rel";s:2:"ge";s:7:"version";s:3:"1.8";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:10:"eZ systems";s:5:"email";s:9:"ezc@ez.no";s:6:"active";s:3:"yes";s:6:"handle";s:3:"ezc";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506489;}PK!Mi4.registry/.channel.components.ez.no/consoletools.regnu[a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.0";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:12:"ConsoleTools";s:7:"channel";s:16:"components.ez.no";s:7:"summary";s:78:"A set of classes to do different actions with the console (also called shell).";s:11:"description";s:187:"A set of classes to do different actions with the console (also called shell). It can render a progress bar, tables and a status bar and contains a class for parsing command line options.";s:4:"lead";a:4:{s:4:"name";s:10:"eZ systems";s:4:"user";s:3:"ezc";s:5:"email";s:9:"ezc@ez.no";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2010-03-22";s:4:"time";s:8:"14:30:18";s:7:"version";a:2:{s:7:"release";s:5:"1.6.1";s:3:"api";s:5:"1.6.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";s:7:"New BSD";s:5:"notes";s:86:"- Fixed issue #16055: Corrected regression in error message for option dependencies.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:106:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"53a2fd46c86d99b961c171a66af52294";s:4:"name";s:24:"design/class_diagram.png";s:4:"role";s:4:"data";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b0e9037513638b06959702b4827d2325";s:4:"name";s:18:"design/console.png";s:4:"role";s:4:"data";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8ec71d0399e811d3ebb49a3a69bea3ad";s:4:"name";s:18:"design/console.xml";s:4:"role";s:4:"data";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"928f4cfd27eaac584c14e11562a1810e";s:4:"name";s:29:"design/console_parameters.png";s:4:"role";s:4:"data";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b984260ee10c0d466594d1c7356fc379";s:4:"name";s:21:"design/design-1.3.txt";s:4:"role";s:4:"data";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9f3666f1fe43c02d93453b6cf5e19f5b";s:4:"name";s:17:"design/design.txt";s:4:"role";s:4:"data";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e3f42a8f3d4359c2619a8abb8c40ae98";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_06.png";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9ef80166b15efecb1fcb147f3eb4a016";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_07.png";s:4:"role";s:3:"doc";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3be4110812d95440c78d6c313d4ed380";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_08.png";s:4:"role";s:3:"doc";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"37c35a19bbe6c983a8ae1c24b9f9c273";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_09.png";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4375674d7ff2271227b5ae9ae1c420f4";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_10.png";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6a44661d8d0ed5dea17e26938c1c388c";s:4:"name";s:12:"docs/CREDITS";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0ded8f674cdc9657885309057e67812f";s:4:"name";s:22:"docs/example_input.php";s:4:"role";s:3:"doc";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"84de543cd335e89b01fab831f231b743";s:4:"name";s:33:"docs/example_menu_dialog_full.php";s:4:"role";s:3:"doc";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b5d0ab2ebca4628c4e1e3bc05ecea61b";s:4:"name";s:23:"docs/example_output.php";s:4:"role";s:3:"doc";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"09648ac0219bfc18c5d7a093b55b280b";s:4:"name";s:28:"docs/example_progressbar.php";s:4:"role";s:3:"doc";}}i:16;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9519aa6d3253ad82f64c7a2c5109fa31";s:4:"name";s:32:"docs/example_progressmonitor.php";s:4:"role";s:3:"doc";}}i:17;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7382b1d71ddeb7bd43b90d582ba18a3b";s:4:"name";s:48:"docs/example_question_dialog_collection_full.php";s:4:"role";s:3:"doc";}}i:18;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"169505e53923c6389ddd987f894328e0";s:4:"name";s:46:"docs/example_question_dialog_factory_yesno.php";s:4:"role";s:3:"doc";}}i:19;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"600a19f4d49a65c5d03c8b3c74d735ac";s:4:"name";s:42:"docs/example_question_dialog_type_full.php";s:4:"role";s:3:"doc";}}i:20;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e829e952f3fa572461175c0966035d51";s:4:"name";s:26:"docs/example_statusbar.php";s:4:"role";s:3:"doc";}}i:21;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1bf46b2ac9e3b5b565a05027d4610918";s:4:"name";s:22:"docs/example_table.php";s:4:"role";s:3:"doc";}}i:22;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"628360cad5c0d6a59a5847faeebfc21d";s:4:"name";s:24:"docs/example_table_2.php";s:4:"role";s:3:"doc";}}i:23;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0d01eec9cb573a51f7cb73a1573c5350";s:4:"name";s:12:"docs/LICENSE";s:4:"role";s:3:"doc";}}i:24;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d33dcb646a07d63a828bf455309d0926";s:4:"name";s:17:"docs/tutorial.txt";s:4:"role";s:3:"doc";}}i:25;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c62acdb41db6b2f5f90506fda0ffe426";s:4:"name";s:26:"docs/tutorial_autoload.php";s:4:"role";s:3:"doc";}}i:26;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"38c2ae0cf8bef46d317983818fc7eeec";s:4:"name";s:41:"docs/tutorial_example_01_output_basic.php";s:4:"role";s:3:"doc";}}i:27;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a9b566b706b217b704f824dd528c245d";s:4:"name";s:44:"docs/tutorial_example_02_output_advanced.php";s:4:"role";s:3:"doc";}}i:28;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5f256cd79a513a1ae8b6d9743dcaf883";s:4:"name";s:43:"docs/tutorial_example_03_output_options.php";s:4:"role";s:3:"doc";}}i:29;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0afbac38453f8d496b9c5ebdff4b7f54";s:4:"name";s:40:"docs/tutorial_example_04_input_basic.php";s:4:"role";s:3:"doc";}}i:30;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9c4dafa4f5a08f20bfc6edc07d3e52a8";s:4:"name";s:43:"docs/tutorial_example_05_input_advanced.php";s:4:"role";s:3:"doc";}}i:31;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2eb8cdf0581dac44124a279903a090b6";s:4:"name";s:46:"docs/tutorial_example_06_progressbar_basic.php";s:4:"role";s:3:"doc";}}i:32;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"ad542c60b818a175aa8f59cbe99f3765";s:4:"name";s:49:"docs/tutorial_example_07_progressbar_advanced.php";s:4:"role";s:3:"doc";}}i:33;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c93007242a832d49a573a9ff71af468d";s:4:"name";s:38:"docs/tutorial_example_08_statusbar.php";s:4:"role";s:3:"doc";}}i:34;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f2de74f7a46f15af94e54f02b8c5190c";s:4:"name";s:40:"docs/tutorial_example_09_table_basic.php";s:4:"role";s:3:"doc";}}i:35;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9c322bff4f25aacbc30b2816a3a693ce";s:4:"name";s:43:"docs/tutorial_example_10_table_advanced.php";s:4:"role";s:3:"doc";}}i:36;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4255cae3b9b8a8ed4a0bf2e6be293925";s:4:"name";s:44:"docs/tutorial_example_11_progressmonitor.php";s:4:"role";s:3:"doc";}}i:37;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5642c76dcad0f38c2bb9cc813ec86635";s:4:"name";s:44:"docs/tutorial_example_12_input_arguments.php";s:4:"role";s:3:"doc";}}i:38;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9dc353f51cf619db963b72ace3e554a1";s:4:"name";s:44:"docs/tutorial_example_13_dialog_question.php";s:4:"role";s:3:"doc";}}i:39;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2fe7147cf77f8595caec34390a869e00";s:4:"name";s:49:"docs/tutorial_example_14_dialog_yesnoquestion.php";s:4:"role";s:3:"doc";}}i:40;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"416ae4c5c942d184d083f89f1d958578";s:4:"name";s:40:"docs/tutorial_example_15_dialog_menu.php";s:4:"role";s:3:"doc";}}i:41;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7e204a3db8893993c618d9fccb63ce80";s:4:"name";s:40:"docs/tutorial_example_output_targets.php";s:4:"role";s:3:"doc";}}i:42;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a5d0832dc9a28b1b83e377ec2f72503c";s:4:"name";s:33:"ezc/autoload/console_autoload.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e168dc91ef4aa95feb62c374850439ad";s:4:"name";s:58:"ezc/ConsoleTools/dialog/validators/menu_dialog_default.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bb23b9eb4ce6ecfc74d3d14697522302";s:4:"name";s:65:"ezc/ConsoleTools/dialog/validators/question_dialog_collection.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6bf4939fecdf3612d26258304e116d68";s:4:"name";s:62:"ezc/ConsoleTools/dialog/validators/question_dialog_mapping.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4426ac09a206b255af3f86e138f3d280";s:4:"name";s:60:"ezc/ConsoleTools/dialog/validators/question_dialog_regex.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"67f5529cb45617843e60a0ea3e4c2941";s:4:"name";s:59:"ezc/ConsoleTools/dialog/validators/question_dialog_type.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4c8dbaf88d94e339940d87341e9e511c";s:4:"name";s:39:"ezc/ConsoleTools/dialog/menu_dialog.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a0f9e7fcbc20920a7718ab4063cedbb3";s:4:"name";s:43:"ezc/ConsoleTools/dialog/question_dialog.php";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"76cf3873bf8de152961bef1a958de739";s:4:"name";s:40:"ezc/ConsoleTools/exceptions/argument.php";s:4:"role";s:3:"php";}}i:51;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e76fb2146d1ab7770ab7b55acac395f6";s:4:"name";s:59:"ezc/ConsoleTools/exceptions/argument_already_registered.php";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b9e1712dced4a71c03299d2d629d8bd9";s:4:"name";s:60:"ezc/ConsoleTools/exceptions/argument_mandatory_violation.php";s:4:"role";s:3:"php";}}i:53;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"016560b74a1713b240b3b2831fb9ce15";s:4:"name";s:49:"ezc/ConsoleTools/exceptions/argument_too_many.php";s:4:"role";s:3:"php";}}i:54;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a928f645d541811a6cb268cfcf989103";s:4:"name";s:55:"ezc/ConsoleTools/exceptions/argument_type_violation.php";s:4:"role";s:3:"php";}}i:55;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dfafc6e5a8f5e95b3f9d7fc83256ba3a";s:4:"name";s:44:"ezc/ConsoleTools/exceptions/dialog_abort.php";s:4:"role";s:3:"php";}}i:56;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3a0932a2bd5a048165650d9c1c65d394";s:4:"name";s:41:"ezc/ConsoleTools/exceptions/exception.php";s:4:"role";s:3:"php";}}i:57;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"55ec00268bfdcabaececab9717e670b0";s:4:"name";s:51:"ezc/ConsoleTools/exceptions/invalid_option_name.php";s:4:"role";s:3:"php";}}i:58;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8387a3ed2488c13d8e85ac1f36d2776d";s:4:"name";s:53:"ezc/ConsoleTools/exceptions/invalid_output_target.php";s:4:"role";s:3:"php";}}i:59;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"adf293f0a7b64a11ad750ceb7d8d06fb";s:4:"name";s:50:"ezc/ConsoleTools/exceptions/no_position_stored.php";s:4:"role";s:3:"php";}}i:60;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"26c6652ca11a904feb0114ea063137ad";s:4:"name";s:54:"ezc/ConsoleTools/exceptions/no_valid_dialog_result.php";s:4:"role";s:3:"php";}}i:61;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1342642994f7e2af6617ab50e1d50201";s:4:"name";s:38:"ezc/ConsoleTools/exceptions/option.php";s:4:"role";s:3:"php";}}i:62;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1c82d9cd44cab9cd2912a7ff85fe778b";s:4:"name";s:57:"ezc/ConsoleTools/exceptions/option_already_registered.php";s:4:"role";s:3:"php";}}i:63;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"920d616d1bc71c83e4730273219d2734";s:4:"name";s:58:"ezc/ConsoleTools/exceptions/option_arguments_violation.php";s:4:"role";s:3:"php";}}i:64;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"524d16a055a3d3a41c2dc3c0c1a1fed2";s:4:"name";s:59:"ezc/ConsoleTools/exceptions/option_dependency_violation.php";s:4:"role";s:3:"php";}}i:65;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"99291a96437e2ab968e1db9e8ef14a11";s:4:"name";s:58:"ezc/ConsoleTools/exceptions/option_exclusion_violation.php";s:4:"role";s:3:"php";}}i:66;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1f5f85eb8c761af0a4c0cf72552a87ac";s:4:"name";s:58:"ezc/ConsoleTools/exceptions/option_mandatory_violation.php";s:4:"role";s:3:"php";}}i:67;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"17756f682466ebd0e1854eefcdb392fb";s:4:"name";s:52:"ezc/ConsoleTools/exceptions/option_missing_value.php";s:4:"role";s:3:"php";}}i:68;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"779c88d8911c1a37a8f62c07a7609fd1";s:4:"name";s:49:"ezc/ConsoleTools/exceptions/option_not_exists.php";s:4:"role";s:3:"php";}}i:69;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bcef6b269e9518b5ab50a665dcefdae4";s:4:"name";s:47:"ezc/ConsoleTools/exceptions/option_no_alias.php";s:4:"role";s:3:"php";}}i:70;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"22cb7a2e3afecccbe82e7a43b7e3c0b0";s:4:"name";s:60:"ezc/ConsoleTools/exceptions/option_string_not_wellformed.php";s:4:"role";s:3:"php";}}i:71;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e65ae0e90ec95ec1b02d427585bcb147";s:4:"name";s:54:"ezc/ConsoleTools/exceptions/option_too_many_values.php";s:4:"role";s:3:"php";}}i:72;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c1b97683c2dada4c35d670f22bf4bfd9";s:4:"name";s:53:"ezc/ConsoleTools/exceptions/option_type_violation.php";s:4:"role";s:3:"php";}}i:73;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1358c658d502de8757d6a8e4ae40d636";s:4:"name";s:51:"ezc/ConsoleTools/input/help_generators/standard.php";s:4:"role";s:3:"php";}}i:74;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3d2a4f1bb8d46856c6da3c266fa8b019";s:4:"name";s:46:"ezc/ConsoleTools/input/validators/standard.php";s:4:"role";s:3:"php";}}i:75;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a3c508cecae94655b9d134c18bf16ad2";s:4:"name";s:35:"ezc/ConsoleTools/input/argument.php";s:4:"role";s:3:"php";}}i:76;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"64be58bc0e7faef3f8548b69f8975ced";s:4:"name";s:36:"ezc/ConsoleTools/input/arguments.php";s:4:"role";s:3:"php";}}i:77;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"464bd6804e9ea90cd7e8c4e395f51a70";s:4:"name";s:33:"ezc/ConsoleTools/input/option.php";s:4:"role";s:3:"php";}}i:78;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"da1589cfccd05250f85b1d8c30f4da7c";s:4:"name";s:38:"ezc/ConsoleTools/interfaces/dialog.php";s:4:"role";s:3:"php";}}i:79;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"fbc7fafd21090e559cbc707bf8d2ea5a";s:4:"name";s:48:"ezc/ConsoleTools/interfaces/dialog_validator.php";s:4:"role";s:3:"php";}}i:80;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1e0b4eb1a29c41f385781ca8b9c3e442";s:4:"name";s:52:"ezc/ConsoleTools/interfaces/input_help_generator.php";s:4:"role";s:3:"php";}}i:81;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2e5f1707fe47153bf4b1e48aa01cf76c";s:4:"name";s:47:"ezc/ConsoleTools/interfaces/input_validator.php";s:4:"role";s:3:"php";}}i:82;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e7e4198450a70f692c5882464a7e9e11";s:4:"name";s:53:"ezc/ConsoleTools/interfaces/menu_dialog_validator.php";s:4:"role";s:3:"php";}}i:83;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8e2d83164e1a649c3f59a13f3915a9f8";s:4:"name";s:57:"ezc/ConsoleTools/interfaces/question_dialog_validator.php";s:4:"role";s:3:"php";}}i:84;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c8c8969fe1528d7e4c28db6c078b0245";s:4:"name";s:35:"ezc/ConsoleTools/options/dialog.php";s:4:"role";s:3:"php";}}i:85;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6f5724cd06d9d4541428384879d42eec";s:4:"name";s:40:"ezc/ConsoleTools/options/menu_dialog.php";s:4:"role";s:3:"php";}}i:86;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c0482b1ed0ecff49594bace3aa62d4d0";s:4:"name";s:35:"ezc/ConsoleTools/options/output.php";s:4:"role";s:3:"php";}}i:87;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3e6808ce1f4843313b1c5d9997507f91";s:4:"name";s:40:"ezc/ConsoleTools/options/progressbar.php";s:4:"role";s:3:"php";}}i:88;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dc171e2272f4929c312c553d452b807d";s:4:"name";s:44:"ezc/ConsoleTools/options/progressmonitor.php";s:4:"role";s:3:"php";}}i:89;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"069eb222843610015ed324dca2b56dec";s:4:"name";s:44:"ezc/ConsoleTools/options/question_dialog.php";s:4:"role";s:3:"php";}}i:90;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"70d32f729b97d036e7729f7426bc7b45";s:4:"name";s:38:"ezc/ConsoleTools/options/statusbar.php";s:4:"role";s:3:"php";}}i:91;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7426cf158c78345d7656a0e23b752d25";s:4:"name";s:34:"ezc/ConsoleTools/options/table.php";s:4:"role";s:3:"php";}}i:92;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"772506539fa9180fbfe3167d95462bdd";s:4:"name";s:40:"ezc/ConsoleTools/structs/option_rule.php";s:4:"role";s:3:"php";}}i:93;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a7ef5dd26f2d70fe8374200c52136451";s:4:"name";s:42:"ezc/ConsoleTools/structs/output_format.php";s:4:"role";s:3:"php";}}i:94;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"fe2a5c4ebcce728d87dab9ffaec878ef";s:4:"name";s:43:"ezc/ConsoleTools/structs/output_formats.php";s:4:"role";s:3:"php";}}i:95;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"84edad158922a7b0b07975b720fd11d4";s:4:"name";s:31:"ezc/ConsoleTools/table/cell.php";s:4:"role";s:3:"php";}}i:96;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2d99e475e21a0a82fd0051ae07e47f4d";s:4:"name";s:30:"ezc/ConsoleTools/table/row.php";s:4:"role";s:3:"php";}}i:97;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1f23811735a6bd4f98b8c2f9a688d934";s:4:"name";s:33:"ezc/ConsoleTools/tools/string.php";s:4:"role";s:3:"php";}}i:98;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a5d0832dc9a28b1b83e377ec2f72503c";s:4:"name";s:37:"ezc/ConsoleTools/console_autoload.php";s:4:"role";s:3:"php";}}i:99;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"131b67a1b928ff63db8ffd6eefbe17b6";s:4:"name";s:34:"ezc/ConsoleTools/dialog_viewer.php";s:4:"role";s:3:"php";}}i:100;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"35da1f48b0fa95bf771729f5bafe3220";s:4:"name";s:26:"ezc/ConsoleTools/input.php";s:4:"role";s:3:"php";}}i:101;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f7b975843f75809d42e6710a7793b4c6";s:4:"name";s:27:"ezc/ConsoleTools/output.php";s:4:"role";s:3:"php";}}i:102;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7de9cac1d84eca29792d54241b210633";s:4:"name";s:32:"ezc/ConsoleTools/progressbar.php";s:4:"role";s:3:"php";}}i:103;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f3b0f156acc3ee5d6e5c1652aac5cb47";s:4:"name";s:36:"ezc/ConsoleTools/progressmonitor.php";s:4:"role";s:3:"php";}}i:104;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d6a504831ced759070096f0585b27e45";s:4:"name";s:30:"ezc/ConsoleTools/statusbar.php";s:4:"role";s:3:"php";}}i:105;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a78728a6c0328a88aec5ea16201e68f0";s:4:"name";s:26:"ezc/ConsoleTools/table.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"5.2.1";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.2";}s:7:"package";a:3:{s:4:"name";s:4:"Base";s:7:"channel";s:16:"components.ez.no";s:3:"min";s:3:"1.8";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.6.1";s:3:"api";s:5:"1.6.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2010-03-22";s:7:"license";s:7:"New BSD";s:5:"notes";s:86:"- Fixed issue #16055: Corrected regression in error message for option dependencies.";}}s:8:"filelist";a:106:{s:24:"design/class_diagram.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"53a2fd46c86d99b961c171a66af52294";s:4:"name";s:24:"design/class_diagram.png";s:4:"role";s:4:"data";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/data/ConsoleTools/design/class_diagram.png";}s:18:"design/console.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b0e9037513638b06959702b4827d2325";s:4:"name";s:18:"design/console.png";s:4:"role";s:4:"data";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/data/ConsoleTools/design/console.png";}s:18:"design/console.xml";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8ec71d0399e811d3ebb49a3a69bea3ad";s:4:"name";s:18:"design/console.xml";s:4:"role";s:4:"data";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/data/ConsoleTools/design/console.xml";}s:29:"design/console_parameters.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"928f4cfd27eaac584c14e11562a1810e";s:4:"name";s:29:"design/console_parameters.png";s:4:"role";s:4:"data";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/data/ConsoleTools/design/console_parameters.png";}s:21:"design/design-1.3.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b984260ee10c0d466594d1c7356fc379";s:4:"name";s:21:"design/design-1.3.txt";s:4:"role";s:4:"data";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/data/ConsoleTools/design/design-1.3.txt";}s:17:"design/design.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9f3666f1fe43c02d93453b6cf5e19f5b";s:4:"name";s:17:"design/design.txt";s:4:"role";s:4:"data";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/data/ConsoleTools/design/design.txt";}s:45:"docs/img/consoletools_tutorial_example_06.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e3f42a8f3d4359c2619a8abb8c40ae98";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_06.png";s:4:"role";s:3:"doc";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/img/consoletools_tutorial_example_06.png";}s:45:"docs/img/consoletools_tutorial_example_07.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9ef80166b15efecb1fcb147f3eb4a016";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_07.png";s:4:"role";s:3:"doc";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/img/consoletools_tutorial_example_07.png";}s:45:"docs/img/consoletools_tutorial_example_08.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3be4110812d95440c78d6c313d4ed380";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_08.png";s:4:"role";s:3:"doc";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/img/consoletools_tutorial_example_08.png";}s:45:"docs/img/consoletools_tutorial_example_09.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"37c35a19bbe6c983a8ae1c24b9f9c273";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_09.png";s:4:"role";s:3:"doc";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/img/consoletools_tutorial_example_09.png";}s:45:"docs/img/consoletools_tutorial_example_10.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4375674d7ff2271227b5ae9ae1c420f4";s:4:"name";s:45:"docs/img/consoletools_tutorial_example_10.png";s:4:"role";s:3:"doc";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/img/consoletools_tutorial_example_10.png";}s:12:"docs/CREDITS";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6a44661d8d0ed5dea17e26938c1c388c";s:4:"name";s:12:"docs/CREDITS";s:4:"role";s:3:"doc";s:12:"installed_as";s:59:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/CREDITS";}s:22:"docs/example_input.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0ded8f674cdc9657885309057e67812f";s:4:"name";s:22:"docs/example_input.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_input.php";}s:33:"docs/example_menu_dialog_full.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"84de543cd335e89b01fab831f231b743";s:4:"name";s:33:"docs/example_menu_dialog_full.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_menu_dialog_full.php";}s:23:"docs/example_output.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b5d0ab2ebca4628c4e1e3bc05ecea61b";s:4:"name";s:23:"docs/example_output.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_output.php";}s:28:"docs/example_progressbar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"09648ac0219bfc18c5d7a093b55b280b";s:4:"name";s:28:"docs/example_progressbar.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_progressbar.php";}s:32:"docs/example_progressmonitor.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9519aa6d3253ad82f64c7a2c5109fa31";s:4:"name";s:32:"docs/example_progressmonitor.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_progressmonitor.php";}s:48:"docs/example_question_dialog_collection_full.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7382b1d71ddeb7bd43b90d582ba18a3b";s:4:"name";s:48:"docs/example_question_dialog_collection_full.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_question_dialog_collection_full.php";}s:46:"docs/example_question_dialog_factory_yesno.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"169505e53923c6389ddd987f894328e0";s:4:"name";s:46:"docs/example_question_dialog_factory_yesno.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_question_dialog_factory_yesno.php";}s:42:"docs/example_question_dialog_type_full.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"600a19f4d49a65c5d03c8b3c74d735ac";s:4:"name";s:42:"docs/example_question_dialog_type_full.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_question_dialog_type_full.php";}s:26:"docs/example_statusbar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e829e952f3fa572461175c0966035d51";s:4:"name";s:26:"docs/example_statusbar.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_statusbar.php";}s:22:"docs/example_table.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1bf46b2ac9e3b5b565a05027d4610918";s:4:"name";s:22:"docs/example_table.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_table.php";}s:24:"docs/example_table_2.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"628360cad5c0d6a59a5847faeebfc21d";s:4:"name";s:24:"docs/example_table_2.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/example_table_2.php";}s:12:"docs/LICENSE";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0d01eec9cb573a51f7cb73a1573c5350";s:4:"name";s:12:"docs/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:59:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/LICENSE";}s:17:"docs/tutorial.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d33dcb646a07d63a828bf455309d0926";s:4:"name";s:17:"docs/tutorial.txt";s:4:"role";s:3:"doc";s:12:"installed_as";s:64:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial.txt";}s:26:"docs/tutorial_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c62acdb41db6b2f5f90506fda0ffe426";s:4:"name";s:26:"docs/tutorial_autoload.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_autoload.php";}s:41:"docs/tutorial_example_01_output_basic.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"38c2ae0cf8bef46d317983818fc7eeec";s:4:"name";s:41:"docs/tutorial_example_01_output_basic.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_01_output_basic.php";}s:44:"docs/tutorial_example_02_output_advanced.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a9b566b706b217b704f824dd528c245d";s:4:"name";s:44:"docs/tutorial_example_02_output_advanced.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_02_output_advanced.php";}s:43:"docs/tutorial_example_03_output_options.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5f256cd79a513a1ae8b6d9743dcaf883";s:4:"name";s:43:"docs/tutorial_example_03_output_options.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_03_output_options.php";}s:40:"docs/tutorial_example_04_input_basic.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0afbac38453f8d496b9c5ebdff4b7f54";s:4:"name";s:40:"docs/tutorial_example_04_input_basic.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_04_input_basic.php";}s:43:"docs/tutorial_example_05_input_advanced.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9c4dafa4f5a08f20bfc6edc07d3e52a8";s:4:"name";s:43:"docs/tutorial_example_05_input_advanced.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_05_input_advanced.php";}s:46:"docs/tutorial_example_06_progressbar_basic.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2eb8cdf0581dac44124a279903a090b6";s:4:"name";s:46:"docs/tutorial_example_06_progressbar_basic.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:93:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_06_progressbar_basic.php";}s:49:"docs/tutorial_example_07_progressbar_advanced.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"ad542c60b818a175aa8f59cbe99f3765";s:4:"name";s:49:"docs/tutorial_example_07_progressbar_advanced.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_07_progressbar_advanced.php";}s:38:"docs/tutorial_example_08_statusbar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c93007242a832d49a573a9ff71af468d";s:4:"name";s:38:"docs/tutorial_example_08_statusbar.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_08_statusbar.php";}s:40:"docs/tutorial_example_09_table_basic.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f2de74f7a46f15af94e54f02b8c5190c";s:4:"name";s:40:"docs/tutorial_example_09_table_basic.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_09_table_basic.php";}s:43:"docs/tutorial_example_10_table_advanced.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9c322bff4f25aacbc30b2816a3a693ce";s:4:"name";s:43:"docs/tutorial_example_10_table_advanced.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_10_table_advanced.php";}s:44:"docs/tutorial_example_11_progressmonitor.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4255cae3b9b8a8ed4a0bf2e6be293925";s:4:"name";s:44:"docs/tutorial_example_11_progressmonitor.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_11_progressmonitor.php";}s:44:"docs/tutorial_example_12_input_arguments.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5642c76dcad0f38c2bb9cc813ec86635";s:4:"name";s:44:"docs/tutorial_example_12_input_arguments.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_12_input_arguments.php";}s:44:"docs/tutorial_example_13_dialog_question.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9dc353f51cf619db963b72ace3e554a1";s:4:"name";s:44:"docs/tutorial_example_13_dialog_question.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:91:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_13_dialog_question.php";}s:49:"docs/tutorial_example_14_dialog_yesnoquestion.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2fe7147cf77f8595caec34390a869e00";s:4:"name";s:49:"docs/tutorial_example_14_dialog_yesnoquestion.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:96:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_14_dialog_yesnoquestion.php";}s:40:"docs/tutorial_example_15_dialog_menu.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"416ae4c5c942d184d083f89f1d958578";s:4:"name";s:40:"docs/tutorial_example_15_dialog_menu.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_15_dialog_menu.php";}s:40:"docs/tutorial_example_output_targets.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7e204a3db8893993c618d9fccb63ce80";s:4:"name";s:40:"docs/tutorial_example_output_targets.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/tutorial_example_output_targets.php";}s:33:"ezc/autoload/console_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a5d0832dc9a28b1b83e377ec2f72503c";s:4:"name";s:33:"ezc/autoload/console_autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/ezc/autoload/console_autoload.php";}s:58:"ezc/ConsoleTools/dialog/validators/menu_dialog_default.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e168dc91ef4aa95feb62c374850439ad";s:4:"name";s:58:"ezc/ConsoleTools/dialog/validators/menu_dialog_default.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog/validators/menu_dialog_default.php";}s:65:"ezc/ConsoleTools/dialog/validators/question_dialog_collection.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bb23b9eb4ce6ecfc74d3d14697522302";s:4:"name";s:65:"ezc/ConsoleTools/dialog/validators/question_dialog_collection.php";s:4:"role";s:3:"php";s:12:"installed_as";s:95:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog/validators/question_dialog_collection.php";}s:62:"ezc/ConsoleTools/dialog/validators/question_dialog_mapping.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6bf4939fecdf3612d26258304e116d68";s:4:"name";s:62:"ezc/ConsoleTools/dialog/validators/question_dialog_mapping.php";s:4:"role";s:3:"php";s:12:"installed_as";s:92:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog/validators/question_dialog_mapping.php";}s:60:"ezc/ConsoleTools/dialog/validators/question_dialog_regex.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4426ac09a206b255af3f86e138f3d280";s:4:"name";s:60:"ezc/ConsoleTools/dialog/validators/question_dialog_regex.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog/validators/question_dialog_regex.php";}s:59:"ezc/ConsoleTools/dialog/validators/question_dialog_type.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"67f5529cb45617843e60a0ea3e4c2941";s:4:"name";s:59:"ezc/ConsoleTools/dialog/validators/question_dialog_type.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog/validators/question_dialog_type.php";}s:39:"ezc/ConsoleTools/dialog/menu_dialog.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4c8dbaf88d94e339940d87341e9e511c";s:4:"name";s:39:"ezc/ConsoleTools/dialog/menu_dialog.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog/menu_dialog.php";}s:43:"ezc/ConsoleTools/dialog/question_dialog.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a0f9e7fcbc20920a7718ab4063cedbb3";s:4:"name";s:43:"ezc/ConsoleTools/dialog/question_dialog.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog/question_dialog.php";}s:40:"ezc/ConsoleTools/exceptions/argument.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"76cf3873bf8de152961bef1a958de739";s:4:"name";s:40:"ezc/ConsoleTools/exceptions/argument.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/argument.php";}s:59:"ezc/ConsoleTools/exceptions/argument_already_registered.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e76fb2146d1ab7770ab7b55acac395f6";s:4:"name";s:59:"ezc/ConsoleTools/exceptions/argument_already_registered.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/argument_already_registered.php";}s:60:"ezc/ConsoleTools/exceptions/argument_mandatory_violation.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"b9e1712dced4a71c03299d2d629d8bd9";s:4:"name";s:60:"ezc/ConsoleTools/exceptions/argument_mandatory_violation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/argument_mandatory_violation.php";}s:49:"ezc/ConsoleTools/exceptions/argument_too_many.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"016560b74a1713b240b3b2831fb9ce15";s:4:"name";s:49:"ezc/ConsoleTools/exceptions/argument_too_many.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/argument_too_many.php";}s:55:"ezc/ConsoleTools/exceptions/argument_type_violation.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a928f645d541811a6cb268cfcf989103";s:4:"name";s:55:"ezc/ConsoleTools/exceptions/argument_type_violation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/argument_type_violation.php";}s:44:"ezc/ConsoleTools/exceptions/dialog_abort.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dfafc6e5a8f5e95b3f9d7fc83256ba3a";s:4:"name";s:44:"ezc/ConsoleTools/exceptions/dialog_abort.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/dialog_abort.php";}s:41:"ezc/ConsoleTools/exceptions/exception.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3a0932a2bd5a048165650d9c1c65d394";s:4:"name";s:41:"ezc/ConsoleTools/exceptions/exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/exception.php";}s:51:"ezc/ConsoleTools/exceptions/invalid_option_name.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"55ec00268bfdcabaececab9717e670b0";s:4:"name";s:51:"ezc/ConsoleTools/exceptions/invalid_option_name.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/invalid_option_name.php";}s:53:"ezc/ConsoleTools/exceptions/invalid_output_target.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8387a3ed2488c13d8e85ac1f36d2776d";s:4:"name";s:53:"ezc/ConsoleTools/exceptions/invalid_output_target.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/invalid_output_target.php";}s:50:"ezc/ConsoleTools/exceptions/no_position_stored.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"adf293f0a7b64a11ad750ceb7d8d06fb";s:4:"name";s:50:"ezc/ConsoleTools/exceptions/no_position_stored.php";s:4:"role";s:3:"php";s:12:"installed_as";s:80:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/no_position_stored.php";}s:54:"ezc/ConsoleTools/exceptions/no_valid_dialog_result.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"26c6652ca11a904feb0114ea063137ad";s:4:"name";s:54:"ezc/ConsoleTools/exceptions/no_valid_dialog_result.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/no_valid_dialog_result.php";}s:38:"ezc/ConsoleTools/exceptions/option.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1342642994f7e2af6617ab50e1d50201";s:4:"name";s:38:"ezc/ConsoleTools/exceptions/option.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option.php";}s:57:"ezc/ConsoleTools/exceptions/option_already_registered.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1c82d9cd44cab9cd2912a7ff85fe778b";s:4:"name";s:57:"ezc/ConsoleTools/exceptions/option_already_registered.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_already_registered.php";}s:58:"ezc/ConsoleTools/exceptions/option_arguments_violation.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"920d616d1bc71c83e4730273219d2734";s:4:"name";s:58:"ezc/ConsoleTools/exceptions/option_arguments_violation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_arguments_violation.php";}s:59:"ezc/ConsoleTools/exceptions/option_dependency_violation.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"524d16a055a3d3a41c2dc3c0c1a1fed2";s:4:"name";s:59:"ezc/ConsoleTools/exceptions/option_dependency_violation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:89:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_dependency_violation.php";}s:58:"ezc/ConsoleTools/exceptions/option_exclusion_violation.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"99291a96437e2ab968e1db9e8ef14a11";s:4:"name";s:58:"ezc/ConsoleTools/exceptions/option_exclusion_violation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_exclusion_violation.php";}s:58:"ezc/ConsoleTools/exceptions/option_mandatory_violation.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1f5f85eb8c761af0a4c0cf72552a87ac";s:4:"name";s:58:"ezc/ConsoleTools/exceptions/option_mandatory_violation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:88:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_mandatory_violation.php";}s:52:"ezc/ConsoleTools/exceptions/option_missing_value.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"17756f682466ebd0e1854eefcdb392fb";s:4:"name";s:52:"ezc/ConsoleTools/exceptions/option_missing_value.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_missing_value.php";}s:49:"ezc/ConsoleTools/exceptions/option_not_exists.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"779c88d8911c1a37a8f62c07a7609fd1";s:4:"name";s:49:"ezc/ConsoleTools/exceptions/option_not_exists.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_not_exists.php";}s:47:"ezc/ConsoleTools/exceptions/option_no_alias.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bcef6b269e9518b5ab50a665dcefdae4";s:4:"name";s:47:"ezc/ConsoleTools/exceptions/option_no_alias.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_no_alias.php";}s:60:"ezc/ConsoleTools/exceptions/option_string_not_wellformed.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"22cb7a2e3afecccbe82e7a43b7e3c0b0";s:4:"name";s:60:"ezc/ConsoleTools/exceptions/option_string_not_wellformed.php";s:4:"role";s:3:"php";s:12:"installed_as";s:90:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_string_not_wellformed.php";}s:54:"ezc/ConsoleTools/exceptions/option_too_many_values.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e65ae0e90ec95ec1b02d427585bcb147";s:4:"name";s:54:"ezc/ConsoleTools/exceptions/option_too_many_values.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_too_many_values.php";}s:53:"ezc/ConsoleTools/exceptions/option_type_violation.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c1b97683c2dada4c35d670f22bf4bfd9";s:4:"name";s:53:"ezc/ConsoleTools/exceptions/option_type_violation.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions/option_type_violation.php";}s:51:"ezc/ConsoleTools/input/help_generators/standard.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1358c658d502de8757d6a8e4ae40d636";s:4:"name";s:51:"ezc/ConsoleTools/input/help_generators/standard.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/input/help_generators/standard.php";}s:46:"ezc/ConsoleTools/input/validators/standard.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3d2a4f1bb8d46856c6da3c266fa8b019";s:4:"name";s:46:"ezc/ConsoleTools/input/validators/standard.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/input/validators/standard.php";}s:35:"ezc/ConsoleTools/input/argument.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a3c508cecae94655b9d134c18bf16ad2";s:4:"name";s:35:"ezc/ConsoleTools/input/argument.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/input/argument.php";}s:36:"ezc/ConsoleTools/input/arguments.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"64be58bc0e7faef3f8548b69f8975ced";s:4:"name";s:36:"ezc/ConsoleTools/input/arguments.php";s:4:"role";s:3:"php";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/input/arguments.php";}s:33:"ezc/ConsoleTools/input/option.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"464bd6804e9ea90cd7e8c4e395f51a70";s:4:"name";s:33:"ezc/ConsoleTools/input/option.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/input/option.php";}s:38:"ezc/ConsoleTools/interfaces/dialog.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"da1589cfccd05250f85b1d8c30f4da7c";s:4:"name";s:38:"ezc/ConsoleTools/interfaces/dialog.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/interfaces/dialog.php";}s:48:"ezc/ConsoleTools/interfaces/dialog_validator.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"fbc7fafd21090e559cbc707bf8d2ea5a";s:4:"name";s:48:"ezc/ConsoleTools/interfaces/dialog_validator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/interfaces/dialog_validator.php";}s:52:"ezc/ConsoleTools/interfaces/input_help_generator.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1e0b4eb1a29c41f385781ca8b9c3e442";s:4:"name";s:52:"ezc/ConsoleTools/interfaces/input_help_generator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:82:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/interfaces/input_help_generator.php";}s:47:"ezc/ConsoleTools/interfaces/input_validator.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2e5f1707fe47153bf4b1e48aa01cf76c";s:4:"name";s:47:"ezc/ConsoleTools/interfaces/input_validator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/interfaces/input_validator.php";}s:53:"ezc/ConsoleTools/interfaces/menu_dialog_validator.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e7e4198450a70f692c5882464a7e9e11";s:4:"name";s:53:"ezc/ConsoleTools/interfaces/menu_dialog_validator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:83:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/interfaces/menu_dialog_validator.php";}s:57:"ezc/ConsoleTools/interfaces/question_dialog_validator.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8e2d83164e1a649c3f59a13f3915a9f8";s:4:"name";s:57:"ezc/ConsoleTools/interfaces/question_dialog_validator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:87:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/interfaces/question_dialog_validator.php";}s:35:"ezc/ConsoleTools/options/dialog.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c8c8969fe1528d7e4c28db6c078b0245";s:4:"name";s:35:"ezc/ConsoleTools/options/dialog.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/options/dialog.php";}s:40:"ezc/ConsoleTools/options/menu_dialog.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6f5724cd06d9d4541428384879d42eec";s:4:"name";s:40:"ezc/ConsoleTools/options/menu_dialog.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/options/menu_dialog.php";}s:35:"ezc/ConsoleTools/options/output.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c0482b1ed0ecff49594bace3aa62d4d0";s:4:"name";s:35:"ezc/ConsoleTools/options/output.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/options/output.php";}s:40:"ezc/ConsoleTools/options/progressbar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3e6808ce1f4843313b1c5d9997507f91";s:4:"name";s:40:"ezc/ConsoleTools/options/progressbar.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/options/progressbar.php";}s:44:"ezc/ConsoleTools/options/progressmonitor.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dc171e2272f4929c312c553d452b807d";s:4:"name";s:44:"ezc/ConsoleTools/options/progressmonitor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/options/progressmonitor.php";}s:44:"ezc/ConsoleTools/options/question_dialog.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"069eb222843610015ed324dca2b56dec";s:4:"name";s:44:"ezc/ConsoleTools/options/question_dialog.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/options/question_dialog.php";}s:38:"ezc/ConsoleTools/options/statusbar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"70d32f729b97d036e7729f7426bc7b45";s:4:"name";s:38:"ezc/ConsoleTools/options/statusbar.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/options/statusbar.php";}s:34:"ezc/ConsoleTools/options/table.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7426cf158c78345d7656a0e23b752d25";s:4:"name";s:34:"ezc/ConsoleTools/options/table.php";s:4:"role";s:3:"php";s:12:"installed_as";s:64:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/options/table.php";}s:40:"ezc/ConsoleTools/structs/option_rule.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"772506539fa9180fbfe3167d95462bdd";s:4:"name";s:40:"ezc/ConsoleTools/structs/option_rule.php";s:4:"role";s:3:"php";s:12:"installed_as";s:70:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/structs/option_rule.php";}s:42:"ezc/ConsoleTools/structs/output_format.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a7ef5dd26f2d70fe8374200c52136451";s:4:"name";s:42:"ezc/ConsoleTools/structs/output_format.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/structs/output_format.php";}s:43:"ezc/ConsoleTools/structs/output_formats.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"fe2a5c4ebcce728d87dab9ffaec878ef";s:4:"name";s:43:"ezc/ConsoleTools/structs/output_formats.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/structs/output_formats.php";}s:31:"ezc/ConsoleTools/table/cell.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"84edad158922a7b0b07975b720fd11d4";s:4:"name";s:31:"ezc/ConsoleTools/table/cell.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/table/cell.php";}s:30:"ezc/ConsoleTools/table/row.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2d99e475e21a0a82fd0051ae07e47f4d";s:4:"name";s:30:"ezc/ConsoleTools/table/row.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/table/row.php";}s:33:"ezc/ConsoleTools/tools/string.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1f23811735a6bd4f98b8c2f9a688d934";s:4:"name";s:33:"ezc/ConsoleTools/tools/string.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/tools/string.php";}s:37:"ezc/ConsoleTools/console_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a5d0832dc9a28b1b83e377ec2f72503c";s:4:"name";s:37:"ezc/ConsoleTools/console_autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/console_autoload.php";}s:34:"ezc/ConsoleTools/dialog_viewer.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"131b67a1b928ff63db8ffd6eefbe17b6";s:4:"name";s:34:"ezc/ConsoleTools/dialog_viewer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:64:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog_viewer.php";}s:26:"ezc/ConsoleTools/input.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"35da1f48b0fa95bf771729f5bafe3220";s:4:"name";s:26:"ezc/ConsoleTools/input.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/input.php";}s:27:"ezc/ConsoleTools/output.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f7b975843f75809d42e6710a7793b4c6";s:4:"name";s:27:"ezc/ConsoleTools/output.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/output.php";}s:32:"ezc/ConsoleTools/progressbar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7de9cac1d84eca29792d54241b210633";s:4:"name";s:32:"ezc/ConsoleTools/progressbar.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/progressbar.php";}s:36:"ezc/ConsoleTools/progressmonitor.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f3b0f156acc3ee5d6e5c1652aac5cb47";s:4:"name";s:36:"ezc/ConsoleTools/progressmonitor.php";s:4:"role";s:3:"php";s:12:"installed_as";s:66:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/progressmonitor.php";}s:30:"ezc/ConsoleTools/statusbar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d6a504831ced759070096f0585b27e45";s:4:"name";s:30:"ezc/ConsoleTools/statusbar.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/statusbar.php";}s:26:"ezc/ConsoleTools/table.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a78728a6c0328a88aec5ea16201e68f0";s:4:"name";s:26:"ezc/ConsoleTools/table.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/table.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:19:{s:54:"/opt/alt/php54/usr/share/pear/data/ConsoleTools/design";b:1;s:47:"/opt/alt/php54/usr/share/pear/data/ConsoleTools";b:1;s:55:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs/img";b:1;s:51:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools/docs";b:1;s:46:"/opt/alt/php54/usr/share/doc/pear/ConsoleTools";b:1;s:42:"/opt/alt/php54/usr/share/pear/ezc/autoload";b:1;s:33:"/opt/alt/php54/usr/share/pear/ezc";b:1;s:64:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog/validators";b:1;s:53:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/dialog";b:1;s:46:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools";b:1;s:57:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/exceptions";b:1;s:68:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/input/help_generators";b:1;s:52:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/input";b:1;s:63:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/input/validators";b:1;s:57:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/interfaces";b:1;s:54:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/options";b:1;s:54:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/structs";b:1;s:52:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/table";b:1;s:52:"/opt/alt/php54/usr/share/pear/ezc/ConsoleTools/tools";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.6.1";s:12:"release_date";s:10:"2010-03-22";s:13:"release_state";s:6:"stable";s:15:"release_license";s:7:"New BSD";s:13:"release_notes";s:86:"- Fixed issue #16055: Corrected regression in error message for option dependencies.";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.2.1";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.2";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:16:"components.ez.no";s:4:"name";s:4:"Base";s:3:"rel";s:2:"ge";s:7:"version";s:3:"1.8";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:10:"eZ systems";s:5:"email";s:9:"ezc@ez.no";s:6:"active";s:3:"yes";s:6:"handle";s:3:"ezc";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506489;}PK!4p4p,.registry/.channel.components.ez.no/base.regnu[a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.9.0";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:4:"Base";s:7:"channel";s:16:"components.ez.no";s:7:"summary";s:77:"The Base package provides the basic infrastructure that all packages rely on.";s:11:"description";s:127:"The Base package provides the basic infrastructure that all packages rely on. Therefore every component relies on this package.";s:4:"lead";a:4:{s:4:"name";s:10:"eZ systems";s:4:"user";s:3:"ezc";s:5:"email";s:9:"ezc@ez.no";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2009-12-21";s:4:"time";s:8:"12:14:24";s:7:"version";a:2:{s:7:"release";s:3:"1.8";s:3:"api";s:3:"1.8";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";s:7:"New BSD";s:5:"notes";s:73:"- Fixed issue #15896: Autoload not working for all lowercase class names.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:1:"/";}s:4:"file";a:53:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"ab5f9f34361961cc74b309325509e87f";s:4:"name";s:24:"design/class_diagram.png";s:4:"role";s:4:"data";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"64dbc0df23c0142f806e3837a4557c07";s:4:"name";s:17:"design/design.txt";s:4:"role";s:4:"data";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"524b92ec3bf9055dd50e0a527b2f4b9c";s:4:"name";s:36:"docs/repos/autoloads/my_autoload.php";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bd6af5ed742435bd1cdc7f2f4f5b998a";s:4:"name";s:38:"docs/repos/autoloads/your_autoload.php";s:4:"role";s:3:"doc";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1300956dd09bc8fc6346eca3ad5d07d9";s:4:"name";s:26:"docs/repos/Me/myclass1.php";s:4:"role";s:3:"doc";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9f53d279b27b65a325be9274d49f6f74";s:4:"name";s:26:"docs/repos/Me/myclass2.php";s:4:"role";s:3:"doc";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8a4863c1e5bc1b10e25fe78b028acd2f";s:4:"name";s:29:"docs/repos/You/yourclass1.php";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2ff7777b81e887c50b09e23bbaa9c152";s:4:"name";s:29:"docs/repos/You/yourclass2.php";s:4:"role";s:3:"doc";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6a44661d8d0ed5dea17e26938c1c388c";s:4:"name";s:12:"docs/CREDITS";s:4:"role";s:3:"doc";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0d01eec9cb573a51f7cb73a1573c5350";s:4:"name";s:12:"docs/LICENSE";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"15e07d15fb1865740da5a5255da0b330";s:4:"name";s:17:"docs/tutorial.txt";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c62acdb41db6b2f5f90506fda0ffe426";s:4:"name";s:26:"docs/tutorial_autoload.php";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7a4a698465b2dbcf948d5a9abdf16ab6";s:4:"name";s:28:"docs/tutorial_example_01.php";s:4:"role";s:3:"doc";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1493849915073e203c09c0615ad1dc22";s:4:"name";s:28:"docs/tutorial_example_02.php";s:4:"role";s:3:"doc";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"09ddc9170be2be2f9a197823f4fb05b3";s:4:"name";s:28:"docs/tutorial_example_03.php";s:4:"role";s:3:"doc";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c93496ab05d259e2f2867c177a31b9df";s:4:"name";s:28:"docs/tutorial_example_04.php";s:4:"role";s:3:"doc";}}i:16;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f6399aeed38cbc422ba7a95a4cc3e4d1";s:4:"name";s:37:"docs/tutorial_lazy_initialization.php";s:4:"role";s:3:"doc";}}i:17;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bf570452286a6c882531370b75ef4ed5";s:4:"name";s:30:"ezc/autoload/base_autoload.php";s:4:"role";s:3:"php";}}i:18;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4cbf7efc1654c118c1ab4013da584ea2";s:4:"name";s:32:"ezc/Base/exceptions/autoload.php";s:4:"role";s:3:"php";}}i:19;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"26ae1c2a3243187d8b281a33e28ab388";s:4:"name";s:54:"ezc/Base/exceptions/double_class_repository_prefix.php";s:4:"role";s:3:"php";}}i:20;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1b1d2ccf1d83e9f2126ce6d423ad4a06";s:4:"name";s:33:"ezc/Base/exceptions/exception.php";s:4:"role";s:3:"php";}}i:21;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d9b8d14dcddd1453d36025842a915c88";s:4:"name";s:43:"ezc/Base/exceptions/extension_not_found.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"83889a8ded5df760a1184a44e64beb08";s:4:"name";s:38:"ezc/Base/exceptions/file_exception.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2a2d0e89497bd188477d43f5a87701d8";s:4:"name";s:31:"ezc/Base/exceptions/file_io.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"cee70f6094d8e6a1da052f3b2e9913ab";s:4:"name";s:38:"ezc/Base/exceptions/file_not_found.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"249cdcf29b1fc357587301d1a8f8a25f";s:4:"name";s:39:"ezc/Base/exceptions/file_permission.php";s:4:"role";s:3:"php";}}i:26;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f914328c784c38af9dcb71d6fdbbac42";s:4:"name";s:51:"ezc/Base/exceptions/functionality_not_supported.php";s:4:"role";s:3:"php";}}i:27;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9ae4f81ab15f52153132439840096a47";s:4:"name";s:48:"ezc/Base/exceptions/init_callback_configured.php";s:4:"role";s:3:"php";}}i:28;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f4f5f5d9599ea1cdde2929e4dbbcbdbe";s:4:"name";s:46:"ezc/Base/exceptions/invalid_callback_class.php";s:4:"role";s:3:"php";}}i:29;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"416b95f88e0480547b51340afef5d647";s:4:"name";s:44:"ezc/Base/exceptions/invalid_parent_class.php";s:4:"role";s:3:"php";}}i:30;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e6147c51e29536df0683a49aeab920e8";s:4:"name";s:42:"ezc/Base/exceptions/property_not_found.php";s:4:"role";s:3:"php";}}i:31;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"58e2f2dc39f347b59a1afc957a8cdfcd";s:4:"name";s:43:"ezc/Base/exceptions/property_permission.php";s:4:"role";s:3:"php";}}i:32;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8b95e40352468ff28126fc02abc8a9b6";s:4:"name";s:41:"ezc/Base/exceptions/setting_not_found.php";s:4:"role";s:3:"php";}}i:33;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a9dd91058d170afb1728619c7b848504";s:4:"name";s:37:"ezc/Base/exceptions/setting_value.php";s:4:"role";s:3:"php";}}i:34;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"ba9fd1b76372a61fdf21788fb57652e3";s:4:"name";s:29:"ezc/Base/exceptions/value.php";s:4:"role";s:3:"php";}}i:35;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"990f3ff806a9b5e7b11d172d8dd98462";s:4:"name";s:32:"ezc/Base/exceptions/whatever.php";s:4:"role";s:3:"php";}}i:36;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dc2ea8522a7c06d5b3569a43ff536e7e";s:4:"name";s:49:"ezc/Base/interfaces/configuration_initializer.php";s:4:"role";s:3:"php";}}i:37;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9f7c4a9cb5cf5c9647f7a827ebe9e435";s:4:"name";s:34:"ezc/Base/interfaces/exportable.php";s:4:"role";s:3:"php";}}i:38;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"916e40d5c700ab2888c01e4ebf587dcc";s:4:"name";s:35:"ezc/Base/interfaces/persistable.php";s:4:"role";s:3:"php";}}i:39;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"71fc5b479b6d8aa27103a16a29a715ea";s:4:"name";s:26:"ezc/Base/metadata/pear.php";s:4:"role";s:3:"php";}}i:40;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"988bce2474a73cf18bad85a2fb9112cf";s:4:"name";s:29:"ezc/Base/metadata/tarball.php";s:4:"role";s:3:"php";}}i:41;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"cb22067aa3adbf0152698040c6194ff8";s:4:"name";s:29:"ezc/Base/options/autoload.php";s:4:"role";s:3:"php";}}i:42;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"23efc7803de088935e856b72e0ee8bea";s:4:"name";s:38:"ezc/Base/structs/file_find_context.php";s:4:"role";s:3:"php";}}i:43;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6dd22392400103056ced0bac2769197c";s:4:"name";s:41:"ezc/Base/structs/repository_directory.php";s:4:"role";s:3:"php";}}i:44;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3c4ce22ba182187085b754f643ee00bd";s:4:"name";s:17:"ezc/Base/base.php";s:4:"role";s:3:"php";}}i:45;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bf570452286a6c882531370b75ef4ed5";s:4:"name";s:26:"ezc/Base/base_autoload.php";s:4:"role";s:3:"php";}}i:46;a:1:{s:7:"attribs";a:3:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:26:"ezc/Base/ezc_bootstrap.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6fd930e0989b4f0ab940d7bfd6f41c90";s:4:"name";s:21:"ezc/Base/features.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dbe0d8855229df798919b9b1d3f84373";s:4:"name";s:17:"ezc/Base/file.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0ccaeea1d41417f464914cebb064b7d7";s:4:"name";s:17:"ezc/Base/init.php";s:4:"role";s:3:"php";}}i:50;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a6c718b782e8c23497183a11ab1e8954";s:4:"name";s:21:"ezc/Base/metadata.php";s:4:"role";s:3:"php";}}i:51;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"89b149eb5eddf69c1424fd9883d51382";s:4:"name";s:20:"ezc/Base/options.php";s:4:"role";s:3:"php";}}i:52;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d817afdeef8ee0d02e1cebddfc8915e5";s:4:"name";s:19:"ezc/Base/struct.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"5.2.1";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.2";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.8";s:3:"api";s:3:"1.8";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-12-21";s:7:"license";s:7:"New BSD";s:5:"notes";s:73:"- Fixed issue #15896: Autoload not working for all lowercase class names.";}}s:8:"filelist";a:53:{s:24:"design/class_diagram.png";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"ab5f9f34361961cc74b309325509e87f";s:4:"name";s:24:"design/class_diagram.png";s:4:"role";s:4:"data";s:12:"installed_as";s:64:"/opt/alt/php54/usr/share/pear/data/Base/design/class_diagram.png";}s:17:"design/design.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"64dbc0df23c0142f806e3837a4557c07";s:4:"name";s:17:"design/design.txt";s:4:"role";s:4:"data";s:12:"installed_as";s:57:"/opt/alt/php54/usr/share/pear/data/Base/design/design.txt";}s:36:"docs/repos/autoloads/my_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"524b92ec3bf9055dd50e0a527b2f4b9c";s:4:"name";s:36:"docs/repos/autoloads/my_autoload.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:75:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos/autoloads/my_autoload.php";}s:38:"docs/repos/autoloads/your_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bd6af5ed742435bd1cdc7f2f4f5b998a";s:4:"name";s:38:"docs/repos/autoloads/your_autoload.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:77:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos/autoloads/your_autoload.php";}s:26:"docs/repos/Me/myclass1.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1300956dd09bc8fc6346eca3ad5d07d9";s:4:"name";s:26:"docs/repos/Me/myclass1.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos/Me/myclass1.php";}s:26:"docs/repos/Me/myclass2.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9f53d279b27b65a325be9274d49f6f74";s:4:"name";s:26:"docs/repos/Me/myclass2.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos/Me/myclass2.php";}s:29:"docs/repos/You/yourclass1.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8a4863c1e5bc1b10e25fe78b028acd2f";s:4:"name";s:29:"docs/repos/You/yourclass1.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos/You/yourclass1.php";}s:29:"docs/repos/You/yourclass2.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2ff7777b81e887c50b09e23bbaa9c152";s:4:"name";s:29:"docs/repos/You/yourclass2.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos/You/yourclass2.php";}s:12:"docs/CREDITS";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6a44661d8d0ed5dea17e26938c1c388c";s:4:"name";s:12:"docs/CREDITS";s:4:"role";s:3:"doc";s:12:"installed_as";s:51:"/opt/alt/php54/usr/share/doc/pear/Base/docs/CREDITS";}s:12:"docs/LICENSE";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0d01eec9cb573a51f7cb73a1573c5350";s:4:"name";s:12:"docs/LICENSE";s:4:"role";s:3:"doc";s:12:"installed_as";s:51:"/opt/alt/php54/usr/share/doc/pear/Base/docs/LICENSE";}s:17:"docs/tutorial.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"15e07d15fb1865740da5a5255da0b330";s:4:"name";s:17:"docs/tutorial.txt";s:4:"role";s:3:"doc";s:12:"installed_as";s:56:"/opt/alt/php54/usr/share/doc/pear/Base/docs/tutorial.txt";}s:26:"docs/tutorial_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c62acdb41db6b2f5f90506fda0ffe426";s:4:"name";s:26:"docs/tutorial_autoload.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/doc/pear/Base/docs/tutorial_autoload.php";}s:28:"docs/tutorial_example_01.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"7a4a698465b2dbcf948d5a9abdf16ab6";s:4:"name";s:28:"docs/tutorial_example_01.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/doc/pear/Base/docs/tutorial_example_01.php";}s:28:"docs/tutorial_example_02.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1493849915073e203c09c0615ad1dc22";s:4:"name";s:28:"docs/tutorial_example_02.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/doc/pear/Base/docs/tutorial_example_02.php";}s:28:"docs/tutorial_example_03.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"09ddc9170be2be2f9a197823f4fb05b3";s:4:"name";s:28:"docs/tutorial_example_03.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/doc/pear/Base/docs/tutorial_example_03.php";}s:28:"docs/tutorial_example_04.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c93496ab05d259e2f2867c177a31b9df";s:4:"name";s:28:"docs/tutorial_example_04.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/doc/pear/Base/docs/tutorial_example_04.php";}s:37:"docs/tutorial_lazy_initialization.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f6399aeed38cbc422ba7a95a4cc3e4d1";s:4:"name";s:37:"docs/tutorial_lazy_initialization.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/doc/pear/Base/docs/tutorial_lazy_initialization.php";}s:30:"ezc/autoload/base_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bf570452286a6c882531370b75ef4ed5";s:4:"name";s:30:"ezc/autoload/base_autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/opt/alt/php54/usr/share/pear/ezc/autoload/base_autoload.php";}s:32:"ezc/Base/exceptions/autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"4cbf7efc1654c118c1ab4013da584ea2";s:4:"name";s:32:"ezc/Base/exceptions/autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/autoload.php";}s:54:"ezc/Base/exceptions/double_class_repository_prefix.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"26ae1c2a3243187d8b281a33e28ab388";s:4:"name";s:54:"ezc/Base/exceptions/double_class_repository_prefix.php";s:4:"role";s:3:"php";s:12:"installed_as";s:84:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/double_class_repository_prefix.php";}s:33:"ezc/Base/exceptions/exception.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"1b1d2ccf1d83e9f2126ce6d423ad4a06";s:4:"name";s:33:"ezc/Base/exceptions/exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/exception.php";}s:43:"ezc/Base/exceptions/extension_not_found.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d9b8d14dcddd1453d36025842a915c88";s:4:"name";s:43:"ezc/Base/exceptions/extension_not_found.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/extension_not_found.php";}s:38:"ezc/Base/exceptions/file_exception.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"83889a8ded5df760a1184a44e64beb08";s:4:"name";s:38:"ezc/Base/exceptions/file_exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/file_exception.php";}s:31:"ezc/Base/exceptions/file_io.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"2a2d0e89497bd188477d43f5a87701d8";s:4:"name";s:31:"ezc/Base/exceptions/file_io.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/file_io.php";}s:38:"ezc/Base/exceptions/file_not_found.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"cee70f6094d8e6a1da052f3b2e9913ab";s:4:"name";s:38:"ezc/Base/exceptions/file_not_found.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/file_not_found.php";}s:39:"ezc/Base/exceptions/file_permission.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"249cdcf29b1fc357587301d1a8f8a25f";s:4:"name";s:39:"ezc/Base/exceptions/file_permission.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/file_permission.php";}s:51:"ezc/Base/exceptions/functionality_not_supported.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f914328c784c38af9dcb71d6fdbbac42";s:4:"name";s:51:"ezc/Base/exceptions/functionality_not_supported.php";s:4:"role";s:3:"php";s:12:"installed_as";s:81:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/functionality_not_supported.php";}s:48:"ezc/Base/exceptions/init_callback_configured.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9ae4f81ab15f52153132439840096a47";s:4:"name";s:48:"ezc/Base/exceptions/init_callback_configured.php";s:4:"role";s:3:"php";s:12:"installed_as";s:78:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/init_callback_configured.php";}s:46:"ezc/Base/exceptions/invalid_callback_class.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f4f5f5d9599ea1cdde2929e4dbbcbdbe";s:4:"name";s:46:"ezc/Base/exceptions/invalid_callback_class.php";s:4:"role";s:3:"php";s:12:"installed_as";s:76:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/invalid_callback_class.php";}s:44:"ezc/Base/exceptions/invalid_parent_class.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"416b95f88e0480547b51340afef5d647";s:4:"name";s:44:"ezc/Base/exceptions/invalid_parent_class.php";s:4:"role";s:3:"php";s:12:"installed_as";s:74:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/invalid_parent_class.php";}s:42:"ezc/Base/exceptions/property_not_found.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"e6147c51e29536df0683a49aeab920e8";s:4:"name";s:42:"ezc/Base/exceptions/property_not_found.php";s:4:"role";s:3:"php";s:12:"installed_as";s:72:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/property_not_found.php";}s:43:"ezc/Base/exceptions/property_permission.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"58e2f2dc39f347b59a1afc957a8cdfcd";s:4:"name";s:43:"ezc/Base/exceptions/property_permission.php";s:4:"role";s:3:"php";s:12:"installed_as";s:73:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/property_permission.php";}s:41:"ezc/Base/exceptions/setting_not_found.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"8b95e40352468ff28126fc02abc8a9b6";s:4:"name";s:41:"ezc/Base/exceptions/setting_not_found.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/setting_not_found.php";}s:37:"ezc/Base/exceptions/setting_value.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a9dd91058d170afb1728619c7b848504";s:4:"name";s:37:"ezc/Base/exceptions/setting_value.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/setting_value.php";}s:29:"ezc/Base/exceptions/value.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"ba9fd1b76372a61fdf21788fb57652e3";s:4:"name";s:29:"ezc/Base/exceptions/value.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/value.php";}s:32:"ezc/Base/exceptions/whatever.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"990f3ff806a9b5e7b11d172d8dd98462";s:4:"name";s:32:"ezc/Base/exceptions/whatever.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions/whatever.php";}s:49:"ezc/Base/interfaces/configuration_initializer.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dc2ea8522a7c06d5b3569a43ff536e7e";s:4:"name";s:49:"ezc/Base/interfaces/configuration_initializer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/opt/alt/php54/usr/share/pear/ezc/Base/interfaces/configuration_initializer.php";}s:34:"ezc/Base/interfaces/exportable.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"9f7c4a9cb5cf5c9647f7a827ebe9e435";s:4:"name";s:34:"ezc/Base/interfaces/exportable.php";s:4:"role";s:3:"php";s:12:"installed_as";s:64:"/opt/alt/php54/usr/share/pear/ezc/Base/interfaces/exportable.php";}s:35:"ezc/Base/interfaces/persistable.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"916e40d5c700ab2888c01e4ebf587dcc";s:4:"name";s:35:"ezc/Base/interfaces/persistable.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/opt/alt/php54/usr/share/pear/ezc/Base/interfaces/persistable.php";}s:26:"ezc/Base/metadata/pear.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"71fc5b479b6d8aa27103a16a29a715ea";s:4:"name";s:26:"ezc/Base/metadata/pear.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/opt/alt/php54/usr/share/pear/ezc/Base/metadata/pear.php";}s:29:"ezc/Base/metadata/tarball.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"988bce2474a73cf18bad85a2fb9112cf";s:4:"name";s:29:"ezc/Base/metadata/tarball.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/opt/alt/php54/usr/share/pear/ezc/Base/metadata/tarball.php";}s:29:"ezc/Base/options/autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"cb22067aa3adbf0152698040c6194ff8";s:4:"name";s:29:"ezc/Base/options/autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/opt/alt/php54/usr/share/pear/ezc/Base/options/autoload.php";}s:38:"ezc/Base/structs/file_find_context.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"23efc7803de088935e856b72e0ee8bea";s:4:"name";s:38:"ezc/Base/structs/file_find_context.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/opt/alt/php54/usr/share/pear/ezc/Base/structs/file_find_context.php";}s:41:"ezc/Base/structs/repository_directory.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6dd22392400103056ced0bac2769197c";s:4:"name";s:41:"ezc/Base/structs/repository_directory.php";s:4:"role";s:3:"php";s:12:"installed_as";s:71:"/opt/alt/php54/usr/share/pear/ezc/Base/structs/repository_directory.php";}s:17:"ezc/Base/base.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"3c4ce22ba182187085b754f643ee00bd";s:4:"name";s:17:"ezc/Base/base.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php54/usr/share/pear/ezc/Base/base.php";}s:26:"ezc/Base/base_autoload.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bf570452286a6c882531370b75ef4ed5";s:4:"name";s:26:"ezc/Base/base_autoload.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/opt/alt/php54/usr/share/pear/ezc/Base/base_autoload.php";}s:26:"ezc/Base/ezc_bootstrap.php";a:4:{s:14:"baseinstalldir";s:1:"/";s:4:"name";s:26:"ezc/Base/ezc_bootstrap.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/opt/alt/php54/usr/share/pear/ezc/Base/ezc_bootstrap.php";}s:21:"ezc/Base/features.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6fd930e0989b4f0ab940d7bfd6f41c90";s:4:"name";s:21:"ezc/Base/features.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php54/usr/share/pear/ezc/Base/features.php";}s:17:"ezc/Base/file.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"dbe0d8855229df798919b9b1d3f84373";s:4:"name";s:17:"ezc/Base/file.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php54/usr/share/pear/ezc/Base/file.php";}s:17:"ezc/Base/init.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"0ccaeea1d41417f464914cebb064b7d7";s:4:"name";s:17:"ezc/Base/init.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/opt/alt/php54/usr/share/pear/ezc/Base/init.php";}s:21:"ezc/Base/metadata.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a6c718b782e8c23497183a11ab1e8954";s:4:"name";s:21:"ezc/Base/metadata.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/opt/alt/php54/usr/share/pear/ezc/Base/metadata.php";}s:20:"ezc/Base/options.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"89b149eb5eddf69c1424fd9883d51382";s:4:"name";s:20:"ezc/Base/options.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/opt/alt/php54/usr/share/pear/ezc/Base/options.php";}s:19:"ezc/Base/struct.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d817afdeef8ee0d02e1cebddfc8915e5";s:4:"name";s:19:"ezc/Base/struct.php";s:4:"role";s:3:"php";s:12:"installed_as";s:49:"/opt/alt/php54/usr/share/pear/ezc/Base/struct.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:16:{s:46:"/opt/alt/php54/usr/share/pear/data/Base/design";b:1;s:39:"/opt/alt/php54/usr/share/pear/data/Base";b:1;s:59:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos/autoloads";b:1;s:49:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos";b:1;s:43:"/opt/alt/php54/usr/share/doc/pear/Base/docs";b:1;s:38:"/opt/alt/php54/usr/share/doc/pear/Base";b:1;s:52:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos/Me";b:1;s:53:"/opt/alt/php54/usr/share/doc/pear/Base/docs/repos/You";b:1;s:42:"/opt/alt/php54/usr/share/pear/ezc/autoload";b:1;s:33:"/opt/alt/php54/usr/share/pear/ezc";b:1;s:49:"/opt/alt/php54/usr/share/pear/ezc/Base/exceptions";b:1;s:38:"/opt/alt/php54/usr/share/pear/ezc/Base";b:1;s:49:"/opt/alt/php54/usr/share/pear/ezc/Base/interfaces";b:1;s:47:"/opt/alt/php54/usr/share/pear/ezc/Base/metadata";b:1;s:46:"/opt/alt/php54/usr/share/pear/ezc/Base/options";b:1;s:46:"/opt/alt/php54/usr/share/pear/ezc/Base/structs";b:1;}s:3:"old";a:7:{s:7:"version";s:3:"1.8";s:12:"release_date";s:10:"2009-12-21";s:13:"release_state";s:6:"stable";s:15:"release_license";s:7:"New BSD";s:13:"release_notes";s:73:"- Fixed issue #15896: Autoload not working for all lowercase class names.";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"5.2.1";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.2";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:10:"eZ systems";s:5:"email";s:9:"ezc@ez.no";s:6:"active";s:3:"yes";s:6:"handle";s:3:"ezc";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1709506489;}PK!gRStructures_LinkedList/CHANGELOGnu[0.2.1 * Apply patch from Bertrand Zuchuat to avoid inheritance strictness alerts 0.2.0 * Adhere to CS (thanks PHP_CodeSniffer!) * Fix docblocks for Double vs. Single confusion * One change to API in that the protected method _getTailNode() has been renamed to getTailNode() per CS 0.0.8 * Add destructors to avoid holding onto way too much memory 0.0.7 * Correct examples * Convert to PEAR_Exception for error handling 0.0.6 0.0.5 * Create a singly linked list (Structures_LinkedList_Single) * Refactor Structures_LinkedList_Double to extend _Single 0.0.4 * Move most globals into class constants 0.0.3 * Separate addNode method into insertNode, appendNode, prependNode * Prevent current node from becoming invalid when adding a new node * Type hinting and avoiding moving current pointer with addNode() 0.0.2 * Implement basic error-handling using PEAR_ErrorStack * Adjust "link" terminology and API to "node" 0.0.1 * First attempt at a separate package for Structures_Linked_List PK! 6Structures_LinkedList/examples/single_link_example.phpnu[_my_number = $num; $this->_my_letter = $letter; } function getNumber() { return $this->_my_number; } function getLetter() { return $this->_my_letter; } function setNumb($numb) { $this->_my_number = $numb; } function __toString() { return "{$this->getNumber()}"; } } /* To enable key=>value iteration, we must override the default key() * method in Structures_LinkedList_Single to return a meaningful value */ class LinkListTester extends Structures_LinkedList_Single { function key() { return $this->current()->getLetter(); } } /* Now we'll create some instances of the new class */ $node1 = new LinkNodeTester(1, 'a'); $node2 = new LinkNodeTester(2, 'b'); $node3 = new LinkNodeTester(3, 'c'); $node4 = new LinkNodeTester(4, 'd'); $node5 = new LinkNodeTester(5, 'e'); /* Start by instantiating a list object. * You can either pass the first node to the constructor, * or leave it null and add nodes later. */ $list = new LinkListTester($node1); // 1 /* appendNode() adds a node to the end of the list */ $list->appendNode($node2); // 1-2 /* prependNode() adds a node to the start of the list */ $list->prependNode($node3); // 3-1-2 /* insertNode($new_node, $reference_node, $before) adds a node * before the reference node if the third parameter is true, * or after the reference node if the third parameter is false */ $list->insertNode($node4, $node2, true); // 3-1-4-2 /* current() returns the current pointer node in the list */ $link = $list->current(); // 1 /* You can iterate through a list with the next() method */ do { print $link->getNumber(); } while ($link = $list->next()); // 1-4-2 /* rewind() resets the pointer to the root node of the list */ $link = $list->rewind(); // 3 /* You can also iterate through a list with foreach() */ foreach ($list as $bull) { print $bull->getNumber(); } // 3-1-4-2 /* Override the key() method to enable $key=>$value iteration */ foreach ($list as $key=>$value) { print "$key => $value\n"; } /* end() resets the pointer to the last node of the list */ $link = $list->end(); // 2 /* You can iterate backwards through a list with previous() */ do { print $link->getNumber(); } while ($link = $list->previous()); // 2-4-1-3 ?> PK!p| | 6Structures_LinkedList/examples/double_link_example.phpnu[_my_number = $number; $this->_my_letter = $letter; } function getNumber() { return $this->_my_number; } function getLetter() { return $this->_my_letter; } function setNumb($number) { $this->_my_number = $number; } function __toString() { return "{$this->getNumber()}"; } } /* To enable key=>value iteration, we must override the default key() * method in Structures_LinkedList_Double to return a meaningful value */ class LinkListTester extends Structures_LinkedList_Double { function key() { return $this->current()->getLetter(); } } /* Now we'll create some instances of the new class */ $node1 = new LinkNodeTester(1, 'a'); $node2 = new LinkNodeTester(2, 'b'); $node3 = new LinkNodeTester(3, 'c'); $node4 = new LinkNodeTester(4, 'd'); $node5 = new LinkNodeTester(5, 'e'); /* Start by instantiating a list object. * You can either pass the first node to the constructor, * or leave it null and add nodes later. */ $list = new LinkListTester($node1); // 1 /* appendNode() adds a node to the end of the list */ $list->appendNode($node2); // 1-2 /* prependNode() adds a node to the start of the list */ $list->prependNode($node3); // 3-1-2 /* insertNode($new_node, $reference_node, $before) adds a node * before the reference node if the third parameter is true, * or after the reference node if the third parameter is false */ $list->insertNode($node4, $node1); // 3-1-4-2 $list->insertNode($node5, $node1, true); // 3-5-1-4-2 /* current() returns the current pointer node in the list */ $link = $list->current(); print $link->getNumber(); // "1" /* rewind() resets the pointer to the root node of the list */ $link = $list->rewind(); print $link->getNumber(); // "3" // iterate through the list with do...while() do { print $link->getNumber(); } while ($link = $list->next()); // "35142" /* You can also iterate through a list with foreach() */ foreach ($list as $bull) { print $bull->getNumber(); } // 3-1-4-2 /* Override the key() method to enable $key=>$value iteration */ foreach ($list as $key=>$value) { print "$key => $value\n"; } /* end() resets the pointer to the last node of the list */ $link = $list->end(); print $link->getNumber(); // "2" /* You can iterate backwards through a list with previous() */ do { print $link->getNumber(); } while ($link = $list->previous()); // "24153" ?> PK!^,^,Structures_LinkedList/LICENSEnu[ 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. PK! Mail/LICENSEnu[Copyright (c) 1997-2017, Chuck Hagenbuch All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PK!y˿Net_Socket/README.mdnu[# Net_Socket - Network Socket Interface [![Build Status](https://travis-ci.org/pear/Net_Socket.svg?branch=master)](https://travis-ci.org/pear/Net_Socket) Net_Socket is a class interface to TCP sockets. It provides blocking and non-blocking operation, with different reading and writing modes (byte-wise, block-wise, line-wise and special formats like network byte-order ip addresses). [Homepage](http://pear.php.net/package/Net_Socket/) ## Installation For a PEAR installation that downloads from the PEAR channel: `$ pear install pear/net_socket` For a PEAR installation from a previously downloaded tarball: `$ pear install Net_Socket-*.tgz` For a PEAR installation from a code clone: `$ pear install package.xml` For a local composer installation: `$ composer install` To add as a dependency to your composer-managed application: `$composer require pear/net_socket` ## Tests Run the tests from a local composer installation: `$ ./vendor/bin/phpunit` ## License BSD-2 license PK!W]HNet_Socket/LICENSEnu[Copyright 1997-2017 The PHP Group Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PK!TkUNet_SMTP/examples/basic.phpnu[connect())) { die($e->getMessage() . "\n"); } $smtp->auth('username','password'); /* Send the 'MAIL FROM:' SMTP command. */ if (PEAR::isError($smtp->mailFrom($from))) { die("Unable to set sender to <$from>\n"); } /* Address the message to each of the recipients. */ foreach ($rcpt as $to) { if (PEAR::isError($res = $smtp->rcptTo($to))) { die("Unable to add recipient <$to>: " . $res->getMessage() . "\n"); } } /* Set the body of the message. */ if (PEAR::isError($smtp->data($subj . "\r\n" . $body))) { die("Unable to send data\n"); } /* Disconnect from the SMTP server. */ $smtp->disconnect(); PK!SOܪ%%Net_SMTP/README.rstnu[====================== The Net_SMTP Package ====================== -------------------- User Documentation -------------------- :Author: Jon Parise :Contact: jon@php.net .. contents:: Table of Contents .. section-numbering:: Dependencies ============ The ``PEAR_Error`` Class ------------------------ The Net_SMTP package uses the `PEAR_Error`_ class for all of its `error handling`_. The ``Net_Socket`` Package -------------------------- The Net_Socket_ package is used as the basis for all network communications. Connection options can be specified via the `$socket_options` construction parameter:: $socket_options = array('ssl' => array('verify_peer_name' => false)); $smtp = new Net_SMTP($host, null, null, false, 0, $socket_options); **Note:** PHP 5.6 introduced `OpenSSL changes`_. Peer certificate verification is now enabled by default. Although not recommended, `$socket_options` can be used to disable peer verification (as shown above). .. _OpenSSL changes: https://php.net/manual/en/migration56.openssl.php The ``Auth_SASL`` Package ------------------------- The `Auth_SASL`_ package is an optional dependency. If it is available, the Net_SMTP package will be able to support the DIGEST-MD5_ and CRAM-MD5_ SMTP authentication methods. Otherwise, only the LOGIN_ and PLAIN_ methods will be available. Error Handling ============== All of the Net_SMTP class's public methods return a PEAR_Error_ object if an error occurs. The standard way to check for a PEAR_Error object is by using `PEAR::isError()`_:: if (PEAR::isError($error = $smtp->connect())) { die($error->getMessage()); } .. _PEAR::isError(): https://pear.php.net/manual/en/core.pear.pear.iserror.php SMTP Authentication =================== The Net_SMTP package supports the SMTP authentication standard (as defined by RFC-2554_). The Net_SMTP package supports the following authentication methods, in order of preference: .. _RFC-2554: https://www.ietf.org/rfc/rfc2554.txt GSSAPI ------ The GSSAPI authentication method uses Kerberos 5 protocol (RFC-4120_). Does not use user/password. Requires Service Principal ``gssapi_principal`` parameter and has an optional Credentials Cache ``gssapi_cname`` parameter. Requires DNS and Key Distribution Center (KDC) setup. It is considered the most secure method of SMTP authentication. **Note:** The GSSAPI authentication method is only supported if the krb5_ php extension is available. .. _RFC-4120: https://tools.ietf.org/html/rfc4120 .. _krb5: https://pecl.php.net/package/krb5 DIGEST-MD5 ---------- The DIGEST-MD5 authentication method uses `RSA Data Security Inc.`_'s MD5 Message Digest algorithm. It is considered a more secure method of SMTP authentication than PLAIN or LOGIN, while still vulnerable to MitM attacks without TLS/SSL. **Note:** The DIGEST-MD5 authentication method is only supported if the AUTH_SASL_ package is available. .. _RSA Data Security Inc.: https://www.rsasecurity.com/ CRAM-MD5 -------- The CRAM-MD5 authentication method has been superseded by the DIGEST-MD5_ method in terms of security. It is provided here for compatibility with older SMTP servers that may not support the newer DIGEST-MD5 algorithm. **Note:** The CRAM-MD5 authentication method is only supported if the AUTH_SASL_ package is available. LOGIN ----- The LOGIN authentication method encrypts the user's password using the Base64_ encoding scheme. Because decrypting a Base64-encoded string is trivial, LOGIN is not considered a secure authentication method and should be avoided. .. _Base64: https://www.php.net/manual/en/function.base64-encode.php PLAIN ----- The PLAIN authentication method sends the user's password in plain text. This method of authentication is not secure and should be avoided. XOAUTH2 ------- The XOAUTH2 authentication method sends a username and an OAuth2 access token as per `Gmail's SASL XOAUTH2 documentation`__. .. __: https://developers.google.com/gmail/imap/xoauth2-protocol#smtp_protocol_exchange Secure Connections ================== If `secure socket transports`_ have been enabled in PHP, it is possible to establish a secure connection to the remote SMTP server:: $smtp = new Net_SMTP('ssl://mail.example.com', 465); This example connects to ``mail.example.com`` on port 465 (a common SMTPS port) using the ``ssl://`` transport. TLS/SSL is enabled for authenticated connections by default (via the ``auth()`` method's ``$tls`` parameter), but the |STARTTLS|_ command can also be sent manually using the ``starttls()`` method. .. _secure socket transports: https://www.php.net/transports .. |STARTTLS| replace:: ``STARTTLS`` .. _STARTTLS: https://tools.ietf.org/html/rfc3207 Sending Data ============ Message data is sent using the ``data()`` method. The data can be supplied as a single string or as an open file resource. If a string is provided, it is passed through the `data quoting`_ system and sent to the socket connection as a single block. These operations are all memory-based, so sending large messages may result in high memory usage. If an open file resource is provided, the ``data()`` method will read the message data from the file line-by-line. Each chunk will be quoted and sent to the socket connection individually, reducing the overall memory overhead of this data sending operation. Header data can be specified separately from message body data by passing it as the optional second parameter to ``data()``. This is especially useful when an open file resource is being used to supply message data because it allows header fields (like *Subject:*) to be built dynamically at runtime. :: $smtp->data($fp, "Subject: My Subject"); Data Quoting ============ By default, all outbound string data is quoted in accordance with SMTP standards. This means that all native Unix (``\n``) and Mac (``\r``) line endings are converted to Internet-standard CRLF (``\r\n``) line endings. Also, because the SMTP protocol uses a single leading period (``.``) to signal an end to the message data, single leading periods in the original data string are "doubled" (e.g. "``..``"). These string transformation can be expensive when large blocks of data are involved. For example, the Net_SMTP package is not aware of MIME parts (it just sees the MIME message as one big string of characters), so it is not able to skip non-text attachments when searching for characters that may need to be quoted. Because of this, it is possible to extend the Net_SMTP class in order to implement your own custom quoting routine. Just create a new class based on the Net_SMTP class and reimplement the ``quotedata()`` method:: require 'Net_SMTP.php'; class Net_SMTP_custom extends Net_SMTP { function quotedata($data) { /* Perform custom data quoting */ } } Note that the ``$data`` parameter will be passed to the ``quotedata()`` function `by reference`_. This means that you can operate directly on ``$data``. It also the overhead of copying a large ``$data`` string to and from the ``quotedata()`` method. .. _by reference: https://www.php.net/manual/en/language.references.pass.php Server Responses ================ The Net_SMTP package retains the server's last response for further inspection. The ``getResponse()`` method returns a 2-tuple (two element array) containing the server's response code as an integer and the response's arguments as a string. Upon a successful connection, the server's greeting string is available via the ``getGreeting()`` method. Debugging ========= The Net_SMTP package contains built-in debugging output routines (disabled by default). Debugging output must be explicitly enabled via the ``setDebug()`` method:: $smtp->setDebug(true); The debugging messages will be sent to the standard output stream by default. If you need more control over the output, you can optionally install your own debug handler. :: function debugHandler($smtp, $message) { echo "[$smtp->host] $message\n"; } $smtp->setDebug(true, "debugHandler"); Examples ======== Basic Use --------- The following script demonstrates how a simple email message can be sent using the Net_SMTP package:: require 'Net/SMTP.php'; $host = 'mail.example.com'; $from = 'user@example.com'; $rcpt = array('recipient1@example.com', 'recipient2@example.com'); $subj = "Subject: Test Message\n"; $body = "Body Line 1\nBody Line 2"; /* Create a new Net_SMTP object. */ if (! ($smtp = new Net_SMTP($host))) { die("Unable to instantiate Net_SMTP object\n"); } /* Connect to the SMTP server. */ if (PEAR::isError($e = $smtp->connect())) { die($e->getMessage() . "\n"); } /* Send the 'MAIL FROM:' SMTP command. */ if (PEAR::isError($smtp->mailFrom($from))) { die("Unable to set sender to <$from>\n"); } /* Address the message to each of the recipients. */ foreach ($rcpt as $to) { if (PEAR::isError($res = $smtp->rcptTo($to))) { die("Unable to add recipient <$to>: " . $res->getMessage() . "\n"); } } /* Set the body of the message. */ if (PEAR::isError($smtp->data($subj . "\r\n" . $body))) { die("Unable to send data\n"); } /* Disconnect from the SMTP server. */ $smtp->disconnect(); .. _PEAR_Error: https://pear.php.net/manual/en/core.pear.pear-error.php .. _Net_Socket: https://pear.php.net/package/Net_Socket .. _Auth_SASL: https://pear.php.net/package/Auth_SASL .. vim: tabstop=4 shiftwidth=4 softtabstop=4 expandtab textwidth=78 ft=rst: PK!((Net_SMTP/LICENSEnu[Copyright 2002-2017 Jon Parise and Chuck Hagenbuch. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PK!!!File_MARC/CHANGELOGnu[1.4.1 * Reintroduce include_path to composer.json 1.4.0 * Update File_MARC_Lint to match MARC::Lint 1.52 (thanks Demian Katz) * Warn about out-of-range skip indicators (thanks Demian Katz) * Support initialization from SimpleXMLELement object (thanks Dan Michael O. Heggø) * Fix Travis-CI support (thanks Daniel O'Connor) * Tweak composer.json to support Composer 2.0 * Silence PEAR style errors and warnings in File/MARCBASE.php 1.3.0 * Support reading MARC-in-JSON serializations * Fix positions using MARC_List's appendNode method (thanks Waldemar Bartikowski!) 1.2.0 * Support injection of extended Record class (thanks Dan Michael O. Heggø!) * Support regular expression matching of subfields (thanks Waldemar Bartikowski!) * Fix deletion of multiple subfields at once (thanks Dan Michael O. Heggø!) 1.1.5 * Drop support for PHP 5.3 and 5.4 1.1.4 * Fix insertField() behaviour, which could truncate records (reported by Andreas Roussos) * Docs correction for Data_Field (thanks Daniel Walter) 1.1.3 * Add a getContents() convenience method, contributed by Carsten Klee 1.1.2 * Fetch pear_exception from Packagist [danmichaelo] 1.1.1 * Add MARC-in-JSON serialization fix for subfield 0 json_encode() limitation (thanks to Bill Dueber for reporting the bug) 1.1.0 * Enable namespaces in MARCXML handling (thanks Carsten Klee!) * Remove skip check for Structures/Linked_List 1.0.2 * Update MARC_Lint set of rules (thanks Demian Katz!) 1.0.1 * Fix bug in MARC binary serialization of subfields with value '0'. Thanks to Mark Jordan (mjordan@sfu.ca) for the bug report. 1.0.0 * First stable release! 0.8.0-beta * Drop Structures_LinkedList dependency in favour of SplDoublyLinkedList. This bumps the minimum PHP version up to 5.2.0. 0.7.3-beta * Merge patch from Karen Coombs (librarywebchic@gmail.com) adding default namespace to record elements 0.7.2-beta * Fix bug #19845 - Record::toXML() returns nothing 0.7.1-beta * Make Validate_ISPN an optional dependency 0.6.2-beta * Improve handling of bad leader data, including declared length and overly long leaders in MARCXML 0.6.1-beta * Correct layout per bug #17704 0.6.0-beta * Add two flavours of JSON output from File_MARC_Record: toJSON() and toJSONHash() 0.5.2-beta * Enable File_MARC_Record to be invoked with a null constructor again, useful for building MARC records from scratch * Add a test to check that the null constructor works to avoid future regressions 0.5.1-beta * Explicitly cast results to strings to avoid returning XML objects when File_MARCXML is in effect; problem doesn't show up in the PHP CLI, but does cause problems on the Web 0.5.0-beta * Drop MARCFLAT as it is unmaintained and, to my knowledge, unused * Add the ability to generate a proper collection of MARCXML records * Factor out some of the common toXML()-related methods to a new base class * Add tests of the new toXML() functionality for both MARC and MARCXML sources 0.4.4-beta * Enable MARCXML to handle bad tags, to match MARC * Handle corner case where only one indicator might have been provided 0.4.3-beta * Fix bug #16783 - handle bad MARC tags via warnings instead of bubbling an exception all the way up 0.4.2-beta * Fix bug #16642 - MARCXML files return keys of an invalid type 0.4.1-beta * Fix suggested by Dan Field (surfrdan @ gmail.com) for addWarnings() typo 0.4.0-beta * Add formatField() convenience method to File_MARC_Field (courtesy Mark Matienzo @ matienzo.org) * Move from split() to explode() to avoid PHP 5.3 deprecation warning (courtesy bertrand.zuchuat @ rero.ch 0.3.0-beta * Add isControlField() and isDataField() convenience methods to File_MARC_Field 0.2.3-beta * Handle single-record MARC21XML files with "record" as the root element 0.1.1-alpha * Add File_MARC_Record::toXML() method for generating MARCXML output * Add File_MARCXML class for reading MARCXML source * Add tests for MARCXML methods 0.1.0-alpha * Split each class out into its own file * Do not return anything from constructors 0.0.9-alpha * Separate getFields() from getField(), getSubfields() from getSubfield() to avoid forcing users to test is_array() after every call * Add addWarnings() / getWarnings() for records to avoid throwing an exception for a non-fatal error * Fix examples, touch up phpdoc in preparation for call for votes 0.0.8-alpha * Switch to PEAR_Exception for error handling 0.0.7-alpha * Implement useful key() overrides for key=>value iteration through fields and subfields * Adjust to new Structures_LinkedList_Double names 0.0.6-alpha * Remove package globals, define class constants & static vars instead * Change addField/Subfield() to append..(), prepend...(), and insert...() 0.0.5-alpha * Work towards a more consistent API (delete getAllSubfields) * Make PCRE expressions in getFields() and deleteFields() optional. * Make duplicate() actually return a deep copy of a record. * Stronger, better, faster (now with typehints) * Iterate with foreach() everywhere now 0.0.4-alpha * Adjust to Structures_Linked_List package name change and minor API changes * Adhere to PEAR CS (thanks PHP_CodeSniffer!) * Correct sloppy use of references (thanks E_STRICT!) * Okay, this time real error handling using PEAR_ErrorStack * Prepare first package for PEPR 0.0.3-alpha * Split MARC into separate File_MARC and Structure_Linked_List packages (with corresponding renaming of classes and constants) * Adopt PEAR naming conventions (s/MARC/File_MARC/) * Initial stab at PEAR_ErrorStack error handling 0.0.2-alpha * Fix marc_004.phpt: explicitly compare object references with === operator * Document all constants. * Fix MARC_Field::deleteSubfield() function * Add this ChangeLog 0.0.1-alpha * First publicly available release, based on MARC decoding algorithm from the emilda.org php-marc package with a completely new API and class hierarchy PK!~File_MARC/examples/read.phpnu[next(); // Retrieve a personal name field from the record $names = $marc_record->getFields('100'); foreach ($names as $name_field) { // Now print the $a subfield switch ($name_field->getIndicator(1)) { case 0: print "Forename: "; break; case 1: print "Surname: "; break; case 2: print "Family name: "; break; } $name = $name_field->getSubfields('a'); if (count($name) == 1) { print $name[0]->getData() . "\n"; } else { print "Error -- \$a subfield appears more than once in this field!"; } } print "\nPrint all series statement fields (4xx):\n"; // Retrieve all series statement fields // Series statement fields start with a 4 (PCRE) $subjects = $marc_record->getFields('^4', true); // Iterate through all of the returned series statement fields foreach ($subjects as $field) { // print with File_MARC_Field_Data's magic __toString() method print $field; } print "\n"; ?> PK! File_MARC/examples/subfields.phpnu[appendSubfield($subfield1); // Insert a new subfield after the first subfield with code 'z' // Expected order: a-z-k-g $sf = $field->getSubfields('z'); // getSubfields() always returns an array; we just want the first subfield if (count($sf) > 0) { $field->insertSubfield($subfield2, $sf[0]); } // Insert a new subfield prior to the first subfield with code 'z' // Expected order: a-t-z-k-g $sf = $field->getSubfield('z'); // getSubfield() simply returns the first matching subfield if ($sf) { $field->insertSubfield($subfield3, $sf, true); } // let's see the results print $field; print "\n"; ?> PK!cVFile_MARC/examples/marc_yaz.phpnu[ "1=4", "au" => "1=1", "isbn" => "1=7" ); // Declare the array that will hold the parsed results $ccl_results = array(); // Connect to the laurentian.ca Z39.50 server $conn = yaz_connect('142.51.8.7:2200/UNICORN'); yaz_ccl_conf($conn, $ccl_fields); // Define our query for a most excellent text $ccl_query = "ti='derby' and au='scott'"; // Parse the CCL query into yaz's native format $result = yaz_ccl_parse($conn, $ccl_query, $ccl_results); if (!$result) { echo "Error: " . $ccl_results['errorstring']; exit(); } // Submit the query $rpn = $ccl_results['rpn']; yaz_search($conn, 'rpn', $rpn); yaz_wait(); // Any errors trying to retrieve this record? $error = yaz_error($conn); if ($error) { print "Error: $error\n"; exit(); } // Retrieve the first MARC record as raw MARC $rec = yaz_record($conn, 1, "raw"); if (!$rec) { print "Error: Retrieved no results.\n"; exit(); } // Parse the retrieved MARC record $marc_file = new File_MARC($rec, File_MARC::SOURCE_STRING); while ($marc_record = $marc_file->next()) { print $marc_record; print "\n"; } ?> PK!~N0::File_MARC/examples/example.mrcnu[01850 2200517 45000010011000000030007000110080039000180200026000570350015000830400007000980420012001050840018001170840018001350840021001530840022001741000030001962450062002262500013002882600058003013000033003594400037003925000023004295990010004527400024004627750034004868410048005208410049005688410047006178410048006648410047007128410047007598520038008068520021008448520013008658520016008788520028008948520021009229000056009439000060009999000057010599000056011169000057011729000060012299760026012890050017013150000000044EMILDA980120s1998 fi j 000 0 swe a9515008808cFIM 72:00 99515008808 aNB 9NB9SEE aHcd,u2kssb/6 5NBauHc2kssb 5SEEaHcf2kssb/6 5QaHcd,uf2kssb/61 aJansson, Tove,d1914-200104aDet osynliga barnet och andra berttelser /cTove Jansson a7. uppl. aHelsingfors :bSchildt,c1998 ;e(Falun :fScandbook) a166, [4] s. :bill. ;c21 cm 0aMumin-biblioteket,x99-0698931-9 aOriginaluppl. 1962 aLi: S4 aDet osynliga barnet1 z951-50-0385-7w9515003857907 5Liaxab0201080u 0 4000uu |000000e1 5SEEaxab0201080u 0 4000uu |000000e1 5Laxab0201080u 0 4000uu |000000e1 5NBaxab0201080u 0 4000uu |000000e1 5Qaxab0201080u 0 4000uu |000000e1 5Saxab0201080u 0 4000uu |000000e1 5NBbNBcNB98:12hpliktjR, 980520 5LibLicCNBhh,u 5SEEbSEE 5QbQj98947 5LbLc0100h98/j3043 H 5SbShSv97j72351saYanson, Tobe,d1914-2001uJansson, Tove,d1914-20011saJanssonov, Tove,d1914-2001uJansson, Tove,d1914-20011saJansone, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJansson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanssonova, Tove,d1914-2001uJansson, Tove,d1914-2001 2aHcd,ubSknlitteratur20050204111518.0PK!DgDgFile_MARC/LICENSEnu[ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! PK!sRrrPEAR/Autoloader.phpnu[ * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version CVS: $Id$ * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader * @since File available since Release 0.1 * @deprecated File deprecated in Release 1.4.0a1 */ // /* vim: set expandtab tabstop=4 shiftwidth=4: */ if (!extension_loaded("overload")) { // die hard without ext/overload die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader"); } /** * Include for PEAR_Error and PEAR classes */ require_once "PEAR.php"; /** * This class is for objects where you want to separate the code for * some methods into separate classes. This is useful if you have a * class with not-frequently-used methods that contain lots of code * that you would like to avoid always parsing. * * The PEAR_Autoloader class provides autoloading and aggregation. * The autoloading lets you set up in which classes the separated * methods are found. Aggregation is the technique used to import new * methods, an instance of each class providing separated methods is * stored and called every time the aggregated method is called. * * @category pear * @package PEAR * @author Stig Bakken * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License * @version Release: 1.9.5 * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader * @since File available since Release 0.1 * @deprecated File deprecated in Release 1.4.0a1 */ class PEAR_Autoloader extends PEAR { // {{{ properties /** * Map of methods and classes where they are defined * * @var array * * @access private */ var $_autoload_map = array(); /** * Map of methods and aggregate objects * * @var array * * @access private */ var $_method_map = array(); // }}} // {{{ addAutoload() /** * Add one or more autoload entries. * * @param string $method which method to autoload * * @param string $classname (optional) which class to find the method in. * If the $method parameter is an array, this * parameter may be omitted (and will be ignored * if not), and the $method parameter will be * treated as an associative array with method * names as keys and class names as values. * * @return void * * @access public */ function addAutoload($method, $classname = null) { if (is_array($method)) { array_walk($method, create_function('$a,&$b', '$b = strtolower($b);')); $this->_autoload_map = array_merge($this->_autoload_map, $method); } else { $this->_autoload_map[strtolower($method)] = $classname; } } // }}} // {{{ removeAutoload() /** * Remove an autoload entry. * * @param string $method which method to remove the autoload entry for * * @return bool TRUE if an entry was removed, FALSE if not * * @access public */ function removeAutoload($method) { $method = strtolower($method); $ok = isset($this->_autoload_map[$method]); unset($this->_autoload_map[$method]); return $ok; } // }}} // {{{ addAggregateObject() /** * Add an aggregate object to this object. If the specified class * is not defined, loading it will be attempted following PEAR's * file naming scheme. All the methods in the class will be * aggregated, except private ones (name starting with an * underscore) and constructors. * * @param string $classname what class to instantiate for the object. * * @return void * * @access public */ function addAggregateObject($classname) { $classname = strtolower($classname); if (!class_exists($classname)) { $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname); include_once $include_file; } $obj =& new $classname; $methods = get_class_methods($classname); foreach ($methods as $method) { // don't import priviate methods and constructors if ($method{0} != '_' && $method != $classname) { $this->_method_map[$method] = $obj; } } } // }}} // {{{ removeAggregateObject() /** * Remove an aggregate object. * * @param string $classname the class of the object to remove * * @return bool TRUE if an object was removed, FALSE if not * * @access public */ function removeAggregateObject($classname) { $ok = false; $classname = strtolower($classname); reset($this->_method_map); while (list($method, $obj) = each($this->_method_map)) { if (is_a($obj, $classname)) { unset($this->_method_map[$method]); $ok = true; } } return $ok; } // }}} // {{{ __call() /** * Overloaded object call handler, called each time an * undefined/aggregated method is invoked. This method repeats * the call in the right aggregate object and passes on the return * value. * * @param string $method which method that was called * * @param string $args An array of the parameters passed in the * original call * * @return mixed The return value from the aggregated method, or a PEAR * error if the called method was unknown. */ function __call($method, $args, &$retval) { $method = strtolower($method); if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) { $this->addAggregateObject($this->_autoload_map[$method]); } if (isset($this->_method_map[$method])) { $retval = call_user_func_array(array($this->_method_map[$method], $method), $args); return true; } return false; } // }}} } overload("PEAR_Autoloader"); ?> PK!qCPEAR/FixPHP5PEARWarnings.phpnu[PK!Z-%##3test/Structures_Graph/tests/testCase/BasicGraph.phpnu[ | // +-----------------------------------------------------------------------------+ // require_once 'Structures/Graph.php'; require_once 'PHPUnit/Framework.php'; /** * @access private */ class BasicGraph extends PHPUnit_Framework_TestCase { var $_graph = null; function test_create_graph() { $this->_graph = new Structures_Graph(); $this->assertTrue(is_a($this->_graph, 'Structures_Graph')); } function test_add_node() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node($data); $this->_graph->addNode($node); $node = new Structures_Graph_Node($data); $this->_graph->addNode($node); $node = new Structures_Graph_Node($data); $this->_graph->addNode($node); } function test_connect_node() { $this->_graph = new Structures_Graph(); $data = 1; $node1 = new Structures_Graph_Node($data); $node2 = new Structures_Graph_Node($data); $this->_graph->addNode($node1); $this->_graph->addNode($node2); $node1->connectTo($node2); $node =& $this->_graph->getNodes(); $node =& $node[0]; $node = $node->getNeighbours(); $node =& $node[0]; /* ZE1 == and === operators fail on $node,$node2 because of the recursion introduced by the _graph field in the Node object. So, we'll use the stupid method for reference testing */ $node = true; $this->assertTrue($node2); $node = false; $this->assertFalse($node2); } function test_data_references() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node(); $node->setData(&$data); $this->_graph->addNode($node); $data = 2; $dataInNode =& $this->_graph->getNodes(); $dataInNode =& $dataInNode[0]; $dataInNode =& $dataInNode->getData(); $this->assertTrue($data === $dataInNode); } function test_metadata_references() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node(); $node->setMetadata('5', &$data); $data = 2; $dataInNode =& $node->getMetadata('5'); $this->assertTrue($data === $dataInNode); } function test_metadata_key_exists() { $this->_graph = new Structures_Graph(); $data = 1; $node = new Structures_Graph_Node(); $node->setMetadata('5', $data); $this->assertTrue($node->metadataKeyExists('5')); $this->assertFalse($node->metadataKeyExists('1')); } function test_directed_degree() { $this->_graph = new Structures_Graph(true); $node = array(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $this->_graph->addNode($node[0]); $this->_graph->addNode($node[1]); $this->_graph->addNode($node[2]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs'); $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs'); $node[0]->connectTo($node[1]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc'); $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc'); $node[0]->connectTo($node[2]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs'); $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs'); $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs'); } function test_undirected_degree() { $this->_graph = new Structures_Graph(false); $node = array(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $node[] = new Structures_Graph_Node(); $this->_graph->addNode($node[0]); $this->_graph->addNode($node[1]); $this->_graph->addNode($node[2]); $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs'); $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs'); $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs'); $node[0]->connectTo($node[1]); $this->assertEquals(1, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc'); $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc'); $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc'); $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc'); $node[0]->connectTo($node[2]); $this->assertEquals(2, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs'); $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs'); $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs'); $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs'); $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs'); $this->assertEquals(1, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs'); } } ?> PK!!test/Net_IDNA2/tests/AllTests.phpnu[addTestSuite('Net_IDNA2Test'); $suite->addTestSuite('draft-josefsson-idn-test-vectors'); return $suite; } } if (PHPUnit2_MAIN_METHOD == 'Net_IDNA2_AllTests::main') { Net_IDNA2_AllTests::main(); } PK!l,test/XML_Util/tests/testBasic_createTag.phptnu[--TEST-- XML_Util::createTag() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- "bar") ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute and content" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar"), "This is inside the tag" ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute, content, and namespace" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#" ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute, content, namespace, and REPLACE_ENTITIES" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar"), "This is inside the tag and has < & @ > in it", "http://www.w3c.org/myNs#", XML_UTIL_REPLACE_ENTITIES ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute, content, namespace, and CDATA_SECTION" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar"), "This is inside the tag and has < & @ > in it", "http://www.w3c.org/myNs#", XML_UTIL_CDATA_SECTION ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = false" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar"), "This is inside the tag and has < & @ > in it", "http://www.w3c.org/myNs#", XML_UTIL_REPLACE_ENTITIES, false ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = true" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar"), "This is inside the tag and has < & @ > in it", "http://www.w3c.org/myNs#", XML_UTIL_REPLACE_ENTITIES, true ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar"), "This is inside the tag and has < & @ > in it", "http://www.w3c.org/myNs#", XML_UTIL_REPLACE_ENTITIES, true, ' ' ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar"), "This is inside the tag and has < & @ > in it", "http://www.w3c.org/myNs#", XML_UTIL_REPLACE_ENTITIES, true, ' ', '^' ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar", "boo" => "baz"), "This is inside the tag and has < & @ > in it", "http://www.w3c.org/myNs#", XML_UTIL_REPLACE_ENTITIES, true, ' ', '^', true ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false" . PHP_EOL; echo XML_Util::createTag( "myNs:myTag", array("foo" => "bar", "boo" => "baz"), "This is inside the tag and has < & @ > in it", "http://www.w3c.org/myNs#", XML_UTIL_REPLACE_ENTITIES, true, ' ', '^', false ) . PHP_EOL . PHP_EOL; ?> --EXPECT-- =====XML_Util::createTag() basic tests===== TEST: tag with attribute TEST: tag with attribute and content This is inside the tag TEST: tag with attribute, content, and namespace This is inside the tag TEST: tag with attribute, content, namespace, and REPLACE_ENTITIES This is inside the tag and has < & @ > in it TEST: tag with attribute, content, namespace, and CDATA_SECTION in it]]> TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = false This is inside the tag and has < & @ > in it TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = true This is inside the tag and has < & @ > in it TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, and indent = (2 spaces) This is inside the tag and has < & @ > in it TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^' This is inside the tag and has < & @ > in it TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true This is inside the tag and has < & @ > in it TEST: tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false This is inside the tag and has < & @ > in it PK!W=0test/XML_Util/tests/testBasic_createComment.phptnu[--TEST-- XML_Util::createComment() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- --EXPECT-- =====XML_Util::createComment() basic tests===== TEST: basic usage PK!ҽyI-test/XML_Util/tests/testBasic_raiseError.phptnu[--TEST-- XML_Util::raiseError() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- getMessage() . PHP_EOL; } ?> --EXPECT-- =====XML_Util::raiseError() basic tests===== PEAR Error: I am an error PK!]$]$5test/XML_Util/tests/testBasic_createTagFromArray.phptnu[--TEST-- XML_Util::createTagFromArray() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- "bar", ); $tag1 = array( "qname" => "foo:bar", ); $tag2 = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", ); $tag3 = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), ); $tag4 = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $tag5 = array( "qname" => "foo:bar", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $tag6 = array( "qname" => "foo:bar", "namespaceUri" => "http://foo.com", "content" => "I'm inside the tag", ); $tag7 = array( "namespaceUri" => "http://foo.com", "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), "content" => "I'm inside the tag", ); $tag8 = array( 'content' => array('foo', 'bar') ); $tag9 = array( 'qname' => 'foo:bar', 'namespaces' => array('ns1' => 'uri1', 'ns2' => 'uri2') ); $tag10 = array( 'namespace' => 'http://foo.org', 'localPart' => 'bar' ); $tag11 = array( 'namespace' => '', 'localPart' => 'bar' ); $tag12 = array( 'localPart' => 'foo', 'namespaceUri' => 'http://bar.org' ); echo "TEST: basic usage with an invalid array" . PHP_EOL; echo XML_Util::createTagFromArray($bad) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname only)" . PHP_EOL; echo XML_Util::createTagFromArray($tag1) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname and namespaceUri)" . PHP_EOL; echo XML_Util::createTagFromArray($tag2) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, and attributes)" . PHP_EOL; echo XML_Util::createTagFromArray($tag3) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content)" . PHP_EOL; echo XML_Util::createTagFromArray($tag4) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, attributes, and content)" . PHP_EOL; echo XML_Util::createTagFromArray($tag5) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, and content)" . PHP_EOL; echo XML_Util::createTagFromArray($tag6) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (namespaceUri, attributes, and content)" . PHP_EOL; echo XML_Util::createTagFromArray($tag7) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), plus REPLACE_ENTITIES" . PHP_EOL; echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), plus ENTITIES_NONE" . PHP_EOL; echo XML_Util::createTagFromArray($tag4, XML_UTIL_ENTITIES_NONE) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = false" . PHP_EOL; echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, false) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = true" . PHP_EOL; echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)" . PHP_EOL; echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, ' ') . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'" . PHP_EOL; echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, ' ', '^') . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true" . PHP_EOL; echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, ' ', '^', true) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false" . PHP_EOL; echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, ' ', '^', false) . PHP_EOL . PHP_EOL; echo 'TEST: cause a non-scalar error on the content tag' . PHP_EOL; echo XML_Util::createTagFromArray($tag8) . PHP_EOL . PHP_EOL; echo 'TEST: handle an array of namespaces being passed' . PHP_EOL; echo XML_Util::createTagFromArray($tag9) . PHP_EOL . PHP_EOL; echo 'TEST: qname is derived from namespace + localPart' . PHP_EOL; echo XML_Util::createTagFromArray($tag10) . PHP_EOL . PHP_EOL; echo 'TEST: qname is derived from localPart only' . PHP_EOL; echo XML_Util::createTagFromArray($tag11) . PHP_EOL . PHP_EOL; echo 'TEST: namespaceUri is given, but namespace is not' . PHP_EOL; echo XML_Util::createTagFromArray($tag12) . PHP_EOL . PHP_EOL; ?> --EXPECT-- =====XML_Util::createTagFromArray() basic tests===== TEST: basic usage with an invalid array You must either supply a qualified name (qname) or local tag name (localPart). TEST: basic usage with a valid array (qname only) TEST: basic usage with a valid array (qname and namespaceUri) TEST: basic usage with a valid array (qname, namespaceUri, and attributes) TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content) I'm inside the tag TEST: basic usage with a valid array (qname, attributes, and content) I'm inside the tag TEST: basic usage with a valid array (qname, namespaceUri, and content) I'm inside the tag TEST: basic usage with a valid array (namespaceUri, attributes, and content) You must either supply a qualified name (qname) or local tag name (localPart). TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), plus REPLACE_ENTITIES I'm inside the tag TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), plus ENTITIES_NONE I'm inside the tag TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = false I'm inside the tag TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = true I'm inside the tag TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, and indent = (2 spaces) I'm inside the tag TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^' I'm inside the tag TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true I'm inside the tag TEST: basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false I'm inside the tag TEST: cause a non-scalar error on the content tag Supplied non-scalar value as tag content TEST: handle an array of namespaces being passed TEST: qname is derived from namespace + localPart TEST: qname is derived from localPart only TEST: namespaceUri is given, but namespace is not PK!ҵII%test/XML_Util/tests/testBug_5392.phptnu[--TEST-- XML_Util tests for Bug #5392 "encoding of ISO-8859-1 is the only supported encoding" --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- , & and " as well as ä, ö, ß, à and ê'; $replaced = XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_HTML, 'UTF-8'); $reversed = XML_Util::reverseEntities($replaced, XML_UTIL_ENTITIES_HTML, 'UTF-8'); echo $replaced . PHP_EOL; echo $reversed . PHP_EOL; ?> --EXPECT-- =====XML_Util tests for Bug #5392 "encoding of ISO-8859-1 is the only supported encoding"===== TEST: test case provided in bug report This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê PK!WB5test/XML_Util/tests/testBasic_splitQualifiedName.phptnu[--TEST-- XML_Util::splitQualifiedName() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- " . $return['namespace'] . PHP_EOL; echo "localPart => " . $return['localPart'] . PHP_EOL; echo PHP_EOL; echo "TEST: basic usage with namespace" . PHP_EOL; $return = XML_Util::splitQualifiedName("stylesheet", "myNs"); echo "namespace => " . $return['namespace'] . PHP_EOL; echo "localPart => " . $return['localPart'] . PHP_EOL; echo PHP_EOL; ?> --EXPECT-- =====XML_Util::splitQualifiedName() basic tests===== TEST: basic usage without namespace namespace => xslt localPart => stylesheet TEST: basic usage with namespace namespace => myNs localPart => stylesheet PK!eb5test/XML_Util/tests/testBasic_createStartElement.phptnu[--TEST-- XML_Util::createStartElement() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- "bar") ) . PHP_EOL . PHP_EOL; echo "TEST: tag only, passing '' as attribute arg" . PHP_EOL; echo XML_Util::createStartElement( 'myNs:myTag', '' ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attributes and namespace" . PHP_EOL; echo XML_Util::createStartElement( "myNs:myTag", array("foo" => "bar"), "http://www.w3c.org/myNs#" ) . PHP_EOL . PHP_EOL; echo "TEST: tag with empty attributes, whose namespaceUri is not a full namespace" . PHP_EOL; echo XML_Util::createStartElement( 'myTag', '', 'foo' ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attributes, namespace, and multiline = true" . PHP_EOL; echo XML_Util::createStartElement( "myNs:myTag", array("foo" => "bar"), "http://www.w3c.org/myNs#", true ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attributes, namespace, multiline = true, and indent = (2 spaces only)" . PHP_EOL; echo XML_Util::createStartElement( "myNs:myTag", array("foo" => "bar"), "http://www.w3c.org/myNs#", true, ' ' ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attributes, namespace, multiline = true, indent = (2 spaces only), and linebreak = '^'" . PHP_EOL; echo XML_Util::createStartElement( "myNs:myTag", array("foo" => "bar"), "http://www.w3c.org/myNs#", true, ' ', '^' ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = true" . PHP_EOL; echo XML_Util::createStartElement( "myNs:myTag", array("foo" => "bar", "boo" => "baz"), "http://www.w3c.org/myNs#", true, ' ', '^', true ) . PHP_EOL . PHP_EOL; echo "TEST: tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = false" . PHP_EOL; echo XML_Util::createStartElement( "myNs:myTag", array("foo" => "bar", "boo" => "baz"), "http://www.w3c.org/myNs#", true, ' ', '^', false ) . PHP_EOL . PHP_EOL; ?> --EXPECT-- =====XML_Util::createStartElement() basic tests===== TEST: tag only TEST: tag with attributes TEST: tag only, passing '' as attribute arg TEST: tag with attributes and namespace TEST: tag with empty attributes, whose namespaceUri is not a full namespace TEST: tag with attributes, namespace, and multiline = true TEST: tag with attributes, namespace, multiline = true, and indent = (2 spaces only) TEST: tag with attributes, namespace, multiline = true, indent = (2 spaces only), and linebreak = '^' TEST: tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = true TEST: tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = false PK!h4test/XML_Util/tests/testBasic_collapseEmptyTags.phptnu[--TEST-- XML_Util::collapseEmptyTags() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- "; $otherTag = "baz"; $xhtmlTag = ""; echo "TEST: basic usage" . PHP_EOL; echo XML_Util::collapseEmptyTags($emptyTag) . PHP_EOL . PHP_EOL; echo "TEST: basic usage alongside non-empty tag" . PHP_EOL; echo XML_Util::collapseEmptyTags($emptyTag . $otherTag) . PHP_EOL . PHP_EOL; echo "TEST: one empty tag, with COLLAPSE_ALL set" . PHP_EOL; echo XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_ALL) . PHP_EOL . PHP_EOL; echo "TEST: one empty tag alongside non-empty tag, with COLLAPSE_ALL set" . PHP_EOL; echo XML_Util::collapseEmptyTags($emptyTag . $otherTag, XML_UTIL_COLLAPSE_ALL) . PHP_EOL . PHP_EOL; echo "TEST: one empty tag, with COLLAPSE_XHTML_ONLY set" . PHP_EOL; echo XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_XHTML_ONLY) . PHP_EOL . PHP_EOL; echo "TEST: one empty tag alongside non-empty tag, with COLLAPSE_XHTML_ONLY set" . PHP_EOL; echo XML_Util::collapseEmptyTags($emptyTag . $xhtmlTag . $otherTag, XML_UTIL_COLLAPSE_XHTML_ONLY) . PHP_EOL . PHP_EOL; ?> --EXPECT-- =====XML_Util::collapseEmptyTags() basic tests===== TEST: basic usage TEST: basic usage alongside non-empty tag baz TEST: one empty tag, with COLLAPSE_ALL set TEST: one empty tag alongside non-empty tag, with COLLAPSE_ALL set baz TEST: one empty tag, with COLLAPSE_XHTML_ONLY set TEST: one empty tag alongside non-empty tag, with COLLAPSE_XHTML_ONLY set baz PK!X.test/XML_Util/tests/testBasic_isValidName.phptnu[--TEST-- XML_Util::isValidName() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- getMessage() . PHP_EOL . PHP_EOL; } else { print "Valid XML name." . PHP_EOL . PHP_EOL; } echo "TEST: invalid tag" . PHP_EOL; $result = XML_Util::isValidName("invalidTag?"); if (is_a($result, 'PEAR_Error')) { print "Invalid XML name: " . $result->getMessage() . PHP_EOL . PHP_EOL; } else { print "Valid XML name." . PHP_EOL . PHP_EOL; } echo "TEST: invalid tag that doesn't start with a letter" . PHP_EOL; $result = XML_Util::isValidName("1234five"); if (is_a($result, 'PEAR_Error')) { print "Invalid XML name: " . $result->getMessage() . PHP_EOL . PHP_EOL; } else { print "Valid XML name." . PHP_EOL . PHP_EOL; } ?> --EXPECT-- =====XML_Util::isValidName() basic tests===== TEST: valid tag Valid XML name. TEST: invalid tag Invalid XML name: XML names may only contain alphanumeric chars, period, hyphen, colon and underscores TEST: invalid tag that doesn't start with a letter Invalid XML name: XML names may only start with letter or underscore PK!.5test/XML_Util/tests/testBasic_createCDataSection.phptnu[--TEST-- XML_Util::createCDataSection() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- --EXPECT-- =====XML_Util::createCDataSection() basic tests===== TEST: basic usage PK!'-test/XML_Util/tests/testBasic_apiVersion.phptnu[--TEST-- XML_Util::apiVersion() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- --EXPECT-- =====XML_Util::apiVersion() basic tests===== TEST: basic apiVersion() call 1.1 PK! _ 2test/XML_Util/tests/testBasic_replaceEntities.phptnu[--TEST-- XML_Util::replaceEntities() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- .'; $utf8 = 'This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê'; echo "TEST: basic usage" . PHP_EOL; echo XML_Util::replaceEntities($data) . PHP_EOL . PHP_EOL; echo "TEST: basic usage but with bogus \$replaceEntities arg" . PHP_EOL; echo XML_Util::replaceEntities($data, 'I_AM_BOGUS') . PHP_EOL . PHP_EOL; echo "TEST: basic usage with ENTITIES_XML" . PHP_EOL; echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with ENTITIES_XML and UTF-8" . PHP_EOL; echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL; echo "TEST: utf8 usage with ENTITIES_XML and UTF-8" . PHP_EOL; echo XML_Util::replaceEntities($utf8, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL; echo "TEST: basic usage with ENTITIES_XML_REQUIRED" . PHP_EOL; echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL; echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL; echo "TEST: utf8 usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL; echo XML_Util::replaceEntities($utf8, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL; echo "TEST: basic usage with ENTITIES_HTML" . PHP_EOL; echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_HTML) . PHP_EOL . PHP_EOL; echo "TEST: basic usage with ENTITIES_HTML and UTF-8" . PHP_EOL; echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL; echo "TEST: utf8 usage with ENTITIES_HTML and UTF-8" . PHP_EOL; echo XML_Util::replaceEntities($utf8, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL; ?> --EXPECT-- =====XML_Util::replaceEntities() basic tests===== TEST: basic usage This string contains < & >. TEST: basic usage but with bogus $replaceEntities arg This string contains < & >. TEST: basic usage with ENTITIES_XML This string contains < & >. TEST: basic usage with ENTITIES_XML and UTF-8 This string contains < & >. TEST: utf8 usage with ENTITIES_XML and UTF-8 This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê TEST: basic usage with ENTITIES_XML_REQUIRED This string contains < & >. TEST: basic usage with ENTITIES_XML_REQUIRED and UTF-8 This string contains < & >. TEST: utf8 usage with ENTITIES_XML_REQUIRED and UTF-8 This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê TEST: basic usage with ENTITIES_HTML This string contains < & >. TEST: basic usage with ENTITIES_HTML and UTF-8 This string contains < & >. TEST: utf8 usage with ENTITIES_HTML and UTF-8 This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê PK! 4test/XML_Util/tests/testBasic_getXmlDeclaration.phptnu[--TEST-- XML_Util::getXmlDeclaration() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- --EXPECT-- =====XML_Util::getXmlDeclaration() basic tests===== TEST: using version only TEST: using version and encoding TEST: using version, encoding, and standalone flag TEST: using version and standalone flag PK!_//5test/XML_Util/tests/testBasic_attributesToString.phptnu[--TEST-- XML_Util::attributesToString() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- "bar", "boo" => "baz"); $sort1 = array( 'multiline' => true, 'indent' => '----', 'linebreak' => "^", 'entities' => XML_UTIL_ENTITIES_XML, 'sort' => true ); $sort2 = array( 'multiline' => true, 'indent' => '----', 'linebreak' => "^", 'entities' => XML_UTIL_ENTITIES_XML, ); echo "TEST: basic usage" . PHP_EOL; echo XML_Util::attributesToString($att) . PHP_EOL . PHP_EOL; echo "TEST: explicit \$sort = true" . PHP_EOL; echo XML_Util::attributesToString($att, true) . PHP_EOL . PHP_EOL; echo "TEST: explicit \$sort = false" . PHP_EOL; echo XML_Util::attributesToString($att, false) . PHP_EOL . PHP_EOL; echo "TEST: explicit \$multiline = false" . PHP_EOL; echo XML_Util::attributesToString($att, true, false) . PHP_EOL . PHP_EOL; echo "TEST: explicit \$multiline = true" . PHP_EOL; echo XML_Util::attributesToString($att, true, true) . PHP_EOL . PHP_EOL; echo "TEST: explicit \$indent = ' ' (8 spaces)" . PHP_EOL; echo XML_Util::attributesToString($att, true, true, ' ') . PHP_EOL . PHP_EOL; echo "TEST: explicit \$linebreak = '^' (some dummy char)" . PHP_EOL; echo XML_Util::attributesToString($att, true, true, '^') . PHP_EOL . PHP_EOL; echo "TEST: passing \$sort array of options that includes 'sort'" . PHP_EOL; echo XML_Util::attributesToString($att, $sort1) . PHP_EOL . PHP_EOL; echo "TEST: passing \$sort array of options that doesn't include 'sort'" . PHP_EOL; echo XML_Util::attributesToString($att, $sort2) . PHP_EOL . PHP_EOL; echo "TEST: do not replace entities" . PHP_EOL; $arr = array("foo" => "b@&r", "boo" => "b> "b@&r", "boo" => "b> "b@&r", "boo" => "b> "b@&r", "boo" => "b> --EXPECT-- =====XML_Util::attributesToString() basic tests===== TEST: basic usage boo="baz" foo="bar" TEST: explicit $sort = true boo="baz" foo="bar" TEST: explicit $sort = false foo="bar" boo="baz" TEST: explicit $multiline = false boo="baz" foo="bar" TEST: explicit $multiline = true boo="baz" foo="bar" TEST: explicit $indent = ' ' (8 spaces) boo="baz" foo="bar" TEST: explicit $linebreak = '^' (some dummy char) boo="baz" ^foo="bar" TEST: passing $sort array of options that includes 'sort' boo="baz" ----foo="bar" TEST: passing $sort array of options that doesn't include 'sort' boo="baz" ----foo="bar" TEST: do not replace entities boo="b> # created for v1.2.0a1 2008-05-04 --FILE-- here!", null, XML_UTIL_CDATA_SECTION) . PHP_EOL; ?> --EXPECT-- =====XML_Util tests for Bug #4950 "Incorrect CDATA serializing"===== TEST: test case provided in bug report here!]]> PK!uf$ &test/XML_Util/tests/testBug_18343.phptnu[--TEST-- XML_Util tests for Bug #18343 Entities in file names decoded during packaging --CREDITS-- Chuck Burgess # created for v1.2.2a1 2014-06-03 --FILE-- "install", "attributes" => array( "as" => "Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&s=Newsweek", "name" => "test/Horde/Feed/fixtures/lexicon/http-p.moreover.com-cgi-local-page%2Fo=rss&s=Newsweek", ) ); echo "No matter what flags are given to createTagFromArray(), an attribute must *always* be at least ENTITIES_XML encoded..." . PHP_EOL . PHP_EOL; $flags = array( 'no flag' => null, 'false' => false, 'ENTITIES_NONE' => XML_UTIL_ENTITIES_NONE, 'ENTITIES_XML' => XML_UTIL_ENTITIES_XML, 'ENTITIES_XML_REQUIRED' => XML_UTIL_ENTITIES_XML_REQUIRED, 'ENTITIES_HTML' => XML_UTIL_ENTITIES_HTML, 'REPLACE_ENTITIES' => XML_UTIL_REPLACE_ENTITIES, ); foreach ($flags as $flagKey => $flagValue) { echo "Testing with $flagKey:" . PHP_EOL; echo XML_Util::createTagFromArray($array, $flagValue) . PHP_EOL . PHP_EOL; } ?> --EXPECT-- =====XML_Util tests for Bug #18343 "Entities in file names decoded during packaging"===== TEST: test case provided in bug report No matter what flags are given to createTagFromArray(), an attribute must *always* be at least ENTITIES_XML encoded... Testing with no flag: Testing with false: Testing with ENTITIES_NONE: Testing with ENTITIES_XML: Testing with ENTITIES_XML_REQUIRED: Testing with ENTITIES_HTML: Testing with REPLACE_ENTITIES: PK!c?8test/XML_Util/tests/testBasic_getDocTypeDeclaration.phptnu[--TEST-- XML_Util::getDocTypeDeclaration() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- 'http://pear.php.net/dtd/package-1.0', 'id' => '-//PHP//PEAR/DTD PACKAGE 0.1' ); $dtdEntry = ''; echo "TEST: using root and an array URI" . PHP_EOL; echo XML_Util::getDocTypeDeclaration("rootTag", $uri) . PHP_EOL . PHP_EOL; echo "TEST: using root and an array URI and an internal DTD entry" . PHP_EOL; echo XML_Util::getDocTypeDeclaration("rootTag", $uri, $dtdEntry) . PHP_EOL . PHP_EOL; ?> --EXPECT-- =====XML_Util::getDocTypeDeclaration() basic tests===== TEST: using root only TEST: using root and a string URI TEST: using root and an array URI TEST: using root and an array URI and an internal DTD entry ]> PK!l  2test/XML_Util/tests/testBasic_reverseEntities.phptnu[--TEST-- XML_Util::reverseEntities() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- --EXPECT-- =====XML_Util::reverseEntities() basic tests===== TEST: basic usage This string contains < & >. TEST: basic usage but with bogus $replaceEntities arg This string contains < & >. TEST: basic usage with ENTITIES_XML This string contains < & >. TEST: basic usage with ENTITIES_XML and UTF-8 This string contains < & >. TEST: utf8 usage with ENTITIES_XML and UTF-8 This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê TEST: basic usage with ENTITIES_XML_REQUIRED This string contains < & >. TEST: basic usage with ENTITIES_XML_REQUIRED and UTF-8 This string contains < & >. TEST: utf8 usage with ENTITIES_XML_REQUIRED and UTF-8 This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê TEST: basic usage with ENTITIES_HTML This string contains < & >. TEST: basic usage with ENTITIES_HTML and UTF-8 This string contains < & >. TEST: utf8 usage with ENTITIES_HTML and UTF-8 This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê PK!^r3test/XML_Util/tests/testBasic_createEndElement.phptnu[--TEST-- XML_Util::createEndElement() basic tests --CREDITS-- Chuck Burgess # created for v1.2.0a1 2008-05-04 --FILE-- --EXPECT-- =====XML_Util::createEndElement() basic tests===== TEST: basic usage (myTag) TEST: basic usage with a namespaced tag (myNs:myTag) PK!2>g>gdata/Structures_Graph/LICENSEnu[ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! PK!x?? PEAR5.phpnu[ File_MARC pear.php.net Parse, modify, and create MARC records The standard for machine-readable cataloging (MARC) records is documented at http://loc.gov/marc/. This package enables you to read existing MARC records from a file, string, or (using the YAZ extension), from a Z39.50 source. You can also use this package to create new MARC records. This package is based on the PHP MARC package, originally called "php-marc", that is part of the Emilda Project (http://www.emilda.org). Christoffer Landtman generously agreed to make the "php-marc" code available under the GNU LGPL so it could be used as the basis of this PEAR package. Dan Scott dbs dbs@php.net yes 2013-09-13 0.7.3 0.7.0 beta beta GNU Lesser General Public License 0.7.3-beta * Merge patch from Karen Coombs (librarywebchic@gmail.com) adding default namespace to record elements 5.2 1.4.0 Structures_LinkedList pear.php.net Validate_ISPN pear.php.net PK!r&& .pkgxml/Pear_Auth_SASL-1.0.6.xmlnu[ Auth_SASL pear.php.net Abstraction of various SASL mechanism responses Provides code to generate responses to common SASL mechanisms, including: - Digest-MD5 - Cram-MD5 - Plain - Anonymous - Login (Pseudo mechanism) - SCRAM Anish Mistry amistry amistry@am-productions.biz no Richard Heyes richard richard@php.net no Michael Bretterklieber mbretter michael@bretterklieber.com no 2011-09-27 1.0.6 1.0.3 stable stable BSD QA release * Bug #18856: Authentication warnings because of wrong Auth_SASL::factory argument [kguest] 4.2.0 1.4.3 1.0.6 1.0.3 stable stable 2011-09-27 BSD QA release * Bug #18856: Authentication warnings because of wrong Auth_SASL::factory argument [kguest] 1.0.5 1.0.3 stable stable 2011-09-04 BSD QA release * Added support for any mechanism of the SCRAM family; with thanks to Jehan Pagès. [kguest] * crammd5 and digestmd5 mechanisms name deprecated in favour of IANA registered names 'cram-md5' and 'digest-md5'; with thanks to Jehan Pagès. [kguest] 1.0.4 1.0.3 stable stable 2010-02-07 BSD QA release * Fix bug #16624: open_basedir restriction warning in DigestMD5.php [till] 1.0.3 1.0.3 stable stable 2009-08-05 BSD QA release * Move SVN to proper directory structure [cweiske] * Fix Bug #8775: Error in package.xml * Fix Bug #14671: Security issue due to seeding random number generator [cweiske] 1.0.2 1.0.2 stable stable 2006-05-21 BSD * Fixed Bug #2143 Auth_SASL_DigestMD5::getResponse() generates invalid response * Fixed Bug #6611 Suppress PHP 5 Notice Errors * Fixed Bug #2154 realm isn't contained in challange 1.0.1 1.0.1 stable stable 2003-09-11 BSD * Added authcid/authzid separation in PLAIN and DIGEST-MD5. PK!Yh .pkgxml/Pear_Net_SMTP-1.6.3.xmlnu[ Net_SMTP pear.php.net An implementation of the SMTP protocol Provides an implementation of the SMTP protocol using PEAR's Net_Socket class. Jon Parise jon jon@php.net yes Chuck Hagenbuch chagenbu chuck@horde.org yes 2015-08-02 1.6.3 1.2.0 stable stable PHP License - Fix redundant CRLF terminator sequence. - Add a note about $socket_options and OpenSSL. - Add Composer support. 4.0.5 1.4.3 Net_Socket pear.php.net 1.0.7 Auth_SASL pear.php.net 1.0.5 PK!1vHH".pkgxml/Pear_Net_Socket-1.0.14.xmlnu[ Net_Socket pear.php.net Network Socket Interface Net_Socket is a class interface to TCP sockets. It provides blocking and non-blocking operation, with different reading and writing modes (byte-wise, block-wise, line-wise and special formats like network byte-order ip addresses). Chuck Hagenbuch chagenbu chuck@horde.org yes Stig Bakken ssb stig@php.net no Aleksander Machniak alec alec@php.net yes 2013-05-24 1.0.14 1.0.10 stable stable PHP License - Fix connecting when host is specified with protocol prefix e.g. ssl:// 4.3.0 1.4.0b1 PK!6w&Yc c .pkgxml/Pear_Net_IDNA2-0.1.1.xmlnu[ Net_IDNA2 pear.php.net Punycode encoding and decoding. This package helps you to encode and decode punycode strings easily. Stefan Neufeind neufeind pear.neufeind@speedpartner.de yes Daniel O'Connor doconnor daniel.oconnor@gmail.com no 2010-12-09 0.1.1 0.1.0 beta beta LGPL * Added initial support for IDNA2008. This is needed for characters like the German "Eszett" which would otherwise be turned into "ss" during nameprep. Use $n->setParams('version', '2008') to use the "new" IDNA-encoding. Default is still IDNA2003 for backwards-compatibility. Further aspects of IDNA2008-encoding (for example some checks) should be added later according to RFCs. * #16466: Unit tests (testcaseses from draft-josefsson-idn-test-vectors; thanks to Daniel) * Unit tests (coverage, refactoring/cleanup, more tests) * #17542: URIs get mangled when decoding (UTF8-fix) * Codingstyle fixes * fixed handling of URLs with more than a domain-name (fixed opposite of parse_url()) * Added specialized and spl exceptions * #17533: Releases and roles do not seem to work. 5.2.1 1.9.0 0.1.0 0.1.0 beta beta 2010-06-03 LGPL QA Release Bug #17430 Multiple Net_IDNA class declarations Warning: This package is now split between Net_IDNA (php4) and Net_IDNA2 (php5) PK!a pkgxml/alt-php80-vld.xmlnu[PK!a  pkgxml/alt-php83-vld.xmlnu[PK!J?jf f pkgxml/alt-php73-vld.xmlnu[PK!J?jf f  pkgxml/alt-php74-vld.xmlnu[PK!J?jf f R+pkgxml/alt-php71-vld.xmlnu[PK!6.depdbnu[PK!G.locknu[PK! G.depdblocknu[PK!Zaa9H.filemapnu[PK!`  e.channels/__uri.regnu[PK!v++ g.channels/pecl.php.net.regnu[PK!o/ i.channels/.alias/phpdocs.txtnu[PK! i.channels/.alias/pear.txtnu[PK!ui< Aj.channels/.alias/pecl.txtnu[PK!Vj.channels/doc.php.net.regnu[PK!4M((l.channels/pear.php.net.regnu[PK!uvuvfo.registry/xml_util.regnu[PK!sРWW!.registry/archive_tar.regnu[PK!)) >.registry/console_getopt.regnu[PK!՘DD%h.registry/pear.regnu[PK! C}++.registry/structures_graph.regnu[PK!RRRpkgxml/Archive_Tar.xmlnu[PK!+8Nrpkgxml/PEAR.xmlnu[PK!#ybb4gpkgxml/Structures_Graph.xmlnu[PK!7pKK}pkgxml/XML_Util.xmlnu[PK!W^pkgxml/Console_Getopt.xmlnu[PK!a pkgxml/alt-php85-vld.xmlnu[PK!a pkgxml/alt-php84-vld.xmlnu[PK!a pkgxml/alt-php81-vld.xmlnu[PK!{ Mail/null.phpnu[PK!E@%>>Mail/sendmail.phpnu[PK!A~{{93Mail/RFC822.phpnu[PK!+V Mail/mime.phpnu[PK!x عMail/mimeDecode.phpnu[PK!B_Ǭ== Mail/smtp.phpnu[PK!wԐE;E;]Mail/smtpmx.phpnu[PK!؛JJZMail/mimePart.phpnu[PK!Bshh PMail/mock.phpnu[PK!@iE\\ dMail/mail.phpnu[PK!*z%-%- #}Structures/LinkedList/Double.phpnu[PK!p:p: Structures/LinkedList/Single.phpnu[PK!UyvXStructures/Graph.phpnu[PK!C + +Structures/Graph/Node.phpnu[PK!9,$) Structures/Graph/Manipulator/AcyclicTest.phpnu[PK!~(htt2@ Structures/Graph/Manipulator/TopologicalSorter.phpnu[PK!J} } [ Auth/SASL/Anonymous.phpnu[PK!P(~T T i Auth/SASL/CramMD5.phpnu[PK!= = 4w Auth/SASL/Plain.phpnu[PK!< O O  Auth/SASL/Login.phpnu[PK!%ׅtg!g!F Auth/SASL/DigestMD5.phpnu[PK!T Auth/SASL/Common.phpnu[PK!vRr, , N Auth/SASL/External.phpnu[PK!ќ00 Auth/SASL/SCRAM.phpnu[PK!K   Auth/SASL.phpnu[PK!T,,  OS/Guess.phpnu[PK!=C PEAR/Config.phpnu[PK!`eEAEA Q PEAR/REST.phpnu[PK!ym6m6 PEAR/Exception.phpnu[PK!r" PEAR/ChannelFile.phpnu[PK!gkUU PEAR/Validate.phpnu[PK!d֣S PEAR/Command/Pickle.xmlnu[PK!zk<k< PEAR/Command/Config.phpnu[PK!݄>3PEAR/Command/Pickle.phpnu[PK!TIIcqPEAR/Builder.phpnu[PK![ WPEAR/XMLParser.phpnu[PK!l(ePEAR/Downloader.phpnu[PK!b PEAR/ErrorStack.phpnu[PK!(PzJ]PEAR/Proxy.phpnu[PK!'rsPEAR/RunTest.phpnu[PK!jy99LPEAR/Validator/PECL.phpnu[PK!p PEAR/Dependency2.phpnu[PK!wv@@PEAR/PackageFile/v2.phpnu[PK!C8LL!PEAR/PackageFile/v2/Validator.phpnu[PK!=__v-PEAR/PackageFile/v2/rw.phpnu[PK!5$PEAR/PackageFile/v1.phpnu[PK!ɁɁ!PEAR/PackageFile/Generator/v2.phpnu[PK!`=!3lPEAR/PackageFile/Generator/v1.phpnu[PK!OWH H 51PEAR/PackageFile/Parser/v2.phpnu[PK!_=@@=PEAR/PackageFile/Parser/v1.phpnu[PK!c__~PEAR/DependencyDB.phpnu[PK!@PPEAR/ChannelFile/Parser.phpnu[PK!_00PEAR/Command.phpnu[PK!ٲ==PEAR/PackageFile.phpnu[PK!JDSPEAR/Task/Replace.phpnu[PK!&%75))oPEAR/Task/Windowseol/rw.phpnu[PK!3}tPEAR/Task/Replace/rw.phpnu[PK!& i."zPEAR/Task/Postinstallscript/rw.phpnu[PK!-!QPEAR/Task/Common.phpnu[PK!D$PEAR/Task/Windowseol.phpnu[PK!ZEx9x9PEAR/Task/Postinstallscript.phpnu[PK!\kPEAR/Task/Unixeol/rw.phpnu[PK! PEAR/Task/Unixeol.phpnu[PK!Wf^PEAR/REST/10.phpnu[PK!Y;;/}PEAR/REST/13.phpnu[PK!,#y++PEAR/REST/11.phpnu[PK!U  PEAR/Packager.phpnu[PK!ZbgbgPEAR/Common.phpnu[PK!$((jPEAR/Registry.phpnu[PK! MdMdPEAR/Frontend/CLI.phpnu[PK!  <PEAR/Installer/Role/Doc.phpnu[PK!/PEAR/Installer/Role/Cfg.xmlnu[PK!>1HPEAR/Installer/Role/Www.xmlnu[PK!?m  sPEAR/Installer/Role/Php.phpnu[PK!*Y| %%PEAR/Installer/Role/Man.phpnu[PK!BB;PEAR/Installer/Role/Ext.xmlnu[PK!p""PEAR/Installer/Role/Src.xmlnu[PK!h&P*5 PEAR/Installer/Role/Doc.xmlnu[PK!B]  PEAR/Installer/Role/Test.xmlnu[PK!zq PEAR/Installer/Role/Php.xmlnu[PK! PEAR/Installer/Role/Data.phpnu[PK!0cBPEAR/Installer/Role/Man.xmlnu[PK!K  2PEAR/Installer/Role/Ext.phpnu[PK!YPEAR/Installer/Role/Test.phpnu[PK!@vаPEAR/Installer/Role/Script.xmlnu[PK!fszPEAR/Installer/Role/Data.xmlnu[PK!?GGPEAR/Installer/Role/Common.phpnu[PK!^D{  V7PEAR/Installer/Role/Www.phpnu[PK!Ƥ:PEAR/Installer/Role/Cfg.phpnu[PK![tJPEAR/Installer/Role/Script.phpnu[PK!srrMPEAR/Installer/Role/Src.phpnu[PK!VZQPEAR/Installer/Role.phpnu[PK!{ ))pPEAR/Downloader/Package.phpnu[PK!.4 PEAR/Frontend.phpnu[PK!،wʴ PEAR/Installer.phpnu[PK!#K !Net/IDNA2.phpnu[PK!S66]#Net/IDNA2/Exception.phpnu[PK!&#rr M^#Net/IDNA2/Exception/Nameprep.phpnu[PK!ZZ _#Net/Sieve.phpnu[PK!³[KK $Net/SMTP.phpnu[PK!6zNN-$Net/Socket.phpnu[PK!=YYd%Archive/Tar.phpnu[PK!smmh&File/MARCBASE.phpnu[PK!6lY{&File/MARCXML.phpnu[PK! (7(7 `&File/MARC.phpnu[PK!zWW&File/MARC/Record.phpnu[PK!(#~''File/MARC/Exception.phpnu[PK!灴4 D'File/MARC/List.phpnu[PK!<`R'File/MARC/Field.phpnu[PK!t;;m'File/MARC/Lint/CodeData.phpnu[PK!j:j:?'File/MARC/Data_Field.phpnu[PK!lz`'File/MARC/Control_Field.phpnu[PK!Ē˪S'File/MARC/Lint.phpnu[PK!&?)File/MARC/Subfield.phpnu[PK!15t*test/Structures_LinkedList/tests/single_link_007.phptnu[PK!Zx5*test/Structures_LinkedList/tests/single_link_002.phptnu[PK!(  .*test/Structures_LinkedList/tests/link_004.phptnu[PK!|5.*test/Structures_LinkedList/tests/SingleLinkTester.phpnu[PK!髂[5a*test/Structures_LinkedList/tests/single_link_006.phptnu[PK!sDHH.*test/Structures_LinkedList/tests/link_007.phptnu[PK!.X%*test/Structures_LinkedList/tests/link_005.phptnu[PK!#,E5**test/Structures_LinkedList/tests/single_link_005.phptnu[PK!//*test/Structures_LinkedList/tests/LinkTester.phpnu[PK! .#2*test/Structures_LinkedList/tests/link_001.phptnu[PK!骗.\6*test/Structures_LinkedList/tests/link_006.phptnu[PK!).:*test/Structures_LinkedList/tests/link_002.phptnu[PK!45=*test/Structures_LinkedList/tests/single_link_001.phptnu[PK!)y--5A*test/Structures_LinkedList/tests/single_link_004.phptnu[PK!K5yD*test/Structures_LinkedList/tests/single_link_003.phptnu[PK!o.H*test/Structures_LinkedList/tests/link_003.phptnu[PK!x`(M*test/Mail/tests/bug17317.phptnu[PK!q/ O*test/Mail/tests/13659.phptnu[PK!óQ*test/Mail/tests/9137_2.phptnu[PK!wV*test/Mail/tests/smtp_error.phptnu[PK!)f$! ! 5Z*test/Mail/tests/rfc822.phptnu[PK!8xe*test/Mail/tests/bug17178.phptnu[PK!*f*test/Mail/tests/9137.phptnu[PK!W8j#j#.k*test/Structures_Graph/tests/BasicGraphTest.phpnu[PK!6:UU5̎*test/Structures_Graph/tests/TopologicalSorterTest.phpnu[PK!V(*test/Structures_Graph/tests/AllTests.phpnu[PK!/*test/Structures_Graph/tests/AcyclicTestTest.phpnu[PK!`ii&*test/Structures_Graph/tests/helper.incnu[PK!)ԟ*test/Console_Getopt/tests/001-getopt.phptnu[PK!'*test/Console_Getopt/tests/bug11068.phptnu[PK!'k*test/Console_Getopt/tests/bug10557.phptnu[PK!|EE'*test/Console_Getopt/tests/bug13140.phptnu[PK!?7EE9L*test/Net_IDNA2/tests/draft-josefsson-idn-test-vectors.phpnu[PK!K&*test/Net_IDNA2/tests/Net_IDNA2Test.phpnu[PK!. "*test/XML_RPC/tests/extra-lines.phpnu[PK!|E  )+test/XML_RPC/tests/empty-value-struct.phpnu[PK!3l** ?+test/XML_RPC/tests/protoport.phpnu[PK!B9+test/XML_RPC/tests/allgot.incnu[PK!̢ >+test/XML_RPC/tests/types.phpnu[PK!J&I+test/XML_RPC/tests/encode.phpnu[PK!XX DR+test/XML_RPC/tests/test_Dump.phpnu[PK!$]"Z+test/XML_RPC/tests/empty-value.phpnu[PK!b)))%7b+test/XML_RPC/tests/actual-request.phpnu[PK!e>44/i+test/XML_Util/tests/CreateTagFromArrayTests.phpnu[PK!C,Ȟ+test/XML_Util/tests/ReplaceEntitiesTests.phpnu[PK!یu'+test/XML_Util/tests/ApiVersionTests.phpnu[PK!Gs$9+test/XML_Util/tests/Bug5392Tests.phpnu[PK!4ejj/+test/XML_Util/tests/CreateCDataSectionTests.phpnu[PK!|\5.U+test/XML_Util/tests/CollapseEmptyTagsTests.phpnu[PK!GG/+test/XML_Util/tests/SplitQualifiedNameTests.phpnu[PK!Yq%Z+test/XML_Util/tests/Bug21184Tests.phpnu[PK!>M$q+test/XML_Util/tests/Bug4950Tests.phpnu[PK!YR""/+test/XML_Util/tests/CreateStartElementTests.phpnu[PK!ܬ$2+test/XML_Util/tests/GetDocTypeDeclarationTests.phpnu[PK!G%t+test/XML_Util/tests/Bug21177Tests.phpnu[PK!۩%+test/XML_Util/tests/Bug18343Tests.phpnu[PK!zt, +test/XML_Util/tests/ReverseEntitiesTests.phpnu[PK!~$[ee-< ,test/XML_Util/tests/CreateEndElementTests.phpnu[PK!!) ,test/XML_Util/tests/AbstractUnitTests.phpnu[PK!m4**&,test/XML_Util/tests/CreateTagTests.phpnu[PK!Df:..,test/XML_Util/tests/GetXmlDeclarationTests.phpnu[PK!Zt/i3,test/XML_Util/tests/AttributesToStringTests.phpnu[PK!ݑh(Q,test/XML_Util/tests/IsValidNameTests.phpnu[PK!TT*Y,test/XML_Util/tests/CreateCommentTests.phpnu[PK!rv'[,test/XML_Util/tests/RaiseErrorTests.phpnu[PK!<ȸB!!],test/Net_SMTP/tests/auth.phptnu[PK!Pgހ"(`,test/Net_SMTP/tests/quotedata.phptnu[PK!A-g,test/Net_SMTP/tests/basic.phptnu[PK!6#k,test/Net_SMTP/tests/config.php.distnu[PK!$n,test/Net_Sieve/tests/largescript.sivnu[PK!g--"D/test/Net_Sieve/tests/SieveTest.phpnu[PK!Ynpp$T/test/Net_Sieve/tests/config.php.distnu[PK!ҵ3>/test/Mail_mimeDecode/tests/semicolon_content_type_bug1724.phptnu[PK!s%2/test/Mail_mimeDecode/tests/parse_header_value.phptnu[PK!;{'/test/Mail_Mime/tests/test_Bug_GH19.phptnu[PK!Eoo(Q/test/Mail_Mime/tests/test_Bug_13962.phptnu[PK!Ԣ``(/test/Mail_Mime/tests/test_Bug_21255.phptnu[PK!i;)/test/Mail_Mime/tests/test_Bug_7561_1.phptnu[PK!e;I(/test/Mail_Mime/tests/test_Bug_21205.phptnu[PK!Y'$/test/Mail_Mime/tests/test_Bug_GH26.phptnu[PK!RoUU(n/test/Mail_Mime/tests/test_Bug_20226.phptnu[PK!g+(/test/Mail_Mime/tests/test_Bug_13444.phptnu[PK!%BB'/test/Mail_Mime/tests/test_Bug_GH16.phptnu[PK!-7c77)/test/Mail_Mime/tests/test_Bug_3513_2.phptnu[PK!(V,(:/test/Mail_Mime/tests/test_Bug_12411.phptnu[PK!qS*/test/Mail_Mime/tests/test_Bug_10999_1.phptnu[PK!29r'`/test/Mail_Mime/tests/encoding_case.phptnu[PK!M-\(/test/Mail_Mime/tests/test_Bug_17175.phptnu[PK!ّB */test/Mail_Mime/tests/qp_encoding_test.phptnu[PK!)#pp(/test/Mail_Mime/tests/test_Bug_18772.phptnu[PK!2!B,0test/Mail_Mime/tests/test_linebreak_dot.phptnu[PK!B&( 0test/Mail_Mime/tests/test_Bug_12466.phptnu[PK!MU..( 0test/Mail_Mime/tests/test_Bug_20273.phptnu[PK![b3P0test/Mail_Mime/tests/content_transfer_encoding.phptnu[PK!k0(O0test/Mail_Mime/tests/test_Bug_20564.phptnu[PK!a[(0test/Mail_Mime/tests/class-filename.phptnu[PK!o  (0test/Mail_Mime/tests/test_Bug_14529.phptnu[PK!Cz2}}(`0test/Mail_Mime/tests/test_Bug_12165.phptnu[PK!Yak!!850test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part1.phptnu[PK!@/NN(0test/Mail_Mime/tests/test_Bug_21206.phptnu[PK!8)d0test/Mail_Mime/tests/test_Bug_3513_1.phptnu[PK!5( 0test/Mail_Mime/tests/test_Bug_21098.phptnu[PK!v)v"0test/Mail_Mime/tests/test_Bug_8541_1.phptnu[PK!UiE!E!2$0test/Mail_Mime/tests/headers_without_mbstring.phptnu[PK!(iF0test/Mail_Mime/tests/test_Bug_21027.phptnu[PK!`~@*@c0test/Mail_Mime/tests/test_Bug_12385_1.phptnu[PK!zŬ(e0test/Mail_Mime/tests/test_Bug_11731.phptnu[PK!Xb(h0test/Mail_Mime/tests/test_Bug_14779.phptnu[PK!Izz(j0test/Mail_Mime/tests/test_Bug_20563.phptnu[PK!ZXHww)l0test/Mail_Mime/tests/test_Bug_3513_3.phptnu[PK!(o0test/Mail_Mime/tests/test_Bug_15320.phptnu[PK!-b2(q0test/Mail_Mime/tests/test_Bug_13032.phptnu[PK!%+2PP(5t0test/Mail_Mime/tests/test_Bug_18083.phptnu[PK!Qi"--(v0test/Mail_Mime/tests/test_Bug_11381.phptnu[PK!X##(by0test/Mail_Mime/tests/test_Bug_19497.phptnu[PK!'''){0test/Mail_Mime/tests/test_Bug_8386_1.phptnu[PK!1d(]~0test/Mail_Mime/tests/test_Bug_17025.phptnu[PK!e@Q__(Q0test/Mail_Mime/tests/test_Bug_14780.phptnu[PK! Ǟ  20test/Mail_Mime/tests/test_linebreak_larger_76.phptnu[PK!ܶghh)m0test/Mail_Mime/tests/test_Bug_9722_1.phptnu[PK!YcLYY(.0test/Mail_Mime/tests/test_Bug_16539.phptnu[PK! ((*ߪ0test/Mail_Mime/tests/test_Bug_10596_1.phptnu[PK!9::*a0test/Mail_Mime/tests/test_Bug_10816_1.phptnu[PK!᠗""/0test/Mail_Mime/tests/headers_with_mbstring.phptnu[PK!|JJ80test/Mail_Mime/tests/sleep_wakeup_EOL-bug3488-part2.phptnu[PK!:N *0test/File_MARC/tests/marc_xml_rsinger.phptnu[PK!a!"0test/File_MARC/tests/namespace.xmlnu[PK!9;(0test/File_MARC/tests/marc_field_003.phptnu[PK!W1(1test/File_MARC/tests/marc_xml_16642.phptnu[PK!è{{"1test/File_MARC/tests/marc_020.phptnu[PK!5Nĩ $1test/File_MARC/tests/marc_16783.phptnu[PK!_("1test/File_MARC/tests/marc_field_002.phptnu[PK!Ya3' %1test/File_MARC/tests/marc_lint_001.phptnu[PK! &-71test/File_MARC/tests/marc_xml_004.phptnu[PK!a+B1test/File_MARC/tests/marc_subfield_001.phptnu[PK!L"E1test/File_MARC/tests/marc_006.phptnu[PK!' K1test/File_MARC/tests/marc_lint_004.phptnu[PK!6N&v_1test/File_MARC/tests/marc_xml_006.phptnu[PK! (me1test/File_MARC/tests/marc_field_005.phptnu[PK!ewWW"i1test/File_MARC/tests/marc_003.phptnu[PK!(NNeo1test/File_MARC/tests/camel.mrcnu[PK!Ujڧ"1test/File_MARC/tests/marc_007.phptnu[PK!t1t1&1test/File_MARC/tests/marc_xml_008.phptnu[PK!uN9 "1test/File_MARC/tests/marc_005.phptnu[PK! VU,,*1test/File_MARC/tests/marc_field_21246.phptnu[PK!d z= = ':1test/File_MARC/tests/marc_lint_002.phptnu[PK!=O !1test/File_MARC/tests/sandburg.xmlnu[PK!s}3(1test/File_MARC/tests/marc_xml_namespace_prefix.phptnu[PK!<&F1test/File_MARC/tests/marc_xml_001.phptnu[PK!b|T%T%"h 2test/File_MARC/tests/marc_004.phptnu[PK!"12test/File_MARC/tests/marc_015.phptnu[PK!X""[D2test/File_MARC/tests/marc_009.phptnu[PK!(Y"J2test/File_MARC/tests/xmlescape.mrcnu[PK!ҋX X "M2test/File_MARC/tests/marc_018.phptnu[PK!  )vZ2test/File_MARC/tests/marc_record_001.phptnu[PK!ri\2test/File_MARC/tests/skipif.incnu[PK!\.ivv!^2test/File_MARC/tests/sandburg.mrcnu[PK!#c "c2test/File_MARC/tests/onerecord.xmlnu[PK!<(p2test/File_MARC/tests/marc_field_004.phptnu[PK!OVOO"t2test/File_MARC/tests/marc_010.phptnu[PK!rOϋ '`2test/File_MARC/tests/marc_lint_005.phptnu[PK!=.&B2test/File_MARC/tests/marc_xml_007.phptnu[PK!+6"d2test/File_MARC/tests/marc_008.phptnu[PK!+W #2test/File_MARC/tests/bigarchive.xmlnu[PK!vh "2test/File_MARC/tests/marc_014.phptnu[PK!,Ͳ2test/File_MARC/tests/marc_xml_namespace.phptnu[PK!a nn(2test/File_MARC/tests/marc_field_001.phptnu[PK!CKK&2test/File_MARC/tests/marc_xml_009.phptnu[PK!~N0:: `2test/File_MARC/tests/example.mrcnu[PK!}۶\pp$2test/File_MARC/tests/bad_example.xmlnu[PK!^Cg33"2test/File_MARC/tests/marc_017.phptnu[PK!^OXRR"32test/File_MARC/tests/marc_002.phptnu[PK! =&3test/File_MARC/tests/marc_xml_005.phptnu[PK!5;-- 3test/File_MARC/tests/music.xmlnu[PK!=d"93test/File_MARC/tests/marc_012.phptnu[PK!S3  "A3test/File_MARC/tests/marc_021.phptnu[PK!3ը+vT3test/File_MARC/tests/marc_subfield_002.phptnu[PK!f==$X3test/File_MARC/tests/bad_example.mrcnu[PK!kP"~`3test/File_MARC/tests/marc_023.phptnu[PK!Yz"b3test/File_MARC/tests/marc_019.phptnu[PK!泮Vs3test/File_MARC/tests/music.mrcnu[PK! < "R3test/File_MARC/tests/marc_001.phptnu[PK!#" ) )"^3test/File_MARC/tests/marc_022.phptnu[PK!44*C=XML_Util/tests/CreateTagFromArrayTests.phpnu[PK!C'Q=XML_Util/tests/ReplaceEntitiesTests.phpnu[PK!یu" >XML_Util/tests/ApiVersionTests.phpnu[PK!Gs >XML_Util/tests/Bug5392Tests.phpnu[PK!4ejj*>XML_Util/tests/CreateCDataSectionTests.phpnu[PK!|\5)>XML_Util/tests/CollapseEmptyTagsTests.phpnu[PK!GG*$#>XML_Util/tests/SplitQualifiedNameTests.phpnu[PK!Yq &>XML_Util/tests/Bug21184Tests.phpnu[PK!>M(>XML_Util/tests/Bug4950Tests.phpnu[PK!YR""*+>XML_Util/tests/CreateStartElementTests.phpnu[PK!ܬ$-{A>XML_Util/tests/GetDocTypeDeclarationTests.phpnu[PK!G H>XML_Util/tests/Bug21177Tests.phpnu[PK!۩ 9M>XML_Util/tests/Bug18343Tests.phpnu[PK!zt'WT>XML_Util/tests/ReverseEntitiesTests.phpnu[PK!~$[ee(e>XML_Util/tests/CreateEndElementTests.phpnu[PK!!$Ah>XML_Util/tests/AbstractUnitTests.phpnu[PK!m4**!=j>XML_Util/tests/CreateTagTests.phpnu[PK!Df:)>XML_Util/tests/GetXmlDeclarationTests.phpnu[PK!Zt*>XML_Util/tests/AttributesToStringTests.phpnu[PK!ݑh# >XML_Util/tests/IsValidNameTests.phpnu[PK!TT%>XML_Util/tests/CreateCommentTests.phpnu[PK!rv"ȶ>XML_Util/tests/RaiseErrorTests.phpnu[PK! Xxo -ڸ>Symfony/Bridge/Doctrine/Logger/DbalLogger.phpnu[PK!eOO&>Symfony/Bridge/Doctrine/autoloader.phpnu[PK!X+8w>Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.phpnu[PK! 9,5>Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.phpnu[PK!0N>Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.phpnu[PK!!%d==A>Symfony/Bridge/Doctrine/Form/ChoiceList/EntityLoaderInterface.phpnu[PK! ?x77<>Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.phpnu[PK!GCt A?Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.phpnu[PK!`. qpp7"?Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.phpnu[PK!CiPPM:?Symfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.phpnu[PK!憝0B?Symfony/Bridge/Doctrine/Form/Type/EntityType.phpnu[PK!S;,:2F?Symfony/Bridge/Doctrine/Form/Type/DoctrineType.phpnu[PK!W&v<`?Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.phpnu[PK!Eo?Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.phpnu[PK!(y9P?Symfony/Bridge/Doctrine/Validator/DoctrineInitializer.phpnu[PK!QГ>]?Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.phpnu[PK!:dG?Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.phpnu[PK!Ta==B.?Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.phpnu[PK!qm m -ݥ?Symfony/Bridge/Doctrine/RegistryInterface.phpnu[PK!lf/qq=?Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.phpnu[PK!=?Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.phpnu[PK!C?Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.phpnu[PK!OlQ996?Symfony/Bridge/Doctrine/ContainerAwareEventManager.phpnu[PK!؈3?Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.phpnu[PK!̳֨+?Symfony/Bridge/Doctrine/ManagerRegistry.phpnu[PK!+çxAA??Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.phpnu[PK!*+JJI?Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.phpnu[PK!*SJ@Symfony/Bridge/Doctrine/DependencyInjection/Security/UserProvider/EntityFactory.phpnu[PK!㛕Q.R@Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.phpnu[PK!~YAAeDj@Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.phpnu[PK!,S@Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.phpnu[PK!4NN%@Symfony/Bridge/Monolog/autoloader.phpnu[PK!մ1?@Symfony/Bridge/Monolog/Handler/FirePHPHandler.phpnu[PK!Zv/2@Symfony/Bridge/Monolog/Handler/DebugHandler.phpnu[PK!y1H@Symfony/Bridge/Monolog/Handler/ConsoleHandler.phpnu[PK!*vv5@Symfony/Bridge/Monolog/Handler/SwiftMailerHandler.phpnu[PK!"II3a@Symfony/Bridge/Monolog/Handler/ChromePhpHandler.phpnu[PK!; ! @Symfony/Bridge/Monolog/Logger.phpnu[PK!b115F@Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.phpnu[PK!,1@Symfony/Bridge/Monolog/Processor/WebProcessor.phpnu[PK!$KK"@Symfony/Bridge/Twig/autoloader.phpnu[PK!)UU1y@Symfony/Bridge/Twig/Translation/TwigExtractor.phpnu[PK!6 DZ77*/@Symfony/Bridge/Twig/Node/StopwatchNode.phpnu[PK!, @5@Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.phpnu[PK! s>>*@Symfony/Bridge/Twig/Node/FormThemeNode.phpnu[PK!PIAA3M@Symfony/Bridge/Twig/Node/TransDefaultDomainNode.phpnu[PK!U,tt,@Symfony/Bridge/Twig/Node/FormEnctypeNode.phpnu[PK!ʦ\G G &ASymfony/Bridge/Twig/Node/TransNode.phpnu[PK!^,^ASymfony/Bridge/Twig/Node/RenderBlockNode.phpnu[PK!vq)rASymfony/Bridge/Twig/Form/TwigRenderer.phpnu[PK!b3}}8ASymfony/Bridge/Twig/Form/TwigRendererEngineInterface.phpnu[PK!Qkk2ASymfony/Bridge/Twig/Form/TwigRendererInterface.phpnu[PK!</ ASymfony/Bridge/Twig/Form/TwigRendererEngine.phpnu[PK!  G|=ASymfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.phpnu[PK!)[n n ) JASymfony/Bridge/Twig/NodeVisitor/Scope.phpnu[PK!tA:SASymfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.phpnu[PK! 9292B>bASymfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twignu[PK![[DASymfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twignu[PK!.8ASymfony/Bridge/Twig/TokenParser/StopwatchTokenParser.phpnu[PK!%] 4$ASymfony/Bridge/Twig/TokenParser/TransTokenParser.phpnu[PK!/ :mASymfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.phpnu[PK!>8ASymfony/Bridge/Twig/TokenParser/FormThemeTokenParser.phpnu[PK!ʶ̭A߼ASymfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.phpnu[PK!9=KK/ASymfony/Bridge/Twig/Extension/FormExtension.phpnu[PK!|/ASymfony/Bridge/Twig/Extension/YamlExtension.phpnu[PK!&a a 5 ASymfony/Bridge/Twig/Extension/HttpKernelExtension.phpnu[PK!KΙ5ASymfony/Bridge/Twig/Extension/ExpressionExtension.phpnu[PK!`fS..2=ASymfony/Bridge/Twig/Extension/RoutingExtension.phpnu[PK!5mm4ASymfony/Bridge/Twig/Extension/StopwatchExtension.phpnu[PK!? 6ASymfony/Bridge/Twig/Extension/TranslationExtension.phpnu[PK!doo3 BSymfony/Bridge/Twig/Extension/SecurityExtension.phpnu[PK! /BSymfony/Bridge/Twig/Extension/CodeExtension.phpnu[PK!^Ddd"0BSymfony/Bridge/Twig/TwigEngine.phpnu[PK!4˵(?BSymfony/Component/Finder/Shell/Shell.phpnu[PK!5K*vGBSymfony/Component/Finder/Shell/Command.phpnu[PK!59(h`BSymfony/Component/Finder/SplFileInfo.phpnu[PK!%uMPP'gBSymfony/Component/Finder/autoloader.phpnu[PK!99CoiBSymfony/Component/Finder/Exception/ShellCommandFailureException.phpnu[PK!79nBSymfony/Component/Finder/Exception/ExceptionInterface.phpnu[PK!cWޫ<spBSymfony/Component/Finder/Exception/AccessDeniedException.phpnu[PK!>@>rBSymfony/Component/Finder/Exception/AdapterFailureException.phpnu[PK!PDywBSymfony/Component/Finder/Exception/OperationNotPermitedException.phpnu[PK! 6yBSymfony/Component/Finder/Comparator/DateComparator.phpnu[PK!|Fz  2BSymfony/Component/Finder/Comparator/Comparator.phpnu[PK!P  8BSymfony/Component/Finder/Comparator/NumberComparator.phpnu[PK!g@Mb b !BSymfony/Component/Finder/Glob.phpnu[PK!dVV#UBSymfony/Component/Finder/Finder.phpnu[PK!ils_>BSymfony/Component/Finder/Iterator/DepthRangeFilterIterator.phpnu[PK!ɔ 7BSymfony/Component/Finder/Iterator/FilePathsIterator.phpnu[PK!,G4CSymfony/Component/Finder/Iterator/FilterIterator.phpnu[PK!ʽ? CSymfony/Component/Finder/Iterator/FilecontentFilterIterator.phpnu[PK! @CSymfony/Component/Finder/Iterator/MultiplePcreFilterIterator.phpnu[PK!z":LCSymfony/Component/Finder/Iterator/CustomFilterIterator.phpnu[PK!{^ǽ<"CSymfony/Component/Finder/Iterator/FilenameFilterIterator.phpnu[PK!dD)CSymfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.phpnu[PK!xP=/CSymfony/Component/Finder/Iterator/SizeRangeFilterIterator.phpnu[PK! U= 6CSymfony/Component/Finder/Iterator/DateRangeFilterIterator.phpnu[PK!n bb<+DSymfony/Component/Translation/Extractor/ExtractorInterface.phpnu[PK!b*0oo4 DSymfony/Component/Translation/PluralizationRules.phpnu[PK!qUU,%DSymfony/Component/Translation/autoloader.phpnu[PK!9DSymfony/Component/Translation/Catalogue/OperationInterface.phpnu[PK!fb =?DSymfony/Component/Translation/Catalogue/AbstractOperation.phpnu[PK!ӄ9MDSymfony/Component/Translation/Catalogue/DiffOperation.phpnu[PK!6">RDSymfony/Component/Translation/Exception/ExceptionInterface.phpnu[PK!DŽD6UDSymfony/Component/Translation/Exception/InvalidResourceException.phpnu[PK!2BEWDSymfony/Component/Translation/Exception/NotFoundResourceException.phpnu[PK!y42ZDSymfony/Component/Translation/MessageCatalogue.phpnu[PK!%Mt8sDSymfony/Component/Translation/MetadataAwareInterface.phpnu[PK!d<<4izDSymfony/Component/Translation/IdentityTranslator.phpnu[PK!eG, DSymfony/Component/Translation/Translator.phpnu[PK!֛;DSymfony/Component/Translation/MessageCatalogueInterface.phpnu[PK!M 9DSymfony/Component/Translation/Dumper/IcuResFileDumper.phpnu[PK!ਪ(5DSymfony/Component/Translation/Dumper/PoFileDumper.phpnu[PK!%LL6LDSymfony/Component/Translation/Dumper/PhpFileDumper.phpnu[PK!<̧8DSymfony/Component/Translation/Dumper/XliffFileDumper.phpnu[PK!>{GG5DSymfony/Component/Translation/Dumper/QtFileDumper.phpnu[PK!667DSymfony/Component/Translation/Dumper/YamlFileDumper.phpnu[PK!oB6gDSymfony/Component/Translation/Dumper/CsvFileDumper.phpnu[PK!B^[[3DSymfony/Component/Translation/Dumper/FileDumper.phpnu[PK!:$}}7XDSymfony/Component/Translation/Dumper/JsonFileDumper.phpnu[PK!&X6HSymfony/Component/Routing/Exception/RouteNotFoundException.phpnu[PK!): HSymfony/Component/Routing/Exception/ExceptionInterface.phpnu[PK!JJAHSymfony/Component/Routing/Exception/MethodNotAllowedException.phpnu[PK!?]//AֲHSymfony/Component/Routing/Exception/ResourceNotFoundException.phpnu[PK!^==#vHSymfony/Component/Routing/Route.phpnu[PK!r:HSymfony/Component/Routing/RequestContextAwareInterface.phpnu[PK!|,{Ȫ-HSymfony/Component/Routing/RouteCollection.phpnu[PK!h,ISymfony/Component/Routing/RequestContext.phpnu[PK!մIU-ISymfony/Component/Routing/Generator/ConfigurableRequirementsInterface.phpnu[PK! 1146ISymfony/Component/Routing/Generator/UrlGenerator.phpnu[PK!1O AhISymfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.phpnu[PK!u '>wISymfony/Component/Routing/Generator/Dumper/GeneratorDumper.phpnu[PK!4G+{ISymfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.phpnu[PK!@@=ISymfony/Component/Routing/Generator/UrlGeneratorInterface.phpnu[PK!nhh28ISymfony/Component/Routing/Loader/ClosureLoader.phpnu[PK!? >ISymfony/Component/Routing/Loader/AnnotationDirectoryLoader.phpnu[PK!~ޟ 9pISymfony/Component/Routing/Loader/AnnotationFileLoader.phpnu[PK!~LW:xISymfony/Component/Routing/Loader/AnnotationClassLoader.phpnu[PK!Pi{2nISymfony/Component/Routing/Loader/PhpFileLoader.phpnu[PK!?-[ ?ISymfony/Component/Routing/Loader/schema/routing/routing-1.0.xsdnu[PK!أ2D$D$2ISymfony/Component/Routing/Loader/XmlFileLoader.phpnu[PK!pBQ Q 3bISymfony/Component/Routing/Loader/YamlFileLoader.phpnu[PK!qF>>4JSymfony/Component/Routing/RouteCompilerInterface.phpnu[PK!0QQ("JSymfony/Component/Process/autoloader.phpnu[PK!g''*a$JSymfony/Component/Process/ProcessPipes.phpnu[PK!2{{@LJSymfony/Component/Process/Exception/ProcessTimedOutException.phpnu[PK!<:SJSymfony/Component/Process/Exception/ExceptionInterface.phpnu[PK!>H8UJSymfony/Component/Process/Exception/RuntimeException.phpnu[PK!W6WJSymfony/Component/Process/Exception/LogicException.phpnu[PK!˅@+ZJSymfony/Component/Process/Exception/InvalidArgumentException.phpnu[PK!_>\JSymfony/Component/Process/Exception/ProcessFailedException.phpnu[PK!@s(aJSymfony/Component/Process/PhpProcess.phpnu[PK!nL L *eiJSymfony/Component/Process/ProcessUtils.phpnu[PK!!,$  . sJSymfony/Component/Process/ExecutableFinder.phpnu[PK!!/,~}JSymfony/Component/Process/ProcessBuilder.phpnu[PK!y>81^JSymfony/Component/Process/PhpExecutableFinder.phpnu[PK!M%NJSymfony/Component/Process/Process.phpnu[PK![i55E*KSymfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.phpnu[PK!=Vxe::Al.KSymfony/Component/Serializer/Normalizer/NormalizableInterface.phpnu[PK!SVV<4KSymfony/Component/Serializer/Normalizer/CustomNormalizer.phpnu[PK! ,,B;KSymfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.phpnu[PK!"pyy?wZKSymfony/Component/Serializer/Normalizer/NormalizerInterface.phpnu[PK!qUC__KSymfony/Component/Serializer/Normalizer/DenormalizableInterface.phpnu[PK!A`eKSymfony/Component/Serializer/Normalizer/DenormalizerInterface.phpnu[PK!OO9jKSymfony/Component/Serializer/SerializerAwareInterface.phpnu[PK!TT+mKSymfony/Component/Serializer/autoloader.phpnu[PK!x蕰  4KoKSymfony/Component/Serializer/SerializerInterface.phpnu[PK!,c9sKSymfony/Component/Serializer/Encoder/EncoderInterface.phpnu[PK![553wKSymfony/Component/Serializer/Encoder/XmlEncoder.phpnu[PK!<=ggD/KSymfony/Component/Serializer/Encoder/NormalizationAwareInterface.phpnu[PK!VO5 KSymfony/Component/Serializer/Encoder/ChainDecoder.phpnu[PK!=?`KSymfony/Component/Serializer/Encoder/SerializerAwareEncoder.phpnu[PK!v:hh3˼KSymfony/Component/Serializer/Encoder/JsonEncode.phpnu[PK!@3KSymfony/Component/Serializer/Encoder/JsonDecode.phpnu[PK!S R 5KSymfony/Component/Serializer/Encoder/ChainEncoder.phpnu[PK! ovv4%KSymfony/Component/Serializer/Encoder/JsonEncoder.phpnu[PK!|ͼ9KSymfony/Component/Serializer/Encoder/DecoderInterface.phpnu[PK!AA 4)KSymfony/Component/Serializer/Exception/Exception.phpnu[PK!^L?KSymfony/Component/Serializer/Exception/UnsupportedException.phpnu[PK!h=;BKSymfony/Component/Serializer/Exception/RuntimeException.phpnu[PK!J9mKSymfony/Component/Serializer/Exception/LogicException.phpnu[PK!TYCKSymfony/Component/Serializer/Exception/InvalidArgumentException.phpnu[PK![CKSymfony/Component/Serializer/Exception/UnexpectedValueException.phpnu[PK!ʪ2 /&/&+"KSymfony/Component/Serializer/Serializer.phpnu[PK!FPPP'LSymfony/Component/Locale/autoloader.phpnu[PK!QUULSLSymfony/Component/Locale/Exception/MethodArgumentNotImplementedException.phpnu[PK! E>$#LSymfony/Component/Locale/Exception/NotImplementedException.phpnu[PK!S?a%%D&LSymfony/Component/Locale/Exception/MethodNotImplementedException.phpnu[PK!ssQ,*LSymfony/Component/Locale/Exception/MethodArgumentValueNotImplementedException.phpnu[PK!C* .LSymfony/Component/Locale/Stub/StubIntl.phpnu[PK!&51LSymfony/Component/Locale/Stub/StubNumberFormatter.phpnu[PK!v/@44LSymfony/Component/Locale/Stub/DateFormat/Hour2401Transformer.phpnu[PK!S@7LSymfony/Component/Locale/Stub/DateFormat/TimeZoneTransformer.phpnu[PK!} ""AL;LSymfony/Component/Locale/Stub/DateFormat/DayOfYearTransformer.phpnu[PK!X<>LSymfony/Component/Locale/Stub/DateFormat/AmPmTransformer.phpnu[PK!<OBLSymfony/Component/Locale/Stub/DateFormat/YearTransformer.phpnu[PK!mў?ELSymfony/Component/Locale/Stub/DateFormat/QuarterTransformer.phpnu[PK!g[ep>DILSymfony/Component/Locale/Stub/DateFormat/MinuteTransformer.phpnu[PK!:6""ALLSymfony/Component/Locale/Stub/DateFormat/DayOfWeekTransformer.phpnu[PK! 9u@UPLSymfony/Component/Locale/Stub/DateFormat/Hour1200Transformer.phpnu[PK!k&"M@SLSymfony/Component/Locale/Stub/DateFormat/Hour1201Transformer.phpnu[PK!;mWLSymfony/Component/Locale/Stub/DateFormat/DayTransformer.phpnu[PK!@ZLSymfony/Component/Locale/Stub/DateFormat/Hour2400Transformer.phpnu[PK!Ed8b^LSymfony/Component/Locale/Stub/DateFormat/Transformer.phpnu[PK!tz  =aLSymfony/Component/Locale/Stub/DateFormat/MonthTransformer.phpnu[PK!kH<6eLSymfony/Component/Locale/Stub/DateFormat/FullTransformer.phpnu[PK!3X>hLSymfony/Component/Locale/Stub/DateFormat/SecondTransformer.phpnu[PK!   <$lLSymfony/Component/Locale/Stub/DateFormat/HourTransformer.phpnu[PK!?.oLSymfony/Component/Locale/Stub/StubCollator.phpnu[PK!q*( ( ,{rLSymfony/Component/Locale/Stub/StubLocale.phpnu[PK! S7}LSymfony/Component/Locale/Stub/StubIntlDateFormatter.phpnu[PK!ll#1LSymfony/Component/Locale/Locale.phpnu[PK!tTT+#LSymfony/Component/Filesystem/autoloader.phpnu[PK!dP@җLSymfony/Component/Filesystem/Exception/FileNotFoundException.phpnu[PK!3{=LSymfony/Component/Filesystem/Exception/ExceptionInterface.phpnu[PK!oC~?-LSymfony/Component/Filesystem/Exception/IOExceptionInterface.phpnu[PK!;{6=LSymfony/Component/Filesystem/Exception/IOException.phpnu[PK!OظGG+WLSymfony/Component/Filesystem/Filesystem.phpnu[PK!)..'LSymfony/Component/Form/FormRenderer.phpnu[PK!C.MSymfony/Component/Form/ButtonTypeInterface.phpnu[PK!K'$&MSymfony/Component/Form/FormBuilder.phpnu[PK!&"̰TT,=MSymfony/Component/Form/FormConfigBuilder.phpnu[PK!E1'4MSymfony/Component/Form/SubmitButtonTypeInterface.phpnu[PK!d'XMSymfony/Component/Form/FormRegistry.phpnu[PK!ÊM'%%.@MSymfony/Component/Form/FormConfigInterface.phpnu[PK!@ @ /MSymfony/Component/Form/FormTypeGuesserChain.phpnu[PK!R+bMSymfony/Component/Form/Guess/ValueGuess.phpnu[PK!51 1 &MSymfony/Component/Form/Guess/Guess.phpnu[PK!  *#MSymfony/Component/Form/Guess/TypeGuess.phpnu[PK!0\ZZ.MSymfony/Component/Form/CallbackTransformer.phpnu[PK!4Nz"z"!UMSymfony/Component/Form/Button.phpnu[PK!-9NN% NSymfony/Component/Form/autoloader.phpnu[PK!/tt%NSymfony/Component/Form/FormEvents.phpnu[PK! ,NSymfony/Component/Form/FormTypeInterface.phpnu[PK!>0~"NSymfony/Component/Form/FormRegistryInterface.phpnu[PK!?zz3(NSymfony/Component/Form/FormTypeGuesserInterface.phpnu[PK!*+]1NSymfony/Component/Form/ResolvedFormType.phpnu[PK!ObXqq'ONSymfony/Component/Form/SubmitButton.phpnu[PK!p1nTNSymfony/Component/Form/AbstractRendererEngine.phpnu[PK!DjN,rNSymfony/Component/Form/AbstractExtension.phpnu[PK!f#jK6NSymfony/Component/Form/FormRendererEngineInterface.phpnu[PK!11NSymfony/Component/Form/Form.phpnu[PK!di;*OSymfony/Component/Form/Exception/BadMethodCallException.phpnu[PK!W  :,OSymfony/Component/Form/Exception/AlreadyBoundException.phpnu[PK!(ddB`/OSymfony/Component/Form/Exception/InvalidConfigurationException.phpnu[PK!_c==<61OSymfony/Component/Form/Exception/UnexpectedTypeException.phpnu[PK!SDB3OSymfony/Component/Form/Exception/TransformationFailedException.phpnu[PK!é96OSymfony/Component/Form/Exception/OutOfBoundsException.phpnu[PK!yu7i8OSymfony/Component/Form/Exception/ExceptionInterface.phpnu[PK!N5}:OSymfony/Component/Form/Exception/RuntimeException.phpnu[PK!K9>*ii&|OSymfony/Component/Form/FormFactory.phpnu[PK!\g2;OSymfony/Component/Form/RequestHandlerInterface.phpnu[PK!+qDAA79OSymfony/Component/Form/Test/FormPerformanceTestCase.phpnu[PK!sŪ,OSymfony/Component/Form/Test/TypeTestCase.phpnu[PK!,7//7EOSymfony/Component/Form/Test/DeprecationErrorHandler.phpnu[PK!B4I++7ۯOSymfony/Component/Form/Test/FormIntegrationTestCase.phpnu[PK!myy4mOSymfony/Component/Form/Test/FormBuilderInterface.phpnu[PK!a(0kk-JOSymfony/Component/Form/Test/FormInterface.phpnu[PK!n1OSymfony/Component/Form/FormExtensionInterface.phpnu[PK!|G 4OSymfony/Component/Form/ResolvedFormTypeInterface.phpnu[PK!{d!!5FOSymfony/Component/Form/FormConfigBuilderInterface.phpnu[PK!ɃT 6OSymfony/Component/Form/FormFactoryBuilderInterface.phpnu[PK!N̷;OSymfony/Component/Form/ResolvedFormTypeFactoryInterface.phpnu[PK!2-^OSymfony/Component/Form/FormFactoryBuilder.phpnu[PK!C0 PSymfony/Component/Form/AbstractTypeExtension.phpnu[PK!E 0PSymfony/Component/Form/FormRendererInterface.phpnu[PK!:  /DPSymfony/Component/Form/FormBuilderInterface.phpnu[PK!Z)/(PSymfony/Component/Form/FormFactoryInterface.phpnu[PK!YB.9PSymfony/Component/Form/ReversedTransformer.phpnu[PK!rW W 3>PSymfony/Component/Form/DataTransformerInterface.phpnu[PK!Wb[H[H(KPSymfony/Component/Form/ButtonBuilder.phpnu[PK!n?hPSymfony/Component/Form/Resources/translations/validators.en.xlfnu[PK!誫?PSymfony/Component/Form/Resources/translations/validators.sk.xlfnu[PK!<yy?PSymfony/Component/Form/Resources/translations/validators.uk.xlfnu[PK!:?PSymfony/Component/Form/Resources/translations/validators.pl.xlfnu[PK! ?˥PSymfony/Component/Form/Resources/translations/validators.pt.xlfnu[PK!%?PSymfony/Component/Form/Resources/translations/validators.lv.xlfnu[PK!္o33DcPSymfony/Component/Form/Resources/translations/validators.sr_Cyrl.xlfnu[PK!? PSymfony/Component/Form/Resources/translations/validators.fi.xlfnu[PK!0h?UPSymfony/Component/Form/Resources/translations/validators.es.xlfnu[PK!TI?PSymfony/Component/Form/Resources/translations/validators.de.xlfnu[PK!!aZ?PSymfony/Component/Form/Resources/translations/validators.it.xlfnu[PK! !?PSymfony/Component/Form/Resources/translations/validators.ca.xlfnu[PK!?KPSymfony/Component/Form/Resources/translations/validators.mn.xlfnu[PK!-?PSymfony/Component/Form/Resources/translations/validators.ru.xlfnu[PK!3Ե^^?PSymfony/Component/Form/Resources/translations/validators.bg.xlfnu[PK!Ed?PSymfony/Component/Form/Resources/translations/validators.ro.xlfnu[PK!O?PSymfony/Component/Form/Resources/translations/validators.nl.xlfnu[PK!S*?PSymfony/Component/Form/Resources/translations/validators.et.xlfnu[PK!V5?-PSymfony/Component/Form/Resources/translations/validators.fa.xlfnu[PK!q?PSymfony/Component/Form/Resources/translations/validators.id.xlfnu[PK! ?PSymfony/Component/Form/Resources/translations/validators.cs.xlfnu[PK!8,:B PSymfony/Component/Form/Resources/translations/validators.zh_CN.xlfnu[PK!Hq?PSymfony/Component/Form/Resources/translations/validators.lt.xlfnu[PK!_8?PSymfony/Component/Form/Resources/translations/validators.fr.xlfnu[PK!A4?dPSymfony/Component/Form/Resources/translations/validators.gl.xlfnu[PK! b8?QSymfony/Component/Form/Resources/translations/validators.hr.xlfnu[PK!WgUugg?QSymfony/Component/Form/Resources/translations/validators.nb.xlfnu[PK!ٻ||?QSymfony/Component/Form/Resources/translations/validators.eu.xlfnu[PK!4@B QSymfony/Component/Form/Resources/translations/validators.pt_BR.xlfnu[PK!5?QSymfony/Component/Form/Resources/translations/validators.sl.xlfnu[PK!*{?QSymfony/Component/Form/Resources/translations/validators.lb.xlfnu[PK!be@?IQSymfony/Component/Form/Resources/translations/validators.hu.xlfnu[PK!_Π?QSymfony/Component/Form/Resources/translations/validators.el.xlfnu[PK!X?x"QSymfony/Component/Form/Resources/translations/validators.da.xlfnu[PK!?h&QSymfony/Component/Form/Resources/translations/validators.ja.xlfnu[PK!s>ll?*QSymfony/Component/Form/Resources/translations/validators.sv.xlfnu[PK!y99?.QSymfony/Component/Form/Resources/translations/validators.hy.xlfnu[PK!|C?43QSymfony/Component/Form/Resources/translations/validators.ar.xlfnu[PK!rD7QSymfony/Component/Form/Resources/translations/validators.sr_Latn.xlfnu[PK!NP\?;QSymfony/Component/Form/Resources/translations/validators.he.xlfnu[PK!xfh..6?QSymfony/Component/Form/Resources/config/validation.xmlnu[PK!R}jj.hBQSymfony/Component/Form/DataMapperInterface.phpnu[PK!s (0GQSymfony/Component/Form/FormInterface.phpnu[PK!"$hQSymfony/Component/Form/FormEvent.phpnu[PK!=MM5CmQSymfony/Component/Form/FormTypeExtensionInterface.phpnu[PK!}p  $uQSymfony/Component/Form/FormError.phpnu[PK! /LQSymfony/Component/Form/NativeRequestHandler.phpnu[PK!*OQSymfony/Component/Form/Extension/Validator/EventListener/ValidationListener.phpnu[PK!Ck@QSymfony/Component/Form/Extension/Validator/Util/ServerParams.phpnu[PK!2=[<((AQSymfony/Component/Form/Extension/Validator/ValidatorExtension.phpnu[PK!}>ُ?:QSymfony/Component/Form/Extension/Validator/Constraints/Form.phpnu[PK!-PH8QSymfony/Component/Form/Extension/Validator/Constraints/FormValidator.phpnu[PK!lCt*t*CFQSymfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.phpnu[PK!ɥST-QSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu[PK!\TKqQSymfony/Component/Form/Extension/Validator/ViolationMapper/RelativePath.phpnu[PK!C_hU+U+NQSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.phpnu[PK!kt==Wa*RSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu[PK!-!!L%/RSymfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.phpnu[PK!f JHRSymfony/Component/Form/Extension/Validator/ViolationMapper/MappingRule.phpnu[PK!JSRSymfony/Component/Form/Extension/Validator/Type/BaseValidatorExtension.phpnu[PK!eBR NEZRSymfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.phpnu[PK!͚>@@RdRSymfony/Component/Form/Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu[PK!1P]iRSymfony/Component/Form/Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu[PK!,QQCkRSymfony/Component/Form/Extension/Templating/TemplatingExtension.phpnu[PK!զYHrRSymfony/Component/Form/Extension/Templating/TemplatingRendererEngine.phpnu[PK!䋧 U'RSymfony/Component/Form/Extension/HttpFoundation/EventListener/BindRequestListener.phpnu[PK!j= = PDRSymfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu[PK!QKRSymfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.phpnu[PK!PffX"RSymfony/Component/Form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu[PK!"q7RSymfony/Component/Form/Extension/Csrf/CsrfExtension.phpnu[PK!CJ;RSymfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu[PK![^JiRSymfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu[PK!%GLwRSymfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu[PK!JRSymfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu[PK!R'WTTNRSymfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu[PK!?ooNRSymfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.phpnu[PK! fDRSymfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.phpnu[PK!CW7+RSymfony/Component/Form/Extension/Core/CoreExtension.phpnu[PK!:AADkRSymfony/Component/Form/Extension/Core/EventListener/TrimListener.phpnu[PK!õeO SSymfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.phpnu[PK!>Q?N1SSymfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.phpnu[PK!b PFSSymfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.phpnu[PK!\//JP'SSymfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.phpnu[PK!?DM:SSymfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.phpnu[PK!jюEPDSSymfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.phpnu[PK! ##EaZSSymfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.phpnu[PK!l_R(HxSSymfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.phpnu[PK!В4 4 CwSSymfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.phpnu[PK!'ç???SSymfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.phpnu[PK!&PP9#SSymfony/Component/Form/Extension/Core/View/ChoiceView.phpnu[PK!  GSSymfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.phpnu[PK!O###\bSSymfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu[PK!)b""^TSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu[PK!e^  V0)TSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu[PK!Þ X2TSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu[PK!c8V N=TSymfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.phpnu[PK!;dd]GTSymfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu[PK!Ze  TXTSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu[PK!Lpx&&YwsTSymfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu[PK!  V&TSymfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu[PK!'tqk55ZTSymfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu[PK!ggTyTSymfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu[PK!Udq]dTSymfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu[PK!ΎgW UTSymfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu[PK!"hRTSymfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu[PK!H  Q/TSymfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu[PK!/CQTSymfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu[PK!TT"TSymfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu[PK!]yD D [TSymfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu[PK!/++9nTSymfony/Component/Form/Extension/Core/Type/ChoiceType.phpnu[PK!h9{#USymfony/Component/Form/Extension/Core/Type/ButtonType.phpnu[PK!DU9'USymfony/Component/Form/Extension/Core/Type/SubmitType.phpnu[PK!񍢸;),USymfony/Component/Form/Extension/Core/Type/CurrencyType.phpnu[PK!Ѝ'9;0USymfony/Component/Form/Extension/Core/Type/HiddenType.phpnu[PK!D9N4USymfony/Component/Form/Extension/Core/Type/LocaleType.phpnu[PK!uƵ``:{8USymfony/Component/Form/Extension/Core/Type/IntegerType.phpnu[PK!a8EAUSymfony/Component/Form/Extension/Core/Type/ResetType.phpnu[PK!옇;DUSymfony/Component/Form/Extension/Core/Type/PasswordType.phpnu[PK!ٝGG7IUSymfony/Component/Form/Extension/Core/Type/BaseType.phpnu[PK!Z^^:{[USymfony/Component/Form/Extension/Core/Type/PercentType.phpnu[PK!TT;CaUSymfony/Component/Form/Extension/Core/Type/CheckboxType.phpnu[PK!&ߏvv;jUSymfony/Component/Form/Extension/Core/Type/BirthdayType.phpnu[PK!7pOLL8mUSymfony/Component/Form/Extension/Core/Type/RadioType.phpnu[PK!Goo7pUSymfony/Component/Form/Extension/Core/Type/FileType.phpnu[PK!8JJ9mvUSymfony/Component/Form/Extension/Core/Type/SearchType.phpnu[PK!_LL; yUSymfony/Component/Form/Extension/Core/Type/TimezoneType.phpnu[PK!HH8ׁUSymfony/Component/Form/Extension/Core/Type/EmailType.phpnu[PK![Gԃ =USymfony/Component/Form/Extension/Core/Type/CollectionType.phpnu[PK!tII;USymfony/Component/Form/Extension/Core/Type/TextareaType.phpnu[PK!;UUSymfony/Component/Form/Extension/Core/Type/LanguageType.phpnu[PK!T;7gUSymfony/Component/Form/Extension/Core/Type/TextType.phpnu[PK!H?!a7USymfony/Component/Form/Extension/Core/Type/TimeType.phpnu[PK! &'';USymfony/Component/Form/Extension/Core/Type/DateTimeType.phpnu[PK!q6USymfony/Component/Form/Extension/Core/Type/UrlType.phpnu[PK!9;3XSymfony/Component/Security/Acl/Domain/UserSecurityIdentity.phpnu[PK!C3:{@XSymfony/Component/Security/Acl/Domain/DoctrineAclCache.phpnu[PK!(]DYXSymfony/Component/Security/Acl/Domain/PermissionGrantingStrategy.phpnu[PK!%}`M`M-wXSymfony/Component/Security/Acl/Domain/Acl.phpnu[PK! KXSymfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.phpnu[PK!X / / <XSymfony/Component/Security/Acl/Domain/AclCollectionCache.phpnu[PK!5D[/VXSymfony/Component/Security/Acl/Domain/Entry.phpnu[PK!pU4XSymfony/Component/Security/Acl/Domain/FieldEntry.phpnu[PK!^@.Y Y 8XSymfony/Component/Security/Acl/Domain/ObjectIdentity.phpnu[PK!0FIYSymfony/Component/Security/Acl/Domain/ObjectIdentityRetrievalStrategy.phpnu[PK!tA)==>YSymfony/Component/Security/Acl/Domain/RoleSecurityIdentity.phpnu[PK!#~~<e YSymfony/Component/Security/Acl/Resources/bin/generateSql.phpnu[PK!j~ cF F 7OYSymfony/Component/Security/Acl/Resources/schema/db2.sqlnu[PK!Tsk k >!YSymfony/Component/Security/Acl/Resources/schema/postgresql.sqlnu[PK!Jx.  9.YSymfony/Component/Security/Acl/Resources/schema/mssql.sqlnu[PK!fZ^ ^ 9TDYSymfony/Component/Security/Acl/Model/DomainObjectInterface.phpnu[PK!5Ayy@zYSymfony/Component/Security/Acl/Model/ObjectIdentityInterface.phpnu[PK!t @cYSymfony/Component/Security/Acl/Model/AuditableEntryInterface.phpnu[PK!-癥LYSymfony/Component/Security/Acl/Model/PermissionGrantingStrategyInterface.phpnu[PK!=@YSymfony/Component/Security/Acl/Model/AclProviderInterface.phpnu[PK!#:YSymfony/Component/Security/Acl/Model/AclCacheInterface.phpnu[PK!ӗ&1>YSymfony/Component/Security/Acl/Model/AuditableAclInterface.phpnu[PK!ݤUU<YSymfony/Component/Security/Acl/Model/FieldEntryInterface.phpnu[PK! 8FF7FYSymfony/Component/Security/Acl/Model/EntryInterface.phpnu[PK!H }ZSymfony/Component/Security/Http/Firewall/ListenerInterface.phpnu[PK!|L@**;%ZSymfony/Component/Security/Http/Firewall/LogoutListener.phpnu[PK!B b  ?ZSymfony/Component/Security/Http/Firewall/SwitchUserListener.phpnu[PK!(T b!b!>3ZSymfony/Component/Security/Http/Firewall/ExceptionListener.phpnu[PK!׺=GZSymfony/Component/Security/Http/Firewall/X509AuthenticationListener.phpnu[PK!׿ͼ IUZSymfony/Component/Security/Http/Firewall/DigestAuthenticationListener.phpnu[PK!~k<ZSymfony/Component/Security/Http/Firewall/ChannelListener.phpnu[PK! 6'6'K[Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.phpnu[PK!"?<*[Symfony/Component/Security/Http/Firewall/ContextListener.phpnu[PK!MB[Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.phpnu[PK!+/Z Z ;[[Symfony/Component/Security/Http/Firewall/AccessListener.phpnu[PK!ZMd[Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.phpnu[PK!nLw[Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.phpnu[PK!&! H[Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.phpnu[PK!2j-[Symfony/Component/Security/Http/AccessMap.phpnu[PK!/``6[Symfony/Component/Security/Http/AccessMapInterface.phpnu[PK!\\8[Symfony/Component/Security/Http/FirewallMapInterface.phpnu[PK! z J[Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.phpnu[PK!Pڕ?9[Symfony/Component/Security/Http/RememberMe/ResponseListener.phpnu[PK!s44U[Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.phpnu[PK!*b&&I8[Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.phpnu[PK!a$K[Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.phpnu[PK!:&GGR\Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.phpnu[PK!La[[IZ \Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.phpnu[PK!a7llF.\Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.phpnu[PK!1dH\Symfony/Component/Security/Http/Logout/LogoutSuccessHandlerInterface.phpnu[PK!\ü?m\Symfony/Component/Security/Http/Logout/SessionLogoutHandler.phpnu[PK!6OA \Symfony/Component/Security/Http/Logout/LogoutHandlerInterface.phpnu[PK!ddF%\Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.phpnu[PK!/ sG2*\Symfony/Component/Security/Http/SecurityEvents.phpnu[PK!NAXB/\Symfony/Component/Security/Http/Authentication/AuthenticationSuccessHandlerInterface.phpnu[PK! V4\Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.phpnu[PK!H]  XA\Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.phpnu[PK!xGA A VG\Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.phpnu[PK!AH\ݞNUT\Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.phpnu[PK!D9qe\Symfony/Component/Security/Http/Event/SwitchUserEvent.phpnu[PK!Zv}?i\Symfony/Component/Security/Http/Event/InteractiveLoginEvent.phpnu[PK!VǴ=o\Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.phpnu[PK!&%L L 4w\Symfony/Component/Security/Csrf/CsrfTokenManager.phpnu[PK! J\Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.phpnu[PK!Fލ\Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.phpnu[PK!]N N D\Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.phpnu[PK!eID\Symfony/Component/Security/Csrf/Exception/TokenNotFoundException.phpnu[PK! =H\Symfony/Component/Security/Csrf/TokenGenerator/UriSafeTokenGenerator.phpnu[PK!J,pJx\Symfony/Component/Security/Csrf/TokenGenerator/TokenGeneratorInterface.phpnu[PK!O-\Symfony/Component/Security/Csrf/CsrfToken.phpnu[PK!S<\Symfony/Component/Security/Core/SecurityContextInterface.phpnu[PK!}ww?\Symfony/Component/Security/Core/Role/RoleHierarchyInterface.phpnu[PK! w??6ݼ\Symfony/Component/Security/Core/Role/RoleHierarchy.phpnu[PK!Ħ-\Symfony/Component/Security/Core/Role/Role.phpnu[PK!XS007\Symfony/Component/Security/Core/Role/SwitchUserRole.phpnu[PK!'c6{\Symfony/Component/Security/Core/Role/RoleInterface.phpnu[PK!E Dp\Symfony/Component/Security/Core/Encoder/PasswordEncoderInterface.phpnu[PK!Æ A\Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.phpnu[PK!^HM\Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.phpnu[PK!,>"DO\Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.phpnu[PK!;D:\Symfony/Component/Security/Core/Encoder/EncoderFactory.phpnu[PK!!@  A\Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.phpnu[PK!#MMqqC]Symfony/Component/Security/Core/Encoder/EncoderFactoryInterface.phpnu[PK!7 ?]Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.phpnu[PK! 77O#]Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.phpnu[PK!iF]Symfony/Component/Security/Core/Validator/Constraints/UserPassword.phpnu[PK!ΕE]Symfony/Component/Security/Core/Exception/BadCredentialsException.phpnu[PK!zz= ]Symfony/Component/Security/Core/Exception/LockedException.phpnu[PK!bM<<F#]Symfony/Component/Security/Core/Exception/UnsupportedUserException.phpnu[PK!z&I&]Symfony/Component/Security/Core/Exception/CredentialsExpiredException.phpnu[PK!Xss=)]Symfony/Component/Security/Core/Exception/LogoutException.phpnu[PK! 04}}G,]Symfony/Component/Security/Core/Exception/UsernameNotFoundException.phpnu[PK!#q44Q}2]Symfony/Component/Security/Core/Exception/InsufficientAuthenticationException.phpnu[PK!5]I26]Symfony/Component/Security/Core/Exception/SessionUnavailableException.phpnu[PK!D9D3:]Symfony/Component/Security/Core/Exception/TokenNotFoundException.phpnu[PK!hcB8=]Symfony/Component/Security/Core/Exception/CookieTheftException.phpnu[PK!A@@]Symfony/Component/Security/Core/Exception/ExceptionInterface.phpnu[PK!qUSąCB]Symfony/Component/Security/Core/Exception/AccessDeniedException.phpnu[PK!'EE]Symfony/Component/Security/Core/Exception/AuthenticationException.phpnu[PK! >HM]Symfony/Component/Security/Core/Exception/RuntimeException.phpnu[PK!@ GO]Symfony/Component/Security/Core/Exception/ProviderNotFoundException.phpnu[PK!ĸXS]Symfony/Component/Security/Core/Exception/AuthenticationCredentialsNotFoundException.phpnu[PK!:AADV]Symfony/Component/Security/Core/Exception/AccountStatusException.phpnu[PK!7w-L@\]Symfony/Component/Security/Core/Exception/AuthenticationServiceException.phpnu[PK!xBE_]Symfony/Component/Security/Core/Exception/AccountExpiredException.phpnu[PK!և?b]Symfony/Component/Security/Core/Exception/DisabledException.phpnu[PK!eCe]Symfony/Component/Security/Core/Exception/NonceExpiredException.phpnu[PK!ʝ9Fh]Symfony/Component/Security/Core/Exception/InvalidArgumentException.phpnu[PK!OGWk]Symfony/Component/Security/Core/Exception/InvalidCsrfTokenException.phpnu[PK!Õ  5Yn]Symfony/Component/Security/Core/Util/SecureRandom.phpnu[PK!Ua4{]Symfony/Component/Security/Core/Util/StringUtils.phpnu[PK!T,,3]Symfony/Component/Security/Core/Util/ClassUtils.phpnu[PK! >]Symfony/Component/Security/Core/Util/SecureRandomInterface.phpnu[PK!m2G]Symfony/Component/Security/Core/Authorization/AccessDecisionManager.phpnu[PK!З~Aۤ]Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.phpnu[PK!~fJ5]Symfony/Component/Security/Core/Authorization/Voter/RoleHierarchyVoter.phpnu[PK!`c GͰ]Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.phpnu[PK!X,m  J]Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.phpnu[PK!>F]Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.phpnu[PK!:22P]Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.phpnu[PK!ѵ^D\]Symfony/Component/Security/Core/Authorization/ExpressionLanguage.phpnu[PK!=f]Symfony/Component/Security/Core/User/UserCheckerInterface.phpnu[PK!^ :X]Symfony/Component/Security/Core/User/ChainUserProvider.phpnu[PK!D$..4]Symfony/Component/Security/Core/User/UserChecker.phpnu[PK!6bY Y >t]Symfony/Component/Security/Core/User/AdvancedUserInterface.phpnu[PK! 6;^Symfony/Component/Security/Core/User/UserInterface.phpnu[PK!/!  =L ^Symfony/Component/Security/Core/User/InMemoryUserProvider.phpnu[PK!//;^Symfony/Component/Security/Core/User/EquatableInterface.phpnu[PK!svW W >g^Symfony/Component/Security/Core/User/UserProviderInterface.phpnu[PK!1G G -,'^Symfony/Component/Security/Core/User/User.phpnu[PK!'za! ! 30^Symfony/Component/Security/Core/SecurityContext.phpnu[PK!l8T<^Symfony/Component/Security/Core/AuthenticationEvents.phpnu[PK!x$ccP@^Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.phpnu[PK!¬> ##RO^Symfony/Component/Security/Core/Authentication/SimplePreAuthenticatorInterface.phpnu[PK!WOGR^Symfony/Component/Security/Core/Authentication/SimpleAuthenticatorInterface.phpnu[PK!>,vvXU^Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.phpnu[PK!U\^Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.phpnu[PK!byyV6l^Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.phpnu[PK!JA\5^Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.phpnu[PK!X[^Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.phpnu[PK!a""[ҏ^Symfony/Component/Security/Core/Authentication/Provider/AuthenticationProviderInterface.phpnu[PK!un\ b^Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.phpnu[PK!r3WWW^Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolverInterface.phpnu[PK!ZvmS^Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.phpnu[PK!QZZV^Symfony/Component/Security/Core/Authentication/RememberMe/PersistentTokenInterface.phpnu[PK! TOM^Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.phpnu[PK! CfT^Symfony/Component/Security/Core/Authentication/RememberMe/TokenProviderInterface.phpnu[PK!J-W;::S)^Symfony/Component/Security/Core/Authentication/SimpleFormAuthenticatorInterface.phpnu[PK!:6N^Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.phpnu[PK!f Q^Symfony/Component/Security/Core/Authentication/AuthenticationManagerInterface.phpnu[PK!γ__N^Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.phpnu[PK!4Fg^Symfony/Component/Security/Core/Authentication/Token/AbstractToken.phpnu[PK!tC G^Symfony/Component/Security/Core/Authentication/Token/TokenInterface.phpnu[PK!{Z--G_Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.phpnu[PK!6` ` N_Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.phpnu[PK!w Ht_Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.phpnu[PK!m|JJKn_Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlfnu[PK!&MЎ F3-_Symfony/Component/Security/Core/Resources/translations/security.es.xlfnu[PK!M-@Fl;_Symfony/Component/Security/Core/Resources/translations/security.fa.xlfnu[PK!de FJ_Symfony/Component/Security/Core/Resources/translations/security.fr.xlfnu[PK!) F:Y_Symfony/Component/Security/Core/Resources/translations/security.ro.xlfnu[PK!y F=g_Symfony/Component/Security/Core/Resources/translations/security.gl.xlfnu[PK!u^ ^ FRu_Symfony/Component/Security/Core/Resources/translations/security.sv.xlfnu[PK!ţ F&_Symfony/Component/Security/Core/Resources/translations/security.ca.xlfnu[PK!o'N F?_Symfony/Component/Security/Core/Resources/translations/security.de.xlfnu[PK!.W F}_Symfony/Component/Security/Core/Resources/translations/security.no.xlfnu[PK!ق Fx_Symfony/Component/Security/Core/Resources/translations/security.sk.xlfnu[PK!w=Fp_Symfony/Component/Security/Core/Resources/translations/security.ru.xlfnu[PK!UɎd d F_Symfony/Component/Security/Core/Resources/translations/security.sl.xlfnu[PK! F}_Symfony/Component/Security/Core/Resources/translations/security.lb.xlfnu[PK!#@y y I_Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlfnu[PK!YWg g K_Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlfnu[PK!= I`Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlfnu[PK! ( F`Symfony/Component/Security/Core/Resources/translations/security.cs.xlfnu[PK!O F`Symfony/Component/Security/Core/Resources/translations/security.it.xlfnu[PK!TkfF-`Symfony/Component/Security/Core/Resources/translations/security.ar.xlfnu[PK!|H F<`Symfony/Component/Security/Core/Resources/translations/security.hu.xlfnu[PK!pU FJ`Symfony/Component/Security/Core/Resources/translations/security.nl.xlfnu[PK!'{ { F,Y`Symfony/Component/Security/Core/Resources/translations/security.tr.xlfnu[PK!UFg`Symfony/Component/Security/Core/Resources/translations/security.el.xlfnu[PK!.X: : Fuw`Symfony/Component/Security/Core/Resources/translations/security.en.xlfnu[PK!d F%`Symfony/Component/Security/Core/Resources/translations/security.pl.xlfnu[PK!5˙F!`Symfony/Component/Security/Core/Resources/translations/security.ua.xlfnu[PK!z J J F`Symfony/Component/Security/Core/Resources/translations/security.da.xlfnu[PK!EhDڰ`Symfony/Component/Security/Core/Event/AuthenticationFailureEvent.phpnu[PK!+\ //=`Symfony/Component/Security/Core/Event/AuthenticationEvent.phpnu[PK!(SSA`Symfony/Component/Security/Resources/translations/security.bg.xlfnu[PK!m|JJF``Symfony/Component/Security/Resources/translations/security.sr_Cyrl.xlfnu[PK!&MЎ A `Symfony/Component/Security/Resources/translations/security.es.xlfnu[PK!M-@AT`Symfony/Component/Security/Resources/translations/security.fa.xlfnu[PK!A`Symfony/Component/Security/Resources/translations/security.vi.xlfnu[PK!de AdaSymfony/Component/Security/Resources/translations/security.fr.xlfnu[PK!) AaSymfony/Component/Security/Resources/translations/security.ro.xlfnu[PK!y A aSymfony/Component/Security/Resources/translations/security.gl.xlfnu[PK!u^ ^ A.aSymfony/Component/Security/Resources/translations/security.sv.xlfnu[PK!ţ A{%bSymfony/Component/Validator/GroupSequenceProviderInterface.phpnu[PK!d)cSymfony/Component/Validator/Validator.phpnu[PK!&{{9ZcSymfony/Component/Validator/ValidatorBuilderInterface.phpnu[PK!oSS*>2cSymfony/Component/Validator/autoloader.phpnu[PK!C0C093cSymfony/Component/Validator/ExecutionContextInterface.phpnu[PK!}`9dcSymfony/Component/Validator/PropertyMetadataInterface.phpnu[PK!޽/!/!0icSymfony/Component/Validator/ExecutionContext.phpnu[PK!+s:ycSymfony/Component/Validator/ConstraintValidatorFactory.phpnu[PK!SqK K 1ܔcSymfony/Component/Validator/MetadataInterface.phpnu[PK!R'<cSymfony/Component/Validator/ConstraintViolationInterface.phpnu[PK!ƭW*cSymfony/Component/Validator/Constraint.phpnu[PK!|6cSymfony/Component/Validator/Mapping/GetterMetadata.phpnu[PK! r 8(cSymfony/Component/Validator/Mapping/PropertyMetadata.phpnu[PK!t././5TcSymfony/Component/Validator/Mapping/ClassMetadata.phpnu[PK!!" " 7dSymfony/Component/Validator/Mapping/ElementMetadata.phpnu[PK!/;aa6pdSymfony/Component/Validator/Mapping/MemberMetadata.phpnu[PK!+d%%<7*dSymfony/Component/Validator/Mapping/Cache/CacheInterface.phpnu[PK!6.dSymfony/Component/Validator/Mapping/Cache/ApcCache.phpnu[PK!d#[N <3dSymfony/Component/Validator/Mapping/ClassMetadataFactory.phpnu[PK!ʚ9@dSymfony/Component/Validator/Mapping/Loader/FileLoader.phpnu[PK!kG+=ZEdSymfony/Component/Validator/Mapping/Loader/AbstractLoader.phpnu[PK!Rᠯ=MdSymfony/Component/Validator/Mapping/Loader/XmlFilesLoader.phpnu[PK!?>PdSymfony/Component/Validator/Mapping/Loader/YamlFilesLoader.phpnu[PK!:wSdSymfony/Component/Validator/Mapping/Loader/LoaderChain.phpnu[PK!TbAZdSymfony/Component/Validator/Mapping/Loader/StaticMethodLoader.phpnu[PK!>??>`dSymfony/Component/Validator/Mapping/Loader/LoaderInterface.phpnu[PK!*:cdSymfony/Component/Validator/Mapping/Loader/FilesLoader.phpnu[PK!TO--cidSymfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsdnu[PK!;QF11<YdSymfony/Component/Validator/Mapping/Loader/XmlFileLoader.phpnu[PK! lw#Q Q ?dSymfony/Component/Validator/Mapping/Loader/AnnotationLoader.phpnu[PK!'pkk=dSymfony/Component/Validator/Mapping/Loader/YamlFileLoader.phpnu[PK!۔@dSymfony/Component/Validator/Mapping/BlackholeMetadataFactory.phpnu[PK!L8 :dSymfony/Component/Validator/ValidationVisitorInterface.phpnu[PK!QVV:dSymfony/Component/Validator/Exception/MappingException.phpnu[PK!y@dSymfony/Component/Validator/Exception/BadMethodCallException.phpnu[PK!LЉRRAdSymfony/Component/Validator/Exception/InvalidOptionsException.phpnu[PK!k1+WW<dSymfony/Component/Validator/Exception/ValidatorException.phpnu[PK!b<<AdSymfony/Component/Validator/Exception/UnexpectedTypeException.phpnu[PK!1"ccG6dSymfony/Component/Validator/Exception/ConstraintDefinitionException.phpnu[PK!T<dSymfony/Component/Validator/Exception/ExceptionInterface.phpnu[PK!z:3dSymfony/Component/Validator/Exception/RuntimeException.phpnu[PK!xAdSymfony/Component/Validator/Exception/NoSuchMetadataException.phpnu[PK!uRRAdSymfony/Component/Validator/Exception/MissingOptionsException.phpnu[PK!M#^^BPdSymfony/Component/Validator/Exception/GroupDefinitionException.phpnu[PK!\B dSymfony/Component/Validator/Exception/InvalidArgumentException.phpnu[PK!U<<3dSymfony/Component/Validator/ClassBasedInterface.phpnu[PK!;5t 70dSymfony/Component/Validator/ConstraintViolationList.phpnu[PK!AbI̲1DdSymfony/Component/Validator/ValidationVisitor.phpnu[PK!bhBWeSymfony/Component/Validator/PropertyMetadataContainerInterface.phpnu[PK!Y8eSymfony/Component/Validator/MetadataFactoryInterface.phpnu[PK!D#??DeSymfony/Component/Validator/Resources/translations/validators.en.xlfnu[PK!-uCuCDWeSymfony/Component/Validator/Resources/translations/validators.sk.xlfnu[PK!τ}K}KDeSymfony/Component/Validator/Resources/translations/validators.uk.xlfnu[PK!-11DeSymfony/Component/Validator/Resources/translations/validators.cy.xlfnu[PK!mwBBDfSymfony/Component/Validator/Resources/translations/validators.pl.xlfnu[PK!@T\44D<]fSymfony/Component/Validator/Resources/translations/validators.af.xlfnu[PK!b@@DfSymfony/Component/Validator/Resources/translations/validators.pt.xlfnu[PK!e]߭AAIfSymfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlfnu[PK!a22DgSymfony/Component/Validator/Resources/translations/validators.fi.xlfnu[PK!"}2A2ADHgSymfony/Component/Validator/Resources/translations/validators.es.xlfnu[PK!sE#AADgSymfony/Component/Validator/Resources/translations/validators.de.xlfnu[PK!=^::DgSymfony/Component/Validator/Resources/translations/validators.it.xlfnu[PK! AADphSymfony/Component/Validator/Resources/translations/validators.ca.xlfnu[PK!D#"#"DGhSymfony/Component/Validator/Resources/translations/validators.mn.xlfnu[PK!-tZMZMDjhSymfony/Component/Validator/Resources/translations/validators.ru.xlfnu[PK!L>D[ jSymfony/Component/Validator/Resources/translations/validators.id.xlfnu[PK!˺Q1Q1DKjSymfony/Component/Validator/Resources/translations/validators.tr.xlfnu[PK! )BBD|jSymfony/Component/Validator/Resources/translations/validators.cs.xlfnu[PK!6%=%=GjSymfony/Component/Validator/Resources/translations/validators.zh_CN.xlfnu[PK!PhBhBDjSymfony/Component/Validator/Resources/translations/validators.lt.xlfnu[PK!+ B BD@kSymfony/Component/Validator/Resources/translations/validators.fr.xlfnu[PK!(=A=AD kSymfony/Component/Validator/Resources/translations/validators.gl.xlfnu[PK!wX@X@DkSymfony/Component/Validator/Resources/translations/validators.hr.xlfnu[PK!Y.355DlSymfony/Component/Validator/Resources/translations/validators.sq.xlfnu[PK!(eeD;lSymfony/Component/Validator/Resources/translations/validators.nb.xlfnu[PK!tAAD|[lSymfony/Component/Validator/Resources/translations/validators.eu.xlfnu[PK!1ar==GѝlSymfony/Component/Validator/Resources/translations/validators.zh_TW.xlfnu[PK!Tл@@GXlSymfony/Component/Validator/Resources/translations/validators.pt_BR.xlfnu[PK!11DmSymfony/Component/Validator/Resources/translations/validators.no.xlfnu[PK!nCCDNmSymfony/Component/Validator/Resources/translations/validators.sl.xlfnu[PK!qb??DmSymfony/Component/Validator/Resources/translations/validators.lb.xlfnu[PK!93XaoAoADmSymfony/Component/Validator/Resources/translations/validators.hu.xlfnu[PK!MMDpnSymfony/Component/Validator/Resources/translations/validators.el.xlfnu[PK!9>55DcnSymfony/Component/Validator/Resources/translations/validators.da.xlfnu[PK!AAD nSymfony/Component/Validator/Resources/translations/validators.ja.xlfnu[PK!Q>??DnSymfony/Component/Validator/Resources/translations/validators.sv.xlfnu[PK!v_w,w,DoSymfony/Component/Validator/Resources/translations/validators.hy.xlfnu[PK!OODuHoSymfony/Component/Validator/Resources/translations/validators.ar.xlfnu[PK!1^44IoSymfony/Component/Validator/Resources/translations/validators.sr_Latn.xlfnu[PK!@T'%BBDoSymfony/Component/Validator/Resources/translations/validators.vi.xlfnu[PK!tý55DpSymfony/Component/Validator/Resources/translations/validators.he.xlfnu[PK!D<NGpSymfony/Component/Validator/Constraints/NotNullValidator.phpnu[PK!D~SS2JpSymfony/Component/Validator/Constraints/Choice.phpnu[PK!~%ɋ1GOpSymfony/Component/Validator/Constraints/Valid.phpnu[PK!+ 63SpSymfony/Component/Validator/Constraints/NotEqualTo.phpnu[PK!mԼ\\CUpSymfony/Component/Validator/Constraints/NotIdenticalToValidator.phpnu[PK!Ŀ:KK6XXpSymfony/Component/Validator/Constraints/Expression.phpnu[PK!خ zz? ]pSymfony/Component/Validator/Constraints/Collection/Optional.phpnu[PK!\,yzz?_pSymfony/Component/Validator/Constraints/Collection/Required.phpnu[PK! n?bpSymfony/Component/Validator/Constraints/CollectionValidator.phpnu[PK! y:kpSymfony/Component/Validator/Constraints/BlankValidator.phpnu[PK!+0HopSymfony/Component/Validator/Constraints/Iban.phpnu[PK! =qpSymfony/Component/Validator/Constraints/CallbackValidator.phpnu[PK!}&&2{pSymfony/Component/Validator/Constraints/Length.phpnu[PK!b=n n 9-pSymfony/Component/Validator/Constraints/IsbnValidator.phpnu[PK! i//5GpSymfony/Component/Validator/Constraints/Existence.phpnu[PK!tUה4pSymfony/Component/Validator/Constraints/Required.phpnu[PK!m\\>pSymfony/Component/Validator/Constraints/AbstractComparison.phpnu[PK!cy  4pSymfony/Component/Validator/Constraints/DateTime.phpnu[PK!l˘ 7 pSymfony/Component/Validator/Constraints/IpValidator.phpnu[PK!\\=qSymfony/Component/Validator/Constraints/LessThanValidator.phpnu[PK!U4 qSymfony/Component/Validator/Constraints/NotBlank.phpnu[PK!<8S:3 qSymfony/Component/Validator/Constraints/ImageValidator.phpnu[PK!Lֻ6,#qSymfony/Component/Validator/Constraints/CardScheme.phpnu[PK!"?M&qSymfony/Component/Validator/Constraints/CardSchemeValidator.phpnu[PK!N306qSymfony/Component/Validator/Constraints/Type.phpnu[PK!@vqq9:qSymfony/Component/Validator/Constraints/FileValidator.phpnu[PK!'1RqSymfony/Component/Validator/Constraints/Count.phpnu[PK!̢VV@(YqSymfony/Component/Validator/Constraints/IdenticalToValidator.phpnu[PK!dXBB0[qSymfony/Component/Validator/Constraints/Issn.phpnu[PK!ଏA^qSymfony/Component/Validator/Constraints/GroupSequenceProvider.phpnu[PK!}a7`qSymfony/Component/Validator/Constraints/GreaterThan.phpnu[PK!Ǧ3bqSymfony/Component/Validator/Constraints/EqualTo.phpnu[PK!b+94eqSymfony/Component/Validator/Constraints/LuhnValidator.phpnu[PK!ٜ?05mqSymfony/Component/Validator/Constraints/True.phpnu[PK!?GoqSymfony/Component/Validator/Constraints/AbstractComparisonValidator.phpnu[PK!̋ 1xqSymfony/Component/Validator/Constraints/Regex.phpnu[PK!BB1ՂqSymfony/Component/Validator/Constraints/Range.phpnu[PK![A;xqSymfony/Component/Validator/Constraints/LessThanOrEqual.phpnu[PK!q;O3qSymfony/Component/Validator/Constraints/Country.phpnu[PK!5:LqSymfony/Component/Validator/Constraints/EmailValidator.phpnu[PK!`v;qSymfony/Component/Validator/Constraints/LocaleValidator.phpnu[PK!'㔘  7qSymfony/Component/Validator/Constraints/IdenticalTo.phpnu[PK!/tqSymfony/Component/Validator/Constraints/All.phpnu[PK!{UU?qSymfony/Component/Validator/Constraints/NotEqualToValidator.phpnu[PK!ɑ559qSymfony/Component/Validator/Constraints/TrueValidator.phpnu[PK!(.wwGIqSymfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.phpnu[PK!(97qSymfony/Component/Validator/Constraints/TimeValidator.phpnu[PK!Fn8xqSymfony/Component/Validator/Constraints/AllValidator.phpnu[PK!c.sqSymfony/Component/Validator/Constraints/Ip.phpnu[PK!Hð2¾qSymfony/Component/Validator/Constraints/Locale.phpnu[PK!Q=*qSymfony/Component/Validator/Constraints/LanguageValidator.phpnu[PK!aHβ  ;qSymfony/Component/Validator/Constraints/ChoiceValidator.phpnu[PK!{HH1qSymfony/Component/Validator/Constraints/Email.phpnu[PK!x.`ss4.qSymfony/Component/Validator/Constraints/Callback.phpnu[PK!=qSymfony/Component/Validator/Constraints/DateTimeValidator.phpnu[PK!&0pqSymfony/Component/Validator/Constraints/Luhn.phpnu[PK!F9qSymfony/Component/Validator/Constraints/TypeValidator.phpnu[PK!&=qSymfony/Component/Validator/Constraints/NotBlankValidator.phpnu[PK!e8B 6 qSymfony/Component/Validator/Constraints/Collection.phpnu[PK!I7U1]qSymfony/Component/Validator/Constraints/False.phpnu[PK!Q>qSymfony/Component/Validator/Constraints/GreaterThanOrEqual.phpnu[PK!l1/qSymfony/Component/Validator/Constraints/Blank.phpnu[PK!CG^LL<qSymfony/Component/Validator/Constraints/EqualToValidator.phpnu[PK!^T :GqSymfony/Component/Validator/Constraints/FalseValidator.phpnu[PK!OqqDrSymfony/Component/Validator/Constraints/LessThanOrEqualValidator.phpnu[PK!vv9rSymfony/Component/Validator/Constraints/GroupSequence.phpnu[PK!_1rSymfony/Component/Validator/Constraints/Image.phpnu[PK!F;;rSymfony/Component/Validator/Constraints/LengthValidator.phpnu[PK!!xHH:rSymfony/Component/Validator/Constraints/CountValidator.phpnu[PK!70!rSymfony/Component/Validator/Constraints/Time.phpnu[PK!NH4#rSymfony/Component/Validator/Constraints/LessThan.phpnu[PK!e:8&rSymfony/Component/Validator/Constraints/NotIdenticalTo.phpnu[PK!Z=(rSymfony/Component/Validator/Constraints/CurrencyValidator.phpnu[PK!Gk 3".rSymfony/Component/Validator/ConstraintValidator.phpnu[PK!KOCA1rSymfony/Component/Validator/ConstraintValidatorFactoryInterface.phpnu[PK!8Wc?4rSymfony/Component/Validator/GlobalExecutionContextInterface.phpnu[PK!xfJJ*3rSymfony/Component/Templating/Loader/ChainLoader.phpnu[PK!b8rSymfony/Component/Templating/Loader/FilesystemLoader.phpnu[PK!g((.YrSymfony/Component/Templating/Loader/Loader.phpnu[PK!yAn n 3߹rSymfony/Component/Templating/Loader/CacheLoader.phpnu[PK!IsSymfony/Component/Yaml/Yaml.phpnu[PK!+l7sSymfony/Component/Yaml/Exception/ExceptionInterface.phpnu[PK!|-5sSymfony/Component/Yaml/Exception/RuntimeException.phpnu[PK! 3sSymfony/Component/Yaml/Exception/ParseException.phpnu[PK!ؙ՚2nsSymfony/Component/Yaml/Exception/DumpException.phpnu[PK!)%,m m "sSymfony/Component/Yaml/Escaper.phpnu[PK!q+3??!asSymfony/Component/Yaml/Inline.phpnu[PK!ݣ""6U'tSymfony/Component/HttpFoundation/ResponseHeaderBag.phpnu[PK!}xx.LJtSymfony/Component/HttpFoundation/ServerBag.phpnu[PK!_DK 5"YtSymfony/Component/HttpFoundation/RedirectResponse.phpnu[PK!s 5 dtSymfony/Component/HttpFoundation/StreamedResponse.phpnu[PK!F+ptSymfony/Component/HttpFoundation/Cookie.phpnu[PK!6= , tSymfony/Component/HttpFoundation/IpUtils.phpnu[PK!Pi,6tSymfony/Component/HttpFoundation/FileBag.phpnu[PK!1y<StSymfony/Component/HttpFoundation/RequestMatcherInterface.phpnu[PK!PE XX/֦tSymfony/Component/HttpFoundation/autoloader.phpnu[PK!8{?3tSymfony/Component/HttpFoundation/RequestMatcher.phpnu[PK!͢|1ɷtSymfony/Component/HttpFoundation/JsonResponse.phpnu[PK!Vkb335CtSymfony/Component/HttpFoundation/AcceptHeaderItem.phpnu[PK!nOO=tSymfony/Component/HttpFoundation/ExpressionRequestMatcher.phpnu[PK!a.1tSymfony/Component/HttpFoundation/AcceptHeader.phpnu[PK!\81tSymfony/Component/HttpFoundation/ParameterBag.phpnu[PK!6BuSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.phpnu[PK!5p1Jk!uSymfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.phpnu[PK!q xLp(uSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesserInterface.phpnu[PK!JL+uSymfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.phpnu[PK!2 k C4uSymfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.phpnu[PK!wnMMK>uSymfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.phpnu[PK! LKuSymfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.phpnu[PK!).uSymfony/Component/HttpFoundation/File/File.phpnu[PK!s-IuSymfony/Component/HttpFoundation/File/Exception/FileNotFoundException.phpnu[PK!S==KuSymfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.phpnu[PK!1eIuSymfony/Component/HttpFoundation/File/Exception/AccessDeniedException.phpnu[PK!grCuSymfony/Component/HttpFoundation/File/Exception/UploadException.phpnu[PK!oAuSymfony/Component/HttpFoundation/File/Exception/FileException.phpnu[PK!ގ##6SuSymfony/Component/HttpFoundation/File/UploadedFile.phpnu[PK!7 E E 1vSymfony/Component/HttpFoundation/RequestStack.phpnu[PK!W ;IvSymfony/Component/HttpFoundation/Session/Flash/FlashBag.phpnu[PK!@WWEp,vSymfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.phpnu[PK!aD<;vSymfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.phpnu[PK!=\\=SCvSymfony/Component/HttpFoundation/Session/SessionInterface.phpnu[PK!:au774VvSymfony/Component/HttpFoundation/Session/Session.phpnu[PK!M&zrr@kvSymfony/Component/HttpFoundation/Session/SessionBagInterface.phpnu[PK!e  LovSymfony/Component/HttpFoundation/Session/Attribute/AttributeBagInterface.phpnu[PK!( C vvSymfony/Component/HttpFoundation/Session/Attribute/AttributeBag.phpnu[PK!0H66MOvSymfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.phpnu[PK!t33IvSymfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.phpnu[PK!ގ!LvSymfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.phpnu[PK!$  KvSymfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.phpnu[PK!33Q9vSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.phpnu[PK!>qOvSymfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.phpnu[PK!iRvSymfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.phpnu[PK!OZP""NrwSymfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.phpnu[PK!k4{ { T&wSymfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.phpnu[PK!uY0U2wSymfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.phpnu[PK!ڏ۹ S9wSymfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.phpnu[PK!UvDwSymfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.phpnu[PK!zu00LLwSymfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.phpnu[PK!mwȡNTwSymfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.phpnu[PK!2] H\wSymfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.phpnu[PK!AFhwSymfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.phpnu[PK!g_@mwSymfony/Component/HttpFoundation/Session/Storage/MetadataBag.phpnu[PK!?yyL |wSymfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.phpnu[PK!K>2wSymfony/Component/HttpFoundation/ApacheRequest.phpnu[PK!qugdd,wSymfony/Component/HttpFoundation/Request.phpnu[PK!d}޷%%7ixSymfony/Component/HttpFoundation/BinaryFileResponse.phpnu[PK!pߋߋ-xSymfony/Component/HttpFoundation/Response.phpnu[PK!?` y y LySymfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.phpnu[PK!EY.&ySymfony/Component/HttpFoundation/HeaderBag.phpnu[PK!9;""'=FySymfony/Component/BrowserKit/Cookie.phpnu[PK!.TT+hySymfony/Component/BrowserKit/autoloader.phpnu[PK!*VjySymfony/Component/BrowserKit/CookieJar.phpnu[PK! (MySymfony/Component/BrowserKit/Request.phpnu[PK!l- - )ySymfony/Component/BrowserKit/Response.phpnu[PK!㩑eCC'ySymfony/Component/BrowserKit/Client.phpnu[PK!/  (ySymfony/Component/BrowserKit/History.phpnu[PK!V|Symfony/Component/CssSelector/Exception/ExceptionInterface.phpnu[PK!'[|ɀ:X|Symfony/Component/CssSelector/Exception/ParseException.phpnu[PK!^}  -B|Symfony/Component/CssSelector/CssSelector.phpnu[PK!5# HH<&|Symfony/Component/CssSelector/Parser/Shortcut/HashParser.phpnu[PK!ҵܗCX-|Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.phpnu[PK!TR#[PP=2|Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.phpnu[PK!Z>?D9|Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.phpnu[PK!QQ49?|Symfony/Component/CssSelector/Parser/TokenStream.phpnu[PK!6\5 5 >M|Symfony/Component/CssSelector/Parser/Handler/StringHandler.phpnu[PK!8D^^?X|Symfony/Component/CssSelector/Parser/Handler/CommentHandler.phpnu[PK!X{<^]|Symfony/Component/CssSelector/Parser/Handler/HashHandler.phpnu[PK!hffAd|Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.phpnu[PK!e'n>h|Symfony/Component/CssSelector/Parser/Handler/NumberHandler.phpnu[PK!#Bn|Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.phpnu[PK!B8v|Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.phpnu[PK!6ND1D1/<{|Symfony/Component/CssSelector/Parser/Parser.phpnu[PK!;  /߬|Symfony/Component/CssSelector/Parser/Reader.phpnu[PK!AEo118L|Symfony/Component/CssSelector/Parser/ParserInterface.phpnu[PK!zZ< .|Symfony/Component/CssSelector/Parser/Token.phpnu[PK!>< D|Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.phpnu[PK!SkFF<|Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.phpnu[PK! W55D|Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.phpnu[PK!bk +s|Symfony/Component/EventDispatcher/Event.phpnu[PK! YY0T|Symfony/Component/EventDispatcher/autoloader.phpnu[PK! M |Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.phpnu[PK!,DD2K|Symfony/Component/EventDispatcher/GenericEvent.phpnu[PK!cG11>}Symfony/Component/EventDispatcher/EventSubscriberInterface.phpnu[PK!s > }Symfony/Component/EventDispatcher/ImmutableEventDispatcher.phpnu[PK!U >}Symfony/Component/EventDispatcher/EventDispatcherInterface.phpnu[PK!NmC!}Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.phpnu[PK!Y"5u<}Symfony/Component/EventDispatcher/EventDispatcher.phpnu[PK! x 1R}Symfony/Component/Console/Command/ListCommand.phpnu[PK!Ƙ7@7@-]}Symfony/Component/Console/Command/Command.phpnu[PK!m_ _ 1J}Symfony/Component/Console/Command/HelpCommand.phpnu[PK!\0E+ }Symfony/Component/Console/ConsoleEvents.phpnu[PK!2V#]}Symfony/Component/Console/Shell.phpnu[PK!.QQ(}Symfony/Component/Console/autoloader.phpnu[PK!hrf f 6T}Symfony/Component/Console/Tester/ApplicationTester.phpnu[PK!~H(R2 }Symfony/Component/Console/Tester/CommandTester.phpnu[PK!Q))-}Symfony/Component/Console/Input/ArgvInput.phpnu[PK!' 1~Symfony/Component/Console/Input/InputArgument.phpnu[PK!AM662~Symfony/Component/Console/Input/InputInterface.phpnu[PK!OVV/.~Symfony/Component/Console/Input/InputOption.phpnu[PK!1E(0(038F~Symfony/Component/Console/Input/InputDefinition.phpnu[PK!΂= /v~Symfony/Component/Console/Input/StringInput.phpnu[PK!gm()~Symfony/Component/Console/Input/Input.phpnu[PK!p%%.v~Symfony/Component/Console/Input/ArrayInput.phpnu[PK!9Kh^^7~Symfony/Component/Console/Input/InputAwareInterface.phpnu[PK!onj&&<~Symfony/Component/Console/Formatter/OutputFormatterStyle.phpnu[PK!l7P~Symfony/Component/Console/Formatter/OutputFormatter.phpnu[PK!5E|~Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.phpnu[PK!v A~Symfony/Component/Console/Formatter/OutputFormatterStyleStack.phpnu[PK!Jp@~Symfony/Component/Console/Formatter/OutputFormatterInterface.phpnu[PK!0KK;8~Symfony/Component/Console/Output/ConsoleOutputInterface.phpnu[PK!ϱ} } 2Symfony/Component/Console/Output/ConsoleOutput.phpnu[PK!zM M 4 Symfony/Component/Console/Output/OutputInterface.phpnu[PK!F$_/~Symfony/Component/Console/Output/NullOutput.phpnu[PK!sQ;;+ Symfony/Component/Console/Output/Output.phpnu[PK!,QM M 1G1Symfony/Component/Console/Output/StreamOutput.phpnu[PK!t|X4hh3=Symfony/Component/Console/Output/BufferedOutput.phpnu[PK!LUҊҊ)ASymfony/Component/Console/Application.phpnu[PK! .Symfony/Component/Console/Helper/HelperSet.phpnu[PK!z4'Symfony/Component/Console/Helper/HelperInterface.phpnu[PK!Z\+~Symfony/Component/Console/Helper/Helper.phpnu[PK!gse4Symfony/Component/Console/Helper/FormatterHelper.phpnu[PK!220Symfony/Component/Console/Helper/TableHelper.phpnu[PK!"U1  5Symfony/Component/Console/Helper/DescriptorHelper.phpnu[PK!s H5~'Symfony/Component/Console/Helper/InputAwareHelper.phpnu[PK!|po.o.3*Symfony/Component/Console/Helper/ProgressHelper.phpnu[PK!&>@>@1YSymfony/Component/Console/Helper/DialogHelper.phpnu[PK!Duu7?Symfony/Component/Console/Descriptor/JsonDescriptor.phpnu[PK!m 3Symfony/Component/Console/Descriptor/Descriptor.phpnu[PK!lP..;:Symfony/Component/Console/Descriptor/MarkdownDescriptor.phpnu[PK!sX ?πSymfony/Component/Console/Descriptor/ApplicationDescription.phpnu[PK!ﶲ%%6݀Symfony/Component/Console/Descriptor/XmlDescriptor.phpnu[PK!7QSymfony/Component/Console/Descriptor/TextDescriptor.phpnu[PK!JZ0<<$Symfony/Component/Console/Descriptor/DescriptorInterface.phpnu[PK!v$$7'Symfony/Component/Console/Resources/bin/hiddeninput.exenu[PK!||-&7dLSymfony/Component/Console/Event/ConsoleCommandEvent.phpnu[PK!Z&&9NSymfony/Component/Console/Event/ConsoleTerminateEvent.phpnu[PK!sKAA9TSymfony/Component/Console/Event/ConsoleExceptionEvent.phpnu[PK! 0ZSymfony/Component/Console/Event/ConsoleEvent.phpnu[PK!]='YY0`Symfony/Component/OptionsResolver/autoloader.phpnu[PK!sZGbSymfony/Component/OptionsResolver/Exception/InvalidOptionsException.phpnu[PK!yPHIeSymfony/Component/OptionsResolver/Exception/OptionDefinitionException.phpnu[PK!E@^BqgSymfony/Component/OptionsResolver/Exception/ExceptionInterface.phpnu[PK! pGiSymfony/Component/OptionsResolver/Exception/MissingOptionsException.phpnu[PK!G> lSymfony/Component/OptionsResolver/OptionsResolverInterface.phpnu[PK!^R<<-pSymfony/Component/OptionsResolver/Options.phpnu[PK!}8%8%5\ǁSymfony/Component/OptionsResolver/OptionsResolver.phpnu[PK!fJ5Symfony/Component/Config/Definition/NodeInterface.phpnu[PK!jkk3Symfony/Component/Config/Definition/IntegerNode.phpnu[PK!aVp  0Symfony/Component/Config/Definition/EnumNode.phpnu[PK!Un=#'#';!Symfony/Component/Config/Definition/PrototypedArrayNode.phpnu[PK!U' ' 1&Symfony/Component/Config/Definition/Processor.phpnu[PK!C;72Symfony/Component/Config/Definition/Exception/Exception.phpnu[PK!5-Ol4Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.phpnu[PK!C7Symfony/Component/Config/Definition/Exception/UnsetKeyException.phpnu[PK!@F1:Symfony/Component/Config/Definition/Exception/InvalidTypeException.phpnu[PK!]F4L<Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.phpnu[PK!|EEG>Symfony/Component/Config/Definition/Exception/DuplicateKeyException.phpnu[PK!:2&QQMASymfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.phpnu[PK!# ֕44DtDSymfony/Component/Config/Definition/Builder/NormalizationBuilder.phpnu[PK!VhU;KSymfony/Component/Config/Definition/Builder/TreeBuilder.phpnu[PK!ʍBRSymfony/Component/Config/Definition/Builder/EnumNodeDefinition.phpnu[PK!{{<=WSymfony/Component/Config/Definition/Builder/MergeBuilder.phpnu[PK!,l[[A$]Symfony/Component/Config/Definition/Builder/ValidationBuilder.phpnu[PK!PEaSymfony/Component/Config/Definition/Builder/BooleanNodeDefinition.phpnu[PK!e@FfSymfony/Component/Config/Definition/Builder/VariableNodeDefinition.phpnu[PK!88C mSymfony/Component/Config/Definition/Builder/ArrayNodeDefinition.phpnu[PK! "$$;wSymfony/Component/Config/Definition/Builder/ExprBuilder.phpnu[PK!3d__MSymfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.phpnu[PK!mcD⽂Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.phpnu[PK!'nڭE3Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.phpnu[PK!tpCĂSymfony/Component/Config/Definition/Builder/FloatNodeDefinition.phpnu[PK!U=CȂSymfony/Component/Config/Definition/Builder/NodeParentInterface.phpnu[PK! };IʂSymfony/Component/Config/Definition/Builder/NodeBuilder.phpnu[PK!~GXXEfSymfony/Component/Config/Definition/Builder/NumericNodeDefinition.phpnu[PK!K>3Symfony/Component/Config/Definition/Builder/NodeDefinition.phpnu[PK!3Symfony/Component/Config/Definition/BooleanNode.phpnu[PK!+;;2 Symfony/Component/Config/Definition/ScalarNode.phpnu[PK!m+1<Symfony/Component/Config/Definition/FloatNode.phpnu[PK!i >>BSymfony/Component/Config/Definition/Dumper/YamlReferenceDumper.phpnu[PK!2&&A>+Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.phpnu[PK!$¸ 45RSymfony/Component/Config/Definition/VariableNode.phpnu[PK!G4**1Q\Symfony/Component/Config/Definition/ArrayNode.phpnu[PK!*dd>Symfony/Component/Config/Definition/ConfigurationInterface.phpnu[PK!eww>kSymfony/Component/Config/Definition/PrototypeNodeInterface.phpnu[PK!-*ҹ--3PSymfony/Component/Config/Definition/NumericNode.phpnu[PK!B""0Symfony/Component/Config/Definition/BaseNode.phpnu[PK!0007FSymfony/Component/Config/Definition/ReferenceDumper.phpnu[PK!`PP'ݸSymfony/Component/Config/autoloader.phpnu[PK!fKEDD7Symfony/Component/Config/Resource/ResourceInterface.phpnu[PK!T!!2/Symfony/Component/Config/Resource/FileResource.phpnu[PK! # 7ƃSymfony/Component/Config/Resource/DirectoryResource.phpnu[PK!C3kll1уSymfony/Component/Config/FileLocatorInterface.phpnu[PK!7 TTQՃSymfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.phpnu[PK!W >كSymfony/Component/Config/Exception/FileLoaderLoadException.phpnu[PK!k*Symfony/Component/Config/Util/XmlUtils.phpnu[PK!I (?Symfony/Component/Config/FileLocator.phpnu[PK!__wP< < .Symfony/Component/Config/Loader/FileLoader.phpnu[PK!))41Symfony/Component/Config/Loader/DelegatingLoader.phpnu[PK!;"Symfony/Component/Config/Loader/LoaderResolverInterface.phpnu[PK!HPʉ2&Symfony/Component/Config/Loader/LoaderResolver.phpnu[PK!=*-Symfony/Component/Config/Loader/Loader.phpnu[PK!49936Symfony/Component/Config/Loader/LoaderInterface.phpnu[PK!:a (;Symfony/Component/Config/ConfigCache.phpnu[PK!\[0GSymfony/Component/HttpKernel/KernelInterface.phpnu[PK!?.\\'![Symfony/Component/HttpKernel/Kernel.phpnu[PK!?4Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.phpnu[PK!Yxځ55C"Symfony/Component/HttpKernel/CacheClearer/CacheClearerInterface.phpnu[PK!z TT+ʿSymfony/Component/HttpKernel/autoloader.phpnu[PK!_S77AySymfony/Component/HttpKernel/CacheWarmer/CacheWarmerInterface.phpnu[PK!^FF>!ńSymfony/Component/HttpKernel/CacheWarmer/WarmableInterface.phpnu[PK!8ee8DŽSymfony/Component/HttpKernel/CacheWarmer/CacheWarmer.phpnu[PK!R!MMA˄Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.phpnu[PK! KK3`҄Symfony/Component/HttpKernel/Debug/ErrorHandler.phpnu[PK!97ՄSymfony/Component/HttpKernel/Debug/ExceptionHandler.phpnu[PK!eڮ55?ׄSymfony/Component/HttpKernel/Debug/TraceableEventDispatcher.phpnu[PK!></q Symfony/Component/HttpKernel/Log/NullLogger.phpnu[PK!~[  4Symfony/Component/HttpKernel/Log/LoggerInterface.phpnu[PK!J=[[9.Symfony/Component/HttpKernel/Log/DebugLoggerInterface.phpnu[PK!s s -Symfony/Component/HttpKernel/KernelEvents.phpnu[PK!E^?(Symfony/Component/HttpKernel/EventListener/ProfilerListener.phpnu[PK! ?>Symfony/Component/HttpKernel/EventListener/FragmentListener.phpnu[PK!@S>LSymfony/Component/HttpKernel/EventListener/SessionListener.phpnu[PK!|$CRSymfony/Component/HttpKernel/EventListener/ErrorsLoggerListener.phpnu[PK!$$GXSymfony/Component/HttpKernel/EventListener/StreamedResponseListener.phpnu[PK! @]Symfony/Component/HttpKernel/EventListener/ExceptionListener.phpnu[PK!PCyy?nSymfony/Component/HttpKernel/EventListener/ResponseListener.phpnu[PK!S "P P =tSymfony/Component/HttpKernel/EventListener/LocaleListener.phpnu[PK!/)A A BSymfony/Component/HttpKernel/EventListener/TestSessionListener.phpnu[PK! --=MSymfony/Component/HttpKernel/EventListener/RouterListener.phpnu[PK!^:秅Symfony/Component/HttpKernel/EventListener/EsiListener.phpnu[PK!qK-##@ꭅSymfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.phpnu[PK!m3 3 B}ÅSymfony/Component/HttpKernel/Fragment/RoutableFragmentRenderer.phpnu[PK!jg ="ЅSymfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.phpnu[PK!R9}څSymfony/Component/HttpKernel/Fragment/FragmentHandler.phpnu[PK!5앾BrSymfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.phpnu[PK!zCSymfony/Component/HttpKernel/Fragment/FragmentRendererInterface.phpnu[PK!ST; Symfony/Component/HttpKernel/Exception/FlattenException.phpnu[PK![G??B, Symfony/Component/HttpKernel/Exception/BadRequestHttpException.phpnu[PK!7GSymfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.phpnu[PK!W1d8Symfony/Component/HttpKernel/Exception/HttpException.phpnu[PK!N0;;@Symfony/Component/HttpKernel/Exception/ConflictHttpException.phpnu[PK!C%؝SSLSymfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.phpnu[PK!EEE`!Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.phpnu[PK!Ѕ33<%Symfony/Component/HttpKernel/Exception/GoneHttpException.phpnu[PK!^>(Symfony/Component/HttpKernel/Exception/FatalErrorException.phpnu[PK!)8*uuD+Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.phpnu[PK!+~~L/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.phpnu[PK!+;XXJ3Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.phpnu[PK!*D[8Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.phpnu[PK!瞻??@<Symfony/Component/HttpKernel/Exception/NotFoundHttpException.phpnu[PK!<~HQ@Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.phpnu[PK! GGFDSymfony/Component/HttpKernel/Exception/LengthRequiredHttpException.phpnu[PK!;COOJhHSymfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.phpnu[PK!rQrWA1LSymfony/Component/HttpKernel/Exception/HttpExceptionInterface.phpnu[PK!^t4YOSymfony/Component/HttpKernel/TerminableInterface.phpnu[PK!=AA4SSymfony/Component/HttpKernel/HttpKernelInterface.phpnu[PK!kt$$+~YSymfony/Component/HttpKernel/HttpKernel.phpnu[PK!b b 9}Symfony/Component/HttpKernel/HttpCache/StoreInterface.phpnu[PK!M~CCLSymfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategyInterface.phpnu[PK!wn n .jSymfony/Component/HttpKernel/HttpCache/Esi.phpnu[PK!#[[46Symfony/Component/HttpKernel/HttpCache/HttpCache.phpnu[PK!K:110 Symfony/Component/HttpKernel/HttpCache/Store.phpnu[PK!/) C<Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.phpnu[PK!Jz*GSymfony/Component/HttpKernel/UriSigner.phpnu[PK!d3MSymfony/Component/HttpKernel/Config/FileLocator.phpnu[PK!!ll.TSymfony/Component/HttpKernel/Bundle/Bundle.phpnu[PK!3a7iSymfony/Component/HttpKernel/Bundle/BundleInterface.phpnu[PK!BWzll@'sSymfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.phpnu[PK!  2Symfony/Component/HttpKernel/Profiler/Profiler.phpnu[PK!$ BrSymfony/Component/HttpKernel/Profiler/MemcachedProfilerStorage.phpnu[PK!rLUBSymfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.phpnu[PK!TsX X >弇Symfony/Component/HttpKernel/Profiler/MysqlProfilerStorage.phpnu[PK!N''>ƇSymfony/Component/HttpKernel/Profiler/RedisProfilerStorage.phpnu[PK!<Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.phpnu[PK!iY~2 2 A Symfony/Component/HttpKernel/Profiler/MemcacheProfilerStorage.phpnu[PK! 1Symfony/Component/HttpKernel/Profiler/Profile.phpnu[PK!tE-Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.phpnu[PK!t}[? LSymfony/Component/HttpKernel/Profiler/SqliteProfilerStorage.phpnu[PK!\Y`=m_Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.phpnu[PK!,&&8}Symfony/Component/HttpKernel/Event/PostResponseEvent.phpnu[PK! 79Symfony/Component/HttpKernel/Event/FinishRequestEvent.phpnu[PK!`g:<Symfony/Component/HttpKernel/Event/FilterResponseEvent.phpnu[PK!٨.kkJgSymfony/Component/HttpKernel/Event/GetResponseForControllerResultEvent.phpnu[PK!9I7LSymfony/Component/HttpKernel/Event/GetResponseEvent.phpnu[PK!9C>Symfony/Component/HttpKernel/Event/GetResponseForExceptionEvent.phpnu[PK!% <Symfony/Component/HttpKernel/Event/FilterControllerEvent.phpnu[PK!}x2Symfony/Component/HttpKernel/Event/KernelEvent.phpnu[PK!N#FF'Symfony/Component/HttpKernel/Client.phpnu[PK! <IψSymfony/Component/HttpKernel/DataCollector/LateDataCollectorInterface.phpnu[PK!8E ҈Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.phpnu[PK!2~~BۈSymfony/Component/HttpKernel/DataCollector/ConfigDataCollector.phpnu[PK!.ESymfony/Component/HttpKernel/DataCollector/DataCollectorInterface.phpnu[PK!޹ BSymfony/Component/HttpKernel/DataCollector/LoggerDataCollector.phpnu[PK!@:o o BSymfony/Component/HttpKernel/DataCollector/RouterDataCollector.phpnu[PK! +66ASymfony/Component/HttpKernel/DataCollector/Util/ValueExporter.phpnu[PK!IYz((CKSymfony/Component/HttpKernel/DataCollector/RequestDataCollector.phpnu[PK! A>Symfony/Component/HttpKernel/DataCollector/EventDataCollector.phpnu[PK!ƏGV @ISymfony/Component/HttpKernel/DataCollector/TimeDataCollector.phpnu[PK!n--<VSymfony/Component/HttpKernel/DataCollector/DataCollector.phpnu[PK!(; ; BA\Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.phpnu[PK!^/|GooGeSymfony/Component/HttpKernel/Controller/ControllerResolverInterface.phpnu[PK!|  GmSymfony/Component/HttpKernel/Controller/TraceableControllerResolver.phpnu[PK!xXX?WtSymfony/Component/HttpKernel/Controller/ControllerReference.phpnu[PK!NCtt>zSymfony/Component/HttpKernel/Controller/ControllerResolver.phpnu[PK!;M>Symfony/Component/HttpKernel/DependencyInjection/Extension.phpnu[PK!6V V MRSymfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.phpnu[PK!kJ%Symfony/Component/HttpKernel/DependencyInjection/RegisterListenersPass.phpnu[PK!u__JqSymfony/Component/HttpKernel/DependencyInjection/ConfigurableExtension.phpnu[PK!&!#ffTJSymfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.phpnu[PK!QNRJ4Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.phpnu[PK!a 9Symfony/Component/ClassLoader/ApcUniversalClassLoader.phpnu[PK!PЩ 3ɉSymfony/Component/ClassLoader/XcacheClassLoader.phpnu[PK!"KUU,׉Symfony/Component/ClassLoader/autoloader.phpnu[PK!A0ىSymfony/Component/ClassLoader/MapClassLoader.phpnu[PK!w!));߉Symfony/Component/ClassLoader/DebugUniversalClassLoader.phpnu[PK!v . .7Symfony/Component/ClassLoader/ClassCollectionLoader.phpnu[PK!a.e"e"6Symfony/Component/ClassLoader/UniversalClassLoader.phpnu[PK!S  29Symfony/Component/ClassLoader/DebugClassLoader.phpnu[PK!O5KGSymfony/Component/ClassLoader/WinCacheClassLoader.phpnu[PK!?wy 3VSymfony/Component/ClassLoader/ClassMapGenerator.phpnu[PK!lOݫ0dSymfony/Component/ClassLoader/ApcClassLoader.phpnu[PK!v'-sSymfony/Component/ClassLoader/ClassLoader.phpnu[PK!] I I :ÈSymfony/Component/DependencyInjection/SimpleXMLElement.phpnu[PK!l5/vSymfony/Component/DependencyInjection/Alias.phpnu[PK!MћSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.phpnu[PK!ҳHiSymfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.phpnu[PK!JJVSymfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.phpnu[PK!innXeSymfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.phpnu[PK!$772[Symfony/Component/DependencyInjection/Variable.phpnu[PK!U" " CSymfony/Component/DependencyInjection/ParameterBag/ParameterBag.phpnu[PK!ܮP8 LӊSymfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.phpnu[PK!ךI݊Symfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.phpnu[PK!,xmm/'Symfony/Component/DependencyInjection/Scope.phpnu[PK! ]]4Symfony/Component/DependencyInjection/autoloader.phpnu[PK!_J8Symfony/Component/DependencyInjection/ScopeInterface.phpnu[PK!BtBBJ6Symfony/Component/DependencyInjection/IntrospectableContainerInterface.phpnu[PK! O,JSymfony/Component/DependencyInjection/Exception/BadMethodCallException.phpnu[PK! L@Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.phpnu[PK!{HySymfony/Component/DependencyInjection/Exception/OutOfBoundsException.phpnu[PK!9FSymfony/Component/DependencyInjection/Exception/ExceptionInterface.phpnu[PK! +D7Symfony/Component/DependencyInjection/Exception/RuntimeException.phpnu[PK!\ NSymfony/Component/DependencyInjection/Exception/ParameterNotFoundException.phpnu[PK!I_J Symfony/Component/DependencyInjection/Exception/InactiveScopeException.phpnu[PK!zSNSymfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.phpnu[PK!l.BhSymfony/Component/DependencyInjection/Exception/LogicException.phpnu[PK!]USymfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.phpnu[PK!LSymfony/Component/DependencyInjection/Exception/InvalidArgumentException.phpnu[PK!= ԥS Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.phpnu[PK!qBW(Symfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.phpnu[PK!q8IA,Symfony/Component/DependencyInjection/ContainerAwareInterface.phpnu[PK!-&:-0Symfony/Component/DependencyInjection/ContainerBuilder.phpnu[PK!c!89894Symfony/Component/DependencyInjection/Definition.phpnu[PK!uii8Symfony/Component/DependencyInjection/ContainerAware.phpnu[PK!H 8=Symfony/Component/DependencyInjection/ContainerAwareTrait.phpnu[PK!BSymfony/Component/DependencyInjection/TaggedContainerInterface.phpnu[PK!A:$:$;HSymfony/Component/DependencyInjection/Dumper/YamlDumper.phpnu[PK!N/++7Symfony/Component/DependencyInjection/Dumper/Dumper.phpnu[PK!%%?Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.phpnu[PK!"^ :ESymfony/Component/DependencyInjection/Dumper/PhpDumper.phpnu[PK!}@sSymfony/Component/DependencyInjection/Dumper/DumperInterface.phpnu[PK!**:Symfony/Component/DependencyInjection/Dumper/XmlDumper.phpnu[PK!;Yޯ< Symfony/Component/DependencyInjection/ExpressionLanguage.phpnu[PK!U穌PP=%Symfony/Component/DependencyInjection/DefinitionDecorator.phpnu[PK!-R],,38Symfony/Component/DependencyInjection/Reference.phpnu[PK!Ua--;CSymfony/Component/DependencyInjection/Loader/IniFileLoader.phpnu[PK! >aKSymfony/Component/DependencyInjection/Loader/ClosureLoader.phpnu[PK!((>QSymfony/Component/DependencyInjection/Loader/PhpFileLoader.phpnu[PK!z#aQVXSymfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsdnu[PK!L88>uSymfony/Component/DependencyInjection/Loader/XmlFileLoader.phpnu[PK!!+++?4Symfony/Component/DependencyInjection/Loader/YamlFileLoader.phpnu[PK!Gp5 5 ;=ۍSymfony/Component/DependencyInjection/Compiler/Compiler.phpnu[PK!0є##?Symfony/Component/DependencyInjection/Compiler/RepeatedPass.phpnu[PK!LFFUoSymfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.phpnu[PK!C\Z=:Symfony/Component/DependencyInjection/Compiler/PassConfig.phpnu[PK!x7L?Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.phpnu[PK! MSymfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.phpnu[PK!iZ N'4Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.phpnu[PK!!?Ky?Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.phpnu[PK!U*''PDSymfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.phpnu[PK!mOISymfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.phpnu[PK!iJT O[Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.phpnu[PK!P P Q(jSymfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.phpnu[PK!V%) ) HuSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.phpnu[PK![ LSymfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.phpnu[PK!ϒQSymfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.phpnu[PK!nnS6Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.phpnu[PK!X\\R'Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.phpnu[PK!_9HSymfony/Component/DependencyInjection/Compiler/CompilerPassInterface.phpnu[PK!EųJgSymfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.phpnu[PK!b[_66_Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.phpnu[PK!@ q q NYŽSymfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.phpnu[PK!ddNH̎Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.phpnu[PK!ۻǠO*ێSymfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.phpnu[PK!CISymfony/Component/DependencyInjection/Compiler/LoggingFormatter.phpnu[PK!EBEB3xSymfony/Component/DependencyInjection/Container.phpnu[PK!E?< 6Symfony/Component/DependencyInjection/ContainerInterface.phpnu[PK!o =ESymfony/Component/DependencyInjection/Extension/Extension.phpnu[PK!DSFUSymfony/Component/DependencyInjection/Extension/ExtensionInterface.phpnu[PK!JS[Symfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.phpnu[PK!CoMMM_Symfony/Component/DependencyInjection/Extension/PrependExtensionInterface.phpnu[PK!F"3bSymfony/Component/DependencyInjection/Parameter.phpnu[PK!'P 'fezc/Base/metadata.phpnu[PK!:|| tezc/Base/ezc_bootstrap.phpnu[PK!xezc/Base/options/autoload.phpnu[PK!|R  )0ezc/Base/structs/repository_directory.phpnu[PK!S،&ezc/Base/structs/file_find_context.phpnu[PK!jezc/Base/metadata/tarball.phpnu[PK!myv  衏ezc/Base/metadata/pear.phpnu[PK!BX++;ezc/Base/features.phpnu[PK!lVV%ݏezc/Base/exceptions/setting_value.phpnu[PK!HDfPEE&ezc/Base/exceptions/file_not_found.phpnu[PK!Ū!`ezc/Base/exceptions/exception.phpnu[PK!@c*Vezc/Base/exceptions/property_not_found.phpnu[PK!u3 ezc/Base/exceptions/whatever.phpnu[PK!b993ezc/Base/exceptions/functionality_not_supported.phpnu[PK!ll.ezc/Base/exceptions/invalid_callback_class.phpnu[PK!!`ezc/Base/exceptions/file_io.phpnu[PK!ӥ'ezc/Base/exceptions/file_permission.phpnu[PK!²Gi{ ezc/Base/exceptions/value.phpnu[PK!R~11+ezc/Base/exceptions/extension_not_found.phpnu[PK!Ն((&ezc/Base/exceptions/file_exception.phpnu[PK!aa+ezc/Base/exceptions/property_permission.phpnu[PK!^M@@,Oezc/Base/exceptions/invalid_parent_class.phpnu[PK!{QQ6ezc/Base/exceptions/double_class_repository_prefix.phpnu[PK!0$ezc/Base/exceptions/init_callback_configured.phpnu[PK!rr (ezc/Base/exceptions/autoload.phpnu[PK!םOO)n-ezc/Base/exceptions/setting_not_found.phpnu[PK!UJX1ezc/Base/options.phpnu[PK!4QEQEGFezc/Base/file.phpnu[PK!S]KKًezc/Base/init.phpnu[PK!/#eezc/Base/interfaces/persistable.phpnu[PK!4ei"ezc/Base/interfaces/exportable.phpnu[PK!PBs|1ezc/Base/interfaces/configuration_initializer.phpnu[PK!%N N ezc/Base/base_autoload.phpnu[PK!xr44)ezc/Base/struct.phpnu[PK!Eezc/ConsoleTools/dialog/validators/question_dialog_mapping.phpnu[PK!H!AZezc/ConsoleTools/dialog/validators/question_dialog_collection.phpnu[PK!kx2'crezc/ConsoleTools/dialog/menu_dialog.phpnu[PK!%p%pezc/ConsoleTools/table.phpnu[PK!, , ezc/ConsoleTools/options/question_dialog.phpnu[PK!ͅ(T ezc/ConsoleTools/options/progressbar.phpnu[PK!y&ezc/ConsoleTools/options/statusbar.phpnu[PK!88HH"#ezc/ConsoleTools/options/table.phpnu[PK!*..# Cezc/ConsoleTools/options/dialog.phpnu[PK! BB,Kezc/ConsoleTools/options/progressmonitor.phpnu[PK!'J  #?Rezc/ConsoleTools/options/output.phpnu[PK!Q(`ezc/ConsoleTools/options/menu_dialog.phpnu[PK!cgg*oezc/ConsoleTools/structs/output_format.phpnu[PK!#j''+ezc/ConsoleTools/structs/output_formats.phpnu[PK!!{D(1ezc/ConsoleTools/structs/option_rule.phpnu[PK!\)|1Fezc/ConsoleTools/exceptions/argument_too_many.phpnu[PK!:  <\ezc/ConsoleTools/exceptions/option_string_not_wellformed.phpnu[PK!%agg:Ӵezc/ConsoleTools/exceptions/option_mandatory_violation.phpnu[PK!J8&ezc/ConsoleTools/exceptions/option.phpnu[PK!<zezc/ConsoleTools/exceptions/argument_mandatory_violation.phpnu[PK!:jezc/ConsoleTools/exceptions/option_exclusion_violation.phpnu[PK!5ēezc/ConsoleTools/exceptions/option_type_violation.phpnu[PK! 7)9ʓezc/ConsoleTools/exceptions/exception.phpnu[PK!e8##1=̓ezc/ConsoleTools/exceptions/option_not_exists.phpnu[PK!arr7ϓezc/ConsoleTools/exceptions/argument_type_violation.phpnu[PK!XXDD;ԓezc/ConsoleTools/exceptions/argument_already_registered.phpnu[PK!] 5(Iۓezc/ConsoleTools/exceptions/argument.phpnu[PK!ī2*ޓezc/ConsoleTools/exceptions/no_position_stored.phpnu[PK! a37ezc/ConsoleTools/exceptions/invalid_option_name.phpnu[PK!|9ezc/ConsoleTools/exceptions/option_already_registered.phpnu[PK!J:ezc/ConsoleTools/exceptions/option_arguments_violation.phpnu[PK!BW95 ezc/ConsoleTools/exceptions/invalid_output_target.phpnu[PK!H6_ezc/ConsoleTools/exceptions/no_valid_dialog_result.phpnu[PK!=?,ezc/ConsoleTools/exceptions/dialog_abort.phpnu[PK!ř4ezc/ConsoleTools/exceptions/option_missing_value.phpnu[PK!;ezc/ConsoleTools/exceptions/option_dependency_violation.phpnu[PK!s  /ezc/ConsoleTools/exceptions/option_no_alias.phpnu[PK!vv6gezc/ConsoleTools/exceptions/option_too_many_values.phpnu[PK!= RLL!Cezc/ConsoleTools/input/option.phpnu[PK! t^^$OSezc/ConsoleTools/input/arguments.phpnu[PK!%663rezc/ConsoleTools/input/help_generators/standard.phpnu[PK!p#|ezc/ConsoleTools/input/argument.phpnu[PK!&T.”ezc/ConsoleTools/input/validators/standard.phpnu[PK!T\GGהezc/ConsoleTools/input.phpnu[PK!JqVV$ezc/ConsoleTools/progressmonitor.phpnu[PK!wQO~4+ezc/ConsoleTools/interfaces/input_help_generator.phpnu[PK!9c"9ezc/ConsoleTools/interfaces/question_dialog_validator.phpnu[PK!%uu/ezc/ConsoleTools/interfaces/input_validator.phpnu[PK!+5оezc/ConsoleTools/interfaces/menu_dialog_validator.phpnu[PK!A NS S &ezc/ConsoleTools/interfaces/dialog.phpnu[PK!eެ0g̕ezc/ConsoleTools/interfaces/dialog_validator.phpnu[PK!4JJsҕezc/ConsoleTools/output.phpnu[PK!unšwwwezc/Archive/archive.phpnu[PK!Ԣ"$fIfIezc/Archive/file/block_file.phpnu[PK!cp' ( (#gߖezc/Archive/file/character_file.phpnu[PK!$^33ezc/Archive/file/file.phpnu[PK!5 ;ezc/Archive/archive_autoload.phpnu[PK!U+77Fezc/Archive/utils/stat_mode.phpnu[PK!0nMezc/Archive/utils/checksums.phpnu[PK! zefezc/Archive/utils/file_type.phpnu[PK!}sb xezc/Archive/options/archive.phpnu[PK!f S S fezc/Archive/structs/file.phpnu[PK!L<< ezc/Archive/exceptions/empty.phpnu[PK! 'ezc/Archive/exceptions/unknown_type.phpnu[PK!GMM$ezc/Archive/exceptions/exception.phpnu[PK!&Y#_ezc/Archive/exceptions/checksum.phpnu[PK!0dii%_ezc/Archive/exceptions/block_size.phpnu[PK!N8TT ezc/Archive/exceptions/value.phpnu[PK!9+IIezc/Archive/exceptions/io.phpnu[PK!}H-Wezc/Archive/exceptions/internal_exception.phpnu[PK! 'Fezc/Archive/exceptions/entry_prefix.phpnu[PK!hAAezc/Archive/entry.phpnu[PK!\^G^G-Xezc/Archive/zip/headers/central_directory.phpnu[PK!K`c`c&;ezc/Archive/zip/headers/local_file.phpnu[PK! ,##1ɞezc/Archive/zip/headers/central_directory_end.phpnu[PK!XAVV˜ezc/Archive/zip/zip.phpnu[PK!<#ezc/Archive/interfaces/callback.phpnu[PK!靽  ezc/Archive/tar/pax.phpnu[PK!31 *ezc/Archive/tar/ustar.phpnu[PK!= 4ezc/Archive/tar/gnu.phpnu[PK!$H?ezc/Archive/tar/headers/pax.phpnu[PK!M99!7Qezc/Archive/tar/headers/ustar.phpnu[PK!Nvnntezc/Archive/tar/headers/gnu.phpnu[PK!^881ezc/Archive/tar/headers/v7.phpnu[PK!BLBL)әezc/Archive/tar/v7.phpnu[PK! --ezc/File/file_autoload.phpnu[PK!K(!ezc/File/file.phpnu[PK!5 !d#ezc/autoload/archive_autoload.phpnu[PK!5tt!c.ezc/autoload/console_autoload.phpnu[PK! --(Hezc/autoload/file_autoload.phpnu[PK!%N N Iezc/autoload/base_autoload.phpnu[PK!F?Vtest/Finder/Symfony/Component/Finder/Tests/Fixtures/with space/foo.txtnu[PK!AVtest/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.datnu[PK!>&Wtest/Finder/Symfony/Component/Finder/Tests/Fixtures/A/B/ab.datnu[PK!;Wtest/Finder/Symfony/Component/Finder/Tests/Fixtures/A/a.datnu[PK!9Wtest/Finder/Symfony/Component/Finder/Tests/Fixtures/one/anu[PK!@hXtest/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/d.neonnu[PK!@Xtest/Finder/Symfony/Component/Finder/Tests/Fixtures/one/b/c.neonnu[PK!o5|=HYtest/Finder/Symfony/Component/Finder/Tests/Fixtures/dolor.txtnu[PK!'))=Ytest/Finder/Symfony/Component/Finder/Tests/Fixtures/ipsum.txtnu[PK!55=hZtest/Finder/Symfony/Component/Finder/Tests/Fixtures/lorem.txtnu[PK!E [test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copynu[PK!K[test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copynu[PK!H[test/Finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copynu[PK!˟ׄ Lr\test/Finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.phpnu[PK!W.//Nrftest/Finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.phpnu[PK!ŖHutest/Finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.phpnu[PK!6Gmwmw9-}test/Finder/Symfony/Component/Finder/Tests/FinderTest.phpnu[PK!+드4 4 Ltest/Finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.phpnu[PK!:@ Mtest/Finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.phpnu[PK!qbe U test/Finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.phpnu[PK!YbkMMR7test/Finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.phpnu[PK!ŊVtest/Finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.phpnu[PK!4/aaZ'test/Finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.phpnu[PK!nI N.test/Finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.phpnu[PK!++Vs;test/Finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.phpnu[PK!7Wa a L$Dtest/Finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.phpnu[PK!7RNtest/Finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.phpnu[PK!߫P{Ttest/Finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.phpnu[PK!o GYtest/Finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.phpnu[PK!Zo*))T htest/Finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.phpnu[PK!S@ptest/Finder/Symfony/Component/Finder/Tests/Iterator/Iterator.phpnu[PK!FSNutest/Finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.phpnu[PK!-66J{test/Finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.phpnu[PK!{)\o o Htest/Finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.phpnu[PK![+((Lhtest/Finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.phpnu[PK!(g==S test/Finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.phpnu[PK!|ߐH̕test/Finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.phpnu[PK!9]CԜtest/Finder/Symfony/Component/Finder/Tests/Expression/RegexTest.phpnu[PK!7uttB講test/Finder/Symfony/Component/Finder/Tests/Expression/GlobTest.phpnu[PK!`2Gγtest/Finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.phpnu[PK!IGtest/Finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.phpnu[PK!/00Mtest/Finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.phpnu[PK!mmI/test/Finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.phpnu[PK!555ětest/Finder/Symfony/Component/Finder/phpunit.xml.distnu[PK!9 KǛtest/TwigBridge/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.phpnu[PK!O#''O՛test/TwigBridge/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.phpnu[PK!hH H @test/TwigBridge/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.phpnu[PK!ͅi99<Ztest/TwigBridge/Symfony/Bridge/Twig/Tests/TwigEngineTest.phpnu[PK!kK atest/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.phpnu[PK!¶ Ttest/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.phpnu[PK!j|$  J%test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.phpnu[PK!6!!C.test/TwigBridge/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.phpnu[PK!# R#1test/TwigBridge/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.phpnu[PK!xL?test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.phpnu[PK!:WWTGtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.phpnu[PK!t9A A OVtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.phpnu[PK!V%33Ratest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/page_dynamic_extends.html.twignu[PK!]U4btest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.phpnu[PK!*n**Odtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.phpnu[PK!̙nsGzhtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twignu[PK!+Ijtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.phpnu[PK!%o Nrrtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.phpnu[PK!ߋO|test/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.phpnu[PK!,'KKJtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twignu[PK!Pxtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.phpnu[PK!(Ctest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme.html.twignu[PK!i!!Rtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.phpnu[PK!Һ VVItest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twignu[PK!tdKptest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twignu[PK!bLtest/TwigBridge/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twignu[PK!Pcc4%test/TwigBridge/Symfony/Bridge/Twig/phpunit.xml.distnu[PK!h9=U U Oœtest/Translation/Symfony/Component/Translation/Tests/IdentityTranslatorTest.phpnu[PK!*|1|1GϜtest/Translation/Symfony/Component/Translation/Tests/TranslatorTest.phpnu[PK!l.!Otest/Translation/Symfony/Component/Translation/Tests/PluralizationRulesTest.phpnu[PK!hlTtest/Translation/Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.phpnu[PK!$͒ϛUtest/Translation/Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.phpnu[PK!ײ))X<"test/Translation/Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.phpnu[PK!02E*test/Translation/Symfony/Component/Translation/Tests/IntervalTest.phpnu[PK!VQ0test/Translation/Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.phpnu[PK!`׹S&4test/Translation/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.phpnu[PK!Qb8test/Translation/Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.phpnu[PK!R<test/Translation/Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.phpnu[PK!ub/T@test/Translation/Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.phpnu[PK!QEtest/Translation/Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.phpnu[PK!PJtest/Translation/Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.phpnu[PK!BYP4Ntest/Translation/Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.phpnu[PK!IIR]Rtest/Translation/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.phpnu[PK!&ݙP(Wtest/Translation/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.phpnu[PK!8^kSA[test/Translation/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.phpnu[PK!|=PNktest/Translation/Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.phpnu[PK!3Qrttest/Translation/Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.phpnu[PK!Q wtest/Translation/Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.phpnu[PK!~  R}test/Translation/Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.phpnu[PK!$X  P>test/Translation/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.phpnu[PK![Qґtest/Translation/Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.phpnu[PK!/݂Q test/Translation/Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.phpnu[PK!jTtest/Translation/Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.phpnu[PK!PeR]test/Translation/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.phpnu[PK! Pͱtest/Translation/Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.phpnu[PK!) Ttest/Translation/Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.phpnu[PK!MMĝtest/Translation/Symfony/Component/Translation/Tests/MessageCatalogueTest.phpnu[PK!  L*test/Translation/Symfony/Component/Translation/Tests/MessageSelectorTest.phpnu[PK!W44Jtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.monu[PK!!fJttest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ponu[PK!=BsR{test/Translation/Symfony/Component/Translation/Tests/fixtures/empty-translation.ponu[PK!Gtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ininu[PK!YڸCQtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlfnu[PK!:++Ktest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.phpnu[PK!Gtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ymlnu[PK!H,test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.jsonnu[PK!Y44Itest/Translation/Symfony/Component/Translation/Tests/fixtures/resname.xlfnu[PK!GQtest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.xlfnu[PK!;.BBHtest/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.ponu[PK!ߞLtest/Translation/Symfony/Component/Translation/Tests/fixtures/malformed.jsonnu[PK!.zzKtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.xlfnu[PK!e2~K test/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.ymlnu[PK!'F Ktest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ininu[PK! TTK test/Translation/Symfony/Component/Translation/Tests/fixtures/non-valid.xlfnu[PK!F test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.ponu[PK!GR test/Translation/Symfony/Component/Translation/Tests/fixtures/empty.csvnu[PK!*֔JJH test/Translation/Symfony/Component/Translation/Tests/fixtures/plurals.monu[PK!+LTTW test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/res/en.resnu[PK!w˦(||Wf test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.resnu[PK!X**Wi test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.txtnu[PK!rQ``^test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/resources.datnu[PK!MRxxWtest/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.resnu[PK!g.`test/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/packagelist.txtnu[PK!25''Wtest/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.txtnu[PK!<dStest/Translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted/resources.datnu[PK!Ftest/Translation/Symfony/Component/Translation/Tests/fixtures/empty.monu[PK! jjM`test/Translation/Symfony/Component/Translation/Tests/fixtures/withdoctype.xlfnu[PK!̉^2JGtest/Translation/Symfony/Component/Translation/Tests/fixtures/encoding.xlfnu[PK!B$$Gtest/Translation/Symfony/Component/Translation/Tests/fixtures/valid.csvnu[PK!L)test/Translation/Symfony/Component/Translation/Tests/fixtures/resources.jsonnu[PK!C(Jtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.tsnu[PK!/ Wtest/Translation/Symfony/Component/Translation/Tests/fixtures/invalid-xml-resources.xlfnu[PK! Kjtest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.ymlnu[PK!D``Ktest/Translation/Symfony/Component/Translation/Tests/fixtures/resources.csvnu[PK!^C ::?test/Translation/Symfony/Component/Translation/phpunit.xml.distnu[PK!LLEr"test/Routing/Symfony/Component/Routing/Tests/Annotation/RouteTest.phpnu[PK!%])])B3)test/Routing/Symfony/Component/Routing/Tests/RouteCompilerTest.phpnu[PK!1d nnMStest/Routing/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.phpnu[PK!CUtest/Routing/Symfony/Component/Routing/Tests/Fixtures/annotated.phpnu[PK!?`Vtest/Routing/Symfony/Component/Routing/Tests/Fixtures/empty.ymlnu[PK!/FVtest/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.ymlnu[PK!MF)Ztest/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.xmlnu[PK!/$>>VW_test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.ymlnu[PK!==F`test/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.ymlnu[PK!ieI`test/Routing/Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xmlnu[PK!#q//Ddtest/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_id.xmlnu[PK!x' 11Eetest/Routing/Symfony/Component/Routing/Tests/Fixtures/withdoctype.xmlnu[PK!;h%%PNftest/Routing/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.phpnu[PK!s[//Fitest/Routing/Symfony/Component/Routing/Tests/Fixtures/missing_path.xmlnu[PK!e2~Bktest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.ymlnu[PK!ix77Fltest/Routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.phpnu[PK!GV,+,+Motest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.phpnu[PK!TMdtest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.phpnu[PK!@4Ptest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apachenu[PK!Bx6Ptest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apachenu[PK!nk//MQtest/Routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.phpnu[PK!pBtest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xmlnu[PK!ͼn!!Ftest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xmlnu[PK!TStest/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.phpnu[PK!GGStest/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.phpnu[PK!zUUXtest/Routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.phpnu[PK!MtCtest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid2.ymlnu[PK!bG test/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.xmlnu[PK!qGtest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xmlnu[PK!ϮBBD/test/Routing/Symfony/Component/Routing/Tests/Fixtures/incomplete.ymlnu[PK!J?Ltest/Routing/Symfony/Component/Routing/Tests/Fixtures/special_route_name.ymlnu[PK!q99Ytest/Routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.ymlnu[PK!jXGBtest/Routing/Symfony/Component/Routing/Tests/Fixtures/validresource.ymlnu[PK!>test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo1.xmlnu[PK!=test/Routing/Symfony/Component/Routing/Tests/Fixtures/foo.xmlnu[PK!/ Ctest/Routing/Symfony/Component/Routing/Tests/RequestContextTest.phpnu[PK!Ì P test/Routing/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.phpnu[PK!tkTBBGtest/Routing/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.phpnu[PK!ȁ@ZK\test/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.phpnu[PK!)#0%%Tltest/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.phpnu[PK!UTtest/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.phpnu[PK!IQWttest/Routing/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.phpnu[PK!̼aaM⯟test/Routing/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.phpnu[PK!A Sğtest/Routing/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.phpnu[PK!%"?7?7D̟test/Routing/Symfony/Component/Routing/Tests/RouteCollectionTest.phpnu[PK! klggKtest/Routing/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.phpnu[PK!Xltest/Routing/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.phpnu[PK!8!!&GGB7}test/Routing/Symfony/Component/Routing/Tests/CompiledRouteTest.phpnu[PK!kItest/Routing/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.phpnu[PK!Q3test/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.phpnu[PK!gUItest/Routing/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.phpnu[PK!{tJtest/Routing/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.phpnu[PK!6Utest/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.phpnu[PK!M~##Iܼtest/Routing/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.phpnu[PK!|C44TxѠtest/Routing/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.phpnu[PK!u;P0ՠtest/Routing/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.phpnu[PK!;۠test/Routing/Symfony/Component/Routing/Tests/RouterTest.phpnu[PK!uA,,:6test/Routing/Symfony/Component/Routing/Tests/RouteTest.phpnu[PK!~667test/Routing/Symfony/Component/Routing/phpunit.xml.distnu[PK!+\MMH!test/Process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.phpnu[PK!#T(test/Process/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.phpnu[PK!WKo Km/test/Process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.phpnu[PK!Cu^UUA{:test/Process/Symfony/Component/Process/Tests/ProcessUtilsTest.phpnu[PK![VAChChDA@test/Process/Symfony/Component/Process/Tests/AbstractProcessTest.phpnu[PK!=,j?test/Process/Symfony/Component/Process/Tests/SignalListener.phpnu[PK! Betest/Process/Symfony/Component/Process/Tests/SimpleProcessTest.phpnu[PK!+v,,Cátest/Process/Symfony/Component/Process/Tests/NonStopableProcess.phpnu[PK!mMoǡtest/Process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.phpnu[PK!Lɡtest/Process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.phpnu[PK!HsppCtest/Process/Symfony/Component/Process/Tests/ProcessBuilderTest.phpnu[PK!x[?test/Process/Symfony/Component/Process/Tests/PhpProcessTest.phpnu[PK!钊\\Ktest/Process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.phpnu[PK!p\H7test/Process/Symfony/Component/Process/phpunit.xml.distnu[PK!2c$$Etest/Serializer/Symfony/Component/Serializer/Tests/SerializerTest.phpnu[PK!m))PJ?test/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestNormalizer.phpnu[PK!$ѕVBtest/Serializer/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.phpnu[PK!P1!!\Ktest/Serializer/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.phpnu[PK!qBBR/mtest/Serializer/Symfony/Component/Serializer/Tests/Normalizer/TestDenormalizer.phpnu[PK!K__Kptest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.phpnu[PK!_Putest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.phpnu[PK!G5\Hxtest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.phpnu[PK!LYEW}test/Serializer/Symfony/Component/Serializer/Tests/Fixtures/Dummy.phpnu[PK!Y["uuStest/Serializer/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.phpnu[PK!f|B.B.Mtest/Serializer/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.phpnu[PK!F  Nntest/Serializer/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.phpnu[PK!99=test/Serializer/Symfony/Component/Serializer/phpunit.xml.distnu[PK!Ǫ9test/Locale/Symfony/Component/Locale/Tests/LocaleTest.phpnu[PK!<BȢtest/Locale/Symfony/Component/Locale/Tests/Stub/StubLocaleTest.phpnu[PK!+hh5Ϣtest/Locale/Symfony/Component/Locale/phpunit.xml.distnu[PK!;IҢtest/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTestCase.phpnu[PK!'B 0ooEhtest/Filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.phpnu[PK!íDQtest/Filesystem/Symfony/Component/Filesystem/Tests/ExceptionTest.phpnu[PK!Ejc  =Wtest/Filesystem/Symfony/Component/Filesystem/phpunit.xml.distnu[PK!ag@<@<B [test/Form/Symfony/Component/Form/Tests/AbstractTableLayoutTest.phpnu[PK!KKBtest/Form/Symfony/Component/Form/Tests/FormPerformanceTestCase.phpnu[PK!@U=xtest/Form/Symfony/Component/Form/Tests/AbstractLayoutTest.phpnu[PK!:}test/Form/Symfony/Component/Form/Tests/Guess/GuessTest.phpnu[PK!uEtest/Form/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.phpnu[PK!x:}test/Form/Symfony/Component/Form/Tests/Fixtures/Author.phpnu[PK!3֍test/Form/Symfony/Component/Form/Tests/Fixtures/foonu[PK![َG9test/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.phpnu[PK!*;>test/Form/Symfony/Component/Form/Tests/Fixtures/FooType.phpnu[PK!:.zFtest/Form/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.phpnu[PK!֫v>test/Form/Symfony/Component/Form/Tests/Fixtures/AuthorType.phpnu[PK!#o>Etest/Form/Symfony/Component/Form/Tests/Fixtures/FooSubType.phpnu[PK!8Atest/Form/Symfony/Component/Form/Tests/Fixtures/TestExtension.phpnu[PK!x  Gͥtest/Form/Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.phpnu[PK!m^2++PQtest/Form/Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.phpnu[PK!!uGtest/Form/Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.phpnu[PK!ŲUUH test/Form/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.phpnu[PK!JRR:ָtest/Form/Symfony/Component/Form/Tests/FormFactoryTest.phpnu[PK!ȔfVA6A6B test/Form/Symfony/Component/Form/Tests/Util/OrderedHashMapTest.phpnu[PK!znznz;Btest/Form/Symfony/Component/Form/Tests/CompoundFormTest.phpnu[PK!dAqtest/Form/Symfony/Component/Form/Tests/FormFactoryBuilderTest.phpnu[PK!̈́;ĥtest/Form/Symfony/Component/Form/Tests/FormRegistryTest.phpnu[PK!]9}}99test/Form/Symfony/Component/Form/Tests/FormConfigTest.phpnu[PK!>)bbEtest/Form/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.phpnu[PK!ū@d22?test/Form/Symfony/Component/Form/Tests/ResolvedFormTypeTest.phpnu[PK!O )KKByGtest/Form/Symfony/Component/Form/Tests/FormIntegrationTestCase.phpnu[PK!K)ooF6Jtest/Form/Symfony/Component/Form/Tests/CompoundFormPerformanceTest.phpnu[PK!tٴ;Ptest/Form/Symfony/Component/Form/Tests/FormRendererTest.phpnu[PK!d!!C`Stest/Form/Symfony/Component/Form/Tests/NativeRequestHandlerTest.phpnu[PK!:jtest/Form/Symfony/Component/Form/Tests/FormBuilderTest.phpnu[PK!RmhZTZT@1test/Form/Symfony/Component/Form/Tests/AbstractDivLayoutTest.phpnu[PK!k/6  ;ۦtest/Form/Symfony/Component/Form/Tests/AbstractFormTest.phpnu[PK!rM{{9{test/Form/Symfony/Component/Form/Tests/SimpleFormTest.phpnu[PK!ۿtcdtest/Form/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.phpnu[PK!EY޵Txtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.phpnu[PK!l" W7test/Form/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.phpnu[PK! gOtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.phpnu[PK!ِGbGb\test/Form/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.phpnu[PK!$Ǵ`test/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.phpnu[PK!@1,,btest/Form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.phpnu[PK!`f[PI=test/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.phpnu[PK!Y xx^~Ctest/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.phpnu[PK!SmdLtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.phpnu[PK!7>lˉbOtest/Form/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.phpnu[PK!1 i:Ttest/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.phpnu[PK!f͍ffdutest/Form/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.phpnu[PK!%u^}|test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.phpnu[PK!_Nn^test/Form/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.phpnu[PK!Ab test/Form/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.phpnu[PK!L?..X]test/Form/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.phpnu[PK!܏##WŪtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhashnu[PK!* * avƪtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.phpnu[PK!!$$^1Ӫtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.phpnu[PK!fk5s3 3 Xtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.phpnu[PK!B+Knbtest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.phpnu[PK!@ڦttest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.phpnu[PK!Э hm test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.phpnu[PK!ggb test/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.phpnu[PK!O&ctest/Form/Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.phpnu[PK! Y52test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.phpnu[PK!.p))SStest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.phpnu[PK!![[fhtest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.phpnu[PK!gUI Wȇtest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.phpnu[PK!R Ytest/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.phpnu[PK!x`test/Form/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.phpnu[PK!?R8..[Etest/Form/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.phpnu[PK!4fګtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.phpnu[PK!qtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.phpnu[PK!Ws**r6test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.phpnu[PK!Ub,,Ztest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.phpnu[PK!}! ! ltest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.phpnu[PK!=C?C?h`-test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.phpnu[PK!e;mtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.phpnu[PK!\Rb{test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.phpnu[PK!6hꄬtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.phpnu[PK!Y@zjjo)test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.phpnu[PK!]e"j2test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.phpnu[PK!Nz.z.qXtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.phpnu[PK!`nonops׬test/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.phpnu[PK!?+< < jGtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.phpnu[PK!fJeWStest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.phpnu[PK!.bc))hXtest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.phpnu[PK!JWiatest/Form/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.phpnu[PK!W@@O=|test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.phpnu[PK!xaaMtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.phpnu[PK!CMڇtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.phpnu[PK!'\\K؊test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.phpnu[PK!vzwLLQtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.phpnu[PK!(__Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.phpnu[PK!x=t=t=Otest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.phpnu[PK!P!JsFtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.phpnu[PK!X:::KMtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.phpnu[PK!NbPtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.phpnu[PK!_*GXxWtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.phpnu[PK!{MKK[test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.phpnu[PK!ސ/Omtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.phpnu[PK!dwҢSJSJKSrtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.phpnu[PK!/L!test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.phpnu[PK!JMqĮtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.phpnu[PK!}C%%Mˮtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.phpnu[PK!!]i00OҮtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.phpnu[PK!IJO3׮test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.phpnu[PK!ñIOotest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.phpnu[PK!kƅNtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.phpnu[PK!IEMtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.phpnu[PK!jGgJgJKFtest/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.phpnu[PK!&K(test/Form/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.phpnu[PK!>>Xtest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.phpnu[PK!b,<<] :test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.phpnu[PK!{(,,X?test/Form/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.phpnu[PK!qf=mtest/Form/Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.phpnu[PK!'@kstest/Form/Symfony/Component/Form/Tests/AbstractExtensionTest.phpnu[PK!g 331wtest/Form/Symfony/Component/Form/phpunit.xml.distnu[PK!ԍZP5P5It{test/Security/Symfony/Component/Security/Acl/Tests/Voter/AclVoterTest.phpnu[PK!޻>QQR=test/Security/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.phpnu[PK!  TLtest/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.phpnu[PK!'(''K$test/Security/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderTest.phpnu[PK!ˆ5MLtest/Security/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.phpnu[PK!6x}&&LJUtest/Security/Symfony/Component/Security/Acl/Tests/Domain/FieldEntryTest.phpnu[PK!+&P]test/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityTest.phpnu[PK!_~amtest/Security/Symfony/Component/Security/Acl/Tests/Domain/ObjectIdentityRetrievalStrategyTest.phpnu[PK!H H Rrtest/Security/Symfony/Component/Security/Acl/Tests/Domain/DoctrineAclCacheTest.phpnu[PK!v\dtest/Security/Symfony/Component/Security/Acl/Tests/Domain/PermissionGrantingStrategyTest.phpnu[PK!/bAbAE홱test/Security/Symfony/Component/Security/Acl/Tests/Domain/AclTest.phpnu[PK!5V۱test/Security/Symfony/Component/Security/Acl/Tests/Domain/RoleSecurityIdentityTest.phpnu[PK!a( ( Vtest/Security/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.phpnu[PK!amcwtest/Security/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.phpnu[PK!F@ G test/Security/Symfony/Component/Security/Acl/Tests/Domain/EntryTest.phpnu[PK!yyXtest/Security/Symfony/Component/Security/Acl/Tests/Permission/BasicPermissionMapTest.phpnu[PK!eE Qtest/Security/Symfony/Component/Security/Acl/Tests/Permission/MaskBuilderTest.phpnu[PK!ܲ#&;;=)test/Security/Symfony/Component/Security/Acl/phpunit.xml.distnu[PK!C)!"!"V,test/Security/Symfony/Component/Security/Tests/Http/Firewall/ExceptionListenerTest.phpnu[PK!sf[[L^Otest/Security/Symfony/Component/Security/Tests/Core/User/UserCheckerTest.phpnu[PK!!!U5_test/Security/Symfony/Component/Security/Tests/Core/User/InMemoryUserProviderTest.phpnu[PK!2nBB`ftest/Security/Symfony/Component/Security/Tests/Core/Authentication/Token/RememberMeTokenTest.phpnu[PK!9#  9otest/Security/Symfony/Component/Security/phpunit.xml.distnu[PK!g3%%Dttest/Security/Symfony/Component/Security/Http/Tests/FirewallTest.phpnu[PK!+MbbGtest/Security/Symfony/Component/Security/Http/Tests/FirewallMapTest.phpnu[PK!%%Etest/Security/Symfony/Component/Security/Http/Tests/HttpUtilsTest.phpnu[PK!ck~ ~ ctest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/FormAuthenticationEntryPointTest.phpnu[PK!edŲtest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/BasicAuthenticationEntryPointTest.phpnu[PK!-Ɔ d˲test/Security/Symfony/Component/Security/Http/Tests/EntryPoint/RetryAuthenticationEntryPointTest.phpnu[PK!GrT  eԲtest/Security/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.phpnu[PK!Ғ)Wݲtest/Security/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.phpnu[PK!G  T+test/Security/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.phpnu[PK!e d test/Security/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.phpnu[PK!K$$`test/Security/Symfony/Component/Security/Http/Tests/Firewall/BasicAuthenticationListenerTest.phpnu[PK!lOo;test/Security/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.phpnu[PK!jz9""TWtest/Security/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.phpnu[PK!<%%eztest/Security/Symfony/Component/Security/Http/Tests/Firewall/AbstractPreAuthenticatedListenerTest.phpnu[PK!qStest/Security/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.phpnu[PK!VkS.test/Security/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.phpnu[PK!@&@&WQܳtest/Security/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.phpnu[PK!LMM_test/Security/Symfony/Component/Security/Http/Tests/Firewall/X509AuthenticationListenerTest.phpnu[PK!xWEtest/Security/Symfony/Component/Security/Http/Tests/AccessMapTest.phpnu[PK!F8F8mtest/Security/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.phpnu[PK!䗥1#1#aQtest/Security/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.phpnu[PK!gZ)Z)cutest/Security/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.phpnu[PK!ʅ Wtest/Security/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.phpnu[PK!Y Ң atest/Security/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.phpnu[PK! {{^δtest/Security/Symfony/Component/Security/Http/Tests/Logout/DefaultLogoutSuccessHandlerTest.phpnu[PK!]ͷW׹test/Security/Symfony/Component/Security/Http/Tests/Logout/SessionLogoutHandlerTest.phpnu[PK!k  ^test/Security/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.phpnu[PK!$anƴtest/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationFailureHandlerTest.phpnu[PK!/w!w!ftest/Security/Symfony/Component/Security/Http/Tests/Authentication/SimpleAuthenticationHandlerTest.phpnu[PK!id]zntest/Security/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.phpnu[PK!?k,.<<>test/Security/Symfony/Component/Security/Http/phpunit.xml.distnu[PK!|G   bI test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.phpnu[PK!WW\-test/Security/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.phpnu[PK!-kkLMtest/Security/Symfony/Component/Security/Csrf/Tests/CsrfTokenManagerTest.phpnu[PK!3z((`atest/Security/Symfony/Component/Security/Csrf/Tests/TokenGenerator/UriSafeTokenGeneratorTest.phpnu[PK!*<<>uitest/Security/Symfony/Component/Security/Csrf/phpunit.xml.distnu[PK!ׄHAnnKmtest/Security/Symfony/Component/Security/Core/Tests/SecurityContextTest.phpnu[PK!xFE}test/Security/Symfony/Component/Security/Core/Tests/Role/RoleTest.phpnu[PK!tSNtest/Security/Symfony/Component/Security/Core/Tests/Role/RoleHierarchyTest.phpnu[PK!{{Otest/Security/Symfony/Component/Security/Core/Tests/Role/SwitchUserRoleTest.phpnu[PK!rnnYtest/Security/Symfony/Component/Security/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.phpnu[PK!6\test/Security/Symfony/Component/Security/Core/Tests/Encoder/PlaintextPasswordEncoderTest.phpnu[PK!L' Wՙtest/Security/Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.phpnu[PK!%sR@test/Security/Symfony/Component/Security/Core/Tests/Encoder/EncoderFactoryTest.phpnu[PK!e5`õtest/Security/Symfony/Component/Security/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.phpnu[PK!!? YNtest/Security/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.phpnu[PK!gȵtest/Security/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.phpnu[PK!K NMڵtest/Security/Symfony/Component/Security/Core/Tests/Util/SecureRandomTest.phpnu[PK!n;SSL:test/Security/Symfony/Component/Security/Core/Tests/Util/StringUtilsTest.phpnu[PK!K test/Security/Symfony/Component/Security/Core/Tests/Util/ClassUtilsTest.phpnu[PK!I-_ltest/Security/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.phpnu[PK!bdw \test/Security/Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.phpnu[PK!Ƕ' _B!test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/ExpressionVoterTest.phpnu[PK!jqoYj/test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleVoterTest.phpnu[PK!RMMb7test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.phpnu[PK! , , bw<test/Security/Symfony/Component/Security/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.phpnu[PK!LS(E5Jtest/Security/Symfony/Component/Security/Core/Tests/User/UserTest.phpnu[PK!qRjYtest/Security/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.phpnu[PK!$s qtest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.phpnu[PK!P[.[.mytest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.phpnu[PK!וGi&i&ntest/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.phpnu[PK!75ttt϶test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.phpnu[PK!ZZz߶test/Security/Symfony/Component/Security/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.phpnu[PK!htest/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.phpnu[PK! kY test/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.phpnu[PK!Betest/Security/Symfony/Component/Security/Core/Tests/Authentication/RememberMe/PersistentTokenTest.phpnu[PK!I?  fQtest/Security/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationTrustResolverTest.phpnu[PK!B3$$^"test/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.phpnu[PK!jKKfiGtest/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.phpnu[PK!dfJOtest/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.phpnu[PK!ۛ_Utest/Security/Symfony/Component/Security/Core/Tests/Authentication/Token/AnonymousTokenTest.phpnu[PK!]P<<>T[test/Security/Symfony/Component/Security/Core/phpunit.xml.distnu[PK!nL^test/Validator/Symfony/Component/Validator/Tests/ConstraintViolationTest.phpnu[PK!zJ.4 Pfdtest/Validator/Symfony/Component/Validator/Tests/ConstraintViolationListTest.phpnu[PK!pggXrtest/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.phpnu[PK!5*Iutest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintB.phpnu[PK!]qqI6xtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintC.phpnu[PK!&I {test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.phpnu[PK!ߛ[[D~test/Validator/Symfony/Component/Validator/Tests/Fixtures/Entity.phpnu[PK!pTqZ녷test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.phpnu[PK!@wQtest/Validator/Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.phpnu[PK!aCCM$test/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.phpnu[PK! ?>R䐷test/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.phpnu[PK!^tMtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.phpnu[PK!88J`test/Validator/Symfony/Component/Validator/Tests/Fixtures/EntityParent.phpnu[PK!h  Ytest/Validator/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.phpnu[PK!5>Qtest/Validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.phpnu[PK!= 2Otest/Validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.phpnu[PK!Ol99GDtest/Validator/Symfony/Component/Validator/Tests/Fixtures/Reference.phpnu[PK!2 Otest/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.phpnu[PK!j/Itest/Validator/Symfony/Component/Validator/Tests/Fixtures/FilesLoader.phpnu[PK!Y/Ktest/Validator/Symfony/Component/Validator/Tests/Fixtures/CallbackClass.phpnu[PK!JJXtest/Validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.phpnu[PK!G#iP[test/Validator/Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.phpnu[PK!Ε_) ) Itest/Validator/Symfony/Component/Validator/Tests/ValidatorBuilderTest.phpnu[PK!>NVtest/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.phpnu[PK!FUݷtest/Validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.phpnu[PK!)Ptest/Validator/Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.phpnu[PK!D Otest/Validator/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.phpnu[PK!W_ϘOTtest/Validator/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.phpnu[PK!", Ok test/Validator/Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.phpnu[PK!os%eeYwtest/Validator/Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.phpnu[PK!ug  Setest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.phpnu[PK!=b#test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xmlnu[PK!Dk VW'test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xmlnu[PK!-V4test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.ymlnu[PK!{%uZ:test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.phpnu[PK!mXJtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.phpnu[PK!NV,ftest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.phpnu[PK!N;ONxtest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xmlnu[PK!Qkztest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.ymlnu[PK!QiUztest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.phpnu[PK!e2~Ttest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.ymlnu[PK!^test/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.phpnu[PK!F<<Stest/Validator/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.phpnu[PK!{dQ—test/Validator/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.phpnu[PK!~6FFJꝸtest/Validator/Symfony/Component/Validator/Tests/ValidationVisitorTest.phpnu[PK!Ky'$'$B*test/Validator/Symfony/Component/Validator/Tests/ValidatorTest.phpnu[PK!P6))I test/Validator/Symfony/Component/Validator/Tests/ExecutionContextTest.phpnu[PK! Q3test/Validator/Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.phpnu[PK!ĀDDS@test/Validator/Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.phpnu[PK! Q]Stest/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.phpnu[PK!;55RN[test/Validator/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.phpnu[PK!K1K1Pqtest/Validator/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.phpnu[PK!rHiТtest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.phpnu[PK!GRfUNtest/Validator/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.phpnu[PK!I Octest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionTest.phpnu[PK!WXtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.phpnu[PK!s{*pQQRtest/Validator/Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.phpnu[PK!|++Wƹtest/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gifnu[PK!J++Xǹtest/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gifnu[PK!Ѝ!!NUȹtest/Validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gifnu[PK!)mRT˹test/Validator/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.phpnu[PK!̈́ Tytest/Validator/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.phpnu[PK!sVVXtest/Validator/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.phpnu[PK!8w w S_test/Validator/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.phpnu[PK! w88\Ytest/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.phpnu[PK!];XwwStest/Validator/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.phpnu[PK!3ê dtest/Validator/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.phpnu[PK!7aTtest/Validator/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.phpnu[PK!2((R<test/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.phpnu[PK!Xetest/Validator/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.phpnu[PK!{r>KRytest/Validator/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.phpnu[PK!jTL99UKtest/Validator/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.phpnu[PK!$&Y test/Validator/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.phpnu[PK!|=citest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.phpnu[PK!z0 Uޠtest/Validator/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.phpnu[PK!rZcc\test/Validator/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.phpnu[PK!CNNQ೺test/Validator/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.phpnu[PK!(3Jʺtest/Validator/Symfony/Component/Validator/Tests/Constraints/ValidTest.phpnu[PK!A Vͺtest/Validator/Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.phpnu[PK!BHMںtest/Validator/Symfony/Component/Validator/Tests/Constraints/AllTest.phpnu[PK!p)D D R޺test/Validator/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.phpnu[PK!͸SQtest/Validator/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.phpnu[PK!Qs(s(Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.phpnu[PK!@*VH H R-test/Validator/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.phpnu[PK! BT T RO9test/Validator/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.phpnu[PK!iKKS%Etest/Validator/Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.phpnu[PK!ϏRXKtest/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.phpnu[PK!qC VxNtest/Validator/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.phpnu[PK!ֆSZtest/Validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.phpnu[PK!LwwY$ptest/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.phpnu[PK!kkV$xtest/Validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.phpnu[PK!׫  `|test/Validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.phpnu[PK!W@ Rtest/Validator/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.phpnu[PK!y7{==Rޣtest/Validator/Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.phpnu[PK!\z?++Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.phpnu[PK!C77Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.phpnu[PK!bg g Vtest/Validator/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.phpnu[PK!;,,Xtest/Validator/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.phpnu[PK!Zf^ ^ VGtest/Validator/Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.phpnu[PK!}mW]+test/Validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.phpnu[PK!r3UURtest/Validator/Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.phpnu[PK!0h'SY'test/Validator/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.phpnu[PK!d..CGtest/Validator/Symfony/Component/Validator/Tests/ConstraintTest.phpnu[PK!,Q88;[Ztest/Validator/Symfony/Component/Validator/phpunit.xml.distnu[PK!K]test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.phpnu[PK!l;?:otest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/bootstrap.phpnu[PK!1gP*qtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.phpnu[PK!I>[Zttest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdNoToStringEntity.phpnu[PK! +88Swtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeIntIdEntity.phpnu[PK!ͭP~{test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/AssociationEntity.phpnu[PK!3Ntest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/GroupableEntity.phpnu[PK!!Stest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleStringIdEntity.phpnu[PK!6i+**T݆test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/ContainerAwareFixture.phpnu[PK!ИmOtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/DoubleNameEntity.phpnu[PK!%b99Vtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeStringIdEntity.phpnu[PK!'N|qqCtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Fixtures/User.phpnu[PK!.Itest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DoctrineOrmTestCase.phpnu[PK!۵Utest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.phpnu[PK!`Հp@test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdTest.phpnu[PK!';!!a`test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/GenericEntityChoiceListTest.phpnu[PK!9&Ӽtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleStringIdWithQueryBuilderTest.phpnu[PK!b#mؼtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleIntIdTest.phpnu[PK!AGA}~޼test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdWithQueryBuilderTest.phpnu[PK!~h}test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdWithQueryBuilderTest.phpnu[PK!'jntest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleStringIdTest.phpnu[PK!0ek test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListSingleIntIdTest.phpnu[PK!V zzmytest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListCompositeIdTest.phpnu[PK!*mtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListCompositeIdTest.phpnu[PK!n<- - _test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.phpnu[PK!-1 1 btest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListTest.phpnu[PK!c&zzmw test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/UnloadedEntityChoiceListSingleIntIdTest.phpnu[PK!ǜ"ktest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/LoadedEntityChoiceListCompositeIdTest.phpnu[PK!_UNFptest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/AbstractEntityChoiceListSingleStringIdTest.phpnu[PK!Yv:B B k_test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/DataTransformer/CollectionToArrayTransformerTest.phpnu[PK!(iiN<#test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.phpnu[PK!ImYʌtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.phpnu[PK!; Ztest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.phpnu[PK!}u>u>_itest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueValidatorTest.phpnu[PK!,`mtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.phpnu[PK!$KBBTtest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.phpnu[PK!9qq[test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataFixtures/ContainerAwareLoaderTest.phpnu[PK!CII[test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.phpnu[PK!l]}test/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.phpnu[PK!Otest/DoctrineBridge/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.phpnu[PK!ޠ77<,test/DoctrineBridge/Symfony/Bridge/Doctrine/phpunit.xml.distnu[PK!&ǦGGN(0test/MonologBridge/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.phpnu[PK!o.NGtest/MonologBridge/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.phpnu[PK!Ki66:ZQtest/MonologBridge/Symfony/Bridge/Monolog/phpunit.xml.distnu[PK!}/66MTtest/Templating/Symfony/Component/Templating/Tests/TemplateNameParserTest.phpnu[PK!xxLZtest/Templating/Symfony/Component/Templating/Tests/Fixtures/SimpleHelper.phpnu[PK!`2M]test/Templating/Symfony/Component/Templating/Tests/Fixtures/templates/foo.phpnu[PK!=DN1^test/Templating/Symfony/Component/Templating/Tests/Storage/FileStorageTest.phpnu[PK!` 7SSP/btest/Templating/Symfony/Component/Templating/Tests/Storage/StringStorageTest.phpnu[PK!S ٦Jftest/Templating/Symfony/Component/Templating/Tests/Storage/StorageTest.phpnu[PK!7H"itest/Templating/Symfony/Component/Templating/Tests/Loader/LoaderTest.phpnu[PK!Wl‡Raotest/Templating/Symfony/Component/Templating/Tests/Loader/FilesystemLoaderTest.phpnu[PK! Mjtest/Templating/Symfony/Component/Templating/Tests/Loader/CacheLoaderTest.phpnu[PK!ˡA`Mtest/Templating/Symfony/Component/Templating/Tests/Loader/ChainLoaderTest.phpnu[PK!`n} N4test/Templating/Symfony/Component/Templating/Tests/Helper/AssetsHelperTest.phpnu[PK!q=R  H]test/Templating/Symfony/Component/Templating/Tests/Helper/HelperTest.phpnu[PK!M<R⦾test/Templating/Symfony/Component/Templating/Tests/Helper/CoreAssetsHelperTest.phpnu[PK!0nl  Mhtest/Templating/Symfony/Component/Templating/Tests/Helper/SlotsHelperTest.phpnu[PK! `#`#Dtest/Templating/Symfony/Component/Templating/Tests/PhpEngineTest.phpnu[PK!氵Kݾtest/Templating/Symfony/Component/Templating/Tests/DelegatingEngineTest.phpnu[PK!%D99=test/Templating/Symfony/Component/Templating/phpunit.xml.distnu[PK!Q5test/Yaml/Symfony/Component/Yaml/Tests/DumperTest.phpnu[PK!C test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.ymlnu[PK!U U =test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfCompact.ymlnu[PK!5R[[Bftest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.ymlnu[PK!U;3test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfTests.ymlnu[PK!@UU>(test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfComments.ymlnu[PK!Ç--IX.test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.ymlnu[PK!>;F3test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.ymlnu[PK!trqqA7test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.ymlnu[PK!Z{kXXF:test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.ymlnu[PK!*E@test/Yaml/Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.ymlnu[PK!֋OA9Itest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.ymlnu[PK!ګغzzDXtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.ymlnu[PK!889htest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/index.ymlnu[PK!%MCH-jtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.ymlnu[PK!;:QJJ>ptest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.ymlnu[PK!Z>Wutest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/embededPhp.ymlnu[PK!<=utest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfObjects.ymlnu[PK!$RDmwtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.ymlnu[PK!<Œtest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.ymlnu[PK!ܷU11Ltest/Yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.ymlnu[PK!~;p2p258test/Yaml/Symfony/Component/Yaml/Tests/ParserTest.phpnu[PK!=ao[%[%5ktest/Yaml/Symfony/Component/Yaml/Tests/InlineTest.phpnu[PK!`@ee3Xtest/Yaml/Symfony/Component/Yaml/Tests/YamlTest.phpnu[PK!?o= test/Yaml/Symfony/Component/Yaml/Tests/ParseExceptionTest.phpnu[PK!>[3316test/Yaml/Symfony/Component/Yaml/phpunit.xml.distnu[PK!mg Jʜtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.phpnu[PK!O1test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestStackTest.phpnu[PK!lOD D Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTestCase.phpnu[PK!F9bbIytest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/CookieTest.phpnu[PK!qHSTtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.phpnu[PK!qr [test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ExpressionRequestMatcherTest.phpnu[PK!_|ULtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.phpnu[PK!@LLJztest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/FileBagTest.phpnu[PK!m..L@test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/HeaderBagTest.phpnu[PK!܏##Q2test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/test.gifnu[PK!+vZ3test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/.unknownextensionnu[PK!Y4test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/directory/.emptynu[PK!܏##M4test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/Fixtures/testnu[PK!~rM;;YB5test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.phpnu[PK! ##LEtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/FileTest.phpnu[PK!tAATZtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/File/UploadedFileTest.phpnu[PK!ʾV Sjwtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.phpnu[PK!M{ctest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.phpnu[PK!ƒYtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.phpnu[PK!0atest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/AttributeBagTest.phpnu[PK!)kitest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Attribute/NamespacedAttributeBagTest.phpnu[PK!ppRtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.phpnu[PK!>*itest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.phpnu[PK!5hotest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.phpnu[PK!1Mf f q test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.phpnu[PK!+?  stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.phpnu[PK!>$$ptest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.phpnu[PK!` r4test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.phpnu[PK!c= sBtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.phpnu[PK!Qttl6Ntest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.phpnu[PK!+ɠmF^test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.phpnu[PK!x..jfetest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.phpnu[PK! j.utest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.phpnu[PK!t䪑$$gtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.phpnu[PK!@|B``d$test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.phpnu[PK!F++ftest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.phpnu[PK!Č# lٿtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.phpnu[PK!T S^Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.phpnu[PK!7 Stest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderItemTest.phpnu[PK!`k O test/HttpFoundation/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.phpnu[PK!EQtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.phpnu[PK!,,Ttest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.phpnu[PK!k\BrrKDAtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ResponseTest.phpnu[PK!AkB#B#Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.phpnu[PK!qJHtest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/RequestTest.phpnu[PK!%bD Ptest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ApacheRequestTest.phpnu[PK!1r Otest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/AcceptHeaderTest.phpnu[PK!?Ltest/HttpFoundation/Symfony/Component/HttpFoundation/Tests/ServerBagTest.phpnu[PK!bppEQtest/HttpFoundation/Symfony/Component/HttpFoundation/phpunit.xml.distnu[PK!J=''D6test/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieJarTest.phpnu[PK!N4ZccAAtest/BrowserKit/Symfony/Component/BrowserKit/Tests/ClientTest.phpnu[PK!ɹ(RRAڥtest/BrowserKit/Symfony/Component/BrowserKit/Tests/CookieTest.phpnu[PK!KBtest/BrowserKit/Symfony/Component/BrowserKit/Tests/HistoryTest.phpnu[PK!{2w  Ctest/BrowserKit/Symfony/Component/BrowserKit/Tests/ResponseTest.phpnu[PK!|Btest/BrowserKit/Symfony/Component/BrowserKit/Tests/RequestTest.phpnu[PK!p6ll=test/BrowserKit/Symfony/Component/BrowserKit/phpunit.xml.distnu[PK!w۴Mtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/windows-1250.htmlnu[PK!xHtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Fixtures/no-extensionnu[PK!l#8B;test/DomCrawler/Symfony/Component/DomCrawler/Tests/CrawlerTest.phpnu[PK!Ջ==Pytest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.phpnu[PK!nRTtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/TextareaFormFieldTest.phpnu[PK!! DJtest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTest.phpnu[PK!2$GN test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FormFieldTestCase.phpnu[PK!QQO"test/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/InputFormFieldTest.phpnu[PK!5||Ntest/DomCrawler/Symfony/Component/DomCrawler/Tests/Field/FileFormFieldTest.phpnu[PK!3ʖʖ?test/DomCrawler/Symfony/Component/DomCrawler/Tests/FormTest.phpnu[PK!mY?%xtest/DomCrawler/Symfony/Component/DomCrawler/Tests/LinkTest.phpnu[PK!)q0ll=Gtest/DomCrawler/Symfony/Component/DomCrawler/phpunit.xml.distnu[PK!H77L test/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/ids.htmlnu[PK!miĪ::SӚtest/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/shakespear.htmlnu[PK!B==Ltest/CssSelector/Symfony/Component/CssSelector/Tests/XPath/Fixtures/lang.xmlnu[PK!1HCHCMtest/CssSelector/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.phpnu[PK!o,qMXtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/ElementNodeTest.phpnu[PK!BնVVJtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/HashNodeTest.phpnu[PK!V=hhKg#test/CssSelector/Symfony/Component/CssSelector/Tests/Node/ClassNodeTest.phpnu[PK!g$iNJ'test/CssSelector/Symfony/Component/CssSelector/Tests/Node/NegationNodeTest.phpnu[PK!j V{+test/CssSelector/Symfony/Component/CssSelector/Tests/Node/CombinedSelectorNodeTest.phpnu[PK!(yآN0test/CssSelector/Symfony/Component/CssSelector/Tests/Node/FunctionNodeTest.phpnu[PK!YN8test/CssSelector/Symfony/Component/CssSelector/Tests/Node/AbstractNodeTest.phpnu[PK!_ӴNC<test/CssSelector/Symfony/Component/CssSelector/Tests/Node/SelectorNodeTest.phpnu[PK!uuMu@test/CssSelector/Symfony/Component/CssSelector/Tests/Node/SpecificityTest.phpnu[PK! _ӽOgEtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/AttributeNodeTest.phpnu[PK!W DLKtest/CssSelector/Symfony/Component/CssSelector/Tests/Node/PseudoNodeTest.phpnu[PK!/D  H>Otest/CssSelector/Symfony/Component/CssSelector/Tests/CssSelectorTest.phpnu[PK!u̱Z[test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ElementParserTest.phpnu[PK![nыX5atest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/ClassParserTest.phpnu[PK!>]^Hgtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/EmptyStringParserTest.phpnu[PK![NeeWktest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Shortcut/HashParserTest.phpnu[PK!^22Jqtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ParserTest.phpnu[PK!+̭YҤtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/NumberHandlerTest.phpnu[PK!˶]test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/IdentifierHandlerTest.phpnu[PK!_/RRZtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/CommentHandlerTest.phpnu[PK!Ĉ[rtest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/AbstractHandlerTest.phpnu[PK! ]test/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/WhitespaceHandlerTest.phpnu[PK!쓱Ytest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/StringHandlerTest.phpnu[PK!CUrrWutest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/Handler/HashHandlerTest.phpnu[PK!%9j~ ~ Jntest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/ReaderTest.phpnu[PK!}q q Oftest/CssSelector/Symfony/Component/CssSelector/Tests/Parser/TokenStreamTest.phpnu[PK!Hmm?Vtest/CssSelector/Symfony/Component/CssSelector/phpunit.xml.distnu[PK!X,//T2test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.phpnu[PK!a a ]C test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.phpnu[PK!YQ_AAb1,test/EventDispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.phpnu[PK!nuJJtest/EventDispatcher/Symfony/Component/EventDispatcher/Tests/EventTest.phpnu[PK!\2 QRtest/EventDispatcher/Symfony/Component/EventDispatcher/Tests/GenericEventTest.phpnu[PK!MqqGatest/EventDispatcher/Symfony/Component/EventDispatcher/phpunit.xml.distnu[PK!C C Hdtest/Console/Symfony/Component/Console/Tests/Command/ListCommandTest.phpnu[PK!o"Z9Z9Dntest/Console/Symfony/Component/Console/Tests/Command/CommandTest.phpnu[PK!by1 1 Hutest/Console/Symfony/Component/Console/Tests/Command/HelpCommandTest.phpnu[PK!udMtest/Console/Symfony/Component/Console/Tests/Fixtures/application_astext1.txtnu[PK!cGHtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.mdnu[PK!ooKmtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.jsonnu[PK!fJWtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.xmlnu[PK!9yXBtest/Console/Symfony/Component/Console/Tests/Fixtures/command_1.mdnu[PK!SGtest/Console/Symfony/Component/Console/Tests/Fixtures/command_asxml.txtnu[PK!^t^^Ltest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.xmlnu[PK!PGtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.mdnu[PK!Gtest/Console/Symfony/Component/Console/Tests/Fixtures/BarBucCommand.phpnu[PK!W'Ltest/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txtnu[PK!&Vtest/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txtnu[PK!XXH)test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.xmlnu[PK!GHstest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.xmlnu[PK!Y'ALtest/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.phpnu[PK!CQuLtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.xmlnu[PK!!"Jtest/Console/Symfony/Component/Console/Tests/Fixtures/application_run3.txtnu[PK!edEtest/Console/Symfony/Component/Console/Tests/Fixtures/Foo4Command.phpnu[PK!zՌItest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.mdnu[PK!t;aaHtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.txtnu[PK! aItest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.jsonnu[PK!F:cLtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.xmlnu[PK!oYHJtest/Console/Symfony/Component/Console/Tests/Fixtures/application_1.jsonnu[PK!#"Dtest/Console/Symfony/Component/Console/Tests/Fixtures/command_2.jsonnu[PK!9*AEtest/Console/Symfony/Component/Console/Tests/Fixtures/TestCommand.phpnu[PK!'̒C"test/Console/Symfony/Component/Console/Tests/Fixtures/command_1.txtnu[PK!<|4UUE'test/Console/Symfony/Component/Console/Tests/Fixtures/Foo1Command.phpnu[PK!Ltest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.txtnu[PK!<]]Kmtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.jsonnu[PK!۴2IEtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.jsonnu[PK!q+Pftest/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.phpnu[PK![Kjtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.mdnu[PK!#Fitest/Console/Symfony/Component/Console/Tests/Fixtures/application_2.mdnu[PK!$$Mtest/Console/Symfony/Component/Console/Tests/Fixtures/application_astext2.txtnu[PK!g/11JLtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.txtnu[PK![%Dtest/Console/Symfony/Component/Console/Tests/Fixtures/command_1.jsonnu[PK!ZoF/test/Console/Symfony/Component/Console/Tests/Fixtures/application_1.mdnu[PK!iaJC.test/Console/Symfony/Component/Console/Tests/Fixtures/definition_asxml.txtnu[PK!_nJ3test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.xmlnu[PK!: 8J4test/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.xmlnu[PK!-_6test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txtnu[PK!@]"]"G69test/Console/Symfony/Component/Console/Tests/Fixtures/application_2.xmlnu[PK!K@bbH \test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.txtnu[PK!pK\test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.mdnu[PK!A(ffC^test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.xmlnu[PK!,K`test/Console/Symfony/Component/Console/Tests/Fixtures/definition_astext.txtnu[PK!IH?dtest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_4.xmlnu[PK!u$´!!Hetest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.txtnu[PK!$$M"ftest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.jsonnu[PK!3PLgtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.xmlnu[PK!Ѹ;;L0itest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.txtnu[PK!a66Gitest/Console/Symfony/Component/Console/Tests/Fixtures/application_1.txtnu[PK!Mmtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.jsonnu[PK!X ,,J/ntest/Console/Symfony/Component/Console/Tests/Fixtures/application_run2.txtnu[PK!󚲱}}Krtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.jsonnu[PK!1"8MMPstest/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.phpnu[PK!#ɤbMvtest/Console/Symfony/Component/Console/Tests/Fixtures/application_gethelp.txtnu[PK!(Gytest/Console/Symfony/Component/Console/Tests/Fixtures/application_2.txtnu[PK!;`ML~test/Console/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txtnu[PK!W،Iatest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.mdnu[PK!XIftest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.jsonnu[PK! cDltest/Console/Symfony/Component/Console/Tests/Fixtures/FooCommand.phpnu[PK!G u=Vtest/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txtnu[PK!Ktest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.mdnu[PK!==L|test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.txtnu[PK!H5test/Console/Symfony/Component/Console/Tests/Fixtures/command_astext.txtnu[PK!J2Htest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.xmlnu[PK!lTGtest/Console/Symfony/Component/Console/Tests/Fixtures/application_1.xmlnu[PK!Y-͡G7test/Console/Symfony/Component/Console/Tests/Fixtures/input_option_1.mdnu[PK!(?hJOtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.txtnu[PK!e::Jtest/Console/Symfony/Component/Console/Tests/Fixtures/application_run1.txtnu[PK!x44Htest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.txtnu[PK!6 _AAEEtest/Console/Symfony/Component/Console/Tests/Fixtures/Foo3Command.phpnu[PK!IItest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_3.jsonnu[PK!Xz??Ltest/Console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.phpnu[PK!*[Ǿ44Ktest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.mdnu[PK! ӸGztest/Console/Symfony/Component/Console/Tests/Fixtures/input_option_2.mdnu[PK!UBtest/Console/Symfony/Component/Console/Tests/Fixtures/command_2.mdnu[PK!8UT Jtest/Console/Symfony/Component/Console/Tests/Fixtures/application_run4.txtnu[PK!1G~"//Gtest/Console/Symfony/Component/Console/Tests/Fixtures/FoobarCommand.phpnu[PK!/""E-test/Console/Symfony/Component/Console/Tests/Fixtures/Foo5Command.phpnu[PK!XlV-test/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txtnu[PK!*qMWtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.jsonnu[PK!EOOCtest/Console/Symfony/Component/Console/Tests/Fixtures/command_1.xmlnu[PK!NY__JNtest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.txtnu[PK!M'test/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.jsonnu[PK!hC.test/Console/Symfony/Component/Console/Tests/Fixtures/command_2.txtnu[PK! Etest/Console/Symfony/Component/Console/Tests/Fixtures/Foo2Command.phpnu[PK!,DŽVtest/Console/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txtnu[PK!.p~~LWtest/Console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.txtnu[PK!MHQtest/Console/Symfony/Component/Console/Tests/Fixtures/application_2.jsonnu[PK!ttItest/Console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.mdnu[PK!Qd d Mtest/Console/Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.phpnu[PK!x0mB B Itest/Console/Symfony/Component/Console/Tests/Tester/CommandTesterTest.phpnu[PK!FCtest/Console/Symfony/Component/Console/Tests/Input/StringInputTest.phpnu[PK!p@R!test/Console/Symfony/Component/Console/Tests/Input/InputTest.phpnu[PK!9I;;D7test/Console/Symfony/Component/Console/Tests/Input/ArgvInputTest.phpnu[PK!@HHJrtest/Console/Symfony/Component/Console/Tests/Input/InputDefinitionTest.phpnu[PK!1E<<Etest/Console/Symfony/Component/Console/Tests/Input/ArrayInputTest.phpnu[PK!KU##Ftest/Console/Symfony/Component/Console/Tests/Input/InputOptionTest.phpnu[PK!F5H6test/Console/Symfony/Component/Console/Tests/Input/InputArgumentTest.phpnu[PK!Ĕ@etest/Console/Symfony/Component/Console/Tests/ApplicationTest.phpnu[PK!rHwwSitest/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleTest.phpnu[PK! RwwXctest/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleStackTest.phpnu[PK!]6\Nbtest/Console/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.phpnu[PK!Htest/Console/Symfony/Component/Console/Tests/Output/StreamOutputTest.phpnu[PK!;! FCtest/Console/Symfony/Component/Console/Tests/Output/NullOutputTest.phpnu[PK!}RItest/Console/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.phpnu[PK!Btest/Console/Symfony/Component/Console/Tests/Output/OutputTest.phpnu[PK!gO KKtest/Console/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.phpnu[PK!L""Htest/Console/Symfony/Component/Console/Tests/Helper/DialogHelperTest.phpnu[PK!+vvE3test/Console/Symfony/Component/Console/Tests/Helper/HelperSetTest.phpnu[PK!]_Դ3)3)GLtest/Console/Symfony/Component/Console/Tests/Helper/TableHelperTest.phpnu[PK!" UJvtest/Console/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.phpnu[PK!K 99Ntest/Console/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.phpnu[PK!1HDDDRtest/Console/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.phpnu[PK!oW::N]test/Console/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.phpnu[PK!66Mtest/Console/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.phpnu[PK!ž_J J Kȟtest/Console/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.phpnu[PK!} Rtest/Console/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.phpnu[PK!?UHii7кtest/Console/Symfony/Component/Console/phpunit.xml.distnu[PK!F1yAATtest/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.phpnu[PK!ν3;3;Ltest/OptionsResolver/Symfony/Component/OptionsResolver/Tests/OptionsTest.phpnu[PK!*/AAGd<test/OptionsResolver/Symfony/Component/OptionsResolver/phpunit.xml.distnu[PK!iHF@test/Config/Symfony/Component/Config/Tests/Definition/EnumNodeTest.phpnu[PK!hͼKEtest/Config/Symfony/Component/Config/Tests/Definition/NormalizationTest.phpnu[PK!hE --G^test/Config/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.phpnu[PK!I1rtest/Config/Symfony/Component/Config/Tests/Definition/IntegerNodeTest.phpnu[PK!&]GMxtest/Config/Symfony/Component/Config/Tests/Definition/FloatNodeTest.phpnu[PK!-1Q~test/Config/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.phpnu[PK!<CXMtest/Config/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.phpnu[PK!wX Ytest/Config/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.phpnu[PK! Kmޮ Q-test/Config/Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.phpnu[PK!Q\test/Config/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.phpnu[PK!Ej~j j [test/Config/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.phpnu[PK!jO灃Htest/Config/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.phpnu[PK!yXtest/Config/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.phpnu[PK!~P+Wtest/Config/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.phpnu[PK!D99Cdtest/Config/Symfony/Component/Config/Tests/Definition/MergeTest.phpnu[PK!ARRJ test/Config/Symfony/Component/Config/Tests/Definition/FinalizationTest.phpnu[PK!{Itest/Config/Symfony/Component/Config/Tests/Definition/BooleanNodeTest.phpnu[PK!%JbxQtest/Config/Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.phpnu[PK!b..DS7test/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid.xmlnu[PK!c=J7test/Config/Symfony/Component/Config/Tests/Fixtures/Util/document_type.xmlnu[PK!GɩSSK9test/Config/Symfony/Component/Config/Tests/Fixtures/Util/invalid_schema.xmlnu[PK!\ XXB9test/Config/Symfony/Component/Config/Tests/Fixtures/Util/valid.xmlnu[PK!&C:test/Config/Symfony/Component/Config/Tests/Fixtures/Util/schema.xsdnu[PK!r_Q!<test/Config/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.phpnu[PK!@Vr>test/Config/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.phpnu[PK!u;ssK@test/Config/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.phpnu[PK! ZDtest/Config/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.phpnu[PK!AOtest/Config/Symfony/Component/Config/Tests/Fixtures/Again/foo.xmlnu[PK!;GPtest/Config/Symfony/Component/Config/Tests/Fixtures/foo.xmlnu[PK!MPtest/Config/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.phpnu[PK!D-H gtest/Config/Symfony/Component/Config/Tests/Resource/FileResourceTest.phpnu[PK!s@Fntest/Config/Symfony/Component/Config/Tests/Util/XmlUtilsTest.phpnu[PK! Z^^>ʉtest/Config/Symfony/Component/Config/Tests/ConfigCacheTest.phpnu[PK!KOCC>test/Config/Symfony/Component/Config/Tests/FileLocatorTest.phpnu[PK!L{DGtest/Config/Symfony/Component/Config/Tests/Loader/FileLoaderTest.phpnu[PK!5bc@@@:test/Config/Symfony/Component/Config/Tests/Loader/LoaderTest.phpnu[PK!oq*, Jtest/Config/Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.phpnu[PK!Y  H&test/Config/Symfony/Component/Config/Tests/Loader/LoaderResolverTest.phpnu[PK!Yhh5test/Config/Symfony/Component/Config/phpunit.xml.distnu[PK!?7|ffAwtest/HttpKernel/Symfony/Component/HttpKernel/Tests/KernelTest.phpnu[PK!6^PYFtest/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.phpnu[PK!32ETS>Mtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.phpnu[PK!g&kyPtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.phpnu[PK!xiRtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.phpnu[PK!WiUtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.phpnu[PK!`AļmWtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.phpnu[PK!OgVVYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.phpnu[PK!GQ>` ` i\test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/MockObjectTestProjectContainer.phpnu[PK!#Rgtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/cache/test/classes.mapnu[PK!Qshtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle2Bundle/foo.txtnu[PK!q}VffUhtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForOverrideName.phpnu[PK!Yktest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/foo.txtnu[PK!Zhltest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ChildBundle/Resources/hide.txtnu[PK!Qltest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/foo.txtnu[PK!Qsmtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/bar.txtnu[PK![mtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txtnu[PK!Wntest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/FooBundle/foo.txtnu[PK!Yotest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/ChildBundle/foo.txtnu[PK![otest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txtnu[PK!Yptest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/Resources/BaseBundle/hide.txtnu[PK!Xptest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/foo.txtnu[PK!Y+qtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/BaseBundle/Resources/hide.txtnu[PK!&#Jqtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/TestClient.phpnu[PK!yhMIutest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/KernelForTest.phpnu[PK!0Lxtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/FooBarBundle.phpnu[PK!?ɜkztest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.phpnu[PK!_TT/}test/HttpKernel/Symfony/Component/HttpKernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.phpnu[PK!S [5test/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.phpnu[PK!,%%Rtest/HttpKernel/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerTest.phpnu[PK!0GGE@test/HttpKernel/Symfony/Component/HttpKernel/Tests/TestHttpKernel.phpnu[PK!qAtest/HttpKernel/Symfony/Component/HttpKernel/Tests/ClientTest.phpnu[PK!݂($$Ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.phpnu[PK!!/ / YTtest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/FragmentListenerTest.phpnu[PK!W:ttZ test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.phpnu[PK!(kkY test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.phpnu[PK!=v? Ttest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/EsiListenerTest.phpnu[PK!p66W{test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.phpnu[PK!uu\8)test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.phpnu[PK!,ph h Y98test/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.phpnu[PK!K(^W*Ftest/HttpKernel/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.phpnu[PK!oM\gVtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.phpnu[PK! ((\gtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.phpnu[PK!vZ8wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.phpnu[PK!; Stest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.phpnu[PK!҃ Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.phpnu[PK!p =Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Logger.phpnu[PK!m*Ntest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.phpnu[PK!t~ Outest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.phpnu[PK!`uNNH2test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.phpnu[PK!JJWtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.phpnu[PK!VPRɧtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.phpnu[PK!Z&Z&JPtest/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.phpnu[PK!`1M$test/HttpKernel/Symfony/Component/HttpKernel/Tests/Config/FileLocatorTest.phpnu[PK!KwHtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.phpnu[PK!!g[test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcacheProfilerStorageTest.phpnu[PK![\Btest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MemcachedProfilerStorageTest.phpnu[PK!T Wtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/FileProfilerStorageTest.phpnu[PK!,))[ test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/AbstractProfilerStorageTest.phpnu[PK!.\R3test/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcachedMock.phpnu[PK!i]QDtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/MemcacheMock.phpnu[PK!eK  NYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/Mock/RedisMock.phpnu[PK!`ejZKltest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/MongoDbProfilerStorageTest.phpnu[PK!p3h NNYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/SqliteProfilerStorageTest.phpnu[PK!FEXYtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/RedisProfilerStorageTest.phpnu[PK!&2TTLtest/HttpKernel/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.phpnu[PK!Uu֝Dhtest/HttpKernel/Symfony/Component/HttpKernel/Tests/UriSignerTest.phpnu[PK!bҏ^^\ytest/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/MemoryDataCollectorTest.phpnu[PK!CZctest/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/TimeDataCollectorTest.phpnu[PK! \إtest/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ConfigDataCollectorTest.phpnu[PK!}#_test/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.phpnu[PK!J֌]Rtest/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.phpnu[PK!i i \ktest/HttpKernel/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.phpnu[PK!g]>*>*E`test/HttpKernel/Symfony/Component/HttpKernel/Tests/HttpKernelTest.phpnu[PK!z*V%%X test/HttpKernel/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.phpnu[PK!e ֮n/test/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.phpnu[PK!V^^d7test/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterListenersPassTest.phpnu[PK!ChhgLtest/HttpKernel/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.phpnu[PK!x99=btest/HttpKernel/Symfony/Component/HttpKernel/phpunit.xml.distnu[PK!]Q Rftest/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.phpnu[PK!h4A!AAOtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.phpnu[PK!2[AAOltest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Baz.phpnu[PK! AAO,test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Foo.phpnu[PK!Cq""Utest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.phpnu[PK!֡Z  Xtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.phpnu[PK!KG9ՈU;test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.phpnu[PK!Қ`Htest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/sameNsMultipleClasses.phpnu[PK!.~oDDTtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeClass.phpnu[PK!RTtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notPhpFile.mdnu[PK!iTYtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notAClass.phpnu[PK!{tKK^test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Bar.phpnu[PK!PF\KK^ғtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Foo.phpnu[PK!LkKK^test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Bar.phpnu[PK!vգKK^test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Foo.phpnu[PK!cZZa]test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.phpnu[PK!LVAKZZaHtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Foo.phpnu[PK!KaAAa3test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Bar.phpnu[PK!AAatest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.phpnu[PK!@OOQכtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.phpnu[PK! Z3bOOQtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Baz.phpnu[PK!d0OOQwtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Foo.phpnu[PK!55PGtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.phpnu[PK!ᒟ55Ptest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.phpnu[PK!R55Ptest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.phpnu[PK!UXYftest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.phpnu[PK!dQtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/includepath/Foo.phpnu[PK!l@@Ntest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Bar.phpnu[PK!q@@NZtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Baz.phpnu[PK!Ӽ@@Ntest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Foo.phpnu[PK!5JDDW֨test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/WithComments.phpnu[PK!>XMtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/deps/traits.phpnu[PK!:5T+Otest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/php5.4/traits.phpnu[PK! N77[{test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/ATrait.phpnu[PK!`RR_=test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CInterface.phpnu[PK! ;;Vtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/A.phpnu[PK! LLV߯test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/D.phpnu[PK!tLLVtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/E.phpnu[PK!HGG[test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/BTrait.phpnu[PK!LqGGVUtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/B.phpnu[PK!["77["test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CTrait.phpnu[PK!Z??_test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/GInterface.phpnu[PK!6SII]test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Bar.phpnu[PK! II]test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Foo.phpnu[PK!&FII]^test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Bar.phpnu[PK!II]4test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Foo.phpnu[PK!]>XX` test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.phpnu[PK!~(XX`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Foo.phpnu[PK!99A??`ڹtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Bar.phpnu[PK!i??`test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.phpnu[PK!nDD[xtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2/FooBar.phpnu[PK!gyRR]Gtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.phpnu[PK![“88\&test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.phpnu[PK!xwCCZtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike/FooBar.phpnu[PK!>\oNNitest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.phpnu[PK!GNNitest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Foo.phpnu[PK!FEEitest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Bar.phpnu[PK!][EEictest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.phpnu[PK!/5<<WAtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.phpnu[PK!ے99Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.phpnu[PK!$y99Ttest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.phpnu[PK!0- +99T~test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.phpnu[PK!yQUmDDR;test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.phpnu[PK!&DDRtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Baz.phpnu[PK!EDDRtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Foo.phpnu[PK!7LLhtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Bar.phpnu[PK!.&LLhqtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Foo.phpnu[PK!4CChUtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Bar.phpnu[PK!qoCCh0test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.phpnu[PK!/5<<` test/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced/FooBar.phpnu[PK!GGbtest/ClassLoader/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.phpnu[PK!M Htest/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.phpnu[PK!e:{aTtest/ClassLoader/Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.phpnu[PK!8`##QZtest/ClassLoader/Symfony/Component/ClassLoader/Tests/UniversalClassLoaderTest.phpnu[PK!\|N<test/ClassLoader/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.phpnu[PK!)mm?EUtest/ClassLoader/Symfony/Component/ClassLoader/phpunit.xml.distnu[PK!yMV]!Ytest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.phpnu[PK![VItest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterTest.phpnu[PK!~O99ktest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.phpnu[PK!I8i{ztest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.phpnu[PK!//\ test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.phpnu[PK!G3G@ `test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.phpnu[PK!E))atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.phpnu[PK!oTb_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.phpnu[PK!,j_-test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.phpnu[PK!$oyy`'test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.phpnu[PK!:A!!h-test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.phpnu[PK!7/_RMtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.phpnu[PK!(]  _{Stest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xmlnu[PK!ibĤ_Utest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xmlnu[PK!![  `JXtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services10.xmlnu[PK!u  _Ztest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xmlnu[PK!_+WW_]test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xmlnu[PK!x' 11ah_test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/withdoctype.xmlnu[PK!wzhh_*`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xmlnu[PK!Ujtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xmlnu[PK!}jtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xmlnu[PK!33e)test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dotnu[PK!h dtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dotnu[PK!Ձ1*,,gstest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dotnu[PK!&WWd6test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dotnu[PK!ŏD;;e!test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services13.dotnu[PK!8BBetest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services14.dotnu[PK!N{rryȵtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtensionInPhar.pharnu[PK! ^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.phpnu[PK!]e test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.phpnu[PK!.Y<ҿkxtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.phpnu[PK!Aov:ZZbtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.phpnu[PK!RK:mtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsdnu[PK![[rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.phpnu[PK!`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.ymlnu[PK!|DD`-test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.ymlnu[PK!6e3`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.ymlnu[PK!Vv==`ntest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.ymlnu[PK!#&# `;test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.ymlnu[PK!y ??ktest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.ymlnu[PK!*_6^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.ymlnu[PK!zbnn^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.ymlnu[PK!''`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.ymlnu[PK!%/atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.ymlnu[PK!2`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.ymlnu[PK!MuAaFtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.ymlnu[PK!}>^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.ymlnu[PK!:Ʋ`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.ymlnu[PK!W%`Ztest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.ymlnu[PK!|w`test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.ymlnu[PK!GGa test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.ymlnu[PK!۴)++^test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ininu[PK!pu((atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ininu[PK!s4''`Utest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ininu[PK!5l%%a test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ininu[PK!Fmhtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.phpnu[PK!4hg test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.phpnu[PK! Z g=test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.phpnu[PK!33hWtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.phpnu[PK! |h"test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.phpnu[PK!Cݲ;;htest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.phpnu[PK!BreOOhtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.phpnu[PK!*EEh test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.phpnu[PK!1vha test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.phpnu[PK! ^l test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.phpnu[PK!$99ftest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.phpnu[PK! WOtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.phpnu[PK!2+` ^9]test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.phpnu[PK!v  bgtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.phpnu[PK!)]/ttest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.phpnu[PK!"."."]test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.phpnu[PK!Vbtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ReferenceTest.phpnu[PK!ł``atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.phpnu[PK!SRatest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.phpnu[PK!kV00btest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.phpnu[PK!Q&I8a8aa7test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.phpnu[PK! aLtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.phpnu[PK!' rSWtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.phpnu[PK!'{ { qatest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.phpnu[PK!>" pntest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.phpnu[PK!]t`{test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.phpnu[PK!}1H@@xtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.phpnu[PK!f00rܗtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.phpnu[PK!O atest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.phpnu[PK!@|޵test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.phpnu[PK!@w qJtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.phpnu[PK!~ ` ` rtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.phpnu[PK!I qtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.phpnu[PK! T^??ttest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.phpnu[PK!e55Wtest/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionTest.phpnu[PK!+E `$test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.phpnu[PK!K5WWV;3test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/ContainerTest.phpnu[PK!`= `test/DependencyInjection/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.phpnu[PK!uuOtest/DependencyInjection/Symfony/Component/DependencyInjection/phpunit.xml.distnu[PK!jdata/Base/design/design.txtnu[PK!u+SS"data/Base/design/class_diagram.pngnu[PK!y  #,data/ConsoleTools/design/design.txtnu[PK!?TT':data/ConsoleTools/design/design-1.3.txtnu[PK!>5AA$data/ConsoleTools/design/console.pngnu[PK!_x!!/data/ConsoleTools/design/console_parameters.pngnu[PK!YǾ$data/ConsoleTools/design/console.xmlnu[PK!>'J J *data/ConsoleTools/design/class_diagram.pngnu[PK!>(data/Archive/design/design.txtnu[PK!g3{ { %0data/Archive/design/class_diagram.pngnu[PK!ߦCdata/File/design/design.txtnu[PK! 1D\  !\data/File/design/requirements.txtnu[PK!rCBB$ͷdata/File/design/file_operations.pngnu[PK!XV00cdata/File/design/md5.pngnu[PK! [ooudata/File/design/file.xmlnu[PK!\"Pkdata/File/design/class_diagram.pngnu[PK!oim.channels/components.ez.no.regnu[PK!2"p.channels/pear.symfony.com.regnu[PK! ~%{t.channels/pear.phpunit.de.regnu[PK!t^x.channels/.alias/ezc.txtnu[PK!\x.channels/.alias/symfony2.txtnu[PK!TYy.channels/.alias/phpunit.txtnu[PK!܄#ny.pkgxml/Symfony2_Security-2.4.3.xmlnu[PK!'Jz++UN.pkgxml/symfony2.xmlnu[PK!^\F[[%Q.pkgxml/Symfony2_Serializer-2.4.3.xmlnu[PK!$n77&tm.pkgxml/Symfony2_ClassLoader-2.4.3.xmlnu[PK!n++x.pkgxml/Symfony2_Yaml-2.4.3.xmlnu[PK!}3YN.pkgxml/eZc_Archive-1.4.1.xmlnu[PK!b88!6.pkgxml/Symfony2_Config-2.4.3.xmlnu[PK!$v *.pkgxml/Symfony2_OptionsResolver-2.4.3.xmlnu[PK!tWYnn%a!.pkgxml/Symfony2_HttpKernel-2.4.3.xmlnu[PK!1ss..pkgxml/Symfony2_DependencyInjection-2.4.3.xmlnu[PK!=4 (.pkgxml/Symfony2_MonologBridge-2.4.3.xmlnu[PK!-=-=".pkgxml/Symfony2_Routing-2.4.3.xmlnu[PK!|g$sN.pkgxml/Symfony2_Validator-2.4.3.xmlnu[PK!d+)SS!.pkgxml/Symfony2_Locale-2.4.3.xmlnu[PK!*OO[ .pkgxml/ezc.xmlnu[PK!a.pkgxml/Symfony2_Form-2.4.3.xmlnu[PK!F%.pkgxml/Symfony2_DomCrawler-2.4.3.xmlnu[PK!?4 % .pkgxml/Symfony2_BrowserKit-2.4.3.xmlnu[PK!t8 %F.pkgxml/Symfony2_Filesystem-2.4.3.xmlnu[PK!>tBB&#.pkgxml/Symfony2_Translation-2.4.3.xmlnu[PK!oA A S<.pkgxml/eZc_Base-1.8.xmlnu[PK!3'CC)\.pkgxml/Symfony2_HttpFoundation-2.4.3.xmlnu[PK!֠.pkgxml/Symfony2.listnu[PK!8.pkgxml/phpunit.xmlnu[PK!u&6%%%.pkgxml/Symfony2_TwigBridge-2.4.3.xmlnu[PK!UU__"`.pkgxml/Symfony2_Console-2.4.3.xmlnu[PK!kb*-.pkgxml/Symfony2_EventDispatcher-2.4.3.xmlnu[PK!sYY"p<.pkgxml/Symfony2_Process-2.4.3.xmlnu[PK!nJ/J/)Q.pkgxml/Symfony2_DoctrineBridge-2.4.3.xmlnu[PK!A~0~0&.pkgxml/Symfony2_CssSelector-2.4.3.xmlnu[PK! v~[0[0!.pkgxml/Symfony2_Finder-2.4.3.xmlnu[PK!܋Fcc>.pkgxml/eZc.listnu[PK!\ \ .pkgxml/eZc_File-1.2.xmlnu[PK!IZ%.pkgxml/Symfony2_Templating-2.4.3.xmlnu[PK!n#)v>>"c .pkgxml/eZc_ConsoleTools-1.6.1.xmlnu[PK!pxNJNJ/K.registry/.channel.pear.symfony.com/process.regnu[PK!//.registry/.channel.pear.symfony.com/console.regnu[PK!!6d d 3/.registry/.channel.pear.symfony.com/translation.regnu[PK!DzX&&2$.registry/.channel.pear.symfony.com/filesystem.regnu[PK!>ff0ML.registry/.channel.pear.symfony.com/security.regnu[PK! Gw̟̟1}.registry/.channel.pear.symfony.com/validator.regnu[PK!^.S .registry/.channel.pear.symfony.com/config.regnu[PK!K25 .registry/.channel.pear.symfony.com/httpkernel.regnu[PK!ett3 .registry/.channel.pear.symfony.com/cssselector.regnu[PK!W6Լ .registry/.channel.pear.symfony.com/httpfoundation.regnu[PK!4=//2(.registry/.channel.pear.symfony.com/twigbridge.regnu[PK!KZ((7b.registry/.channel.pear.symfony.com/optionsresolver.regnu[PK!..registry/.channel.pear.symfony.com/finder.regnu[PK!#,\N.registry/.channel.pear.symfony.com/form.regnu[PK!Eӭ++5M.registry/.channel.pear.symfony.com/monologbridge.regnu[PK!q=h=h2y.registry/.channel.pear.symfony.com/serializer.regnu[PK!3Ų..2H.registry/.channel.pear.symfony.com/browserkit.regnu[PK!BgG3G37\.registry/.channel.pear.symfony.com/eventdispatcher.regnu[PK!YdYY, E.registry/.channel.pear.symfony.com/yaml.regnu[PK!19n9n2T.registry/.channel.pear.symfony.com/templating.regnu[PK!@zx@x@2 .registry/.channel.pear.symfony.com/domcrawler.regnu[PK! @O 3N.registry/.channel.pear.symfony.com/classloader.regnu[PK!ý Edd/7D.registry/.channel.pear.symfony.com/routing.regnu[PK!jORR.7.registry/.channel.pear.symfony.com/locale.regnu[PK!eBEgg;.registry/.channel.pear.symfony.com/dependencyinjection.regnu[PK!.P6e.registry/.channel.pear.symfony.com/doctrinebridge.regnu[PK!塕"",E*.registry/.channel.components.ez.no/file.regnu[PK!Lee/L.registry/.channel.components.ez.no/archive.regnu[PK!Mi4.registry/.channel.components.ez.no/consoletools.regnu[PK!4p4p,.registry/.channel.components.ez.no/base.regnu[PK!gRr Structures_LinkedList/CHANGELOGnu[PK! 6Structures_LinkedList/examples/single_link_example.phpnu[PK!p| | 6Structures_LinkedList/examples/double_link_example.phpnu[PK!^,^,&Structures_LinkedList/LICENSEnu[PK! KSMail/LICENSEnu[PK!y˿iYNet_Socket/README.mdnu[PK!W]H]Net_Socket/LICENSEnu[PK!TkUbNet_SMTP/examples/basic.phpnu[PK!SOܪ%%4gNet_SMTP/README.rstnu[PK!((!Net_SMTP/LICENSEnu[PK!!!File_MARC/CHANGELOGnu[PK!~File_MARC/examples/read.phpnu[PK! File_MARC/examples/subfields.phpnu[PK!cVDFile_MARC/examples/marc_yaz.phpnu[PK!~N0::hFile_MARC/examples/example.mrcnu[PK!DgDgFile_MARC/LICENSEnu[PK!sRrru(PEAR/Autoloader.phpnu[PK!qC*BPEAR/FixPHP5PEARWarnings.phpnu[PK!Z-%##3Ctest/Structures_Graph/tests/testCase/BasicGraph.phpnu[PK!!ftest/Net_IDNA2/tests/AllTests.phpnu[PK!l,'jtest/XML_Util/tests/testBasic_createTag.phptnu[PK!W=0test/XML_Util/tests/testBasic_createComment.phptnu[PK!ҽyI-փtest/XML_Util/tests/testBasic_raiseError.phptnu[PK!]$]$5)test/XML_Util/tests/testBasic_createTagFromArray.phptnu[PK!ҵII%test/XML_Util/tests/testBug_5392.phptnu[PK!WB5test/XML_Util/tests/testBasic_splitQualifiedName.phptnu[PK!eb5ųtest/XML_Util/tests/testBasic_createStartElement.phptnu[PK!h4test/XML_Util/tests/testBasic_collapseEmptyTags.phptnu[PK!X.Ntest/XML_Util/tests/testBasic_isValidName.phptnu[PK!.5.test/XML_Util/tests/testBasic_createCDataSection.phptnu[PK!'-test/XML_Util/tests/testBasic_apiVersion.phptnu[PK! _ 2test/XML_Util/tests/testBasic_replaceEntities.phptnu[PK! 4test/XML_Util/tests/testBasic_getXmlDeclaration.phptnu[PK!_//5test/XML_Util/tests/testBasic_attributesToString.phptnu[PK!M%8test/XML_Util/tests/testBug_4950.phptnu[PK!uf$ &0test/XML_Util/tests/testBug_18343.phptnu[PK!c?8test/XML_Util/tests/testBasic_getDocTypeDeclaration.phptnu[PK!l  2m test/XML_Util/tests/testBasic_reverseEntities.phptnu[PK!^r3ptest/XML_Util/tests/testBasic_createEndElement.phptnu[PK!2>g>gdata/Structures_Graph/LICENSEnu[PK!x?? PEAR5.phpnu[PK![x$q)q) .pkgxml/Pear_File_MARC-0.7.3.xmlnu[PK!r&& O.pkgxml/Pear_Auth_SASL-1.0.6.xmlnu[PK!Yh .pkgxml/Pear_Net_SMTP-1.6.3.xmlnu[PK!1vHH" .pkgxml/Pear_Net_Socket-1.0.14.xmlnu[PK!6w&Yc c .pkgxml/Pear_Net_IDNA2-0.1.1.xmlnu[PK XfZ